orchid-orm 1.38.0 → 1.38.2
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.d.ts +7 -2
- package/dist/index.js +109 -11
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +109 -11
- package/dist/index.mjs.map +1 -1
- package/dist/migrations.js +143 -59
- package/dist/migrations.js.map +1 -1
- package/dist/migrations.mjs +144 -60
- package/dist/migrations.mjs.map +1 -1
- package/package.json +5 -5
package/dist/migrations.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { promptSelect, colors, getSchemaAndTableFromName, getDbTableColumnsChecks, dbColumnToAst, instantiateDbColumn, concatSchemaAndName, encodeColumnDefault, getIndexName, getExcludeName, getConstraintName, tableToAst, getDbStructureTableData, makeDomainsMap, astToMigration, createMigrationInterface, introspectDbSchema, exhaustive, pluralize, makeStructureToAstCtx, makeFileVersion, writeMigrationFile, migrate, structureToAst, saveMigratedVersion, rakeDbCommands } from 'rake-db';
|
|
2
2
|
export * from 'rake-db';
|
|
3
|
-
import { toSnakeCase, deepCompare, toArray, addCode, codeToString, toCamelCase, toPascalCase, getImportPath, singleQuote, quoteObjectKey, pathToLog } from 'orchid-core';
|
|
3
|
+
import { toSnakeCase, deepCompare, emptyArray, toArray, addCode, codeToString, toCamelCase, toPascalCase, getImportPath, singleQuote, quoteObjectKey, pathToLog } from 'orchid-core';
|
|
4
4
|
import { EnumColumn, ArrayColumn, DomainColumn, RawSQL, VirtualColumn, UnknownColumn, defaultSchemaConfig, columnsShapeToCode, pushTableDataCode, Adapter } from 'pqb';
|
|
5
5
|
import path from 'node:path';
|
|
6
6
|
import { pathToFileURL } from 'url';
|
|
@@ -14,23 +14,30 @@ const compareSqlExpressions = async (tableExpressions, adapter) => {
|
|
|
14
14
|
tableExpressions.map(async ({ source, compare, handle }) => {
|
|
15
15
|
const viewName = `orchidTmpView${id++}`;
|
|
16
16
|
const values = [];
|
|
17
|
+
let result;
|
|
17
18
|
try {
|
|
18
|
-
const
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
19
|
+
const results = await adapter.query({
|
|
20
|
+
// It is important to run `CREATE TEMPORARY VIEW` and `DROP VIEW` on the same db connection,
|
|
21
|
+
// that's why SQLs are combined into a single query.
|
|
22
|
+
text: [
|
|
23
|
+
`CREATE TEMPORARY VIEW ${viewName} AS (SELECT ${compare.map(
|
|
24
|
+
({ inDb: inDb2, inCode }, i) => `${inDb2} AS "*inDb-${i}*", ${inCode.map(
|
|
25
|
+
(s, j) => `(${typeof s === "string" ? s : s.toSQL({ values })}) "*inCode-${i}-${j}*"`
|
|
26
|
+
).join(", ")}`
|
|
27
|
+
).join(", ")} FROM ${source})`,
|
|
28
|
+
`SELECT pg_get_viewdef('${viewName}') v`,
|
|
29
|
+
`DROP VIEW ${viewName}`
|
|
30
|
+
].join("; "),
|
|
31
|
+
values
|
|
32
|
+
});
|
|
33
|
+
result = results[1];
|
|
34
|
+
} catch {
|
|
35
|
+
}
|
|
36
|
+
if (!result) {
|
|
25
37
|
handle();
|
|
26
38
|
return;
|
|
27
39
|
}
|
|
28
|
-
const
|
|
29
|
-
rows: [{ v }]
|
|
30
|
-
} = await adapter.query(
|
|
31
|
-
`SELECT pg_get_viewdef('${viewName}') v`
|
|
32
|
-
);
|
|
33
|
-
await adapter.query(`DROP VIEW ${viewName}`);
|
|
40
|
+
const v = result.rows[0].v;
|
|
34
41
|
let pos = 7;
|
|
35
42
|
const rgx = /\s+AS\s+"\*(inDb-\d+|inCode-\d+-\d+)\*",?/g;
|
|
36
43
|
let match;
|
|
@@ -618,10 +625,10 @@ const processDomains = async (ast, adapter, structureToAstCtx, domainsMap, dbStr
|
|
|
618
625
|
typmod: -1
|
|
619
626
|
}
|
|
620
627
|
);
|
|
621
|
-
if (domain.
|
|
622
|
-
dbColumn.data.
|
|
623
|
-
sql: new RawSQL([[
|
|
624
|
-
};
|
|
628
|
+
if (domain.checks) {
|
|
629
|
+
dbColumn.data.checks = domain.checks.map((check) => ({
|
|
630
|
+
sql: new RawSQL([[check]])
|
|
631
|
+
}));
|
|
625
632
|
}
|
|
626
633
|
const dbDomain = makeComparableDomain(
|
|
627
634
|
currentSchema,
|
|
@@ -632,13 +639,13 @@ const processDomains = async (ast, adapter, structureToAstCtx, domainsMap, dbStr
|
|
|
632
639
|
const found = codeDomains.filter(
|
|
633
640
|
(codeDomain) => deepCompare(dbDomain.compare, codeDomain.compare)
|
|
634
641
|
);
|
|
635
|
-
if ((domain.default || domain.
|
|
642
|
+
if ((domain.default || domain.checks?.length) && found.length) {
|
|
636
643
|
for (const codeDomain of found) {
|
|
637
644
|
holdCodeDomains.add(codeDomain);
|
|
638
645
|
}
|
|
639
646
|
const compare = [];
|
|
640
|
-
|
|
641
|
-
|
|
647
|
+
pushCompareDefault(compare, domain, found);
|
|
648
|
+
pushCompareChecks(compare, domain, found);
|
|
642
649
|
const source = `(VALUES (NULL::${getColumnDbType(
|
|
643
650
|
dbColumn,
|
|
644
651
|
currentSchema
|
|
@@ -715,17 +722,16 @@ const makeComparableDomain = (currentSchema, schemaName, name, column) => {
|
|
|
715
722
|
dateTimePrecision: inner.data.dateTimePrecision,
|
|
716
723
|
collate: column.data.collate,
|
|
717
724
|
hasDefault: column.data.default !== void 0,
|
|
718
|
-
|
|
725
|
+
hasChecks: !!column.data.checks?.length
|
|
719
726
|
}
|
|
720
727
|
};
|
|
721
728
|
};
|
|
722
|
-
const
|
|
723
|
-
|
|
724
|
-
if (inDb) {
|
|
729
|
+
const pushCompareDefault = (compare, domain, found) => {
|
|
730
|
+
if (domain.default) {
|
|
725
731
|
compare.push({
|
|
726
|
-
inDb,
|
|
732
|
+
inDb: domain.default,
|
|
727
733
|
inCode: found.map((codeDomain) => {
|
|
728
|
-
const value = codeDomain.column.data
|
|
734
|
+
const value = codeDomain.column.data.default;
|
|
729
735
|
if ("sql" in value) {
|
|
730
736
|
return value.sql;
|
|
731
737
|
}
|
|
@@ -734,6 +740,21 @@ const pushCompare = (compare, domain, found, key) => {
|
|
|
734
740
|
});
|
|
735
741
|
}
|
|
736
742
|
};
|
|
743
|
+
const pushCompareChecks = (compare, domain, found) => {
|
|
744
|
+
if (domain.checks?.length) {
|
|
745
|
+
const inCode = found.flatMap(
|
|
746
|
+
(codeDomain) => codeDomain.column.data.checks?.map(
|
|
747
|
+
(check) => typeof check === "string" ? check : check.sql
|
|
748
|
+
) || emptyArray
|
|
749
|
+
);
|
|
750
|
+
compare.push(
|
|
751
|
+
...domain.checks.map((check) => ({
|
|
752
|
+
inDb: check,
|
|
753
|
+
inCode
|
|
754
|
+
}))
|
|
755
|
+
);
|
|
756
|
+
}
|
|
757
|
+
};
|
|
737
758
|
const dropAst = (dbDomain) => ({
|
|
738
759
|
type: "domain",
|
|
739
760
|
action: "drop",
|
|
@@ -1211,6 +1232,7 @@ const collectCodeComparableItemsType = (config, codeItems, key) => {
|
|
|
1211
1232
|
});
|
|
1212
1233
|
};
|
|
1213
1234
|
const normalizeItem = (item) => {
|
|
1235
|
+
if (item.using) item.using = item.using.toLowerCase();
|
|
1214
1236
|
if (item.using === "btree") item.using = void 0;
|
|
1215
1237
|
if (!item.unique) item.unique = void 0;
|
|
1216
1238
|
if (item.nullsNotDistinct === false) item.nullsNotDistinct = void 0;
|
|
@@ -1619,12 +1641,12 @@ const processChecks = (ast, changeTableData, compareExpressions) => {
|
|
|
1619
1641
|
if (!hasDbChecks) {
|
|
1620
1642
|
if (codeChecks.length) {
|
|
1621
1643
|
const constraints = add.constraints ?? (add.constraints = []);
|
|
1622
|
-
for (const
|
|
1623
|
-
if (
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1644
|
+
for (const codeCheck of codeChecks) {
|
|
1645
|
+
if (!codeCheck.column || !changeTableData.changingColumns[codeCheck.column]) {
|
|
1646
|
+
constraints.push({
|
|
1647
|
+
check: codeCheck.check.sql,
|
|
1648
|
+
name: codeCheck.name
|
|
1649
|
+
});
|
|
1628
1650
|
}
|
|
1629
1651
|
}
|
|
1630
1652
|
}
|
|
@@ -1645,20 +1667,40 @@ const processChecks = (ast, changeTableData, compareExpressions) => {
|
|
|
1645
1667
|
compare: [
|
|
1646
1668
|
{
|
|
1647
1669
|
inDb: dbCheck.expression,
|
|
1648
|
-
inCode: codeChecks.map((check) => check.sql)
|
|
1670
|
+
inCode: codeChecks.map(({ check }) => check.sql)
|
|
1649
1671
|
}
|
|
1650
1672
|
],
|
|
1651
1673
|
handle(i) {
|
|
1652
|
-
if (i !== void 0)
|
|
1653
|
-
|
|
1654
|
-
|
|
1674
|
+
if (i !== void 0) {
|
|
1675
|
+
foundCodeChecks.add(i);
|
|
1676
|
+
} else {
|
|
1677
|
+
dropCheck(changeTableData, dbCheck, name);
|
|
1678
|
+
}
|
|
1679
|
+
if (--wait !== 0) return;
|
|
1680
|
+
const checksToAdd = [];
|
|
1681
|
+
codeChecks.forEach((check, i2) => {
|
|
1682
|
+
if (foundCodeChecks.has(i2)) {
|
|
1683
|
+
if (!check.column) return;
|
|
1684
|
+
const change = changeTableData.changingColumns[check.column];
|
|
1685
|
+
if (!change) return;
|
|
1686
|
+
const columnChecks = change.to.data.checks;
|
|
1687
|
+
if (!columnChecks) return;
|
|
1688
|
+
const i3 = columnChecks.indexOf(check.check);
|
|
1689
|
+
if (i3 !== -1) {
|
|
1690
|
+
columnChecks.splice(i3, 1);
|
|
1691
|
+
}
|
|
1692
|
+
return;
|
|
1693
|
+
}
|
|
1694
|
+
checksToAdd.push({
|
|
1695
|
+
name: check.name,
|
|
1696
|
+
check: check.check.sql
|
|
1697
|
+
});
|
|
1698
|
+
});
|
|
1699
|
+
if (checksToAdd.length) {
|
|
1700
|
+
(add.constraints ?? (add.constraints = [])).push(...checksToAdd);
|
|
1701
|
+
}
|
|
1702
|
+
if (!changeTableData.pushedAst && (changeTableData.changeTableAst.drop.constraints?.length || add.constraints?.length)) {
|
|
1655
1703
|
changeTableData.pushedAst = true;
|
|
1656
|
-
(add.constraints ?? (add.constraints = [])).push(
|
|
1657
|
-
...codeChecks.filter((_, i2) => !foundCodeChecks.has(i2)).map((check) => ({
|
|
1658
|
-
name: check.name,
|
|
1659
|
-
check: check.sql
|
|
1660
|
-
}))
|
|
1661
|
-
);
|
|
1662
1704
|
ast.push(changeTableData.changeTableAst);
|
|
1663
1705
|
}
|
|
1664
1706
|
}
|
|
@@ -1672,41 +1714,70 @@ const collectCodeChecks = ({
|
|
|
1672
1714
|
codeTable,
|
|
1673
1715
|
changeTableAst: { shape }
|
|
1674
1716
|
}) => {
|
|
1717
|
+
const names = /* @__PURE__ */ new Set();
|
|
1675
1718
|
const codeChecks = [];
|
|
1676
1719
|
for (const key in codeTable.shape) {
|
|
1677
1720
|
const column = codeTable.shape[key];
|
|
1678
|
-
if (!column.data.
|
|
1679
|
-
const
|
|
1680
|
-
if (checkForColumnAddOrDrop(shape,
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
column
|
|
1684
|
-
|
|
1721
|
+
if (!column.data.checks) continue;
|
|
1722
|
+
const columnName = column.data.name ?? key;
|
|
1723
|
+
if (checkForColumnAddOrDrop(shape, columnName)) continue;
|
|
1724
|
+
const baseName = `${codeTable.table}_${columnName}_check`;
|
|
1725
|
+
codeChecks.push(
|
|
1726
|
+
...column.data.checks.map((check) => {
|
|
1727
|
+
let name = check.name;
|
|
1728
|
+
if (!name) {
|
|
1729
|
+
name = baseName;
|
|
1730
|
+
let n = 0;
|
|
1731
|
+
while (names.has(name)) {
|
|
1732
|
+
name = baseName + ++n;
|
|
1733
|
+
}
|
|
1734
|
+
}
|
|
1735
|
+
names.add(name);
|
|
1736
|
+
return {
|
|
1737
|
+
check,
|
|
1738
|
+
name,
|
|
1739
|
+
column: columnName
|
|
1740
|
+
};
|
|
1741
|
+
})
|
|
1742
|
+
);
|
|
1685
1743
|
}
|
|
1686
1744
|
if (codeTable.internal.tableData.constraints) {
|
|
1687
1745
|
for (const constraint of codeTable.internal.tableData.constraints) {
|
|
1688
1746
|
const { check } = constraint;
|
|
1689
1747
|
if (check) {
|
|
1690
|
-
|
|
1748
|
+
const baseName = `${codeTable.table}_check`;
|
|
1749
|
+
let name = constraint.name;
|
|
1750
|
+
if (!name) {
|
|
1751
|
+
name = baseName;
|
|
1752
|
+
let n = 0;
|
|
1753
|
+
while (names.has(name)) {
|
|
1754
|
+
name = baseName + ++n;
|
|
1755
|
+
}
|
|
1756
|
+
}
|
|
1757
|
+
names.add(name);
|
|
1758
|
+
codeChecks.push({
|
|
1759
|
+
check: { sql: check, name: constraint.name },
|
|
1760
|
+
name
|
|
1761
|
+
});
|
|
1691
1762
|
}
|
|
1692
1763
|
}
|
|
1693
1764
|
}
|
|
1694
1765
|
return codeChecks;
|
|
1695
1766
|
};
|
|
1696
1767
|
const dropCheck = ({ changeTableAst: { drop }, changingColumns }, dbCheck, name) => {
|
|
1697
|
-
|
|
1768
|
+
var _a;
|
|
1698
1769
|
const sql = new RawSQL([
|
|
1699
1770
|
[dbCheck.expression]
|
|
1700
1771
|
]);
|
|
1701
1772
|
if (dbCheck.columns?.length === 1 && changingColumns[dbCheck.columns[0]]) {
|
|
1702
1773
|
const column = changingColumns[dbCheck.columns[0]];
|
|
1703
1774
|
column.from.data.name = "i_d";
|
|
1704
|
-
column.from.data.
|
|
1775
|
+
((_a = column.from.data).checks ?? (_a.checks = [])).push({
|
|
1705
1776
|
name,
|
|
1706
1777
|
sql
|
|
1707
|
-
};
|
|
1778
|
+
});
|
|
1708
1779
|
} else {
|
|
1709
|
-
constraints.push({
|
|
1780
|
+
(drop.constraints ?? (drop.constraints = [])).push({
|
|
1710
1781
|
name,
|
|
1711
1782
|
check: sql
|
|
1712
1783
|
});
|
|
@@ -1920,7 +1991,7 @@ const addChangeTable = (dbStructure, changeTables, tableShapes, currentSchema, d
|
|
|
1920
1991
|
const shape = {};
|
|
1921
1992
|
const schema = codeTable.q.schema ?? currentSchema;
|
|
1922
1993
|
changeTables.push({
|
|
1923
|
-
codeTable,
|
|
1994
|
+
codeTable: cloneCodeTableForChange(codeTable),
|
|
1924
1995
|
dbTable,
|
|
1925
1996
|
dbTableData: getDbStructureTableData(dbStructure, dbTable),
|
|
1926
1997
|
schema,
|
|
@@ -1938,6 +2009,19 @@ const addChangeTable = (dbStructure, changeTables, tableShapes, currentSchema, d
|
|
|
1938
2009
|
});
|
|
1939
2010
|
tableShapes[`${schema}.${codeTable.table}`] = shape;
|
|
1940
2011
|
};
|
|
2012
|
+
const cloneCodeTableForChange = (codeTable) => ({
|
|
2013
|
+
...codeTable,
|
|
2014
|
+
shape: Object.fromEntries(
|
|
2015
|
+
Object.entries(codeTable.shape).map(([key, column]) => {
|
|
2016
|
+
const cloned = Object.create(column);
|
|
2017
|
+
cloned.data = {
|
|
2018
|
+
...cloned.data,
|
|
2019
|
+
checks: cloned.data.checks && [...cloned.data.checks]
|
|
2020
|
+
};
|
|
2021
|
+
return [key, cloned];
|
|
2022
|
+
})
|
|
2023
|
+
)
|
|
2024
|
+
});
|
|
1941
2025
|
const createTableAst = (currentSchema, table) => {
|
|
1942
2026
|
return {
|
|
1943
2027
|
type: "table",
|
|
@@ -2106,8 +2190,8 @@ const report = (ast, config, currentSchema) => {
|
|
|
2106
2190
|
if (column.data.foreignKeys) {
|
|
2107
2191
|
counters["foreign key"] += column.data.foreignKeys.length;
|
|
2108
2192
|
}
|
|
2109
|
-
if (column.data.
|
|
2110
|
-
counters.check
|
|
2193
|
+
if (column.data.checks) {
|
|
2194
|
+
counters.check += column.data.checks.length;
|
|
2111
2195
|
}
|
|
2112
2196
|
}
|
|
2113
2197
|
const summary = [];
|
|
@@ -2140,13 +2224,13 @@ const report = (ast, config, currentSchema) => {
|
|
|
2140
2224
|
for (const change of changes) {
|
|
2141
2225
|
if (change.type === "add" || change.type === "drop") {
|
|
2142
2226
|
const column = change.item;
|
|
2143
|
-
const { primaryKey, indexes, excludes, foreignKeys,
|
|
2227
|
+
const { primaryKey, indexes, excludes, foreignKeys, checks } = column.data;
|
|
2144
2228
|
inner.push(
|
|
2145
2229
|
`${change.type === "add" ? green("+ add column") : red("- drop column")} ${key} ${column.data.alias ?? getColumnDbType(column, currentSchema)}${column.data.isNullable ? " nullable" : ""}${primaryKey ? " primary key" : ""}${foreignKeys ? ` references ${foreignKeys.map((fk) => {
|
|
2146
2230
|
return `${fnOrTableToString(
|
|
2147
2231
|
fk.fnOrTable
|
|
2148
2232
|
)}(${fk.foreignColumns.join(", ")})`;
|
|
2149
|
-
}).join(", ")}` : ""}${indexes?.length ? indexes.length === 1 ? ", has index" : `, has ${indexes.length} indexes` : ""}${excludes?.length ? excludes.length === 1 ? ", has exclude" : `, has ${excludes.length} excludes` : ""}${
|
|
2233
|
+
}).join(", ")}` : ""}${indexes?.length ? indexes.length === 1 ? ", has index" : `, has ${indexes.length} indexes` : ""}${excludes?.length ? excludes.length === 1 ? ", has exclude" : `, has ${excludes.length} excludes` : ""}${checks?.length ? `, checks ${checks.map((check) => check.sql.toSQL({ values: [] })).join(", ")}` : ""}`
|
|
2150
2234
|
);
|
|
2151
2235
|
} else if (change.type === "change") {
|
|
2152
2236
|
const name = change.from.column?.data.name ?? key;
|