@graffy/pg 0.16.8 → 0.16.9-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 +84 -31
- package/index.mjs +85 -32
- package/package.json +2 -2
- package/types/sql/clauses.d.ts +2 -1
- package/types/sql/upsert.d.ts +1 -1
package/index.cjs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
3
|
const common = require("@graffy/common");
|
|
4
|
-
const pg$1 = require("pg");
|
|
5
4
|
const debug = require("debug");
|
|
5
|
+
const pg$1 = require("pg");
|
|
6
6
|
class Sql {
|
|
7
7
|
constructor(rawStrings, rawValues) {
|
|
8
8
|
if (rawStrings.length - 1 !== rawValues.length) {
|
|
@@ -298,14 +298,43 @@ function castValue(value, type, name, isPut) {
|
|
|
298
298
|
return cubeLiteralSql(value);
|
|
299
299
|
return value;
|
|
300
300
|
}
|
|
301
|
-
const getInsert = (
|
|
301
|
+
const getInsert = (rows, options) => {
|
|
302
|
+
const { verCol, schema } = options;
|
|
302
303
|
const cols = [];
|
|
304
|
+
const colSqls = [];
|
|
305
|
+
const colIx = {};
|
|
306
|
+
const colUsed = [];
|
|
307
|
+
for (const col of Object.keys(options.schema.types)) {
|
|
308
|
+
colIx[col] = cols.length;
|
|
309
|
+
colUsed[cols.length] = false;
|
|
310
|
+
cols.push(col);
|
|
311
|
+
colSqls.push(sql`"${raw(col)}"`);
|
|
312
|
+
}
|
|
313
|
+
colUsed[colIx[verCol]] = true;
|
|
303
314
|
const vals = [];
|
|
304
|
-
|
|
305
|
-
cols.
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
315
|
+
for (const row of rows) {
|
|
316
|
+
const rowVals = Array(cols.length).fill(sql`default`);
|
|
317
|
+
for (const col of cols) {
|
|
318
|
+
if (col === verCol || !(col in row))
|
|
319
|
+
continue;
|
|
320
|
+
const ix = colIx[col];
|
|
321
|
+
colUsed[ix] = true;
|
|
322
|
+
rowVals[ix] = castValue(row[col], schema.types[col], col, row.$put);
|
|
323
|
+
}
|
|
324
|
+
vals.push(rowVals);
|
|
325
|
+
}
|
|
326
|
+
const isUsed = (_, ix) => colUsed[ix];
|
|
327
|
+
return {
|
|
328
|
+
cols: join(colSqls.filter(isUsed), ", "),
|
|
329
|
+
vals: join(
|
|
330
|
+
vals.map((rowVals) => sql`(${join(rowVals.filter(isUsed), ", ")})`),
|
|
331
|
+
", "
|
|
332
|
+
),
|
|
333
|
+
updates: join(
|
|
334
|
+
colSqls.map((col, ix) => sql`${col} = "excluded".${col}`).filter(isUsed),
|
|
335
|
+
", "
|
|
336
|
+
)
|
|
337
|
+
};
|
|
309
338
|
};
|
|
310
339
|
const getUpdates = (row, options) => {
|
|
311
340
|
return join(
|
|
@@ -595,23 +624,35 @@ function patch(object, arg, options) {
|
|
|
595
624
|
WHERE ${where}
|
|
596
625
|
RETURNING ${getSelectCols(options)}, ${meta}`;
|
|
597
626
|
}
|
|
598
|
-
function put(
|
|
627
|
+
function put(puts, options) {
|
|
599
628
|
const { idCol, table } = options;
|
|
600
|
-
const
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
629
|
+
const sqls = [];
|
|
630
|
+
const addSql = (rows, meta, conflictTarget) => {
|
|
631
|
+
const { cols, vals, updates } = getInsert(rows, options);
|
|
632
|
+
sqls.push(sql`
|
|
633
|
+
INSERT INTO "${raw(table)}" (${cols}) VALUES ${vals}
|
|
634
|
+
ON CONFLICT (${conflictTarget}) DO UPDATE SET ${updates}
|
|
635
|
+
RETURNING ${getSelectCols(options)}, ${meta}`);
|
|
636
|
+
};
|
|
637
|
+
const idRows = [];
|
|
638
|
+
for (const put2 of puts) {
|
|
639
|
+
const [row, arg] = put2;
|
|
640
|
+
if (!common.isPlainObject(arg)) {
|
|
641
|
+
idRows.push(row);
|
|
642
|
+
continue;
|
|
643
|
+
}
|
|
644
|
+
const { meta } = getArgSql(arg, options);
|
|
645
|
+
const conflictTarget = join(
|
|
646
|
+
Object.keys(arg).map((col) => sql`"${raw(col)}"`)
|
|
647
|
+
);
|
|
648
|
+
addSql([row], meta, conflictTarget);
|
|
609
649
|
}
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
650
|
+
if (idRows.length) {
|
|
651
|
+
const meta = getIdMeta(options);
|
|
652
|
+
const conflictTarget = sql`"${raw(idCol)}"`;
|
|
653
|
+
addSql(idRows, meta, conflictTarget);
|
|
654
|
+
}
|
|
655
|
+
return sqls;
|
|
615
656
|
}
|
|
616
657
|
function del(arg, options) {
|
|
617
658
|
const { table } = options;
|
|
@@ -676,7 +717,7 @@ class Db {
|
|
|
676
717
|
if (!res.rowCount) {
|
|
677
718
|
throw Error(`pg.nothing_written ${sql2.text} with ${sql2.values}`);
|
|
678
719
|
}
|
|
679
|
-
return res.rows
|
|
720
|
+
return res.rows;
|
|
680
721
|
}
|
|
681
722
|
async ensureSchema(tableOptions, typeOids) {
|
|
682
723
|
if (tableOptions.schema)
|
|
@@ -740,11 +781,11 @@ class Db {
|
|
|
740
781
|
selectByIds(Object.keys(idQueries), null, tableOptions),
|
|
741
782
|
tableOptions
|
|
742
783
|
);
|
|
743
|
-
|
|
784
|
+
for (const object of result) {
|
|
744
785
|
const wrappedGraph = common.encodeGraph(common.wrapObject(object, rawPrefix));
|
|
745
786
|
log("getByIds", wrappedGraph);
|
|
746
787
|
common.merge(results, wrappedGraph);
|
|
747
|
-
}
|
|
788
|
+
}
|
|
748
789
|
};
|
|
749
790
|
const query = common.unwrap(rootQuery, prefix);
|
|
750
791
|
for (const node of query) {
|
|
@@ -775,28 +816,40 @@ class Db {
|
|
|
775
816
|
const prefix = common.encodePath(rawPrefix);
|
|
776
817
|
await this.ensureSchema(tableOptions);
|
|
777
818
|
const change = common.unwrap(rootChange, prefix);
|
|
778
|
-
const
|
|
819
|
+
const puts = [];
|
|
820
|
+
const sqls = [];
|
|
821
|
+
for (const node of change) {
|
|
779
822
|
const arg = common.decodeArgs(node);
|
|
780
823
|
if (common.isRange(node)) {
|
|
781
|
-
if (common.cmp(node.key, node.end) === 0)
|
|
782
|
-
|
|
824
|
+
if (common.cmp(node.key, node.end) === 0) {
|
|
825
|
+
log("delete", node);
|
|
826
|
+
sqls.push(del(arg, tableOptions));
|
|
827
|
+
continue;
|
|
828
|
+
}
|
|
783
829
|
throw Error("pg_write.write_range_unsupported");
|
|
784
830
|
}
|
|
785
831
|
const object = common.decodeGraph(node.children);
|
|
786
832
|
if (common.isPlainObject(arg)) {
|
|
787
833
|
common.mergeObject(object, arg);
|
|
788
834
|
} else {
|
|
789
|
-
object.
|
|
835
|
+
object[tableOptions.idCol] = arg;
|
|
790
836
|
}
|
|
791
837
|
if (object.$put && object.$put !== true) {
|
|
792
838
|
throw Error("pg_write.partial_put_unsupported");
|
|
793
839
|
}
|
|
794
|
-
|
|
795
|
-
|
|
840
|
+
if (object.$put) {
|
|
841
|
+
puts.push([object, arg]);
|
|
842
|
+
} else {
|
|
843
|
+
sqls.push(patch(object, arg, tableOptions));
|
|
844
|
+
}
|
|
845
|
+
}
|
|
846
|
+
if (puts.length)
|
|
847
|
+
sqls.push(...put(puts, tableOptions));
|
|
796
848
|
const result = [];
|
|
797
849
|
await Promise.all(
|
|
798
850
|
sqls.map(
|
|
799
851
|
(sql2) => this.writeSql(sql2, tableOptions).then((object) => {
|
|
852
|
+
log("returned_object_wrapped", common.wrapObject(object, rawPrefix));
|
|
800
853
|
common.merge(result, common.encodeGraph(common.wrapObject(object, rawPrefix)));
|
|
801
854
|
})
|
|
802
855
|
)
|
package/index.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { isEmpty, isPlainObject, encodePath, unwrap, decodeArgs, decodeQuery, finalize, wrap, isRange, cmp, decodeGraph, mergeObject, merge, encodeGraph,
|
|
2
|
-
import pg$1 from "pg";
|
|
1
|
+
import { isEmpty, isPlainObject, encodePath, unwrap, decodeArgs, decodeQuery, finalize, wrap, isRange, cmp, decodeGraph, mergeObject, wrapObject, merge, encodeGraph, remove } from "@graffy/common";
|
|
3
2
|
import debug from "debug";
|
|
3
|
+
import pg$1 from "pg";
|
|
4
4
|
class Sql {
|
|
5
5
|
constructor(rawStrings, rawValues) {
|
|
6
6
|
if (rawStrings.length - 1 !== rawValues.length) {
|
|
@@ -296,14 +296,43 @@ function castValue(value, type, name, isPut) {
|
|
|
296
296
|
return cubeLiteralSql(value);
|
|
297
297
|
return value;
|
|
298
298
|
}
|
|
299
|
-
const getInsert = (
|
|
299
|
+
const getInsert = (rows, options) => {
|
|
300
|
+
const { verCol, schema } = options;
|
|
300
301
|
const cols = [];
|
|
302
|
+
const colSqls = [];
|
|
303
|
+
const colIx = {};
|
|
304
|
+
const colUsed = [];
|
|
305
|
+
for (const col of Object.keys(options.schema.types)) {
|
|
306
|
+
colIx[col] = cols.length;
|
|
307
|
+
colUsed[cols.length] = false;
|
|
308
|
+
cols.push(col);
|
|
309
|
+
colSqls.push(sql`"${raw(col)}"`);
|
|
310
|
+
}
|
|
311
|
+
colUsed[colIx[verCol]] = true;
|
|
301
312
|
const vals = [];
|
|
302
|
-
|
|
303
|
-
cols.
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
313
|
+
for (const row of rows) {
|
|
314
|
+
const rowVals = Array(cols.length).fill(sql`default`);
|
|
315
|
+
for (const col of cols) {
|
|
316
|
+
if (col === verCol || !(col in row))
|
|
317
|
+
continue;
|
|
318
|
+
const ix = colIx[col];
|
|
319
|
+
colUsed[ix] = true;
|
|
320
|
+
rowVals[ix] = castValue(row[col], schema.types[col], col, row.$put);
|
|
321
|
+
}
|
|
322
|
+
vals.push(rowVals);
|
|
323
|
+
}
|
|
324
|
+
const isUsed = (_, ix) => colUsed[ix];
|
|
325
|
+
return {
|
|
326
|
+
cols: join(colSqls.filter(isUsed), ", "),
|
|
327
|
+
vals: join(
|
|
328
|
+
vals.map((rowVals) => sql`(${join(rowVals.filter(isUsed), ", ")})`),
|
|
329
|
+
", "
|
|
330
|
+
),
|
|
331
|
+
updates: join(
|
|
332
|
+
colSqls.map((col, ix) => sql`${col} = "excluded".${col}`).filter(isUsed),
|
|
333
|
+
", "
|
|
334
|
+
)
|
|
335
|
+
};
|
|
307
336
|
};
|
|
308
337
|
const getUpdates = (row, options) => {
|
|
309
338
|
return join(
|
|
@@ -593,23 +622,35 @@ function patch(object, arg, options) {
|
|
|
593
622
|
WHERE ${where}
|
|
594
623
|
RETURNING ${getSelectCols(options)}, ${meta}`;
|
|
595
624
|
}
|
|
596
|
-
function put(
|
|
625
|
+
function put(puts, options) {
|
|
597
626
|
const { idCol, table } = options;
|
|
598
|
-
const
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
627
|
+
const sqls = [];
|
|
628
|
+
const addSql = (rows, meta, conflictTarget) => {
|
|
629
|
+
const { cols, vals, updates } = getInsert(rows, options);
|
|
630
|
+
sqls.push(sql`
|
|
631
|
+
INSERT INTO "${raw(table)}" (${cols}) VALUES ${vals}
|
|
632
|
+
ON CONFLICT (${conflictTarget}) DO UPDATE SET ${updates}
|
|
633
|
+
RETURNING ${getSelectCols(options)}, ${meta}`);
|
|
634
|
+
};
|
|
635
|
+
const idRows = [];
|
|
636
|
+
for (const put2 of puts) {
|
|
637
|
+
const [row, arg] = put2;
|
|
638
|
+
if (!isPlainObject(arg)) {
|
|
639
|
+
idRows.push(row);
|
|
640
|
+
continue;
|
|
641
|
+
}
|
|
642
|
+
const { meta } = getArgSql(arg, options);
|
|
643
|
+
const conflictTarget = join(
|
|
644
|
+
Object.keys(arg).map((col) => sql`"${raw(col)}"`)
|
|
645
|
+
);
|
|
646
|
+
addSql([row], meta, conflictTarget);
|
|
607
647
|
}
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
648
|
+
if (idRows.length) {
|
|
649
|
+
const meta = getIdMeta(options);
|
|
650
|
+
const conflictTarget = sql`"${raw(idCol)}"`;
|
|
651
|
+
addSql(idRows, meta, conflictTarget);
|
|
652
|
+
}
|
|
653
|
+
return sqls;
|
|
613
654
|
}
|
|
614
655
|
function del(arg, options) {
|
|
615
656
|
const { table } = options;
|
|
@@ -674,7 +715,7 @@ class Db {
|
|
|
674
715
|
if (!res.rowCount) {
|
|
675
716
|
throw Error(`pg.nothing_written ${sql2.text} with ${sql2.values}`);
|
|
676
717
|
}
|
|
677
|
-
return res.rows
|
|
718
|
+
return res.rows;
|
|
678
719
|
}
|
|
679
720
|
async ensureSchema(tableOptions, typeOids) {
|
|
680
721
|
if (tableOptions.schema)
|
|
@@ -738,11 +779,11 @@ class Db {
|
|
|
738
779
|
selectByIds(Object.keys(idQueries), null, tableOptions),
|
|
739
780
|
tableOptions
|
|
740
781
|
);
|
|
741
|
-
|
|
782
|
+
for (const object of result) {
|
|
742
783
|
const wrappedGraph = encodeGraph(wrapObject(object, rawPrefix));
|
|
743
784
|
log("getByIds", wrappedGraph);
|
|
744
785
|
merge(results, wrappedGraph);
|
|
745
|
-
}
|
|
786
|
+
}
|
|
746
787
|
};
|
|
747
788
|
const query = unwrap(rootQuery, prefix);
|
|
748
789
|
for (const node of query) {
|
|
@@ -773,28 +814,40 @@ class Db {
|
|
|
773
814
|
const prefix = encodePath(rawPrefix);
|
|
774
815
|
await this.ensureSchema(tableOptions);
|
|
775
816
|
const change = unwrap(rootChange, prefix);
|
|
776
|
-
const
|
|
817
|
+
const puts = [];
|
|
818
|
+
const sqls = [];
|
|
819
|
+
for (const node of change) {
|
|
777
820
|
const arg = decodeArgs(node);
|
|
778
821
|
if (isRange(node)) {
|
|
779
|
-
if (cmp(node.key, node.end) === 0)
|
|
780
|
-
|
|
822
|
+
if (cmp(node.key, node.end) === 0) {
|
|
823
|
+
log("delete", node);
|
|
824
|
+
sqls.push(del(arg, tableOptions));
|
|
825
|
+
continue;
|
|
826
|
+
}
|
|
781
827
|
throw Error("pg_write.write_range_unsupported");
|
|
782
828
|
}
|
|
783
829
|
const object = decodeGraph(node.children);
|
|
784
830
|
if (isPlainObject(arg)) {
|
|
785
831
|
mergeObject(object, arg);
|
|
786
832
|
} else {
|
|
787
|
-
object.
|
|
833
|
+
object[tableOptions.idCol] = arg;
|
|
788
834
|
}
|
|
789
835
|
if (object.$put && object.$put !== true) {
|
|
790
836
|
throw Error("pg_write.partial_put_unsupported");
|
|
791
837
|
}
|
|
792
|
-
|
|
793
|
-
|
|
838
|
+
if (object.$put) {
|
|
839
|
+
puts.push([object, arg]);
|
|
840
|
+
} else {
|
|
841
|
+
sqls.push(patch(object, arg, tableOptions));
|
|
842
|
+
}
|
|
843
|
+
}
|
|
844
|
+
if (puts.length)
|
|
845
|
+
sqls.push(...put(puts, tableOptions));
|
|
794
846
|
const result = [];
|
|
795
847
|
await Promise.all(
|
|
796
848
|
sqls.map(
|
|
797
849
|
(sql2) => this.writeSql(sql2, tableOptions).then((object) => {
|
|
850
|
+
log("returned_object_wrapped", wrapObject(object, rawPrefix));
|
|
798
851
|
merge(result, encodeGraph(wrapObject(object, rawPrefix)));
|
|
799
852
|
})
|
|
800
853
|
)
|
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.16.
|
|
5
|
+
"version": "0.16.9-alpha.2",
|
|
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.16.
|
|
19
|
+
"@graffy/common": "0.16.9-alpha.2",
|
|
20
20
|
"debug": "^4.3.3"
|
|
21
21
|
},
|
|
22
22
|
"peerDependencies": {
|
package/types/sql/clauses.d.ts
CHANGED
|
@@ -3,9 +3,10 @@ export function getJsonBuildTrusted(variadic: any): Sql;
|
|
|
3
3
|
export function lookup(prop: any, options: any): Sql;
|
|
4
4
|
export function lookupNumeric(prop: any): Sql;
|
|
5
5
|
export function getSelectCols(options: any, projection?: any): Sql;
|
|
6
|
-
export function getInsert(
|
|
6
|
+
export function getInsert(rows: any, options: any): {
|
|
7
7
|
cols: Sql;
|
|
8
8
|
vals: Sql;
|
|
9
|
+
updates: Sql;
|
|
9
10
|
};
|
|
10
11
|
export function getUpdates(row: any, options: any): Sql;
|
|
11
12
|
import { Sql } from "sql-template-tag";
|
package/types/sql/upsert.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
export function patch(object: any, arg: any, options: any): import("sql-template-tag").Sql;
|
|
2
|
-
export function put(
|
|
2
|
+
export function put(puts: any, options: any): any[];
|
|
3
3
|
export function del(arg: any, options: any): import("sql-template-tag").Sql;
|