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