rake-db 2.4.25 → 2.4.30

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.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { quote, getRaw, EnumColumn, UnknownColumn, columnTypes, getColumnTypes, getTableData, ColumnType, resetTableData, TransactionAdapter, logParamToLogObject, createDb as createDb$1, Adapter, columnsByType, instantiateColumn, DomainColumn, CustomTypeColumn, ArrayColumn, primaryKeyToCode, indexToCode, foreignKeyToCode, TimestampColumn, foreignKeyArgsToCode } from 'pqb';
1
+ import { quote, getRaw, EnumColumn, columnTypes, getColumnTypes, getTableData, ColumnType, resetTableData, UnknownColumn, TransactionAdapter, logParamToLogObject, createDb as createDb$1, Adapter, columnsByType, instantiateColumn, DomainColumn, CustomTypeColumn, ArrayColumn, getConstraintKind, primaryKeyToCode, indexToCode, constraintToCode, TimestampColumn, referencesArgsToCode, constraintPropsToCode } from 'pqb';
2
2
  import { singleQuote, toSnakeCase, isRaw, toArray, snakeCaseKey, nameKey, emptyObject, pathToLog, raw, toCamelCase, codeToString, addCode, rawToCode, quoteObjectKey } from 'orchid-core';
3
3
  import path from 'path';
4
4
  import { readdir, mkdir, writeFile } from 'fs/promises';
@@ -294,7 +294,7 @@ const columnToSql = (name, item, values, hasMultiplePrimaryKeys, snakeCase) => {
294
294
  line.push("NOT NULL");
295
295
  }
296
296
  if (item.data.check) {
297
- line.push(`CHECK (${getRaw(item.data.check, values)})`);
297
+ line.push(checkToSql(item.data.check, values));
298
298
  }
