@vibeorm/migrate 2.0.0-alpha.4 → 2.0.0-alpha.6
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/ddl/sqlite.d.ts.map +1 -1
- package/dist/differ.d.ts.map +1 -1
- package/dist/index.js +226 -24
- package/dist/index.js.map +13 -13
- package/dist/introspect/mysql.d.ts.map +1 -1
- package/dist/introspect/postgres.d.ts.map +1 -1
- package/dist/introspect/shared.d.ts +2 -0
- package/dist/introspect/shared.d.ts.map +1 -1
- package/dist/introspect/sqlite.d.ts.map +1 -1
- package/dist/normalize.d.ts +8 -0
- package/dist/normalize.d.ts.map +1 -1
- package/dist/sqlite-types.d.ts +14 -0
- package/dist/sqlite-types.d.ts.map +1 -1
- package/dist/types.d.ts +17 -1
- package/dist/types.d.ts.map +1 -1
- package/package.json +3 -3
package/dist/ddl/sqlite.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sqlite.d.ts","sourceRoot":"","sources":["../../src/ddl/sqlite.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgDG;AAGH,OAAO,KAAK,EAAmB,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAajE,OAAO,KAAK,EAAe,aAAa,EAAE,MAAM,aAAa,CAAC;AAI9D;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE;IACxC,KAAK,EAAE,SAAS,aAAa,EAAE,CAAC;IAChC,IAAI,CAAC,EAAE,QAAQ,CAAC;IAChB,EAAE,CAAC,EAAE,QAAQ,CAAC;CACf,GAAG,MAAM,EAAE,
|
|
1
|
+
{"version":3,"file":"sqlite.d.ts","sourceRoot":"","sources":["../../src/ddl/sqlite.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgDG;AAGH,OAAO,KAAK,EAAmB,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAajE,OAAO,KAAK,EAAe,aAAa,EAAE,MAAM,aAAa,CAAC;AAI9D;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE;IACxC,KAAK,EAAE,SAAS,aAAa,EAAE,CAAC;IAChC,IAAI,CAAC,EAAE,QAAQ,CAAC;IAChB,EAAE,CAAC,EAAE,QAAQ,CAAC;CACf,GAAG,MAAM,EAAE,CA0LX"}
|
package/dist/differ.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"differ.d.ts","sourceRoot":"","sources":["../src/differ.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAGH,OAAO,KAAK,EAAE,OAAO,EAAU,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAKjE,OAAO,KAAK,EAAqB,aAAa,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"differ.d.ts","sourceRoot":"","sources":["../src/differ.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAGH,OAAO,KAAK,EAAE,OAAO,EAAU,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAKjE,OAAO,KAAK,EAAqB,aAAa,EAAE,MAAM,YAAY,CAAC;AAoCnE;;;;;;;;;;GAUG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE;IAClC,IAAI,EAAE,QAAQ,CAAC;IACf,EAAE,EAAE,QAAQ,CAAC;IACb,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,GAAG,aAAa,EAAE,CA0DlB"}
|
package/dist/index.js
CHANGED
|
@@ -21,6 +21,10 @@ function describeStep(params) {
|
|
|
21
21
|
return `alter column "${step.table}"."${step.column}" (${step.changes.join(", ")})`;
|
|
22
22
|
case "createIndex":
|
|
23
23
|
return `create ${step.unique ? "unique " : ""}index "${step.name}" on "${step.table}"`;
|
|
24
|
+
case "addCheck":
|
|
25
|
+
return `add check "${step.name}" on "${step.table}"`;
|
|
26
|
+
case "dropCheck":
|
|
27
|
+
return `drop check "${step.name}" on "${step.table}"`;
|
|
24
28
|
case "dropIndex":
|
|
25
29
|
return `drop index "${step.name}"`;
|
|
26
30
|
case "addForeignKey":
|
|
@@ -389,6 +393,32 @@ function sqliteEnumCheckName(params) {
|
|
|
389
393
|
return `${params.table}_${params.column}_enum_${params.enumName}`;
|
|
390
394
|
}
|
|
391
395
|
var ENUM_CHECK_PATTERN = /CONSTRAINT "((?:[^"]|"")+)_enum_((?:[^"]|"")+)" CHECK \("((?:[^"]|"")+)" IN \(([^)]*)\)\)/g;
|
|
396
|
+
function parseSqliteNamedChecks(params) {
|
|
397
|
+
const { tableSql } = params;
|
|
398
|
+
const result = [];
|
|
399
|
+
for (const match of tableSql.matchAll(/CONSTRAINT "((?:[^"]|"")+)" CHECK\s*\(/g)) {
|
|
400
|
+
const name = match[1].replaceAll('""', '"');
|
|
401
|
+
const open = (match.index ?? 0) + match[0].length - 1;
|
|
402
|
+
let depth = 0;
|
|
403
|
+
let close = -1;
|
|
404
|
+
for (let index = open;index < tableSql.length; index++) {
|
|
405
|
+
const char = tableSql[index];
|
|
406
|
+
if (char === "(")
|
|
407
|
+
depth += 1;
|
|
408
|
+
else if (char === ")") {
|
|
409
|
+
depth -= 1;
|
|
410
|
+
if (depth === 0) {
|
|
411
|
+
close = index;
|
|
412
|
+
break;
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
if (close === -1)
|
|
417
|
+
continue;
|
|
418
|
+
result.push({ name, expression: tableSql.slice(open + 1, close) });
|
|
419
|
+
}
|
|
420
|
+
return result;
|
|
421
|
+
}
|
|
392
422
|
function parseSqliteEnumChecks(params) {
|
|
393
423
|
const result = [];
|
|
394
424
|
for (const match of params.tableSql.matchAll(ENUM_CHECK_PATTERN)) {
|
|
@@ -599,7 +629,10 @@ function normalizeModel(params) {
|
|
|
599
629
|
const pk = normalizePk({ model });
|
|
600
630
|
const indexes = normalizeIndexes({ model, table });
|
|
601
631
|
const fks = normalizeFks({ model, table, schema });
|
|
602
|
-
|
|
632
|
+
const checks = new Map;
|
|
633
|
+
for (const check of model.checks ?? [])
|
|
634
|
+
checks.set(check.name, check.expression);
|
|
635
|
+
return { model, table, columns, pk, indexes, fks, checks };
|
|
603
636
|
}
|
|
604
637
|
function normalizePk(params) {
|
|
605
638
|
const { model } = params;
|
|
@@ -624,7 +657,8 @@ function normalizeIndexes(params) {
|
|
|
624
657
|
};
|
|
625
658
|
});
|
|
626
659
|
const where = index.where;
|
|
627
|
-
const
|
|
660
|
+
const nullsNotDistinct = unique && index.nullsNotDistinct === true;
|
|
661
|
+
const key = indexComparisonKey({ unique, kind, columns, where, nullsNotDistinct });
|
|
628
662
|
if (result.has(key))
|
|
629
663
|
return;
|
|
630
664
|
const name = index.name ?? `${table}_${columns.map((column) => column.name).join("_")}_${unique ? "key" : "idx"}`;
|
|
@@ -634,7 +668,8 @@ function normalizeIndexes(params) {
|
|
|
634
668
|
kind,
|
|
635
669
|
unique,
|
|
636
670
|
columns,
|
|
637
|
-
...where === undefined ? {} : { where }
|
|
671
|
+
...where === undefined ? {} : { where },
|
|
672
|
+
...nullsNotDistinct ? { nullsNotDistinct: true } : {}
|
|
638
673
|
});
|
|
639
674
|
};
|
|
640
675
|
for (const index of model.indexes)
|
|
@@ -647,9 +682,9 @@ function normalizeIndexes(params) {
|
|
|
647
682
|
return result;
|
|
648
683
|
}
|
|
649
684
|
function indexComparisonKey(params) {
|
|
650
|
-
const { unique, kind, columns, where } = params;
|
|
685
|
+
const { unique, kind, columns, where, nullsNotDistinct } = params;
|
|
651
686
|
const cols = columns.map((column) => `${column.name}${column.desc ? " desc" : ""}`).join(",");
|
|
652
|
-
return `${unique ? "u" : "i"}:${kind}:${cols}:${normalizeWhere({ where })}`;
|
|
687
|
+
return `${unique ? "u" : "i"}${nullsNotDistinct === true ? "n" : ""}:${kind}:${cols}:${normalizeWhere({ where })}`;
|
|
653
688
|
}
|
|
654
689
|
function normalizeWhere(params) {
|
|
655
690
|
const { where } = params;
|
|
@@ -748,6 +783,8 @@ function diffSchemas(params) {
|
|
|
748
783
|
dropColumn: [],
|
|
749
784
|
dropPrimaryKey: [],
|
|
750
785
|
addPrimaryKey: [],
|
|
786
|
+
dropCheck: [],
|
|
787
|
+
addCheck: [],
|
|
751
788
|
createIndex: [],
|
|
752
789
|
addForeignKey: [],
|
|
753
790
|
createJoinTable: [],
|
|
@@ -772,6 +809,8 @@ function diffSchemas(params) {
|
|
|
772
809
|
...buckets.dropColumn,
|
|
773
810
|
...buckets.dropPrimaryKey,
|
|
774
811
|
...buckets.addPrimaryKey,
|
|
812
|
+
...buckets.dropCheck,
|
|
813
|
+
...buckets.addCheck,
|
|
775
814
|
...buckets.createIndex,
|
|
776
815
|
...buckets.addForeignKey,
|
|
777
816
|
...buckets.createJoinTable,
|
|
@@ -881,6 +920,7 @@ function createWholeTable(params) {
|
|
|
881
920
|
table: table.table,
|
|
882
921
|
columns: [...table.columns.values()].map((column) => column.field),
|
|
883
922
|
primaryKey: table.pk,
|
|
923
|
+
checks: [...table.checks].map(([name, expression]) => ({ name, expression })),
|
|
884
924
|
destructive: false
|
|
885
925
|
});
|
|
886
926
|
for (const index of table.indexes.values()) {
|
|
@@ -892,6 +932,7 @@ function createWholeTable(params) {
|
|
|
892
932
|
unique: index.unique,
|
|
893
933
|
columns: index.columns,
|
|
894
934
|
...index.where === undefined ? {} : { where: index.where },
|
|
935
|
+
...index.nullsNotDistinct === true ? { nullsNotDistinct: true } : {},
|
|
895
936
|
destructive: false
|
|
896
937
|
});
|
|
897
938
|
}
|
|
@@ -973,6 +1014,16 @@ function diffOneTable(params) {
|
|
|
973
1014
|
});
|
|
974
1015
|
}
|
|
975
1016
|
}
|
|
1017
|
+
for (const [name, expression] of current.checks) {
|
|
1018
|
+
if (previous.checks.has(name))
|
|
1019
|
+
continue;
|
|
1020
|
+
buckets.addCheck.push({ kind: "addCheck", table, name, expression, destructive: false });
|
|
1021
|
+
}
|
|
1022
|
+
for (const [name] of previous.checks) {
|
|
1023
|
+
if (current.checks.has(name))
|
|
1024
|
+
continue;
|
|
1025
|
+
buckets.dropCheck.push({ kind: "dropCheck", table, name, destructive: false });
|
|
1026
|
+
}
|
|
976
1027
|
for (const [key, index] of current.indexes) {
|
|
977
1028
|
if (previous.indexes.has(key))
|
|
978
1029
|
continue;
|
|
@@ -984,6 +1035,7 @@ function diffOneTable(params) {
|
|
|
984
1035
|
unique: index.unique,
|
|
985
1036
|
columns: index.columns,
|
|
986
1037
|
...index.where === undefined ? {} : { where: index.where },
|
|
1038
|
+
...index.nullsNotDistinct === true ? { nullsNotDistinct: true } : {},
|
|
987
1039
|
destructive: false
|
|
988
1040
|
});
|
|
989
1041
|
}
|
|
@@ -1065,6 +1117,9 @@ function renderStep(params) {
|
|
|
1065
1117
|
const pkCols = step.primaryKey.map((column) => q(column)).join(", ");
|
|
1066
1118
|
lines.push(` CONSTRAINT ${q(`${step.table}_pkey`)} PRIMARY KEY (${pkCols})`);
|
|
1067
1119
|
}
|
|
1120
|
+
for (const check of step.checks ?? []) {
|
|
1121
|
+
lines.push(` CONSTRAINT ${q(check.name)} CHECK (${check.expression})`);
|
|
1122
|
+
}
|
|
1068
1123
|
return [`CREATE TABLE ${q(step.table)} (
|
|
1069
1124
|
${lines.join(`,
|
|
1070
1125
|
`)}
|
|
@@ -1085,13 +1140,20 @@ ${lines.join(`,
|
|
|
1085
1140
|
const unique = step.unique ? "UNIQUE " : "";
|
|
1086
1141
|
const using = !step.unique && step.indexKind !== "btree" ? ` USING ${step.indexKind}` : "";
|
|
1087
1142
|
const cols = step.columns.map((column) => `${q(column.name)}${column.desc ? " DESC" : ""}`).join(", ");
|
|
1143
|
+
const nulls = step.nullsNotDistinct === true ? " NULLS NOT DISTINCT" : "";
|
|
1088
1144
|
const where = step.where === undefined ? "" : ` WHERE ${step.where}`;
|
|
1089
1145
|
return [
|
|
1090
|
-
`CREATE ${unique}INDEX ${q(step.name)} ON ${q(step.table)}${using} (${cols})${where};`
|
|
1146
|
+
`CREATE ${unique}INDEX ${q(step.name)} ON ${q(step.table)}${using} (${cols})${nulls}${where};`
|
|
1091
1147
|
];
|
|
1092
1148
|
}
|
|
1093
1149
|
case "dropIndex":
|
|
1094
1150
|
return [`DROP INDEX ${q(step.name)};`];
|
|
1151
|
+
case "addCheck":
|
|
1152
|
+
return [
|
|
1153
|
+
`ALTER TABLE ${q(step.table)} ADD CONSTRAINT ${q(step.name)} CHECK (${step.expression});`
|
|
1154
|
+
];
|
|
1155
|
+
case "dropCheck":
|
|
1156
|
+
return [`ALTER TABLE ${q(step.table)} DROP CONSTRAINT ${q(step.name)};`];
|
|
1095
1157
|
case "addForeignKey": {
|
|
1096
1158
|
const cols = step.columns.map((column) => q(column)).join(", ");
|
|
1097
1159
|
const refCols = step.refColumns.map((column) => q(column)).join(", ");
|
|
@@ -1245,6 +1307,8 @@ function renderSqliteSteps(params) {
|
|
|
1245
1307
|
case "dropForeignKey":
|
|
1246
1308
|
case "addPrimaryKey":
|
|
1247
1309
|
case "dropPrimaryKey":
|
|
1310
|
+
case "addCheck":
|
|
1311
|
+
case "dropCheck":
|
|
1248
1312
|
markRebuild(step.table);
|
|
1249
1313
|
break;
|
|
1250
1314
|
case "addColumn":
|
|
@@ -1288,6 +1352,7 @@ function renderSqliteSteps(params) {
|
|
|
1288
1352
|
constraintTable: step.table,
|
|
1289
1353
|
columns: step.columns,
|
|
1290
1354
|
primaryKey: step.primaryKey,
|
|
1355
|
+
checks: step.checks ?? [],
|
|
1291
1356
|
fks: (foldedFks.get(step.table) ?? []).map((fk) => ({
|
|
1292
1357
|
constraintName: fk.constraintName,
|
|
1293
1358
|
columns: fk.columns,
|
|
@@ -1299,6 +1364,9 @@ function renderSqliteSteps(params) {
|
|
|
1299
1364
|
enums
|
|
1300
1365
|
}));
|
|
1301
1366
|
break;
|
|
1367
|
+
case "addCheck":
|
|
1368
|
+
case "dropCheck":
|
|
1369
|
+
break;
|
|
1302
1370
|
case "createJoinTable": {
|
|
1303
1371
|
const aType = sqliteStorageType({ field: { ...step.a.field, isList: false } });
|
|
1304
1372
|
const bType = sqliteStorageType({ field: { ...step.b.field, isList: false } });
|
|
@@ -1333,7 +1401,8 @@ function renderSqliteSteps(params) {
|
|
|
1333
1401
|
unique: step.unique,
|
|
1334
1402
|
kind: step.indexKind,
|
|
1335
1403
|
columns: step.columns,
|
|
1336
|
-
where: step.where
|
|
1404
|
+
where: step.where,
|
|
1405
|
+
nullsNotDistinct: step.nullsNotDistinct
|
|
1337
1406
|
}));
|
|
1338
1407
|
}
|
|
1339
1408
|
break;
|
|
@@ -1389,6 +1458,7 @@ function renderTableRebuild(params) {
|
|
|
1389
1458
|
constraintTable: table,
|
|
1390
1459
|
columns: [...target.columns.values()].map((column) => column.field),
|
|
1391
1460
|
primaryKey: target.pk,
|
|
1461
|
+
checks: [...target.checks].map(([name, expression]) => ({ name, expression })),
|
|
1392
1462
|
fks: [...target.fks.values()].map((fk) => ({
|
|
1393
1463
|
constraintName: fk.constraintName,
|
|
1394
1464
|
columns: fk.columns,
|
|
@@ -1412,7 +1482,8 @@ function renderTableRebuild(params) {
|
|
|
1412
1482
|
unique: index.unique,
|
|
1413
1483
|
kind: index.kind,
|
|
1414
1484
|
columns: index.columns,
|
|
1415
|
-
where: index.where
|
|
1485
|
+
where: index.where,
|
|
1486
|
+
nullsNotDistinct: index.nullsNotDistinct
|
|
1416
1487
|
}));
|
|
1417
1488
|
}
|
|
1418
1489
|
statements.push("PRAGMA foreign_key_check;", "COMMIT;", "PRAGMA foreign_keys=ON;");
|
|
@@ -1470,6 +1541,9 @@ function createTableSql(params) {
|
|
|
1470
1541
|
if (primaryKey.length > 0 && autoincrementPk === undefined) {
|
|
1471
1542
|
lines.push(` PRIMARY KEY (${primaryKey.map((column) => q2(column)).join(", ")})`);
|
|
1472
1543
|
}
|
|
1544
|
+
for (const check of params.checks) {
|
|
1545
|
+
lines.push(` CONSTRAINT ${q2(check.name)} CHECK (${check.expression})`);
|
|
1546
|
+
}
|
|
1473
1547
|
for (const fk of fks) {
|
|
1474
1548
|
lines.push(` CONSTRAINT ${q2(fk.constraintName)} FOREIGN KEY (${fk.columns.map((column) => q2(column)).join(", ")}) REFERENCES ${q2(fk.refTable)} (${fk.refColumns.map((column) => q2(column)).join(", ")}) ON DELETE ${fk.onDelete} ON UPDATE ${fk.onUpdate}`);
|
|
1475
1549
|
}
|
|
@@ -1525,6 +1599,13 @@ function columnDefSql2(params) {
|
|
|
1525
1599
|
}
|
|
1526
1600
|
function createIndexSql(params) {
|
|
1527
1601
|
const { table, name, unique, kind, columns, where } = params;
|
|
1602
|
+
if (params.nullsNotDistinct === true) {
|
|
1603
|
+
throw unsupportedCapability4({
|
|
1604
|
+
dialect: "sqlite",
|
|
1605
|
+
feature: `UNIQUE NULLS NOT DISTINCT (index "${name}")`,
|
|
1606
|
+
hint: "sqlite treats NULLs as distinct in unique indexes and has no switch \u2014 gate the flag per dialect"
|
|
1607
|
+
});
|
|
1608
|
+
}
|
|
1528
1609
|
if (!unique && kind !== "btree") {
|
|
1529
1610
|
throw unsupportedCapability4({
|
|
1530
1611
|
dialect: "sqlite",
|
|
@@ -1583,6 +1664,9 @@ function renderStep2(params) {
|
|
|
1583
1664
|
if (step.primaryKey.length > 0) {
|
|
1584
1665
|
lines.push(` PRIMARY KEY (${step.primaryKey.map((column) => q3(column)).join(", ")})`);
|
|
1585
1666
|
}
|
|
1667
|
+
for (const check of step.checks ?? []) {
|
|
1668
|
+
lines.push(` CONSTRAINT ${q3(check.name)} CHECK (${check.expression})`);
|
|
1669
|
+
}
|
|
1586
1670
|
return [`CREATE TABLE ${q3(step.table)} (
|
|
1587
1671
|
${lines.join(`,
|
|
1588
1672
|
`)}
|
|
@@ -1609,6 +1693,13 @@ ${lines.join(`,
|
|
|
1609
1693
|
hint: "mysql has no partial indexes \u2014 drop the WHERE predicate or gate the index per dialect"
|
|
1610
1694
|
});
|
|
1611
1695
|
}
|
|
1696
|
+
if (step.nullsNotDistinct === true) {
|
|
1697
|
+
throw unsupportedCapability5({
|
|
1698
|
+
dialect: "mysql",
|
|
1699
|
+
feature: `UNIQUE NULLS NOT DISTINCT (index "${step.name}")`,
|
|
1700
|
+
hint: "mysql treats NULLs as distinct in unique indexes and has no switch \u2014 gate the flag per dialect"
|
|
1701
|
+
});
|
|
1702
|
+
}
|
|
1612
1703
|
if (!step.unique && step.indexKind !== "btree") {
|
|
1613
1704
|
throw unsupportedCapability5({
|
|
1614
1705
|
dialect: "mysql",
|
|
@@ -1621,6 +1712,12 @@ ${lines.join(`,
|
|
|
1621
1712
|
`CREATE ${step.unique ? "UNIQUE " : ""}INDEX ${q3(step.name)} ON ${q3(step.table)} (${cols});`
|
|
1622
1713
|
];
|
|
1623
1714
|
}
|
|
1715
|
+
case "addCheck":
|
|
1716
|
+
return [
|
|
1717
|
+
`ALTER TABLE ${q3(step.table)} ADD CONSTRAINT ${q3(step.name)} CHECK (${step.expression});`
|
|
1718
|
+
];
|
|
1719
|
+
case "dropCheck":
|
|
1720
|
+
return [`ALTER TABLE ${q3(step.table)} DROP CHECK ${q3(step.name)};`];
|
|
1624
1721
|
case "dropIndex": {
|
|
1625
1722
|
if (step.table === undefined) {
|
|
1626
1723
|
throw new VibeError7({
|
|
@@ -2561,6 +2658,18 @@ var CONSTRAINTS_QUERY = `
|
|
|
2561
2658
|
AND n.nspname = 'public'
|
|
2562
2659
|
ORDER BY cl.relname, c.conname, k.ord;
|
|
2563
2660
|
`;
|
|
2661
|
+
var CHECKS_QUERY = `
|
|
2662
|
+
SELECT
|
|
2663
|
+
cl.relname AS table_name,
|
|
2664
|
+
c.conname AS constraint_name,
|
|
2665
|
+
pg_get_constraintdef(c.oid) AS definition
|
|
2666
|
+
FROM pg_catalog.pg_constraint c
|
|
2667
|
+
JOIN pg_catalog.pg_class cl ON cl.oid = c.conrelid
|
|
2668
|
+
JOIN pg_catalog.pg_namespace n ON n.oid = cl.relnamespace
|
|
2669
|
+
WHERE c.contype = 'c'
|
|
2670
|
+
AND n.nspname = 'public'
|
|
2671
|
+
ORDER BY cl.relname, c.conname;
|
|
2672
|
+
`;
|
|
2564
2673
|
var FOREIGN_KEYS_QUERY = `
|
|
2565
2674
|
SELECT
|
|
2566
2675
|
c.conname AS constraint_name,
|
|
@@ -2606,14 +2715,15 @@ var INDEXES_QUERY = `
|
|
|
2606
2715
|
`;
|
|
2607
2716
|
async function introspectPostgres(params) {
|
|
2608
2717
|
const { executor } = params;
|
|
2609
|
-
const [tableRows, viewRows, columnRows, constraintRows, fkRows, enumRows, indexRows] = await Promise.all([
|
|
2718
|
+
const [tableRows, viewRows, columnRows, constraintRows, fkRows, enumRows, indexRows, checkRows] = await Promise.all([
|
|
2610
2719
|
executor({ text: TABLES_QUERY }),
|
|
2611
2720
|
executor({ text: VIEWS_QUERY }),
|
|
2612
2721
|
executor({ text: COLUMNS_QUERY }),
|
|
2613
2722
|
executor({ text: CONSTRAINTS_QUERY }),
|
|
2614
2723
|
executor({ text: FOREIGN_KEYS_QUERY }),
|
|
2615
2724
|
executor({ text: ENUMS_QUERY }),
|
|
2616
|
-
executor({ text: INDEXES_QUERY })
|
|
2725
|
+
executor({ text: INDEXES_QUERY }),
|
|
2726
|
+
executor({ text: CHECKS_QUERY })
|
|
2617
2727
|
]);
|
|
2618
2728
|
const tables = tableRows.map((row) => row.table_name);
|
|
2619
2729
|
const views = viewRows.map((row) => row.table_name);
|
|
@@ -2668,6 +2778,17 @@ async function introspectPostgres(params) {
|
|
|
2668
2778
|
entry.columns.push(columnName);
|
|
2669
2779
|
}
|
|
2670
2780
|
}
|
|
2781
|
+
const checksByTable = new Map;
|
|
2782
|
+
for (const row of checkRows) {
|
|
2783
|
+
const table = row.table_name;
|
|
2784
|
+
const name = row.constraint_name;
|
|
2785
|
+
const expression = stripCheckDefinition({ definition: String(row.definition ?? "") });
|
|
2786
|
+
const list = checksByTable.get(table);
|
|
2787
|
+
if (list === undefined)
|
|
2788
|
+
checksByTable.set(table, [{ name, expression }]);
|
|
2789
|
+
else
|
|
2790
|
+
list.push({ name, expression });
|
|
2791
|
+
}
|
|
2671
2792
|
const fkGroupsByName = new Map;
|
|
2672
2793
|
for (const row of fkRows) {
|
|
2673
2794
|
const constraintName = row.constraint_name;
|
|
@@ -2727,7 +2848,8 @@ async function introspectPostgres(params) {
|
|
|
2727
2848
|
uniquesByConstraint,
|
|
2728
2849
|
constraintNames,
|
|
2729
2850
|
indexes,
|
|
2730
|
-
enumNames
|
|
2851
|
+
enumNames,
|
|
2852
|
+
checks: checksByTable.get(table) ?? []
|
|
2731
2853
|
}));
|
|
2732
2854
|
}
|
|
2733
2855
|
for (const view of views) {
|
|
@@ -2739,7 +2861,8 @@ async function introspectPostgres(params) {
|
|
|
2739
2861
|
uniquesByConstraint,
|
|
2740
2862
|
constraintNames,
|
|
2741
2863
|
indexes: [],
|
|
2742
|
-
enumNames
|
|
2864
|
+
enumNames,
|
|
2865
|
+
checks: []
|
|
2743
2866
|
}));
|
|
2744
2867
|
}
|
|
2745
2868
|
addFkRelations({ models, fkGroups, joinTables });
|
|
@@ -2769,8 +2892,9 @@ function buildModel(params) {
|
|
|
2769
2892
|
for (const index of tableIndexes) {
|
|
2770
2893
|
if (!index.unique)
|
|
2771
2894
|
continue;
|
|
2772
|
-
if (index.columns.length === 1)
|
|
2895
|
+
if (index.columns.length === 1 && index.where === undefined && index.nullsNotDistinct !== true) {
|
|
2773
2896
|
uniqueSingles.add(index.columns[0].name);
|
|
2897
|
+
}
|
|
2774
2898
|
}
|
|
2775
2899
|
const fields = tableColumns.map((column) => buildField({ column, pk, uniqueSingles, enumNames }));
|
|
2776
2900
|
const modelIndexes = [];
|
|
@@ -2782,8 +2906,9 @@ function buildModel(params) {
|
|
|
2782
2906
|
});
|
|
2783
2907
|
}
|
|
2784
2908
|
for (const index of tableIndexes) {
|
|
2785
|
-
if (index.unique && index.columns.length === 1)
|
|
2909
|
+
if (index.unique && index.columns.length === 1 && index.where === undefined && index.nullsNotDistinct !== true) {
|
|
2786
2910
|
continue;
|
|
2911
|
+
}
|
|
2787
2912
|
modelIndexes.push({
|
|
2788
2913
|
name: index.name,
|
|
2789
2914
|
kind: index.unique ? "unique" : index.kind,
|
|
@@ -2791,7 +2916,8 @@ function buildModel(params) {
|
|
|
2791
2916
|
name: column.name,
|
|
2792
2917
|
...column.desc ? { sort: "desc" } : {}
|
|
2793
2918
|
})),
|
|
2794
|
-
...index.where === undefined ? {} : { where: index.where }
|
|
2919
|
+
...index.where === undefined ? {} : { where: index.where },
|
|
2920
|
+
...index.nullsNotDistinct === true ? { nullsNotDistinct: true } : {}
|
|
2795
2921
|
});
|
|
2796
2922
|
}
|
|
2797
2923
|
return {
|
|
@@ -2799,10 +2925,16 @@ function buildModel(params) {
|
|
|
2799
2925
|
fields,
|
|
2800
2926
|
relations: [],
|
|
2801
2927
|
indexes: modelIndexes,
|
|
2928
|
+
...params.checks.length === 0 ? {} : { checks: params.checks },
|
|
2802
2929
|
isView,
|
|
2803
2930
|
...pk.length > 1 ? { primaryKey: { fields: pk } } : {}
|
|
2804
2931
|
};
|
|
2805
2932
|
}
|
|
2933
|
+
function stripCheckDefinition(params) {
|
|
2934
|
+
const trimmed = params.definition.trim();
|
|
2935
|
+
const match = trimmed.match(/^CHECK\s*\((.*)\)$/is);
|
|
2936
|
+
return match === null ? trimmed : match[1].trim();
|
|
2937
|
+
}
|
|
2806
2938
|
function buildField(params) {
|
|
2807
2939
|
const { column, pk, uniqueSingles, enumNames } = params;
|
|
2808
2940
|
const mapped = reverseMapType({ column, enumNames });
|
|
@@ -2953,7 +3085,10 @@ function parseIndexDef(params) {
|
|
|
2953
3085
|
const nameOnly = trimmed.replace(/ (DESC|ASC)( NULLS (FIRST|LAST))?$/i, "");
|
|
2954
3086
|
return { name: nameOnly.replaceAll('"', ""), desc };
|
|
2955
3087
|
});
|
|
2956
|
-
|
|
3088
|
+
let tail = def.slice(end + 1).trim();
|
|
3089
|
+
const nullsNotDistinct = /^NULLS NOT DISTINCT\b/i.test(tail);
|
|
3090
|
+
if (nullsNotDistinct)
|
|
3091
|
+
tail = tail.slice("NULLS NOT DISTINCT".length).trim();
|
|
2957
3092
|
const whereMatch = tail.match(/^WHERE (.*)$/);
|
|
2958
3093
|
const whereRaw = whereMatch?.[1];
|
|
2959
3094
|
return {
|
|
@@ -2962,7 +3097,8 @@ function parseIndexDef(params) {
|
|
|
2962
3097
|
unique: head[1] !== undefined,
|
|
2963
3098
|
kind: head[2].toLowerCase(),
|
|
2964
3099
|
columns,
|
|
2965
|
-
...whereRaw === undefined ? {} : { where: whereRaw }
|
|
3100
|
+
...whereRaw === undefined ? {} : { where: whereRaw },
|
|
3101
|
+
...nullsNotDistinct ? { nullsNotDistinct: true } : {}
|
|
2966
3102
|
};
|
|
2967
3103
|
}
|
|
2968
3104
|
function splitTopLevel(params) {
|
|
@@ -3026,6 +3162,7 @@ async function introspectSqlite(params) {
|
|
|
3026
3162
|
const indexes = [];
|
|
3027
3163
|
const uniqueSinglesByTable = new Map;
|
|
3028
3164
|
const modelIndexesByTable = new Map;
|
|
3165
|
+
const checksByTable = new Map;
|
|
3029
3166
|
const fkGroups = [];
|
|
3030
3167
|
const enumsByColumn = new Map;
|
|
3031
3168
|
const enumRegistry = new Map;
|
|
@@ -3033,15 +3170,18 @@ async function introspectSqlite(params) {
|
|
|
3033
3170
|
for (const table of tables) {
|
|
3034
3171
|
const columns = await readColumns({ executor, table: table.name });
|
|
3035
3172
|
columnsByTable.set(table.name, columns);
|
|
3173
|
+
const enumCheckNames = new Set;
|
|
3036
3174
|
for (const check of parseSqliteEnumChecks({ tableSql: table.sql ?? "" })) {
|
|
3037
3175
|
enumsByColumn.set(`${table.name}.${check.column}`, {
|
|
3038
3176
|
enumName: check.enumName,
|
|
3039
3177
|
values: check.values
|
|
3040
3178
|
});
|
|
3179
|
+
enumCheckNames.add(sqliteEnumCheckName({ table: table.name, column: check.column, enumName: check.enumName }));
|
|
3041
3180
|
if (!enumRegistry.has(check.enumName)) {
|
|
3042
3181
|
enumRegistry.set(check.enumName, { name: check.enumName, values: check.values });
|
|
3043
3182
|
}
|
|
3044
3183
|
}
|
|
3184
|
+
checksByTable.set(table.name, parseSqliteNamedChecks({ tableSql: table.sql ?? "" }).filter((check) => !enumCheckNames.has(check.name)));
|
|
3045
3185
|
if (/PRIMARY KEY AUTOINCREMENT/i.test(table.sql ?? "")) {
|
|
3046
3186
|
autoincrementTables.add(table.name);
|
|
3047
3187
|
}
|
|
@@ -3077,7 +3217,8 @@ async function introspectSqlite(params) {
|
|
|
3077
3217
|
uniqueSingles: uniqueSinglesByTable.get(table.name) ?? new Set,
|
|
3078
3218
|
modelIndexes: modelIndexesByTable.get(table.name) ?? [],
|
|
3079
3219
|
enumsByColumn,
|
|
3080
|
-
autoincrement: autoincrementTables.has(table.name)
|
|
3220
|
+
autoincrement: autoincrementTables.has(table.name),
|
|
3221
|
+
checks: checksByTable.get(table.name) ?? []
|
|
3081
3222
|
}));
|
|
3082
3223
|
}
|
|
3083
3224
|
for (const view of views) {
|
|
@@ -3088,7 +3229,8 @@ async function introspectSqlite(params) {
|
|
|
3088
3229
|
uniqueSingles: new Set,
|
|
3089
3230
|
modelIndexes: [],
|
|
3090
3231
|
enumsByColumn,
|
|
3091
|
-
autoincrement: false
|
|
3232
|
+
autoincrement: false,
|
|
3233
|
+
checks: []
|
|
3092
3234
|
}));
|
|
3093
3235
|
}
|
|
3094
3236
|
addFkRelations({ models, fkGroups, joinTables });
|
|
@@ -3289,6 +3431,7 @@ function buildModel2(params) {
|
|
|
3289
3431
|
fields,
|
|
3290
3432
|
relations: [],
|
|
3291
3433
|
indexes: [...modelIndexes],
|
|
3434
|
+
...params.checks.length === 0 ? {} : { checks: params.checks },
|
|
3292
3435
|
isView,
|
|
3293
3436
|
...pk.length > 1 ? { primaryKey: { fields: pk } } : {}
|
|
3294
3437
|
};
|
|
@@ -3394,6 +3537,19 @@ var REFERENTIAL_QUERY = `
|
|
|
3394
3537
|
FROM information_schema.referential_constraints
|
|
3395
3538
|
WHERE constraint_schema = DATABASE();
|
|
3396
3539
|
`;
|
|
3540
|
+
var CHECKS_QUERY2 = `
|
|
3541
|
+
SELECT
|
|
3542
|
+
tc.table_name AS table_name,
|
|
3543
|
+
tc.constraint_name AS constraint_name,
|
|
3544
|
+
cc.check_clause AS definition
|
|
3545
|
+
FROM information_schema.table_constraints tc
|
|
3546
|
+
JOIN information_schema.check_constraints cc
|
|
3547
|
+
ON cc.constraint_schema = tc.constraint_schema
|
|
3548
|
+
AND cc.constraint_name = tc.constraint_name
|
|
3549
|
+
WHERE tc.table_schema = DATABASE()
|
|
3550
|
+
AND tc.constraint_type = 'CHECK'
|
|
3551
|
+
ORDER BY tc.table_name, tc.constraint_name;
|
|
3552
|
+
`;
|
|
3397
3553
|
var MYSQL_RULE_TO_CASCADE = {
|
|
3398
3554
|
"NO ACTION": "NoAction",
|
|
3399
3555
|
RESTRICT: "Restrict",
|
|
@@ -3407,14 +3563,26 @@ function catalogField(params) {
|
|
|
3407
3563
|
}
|
|
3408
3564
|
async function introspectMysql(params) {
|
|
3409
3565
|
const { executor } = params;
|
|
3410
|
-
const [tableRows, viewRows, columnRows, statisticRows, fkRows, refRows] = await Promise.all([
|
|
3566
|
+
const [tableRows, viewRows, columnRows, statisticRows, fkRows, refRows, checkRows] = await Promise.all([
|
|
3411
3567
|
executor({ text: TABLES_QUERY2 }),
|
|
3412
3568
|
executor({ text: VIEWS_QUERY2 }),
|
|
3413
3569
|
executor({ text: COLUMNS_QUERY2 }),
|
|
3414
3570
|
executor({ text: STATISTICS_QUERY }),
|
|
3415
3571
|
executor({ text: FOREIGN_KEYS_QUERY2 }),
|
|
3416
|
-
executor({ text: REFERENTIAL_QUERY })
|
|
3572
|
+
executor({ text: REFERENTIAL_QUERY }),
|
|
3573
|
+
executor({ text: CHECKS_QUERY2 })
|
|
3417
3574
|
]);
|
|
3575
|
+
const checksByTable = new Map;
|
|
3576
|
+
for (const row of checkRows) {
|
|
3577
|
+
const table = catalogField({ row, name: "table_name" });
|
|
3578
|
+
const name = catalogField({ row, name: "constraint_name" });
|
|
3579
|
+
const expression = stripBalancedOuterParens(String(catalogField({ row, name: "definition" }) ?? ""));
|
|
3580
|
+
const list = checksByTable.get(table);
|
|
3581
|
+
if (list === undefined)
|
|
3582
|
+
checksByTable.set(table, [{ name, expression }]);
|
|
3583
|
+
else
|
|
3584
|
+
list.push({ name, expression });
|
|
3585
|
+
}
|
|
3418
3586
|
const tables = tableRows.map((row) => catalogField({ row, name: "table_name" }));
|
|
3419
3587
|
const views = viewRows.map((row) => catalogField({ row, name: "table_name" }));
|
|
3420
3588
|
const columns = columnRows.map((row) => ({
|
|
@@ -3524,10 +3692,26 @@ async function introspectMysql(params) {
|
|
|
3524
3692
|
for (const table of tables) {
|
|
3525
3693
|
if (joinTables.has(table))
|
|
3526
3694
|
continue;
|
|
3527
|
-
models.push(buildModel3({
|
|
3695
|
+
models.push(buildModel3({
|
|
3696
|
+
table,
|
|
3697
|
+
isView: false,
|
|
3698
|
+
columns,
|
|
3699
|
+
pkByTable,
|
|
3700
|
+
indexes,
|
|
3701
|
+
enums,
|
|
3702
|
+
checks: checksByTable.get(table) ?? []
|
|
3703
|
+
}));
|
|
3528
3704
|
}
|
|
3529
3705
|
for (const view of views) {
|
|
3530
|
-
models.push(buildModel3({
|
|
3706
|
+
models.push(buildModel3({
|
|
3707
|
+
table: view,
|
|
3708
|
+
isView: true,
|
|
3709
|
+
columns,
|
|
3710
|
+
pkByTable: new Map,
|
|
3711
|
+
indexes: [],
|
|
3712
|
+
enums,
|
|
3713
|
+
checks: []
|
|
3714
|
+
}));
|
|
3531
3715
|
}
|
|
3532
3716
|
addFkRelations({ models, fkGroups, joinTables });
|
|
3533
3717
|
addJoinTableRelations({ models, joinTables });
|
|
@@ -3584,10 +3768,28 @@ function buildModel3(params) {
|
|
|
3584
3768
|
fields,
|
|
3585
3769
|
relations: [],
|
|
3586
3770
|
indexes: modelIndexes,
|
|
3771
|
+
...params.checks.length === 0 ? {} : { checks: params.checks },
|
|
3587
3772
|
isView,
|
|
3588
3773
|
...pk.length > 1 ? { primaryKey: { fields: pk } } : {}
|
|
3589
3774
|
};
|
|
3590
3775
|
}
|
|
3776
|
+
function stripBalancedOuterParens(text) {
|
|
3777
|
+
const trimmed = text.trim();
|
|
3778
|
+
if (!trimmed.startsWith("(") || !trimmed.endsWith(")"))
|
|
3779
|
+
return trimmed;
|
|
3780
|
+
let depth = 0;
|
|
3781
|
+
for (let index = 0;index < trimmed.length; index++) {
|
|
3782
|
+
const char = trimmed[index];
|
|
3783
|
+
if (char === "(")
|
|
3784
|
+
depth += 1;
|
|
3785
|
+
else if (char === ")") {
|
|
3786
|
+
depth -= 1;
|
|
3787
|
+
if (depth === 0 && index < trimmed.length - 1)
|
|
3788
|
+
return trimmed;
|
|
3789
|
+
}
|
|
3790
|
+
}
|
|
3791
|
+
return trimmed.slice(1, -1).trim();
|
|
3792
|
+
}
|
|
3591
3793
|
var CANONICAL_MYSQL = {
|
|
3592
3794
|
"varchar(191)": "String",
|
|
3593
3795
|
"tinyint(1)": "Boolean",
|
|
@@ -3855,4 +4057,4 @@ export {
|
|
|
3855
4057
|
MIGRATIONS_TABLE_NAME
|
|
3856
4058
|
};
|
|
3857
4059
|
|
|
3858
|
-
//# debugId=
|
|
4060
|
+
//# debugId=CA4C1473A398313F64756E2164756E21
|