typeorm 0.3.12-dev.ae91c05 → 0.3.12-dev.defb409

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.
Files changed (157) hide show
  1. package/browser/decorator/options/SpatialColumnOptions.d.ts +2 -1
  2. package/browser/decorator/options/SpatialColumnOptions.js.map +1 -1
  3. package/browser/driver/Driver.d.ts +1 -1
  4. package/browser/driver/Driver.js.map +1 -1
  5. package/browser/driver/DriverUtils.js +1 -1
  6. package/browser/driver/DriverUtils.js.map +1 -1
  7. package/browser/driver/aurora-mysql/AuroraMysqlDriver.d.ts +2 -1
  8. package/browser/driver/aurora-mysql/AuroraMysqlDriver.js +1 -1
  9. package/browser/driver/aurora-mysql/AuroraMysqlDriver.js.map +1 -1
  10. package/browser/driver/cockroachdb/CockroachConnectionOptions.d.ts +5 -0
  11. package/browser/driver/cockroachdb/CockroachConnectionOptions.js.map +1 -1
  12. package/browser/driver/cockroachdb/CockroachDriver.d.ts +19 -14
  13. package/browser/driver/cockroachdb/CockroachDriver.js +128 -13
  14. package/browser/driver/cockroachdb/CockroachDriver.js.map +1 -1
  15. package/browser/driver/cockroachdb/CockroachQueryRunner.d.ts +28 -0
  16. package/browser/driver/cockroachdb/CockroachQueryRunner.js +283 -11
  17. package/browser/driver/cockroachdb/CockroachQueryRunner.js.map +1 -1
  18. package/browser/driver/mongodb/MongoDriver.d.ts +5 -0
  19. package/browser/driver/mongodb/MongoDriver.js.map +1 -1
  20. package/browser/driver/mysql/MysqlDriver.d.ts +2 -1
  21. package/browser/driver/mysql/MysqlDriver.js +1 -1
  22. package/browser/driver/mysql/MysqlDriver.js.map +1 -1
  23. package/browser/driver/oracle/OracleDriver.d.ts +5 -0
  24. package/browser/driver/oracle/OracleDriver.js +4 -0
  25. package/browser/driver/oracle/OracleDriver.js.map +1 -1
  26. package/browser/driver/oracle/OracleQueryRunner.js +15 -7
  27. package/browser/driver/oracle/OracleQueryRunner.js.map +1 -1
  28. package/browser/driver/postgres/PostgresDriver.d.ts +2 -1
  29. package/browser/driver/postgres/PostgresDriver.js +1 -1
  30. package/browser/driver/postgres/PostgresDriver.js.map +1 -1
  31. package/browser/driver/postgres/PostgresQueryRunner.js +11 -36
  32. package/browser/driver/postgres/PostgresQueryRunner.js.map +1 -1
  33. package/browser/driver/sap/SapDriver.d.ts +5 -0
  34. package/browser/driver/sap/SapDriver.js +4 -0
  35. package/browser/driver/sap/SapDriver.js.map +1 -1
  36. package/browser/driver/spanner/SpannerDriver.d.ts +2 -1
  37. package/browser/driver/spanner/SpannerDriver.js +1 -1
  38. package/browser/driver/spanner/SpannerDriver.js.map +1 -1
  39. package/browser/driver/sqlite/SqliteConnectionOptions.d.ts +7 -0
  40. package/browser/driver/sqlite/SqliteConnectionOptions.js.map +1 -1
  41. package/browser/driver/sqlite/SqliteDriver.js +5 -0
  42. package/browser/driver/sqlite/SqliteDriver.js.map +1 -1
  43. package/browser/driver/sqlite-abstract/AbstractSqliteDriver.d.ts +2 -1
  44. package/browser/driver/sqlite-abstract/AbstractSqliteDriver.js +1 -1
  45. package/browser/driver/sqlite-abstract/AbstractSqliteDriver.js.map +1 -1
  46. package/browser/driver/sqlserver/SqlServerDriver.d.ts +5 -0
  47. package/browser/driver/sqlserver/SqlServerDriver.js +4 -0
  48. package/browser/driver/sqlserver/SqlServerDriver.js.map +1 -1
  49. package/browser/driver/types/GeoJsonTypes.d.ts +87 -0
  50. package/browser/driver/types/GeoJsonTypes.js +3 -0
  51. package/browser/driver/types/GeoJsonTypes.js.map +1 -0
  52. package/browser/driver/types/UpsertType.d.ts +1 -1
  53. package/browser/driver/types/UpsertType.js.map +1 -1
  54. package/browser/entity-manager/EntityManager.js +2 -0
  55. package/browser/entity-manager/EntityManager.js.map +1 -1
  56. package/browser/find-options/mongodb/MongoFindOneOptions.d.ts +2 -2
  57. package/browser/find-options/mongodb/MongoFindOneOptions.js.map +1 -1
  58. package/browser/index.d.ts +1 -0
  59. package/browser/index.js +1 -0
  60. package/browser/index.js.map +1 -1
  61. package/browser/query-builder/InsertOrUpdateOptions.d.ts +2 -0
  62. package/browser/query-builder/InsertOrUpdateOptions.js.map +1 -1
  63. package/browser/query-builder/InsertQueryBuilder.d.ts +4 -4
  64. package/browser/query-builder/InsertQueryBuilder.js +80 -74
  65. package/browser/query-builder/InsertQueryBuilder.js.map +1 -1
  66. package/browser/query-builder/QueryBuilder.d.ts +4 -0
  67. package/browser/query-builder/QueryBuilder.js +28 -8
  68. package/browser/query-builder/QueryBuilder.js.map +1 -1
  69. package/browser/query-builder/QueryExpressionMap.d.ts +7 -0
  70. package/browser/query-builder/QueryExpressionMap.js +4 -0
  71. package/browser/query-builder/QueryExpressionMap.js.map +1 -1
  72. package/browser/query-builder/SelectQueryBuilder.d.ts +4 -0
  73. package/browser/query-builder/SelectQueryBuilder.js +22 -1
  74. package/browser/query-builder/SelectQueryBuilder.js.map +1 -1
  75. package/browser/query-builder/UpdateQueryBuilder.js +1 -2
  76. package/browser/query-builder/UpdateQueryBuilder.js.map +1 -1
  77. package/browser/repository/UpsertOptions.d.ts +7 -0
  78. package/browser/repository/UpsertOptions.js.map +1 -1
  79. package/decorator/options/SpatialColumnOptions.d.ts +2 -1
  80. package/decorator/options/SpatialColumnOptions.js.map +1 -1
  81. package/driver/Driver.d.ts +1 -1
  82. package/driver/Driver.js.map +1 -1
  83. package/driver/DriverUtils.js +1 -1
  84. package/driver/DriverUtils.js.map +1 -1
  85. package/driver/aurora-mysql/AuroraMysqlDriver.d.ts +2 -1
  86. package/driver/aurora-mysql/AuroraMysqlDriver.js +1 -1
  87. package/driver/aurora-mysql/AuroraMysqlDriver.js.map +1 -1
  88. package/driver/cockroachdb/CockroachConnectionOptions.d.ts +5 -0
  89. package/driver/cockroachdb/CockroachConnectionOptions.js.map +1 -1
  90. package/driver/cockroachdb/CockroachDriver.d.ts +19 -14
  91. package/driver/cockroachdb/CockroachDriver.js +128 -13
  92. package/driver/cockroachdb/CockroachDriver.js.map +1 -1
  93. package/driver/cockroachdb/CockroachQueryRunner.d.ts +28 -0
  94. package/driver/cockroachdb/CockroachQueryRunner.js +283 -11
  95. package/driver/cockroachdb/CockroachQueryRunner.js.map +1 -1
  96. package/driver/mongodb/MongoDriver.d.ts +5 -0
  97. package/driver/mongodb/MongoDriver.js.map +1 -1
  98. package/driver/mysql/MysqlDriver.d.ts +2 -1
  99. package/driver/mysql/MysqlDriver.js +1 -1
  100. package/driver/mysql/MysqlDriver.js.map +1 -1
  101. package/driver/oracle/OracleDriver.d.ts +5 -0
  102. package/driver/oracle/OracleDriver.js +4 -0
  103. package/driver/oracle/OracleDriver.js.map +1 -1
  104. package/driver/oracle/OracleQueryRunner.js +15 -7
  105. package/driver/oracle/OracleQueryRunner.js.map +1 -1
  106. package/driver/postgres/PostgresDriver.d.ts +2 -1
  107. package/driver/postgres/PostgresDriver.js +1 -1
  108. package/driver/postgres/PostgresDriver.js.map +1 -1
  109. package/driver/postgres/PostgresQueryRunner.js +11 -36
  110. package/driver/postgres/PostgresQueryRunner.js.map +1 -1
  111. package/driver/sap/SapDriver.d.ts +5 -0
  112. package/driver/sap/SapDriver.js +4 -0
  113. package/driver/sap/SapDriver.js.map +1 -1
  114. package/driver/spanner/SpannerDriver.d.ts +2 -1
  115. package/driver/spanner/SpannerDriver.js +1 -1
  116. package/driver/spanner/SpannerDriver.js.map +1 -1
  117. package/driver/sqlite/SqliteConnectionOptions.d.ts +7 -0
  118. package/driver/sqlite/SqliteConnectionOptions.js.map +1 -1
  119. package/driver/sqlite/SqliteDriver.js +5 -0
  120. package/driver/sqlite/SqliteDriver.js.map +1 -1
  121. package/driver/sqlite-abstract/AbstractSqliteDriver.d.ts +2 -1
  122. package/driver/sqlite-abstract/AbstractSqliteDriver.js +1 -1
  123. package/driver/sqlite-abstract/AbstractSqliteDriver.js.map +1 -1
  124. package/driver/sqlserver/SqlServerDriver.d.ts +5 -0
  125. package/driver/sqlserver/SqlServerDriver.js +4 -0
  126. package/driver/sqlserver/SqlServerDriver.js.map +1 -1
  127. package/driver/types/GeoJsonTypes.d.ts +87 -0
  128. package/driver/types/GeoJsonTypes.js +4 -0
  129. package/driver/types/GeoJsonTypes.js.map +1 -0
  130. package/driver/types/UpsertType.d.ts +1 -1
  131. package/driver/types/UpsertType.js.map +1 -1
  132. package/entity-manager/EntityManager.js +2 -0
  133. package/entity-manager/EntityManager.js.map +1 -1
  134. package/find-options/mongodb/MongoFindOneOptions.d.ts +2 -2
  135. package/find-options/mongodb/MongoFindOneOptions.js.map +1 -1
  136. package/index.d.ts +1 -0
  137. package/index.js +1 -0
  138. package/index.js.map +1 -1
  139. package/package.json +1 -1
  140. package/query-builder/InsertOrUpdateOptions.d.ts +2 -0
  141. package/query-builder/InsertOrUpdateOptions.js.map +1 -1
  142. package/query-builder/InsertQueryBuilder.d.ts +4 -4
  143. package/query-builder/InsertQueryBuilder.js +80 -74
  144. package/query-builder/InsertQueryBuilder.js.map +1 -1
  145. package/query-builder/QueryBuilder.d.ts +4 -0
  146. package/query-builder/QueryBuilder.js +28 -8
  147. package/query-builder/QueryBuilder.js.map +1 -1
  148. package/query-builder/QueryExpressionMap.d.ts +7 -0
  149. package/query-builder/QueryExpressionMap.js +4 -0
  150. package/query-builder/QueryExpressionMap.js.map +1 -1
  151. package/query-builder/SelectQueryBuilder.d.ts +4 -0
  152. package/query-builder/SelectQueryBuilder.js +22 -1
  153. package/query-builder/SelectQueryBuilder.js.map +1 -1
  154. package/query-builder/UpdateQueryBuilder.js +1 -2
  155. package/query-builder/UpdateQueryBuilder.js.map +1 -1
  156. package/repository/UpsertOptions.d.ts +7 -0
  157. package/repository/UpsertOptions.js.map +1 -1
