neoorm 0.3.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -6
- package/dist/bin/neoorm.js +45 -15
- package/dist/bin/neoorm.js.map +1 -1
- package/dist/codegen/diff-manifest.d.ts +7 -7
- package/dist/codegen/diff-manifest.d.ts.map +1 -1
- package/dist/codegen/diff-manifest.js +67 -54
- package/dist/codegen/diff-manifest.js.map +1 -1
- package/dist/codegen/generate-summary.js.map +1 -1
- package/dist/codegen/generate.d.ts.map +1 -1
- package/dist/codegen/generate.js +11 -1
- package/dist/codegen/generate.js.map +1 -1
- package/dist/codegen/manifest-relations.d.ts.map +1 -1
- package/dist/codegen/manifest-relations.js +21 -0
- package/dist/codegen/manifest-relations.js.map +1 -1
- package/dist/codegen/schema-to-manifest.js.map +1 -1
- package/dist/config.d.ts +1 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +1 -1
- package/dist/config.js.map +1 -1
- package/dist/dialect/postgres.d.ts +3 -4
- package/dist/dialect/postgres.d.ts.map +1 -1
- package/dist/dialect/postgres.js +19 -11
- package/dist/dialect/postgres.js.map +1 -1
- package/dist/dialect/shared.d.ts +6 -0
- package/dist/dialect/shared.d.ts.map +1 -0
- package/dist/dialect/shared.js +16 -0
- package/dist/dialect/shared.js.map +1 -0
- package/dist/dialect/sqlite.d.ts +4 -0
- package/dist/dialect/sqlite.d.ts.map +1 -0
- package/dist/dialect/sqlite.js +276 -0
- package/dist/dialect/sqlite.js.map +1 -0
- package/dist/dialect/types.d.ts +7 -0
- package/dist/dialect/types.d.ts.map +1 -1
- package/dist/init/scaffold.js.map +1 -1
- package/dist/introspect/pull.d.ts +3 -2
- package/dist/introspect/pull.d.ts.map +1 -1
- package/dist/introspect/pull.js +124 -13
- package/dist/introspect/pull.js.map +1 -1
- package/dist/introspect/queries.d.ts +9 -9
- package/dist/introspect/queries.d.ts.map +1 -1
- package/dist/introspect/queries.js +16 -16
- package/dist/introspect/queries.js.map +1 -1
- package/dist/introspect/sqlite/to-manifest.d.ts +4 -0
- package/dist/introspect/sqlite/to-manifest.d.ts.map +1 -0
- package/dist/introspect/sqlite/to-manifest.js +166 -0
- package/dist/introspect/sqlite/to-manifest.js.map +1 -0
- package/dist/introspect/to-manifest.d.ts +2 -2
- package/dist/introspect/to-manifest.d.ts.map +1 -1
- package/dist/introspect/to-manifest.js +20 -12
- package/dist/introspect/to-manifest.js.map +1 -1
- package/dist/migrate/runner.d.ts +14 -14
- package/dist/migrate/runner.d.ts.map +1 -1
- package/dist/migrate/runner.js +83 -88
- package/dist/migrate/runner.js.map +1 -1
- package/dist/plugins/builtin.d.ts +1 -0
- package/dist/plugins/builtin.d.ts.map +1 -1
- package/dist/plugins/builtin.js +96 -6
- package/dist/plugins/builtin.js.map +1 -1
- package/dist/plugins/json/operators.d.ts.map +1 -1
- package/dist/plugins/json/operators.js +14 -5
- package/dist/plugins/json/operators.js.map +1 -1
- package/dist/plugins/types.d.ts +4 -4
- package/dist/plugins/types.d.ts.map +1 -1
- package/dist/runtime/client.d.ts +32 -7
- package/dist/runtime/client.d.ts.map +1 -1
- package/dist/runtime/client.js +68 -9
- package/dist/runtime/client.js.map +1 -1
- package/dist/runtime/driver.d.ts +28 -0
- package/dist/runtime/driver.d.ts.map +1 -0
- package/dist/runtime/driver.js +265 -0
- package/dist/runtime/driver.js.map +1 -0
- package/dist/runtime/errors.d.ts +1 -1
- package/dist/runtime/errors.d.ts.map +1 -1
- package/dist/runtime/errors.js +1 -0
- package/dist/runtime/errors.js.map +1 -1
- package/dist/runtime/executor.d.ts +11 -3
- package/dist/runtime/executor.d.ts.map +1 -1
- package/dist/runtime/executor.js +69 -37
- package/dist/runtime/executor.js.map +1 -1
- package/dist/runtime/pg-error.d.ts +1 -1
- package/dist/runtime/pg-error.d.ts.map +1 -1
- package/dist/runtime/pg-error.js +6 -1
- package/dist/runtime/pg-error.js.map +1 -1
- package/dist/runtime/query/aggregate.d.ts.map +1 -1
- package/dist/runtime/query/aggregate.js +5 -4
- package/dist/runtime/query/aggregate.js.map +1 -1
- package/dist/runtime/query/compile.d.ts +42 -16
- package/dist/runtime/query/compile.d.ts.map +1 -1
- package/dist/runtime/query/compile.js +479 -91
- package/dist/runtime/query/compile.js.map +1 -1
- package/dist/runtime/query/count.d.ts.map +1 -1
- package/dist/runtime/query/count.js +7 -3
- package/dist/runtime/query/count.js.map +1 -1
- package/dist/runtime/query/create.d.ts +5 -0
- package/dist/runtime/query/create.d.ts.map +1 -1
- package/dist/runtime/query/create.js +89 -23
- package/dist/runtime/query/create.js.map +1 -1
- package/dist/runtime/query/cursor.d.ts +4 -3
- package/dist/runtime/query/cursor.d.ts.map +1 -1
- package/dist/runtime/query/cursor.js +13 -9
- package/dist/runtime/query/cursor.js.map +1 -1
- package/dist/runtime/query/delete.d.ts +2 -1
- package/dist/runtime/query/delete.d.ts.map +1 -1
- package/dist/runtime/query/delete.js +27 -14
- package/dist/runtime/query/delete.js.map +1 -1
- package/dist/runtime/query/execute.d.ts +11 -4
- package/dist/runtime/query/execute.d.ts.map +1 -1
- package/dist/runtime/query/execute.js +20 -5
- package/dist/runtime/query/execute.js.map +1 -1
- package/dist/runtime/query/find-or-create.d.ts +17 -0
- package/dist/runtime/query/find-or-create.d.ts.map +1 -0
- package/dist/runtime/query/find-or-create.js +90 -0
- package/dist/runtime/query/find-or-create.js.map +1 -0
- package/dist/runtime/query/find.d.ts +13 -4
- package/dist/runtime/query/find.d.ts.map +1 -1
- package/dist/runtime/query/find.js +201 -47
- package/dist/runtime/query/find.js.map +1 -1
- package/dist/runtime/query/manifest-lookup.d.ts +3 -2
- package/dist/runtime/query/manifest-lookup.d.ts.map +1 -1
- package/dist/runtime/query/manifest-lookup.js +5 -4
- package/dist/runtime/query/manifest-lookup.js.map +1 -1
- package/dist/runtime/query/paginate.d.ts.map +1 -1
- package/dist/runtime/query/paginate.js +16 -11
- package/dist/runtime/query/paginate.js.map +1 -1
- package/dist/runtime/query/primary-key.d.ts +9 -6
- package/dist/runtime/query/primary-key.d.ts.map +1 -1
- package/dist/runtime/query/primary-key.js +65 -35
- package/dist/runtime/query/primary-key.js.map +1 -1
- package/dist/runtime/query/relation-planner.d.ts +74 -0
- package/dist/runtime/query/relation-planner.d.ts.map +1 -0
- package/dist/runtime/query/relation-planner.js +648 -0
- package/dist/runtime/query/relation-planner.js.map +1 -0
- package/dist/runtime/query/relation-writes.d.ts +2 -1
- package/dist/runtime/query/relation-writes.d.ts.map +1 -1
- package/dist/runtime/query/relation-writes.js +46 -53
- package/dist/runtime/query/relation-writes.js.map +1 -1
- package/dist/runtime/query/table-index.d.ts +61 -0
- package/dist/runtime/query/table-index.d.ts.map +1 -0
- package/dist/runtime/query/table-index.js +152 -0
- package/dist/runtime/query/table-index.js.map +1 -0
- package/dist/runtime/query/unique.d.ts +3 -2
- package/dist/runtime/query/unique.d.ts.map +1 -1
- package/dist/runtime/query/unique.js +7 -6
- package/dist/runtime/query/unique.js.map +1 -1
- package/dist/runtime/query/update.d.ts +3 -1
- package/dist/runtime/query/update.d.ts.map +1 -1
- package/dist/runtime/query/update.js +117 -36
- package/dist/runtime/query/update.js.map +1 -1
- package/dist/runtime/query/updated-at.d.ts +6 -4
- package/dist/runtime/query/updated-at.d.ts.map +1 -1
- package/dist/runtime/query/updated-at.js +23 -9
- package/dist/runtime/query/updated-at.js.map +1 -1
- package/dist/runtime/query/upsert.d.ts.map +1 -1
- package/dist/runtime/query/upsert.js +11 -9
- package/dist/runtime/query/upsert.js.map +1 -1
- package/dist/runtime/sqlite-open.d.ts +3 -0
- package/dist/runtime/sqlite-open.d.ts.map +1 -0
- package/dist/runtime/sqlite-open.js +22 -0
- package/dist/runtime/sqlite-open.js.map +1 -0
- package/dist/runtime/transaction.d.ts +5 -0
- package/dist/runtime/transaction.d.ts.map +1 -0
- package/dist/runtime/transaction.js +26 -0
- package/dist/runtime/transaction.js.map +1 -0
- package/dist/runtime/types.d.ts +9 -4
- package/dist/runtime/types.d.ts.map +1 -1
- package/dist/schema/column.d.ts +1 -1
- package/dist/schema/column.d.ts.map +1 -1
- package/dist/schema/column.js +1 -1
- package/dist/schema/column.js.map +1 -1
- package/dist/schema/define-schema.js.map +1 -1
- package/dist/schema/index.d.ts +2 -2
- package/dist/schema/index.d.ts.map +1 -1
- package/dist/schema/index.js +1 -1
- package/dist/schema/index.js.map +1 -1
- package/dist/schema/relation-types.d.ts +1 -0
- package/dist/schema/relation-types.d.ts.map +1 -1
- package/dist/schema/types.d.ts +12 -0
- package/dist/schema/types.d.ts.map +1 -1
- package/dist/sql/builder.d.ts.map +1 -1
- package/dist/sql/template.d.ts +7 -0
- package/dist/sql/template.d.ts.map +1 -1
- package/dist/sql/template.js +89 -3
- package/dist/sql/template.js.map +1 -1
- package/dist/utils/case.d.ts +4 -0
- package/dist/utils/case.d.ts.map +1 -1
- package/dist/utils/case.js +11 -0
- package/dist/utils/case.js.map +1 -1
- package/dist/utils/uuid.js.map +1 -1
- package/package.json +21 -4
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
import { effectiveRelations } from "../../codegen/manifest-relations.js";
|
|
2
|
-
import { quoteIdentifier, tableRef } from "../../dialect/postgres.js";
|
|
2
|
+
import { postgresDialect, quoteIdentifier, tableRef } from "../../dialect/postgres.js";
|
|
3
3
|
import { getColumnType } from "../../plugins/registry.js";
|
|
4
|
+
import { rebaseParamRefs } from "../../sql/template.js";
|
|
4
5
|
import { findM2M } from "./manifest-lookup.js";
|
|
5
6
|
import { primaryKeySqlName, requireScalarPrimaryKey, targetRelationPkSql, } from "./primary-key.js";
|
|
7
|
+
import { columnBySqlName, columnByTsName, columnsByTsNames, getOrSetSqlCache, getTableIndex, reorderKeyValues, sortedKeysCacheKey, } from "./table-index.js";
|
|
8
|
+
function colByTs(table, tsName, manifestIndex) {
|
|
9
|
+
return columnByTsName(getTableIndex(manifestIndex, table.accessor), table, tsName);
|
|
10
|
+
}
|
|
6
11
|
const PARAMLESS_OPERATORS = new Set(["isNull", "isNotNull"]);
|
|
7
12
|
function isOperatorObject(value) {
|
|
8
13
|
return (typeof value === "object" &&
|
|
@@ -20,18 +25,21 @@ function pluginWhereOperators(col) {
|
|
|
20
25
|
return {};
|
|
21
26
|
return getColumnType(col.kind)?.whereOperators ?? {};
|
|
22
27
|
}
|
|
23
|
-
export function serializeColumnValue(col, value) {
|
|
28
|
+
export function serializeColumnValue(col, value, dialect = postgresDialect) {
|
|
24
29
|
if (col.kind === "fk")
|
|
25
30
|
return value;
|
|
26
31
|
const plugin = getColumnType(col.kind);
|
|
27
32
|
if (plugin?.serializeValue) {
|
|
28
|
-
return plugin.serializeValue(col, value);
|
|
33
|
+
return plugin.serializeValue(col, value, dialect);
|
|
29
34
|
}
|
|
30
35
|
return value;
|
|
31
36
|
}
|
|
32
37
|
function defaultColumnRef(col) {
|
|
33
38
|
return quoteIdentifier(col.sqlName);
|
|
34
39
|
}
|
|
40
|
+
function qualifiedColumnRefForTable(table) {
|
|
41
|
+
return (col) => `${tableRef(table)}.${quoteIdentifier(col.sqlName)}`;
|
|
42
|
+
}
|
|
35
43
|
function parentPkRef(table) {
|
|
36
44
|
const pkSql = primaryKeySqlName(table);
|
|
37
45
|
return `${tableRef(table)}.${quoteIdentifier(pkSql)}`;
|
|
@@ -77,6 +85,15 @@ function compileColumnCondition(col, rawValue, dialect, paramIndex, columnRef) {
|
|
|
77
85
|
conditions.push(dialect.whereOperators[operator](sqlCol, nextParamIndex));
|
|
78
86
|
continue;
|
|
79
87
|
}
|
|
88
|
+
if (Array.isArray(value) && value.length === 0) {
|
|
89
|
+
if (operator === "in") {
|
|
90
|
+
conditions.push("1=0");
|
|
91
|
+
}
|
|
92
|
+
else if (operator === "notIn") {
|
|
93
|
+
conditions.push("1=1");
|
|
94
|
+
}
|
|
95
|
+
continue;
|
|
96
|
+
}
|
|
80
97
|
const transform = operatorParamTransform[operator];
|
|
81
98
|
const paramValue = operator === "in" || operator === "notIn"
|
|
82
99
|
? Array.isArray(value)
|
|
@@ -94,20 +111,22 @@ function compileColumnCondition(col, rawValue, dialect, paramIndex, columnRef) {
|
|
|
94
111
|
function compileExistsSubquery(existsSql, negate) {
|
|
95
112
|
return negate ? `NOT EXISTS (${existsSql})` : `EXISTS (${existsSql})`;
|
|
96
113
|
}
|
|
97
|
-
function compileRelationCondition(manifest, parentTable, relation, rawValue, dialect, paramIndex) {
|
|
114
|
+
function compileRelationCondition(manifest, parentTable, relation, rawValue, dialect, paramIndex, manifestIndex) {
|
|
98
115
|
const m2m = findM2M(manifest, parentTable.accessor, relation.name);
|
|
99
116
|
const targetTable = manifest.tables[relation.targetAccessor];
|
|
100
117
|
if (!targetTable) {
|
|
101
118
|
return { sql: "", params: [], nextParamIndex: paramIndex };
|
|
102
119
|
}
|
|
120
|
+
const parentTableIndex = getTableIndex(manifestIndex, parentTable.accessor);
|
|
121
|
+
const targetTableIndex = getTableIndex(manifestIndex, targetTable.accessor);
|
|
103
122
|
if (relation.cardinality === "one") {
|
|
104
123
|
if (!isOperatorObject(rawValue) || Array.isArray(rawValue)) {
|
|
105
124
|
return { sql: "", params: [], nextParamIndex: paramIndex };
|
|
106
125
|
}
|
|
107
126
|
const relAlias = "_rel";
|
|
108
127
|
const columnRef = (col) => `${quoteIdentifier(relAlias)}.${quoteIdentifier(col.sqlName)}`;
|
|
109
|
-
const nested = compileWhereNode(manifest, targetTable, rawValue, dialect, paramIndex, columnRef);
|
|
110
|
-
const parentFkCol =
|
|
128
|
+
const nested = compileWhereNode(manifest, targetTable, rawValue, dialect, paramIndex, columnRef, manifestIndex);
|
|
129
|
+
const parentFkCol = columnByTsName(parentTableIndex, parentTable, relation.fkColumn);
|
|
111
130
|
const parentFkRef = parentFkCol
|
|
112
131
|
? `${tableRef(parentTable)}.${quoteIdentifier(parentFkCol.sqlName)}`
|
|
113
132
|
: `${tableRef(parentTable)}.${quoteIdentifier(relation.fkSqlColumn)}`;
|
|
@@ -136,7 +155,7 @@ function compileRelationCondition(manifest, parentTable, relation, rawValue, dia
|
|
|
136
155
|
}
|
|
137
156
|
const relAlias = "_rel";
|
|
138
157
|
const columnRef = (col) => `${quoteIdentifier(relAlias)}.${quoteIdentifier(col.sqlName)}`;
|
|
139
|
-
const nested = compileWhereNode(manifest, targetTable, (nestedWhere ?? {}), dialect, paramIndex, columnRef);
|
|
158
|
+
const nested = compileWhereNode(manifest, targetTable, (nestedWhere ?? {}), dialect, paramIndex, columnRef, manifestIndex);
|
|
140
159
|
let fromClause;
|
|
141
160
|
let whereParts;
|
|
142
161
|
if (m2m) {
|
|
@@ -193,18 +212,20 @@ function compileRelationCondition(manifest, parentTable, relation, rawValue, dia
|
|
|
193
212
|
nextParamIndex: nested.nextParamIndex,
|
|
194
213
|
};
|
|
195
214
|
}
|
|
196
|
-
function compileWhereNode(manifest, table, where, dialect, startParamIndex, columnRef = defaultColumnRef) {
|
|
215
|
+
function compileWhereNode(manifest, table, where, dialect, startParamIndex, columnRef = defaultColumnRef, manifestIndex) {
|
|
197
216
|
const conditions = [];
|
|
198
217
|
const params = [];
|
|
199
218
|
let paramIndex = startParamIndex;
|
|
200
|
-
const
|
|
219
|
+
const tableIndex = getTableIndex(manifestIndex, table.accessor);
|
|
220
|
+
const relations = tableIndex?.effectiveRelationsByName ??
|
|
221
|
+
new Map(effectiveRelations(manifest, table).map((rel) => [rel.name, rel]));
|
|
201
222
|
for (const [key, value] of Object.entries(where)) {
|
|
202
223
|
if (key === "AND" && Array.isArray(value)) {
|
|
203
224
|
const parts = [];
|
|
204
225
|
for (const item of value) {
|
|
205
226
|
if (!item || typeof item !== "object" || Array.isArray(item))
|
|
206
227
|
continue;
|
|
207
|
-
const compiled = compileWhereNode(manifest, table, item, dialect, paramIndex, columnRef);
|
|
228
|
+
const compiled = compileWhereNode(manifest, table, item, dialect, paramIndex, columnRef, manifestIndex);
|
|
208
229
|
if (compiled.sql)
|
|
209
230
|
parts.push(`(${compiled.sql})`);
|
|
210
231
|
params.push(...compiled.params);
|
|
@@ -219,7 +240,7 @@ function compileWhereNode(manifest, table, where, dialect, startParamIndex, colu
|
|
|
219
240
|
for (const item of value) {
|
|
220
241
|
if (!item || typeof item !== "object" || Array.isArray(item))
|
|
221
242
|
continue;
|
|
222
|
-
const compiled = compileWhereNode(manifest, table, item, dialect, paramIndex, columnRef);
|
|
243
|
+
const compiled = compileWhereNode(manifest, table, item, dialect, paramIndex, columnRef, manifestIndex);
|
|
223
244
|
if (compiled.sql)
|
|
224
245
|
parts.push(`(${compiled.sql})`);
|
|
225
246
|
params.push(...compiled.params);
|
|
@@ -230,7 +251,7 @@ function compileWhereNode(manifest, table, where, dialect, startParamIndex, colu
|
|
|
230
251
|
continue;
|
|
231
252
|
}
|
|
232
253
|
if (key === "NOT" && isOperatorObject(value)) {
|
|
233
|
-
const compiled = compileWhereNode(manifest, table, value, dialect, paramIndex, columnRef);
|
|
254
|
+
const compiled = compileWhereNode(manifest, table, value, dialect, paramIndex, columnRef, manifestIndex);
|
|
234
255
|
if (compiled.sql)
|
|
235
256
|
conditions.push(`NOT (${compiled.sql})`);
|
|
236
257
|
params.push(...compiled.params);
|
|
@@ -239,14 +260,14 @@ function compileWhereNode(manifest, table, where, dialect, startParamIndex, colu
|
|
|
239
260
|
}
|
|
240
261
|
const relation = relations.get(key);
|
|
241
262
|
if (relation) {
|
|
242
|
-
const compiled = compileRelationCondition(manifest, table, relation, value, dialect, paramIndex);
|
|
263
|
+
const compiled = compileRelationCondition(manifest, table, relation, value, dialect, paramIndex, manifestIndex);
|
|
243
264
|
if (compiled.sql)
|
|
244
265
|
conditions.push(compiled.sql);
|
|
245
266
|
params.push(...compiled.params);
|
|
246
267
|
paramIndex = compiled.nextParamIndex;
|
|
247
268
|
continue;
|
|
248
269
|
}
|
|
249
|
-
const col =
|
|
270
|
+
const col = columnByTsName(tableIndex, table, key);
|
|
250
271
|
if (!col)
|
|
251
272
|
continue;
|
|
252
273
|
const compiled = compileColumnCondition(col, value, dialect, paramIndex, columnRef);
|
|
@@ -261,16 +282,173 @@ function compileWhereNode(manifest, table, where, dialect, startParamIndex, colu
|
|
|
261
282
|
nextParamIndex: paramIndex,
|
|
262
283
|
};
|
|
263
284
|
}
|
|
264
|
-
export function compileWhere(manifest, table, where, dialect, startParamIndex = 1) {
|
|
285
|
+
export function compileWhere(manifest, table, where, dialect, startParamIndex = 1, manifestIndex, qualifyColumns = false) {
|
|
265
286
|
if (!where || Object.keys(where).length === 0) {
|
|
266
287
|
return { sql: "", params: [] };
|
|
267
288
|
}
|
|
268
|
-
const
|
|
289
|
+
const columnRef = qualifyColumns
|
|
290
|
+
? qualifiedColumnRefForTable(table)
|
|
291
|
+
: defaultColumnRef;
|
|
292
|
+
const result = compileWhereNode(manifest, table, where, dialect, startParamIndex, columnRef, manifestIndex);
|
|
293
|
+
const impossible = isImpossibleWhereSql(result.sql);
|
|
269
294
|
return {
|
|
270
295
|
sql: result.sql ? `WHERE ${result.sql}` : "",
|
|
271
296
|
params: result.params,
|
|
297
|
+
...(impossible ? { impossible: true } : {}),
|
|
272
298
|
};
|
|
273
299
|
}
|
|
300
|
+
function whereShapeKey(where) {
|
|
301
|
+
const parts = [];
|
|
302
|
+
for (const [key, value] of Object.entries(where)) {
|
|
303
|
+
if (key === "AND" && Array.isArray(value)) {
|
|
304
|
+
parts.push(`AND:${value
|
|
305
|
+
.filter((item) => !!item && typeof item === "object" && !Array.isArray(item))
|
|
306
|
+
.map((item) => whereShapeKey(item))
|
|
307
|
+
.join(",")}`);
|
|
308
|
+
continue;
|
|
309
|
+
}
|
|
310
|
+
if (key === "OR" && Array.isArray(value)) {
|
|
311
|
+
parts.push(`OR:${value
|
|
312
|
+
.filter((item) => !!item && typeof item === "object" && !Array.isArray(item))
|
|
313
|
+
.map((item) => whereShapeKey(item))
|
|
314
|
+
.join(",")}`);
|
|
315
|
+
continue;
|
|
316
|
+
}
|
|
317
|
+
if (key === "NOT" && isOperatorObject(value)) {
|
|
318
|
+
parts.push(`NOT:${whereShapeKey(value)}`);
|
|
319
|
+
continue;
|
|
320
|
+
}
|
|
321
|
+
if (isOperatorObject(value) && !(value instanceof Date)) {
|
|
322
|
+
const ops = Object.keys(value).sort();
|
|
323
|
+
if (ops.some((op) => op === "some" || op === "every" || op === "none")) {
|
|
324
|
+
const mode = ops.find((op) => op === "some" || op === "every" || op === "none");
|
|
325
|
+
const nested = value[mode ?? ""];
|
|
326
|
+
parts.push(`${key}:rel:${mode}:${isOperatorObject(nested) ? whereShapeKey(nested) : "{}"}`);
|
|
327
|
+
}
|
|
328
|
+
else if (ops.includes("in") || ops.includes("notIn")) {
|
|
329
|
+
const arr = value.in ?? value.notIn;
|
|
330
|
+
const len = Array.isArray(arr) ? arr.length : 0;
|
|
331
|
+
const op = ops.includes("in") ? "in" : "notIn";
|
|
332
|
+
parts.push(`${key}:${op}:${len}`);
|
|
333
|
+
}
|
|
334
|
+
else {
|
|
335
|
+
parts.push(`${key}:${ops.join(",")}`);
|
|
336
|
+
}
|
|
337
|
+
continue;
|
|
338
|
+
}
|
|
339
|
+
parts.push(`${key}:eq`);
|
|
340
|
+
}
|
|
341
|
+
return parts.join("&");
|
|
342
|
+
}
|
|
343
|
+
function collectWhereParams(manifest, table, where, dialect, manifestIndex) {
|
|
344
|
+
const params = [];
|
|
345
|
+
function walk(node, columnRef) {
|
|
346
|
+
const tableIndex = getTableIndex(manifestIndex, table.accessor);
|
|
347
|
+
const relations = tableIndex?.effectiveRelationsByName ??
|
|
348
|
+
new Map(effectiveRelations(manifest, table).map((rel) => [rel.name, rel]));
|
|
349
|
+
for (const [key, value] of Object.entries(node)) {
|
|
350
|
+
if (key === "AND" || key === "OR") {
|
|
351
|
+
if (Array.isArray(value)) {
|
|
352
|
+
for (const item of value) {
|
|
353
|
+
if (item && typeof item === "object" && !Array.isArray(item)) {
|
|
354
|
+
walk(item, columnRef);
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
continue;
|
|
359
|
+
}
|
|
360
|
+
if (key === "NOT" && isOperatorObject(value)) {
|
|
361
|
+
walk(value, columnRef);
|
|
362
|
+
continue;
|
|
363
|
+
}
|
|
364
|
+
if (relations.get(key)) {
|
|
365
|
+
const compiled = compileRelationCondition(manifest, table, relations.get(key), value, dialect, 1, manifestIndex);
|
|
366
|
+
params.push(...compiled.params);
|
|
367
|
+
continue;
|
|
368
|
+
}
|
|
369
|
+
const col = columnByTsName(tableIndex, table, key);
|
|
370
|
+
if (!col)
|
|
371
|
+
continue;
|
|
372
|
+
const compiled = compileColumnCondition(col, value, dialect, 1, columnRef);
|
|
373
|
+
params.push(...compiled.params);
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
walk(where, defaultColumnRef);
|
|
377
|
+
return params;
|
|
378
|
+
}
|
|
379
|
+
function whereValuesFingerprint(manifest, table, where, dialect, manifestIndex) {
|
|
380
|
+
return JSON.stringify(collectWhereParams(manifest, table, where, dialect, manifestIndex));
|
|
381
|
+
}
|
|
382
|
+
export function getCachedWhereClause(manifest, table, where, dialect, startParamIndex = 1, manifestIndex, qualifyColumns = false) {
|
|
383
|
+
if (!where || Object.keys(where).length === 0) {
|
|
384
|
+
return { sql: "", params: [] };
|
|
385
|
+
}
|
|
386
|
+
const tableIndex = getTableIndex(manifestIndex, table.accessor);
|
|
387
|
+
const shape = qualifyColumns
|
|
388
|
+
? `${whereShapeKey(where)}|qualified`
|
|
389
|
+
: whereShapeKey(where);
|
|
390
|
+
const shellCached = tableIndex?.whereClauseByShape.get(shape);
|
|
391
|
+
if (shellCached) {
|
|
392
|
+
return {
|
|
393
|
+
sql: shellCached.sql,
|
|
394
|
+
params: collectWhereParams(manifest, table, where, dialect, manifestIndex),
|
|
395
|
+
...(shellCached.impossible ? { impossible: true } : {}),
|
|
396
|
+
};
|
|
397
|
+
}
|
|
398
|
+
const fingerprint = whereValuesFingerprint(manifest, table, where, dialect, manifestIndex);
|
|
399
|
+
const cacheKey = `${shape}\0${fingerprint}`;
|
|
400
|
+
const cached = tableIndex?.whereClauseByFingerprint.get(cacheKey);
|
|
401
|
+
if (cached)
|
|
402
|
+
return cached;
|
|
403
|
+
const compiled = compileWhere(manifest, table, where, dialect, startParamIndex, manifestIndex, qualifyColumns);
|
|
404
|
+
tableIndex?.whereClauseByShape.set(shape, {
|
|
405
|
+
sql: compiled.sql,
|
|
406
|
+
...(compiled.impossible ? { impossible: true } : {}),
|
|
407
|
+
});
|
|
408
|
+
tableIndex?.whereClauseByFingerprint.set(cacheKey, compiled);
|
|
409
|
+
return compiled;
|
|
410
|
+
}
|
|
411
|
+
export function orderByShapeKey(orderBy, tableAlias) {
|
|
412
|
+
if (!orderBy || Object.keys(orderBy).length === 0)
|
|
413
|
+
return "";
|
|
414
|
+
const entries = Object.entries(orderBy)
|
|
415
|
+
.filter(([key]) => key !== "_count")
|
|
416
|
+
.map(([key, direction]) => typeof direction === "string" ? `${key}:${direction.toUpperCase()}` : "")
|
|
417
|
+
.filter(Boolean)
|
|
418
|
+
.sort((a, b) => a.localeCompare(b));
|
|
419
|
+
if (entries.length === 0)
|
|
420
|
+
return "";
|
|
421
|
+
const base = entries.join("|");
|
|
422
|
+
return tableAlias ? `${base}|@${tableAlias}` : base;
|
|
423
|
+
}
|
|
424
|
+
export function getCachedOrderByClause(table, orderBy, tableAlias, manifestIndex) {
|
|
425
|
+
if (!orderBy || Object.keys(orderBy).length === 0)
|
|
426
|
+
return "";
|
|
427
|
+
const tableIndex = getTableIndex(manifestIndex, table.accessor);
|
|
428
|
+
const shape = orderByShapeKey(orderBy, tableAlias);
|
|
429
|
+
if (!shape)
|
|
430
|
+
return "";
|
|
431
|
+
if (!tableIndex) {
|
|
432
|
+
return compileOrderBy(table, orderBy, tableAlias, manifestIndex);
|
|
433
|
+
}
|
|
434
|
+
return getOrSetSqlCache(tableIndex.orderBySqlByShape, shape, () => compileOrderBy(table, orderBy, tableAlias, manifestIndex));
|
|
435
|
+
}
|
|
436
|
+
export function getCachedDeleteManyQuery(tableIndex, table, whereSql) {
|
|
437
|
+
const cacheKey = whereSql || "";
|
|
438
|
+
if (!tableIndex)
|
|
439
|
+
return buildDeleteManyQuery(table, whereSql);
|
|
440
|
+
return getOrSetSqlCache(tableIndex.deleteManySqlByWhereShape, cacheKey, () => buildDeleteManyQuery(table, whereSql));
|
|
441
|
+
}
|
|
442
|
+
export function isImpossibleWhereSql(sql) {
|
|
443
|
+
if (!sql)
|
|
444
|
+
return false;
|
|
445
|
+
return /\b1\s*=\s*0\b/.test(sql);
|
|
446
|
+
}
|
|
447
|
+
export function isImpossibleWhere(whereSql) {
|
|
448
|
+
if (!whereSql)
|
|
449
|
+
return false;
|
|
450
|
+
return isImpossibleWhereSql(whereSql.replace(/^WHERE\s+/i, ""));
|
|
451
|
+
}
|
|
274
452
|
function buildValuePlaceholder(col, paramIndex) {
|
|
275
453
|
if (!col || col.kind === "fk")
|
|
276
454
|
return `$${paramIndex}`;
|
|
@@ -284,16 +462,20 @@ function buildSetExpression(col, paramIndex) {
|
|
|
284
462
|
const sqlCol = quoteIdentifier(col?.sqlName ?? "");
|
|
285
463
|
return `${sqlCol} = ${buildValuePlaceholder(col, paramIndex)}`;
|
|
286
464
|
}
|
|
287
|
-
export function compileOrderBy(table, orderBy) {
|
|
465
|
+
export function compileOrderBy(table, orderBy, tableAlias, manifestIndex) {
|
|
288
466
|
if (!orderBy || Object.keys(orderBy).length === 0)
|
|
289
467
|
return "";
|
|
468
|
+
const tableIndex = getTableIndex(manifestIndex, table.accessor);
|
|
469
|
+
const prefix = tableAlias ? `${quoteIdentifier(tableAlias)}.` : "";
|
|
290
470
|
const parts = [];
|
|
291
471
|
for (const [tsKey, direction] of Object.entries(orderBy)) {
|
|
292
|
-
|
|
472
|
+
if (tsKey === "_count" || typeof direction !== "string")
|
|
473
|
+
continue;
|
|
474
|
+
const col = columnByTsName(tableIndex, table, tsKey);
|
|
293
475
|
if (!col)
|
|
294
476
|
continue;
|
|
295
477
|
const dir = direction.toUpperCase() === "DESC" ? "DESC" : "ASC";
|
|
296
|
-
parts.push(`${quoteIdentifier(col.sqlName)} ${dir}`);
|
|
478
|
+
parts.push(`${prefix}${quoteIdentifier(col.sqlName)} ${dir}`);
|
|
297
479
|
}
|
|
298
480
|
return parts.length > 0 ? `ORDER BY ${parts.join(", ")}` : "";
|
|
299
481
|
}
|
|
@@ -306,90 +488,129 @@ export function normalizeSelectColumns(select) {
|
|
|
306
488
|
.filter(([, enabled]) => enabled === true)
|
|
307
489
|
.map(([key]) => key);
|
|
308
490
|
}
|
|
491
|
+
function aliasToTsName(expression, col) {
|
|
492
|
+
if (col.sqlName === col.tsName)
|
|
493
|
+
return expression;
|
|
494
|
+
return `${expression} AS ${quoteIdentifier(col.tsName)}`;
|
|
495
|
+
}
|
|
309
496
|
function selectExpression(col) {
|
|
310
497
|
if (col.kind === "fk") {
|
|
311
|
-
return quoteIdentifier(col.sqlName);
|
|
498
|
+
return aliasToTsName(quoteIdentifier(col.sqlName), col);
|
|
312
499
|
}
|
|
313
500
|
const plugin = getColumnType(col.kind);
|
|
314
501
|
if (plugin?.selectExpression) {
|
|
315
|
-
return plugin.selectExpression(col);
|
|
502
|
+
return aliasToTsName(plugin.selectExpression(col), col);
|
|
316
503
|
}
|
|
317
|
-
return quoteIdentifier(col.sqlName);
|
|
504
|
+
return aliasToTsName(quoteIdentifier(col.sqlName), col);
|
|
318
505
|
}
|
|
319
|
-
export function buildSelectColumns(table, select) {
|
|
506
|
+
export function buildSelectColumns(table, select, manifestIndex) {
|
|
507
|
+
const tableIndex = getTableIndex(manifestIndex, table.accessor);
|
|
320
508
|
const cols = select && select.length > 0
|
|
321
|
-
?
|
|
509
|
+
? columnsByTsNames(tableIndex, table, select)
|
|
322
510
|
: table.columns;
|
|
323
511
|
return cols.map((c) => selectExpression(c)).join(", ");
|
|
324
512
|
}
|
|
513
|
+
export function buildQualifiedSelectColumns(table, select, manifestIndex) {
|
|
514
|
+
const ref = tableRef(table);
|
|
515
|
+
const tableIndex = getTableIndex(manifestIndex, table.accessor);
|
|
516
|
+
const cols = select && select.length > 0
|
|
517
|
+
? columnsByTsNames(tableIndex, table, select)
|
|
518
|
+
: table.columns;
|
|
519
|
+
return cols.map((c) => `${ref}.${selectExpression(c)}`).join(", ");
|
|
520
|
+
}
|
|
325
521
|
export function buildFindByIdQuery(table) {
|
|
326
522
|
const { sqlName } = requireScalarPrimaryKey(table);
|
|
327
523
|
const sqlCol = quoteIdentifier(sqlName);
|
|
328
524
|
const selectCols = buildSelectColumns(table);
|
|
329
525
|
return `SELECT ${selectCols} FROM ${tableRef(table)} WHERE ${sqlCol} = $1`;
|
|
330
526
|
}
|
|
331
|
-
export function
|
|
332
|
-
|
|
527
|
+
export function buildFindAllQuery(table) {
|
|
528
|
+
return `SELECT ${buildSelectColumns(table)} FROM ${tableRef(table)}`;
|
|
529
|
+
}
|
|
530
|
+
export function normalizeLimitOffset(value, label) {
|
|
531
|
+
if (typeof value !== "number" || !Number.isInteger(value) || value < 0) {
|
|
532
|
+
throw new Error(`${label} must be a non-negative integer, got ${JSON.stringify(value)}`);
|
|
533
|
+
}
|
|
534
|
+
return value;
|
|
535
|
+
}
|
|
536
|
+
export function buildFindManyQuery(table, whereSql, orderSql, limit, offset, distinctOn, extraSelectCols, joinClauses, manifestIndex, groupBySql) {
|
|
537
|
+
const hasJoins = Boolean(joinClauses && joinClauses.length > 0);
|
|
538
|
+
const tableIndex = getTableIndex(manifestIndex, table.accessor);
|
|
539
|
+
const selectCols = hasJoins
|
|
540
|
+
? buildQualifiedSelectColumns(table, undefined, manifestIndex)
|
|
541
|
+
: buildSelectColumns(table, undefined, manifestIndex);
|
|
333
542
|
let sql = "SELECT ";
|
|
334
543
|
if (distinctOn && distinctOn.length > 0) {
|
|
335
|
-
const distinctCols = distinctOn
|
|
336
|
-
.map((
|
|
337
|
-
|
|
338
|
-
|
|
544
|
+
const distinctCols = columnsByTsNames(tableIndex, table, distinctOn)
|
|
545
|
+
.map((col) => hasJoins
|
|
546
|
+
? `${tableRef(table)}.${quoteIdentifier(col.sqlName)}`
|
|
547
|
+
: quoteIdentifier(col.sqlName))
|
|
339
548
|
.join(", ");
|
|
340
549
|
sql += `DISTINCT ON (${distinctCols}) `;
|
|
341
550
|
}
|
|
342
|
-
sql +=
|
|
551
|
+
sql += selectCols;
|
|
552
|
+
if (extraSelectCols && extraSelectCols.length > 0) {
|
|
553
|
+
sql += `, ${extraSelectCols.join(", ")}`;
|
|
554
|
+
}
|
|
555
|
+
sql += ` FROM ${tableRef(table)}`;
|
|
556
|
+
if (joinClauses && joinClauses.length > 0) {
|
|
557
|
+
sql += ` ${joinClauses.join(" ")}`;
|
|
558
|
+
}
|
|
343
559
|
if (whereSql)
|
|
344
560
|
sql += ` ${whereSql}`;
|
|
561
|
+
if (groupBySql)
|
|
562
|
+
sql += ` ${groupBySql}`;
|
|
345
563
|
if (orderSql)
|
|
346
564
|
sql += ` ${orderSql}`;
|
|
347
|
-
if (limit !== undefined)
|
|
348
|
-
sql += ` LIMIT ${limit}`;
|
|
349
|
-
|
|
350
|
-
|
|
565
|
+
if (limit !== undefined) {
|
|
566
|
+
sql += ` LIMIT ${normalizeLimitOffset(limit, "limit")}`;
|
|
567
|
+
}
|
|
568
|
+
if (offset !== undefined) {
|
|
569
|
+
sql += ` OFFSET ${normalizeLimitOffset(offset, "offset")}`;
|
|
570
|
+
}
|
|
351
571
|
return sql;
|
|
352
572
|
}
|
|
353
|
-
export function buildPaginateQuery(table, whereSql, orderSql, take) {
|
|
354
|
-
return buildFindManyQuery(table, whereSql, orderSql, take + 1);
|
|
573
|
+
export function buildPaginateQuery(table, whereSql, orderSql, take, extraSelectCols, joinClauses, manifestIndex) {
|
|
574
|
+
return buildFindManyQuery(table, whereSql, orderSql, take + 1, undefined, undefined, extraSelectCols, joinClauses, manifestIndex);
|
|
355
575
|
}
|
|
356
|
-
export function buildCountQuery(table, whereSql) {
|
|
357
|
-
let sql = `SELECT COUNT(*)
|
|
576
|
+
export function buildCountQuery(table, whereSql, dialect = postgresDialect) {
|
|
577
|
+
let sql = `SELECT ${dialect.castToInt("COUNT(*)")} AS count FROM ${tableRef(table)}`;
|
|
358
578
|
if (whereSql)
|
|
359
579
|
sql += ` ${whereSql}`;
|
|
360
580
|
return sql;
|
|
361
581
|
}
|
|
362
|
-
function aggregateSqlCol(table, tsName) {
|
|
363
|
-
const
|
|
582
|
+
function aggregateSqlCol(table, tsName, dialect, manifestIndex) {
|
|
583
|
+
const tableIndex = getTableIndex(manifestIndex, table.accessor);
|
|
584
|
+
const col = columnByTsName(tableIndex, table, tsName);
|
|
364
585
|
if (!col)
|
|
365
586
|
return undefined;
|
|
366
587
|
const sqlCol = quoteIdentifier(col.sqlName);
|
|
367
588
|
if (col.kind === "decimal")
|
|
368
|
-
return
|
|
589
|
+
return dialect.castToNumeric(sqlCol);
|
|
369
590
|
return sqlCol;
|
|
370
591
|
}
|
|
371
|
-
export function buildAggregateQuery(table, selectors, whereSql) {
|
|
592
|
+
export function buildAggregateQuery(table, selectors, whereSql, manifestIndex, dialect = postgresDialect) {
|
|
372
593
|
const parts = [];
|
|
373
594
|
if (selectors._count) {
|
|
374
|
-
parts.push(
|
|
595
|
+
parts.push(`${dialect.castToInt("COUNT(*)")} AS "__count"`);
|
|
375
596
|
}
|
|
376
597
|
for (const colName of Object.keys(selectors._avg ?? {})) {
|
|
377
|
-
const sqlCol = aggregateSqlCol(table, colName);
|
|
598
|
+
const sqlCol = aggregateSqlCol(table, colName, dialect, manifestIndex);
|
|
378
599
|
if (sqlCol)
|
|
379
600
|
parts.push(`AVG(${sqlCol}) AS "_avg_${colName}"`);
|
|
380
601
|
}
|
|
381
602
|
for (const colName of Object.keys(selectors._sum ?? {})) {
|
|
382
|
-
const sqlCol = aggregateSqlCol(table, colName);
|
|
603
|
+
const sqlCol = aggregateSqlCol(table, colName, dialect, manifestIndex);
|
|
383
604
|
if (sqlCol)
|
|
384
605
|
parts.push(`SUM(${sqlCol}) AS "_sum_${colName}"`);
|
|
385
606
|
}
|
|
386
607
|
for (const colName of Object.keys(selectors._min ?? {})) {
|
|
387
|
-
const sqlCol = aggregateSqlCol(table, colName);
|
|
608
|
+
const sqlCol = aggregateSqlCol(table, colName, dialect, manifestIndex);
|
|
388
609
|
if (sqlCol)
|
|
389
610
|
parts.push(`MIN(${sqlCol}) AS "_min_${colName}"`);
|
|
390
611
|
}
|
|
391
612
|
for (const colName of Object.keys(selectors._max ?? {})) {
|
|
392
|
-
const sqlCol = aggregateSqlCol(table, colName);
|
|
613
|
+
const sqlCol = aggregateSqlCol(table, colName, dialect, manifestIndex);
|
|
393
614
|
if (sqlCol)
|
|
394
615
|
parts.push(`MAX(${sqlCol}) AS "_max_${colName}"`);
|
|
395
616
|
}
|
|
@@ -401,54 +622,118 @@ export function buildAggregateQuery(table, selectors, whereSql) {
|
|
|
401
622
|
sql += ` ${whereSql}`;
|
|
402
623
|
return sql;
|
|
403
624
|
}
|
|
404
|
-
export function
|
|
625
|
+
export function aggregateSelectorCacheKey(selectors) {
|
|
626
|
+
const parts = [];
|
|
627
|
+
if (selectors._count)
|
|
628
|
+
parts.push("_count");
|
|
629
|
+
for (const key of ["_avg", "_sum", "_min", "_max"]) {
|
|
630
|
+
const fieldMap = selectors[key];
|
|
631
|
+
if (!fieldMap)
|
|
632
|
+
continue;
|
|
633
|
+
parts.push(`${key}:${Object.keys(fieldMap).sort().join(",")}`);
|
|
634
|
+
}
|
|
635
|
+
return parts.join("|");
|
|
636
|
+
}
|
|
637
|
+
export function getCachedAggregateQuery(tableIndex, table, selectors, whereSql, manifestIndex, dialect = postgresDialect) {
|
|
638
|
+
const cacheKey = `${dialect.name}|${aggregateSelectorCacheKey(selectors)}|${whereSql}`;
|
|
639
|
+
if (!tableIndex) {
|
|
640
|
+
return buildAggregateQuery(table, selectors, whereSql, manifestIndex, dialect);
|
|
641
|
+
}
|
|
642
|
+
return getOrSetSqlCache(tableIndex.aggregateSqlBySelector, cacheKey, () => buildAggregateQuery(table, selectors, whereSql, manifestIndex, dialect));
|
|
643
|
+
}
|
|
644
|
+
export function buildUpsertQuery(table, insertKeys, updateKeys, conflictSqlColumns, exprSets = [], manifestIndex) {
|
|
405
645
|
const insertCols = insertKeys.map((k) => {
|
|
406
|
-
const col = table
|
|
646
|
+
const col = colByTs(table, k, manifestIndex);
|
|
407
647
|
return quoteIdentifier(col?.sqlName ?? k);
|
|
408
648
|
});
|
|
409
649
|
const insertPlaceholders = insertKeys
|
|
410
650
|
.map((k, i) => {
|
|
411
|
-
const col = table
|
|
651
|
+
const col = colByTs(table, k, manifestIndex);
|
|
412
652
|
return buildValuePlaceholder(col, i + 1);
|
|
413
653
|
})
|
|
414
654
|
.join(", ");
|
|
415
|
-
const selectCols = buildSelectColumns(table);
|
|
655
|
+
const selectCols = buildSelectColumns(table, undefined, manifestIndex);
|
|
416
656
|
const conflictCols = conflictSqlColumns
|
|
417
657
|
.map((c) => quoteIdentifier(c))
|
|
418
658
|
.join(", ");
|
|
419
659
|
const updateSets = updateKeys.length > 0
|
|
420
660
|
? updateKeys.map((k) => {
|
|
421
|
-
const col = table
|
|
661
|
+
const col = colByTs(table, k, manifestIndex);
|
|
422
662
|
const sqlCol = quoteIdentifier(col?.sqlName ?? k);
|
|
423
|
-
return `${sqlCol} =
|
|
663
|
+
return `${sqlCol} = excluded.${sqlCol}`;
|
|
424
664
|
})
|
|
425
665
|
: exprSets.length === 0
|
|
426
666
|
? conflictSqlColumns.map((c) => {
|
|
427
667
|
const sqlCol = quoteIdentifier(c);
|
|
428
|
-
return `${sqlCol} =
|
|
668
|
+
return `${sqlCol} = excluded.${sqlCol}`;
|
|
429
669
|
})
|
|
430
670
|
: [];
|
|
431
671
|
const allUpdateSets = [...updateSets, ...exprSets];
|
|
432
672
|
return `INSERT INTO ${tableRef(table)} (${insertCols.join(", ")}) VALUES (${insertPlaceholders}) ON CONFLICT (${conflictCols}) DO UPDATE SET ${allUpdateSets.join(", ")} RETURNING ${selectCols}`;
|
|
433
673
|
}
|
|
434
|
-
export
|
|
674
|
+
export const FIND_OR_CREATE_FLAG = "__neoorm_created";
|
|
675
|
+
export function buildFindOrCreateQuery(table, insertKeys, conflictSqlColumns, fallbackWhereBody, manifestIndex) {
|
|
676
|
+
const insertCols = insertKeys.map((k) => {
|
|
677
|
+
const col = colByTs(table, k, manifestIndex);
|
|
678
|
+
return quoteIdentifier(col?.sqlName ?? k);
|
|
679
|
+
});
|
|
680
|
+
const insertPlaceholders = insertKeys
|
|
681
|
+
.map((k, i) => {
|
|
682
|
+
const col = colByTs(table, k, manifestIndex);
|
|
683
|
+
return buildValuePlaceholder(col, i + 1);
|
|
684
|
+
})
|
|
685
|
+
.join(", ");
|
|
686
|
+
const selectCols = buildSelectColumns(table, undefined, manifestIndex);
|
|
687
|
+
const conflictCols = conflictSqlColumns
|
|
688
|
+
.map((c) => quoteIdentifier(c))
|
|
689
|
+
.join(", ");
|
|
690
|
+
const tableSql = tableRef(table);
|
|
691
|
+
const fallbackClause = fallbackWhereBody
|
|
692
|
+
? ` AND (${fallbackWhereBody})`
|
|
693
|
+
: "";
|
|
694
|
+
return `WITH ins AS (
|
|
695
|
+
INSERT INTO ${tableSql} (${insertCols.join(", ")}) VALUES (${insertPlaceholders})
|
|
696
|
+
ON CONFLICT (${conflictCols}) DO NOTHING
|
|
697
|
+
RETURNING ${selectCols}
|
|
698
|
+
)
|
|
699
|
+
SELECT ${selectCols}, true AS "${FIND_OR_CREATE_FLAG}" FROM ins
|
|
700
|
+
UNION ALL
|
|
701
|
+
SELECT ${selectCols}, false AS "${FIND_OR_CREATE_FLAG}" FROM ${tableSql} t
|
|
702
|
+
WHERE NOT EXISTS (SELECT 1 FROM ins)${fallbackClause}
|
|
703
|
+
LIMIT 1`;
|
|
704
|
+
}
|
|
705
|
+
export function buildInsertQuery(table, dataKeys, manifestIndex, returning = "pk") {
|
|
435
706
|
if (dataKeys.length === 0) {
|
|
436
707
|
throw new Error("Cannot build INSERT query with no columns");
|
|
437
708
|
}
|
|
438
|
-
const
|
|
439
|
-
|
|
709
|
+
const orderedKeys = [...dataKeys].sort();
|
|
710
|
+
const cols = orderedKeys.map((k) => {
|
|
711
|
+
const col = colByTs(table, k, manifestIndex);
|
|
440
712
|
return quoteIdentifier(col?.sqlName ?? k);
|
|
441
713
|
});
|
|
442
|
-
const placeholders =
|
|
714
|
+
const placeholders = orderedKeys
|
|
443
715
|
.map((k, i) => {
|
|
444
|
-
const col = table
|
|
716
|
+
const col = colByTs(table, k, manifestIndex);
|
|
445
717
|
return buildValuePlaceholder(col, i + 1);
|
|
446
718
|
})
|
|
447
719
|
.join(", ");
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
720
|
+
let sql = `INSERT INTO ${tableRef(table)} (${cols.join(", ")}) VALUES (${placeholders})`;
|
|
721
|
+
if (returning === "none")
|
|
722
|
+
return sql;
|
|
723
|
+
const returningCols = returning === "full"
|
|
724
|
+
? buildSelectColumns(table, undefined, manifestIndex)
|
|
725
|
+
: buildReturningPkColumns(table, manifestIndex);
|
|
726
|
+
return `${sql} RETURNING ${returningCols}`;
|
|
727
|
+
}
|
|
728
|
+
export function getCachedInsertQuery(tableIndex, table, dataKeys, returning, manifestIndex) {
|
|
729
|
+
const orderedKeys = [...dataKeys].sort();
|
|
730
|
+
const cacheKey = `${sortedKeysCacheKey(orderedKeys)}:${returning}`;
|
|
731
|
+
if (!tableIndex) {
|
|
732
|
+
return buildInsertQuery(table, orderedKeys, manifestIndex, returning);
|
|
733
|
+
}
|
|
734
|
+
return getOrSetSqlCache(tableIndex.insertSqlByKeys, cacheKey, () => buildInsertQuery(table, orderedKeys, manifestIndex, returning));
|
|
735
|
+
}
|
|
736
|
+
export function buildInsertManyValueRows(table, dataKeys, rows, manifestIndex) {
|
|
452
737
|
if (dataKeys.length === 0) {
|
|
453
738
|
throw new Error("Cannot build INSERT many value rows with no columns");
|
|
454
739
|
}
|
|
@@ -462,7 +747,7 @@ export function buildInsertManyValueRows(table, dataKeys, rows) {
|
|
|
462
747
|
if (key === undefined) {
|
|
463
748
|
throw new Error("dataKeys index out of bounds");
|
|
464
749
|
}
|
|
465
|
-
const col = table
|
|
750
|
+
const col = colByTs(table, key, manifestIndex);
|
|
466
751
|
const val = row[i];
|
|
467
752
|
if (val === undefined) {
|
|
468
753
|
placeholders.push("DEFAULT");
|
|
@@ -477,37 +762,50 @@ export function buildInsertManyValueRows(table, dataKeys, rows) {
|
|
|
477
762
|
}
|
|
478
763
|
return { valueRows, values };
|
|
479
764
|
}
|
|
480
|
-
export function buildInsertManyQuery(table, dataKeys, valueRows) {
|
|
765
|
+
export function buildInsertManyQuery(table, dataKeys, valueRows, manifestIndex) {
|
|
481
766
|
if (dataKeys.length === 0) {
|
|
482
767
|
throw new Error("Cannot build INSERT many query with no columns");
|
|
483
768
|
}
|
|
484
769
|
const cols = dataKeys.map((k) => {
|
|
485
|
-
const col = table
|
|
770
|
+
const col = colByTs(table, k, manifestIndex);
|
|
486
771
|
return quoteIdentifier(col?.sqlName ?? k);
|
|
487
772
|
});
|
|
488
|
-
const selectCols = buildSelectColumns(table);
|
|
773
|
+
const selectCols = buildSelectColumns(table, undefined, manifestIndex);
|
|
489
774
|
return `INSERT INTO ${tableRef(table)} (${cols.join(", ")}) VALUES ${valueRows.join(", ")} RETURNING ${selectCols}`;
|
|
490
775
|
}
|
|
491
|
-
export function buildUpdateQuery(table, dataKeys, whereSql, exprSets = []) {
|
|
492
|
-
const
|
|
493
|
-
|
|
776
|
+
export function buildUpdateQuery(table, dataKeys, whereSql, exprSets = [], manifestIndex, returning = "full") {
|
|
777
|
+
const orderedKeys = [...dataKeys].sort();
|
|
778
|
+
const paramSets = orderedKeys.map((k, i) => {
|
|
779
|
+
const col = colByTs(table, k, manifestIndex);
|
|
494
780
|
return buildSetExpression(col, i + 1);
|
|
495
781
|
});
|
|
496
782
|
const sets = [...paramSets, ...exprSets];
|
|
497
|
-
const
|
|
498
|
-
const whereOffset = dataKeys.length;
|
|
783
|
+
const whereOffset = orderedKeys.length;
|
|
499
784
|
let sql = `UPDATE ${tableRef(table)} SET ${sets.join(", ")}`;
|
|
500
785
|
if (whereSql) {
|
|
501
|
-
const adjustedWhere = whereSql
|
|
502
|
-
return `$${Number(n) + whereOffset}`;
|
|
503
|
-
});
|
|
786
|
+
const adjustedWhere = rebaseParamRefs(whereSql, whereOffset);
|
|
504
787
|
sql += ` ${adjustedWhere}`;
|
|
505
788
|
}
|
|
506
|
-
|
|
507
|
-
|
|
789
|
+
if (returning === "none")
|
|
790
|
+
return sql;
|
|
791
|
+
const returningCols = returning === "full"
|
|
792
|
+
? buildSelectColumns(table, undefined, manifestIndex)
|
|
793
|
+
: buildReturningPkColumns(table, manifestIndex);
|
|
794
|
+
return `${sql} RETURNING ${returningCols}`;
|
|
795
|
+
}
|
|
796
|
+
export function buildReturningPkColumns(table, manifestIndex) {
|
|
797
|
+
const tableIndex = getTableIndex(manifestIndex, table.accessor);
|
|
798
|
+
return table.primaryKey
|
|
799
|
+
.map((sqlName) => {
|
|
800
|
+
const col = columnBySqlName(tableIndex, table, sqlName);
|
|
801
|
+
return quoteIdentifier(col?.sqlName ?? sqlName);
|
|
802
|
+
})
|
|
803
|
+
.join(", ");
|
|
508
804
|
}
|
|
509
|
-
export function buildDeleteQuery(table, whereSql) {
|
|
510
|
-
const selectCols =
|
|
805
|
+
export function buildDeleteQuery(table, whereSql, returning, manifestIndex) {
|
|
806
|
+
const selectCols = returning === "full"
|
|
807
|
+
? buildSelectColumns(table, undefined, manifestIndex)
|
|
808
|
+
: buildReturningPkColumns(table, manifestIndex);
|
|
511
809
|
let sql = `DELETE FROM ${tableRef(table)}`;
|
|
512
810
|
if (whereSql)
|
|
513
811
|
sql += ` ${whereSql}`;
|
|
@@ -520,27 +818,40 @@ export function buildDeleteManyQuery(table, whereSql) {
|
|
|
520
818
|
sql += ` ${whereSql}`;
|
|
521
819
|
return sql;
|
|
522
820
|
}
|
|
523
|
-
export function buildUpdateManyQuery(table, dataKeys, whereSql, exprSets = []) {
|
|
524
|
-
const
|
|
525
|
-
|
|
821
|
+
export function buildUpdateManyQuery(table, dataKeys, whereSql, exprSets = [], manifestIndex) {
|
|
822
|
+
const orderedKeys = [...dataKeys].sort();
|
|
823
|
+
const paramSets = orderedKeys.map((k, i) => {
|
|
824
|
+
const col = colByTs(table, k, manifestIndex);
|
|
526
825
|
return buildSetExpression(col, i + 1);
|
|
527
826
|
});
|
|
528
827
|
const sets = [...paramSets, ...exprSets];
|
|
529
|
-
const whereOffset =
|
|
828
|
+
const whereOffset = orderedKeys.length;
|
|
530
829
|
let sql = `UPDATE ${tableRef(table)} SET ${sets.join(", ")}`;
|
|
531
830
|
if (whereSql) {
|
|
532
|
-
const adjustedWhere = whereSql
|
|
533
|
-
return `$${Number(n) + whereOffset}`;
|
|
534
|
-
});
|
|
831
|
+
const adjustedWhere = rebaseParamRefs(whereSql, whereOffset);
|
|
535
832
|
sql += ` ${adjustedWhere}`;
|
|
536
833
|
}
|
|
537
834
|
return sql;
|
|
538
835
|
}
|
|
539
|
-
export function
|
|
836
|
+
export function getCachedUpdateManyQuery(tableIndex, table, dataKeys, whereSql, exprSets, manifestIndex) {
|
|
837
|
+
const orderedKeys = [...dataKeys].sort();
|
|
838
|
+
const cacheKey = `${sortedKeysCacheKey(orderedKeys)}|${exprSets.length}|${whereSql}`;
|
|
839
|
+
if (!tableIndex) {
|
|
840
|
+
return buildUpdateManyQuery(table, orderedKeys, whereSql, exprSets, manifestIndex);
|
|
841
|
+
}
|
|
842
|
+
return getOrSetSqlCache(tableIndex.updateManySqlByKeys, cacheKey, () => buildUpdateManyQuery(table, orderedKeys, whereSql, exprSets, manifestIndex));
|
|
843
|
+
}
|
|
844
|
+
export function getCachedFindManyQuery(tableIndex, signature, build) {
|
|
845
|
+
if (!tableIndex)
|
|
846
|
+
return build();
|
|
847
|
+
return getOrSetSqlCache(tableIndex.findManySqlBySignature, signature, build);
|
|
848
|
+
}
|
|
849
|
+
export function dataToSqlValues(table, data, options, manifestIndex, dialect = postgresDialect) {
|
|
850
|
+
const tableIndex = getTableIndex(manifestIndex, table.accessor);
|
|
540
851
|
const keys = [];
|
|
541
852
|
const values = [];
|
|
542
853
|
for (const [key, value] of Object.entries(data)) {
|
|
543
|
-
const col =
|
|
854
|
+
const col = columnByTsName(tableIndex, table, key);
|
|
544
855
|
if (!col)
|
|
545
856
|
continue;
|
|
546
857
|
if (options?.excludePrimary && col.primary)
|
|
@@ -548,9 +859,9 @@ export function dataToSqlValues(table, data, options) {
|
|
|
548
859
|
if (value === undefined)
|
|
549
860
|
continue;
|
|
550
861
|
keys.push(key);
|
|
551
|
-
values.push(serializeColumnValue(col, value));
|
|
862
|
+
values.push(serializeColumnValue(col, value, dialect));
|
|
552
863
|
}
|
|
553
|
-
return
|
|
864
|
+
return reorderKeyValues(keys, values);
|
|
554
865
|
}
|
|
555
866
|
export function rowToTs(table, row) {
|
|
556
867
|
const result = {};
|
|
@@ -569,7 +880,84 @@ export function rowToTs(table, row) {
|
|
|
569
880
|
}
|
|
570
881
|
return result;
|
|
571
882
|
}
|
|
883
|
+
function rowHasSqlNames(index, row) {
|
|
884
|
+
for (const col of index.renameColumns) {
|
|
885
|
+
if (col.sqlName !== col.tsName && col.sqlName in row) {
|
|
886
|
+
return true;
|
|
887
|
+
}
|
|
888
|
+
}
|
|
889
|
+
return false;
|
|
890
|
+
}
|
|
891
|
+
export function rowToTsIndexed(index, table, row) {
|
|
892
|
+
if (index.selectUsesColumnAliases && !rowHasSqlNames(index, row)) {
|
|
893
|
+
if (index.deserializeColumns.length === 0) {
|
|
894
|
+
return row;
|
|
895
|
+
}
|
|
896
|
+
const result = { ...row };
|
|
897
|
+
for (const col of index.deserializeColumns) {
|
|
898
|
+
const key = col.tsName in row ? col.tsName : col.sqlName;
|
|
899
|
+
if (key in row) {
|
|
900
|
+
const plugin = getColumnType(col.kind);
|
|
901
|
+
if (plugin?.deserializeValue) {
|
|
902
|
+
result[col.tsName] = plugin.deserializeValue(col, row[key]);
|
|
903
|
+
}
|
|
904
|
+
}
|
|
905
|
+
}
|
|
906
|
+
return result;
|
|
907
|
+
}
|
|
908
|
+
if (!index.needsRowRename && index.deserializeColumns.length === 0) {
|
|
909
|
+
return row;
|
|
910
|
+
}
|
|
911
|
+
if (!index.needsRowRename) {
|
|
912
|
+
const result = { ...row };
|
|
913
|
+
for (const col of index.deserializeColumns) {
|
|
914
|
+
if (col.sqlName in row) {
|
|
915
|
+
const plugin = getColumnType(col.kind);
|
|
916
|
+
if (plugin?.deserializeValue) {
|
|
917
|
+
result[col.tsName] = plugin.deserializeValue(col, row[col.sqlName]);
|
|
918
|
+
}
|
|
919
|
+
}
|
|
920
|
+
}
|
|
921
|
+
return result;
|
|
922
|
+
}
|
|
923
|
+
const result = {};
|
|
924
|
+
for (const col of table.columns) {
|
|
925
|
+
if (col.sqlName in row) {
|
|
926
|
+
result[col.tsName] = row[col.sqlName];
|
|
927
|
+
}
|
|
928
|
+
}
|
|
929
|
+
for (const col of index.deserializeColumns) {
|
|
930
|
+
if (col.sqlName in row) {
|
|
931
|
+
const plugin = getColumnType(col.kind);
|
|
932
|
+
if (plugin?.deserializeValue) {
|
|
933
|
+
result[col.tsName] = plugin.deserializeValue(col, row[col.sqlName]);
|
|
934
|
+
}
|
|
935
|
+
}
|
|
936
|
+
}
|
|
937
|
+
return result;
|
|
938
|
+
}
|
|
939
|
+
export function rowsToTsIndexed(index, table, rows) {
|
|
940
|
+
if (index.selectUsesColumnAliases &&
|
|
941
|
+
index.deserializeColumns.length === 0 &&
|
|
942
|
+
!index.needsRowRename) {
|
|
943
|
+
return rows;
|
|
944
|
+
}
|
|
945
|
+
if (!index.needsRowRename && index.deserializeColumns.length === 0) {
|
|
946
|
+
return rows;
|
|
947
|
+
}
|
|
948
|
+
return rows.map((row) => rowToTsIndexed(index, table, row));
|
|
949
|
+
}
|
|
572
950
|
export function rowsToTs(table, rows) {
|
|
573
951
|
return rows.map((row) => rowToTs(table, row));
|
|
574
952
|
}
|
|
953
|
+
export function mapRowToTs(tableIndex, table, row) {
|
|
954
|
+
return tableIndex
|
|
955
|
+
? rowToTsIndexed(tableIndex, table, row)
|
|
956
|
+
: rowToTs(table, row);
|
|
957
|
+
}
|
|
958
|
+
export function mapRowsToTs(tableIndex, table, rows) {
|
|
959
|
+
return tableIndex
|
|
960
|
+
? rowsToTsIndexed(tableIndex, table, rows)
|
|
961
|
+
: rowsToTs(table, rows);
|
|
962
|
+
}
|
|
575
963
|
//# sourceMappingURL=compile.js.map
|