orchid-orm 1.72.5 → 1.72.6
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/dist/index.d.ts +10 -0
- package/dist/index.js +107 -47
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +108 -48
- package/dist/index.mjs.map +1 -1
- package/package.json +5 -5
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { DynamicRawSQL, QueryHooks, RawSql, VirtualColumn, _appendQuery, _clone, _createDbSqlMethod, _hookSelectColumns, _initQueryBuilder, _orCreate, _prependWith, _queryCreate, _queryCreateMany, _queryCreateManyFrom, _queryDefaults, _queryDelete, _queryFindBy, _queryFindByOptional, _queryHookAfterCreate, _queryHookAfterUpdate, _queryInsert, _queryInsertMany, _queryJoinOn, _queryRows, _querySelect, _queryTake, _queryTakeOptional, _queryUpdate, _queryUpdateOrThrow, _queryUpsert, _queryWhere, _queryWhereExists, _queryWhereIn, applyMixins, cloneQueryBaseUnscoped, defaultSchemaConfig, emptyArray, emptyObject, getCallerFilePath, getClonedQueryData, getColumnTypes, getFreeAlias, getPrimaryKeys, getQueryAs, getShapeFromSelect, getStackTrace, internalSchemaConfig, isExpression, isQueryReturnsAll, makeColumnTypes, noop, objectHasValues, parseTableData, pick, prepareSubQueryForSql, pushQueryOnForOuter, setQueryObjectValueImmutable, toArray, toSnakeCase } from "pqb/internal";
|
|
1
|
+
import { DynamicRawSQL, QueryHooks, RawSql, VirtualColumn, _appendQuery, _appendQueryOnUpsertCreate, _clone, _createDbSqlMethod, _hookSelectColumns, _initQueryBuilder, _orCreate, _prependWith, _queryCreate, _queryCreateMany, _queryCreateManyFrom, _queryDefaults, _queryDelete, _queryFindBy, _queryFindByOptional, _queryHookAfterCreate, _queryHookAfterUpdate, _queryInsert, _queryInsertMany, _queryJoinOn, _queryRows, _querySelect, _queryTake, _queryTakeOptional, _queryUpdate, _queryUpdateOrThrow, _queryUpsert, _queryWhere, _queryWhereExists, _queryWhereIn, applyMixins, cloneQueryBaseUnscoped, defaultSchemaConfig, emptyArray, emptyObject, getCallerFilePath, getClonedQueryData, getColumnTypes, getFreeAlias, getPrimaryKeys, getQueryAs, getShapeFromSelect, getStackTrace, internalSchemaConfig, isExpression, isQueryReturnsAll, makeColumnTypes, noop, objectHasValues, parseTableData, pick, prepareSubQueryForSql, pushQueryOnForOuter, setQueryObjectValueImmutable, toArray, toSnakeCase } from "pqb/internal";
|
|
2
2
|
import { Db, NotFoundError, OrchidOrmInternalError } from "pqb";
|
|
3
3
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
4
4
|
export * from "pqb";
|
|
@@ -137,6 +137,25 @@ function createBaseTable({ schemaConfig = defaultSchemaConfig, columnTypes: colu
|
|
|
137
137
|
base.prototype.autoForeignKeys = autoForeignKeys === true ? {} : autoForeignKeys || void 0;
|
|
138
138
|
return base;
|
|
139
139
|
}
|
|
140
|
+
const throwIfQueryReturnsAllForNestedUpdate = (q, params) => {
|
|
141
|
+
if (!(params.set || params.create || params.upsert) || !isQueryReturnsAll(q)) return;
|
|
142
|
+
let key;
|
|
143
|
+
if (params.set) key = "set";
|
|
144
|
+
else if (params.create) key = "create";
|
|
145
|
+
else key = "upsert";
|
|
146
|
+
throw new Error(`\`${key}\` option is not allowed in a batch update`);
|
|
147
|
+
};
|
|
148
|
+
const getNestedUpdateUpsertCreate = (upsert) => {
|
|
149
|
+
if (typeof upsert.create === "function") return upsert.create();
|
|
150
|
+
return upsert.create || emptyObject;
|
|
151
|
+
};
|
|
152
|
+
const makeNestedUpdateUpsertData = (upsert, setIds) => ({
|
|
153
|
+
update: upsert.update,
|
|
154
|
+
create: {
|
|
155
|
+
...getNestedUpdateUpsertCreate(upsert),
|
|
156
|
+
...setIds
|
|
157
|
+
}
|
|
158
|
+
});
|
|
140
159
|
const getThroughRelation = (table, through) => {
|
|
141
160
|
return table.relations[through];
|
|
142
161
|
};
|
|
@@ -224,8 +243,27 @@ const getColumnKeyFromDbName = (query, name) => {
|
|
|
224
243
|
for (const k in query.shape) if (query.shape[k].data.name === name) return k;
|
|
225
244
|
return name;
|
|
226
245
|
};
|
|
227
|
-
const selectCteColumnsSql = (cteAs, columns) => `(SELECT ${columns.map((c) => `"${cteAs}"."${c}"`).join(", ")} FROM "${cteAs}")`;
|
|
228
|
-
const selectCteColumnSql = (cteAs, column) => `(SELECT "${cteAs}"."${column}" FROM "${cteAs}")`;
|
|
246
|
+
const selectCteColumnsSql$1 = (cteAs, columns) => `(SELECT ${columns.map((c) => `"${cteAs}"."${c}"`).join(", ")} FROM "${cteAs}")`;
|
|
247
|
+
const selectCteColumnSql$1 = (cteAs, column) => `(SELECT "${cteAs}"."${column}" FROM "${cteAs}")`;
|
|
248
|
+
const makeNestedUpdateRelationIds = (q, relQuery, primaryKeys, foreignKeys) => {
|
|
249
|
+
const selectIdsSql = new RawSql("");
|
|
250
|
+
const setIds = {};
|
|
251
|
+
for (const foreignKey of foreignKeys) setIds[foreignKey] = new RawSql("");
|
|
252
|
+
let appendedAs;
|
|
253
|
+
_hookSelectColumns(q, primaryKeys, (aliasedPrimaryKeys) => {
|
|
254
|
+
selectIdsSql._sql = selectCteColumnsSql$1(appendedAs, aliasedPrimaryKeys);
|
|
255
|
+
foreignKeys.forEach((foreignKey, i) => {
|
|
256
|
+
setIds[foreignKey]._sql = selectCteColumnSql$1(appendedAs, aliasedPrimaryKeys[i]);
|
|
257
|
+
});
|
|
258
|
+
});
|
|
259
|
+
return {
|
|
260
|
+
existingRelQuery: _queryWhereIn(_clone(relQuery), true, foreignKeys, selectIdsSql),
|
|
261
|
+
setIds,
|
|
262
|
+
setAppendedAs(as) {
|
|
263
|
+
appendedAs = as;
|
|
264
|
+
}
|
|
265
|
+
};
|
|
266
|
+
};
|
|
229
267
|
const selectCteColumnFromManySql = (cteAs, column, rowIndex, count) => {
|
|
230
268
|
let sql = `(SELECT "${cteAs}"."${column}" FROM "${cteAs}"`;
|
|
231
269
|
if (count > 1) {
|
|
@@ -406,7 +444,7 @@ const nestedUpdate$2 = ({ query, primaryKeys, foreignKeys, len }) => {
|
|
|
406
444
|
} else if (params.update) {
|
|
407
445
|
let appendedAs;
|
|
408
446
|
_hookSelectColumns(self, foreignKeys, (aliasedForeignKeys) => {
|
|
409
|
-
selectIdsSql._sql = selectCteColumnsSql(appendedAs, aliasedForeignKeys);
|
|
447
|
+
selectIdsSql._sql = selectCteColumnsSql$1(appendedAs, aliasedForeignKeys);
|
|
410
448
|
});
|
|
411
449
|
const selectIdsSql = new RawSql("");
|
|
412
450
|
const updateQuery = _queryUpdate(_queryWhereIn(query.clone(), true, primaryKeys, selectIdsSql), params.update);
|
|
@@ -449,7 +487,7 @@ const relWithSelectIds = (self, rel, primaryKeys, foreignKeys) => {
|
|
|
449
487
|
const selectIdsQuery = makeSelectIdsQuery(self, foreignKeys);
|
|
450
488
|
const selectIdsSql = new RawSql("");
|
|
451
489
|
_prependWith(self, (as) => {
|
|
452
|
-
selectIdsSql._sql = selectCteColumnsSql(as, foreignKeys);
|
|
490
|
+
selectIdsSql._sql = selectCteColumnsSql$1(as, foreignKeys);
|
|
453
491
|
}, selectIdsQuery);
|
|
454
492
|
return {
|
|
455
493
|
selectIdsSql,
|
|
@@ -470,12 +508,12 @@ const setForeignKeysFromCte = (record, primaryKeys, foreignKeys, mustExist) => {
|
|
|
470
508
|
foreignKeys.forEach(mustExist ? (foreignKey, i) => {
|
|
471
509
|
record[foreignKey]._sql = selectCteColumnMustExistSql(i, as, primaryKeys[i]);
|
|
472
510
|
} : (foreignKey, i) => {
|
|
473
|
-
record[foreignKey]._sql = selectCteColumnSql(as, primaryKeys[i]);
|
|
511
|
+
record[foreignKey]._sql = selectCteColumnSql$1(as, primaryKeys[i]);
|
|
474
512
|
});
|
|
475
513
|
};
|
|
476
514
|
};
|
|
477
515
|
const selectCteColumnMustExistSql = (i, cteAs, column) => {
|
|
478
|
-
const selectColumn = selectCteColumnSql(cteAs, column);
|
|
516
|
+
const selectColumn = selectCteColumnSql$1(cteAs, column);
|
|
479
517
|
return i === 0 ? `CASE WHEN (SELECT count(*) FROM "${cteAs}") = 0 AND (SELECT 'not-found')::int = 0 THEN NULL ELSE ${selectColumn} END` : selectColumn;
|
|
480
518
|
};
|
|
481
519
|
var HasOneVirtualColumn = class extends VirtualColumn {
|
|
@@ -541,43 +579,19 @@ var HasOneVirtualColumn = class extends VirtualColumn {
|
|
|
541
579
|
update(self, set) {
|
|
542
580
|
const querySelf = self;
|
|
543
581
|
const params = set[this.key];
|
|
544
|
-
|
|
545
|
-
const key = params.set ? "set" : params.create ? "create" : "upsert";
|
|
546
|
-
throw new Error(`\`${key}\` option is not allowed in a batch update`);
|
|
547
|
-
}
|
|
582
|
+
throwIfQueryReturnsAllForNestedUpdate(querySelf, params);
|
|
548
583
|
const { primaryKeys, foreignKeys, query: relQuery } = this.state;
|
|
549
584
|
if (params.create || params.update || params.upsert || params.disconnect || params.set || params.delete) {
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
selectIdsSql._sql = selectCteColumnsSql(appendedAs, aliasedPrimaryKeys);
|
|
553
|
-
if (params.create || params.set || params.upsert) foreignKeys.forEach((foreignKey, i) => {
|
|
554
|
-
setIds[foreignKey]._sql = selectCteColumnSql(appendedAs, aliasedPrimaryKeys[i]);
|
|
555
|
-
});
|
|
556
|
-
});
|
|
557
|
-
const selectIdsSql = new RawSql("");
|
|
558
|
-
const existingRelQuery = _queryWhereIn(_clone(relQuery), true, foreignKeys, selectIdsSql);
|
|
559
|
-
let setIds = void 0;
|
|
560
|
-
if (params.create || params.set || params.upsert) {
|
|
561
|
-
setIds = {};
|
|
562
|
-
foreignKeys.forEach((foreignKey) => {
|
|
563
|
-
setIds[foreignKey] = new RawSql("");
|
|
564
|
-
});
|
|
565
|
-
}
|
|
566
|
-
const nullifyOrDeleteQuery = params.update ? _queryUpdate(existingRelQuery, params.update) : params.upsert ? _queryUpsert(existingRelQuery, {
|
|
567
|
-
update: params.upsert.update,
|
|
568
|
-
create: {
|
|
569
|
-
...typeof params.upsert.create === "function" ? params.upsert.create() : params.upsert.create,
|
|
570
|
-
...setIds
|
|
571
|
-
}
|
|
572
|
-
}) : params.delete ? _queryDelete(existingRelQuery) : _queryUpdate(existingRelQuery, this.setNulls);
|
|
585
|
+
const ids = makeNestedUpdateRelationIds(querySelf, relQuery, primaryKeys, foreignKeys);
|
|
586
|
+
const nullifyOrDeleteQuery = params.update ? _queryUpdate(ids.existingRelQuery, params.update) : params.upsert ? _queryUpsert(ids.existingRelQuery, makeNestedUpdateUpsertData(params.upsert, ids.setIds)) : params.delete ? _queryDelete(ids.existingRelQuery) : _queryUpdate(ids.existingRelQuery, this.setNulls);
|
|
573
587
|
nullifyOrDeleteQuery.q.returnType = "void";
|
|
574
|
-
_appendQuery(querySelf, nullifyOrDeleteQuery,
|
|
588
|
+
_appendQuery(querySelf, nullifyOrDeleteQuery, ids.setAppendedAs);
|
|
575
589
|
if (params.create) _appendQuery(querySelf, _queryInsert(_clone(relQuery), {
|
|
576
590
|
...params.create,
|
|
577
|
-
...setIds
|
|
591
|
+
...ids.setIds
|
|
578
592
|
}), noop);
|
|
579
593
|
else if (params.set) {
|
|
580
|
-
const setQuery = _queryUpdate(_queryWhere(_clone(relQuery), [params.set]), setIds);
|
|
594
|
+
const setQuery = _queryUpdate(_queryWhere(_clone(relQuery), [params.set]), ids.setIds);
|
|
581
595
|
setQuery.q.returnType = "void";
|
|
582
596
|
_appendQuery(querySelf, setQuery, noop);
|
|
583
597
|
}
|
|
@@ -691,6 +705,8 @@ var HasManyVirtualColumn = class extends VirtualColumn {
|
|
|
691
705
|
this.state = state;
|
|
692
706
|
this.nestedInsert = nestedInsert$1(state);
|
|
693
707
|
this.nestedUpdate = nestedUpdate$1(state);
|
|
708
|
+
this.setNulls = {};
|
|
709
|
+
for (const foreignKey of state.foreignKeys) this.setNulls[foreignKey] = null;
|
|
694
710
|
}
|
|
695
711
|
create(self, ctx, items, rowIndexes, count) {
|
|
696
712
|
const querySelf = self;
|
|
@@ -761,14 +777,18 @@ var HasManyVirtualColumn = class extends VirtualColumn {
|
|
|
761
777
|
});
|
|
762
778
|
} else hasRelationHandleCreate(querySelf, ctx, items, rowIndexes, this.key, this.state.primaryKeys, this.nestedInsert);
|
|
763
779
|
}
|
|
764
|
-
update(
|
|
765
|
-
const
|
|
780
|
+
update(self, set) {
|
|
781
|
+
const querySelf = self;
|
|
766
782
|
const params = set[this.key];
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
783
|
+
throwIfQueryReturnsAllForNestedUpdate(querySelf, params);
|
|
784
|
+
hasRelationHandleUpdate(querySelf, set, this.key, this.state.primaryKeys, this.nestedUpdate);
|
|
785
|
+
if (params.upsert) {
|
|
786
|
+
const { primaryKeys, foreignKeys, query: relQuery } = this.state;
|
|
787
|
+
const ids = makeNestedUpdateRelationIds(querySelf, relQuery, primaryKeys, foreignKeys);
|
|
788
|
+
const appendedQuery = _queryUpsert(ids.existingRelQuery, makeNestedUpdateUpsertData(params.upsert, ids.setIds));
|
|
789
|
+
appendedQuery.q.returnType = "void";
|
|
790
|
+
_appendQuery(querySelf, appendedQuery, ids.setAppendedAs);
|
|
770
791
|
}
|
|
771
|
-
hasRelationHandleUpdate(query, set, this.key, this.state.primaryKeys, this.nestedUpdate);
|
|
772
792
|
}
|
|
773
793
|
};
|
|
774
794
|
const makeHasManyMethod = (tableConfig, table, relation, relationName, query) => {
|
|
@@ -908,10 +928,10 @@ const nestedInsert$1 = ({ query, primaryKeys, foreignKeys }) => {
|
|
|
908
928
|
}
|
|
909
929
|
});
|
|
910
930
|
};
|
|
911
|
-
const nestedUpdate$1 = ({ query, primaryKeys, foreignKeys }) => {
|
|
931
|
+
const nestedUpdate$1 = ({ query: relQuery, primaryKeys, foreignKeys }) => {
|
|
912
932
|
const len = primaryKeys.length;
|
|
913
933
|
return (async (_, data, params) => {
|
|
914
|
-
const t =
|
|
934
|
+
const t = relQuery.clone();
|
|
915
935
|
if (params.create) {
|
|
916
936
|
const obj = {};
|
|
917
937
|
for (let i = 0; i < len; i++) obj[foreignKeys[i]] = data[0][primaryKeys[i]];
|
|
@@ -921,12 +941,12 @@ const nestedUpdate$1 = ({ query, primaryKeys, foreignKeys }) => {
|
|
|
921
941
|
})));
|
|
922
942
|
}
|
|
923
943
|
if (params.add) {
|
|
924
|
-
if (data.length > 1) throw new OrchidOrmInternalError(
|
|
944
|
+
if (data.length > 1) throw new OrchidOrmInternalError(relQuery, "`connect` is not available when updating multiple records, it is only applicable for a single record update");
|
|
925
945
|
const obj = {};
|
|
926
946
|
for (let i = 0; i < len; i++) obj[foreignKeys[i]] = data[0][primaryKeys[i]];
|
|
927
947
|
const relatedWheres = toArray(params.add);
|
|
928
948
|
const count = await _queryUpdate(t.where({ OR: relatedWheres }), obj);
|
|
929
|
-
if (count < relatedWheres.length) throw new OrchidOrmInternalError(
|
|
949
|
+
if (count < relatedWheres.length) throw new OrchidOrmInternalError(relQuery, `Expected to find at least ${relatedWheres.length} record(s) based on \`add\` conditions, but found ${count}`);
|
|
930
950
|
}
|
|
931
951
|
if (params.disconnect || params.set) {
|
|
932
952
|
const obj = {};
|
|
@@ -961,9 +981,48 @@ var HasAndBelongsToManyVirtualColumn = class extends VirtualColumn {
|
|
|
961
981
|
hasRelationHandleCreate(q, ctx, items, rowIndexes, this.key, this.state.primaryKeys, this.nestedInsert);
|
|
962
982
|
}
|
|
963
983
|
update(q, set) {
|
|
964
|
-
|
|
984
|
+
const querySelf = q;
|
|
985
|
+
const params = set[this.key];
|
|
986
|
+
hasRelationHandleUpdate(querySelf, set, this.key, this.state.primaryKeys, this.nestedUpdate);
|
|
987
|
+
if (params.upsert) {
|
|
988
|
+
throwIfQueryReturnsAllForNestedUpdate(querySelf, { upsert: params.upsert });
|
|
989
|
+
nestedUpdateUpsert(querySelf, this.state, params.upsert);
|
|
990
|
+
}
|
|
965
991
|
}
|
|
966
992
|
};
|
|
993
|
+
const selectCteColumnsSql = (cteAs, columns) => `(SELECT ${columns.map((c) => `"${cteAs}"."${c}"`).join(", ")} FROM "${cteAs}")`;
|
|
994
|
+
const selectCteColumnSql = (cteAs, column) => `(SELECT "${cteAs}"."${column}" FROM "${cteAs}")`;
|
|
995
|
+
const nestedUpdateUpsert = (querySelf, state, upsert) => {
|
|
996
|
+
const parentIdsSql = new RawSql("");
|
|
997
|
+
const parentValues = state.foreignKeys.map(() => new RawSql(""));
|
|
998
|
+
const relatedIdsSql = new RawSql("");
|
|
999
|
+
const relatedValues = state.throughPrimaryKeys.map(() => new RawSql(""));
|
|
1000
|
+
let parentAs;
|
|
1001
|
+
_hookSelectColumns(querySelf, state.primaryKeys, (aliasedPrimaryKeys) => {
|
|
1002
|
+
parentIdsSql._sql = selectCteColumnsSql(parentAs, aliasedPrimaryKeys);
|
|
1003
|
+
for (let i = 0; i < state.foreignKeys.length; i++) parentValues[i]._sql = selectCteColumnSql(parentAs, aliasedPrimaryKeys[i]);
|
|
1004
|
+
});
|
|
1005
|
+
const upsertQuery = _querySelect(_queryUpsert(_queryWhereExists(_queryWhere(_clone(state.relatedTableQuery), [upsert.findBy]), state.joinTableQuery, [(q) => {
|
|
1006
|
+
for (let i = 0; i < state.throughPrimaryKeys.length; i++) _queryJoinOn(q, [state.throughForeignKeysFull[i], state.throughPrimaryKeysFull[i]]);
|
|
1007
|
+
return _queryWhereIn(q, true, state.foreignKeysFull, parentIdsSql);
|
|
1008
|
+
}]), {
|
|
1009
|
+
update: upsert.update,
|
|
1010
|
+
create: upsert.create || {}
|
|
1011
|
+
}), state.throughPrimaryKeys);
|
|
1012
|
+
const selectAs = {};
|
|
1013
|
+
for (let i = 0; i < state.foreignKeys.length; i++) selectAs[state.foreignKeys[i]] = parentValues[i];
|
|
1014
|
+
for (let i = 0; i < state.throughForeignKeys.length; i++) selectAs[state.throughForeignKeys[i]] = relatedValues[i];
|
|
1015
|
+
const joinRows = _querySelect(_clone(state.queryBuilder), [selectAs]);
|
|
1016
|
+
_queryWhere(joinRows, [relatedIdsSql]);
|
|
1017
|
+
const joinQuery = state.joinTableQuery.insertForEachFrom(joinRows);
|
|
1018
|
+
joinQuery.q.returnType = "void";
|
|
1019
|
+
_appendQuery(querySelf, _appendQueryOnUpsertCreate(upsertQuery, joinQuery, (as) => {
|
|
1020
|
+
relatedIdsSql._sql = `EXISTS (SELECT 1 FROM "${as}")`;
|
|
1021
|
+
for (let i = 0; i < relatedValues.length; i++) relatedValues[i]._sql = selectCteColumnSql(as, state.throughPrimaryKeys[i]);
|
|
1022
|
+
}), (as) => {
|
|
1023
|
+
parentAs = as;
|
|
1024
|
+
});
|
|
1025
|
+
};
|
|
967
1026
|
const removeColumnName = (column) => {
|
|
968
1027
|
if (!column.data.name) return column;
|
|
969
1028
|
const cloned = Object.create(column);
|
|
@@ -1021,6 +1080,7 @@ const makeHasAndBelongsToManyMethod = (tableConfig, table, qb, relation, relatio
|
|
|
1021
1080
|
addAutoForeignKey(tableConfig, subQuery, table, primaryKeys, foreignKeys, relation.options, originalForeignKeys);
|
|
1022
1081
|
addAutoForeignKey(tableConfig, subQuery, query, throughPrimaryKeys, throughForeignKeys, relation.options.through, originalThroughForeignKeys);
|
|
1023
1082
|
const state = {
|
|
1083
|
+
queryBuilder: qb,
|
|
1024
1084
|
relatedTableQuery: query,
|
|
1025
1085
|
joinTableQuery: subQuery,
|
|
1026
1086
|
primaryKeys,
|