@@ -17,6 +17,7 @@ import { TableExclusion } from "../../schema-builder/table/TableExclusion";
17
17
  import { TypeORMError } from "../../error";
18
18
  import { MetadataTableType } from "../types/MetadataTableType";
19
19
  import { InstanceChecker } from "../../util/InstanceChecker";
20
+ import { VersionUtils } from "../../util/VersionUtils.js";
20
21
  /**
21
22
  * Runs queries on a single postgres database connection.
22
23
  */
@@ -79,6 +80,9 @@ export class CockroachQueryRunner extends BaseQueryRunner {
79
80
  * You cannot use query runner methods once its released.
80
81
  */
81
82
  release() {
83
+ if (this.isReleased) {
84
+ return Promise.resolve();
85
+ }
82
86
  this.isReleased = true;
83
87
  if (this.releaseCallback)
84
88
  this.releaseCallback();
@@ -356,6 +360,20 @@ export class CockroachQueryRunner extends BaseQueryRunner {
356
360
  }
357
361
  const upQueries = [];
358
362
  const downQueries = [];
363
+ // if table have column with ENUM type, we must create this type in postgres.
364
+ const enumColumns = table.columns.filter((column) => column.type === "enum" || column.type === "simple-enum");
365
+ const createdEnumTypes = [];
366
+ for (const column of enumColumns) {
367
+ // TODO: Should also check if values of existing type matches expected ones
368
+ const hasEnum = await this.hasEnumType(table, column);
369
+ const enumName = this.buildEnumName(table, column);
370
+ // if enum with the same "enumName" is defined more then once, me must prevent double creation
371
+ if (!hasEnum && createdEnumTypes.indexOf(enumName) === -1) {
372
+ createdEnumTypes.push(enumName);
373
+ upQueries.push(this.createEnumTypeSql(table, column, enumName));
374
+ downQueries.push(this.dropEnumTypeSql(table, column, enumName));
375
+ }
376
+ }
359
377
  table.columns
360
378
  .filter((column) => column.isGenerated &&
361
379
  column.generationStrategy === "increment")
@@ -569,6 +587,16 @@ export class CockroachQueryRunner extends BaseQueryRunner {
569
587
  // replace constraint name
570
588
  foreignKey.name = newForeignKeyName;
571
589
  });
590
+ // rename ENUM types
591
+ const enumColumns = newTable.columns.filter((column) => column.type === "enum" || column.type === "simple-enum");
592
+ for (let column of enumColumns) {
593
+ // skip renaming for user-defined enum name
594
+ if (column.enumName)
595
+ continue;
596
+ const oldEnumType = await this.getUserDefinedTypeName(oldTable, column);
597
+ upQueries.push(new Query(`ALTER TYPE "${oldEnumType.schema}"."${oldEnumType.name}" RENAME TO ${this.buildEnumName(newTable, column, false)}`));
598
+ downQueries.push(new Query(`ALTER TYPE ${this.buildEnumName(newTable, column)} RENAME TO "${oldEnumType.name}"`));
599
+ }
572
600
  await this.executeQueries(upQueries, downQueries);
573
601
  }
