pqb 0.54.0 → 0.54.2
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 +105 -109
- package/dist/index.js +380 -323
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +349 -291
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -432,7 +432,7 @@ class ColumnType extends orchidCore.ColumnTypeBase {
|
|
|
432
432
|
return sql2;
|
|
433
433
|
}
|
|
434
434
|
});
|
|
435
|
-
column.data.
|
|
435
|
+
column.data.readOnly = true;
|
|
436
436
|
return column;
|
|
437
437
|
}
|
|
438
438
|
}
|
|
@@ -2158,7 +2158,7 @@ class TsVectorColumn extends ColumnType {
|
|
|
2158
2158
|
toSQL,
|
|
2159
2159
|
toCode
|
|
2160
2160
|
});
|
|
2161
|
-
column.data.
|
|
2161
|
+
column.data.readOnly = true;
|
|
2162
2162
|
return column;
|
|
2163
2163
|
}
|
|
2164
2164
|
}
|
|
@@ -2458,8 +2458,7 @@ class VirtualColumn extends ColumnType {
|
|
|
2458
2458
|
super(schema, inputSchema);
|
|
2459
2459
|
this.dataType = "";
|
|
2460
2460
|
this.operators = Operators.any;
|
|
2461
|
-
this.data.explicitSelect = true;
|
|
2462
|
-
this.data.insertable = this.data.updatable = false;
|
|
2461
|
+
this.data.explicitSelect = this.data.appReadOnly = this.data.virtual = true;
|
|
2463
2462
|
}
|
|
2464
2463
|
toCode() {
|
|
2465
2464
|
throw new Error(`toCode is not implemented for virtual column`);
|
|
@@ -2470,8 +2469,7 @@ const _UnknownColumn = class _UnknownColumn extends VirtualColumn {
|
|
|
2470
2469
|
constructor(schema) {
|
|
2471
2470
|
super(schema, schema.unknown());
|
|
2472
2471
|
this.selectable = true;
|
|
2473
|
-
this.data.explicitSelect = void 0;
|
|
2474
|
-
this.data.insertable = this.data.updatable = true;
|
|
2472
|
+
this.data.explicitSelect = this.data.appReadOnly = this.data.virtual = void 0;
|
|
2475
2473
|
}
|
|
2476
2474
|
};
|
|
2477
2475
|
_UnknownColumn.instance = new _UnknownColumn(defaultSchemaConfig);
|
|
@@ -2730,8 +2728,9 @@ class NotFoundError extends OrchidOrmError {
|
|
|
2730
2728
|
}
|
|
2731
2729
|
_query = new WeakMap();
|
|
2732
2730
|
class OrchidOrmInternalError extends Error {
|
|
2733
|
-
constructor(query, message) {
|
|
2731
|
+
constructor(query, message, data) {
|
|
2734
2732
|
super(message);
|
|
2733
|
+
this.data = data;
|
|
2735
2734
|
// `#query` is private to prevent it from serializing to not cause problems to test runner reports
|
|
2736
2735
|
__privateAdd(this, _query2);
|
|
2737
2736
|
__privateSet(this, _query2, query);
|
|
@@ -3380,8 +3379,8 @@ const noneMethods = {
|
|
|
3380
3379
|
const _queryNone = (q) => {
|
|
3381
3380
|
if (isQueryNone(q)) return q;
|
|
3382
3381
|
q = extendQuery(q, noneMethods);
|
|
3383
|
-
pushQueryValueImmutable(q, "and", new RawSQL("false"));
|
|
3384
|
-
pushQueryValueImmutable(
|
|
3382
|
+
orchidCore.pushQueryValueImmutable(q, "and", new RawSQL("false"));
|
|
3383
|
+
orchidCore.pushQueryValueImmutable(
|
|
3385
3384
|
q,
|
|
3386
3385
|
"transform",
|
|
3387
3386
|
(_, queryData) => noneResult(q, queryData, queryData.returnType)
|
|
@@ -3405,11 +3404,7 @@ const resolveCallbacksInArgs = (q, args) => {
|
|
|
3405
3404
|
};
|
|
3406
3405
|
const _queryWhere = (q, args) => {
|
|
3407
3406
|
resolveCallbacksInArgs(q, args);
|
|
3408
|
-
return pushQueryArrayImmutable(
|
|
3409
|
-
q,
|
|
3410
|
-
"and",
|
|
3411
|
-
args
|
|
3412
|
-
);
|
|
3407
|
+
return pushQueryArrayImmutable(q, "and", args);
|
|
3413
3408
|
};
|
|
3414
3409
|
const _queryFindBy = (q, args) => {
|
|
3415
3410
|
return _queryTake(_queryWhere(q, args));
|
|
@@ -3418,7 +3413,7 @@ const _queryFindByOptional = (q, args) => {
|
|
|
3418
3413
|
return _queryTakeOptional(_queryWhere(q, args));
|
|
3419
3414
|
};
|
|
3420
3415
|
const _queryWhereSql = (q, args) => {
|
|
3421
|
-
return pushQueryValueImmutable(
|
|
3416
|
+
return orchidCore.pushQueryValueImmutable(
|
|
3422
3417
|
q,
|
|
3423
3418
|
"and",
|
|
3424
3419
|
sqlQueryArgsToExpression(args)
|
|
@@ -3426,24 +3421,24 @@ const _queryWhereSql = (q, args) => {
|
|
|
3426
3421
|
};
|
|
3427
3422
|
const _queryWhereNot = (q, args) => {
|
|
3428
3423
|
resolveCallbacksInArgs(q, args);
|
|
3429
|
-
return pushQueryValueImmutable(q, "and", {
|
|
3424
|
+
return orchidCore.pushQueryValueImmutable(q, "and", {
|
|
3430
3425
|
NOT: args
|
|
3431
3426
|
});
|
|
3432
3427
|
};
|
|
3433
3428
|
const _queryWhereNotSql = (q, args) => {
|
|
3434
|
-
return pushQueryValueImmutable(q, "and", {
|
|
3429
|
+
return orchidCore.pushQueryValueImmutable(q, "and", {
|
|
3435
3430
|
NOT: sqlQueryArgsToExpression(args)
|
|
3436
3431
|
});
|
|
3437
3432
|
};
|
|
3438
3433
|
const _queryWhereOneOf = (q, args) => {
|
|
3439
3434
|
resolveCallbacksInArgs(q, args);
|
|
3440
|
-
return pushQueryValueImmutable(q, "and", {
|
|
3435
|
+
return orchidCore.pushQueryValueImmutable(q, "and", {
|
|
3441
3436
|
OR: args
|
|
3442
3437
|
});
|
|
3443
3438
|
};
|
|
3444
3439
|
const _queryWhereNotOneOf = (q, args) => {
|
|
3445
3440
|
resolveCallbacksInArgs(q, args);
|
|
3446
|
-
return pushQueryValueImmutable(q, "and", {
|
|
3441
|
+
return orchidCore.pushQueryValueImmutable(q, "and", {
|
|
3447
3442
|
NOT: { OR: args }
|
|
3448
3443
|
});
|
|
3449
3444
|
};
|
|
@@ -3493,9 +3488,9 @@ const _queryWhereIn = (q, and, arg, values, not) => {
|
|
|
3493
3488
|
}
|
|
3494
3489
|
if (not) item = { NOT: item };
|
|
3495
3490
|
if (and) {
|
|
3496
|
-
pushQueryValueImmutable(q, "and", item);
|
|
3491
|
+
orchidCore.pushQueryValueImmutable(q, "and", item);
|
|
3497
3492
|
} else {
|
|
3498
|
-
pushQueryValueImmutable(q, "or", [item]);
|
|
3493
|
+
orchidCore.pushQueryValueImmutable(q, "or", [item]);
|
|
3499
3494
|
}
|
|
3500
3495
|
return q;
|
|
3501
3496
|
};
|
|
@@ -4299,10 +4294,6 @@ const pushQueryArrayImmutable = (q, key, value) => {
|
|
|
4299
4294
|
q.q[key] = arr ? [...arr, ...value] : value;
|
|
4300
4295
|
return q;
|
|
4301
4296
|
};
|
|
4302
|
-
const pushQueryValueImmutable = (q, key, value) => {
|
|
4303
|
-
orchidCore.pushOrNewArrayToObjectImmutable(q.q, key, value);
|
|
4304
|
-
return q;
|
|
4305
|
-
};
|
|
4306
4297
|
const setQueryObjectValueImmutable = (q, object, key, value) => {
|
|
4307
4298
|
q.q[object] = {
|
|
4308
4299
|
...q.q[object],
|
|
@@ -4518,7 +4509,7 @@ const _join = (query, require, type, first, args) => {
|
|
|
4518
4509
|
computeds
|
|
4519
4510
|
);
|
|
4520
4511
|
}
|
|
4521
|
-
pushQueryValueImmutable(query, "join", {
|
|
4512
|
+
orchidCore.pushQueryValueImmutable(query, "join", {
|
|
4522
4513
|
type,
|
|
4523
4514
|
args: joinArgs
|
|
4524
4515
|
});
|
|
@@ -4595,7 +4586,7 @@ const _joinLateral = (self, type, arg, as, innerJoinLateral) => {
|
|
|
4595
4586
|
}
|
|
4596
4587
|
as || (as = getQueryAs(arg));
|
|
4597
4588
|
orchidCore.setObjectValueImmutable(q.q, "joinedComputeds", as, arg.q.computeds);
|
|
4598
|
-
pushQueryValueImmutable(q, "join", {
|
|
4589
|
+
orchidCore.pushQueryValueImmutable(q, "join", {
|
|
4599
4590
|
type: `${type} LATERAL`,
|
|
4600
4591
|
args: { l: arg, a: as, i: innerJoinLateral }
|
|
4601
4592
|
});
|
|
@@ -4986,7 +4977,7 @@ const applyComputedColumns = (q, fn) => {
|
|
|
4986
4977
|
const { data } = col;
|
|
4987
4978
|
data.computed = item;
|
|
4988
4979
|
data.explicitSelect = true;
|
|
4989
|
-
data.
|
|
4980
|
+
data.readOnly = true;
|
|
4990
4981
|
addColumnParserToQuery(
|
|
4991
4982
|
q.q,
|
|
4992
4983
|
key,
|
|
@@ -5800,7 +5791,7 @@ const addParserForSelectItem = (q, as, key, arg, columnAlias, joinQuery) => {
|
|
|
5800
5791
|
);
|
|
5801
5792
|
}
|
|
5802
5793
|
if (query.hookSelect || query.parsers || query.transform) {
|
|
5803
|
-
pushQueryValueImmutable(q, "batchParsers", {
|
|
5794
|
+
orchidCore.pushQueryValueImmutable(q, "batchParsers", {
|
|
5804
5795
|
path: [key],
|
|
5805
5796
|
fn: (path, queryResult) => {
|
|
5806
5797
|
const { rows } = queryResult;
|
|
@@ -6240,6 +6231,8 @@ function _querySelect(q, args) {
|
|
|
6240
6231
|
q.q.returnType = q.q.returningMany ? "all" : "oneOrThrow";
|
|
6241
6232
|
} else if (returnType === "value") {
|
|
6242
6233
|
q.q.returnType = q.q.returningMany ? "all" : "one";
|
|
6234
|
+
} else if (returnType === "void") {
|
|
6235
|
+
q.q.returnType = q.q.returningMany ? "all" : "oneOrThrow";
|
|
6243
6236
|
}
|
|
6244
6237
|
const len = args.length;
|
|
6245
6238
|
if (!len) {
|
|
@@ -6429,7 +6422,22 @@ const pushWithSql = (ctx, items) => {
|
|
|
6429
6422
|
};
|
|
6430
6423
|
|
|
6431
6424
|
const makeInsertSql = (ctx, q, query, quotedAs) => {
|
|
6432
|
-
|
|
6425
|
+
let { columns } = query;
|
|
6426
|
+
const { shape, inCTE, hookCreateSet } = query;
|
|
6427
|
+
const QueryClass = ctx.qb.constructor;
|
|
6428
|
+
let values = query.values;
|
|
6429
|
+
let hookSetSql;
|
|
6430
|
+
if (hookCreateSet) {
|
|
6431
|
+
({ hookSetSql, columns, values } = processHookSet(
|
|
6432
|
+
ctx,
|
|
6433
|
+
q,
|
|
6434
|
+
values,
|
|
6435
|
+
hookCreateSet,
|
|
6436
|
+
columns,
|
|
6437
|
+
QueryClass,
|
|
6438
|
+
quotedAs
|
|
6439
|
+
));
|
|
6440
|
+
}
|
|
6433
6441
|
const quotedColumns = columns.map(
|
|
6434
6442
|
(column) => `"${shape[column]?.data.name || column}"`
|
|
6435
6443
|
);
|
|
@@ -6444,7 +6452,6 @@ const makeInsertSql = (ctx, q, query, quotedAs) => {
|
|
|
6444
6452
|
}
|
|
6445
6453
|
}
|
|
6446
6454
|
}
|
|
6447
|
-
let values = query.values;
|
|
6448
6455
|
if (quotedColumns.length === 0) {
|
|
6449
6456
|
const key = Object.keys(q.shape)[0];
|
|
6450
6457
|
if (key) {
|
|
@@ -6456,12 +6463,11 @@ const makeInsertSql = (ctx, q, query, quotedAs) => {
|
|
|
6456
6463
|
}
|
|
6457
6464
|
}
|
|
6458
6465
|
const insertSql = `INSERT INTO ${quotedAs}${quotedColumns.length ? "(" + quotedColumns.join(", ") + ")" : ""}`;
|
|
6459
|
-
if (
|
|
6466
|
+
if ("from" in values && query.insertWith) {
|
|
6460
6467
|
pushWithSql(ctx, Object.values(query.insertWith).flat());
|
|
6461
6468
|
}
|
|
6462
6469
|
const valuesPos = ctx.sql.length + 1;
|
|
6463
6470
|
ctx.sql.push(insertSql, null);
|
|
6464
|
-
const QueryClass = ctx.qb.constructor;
|
|
6465
6471
|
if (query.onConflict) {
|
|
6466
6472
|
ctx.sql.push("ON CONFLICT");
|
|
6467
6473
|
const { target } = query.onConflict;
|
|
@@ -6525,7 +6531,28 @@ const makeInsertSql = (ctx, q, query, quotedAs) => {
|
|
|
6525
6531
|
returning = makeReturningSql(ctx, q, query, quotedAs, 2);
|
|
6526
6532
|
}
|
|
6527
6533
|
if (returning.select) ctx.sql.push("RETURNING", returning.select);
|
|
6528
|
-
if (
|
|
6534
|
+
if ("from" in values) {
|
|
6535
|
+
const { from, values: v } = values;
|
|
6536
|
+
const q2 = from.clone();
|
|
6537
|
+
if (v) {
|
|
6538
|
+
orchidCore.pushQueryValueImmutable(
|
|
6539
|
+
q2,
|
|
6540
|
+
"select",
|
|
6541
|
+
new RawSQL(
|
|
6542
|
+
encodeRow(
|
|
6543
|
+
ctx,
|
|
6544
|
+
ctx.values,
|
|
6545
|
+
q2,
|
|
6546
|
+
QueryClass,
|
|
6547
|
+
v,
|
|
6548
|
+
runtimeDefaults,
|
|
6549
|
+
quotedAs
|
|
6550
|
+
)
|
|
6551
|
+
)
|
|
6552
|
+
);
|
|
6553
|
+
}
|
|
6554
|
+
ctx.sql[valuesPos] = getSqlText(toSQL(q2, { values: ctx.values }));
|
|
6555
|
+
} else {
|
|
6529
6556
|
const valuesSql = [];
|
|
6530
6557
|
let ctxValues = ctx.values;
|
|
6531
6558
|
const restValuesLen = ctxValues.length;
|
|
@@ -6546,7 +6573,8 @@ const makeInsertSql = (ctx, q, query, quotedAs) => {
|
|
|
6546
6573
|
QueryClass,
|
|
6547
6574
|
values[i],
|
|
6548
6575
|
runtimeDefaults,
|
|
6549
|
-
quotedAs
|
|
6576
|
+
quotedAs,
|
|
6577
|
+
hookSetSql
|
|
6550
6578
|
);
|
|
6551
6579
|
if (!inCTE) encodedRow = "(" + encodedRow + ")";
|
|
6552
6580
|
if (ctxValues.length > MAX_BINDING_PARAMS) {
|
|
@@ -6595,32 +6623,127 @@ const makeInsertSql = (ctx, q, query, quotedAs) => {
|
|
|
6595
6623
|
if (inCTE) {
|
|
6596
6624
|
ctx.sql[valuesPos] += ' WHERE NOT EXISTS (SELECT 1 FROM "f")';
|
|
6597
6625
|
}
|
|
6598
|
-
}
|
|
6599
|
-
|
|
6600
|
-
|
|
6601
|
-
|
|
6602
|
-
|
|
6603
|
-
|
|
6604
|
-
|
|
6605
|
-
|
|
6606
|
-
|
|
6626
|
+
}
|
|
6627
|
+
return {
|
|
6628
|
+
hookSelect: returning.hookSelect,
|
|
6629
|
+
text: ctx.sql.join(" "),
|
|
6630
|
+
values: ctx.values
|
|
6631
|
+
};
|
|
6632
|
+
};
|
|
6633
|
+
const processHookSet = (ctx, q, values, hookCreateSet, columns, QueryClass, quotedAs) => {
|
|
6634
|
+
const hookSet = {};
|
|
6635
|
+
for (const item of hookCreateSet) {
|
|
6636
|
+
Object.assign(hookSet, item);
|
|
6637
|
+
}
|
|
6638
|
+
const addHookSetColumns = Object.keys(hookSet).filter(
|
|
6639
|
+
(key) => !columns.includes(key)
|
|
6640
|
+
);
|
|
6641
|
+
if ("from" in values) {
|
|
6642
|
+
const v = { ...values };
|
|
6643
|
+
const newColumns = [];
|
|
6644
|
+
const originalSelect = v.from.q.select;
|
|
6645
|
+
if (originalSelect) {
|
|
6646
|
+
v.from = _clone(v.from);
|
|
6647
|
+
const select = [];
|
|
6648
|
+
for (const s of originalSelect) {
|
|
6649
|
+
if (typeof s === "string" && !hookSet[s]) {
|
|
6650
|
+
select.push(s);
|
|
6651
|
+
newColumns.push(s);
|
|
6652
|
+
} else if (typeof s === "object" && "selectAs" in s) {
|
|
6653
|
+
const filtered = {};
|
|
6654
|
+
for (const key in s.selectAs) {
|
|
6655
|
+
if (!hookSet[key]) {
|
|
6656
|
+
filtered[key] = s.selectAs[key];
|
|
6657
|
+
newColumns.push(key);
|
|
6658
|
+
}
|
|
6659
|
+
}
|
|
6660
|
+
select.push({ selectAs: filtered });
|
|
6661
|
+
}
|
|
6662
|
+
}
|
|
6663
|
+
v.from.q.select = select;
|
|
6664
|
+
}
|
|
6665
|
+
let row;
|
|
6666
|
+
if (v.values) {
|
|
6667
|
+
const originalRow = v.values;
|
|
6668
|
+
const valuesColumns = columns.slice(-originalRow.length);
|
|
6669
|
+
row = [];
|
|
6670
|
+
valuesColumns.forEach((c, i) => {
|
|
6671
|
+
if (!hookSet[c]) {
|
|
6672
|
+
newColumns.push(c);
|
|
6673
|
+
row.push(originalRow[i]);
|
|
6674
|
+
}
|
|
6675
|
+
});
|
|
6676
|
+
} else {
|
|
6677
|
+
row = [];
|
|
6678
|
+
}
|
|
6679
|
+
v.values = row;
|
|
6680
|
+
columns.forEach((column) => {
|
|
6681
|
+
if (column in hookSet) {
|
|
6682
|
+
newColumns.push(column);
|
|
6683
|
+
const fromHook = {
|
|
6684
|
+
fromHook: encodeValue(
|
|
6607
6685
|
ctx,
|
|
6608
6686
|
ctx.values,
|
|
6609
|
-
|
|
6687
|
+
q,
|
|
6610
6688
|
QueryClass,
|
|
6611
|
-
|
|
6612
|
-
runtimeDefaults,
|
|
6689
|
+
hookSet[column],
|
|
6613
6690
|
quotedAs
|
|
6614
6691
|
)
|
|
6615
|
-
|
|
6616
|
-
|
|
6692
|
+
};
|
|
6693
|
+
row.push(fromHook);
|
|
6694
|
+
}
|
|
6695
|
+
});
|
|
6696
|
+
if (addHookSetColumns) {
|
|
6697
|
+
for (const key of addHookSetColumns) {
|
|
6698
|
+
row.push({
|
|
6699
|
+
fromHook: encodeValue(
|
|
6700
|
+
ctx,
|
|
6701
|
+
ctx.values,
|
|
6702
|
+
q,
|
|
6703
|
+
QueryClass,
|
|
6704
|
+
hookSet[key],
|
|
6705
|
+
quotedAs
|
|
6706
|
+
)
|
|
6707
|
+
});
|
|
6708
|
+
}
|
|
6709
|
+
return {
|
|
6710
|
+
columns: [...newColumns, ...addHookSetColumns],
|
|
6711
|
+
values: v
|
|
6712
|
+
};
|
|
6617
6713
|
}
|
|
6618
|
-
|
|
6714
|
+
return { columns: newColumns, values: v };
|
|
6619
6715
|
}
|
|
6716
|
+
columns.forEach((column, i) => {
|
|
6717
|
+
if (column in hookSet) {
|
|
6718
|
+
const fromHook = {
|
|
6719
|
+
fromHook: encodeValue(
|
|
6720
|
+
ctx,
|
|
6721
|
+
ctx.values,
|
|
6722
|
+
q,
|
|
6723
|
+
QueryClass,
|
|
6724
|
+
hookSet[column],
|
|
6725
|
+
quotedAs
|
|
6726
|
+
)
|
|
6727
|
+
};
|
|
6728
|
+
for (const row of values) {
|
|
6729
|
+
row[i] = fromHook;
|
|
6730
|
+
}
|
|
6731
|
+
}
|
|
6732
|
+
});
|
|
6733
|
+
const hookSetSql = addHookSetColumns.map(
|
|
6734
|
+
(key) => encodeValue(
|
|
6735
|
+
ctx,
|
|
6736
|
+
ctx.values,
|
|
6737
|
+
q,
|
|
6738
|
+
QueryClass,
|
|
6739
|
+
hookSet[key],
|
|
6740
|
+
quotedAs
|
|
6741
|
+
)
|
|
6742
|
+
).join(", ");
|
|
6620
6743
|
return {
|
|
6621
|
-
|
|
6622
|
-
|
|
6623
|
-
values
|
|
6744
|
+
hookSetSql,
|
|
6745
|
+
columns: addHookSetColumns ? [...columns, ...addHookSetColumns] : columns,
|
|
6746
|
+
values
|
|
6624
6747
|
};
|
|
6625
6748
|
};
|
|
6626
6749
|
const mergeColumnsSql = (columns, quotedColumns, target, except) => {
|
|
@@ -6644,24 +6767,30 @@ const mergeColumnsSql = (columns, quotedColumns, target, except) => {
|
|
|
6644
6767
|
`DO UPDATE SET ${quotedColumns[0]} = excluded.${quotedColumns[0]}`
|
|
6645
6768
|
);
|
|
6646
6769
|
};
|
|
6647
|
-
const encodeRow = (ctx, values, q, QueryClass, row, runtimeDefaults, quotedAs) => {
|
|
6648
|
-
const arr = row.map(
|
|
6649
|
-
|
|
6650
|
-
|
|
6651
|
-
return value.toSQL(ctx, quotedAs);
|
|
6652
|
-
} else if (value instanceof QueryClass) {
|
|
6653
|
-
return `(${getSqlText(joinSubQuery(q, value).toSQL(ctx))})`;
|
|
6654
|
-
}
|
|
6655
|
-
}
|
|
6656
|
-
return value === void 0 ? "DEFAULT" : orchidCore.addValue(values, value);
|
|
6657
|
-
});
|
|
6770
|
+
const encodeRow = (ctx, values, q, QueryClass, row, runtimeDefaults, quotedAs, hookSetSql) => {
|
|
6771
|
+
const arr = row.map(
|
|
6772
|
+
(value) => encodeValue(ctx, values, q, QueryClass, value, quotedAs)
|
|
6773
|
+
);
|
|
6658
6774
|
if (runtimeDefaults) {
|
|
6659
6775
|
for (const fn of runtimeDefaults) {
|
|
6660
6776
|
arr.push(orchidCore.addValue(values, fn()));
|
|
6661
6777
|
}
|
|
6662
6778
|
}
|
|
6779
|
+
if (hookSetSql) arr.push(hookSetSql);
|
|
6663
6780
|
return arr.join(", ");
|
|
6664
6781
|
};
|
|
6782
|
+
const encodeValue = (ctx, values, q, QueryClass, value, quotedAs) => {
|
|
6783
|
+
if (value && typeof value === "object") {
|
|
6784
|
+
if (value instanceof orchidCore.Expression) {
|
|
6785
|
+
return value.toSQL(ctx, quotedAs);
|
|
6786
|
+
} else if (value instanceof QueryClass) {
|
|
6787
|
+
return `(${getSqlText(joinSubQuery(q, value).toSQL(ctx))})`;
|
|
6788
|
+
} else if ("fromHook" in value) {
|
|
6789
|
+
return value.fromHook;
|
|
6790
|
+
}
|
|
6791
|
+
}
|
|
6792
|
+
return value === void 0 ? "DEFAULT" : orchidCore.addValue(values, value);
|
|
6793
|
+
};
|
|
6665
6794
|
const hookSelectKeys = [
|
|
6666
6795
|
null,
|
|
6667
6796
|
"afterUpdateSelect",
|
|
@@ -7240,8 +7369,20 @@ const pushUpdateSql = (ctx, table, query, quotedAs) => {
|
|
|
7240
7369
|
query.schema,
|
|
7241
7370
|
table.table || query.from
|
|
7242
7371
|
);
|
|
7372
|
+
let hookSet;
|
|
7373
|
+
if (query.hookUpdateSet) {
|
|
7374
|
+
hookSet = {};
|
|
7375
|
+
for (const item of query.hookUpdateSet) {
|
|
7376
|
+
Object.assign(hookSet, item);
|
|
7377
|
+
}
|
|
7378
|
+
} else {
|
|
7379
|
+
hookSet = orchidCore.emptyObject;
|
|
7380
|
+
}
|
|
7243
7381
|
const set = [];
|
|
7244
|
-
processData(ctx, table, set, query.updateData, quotedAs);
|
|
7382
|
+
processData(ctx, table, set, query.updateData, hookSet, quotedAs);
|
|
7383
|
+
if (query.hookUpdateSet) {
|
|
7384
|
+
applySet(ctx, table, set, hookSet, orchidCore.emptyObject, quotedAs);
|
|
7385
|
+
}
|
|
7245
7386
|
if (!set.length) {
|
|
7246
7387
|
if (!query.select) {
|
|
7247
7388
|
query.select = countSelect;
|
|
@@ -7281,32 +7422,35 @@ const pushUpdateReturning = (ctx, table, query, quotedAs, keyword) => {
|
|
|
7281
7422
|
if (s) ctx.sql.push(keyword, s);
|
|
7282
7423
|
return hookSelect;
|
|
7283
7424
|
};
|
|
7284
|
-
const processData = (ctx, table, set, data, quotedAs) => {
|
|
7425
|
+
const processData = (ctx, table, set, data, hookSet, quotedAs) => {
|
|
7285
7426
|
let append;
|
|
7286
|
-
const QueryClass = ctx.qb.constructor;
|
|
7287
7427
|
for (const item of data) {
|
|
7288
7428
|
if (typeof item === "function") {
|
|
7289
7429
|
const result = item(data);
|
|
7290
7430
|
if (result) append = orchidCore.pushOrNewArray(append, result);
|
|
7291
7431
|
} else {
|
|
7292
|
-
|
|
7293
|
-
for (const key in item) {
|
|
7294
|
-
const value = item[key];
|
|
7295
|
-
if (value === void 0) continue;
|
|
7296
|
-
set.push(
|
|
7297
|
-
`"${shape[key].data.name || key}" = ${processValue(
|
|
7298
|
-
ctx,
|
|
7299
|
-
table,
|
|
7300
|
-
QueryClass,
|
|
7301
|
-
key,
|
|
7302
|
-
value,
|
|
7303
|
-
quotedAs
|
|
7304
|
-
)}`
|
|
7305
|
-
);
|
|
7306
|
-
}
|
|
7432
|
+
applySet(ctx, table, set, item, hookSet, quotedAs);
|
|
7307
7433
|
}
|
|
7308
7434
|
}
|
|
7309
|
-
if (append) processData(ctx, table, set, append, quotedAs);
|
|
7435
|
+
if (append) processData(ctx, table, set, append, hookSet, quotedAs);
|
|
7436
|
+
};
|
|
7437
|
+
const applySet = (ctx, table, set, item, hookSet, quotedAs) => {
|
|
7438
|
+
const QueryClass = ctx.qb.constructor;
|
|
7439
|
+
const shape = table.q.shape;
|
|
7440
|
+
for (const key in item) {
|
|
7441
|
+
const value = item[key];
|
|
7442
|
+
if (value === void 0 || key in hookSet) continue;
|
|
7443
|
+
set.push(
|
|
7444
|
+
`"${shape[key].data.name || key}" = ${processValue(
|
|
7445
|
+
ctx,
|
|
7446
|
+
table,
|
|
7447
|
+
QueryClass,
|
|
7448
|
+
key,
|
|
7449
|
+
value,
|
|
7450
|
+
quotedAs
|
|
7451
|
+
)}`
|
|
7452
|
+
);
|
|
7453
|
+
}
|
|
7310
7454
|
};
|
|
7311
7455
|
const processValue = (ctx, table, QueryClass, key, value, quotedAs) => {
|
|
7312
7456
|
if (value && typeof value === "object") {
|
|
@@ -8649,7 +8793,7 @@ class WithMethods {
|
|
|
8649
8793
|
withSql(name, ...args) {
|
|
8650
8794
|
const q = _clone(this);
|
|
8651
8795
|
const [options, shape, sql] = args.length === 2 ? [void 0, args[0], args[1]] : args;
|
|
8652
|
-
pushQueryValueImmutable(q, "with", {
|
|
8796
|
+
orchidCore.pushQueryValueImmutable(q, "with", {
|
|
8653
8797
|
n: name,
|
|
8654
8798
|
o: options,
|
|
8655
8799
|
s: sql(q)
|
|
@@ -8672,36 +8816,48 @@ const processCreateItem = (q, item, rowIndex, ctx, encoders) => {
|
|
|
8672
8816
|
var _a;
|
|
8673
8817
|
const { shape } = q.q;
|
|
8674
8818
|
for (const key in item) {
|
|
8675
|
-
|
|
8676
|
-
|
|
8677
|
-
|
|
8678
|
-
|
|
8679
|
-
q,
|
|
8680
|
-
value
|
|
8681
|
-
);
|
|
8682
|
-
if (value && typeof value === "object" && value instanceof Db) {
|
|
8683
|
-
moveQueryValueToWith(
|
|
8684
|
-
q,
|
|
8685
|
-
(_a = q.q).insertWith ?? (_a.insertWith = {}),
|
|
8686
|
-
value,
|
|
8687
|
-
item,
|
|
8688
|
-
key,
|
|
8689
|
-
rowIndex
|
|
8690
|
-
);
|
|
8691
|
-
}
|
|
8692
|
-
}
|
|
8693
|
-
if (!ctx.columns.has(key) && (shape[key] && !shape[key].data.readonly || shape === anyShape) && value !== void 0) {
|
|
8694
|
-
ctx.columns.set(key, ctx.columns.size);
|
|
8695
|
-
encoders[key] = shape[key]?.data.encode;
|
|
8696
|
-
}
|
|
8697
|
-
} else if (shape[key] instanceof VirtualColumn) {
|
|
8698
|
-
shape[key].create?.(
|
|
8819
|
+
const column = shape[key];
|
|
8820
|
+
if (!column) continue;
|
|
8821
|
+
if (column.data.virtual) {
|
|
8822
|
+
column.create?.(
|
|
8699
8823
|
q,
|
|
8700
8824
|
ctx,
|
|
8701
8825
|
item,
|
|
8702
8826
|
rowIndex
|
|
8703
8827
|
);
|
|
8828
|
+
continue;
|
|
8704
8829
|
}
|
|
8830
|
+
throwOnReadOnly$1(q, column, key);
|
|
8831
|
+
let value = item[key];
|
|
8832
|
+
if (typeof value === "function") {
|
|
8833
|
+
value = item[key] = resolveSubQueryCallbackV2(
|
|
8834
|
+
q,
|
|
8835
|
+
value
|
|
8836
|
+
);
|
|
8837
|
+
if (value && typeof value === "object" && value instanceof Db) {
|
|
8838
|
+
moveQueryValueToWith(
|
|
8839
|
+
q,
|
|
8840
|
+
(_a = q.q).insertWith ?? (_a.insertWith = {}),
|
|
8841
|
+
value,
|
|
8842
|
+
item,
|
|
8843
|
+
key,
|
|
8844
|
+
rowIndex
|
|
8845
|
+
);
|
|
8846
|
+
}
|
|
8847
|
+
}
|
|
8848
|
+
if (!ctx.columns.has(key) && (column && !column.data.readOnly || shape === anyShape) && value !== void 0) {
|
|
8849
|
+
ctx.columns.set(key, ctx.columns.size);
|
|
8850
|
+
encoders[key] = column?.data.encode;
|
|
8851
|
+
}
|
|
8852
|
+
}
|
|
8853
|
+
};
|
|
8854
|
+
const throwOnReadOnly$1 = (q, column, key) => {
|
|
8855
|
+
if (column.data.appReadOnly || column.data.readOnly) {
|
|
8856
|
+
throw new OrchidOrmInternalError(
|
|
8857
|
+
q,
|
|
8858
|
+
"Trying to insert a readonly column",
|
|
8859
|
+
{ column: key }
|
|
8860
|
+
);
|
|
8705
8861
|
}
|
|
8706
8862
|
};
|
|
8707
8863
|
const createCtx = () => ({
|
|
@@ -8747,7 +8903,7 @@ const handleManyData = (q, data, ctx) => {
|
|
|
8747
8903
|
const insert = (self, {
|
|
8748
8904
|
columns,
|
|
8749
8905
|
values
|
|
8750
|
-
},
|
|
8906
|
+
}, many) => {
|
|
8751
8907
|
const { q } = self;
|
|
8752
8908
|
if (!q.select?.length) {
|
|
8753
8909
|
q.returning = true;
|
|
@@ -8758,7 +8914,6 @@ const insert = (self, {
|
|
|
8758
8914
|
q.type = "insert";
|
|
8759
8915
|
q.columns = columns;
|
|
8760
8916
|
q.values = values;
|
|
8761
|
-
if (!q.kind) q.kind = kind;
|
|
8762
8917
|
const { select, returnType } = q;
|
|
8763
8918
|
if (!select) {
|
|
8764
8919
|
if (returnType !== "void") {
|
|
@@ -8778,7 +8933,7 @@ const insert = (self, {
|
|
|
8778
8933
|
}
|
|
8779
8934
|
return self;
|
|
8780
8935
|
};
|
|
8781
|
-
const getFromSelectColumns = (from, obj, many) => {
|
|
8936
|
+
const getFromSelectColumns = (q, from, obj, many) => {
|
|
8782
8937
|
if (!many && !queryTypeWithLimitOne[from.q.returnType]) {
|
|
8783
8938
|
throw new Error(
|
|
8784
8939
|
"Cannot create based on a query which returns multiple records"
|
|
@@ -8796,19 +8951,22 @@ const getFromSelectColumns = (from, obj, many) => {
|
|
|
8796
8951
|
if (obj?.columns) {
|
|
8797
8952
|
queryColumns.push(...obj.columns);
|
|
8798
8953
|
}
|
|
8954
|
+
for (const key of queryColumns) {
|
|
8955
|
+
const column = q.shape[key];
|
|
8956
|
+
if (column) throwOnReadOnly$1(from, column, key);
|
|
8957
|
+
}
|
|
8799
8958
|
return queryColumns;
|
|
8800
8959
|
};
|
|
8801
8960
|
const insertFromQuery = (q, from, many, data) => {
|
|
8802
8961
|
const ctx = createCtx();
|
|
8803
8962
|
const obj = data && handleOneData(q, data, ctx);
|
|
8804
|
-
const columns = getFromSelectColumns(from, obj, many);
|
|
8963
|
+
const columns = getFromSelectColumns(q, from, obj, many);
|
|
8805
8964
|
return insert(
|
|
8806
8965
|
q,
|
|
8807
8966
|
{
|
|
8808
8967
|
columns,
|
|
8809
|
-
values: { from, values: obj?.values }
|
|
8968
|
+
values: { from, values: obj?.values[0] }
|
|
8810
8969
|
},
|
|
8811
|
-
"from",
|
|
8812
8970
|
many
|
|
8813
8971
|
);
|
|
8814
8972
|
};
|
|
@@ -8821,11 +8979,11 @@ const _queryInsert = (q, data) => {
|
|
|
8821
8979
|
const obj = handleOneData(q, data, ctx);
|
|
8822
8980
|
const values = q.q.values;
|
|
8823
8981
|
if (values && "from" in values) {
|
|
8824
|
-
obj.columns = getFromSelectColumns(values.from, obj);
|
|
8825
|
-
values.values = obj.values;
|
|
8982
|
+
obj.columns = getFromSelectColumns(q, values.from, obj);
|
|
8983
|
+
values.values = obj.values[0];
|
|
8826
8984
|
obj.values = values;
|
|
8827
8985
|
}
|
|
8828
|
-
return insert(q, obj
|
|
8986
|
+
return insert(q, obj);
|
|
8829
8987
|
};
|
|
8830
8988
|
const _queryCreateMany = (q, data) => {
|
|
8831
8989
|
createSelect(q);
|
|
@@ -8833,7 +8991,7 @@ const _queryCreateMany = (q, data) => {
|
|
|
8833
8991
|
};
|
|
8834
8992
|
const _queryInsertMany = (q, data) => {
|
|
8835
8993
|
const ctx = createCtx();
|
|
8836
|
-
let result = insert(q, handleManyData(q, data, ctx),
|
|
8994
|
+
let result = insert(q, handleManyData(q, data, ctx), true);
|
|
8837
8995
|
if (!data.length) result = result.none();
|
|
8838
8996
|
return result;
|
|
8839
8997
|
};
|
|
@@ -8855,7 +9013,7 @@ const _queryDefaults = (q, data) => {
|
|
|
8855
9013
|
q.q.defaults = data;
|
|
8856
9014
|
return q;
|
|
8857
9015
|
};
|
|
8858
|
-
class
|
|
9016
|
+
class QueryCreate {
|
|
8859
9017
|
/**
|
|
8860
9018
|
* `create` and `insert` create a single record.
|
|
8861
9019
|
*
|
|
@@ -9259,6 +9417,8 @@ class OnConflictQueryBuilder {
|
|
|
9259
9417
|
set(set) {
|
|
9260
9418
|
let resolved;
|
|
9261
9419
|
for (const key in set) {
|
|
9420
|
+
const column = this.query.shape[key];
|
|
9421
|
+
if (column) throwOnReadOnly$1(this.query, column, key);
|
|
9262
9422
|
if (typeof set[key] === "function") {
|
|
9263
9423
|
if (!resolved) resolved = { ...set };
|
|
9264
9424
|
resolved[key] = set[key]();
|
|
@@ -9528,7 +9688,7 @@ class Having {
|
|
|
9528
9688
|
*/
|
|
9529
9689
|
having(...args) {
|
|
9530
9690
|
const q = _clone(this);
|
|
9531
|
-
return pushQueryValueImmutable(
|
|
9691
|
+
return orchidCore.pushQueryValueImmutable(
|
|
9532
9692
|
q,
|
|
9533
9693
|
"having",
|
|
9534
9694
|
args.map((arg) => arg(q).q.expr)
|
|
@@ -9544,14 +9704,18 @@ class Having {
|
|
|
9544
9704
|
* @param args - SQL expression
|
|
9545
9705
|
*/
|
|
9546
9706
|
havingSql(...args) {
|
|
9547
|
-
return pushQueryValueImmutable(_clone(this), "having", args);
|
|
9707
|
+
return orchidCore.pushQueryValueImmutable(_clone(this), "having", args);
|
|
9548
9708
|
}
|
|
9549
9709
|
}
|
|
9550
9710
|
|
|
9551
|
-
const before = (q, key, cb) => pushQueryValueImmutable(q, `before${key}`, cb);
|
|
9711
|
+
const before = (q, key, cb) => orchidCore.pushQueryValueImmutable(q, `before${key}`, cb);
|
|
9552
9712
|
const after = (query, key, select, cb, commit) => {
|
|
9553
9713
|
const q = query;
|
|
9554
|
-
pushQueryValueImmutable(
|
|
9714
|
+
orchidCore.pushQueryValueImmutable(
|
|
9715
|
+
q,
|
|
9716
|
+
`after${key}${commit ? "Commit" : ""}`,
|
|
9717
|
+
cb
|
|
9718
|
+
);
|
|
9555
9719
|
const prop = `after${key}Select`;
|
|
9556
9720
|
const set = q.q[prop] = new Set(q.q[prop]);
|
|
9557
9721
|
for (const column of select) {
|
|
@@ -9560,13 +9724,19 @@ const after = (query, key, select, cb, commit) => {
|
|
|
9560
9724
|
return query;
|
|
9561
9725
|
};
|
|
9562
9726
|
const _queryHookBeforeQuery = (q, cb) => {
|
|
9563
|
-
return pushQueryValueImmutable(q, "before", cb);
|
|
9727
|
+
return orchidCore.pushQueryValueImmutable(q, "before", cb);
|
|
9564
9728
|
};
|
|
9565
9729
|
const _queryHookAfterQuery = (q, cb) => {
|
|
9566
|
-
return pushQueryValueImmutable(q, "after", cb);
|
|
9730
|
+
return orchidCore.pushQueryValueImmutable(q, "after", cb);
|
|
9567
9731
|
};
|
|
9568
9732
|
const _queryHookBeforeCreate = (q, cb) => {
|
|
9569
|
-
return before(
|
|
9733
|
+
return before(
|
|
9734
|
+
q,
|
|
9735
|
+
"Create",
|
|
9736
|
+
(q2) => cb(
|
|
9737
|
+
new orchidCore.QueryHookUtils(q2, q2.q.columns, "hookCreateSet")
|
|
9738
|
+
)
|
|
9739
|
+
);
|
|
9570
9740
|
};
|
|
9571
9741
|
const _queryHookAfterCreate = (q, select, cb) => {
|
|
9572
9742
|
return after(q, "Create", select, cb);
|
|
@@ -9575,7 +9745,15 @@ const _queryHookAfterCreateCommit = (q, select, cb) => {
|
|
|
9575
9745
|
return after(q, "Create", select, cb, true);
|
|
9576
9746
|
};
|
|
9577
9747
|
const _queryHookBeforeUpdate = (q, cb) => {
|
|
9578
|
-
return before(q, "Update",
|
|
9748
|
+
return before(q, "Update", (q2) => {
|
|
9749
|
+
const columns = [];
|
|
9750
|
+
for (const item of q2.q.updateData) {
|
|
9751
|
+
if (typeof item === "object") {
|
|
9752
|
+
columns.push(...Object.keys(item));
|
|
9753
|
+
}
|
|
9754
|
+
}
|
|
9755
|
+
return cb(new orchidCore.QueryHookUtils(q2, columns, "hookUpdateSet"));
|
|
9756
|
+
});
|
|
9579
9757
|
};
|
|
9580
9758
|
const _queryHookAfterUpdate = (q, select, cb) => {
|
|
9581
9759
|
return after(q, "Update", select, cb);
|
|
@@ -9584,7 +9762,7 @@ const _queryHookAfterUpdateCommit = (q, select, cb) => {
|
|
|
9584
9762
|
return after(q, "Update", select, cb, true);
|
|
9585
9763
|
};
|
|
9586
9764
|
const _queryHookBeforeSave = (q, cb) => {
|
|
9587
|
-
return
|
|
9765
|
+
return _queryHookBeforeUpdate(_queryHookBeforeCreate(q, cb), cb);
|
|
9588
9766
|
};
|
|
9589
9767
|
const _queryHookAfterSave = (q, select, cb) => {
|
|
9590
9768
|
return after(after(q, "Create", select, cb), "Update", select, cb);
|
|
@@ -9789,7 +9967,7 @@ class QueryHooks {
|
|
|
9789
9967
|
*/
|
|
9790
9968
|
catchAfterCommitError(fn) {
|
|
9791
9969
|
const q = _clone(this);
|
|
9792
|
-
pushQueryValueImmutable(q, "catchAfterCommitErrors", fn);
|
|
9970
|
+
orchidCore.pushQueryValueImmutable(q, "catchAfterCommitErrors", fn);
|
|
9793
9971
|
return q;
|
|
9794
9972
|
}
|
|
9795
9973
|
}
|
|
@@ -10471,7 +10649,7 @@ const makeOnItem = (joinTo, joinFrom, args) => ({
|
|
|
10471
10649
|
}
|
|
10472
10650
|
});
|
|
10473
10651
|
const pushQueryOnForOuter = (q, joinFrom, joinTo, leftColumn, rightColumn) => {
|
|
10474
|
-
return pushQueryValueImmutable(q, "and", {
|
|
10652
|
+
return orchidCore.pushQueryValueImmutable(q, "and", {
|
|
10475
10653
|
ON: {
|
|
10476
10654
|
joinFrom: joinTo,
|
|
10477
10655
|
from: leftColumn,
|
|
@@ -10482,14 +10660,14 @@ const pushQueryOnForOuter = (q, joinFrom, joinTo, leftColumn, rightColumn) => {
|
|
|
10482
10660
|
});
|
|
10483
10661
|
};
|
|
10484
10662
|
const pushQueryOn = (q, joinFrom, joinTo, ...on) => {
|
|
10485
|
-
return pushQueryValueImmutable(
|
|
10663
|
+
return orchidCore.pushQueryValueImmutable(
|
|
10486
10664
|
q,
|
|
10487
10665
|
"and",
|
|
10488
10666
|
makeOnItem(joinFrom, joinTo, on)
|
|
10489
10667
|
);
|
|
10490
10668
|
};
|
|
10491
10669
|
const pushQueryOrOn = (q, joinFrom, joinTo, ...on) => {
|
|
10492
|
-
return pushQueryValueImmutable(q, "or", [
|
|
10670
|
+
return orchidCore.pushQueryValueImmutable(q, "or", [
|
|
10493
10671
|
makeOnItem(joinFrom, joinTo, on)
|
|
10494
10672
|
]);
|
|
10495
10673
|
};
|
|
@@ -10521,7 +10699,7 @@ const _queryJoinOrOn = (q, args) => {
|
|
|
10521
10699
|
);
|
|
10522
10700
|
};
|
|
10523
10701
|
const _queryJoinOnJsonPathEquals = (q, args) => {
|
|
10524
|
-
return pushQueryValueImmutable(q, "and", {
|
|
10702
|
+
return orchidCore.pushQueryValueImmutable(q, "and", {
|
|
10525
10703
|
ON: args
|
|
10526
10704
|
});
|
|
10527
10705
|
};
|
|
@@ -10637,6 +10815,15 @@ class MergeQueryMethods {
|
|
|
10637
10815
|
}
|
|
10638
10816
|
}
|
|
10639
10817
|
|
|
10818
|
+
const throwOnReadOnly = (q, column, key) => {
|
|
10819
|
+
if (column.data.appReadOnly || column.data.readOnly) {
|
|
10820
|
+
throw new OrchidOrmInternalError(
|
|
10821
|
+
q,
|
|
10822
|
+
"Trying to update a readonly column",
|
|
10823
|
+
{ column: key }
|
|
10824
|
+
);
|
|
10825
|
+
}
|
|
10826
|
+
};
|
|
10640
10827
|
const _queryChangeCounter = (self, op, data) => {
|
|
10641
10828
|
const q = self.q;
|
|
10642
10829
|
q.type = "update";
|
|
@@ -10653,11 +10840,19 @@ const _queryChangeCounter = (self, op, data) => {
|
|
|
10653
10840
|
map = {};
|
|
10654
10841
|
for (const key in data) {
|
|
10655
10842
|
map[key] = { op, arg: data[key] };
|
|
10843
|
+
const column = self.shape[key];
|
|
10844
|
+
if (column) {
|
|
10845
|
+
throwOnReadOnly(self, column, key);
|
|
10846
|
+
}
|
|
10656
10847
|
}
|
|
10657
10848
|
} else {
|
|
10658
10849
|
map = { [data]: { op, arg: 1 } };
|
|
10850
|
+
const column = self.shape[data];
|
|
10851
|
+
if (column) {
|
|
10852
|
+
throwOnReadOnly(self, column, data);
|
|
10853
|
+
}
|
|
10659
10854
|
}
|
|
10660
|
-
pushQueryValueImmutable(self, "updateData", map);
|
|
10855
|
+
orchidCore.pushQueryValueImmutable(self, "updateData", map);
|
|
10661
10856
|
return self;
|
|
10662
10857
|
};
|
|
10663
10858
|
const update = (self) => {
|
|
@@ -10674,17 +10869,18 @@ const update = (self) => {
|
|
|
10674
10869
|
const _queryUpdate = (query, arg) => {
|
|
10675
10870
|
const { q } = query;
|
|
10676
10871
|
const set = { ...arg };
|
|
10677
|
-
pushQueryValueImmutable(query, "updateData", set);
|
|
10872
|
+
orchidCore.pushQueryValueImmutable(query, "updateData", set);
|
|
10678
10873
|
const { shape } = q;
|
|
10679
10874
|
const ctx = {};
|
|
10680
10875
|
for (const key in arg) {
|
|
10681
10876
|
const item = shape[key];
|
|
10682
|
-
if (item
|
|
10683
|
-
item.update(query, ctx, set);
|
|
10877
|
+
if (!item && shape !== anyShape) {
|
|
10684
10878
|
delete set[key];
|
|
10685
|
-
} else if (
|
|
10879
|
+
} else if (item.data.virtual) {
|
|
10880
|
+
item.update?.(query, ctx, set);
|
|
10686
10881
|
delete set[key];
|
|
10687
10882
|
} else {
|
|
10883
|
+
if (item) throwOnReadOnly(query, item, key);
|
|
10688
10884
|
let value = set[key];
|
|
10689
10885
|
if (typeof value === "function") {
|
|
10690
10886
|
value = resolveSubQueryCallbackV2(
|
|
@@ -10710,7 +10906,7 @@ const _queryUpdate = (query, arg) => {
|
|
|
10710
10906
|
"with"
|
|
10711
10907
|
);
|
|
10712
10908
|
} else {
|
|
10713
|
-
const encode =
|
|
10909
|
+
const encode = item?.data.encode;
|
|
10714
10910
|
if (encode) set[key] = encode(value);
|
|
10715
10911
|
}
|
|
10716
10912
|
}
|
|
@@ -11288,9 +11484,9 @@ class SearchMethods {
|
|
|
11288
11484
|
}
|
|
11289
11485
|
setQueryObjectValueImmutable(q, "sources", arg.as, arg);
|
|
11290
11486
|
if (arg.order) {
|
|
11291
|
-
pushQueryValueImmutable(q, "order", arg.as);
|
|
11487
|
+
orchidCore.pushQueryValueImmutable(q, "order", arg.as);
|
|
11292
11488
|
}
|
|
11293
|
-
return pushQueryValueImmutable(q, "and", { SEARCH: arg });
|
|
11489
|
+
return orchidCore.pushQueryValueImmutable(q, "and", { SEARCH: arg });
|
|
11294
11490
|
}
|
|
11295
11491
|
}
|
|
11296
11492
|
|
|
@@ -11358,7 +11554,7 @@ function orCreate(query, data, updateData, mergeData) {
|
|
|
11358
11554
|
q22.q.log = q2.q.log;
|
|
11359
11555
|
q22.q.logger = q2.q.logger;
|
|
11360
11556
|
q22.q.type = "upsert";
|
|
11361
|
-
q22.q.beforeCreate = q2.q.beforeCreate;
|
|
11557
|
+
q22.q.beforeCreate = q2.q.beforeCreate?.map((cb) => () => cb(c));
|
|
11362
11558
|
if (hasAfterCallback) {
|
|
11363
11559
|
((_a = q22.q).afterCreate ?? (_a.afterCreate = [])).push(
|
|
11364
11560
|
(data2, query2) => afterHooks && Promise.all([...afterHooks].map((fn) => fn(data2, query2)))
|
|
@@ -11380,109 +11576,13 @@ function orCreate(query, data, updateData, mergeData) {
|
|
|
11380
11576
|
};
|
|
11381
11577
|
return query;
|
|
11382
11578
|
}
|
|
11383
|
-
|
|
11384
|
-
|
|
11385
|
-
|
|
11386
|
-
|
|
11387
|
-
|
|
11388
|
-
|
|
11389
|
-
|
|
11390
|
-
*
|
|
11391
|
-
* It can take `update` and `create` objects, then they are used separately for update and create queries.
|
|
11392
|
-
* Or, it can take `data` and `create` objects, `data` will be used for update and be mixed to `create` object.
|
|
11393
|
-
*
|
|
11394
|
-
* `data` and `update` objects are of the same type that's expected by `update` method, `create` object is of type of `create` method argument.
|
|
11395
|
-
*
|
|
11396
|
-
* No values are returned by default, place `select` or `selectAll` before `upsert` to specify returning columns.
|
|
11397
|
-
*
|
|
11398
|
-
* ```ts
|
|
11399
|
-
* await User.selectAll()
|
|
11400
|
-
* .findBy({ email: 'some@email.com' })
|
|
11401
|
-
* .upsert({
|
|
11402
|
-
* data: {
|
|
11403
|
-
* // update record's name
|
|
11404
|
-
* name: 'new name',
|
|
11405
|
-
* // supports sql and nested queries
|
|
11406
|
-
* fromSQL: () => sql`*SQL expression*`,
|
|
11407
|
-
* fromQuery: () => db.someTable.create(data).get('column'),
|
|
11408
|
-
* },
|
|
11409
|
-
* create: {
|
|
11410
|
-
* // create a new record with this email and a name 'new name'
|
|
11411
|
-
* email: 'some@email.com',
|
|
11412
|
-
* // supports sql and nested queries as well
|
|
11413
|
-
* },
|
|
11414
|
-
* create: {
|
|
11415
|
-
* // create a new record with this email and a name 'new name'
|
|
11416
|
-
* email: 'some@email.com',
|
|
11417
|
-
* },
|
|
11418
|
-
* });
|
|
11419
|
-
*
|
|
11420
|
-
* // the same as above but using `update` and `create`
|
|
11421
|
-
* await User.selectAll()
|
|
11422
|
-
* .findBy({ email: 'some@email.com' })
|
|
11423
|
-
* .upsert({
|
|
11424
|
-
* update: {
|
|
11425
|
-
* name: 'updated user',
|
|
11426
|
-
* },
|
|
11427
|
-
* create: {
|
|
11428
|
-
* email: 'some@email.com',
|
|
11429
|
-
* // here we use a different name when creating a record
|
|
11430
|
-
* name: 'created user',
|
|
11431
|
-
* },
|
|
11432
|
-
* });
|
|
11433
|
-
* ```
|
|
11434
|
-
*
|
|
11435
|
-
* The data for `create` may be returned from a function, it won't be called if a record was updated:
|
|
11436
|
-
*
|
|
11437
|
-
* ```ts
|
|
11438
|
-
* await User.selectAll()
|
|
11439
|
-
* .findBy({ email: 'some@email.com' })
|
|
11440
|
-
* .upsert({
|
|
11441
|
-
* update: {
|
|
11442
|
-
* name: 'updated user',
|
|
11443
|
-
* },
|
|
11444
|
-
* create: () => ({
|
|
11445
|
-
* email: 'some@email.com',
|
|
11446
|
-
* name: 'created user',
|
|
11447
|
-
* }),
|
|
11448
|
-
* });
|
|
11449
|
-
*
|
|
11450
|
-
* // the same as above using `data`
|
|
11451
|
-
* await User.selectAll()
|
|
11452
|
-
* .findBy({ email: 'some@email.com' })
|
|
11453
|
-
* .upsert({
|
|
11454
|
-
* data: {
|
|
11455
|
-
* name: 'updated user',
|
|
11456
|
-
* },
|
|
11457
|
-
* create: () => ({
|
|
11458
|
-
* email: 'some@email.com',
|
|
11459
|
-
* // name in `create` is overriding the name from `data`
|
|
11460
|
-
* name: 'created user',
|
|
11461
|
-
* }),
|
|
11462
|
-
* });
|
|
11463
|
-
* ```
|
|
11464
|
-
*
|
|
11465
|
-
* Data from `data` or `update` is passed to the `create` function and can be used:
|
|
11466
|
-
*
|
|
11467
|
-
* ```ts
|
|
11468
|
-
* const user = await User.selectAll()
|
|
11469
|
-
* .findBy({ email: 'some@email.com' })
|
|
11470
|
-
* .upsert({
|
|
11471
|
-
* data: {
|
|
11472
|
-
* name: 'updated user',
|
|
11473
|
-
* },
|
|
11474
|
-
* // `updateData` has the exact type of what is passed to `data`
|
|
11475
|
-
* create: (updateData) => ({
|
|
11476
|
-
* email: `${updateData.name}@email.com`,
|
|
11477
|
-
* }),
|
|
11478
|
-
* });
|
|
11479
|
-
* ```
|
|
11480
|
-
*
|
|
11481
|
-
* `upsert` works in the exact same way as [orCreate](#orCreate), but with `UPDATE` statement instead of `SELECT`.
|
|
11482
|
-
* it also performs a single query if the record exists, and two queries if there is no record yet.
|
|
11483
|
-
*
|
|
11484
|
-
* @param data - `update` property for the data to update, `create` property for the data to create
|
|
11485
|
-
*/
|
|
11579
|
+
const QueryOrCreate = {
|
|
11580
|
+
orCreate(data) {
|
|
11581
|
+
return orCreate(_clone(this), data);
|
|
11582
|
+
}
|
|
11583
|
+
};
|
|
11584
|
+
|
|
11585
|
+
const QueryUpsert = {
|
|
11486
11586
|
upsert(data) {
|
|
11487
11587
|
const q = _clone(this);
|
|
11488
11588
|
let updateData;
|
|
@@ -11497,75 +11597,7 @@ class QueryUpsertOrCreate {
|
|
|
11497
11597
|
}
|
|
11498
11598
|
return orCreate(q, data.create, updateData, mergeData);
|
|
11499
11599
|
}
|
|
11500
|
-
|
|
11501
|
-
* `orCreate` creates a record only if it was not found by conditions.
|
|
11502
|
-
*
|
|
11503
|
-
* `find` or `findBy` must precede `orCreate`.
|
|
11504
|
-
*
|
|
11505
|
-
* It is accepting the same argument as `create` commands.
|
|
11506
|
-
*
|
|
11507
|
-
* No result is returned by default, place `get`, `select`, or `selectAll` before `orCreate` to specify returning columns.
|
|
11508
|
-
*
|
|
11509
|
-
* ```ts
|
|
11510
|
-
* const user = await db.user
|
|
11511
|
-
* .selectAll()
|
|
11512
|
-
* .findBy({ email: 'some@email.com' })
|
|
11513
|
-
* .orCreate({
|
|
11514
|
-
* email: 'some@email.com',
|
|
11515
|
-
* name: 'created user',
|
|
11516
|
-
* // supports sql and nested queries
|
|
11517
|
-
* fromSQL: () => sql`*SQL expression*`,
|
|
11518
|
-
* fromQuery: () => db.someTable.create(data).get('column'),
|
|
11519
|
-
* fromRelated: (q) => q.relatedTable.update(data).get('column'),
|
|
11520
|
-
* });
|
|
11521
|
-
* ```
|
|
11522
|
-
*
|
|
11523
|
-
* The data can be returned from a function, it won't be called if the record was found:
|
|
11524
|
-
*
|
|
11525
|
-
* ```ts
|
|
11526
|
-
* const user = await User.selectAll()
|
|
11527
|
-
* .findBy({ email: 'some@email.com' })
|
|
11528
|
-
* .orCreate(() => ({
|
|
11529
|
-
* email: 'some@email.com',
|
|
11530
|
-
* name: 'created user',
|
|
11531
|
-
* }));
|
|
11532
|
-
* ```
|
|
11533
|
-
*
|
|
11534
|
-
* `orCreate` works by performing just a single query in the case if the record exists, and one additional query when the record does not exist.
|
|
11535
|
-
*
|
|
11536
|
-
* At first, it performs a "find" query, the query cost is exact same as if you didn't use `orCreate`.
|
|
11537
|
-
*
|
|
11538
|
-
* Then, if the record wasn't found, it performs a single query with CTE expressions to try finding it again, for the case it was already created just a moment before,
|
|
11539
|
-
* and then it creates the record if it's still not found. Using such CTE allows to skip using transactions, while still conforming to atomicity.
|
|
11540
|
-
*
|
|
11541
|
-
* ```sql
|
|
11542
|
-
* -- first query
|
|
11543
|
-
* SELECT * FROM "table" WHERE "key" = 'value'
|
|
11544
|
-
*
|
|
11545
|
-
* -- the record could have been created in between these two queries
|
|
11546
|
-
*
|
|
11547
|
-
* -- second query
|
|
11548
|
-
* WITH find_row AS (
|
|
11549
|
-
* SELECT * FROM "table" WHERE "key" = 'value'
|
|
11550
|
-
* )
|
|
11551
|
-
* WITH insert_row AS (
|
|
11552
|
-
* INSERT INTO "table" ("key")
|
|
11553
|
-
* SELECT 'value'
|
|
11554
|
-
* -- skip the insert if the row already exists
|
|
11555
|
-
* WHERE NOT EXISTS (SELECT 1 FROM find_row)
|
|
11556
|
-
* RETURNING *
|
|
11557
|
-
* )
|
|
11558
|
-
* SELECT * FROM find_row
|
|
11559
|
-
* UNION ALL
|
|
11560
|
-
* SELECT * FROM insert_row
|
|
11561
|
-
* ```
|
|
11562
|
-
*
|
|
11563
|
-
* @param data - the same data as for `create`, it may be returned from a callback
|
|
11564
|
-
*/
|
|
11565
|
-
orCreate(data) {
|
|
11566
|
-
return orCreate(_clone(this), data);
|
|
11567
|
-
}
|
|
11568
|
-
}
|
|
11600
|
+
};
|
|
11569
11601
|
|
|
11570
11602
|
class SqlMethod {
|
|
11571
11603
|
sql(...args) {
|
|
@@ -11630,7 +11662,7 @@ class TransformMethods {
|
|
|
11630
11662
|
* @param fn - function to transform query result with
|
|
11631
11663
|
*/
|
|
11632
11664
|
transform(fn) {
|
|
11633
|
-
return pushQueryValueImmutable(_clone(this), "transform", fn);
|
|
11665
|
+
return orchidCore.pushQueryValueImmutable(_clone(this), "transform", fn);
|
|
11634
11666
|
}
|
|
11635
11667
|
}
|
|
11636
11668
|
|
|
@@ -11676,7 +11708,7 @@ class QueryMap {
|
|
|
11676
11708
|
* @param fn - function to transform an individual record
|
|
11677
11709
|
*/
|
|
11678
11710
|
map(fn) {
|
|
11679
|
-
return pushQueryValueImmutable(_clone(this), "transform", {
|
|
11711
|
+
return orchidCore.pushQueryValueImmutable(_clone(this), "transform", {
|
|
11680
11712
|
map: fn
|
|
11681
11713
|
});
|
|
11682
11714
|
}
|
|
@@ -12305,7 +12337,7 @@ class QueryMethods {
|
|
|
12305
12337
|
* @param arg - window config
|
|
12306
12338
|
*/
|
|
12307
12339
|
window(arg) {
|
|
12308
|
-
return pushQueryValueImmutable(_clone(this), "window", arg);
|
|
12340
|
+
return orchidCore.pushQueryValueImmutable(_clone(this), "window", arg);
|
|
12309
12341
|
}
|
|
12310
12342
|
wrap(query, as) {
|
|
12311
12343
|
return queryWrap(this, _clone(query), as);
|
|
@@ -12360,7 +12392,7 @@ class QueryMethods {
|
|
|
12360
12392
|
* @param args - SQL expression
|
|
12361
12393
|
*/
|
|
12362
12394
|
orderSql(...args) {
|
|
12363
|
-
return pushQueryValueImmutable(
|
|
12395
|
+
return orchidCore.pushQueryValueImmutable(
|
|
12364
12396
|
_clone(this),
|
|
12365
12397
|
"order",
|
|
12366
12398
|
sqlQueryArgsToExpression(args)
|
|
@@ -12649,6 +12681,8 @@ class QueryMethods {
|
|
|
12649
12681
|
return _chain(this, _clone(rel.query), rel);
|
|
12650
12682
|
}
|
|
12651
12683
|
}
|
|
12684
|
+
Object.assign(QueryMethods.prototype, QueryUpsert);
|
|
12685
|
+
Object.assign(QueryMethods.prototype, QueryOrCreate);
|
|
12652
12686
|
orchidCore.applyMixins(QueryMethods, [
|
|
12653
12687
|
AsMethods,
|
|
12654
12688
|
AggregateMethods,
|
|
@@ -12659,7 +12693,7 @@ orchidCore.applyMixins(QueryMethods, [
|
|
|
12659
12693
|
WithMethods,
|
|
12660
12694
|
Union,
|
|
12661
12695
|
JsonMethods,
|
|
12662
|
-
|
|
12696
|
+
QueryCreate,
|
|
12663
12697
|
Update,
|
|
12664
12698
|
Delete,
|
|
12665
12699
|
Transaction,
|
|
@@ -12671,7 +12705,6 @@ orchidCore.applyMixins(QueryMethods, [
|
|
|
12671
12705
|
Then,
|
|
12672
12706
|
QueryLog,
|
|
12673
12707
|
QueryHooks,
|
|
12674
|
-
QueryUpsertOrCreate,
|
|
12675
12708
|
QueryGet,
|
|
12676
12709
|
MergeQueryMethods,
|
|
12677
12710
|
SqlMethod,
|
|
@@ -12847,6 +12880,7 @@ class Db extends QueryMethods {
|
|
|
12847
12880
|
let hasParsers = false;
|
|
12848
12881
|
let modifyQuery = void 0;
|
|
12849
12882
|
let prepareSelectAll = false;
|
|
12883
|
+
let hasHookSetters;
|
|
12850
12884
|
const { snakeCase } = options;
|
|
12851
12885
|
for (const key in shape) {
|
|
12852
12886
|
const column = shape[key];
|
|
@@ -12882,6 +12916,9 @@ class Db extends QueryMethods {
|
|
|
12882
12916
|
column.data.runtimeDefault = encode ? () => encode(def()) : def;
|
|
12883
12917
|
}
|
|
12884
12918
|
}
|
|
12919
|
+
if (column.data.setOnCreate || column.data.setOnUpdate || column.data.setOnSave) {
|
|
12920
|
+
hasHookSetters = true;
|
|
12921
|
+
}
|
|
12885
12922
|
}
|
|
12886
12923
|
this.q = {
|
|
12887
12924
|
adapter,
|
|
@@ -12956,6 +12993,27 @@ class Db extends QueryMethods {
|
|
|
12956
12993
|
if (softDelete) {
|
|
12957
12994
|
enableSoftDelete(this, table, shape, softDelete, scopes);
|
|
12958
12995
|
}
|
|
12996
|
+
if (hasHookSetters) {
|
|
12997
|
+
const hooks = {
|
|
12998
|
+
setOnCreate: _queryHookBeforeCreate,
|
|
12999
|
+
setOnUpdate: _queryHookBeforeUpdate,
|
|
13000
|
+
setOnSave: _queryHookBeforeSave
|
|
13001
|
+
};
|
|
13002
|
+
for (const key in shape) {
|
|
13003
|
+
const { data } = shape[key];
|
|
13004
|
+
for (const hookKey in hooks) {
|
|
13005
|
+
const fn = data[hookKey];
|
|
13006
|
+
if (fn) {
|
|
13007
|
+
hooks[hookKey](this, (arg) => {
|
|
13008
|
+
const value = fn(arg);
|
|
13009
|
+
if (value !== void 0) {
|
|
13010
|
+
arg.set({ [key]: value });
|
|
13011
|
+
}
|
|
13012
|
+
});
|
|
13013
|
+
}
|
|
13014
|
+
}
|
|
13015
|
+
}
|
|
13016
|
+
}
|
|
12959
13017
|
}
|
|
12960
13018
|
[node_util.inspect.custom]() {
|
|
12961
13019
|
return `Query<${this.table}>`;
|
|
@@ -13308,7 +13366,6 @@ exports.Clear = Clear;
|
|
|
13308
13366
|
exports.ColumnRefExpression = ColumnRefExpression;
|
|
13309
13367
|
exports.ColumnType = ColumnType;
|
|
13310
13368
|
exports.ComputedColumn = ComputedColumn;
|
|
13311
|
-
exports.Create = Create;
|
|
13312
13369
|
exports.CustomTypeColumn = CustomTypeColumn;
|
|
13313
13370
|
exports.DateBaseColumn = DateBaseColumn;
|
|
13314
13371
|
exports.DateColumn = DateColumn;
|
|
@@ -13355,12 +13412,13 @@ exports.PathColumn = PathColumn;
|
|
|
13355
13412
|
exports.PointColumn = PointColumn;
|
|
13356
13413
|
exports.PolygonColumn = PolygonColumn;
|
|
13357
13414
|
exports.PostgisGeographyPointColumn = PostgisGeographyPointColumn;
|
|
13415
|
+
exports.QueryCreate = QueryCreate;
|
|
13358
13416
|
exports.QueryError = QueryError;
|
|
13359
13417
|
exports.QueryGet = QueryGet;
|
|
13360
13418
|
exports.QueryHooks = QueryHooks;
|
|
13361
13419
|
exports.QueryLog = QueryLog;
|
|
13362
13420
|
exports.QueryMethods = QueryMethods;
|
|
13363
|
-
exports.
|
|
13421
|
+
exports.QueryUpsert = QueryUpsert;
|
|
13364
13422
|
exports.RawSQL = RawSQL;
|
|
13365
13423
|
exports.RealColumn = RealColumn;
|
|
13366
13424
|
exports.RefExpression = RefExpression;
|
|
@@ -13515,7 +13573,6 @@ exports.pushQueryArrayImmutable = pushQueryArrayImmutable;
|
|
|
13515
13573
|
exports.pushQueryOn = pushQueryOn;
|
|
13516
13574
|
exports.pushQueryOnForOuter = pushQueryOnForOuter;
|
|
13517
13575
|
exports.pushQueryOrOn = pushQueryOrOn;
|
|
13518
|
-
exports.pushQueryValueImmutable = pushQueryValueImmutable;
|
|
13519
13576
|
exports.pushTableDataCode = pushTableDataCode;
|
|
13520
13577
|
exports.queryFrom = queryFrom;
|
|
13521
13578
|
exports.queryFromSql = queryFromSql;
|