imodel-pg 0.14.0 → 0.15.0

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 (3) hide show
  1. package/index.d.mts +1 -1
  2. package/index.mjs +79 -39
  3. package/package.json +1 -1
package/index.d.mts CHANGED
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * imodel v0.14.0
2
+ * imodel v0.15.0
3
3
  * (c) 2019-2026 undefined
4
4
  * @license undefined
5
5
  */
package/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * imodel v0.14.0
2
+ * imodel v0.15.0
3
3
  * (c) 2019-2026 undefined
4
4
  * @license undefined
5
5
  */
@@ -340,14 +340,14 @@ function renameColumn(table, column, newName) {
340
340
  */
341
341
  function addIndex(table, name, columns, {
342
342
  unique,
343
- include
343
+ includes
344
344
  } = {}) {
345
345
  const create = unique ? Sql`CREATE UNIQUE INDEX` : Sql`CREATE INDEX`;
346
346
  const id = Sql.Id(`${table}#${name}`);
347
347
  const allColumns = Sql`, `.glue(...columns.map(v => Sql.Field(v)));
348
348
  const fieldSqls = Sql`ON ${Sql.Table(table)}(${allColumns})`;
349
- const includes = include?.length ? Sql`INCLUDE (${Sql`, `.glue(...include.map(v => Sql.Field(v)))})` : undefined;
350
- return Sql(create, id, fieldSqls, includes);
349
+ const includesSql = includes?.length ? Sql`INCLUDE (${Sql`, `.glue(...includes.map(v => Sql.Field(v)))})` : undefined;
350
+ return Sql(create, id, fieldSqls, includesSql);
351
351
  }
352
352
 
353
353
  /**
@@ -950,25 +950,29 @@ FROM (values${Sql`,`.glue(list.map(data => Sql`(${Sql`,`.glue(dataFieldType.map(
950
950
  WHERE ${Sql`AND`.glue([pKeys.map(f => Sql`${main.field(f)}=${tmp.field(f)}`), getWhere2(env, where)].flat().filter(Boolean))}${returnSql}`;
951
951
  }
952
952
 
953
+ const defaultSchema = Sql`(SELECT (current_schemas(false))[1])`;
954
+
953
955
  /** @import { Environment, IConnection } from 'imodel' */
954
956
  /** @import { PgEnvTrans } from '../index.mjs' */
955
957
  /** @import { DBIndex, DBTable, DBColumn } from 'imodel' */
956
958
  const tableType = 'BASE TABLE';
959
+ // eslint-disable-next-line max-len
960
+ const textRegex = /^'(?<text>(?:[^']|'')+)'(?:::(?<type>character varying|text|jsonb?))?$/;
957
961
  /**
958
962
  *
959
963
  * @param {Environment<PgEnvTrans>} env
960
- * @param {string} schema
961
964
  * @param {<T extends pg.QueryResultRow>(env: Environment<PgEnvTrans>, sql: Sql) => Promise<T[]>} query
962
965
  * @param {string[]} tables
963
- * @returns {Promise<(DBColumn & {table: string; name: string})[]>}
966
+ * @param {string?} [schema]
967
+ * @returns {Promise<(DBColumn & {table: string; name: string; defaultExp: string?})[]>}
964
968
  */
