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