mirror of
				https://github.com/strapi/strapi.git
				synced 2025-10-31 01:47:13 +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); | ||||
| } | ||||
| 
 | ||||
| export const createConnection = (config: Knex.Config) => { | ||||
|   if (!isClientValid(config)) { | ||||
|     throw new Error(`Unsupported database client ${config.client}`); | ||||
| export const createConnection = (userConfig: Knex.Config, strapiConfig?: Partial<Knex.Config>) => { | ||||
|   if (!isClientValid(userConfig)) { | ||||
|     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); | ||||
| }; | ||||
|  | ||||
| @ -19,7 +19,10 @@ export default class Dialect { | ||||
| 
 | ||||
|   configure() {} | ||||
| 
 | ||||
|   initialize() {} | ||||
|   // eslint-disable-next-line @typescript-eslint/no-unused-vars
 | ||||
|   async initialize(_nativeConnection?: unknown) { | ||||
|     // noop
 | ||||
|   } | ||||
| 
 | ||||
|   getSqlType(type: unknown) { | ||||
|     return type; | ||||
|  | ||||
| @ -52,15 +52,20 @@ export default class MysqlDialect extends Dialect { | ||||
|     }; | ||||
|   } | ||||
| 
 | ||||
|   async initialize() { | ||||
|   async initialize(nativeConnection: unknown) { | ||||
|     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) { | ||||
|       // 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(); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   async startSchemaUpdate() { | ||||
|     try { | ||||
|  | ||||
| @ -16,7 +16,7 @@ export default class PostgresDialect extends Dialect { | ||||
|     return true; | ||||
|   } | ||||
| 
 | ||||
|   async initialize() { | ||||
|   async initialize(nativeConnection: unknown) { | ||||
|     // Don't cast DATE string to Date()
 | ||||
|     this.db.connection.client.driver.types.setTypeParser( | ||||
|       this.db.connection.client.driver.types.builtins.DATE, | ||||
| @ -34,6 +34,14 @@ export default class PostgresDialect extends Dialect { | ||||
|       'text', | ||||
|       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() { | ||||
|  | ||||
| @ -33,8 +33,8 @@ export default class SqliteDialect extends Dialect { | ||||
|     return true; | ||||
|   } | ||||
| 
 | ||||
|   async initialize() { | ||||
|     await this.db.connection.raw('pragma foreign_keys = on'); | ||||
|   async initialize(nativeConnection: unknown) { | ||||
|     await this.db.connection.raw('pragma foreign_keys = on').connection(nativeConnection); | ||||
|   } | ||||
| 
 | ||||
|   canAlterConstraints() { | ||||
|  | ||||
| @ -69,9 +69,17 @@ class Database { | ||||
|     this.dialect = getDialect(this); | ||||
|     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); | ||||
| 
 | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Ben Irvin
						Ben Irvin