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