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.
- package/index.d.mts +1 -1
- package/index.mjs +79 -39
- package/package.json +1 -1
package/index.d.mts
CHANGED
package/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* imodel v0.
|
|
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
|
-
|
|
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
|
|
350
|
-
return Sql(create, id, fieldSqls,
|
|
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
|
-
* @
|
|
966
|
+
* @param {string?} [schema]
|
|
967
|
+
* @returns {Promise<(DBColumn & {table: string; name: string; defaultExp: string?})[]>}
|
|
964
968
|
*/
|
|
965
|
-
async function loadFields(env,
|
|
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 = ${
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
1088
|
+
defaultExp = null;
|
|
1089
|
+
} else if (defaultExp === 'gen_random_uuid()') {
|
|
1063
1090
|
defaultValue = env.values.uuid;
|
|
1064
|
-
|
|
1091
|
+
defaultExp = null;
|
|
1092
|
+
} else if (defaultExp === 'false') {
|
|
1065
1093
|
defaultValue = false;
|
|
1066
|
-
|
|
1094
|
+
defaultExp = null;
|
|
1095
|
+
} else if (defaultExp === 'true') {
|
|
1067
1096
|
defaultValue = true;
|
|
1068
|
-
|
|
1097
|
+
defaultExp = null;
|
|
1098
|
+
} else if (defaultExp === `''::character varying`) {
|
|
1069
1099
|
defaultValue = '';
|
|
1070
|
-
|
|
1100
|
+
defaultExp = null;
|
|
1101
|
+
} else if (defaultExp === `''::text`) {
|
|
1071
1102
|
defaultValue = '';
|
|
1072
|
-
|
|
1103
|
+
defaultExp = null;
|
|
1104
|
+
} else if (defaultExp === `'[]'::json`) {
|
|
1073
1105
|
defaultValue = [];
|
|
1074
|
-
|
|
1106
|
+
defaultExp = null;
|
|
1107
|
+
} else if (defaultExp === `'{}'::json`) {
|
|
1075
1108
|
defaultValue = {};
|
|
1076
|
-
|
|
1109
|
+
defaultExp = null;
|
|
1110
|
+
} else if (/^ARRAY\[\]::[a-z \d]+\[\]$/.test(defaultExp)) {
|
|
1077
1111
|
defaultValue = [];
|
|
1078
|
-
|
|
1079
|
-
|
|
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.
|
|
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.
|
|
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,
|
|
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,
|
|
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 = ${
|
|
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,
|
|
1199
|
-
const [baseTables, allFields, [allIndexes, allPrimary]] = await Promise.all([loadBaseTables(env,
|
|
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 {
|
|
1637
|
+
* @param {string} [schema]
|
|
1598
1638
|
*/
|
|
1599
|
-
async function syncTables(env,
|
|
1639
|
+
async function syncTables(env, query, tables, schema) {
|
|
1600
1640
|
const tableNames = tables.map(v => v.table);
|
|
1601
|
-
const dbTables = await loadTables(env,
|
|
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 =
|
|
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,
|
|
1894
|
+
return loadTables(env, query, tables);
|
|
1855
1895
|
},
|
|
1856
1896
|
syncTables(env, tables) {
|
|
1857
|
-
return syncTables(env,
|
|
1897
|
+
return syncTables(env, query, tables);
|
|
1858
1898
|
},
|
|
1859
1899
|
async transaction(env, fn) {
|
|
1860
1900
|
if (env?.transaction?.client) {
|