@graffy/pg 0.15.23 → 0.15.25-alpha.1
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 +56 -47
- package/index.mjs +63 -55
- package/package.json +2 -2
- package/types/sql/clauses.d.ts +1 -0
- package/types/sql/getArgSql.d.ts +2 -1
- package/types/sql/getMeta.d.ts +1 -1
package/index.cjs
CHANGED
|
@@ -27,7 +27,8 @@ var __objRest = (source, exclude) => {
|
|
|
27
27
|
}
|
|
28
28
|
return target;
|
|
29
29
|
};
|
|
30
|
-
Object.
|
|
30
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
31
|
+
exports[Symbol.toStringTag] = "Module";
|
|
31
32
|
var common = require("@graffy/common");
|
|
32
33
|
var pg$1 = require("pg");
|
|
33
34
|
var sql = require("sql-template-tag");
|
|
@@ -174,31 +175,35 @@ const lookup = (prop) => {
|
|
|
174
175
|
const [prefix, ...suffix] = common.encodePath(prop);
|
|
175
176
|
return suffix.length ? sql__default["default"]`"${sql.raw(prefix)}" #> ${suffix}` : sql__default["default"]`"${sql.raw(prefix)}"`;
|
|
176
177
|
};
|
|
178
|
+
const lookupNumeric = (prop) => {
|
|
179
|
+
const [prefix, ...suffix] = common.encodePath(prop);
|
|
180
|
+
return suffix.length ? sql__default["default"]`CASE WHEN "${sql.raw(prefix)}" #> ${suffix} = 'null'::jsonb THEN 0 ELSE ("${sql.raw(prefix)}" #> ${suffix})::numeric END` : sql__default["default"]`"${sql.raw(prefix)}"`;
|
|
181
|
+
};
|
|
177
182
|
const aggSql = {
|
|
178
|
-
$sum: (prop) => sql__default["default"]`sum((${
|
|
183
|
+
$sum: (prop) => sql__default["default"]`sum((${lookupNumeric(prop)})::numeric)`,
|
|
179
184
|
$card: (prop) => sql__default["default"]`count(distinct(${lookup(prop)}))`,
|
|
180
|
-
$avg: (prop) => sql__default["default"]`
|
|
181
|
-
$max: (prop) => sql__default["default"]`
|
|
182
|
-
$min: (prop) => sql__default["default"]`
|
|
185
|
+
$avg: (prop) => sql__default["default"]`avg((${lookupNumeric(prop)})::numeric)`,
|
|
186
|
+
$max: (prop) => sql__default["default"]`max((${lookupNumeric(prop)})::numeric)`,
|
|
187
|
+
$min: (prop) => sql__default["default"]`min((${lookupNumeric(prop)})::numeric)`
|
|
183
188
|
};
|
|
184
189
|
const getSelectCols = (table, projection = null) => {
|
|
185
190
|
if (!projection)
|
|
186
|
-
return sql__default["default"]
|
|
191
|
+
return sql__default["default"]`*`;
|
|
187
192
|
const sqls = [];
|
|
188
193
|
for (const key in projection) {
|
|
189
194
|
if (key === "$count") {
|
|
190
|
-
sqls.push(sql__default["default"]`
|
|
195
|
+
sqls.push(sql__default["default"]`count(*) AS "$count"`);
|
|
191
196
|
} else if (aggSql[key]) {
|
|
192
197
|
const subSqls = [];
|
|
193
198
|
for (const prop in projection[key]) {
|
|
194
199
|
subSqls.push(sql__default["default"]`${prop}::text, ${aggSql[key](prop)}`);
|
|
195
200
|
}
|
|
196
|
-
sqls.push(sql__default["default"]
|
|
201
|
+
sqls.push(sql__default["default"]`jsonb_build_object(${sql.join(subSqls, ", ")}) AS "${sql.raw(key)}"`);
|
|
197
202
|
} else {
|
|
198
|
-
sqls.push(sql__default["default"]
|
|
203
|
+
sqls.push(sql__default["default"]`"${sql.raw(key)}"`);
|
|
199
204
|
}
|
|
200
205
|
}
|
|
201
|
-
return
|
|
206
|
+
return sql.join(sqls, ", ");
|
|
202
207
|
};
|
|
203
208
|
function vertexSql(array, nullValue) {
|
|
204
209
|
return sql__default["default"]`array[${sql.join(array.map((num) => num === null ? nullValue : num))}]::float8[]`;
|
|
@@ -336,49 +341,46 @@ function getSql(filter, options) {
|
|
|
336
341
|
}
|
|
337
342
|
return getNodeSql(getAst(filter));
|
|
338
343
|
}
|
|
339
|
-
const getIdMeta = ({ idCol, verDefault }) =>
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
}
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
const getAggMeta = (key,
|
|
349
|
-
$key: sql.join([key, getJsonBuildTrusted({ $group })].filter(Boolean), " || "),
|
|
350
|
-
$ver: sql.raw(verDefault)
|
|
351
|
-
});
|
|
344
|
+
const getIdMeta = ({ idCol, verDefault }) => sql__default["default"]`"${sql.raw(idCol)}" AS "$key", ${sql.raw(verDefault)} AS "$ver"`;
|
|
345
|
+
const getArgMeta = (key, { prefix, idCol, verDefault }) => sql__default["default"]`
|
|
346
|
+
${key} AS "$key",
|
|
347
|
+
${sql.raw(verDefault)} AS "$ver",
|
|
348
|
+
array[
|
|
349
|
+
${sql.join(prefix.map((k) => sql__default["default"]`${k}::text`))},
|
|
350
|
+
"${sql.raw(idCol)}"
|
|
351
|
+
]::text[] AS "$ref"
|
|
352
|
+
`;
|
|
353
|
+
const getAggMeta = (key, { verDefault }) => sql__default["default"]`${key} AS "$key", ${sql.raw(verDefault)} AS "$ver"`;
|
|
352
354
|
function getArgSql(_a, options) {
|
|
353
355
|
var _b = _a, { $first, $last, $after, $before, $since, $until, $all, $cursor: _ } = _b, rest = __objRest(_b, ["$first", "$last", "$after", "$before", "$since", "$until", "$all", "$cursor"]);
|
|
354
356
|
const _a2 = rest, { $order, $group } = _a2, filter = __objRest(_a2, ["$order", "$group"]);
|
|
355
357
|
const { prefix, idCol } = options;
|
|
358
|
+
const meta = (key2) => $group ? getAggMeta(key2, options) : getArgMeta(key2, options);
|
|
359
|
+
const hasRangeArg = $before || $after || $since || $until || $first || $last || $all;
|
|
356
360
|
if ($order && $group) {
|
|
357
361
|
throw Error("pg_arg.order_and_group_unsupported in " + prefix);
|
|
358
362
|
}
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
const
|
|
363
|
-
let key;
|
|
363
|
+
if (($order || $group && $group !== true) && !hasRangeArg) {
|
|
364
|
+
throw Error("pg_arg.range_arg_expected in " + prefix);
|
|
365
|
+
}
|
|
366
|
+
const baseKey = sql__default["default"]`${JSON.stringify(rest)}::jsonb`;
|
|
364
367
|
const where = [];
|
|
365
|
-
if (!common.isEmpty(filter))
|
|
368
|
+
if (!common.isEmpty(filter))
|
|
366
369
|
where.push(getSql(filter, options));
|
|
367
|
-
key = sql__default["default"]`${JSON.stringify(filter)}::jsonb`;
|
|
368
|
-
}
|
|
369
370
|
if (!hasRangeArg)
|
|
370
|
-
return { meta: meta(
|
|
371
|
+
return { meta: meta(baseKey), where, limit: 1 };
|
|
372
|
+
const groupCols = Array.isArray($group) && $group.length && $group.map(lookup);
|
|
373
|
+
const group = groupCols ? sql.join(groupCols, ", ") : void 0;
|
|
371
374
|
const orderCols = ($order || [idCol]).map((orderItem) => orderItem[0] === "!" ? sql__default["default"]`-(${lookup(orderItem.slice(1))})::float8` : lookup(orderItem));
|
|
372
375
|
Object.entries({ $after, $before, $since, $until }).forEach(([name, value]) => {
|
|
373
376
|
if (value)
|
|
374
377
|
where.push(getBoundCond(orderCols, value, name));
|
|
375
378
|
});
|
|
376
379
|
const order = !$group && sql.join(($order || [idCol]).map((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`}`), `, `);
|
|
377
|
-
const orderKey = $order && getJsonBuildTrusted({ $order: sql__default["default"]`${JSON.stringify($order)}::jsonb` });
|
|
378
380
|
const cursorKey = getJsonBuildTrusted({
|
|
379
|
-
$cursor: sql__default["default"]`jsonb_build_array(${sql.join(groupCols || orderCols)})`
|
|
381
|
+
$cursor: $group === true ? sql__default["default"]`''` : sql__default["default"]`jsonb_build_array(${sql.join(groupCols || orderCols)})`
|
|
380
382
|
});
|
|
381
|
-
key = sql__default["default"]`(${
|
|
383
|
+
const key = sql__default["default"]`(${baseKey} || ${cursorKey})`;
|
|
382
384
|
return {
|
|
383
385
|
meta: meta(key),
|
|
384
386
|
where,
|
|
@@ -423,7 +425,7 @@ function selectByArgs(args, projection, options) {
|
|
|
423
425
|
const clampedLimit = Math.min(MAX_LIMIT, limit || MAX_LIMIT);
|
|
424
426
|
return sql__default["default"]`
|
|
425
427
|
SELECT
|
|
426
|
-
${getSelectCols(table, projection)}
|
|
428
|
+
${getSelectCols(table, projection)}, ${meta}
|
|
427
429
|
FROM "${sql.raw(table)}"
|
|
428
430
|
${where.length ? sql__default["default"]`WHERE ${sql.join(where, ` AND `)}` : sql.empty}
|
|
429
431
|
${group ? sql__default["default"]`GROUP BY ${group}` : sql.empty}
|
|
@@ -435,7 +437,7 @@ function selectByIds(ids, projection, options) {
|
|
|
435
437
|
const { table, idCol } = options;
|
|
436
438
|
return sql__default["default"]`
|
|
437
439
|
SELECT
|
|
438
|
-
${getSelectCols(table, projection)}
|
|
440
|
+
${getSelectCols(table, projection)}, ${getIdMeta(options)}
|
|
439
441
|
FROM "${sql.raw(table)}"
|
|
440
442
|
WHERE "${sql.raw(idCol)}" IN (${sql.join(ids)})
|
|
441
443
|
`;
|
|
@@ -468,7 +470,7 @@ function patch(object, arg, options) {
|
|
|
468
470
|
return sql__default["default"]`
|
|
469
471
|
UPDATE "${sql.raw(table)}" SET ${getUpdates(row, options)}
|
|
470
472
|
WHERE ${where}
|
|
471
|
-
RETURNING
|
|
473
|
+
RETURNING ${getSelectCols(table)}, ${meta}`;
|
|
472
474
|
}
|
|
473
475
|
function put(object, arg, options) {
|
|
474
476
|
const { idCol, table } = options;
|
|
@@ -485,7 +487,7 @@ function put(object, arg, options) {
|
|
|
485
487
|
return sql__default["default"]`
|
|
486
488
|
INSERT INTO "${sql.raw(table)}" (${cols}) VALUES (${vals})
|
|
487
489
|
ON CONFLICT (${conflictTarget}) DO UPDATE SET (${cols}) = (${vals})
|
|
488
|
-
RETURNING
|
|
490
|
+
RETURNING ${getSelectCols(table)}, ${meta}`;
|
|
489
491
|
}
|
|
490
492
|
function del(arg, options) {
|
|
491
493
|
const { table } = options;
|
|
@@ -493,7 +495,7 @@ function del(arg, options) {
|
|
|
493
495
|
return sql__default["default"]`
|
|
494
496
|
DELETE FROM "${sql.raw(table)}"
|
|
495
497
|
WHERE ${where}
|
|
496
|
-
RETURNING
|
|
498
|
+
RETURNING ${arg} "$key"`;
|
|
497
499
|
}
|
|
498
500
|
const log = debug__default["default"]("graffy:pg:db");
|
|
499
501
|
class Db {
|
|
@@ -505,9 +507,16 @@ class Db {
|
|
|
505
507
|
}
|
|
506
508
|
}
|
|
507
509
|
async query(sql2) {
|
|
508
|
-
sql2.rowMode = "array";
|
|
509
510
|
log("Making SQL query: " + sql2.text, sql2.values);
|
|
510
511
|
try {
|
|
512
|
+
sql2.types = {
|
|
513
|
+
getTypeParser: (oid, format) => {
|
|
514
|
+
if (oid === pg$1.types.builtins.INT8) {
|
|
515
|
+
return (value) => parseInt(value, 10);
|
|
516
|
+
}
|
|
517
|
+
return pg$1.types.getTypeParser(oid, format);
|
|
518
|
+
}
|
|
519
|
+
};
|
|
511
520
|
return await this.client.query(sql2);
|
|
512
521
|
} catch (e) {
|
|
513
522
|
const message = [
|
|
@@ -522,7 +531,7 @@ class Db {
|
|
|
522
531
|
}
|
|
523
532
|
}
|
|
524
533
|
async readSql(sql2) {
|
|
525
|
-
const result = (await this.query(sql2)).rows
|
|
534
|
+
const result = (await this.query(sql2)).rows;
|
|
526
535
|
log("Read result", result);
|
|
527
536
|
return result;
|
|
528
537
|
}
|
|
@@ -532,7 +541,7 @@ class Db {
|
|
|
532
541
|
if (!res.rowCount) {
|
|
533
542
|
throw Error("pg.nothing_written " + sql2.text + " with " + sql2.values);
|
|
534
543
|
}
|
|
535
|
-
return res.rows[0]
|
|
544
|
+
return res.rows[0];
|
|
536
545
|
}
|
|
537
546
|
async ensureSchema(tableOptions) {
|
|
538
547
|
if (tableOptions.schema)
|
|
@@ -543,13 +552,13 @@ class Db {
|
|
|
543
552
|
FROM information_schema.tables
|
|
544
553
|
WHERE table_name = ${table}
|
|
545
554
|
ORDER BY array_position(current_schemas(false)::text[], table_schema::text) ASC
|
|
546
|
-
LIMIT 1`)).rows[0]
|
|
555
|
+
LIMIT 1`)).rows[0].table_schema;
|
|
547
556
|
const types = (await this.query(sql__default["default"]`
|
|
548
|
-
SELECT jsonb_object_agg(column_name, udt_name)
|
|
557
|
+
SELECT jsonb_object_agg(column_name, udt_name) AS column_types
|
|
549
558
|
FROM information_schema.columns
|
|
550
559
|
WHERE
|
|
551
560
|
table_name = ${table} AND
|
|
552
|
-
table_schema = ${tableSchema}`)).rows[0]
|
|
561
|
+
table_schema = ${tableSchema}`)).rows[0].column_types;
|
|
553
562
|
if (!types)
|
|
554
563
|
throw Error(`pg.missing_table ${table}`);
|
|
555
564
|
const verDefault = (await this.query(sql__default["default"]`
|
|
@@ -558,7 +567,7 @@ class Db {
|
|
|
558
567
|
WHERE
|
|
559
568
|
table_name = ${table} AND
|
|
560
569
|
table_schema = ${tableSchema} AND
|
|
561
|
-
column_name = ${verCol}`)).rows[0]
|
|
570
|
+
column_name = ${verCol}`)).rows[0].column_default;
|
|
562
571
|
if (!verDefault) {
|
|
563
572
|
throw Error(`pg.verCol_without_default ${verCol}`);
|
|
564
573
|
}
|
package/index.mjs
CHANGED
|
@@ -27,7 +27,7 @@ var __objRest = (source, exclude) => {
|
|
|
27
27
|
return target;
|
|
28
28
|
};
|
|
29
29
|
import { isEmpty, encodePath, isPlainObject, unwrap, decodeArgs, decodeQuery, finalize, wrap, isRange, decodeGraph, mergeObject, merge, encodeGraph, wrapObject, remove } from "@graffy/common";
|
|
30
|
-
import { Pool, Client } from "pg";
|
|
30
|
+
import { Pool, Client, types } from "pg";
|
|
31
31
|
import sql, { join, raw, Sql, empty } from "sql-template-tag";
|
|
32
32
|
import debug from "debug";
|
|
33
33
|
const valid = {
|
|
@@ -167,31 +167,35 @@ const lookup = (prop) => {
|
|
|
167
167
|
const [prefix, ...suffix] = encodePath(prop);
|
|
168
168
|
return suffix.length ? sql`"${raw(prefix)}" #> ${suffix}` : sql`"${raw(prefix)}"`;
|
|
169
169
|
};
|
|
170
|
+
const lookupNumeric = (prop) => {
|
|
171
|
+
const [prefix, ...suffix] = encodePath(prop);
|
|
172
|
+
return suffix.length ? sql`CASE WHEN "${raw(prefix)}" #> ${suffix} = 'null'::jsonb THEN 0 ELSE ("${raw(prefix)}" #> ${suffix})::numeric END` : sql`"${raw(prefix)}"`;
|
|
173
|
+
};
|
|
170
174
|
const aggSql = {
|
|
171
|
-
$sum: (prop) => sql`sum((${
|
|
175
|
+
$sum: (prop) => sql`sum((${lookupNumeric(prop)})::numeric)`,
|
|
172
176
|
$card: (prop) => sql`count(distinct(${lookup(prop)}))`,
|
|
173
|
-
$avg: (prop) => sql`
|
|
174
|
-
$max: (prop) => sql`
|
|
175
|
-
$min: (prop) => sql`
|
|
177
|
+
$avg: (prop) => sql`avg((${lookupNumeric(prop)})::numeric)`,
|
|
178
|
+
$max: (prop) => sql`max((${lookupNumeric(prop)})::numeric)`,
|
|
179
|
+
$min: (prop) => sql`min((${lookupNumeric(prop)})::numeric)`
|
|
176
180
|
};
|
|
177
181
|
const getSelectCols = (table, projection = null) => {
|
|
178
182
|
if (!projection)
|
|
179
|
-
return sql
|
|
183
|
+
return sql`*`;
|
|
180
184
|
const sqls = [];
|
|
181
185
|
for (const key in projection) {
|
|
182
186
|
if (key === "$count") {
|
|
183
|
-
sqls.push(sql`
|
|
187
|
+
sqls.push(sql`count(*) AS "$count"`);
|
|
184
188
|
} else if (aggSql[key]) {
|
|
185
189
|
const subSqls = [];
|
|
186
190
|
for (const prop in projection[key]) {
|
|
187
191
|
subSqls.push(sql`${prop}::text, ${aggSql[key](prop)}`);
|
|
188
192
|
}
|
|
189
|
-
sqls.push(sql
|
|
193
|
+
sqls.push(sql`jsonb_build_object(${join(subSqls, ", ")}) AS "${raw(key)}"`);
|
|
190
194
|
} else {
|
|
191
|
-
sqls.push(sql
|
|
195
|
+
sqls.push(sql`"${raw(key)}"`);
|
|
192
196
|
}
|
|
193
197
|
}
|
|
194
|
-
return
|
|
198
|
+
return join(sqls, ", ");
|
|
195
199
|
};
|
|
196
200
|
function vertexSql(array, nullValue) {
|
|
197
201
|
return sql`array[${join(array.map((num) => num === null ? nullValue : num))}]::float8[]`;
|
|
@@ -312,10 +316,10 @@ function getSql(filter, options) {
|
|
|
312
316
|
return sql`${opSql[op]} (${getNodeSql(ast[1])})`;
|
|
313
317
|
}
|
|
314
318
|
const [prefix, ...suffix] = encodePath(ast[1]);
|
|
315
|
-
const { types } = options.schema;
|
|
316
|
-
if (!
|
|
319
|
+
const { types: types2 } = options.schema;
|
|
320
|
+
if (!types2[prefix])
|
|
317
321
|
throw Error("pg.no_column " + prefix);
|
|
318
|
-
if (
|
|
322
|
+
if (types2[prefix] === "jsonb") {
|
|
319
323
|
const [lhs, textLhs] = suffix.length ? [
|
|
320
324
|
sql`"${raw(prefix)}" #> ${suffix}`,
|
|
321
325
|
sql`"${raw(prefix)}" #>> ${suffix}`
|
|
@@ -324,54 +328,51 @@ function getSql(filter, options) {
|
|
|
324
328
|
} else {
|
|
325
329
|
if (suffix.length)
|
|
326
330
|
throw Error("pg.lookup_not_jsonb " + prefix);
|
|
327
|
-
return getBinarySql(sql`"${raw(prefix)}"`,
|
|
331
|
+
return getBinarySql(sql`"${raw(prefix)}"`, types2[prefix], op, ast[2]);
|
|
328
332
|
}
|
|
329
333
|
}
|
|
330
334
|
return getNodeSql(getAst(filter));
|
|
331
335
|
}
|
|
332
|
-
const getIdMeta = ({ idCol, verDefault }) =>
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
}
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
const getAggMeta = (key,
|
|
342
|
-
$key: join([key, getJsonBuildTrusted({ $group })].filter(Boolean), " || "),
|
|
343
|
-
$ver: raw(verDefault)
|
|
344
|
-
});
|
|
336
|
+
const getIdMeta = ({ idCol, verDefault }) => sql`"${raw(idCol)}" AS "$key", ${raw(verDefault)} AS "$ver"`;
|
|
337
|
+
const getArgMeta = (key, { prefix, idCol, verDefault }) => sql`
|
|
338
|
+
${key} AS "$key",
|
|
339
|
+
${raw(verDefault)} AS "$ver",
|
|
340
|
+
array[
|
|
341
|
+
${join(prefix.map((k) => sql`${k}::text`))},
|
|
342
|
+
"${raw(idCol)}"
|
|
343
|
+
]::text[] AS "$ref"
|
|
344
|
+
`;
|
|
345
|
+
const getAggMeta = (key, { verDefault }) => sql`${key} AS "$key", ${raw(verDefault)} AS "$ver"`;
|
|
345
346
|
function getArgSql(_a, options) {
|
|
346
347
|
var _b = _a, { $first, $last, $after, $before, $since, $until, $all, $cursor: _ } = _b, rest = __objRest(_b, ["$first", "$last", "$after", "$before", "$since", "$until", "$all", "$cursor"]);
|
|
347
348
|
const _a2 = rest, { $order, $group } = _a2, filter = __objRest(_a2, ["$order", "$group"]);
|
|
348
349
|
const { prefix, idCol } = options;
|
|
350
|
+
const meta = (key2) => $group ? getAggMeta(key2, options) : getArgMeta(key2, options);
|
|
351
|
+
const hasRangeArg = $before || $after || $since || $until || $first || $last || $all;
|
|
349
352
|
if ($order && $group) {
|
|
350
353
|
throw Error("pg_arg.order_and_group_unsupported in " + prefix);
|
|
351
354
|
}
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
const
|
|
356
|
-
let key;
|
|
355
|
+
if (($order || $group && $group !== true) && !hasRangeArg) {
|
|
356
|
+
throw Error("pg_arg.range_arg_expected in " + prefix);
|
|
357
|
+
}
|
|
358
|
+
const baseKey = sql`${JSON.stringify(rest)}::jsonb`;
|
|
357
359
|
const where = [];
|
|
358
|
-
if (!isEmpty(filter))
|
|
360
|
+
if (!isEmpty(filter))
|
|
359
361
|
where.push(getSql(filter, options));
|
|
360
|
-
key = sql`${JSON.stringify(filter)}::jsonb`;
|
|
361
|
-
}
|
|
362
362
|
if (!hasRangeArg)
|
|
363
|
-
return { meta: meta(
|
|
363
|
+
return { meta: meta(baseKey), where, limit: 1 };
|
|
364
|
+
const groupCols = Array.isArray($group) && $group.length && $group.map(lookup);
|
|
365
|
+
const group = groupCols ? join(groupCols, ", ") : void 0;
|
|
364
366
|
const orderCols = ($order || [idCol]).map((orderItem) => orderItem[0] === "!" ? sql`-(${lookup(orderItem.slice(1))})::float8` : lookup(orderItem));
|
|
365
367
|
Object.entries({ $after, $before, $since, $until }).forEach(([name, value]) => {
|
|
366
368
|
if (value)
|
|
367
369
|
where.push(getBoundCond(orderCols, value, name));
|
|
368
370
|
});
|
|
369
371
|
const order = !$group && join(($order || [idCol]).map((orderItem) => orderItem[0] === "!" ? sql`${lookup(orderItem.slice(1))} ${$last ? sql`ASC` : sql`DESC`}` : sql`${lookup(orderItem)} ${$last ? sql`DESC` : sql`ASC`}`), `, `);
|
|
370
|
-
const orderKey = $order && getJsonBuildTrusted({ $order: sql`${JSON.stringify($order)}::jsonb` });
|
|
371
372
|
const cursorKey = getJsonBuildTrusted({
|
|
372
|
-
$cursor: sql`jsonb_build_array(${join(groupCols || orderCols)})`
|
|
373
|
+
$cursor: $group === true ? sql`''` : sql`jsonb_build_array(${join(groupCols || orderCols)})`
|
|
373
374
|
});
|
|
374
|
-
key = sql`(${
|
|
375
|
+
const key = sql`(${baseKey} || ${cursorKey})`;
|
|
375
376
|
return {
|
|
376
377
|
meta: meta(key),
|
|
377
378
|
where,
|
|
@@ -416,7 +417,7 @@ function selectByArgs(args, projection, options) {
|
|
|
416
417
|
const clampedLimit = Math.min(MAX_LIMIT, limit || MAX_LIMIT);
|
|
417
418
|
return sql`
|
|
418
419
|
SELECT
|
|
419
|
-
${getSelectCols(table, projection)}
|
|
420
|
+
${getSelectCols(table, projection)}, ${meta}
|
|
420
421
|
FROM "${raw(table)}"
|
|
421
422
|
${where.length ? sql`WHERE ${join(where, ` AND `)}` : empty}
|
|
422
423
|
${group ? sql`GROUP BY ${group}` : empty}
|
|
@@ -428,7 +429,7 @@ function selectByIds(ids, projection, options) {
|
|
|
428
429
|
const { table, idCol } = options;
|
|
429
430
|
return sql`
|
|
430
431
|
SELECT
|
|
431
|
-
${getSelectCols(table, projection)}
|
|
432
|
+
${getSelectCols(table, projection)}, ${getIdMeta(options)}
|
|
432
433
|
FROM "${raw(table)}"
|
|
433
434
|
WHERE "${raw(idCol)}" IN (${join(ids)})
|
|
434
435
|
`;
|
|
@@ -461,7 +462,7 @@ function patch(object, arg, options) {
|
|
|
461
462
|
return sql`
|
|
462
463
|
UPDATE "${raw(table)}" SET ${getUpdates(row, options)}
|
|
463
464
|
WHERE ${where}
|
|
464
|
-
RETURNING
|
|
465
|
+
RETURNING ${getSelectCols(table)}, ${meta}`;
|
|
465
466
|
}
|
|
466
467
|
function put(object, arg, options) {
|
|
467
468
|
const { idCol, table } = options;
|
|
@@ -478,7 +479,7 @@ function put(object, arg, options) {
|
|
|
478
479
|
return sql`
|
|
479
480
|
INSERT INTO "${raw(table)}" (${cols}) VALUES (${vals})
|
|
480
481
|
ON CONFLICT (${conflictTarget}) DO UPDATE SET (${cols}) = (${vals})
|
|
481
|
-
RETURNING
|
|
482
|
+
RETURNING ${getSelectCols(table)}, ${meta}`;
|
|
482
483
|
}
|
|
483
484
|
function del(arg, options) {
|
|
484
485
|
const { table } = options;
|
|
@@ -486,7 +487,7 @@ function del(arg, options) {
|
|
|
486
487
|
return sql`
|
|
487
488
|
DELETE FROM "${raw(table)}"
|
|
488
489
|
WHERE ${where}
|
|
489
|
-
RETURNING
|
|
490
|
+
RETURNING ${arg} "$key"`;
|
|
490
491
|
}
|
|
491
492
|
const log = debug("graffy:pg:db");
|
|
492
493
|
class Db {
|
|
@@ -498,9 +499,16 @@ class Db {
|
|
|
498
499
|
}
|
|
499
500
|
}
|
|
500
501
|
async query(sql2) {
|
|
501
|
-
sql2.rowMode = "array";
|
|
502
502
|
log("Making SQL query: " + sql2.text, sql2.values);
|
|
503
503
|
try {
|
|
504
|
+
sql2.types = {
|
|
505
|
+
getTypeParser: (oid, format) => {
|
|
506
|
+
if (oid === types.builtins.INT8) {
|
|
507
|
+
return (value) => parseInt(value, 10);
|
|
508
|
+
}
|
|
509
|
+
return types.getTypeParser(oid, format);
|
|
510
|
+
}
|
|
511
|
+
};
|
|
504
512
|
return await this.client.query(sql2);
|
|
505
513
|
} catch (e) {
|
|
506
514
|
const message = [
|
|
@@ -515,7 +523,7 @@ class Db {
|
|
|
515
523
|
}
|
|
516
524
|
}
|
|
517
525
|
async readSql(sql2) {
|
|
518
|
-
const result = (await this.query(sql2)).rows
|
|
526
|
+
const result = (await this.query(sql2)).rows;
|
|
519
527
|
log("Read result", result);
|
|
520
528
|
return result;
|
|
521
529
|
}
|
|
@@ -525,7 +533,7 @@ class Db {
|
|
|
525
533
|
if (!res.rowCount) {
|
|
526
534
|
throw Error("pg.nothing_written " + sql2.text + " with " + sql2.values);
|
|
527
535
|
}
|
|
528
|
-
return res.rows[0]
|
|
536
|
+
return res.rows[0];
|
|
529
537
|
}
|
|
530
538
|
async ensureSchema(tableOptions) {
|
|
531
539
|
if (tableOptions.schema)
|
|
@@ -536,14 +544,14 @@ class Db {
|
|
|
536
544
|
FROM information_schema.tables
|
|
537
545
|
WHERE table_name = ${table}
|
|
538
546
|
ORDER BY array_position(current_schemas(false)::text[], table_schema::text) ASC
|
|
539
|
-
LIMIT 1`)).rows[0]
|
|
540
|
-
const
|
|
541
|
-
SELECT jsonb_object_agg(column_name, udt_name)
|
|
547
|
+
LIMIT 1`)).rows[0].table_schema;
|
|
548
|
+
const types2 = (await this.query(sql`
|
|
549
|
+
SELECT jsonb_object_agg(column_name, udt_name) AS column_types
|
|
542
550
|
FROM information_schema.columns
|
|
543
551
|
WHERE
|
|
544
552
|
table_name = ${table} AND
|
|
545
|
-
table_schema = ${tableSchema}`)).rows[0]
|
|
546
|
-
if (!
|
|
553
|
+
table_schema = ${tableSchema}`)).rows[0].column_types;
|
|
554
|
+
if (!types2)
|
|
547
555
|
throw Error(`pg.missing_table ${table}`);
|
|
548
556
|
const verDefault = (await this.query(sql`
|
|
549
557
|
SELECT column_default
|
|
@@ -551,12 +559,12 @@ class Db {
|
|
|
551
559
|
WHERE
|
|
552
560
|
table_name = ${table} AND
|
|
553
561
|
table_schema = ${tableSchema} AND
|
|
554
|
-
column_name = ${verCol}`)).rows[0]
|
|
562
|
+
column_name = ${verCol}`)).rows[0].column_default;
|
|
555
563
|
if (!verDefault) {
|
|
556
564
|
throw Error(`pg.verCol_without_default ${verCol}`);
|
|
557
565
|
}
|
|
558
|
-
log("ensureSchema",
|
|
559
|
-
tableOptions.schema = { types };
|
|
566
|
+
log("ensureSchema", types2);
|
|
567
|
+
tableOptions.schema = { types: types2 };
|
|
560
568
|
tableOptions.verDefault = verDefault;
|
|
561
569
|
}
|
|
562
570
|
async read(rootQuery, tableOptions) {
|
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.
|
|
5
|
+
"version": "0.15.25-alpha.1",
|
|
6
6
|
"main": "./index.cjs",
|
|
7
7
|
"exports": {
|
|
8
8
|
"import": "./index.mjs",
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
},
|
|
17
17
|
"license": "Apache-2.0",
|
|
18
18
|
"dependencies": {
|
|
19
|
-
"@graffy/common": "0.15.
|
|
19
|
+
"@graffy/common": "0.15.25-alpha.1",
|
|
20
20
|
"sql-template-tag": "^4.1.0",
|
|
21
21
|
"debug": "^4.3.3"
|
|
22
22
|
},
|
package/types/sql/clauses.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export function cubeLiteralSql(value: any): Sql;
|
|
2
2
|
export function getJsonBuildTrusted(variadic: any): Sql;
|
|
3
3
|
export function lookup(prop: any): Sql;
|
|
4
|
+
export function lookupNumeric(prop: any): Sql;
|
|
4
5
|
export function getSelectCols(table: any, projection?: any): Sql;
|
|
5
6
|
export function getInsert(row: any, options: any): {
|
|
6
7
|
cols: Sql;
|
package/types/sql/getArgSql.d.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
Uses the args object (typically passed in the $key attribute)
|
|
3
3
|
|
|
4
4
|
@param {object} args
|
|
5
|
-
@param {{prefix: string, idCol: string}} options
|
|
5
|
+
@param {{prefix: string, idCol: string, verDefault: string}} options
|
|
6
6
|
|
|
7
7
|
@typedef { import('sql-template-tag').Sql } Sql
|
|
8
8
|
@return {{ meta: Sql, where: Sql[], order?: Sql, group?: Sql, limit: number }}
|
|
@@ -10,6 +10,7 @@
|
|
|
10
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
|
+
verDefault: string;
|
|
13
14
|
}): {
|
|
14
15
|
meta: Sql;
|
|
15
16
|
where: Sql[];
|
package/types/sql/getMeta.d.ts
CHANGED
|
@@ -7,6 +7,6 @@ export function getArgMeta(key: any, { prefix, idCol, verDefault }: {
|
|
|
7
7
|
idCol: any;
|
|
8
8
|
verDefault: any;
|
|
9
9
|
}): import("sql-template-tag").Sql;
|
|
10
|
-
export function getAggMeta(key: any,
|
|
10
|
+
export function getAggMeta(key: any, { verDefault }: {
|
|
11
11
|
verDefault: any;
|
|
12
12
|
}): import("sql-template-tag").Sql;
|