orchid-orm 1.32.6 → 1.32.8

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.
@@ -1,7 +1,7 @@
1
1
  import { promptSelect, colors, getSchemaAndTableFromName, getDbTableColumnsChecks, dbColumnToAst, instantiateDbColumn, concatSchemaAndName, encodeColumnDefault, getIndexName, 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
3
  import { toSnakeCase, deepCompare, toArray, columnToCode, addCode, codeToString, toCamelCase, toPascalCase, getImportPath, singleQuote, quoteObjectKey, pathToLog } from 'orchid-core';
4
- import { EnumColumn, DomainColumn, RawSQL, ArrayColumn, VirtualColumn, UnknownColumn, defaultSchemaConfig, columnsShapeToCode, pushTableDataCode, Adapter } from 'pqb';
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';
7
7
  import fs from 'fs/promises';
@@ -396,172 +396,190 @@ const dropColumns = ({ changeTableAst: { shape } }, columnsToDrop) => {
396
396
  }
397
397
  };
398
398
  const changeColumns = async (adapter, config, structureToAstCtx, dbStructure, domainsMap, ast, currentSchema, dbColumns, columnsToChange, compareSql, changeTableData, typeCastsCache, verifying) => {
399
- var _a, _b, _c, _d, _e;
399
+ var _a;
400
400
  for (const [
401
401
  key,
402
402
  { key: codeKey, dbName, column: codeColumn }
403
403
  ] of columnsToChange) {
404
404
  const dbColumnStructure = dbColumns[dbName];
405
405
  const { shape } = changeTableData.changeTableAst;
406
- let changed = false;
407
406
  const dbColumn = instantiateDbColumn(
408
407
  structureToAstCtx,
409
408
  dbStructure,
410
409
  domainsMap,
411
410
  dbColumnStructure
412
411
  );
413
- const dbType = getColumnDbType(dbColumn, currentSchema);
414
- const codeType = getColumnDbType(codeColumn, currentSchema);
415
- if (dbType !== codeType) {
416
- let typeCasts = typeCastsCache.value;
417
- if (!typeCasts) {
418
- const { rows } = await adapter.arrays(`SELECT s.typname, t.typname
412
+ const action = await compareColumns(
413
+ adapter,
414
+ domainsMap,
415
+ ast,
416
+ currentSchema,
417
+ compareSql,
418
+ changeTableData,
419
+ typeCastsCache,
420
+ verifying,
421
+ key,
422
+ dbColumn,
423
+ codeColumn
424
+ );
425
+ if (action === "change") {
426
+ changeColumn(shape, key, dbColumn, codeColumn);
427
+ } else if (action === "recreate") {
428
+ changeTableData.changeTableAst.shape[key] = [
429
+ {
430
+ type: "drop",
431
+ item: dbColumn
432
+ },
433
+ {
434
+ type: "add",
435
+ item: codeColumn
436
+ }
437
+ ];
438
+ } else if (action !== "recreate") {
439
+ const to = (_a = codeColumn.data.name) != null ? _a : codeKey;
440
+ if (dbName !== to) {
441
+ shape[config.snakeCase ? dbName === toSnakeCase(codeKey) ? codeKey : dbName : dbName] = {
442
+ type: "rename",
443
+ name: config.snakeCase ? to === toSnakeCase(codeKey) ? codeKey : to : to
444
+ };
445
+ }
446
+ }
447
+ }
448
+ };
449
+ const compareColumns = async (adapter, domainsMap, ast, currentSchema, compareSql, changeTableData, typeCastsCache, verifying, key, dbColumn, codeColumn) => {
450
+ var _a, _b, _c, _d;
451
+ const dbType = getColumnDbType(dbColumn, currentSchema);
452
+ const codeType = getColumnDbType(codeColumn, currentSchema);
453
+ if (dbColumn instanceof ArrayColumn && codeColumn instanceof ArrayColumn) {
454
+ dbColumn = dbColumn.data.item;
455
+ codeColumn = codeColumn.data.item;
456
+ }
457
+ if (dbType !== codeType) {
458
+ let typeCasts = typeCastsCache.value;
459
+ if (!typeCasts) {
460
+ const { rows } = await adapter.arrays(`SELECT s.typname, t.typname
419
461
  FROM pg_cast
420
462
  JOIN pg_type AS s ON s.oid = castsource
421
463
  JOIN pg_type AS t ON t.oid = casttarget`);
422
- const directTypeCasts = /* @__PURE__ */ new Map();
423
- for (const [source, target] of rows) {
424
- const set = directTypeCasts.get(source);
425
- if (set) {
426
- set.add(target);
427
- } else {
428
- directTypeCasts.set(source, /* @__PURE__ */ new Set([target]));
429
- }
430
- }
431
- typeCasts = /* @__PURE__ */ new Map();
432
- for (const [type, directSet] of directTypeCasts.entries()) {
433
- const set = new Set(directSet);
434
- typeCasts.set(type, set);
435
- for (const subtype of directSet) {
436
- const subset = directTypeCasts.get(subtype);
437
- if (subset) {
438
- for (const type2 of subset) {
439
- set.add(type2);
440
- }
441
- }
442
- }
464
+ const directTypeCasts = /* @__PURE__ */ new Map();
465
+ for (const [source, target] of rows) {
466
+ const set = directTypeCasts.get(source);
467
+ if (set) {
468
+ set.add(target);
469
+ } else {
470
+ directTypeCasts.set(source, /* @__PURE__ */ new Set([target]));
443
471
  }
444
- typeCastsCache.value = typeCasts;
445
472
  }
446
- const dbBaseType = dbColumn instanceof DomainColumn ? (_a = domainsMap[dbColumn.dataType]) == null ? void 0 : _a.dataType : dbType;
447
- const codeBaseType = codeColumn instanceof DomainColumn ? (_b = domainsMap[codeColumn.dataType]) == null ? void 0 : _b.dataType : codeType;
448
- if (!((_c = typeCasts.get(dbBaseType)) == null ? void 0 : _c.has(codeBaseType))) {
449
- if (!(dbColumn instanceof EnumColumn) || !(codeColumn instanceof EnumColumn) || !deepCompare(dbColumn.options, codeColumn.options)) {
450
- if (verifying)
451
- throw new AbortSignal();
452
- const tableName = concatSchemaAndName(changeTableData.changeTableAst);
453
- const abort = await promptSelect({
454
- message: `Cannot cast type of ${tableName}'s column ${key} from ${dbType} to ${codeType}`,
455
- options: [
456
- `${colors.yellowBold(
457
- `-/+`
458
- )} recreate the column, existing data will be ${colors.red(
459
- "lost"
460
- )}`,
461
- `write migration manually`
462
- ]
463
- });
464
- if (abort) {
465
- throw new AbortSignal();
466
- }
467
- dbColumn.data.name = codeColumn.data.name;
468
- shape[key] = [
469
- {
470
- type: "drop",
471
- item: dbColumn
472
- },
473
- {
474
- type: "add",
475
- item: codeColumn
473
+ typeCasts = /* @__PURE__ */ new Map();
474
+ for (const [type, directSet] of directTypeCasts.entries()) {
475
+ const set = new Set(directSet);
476
+ typeCasts.set(type, set);
477
+ for (const subtype of directSet) {
478
+ const subset = directTypeCasts.get(subtype);
479
+ if (subset) {
480
+ for (const type2 of subset) {
481
+ set.add(type2);
476
482
  }
477
- ];
478
- return;
479
- }
480
- }
481
- changed = true;
482
- }
483
- const dbData = dbColumn.data;
484
- const codeData = codeColumn.data;
485
- if (!changed) {
486
- if (!dbData.isNullable)
487
- dbData.isNullable = void 0;
488
- for (const key2 of ["isNullable", "comment"]) {
489
- if (dbData[key2] !== codeData[key2]) {
490
- changed = true;
491
- break;
483
+ }
492
484
  }
493
485
  }
494
- }
495
- if (!changed) {
496
- for (const key2 of [
497
- "maxChars",
498
- "collation",
499
- "compression",
500
- "numericPrecision",
501
- "numericScale",
502
- "dateTimePrecision"
503
- ]) {
504
- if (key2 in codeData && dbData[key2] !== codeData[key2]) {
505
- changed = true;
506
- break;
486
+ typeCastsCache.value = typeCasts;
487
+ }
488
+ const dbBaseType = dbColumn instanceof DomainColumn ? (_a = domainsMap[dbColumn.dataType]) == null ? void 0 : _a.dataType : dbType;
489
+ const codeBaseType = codeColumn instanceof DomainColumn ? (_b = domainsMap[codeColumn.dataType]) == null ? void 0 : _b.dataType : codeType;
490
+ if (!((_c = typeCasts.get(dbBaseType)) == null ? void 0 : _c.has(codeBaseType))) {
491
+ if (!(dbColumn instanceof EnumColumn) || !(codeColumn instanceof EnumColumn) || !deepCompare(dbColumn.options, codeColumn.options)) {
492
+ if (verifying)
493
+ throw new AbortSignal();
494
+ const tableName = concatSchemaAndName(changeTableData.changeTableAst);
495
+ const abort = await promptSelect({
496
+ message: `Cannot cast type of ${tableName}'s column ${key} from ${dbType} to ${codeType}`,
497
+ options: [
498
+ `${colors.yellowBold(
499
+ `-/+`
500
+ )} recreate the column, existing data will be ${colors.red(
501
+ "lost"
502
+ )}`,
503
+ `write migration manually`
504
+ ]
505
+ });
506
+ if (abort) {
507
+ throw new AbortSignal();
507
508
  }
509
+ dbColumn.data.name = codeColumn.data.name;
510
+ return "recreate";
508
511
  }
509
512
  }
510
- if (!changed && !deepCompare(
511
- dbData.identity,
512
- codeData.identity ? __spreadValues$6({
513
- always: false,
514
- start: 1,
515
- increment: 1,
516
- cache: 1,
517
- cycle: false
518
- }, (_d = codeData.identity) != null ? _d : {}) : void 0
519
- )) {
520
- changed = true;
521
- }
522
- if (!changed && dbData.default !== void 0 && dbData.default !== null && codeData.default !== void 0 && codeData.default !== null) {
523
- const valuesBeforeLen = compareSql.values.length;
524
- const dbDefault = encodeColumnDefault(
525
- dbData.default,
526
- compareSql.values,
527
- dbColumn
528
- );
529
- const dbValues = compareSql.values.slice(valuesBeforeLen);
530
- const codeDefault = encodeColumnDefault(
531
- codeData.default,
532
- compareSql.values,
533
- codeColumn
534
- );
535
- const codeValues = compareSql.values.slice(valuesBeforeLen);
536
- if (dbValues.length !== codeValues.length || dbValues.length && JSON.stringify(dbValues) !== JSON.stringify(codeValues)) {
537
- changed = true;
538
- compareSql.values.length = valuesBeforeLen;
539
- } else if (dbDefault !== codeDefault && dbDefault !== `(${codeDefault})`) {
540
- compareSql.expressions.push({
541
- inDb: dbDefault,
542
- inCode: codeDefault,
543
- change: () => {
544
- changeColumn(shape, key, dbColumn, codeColumn);
545
- if (!changeTableData.pushedAst) {
546
- changeTableData.pushedAst = true;
547
- ast.push(changeTableData.changeTableAst);
548
- }
513
+ return "change";
514
+ }
515
+ const dbData = dbColumn.data;
516
+ const codeData = codeColumn.data;
517
+ for (const key2 of ["isNullable", "comment"]) {
518
+ if (dbData[key2] !== codeData[key2]) {
519
+ return "change";
520
+ }
521
+ }
522
+ for (const key2 of [
523
+ "maxChars",
524
+ "collation",
525
+ "compression",
526
+ "numericPrecision",
527
+ "numericScale",
528
+ "dateTimePrecision"
529
+ ]) {
530
+ if (key2 in codeData && dbData[key2] !== codeData[key2]) {
531
+ return "change";
532
+ }
533
+ }
534
+ if (!deepCompare(
535
+ dbData.identity,
536
+ codeData.identity ? __spreadValues$6({
537
+ always: false,
538
+ start: 1,
539
+ increment: 1,
540
+ cache: 1,
541
+ cycle: false
542
+ }, (_d = codeData.identity) != null ? _d : {}) : void 0
543
+ )) {
544
+ return "change";
545
+ }
546
+ if (dbData.default !== void 0 && dbData.default !== null && codeData.default !== void 0 && codeData.default !== null) {
547
+ const valuesBeforeLen = compareSql.values.length;
548
+ const dbDefault = encodeColumnDefault(
549
+ dbData.default,
550
+ compareSql.values,
551
+ dbColumn
552
+ );
553
+ const dbValues = compareSql.values.slice(valuesBeforeLen);
554
+ const codeDefault = encodeColumnDefault(
555
+ codeData.default,
556
+ compareSql.values,
557
+ codeColumn
558
+ );
559
+ const codeValues = compareSql.values.slice(valuesBeforeLen);
560
+ if (dbValues.length !== codeValues.length || dbValues.length && JSON.stringify(dbValues) !== JSON.stringify(codeValues)) {
561
+ compareSql.values.length = valuesBeforeLen;
562
+ return "change";
563
+ } else if (dbDefault !== codeDefault && dbDefault !== `(${codeDefault})`) {
564
+ compareSql.expressions.push({
565
+ inDb: dbDefault,
566
+ inCode: codeDefault,
567
+ change: () => {
568
+ changeColumn(
569
+ changeTableData.changeTableAst.shape,
570
+ key,
571
+ dbColumn,
572
+ codeColumn
573
+ );
574
+ if (!changeTableData.pushedAst) {
575
+ changeTableData.pushedAst = true;
576
+ ast.push(changeTableData.changeTableAst);
549
577
  }
550
- });
551
- }
552
- }
553
- if (changed) {
554
- changeColumn(shape, key, dbColumn, codeColumn);
555
- } else {
556
- const to = (_e = codeColumn.data.name) != null ? _e : codeKey;
557
- if (dbName !== to) {
558
- shape[config.snakeCase ? dbName === toSnakeCase(codeKey) ? codeKey : dbName : dbName] = {
559
- type: "rename",
560
- name: config.snakeCase ? to === toSnakeCase(codeKey) ? codeKey : to : to
561
- };
562
- }
578
+ }
579
+ });
563
580
  }
564
581
  }
582
+ return;
565
583
  };
566
584
  const changeColumn = (shape, name, dbColumn, codeColumn) => {
567
585
  dbColumn.data.as = codeColumn.data.as = void 0;
@@ -577,6 +595,8 @@ const getColumnDbType = (column, currentSchema) => {
577
595
  column.enumName
578
596
  );
579
597
  return column.enumName = `${schema}.${name}`;
598
+ } else if (column instanceof ArrayColumn) {
599
+ return column.data.item.dataType + "[]".repeat(column.data.arrayDims);
580
600
  } else {
581
601
  return column.dataType;
582
602
  }
@@ -613,7 +633,7 @@ const processDomains = async (ast, adapter, structureToAstCtx, domainsMap, dbStr
613
633
  name: domain.name,
614
634
  typeSchema: domain.typeSchema,
615
635
  type: domain.type,
616
- isArray: domain.isArray,
636
+ arrayDims: domain.arrayDims,
617
637
  default: domain.default,
618
638
  isNullable: domain.isNullable,
619
639
  collate: domain.collate,
@@ -694,12 +714,12 @@ const processDomains = async (ast, adapter, structureToAstCtx, domainsMap, dbStr
694
714
  };
695
715
  const makeComparableDomain = (currentSchema, schemaName, name, column) => {
696
716
  var _a;
697
- let isArray = false;
717
+ let arrayDims = 0;
698
718
  const isNullable = (_a = column.data.isNullable) != null ? _a : false;
699
719
  let inner = column;
700
- if (column instanceof ArrayColumn) {
701
- inner = column.data.item;
702
- isArray = true;
720
+ while (inner instanceof ArrayColumn) {
721
+ inner = inner.data.item;
722
+ arrayDims++;
703
723
  }
704
724
  const fullType = getColumnDbType(inner, currentSchema);
705
725
  const [typeSchema = "pg_catalog", type] = getSchemaAndTableFromName(fullType);
@@ -710,7 +730,7 @@ const makeComparableDomain = (currentSchema, schemaName, name, column) => {
710
730
  compare: {
711
731
  type,
712
732
  typeSchema,
713
- isArray,
733
+ arrayDims,
714
734
  isNullable,
715
735
  maxChars: inner.data.maxChars,
716
736
  numericPrecision: inner.data.numericPrecision,