574
602
  /**
@@ -584,6 +612,13 @@ export class CockroachQueryRunner extends BaseQueryRunner {
584
612
  if (column.generationStrategy === "increment") {
585
613
  throw new TypeORMError(`Adding sequential generated columns into existing table is not supported`);
586
614
  }
615
+ if (column.type === "enum" || column.type === "simple-enum") {
616
+ const hasEnum = await this.hasEnumType(table, column);
617
+ if (!hasEnum) {
618
+ upQueries.push(this.createEnumTypeSql(table, column));
619
+ downQueries.push(this.dropEnumTypeSql(table, column));
620
+ }
621
+ }
587
622
  upQueries.push(new Query(`ALTER TABLE ${this.escapePath(table)} ADD ${this.buildCreateColumnSql(table, column)}`));
588
623
  downQueries.push(new Query(`ALTER TABLE ${this.escapePath(table)} DROP COLUMN "${column.name}"`));
589
624
  // create or update primary key constraint
@@ -711,6 +746,7 @@ export class CockroachQueryRunner extends BaseQueryRunner {
711
746
  let clonedTable = table.clone();
712
747
  const upQueries = [];
713
748
  const downQueries = [];
749
+ let defaultValueChanged = false;
714
750
  const oldColumn = InstanceChecker.isTableColumn(oldTableColumnOrName)
715
751
  ? oldTableColumnOrName
716
752
  : table.columns.find((column) => column.name === oldTableColumnOrName);
@@ -718,6 +754,7 @@ export class CockroachQueryRunner extends BaseQueryRunner {
718
754
  throw new TypeORMError(`Column "${oldTableColumnOrName}" was not found in the "${table.name}" table.`);
719
755
  if (oldColumn.type !== newColumn.type ||
720
756
  oldColumn.length !== newColumn.length ||
757
+ newColumn.isArray !== oldColumn.isArray ||
721
758
  oldColumn.generatedType !== newColumn.generatedType ||
722
759
  oldColumn.asExpression !== newColumn.asExpression) {
723
760
  // To avoid data conversion, we just recreate column
@@ -731,6 +768,13 @@ export class CockroachQueryRunner extends BaseQueryRunner {
731
768
  // rename column
732
769
  upQueries.push(new Query(`ALTER TABLE ${this.escapePath(table)} RENAME COLUMN "${oldColumn.name}" TO "${newColumn.name}"`));
733
770
  downQueries.push(new Query(`ALTER TABLE ${this.escapePath(table)} RENAME COLUMN "${newColumn.name}" TO "${oldColumn.name}"`));
771
+ // rename ENUM type
772
+ if (oldColumn.type === "enum" ||
773
+ oldColumn.type === "simple-enum") {
774
+ const oldEnumType = await this.getUserDefinedTypeName(table, oldColumn);
775
+ upQueries.push(new Query(`ALTER TYPE "${oldEnumType.schema}"."${oldEnumType.name}" RENAME TO ${this.buildEnumName(table, newColumn, false)}`));
776
+ downQueries.push(new Query(`ALTER TYPE ${this.buildEnumName(table, newColumn)} RENAME TO "${oldEnumType.name}"`));
777
+ }
734
778
  // rename column primary key constraint
735
779
  if (oldColumn.isPrimary === true &&
736
780
  !oldColumn.primaryKeyConstraintName) {
@@ -898,6 +942,57 @@ export class CockroachQueryRunner extends BaseQueryRunner {
898
942
  downQueries.push(this.createUniqueConstraintSql(table, uniqueConstraint));
899
943
  }
900
944
  }
945
+ if ((newColumn.type === "enum" ||
946
+ newColumn.type === "simple-enum") &&
947
+ (oldColumn.type === "enum" ||
948
+ oldColumn.type === "simple-enum") &&
949
+ (!OrmUtils.isArraysEqual(newColumn.enum, oldColumn.enum) ||
950
+ newColumn.enumName !== oldColumn.enumName)) {
951
+ const arraySuffix = newColumn.isArray ? "[]" : "";
952
+ // "public"."new_enum"
953
+ const newEnumName = this.buildEnumName(table, newColumn);
954
+ // "public"."old_enum"
955
+ const oldEnumName = this.buildEnumName(table, oldColumn);
956
+ // "old_enum"
957
+ const oldEnumNameWithoutSchema = this.buildEnumName(table, oldColumn, false);
958
+ //"public"."old_enum_old"
959
+ const oldEnumNameWithSchema_old = this.buildEnumName(table, oldColumn, true, false, true);
960
+ //"old_enum_old"
961
+ const oldEnumNameWithoutSchema_old = this.buildEnumName(table, oldColumn, false, false, true);
962
+ // rename old ENUM
963
+ upQueries.push(new Query(`ALTER TYPE ${oldEnumName} RENAME TO ${oldEnumNameWithoutSchema_old}`));
964
+ downQueries.push(new Query(`ALTER TYPE ${oldEnumNameWithSchema_old} RENAME TO ${oldEnumNameWithoutSchema}`));
965
+ // create new ENUM
966
+ upQueries.push(this.createEnumTypeSql(table, newColumn, newEnumName));
967
+ downQueries.push(this.dropEnumTypeSql(table, newColumn, newEnumName));
968
+ // if column have default value, we must drop it to avoid issues with type casting
969
+ if (oldColumn.default !== null &&
970
+ oldColumn.default !== undefined) {
971
+ // mark default as changed to prevent double update
972
+ defaultValueChanged = true;
973
+ upQueries.push(new Query(`ALTER TABLE ${this.escapePath(table)} ALTER COLUMN "${oldColumn.name}" DROP DEFAULT`));
974
+ downQueries.push(new Query(`ALTER TABLE ${this.escapePath(table)} ALTER COLUMN "${oldColumn.name}" SET DEFAULT ${oldColumn.default}`));
975
+ }
976
+ // build column types
977
+ const upType = `${newEnumName}${arraySuffix} USING "${newColumn.name}"::"text"::${newEnumName}${arraySuffix}`;
978
+ const downType = `${oldEnumNameWithSchema_old}${arraySuffix} USING "${newColumn.name}"::"text"::${oldEnumNameWithSchema_old}${arraySuffix}`;
979
+ upQueries.push(new Query(`ALTER TABLE ${this.escapePath(table)} ALTER COLUMN "${newColumn.name}" TYPE ${upType}`));
980
+ // we add a delay here since for some reason cockroachdb fails with
981
+ // "cannot drop type because other objects still depend on it" error
982
+ // if we are trying to drop type right after we altered it.
983
+ upQueries.push(new Query(`SELECT pg_sleep(0.1)`));
984
+ downQueries.push(new Query(`SELECT pg_sleep(0.1)`));
985
+ downQueries.push(new Query(`ALTER TABLE ${this.escapePath(table)} ALTER COLUMN "${newColumn.name}" TYPE ${downType}`));
986
+ // restore column default or create new one
987
+ if (newColumn.default !== null &&
988
+ newColumn.default !== undefined) {
989
+ upQueries.push(new Query(`ALTER TABLE ${this.escapePath(table)} ALTER COLUMN "${newColumn.name}" SET DEFAULT ${newColumn.default}`));
990
+ downQueries.push(new Query(`ALTER TABLE ${this.escapePath(table)} ALTER COLUMN "${newColumn.name}" DROP DEFAULT`));
991
+ }
992
+ // remove old ENUM
993
+ upQueries.push(this.dropEnumTypeSql(table, oldColumn, oldEnumNameWithSchema_old));
994
+ downQueries.push(this.createEnumTypeSql(table, oldColumn, oldEnumNameWithSchema_old));
995
+ }
901
996
  if (oldColumn.isGenerated !== newColumn.isGenerated &&
902
997
  newColumn.generationStrategy !== "uuid") {
903
998
  if (newColumn.isGenerated) {
@@ -914,7 +1009,8 @@ export class CockroachQueryRunner extends BaseQueryRunner {
914
1009
  downQueries.push(new Query(`ALTER TABLE ${this.escapePath(table)} ALTER COLUMN "${newColumn.name}" SET DEFAULT unique_rowid()`));
915
1010
  }
916
1011
  }
917
- if (newColumn.default !== oldColumn.default) {
1012
+ if (newColumn.default !== oldColumn.default &&
1013
+ !defaultValueChanged) {
918
1014
  if (newColumn.default !== null &&
919
1015
  newColumn.default !== undefined) {
920
1016
  upQueries.push(new Query(`ALTER TABLE ${this.escapePath(table)} ALTER COLUMN "${newColumn.name}" SET DEFAULT ${newColumn.default}`));
@@ -933,6 +1029,12 @@ export class CockroachQueryRunner extends BaseQueryRunner {
933
1029
  }
934
1030
  }
935
1031
  }
1032
+ if ((newColumn.spatialFeatureType || "").toLowerCase() !==
1033
+ (oldColumn.spatialFeatureType || "").toLowerCase() ||
1034
+ newColumn.srid !== oldColumn.srid) {
1035
+ upQueries.push(new Query(`ALTER TABLE ${this.escapePath(table)} ALTER COLUMN "${newColumn.name}" TYPE ${this.driver.createFullType(newColumn)}`));
1036
+ downQueries.push(new Query(`ALTER TABLE ${this.escapePath(table)} ALTER COLUMN "${newColumn.name}" TYPE ${this.driver.createFullType(oldColumn)}`));
1037
+ }
936
1038
  await this.executeQueries(upQueries, downQueries);
937
1039
  this.replaceCachedTable(table, clonedTable);
938
1040
  }
@@ -1039,6 +1141,16 @@ export class CockroachQueryRunner extends BaseQueryRunner {
1039
1141
  upQueries.push(deleteQuery);
1040
1142
  downQueries.push(insertQuery);
1041
1143
  }
1144
+ // drop enum type
1145
+ if (column.type === "enum" || column.type === "simple-enum") {
1146
+ const hasEnum = await this.hasEnumType(table, column);
1147
+ if (hasEnum) {
1148
+ const enumType = await this.getUserDefinedTypeName(table, column);
1149
+ const escapedEnumName = `"${enumType.schema}"."${enumType.name}"`;
1150
+ upQueries.push(this.dropEnumTypeSql(table, column, escapedEnumName));
1151
+ downQueries.push(this.createEnumTypeSql(table, column, escapedEnumName));
1152
+ }
1153
+ }
1042
1154
  await this.executeQueries(upQueries, downQueries);
1043
1155
  clonedTable.removeColumn(column);
1044
1156
  this.replaceCachedTable(table, clonedTable);
@@ -1388,6 +1500,7 @@ export class CockroachQueryRunner extends BaseQueryRunner {
1388
1500
  if (!isAnotherTransactionActive)
1389
1501
  await this.startTransaction();
1390
1502
  try {
1503
+ const version = await this.getVersion();
1391
1504
  const selectViewDropsQuery = `SELECT 'DROP VIEW IF EXISTS "' || schemaname || '"."' || viewname || '" CASCADE;' as "query" ` +
1392
1505
  `FROM "pg_views" WHERE "schemaname" IN (${schemaNamesString})`;
1393
1506
  const dropViewQueries = await this.query(selectViewDropsQuery);
@@ -1398,6 +1511,10 @@ export class CockroachQueryRunner extends BaseQueryRunner {
1398
1511
  const selectSequenceDropsQuery = `SELECT 'DROP SEQUENCE "' || sequence_schema || '"."' || sequence_name || '";' as "query" FROM "information_schema"."sequences" WHERE "sequence_schema" IN (${schemaNamesString})`;
1399
1512
  const sequenceDropQueries = await this.query(selectSequenceDropsQuery);
1400
1513
  await Promise.all(sequenceDropQueries.map((q) => this.query(q["query"])));
1514
+ // drop enum types. Supported starting from v20.2.19.
1515
+ if (VersionUtils.isGreaterOrEqual(version, "20.2.19")) {
1516
+ await this.dropEnumTypes(schemaNamesString);
1517
+ }
1401
1518
  if (!isAnotherTransactionActive)
1402
1519
  await this.commitTransaction();
1403
1520
  }
@@ -1532,11 +1649,21 @@ export class CockroachQueryRunner extends BaseQueryRunner {
1532
1649
  `INNER JOIN "pg_class" "cl" ON "cl"."oid" = "con"."confrelid" ` +
1533
1650
  `INNER JOIN "pg_namespace" "ns" ON "cl"."relnamespace" = "ns"."oid" ` +
1534
1651
  `INNER JOIN "pg_attribute" "att2" ON "att2"."attrelid" = "con"."conrelid" AND "att2"."attnum" = "con"."parent"`;
1535
- const [dbColumns, dbConstraints, dbIndices, dbForeignKeys,] = await Promise.all([
1652
+ const tableSchemas = dbTables
1653
+ .map((dbTable) => `'${dbTable.table_schema}'`)
1654
+ .join(", ");
1655
+ const enumsSql = `SELECT "t"."typname" AS "name", string_agg("e"."enumlabel", '|') AS "value" ` +
1656
+ `FROM "pg_enum" "e" ` +
1657
+ `INNER JOIN "pg_type" "t" ON "t"."oid" = "e"."enumtypid" ` +
1658
+ `INNER JOIN "pg_namespace" "n" ON "n"."oid" = "t"."typnamespace" ` +
1659
+ `WHERE "n"."nspname" IN (${tableSchemas}) ` +
1660
+ `GROUP BY "t"."typname"`;
1661
+ const [dbColumns, dbConstraints, dbIndices, dbForeignKeys, dbEnums,] = await Promise.all([
1536
1662
  this.query(columnsSql),
1537
1663
  this.query(constraintsSql),
1538
1664
  this.query(indicesSql),
1539
1665
  this.query(foreignKeysSql),
1666
+ this.query(enumsSql),
1540
1667
  ]);
1541
1668
  // create tables for loaded tables
1542
1669
  return Promise.all(dbTables.map(async (dbTable) => {
@@ -1600,15 +1727,39 @@ export class CockroachQueryRunner extends BaseQueryRunner {
1600
1727
  tableColumn.scale = undefined;
1601
1728
  }
1602
1729
  }
1730
+ // docs: https://www.postgresql.org/docs/current/xtypes.html
1731
+ // When you define a new base type, PostgreSQL automatically provides support for arrays of that type.
1732
+ // The array type typically has the same name as the base type with the underscore character (_) prepended.
1733
+ // ----
1734
+ // so, we must remove this underscore character from enum type name
1735
+ let udtName = dbColumn["udt_name"];
1736
+ if (udtName.indexOf("_") === 0) {
1737
+ udtName = udtName.substr(1, udtName.length);
1738
+ }
1739
+ const enumType = dbEnums.find((dbEnum) => {
1740
+ return dbEnum["name"] === udtName;
1741
+ });
1742
+ if (enumType) {
1743
+ // check if `enumName` is specified by user
1744
+ const builtEnumName = this.buildEnumName(table, tableColumn, false, true);
1745
+ const enumName = builtEnumName !== enumType["name"]
1746
+ ? enumType["name"]
1747
+ : undefined;
1748
+ tableColumn.type = "enum";
1749
+ tableColumn.enum = enumType["value"].split("|");
1750
+ tableColumn.enumName = enumName;
1751
+ }
1603
1752
  if (dbColumn["data_type"].toLowerCase() === "array") {
1604
1753
  tableColumn.isArray = true;
1605
- const type = dbColumn["crdb_sql_type"]
1606
- .replace("[]", "")
1607
- .toLowerCase();
1608
- tableColumn.type =
1609
- this.connection.driver.normalizeType({
1610
- type: type,
1611
- });
1754
+ if (!enumType) {
1755
+ const type = dbColumn["crdb_sql_type"]
1756
+ .replace("[]", "")
1757
+ .toLowerCase();
1758
+ tableColumn.type =
1759
+ this.connection.driver.normalizeType({
1760
+ type: type,
1761
+ });
1762
+ }
1612
1763
  }
1613
1764
  // check only columns that have length property
1614
1765
  if (this.driver.withLengthColumnTypes.indexOf(tableColumn.type) !== -1 &&
@@ -1677,6 +1828,10 @@ export class CockroachQueryRunner extends BaseQueryRunner {
1677
1828
  tableColumn.default = dbColumn["column_default"].replace(/:::[\w\s\[\]\"]+/g, "");
1678
1829
  tableColumn.default =
1679
1830
  tableColumn.default.replace(/^(-?[\d\.]+)$/, "($1)");
1831
+ if (enumType) {
1832
+ tableColumn.default =
1833
+ tableColumn.default.replace(`.${enumType["name"]}`, "");
1834
+ }
1680
1835
  }
1681
1836
  }
1682
1837
  if (dbColumn["is_generated"] === "YES" &&
@@ -1707,6 +1862,25 @@ export class CockroachQueryRunner extends BaseQueryRunner {
1707
1862
  if (dbColumn["character_set_name"])
1708
1863
  tableColumn.charset =
1709
1864
  dbColumn["character_set_name"];
1865
+ if (tableColumn.type === "geometry" ||
1866
+ tableColumn.type === "geography") {
1867
+ const sql = `SELECT * FROM (` +
1868
+ `SELECT "f_table_schema" "table_schema", "f_table_name" "table_name", ` +
1869
+ `"f_${tableColumn.type}_column" "column_name", "srid", "type" ` +
1870
+ `FROM "${tableColumn.type}_columns"` +
1871
+ `) AS _ ` +
1872
+ `WHERE "column_name" = '${dbColumn["column_name"]}' AND ` +
1873
+ `"table_schema" = '${dbColumn["table_schema"]}' AND ` +
1874
+ `"table_name" = '${dbColumn["table_name"]}'`;
1875
+ const results = await this.query(sql);
1876
+ if (results.length > 0) {
1877
+ tableColumn.spatialFeatureType =
1878
+ results[0].type;
1879
+ tableColumn.srid = results[0].srid
1880
+ ? parseInt(results[0].srid)
1881
+ : undefined;
1882
+ }
1883
+ }
1710
1884
  return tableColumn;
1711
1885
  }));
1712
1886
  // find unique constraints of table, group them by constraint name and build TableUnique.
@@ -1889,6 +2063,13 @@ export class CockroachQueryRunner extends BaseQueryRunner {
1889
2063
  .forEach((it) => (sql += `; COMMENT ON COLUMN ${this.escapePath(table)}."${it.name}" IS ${this.escapeComment(it.comment)}`));
1890
2064
  return new Query(sql);
1891
2065
  }
2066
+ /**
2067
+ * Loads Cockroachdb version.
2068
+ */
2069
+ async getVersion() {
2070
+ const result = await this.query(`SELECT version()`);
2071
+ return result[0]["version"].replace(/^CockroachDB CCL v([\d\.]+) .*$/, "$1");
2072
+ }
1892
2073
  /**
1893
2074
  * Builds drop table sql.
1894
2075
  */
