imodel-pg 0.14.0 → 0.15.1
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 +87 -45
- 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.1
|
|
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
|
/**
|
|
@@ -874,11 +874,13 @@ function insertSql(env, table, columns, list, keys, conflict, conflictSet) {
|
|
|
874
874
|
const setList = conflictSet && typeof conflictSet === 'object' ? getSet(conflictSet, columns, env) : [];
|
|
875
875
|
if (fields?.length) {
|
|
876
876
|
conflictSql = Sql(['ON CONFLICT (', ...Array(fields.length - 1).fill(','), ')'], ...fields.map(f => Sql.Field(f)));
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
877
|
+
if (!setList.length) {
|
|
878
|
+
for (const f of key) {
|
|
879
|
+
if (fields.includes(f)) {
|
|
880
|
+
continue;
|
|
881
|
+
}
|
|
882
|
+
setList.push(Sql`${Sql.Field(f)} = EXCLUDED.${Sql.Field(f)}`);
|
|
880
883
|
}
|
|
881
|
-
setList.push(Sql`${Sql.Field(f)} = EXCLUDED.${Sql.Field(f)}`);
|
|
882
884
|
}
|
|
883
885
|
} else {
|
|
884
886
|
conflictSql = Sql`ON CONFLICT`;
|
|
@@ -950,25 +952,29 @@ FROM (values${Sql`,`.glue(list.map(data => Sql`(${Sql`,`.glue(dataFieldType.map(
|
|
|
950
952
|
WHERE ${Sql`AND`.glue([pKeys.map(f => Sql`${main.field(f)}=${tmp.field(f)}`), getWhere2(env, where)].flat().filter(Boolean))}${returnSql}`;
|
|
951
953
|
}
|
|
952
954
|
|
|
955
|
+
const defaultSchema = Sql`(SELECT (current_schemas(false))[1])`;
|
|
956
|
+
|
|
953
957
|
/** @import { Environment, IConnection } from 'imodel' */
|
|
954
958
|
/** @import { PgEnvTrans } from '../index.mjs' */
|
|
955
959
|
/** @import { DBIndex, DBTable, DBColumn } from 'imodel' */
|
|
956
960
|
const tableType = 'BASE TABLE';
|
|
961
|
+
// eslint-disable-next-line max-len
|
|
962
|
+
const textRegex = /^'(?<text>(?:[^']|'')+)'(?:::(?<type>character varying|text|jsonb?))?$/;
|
|
957
963
|
/**
|
|
958
964
|
*
|
|
959
965
|
* @param {Environment<PgEnvTrans>} env
|
|
960
|
-
* @param {string} schema
|
|
961
966
|
* @param {<T extends pg.QueryResultRow>(env: Environment<PgEnvTrans>, sql: Sql) => Promise<T[]>} query
|
|
962
967
|
* @param {string[]} tables
|
|
963
|
-
* @
|
|
968
|
+
* @param {string?} [schema]
|
|
969
|
+
* @returns {Promise<(DBColumn & {table: string; name: string; defaultExp: string?})[]>}
|
|
964
970
|
*/
|
|
965
|
-
async function loadFields(env,
|
|
971
|
+
async function loadFields(env, query, tables, schema) {
|
|
966
972
|
const sql = Sql`
|
|
967
973
|
SELECT *
|
|
968
974
|
FROM
|
|
969
975
|
information_schema.columns t
|
|
970
976
|
WHERE
|
|
971
|
-
table_schema = ${
|
|
977
|
+
table_schema = ${defaultSchema}
|
|
972
978
|
AND
|
|
973
979
|
t.table_name IN (${Sql`,`.glue(tables.map(t => Sql`${t}`))})
|
|
974
980
|
`;
|
|
@@ -984,7 +990,7 @@ WHERE
|
|
|
984
990
|
let scale = 0;
|
|
985
991
|
const nullable = column.is_nullable === 'YES';
|
|
986
992
|
/** @type {any} */
|
|
987
|
-
let
|
|
993
|
+
let defaultExp = column.column_default;
|
|
988
994
|
switch (type) {
|
|
989
995
|
case 'int2':
|
|
990
996
|
type = 'i16';
|
|
@@ -1057,26 +1063,58 @@ WHERE
|
|
|
1057
1063
|
case 'json':
|
|
1058
1064
|
type = 'json';
|
|
1059
1065
|
}
|
|
1060
|
-
|
|
1066
|
+
let defaultValue;
|
|
1067
|
+
const regexResult = textRegex.exec(defaultExp)?.groups;
|
|
1068
|
+
if (regexResult) {
|
|
1069
|
+
const {
|
|
1070
|
+
text,
|
|
1071
|
+
type
|
|
1072
|
+
} = regexResult;
|
|
1073
|
+
if (typeof text === 'string') {
|
|
1074
|
+
const str = text.replaceAll("''", '');
|
|
1075
|
+
switch (type) {
|
|
1076
|
+
case 'json':
|
|
1077
|
+
case 'jsonb':
|
|
1078
|
+
try {
|
|
1079
|
+
defaultValue = JSON.parse(str);
|
|
1080
|
+
} catch {}
|
|
1081
|
+
break;
|
|
1082
|
+
default:
|
|
1083
|
+
defaultValue = str;
|
|
1084
|
+
break;
|
|
1085
|
+
}
|
|
1086
|
+
defaultExp = null;
|
|
1087
|
+
}
|
|
1088
|
+
} else if (defaultExp === 'CURRENT_TIMESTAMP' || defaultExp === 'now()') {
|
|
1061
1089
|
defaultValue = env.values.now;
|
|
1062
|
-
|
|
1090
|
+
defaultExp = null;
|
|
1091
|
+
} else if (defaultExp === 'gen_random_uuid()') {
|
|
1063
1092
|
defaultValue = env.values.uuid;
|
|
1064
|
-
|
|
1093
|
+
defaultExp = null;
|
|
1094
|
+
} else if (defaultExp === 'false') {
|
|
1065
1095
|
defaultValue = false;
|
|
1066
|
-
|
|
1096
|
+
defaultExp = null;
|
|
1097
|
+
} else if (defaultExp === 'true') {
|
|
1067
1098
|
defaultValue = true;
|
|
1068
|
-
|
|
1099
|
+
defaultExp = null;
|
|
1100
|
+
} else if (defaultExp === `''::character varying`) {
|
|
1069
1101
|
defaultValue = '';
|
|
1070
|
-
|
|
1102
|
+
defaultExp = null;
|
|
1103
|
+
} else if (defaultExp === `''::text`) {
|
|
1071
1104
|
defaultValue = '';
|
|
1072
|
-
|
|
1105
|
+
defaultExp = null;
|
|
1106
|
+
} else if (defaultExp === `'[]'::json`) {
|
|
1073
1107
|
defaultValue = [];
|
|
1074
|
-
|
|
1108
|
+
defaultExp = null;
|
|
1109
|
+
} else if (defaultExp === `'{}'::json`) {
|
|
1075
1110
|
defaultValue = {};
|
|
1076
|
-
|
|
1111
|
+
defaultExp = null;
|
|
1112
|
+
} else if (/^ARRAY\[\]::[a-z \d]+\[\]$/.test(defaultExp)) {
|
|
1077
1113
|
defaultValue = [];
|
|
1078
|
-
|
|
1079
|
-
|
|
1114
|
+
defaultExp = null;
|
|
1115
|
+
} else if (/^\d+(.\d+)?(?:::[a-z \d]+)?$/.test(defaultExp)) {
|
|
1116
|
+
defaultValue = Number(defaultExp);
|
|
1117
|
+
defaultExp = null;
|
|
1080
1118
|
}
|
|
1081
1119
|
return {
|
|
1082
1120
|
table: column.table_name,
|
|
@@ -1086,6 +1124,7 @@ WHERE
|
|
|
1086
1124
|
scale,
|
|
1087
1125
|
nullable,
|
|
1088
1126
|
default: defaultValue,
|
|
1127
|
+
defaultExp,
|
|
1089
1128
|
array
|
|
1090
1129
|
};
|
|
1091
1130
|
});
|
|
@@ -1094,16 +1133,16 @@ WHERE
|
|
|
1094
1133
|
*
|
|
1095
1134
|
* @param {Environment<PgEnvTrans>} env
|
|
1096
1135
|
* @param {<T extends pg.QueryResultRow>(env: Environment<PgEnvTrans>, sql: Sql) => Promise<T[]>} query
|
|
1097
|
-
* @param {(DBColumn & {table: string; name: string})[]} fields
|
|
1136
|
+
* @param {(DBColumn & {table: string; name: string; defaultExp: string?})[]} fields
|
|
1098
1137
|
* @returns {Promise<(DBColumn & {table: string; name: string})[]>}
|
|
1099
1138
|
*/
|
|
1100
1139
|
async function loadDefault(env, query, fields) {
|
|
1101
|
-
const data = fields.filter(v => v.
|
|
1140
|
+
const data = fields.filter(v => v.defaultExp);
|
|
1102
1141
|
if (!data.length) {
|
|
1103
1142
|
return fields;
|
|
1104
1143
|
}
|
|
1105
1144
|
const sql = Sql`
|
|
1106
|
-
SELECT ${Sql`,`.glue(data.map((v, k) => Sql(`${v.
|
|
1145
|
+
SELECT ${Sql`,`.glue(data.map((v, k) => Sql(`${v.defaultExp} as a${k}`)))}
|
|
1107
1146
|
`;
|
|
1108
1147
|
const [values = {}] = await query(env, sql);
|
|
1109
1148
|
for (const [index, column] of data.entries()) {
|
|
@@ -1114,12 +1153,12 @@ SELECT ${Sql`,`.glue(data.map((v, k) => Sql(`${v.default} as a${k}`)))}
|
|
|
1114
1153
|
/**
|
|
1115
1154
|
*
|
|
1116
1155
|
* @param {Environment<PgEnvTrans>} env
|
|
1117
|
-
* @param {string} schema
|
|
1118
1156
|
* @param {<T extends pg.QueryResultRow>(env: Environment<PgEnvTrans>, sql: Sql) => Promise<T[]>} query
|
|
1119
1157
|
* @param {string[]} tables
|
|
1158
|
+
* @param {string?} [schema]
|
|
1120
1159
|
* @returns {Promise<[(DBIndex & {table: string})[], ({fields: string[], name: string, table: string})[]]>}
|
|
1121
1160
|
*/
|
|
1122
|
-
async function loadIndex(env,
|
|
1161
|
+
async function loadIndex(env, query, tables, schema) {
|
|
1123
1162
|
const sql = Sql`
|
|
1124
1163
|
SELECT
|
|
1125
1164
|
t.relname AS table,
|
|
@@ -1140,6 +1179,10 @@ JOIN
|
|
|
1140
1179
|
JOIN
|
|
1141
1180
|
pg_class i ON ix.indexrelid = i.oid
|
|
1142
1181
|
WHERE
|
|
1182
|
+
t.relnamespace IN (
|
|
1183
|
+
SELECT oid FROM pg_namespace WHERE nspname = ${defaultSchema}
|
|
1184
|
+
)
|
|
1185
|
+
AND
|
|
1143
1186
|
t.relname IN (${Sql`,`.glue(tables.map(t => Sql`${t}`))})
|
|
1144
1187
|
AND
|
|
1145
1188
|
t.relkind = 'r'; -- 只匹配普通表
|
|
@@ -1170,16 +1213,16 @@ WHERE
|
|
|
1170
1213
|
/**
|
|
1171
1214
|
*
|
|
1172
1215
|
* @param {Environment<PgEnvTrans>} env
|
|
1173
|
-
* @param {string} schema
|
|
1174
1216
|
* @param {<T extends pg.QueryResultRow>(env: Environment<PgEnvTrans>, sql: Sql) => Promise<T[]>} query
|
|
1175
1217
|
* @param {string[]} tables
|
|
1218
|
+
* @param {string?} [schema]
|
|
1176
1219
|
* @returns {Promise<string[]>}
|
|
1177
1220
|
*/
|
|
1178
|
-
async function loadBaseTables(env,
|
|
1221
|
+
async function loadBaseTables(env, query, tables, schema) {
|
|
1179
1222
|
const sql = Sql`SELECT *
|
|
1180
1223
|
FROM information_schema.tables
|
|
1181
1224
|
WHERE
|
|
1182
|
-
table_schema = ${
|
|
1225
|
+
table_schema = ${defaultSchema}
|
|
1183
1226
|
AND
|
|
1184
1227
|
table_type = ${tableType}
|
|
1185
1228
|
AND
|
|
@@ -1190,13 +1233,13 @@ async function loadBaseTables(env, schema, query, tables) {
|
|
|
1190
1233
|
/**
|
|
1191
1234
|
*
|
|
1192
1235
|
* @param {Environment<PgEnvTrans>} env
|
|
1193
|
-
* @param {string} schema
|
|
1194
1236
|
* @param {<T extends pg.QueryResultRow>(env: Environment<PgEnvTrans>, sql: Sql) => Promise<T[]>} query
|
|
1195
1237
|
* @param {string[]} tables
|
|
1238
|
+
* @param {string?} [schema]
|
|
1196
1239
|
* @returns {Promise<DBTable[]>}
|
|
1197
1240
|
*/
|
|
1198
|
-
async function loadTables(env,
|
|
1199
|
-
const [baseTables, allFields, [allIndexes, allPrimary]] = await Promise.all([loadBaseTables(env,
|
|
1241
|
+
async function loadTables(env, query, tables, schema) {
|
|
1242
|
+
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
1243
|
const allTables = new Set(baseTables);
|
|
1201
1244
|
const fieldsGroup = Object.groupBy(allFields, f => f.table);
|
|
1202
1245
|
const indexesGroup = Object.groupBy(allIndexes, f => f.table);
|
|
@@ -1591,14 +1634,13 @@ ADD PRIMARY KEY (${Sql`,`.glue(primary.map(f => Sql.Field(f)))})
|
|
|
1591
1634
|
/**
|
|
1592
1635
|
*
|
|
1593
1636
|
* @param {Environment<PgEnvTrans>} env
|
|
1594
|
-
* @param {string} schema
|
|
1595
1637
|
* @param {<T extends pg.QueryResultRow>(env: Environment<PgEnvTrans>, sql: Sql) => Promise<T[]>} query
|
|
1596
1638
|
* @param {DBTable[]} tables
|
|
1597
|
-
* @param {
|
|
1639
|
+
* @param {string} [schema]
|
|
1598
1640
|
*/
|
|
1599
|
-
async function syncTables(env,
|
|
1641
|
+
async function syncTables(env, query, tables, schema) {
|
|
1600
1642
|
const tableNames = tables.map(v => v.table);
|
|
1601
|
-
const dbTables = await loadTables(env,
|
|
1643
|
+
const dbTables = await loadTables(env, query, tableNames);
|
|
1602
1644
|
const tableMap = new Map(dbTables.map(v => [v.table, v]));
|
|
1603
1645
|
for (const table of tables) {
|
|
1604
1646
|
const old = tableMap.get(table.table);
|
|
@@ -1691,7 +1733,6 @@ function toPoolConnection(pool) {
|
|
|
1691
1733
|
*/
|
|
1692
1734
|
function index (pool, version) {
|
|
1693
1735
|
const connect = toPoolConnection(pool);
|
|
1694
|
-
const schema = 'public';
|
|
1695
1736
|
const dbVersion = typeof version === 'function' ? version : createVersion(connect);
|
|
1696
1737
|
/**
|
|
1697
1738
|
* @template {pg.QueryResultRow} T
|
|
@@ -1762,7 +1803,8 @@ function index (pool, version) {
|
|
|
1762
1803
|
async type(env, table) {
|
|
1763
1804
|
const sql = Sql`SELECT table_type as type
|
|
1764
1805
|
FROM information_schema.tables
|
|
1765
|
-
WHERE table_schema =
|
|
1806
|
+
WHERE table_schema = (SELECT (current_schemas(false))[1])
|
|
1807
|
+
AND table_name = ${table} LIMIT 1`;
|
|
1766
1808
|
/** @type {pg.QueryResult<{ type: string; }>} */
|
|
1767
1809
|
const {
|
|
1768
1810
|
rows: [row]
|
|
@@ -1779,8 +1821,8 @@ function index (pool, version) {
|
|
|
1779
1821
|
return '';
|
|
1780
1822
|
}
|
|
1781
1823
|
},
|
|
1782
|
-
insert(env, table, columns, data, keys) {
|
|
1783
|
-
return query(env, insertSql(env, table, columns, data, keys));
|
|
1824
|
+
insert(env, table, columns, data, keys, ignore) {
|
|
1825
|
+
return query(env, insertSql(env, table, columns, data, keys, ignore));
|
|
1784
1826
|
},
|
|
1785
1827
|
upsert(env, table, columns, data, keys, conflict, conflictSet) {
|
|
1786
1828
|
return query(env, insertSql(env, table, columns, data, keys, conflict, conflictSet));
|
|
@@ -1851,10 +1893,10 @@ function index (pool, version) {
|
|
|
1851
1893
|
return exec(env, renameTable(table, newName));
|
|
1852
1894
|
},
|
|
1853
1895
|
loadTables(env, tables) {
|
|
1854
|
-
return loadTables(env,
|
|
1896
|
+
return loadTables(env, query, tables);
|
|
1855
1897
|
},
|
|
1856
1898
|
syncTables(env, tables) {
|
|
1857
|
-
return syncTables(env,
|
|
1899
|
+
return syncTables(env, query, tables);
|
|
1858
1900
|
},
|
|
1859
1901
|
async transaction(env, fn) {
|
|
1860
1902
|
if (env?.transaction?.client) {
|