299
299
  if (item.data.default !== void 0) {
300
300
  if (typeof item.data.default === "object" && item.data.default && isRaw(item.data.default)) {
@@ -306,18 +306,17 @@ const columnToSql = (name, item, values, hasMultiplePrimaryKeys, snakeCase) => {
306
306
  const { foreignKeys } = item.data;
307
307
  if (foreignKeys) {
308
308
  for (const foreignKey of foreignKeys) {
309
- const [schema, table] = getForeignKeyTable(
310
- "fn" in foreignKey ? foreignKey.fn : foreignKey.table
311
- );
312
309
  if (foreignKey.name) {
313
310
  line.push(`CONSTRAINT "${foreignKey.name}"`);
314
311
  }
315
312
  line.push(
316
313
  referencesToSql(
317
- schema,
318
- table,
319
- foreignKey.columns,
320
- foreignKey,
314
+ {
315
+ columns: foreignKey.columns,
316
+ fnOrTable: "fn" in foreignKey ? foreignKey.fn : foreignKey.table,
317
+ foreignColumns: foreignKey.columns,
318
+ options: foreignKey
319
+ },
321
320
  snakeCase
322
321
  )
323
322
  );
@@ -347,40 +346,53 @@ const getForeignKeyTable = (fnOrTable) => {
347
346
  const item = new (fnOrTable())();
348
347
  return [item.schema, item.table];
349
348
  };
350
- const getForeignKeyName = (table, columns) => {
351
- return `${table}_${columns.join("_")}_fkey`;
349
+ const getConstraintName = (table, constraint) => {
350
+ if (constraint.references)
351
+ return `${table}_${constraint.references.columns.join("_")}_fkey`;
352
+ if (constraint.check)
353
+ return `${table}_check`;
354
+ return `${table}_constraint`;
352
355
  };
353
- const constraintToSql = ({ name }, up, foreignKey, snakeCase) => {
354
- const constraintName = foreignKey.options.name || getForeignKeyName(name, foreignKey.columns);
356
+ const constraintToSql = ({ name }, up, constraint, values, snakeCase) => {
357
+ const constraintName = constraint.name || getConstraintName(name, constraint);
355
358
  if (!up) {
356
- const { dropMode } = foreignKey.options;
359
+ const { dropMode } = constraint;
357
360
  return `CONSTRAINT "${constraintName}"${dropMode ? ` ${dropMode}` : ""}`;
358
361
  }
359
- const [schema, table] = getForeignKeyTable(foreignKey.fnOrTable);
360
- return `CONSTRAINT "${constraintName}" FOREIGN KEY (${joinColumns(
361
- foreignKey.columns
362
- )}) ${referencesToSql(
363
- schema,
364
- table,
365
- foreignKey.foreignColumns,
366
- foreignKey.options,
362
+ const sql = [`CONSTRAINT "${constraintName}"`];
363
+ if (constraint.references) {
364
+ sql.push(foreignKeyToSql(constraint.references, snakeCase));
365
+ }
366
+ if (constraint.check) {
367
+ sql.push(checkToSql(constraint.check, values));
368
+ }
369
+ return sql.join(" ");
370
+ };
371
+ const checkToSql = (check, values) => {
372
+ return `CHECK (${getRaw(check, values)})`;
373
+ };
374
+ const foreignKeyToSql = (item, snakeCase) => {
375
+ return `FOREIGN KEY (${joinColumns(item.columns)}) ${referencesToSql(
376
+ item,
367
377
  snakeCase
368
378
  )}`;
369
379
  };
370
- const referencesToSql = (schema, table, columns, foreignKey, snakeCase) => {
380
+ const referencesToSql = (references, snakeCase) => {
381
+ const [schema, table] = getForeignKeyTable(references.fnOrTable);
371
382
  const sql = [
372
383
  `REFERENCES ${quoteWithSchema({ schema, name: table })}(${joinColumns(
373
- snakeCase ? columns.map(toSnakeCase) : columns
384
+ snakeCase ? references.foreignColumns.map(toSnakeCase) : references.foreignColumns
374
385
  )})`
375
386
  ];
376
- if (foreignKey.match) {
377
- sql.push(`MATCH ${foreignKey.match.toUpperCase()}`);
387
+ const { options } = references;
388
+ if (options == null ? void 0 : options.match) {
389
+ sql.push(`MATCH ${options == null ? void 0 : options.match.toUpperCase()}`);
378
390
  }
379
- if (foreignKey.onDelete) {
380
- sql.push(`ON DELETE ${foreignKey.onDelete.toUpperCase()}`);
391
+ if (options == null ? void 0 : options.onDelete) {
392
+ sql.push(`ON DELETE ${options == null ? void 0 : options.onDelete.toUpperCase()}`);
381
393
  }
382
- if (foreignKey.onUpdate) {
383
- sql.push(`ON UPDATE ${foreignKey.onUpdate.toUpperCase()}`);
394
+ if (options == null ? void 0 : options.onUpdate) {
395
+ sql.push(`ON UPDATE ${options == null ? void 0 : options.onUpdate.toUpperCase()}`);
384
396
  }
385
397
  return sql.join(" ");
386
398
  };
@@ -465,9 +477,6 @@ const primaryKeyToSql = (primaryKey) => {
465
477
  const tableMethods = {
466
478
  enum(name) {
467
479
  return new EnumColumn(this, name, []);
468
- },
469
- check(value) {
470
- return new UnknownColumn(this).check(value);
471
480
  }
472
481
  };
473
482
 
@@ -578,6 +587,7 @@ You can suppress this error by setting { noPrimaryKey: true } after a table name
578
587
  }
579
588
  };
580
589
  const astToQueries$1 = (ast, snakeCase) => {
590
+ var _a, _b;
581
591
  const queries = [];
582
592
  const { shape } = ast;
583
593
  for (const key in shape) {
@@ -617,27 +627,30 @@ const astToQueries$1 = (ast, snakeCase) => {
617
627
  })}`
618
628
  );
619
629
  }
620
- ast.foreignKeys.forEach((foreignKey) => {
630
+ (_a = ast.constraints) == null ? void 0 : _a.forEach((item) => {
621
631
  lines.push(
622
632
  `
623
633
  ${constraintToSql(
624
634
  ast,
625
635
  true,
626
- __spreadProps$3(__spreadValues$4({}, foreignKey), {
627
- columns: foreignKey.columns.map(
628
- (column) => getColumnName(shape[column], column, snakeCase)
629
- )
636
+ __spreadProps$3(__spreadValues$4({}, item), {
637
+ references: item.references ? __spreadProps$3(__spreadValues$4({}, item.references), {
638
+ columns: item.references.columns.map(
639
+ (column) => getColumnName(shape[column], column, snakeCase)
640
+ )
641
+ }) : void 0
630
642
  }),
643
+ values,
631
644
  snakeCase
632
645
  )}`
633
646
  );
634
647
  });
635
648
  indexes.push(
636
- ...ast.indexes.map((index) => __spreadProps$3(__spreadValues$4({}, index), {
649
+ ...((_b = ast.indexes) == null ? void 0 : _b.map((index) => __spreadProps$3(__spreadValues$4({}, index), {
637
650
  columns: index.columns.map((item) => __spreadValues$4(__spreadValues$4({}, item), "column" in item ? {
638
651
  column: getColumnName(shape[item.column], item.column, snakeCase)
639
652
  } : {}))
640
- }))
653
+ }))) || []
641
654
  );
642
655
  queries.push(
643
656
  {
@@ -676,8 +689,8 @@ var __spreadValues$3 = (a, b) => {
676
689
  };
677
690
  var __spreadProps$2 = (a, b) => __defProps$2(a, __getOwnPropDescs$2(b));
678
691
  const newChangeTableData = () => ({
679
- add: { indexes: [], foreignKeys: [] },
680
- drop: { indexes: [], foreignKeys: [] }
692
+ add: {},
693
+ drop: {}
681
694
  });
682
695
  let changeTableData = newChangeTableData();
683
696
  const resetChangeTableData = () => {
@@ -694,8 +707,8 @@ const mergeTableData = (a, b) => {
694
707
  };
695
708
  }
696
709
  }
697
- a.indexes = [...a.indexes, ...b.indexes];
698
- a.foreignKeys = [...a.foreignKeys, ...b.foreignKeys];
710
+ a.indexes = [...a.indexes || [], ...b.indexes || []];
711
+ a.constraints = [...a.constraints || [], ...b.constraints || []];
699
712
  };
700
713
  function add(item, options) {
701
714
  if (item instanceof ColumnType) {
@@ -920,20 +933,14 @@ const astToQueries = (ast, snakeCase) => {
920
933
  }
921
934
  const alterTable = [];
922
935
  const values = [];
923
- const addIndexes = mapIndexesForSnakeCase(
924
- ast.add.indexes,
936
+ const addIndexes = mapIndexesForSnakeCase(ast.add.indexes, snakeCase);
937
+ const dropIndexes = mapIndexesForSnakeCase(ast.drop.indexes, snakeCase);
938
+ const addConstraints = mapConstraintsToSnakeCase(
939
+ ast.add.constraints,
925
940
  snakeCase
926
941
  );
927
- const dropIndexes = mapIndexesForSnakeCase(
928
- ast.drop.indexes,
929
- snakeCase
930
- );
931
- const addForeignKeys = mapForeignKeysForSnakeCase(
932
- ast.add.foreignKeys,
933
- snakeCase
934
- );
935
- const dropForeignKeys = mapForeignKeysForSnakeCase(
936
- ast.drop.foreignKeys,
942
+ const dropConstraints = mapConstraintsToSnakeCase(
943
+ ast.drop.constraints,
937
944
  snakeCase
938
945
  );
939
946
  const comments = [];
@@ -1007,19 +1014,27 @@ const astToQueries = (ast, snakeCase) => {
1007
1014
  const toFkey = (_d = to.foreignKeys) == null ? void 0 : _d[i];
1008
1015
  if ((fromFkey || toFkey) && (!fromFkey || !toFkey || fromFkey.name !== toFkey.name || fromFkey.match !== toFkey.match || fromFkey.onUpdate !== toFkey.onUpdate || fromFkey.onDelete !== toFkey.onDelete || fromFkey.dropMode !== toFkey.dropMode || fromFkey.table !== toFkey.table || fromFkey.columns.join(",") !== toFkey.columns.join(","))) {
1009
1016
  if (fromFkey) {
1010
- dropForeignKeys.push({
1011
- columns: [name],
1012
- fnOrTable: fromFkey.table,
1013
- foreignColumns: snakeCase ? fromFkey.columns.map(toSnakeCase) : fromFkey.columns,
1014
- options: fromFkey
1017
+ dropConstraints.push({
1018
+ name: fromFkey.name,
1019
+ dropMode: fromFkey.dropMode,
1020
+ references: {
1021
+ columns: [name],
1022
+ fnOrTable: fromFkey.table,
1023
+ foreignColumns: snakeCase ? fromFkey.columns.map(toSnakeCase) : fromFkey.columns,
1024
+ options: fromFkey
1025
+ }
1015
1026
  });
1016
1027
  }
1017
1028
  if (toFkey) {
1018
- addForeignKeys.push({
1019
- columns: [name],
1020
- fnOrTable: toFkey.table,
1021
- foreignColumns: snakeCase ? toFkey.columns.map(toSnakeCase) : toFkey.columns,
1022
- options: toFkey
1029
+ addConstraints.push({
1030
+ name: toFkey.name,
1031
+ dropMode: toFkey.dropMode,
1032
+ references: {
1033
+ columns: [name],
1034
+ fnOrTable: toFkey.table,
1035
+ foreignColumns: snakeCase ? toFkey.columns.map(toSnakeCase) : toFkey.columns,
1036
+ options: toFkey
1037
+ }
1023
1038
  });
1024
1039
  }
1025
1040
  }
@@ -1069,9 +1084,9 @@ const astToQueries = (ast, snakeCase) => {
1069
1084
  prependAlterTable.push(`DROP CONSTRAINT "${name}"`);
1070
1085
  }
1071
1086
  prependAlterTable.push(
1072
- ...dropForeignKeys.map(
1087
+ ...dropConstraints.map(
1073
1088
  (foreignKey) => `
1074
- DROP ${constraintToSql(ast, false, foreignKey, snakeCase)}`
1089
+ DROP ${constraintToSql(ast, false, foreignKey, values, snakeCase)}`
1075
1090
  )
1076
1091
  );
1077
1092
  alterTable.unshift(...prependAlterTable);
@@ -1086,9 +1101,9 @@ const astToQueries = (ast, snakeCase) => {
1086
1101
  );
1087
1102
  }
1088
1103
  alterTable.push(
1089
- ...addForeignKeys.map(
1104
+ ...addConstraints.map(
1090
1105
  (foreignKey) => `
1091
- ADD ${constraintToSql(ast, true, foreignKey, snakeCase)}`
1106
+ ADD ${constraintToSql(ast, true, foreignKey, values, snakeCase)}`
1092
1107
  )
1093
1108
  );
1094
1109
  if (alterTable.length) {
@@ -1107,17 +1122,19 @@ const getChangeColumnName = (change, key, snakeCase) => {
1107
1122
  return change.name || (change.to.column ? getColumnName(change.to.column, key, snakeCase) : snakeCase ? toSnakeCase(key) : key);
1108
1123
  };
1109
1124
  const mapIndexesForSnakeCase = (indexes, snakeCase) => {
1110
- return indexes.map((index) => ({
1125
+ return (indexes == null ? void 0 : indexes.map((index) => ({
1111
1126
  options: index.options,
1112
1127
  columns: snakeCase ? index.columns.map(
1113
1128
  (item) => "column" in item ? __spreadProps$2(__spreadValues$3({}, item), { column: toSnakeCase(item.column) }) : item
1114
1129
  ) : index.columns
1115
- }));
1130
+ }))) || [];
1116
1131
  };
1117
- const mapForeignKeysForSnakeCase = (foreignKeys, snakeCase) => {
1118
- return foreignKeys.map((foreignKey) => __spreadProps$2(__spreadValues$3({}, foreignKey), {
1119
- columns: snakeCase ? foreignKey.columns.map(toSnakeCase) : foreignKey.columns
1120
- }));
1132
+ const mapConstraintsToSnakeCase = (foreignKeys, snakeCase) => {
1133
+ return (foreignKeys == null ? void 0 : foreignKeys.map((item) => __spreadProps$2(__spreadValues$3({}, item), {
1134
+ references: item.references ? snakeCase ? __spreadProps$2(__spreadValues$3({}, item.references), {
1135
+ columns: item.references.columns.map(toSnakeCase)
1136
+ }) : item.references : void 0
1137
+ }))) || [];
1121
1138
  };
1122
1139
 
1123
1140
  var __defProp$2 = Object.defineProperty;
@@ -1238,6 +1255,18 @@ class MigrationBase {
1238
1255
  dropPrimaryKey(tableName, columns, options) {
1239
1256
  return addPrimaryKey(this, !this.up, tableName, columns, options);
1240
1257
  }
1258
+ addCheck(tableName, check) {
1259
+ return addCheck(this, this.up, tableName, check);
1260
+ }
1261
+ dropCheck(tableName, check) {
1262
+ return addCheck(this, !this.up, tableName, check);
1263
+ }
1264
+ addConstraint(tableName, constraint) {
1265
+ return addConstraint(this, this.up, tableName, constraint);
1266
+ }
1267
+ dropConstraint(tableName, constraint) {
1268
+ return addConstraint(this, !this.up, tableName, constraint);
1269
+ }
1241
1270
  renameColumn(tableName, from, to) {
1242
1271
  return this.changeTable(tableName, (t) => ({
1243
1272
  [from]: t.rename(to)
@@ -1316,6 +1345,12 @@ const addForeignKey = (migration, up, tableName, columns, foreignTable, foreignC
1316
1345
  const addPrimaryKey = (migration, up, tableName, columns, options) => {
1317
1346
  return changeTable(migration, up, tableName, {}, (t) => __spreadValues$2({}, t.add(t.primaryKey(columns, options))));
1318
1347
  };
1348
+ const addCheck = (migration, up, tableName, check) => {
1349
+ return changeTable(migration, up, tableName, {}, (t) => __spreadValues$2({}, t.add(t.check(check))));
1350
+ };
1351
+ const addConstraint = (migration, up, tableName, constraint) => {
1352
+ return changeTable(migration, up, tableName, {}, (t) => __spreadValues$2({}, t.add(t.constraint(constraint))));
1353
+ };
1319
1354
  const createSchema$1 = async (migration, up, name) => {
1320
1355
  const ast = {
1321
1356
  type: "schema",
@@ -1925,57 +1960,78 @@ ORDER BY ic.relname`
1925
1960
  );
1926
1961
  return rows;
1927
1962
  }
1928
- async getForeignKeys() {
1963
+ async getConstraints() {
1929
1964
  const { rows } = await this.db.query(
1930
1965
  `SELECT
1931
1966
  s.nspname AS "schemaName",
1932
1967
  t.relname AS "tableName",
1933
- fs.nspname AS "foreignTableSchemaName",
1934
- ft.relname AS "foreignTableName",
1935
1968
  c.conname AS "name",
1936
1969
  (
1937
1970
  SELECT json_agg(ccu.column_name)
1938
- FROM information_schema.key_column_usage ccu
1939
- WHERE ccu.constraint_name = c.conname
1940
- AND ccu.table_schema = cs.nspname
1941
- ) AS "columnNames",
1971
+ FROM information_schema.constraint_column_usage ccu
1972
+ WHERE contype = 'p'
1973
+ AND ccu.constraint_name = c.conname
1974
+ AND ccu.table_schema = s.nspname
1975
+ ) AS "primaryKey",
1942
1976
  (
1943
- SELECT json_agg(ccu.column_name)
1977
+ SELECT
1978
+ json_build_object(
1979
+ 'foreignSchema',
1980
+ fs.nspname,
1981
+ 'foreignTable',
1982
+ ft.relname,
1983
+ 'columns',
1984
+ (
1985
+ SELECT json_agg(ccu.column_name)
1986
+ FROM information_schema.key_column_usage ccu
1987
+ WHERE ccu.constraint_name = c.conname
1988
+ AND ccu.table_schema = cs.nspname
1989
+ ),
1990
+ 'foreignColumns',
1991
+ (
1992
+ SELECT json_agg(ccu.column_name)
1993
+ FROM information_schema.constraint_column_usage ccu
1994
+ WHERE ccu.constraint_name = c.conname
1995
+ AND ccu.table_schema = cs.nspname
1996
+ ),
1997
+ 'match',
1998
+ c.confmatchtype,
1999
+ 'onUpdate',
2000
+ c.confupdtype,
2001
+ 'onDelete',
2002
+ c.confdeltype
2003
+ )
2004
+ FROM pg_class ft
2005
+ JOIN pg_catalog.pg_namespace fs ON fs.oid = ft.relnamespace
2006
+ JOIN pg_catalog.pg_namespace cs ON cs.oid = c.connamespace
2007
+ WHERE contype = 'f' AND ft.oid = confrelid
2008
+ ) AS "references",
2009
+ (
2010
+ SELECT
2011
+ CASE conbin IS NULL
2012
+ WHEN false THEN
2013
+ json_build_object(
2014
+ 'columns',
2015
+ json_agg(ccu.column_name),
2016
+ 'expression',
2017
+ pg_get_expr(conbin, conrelid)
2018
+ )
2019
+ END
1944
2020
  FROM information_schema.constraint_column_usage ccu
1945
- WHERE ccu.constraint_name = c.conname
1946
- AND ccu.table_schema = cs.nspname
1947
- ) AS "foreignColumnNames",
1948
- c.confmatchtype AS match,
1949
- c.confupdtype AS "onUpdate",
1950
- c.confdeltype AS "onDelete"
2021
+ WHERE conbin IS NOT NULL
2022
+ AND ccu.constraint_name = c.conname
2023
+ AND ccu.table_schema = s.nspname
2024
+ ) AS "check"
1951
2025
  FROM pg_catalog.pg_constraint c
1952
2026
  JOIN pg_class t ON t.oid = conrelid
1953
- JOIN pg_catalog.pg_namespace s ON s.oid = t.relnamespace
1954
- JOIN pg_class ft ON ft.oid = confrelid
1955
- JOIN pg_catalog.pg_namespace fs ON fs.oid = ft.relnamespace
1956
- JOIN pg_catalog.pg_namespace cs ON cs.oid = c.connamespace
1957
- WHERE contype = 'f'
2027
+ JOIN pg_catalog.pg_namespace s
2028
+ ON s.oid = t.relnamespace
2029
+ AND contype IN ('p', 'f', 'c')
2030
+ AND ${filterSchema("s.nspname")}
1958
2031
  ORDER BY c.conname`
1959
2032
  );
1960
2033
  return rows;
1961
2034
  }
1962
- async getPrimaryKeys() {
1963
- const { rows } = await this.db.query(
1964
- `SELECT tc.table_schema AS "schemaName",
1965
- tc.table_name AS "tableName",
1966
- tc.constraint_name AS "name",
1967
- json_agg(ccu.column_name) "columnNames"
1968
- FROM information_schema.table_constraints tc
1969
- JOIN information_schema.constraint_column_usage ccu
1970
- ON ccu.constraint_name = tc.constraint_name
1971
- AND ccu.table_schema = tc.table_schema
1972
- WHERE tc.constraint_type = 'PRIMARY KEY'
1973
- AND ${filterSchema("tc.table_schema")}
1974
- GROUP BY "schemaName", "tableName", "name"
1975
- ORDER BY "name"`
1976
- );
1977
- return rows;
1978
- }
1979
2035
  async getTriggers() {
1980
2036
  const { rows } = await this.db.query(
1981
2037
  `SELECT event_object_schema AS "schemaName",
@@ -2019,31 +2075,6 @@ GROUP BY n.nspname, t.typname`
2019
2075
  );
2020
2076
  return rows;
2021
2077
  }
2022
- async getChecks() {
2023
- const { rows } = await this.db.query(`SELECT
2024
- s.nspname AS "schemaName",
2025
- t.relname AS "tableName",
2026
- c.conname AS "name",
2027
- (
2028
- SELECT json_agg(ccu.column_name)
2029
- FROM information_schema.constraint_column_usage ccu
2030
- WHERE ccu.constraint_name = c.conname
2031
- AND ccu.table_schema = cs.nspname
2032
- ) AS "columnNames",
2033
- pg_get_expr(conbin, conrelid) AS "expression"
2034
- FROM pg_catalog.pg_constraint c
2035
- JOIN pg_class t ON t.oid = conrelid
2036
- JOIN pg_catalog.pg_namespace s ON s.oid = t.relnamespace
2037
- JOIN pg_catalog.pg_namespace cs ON cs.oid = c.connamespace
2038
- WHERE contype = 'c'
2039
- ORDER BY c.conname`);
2040
- for (const row of rows) {
2041
- if (row.expression[0] === "(" && row.expression[row.expression.length - 1] === ")") {
2042
- row.expression = row.expression.slice(1, -1);
2043
- }
2044
- }
2045
- return rows;
2046
- }
2047
2078
  async getDomains() {
2048
2079
  const { rows } = await this.db.query(`SELECT
2049
2080
  n.nspname AS "schemaName",
@@ -2137,10 +2168,11 @@ const structureToAst = async (ctx, db) => {
2137
2168
  for (const table of data.tables) {
2138
2169
  const key = `${table.schemaName}.${table.name}`;
2139
2170
  const dependsOn = /* @__PURE__ */ new Set();
2140
- for (const fk of data.foreignKeys) {
2141
- if (fk.schemaName !== table.schemaName || fk.tableName !== table.name)
2171
+ for (const fk of data.constraints) {
2172
+ const { references } = fk;
2173
+ if (!references || fk.schemaName !== table.schemaName || fk.tableName !== table.name)
2142
2174
  continue;
2143
- const otherKey = `${fk.foreignTableSchemaName}.${fk.foreignTableName}`;
2175
+ const otherKey = `${references.foreignSchema}.${references.foreignTable}`;
2144
2176
  if (otherKey !== key) {
2145
2177
  dependsOn.add(otherKey);
2146
2178
  }
@@ -2164,7 +2196,7 @@ const structureToAst = async (ctx, db) => {
2164
2196
  pushTableAst(ctx, ast, data, domains, table, pendingTables);
2165
2197
  }
2166
2198
  }
2167
- const outerFKeys = [];
2199
+ const outerConstraints = [];
2168
2200
  for (const it of data.extensions) {
2169
2201
  ast.push({
2170
2202
  type: "extension",
@@ -2197,23 +2229,31 @@ const structureToAst = async (ctx, db) => {
2197
2229
  });
2198
2230
  }
2199
2231
  for (const key in pendingTables) {
2200
- const innerFKeys = [];
2232
+ const innerConstraints = [];
2201
2233
  const { table } = pendingTables[key];
2202
- for (const fkey of data.foreignKeys) {
2234
+ for (const fkey of data.constraints) {
2203
2235
  if (fkey.schemaName !== table.schemaName || fkey.tableName !== table.name)
2204
2236
  continue;
2205
- const otherKey = `${fkey.foreignTableSchemaName}.${fkey.foreignTableName}`;
2206
- if (!pendingTables[otherKey] || otherKey === key) {
2207
- innerFKeys.push(fkey);
2237
+ const otherKey = fkey.references && `${fkey.references.foreignSchema}.${fkey.references.foreignTable}`;
2238
+ if (!otherKey || !pendingTables[otherKey] || otherKey === key) {
2239
+ innerConstraints.push(fkey);
2208
2240
  } else {
2209
- outerFKeys.push([fkey, table]);
2241
+ outerConstraints.push([fkey, table]);
2210
2242
  }
2211
2243
  }
2212
- pushTableAst(ctx, ast, data, domains, table, pendingTables, innerFKeys);
2244
+ pushTableAst(
2245
+ ctx,
2246
+ ast,
2247
+ data,
2248
+ domains,
2249
+ table,
2250
+ pendingTables,
2251
+ innerConstraints
2252
+ );
2213
2253
  }
2214
- for (const [fkey, table] of outerFKeys) {
2215
- ast.push(__spreadProps(__spreadValues({}, foreignKeyToAst(fkey)), {
2216
- type: "foreignKey",
2254
+ for (const [fkey, table] of outerConstraints) {
2255
+ ast.push(__spreadProps(__spreadValues({}, constraintToAst(fkey)), {
2256
+ type: "constraint",
2217
2257
  action: "create",
2218
2258
  tableSchema: table.schemaName === "public" ? void 0 : table.schemaName,
2219
2259
  tableName: fkey.tableName
@@ -2226,35 +2266,29 @@ const getData = async (db) => {
2226
2266
  schemas,
2227
2267
  tables,
2228
2268
  columns,
2229
- primaryKeys,
2269
+ constraints,
2230
2270
  indexes,
2231
- foreignKeys,
2232
2271
  extensions,
2233
2272
  enums,
2234
- checks,
2235
2273
  domains
2236
2274
  ] = await Promise.all([
2237
2275
  db.getSchemas(),
2238
2276
  db.getTables(),
2239
2277
  db.getColumns(),
2240
- db.getPrimaryKeys(),
2278
+ db.getConstraints(),
2241
2279
  db.getIndexes(),
2242
- db.getForeignKeys(),
2243
2280
  db.getExtensions(),
2244
2281
  db.getEnums(),
2245
- db.getChecks(),
2246
2282
  db.getDomains()
2247
2283
  ]);
2248
2284
  return {
2249
2285
  schemas,
2250
2286
  tables,
2251
2287
  columns,
2252
- primaryKeys,
2288
+ constraints,
2253
2289
  indexes,
2254
- foreignKeys,
2255
2290
  extensions,
2256
2291
  enums,
2257
- checks,
2258
2292
  domains
2259
2293
  };
2260
2294
  };
@@ -2317,23 +2351,61 @@ const getColumnType = (type, isSerial) => {
2317
2351
  return type;
2318
2352
  return type === "int2" ? "smallserial" : type === "int4" ? "serial" : "bigserial";
2319
2353
  };
2320
- const pushTableAst = (ctx, ast, data, domains, table, pendingTables, innerFKeys = data.foreignKeys) => {
2321
- const { schemaName, name } = table;
2354
+ const pushTableAst = (ctx, ast, data, domains, table, pendingTables, innerConstraints = data.constraints) => {
2355
+ var _a;
2356
+ const { schemaName, name: tableName } = table;
2322
2357
  const key = `${schemaName}.${table.name}`;
2323
2358
  delete pendingTables[key];
2324
- if (name === "schemaMigrations")
2359
+ if (tableName === "schemaMigrations")
2325
2360
  return;
2326
- const belongsToTable = makeBelongsToTable(schemaName, name);
2361
+ const belongsToTable = makeBelongsToTable(schemaName, tableName);
2327
2362
  const columns = data.columns.filter(belongsToTable);
2328
- const primaryKey = data.primaryKeys.find(belongsToTable);
2329
- const tableIndexes = data.indexes.filter(belongsToTable);
2330
- const tableForeignKeys = innerFKeys.filter(belongsToTable);
2331
- const columnChecks = {};
2332
- for (const check of data.checks) {
2333
- if (check.columnNames.length === 1) {
2334
- columnChecks[check.columnNames[0]] = check;
2335
- }
2363
+ let primaryKey;
2364
+ for (const item of data.constraints) {
2365
+ if (belongsToTable(item) && item.primaryKey)
2366
+ primaryKey = { columns: item.primaryKey, name: item.name };
2336
2367
  }
2368
+ const tableIndexes = data.indexes.filter(belongsToTable);
2369
+ const tableConstraints = innerConstraints.reduce(
2370
+ (acc, item) => {
2371
+ var _a2;
2372
+ const { references, check } = item;
2373
+ if (belongsToTable(item) && (references || check && !isColumnCheck(item))) {
2374
+ const constraint = {
2375
+ references: references ? {
2376
+ columns: references.columns,
2377
+ fnOrTable: getReferencesTable(references),
2378
+ foreignColumns: references.foreignColumns,
2379
+ options: {
2380
+ match: matchMap[references.match],
2381
+ onUpdate: fkeyActionMap[references.onUpdate],
2382
+ onDelete: fkeyActionMap[references.onDelete]
2383
+ }
2384
+ } : void 0,
2385
+ check: check ? raw(check.expression) : void 0
2386
+ };
2387
+ const name = item.name && item.name !== getConstraintName(tableName, constraint) ? item.name : void 0;
2388
+ if (name) {
2389
+ constraint.name = name;
2390
+ if ((_a2 = constraint.references) == null ? void 0 : _a2.options) {
2391
+ constraint.references.options.name = name;
2392
+ }
2393
+ }
2394
+ acc.push(constraint);
2395
+ }
2396
+ return acc;
2397
+ },
2398
+ []
2399
+ );
2400
+ const columnChecks = innerConstraints.reduce(
2401
+ (acc, item) => {
2402
+ if (belongsToTable(item) && isColumnCheck(item)) {
2403
+ acc[item.check.columns[0]] = item.check.expression;
2404
+ }
2405
+ return acc;
2406
+ },
2407
+ {}
2408
+ );
2337
2409
  const shape = {};
2338
2410
  for (let item of columns) {
2339
2411
  const isSerial = getIsSerial(item);
@@ -2345,7 +2417,7 @@ const pushTableAst = (ctx, ast, data, domains, table, pendingTables, innerFKeys
2345
2417
  isArray: item.isArray,
2346
2418
  isSerial
2347
2419
  }));
2348
- if ((primaryKey == null ? void 0 : primaryKey.columnNames.length) === 1 && (primaryKey == null ? void 0 : primaryKey.columnNames[0]) === item.name) {
2420
+ if (((_a = primaryKey == null ? void 0 : primaryKey.columns) == null ? void 0 : _a.length) === 1 && (primaryKey == null ? void 0 : primaryKey.columns[0]) === item.name) {
2349
2421
  column = column.primaryKey();
2350
2422
  }
2351
2423
  const indexes = tableIndexes.filter(
@@ -2357,7 +2429,7 @@ const pushTableAst = (ctx, ast, data, domains, table, pendingTables, innerFKeys
2357
2429
  collate: options.collate,
2358
2430
  opclass: options.opclass,
2359
2431
  order: options.order,
2360
- name: index.name !== getIndexName(name, index.columns) ? index.name : void 0,
2432
+ name: index.name !== getIndexName(tableName, index.columns) ? index.name : void 0,
2361
2433
  using: index.using === "btree" ? void 0 : index.using,
2362
2434
  unique: index.isUnique,
2363
2435
  include: index.include,
@@ -2366,24 +2438,18 @@ const pushTableAst = (ctx, ast, data, domains, table, pendingTables, innerFKeys
2366
2438
  where: index.where
2367
2439
  });
2368
2440
  }
2369
- const foreignKeys = tableForeignKeys.filter(
2370
- (it) => it.columnNames.length === 1 && it.columnNames[0] === item.name
2371
- );
2372
- for (const foreignKey of foreignKeys) {
2441
+ for (const it of tableConstraints) {
2442
+ if (!isColumnFkey(it) || it.references.columns[0] !== item.name)
2443
+ continue;
2373
2444
  column = column.foreignKey(
2374
- foreignKey.foreignTableName,
2375
- foreignKey.foreignColumnNames[0],
2376
- {
2377
- name: foreignKey.name && foreignKey.name !== getForeignKeyName(name, foreignKey.columnNames) ? foreignKey.name : void 0,
2378
- match: matchMap[foreignKey.match],
2379
- onUpdate: fkeyActionMap[foreignKey.onUpdate],
2380
- onDelete: fkeyActionMap[foreignKey.onDelete]
2381
- }
2445
+ it.references.fnOrTable,
2446
+ it.references.foreignColumns[0],
2447
+ it.references.options
2382
2448
  );
2383
2449
  }
2384
2450
  const check = columnChecks[item.name];
2385
2451
  if (check) {
2386
- column.data.check = raw(check.expression);
2452
+ column.data.check = raw(check);
2387
2453
  }
2388
2454
  const camelCaseName = toCamelCase(item.name);
2389
2455
  if (ctx.snakeCase) {
@@ -2399,12 +2465,12 @@ const pushTableAst = (ctx, ast, data, domains, table, pendingTables, innerFKeys
2399
2465
  action: "create",
2400
2466
  schema: schemaName === "public" ? void 0 : schemaName,
2401
2467
  comment: table.comment,
2402
- name,
2468
+ name: tableName,
2403
2469
  shape,
2404
2470
  noPrimaryKey: primaryKey ? "error" : "ignore",
2405
- primaryKey: primaryKey && primaryKey.columnNames.length > 1 ? {
2406
- columns: primaryKey.columnNames,
2407
- options: primaryKey.name === `${name}_pkey` ? void 0 : { name: primaryKey.name }
2471
+ primaryKey: primaryKey && primaryKey.columns.length > 1 ? {
2472
+ columns: primaryKey.columns,
2473
+ options: primaryKey.name === `${tableName}_pkey` ? void 0 : { name: primaryKey.name }
2408
2474
  } : void 0,
2409
2475
  indexes: tableIndexes.filter(
2410
2476
  (index) => index.columns.length > 1 || index.columns.some((it) => "expression" in it)
@@ -2415,7 +2481,7 @@ const pushTableAst = (ctx, ast, data, domains, table, pendingTables, innerFKeys
2415
2481
  order: it.order
2416
2482
  })),
2417
2483
  options: {
2418
- name: index.name !== getIndexName(name, index.columns) ? index.name : void 0,
2484
+ name: index.name !== getIndexName(tableName, index.columns) ? index.name : void 0,
2419
2485
  using: index.using === "btree" ? void 0 : index.using,
2420
2486
  unique: index.isUnique,
2421
2487
  include: index.include,
@@ -2424,7 +2490,9 @@ const pushTableAst = (ctx, ast, data, domains, table, pendingTables, innerFKeys
2424
2490
  where: index.where
2425
2491
  }
2426
2492
  })),
2427
- foreignKeys: tableForeignKeys.filter((it) => it.columnNames.length > 1).map(foreignKeyToAst)
2493
+ constraints: tableConstraints.filter(
2494
+ (it) => getConstraintKind(it) === "constraint" || !isColumnFkey(it)
2495
+ )
2428
2496
  });
2429
2497
  for (const otherKey in pendingTables) {
2430
2498
  const item = pendingTables[otherKey];
@@ -2433,32 +2501,55 @@ const pushTableAst = (ctx, ast, data, domains, table, pendingTables, innerFKeys
2433
2501
  }
2434
2502
  }
2435
2503
  };
2436
- const foreignKeyToAst = (fkey) => {
2437
- const result = {
2438
- columns: fkey.columnNames,
2439
- fnOrTable: fkey.foreignTableName,
2440
- foreignColumns: fkey.foreignColumnNames,
2441
- options: {}
2442
- };
2443
- if (fkey.name && fkey.name !== getForeignKeyName(fkey.tableName, fkey.columnNames)) {
2444
- result.options.name = fkey.name;
2445
- }
2446
- const match = matchMap[fkey.match];
2447
- if (match)
2448
- result.options.match = match;
2449
- const onUpdate = fkeyActionMap[fkey.onUpdate];
2450
- if (onUpdate)
2451
- result.options.onUpdate = onUpdate;
2452
- const onDelete = fkeyActionMap[fkey.onDelete];
2453
- if (onDelete)
2454
- result.options.onDelete = onDelete;
2504
+ const constraintToAst = (item) => {
2505
+ var _a;
2506
+ const result = {};
2507
+ const { references, check } = item;
2508
+ if (references) {
2509
+ const options = {};
2510
+ result.references = {
2511
+ columns: references.columns,
2512
+ fnOrTable: getReferencesTable(references),
2513
+ foreignColumns: references.foreignColumns,
2514
+ options
2515
+ };
2516
+ const match = matchMap[references.match];
2517
+ if (match)
2518
+ options.match = match;
2519
+ const onUpdate = fkeyActionMap[references.onUpdate];
2520
+ if (onUpdate)
2521
+ options.onUpdate = onUpdate;
2522
+ const onDelete = fkeyActionMap[references.onDelete];
2523
+ if (onDelete)
2524
+ options.onDelete = onDelete;
2525
+ }
2526
+ if (check) {
2527
+ result.check = raw(check.expression);
2528
+ }
2529
+ if (item.name && item.name !== getConstraintName(item.tableName, result)) {
2530
+ result.name = item.name;
2531
+ if ((_a = result.references) == null ? void 0 : _a.options) {
2532
+ result.references.options.name = item.name;
2533
+ }
2534
+ }
2455
2535
  return result;
2456
2536
  };
2537
+ const getReferencesTable = (references) => {
2538
+ return references.foreignSchema !== "public" ? `${references.foreignSchema}.${references.foreignTable}` : references.foreignTable;
2539
+ };
2540
+ const isColumnCheck = (it) => {
2541
+ var _a, _b;
2542
+ return !it.references && ((_b = (_a = it.check) == null ? void 0 : _a.columns) == null ? void 0 : _b.length) === 1;
2543
+ };
2544
+ const isColumnFkey = (it) => {
2545
+ var _a;
2546
+ return !it.check && ((_a = it.references) == null ? void 0 : _a.columns.length) === 1;
2547
+ };
2457
2548
 
2458
2549
  const astToMigration = (config, ast) => {
2459
2550
  const first = [];
2460
2551
  const tables = [];
2461
- const foreignKeys = [];
2552
+ const constraints = [];
2462
2553
  for (const item of ast) {
2463
2554
  if (item.type === "schema" && item.action === "create") {
2464
2555
  first.push(createSchema(item));
@@ -2476,13 +2567,13 @@ const astToMigration = (config, ast) => {
2476
2567
  first.push(...createDomain(item));
2477
2568
  } else if (item.type === "table" && item.action === "create") {
2478
2569
  tables.push(createTable(config, item));
2479
- } else if (item.type === "foreignKey") {
2480
- if (foreignKeys.length)
2481
- foreignKeys.push([]);
2482
- foreignKeys.push(...createForeignKey(item));
2570
+ } else if (item.type === "constraint") {
2571
+ if (constraints.length)
2572
+ constraints.push([]);
2573
+ constraints.push(...createConstraint(item));
2483
2574
  }
2484
2575
  }
2485
- if (!first.length && !tables.length && !foreignKeys.length)
2576
+ if (!first.length && !tables.length && !constraints.length)
2486
2577
  return;
2487
2578
  let code = `import { change } from 'rake-db';
2488
2579
  `;
@@ -2502,10 +2593,10 @@ ${codeToString(table, " ", " ")}
2502
2593
  `;
2503
2594
  }
2504
2595
  }
2505
- if (foreignKeys.length) {
2596
+ if (constraints.length) {
2506
2597
  code += `
2507
2598
  change(async (db) => {
2508
- ${codeToString(foreignKeys, " ", " ")}
2599
+ ${codeToString(constraints, " ", " ")}
2509
2600
  });
2510
2601
  `;
2511
2602
  }
@@ -2583,11 +2674,15 @@ const createTable = (config, ast) => {
2583
2674
  if (ast.primaryKey) {
2584
2675
  code.push([primaryKeyToCode(ast.primaryKey, "t")]);
2585
2676
  }
2586
- for (const index of ast.indexes) {
2587
- code.push(indexToCode(index, "t"));
2677
+ if (ast.indexes) {
2678
+ for (const index of ast.indexes) {
2679
+ code.push(indexToCode(index, "t"));
2680
+ }
2588
2681
  }
2589
- for (const foreignKey of ast.foreignKeys) {
2590
- code.push(foreignKeyToCode(foreignKey, "t"));
2682
+ if (ast.constraints) {
2683
+ for (const constraint of ast.constraints) {
2684
+ code.push(constraintToCode(constraint, "t"));
2685
+ }
2591
2686
  }
2592
2687
  addCode(code, "}));");
2593
2688
  return code;
@@ -2598,17 +2693,26 @@ const isTimestamp = (column) => {
2598
2693
  const { default: def } = column.data;
2599
2694
  return column instanceof TimestampColumn && !column.data.isNullable && def && typeof def === "object" && isRaw(def) && def.__raw === "now()";
2600
2695
  };
2601
- const createForeignKey = (item) => {
2696
+ const createConstraint = (item) => {
2697
+ const kind = getConstraintKind(item);
2698
+ const table = quoteSchemaTable({
2699
+ schema: item.tableSchema,
2700
+ name: item.tableName
2701
+ });
2702
+ if (kind === "foreignKey" && item.references) {
2703
+ return [
2704
+ `await db.addForeignKey(`,
2705
+ [`${table},`, ...referencesArgsToCode(item.references, item.name)],
2706
+ ");"
2707
+ ];
2708
+ }
2709
+ if (kind === "check" && item.check) {
2710
+ return [`await db.addCheck(${table}, ${rawToCode("t", item.check)});`];
2711
+ }
2602
2712
  return [
2603
- `await db.addForeignKey(`,
2604
- [
2605
- `${quoteSchemaTable({
2606
- schema: item.tableSchema,
2607
- name: item.tableName
2608
- })},`,
2609
- ...foreignKeyArgsToCode(item)
2610
- ],
2611
- ");"
2713
+ `await db.addConstraint(${table}, {`,
2714
+ constraintPropsToCode("t", item),
2715
+ "});"
2612
2716
  ];
2613
2717
  };
2614
2718