@graffy/pg 0.15.25-alpha.1 → 0.15.25-alpha.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/index.cjs +194 -169
- package/index.mjs +105 -76
- package/package.json +3 -3
- package/types/sql/getArgSql.d.ts +1 -1
package/index.cjs
CHANGED
|
@@ -1,43 +1,13 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
if (__getOwnPropSymbols)
|
|
12
|
-
for (var prop of __getOwnPropSymbols(b)) {
|
|
13
|
-
if (__propIsEnum.call(b, prop))
|
|
14
|
-
__defNormalProp(a, prop, b[prop]);
|
|
15
|
-
}
|
|
16
|
-
return a;
|
|
17
|
-
};
|
|
18
|
-
var __objRest = (source, exclude) => {
|
|
19
|
-
var target = {};
|
|
20
|
-
for (var prop in source)
|
|
21
|
-
if (__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0)
|
|
22
|
-
target[prop] = source[prop];
|
|
23
|
-
if (source != null && __getOwnPropSymbols)
|
|
24
|
-
for (var prop of __getOwnPropSymbols(source)) {
|
|
25
|
-
if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop))
|
|
26
|
-
target[prop] = source[prop];
|
|
27
|
-
}
|
|
28
|
-
return target;
|
|
29
|
-
};
|
|
30
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
31
|
-
exports[Symbol.toStringTag] = "Module";
|
|
32
|
-
var common = require("@graffy/common");
|
|
33
|
-
var pg$1 = require("pg");
|
|
34
|
-
var sql = require("sql-template-tag");
|
|
35
|
-
var debug = require("debug");
|
|
36
|
-
function _interopDefaultLegacy(e) {
|
|
37
|
-
return e && typeof e === "object" && "default" in e ? e : { "default": e };
|
|
38
|
-
}
|
|
39
|
-
var sql__default = /* @__PURE__ */ _interopDefaultLegacy(sql);
|
|
40
|
-
var debug__default = /* @__PURE__ */ _interopDefaultLegacy(debug);
|
|
2
|
+
Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toStringTag]: { value: "Module" } });
|
|
3
|
+
const common = require("@graffy/common");
|
|
4
|
+
const pg$1 = require("pg");
|
|
5
|
+
const sql = require("sql-template-tag");
|
|
6
|
+
const debug = require("debug");
|
|
7
|
+
const _interopDefaultLegacy = (e) => e && typeof e === "object" && "default" in e ? e : { default: e };
|
|
8
|
+
const pg__default = /* @__PURE__ */ _interopDefaultLegacy(pg$1);
|
|
9
|
+
const sql__default = /* @__PURE__ */ _interopDefaultLegacy(sql);
|
|
10
|
+
const debug__default = /* @__PURE__ */ _interopDefaultLegacy(debug);
|
|
41
11
|
const valid = {
|
|
42
12
|
$eq: true,
|
|
43
13
|
$lt: true,
|
|
@@ -129,22 +99,27 @@ function simplify(node) {
|
|
|
129
99
|
return !node[1];
|
|
130
100
|
}
|
|
131
101
|
if (op === "$or") {
|
|
132
|
-
const { eqmap, noneq, change } = node[1].reduce(
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
acc.
|
|
137
|
-
|
|
102
|
+
const { eqmap, noneq, change } = node[1].reduce(
|
|
103
|
+
(acc, item) => {
|
|
104
|
+
if (item[0] !== "$eq") {
|
|
105
|
+
acc.noneq.push(item);
|
|
106
|
+
} else if (acc.eqmap[item[1]]) {
|
|
107
|
+
acc.change = true;
|
|
108
|
+
acc.eqmap[item[1]].push(item[2]);
|
|
109
|
+
return acc;
|
|
110
|
+
} else {
|
|
111
|
+
acc.eqmap[item[1]] = [item[2]];
|
|
112
|
+
}
|
|
138
113
|
return acc;
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
return acc;
|
|
143
|
-
}, { eqmap: {}, noneq: [], change: false });
|
|
114
|
+
},
|
|
115
|
+
{ eqmap: {}, noneq: [], change: false }
|
|
116
|
+
);
|
|
144
117
|
if (change) {
|
|
145
118
|
node[1] = [
|
|
146
119
|
...noneq,
|
|
147
|
-
...Object.entries(eqmap).map(
|
|
120
|
+
...Object.entries(eqmap).map(
|
|
121
|
+
([prop, val]) => val.length > 1 ? ["$in", prop, val] : ["$eq", prop, val[0]]
|
|
122
|
+
)
|
|
148
123
|
];
|
|
149
124
|
}
|
|
150
125
|
}
|
|
@@ -159,60 +134,71 @@ function simplify(node) {
|
|
|
159
134
|
return node;
|
|
160
135
|
}
|
|
161
136
|
const getJsonBuildTrusted = (variadic) => {
|
|
162
|
-
const args = sql.join(
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
137
|
+
const args = sql.join(
|
|
138
|
+
Object.entries(variadic).map(([name, value]) => {
|
|
139
|
+
return sql__default.default`'${sql.raw(name)}', ${getJsonBuildValue(value)}`;
|
|
140
|
+
})
|
|
141
|
+
);
|
|
142
|
+
return sql__default.default`jsonb_build_object(${args})`;
|
|
166
143
|
};
|
|
167
144
|
const getJsonBuildValue = (value) => {
|
|
168
145
|
if (value instanceof sql.Sql)
|
|
169
146
|
return value;
|
|
170
147
|
if (typeof value === "string")
|
|
171
|
-
return sql__default
|
|
172
|
-
return sql__default
|
|
148
|
+
return sql__default.default`${value}::text`;
|
|
149
|
+
return sql__default.default`${JSON.stringify(stripAttributes(value))}::jsonb`;
|
|
173
150
|
};
|
|
174
151
|
const lookup = (prop) => {
|
|
175
152
|
const [prefix, ...suffix] = common.encodePath(prop);
|
|
176
|
-
return suffix.length ? sql__default
|
|
153
|
+
return suffix.length ? sql__default.default`"${sql.raw(prefix)}" #> ${suffix}` : sql__default.default`"${sql.raw(prefix)}"`;
|
|
177
154
|
};
|
|
178
155
|
const lookupNumeric = (prop) => {
|
|
179
156
|
const [prefix, ...suffix] = common.encodePath(prop);
|
|
180
|
-
return suffix.length ? sql__default
|
|
157
|
+
return suffix.length ? sql__default.default`CASE WHEN "${sql.raw(prefix)}" #> ${suffix} = 'null'::jsonb THEN 0 ELSE ("${sql.raw(
|
|
158
|
+
prefix
|
|
159
|
+
)}" #> ${suffix})::numeric END` : sql__default.default`"${sql.raw(prefix)}"`;
|
|
181
160
|
};
|
|
182
161
|
const aggSql = {
|
|
183
|
-
$sum: (prop) => sql__default
|
|
184
|
-
$card: (prop) => sql__default
|
|
185
|
-
$avg: (prop) => sql__default
|
|
186
|
-
$max: (prop) => sql__default
|
|
187
|
-
$min: (prop) => sql__default
|
|
162
|
+
$sum: (prop) => sql__default.default`sum((${lookupNumeric(prop)})::numeric)`,
|
|
163
|
+
$card: (prop) => sql__default.default`count(distinct(${lookup(prop)}))`,
|
|
164
|
+
$avg: (prop) => sql__default.default`avg((${lookupNumeric(prop)})::numeric)`,
|
|
165
|
+
$max: (prop) => sql__default.default`max((${lookupNumeric(prop)})::numeric)`,
|
|
166
|
+
$min: (prop) => sql__default.default`min((${lookupNumeric(prop)})::numeric)`
|
|
188
167
|
};
|
|
189
168
|
const getSelectCols = (table, projection = null) => {
|
|
190
169
|
if (!projection)
|
|
191
|
-
return sql__default
|
|
170
|
+
return sql__default.default`*`;
|
|
192
171
|
const sqls = [];
|
|
193
172
|
for (const key in projection) {
|
|
194
173
|
if (key === "$count") {
|
|
195
|
-
sqls.push(sql__default
|
|
174
|
+
sqls.push(sql__default.default`count(*) AS "$count"`);
|
|
196
175
|
} else if (aggSql[key]) {
|
|
197
176
|
const subSqls = [];
|
|
198
177
|
for (const prop in projection[key]) {
|
|
199
|
-
subSqls.push(sql__default
|
|
178
|
+
subSqls.push(sql__default.default`${prop}::text, ${aggSql[key](prop)}`);
|
|
200
179
|
}
|
|
201
|
-
sqls.push(
|
|
180
|
+
sqls.push(
|
|
181
|
+
sql__default.default`jsonb_build_object(${sql.join(subSqls, ", ")}) AS "${sql.raw(key)}"`
|
|
182
|
+
);
|
|
202
183
|
} else {
|
|
203
|
-
sqls.push(sql__default
|
|
184
|
+
sqls.push(sql__default.default`"${sql.raw(key)}"`);
|
|
204
185
|
}
|
|
205
186
|
}
|
|
206
187
|
return sql.join(sqls, ", ");
|
|
207
188
|
};
|
|
208
189
|
function vertexSql(array, nullValue) {
|
|
209
|
-
return sql__default
|
|
190
|
+
return sql__default.default`array[${sql.join(
|
|
191
|
+
array.map((num) => num === null ? nullValue : num)
|
|
192
|
+
)}]::float8[]`;
|
|
210
193
|
}
|
|
211
194
|
function cubeLiteralSql(value) {
|
|
212
195
|
if (!Array.isArray(value) || !value.length || Array.isArray(value[0]) && value.length !== 2) {
|
|
213
196
|
throw Error("pg.castValue_bad_cube" + JSON.stringify(value));
|
|
214
197
|
}
|
|
215
|
-
return Array.isArray(value[0]) ? sql__default
|
|
198
|
+
return Array.isArray(value[0]) ? sql__default.default`cube(${vertexSql(value[0], sql__default.default`'-Infinity'`)}, ${vertexSql(
|
|
199
|
+
value[1],
|
|
200
|
+
sql__default.default`'Infinity'`
|
|
201
|
+
)})` : sql__default.default`cube(${vertexSql(value, 0)})`;
|
|
216
202
|
}
|
|
217
203
|
function castValue(value, type, name, isPut) {
|
|
218
204
|
if (!type)
|
|
@@ -220,9 +206,9 @@ function castValue(value, type, name, isPut) {
|
|
|
220
206
|
if (value instanceof sql.Sql)
|
|
221
207
|
return value;
|
|
222
208
|
if (value === null)
|
|
223
|
-
return sql__default
|
|
209
|
+
return sql__default.default`NULL`;
|
|
224
210
|
if (type === "jsonb") {
|
|
225
|
-
return isPut ? JSON.stringify(stripAttributes(value)) : sql__default
|
|
211
|
+
return isPut ? JSON.stringify(stripAttributes(value)) : sql__default.default`jsonb_strip_nulls(${getJsonUpdate(value, name, [])})`;
|
|
226
212
|
}
|
|
227
213
|
if (type === "cube")
|
|
228
214
|
return cubeLiteralSql(value);
|
|
@@ -231,26 +217,41 @@ function castValue(value, type, name, isPut) {
|
|
|
231
217
|
const getInsert = (row, options) => {
|
|
232
218
|
const cols = [];
|
|
233
219
|
const vals = [];
|
|
234
|
-
Object.entries(row).filter(([col]) => col !== options.verCol && col[0] !== "$").concat([[options.verCol, sql__default
|
|
235
|
-
cols.push(sql__default
|
|
220
|
+
Object.entries(row).filter(([col]) => col !== options.verCol && col[0] !== "$").concat([[options.verCol, sql__default.default`default`]]).forEach(([col, val]) => {
|
|
221
|
+
cols.push(sql__default.default`"${sql.raw(col)}"`);
|
|
236
222
|
vals.push(castValue(val, options.schema.types[col], col, row.$put));
|
|
237
223
|
});
|
|
238
224
|
return { cols: sql.join(cols, ", "), vals: sql.join(vals, ", ") };
|
|
239
225
|
};
|
|
240
226
|
const getUpdates = (row, options) => {
|
|
241
|
-
return sql.join(
|
|
227
|
+
return sql.join(
|
|
228
|
+
Object.entries(row).filter(([col]) => col !== options.idCol && col[0] !== "$").map(
|
|
229
|
+
([col, val]) => sql__default.default`"${sql.raw(col)}" = ${castValue(
|
|
230
|
+
val,
|
|
231
|
+
options.schema.types[col],
|
|
232
|
+
col,
|
|
233
|
+
row.$put
|
|
234
|
+
)}`
|
|
235
|
+
).concat(sql__default.default`"${sql.raw(options.verCol)}" = default`),
|
|
236
|
+
", "
|
|
237
|
+
);
|
|
242
238
|
};
|
|
243
239
|
function getJsonUpdate(object, col, path) {
|
|
244
240
|
if (!object || typeof object !== "object" || Array.isArray(object) || object.$put) {
|
|
245
241
|
return getJsonBuildValue(object);
|
|
246
242
|
}
|
|
247
|
-
const curr = sql__default
|
|
243
|
+
const curr = sql__default.default`"${sql.raw(col)}"${path.length ? sql__default.default`#>${path}` : sql.empty}`;
|
|
248
244
|
if (common.isEmpty(object))
|
|
249
245
|
return curr;
|
|
250
|
-
return sql__default
|
|
246
|
+
return sql__default.default`(case jsonb_typeof(${curr})
|
|
251
247
|
when 'object' then ${curr}
|
|
252
248
|
else '{}'::jsonb
|
|
253
|
-
end) || jsonb_build_object(${sql.join(
|
|
249
|
+
end) || jsonb_build_object(${sql.join(
|
|
250
|
+
Object.entries(object).map(
|
|
251
|
+
([key, value]) => sql__default.default`${key}::text, ${getJsonUpdate(value, col, path.concat(key))}`
|
|
252
|
+
),
|
|
253
|
+
", "
|
|
254
|
+
)})`;
|
|
254
255
|
}
|
|
255
256
|
function stripAttributes(object) {
|
|
256
257
|
if (typeof object !== "object" || !object)
|
|
@@ -268,50 +269,50 @@ function stripAttributes(object) {
|
|
|
268
269
|
const opSql = {
|
|
269
270
|
$and: `AND`,
|
|
270
271
|
$or: `OR`,
|
|
271
|
-
$not: sql__default
|
|
272
|
-
$eq: sql__default
|
|
273
|
-
$neq: sql__default
|
|
274
|
-
$in: sql__default
|
|
275
|
-
$nin: sql__default
|
|
276
|
-
$lt: sql__default
|
|
277
|
-
$lte: sql__default
|
|
278
|
-
$gt: sql__default
|
|
279
|
-
$gte: sql__default
|
|
280
|
-
$re: sql__default
|
|
281
|
-
$ire: sql__default
|
|
282
|
-
$cts: sql__default
|
|
283
|
-
$ctd: sql__default
|
|
272
|
+
$not: sql__default.default`NOT`,
|
|
273
|
+
$eq: sql__default.default`=`,
|
|
274
|
+
$neq: sql__default.default`<>`,
|
|
275
|
+
$in: sql__default.default`IN`,
|
|
276
|
+
$nin: sql__default.default`NOT IN`,
|
|
277
|
+
$lt: sql__default.default`<`,
|
|
278
|
+
$lte: sql__default.default`<=`,
|
|
279
|
+
$gt: sql__default.default`>`,
|
|
280
|
+
$gte: sql__default.default`>=`,
|
|
281
|
+
$re: sql__default.default`~`,
|
|
282
|
+
$ire: sql__default.default`~*`,
|
|
283
|
+
$cts: sql__default.default`@>`,
|
|
284
|
+
$ctd: sql__default.default`<@`
|
|
284
285
|
};
|
|
285
286
|
function getBinarySql(lhs, type, op, value, textLhs) {
|
|
286
287
|
if (value === null && op === "$eq")
|
|
287
|
-
return sql__default
|
|
288
|
+
return sql__default.default`${lhs} IS NULL`;
|
|
288
289
|
if (value === null && op === "$neq")
|
|
289
|
-
return sql__default
|
|
290
|
+
return sql__default.default`${lhs} IS NOT NULL`;
|
|
290
291
|
const sqlOp = opSql[op];
|
|
291
292
|
if (!sqlOp)
|
|
292
293
|
throw Error("pg.getSql_unknown_operator " + op);
|
|
293
294
|
if (op === "$in" || op === "$nin") {
|
|
294
295
|
if (type === "jsonb" && typeof value[0] === "string")
|
|
295
296
|
lhs = textLhs;
|
|
296
|
-
return sql__default
|
|
297
|
+
return sql__default.default`${lhs} ${sqlOp} (${sql.join(value)})`;
|
|
297
298
|
}
|
|
298
299
|
if (op === "$re" || op === "$ire") {
|
|
299
300
|
if (type === "jsonb") {
|
|
300
301
|
lhs = textLhs;
|
|
301
302
|
} else if (type !== "text") {
|
|
302
|
-
lhs = sql__default
|
|
303
|
+
lhs = sql__default.default`(${lhs})::text`;
|
|
303
304
|
}
|
|
304
|
-
return sql__default
|
|
305
|
+
return sql__default.default`${lhs} ${sqlOp} ${String(value)}`;
|
|
305
306
|
}
|
|
306
307
|
if (type === "jsonb") {
|
|
307
308
|
if (typeof value === "string") {
|
|
308
|
-
return sql__default
|
|
309
|
+
return sql__default.default`${textLhs} ${sqlOp} ${value}`;
|
|
309
310
|
}
|
|
310
|
-
return sql__default
|
|
311
|
+
return sql__default.default`${lhs} ${sqlOp} ${JSON.stringify(value)}::jsonb`;
|
|
311
312
|
}
|
|
312
313
|
if (type === "cube")
|
|
313
|
-
return sql__default
|
|
314
|
-
return sql__default
|
|
314
|
+
return sql__default.default`${lhs} ${sqlOp} ${cubeLiteralSql(value)}`;
|
|
315
|
+
return sql__default.default`${lhs} ${sqlOp} ${value}`;
|
|
315
316
|
}
|
|
316
317
|
function getSql(filter, options) {
|
|
317
318
|
function getNodeSql(ast) {
|
|
@@ -319,41 +320,43 @@ function getSql(filter, options) {
|
|
|
319
320
|
return ast;
|
|
320
321
|
const op = ast[0];
|
|
321
322
|
if (op === "$and" || op === "$or") {
|
|
322
|
-
return sql__default
|
|
323
|
+
return sql__default.default`(${sql.join(
|
|
324
|
+
ast[1].map((node) => getNodeSql(node)),
|
|
325
|
+
`) ${opSql[op]} (`
|
|
326
|
+
)})`;
|
|
323
327
|
} else if (op === "$not") {
|
|
324
|
-
return sql__default
|
|
328
|
+
return sql__default.default`${opSql[op]} (${getNodeSql(ast[1])})`;
|
|
325
329
|
}
|
|
326
330
|
const [prefix, ...suffix] = common.encodePath(ast[1]);
|
|
327
|
-
const { types } = options.schema;
|
|
328
|
-
if (!
|
|
331
|
+
const { types: types2 } = options.schema;
|
|
332
|
+
if (!types2[prefix])
|
|
329
333
|
throw Error("pg.no_column " + prefix);
|
|
330
|
-
if (
|
|
334
|
+
if (types2[prefix] === "jsonb") {
|
|
331
335
|
const [lhs, textLhs] = suffix.length ? [
|
|
332
|
-
sql__default
|
|
333
|
-
sql__default
|
|
334
|
-
] : [sql__default
|
|
336
|
+
sql__default.default`"${sql.raw(prefix)}" #> ${suffix}`,
|
|
337
|
+
sql__default.default`"${sql.raw(prefix)}" #>> ${suffix}`
|
|
338
|
+
] : [sql__default.default`"${sql.raw(prefix)}"`, sql__default.default`"${sql.raw(prefix)}" #>> '{}'`];
|
|
335
339
|
return getBinarySql(lhs, "jsonb", op, ast[2], textLhs);
|
|
336
340
|
} else {
|
|
337
341
|
if (suffix.length)
|
|
338
342
|
throw Error("pg.lookup_not_jsonb " + prefix);
|
|
339
|
-
return getBinarySql(sql__default
|
|
343
|
+
return getBinarySql(sql__default.default`"${sql.raw(prefix)}"`, types2[prefix], op, ast[2]);
|
|
340
344
|
}
|
|
341
345
|
}
|
|
342
346
|
return getNodeSql(getAst(filter));
|
|
343
347
|
}
|
|
344
|
-
const getIdMeta = ({ idCol, verDefault }) => sql__default
|
|
345
|
-
const getArgMeta = (key, { prefix, idCol, verDefault }) => sql__default
|
|
348
|
+
const getIdMeta = ({ idCol, verDefault }) => sql__default.default`"${sql.raw(idCol)}" AS "$key", ${sql.raw(verDefault)} AS "$ver"`;
|
|
349
|
+
const getArgMeta = (key, { prefix, idCol, verDefault }) => sql__default.default`
|
|
346
350
|
${key} AS "$key",
|
|
347
351
|
${sql.raw(verDefault)} AS "$ver",
|
|
348
352
|
array[
|
|
349
|
-
${sql.join(prefix.map((k) => sql__default
|
|
353
|
+
${sql.join(prefix.map((k) => sql__default.default`${k}::text`))},
|
|
350
354
|
"${sql.raw(idCol)}"
|
|
351
355
|
]::text[] AS "$ref"
|
|
352
356
|
`;
|
|
353
|
-
const getAggMeta = (key, { verDefault }) => sql__default
|
|
354
|
-
function getArgSql(
|
|
355
|
-
|
|
356
|
-
const _a2 = rest, { $order, $group } = _a2, filter = __objRest(_a2, ["$order", "$group"]);
|
|
357
|
+
const getAggMeta = (key, { verDefault }) => sql__default.default`${key} AS "$key", ${sql.raw(verDefault)} AS "$ver"`;
|
|
358
|
+
function getArgSql({ $first, $last, $after, $before, $since, $until, $all, $cursor: _, ...rest }, options) {
|
|
359
|
+
const { $order, $group, ...filter } = rest;
|
|
357
360
|
const { prefix, idCol } = options;
|
|
358
361
|
const meta = (key2) => $group ? getAggMeta(key2, options) : getArgMeta(key2, options);
|
|
359
362
|
const hasRangeArg = $before || $after || $since || $until || $first || $last || $all;
|
|
@@ -363,7 +366,7 @@ function getArgSql(_a, options) {
|
|
|
363
366
|
if (($order || $group && $group !== true) && !hasRangeArg) {
|
|
364
367
|
throw Error("pg_arg.range_arg_expected in " + prefix);
|
|
365
368
|
}
|
|
366
|
-
const baseKey = sql__default
|
|
369
|
+
const baseKey = sql__default.default`${JSON.stringify(rest)}::jsonb`;
|
|
367
370
|
const where = [];
|
|
368
371
|
if (!common.isEmpty(filter))
|
|
369
372
|
where.push(getSql(filter, options));
|
|
@@ -371,16 +374,25 @@ function getArgSql(_a, options) {
|
|
|
371
374
|
return { meta: meta(baseKey), where, limit: 1 };
|
|
372
375
|
const groupCols = Array.isArray($group) && $group.length && $group.map(lookup);
|
|
373
376
|
const group = groupCols ? sql.join(groupCols, ", ") : void 0;
|
|
374
|
-
const orderCols = ($order || [idCol]).map(
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
377
|
+
const orderCols = ($order || [idCol]).map(
|
|
378
|
+
(orderItem) => orderItem[0] === "!" ? sql__default.default`-(${lookup(orderItem.slice(1))})::float8` : lookup(orderItem)
|
|
379
|
+
);
|
|
380
|
+
Object.entries({ $after, $before, $since, $until }).forEach(
|
|
381
|
+
([name, value]) => {
|
|
382
|
+
if (value)
|
|
383
|
+
where.push(getBoundCond(orderCols, value, name));
|
|
384
|
+
}
|
|
385
|
+
);
|
|
386
|
+
const order = !$group && sql.join(
|
|
387
|
+
($order || [idCol]).map(
|
|
388
|
+
(orderItem) => orderItem[0] === "!" ? sql__default.default`${lookup(orderItem.slice(1))} ${$last ? sql__default.default`ASC` : sql__default.default`DESC`}` : sql__default.default`${lookup(orderItem)} ${$last ? sql__default.default`DESC` : sql__default.default`ASC`}`
|
|
389
|
+
),
|
|
390
|
+
`, `
|
|
391
|
+
);
|
|
380
392
|
const cursorKey = getJsonBuildTrusted({
|
|
381
|
-
$cursor: $group === true ? sql__default
|
|
393
|
+
$cursor: $group === true ? sql__default.default`''` : sql__default.default`jsonb_build_array(${sql.join(groupCols || orderCols)})`
|
|
382
394
|
});
|
|
383
|
-
const key = sql__default
|
|
395
|
+
const key = sql__default.default`(${baseKey} || ${cursorKey})`;
|
|
384
396
|
return {
|
|
385
397
|
meta: meta(key),
|
|
386
398
|
where,
|
|
@@ -400,21 +412,21 @@ function getBoundCond(orderCols, bound, kind) {
|
|
|
400
412
|
switch (kind) {
|
|
401
413
|
case "$after":
|
|
402
414
|
case "$since":
|
|
403
|
-
return sql__default
|
|
415
|
+
return sql__default.default`${lhs} > ${rhs} OR ${lhs} = ${rhs} AND (${subCond})`;
|
|
404
416
|
case "$before":
|
|
405
417
|
case "$until":
|
|
406
|
-
return sql__default
|
|
418
|
+
return sql__default.default`${lhs} < ${rhs} OR ${lhs} = ${rhs} AND (${subCond})`;
|
|
407
419
|
}
|
|
408
420
|
} else {
|
|
409
421
|
switch (kind) {
|
|
410
422
|
case "$after":
|
|
411
|
-
return sql__default
|
|
423
|
+
return sql__default.default`${lhs} > ${rhs}`;
|
|
412
424
|
case "$since":
|
|
413
|
-
return sql__default
|
|
425
|
+
return sql__default.default`${lhs} >= ${rhs}`;
|
|
414
426
|
case "$before":
|
|
415
|
-
return sql__default
|
|
427
|
+
return sql__default.default`${lhs} < ${rhs}`;
|
|
416
428
|
case "$until":
|
|
417
|
-
return sql__default
|
|
429
|
+
return sql__default.default`${lhs} <= ${rhs}`;
|
|
418
430
|
}
|
|
419
431
|
}
|
|
420
432
|
}
|
|
@@ -423,19 +435,19 @@ function selectByArgs(args, projection, options) {
|
|
|
423
435
|
const { table } = options;
|
|
424
436
|
const { where, order, group, limit, meta } = getArgSql(args, options);
|
|
425
437
|
const clampedLimit = Math.min(MAX_LIMIT, limit || MAX_LIMIT);
|
|
426
|
-
return sql__default
|
|
438
|
+
return sql__default.default`
|
|
427
439
|
SELECT
|
|
428
440
|
${getSelectCols(table, projection)}, ${meta}
|
|
429
441
|
FROM "${sql.raw(table)}"
|
|
430
|
-
${where.length ? sql__default
|
|
431
|
-
${group ? sql__default
|
|
432
|
-
${order ? sql__default
|
|
442
|
+
${where.length ? sql__default.default`WHERE ${sql.join(where, ` AND `)}` : sql.empty}
|
|
443
|
+
${group ? sql__default.default`GROUP BY ${group}` : sql.empty}
|
|
444
|
+
${order ? sql__default.default`ORDER BY ${order}` : sql.empty}
|
|
433
445
|
LIMIT ${clampedLimit}
|
|
434
446
|
`;
|
|
435
447
|
}
|
|
436
448
|
function selectByIds(ids, projection, options) {
|
|
437
449
|
const { table, idCol } = options;
|
|
438
|
-
return sql__default
|
|
450
|
+
return sql__default.default`
|
|
439
451
|
SELECT
|
|
440
452
|
${getSelectCols(table, projection)}, ${getIdMeta(options)}
|
|
441
453
|
FROM "${sql.raw(table)}"
|
|
@@ -446,7 +458,7 @@ function getSingleSql(arg, options) {
|
|
|
446
458
|
const { table, idCol } = options;
|
|
447
459
|
if (!common.isPlainObject(arg)) {
|
|
448
460
|
return {
|
|
449
|
-
where: sql__default
|
|
461
|
+
where: sql__default.default`"${sql.raw(idCol)}" = ${arg}`,
|
|
450
462
|
meta: getIdMeta(options)
|
|
451
463
|
};
|
|
452
464
|
}
|
|
@@ -454,7 +466,7 @@ function getSingleSql(arg, options) {
|
|
|
454
466
|
if (!where || !where.length)
|
|
455
467
|
throw Error("pg_write.no_condition");
|
|
456
468
|
return {
|
|
457
|
-
where: sql__default
|
|
469
|
+
where: sql__default.default`"${sql.raw(idCol)}" = (
|
|
458
470
|
SELECT "${sql.raw(idCol)}"
|
|
459
471
|
FROM "${sql.raw(table)}"
|
|
460
472
|
WHERE ${sql.join(where, ` AND `)}
|
|
@@ -467,10 +479,10 @@ function patch(object, arg, options) {
|
|
|
467
479
|
const { table } = options;
|
|
468
480
|
const { where, meta } = getSingleSql(arg, options);
|
|
469
481
|
const row = object;
|
|
470
|
-
return sql__default
|
|
482
|
+
return sql__default.default`
|
|
471
483
|
UPDATE "${sql.raw(table)}" SET ${getUpdates(row, options)}
|
|
472
484
|
WHERE ${where}
|
|
473
|
-
RETURNING ${getSelectCols(
|
|
485
|
+
RETURNING ${getSelectCols()}, ${meta}`;
|
|
474
486
|
}
|
|
475
487
|
function put(object, arg, options) {
|
|
476
488
|
const { idCol, table } = options;
|
|
@@ -478,32 +490,33 @@ function put(object, arg, options) {
|
|
|
478
490
|
let meta, conflictTarget;
|
|
479
491
|
if (common.isPlainObject(arg)) {
|
|
480
492
|
({ meta } = getArgSql(arg, options));
|
|
481
|
-
conflictTarget = sql.join(Object.keys(arg).map((col) => sql__default
|
|
493
|
+
conflictTarget = sql.join(Object.keys(arg).map((col) => sql__default.default`"${sql.raw(col)}"`));
|
|
482
494
|
} else {
|
|
483
495
|
meta = getIdMeta(options);
|
|
484
|
-
conflictTarget = sql__default
|
|
496
|
+
conflictTarget = sql__default.default`"${sql.raw(idCol)}"`;
|
|
485
497
|
}
|
|
486
498
|
const { cols, vals } = getInsert(row, options);
|
|
487
|
-
return sql__default
|
|
499
|
+
return sql__default.default`
|
|
488
500
|
INSERT INTO "${sql.raw(table)}" (${cols}) VALUES (${vals})
|
|
489
501
|
ON CONFLICT (${conflictTarget}) DO UPDATE SET (${cols}) = (${vals})
|
|
490
|
-
RETURNING ${getSelectCols(
|
|
502
|
+
RETURNING ${getSelectCols()}, ${meta}`;
|
|
491
503
|
}
|
|
492
504
|
function del(arg, options) {
|
|
493
505
|
const { table } = options;
|
|
494
506
|
const { where } = getSingleSql(arg, options);
|
|
495
|
-
return sql__default
|
|
507
|
+
return sql__default.default`
|
|
496
508
|
DELETE FROM "${sql.raw(table)}"
|
|
497
509
|
WHERE ${where}
|
|
498
510
|
RETURNING ${arg} "$key"`;
|
|
499
511
|
}
|
|
500
|
-
const log = debug__default
|
|
512
|
+
const log = debug__default.default("graffy:pg:db");
|
|
513
|
+
const { Pool, Client, types } = pg__default.default;
|
|
501
514
|
class Db {
|
|
502
515
|
constructor(connection) {
|
|
503
|
-
if (typeof connection === "object" && connection && (connection instanceof
|
|
516
|
+
if (typeof connection === "object" && connection && (connection instanceof Pool || connection instanceof Client)) {
|
|
504
517
|
this.client = connection;
|
|
505
518
|
} else {
|
|
506
|
-
this.client = new
|
|
519
|
+
this.client = new Pool(connection);
|
|
507
520
|
}
|
|
508
521
|
}
|
|
509
522
|
async query(sql2) {
|
|
@@ -511,10 +524,10 @@ class Db {
|
|
|
511
524
|
try {
|
|
512
525
|
sql2.types = {
|
|
513
526
|
getTypeParser: (oid, format) => {
|
|
514
|
-
if (oid ===
|
|
527
|
+
if (oid === types.builtins.INT8) {
|
|
515
528
|
return (value) => parseInt(value, 10);
|
|
516
529
|
}
|
|
517
|
-
return
|
|
530
|
+
return types.getTypeParser(oid, format);
|
|
518
531
|
}
|
|
519
532
|
};
|
|
520
533
|
return await this.client.query(sql2);
|
|
@@ -547,21 +560,21 @@ class Db {
|
|
|
547
560
|
if (tableOptions.schema)
|
|
548
561
|
return;
|
|
549
562
|
const { table, verCol } = tableOptions;
|
|
550
|
-
const tableSchema = (await this.query(sql__default
|
|
563
|
+
const tableSchema = (await this.query(sql__default.default`
|
|
551
564
|
SELECT table_schema
|
|
552
565
|
FROM information_schema.tables
|
|
553
566
|
WHERE table_name = ${table}
|
|
554
567
|
ORDER BY array_position(current_schemas(false)::text[], table_schema::text) ASC
|
|
555
568
|
LIMIT 1`)).rows[0].table_schema;
|
|
556
|
-
const
|
|
569
|
+
const types2 = (await this.query(sql__default.default`
|
|
557
570
|
SELECT jsonb_object_agg(column_name, udt_name) AS column_types
|
|
558
571
|
FROM information_schema.columns
|
|
559
572
|
WHERE
|
|
560
573
|
table_name = ${table} AND
|
|
561
574
|
table_schema = ${tableSchema}`)).rows[0].column_types;
|
|
562
|
-
if (!
|
|
575
|
+
if (!types2)
|
|
563
576
|
throw Error(`pg.missing_table ${table}`);
|
|
564
|
-
const verDefault = (await this.query(sql__default
|
|
577
|
+
const verDefault = (await this.query(sql__default.default`
|
|
565
578
|
SELECT column_default
|
|
566
579
|
FROM information_schema.columns
|
|
567
580
|
WHERE
|
|
@@ -571,8 +584,8 @@ class Db {
|
|
|
571
584
|
if (!verDefault) {
|
|
572
585
|
throw Error(`pg.verCol_without_default ${verCol}`);
|
|
573
586
|
}
|
|
574
|
-
log("ensureSchema",
|
|
575
|
-
tableOptions.schema = { types };
|
|
587
|
+
log("ensureSchema", types2);
|
|
588
|
+
tableOptions.schema = { types: types2 };
|
|
576
589
|
tableOptions.verDefault = verDefault;
|
|
577
590
|
}
|
|
578
591
|
async read(rootQuery, tableOptions) {
|
|
@@ -582,13 +595,17 @@ class Db {
|
|
|
582
595
|
const { prefix } = tableOptions;
|
|
583
596
|
await this.ensureSchema(tableOptions);
|
|
584
597
|
const getByArgs = async (args, projection) => {
|
|
585
|
-
const result = await this.readSql(
|
|
598
|
+
const result = await this.readSql(
|
|
599
|
+
selectByArgs(args, projection, tableOptions)
|
|
600
|
+
);
|
|
586
601
|
const wrappedGraph = common.encodeGraph(common.wrapObject(result, prefix));
|
|
587
602
|
log("getByArgs", wrappedGraph);
|
|
588
603
|
common.merge(results, wrappedGraph);
|
|
589
604
|
};
|
|
590
605
|
const getByIds = async () => {
|
|
591
|
-
const result = await this.readSql(
|
|
606
|
+
const result = await this.readSql(
|
|
607
|
+
selectByIds(Object.keys(idQueries), null, tableOptions)
|
|
608
|
+
);
|
|
592
609
|
result.forEach((object) => {
|
|
593
610
|
const wrappedGraph = common.encodeGraph(common.wrapObject(object, prefix));
|
|
594
611
|
log("getByIds", wrappedGraph);
|
|
@@ -603,7 +620,7 @@ class Db {
|
|
|
603
620
|
for (const childNode of node.children) {
|
|
604
621
|
const childArgs = common.decodeArgs(childNode);
|
|
605
622
|
const projection = childNode.children ? common.decodeQuery(childNode.children) : null;
|
|
606
|
-
promises.push(getByArgs(
|
|
623
|
+
promises.push(getByArgs({ ...args, ...childArgs }, projection));
|
|
607
624
|
}
|
|
608
625
|
} else {
|
|
609
626
|
const projection = node.children ? common.decodeQuery(node.children) : null;
|
|
@@ -642,9 +659,13 @@ class Db {
|
|
|
642
659
|
return object.$put ? put(object, arg, tableOptions) : patch(object, arg, tableOptions);
|
|
643
660
|
});
|
|
644
661
|
const result = [];
|
|
645
|
-
await Promise.all(
|
|
646
|
-
|
|
647
|
-
|
|
662
|
+
await Promise.all(
|
|
663
|
+
sqls.map(
|
|
664
|
+
(sql2) => this.writeSql(sql2).then((object) => {
|
|
665
|
+
common.merge(result, common.encodeGraph(common.wrapObject(object, prefix)));
|
|
666
|
+
})
|
|
667
|
+
)
|
|
668
|
+
);
|
|
648
669
|
log("dbWrite", rootChange, result);
|
|
649
670
|
return result;
|
|
650
671
|
}
|
|
@@ -668,9 +689,11 @@ const pg = ({ table, idCol, verCol, connection, schema, verDefault }) => (store)
|
|
|
668
689
|
const readPromise = db.read(query, tableOpts);
|
|
669
690
|
const remainingQuery = common.remove(query, prefix);
|
|
670
691
|
const nextPromise = next(remainingQuery);
|
|
671
|
-
return Promise.all([readPromise, nextPromise]).then(
|
|
672
|
-
|
|
673
|
-
|
|
692
|
+
return Promise.all([readPromise, nextPromise]).then(
|
|
693
|
+
([readRes, nextRes]) => {
|
|
694
|
+
return common.merge(readRes, nextRes);
|
|
695
|
+
}
|
|
696
|
+
);
|
|
674
697
|
}
|
|
675
698
|
function write(change, options, next) {
|
|
676
699
|
const { pgClient } = options;
|
|
@@ -678,9 +701,11 @@ const pg = ({ table, idCol, verCol, connection, schema, verDefault }) => (store)
|
|
|
678
701
|
const writePromise = db.write(change, tableOpts);
|
|
679
702
|
const remainingChange = common.remove(change, prefix);
|
|
680
703
|
const nextPromise = next(remainingChange);
|
|
681
|
-
return Promise.all([writePromise, nextPromise]).then(
|
|
682
|
-
|
|
683
|
-
|
|
704
|
+
return Promise.all([writePromise, nextPromise]).then(
|
|
705
|
+
([writeRes, nextRes]) => {
|
|
706
|
+
return common.merge(writeRes, nextRes);
|
|
707
|
+
}
|
|
708
|
+
);
|
|
684
709
|
}
|
|
685
710
|
};
|
|
686
711
|
exports.pg = pg;
|
package/index.mjs
CHANGED
|
@@ -1,33 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
4
|
-
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
5
|
-
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
6
|
-
var __spreadValues = (a, b) => {
|
|
7
|
-
for (var prop in b || (b = {}))
|
|
8
|
-
if (__hasOwnProp.call(b, prop))
|
|
9
|
-
__defNormalProp(a, prop, b[prop]);
|
|
10
|
-
if (__getOwnPropSymbols)
|
|
11
|
-
for (var prop of __getOwnPropSymbols(b)) {
|
|
12
|
-
if (__propIsEnum.call(b, prop))
|
|
13
|
-
__defNormalProp(a, prop, b[prop]);
|
|
14
|
-
}
|
|
15
|
-
return a;
|
|
16
|
-
};
|
|
17
|
-
var __objRest = (source, exclude) => {
|
|
18
|
-
var target = {};
|
|
19
|
-
for (var prop in source)
|
|
20
|
-
if (__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0)
|
|
21
|
-
target[prop] = source[prop];
|
|
22
|
-
if (source != null && __getOwnPropSymbols)
|
|
23
|
-
for (var prop of __getOwnPropSymbols(source)) {
|
|
24
|
-
if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop))
|
|
25
|
-
target[prop] = source[prop];
|
|
26
|
-
}
|
|
27
|
-
return target;
|
|
28
|
-
};
|
|
29
|
-
import { isEmpty, encodePath, isPlainObject, unwrap, decodeArgs, decodeQuery, finalize, wrap, isRange, decodeGraph, mergeObject, merge, encodeGraph, wrapObject, remove } from "@graffy/common";
|
|
30
|
-
import { Pool, Client, types } from "pg";
|
|
1
|
+
import { encodePath, isEmpty, isPlainObject, unwrap, decodeArgs, decodeQuery, finalize, wrap, isRange, decodeGraph, mergeObject, merge, encodeGraph, wrapObject, remove } from "@graffy/common";
|
|
2
|
+
import pg$1 from "pg";
|
|
31
3
|
import sql, { join, raw, Sql, empty } from "sql-template-tag";
|
|
32
4
|
import debug from "debug";
|
|
33
5
|
const valid = {
|
|
@@ -121,22 +93,27 @@ function simplify(node) {
|
|
|
121
93
|
return !node[1];
|
|
122
94
|
}
|
|
123
95
|
if (op === "$or") {
|
|
124
|
-
const { eqmap, noneq, change } = node[1].reduce(
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
acc.
|
|
129
|
-
|
|
96
|
+
const { eqmap, noneq, change } = node[1].reduce(
|
|
97
|
+
(acc, item) => {
|
|
98
|
+
if (item[0] !== "$eq") {
|
|
99
|
+
acc.noneq.push(item);
|
|
100
|
+
} else if (acc.eqmap[item[1]]) {
|
|
101
|
+
acc.change = true;
|
|
102
|
+
acc.eqmap[item[1]].push(item[2]);
|
|
103
|
+
return acc;
|
|
104
|
+
} else {
|
|
105
|
+
acc.eqmap[item[1]] = [item[2]];
|
|
106
|
+
}
|
|
130
107
|
return acc;
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
return acc;
|
|
135
|
-
}, { eqmap: {}, noneq: [], change: false });
|
|
108
|
+
},
|
|
109
|
+
{ eqmap: {}, noneq: [], change: false }
|
|
110
|
+
);
|
|
136
111
|
if (change) {
|
|
137
112
|
node[1] = [
|
|
138
113
|
...noneq,
|
|
139
|
-
...Object.entries(eqmap).map(
|
|
114
|
+
...Object.entries(eqmap).map(
|
|
115
|
+
([prop, val]) => val.length > 1 ? ["$in", prop, val] : ["$eq", prop, val[0]]
|
|
116
|
+
)
|
|
140
117
|
];
|
|
141
118
|
}
|
|
142
119
|
}
|
|
@@ -151,9 +128,11 @@ function simplify(node) {
|
|
|
151
128
|
return node;
|
|
152
129
|
}
|
|
153
130
|
const getJsonBuildTrusted = (variadic) => {
|
|
154
|
-
const args = join(
|
|
155
|
-
|
|
156
|
-
|
|
131
|
+
const args = join(
|
|
132
|
+
Object.entries(variadic).map(([name, value]) => {
|
|
133
|
+
return sql`'${raw(name)}', ${getJsonBuildValue(value)}`;
|
|
134
|
+
})
|
|
135
|
+
);
|
|
157
136
|
return sql`jsonb_build_object(${args})`;
|
|
158
137
|
};
|
|
159
138
|
const getJsonBuildValue = (value) => {
|
|
@@ -169,7 +148,9 @@ const lookup = (prop) => {
|
|
|
169
148
|
};
|
|
170
149
|
const lookupNumeric = (prop) => {
|
|
171
150
|
const [prefix, ...suffix] = encodePath(prop);
|
|
172
|
-
return suffix.length ? sql`CASE WHEN "${raw(prefix)}" #> ${suffix} = 'null'::jsonb THEN 0 ELSE ("${raw(
|
|
151
|
+
return suffix.length ? sql`CASE WHEN "${raw(prefix)}" #> ${suffix} = 'null'::jsonb THEN 0 ELSE ("${raw(
|
|
152
|
+
prefix
|
|
153
|
+
)}" #> ${suffix})::numeric END` : sql`"${raw(prefix)}"`;
|
|
173
154
|
};
|
|
174
155
|
const aggSql = {
|
|
175
156
|
$sum: (prop) => sql`sum((${lookupNumeric(prop)})::numeric)`,
|
|
@@ -190,7 +171,9 @@ const getSelectCols = (table, projection = null) => {
|
|
|
190
171
|
for (const prop in projection[key]) {
|
|
191
172
|
subSqls.push(sql`${prop}::text, ${aggSql[key](prop)}`);
|
|
192
173
|
}
|
|
193
|
-
sqls.push(
|
|
174
|
+
sqls.push(
|
|
175
|
+
sql`jsonb_build_object(${join(subSqls, ", ")}) AS "${raw(key)}"`
|
|
176
|
+
);
|
|
194
177
|
} else {
|
|
195
178
|
sqls.push(sql`"${raw(key)}"`);
|
|
196
179
|
}
|
|
@@ -198,13 +181,18 @@ const getSelectCols = (table, projection = null) => {
|
|
|
198
181
|
return join(sqls, ", ");
|
|
199
182
|
};
|
|
200
183
|
function vertexSql(array, nullValue) {
|
|
201
|
-
return sql`array[${join(
|
|
184
|
+
return sql`array[${join(
|
|
185
|
+
array.map((num) => num === null ? nullValue : num)
|
|
186
|
+
)}]::float8[]`;
|
|
202
187
|
}
|
|
203
188
|
function cubeLiteralSql(value) {
|
|
204
189
|
if (!Array.isArray(value) || !value.length || Array.isArray(value[0]) && value.length !== 2) {
|
|
205
190
|
throw Error("pg.castValue_bad_cube" + JSON.stringify(value));
|
|
206
191
|
}
|
|
207
|
-
return Array.isArray(value[0]) ? sql`cube(${vertexSql(value[0], sql`'-Infinity'`)}, ${vertexSql(
|
|
192
|
+
return Array.isArray(value[0]) ? sql`cube(${vertexSql(value[0], sql`'-Infinity'`)}, ${vertexSql(
|
|
193
|
+
value[1],
|
|
194
|
+
sql`'Infinity'`
|
|
195
|
+
)})` : sql`cube(${vertexSql(value, 0)})`;
|
|
208
196
|
}
|
|
209
197
|
function castValue(value, type, name, isPut) {
|
|
210
198
|
if (!type)
|
|
@@ -230,7 +218,17 @@ const getInsert = (row, options) => {
|
|
|
230
218
|
return { cols: join(cols, ", "), vals: join(vals, ", ") };
|
|
231
219
|
};
|
|
232
220
|
const getUpdates = (row, options) => {
|
|
233
|
-
return join(
|
|
221
|
+
return join(
|
|
222
|
+
Object.entries(row).filter(([col]) => col !== options.idCol && col[0] !== "$").map(
|
|
223
|
+
([col, val]) => sql`"${raw(col)}" = ${castValue(
|
|
224
|
+
val,
|
|
225
|
+
options.schema.types[col],
|
|
226
|
+
col,
|
|
227
|
+
row.$put
|
|
228
|
+
)}`
|
|
229
|
+
).concat(sql`"${raw(options.verCol)}" = default`),
|
|
230
|
+
", "
|
|
231
|
+
);
|
|
234
232
|
};
|
|
235
233
|
function getJsonUpdate(object, col, path) {
|
|
236
234
|
if (!object || typeof object !== "object" || Array.isArray(object) || object.$put) {
|
|
@@ -242,7 +240,12 @@ function getJsonUpdate(object, col, path) {
|
|
|
242
240
|
return sql`(case jsonb_typeof(${curr})
|
|
243
241
|
when 'object' then ${curr}
|
|
244
242
|
else '{}'::jsonb
|
|
245
|
-
end) || jsonb_build_object(${join(
|
|
243
|
+
end) || jsonb_build_object(${join(
|
|
244
|
+
Object.entries(object).map(
|
|
245
|
+
([key, value]) => sql`${key}::text, ${getJsonUpdate(value, col, path.concat(key))}`
|
|
246
|
+
),
|
|
247
|
+
", "
|
|
248
|
+
)})`;
|
|
246
249
|
}
|
|
247
250
|
function stripAttributes(object) {
|
|
248
251
|
if (typeof object !== "object" || !object)
|
|
@@ -311,7 +314,10 @@ function getSql(filter, options) {
|
|
|
311
314
|
return ast;
|
|
312
315
|
const op = ast[0];
|
|
313
316
|
if (op === "$and" || op === "$or") {
|
|
314
|
-
return sql`(${join(
|
|
317
|
+
return sql`(${join(
|
|
318
|
+
ast[1].map((node) => getNodeSql(node)),
|
|
319
|
+
`) ${opSql[op]} (`
|
|
320
|
+
)})`;
|
|
315
321
|
} else if (op === "$not") {
|
|
316
322
|
return sql`${opSql[op]} (${getNodeSql(ast[1])})`;
|
|
317
323
|
}
|
|
@@ -343,9 +349,8 @@ const getArgMeta = (key, { prefix, idCol, verDefault }) => sql`
|
|
|
343
349
|
]::text[] AS "$ref"
|
|
344
350
|
`;
|
|
345
351
|
const getAggMeta = (key, { verDefault }) => sql`${key} AS "$key", ${raw(verDefault)} AS "$ver"`;
|
|
346
|
-
function getArgSql(
|
|
347
|
-
|
|
348
|
-
const _a2 = rest, { $order, $group } = _a2, filter = __objRest(_a2, ["$order", "$group"]);
|
|
352
|
+
function getArgSql({ $first, $last, $after, $before, $since, $until, $all, $cursor: _, ...rest }, options) {
|
|
353
|
+
const { $order, $group, ...filter } = rest;
|
|
349
354
|
const { prefix, idCol } = options;
|
|
350
355
|
const meta = (key2) => $group ? getAggMeta(key2, options) : getArgMeta(key2, options);
|
|
351
356
|
const hasRangeArg = $before || $after || $since || $until || $first || $last || $all;
|
|
@@ -363,12 +368,21 @@ function getArgSql(_a, options) {
|
|
|
363
368
|
return { meta: meta(baseKey), where, limit: 1 };
|
|
364
369
|
const groupCols = Array.isArray($group) && $group.length && $group.map(lookup);
|
|
365
370
|
const group = groupCols ? join(groupCols, ", ") : void 0;
|
|
366
|
-
const orderCols = ($order || [idCol]).map(
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
371
|
+
const orderCols = ($order || [idCol]).map(
|
|
372
|
+
(orderItem) => orderItem[0] === "!" ? sql`-(${lookup(orderItem.slice(1))})::float8` : lookup(orderItem)
|
|
373
|
+
);
|
|
374
|
+
Object.entries({ $after, $before, $since, $until }).forEach(
|
|
375
|
+
([name, value]) => {
|
|
376
|
+
if (value)
|
|
377
|
+
where.push(getBoundCond(orderCols, value, name));
|
|
378
|
+
}
|
|
379
|
+
);
|
|
380
|
+
const order = !$group && join(
|
|
381
|
+
($order || [idCol]).map(
|
|
382
|
+
(orderItem) => orderItem[0] === "!" ? sql`${lookup(orderItem.slice(1))} ${$last ? sql`ASC` : sql`DESC`}` : sql`${lookup(orderItem)} ${$last ? sql`DESC` : sql`ASC`}`
|
|
383
|
+
),
|
|
384
|
+
`, `
|
|
385
|
+
);
|
|
372
386
|
const cursorKey = getJsonBuildTrusted({
|
|
373
387
|
$cursor: $group === true ? sql`''` : sql`jsonb_build_array(${join(groupCols || orderCols)})`
|
|
374
388
|
});
|
|
@@ -462,7 +476,7 @@ function patch(object, arg, options) {
|
|
|
462
476
|
return sql`
|
|
463
477
|
UPDATE "${raw(table)}" SET ${getUpdates(row, options)}
|
|
464
478
|
WHERE ${where}
|
|
465
|
-
RETURNING ${getSelectCols(
|
|
479
|
+
RETURNING ${getSelectCols()}, ${meta}`;
|
|
466
480
|
}
|
|
467
481
|
function put(object, arg, options) {
|
|
468
482
|
const { idCol, table } = options;
|
|
@@ -479,7 +493,7 @@ function put(object, arg, options) {
|
|
|
479
493
|
return sql`
|
|
480
494
|
INSERT INTO "${raw(table)}" (${cols}) VALUES (${vals})
|
|
481
495
|
ON CONFLICT (${conflictTarget}) DO UPDATE SET (${cols}) = (${vals})
|
|
482
|
-
RETURNING ${getSelectCols(
|
|
496
|
+
RETURNING ${getSelectCols()}, ${meta}`;
|
|
483
497
|
}
|
|
484
498
|
function del(arg, options) {
|
|
485
499
|
const { table } = options;
|
|
@@ -490,6 +504,7 @@ function del(arg, options) {
|
|
|
490
504
|
RETURNING ${arg} "$key"`;
|
|
491
505
|
}
|
|
492
506
|
const log = debug("graffy:pg:db");
|
|
507
|
+
const { Pool, Client, types } = pg$1;
|
|
493
508
|
class Db {
|
|
494
509
|
constructor(connection) {
|
|
495
510
|
if (typeof connection === "object" && connection && (connection instanceof Pool || connection instanceof Client)) {
|
|
@@ -574,13 +589,17 @@ class Db {
|
|
|
574
589
|
const { prefix } = tableOptions;
|
|
575
590
|
await this.ensureSchema(tableOptions);
|
|
576
591
|
const getByArgs = async (args, projection) => {
|
|
577
|
-
const result = await this.readSql(
|
|
592
|
+
const result = await this.readSql(
|
|
593
|
+
selectByArgs(args, projection, tableOptions)
|
|
594
|
+
);
|
|
578
595
|
const wrappedGraph = encodeGraph(wrapObject(result, prefix));
|
|
579
596
|
log("getByArgs", wrappedGraph);
|
|
580
597
|
merge(results, wrappedGraph);
|
|
581
598
|
};
|
|
582
599
|
const getByIds = async () => {
|
|
583
|
-
const result = await this.readSql(
|
|
600
|
+
const result = await this.readSql(
|
|
601
|
+
selectByIds(Object.keys(idQueries), null, tableOptions)
|
|
602
|
+
);
|
|
584
603
|
result.forEach((object) => {
|
|
585
604
|
const wrappedGraph = encodeGraph(wrapObject(object, prefix));
|
|
586
605
|
log("getByIds", wrappedGraph);
|
|
@@ -595,7 +614,7 @@ class Db {
|
|
|
595
614
|
for (const childNode of node.children) {
|
|
596
615
|
const childArgs = decodeArgs(childNode);
|
|
597
616
|
const projection = childNode.children ? decodeQuery(childNode.children) : null;
|
|
598
|
-
promises.push(getByArgs(
|
|
617
|
+
promises.push(getByArgs({ ...args, ...childArgs }, projection));
|
|
599
618
|
}
|
|
600
619
|
} else {
|
|
601
620
|
const projection = node.children ? decodeQuery(node.children) : null;
|
|
@@ -634,9 +653,13 @@ class Db {
|
|
|
634
653
|
return object.$put ? put(object, arg, tableOptions) : patch(object, arg, tableOptions);
|
|
635
654
|
});
|
|
636
655
|
const result = [];
|
|
637
|
-
await Promise.all(
|
|
638
|
-
|
|
639
|
-
|
|
656
|
+
await Promise.all(
|
|
657
|
+
sqls.map(
|
|
658
|
+
(sql2) => this.writeSql(sql2).then((object) => {
|
|
659
|
+
merge(result, encodeGraph(wrapObject(object, prefix)));
|
|
660
|
+
})
|
|
661
|
+
)
|
|
662
|
+
);
|
|
640
663
|
log("dbWrite", rootChange, result);
|
|
641
664
|
return result;
|
|
642
665
|
}
|
|
@@ -660,9 +683,11 @@ const pg = ({ table, idCol, verCol, connection, schema, verDefault }) => (store)
|
|
|
660
683
|
const readPromise = db.read(query, tableOpts);
|
|
661
684
|
const remainingQuery = remove(query, prefix);
|
|
662
685
|
const nextPromise = next(remainingQuery);
|
|
663
|
-
return Promise.all([readPromise, nextPromise]).then(
|
|
664
|
-
|
|
665
|
-
|
|
686
|
+
return Promise.all([readPromise, nextPromise]).then(
|
|
687
|
+
([readRes, nextRes]) => {
|
|
688
|
+
return merge(readRes, nextRes);
|
|
689
|
+
}
|
|
690
|
+
);
|
|
666
691
|
}
|
|
667
692
|
function write(change, options, next) {
|
|
668
693
|
const { pgClient } = options;
|
|
@@ -670,9 +695,13 @@ const pg = ({ table, idCol, verCol, connection, schema, verDefault }) => (store)
|
|
|
670
695
|
const writePromise = db.write(change, tableOpts);
|
|
671
696
|
const remainingChange = remove(change, prefix);
|
|
672
697
|
const nextPromise = next(remainingChange);
|
|
673
|
-
return Promise.all([writePromise, nextPromise]).then(
|
|
674
|
-
|
|
675
|
-
|
|
698
|
+
return Promise.all([writePromise, nextPromise]).then(
|
|
699
|
+
([writeRes, nextRes]) => {
|
|
700
|
+
return merge(writeRes, nextRes);
|
|
701
|
+
}
|
|
702
|
+
);
|
|
676
703
|
}
|
|
677
704
|
};
|
|
678
|
-
export {
|
|
705
|
+
export {
|
|
706
|
+
pg
|
|
707
|
+
};
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@graffy/pg",
|
|
3
3
|
"description": "The standard Postgres module for Graffy. Each instance this module mounts a Postgres table as a Graffy subtree.",
|
|
4
4
|
"author": "aravind (https://github.com/aravindet)",
|
|
5
|
-
"version": "0.15.25-alpha.
|
|
5
|
+
"version": "0.15.25-alpha.2",
|
|
6
6
|
"main": "./index.cjs",
|
|
7
7
|
"exports": {
|
|
8
8
|
"import": "./index.mjs",
|
|
@@ -16,8 +16,8 @@
|
|
|
16
16
|
},
|
|
17
17
|
"license": "Apache-2.0",
|
|
18
18
|
"dependencies": {
|
|
19
|
-
"@graffy/common": "0.15.25-alpha.
|
|
20
|
-
"sql-template-tag": "^
|
|
19
|
+
"@graffy/common": "0.15.25-alpha.2",
|
|
20
|
+
"sql-template-tag": "^5.0.3",
|
|
21
21
|
"debug": "^4.3.3"
|
|
22
22
|
},
|
|
23
23
|
"peerDependencies": {
|
package/types/sql/getArgSql.d.ts
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
@typedef { import('sql-template-tag').Sql } Sql
|
|
8
8
|
@return {{ meta: Sql, where: Sql[], order?: Sql, group?: Sql, limit: number }}
|
|
9
9
|
*/
|
|
10
|
-
export default function getArgSql({ $first, $last, $after, $before, $since, $until, $all, $cursor
|
|
10
|
+
export default function getArgSql({ $first, $last, $after, $before, $since, $until, $all, $cursor, ...rest }: object, options: {
|
|
11
11
|
prefix: string;
|
|
12
12
|
idCol: string;
|
|
13
13
|
verDefault: string;
|