@@ -1942,6 +2123,51 @@ export class CockroachQueryRunner extends BaseQueryRunner {
1942
2123
  name,
1943
2124
  });
1944
2125
  }
2126
+ /**
2127
+ * Drops ENUM type from given schemas.
2128
+ */
2129
+ async dropEnumTypes(schemaNames) {
2130
+ const selectDropsQuery = `SELECT 'DROP TYPE IF EXISTS "' || n.nspname || '"."' || t.typname || '";' as "query" FROM "pg_type" "t" ` +
2131
+ `INNER JOIN "pg_enum" "e" ON "e"."enumtypid" = "t"."oid" ` +
2132
+ `INNER JOIN "pg_namespace" "n" ON "n"."oid" = "t"."typnamespace" ` +
2133
+ `WHERE "n"."nspname" IN (${schemaNames}) GROUP BY "n"."nspname", "t"."typname"`;
2134
+ const dropQueries = await this.query(selectDropsQuery);
2135
+ await Promise.all(dropQueries.map((q) => this.query(q["query"])));
2136
+ }
2137
+ /**
2138
+ * Checks if enum with the given name exist in the database.
2139
+ */
2140
+ async hasEnumType(table, column) {
2141
+ let { schema } = this.driver.parseTableName(table);
2142
+ if (!schema) {
2143
+ schema = await this.getCurrentSchema();
2144
+ }
2145
+ const enumName = this.buildEnumName(table, column, false, true);
2146
+ const sql = `SELECT "n"."nspname", "t"."typname" FROM "pg_type" "t" ` +
2147
+ `INNER JOIN "pg_namespace" "n" ON "n"."oid" = "t"."typnamespace" ` +
2148
+ `WHERE "n"."nspname" = '${schema}' AND "t"."typname" = '${enumName}'`;
2149
+ const result = await this.query(sql);
2150
+ return result.length ? true : false;
2151
+ }
2152
+ /**
2153
+ * Builds create ENUM type sql.
2154
+ */
2155
+ createEnumTypeSql(table, column, enumName) {
2156
+ if (!enumName)
2157
+ enumName = this.buildEnumName(table, column);
2158
+ const enumValues = column
2159
+ .enum.map((value) => `'${value.replace("'", "''")}'`)
2160
+ .join(", ");
2161
+ return new Query(`CREATE TYPE ${enumName} AS ENUM(${enumValues})`);
2162
+ }
2163
+ /**
2164
+ * Builds create ENUM type sql.
2165
+ */
2166
+ dropEnumTypeSql(table, column, enumName) {
2167
+ if (!enumName)
2168
+ enumName = this.buildEnumName(table, column);
2169
+ return new Query(`DROP TYPE ${enumName}`);
2170
+ }
1945
2171
  /**
1946
2172
  * Builds create index sql.
1947
2173
  * UNIQUE indices creates as UNIQUE constraints.
@@ -1950,7 +2176,7 @@ export class CockroachQueryRunner extends BaseQueryRunner {
1950
2176
  const columns = index.columnNames
1951
2177
  .map((columnName) => `"${columnName}"`)
1952
2178
  .join(", ");
1953
- return new Query(`CREATE INDEX "${index.name}" ON ${this.escapePath(table)} (${columns}) ${index.where ? "WHERE " + index.where : ""}`);
2179
+ return new Query(`CREATE ${index.isUnique ? "UNIQUE " : ""}INDEX "${index.name}" ON ${this.escapePath(table)} ${index.isSpatial ? "USING GiST " : ""}(${columns}) ${index.where ? "WHERE " + index.where : ""}`);
1954
2180
  }
1955
2181
  /**
1956
2182
  * Builds drop index sql.
@@ -2063,6 +2289,46 @@ export class CockroachQueryRunner extends BaseQueryRunner {
2063
2289
  ? `${schema}.${this.buildSequenceName(table, columnOrName)}`
2064
2290
  : this.buildSequenceName(table, columnOrName);
2065
2291
  }
2292
+ /**
2293
+ * Builds ENUM type name from given table and column.
2294
+ */
2295
+ buildEnumName(table, column, withSchema = true, disableEscape, toOld) {
2296
+ const { schema, tableName } = this.driver.parseTableName(table);
2297
+ let enumName = column.enumName
2298
+ ? column.enumName
2299
+ : `${tableName}_${column.name.toLowerCase()}_enum`;
2300
+ if (schema && withSchema)
2301
+ enumName = `${schema}.${enumName}`;
2302
+ if (toOld)
2303
+ enumName = enumName + "_old";
2304
+ return enumName
2305
+ .split(".")
2306
+ .map((i) => {
2307
+ return disableEscape ? i : `"${i}"`;
2308
+ })
2309
+ .join(".");
2310
+ }
2311
+ async getUserDefinedTypeName(table, column) {
2312
+ let { schema, tableName: name } = this.driver.parseTableName(table);
2313
+ if (!schema) {
2314
+ schema = await this.getCurrentSchema();
2315
+ }
2316
+ const result = await this.query(`SELECT "udt_schema", "udt_name" ` +
2317
+ `FROM "information_schema"."columns" WHERE "table_schema" = '${schema}' AND "table_name" = '${name}' AND "column_name"='${column.name}'`);
2318
+ // docs: https://www.postgresql.org/docs/current/xtypes.html
2319
+ // When you define a new base type, PostgreSQL automatically provides support for arrays of that type.
2320
+ // The array type typically has the same name as the base type with the underscore character (_) prepended.
2321
+ // ----
2322
+ // so, we must remove this underscore character from enum type name
2323
+ let udtName = result[0]["udt_name"];
2324
+ if (udtName.indexOf("_") === 0) {
2325
+ udtName = udtName.substr(1, udtName.length);
2326
+ }
2327
+ return {
2328
+ schema: result[0]["udt_schema"],
2329
+ name: udtName,
2330
+ };
2331
+ }
2066
2332
  /**
2067
2333
  * Escapes a given comment so it's safe to include in a query.
2068
2334
  */
@@ -2099,8 +2365,14 @@ export class CockroachQueryRunner extends BaseQueryRunner {
2099
2365
  c += " UUID DEFAULT gen_random_uuid()";
2100
2366
  }
2101
2367
  }
2102
- if (!column.isGenerated)
2368
+ if (column.type === "enum" || column.type === "simple-enum") {
2369
+ c += " " + this.buildEnumName(table, column);
2370
+ if (column.isArray)
2371
+ c += " array";
2372
+ }
2373
+ else if (!column.isGenerated) {
2103
2374
  c += " " + this.connection.driver.createFullType(column);
2375
+ }
2104
2376
  if (column.asExpression) {
2105
2377
  c += ` AS (${column.asExpression}) ${column.generatedType ? column.generatedType : "VIRTUAL"}`;
2106
2378
  }