pqb 0.67.3 → 0.67.4
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 +22 -3
- package/dist/index.js +80 -19
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +80 -19
- package/dist/index.mjs.map +1 -1
- package/dist/internal.d.ts +44 -25
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -748,6 +748,15 @@ var Column = class {
|
|
|
748
748
|
return setColumnData(this, "explicitSelect", !value);
|
|
749
749
|
}
|
|
750
750
|
/**
|
|
751
|
+
* Set SQL to use when selecting this column.
|
|
752
|
+
*
|
|
753
|
+
* The column remains a regular writable database column. Create, update,
|
|
754
|
+
* filters, ordering, grouping, and migrations still use the physical column.
|
|
755
|
+
*/
|
|
756
|
+
selectSql(fn) {
|
|
757
|
+
return setColumnData(this, "selectSqlFn", fn);
|
|
758
|
+
}
|
|
759
|
+
/**
|
|
751
760
|
* Forbid the column to be used in [create](/guide/create-update-delete.html#create-insert) and [update](/guide/create-update-delete.html#update) methods.
|
|
752
761
|
*
|
|
753
762
|
* `readOnly` column is still can be set from a [hook](http://localhost:5173/guide/hooks.html#set-values-before-create-or-update).
|
|
@@ -3969,6 +3978,7 @@ const applyComputedColumns = (q, fn) => {
|
|
|
3969
3978
|
q.shape[key] = col;
|
|
3970
3979
|
const { data } = col;
|
|
3971
3980
|
data.computed = item;
|
|
3981
|
+
data.selectSql = item;
|
|
3972
3982
|
data.explicitSelect = true;
|
|
3973
3983
|
data.readOnly = true;
|
|
3974
3984
|
const parse = col._parse;
|
|
@@ -6504,6 +6514,15 @@ const columnToSql = (ctx, data, shape, column, quotedAs, select) => {
|
|
|
6504
6514
|
if (index !== -1) return columnWithDotToSql(ctx, data, shape, column, index, quotedAs, select);
|
|
6505
6515
|
return simpleColumnToSQL(ctx, column, shape[column], quotedAs);
|
|
6506
6516
|
};
|
|
6517
|
+
const selectedColumnToSql = (ctx, data, shape, column, quotedAs) => {
|
|
6518
|
+
const index = column.indexOf(".");
|
|
6519
|
+
return index !== -1 ? selectedColumnWithDotToSql(ctx, data, shape, column, index, quotedAs) : selectedSimpleColumnToSql(ctx, column, shape[column], quotedAs);
|
|
6520
|
+
};
|
|
6521
|
+
const selectedSimpleColumnToSql = (ctx, key, column, quotedAs) => {
|
|
6522
|
+
if (!column) return `"${key}"`;
|
|
6523
|
+
const { data } = column;
|
|
6524
|
+
return data.selectSql ? `(${data.selectSql.toSQL(ctx, quotedAs)})` : `${quotedAs ? `${quotedAs}.` : ""}"${data.name || key}"`;
|
|
6525
|
+
};
|
|
6507
6526
|
/**
|
|
6508
6527
|
* in a case when ordering or grouping by a column which was selected as expression:
|
|
6509
6528
|
* ```ts
|
|
@@ -6529,7 +6548,7 @@ const columnWithDotToSql = (ctx, data, shape, column, index, quotedAs, select) =
|
|
|
6529
6548
|
const key = column.slice(index + 1);
|
|
6530
6549
|
if (key === "*") {
|
|
6531
6550
|
const shape = data.joinedShapes?.[table];
|
|
6532
|
-
return shape ? select ? makeRowToJson(table, shape, true) : `"${table}".*` : column;
|
|
6551
|
+
return shape ? select ? makeRowToJson(ctx, table, shape, true) : `"${table}".*` : column;
|
|
6533
6552
|
}
|
|
6534
6553
|
const tableName = _getQueryAliasOrName(data, table);
|
|
6535
6554
|
const quoted = `"${table}"`;
|
|
@@ -6541,6 +6560,22 @@ const columnWithDotToSql = (ctx, data, shape, column, index, quotedAs, select) =
|
|
|
6541
6560
|
}
|
|
6542
6561
|
return `"${tableName}"."${key}"`;
|
|
6543
6562
|
};
|
|
6563
|
+
const selectedColumnWithDotToSql = (ctx, data, shape, column, index, quotedAs) => {
|
|
6564
|
+
const table = column.slice(0, index);
|
|
6565
|
+
const key = column.slice(index + 1);
|
|
6566
|
+
if (key === "*") {
|
|
6567
|
+
const shape = data.joinedShapes?.[table];
|
|
6568
|
+
return shape ? makeRowToJson(ctx, table, shape, true) : column;
|
|
6569
|
+
}
|
|
6570
|
+
const tableName = _getQueryAliasOrName(data, table);
|
|
6571
|
+
const quoted = `"${table}"`;
|
|
6572
|
+
const col = quoted === quotedAs ? shape[key] : data.joinedShapes?.[tableName]?.[key];
|
|
6573
|
+
if (col) {
|
|
6574
|
+
if (col.data.selectSql) return `(${col.data.selectSql.toSQL(ctx, quoted)})`;
|
|
6575
|
+
if (col.data.name) return `"${tableName}"."${col.data.name}"`;
|
|
6576
|
+
}
|
|
6577
|
+
return `"${tableName}"."${key}"`;
|
|
6578
|
+
};
|
|
6544
6579
|
const columnToSqlWithAs = (ctx, data, column, as, quotedAs, select, jsonList) => {
|
|
6545
6580
|
const index = column.indexOf(".");
|
|
6546
6581
|
return index !== -1 ? tableColumnToSqlWithAs(ctx, data, column, column.slice(0, index), column.slice(index + 1), as, quotedAs, select, jsonList) : ownColumnToSqlWithAs(ctx, data, column, as, quotedAs, select, jsonList);
|
|
@@ -6550,7 +6585,7 @@ const tableColumnToSqlWithAs = (ctx, data, column, table, key, as, quotedAs, sel
|
|
|
6550
6585
|
if (jsonList) jsonList[as] = void 0;
|
|
6551
6586
|
const shape = data.joinedShapes?.[table];
|
|
6552
6587
|
if (shape) {
|
|
6553
|
-
if (select) return makeRowToJson(table, shape, true) + ` "${as}"`;
|
|
6588
|
+
if (select) return makeRowToJson(ctx, table, shape, true) + ` "${as}"`;
|
|
6554
6589
|
return `"${table}"."${table}" "${as}"`;
|
|
6555
6590
|
}
|
|
6556
6591
|
return column;
|
|
@@ -6558,10 +6593,10 @@ const tableColumnToSqlWithAs = (ctx, data, column, table, key, as, quotedAs, sel
|
|
|
6558
6593
|
const tableName = _getQueryAliasOrName(data, table);
|
|
6559
6594
|
const quoted = `"${table}"`;
|
|
6560
6595
|
const col = quoted === quotedAs ? data.shape[key] : data.joinedShapes?.[tableName][key];
|
|
6561
|
-
if (jsonList) jsonList[as] = col;
|
|
6596
|
+
if (jsonList) jsonList[as] = col && getSelectedColumnData(col);
|
|
6562
6597
|
if (col) {
|
|
6598
|
+
if (col.data.selectSql) return `(${col.data.selectSql.toSQL(ctx, quoted)}) "${as}"`;
|
|
6563
6599
|
if (col.data.name && col.data.name !== key) return `"${tableName}"."${col.data.name}" "${as}"`;
|
|
6564
|
-
if (col.data.computed) return `(${col.data.computed.toSQL(ctx, quoted)}) "${as}"`;
|
|
6565
6600
|
}
|
|
6566
6601
|
return `"${tableName}"."${key}"${key === as ? "" : ` "${as}"`}`;
|
|
6567
6602
|
};
|
|
@@ -6571,10 +6606,10 @@ const ownColumnToSqlWithAs = (ctx, data, column, as, quotedAs, select, jsonList)
|
|
|
6571
6606
|
return `"${column}"."${column}" "${as}"`;
|
|
6572
6607
|
}
|
|
6573
6608
|
const col = data.shape[column];
|
|
6574
|
-
if (jsonList) jsonList[as] = col;
|
|
6609
|
+
if (jsonList) jsonList[as] = col && getSelectedColumnData(col);
|
|
6575
6610
|
if (col) {
|
|
6611
|
+
if (col.data.selectSql) return `(${col.data.selectSql.toSQL(ctx, quotedAs)}) "${as}"`;
|
|
6576
6612
|
if (col.data.name && col.data.name !== column) return `${quotedAs ? `${quotedAs}.` : ""}"${col.data.name}"${col.data.name === as ? "" : ` "${as}"`}`;
|
|
6577
|
-
if (col.data.computed) return `(${col.data.computed.toSQL(ctx, quotedAs)}) "${as}"`;
|
|
6578
6613
|
}
|
|
6579
6614
|
return `${quotedAs ? `${quotedAs}.` : ""}"${column}"${column === as ? "" : ` "${as}"`}`;
|
|
6580
6615
|
};
|
|
@@ -6730,7 +6765,7 @@ var SelectItemExpression = class extends Expression {
|
|
|
6730
6765
|
}
|
|
6731
6766
|
makeSQL(ctx, quotedAs) {
|
|
6732
6767
|
const q = this.q;
|
|
6733
|
-
return typeof this.item === "string" ? this.item === "*" ? selectAllSql(q, quotedAs).join(", ") :
|
|
6768
|
+
return typeof this.item === "string" ? this.item === "*" ? selectAllSql(q, quotedAs, void 0, ctx).join(", ") : selectedColumnToSql(ctx, q, q.shape, this.item, quotedAs) : this.item.toSQL(ctx, quotedAs);
|
|
6734
6769
|
}
|
|
6735
6770
|
};
|
|
6736
6771
|
const _getSelectableColumn = (q, arg) => {
|
|
@@ -7087,12 +7122,12 @@ const selectToSqlList = (ctx, table, query, quotedAs, hookSelect = query.hookSel
|
|
|
7087
7122
|
quotedTable = `"${tableName}"`;
|
|
7088
7123
|
columnName = select.slice(index + 1);
|
|
7089
7124
|
col = table.q.joinedShapes?.[tableName]?.[columnName];
|
|
7090
|
-
sql =
|
|
7125
|
+
sql = selectedColumnToSql(ctx, table.q, table.q.shape, select, void 0);
|
|
7091
7126
|
} else {
|
|
7092
7127
|
quotedTable = quotedAs;
|
|
7093
7128
|
columnName = select;
|
|
7094
7129
|
col = query.shape[select];
|
|
7095
|
-
sql =
|
|
7130
|
+
sql = selectedColumnToSql(ctx, table.q, query.shape, select, quotedAs);
|
|
7096
7131
|
}
|
|
7097
7132
|
} else {
|
|
7098
7133
|
columnName = column;
|
|
@@ -7132,17 +7167,24 @@ const selectToSql = (ctx, table, query, quotedAs, hookSelect = query.hookSelect,
|
|
|
7132
7167
|
return selectToSqlList(ctx, table, query, quotedAs, hookSelect, isSubSql, aliases, jsonList, delayedRelationSelect).join(", ");
|
|
7133
7168
|
};
|
|
7134
7169
|
const internalSelectAllSql = (ctx, query, quotedAs, jsonList) => {
|
|
7135
|
-
if (jsonList)
|
|
7170
|
+
if (jsonList) for (const key in query.selectAllShape) {
|
|
7171
|
+
const column = query.selectAllShape[key];
|
|
7172
|
+
jsonList[key] = getSelectedColumnData(column);
|
|
7173
|
+
}
|
|
7136
7174
|
let columnsCount;
|
|
7137
7175
|
if (query.shape !== anyShape) {
|
|
7138
7176
|
columnsCount = 0;
|
|
7139
7177
|
for (const key in query.shape) if (!query.shape[key].data.explicitSelect) columnsCount++;
|
|
7140
7178
|
ctx.selectedCount += columnsCount;
|
|
7141
7179
|
}
|
|
7142
|
-
return selectAllSql(query, quotedAs, columnsCount);
|
|
7180
|
+
return selectAllSql(query, quotedAs, columnsCount, ctx);
|
|
7181
|
+
};
|
|
7182
|
+
const selectAllSql = (q, quotedAs, columnsCount, ctx) => {
|
|
7183
|
+
return q.join?.length || q.updateFrom || q.updateMany ? q.selectAllColumns?.map((item) => selectAllColumnToSql(item, ctx, quotedAs, true)) || (isEmptySelect(q.shape, columnsCount) ? [] : [`${quotedAs}.*`]) : q.selectAllColumns ? q.selectAllColumns.map((item) => selectAllColumnToSql(item, ctx, quotedAs)) : isEmptySelect(q.shape, columnsCount) ? [] : ["*"];
|
|
7143
7184
|
};
|
|
7144
|
-
const
|
|
7145
|
-
|
|
7185
|
+
const selectAllColumnToSql = (item, ctx, quotedAs, prefix) => {
|
|
7186
|
+
if (typeof item !== "string") return item(ctx, quotedAs);
|
|
7187
|
+
return prefix ? `${quotedAs}.${item}` : item;
|
|
7146
7188
|
};
|
|
7147
7189
|
const isEmptySelect = (shape, columnsCount) => columnsCount === void 0 ? shape === anyShape ? false : isObjectEmpty(shape) : !columnsCount;
|
|
7148
7190
|
const pushSubQuerySql = (ctx, mainQuery, query, as, list, quotedAs, aliases) => {
|
|
@@ -7176,7 +7218,7 @@ const pushSubQuerySql = (ctx, mainQuery, query, as, list, quotedAs, aliases) =>
|
|
|
7176
7218
|
case "oneOrThrow": {
|
|
7177
7219
|
const table = query.q.joinedForSelect;
|
|
7178
7220
|
const shape = mainQuery.joinedShapes?.[as];
|
|
7179
|
-
sql = makeRowToJson(table, shape, false);
|
|
7221
|
+
sql = makeRowToJson(ctx, table, shape, false);
|
|
7180
7222
|
break;
|
|
7181
7223
|
}
|
|
7182
7224
|
case "all":
|
|
@@ -9644,7 +9686,7 @@ const toSql = (table, type, topCtx, isSubSql, cteName, calledByThen, dontAddTabl
|
|
|
9644
9686
|
if (ctx.topCtx.cteHooks.hasSelect) {
|
|
9645
9687
|
if (prependedSelectParenthesis) result.text += ")";
|
|
9646
9688
|
const { tableHooks, ensureCount } = ctx.topCtx.cteHooks;
|
|
9647
|
-
const keyValues = [...tableHooks ? Object.entries(tableHooks).map(([cteName, data]) => `'${cteName}', (SELECT json_agg(${makeRowToJson(cteName, data.shape, false, true)}) FROM "${cteName}")`) : emptyArray, ...ensureCount ? Object.entries(ensureCount).map(([cteName, item]) => `'#${cteName}', CASE WHEN ${"count" in item ? `(SELECT count(*) FROM "${cteName}") < ${item.count}` : `(SELECT "${cteName}"."${item.jsonNotNull}" FROM "${cteName}") IS NULL`} THEN (SELECT 'not-found')::int END`) : emptyArray];
|
|
9689
|
+
const keyValues = [...tableHooks ? Object.entries(tableHooks).map(([cteName, data]) => `'${cteName}', (SELECT json_agg(${makeRowToJson(ctx, cteName, data.shape, false, true)}) FROM "${cteName}")`) : emptyArray, ...ensureCount ? Object.entries(ensureCount).map(([cteName, item]) => `'#${cteName}', CASE WHEN ${"count" in item ? `(SELECT count(*) FROM "${cteName}") < ${item.count}` : `(SELECT "${cteName}"."${item.jsonNotNull}" FROM "${cteName}") IS NULL`} THEN (SELECT 'not-found')::int END`) : emptyArray];
|
|
9648
9690
|
result.text += ` UNION ALL SELECT ${"NULL, ".repeat(ctx.selectedCount || 0)}json_build_object(${keyValues.join(", ")})`;
|
|
9649
9691
|
}
|
|
9650
9692
|
}
|
|
@@ -9772,17 +9814,23 @@ const quoteFromWithSchema = (schema, table) => {
|
|
|
9772
9814
|
const s = typeof schema === "function" ? schema() : schema;
|
|
9773
9815
|
return s ? `"${s}"."${table}"` : `"${table}"`;
|
|
9774
9816
|
};
|
|
9775
|
-
const makeRowToJson = (table, shape, aliasName, includingExplicitSelect) => {
|
|
9817
|
+
const makeRowToJson = (ctx, table, shape, aliasName, includingExplicitSelect) => {
|
|
9776
9818
|
let isSimple = true;
|
|
9777
9819
|
const list = [];
|
|
9778
9820
|
for (const key in shape) {
|
|
9779
9821
|
const column = shape[key];
|
|
9780
9822
|
if (!includingExplicitSelect && column.data.explicitSelect) continue;
|
|
9781
|
-
|
|
9782
|
-
|
|
9823
|
+
const selectSql = !column.data.computed ? column.data.selectSql : void 0;
|
|
9824
|
+
const outputColumn = getSelectedColumnData(column);
|
|
9825
|
+
if (aliasName && column.data.name || outputColumn.data.jsonCast || selectSql) isSimple = false;
|
|
9826
|
+
const value = selectSql ? selectSql.toSQL(ctx, `"${table}"`) : `"${table}"."${aliasName && column.data.name || key}"`;
|
|
9827
|
+
list.push(`'${key}', ${value}${outputColumn.data.jsonCast ? `::${outputColumn.data.jsonCast}` : ""}`);
|
|
9783
9828
|
}
|
|
9784
9829
|
return isSimple ? `row_to_json("${table}".*)` : `CASE WHEN to_jsonb("${table}") IS NULL THEN NULL ELSE json_build_object(` + list.join(", ") + ") END";
|
|
9785
9830
|
};
|
|
9831
|
+
const getSelectedColumnData = (column) => {
|
|
9832
|
+
return column.data.selectSql?.result.value || column;
|
|
9833
|
+
};
|
|
9786
9834
|
const getSqlText = (sql) => {
|
|
9787
9835
|
if ("text" in sql) return sql.text;
|
|
9788
9836
|
throw new Error(`Batch SQL is not supported in this query`);
|
|
@@ -12421,6 +12469,10 @@ var MergeQueryMethods = class {
|
|
|
12421
12469
|
return query;
|
|
12422
12470
|
}
|
|
12423
12471
|
};
|
|
12472
|
+
const applyColumnSelectSql = (column) => {
|
|
12473
|
+
const { selectSqlFn } = column.data;
|
|
12474
|
+
if (selectSqlFn) column.data.selectSql = selectSqlFn(new ColumnRefExpression(column, column.data.key));
|
|
12475
|
+
};
|
|
12424
12476
|
const DEFAULT_PRIVILEGE = {
|
|
12425
12477
|
OBJECT_TYPES: [
|
|
12426
12478
|
"TABLES",
|
|
@@ -13791,6 +13843,10 @@ var Db = class extends QueryMethods {
|
|
|
13791
13843
|
}
|
|
13792
13844
|
if (column.data.explicitSelect) prepareSelectAll = true;
|
|
13793
13845
|
else selectAllCount++;
|
|
13846
|
+
if (column.data.selectSqlFn) {
|
|
13847
|
+
applyColumnSelectSql(column);
|
|
13848
|
+
prepareSelectAll = true;
|
|
13849
|
+
}
|
|
13794
13850
|
const { modifyQuery: mq } = column.data;
|
|
13795
13851
|
if (mq) modifyQuery = pushOrNewArray(modifyQuery, (q) => mq(q, column));
|
|
13796
13852
|
if (typeof column.data.default === "function") {
|
|
@@ -13848,7 +13904,12 @@ var Db = class extends QueryMethods {
|
|
|
13848
13904
|
for (const key in shape) {
|
|
13849
13905
|
const column = shape[key];
|
|
13850
13906
|
if (!column.data.explicitSelect) {
|
|
13851
|
-
|
|
13907
|
+
const { data } = column;
|
|
13908
|
+
const { selectSql } = data;
|
|
13909
|
+
let item;
|
|
13910
|
+
if (selectSql) item = (ctx, quotedAs) => `(${selectSql.toSQL(ctx, quotedAs)}) "${key}"`;
|
|
13911
|
+
else item = data.name ? `"${data.name}" "${key}"` : `"${key}"`;
|
|
13912
|
+
list.push(item);
|
|
13852
13913
|
selectAllShape[key] = column;
|
|
13853
13914
|
}
|
|
13854
13915
|
}
|