965
- async function loadFields(env, schema, query, tables) {
969
+ async function loadFields(env, query, tables, schema) {
966
970
  const sql = Sql`
967
971
  SELECT *
968
972
  FROM
969
973
  information_schema.columns t
970
974
  WHERE
971
- table_schema = ${schema}
975
+ table_schema = ${defaultSchema}
972
976
  AND
973
977
  t.table_name IN (${Sql`,`.glue(tables.map(t => Sql`${t}`))})
974
978
  `;
@@ -984,7 +988,7 @@ WHERE
984
988
  let scale = 0;
985
989
  const nullable = column.is_nullable === 'YES';
986
990
  /** @type {any} */
987
- let defaultValue = column.column_default;
991
+ let defaultExp = column.column_default;
988
992
  switch (type) {
989
993
  case 'int2':
990
994
  type = 'i16';
@@ -1057,26 +1061,58 @@ WHERE
1057
1061
  case 'json':
1058
1062
  type = 'json';
1059
1063
  }
1060
- if (defaultValue === 'CURRENT_TIMESTAMP' || defaultValue === 'now()') {
1064
+ let defaultValue;
1065
+ const regexResult = textRegex.exec(defaultExp)?.groups;
1066
+ if (regexResult) {
1067
+ const {
1068
+ text,
1069
+ type
1070
+ } = regexResult;
1071
+ if (typeof text === 'string') {
1072
+ const str = text.replaceAll("''", '');
1073
+ switch (type) {
1074
+ case 'json':
1075
+ case 'jsonb':
1076
+ try {
1077
+ defaultValue = JSON.parse(str);
1078
+ } catch {}
1079
+ break;
1080
+ default:
1081
+ defaultValue = str;
1082
+ break;
1083
+ }
1084
+ defaultExp = null;
1085
+ }
1086
+ } else if (defaultExp === 'CURRENT_TIMESTAMP' || defaultExp === 'now()') {
1061
1087
  defaultValue = env.values.now;
1062
- } else if (defaultValue === 'gen_random_uuid()') {
1088
+ defaultExp = null;
1089
+ } else if (defaultExp === 'gen_random_uuid()') {
1063
1090
  defaultValue = env.values.uuid;
1064
- } else if (defaultValue === 'false') {
1091
+ defaultExp = null;
1092
+ } else if (defaultExp === 'false') {
1065
1093
  defaultValue = false;
1066
- } else if (defaultValue === 'true') {
1094
+ defaultExp = null;
1095
+ } else if (defaultExp === 'true') {
1067
1096
  defaultValue = true;
1068
- } else if (defaultValue === `''::character varying`) {
1097
+ defaultExp = null;
1098
+ } else if (defaultExp === `''::character varying`) {
1069
1099
  defaultValue = '';
1070
- } else if (defaultValue === `''::text`) {
1100
+ defaultExp = null;
1101
+ } else if (defaultExp === `''::text`) {
1071
1102
  defaultValue = '';
1072
- } else if (defaultValue === `'[]'::json`) {
1103
+ defaultExp = null;
1104
+ } else if (defaultExp === `'[]'::json`) {
1073
1105
  defaultValue = [];
1074
- } else if (defaultValue === `'{}'::json`) {
1106
+ defaultExp = null;
1107
+ } else if (defaultExp === `'{}'::json`) {
1075
1108
  defaultValue = {};
1076
- } else if (/^ARRAY\[\]::[a-z \d]+\[\]$/.test(defaultValue)) {
1109
+ defaultExp = null;
1110
+ } else if (/^ARRAY\[\]::[a-z \d]+\[\]$/.test(defaultExp)) {
1077
1111
  defaultValue = [];
1078
- } else if (/^\d+(.\d+)?(?:::[a-z \d]+)?$/.test(defaultValue)) {
1079
- defaultValue = Number(defaultValue);
1112
+ defaultExp = null;
1113
+ } else if (/^\d+(.\d+)?(?:::[a-z \d]+)?$/.test(defaultExp)) {
1114
+ defaultValue = Number(defaultExp);
1115
+ defaultExp = null;
1080
1116
  }
1081
1117
  return {
1082
1118
  table: column.table_name,
@@ -1086,6 +1122,7 @@ WHERE
1086
1122
  scale,
1087
1123
  nullable,
1088
1124
  default: defaultValue,
1125
+ defaultExp,
1089
1126
  array
1090
1127
  };
1091
1128
  });
@@ -1094,16 +1131,16 @@ WHERE
1094
1131
  *
1095
1132
  * @param {Environment<PgEnvTrans>} env
1096
1133
  * @param {<T extends pg.QueryResultRow>(env: Environment<PgEnvTrans>, sql: Sql) => Promise<T[]>} query
1097
- * @param {(DBColumn & {table: string; name: string})[]} fields
1134
+ * @param {(DBColumn & {table: string; name: string; defaultExp: string?})[]} fields
1098
1135
  * @returns {Promise<(DBColumn & {table: string; name: string})[]>}
1099
1136
  */
1100
1137
  async function loadDefault(env, query, fields) {
1101
- const data = fields.filter(v => v.default && typeof v.default === 'string');
1138
+ const data = fields.filter(v => v.defaultExp);
1102
1139
  if (!data.length) {
1103
1140
  return fields;
1104
1141
  }
1105
1142
  const sql = Sql`
1106
- SELECT ${Sql`,`.glue(data.map((v, k) => Sql(`${v.default} as a${k}`)))}
1143
+ SELECT ${Sql`,`.glue(data.map((v, k) => Sql(`${v.defaultExp} as a${k}`)))}
1107
1144
  `;
1108
1145
  const [values = {}] = await query(env, sql);
1109
1146
  for (const [index, column] of data.entries()) {
@@ -1114,12 +1151,12 @@ SELECT ${Sql`,`.glue(data.map((v, k) => Sql(`${v.default} as a${k}`)))}
1114
1151
  /**
1115
1152
  *
1116
1153
  * @param {Environment<PgEnvTrans>} env
1117
- * @param {string} schema
1118
1154
  * @param {<T extends pg.QueryResultRow>(env: Environment<PgEnvTrans>, sql: Sql) => Promise<T[]>} query
1119
1155
  * @param {string[]} tables
1156
+ * @param {string?} [schema]
1120
1157
  * @returns {Promise<[(DBIndex & {table: string})[], ({fields: string[], name: string, table: string})[]]>}
1121
1158
  */
1122
- async function loadIndex(env, schema, query, tables) {
1159
+ async function loadIndex(env, query, tables, schema) {
1123
1160
  const sql = Sql`
1124
1161
  SELECT
1125
1162
  t.relname AS table,
@@ -1140,6 +1177,10 @@ JOIN
1140
1177
  JOIN
1141
1178
  pg_class i ON ix.indexrelid = i.oid
1142
1179
  WHERE
1180
+ t.relnamespace IN (
1181
+ SELECT oid FROM pg_namespace WHERE nspname = ${defaultSchema}
1182
+ )
1183
+ AND
1143
1184
  t.relname IN (${Sql`,`.glue(tables.map(t => Sql`${t}`))})
1144
1185
  AND
1145
1186
  t.relkind = 'r'; -- 只匹配普通表
@@ -1170,16 +1211,16 @@ WHERE
1170
1211
  /**
1171
1212
  *
1172
1213
  * @param {Environment<PgEnvTrans>} env
1173
- * @param {string} schema
1174
1214
  * @param {<T extends pg.QueryResultRow>(env: Environment<PgEnvTrans>, sql: Sql) => Promise<T[]>} query
1175
1215
  * @param {string[]} tables
1216
+ * @param {string?} [schema]
1176
1217
  * @returns {Promise<string[]>}
1177
1218
  */
1178
- async function loadBaseTables(env, schema, query, tables) {
1219
+ async function loadBaseTables(env, query, tables, schema) {
1179
1220
  const sql = Sql`SELECT *
1180
1221
  FROM information_schema.tables
1181
1222
  WHERE
1182
- table_schema = ${schema}
1223
+ table_schema = ${defaultSchema}
1183
1224
  AND
1184
1225
  table_type = ${tableType}
1185
1226
  AND
@@ -1190,13 +1231,13 @@ async function loadBaseTables(env, schema, query, tables) {
1190
1231
  /**
1191
1232
  *
1192
1233
  * @param {Environment<PgEnvTrans>} env
1193
- * @param {string} schema
1194
1234
  * @param {<T extends pg.QueryResultRow>(env: Environment<PgEnvTrans>, sql: Sql) => Promise<T[]>} query
1195
1235
  * @param {string[]} tables
1236
+ * @param {string?} [schema]
1196
1237
  * @returns {Promise<DBTable[]>}
1197
1238
  */
1198
- async function loadTables(env, schema, query, tables) {
1199
- const [baseTables, allFields, [allIndexes, allPrimary]] = await Promise.all([loadBaseTables(env, schema, query, tables), loadFields(env, schema, query, tables).then(fields => loadDefault(env, query, fields)), loadIndex(env, schema, query, tables)]);
1239
+ async function loadTables(env, query, tables, schema) {
1240
+ const [baseTables, allFields, [allIndexes, allPrimary]] = await Promise.all([loadBaseTables(env, query, tables), loadFields(env, query, tables).then(fields => loadDefault(env, query, fields)), loadIndex(env, query, tables)]);
1200
1241
  const allTables = new Set(baseTables);
1201
1242
  const fieldsGroup = Object.groupBy(allFields, f => f.table);
1202
1243
  const indexesGroup = Object.groupBy(allIndexes, f => f.table);
@@ -1591,14 +1632,13 @@ ADD PRIMARY KEY (${Sql`,`.glue(primary.map(f => Sql.Field(f)))})
1591
1632
  /**
1592
1633
  *
1593
1634
  * @param {Environment<PgEnvTrans>} env
1594
- * @param {string} schema
1595
1635
  * @param {<T extends pg.QueryResultRow>(env: Environment<PgEnvTrans>, sql: Sql) => Promise<T[]>} query
1596
1636
  * @param {DBTable[]} tables
1597
- * @param {boolean} [del]
1637
+ * @param {string} [schema]
1598
1638
  */
1599
- async function syncTables(env, schema, query, tables, del) {
1639
+ async function syncTables(env, query, tables, schema) {
1600
1640
  const tableNames = tables.map(v => v.table);
1601
- const dbTables = await loadTables(env, schema, query, tableNames);
1641
+ const dbTables = await loadTables(env, query, tableNames);
1602
1642
  const tableMap = new Map(dbTables.map(v => [v.table, v]));
1603
1643
  for (const table of tables) {
1604
1644
  const old = tableMap.get(table.table);
@@ -1691,7 +1731,6 @@ function toPoolConnection(pool) {
1691
1731
  */
1692
1732
  function index (pool, version) {
1693
1733
  const connect = toPoolConnection(pool);
1694
- const schema = 'public';
1695
1734
  const dbVersion = typeof version === 'function' ? version : createVersion(connect);
1696
1735
  /**
1697
1736
  * @template {pg.QueryResultRow} T
@@ -1762,7 +1801,8 @@ function index (pool, version) {
1762
1801
  async type(env, table) {
1763
1802
  const sql = Sql`SELECT table_type as type
1764
1803
  FROM information_schema.tables
1765
- WHERE table_schema = ${schema} AND table_name = ${table} LIMIT 1`;
1804
+ WHERE table_schema = (SELECT (current_schemas(false))[1])
1805
+ AND table_name = ${table} LIMIT 1`;
1766
1806
  /** @type {pg.QueryResult<{ type: string; }>} */
1767
1807
  const {
1768
1808
  rows: [row]
@@ -1851,10 +1891,10 @@ function index (pool, version) {
1851
1891
  return exec(env, renameTable(table, newName));
1852
1892
  },
1853
1893
  loadTables(env, tables) {
1854
- return loadTables(env, schema, query, tables);
1894
+ return loadTables(env, query, tables);
1855
1895
  },
1856
1896
  syncTables(env, tables) {
1857
- return syncTables(env, schema, query, tables);
1897
+ return syncTables(env, query, tables);
1858
1898
  },
1859
1899
  async transaction(env, fn) {
1860
1900
  if (env?.transaction?.client) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "imodel-pg",
3
- "version": "0.14.0",
3
+ "version": "0.15.0",
4
4
  "dependencies": {
5
5
  "pg": "^8.13.3",
6
6
  "tagged-sql": "^0.9.0"