mirror of
				https://github.com/strapi/strapi.git
				synced 2025-10-31 09:56:44 +00:00 
			
		
		
		
	fix: init dialect on every new connection in the pool (#18588)
This commit is contained in:
		
							parent
							
								
									3e3b3393e2
								
							
						
					
					
						commit
						7a48741483
					
				| @ -11,12 +11,34 @@ function isClientValid(config: { client?: unknown }): config is { client: keyof | |||||||
|   return Object.keys(clientMap).includes(config.client as string); |   return Object.keys(clientMap).includes(config.client as string); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export const createConnection = (config: Knex.Config) => { | export const createConnection = (userConfig: Knex.Config, strapiConfig?: Partial<Knex.Config>) => { | ||||||
|   if (!isClientValid(config)) { |   if (!isClientValid(userConfig)) { | ||||||
|     throw new Error(`Unsupported database client ${config.client}`); |     throw new Error(`Unsupported database client ${userConfig.client}`); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   const knexConfig = { ...config, client: (clientMap as any)[config.client] }; |   const knexConfig: Knex.Config = { ...userConfig, client: (clientMap as any)[userConfig.client] }; | ||||||
|  | 
 | ||||||
|  |   // initialization code to run upon opening a new connection
 | ||||||
|  |   if (strapiConfig?.pool?.afterCreate) { | ||||||
|  |     knexConfig.pool = knexConfig.pool || {}; | ||||||
|  |     // if the user has set their own afterCreate in config, we will replace it and call it
 | ||||||
|  |     const userAfterCreate = knexConfig.pool?.afterCreate; | ||||||
|  |     const strapiAfterCreate = strapiConfig.pool.afterCreate; | ||||||
|  |     knexConfig.pool.afterCreate = ( | ||||||
|  |       conn: unknown, | ||||||
|  |       done: (err: Error | null | undefined, connection: any) => void | ||||||
|  |     ) => { | ||||||
|  |       strapiAfterCreate(conn, (err: Error | null | undefined, nativeConn: any) => { | ||||||
|  |         if (err) { | ||||||
|  |           return done(err, nativeConn); | ||||||
|  |         } | ||||||
|  |         if (userAfterCreate) { | ||||||
|  |           return userAfterCreate(nativeConn, done); | ||||||
|  |         } | ||||||
|  |         return done(null, nativeConn); | ||||||
|  |       }); | ||||||
|  |     }; | ||||||
|  |   } | ||||||
| 
 | 
 | ||||||
|   return knex(knexConfig); |   return knex(knexConfig); | ||||||
| }; | }; | ||||||
|  | |||||||
| @ -19,7 +19,10 @@ export default class Dialect { | |||||||
| 
 | 
 | ||||||
|   configure() {} |   configure() {} | ||||||
| 
 | 
 | ||||||
|   initialize() {} |   // eslint-disable-next-line @typescript-eslint/no-unused-vars
 | ||||||
|  |   async initialize(_nativeConnection?: unknown) { | ||||||
|  |     // noop
 | ||||||
|  |   } | ||||||
| 
 | 
 | ||||||
|   getSqlType(type: unknown) { |   getSqlType(type: unknown) { | ||||||
|     return type; |     return type; | ||||||
|  | |||||||
| @ -52,15 +52,20 @@ export default class MysqlDialect extends Dialect { | |||||||
|     }; |     }; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   async initialize() { |   async initialize(nativeConnection: unknown) { | ||||||
|     try { |     try { | ||||||
|       await this.db.connection.raw(`set session sql_require_primary_key = 0;`); |       await this.db.connection | ||||||
|  |         .raw(`set session sql_require_primary_key = 0;`) | ||||||
|  |         .connection(nativeConnection); | ||||||
|     } catch (err) { |     } catch (err) { | ||||||
|       // Ignore error due to lack of session permissions
 |       // Ignore error due to lack of session permissions
 | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     // We only need to get info on the first connection in the pool
 | ||||||
|  |     if (!this.info) { | ||||||
|       this.info = await this.databaseInspector.getInformation(); |       this.info = await this.databaseInspector.getInformation(); | ||||||
|     } |     } | ||||||
|  |   } | ||||||
| 
 | 
 | ||||||
|   async startSchemaUpdate() { |   async startSchemaUpdate() { | ||||||
|     try { |     try { | ||||||
|  | |||||||
| @ -16,7 +16,7 @@ export default class PostgresDialect extends Dialect { | |||||||
|     return true; |     return true; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   async initialize() { |   async initialize(nativeConnection: unknown) { | ||||||
|     // Don't cast DATE string to Date()
 |     // Don't cast DATE string to Date()
 | ||||||
|     this.db.connection.client.driver.types.setTypeParser( |     this.db.connection.client.driver.types.setTypeParser( | ||||||
|       this.db.connection.client.driver.types.builtins.DATE, |       this.db.connection.client.driver.types.builtins.DATE, | ||||||
| @ -34,6 +34,14 @@ export default class PostgresDialect extends Dialect { | |||||||
|       'text', |       'text', | ||||||
|       parseFloat |       parseFloat | ||||||
|     ); |     ); | ||||||
|  | 
 | ||||||
|  |     // If we're using a schema, set the default path for all table names in queries to use that schema
 | ||||||
|  |     const schemaName = this.db.getSchemaName(); | ||||||
|  |     if (schemaName) { | ||||||
|  |       await this.db.connection | ||||||
|  |         .raw(`SET search_path TO "${schemaName}"`) | ||||||
|  |         .connection(nativeConnection); | ||||||
|  |     } | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   usesForeignKeys() { |   usesForeignKeys() { | ||||||
|  | |||||||
| @ -33,8 +33,8 @@ export default class SqliteDialect extends Dialect { | |||||||
|     return true; |     return true; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   async initialize() { |   async initialize(nativeConnection: unknown) { | ||||||
|     await this.db.connection.raw('pragma foreign_keys = on'); |     await this.db.connection.raw('pragma foreign_keys = on').connection(nativeConnection); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   canAlterConstraints() { |   canAlterConstraints() { | ||||||
|  | |||||||
| @ -69,9 +69,17 @@ class Database { | |||||||
|     this.dialect = getDialect(this); |     this.dialect = getDialect(this); | ||||||
|     this.dialect.configure(); |     this.dialect.configure(); | ||||||
| 
 | 
 | ||||||
|     this.connection = createConnection(this.config.connection); |     const afterCreate = ( | ||||||
|  |       nativeConnection: unknown, | ||||||
|  |       done: (error: Error | null, nativeConnection: unknown) => Promise<void> | ||||||
|  |     ) => { | ||||||
|  |       // run initialize for it since commands such as postgres SET and sqlite PRAGMA are per-connection
 | ||||||
|  |       this.dialect.initialize(nativeConnection).then(() => { | ||||||
|  |         return done(null, nativeConnection); | ||||||
|  |       }); | ||||||
|  |     }; | ||||||
| 
 | 
 | ||||||
|     this.dialect.initialize(); |     this.connection = createConnection(this.config.connection, { pool: { afterCreate } }); | ||||||
| 
 | 
 | ||||||
|     this.schema = createSchemaProvider(this); |     this.schema = createSchemaProvider(this); | ||||||
| 
 | 
 | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Ben Irvin
						Ben Irvin