mirror of
				https://github.com/strapi/strapi.git
				synced 2025-11-04 03:43:34 +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,14 +52,19 @@ 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
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    this.info = await this.databaseInspector.getInformation();
 | 
			
		||||
    // We only need to get info on the first connection in the pool
 | 
			
		||||
    if (!this.info) {
 | 
			
		||||
      this.info = await this.databaseInspector.getInformation();
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  async startSchemaUpdate() {
 | 
			
		||||
 | 
			
		||||
@ -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