rake-db 2.29.10 → 2.30.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -181,10 +181,6 @@ const promptText = ({
181
181
  };
182
182
 
183
183
  const getMaybeTransactionAdapter = (db) => "$getAdapter" in db ? db.$getAdapter() : db;
184
- const ensureTransaction = (db, fn) => {
185
- const adapter = getMaybeTransactionAdapter(db);
186
- return adapter.isInTransaction() ? fn(adapter) : adapter.transaction(void 0, fn);
187
- };
188
184
  const runSqlInSavePoint = async (db, sql, code) => {
189
185
  const adapter = getMaybeTransactionAdapter(db);
190
186
  try {
@@ -283,19 +279,16 @@ const quoteWithSchema = ({
283
279
  name
284
280
  }) => quoteTable(schema, name);
285
281
  const quoteTable = (schema, table) => schema ? `"${schema}"."${table}"` : `"${table}"`;
286
- const getSchemaAndTableFromName = (config, name) => {
282
+ const getSchemaAndTableFromName = (schema, name) => {
287
283
  const i = name.indexOf(".");
288
- return i !== -1 ? [name.slice(0, i), name.slice(i + 1)] : [
289
- typeof config.schema === "function" ? config.schema() : config.schema,
290
- name
291
- ];
284
+ return i !== -1 ? [name.slice(0, i), name.slice(i + 1)] : [typeof schema === "function" ? schema() : schema, name];
292
285
  };
293
- const quoteNameFromString = (config, string) => {
294
- return quoteTable(...getSchemaAndTableFromName(config, string));
286
+ const quoteNameFromString = (schema, string) => {
287
+ return quoteTable(...getSchemaAndTableFromName(schema, string));
295
288
  };
296
- const quoteCustomType = (config, s) => {
297
- const [schema, type] = getSchemaAndTableFromName(config, s);
298
- return schema ? '"' + schema + '".' + type : type;
289
+ const quoteCustomType = (schema, type) => {
290
+ const [s, t] = getSchemaAndTableFromName(schema, type);
291
+ return s ? '"' + s + '".' + t : t;
299
292
  };
300
293
  const quoteSchemaTable = (arg, excludeCurrentSchema) => {
301
294
  return pqb.singleQuote(concatSchemaAndName(arg, excludeCurrentSchema));
@@ -306,17 +299,25 @@ const concatSchemaAndName = ({
306
299
  }, excludeCurrentSchema) => {
307
300
  return schema && schema !== excludeCurrentSchema ? `${schema}.${name}` : name;
308
301
  };
309
- const makePopulateEnumQuery = (config, item) => {
310
- const [schema, name] = getSchemaAndTableFromName(config, item.enumName);
302
+ const makePopulateEnumQuery = (schema, item) => {
303
+ const [s, name] = getSchemaAndTableFromName(schema, item.enumName);
311
304
  return {
312
- text: `SELECT unnest(enum_range(NULL::${quoteTable(schema, name)}))::text`,
305
+ text: `SELECT unnest(enum_range(NULL::${quoteTable(s, name)}))::text`,
313
306
  then(result) {
314
307
  item.options.push(...result.rows.map(([value]) => value));
315
308
  }
316
309
  };
317
310
  };
318
- const transaction = (adapter, fn) => {
319
- return adapter.transaction(void 0, fn);
311
+ const transaction = (adapter, config, fn) => {
312
+ const searchPath = config.transactionSearchPath;
313
+ return adapter.transaction(
314
+ searchPath ? {
315
+ locals: {
316
+ search_path: typeof searchPath === "function" ? searchPath() : searchPath
317
+ }
318
+ } : void 0,
319
+ fn
320
+ );
320
321
  };
321
322
  const queryLock = (trx) => trx.query(`SELECT pg_advisory_xact_lock('${RAKE_DB_LOCK_KEY}')`);
322
323
  const getCliParam = (args, name) => {
@@ -344,22 +345,22 @@ const getCurrentChanges = () => currentChanges;
344
345
  const pushChange = (change) => currentChanges.push(change);
345
346
 
346
347
  const versionToString = (config, version) => config.migrationId === "timestamp" ? `${version}` : `${version}`.padStart(config.migrationId.serial, "0");
347
- const columnTypeToSql = (config, item) => {
348
- return item.data.isOfCustomType ? item instanceof pqb.DomainColumn ? quoteNameFromString(config, item.dataType) : quoteCustomType(config, item.toSQL()) : item.toSQL();
348
+ const columnTypeToSql = (schema, item) => {
349
+ return item.data.isOfCustomType ? item instanceof pqb.DomainColumn ? quoteNameFromString(schema, item.dataType) : quoteCustomType(schema, item.toSQL()) : item.toSQL();
349
350
  };
350
351
  const getColumnName = (item, key, snakeCase) => {
351
352
  return item.data.name || (snakeCase ? pqb.toSnakeCase(key) : key);
352
353
  };
353
- const columnToSql = (config, name, item, values, hasMultiplePrimaryKeys, snakeCase) => {
354
- const line = [`"${name}" ${columnTypeToSql(config, item)}`];
354
+ const columnToSql = (schema, name, item, values, hasMultiplePrimaryKeys, snakeCase) => {
355
+ const line = [`"${name}" ${columnTypeToSql(schema, item)}`];
355
356
  if (item.data.compression) {
356
357
  line.push(`COMPRESSION ${item.data.compression}`);
357
358
  }
358
359
  if (item.data.collate) {
359
- line.push(`COLLATE ${quoteNameFromString(config, item.data.collate)}`);
360
+ line.push(`COLLATE ${quoteNameFromString(schema, item.data.collate)}`);
360
361
  }
361
362
  if (item.data.identity) {
362
- line.push(identityToSql(config, item.data.identity));
363
+ line.push(identityToSql(schema, item.data.identity));
363
364
  } else if (item.data.generated) {
364
365
  line.push(
365
366
  `GENERATED ALWAYS AS (${item.data.generated.toSQL({
@@ -393,7 +394,7 @@ const columnToSql = (config, name, item, values, hasMultiplePrimaryKeys, snakeCa
393
394
  }
394
395
  line.push(
395
396
  referencesToSql(
396
- config,
397
+ schema,
397
398
  {
398
399
  columns: [name],
399
400
  ...foreignKey
@@ -417,11 +418,11 @@ const encodeColumnDefault = (def, values, column) => {
417
418
  }
418
419
  return null;
419
420
  };
420
- const identityToSql = (config, identity) => {
421
- const options = sequenceOptionsToSql(config, identity);
421
+ const identityToSql = (schema, identity) => {
422
+ const options = sequenceOptionsToSql(schema, identity);
422
423
  return `GENERATED ${identity.always ? "ALWAYS" : "BY DEFAULT"} AS IDENTITY${options ? ` (${options})` : ""}`;
423
424
  };
424
- const sequenceOptionsToSql = (config, item) => {
425
+ const sequenceOptionsToSql = (schema, item) => {
425
426
  const line = [];
426
427
  if (item.dataType) line.push(`AS ${item.dataType}`);
427
428
  if (item.increment !== void 0) line.push(`INCREMENT BY ${item.increment}`);
@@ -431,8 +432,8 @@ const sequenceOptionsToSql = (config, item) => {
431
432
  if (item.cache !== void 0) line.push(`CACHE ${item.cache}`);
432
433
  if (item.cycle) line.push(`CYCLE`);
433
434
  if (item.ownedBy) {
434
- const [schema, table] = getSchemaAndTableFromName(config, item.ownedBy);
435
- line.push(`OWNED BY ${quoteTable(schema, table)}`);
435
+ const [s, table] = getSchemaAndTableFromName(schema, item.ownedBy);
436
+ line.push(`OWNED BY ${quoteTable(s, table)}`);
436
437
  }
437
438
  return line.join(" ");
438
439
  };
@@ -461,9 +462,9 @@ const addColumnComment = (comments, name, item) => {
461
462
  comments.push({ column: name, comment: item.data.comment });
462
463
  }
463
464
  };
464
- const getForeignKeyTable = (config, fnOrTable) => {
465
+ const getForeignKeyTable = (schema, fnOrTable) => {
465
466
  if (typeof fnOrTable === "string") {
466
- return getSchemaAndTableFromName(config, fnOrTable);
467
+ return getSchemaAndTableFromName(schema, fnOrTable);
467
468
  }
468
469
  const item = new (fnOrTable())();
469
470
  return [item.schema, item.table];
@@ -480,7 +481,7 @@ const getConstraintName = (table, constraint, snakeCase) => {
480
481
  if (constraint.identity) return `${table}_identity`;
481
482
  return `${table}_constraint`;
482
483
  };
483
- const constraintToSql = (config, { name }, up, constraint, values, snakeCase) => {
484
+ const constraintToSql = (schema, { name }, up, constraint, values, snakeCase) => {
484
485
  const constraintName = constraint.name || getConstraintName(name, constraint, snakeCase);
485
486
  if (!up) {
486
487
  const { dropMode } = constraint;
@@ -488,7 +489,7 @@ const constraintToSql = (config, { name }, up, constraint, values, snakeCase) =>
488
489
  }
489
490
  const sql = [`CONSTRAINT "${constraintName}"`];
490
491
  if (constraint.references) {
491
- sql.push(foreignKeyToSql(config, constraint.references, snakeCase));
492
+ sql.push(foreignKeyToSql(schema, constraint.references, snakeCase));
492
493
  }
493
494
  if (constraint.check) {
494
495
  sql.push(checkToSql(constraint.check, values));
@@ -498,15 +499,15 @@ const constraintToSql = (config, { name }, up, constraint, values, snakeCase) =>
498
499
  const checkToSql = (check, values) => {
499
500
  return `CHECK (${check.toSQL({ values })})`;
500
501
  };
501
- const foreignKeyToSql = (config, item, snakeCase) => {
502
+ const foreignKeyToSql = (schema, item, snakeCase) => {
502
503
  return `FOREIGN KEY (${joinColumns(
503
504
  snakeCase ? item.columns.map(pqb.toSnakeCase) : item.columns
504
- )}) ${referencesToSql(config, item, snakeCase)}`;
505
+ )}) ${referencesToSql(schema, item, snakeCase)}`;
505
506
  };
506
- const referencesToSql = (config, references, snakeCase) => {
507
- const [schema, table] = getForeignKeyTable(config, references.fnOrTable);
507
+ const referencesToSql = (schema, references, snakeCase) => {
508
+ const [s, table] = getForeignKeyTable(schema, references.fnOrTable);
508
509
  const sql = [
509
- `REFERENCES ${quoteTable(schema, table)}(${joinColumns(
510
+ `REFERENCES ${quoteTable(s, table)}(${joinColumns(
510
511
  snakeCase ? references.foreignColumns.map(pqb.toSnakeCase) : references.foreignColumns
511
512
  )})`
512
513
  ];
@@ -555,7 +556,7 @@ const getIndexOrExcludeName = (table, columns, suffix) => makeConstraintName(
555
556
  );
556
557
  const getIndexName = (table, columns) => getIndexOrExcludeName(table, columns, "idx");
557
558
  const getExcludeName = (table, columns) => getIndexOrExcludeName(table, columns, "exclude");
558
- const indexesToQuery = (config, up, { schema, name: tableName }, indexes, snakeCase, language) => {
559
+ const indexesToQuery = (up, { schema, name: tableName }, indexes, snakeCase, language) => {
559
560
  return indexes.map((index) => {
560
561
  const { options } = index;
561
562
  const { columns, include, name } = getIndexOrExcludeMainOptions(
@@ -584,7 +585,7 @@ const indexesToQuery = (config, up, { schema, name: tableName }, indexes, snakeC
584
585
  const columnsSql = columns.map((column) => {
585
586
  let sql2 = [
586
587
  "expression" in column ? `(${column.expression})` : `"${column.column}"`,
587
- column.collate && `COLLATE ${quoteNameFromString(config, column.collate)}`,
588
+ column.collate && `COLLATE ${quoteNameFromString(schema, column.collate)}`,
588
589
  column.opclass,
589
590
  column.order
590
591
  ].filter((x) => !!x).join(" ");
@@ -628,7 +629,7 @@ const indexesToQuery = (config, up, { schema, name: tableName }, indexes, snakeC
628
629
  return { text: sql.join(" "), values };
629
630
  });
630
631
  };
631
- const excludesToQuery = (config, up, { schema, name: tableName }, excludes, snakeCase) => {
632
+ const excludesToQuery = (up, { schema, name: tableName }, excludes, snakeCase) => {
632
633
  return excludes.map((exclude) => {
633
634
  const { options } = exclude;
634
635
  const { columns, include, name } = getIndexOrExcludeMainOptions(
@@ -648,7 +649,7 @@ const excludesToQuery = (config, up, { schema, name: tableName }, excludes, snak
648
649
  const columnList = columns.map(
649
650
  (column) => [
650
651
  "expression" in column ? `(${column.expression})` : `"${column.column}"`,
651
- column.collate && `COLLATE ${quoteNameFromString(config, column.collate)}`,
652
+ column.collate && `COLLATE ${quoteNameFromString(schema, column.collate)}`,
652
653
  column.opclass,
653
654
  column.order,
654
655
  `WITH ${column.with}`
@@ -715,22 +716,23 @@ const cmpRawSql = (a, b) => {
715
716
  const bValues = JSON.stringify(values);
716
717
  return aSql === bSql && aValues === bValues;
717
718
  };
718
- const getMigrationsSchemaAndTable = (config) => {
719
+ const getMigrationsSchemaAndTable = (adapter, config) => {
720
+ const schema = adapter.getSchema();
719
721
  const [tableSchema, table] = getSchemaAndTableFromName(
720
- config,
722
+ schema,
721
723
  config.migrationsTable
722
724
  );
723
- let schema = tableSchema;
724
- if (!schema) {
725
- schema = typeof config.schema === "function" ? config.schema() : config.schema;
726
- if (schema === "public") {
727
- schema = void 0;
725
+ let s = tableSchema;
726
+ if (!s) {
727
+ s = typeof schema === "function" ? schema() : schema;
728
+ if (s === "public") {
729
+ s = void 0;
728
730
  }
729
731
  }
730
- return { schema, table };
732
+ return { schema: s, table };
731
733
  };
732
- const migrationsSchemaTableSql = (config) => {
733
- const { schema, table } = getMigrationsSchemaAndTable(config);
734
+ const migrationsSchemaTableSql = (adapter, config) => {
735
+ const { schema, table } = getMigrationsSchemaAndTable(adapter, config);
734
736
  return `${schema ? `"${schema}".` : ""}"${table}"`;
735
737
  };
736
738
 
@@ -787,8 +789,9 @@ const createTable = async (migration, up, tableName, first, second, third) => {
787
789
  } else {
788
790
  shape = tableData = pqb.emptyObject;
789
791
  }
790
- const ast = makeAst$2(
791
- migration.options,
792
+ const schema = migration.adapter.getSchema();
793
+ const ast = makeAst$3(
794
+ schema,
792
795
  up,
793
796
  tableName,
794
797
  shape,
@@ -797,7 +800,7 @@ const createTable = async (migration, up, tableName, first, second, third) => {
797
800
  migration.options.noPrimaryKey
798
801
  );
799
802
  fn && validatePrimaryKey(ast);
800
- const queries = astToQueries$1(migration.options, ast, snakeCase, language);
803
+ const queries = astToQueries$1(schema, ast, snakeCase, language);
801
804
  for (const { then, ...query } of queries) {
802
805
  const result = await migration.adapter.arrays(interpolateSqlValues(query));
803
806
  then?.(result);
@@ -817,7 +820,7 @@ const createTable = async (migration, up, tableName, first, second, third) => {
817
820
  }
818
821
  };
819
822
  };
820
- const makeAst$2 = (config, up, tableName, shape, tableData, options, noPrimaryKey) => {
823
+ const makeAst$3 = (schema, up, tableName, shape, tableData, options, noPrimaryKey) => {
821
824
  const shapePKeys = [];
822
825
  for (const key in shape) {
823
826
  const column = shape[key];
@@ -826,11 +829,11 @@ const makeAst$2 = (config, up, tableName, shape, tableData, options, noPrimaryKe
826
829
  }
827
830
  }
828
831
  const { primaryKey } = tableData;
829
- const [schema, table] = getSchemaAndTableFromName(config, tableName);
832
+ const [s, table] = getSchemaAndTableFromName(schema, tableName);
830
833
  return {
831
834
  type: "table",
832
835
  action: up ? "create" : "drop",
833
- schema,
836
+ schema: s,
834
837
  name: table,
835
838
  shape,
836
839
  ...tableData,
@@ -866,13 +869,13 @@ You can suppress this error by setting { noPrimaryKey: true } after a table name
866
869
  }
867
870
  }
868
871
  };
869
- const astToQueries$1 = (config, ast, snakeCase, language) => {
872
+ const astToQueries$1 = (schema, ast, snakeCase, language) => {
870
873
  const queries = [];
871
874
  const { shape } = ast;
872
875
  for (const key in shape) {
873
876
  const item = shape[key];
874
877
  if (!(item instanceof pqb.EnumColumn)) continue;
875
- queries.push(makePopulateEnumQuery(config, item));
878
+ queries.push(makePopulateEnumQuery(schema, item));
876
879
  }
877
880
  if (ast.action === "drop") {
878
881
  queries.push({
@@ -894,7 +897,7 @@ const astToQueries$1 = (config, ast, snakeCase, language) => {
894
897
  lines.push(
895
898
  `
896
899
  ${columnToSql(
897
- config,
900
+ schema,
898
901
  name,
899
902
  item,
900
903
  values,
@@ -918,7 +921,7 @@ const astToQueries$1 = (config, ast, snakeCase, language) => {
918
921
  lines.push(
919
922
  `
920
923
  ${constraintToSql(
921
- config,
924
+ schema,
922
925
  ast,
923
926
  true,
924
927
  {
@@ -943,8 +946,8 @@ const astToQueries$1 = (config, ast, snakeCase, language) => {
943
946
  )`,
944
947
  values
945
948
  },
946
- ...indexesToQuery(config, true, ast, indexes, snakeCase, language),
947
- ...excludesToQuery(config, true, ast, excludes, snakeCase),
949
+ ...indexesToQuery(true, ast, indexes, snakeCase, language),
950
+ ...excludesToQuery(true, ast, excludes, snakeCase),
948
951
  ...commentsToQuery(ast, comments)
949
952
  );
950
953
  if (ast.comment) {
@@ -1166,21 +1169,22 @@ const changeTable = async (migration, up, tableName, options, fn) => {
1166
1169
  tableChanger[pqb.snakeCaseKey] = snakeCase;
1167
1170
  addOrDropChanges.length = 0;
1168
1171
  const changeData = fn?.(tableChanger) || {};
1169
- const ast = makeAst$1(
1170
- migration.options,
1172
+ const schema = migration.adapter.getSchema();
1173
+ const ast = makeAst$2(
1174
+ schema,
1171
1175
  up,
1172
1176
  tableName,
1173
1177
  changeData,
1174
1178
  changeTableData,
1175
1179
  options
1176
1180
  );
1177
- const queries = astToQueries(migration.options, ast, snakeCase, language);
1181
+ const queries = astToQueries(schema, ast, snakeCase, language);
1178
1182
  for (const query of queries) {
1179
1183
  const result = await migration.adapter.arrays(interpolateSqlValues(query));
1180
1184
  query.then?.(result);
1181
1185
  }
1182
1186
  };
1183
- const makeAst$1 = (config, up, name, changeData, changeTableData2, options) => {
1187
+ const makeAst$2 = (schema, up, name, changeData, changeTableData2, options) => {
1184
1188
  const { comment } = options;
1185
1189
  const shape = {};
1186
1190
  const consumedChanges = {};
@@ -1225,17 +1229,17 @@ const makeAst$1 = (config, up, name, changeData, changeTableData2, options) => {
1225
1229
  );
1226
1230
  shape[name2] = arr;
1227
1231
  }
1228
- const [schema, table] = getSchemaAndTableFromName(config, name);
1232
+ const [s, table] = getSchemaAndTableFromName(schema, name);
1229
1233
  return {
1230
1234
  type: "changeTable",
1231
- schema,
1235
+ schema: s,
1232
1236
  name: table,
1233
1237
  comment: comment ? up ? Array.isArray(comment) ? comment[1] : comment : Array.isArray(comment) ? comment[0] : null : void 0,
1234
1238
  shape,
1235
1239
  ...up ? changeTableData2 : { add: changeTableData2.drop, drop: changeTableData2.add }
1236
1240
  };
1237
1241
  };
1238
- const astToQueries = (config, ast, snakeCase, language) => {
1242
+ const astToQueries = (schema, ast, snakeCase, language) => {
1239
1243
  const queries = [];
1240
1244
  if (ast.comment !== void 0) {
1241
1245
  queries.push({
@@ -1255,7 +1259,7 @@ const astToQueries = (config, ast, snakeCase, language) => {
1255
1259
  if (Array.isArray(item)) {
1256
1260
  for (const it of item) {
1257
1261
  handlePrerequisitesForTableItem(
1258
- config,
1262
+ schema,
1259
1263
  key,
1260
1264
  it,
1261
1265
  queries,
@@ -1266,7 +1270,7 @@ const astToQueries = (config, ast, snakeCase, language) => {
1266
1270
  }
1267
1271
  } else {
1268
1272
  handlePrerequisitesForTableItem(
1269
- config,
1273
+ schema,
1270
1274
  key,
1271
1275
  item,
1272
1276
  queries,
@@ -1305,7 +1309,7 @@ const astToQueries = (config, ast, snakeCase, language) => {
1305
1309
  if (Array.isArray(item)) {
1306
1310
  for (const it of item) {
1307
1311
  handleTableItemChange(
1308
- config,
1312
+ schema,
1309
1313
  key,
1310
1314
  it,
1311
1315
  ast,
@@ -1325,7 +1329,7 @@ const astToQueries = (config, ast, snakeCase, language) => {
1325
1329
  }
1326
1330
  } else {
1327
1331
  handleTableItemChange(
1328
- config,
1332
+ schema,
1329
1333
  key,
1330
1334
  item,
1331
1335
  ast,
@@ -1359,7 +1363,7 @@ const astToQueries = (config, ast, snakeCase, language) => {
1359
1363
  ...dropConstraints.map(
1360
1364
  (foreignKey) => `
1361
1365
  DROP ${constraintToSql(
1362
- config,
1366
+ schema,
1363
1367
  ast,
1364
1368
  false,
1365
1369
  foreignKey,
@@ -1384,7 +1388,7 @@ const astToQueries = (config, ast, snakeCase, language) => {
1384
1388
  ...addConstraints.map(
1385
1389
  (foreignKey) => `
1386
1390
  ADD ${constraintToSql(
1387
- config,
1391
+ schema,
1388
1392
  ast,
1389
1393
  true,
1390
1394
  foreignKey,
@@ -1406,14 +1410,10 @@ const astToQueries = (config, ast, snakeCase, language) => {
1406
1410
  if (alterTable.length) {
1407
1411
  queries.push(alterTableSql(tableName, alterTable, values));
1408
1412
  }
1409
- queries.push(
1410
- ...indexesToQuery(config, false, ast, dropIndexes, snakeCase, language)
1411
- );
1412
- queries.push(
1413
- ...indexesToQuery(config, true, ast, addIndexes, snakeCase, language)
1414
- );
1415
- queries.push(...excludesToQuery(config, false, ast, dropExcludes, snakeCase));
1416
- queries.push(...excludesToQuery(config, true, ast, addExcludes, snakeCase));
1413
+ queries.push(...indexesToQuery(false, ast, dropIndexes, snakeCase, language));
1414
+ queries.push(...indexesToQuery(true, ast, addIndexes, snakeCase, language));
1415
+ queries.push(...excludesToQuery(false, ast, dropExcludes, snakeCase));
1416
+ queries.push(...excludesToQuery(true, ast, addExcludes, snakeCase));
1417
1417
  queries.push(...commentsToQuery(ast, comments));
1418
1418
  return queries;
1419
1419
  };
@@ -1422,11 +1422,11 @@ const alterTableSql = (tableName, lines, values) => ({
1422
1422
  ${lines.join(",\n ")}`,
1423
1423
  values
1424
1424
  });
1425
- const handlePrerequisitesForTableItem = (config, key, item, queries, addPrimaryKeys, dropPrimaryKeys, snakeCase) => {
1425
+ const handlePrerequisitesForTableItem = (schema, key, item, queries, addPrimaryKeys, dropPrimaryKeys, snakeCase) => {
1426
1426
  if ("item" in item) {
1427
1427
  const { item: column } = item;
1428
1428
  if (column instanceof pqb.EnumColumn) {
1429
- queries.push(makePopulateEnumQuery(config, column));
1429
+ queries.push(makePopulateEnumQuery(schema, column));
1430
1430
  }
1431
1431
  }
1432
1432
  if (item.type === "add") {
@@ -1439,10 +1439,10 @@ const handlePrerequisitesForTableItem = (config, key, item, queries, addPrimaryK
1439
1439
  }
1440
1440
  } else if (item.type === "change") {
1441
1441
  if (item.from.column instanceof pqb.EnumColumn) {
1442
- queries.push(makePopulateEnumQuery(config, item.from.column));
1442
+ queries.push(makePopulateEnumQuery(schema, item.from.column));
1443
1443
  }
1444
1444
  if (item.to.column instanceof pqb.EnumColumn) {
1445
- queries.push(makePopulateEnumQuery(config, item.to.column));
1445
+ queries.push(makePopulateEnumQuery(schema, item.to.column));
1446
1446
  }
1447
1447
  if (item.from.primaryKey) {
1448
1448
  dropPrimaryKeys.columns.push(
@@ -1458,7 +1458,7 @@ const handlePrerequisitesForTableItem = (config, key, item, queries, addPrimaryK
1458
1458
  }
1459
1459
  }
1460
1460
  };
1461
- const handleTableItemChange = (config, key, item, ast, alterTable, renameItems, values, addPrimaryKeys, addIndexes, dropIndexes, addExcludes, dropExcludes, addConstraints, dropConstraints, comments, snakeCase) => {
1461
+ const handleTableItemChange = (schema, key, item, ast, alterTable, renameItems, values, addPrimaryKeys, addIndexes, dropIndexes, addExcludes, dropExcludes, addConstraints, dropConstraints, comments, snakeCase) => {
1462
1462
  if (item.type === "add") {
1463
1463
  const column = item.item;
1464
1464
  const name = getColumnName(column, key, snakeCase);
@@ -1467,7 +1467,7 @@ const handleTableItemChange = (config, key, item, ast, alterTable, renameItems,
1467
1467
  addColumnComment(comments, name, column);
1468
1468
  alterTable.push(
1469
1469
  `ADD COLUMN ${columnToSql(
1470
- config,
1470
+ schema,
1471
1471
  name,
1472
1472
  column,
1473
1473
  values,
@@ -1490,10 +1490,10 @@ const handleTableItemChange = (config, key, item, ast, alterTable, renameItems,
1490
1490
  let changeType = false;
1491
1491
  if (to.type && (from.type !== to.type || from.collate !== to.collate)) {
1492
1492
  changeType = true;
1493
- const type = !to.column || to.column.data.isOfCustomType ? to.column && to.column instanceof pqb.DomainColumn ? quoteNameFromString(config, to.type) : quoteCustomType(config, to.type) : to.type;
1493
+ const type = !to.column || to.column.data.isOfCustomType ? to.column && to.column instanceof pqb.DomainColumn ? quoteNameFromString(schema, to.type) : quoteCustomType(schema, to.type) : to.type;
1494
1494
  const using = item.using?.usingUp ? ` USING ${item.using.usingUp.toSQL({ values })}` : to.column instanceof pqb.EnumColumn ? ` USING "${name}"::text::${type}` : to.column instanceof pqb.ArrayColumn ? ` USING "${name}"::text[]::${type}` : "";
1495
1495
  alterTable.push(
1496
- `ALTER COLUMN "${name}" TYPE ${type}${to.collate ? ` COLLATE ${quoteNameFromString(config, to.collate)}` : ""}${using}`
1496
+ `ALTER COLUMN "${name}" TYPE ${type}${to.collate ? ` COLLATE ${quoteNameFromString(schema, to.collate)}` : ""}${using}`
1497
1497
  );
1498
1498
  }
1499
1499
  if (typeof from.identity !== typeof to.identity || !pqb.deepCompare(from.identity, to.identity)) {
@@ -1502,7 +1502,7 @@ const handleTableItemChange = (config, key, item, ast, alterTable, renameItems,
1502
1502
  }
1503
1503
  if (to.identity) {
1504
1504
  alterTable.push(
1505
- `ALTER COLUMN "${name}" ADD ${identityToSql(config, to.identity)}`
1505
+ `ALTER COLUMN "${name}" ADD ${identityToSql(schema, to.identity)}`
1506
1506
  );
1507
1507
  }
1508
1508
  }
@@ -1635,19 +1635,20 @@ const renameColumnSql = (from, to) => {
1635
1635
  };
1636
1636
 
1637
1637
  const createView = async (migration, up, name, options, sql) => {
1638
- const ast = makeAst(migration.options, up, name, options, sql);
1639
- const query = astToQuery(ast);
1638
+ const schema = migration.adapter.getSchema();
1639
+ const ast = makeAst$1(schema, up, name, options, sql);
1640
+ const query = astToQuery$1(ast);
1640
1641
  await migration.adapter.arrays(interpolateSqlValues(query));
1641
1642
  };
1642
- const makeAst = (config, up, fullName, options, sql) => {
1643
+ const makeAst$1 = (schema, up, fullName, options, sql) => {
1643
1644
  if (typeof sql === "string") {
1644
1645
  sql = pqb.raw({ raw: sql });
1645
1646
  }
1646
- const [schema, name] = getSchemaAndTableFromName(config, fullName);
1647
+ const [s, name] = getSchemaAndTableFromName(schema, fullName);
1647
1648
  return {
1648
1649
  type: "view",
1649
1650
  action: up ? "create" : "drop",
1650
- schema,
1651
+ schema: s,
1651
1652
  name,
1652
1653
  shape: {},
1653
1654
  sql,
@@ -1655,7 +1656,7 @@ const makeAst = (config, up, fullName, options, sql) => {
1655
1656
  deps: []
1656
1657
  };
1657
1658
  };
1658
- const astToQuery = (ast) => {
1659
+ const astToQuery$1 = (ast) => {
1659
1660
  const values = [];
1660
1661
  const sql = [];
1661
1662
  const { options } = ast;
@@ -1692,6 +1693,130 @@ const astToQuery = (ast) => {
1692
1693
  };
1693
1694
  };
1694
1695
 
1696
+ const serializers = {
1697
+ super: (b) => `${b ? "" : "NO"}SUPERUSER`,
1698
+ inherit: (b) => `${b ? "" : "NO"}INHERIT`,
1699
+ createRole: (b) => `${b ? "" : "NO"}CREATEROLE`,
1700
+ createDb: (b) => `${b ? "" : "NO"}CREATEDB`,
1701
+ canLogin: (b) => `${b ? "" : "NO"}LOGIN`,
1702
+ replication: (b) => `${b ? "" : "NO"}REPLICATION`,
1703
+ bypassRls: (b) => `${b ? "" : "NO"}BYPASSRLS`,
1704
+ connLimit: (value) => `CONNECTION LIMIT ${value === void 0 ? -1 : value}`,
1705
+ validUntil: (value) => `VALID UNTIL '${value === void 0 ? "infinity" : value}'`
1706
+ };
1707
+ const createOrDropRole = async (migration, up, name, params) => {
1708
+ const ast = makeAst(up, name, params);
1709
+ const sql = astToQuery(ast);
1710
+ await migration.adapter.arrays(sql);
1711
+ };
1712
+ const makeAst = (up, name, params) => {
1713
+ return {
1714
+ type: "role",
1715
+ action: up ? "create" : "drop",
1716
+ name,
1717
+ super: false,
1718
+ inherit: false,
1719
+ createRole: false,
1720
+ createDb: false,
1721
+ canLogin: false,
1722
+ replication: false,
1723
+ connLimit: -1,
1724
+ bypassRls: false,
1725
+ ...params
1726
+ };
1727
+ };
1728
+ const astToQuery = (ast) => {
1729
+ const w = [];
1730
+ if (ast.action !== "drop") {
1731
+ for (const key in ast) {
1732
+ if (key in serializers && (key !== "connLimit" || ast[key] !== -1)) {
1733
+ let value = ast[key];
1734
+ if (value instanceof Date) value = value.toISOString();
1735
+ w.push(serializers[key](value));
1736
+ }
1737
+ }
1738
+ }
1739
+ let sql = `${ast.action.toUpperCase()} ROLE "${ast.name}"${w.length ? ` WITH ${w.join(" ")}` : ""}`;
1740
+ if (ast.action !== "drop" && ast.config) {
1741
+ for (const [key, value] of Object.entries(ast.config)) {
1742
+ sql += `;
1743
+ ALTER ROLE "${ast.name}" SET ${key} = '${value}'`;
1744
+ }
1745
+ }
1746
+ return sql;
1747
+ };
1748
+ const changeRole = async (migration, up, name, from, to) => {
1749
+ if (!up) {
1750
+ if (to.name) {
1751
+ from = { ...from, name };
1752
+ name = to.name;
1753
+ }
1754
+ const f = from;
1755
+ from = to;
1756
+ to = { ...f };
1757
+ for (const key in from) {
1758
+ if (!(key in to)) {
1759
+ to[key] = void 0;
1760
+ }
1761
+ }
1762
+ if (from.config) {
1763
+ const config = to.config ?? (to.config = {});
1764
+ for (const key in from.config) {
1765
+ if (!(key in config)) {
1766
+ config[key] = void 0;
1767
+ }
1768
+ }
1769
+ }
1770
+ }
1771
+ const ast = makeChangeAst(name, from, to);
1772
+ const sql = changeAstToQuery(ast);
1773
+ if (sql) await migration.adapter.arrays(sql);
1774
+ };
1775
+ const makeChangeAst = (name, from, to) => {
1776
+ return {
1777
+ type: "changeRole",
1778
+ name,
1779
+ from,
1780
+ to
1781
+ };
1782
+ };
1783
+ const changeAstToQuery = ({ name, from, to }) => {
1784
+ const queries = [];
1785
+ if (to.name && to.name !== name) {
1786
+ queries.push(`ALTER ROLE "${name}" RENAME TO "${to.name}"`);
1787
+ name = to.name;
1788
+ }
1789
+ const w = [];
1790
+ for (const key in to) {
1791
+ let value = to[key];
1792
+ if (key !== "config") {
1793
+ if (value instanceof Date) value = value.toISOString();
1794
+ let other = from[key];
1795
+ if (other instanceof Date) other = other.toISOString();
1796
+ if (value !== other && key in serializers) {
1797
+ w.push(serializers[key](value));
1798
+ }
1799
+ }
1800
+ }
1801
+ if (w.length) {
1802
+ queries.push(`ALTER ROLE "${name}" WITH ${w.join(" ")}`);
1803
+ }
1804
+ const config = to.config;
1805
+ if (config) {
1806
+ const fromConfig = from.config ?? pqb.emptyObject;
1807
+ for (const key in config) {
1808
+ const value = config[key];
1809
+ const other = fromConfig[key];
1810
+ if (value !== other) {
1811
+ queries.push(
1812
+ `ALTER ROLE "${name}" ${value ? `SET ${key} = '${value}'` : `RESET ${key}`}`
1813
+ );
1814
+ }
1815
+ }
1816
+ }
1817
+ return queries.join(";\n");
1818
+ };
1819
+
1695
1820
  const createMigrationInterface = (tx, up, config) => {
1696
1821
  const adapter = Object.create(tx);
1697
1822
  const { query, arrays } = adapter;
@@ -2235,7 +2360,10 @@ class Migration {
2235
2360
  * @param values - object where keys are for old names, values are for new names
2236
2361
  */
2237
2362
  async renameEnumValues(enumName, values) {
2238
- const [schema, name] = getSchemaAndTableFromName(this.options, enumName);
2363
+ const [schema, name] = getSchemaAndTableFromName(
2364
+ this.adapter.getSchema(),
2365
+ enumName
2366
+ );
2239
2367
  const ast = {
2240
2368
  type: "renameEnumValues",
2241
2369
  schema,
@@ -2500,7 +2628,10 @@ class Migration {
2500
2628
  */
2501
2629
  async tableExists(tableName) {
2502
2630
  let text = `SELECT 1 FROM "information_schema"."tables" WHERE "table_name" = $1`;
2503
- const [schema, table] = getSchemaAndTableFromName(this.options, tableName);
2631
+ const [schema, table] = getSchemaAndTableFromName(
2632
+ this.adapter.getSchema(),
2633
+ tableName
2634
+ );
2504
2635
  const values = [table];
2505
2636
  if (schema) {
2506
2637
  text += ' AND "table_schema" = $2';
@@ -2531,7 +2662,10 @@ class Migration {
2531
2662
  */
2532
2663
  async columnExists(tableName, columnName) {
2533
2664
  let text = `SELECT 1 FROM "information_schema"."columns" WHERE "table_name" = $1 AND "column_name" = $2`;
2534
- const [schema, table] = getSchemaAndTableFromName(this.options, tableName);
2665
+ const [schema, table] = getSchemaAndTableFromName(
2666
+ this.adapter.getSchema(),
2667
+ tableName
2668
+ );
2535
2669
  const values = [
2536
2670
  table,
2537
2671
  this.options.snakeCase ? pqb.toSnakeCase(columnName) : columnName
@@ -2566,6 +2700,21 @@ class Migration {
2566
2700
  values: [constraintName]
2567
2701
  });
2568
2702
  }
2703
+ createRole(name, params) {
2704
+ return createOrDropRole(this, this.up, name, params);
2705
+ }
2706
+ dropRole(name, params) {
2707
+ return createOrDropRole(this, !this.up, name, params);
2708
+ }
2709
+ changeRole(name, params) {
2710
+ return changeRole(
2711
+ this,
2712
+ this.up,
2713
+ name,
2714
+ params.from || pqb.emptyObject,
2715
+ params.to
2716
+ );
2717
+ }
2569
2718
  }
2570
2719
  const wrapWithLog = async (log, text, values, fn) => {
2571
2720
  if (!log) {
@@ -2622,7 +2771,10 @@ const createSchema = async (migration, up, name) => {
2622
2771
  );
2623
2772
  };
2624
2773
  const createExtension = async (migration, up, fullName, options) => {
2625
- const [schema, name] = getSchemaAndTableFromName(migration.options, fullName);
2774
+ const [schema, name] = getSchemaAndTableFromName(
2775
+ migration.adapter.getSchema(),
2776
+ fullName
2777
+ );
2626
2778
  const ast = {
2627
2779
  type: "extension",
2628
2780
  action: up ? "create" : "drop",
@@ -2639,7 +2791,10 @@ const createExtension = async (migration, up, fullName, options) => {
2639
2791
  await migration.adapter.query(query);
2640
2792
  };
2641
2793
  const createEnum = async (migration, up, name, values, options = {}) => {
2642
- const [schema, enumName] = getSchemaAndTableFromName(migration.options, name);
2794
+ const [schema, enumName] = getSchemaAndTableFromName(
2795
+ migration.adapter.getSchema(),
2796
+ name
2797
+ );
2643
2798
  const ast = {
2644
2799
  type: "enum",
2645
2800
  action: up ? "create" : "drop",
@@ -2659,7 +2814,7 @@ const createEnum = async (migration, up, name, values, options = {}) => {
2659
2814
  };
2660
2815
  const createDomain = async (migration, up, name, fn) => {
2661
2816
  const [schema, domainName] = getSchemaAndTableFromName(
2662
- migration.options,
2817
+ migration.adapter.getSchema(),
2663
2818
  name
2664
2819
  );
2665
2820
  const ast = {
@@ -2674,10 +2829,7 @@ const createDomain = async (migration, up, name, fn) => {
2674
2829
  const quotedName = quoteWithSchema(ast);
2675
2830
  if (ast.action === "create") {
2676
2831
  const column = ast.baseType;
2677
- query = `CREATE DOMAIN ${quotedName} AS ${columnTypeToSql(
2678
- migration.options,
2679
- column
2680
- )}${column.data.collate ? `
2832
+ query = `CREATE DOMAIN ${quotedName} AS ${columnTypeToSql(schema, column)}${column.data.collate ? `
2681
2833
  COLLATE "${column.data.collate}"` : ""}${column.data.default !== void 0 ? `
2682
2834
  DEFAULT ${encodeColumnDefault(column.data.default, values)}` : ""}${!column.data.isNullable || column.data.checks ? "\n" : ""}${[
2683
2835
  !column.data.isNullable && "NOT NULL",
@@ -2695,7 +2847,7 @@ DEFAULT ${encodeColumnDefault(column.data.default, values)}` : ""}${!column.data
2695
2847
  };
2696
2848
  const createCollation = async (migration, up, name, options) => {
2697
2849
  const [schema, collationName] = getSchemaAndTableFromName(
2698
- migration.options,
2850
+ migration.adapter.getSchema(),
2699
2851
  name
2700
2852
  );
2701
2853
  const ast = {
@@ -2711,7 +2863,7 @@ const createCollation = async (migration, up, name, options) => {
2711
2863
  query = `CREATE COLLATION${ast.createIfNotExists ? " IF NOT EXISTS" : ""} ${quotedName} `;
2712
2864
  if (ast.fromExisting) {
2713
2865
  query += `FROM ${quoteNameFromString(
2714
- migration.options,
2866
+ migration.adapter.getSchema(),
2715
2867
  ast.fromExisting
2716
2868
  )}`;
2717
2869
  } else {
@@ -2737,11 +2889,11 @@ const queryExists = (db, sql) => {
2737
2889
  };
2738
2890
  const renameType = async (migration, from, to, kind) => {
2739
2891
  const [fromSchema, f] = getSchemaAndTableFromName(
2740
- migration.options,
2892
+ migration.adapter.getSchema(),
2741
2893
  migration.up ? from : to
2742
2894
  );
2743
2895
  const [toSchema, t] = getSchemaAndTableFromName(
2744
- migration.options,
2896
+ migration.adapter.getSchema(),
2745
2897
  migration.up ? to : from
2746
2898
  );
2747
2899
  const ast = {
@@ -2758,14 +2910,15 @@ const renameType = async (migration, from, to, kind) => {
2758
2910
  );
2759
2911
  }
2760
2912
  if (ast.fromSchema !== ast.toSchema) {
2913
+ const schema = migration.adapter.getSchema();
2761
2914
  await migration.adapter.query(
2762
- `ALTER ${ast.kind} ${quoteTable(ast.fromSchema, ast.to)} SET SCHEMA "${ast.toSchema ?? migration.options.schema ?? "public"}"`
2915
+ `ALTER ${ast.kind} ${quoteTable(ast.fromSchema, ast.to)} SET SCHEMA "${ast.toSchema ?? (typeof schema === "function" ? schema() : schema) ?? "public"}"`
2763
2916
  );
2764
2917
  }
2765
2918
  };
2766
2919
  const renameTableItem = async (migration, tableName, from, to, kind) => {
2767
2920
  const [schema, table] = getSchemaAndTableFromName(
2768
- migration.options,
2921
+ migration.adapter.getSchema(),
2769
2922
  tableName
2770
2923
  );
2771
2924
  const [f, t] = migration.up ? [from, to] : [to, from];
@@ -2777,7 +2930,10 @@ const renameTableItem = async (migration, tableName, from, to, kind) => {
2777
2930
  );
2778
2931
  };
2779
2932
  const addOrDropEnumValues = async (migration, up, enumName, values, options) => {
2780
- const [schema, name] = getSchemaAndTableFromName(migration.options, enumName);
2933
+ const [schema, name] = getSchemaAndTableFromName(
2934
+ migration.adapter.getSchema(),
2935
+ enumName
2936
+ );
2781
2937
  const quotedName = quoteTable(schema, name);
2782
2938
  const ast = {
2783
2939
  type: "enumValues",
@@ -2813,7 +2969,10 @@ const addOrDropEnumValues = async (migration, up, enumName, values, options) =>
2813
2969
  );
2814
2970
  };
2815
2971
  const changeEnumValues = async (migration, enumName, fromValues, toValues) => {
2816
- const [schema, name] = getSchemaAndTableFromName(migration.options, enumName);
2972
+ const [schema, name] = getSchemaAndTableFromName(
2973
+ migration.adapter.getSchema(),
2974
+ enumName
2975
+ );
2817
2976
  if (!migration.up) {
2818
2977
  const values = fromValues;
2819
2978
  fromValues = toValues;
@@ -2836,7 +2995,7 @@ const changeEnumValues = async (migration, enumName, fromValues, toValues) => {
2836
2995
  );
2837
2996
  };
2838
2997
  const recreateEnum = async (migration, { schema, name }, values, errorMessage) => {
2839
- const configSchema = migration.options.schema;
2998
+ const configSchema = migration.adapter.getSchema();
2840
2999
  const defaultSchema = (typeof configSchema === "function" ? configSchema() : void 0) ?? "public";
2841
3000
  const quotedName = quoteTable(schema, name);
2842
3001
  const relKinds = ["r", "m"];
@@ -3061,6 +3220,7 @@ ${format === "timestamp" || digits !== 4 ? `Set \`migrationId\`: ${format === "t
3061
3220
  const renameMigrationVersionsInDb = async (config, adapter, values) => {
3062
3221
  await adapter.arrays(
3063
3222
  `UPDATE ${migrationsSchemaTableSql(
3223
+ adapter,
3064
3224
  config
3065
3225
  )} AS t SET version = v.version FROM (VALUES ${values.map(
3066
3226
  ([oldVersion, , newVersion], i) => `('${oldVersion}', $${i + 1}, '${newVersion}')`
@@ -3240,13 +3400,15 @@ function getDigitsPrefix(name) {
3240
3400
  const saveMigratedVersion = async (db, version, name, config) => {
3241
3401
  await db.silentArrays(
3242
3402
  `INSERT INTO ${migrationsSchemaTableSql(
3403
+ db,
3243
3404
  config
3244
3405
  )}(version, name) VALUES ($1, $2)`,
3245
3406
  [version, name]
3246
3407
  );
3247
3408
  };
3248
3409
  const createMigrationsSchemaAndTable = async (db, config) => {
3249
- const { schema, table } = getMigrationsSchemaAndTable(config);
3410
+ const adapter = getMaybeTransactionAdapter(db);
3411
+ const { schema, table } = getMigrationsSchemaAndTable(adapter, config);
3250
3412
  if (schema) {
3251
3413
  const res2 = await createSchema$1(db, schema);
3252
3414
  if (res2 === "done") {
@@ -3266,6 +3428,7 @@ const createMigrationsSchemaAndTable = async (db, config) => {
3266
3428
  const deleteMigratedVersion = async (adapter, version, name, config) => {
3267
3429
  const res = await adapter.silentArrays(
3268
3430
  `DELETE FROM ${migrationsSchemaTableSql(
3431
+ adapter,
3269
3432
  config
3270
3433
  )} WHERE version = $1 AND name = $2`,
3271
3434
  [version, name]
@@ -3278,7 +3441,7 @@ class NoMigrationsTableError extends Error {
3278
3441
  }
3279
3442
  const getMigratedVersionsMap = async (ctx, adapter, config, renameTo) => {
3280
3443
  try {
3281
- const table = migrationsSchemaTableSql(config);
3444
+ const table = migrationsSchemaTableSql(adapter, config);
3282
3445
  const result = await adapter.arrays(
3283
3446
  `SELECT * FROM ${table} ORDER BY version`
3284
3447
  );
@@ -3355,7 +3518,7 @@ async function renameMigrations(config, trx, versions, renameTo) {
3355
3518
  }
3356
3519
 
3357
3520
  const transactionIfSingle = (adapter, config, fn) => {
3358
- return !adapter.isInTransaction() && config.transaction === "single" ? transaction(adapter, fn) : fn(adapter);
3521
+ return config.transaction === "single" ? transaction(adapter, config, fn) : fn(adapter);
3359
3522
  };
3360
3523
  function makeMigrateFn(up, defaultCount, fn) {
3361
3524
  return async (db, config, params) => {
@@ -3408,14 +3571,16 @@ const migrateAndClose = async (db, config, params) => {
3408
3571
  await migrate(adapter, config, params);
3409
3572
  await adapter.close();
3410
3573
  };
3411
- const runMigration = async (db, migration) => {
3412
- await ensureTransaction(db, async (trx) => {
3574
+ async function runMigration(db, ...args) {
3575
+ const [config, migration] = args.length === 1 ? [{}, args[0]] : [args[0], args[1]];
3576
+ const adapter = getMaybeTransactionAdapter(db);
3577
+ await transaction(adapter, config, async (trx) => {
3413
3578
  clearChanges();
3414
3579
  const changes = await getChanges({ load: migration });
3415
- const config = changes[0]?.config;
3416
- await applyMigration(trx, true, changes, config);
3580
+ const config2 = changes[0]?.config;
3581
+ await applyMigration(trx, true, changes, config2);
3417
3582
  });
3418
- };
3583
+ }
3419
3584
  const rollback = makeMigrateFn(
3420
3585
  false,
3421
3586
  1,
@@ -3479,7 +3644,7 @@ const migrateOrRollback = async (trx, config, set, versions, count, up, redo2, f
3479
3644
  }
3480
3645
  let loggedAboutStarting = false;
3481
3646
  let migrations;
3482
- const migrationRunner = trx.isInTransaction() || config.transaction === "single" ? applyMigration : runMigrationInOwnTransaction;
3647
+ const migrationRunner = config.transaction === "single" ? applyMigration : runMigrationInOwnTransaction;
3483
3648
  for (const file of set.migrations) {
3484
3649
  if (up && versionsMap[file.version] || !up && !versionsMap[file.version]) {
3485
3650
  continue;
@@ -3572,8 +3737,12 @@ const getChanges = async (file, config) => {
3572
3737
  }
3573
3738
  return changes;
3574
3739
  };
3575
- const runMigrationInOwnTransaction = (adapter, ...rest) => {
3576
- return transaction(adapter, (trx) => applyMigration(trx, ...rest));
3740
+ const runMigrationInOwnTransaction = (adapter, up, changes, config) => {
3741
+ return transaction(
3742
+ adapter,
3743
+ config,
3744
+ (trx) => applyMigration(trx, up, changes, config)
3745
+ );
3577
3746
  };
3578
3747
  const applyMigration = async (trx, up, changes, config) => {
3579
3748
  const db = createMigrationInterface(trx, up, config);
@@ -3657,9 +3826,10 @@ const createOrDropDatabase = async (action, adapters, config, dontClose) => {
3657
3826
  );
3658
3827
  if (!res) continue;
3659
3828
  if (action === "create") {
3660
- await adapter.transaction(void 0, async (tx) => {
3661
- if (config.schema) {
3662
- const quoted = `"${config.schema}"`;
3829
+ await adapter.transaction(async (tx) => {
3830
+ const schema = tx.getSchema();
3831
+ if (schema) {
3832
+ const quoted = `"${typeof schema === "function" ? schema() : schema}"`;
3663
3833
  const res2 = await createSchema$1(tx, quoted);
3664
3834
  if (res2 === "done") {
3665
3835
  config.logger?.log(`Created schema ${quoted}`);
@@ -3771,7 +3941,7 @@ const astToGenerateItem = (config, ast, currentSchema) => {
3771
3941
  let dep = typeSchemaCache.get(type);
3772
3942
  if (!dep) {
3773
3943
  const [schema = currentSchema, name] = getSchemaAndTableFromName(
3774
- config,
3944
+ currentSchema,
3775
3945
  type
3776
3946
  );
3777
3947
  dep = `${schema}.${name}`;
@@ -3915,6 +4085,10 @@ const astToGenerateItem = (config, ast, currentSchema) => {
3915
4085
  deps.push(tableSchema, `${tableSchema}.${tableName}`);
3916
4086
  break;
3917
4087
  }
4088
+ case "role":
4089
+ case "changeRole": {
4090
+ break;
4091
+ }
3918
4092
  default:
3919
4093
  pqb.exhaustive(ast);
3920
4094
  }
@@ -3964,7 +4138,7 @@ const analyzeTableColumns = (config, currentSchema, schema, table, deps, resolve
3964
4138
  )
3965
4139
  );
3966
4140
  const [s = currentSchema, t] = getForeignKeyTable(
3967
- config,
4141
+ currentSchema,
3968
4142
  fkey.fnOrTable
3969
4143
  );
3970
4144
  const foreignTable = `${s}.${t}`;
@@ -4011,7 +4185,7 @@ const analyzeTableData = (config, currentSchema, schema, table, keys, deps, data
4011
4185
  );
4012
4186
  if (constraint.references) {
4013
4187
  const [s = currentSchema, t] = getForeignKeyTable(
4014
- config,
4188
+ currentSchema,
4015
4189
  constraint.references.fnOrTable
4016
4190
  );
4017
4191
  deps.push(`${s}.${t}`);
@@ -4148,7 +4322,7 @@ const astEncoders = {
4148
4322
  const isShifted = hasOptions || hasTableData;
4149
4323
  if (isShifted) {
4150
4324
  pqb.addCode(code, `await db.${ast.action}Table(`);
4151
- const inner = [`${quoteSchemaTable(ast)},`];
4325
+ const inner = [`${quoteSchemaTable(ast, currentSchema)},`];
4152
4326
  code.push(inner);
4153
4327
  code = inner;
4154
4328
  if (hasOptions) {
@@ -4162,7 +4336,10 @@ const astEncoders = {
4162
4336
  } else {
4163
4337
  pqb.addCode(
4164
4338
  code,
4165
- `await db.${ast.action}Table(${quoteSchemaTable(ast)}, (t) => ({`
4339
+ `await db.${ast.action}Table(${quoteSchemaTable(
4340
+ ast,
4341
+ currentSchema
4342
+ )}, (t) => ({`
4166
4343
  );
4167
4344
  }
4168
4345
  const timestamps = getHasTimestamps(
@@ -4373,9 +4550,9 @@ const astEncoders = {
4373
4550
  ast.to
4374
4551
  )});`;
4375
4552
  },
4376
- extension(ast) {
4553
+ extension(ast, _, currentSchema) {
4377
4554
  const code = [
4378
- `await db.${ast.action}Extension(${quoteSchemaTable(ast)}`
4555
+ `await db.${ast.action}Extension(${quoteSchemaTable(ast, currentSchema)}`
4379
4556
  ];
4380
4557
  if (ast.version) {
4381
4558
  pqb.addCode(code, ", {");
@@ -4409,13 +4586,14 @@ const astEncoders = {
4409
4586
  },
4410
4587
  domain(ast, _, currentSchema) {
4411
4588
  return `await db.${ast.action}Domain(${quoteSchemaTable(
4412
- ast
4589
+ ast,
4590
+ currentSchema
4413
4591
  )}, (t) => ${ast.baseType.toCode(
4414
4592
  { t: "t", table: ast.name, currentSchema },
4415
4593
  ast.baseType.data.name ?? ""
4416
4594
  )});`;
4417
4595
  },
4418
- collation(ast) {
4596
+ collation(ast, _, currentSchema) {
4419
4597
  const params = [];
4420
4598
  if (ast.locale) params.push(`locale: '${ast.locale}',`);
4421
4599
  if (ast.lcCollate) params.push(`lcCollate: '${ast.lcCollate}',`);
@@ -4424,7 +4602,7 @@ const astEncoders = {
4424
4602
  if (ast.deterministic) params.push(`deterministic: ${ast.deterministic},`);
4425
4603
  if (ast.version) params.push(`version: '${ast.version}',`);
4426
4604
  return [
4427
- `await db.createCollation(${quoteSchemaTable(ast)}, {`,
4605
+ `await db.createCollation(${quoteSchemaTable(ast, currentSchema)}, {`,
4428
4606
  params,
4429
4607
  "});"
4430
4608
  ];
@@ -4454,8 +4632,10 @@ const astEncoders = {
4454
4632
  })}, ${pqb.singleQuote(ast.from)}, ${pqb.singleQuote(ast.to)});`
4455
4633
  ];
4456
4634
  },
4457
- view(ast) {
4458
- const code = [`await db.createView(${quoteSchemaTable(ast)}`];
4635
+ view(ast, _, currentSchema) {
4636
+ const code = [
4637
+ `await db.createView(${quoteSchemaTable(ast, currentSchema)}`
4638
+ ];
4459
4639
  const options = [];
4460
4640
  if (ast.options.recursive) options.push("recursive: true,");
4461
4641
  const w = ast.options.with;
@@ -4489,7 +4669,60 @@ const astEncoders = {
4489
4669
  }
4490
4670
  pqb.addCode(code, ");");
4491
4671
  return code;
4672
+ },
4673
+ role(ast) {
4674
+ const params = ast.action === "create" ? roleParams(ast) : void 0;
4675
+ const arr = [
4676
+ `await db.${ast.action}Role(${pqb.singleQuote(ast.name)}${params?.length ? ", {" : ");"}`
4677
+ ];
4678
+ if (params?.length) {
4679
+ arr.push(params);
4680
+ arr.push("});");
4681
+ }
4682
+ return arr;
4683
+ },
4684
+ changeRole(ast) {
4685
+ const from = roleParams(ast.from, ast.to);
4686
+ const to = roleParams(ast.to, ast.from, true);
4687
+ return [
4688
+ `await db.changeRole(${pqb.singleQuote(ast.name)}, {`,
4689
+ [...from.length ? ["from: {", from, "},"] : [], "to: {", to, "},"],
4690
+ "});"
4691
+ ];
4692
+ }
4693
+ };
4694
+ const roleParams = (ast, compare, to) => {
4695
+ const params = [];
4696
+ for (const key of [
4697
+ "name",
4698
+ "super",
4699
+ "inherit",
4700
+ "createRole",
4701
+ "createDb",
4702
+ "canLogin",
4703
+ "replication",
4704
+ "connLimit",
4705
+ "validUntil",
4706
+ "bypassRls",
4707
+ "config"
4708
+ ]) {
4709
+ if (key === "name" && !to) continue;
4710
+ let value = ast[key];
4711
+ if (!compare && (!value || key === "connLimit" && value === -1)) {
4712
+ continue;
4713
+ }
4714
+ value = value instanceof Date ? `'${value.toISOString()}'` : key === "config" ? JSON.stringify(value) : typeof value === "string" ? pqb.singleQuote(value) : value;
4715
+ if (compare) {
4716
+ const a = value === -1 || value === false ? void 0 : value;
4717
+ const other = compare[key];
4718
+ const b = other === -1 || other === false ? void 0 : other;
4719
+ if (a === b) {
4720
+ continue;
4721
+ }
4722
+ }
4723
+ params.push(`${key}: ${value},`);
4492
4724
  }
4725
+ return params;
4493
4726
  };
4494
4727
  const isTimestamp = (column, type) => {
4495
4728
  if (!column) return false;
@@ -4897,7 +5130,19 @@ const collationsSql = (version) => `SELECT
4897
5130
  FROM pg_collation
4898
5131
  JOIN pg_namespace n on pg_collation.collnamespace = n.oid
4899
5132
  WHERE ${filterSchema("n.nspname")}`;
4900
- const sql = (version) => `SELECT (${schemasSql}) AS "schemas", ${jsonAgg(
5133
+ const roleSql = (params) => `SELECT json_agg(json_build_object(
5134
+ 'name', rolname,
5135
+ 'super', rolsuper,
5136
+ 'inherit', rolinherit,
5137
+ 'createRole', rolcreaterole,
5138
+ 'canLogin', rolcanlogin,
5139
+ 'replication', rolreplication,
5140
+ 'connLimit', rolconnlimit,
5141
+ 'validUntil', rolvaliduntil,
5142
+ 'bypassRls', rolbypassrls,
5143
+ 'config', rolconfig
5144
+ )) FROM pg_roles WHERE ${params.whereSql ?? `name != 'postgres' AND name !~ '^pg_'`}`;
5145
+ const sql = (version, params) => `SELECT (${schemasSql}) AS "schemas", ${jsonAgg(
4901
5146
  tablesSql,
4902
5147
  "tables"
4903
5148
  )}, ${jsonAgg(viewsSql, "views")}, ${jsonAgg(
@@ -4912,13 +5157,13 @@ const sql = (version) => `SELECT (${schemasSql}) AS "schemas", ${jsonAgg(
4912
5157
  )}, ${jsonAgg(domainsSql, "domains")}, ${jsonAgg(
4913
5158
  collationsSql(version),
4914
5159
  "collations"
4915
- )}`;
4916
- async function introspectDbSchema(db) {
5160
+ )}${params?.roles ? `, (${roleSql(params.roles)}) AS "roles"` : ""}`;
5161
+ async function introspectDbSchema(db, params) {
4917
5162
  const {
4918
5163
  rows: [{ version: versionString }]
4919
5164
  } = await db.query("SELECT version()");
4920
5165
  const version = +versionString.match(/\d+/)[0];
4921
- const data = await db.query(sql(version));
5166
+ const data = await db.query(sql(version, params));
4922
5167
  const result = data.rows[0];
4923
5168
  for (const domain of result.domains) {
4924
5169
  domain.checks = domain.checks?.filter((check) => check);
@@ -4997,6 +5242,26 @@ async function introspectDbSchema(db) {
4997
5242
  }
4998
5243
  result.indexes = indexes;
4999
5244
  result.excludes = excludes;
5245
+ if (result.roles) {
5246
+ for (const role of result.roles) {
5247
+ nullsToUndefined(role);
5248
+ if (role.validUntil) role.validUntil = new Date(role.validUntil);
5249
+ if (role.config) {
5250
+ const arr = role.config;
5251
+ role.config = Object.fromEntries(
5252
+ arr.map((item) => {
5253
+ const i = item.indexOf("=");
5254
+ const key = item.slice(0, i);
5255
+ const value = item.slice(i + 1);
5256
+ return [
5257
+ key,
5258
+ value[0] === '"' ? value.slice(1, -1).replaceAll('""', '"') : value
5259
+ ];
5260
+ })
5261
+ );
5262
+ }
5263
+ }
5264
+ }
5000
5265
  return result;
5001
5266
  }
5002
5267
  const nullsToUndefined = (obj) => {
@@ -5046,7 +5311,7 @@ const structureToAst = async (ctx, adapter, config) => {
5046
5311
  });
5047
5312
  }
5048
5313
  const domains = makeDomainsMap(ctx, data);
5049
- const { schema: migrationsSchema = "public", table: migrationsTable } = getMigrationsSchemaAndTable(config);
5314
+ const { schema: migrationsSchema = "public", table: migrationsTable } = getMigrationsSchemaAndTable(adapter, config);
5050
5315
  for (const table of data.tables) {
5051
5316
  if (table.name === migrationsTable && table.schemaName === migrationsSchema)
5052
5317
  continue;
@@ -5095,6 +5360,15 @@ const structureToAst = async (ctx, adapter, config) => {
5095
5360
  for (const view of data.views) {
5096
5361
  ast.push(viewToAst(ctx, data, domains, view));
5097
5362
  }
5363
+ if (data.roles) {
5364
+ for (const role of data.roles) {
5365
+ ast.push({
5366
+ type: "role",
5367
+ action: "create",
5368
+ ...role
5369
+ });
5370
+ }
5371
+ }
5098
5372
  return ast;
5099
5373
  };
5100
5374
  const makeDomainsMap = (ctx, data) => {
@@ -5261,7 +5535,8 @@ const getDbStructureTableData = (data, { name, schemaName }) => {
5261
5535
  } : void 0,
5262
5536
  indexes: data.indexes.filter(filterFn),
5263
5537
  excludes: data.excludes.filter(filterFn),
5264
- constraints
5538
+ constraints,
5539
+ roles: data.roles
5265
5540
  };
5266
5541
  };
5267
5542
  const filterByTableSchema = (tableName, schemaName) => (x) => x.tableName === tableName && x.schemaName === schemaName;