@saltcorn/postgres 1.1.4-alpha.0 → 1.1.4-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/package.json +2 -2
- package/postgres.js +67 -35
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@saltcorn/postgres",
|
|
3
|
-
"version": "1.1.4-alpha.
|
|
3
|
+
"version": "1.1.4-alpha.1",
|
|
4
4
|
"description": "Postgres structures for Saltcorn, open-source no-code platform",
|
|
5
5
|
"homepage": "https://saltcorn.com",
|
|
6
6
|
"scripts": {
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
"license": "MIT",
|
|
13
13
|
"main": "index.js",
|
|
14
14
|
"dependencies": {
|
|
15
|
-
"@saltcorn/db-common": "1.1.4-alpha.
|
|
15
|
+
"@saltcorn/db-common": "1.1.4-alpha.1",
|
|
16
16
|
"pg": "^8.13.1",
|
|
17
17
|
"pg-copy-streams": "^6.0.6",
|
|
18
18
|
"replacestream": "4.0.3"
|
package/postgres.js
CHANGED
|
@@ -17,9 +17,9 @@ const {
|
|
|
17
17
|
} = require("@saltcorn/db-common/internal");
|
|
18
18
|
|
|
19
19
|
let getTenantSchema;
|
|
20
|
+
let getRequestContext;
|
|
20
21
|
let getConnectObject = null;
|
|
21
22
|
let pool = null;
|
|
22
|
-
let client = null;
|
|
23
23
|
|
|
24
24
|
let log_sql_enabled = false;
|
|
25
25
|
|
|
@@ -74,20 +74,20 @@ const changeConnection = async (connObj = Object.create(null)) => {
|
|
|
74
74
|
};
|
|
75
75
|
|
|
76
76
|
const begin = async () => {
|
|
77
|
-
client = await getClient();
|
|
78
|
-
await
|
|
77
|
+
//client = await getClient();
|
|
78
|
+
await query("BEGIN");
|
|
79
79
|
};
|
|
80
80
|
|
|
81
81
|
const commit = async () => {
|
|
82
|
-
await
|
|
83
|
-
client.release(true);
|
|
84
|
-
client = null;
|
|
82
|
+
await query("COMMIT");
|
|
85
83
|
};
|
|
86
84
|
|
|
87
85
|
const rollback = async () => {
|
|
88
|
-
await
|
|
89
|
-
|
|
90
|
-
|
|
86
|
+
await query("ROLLBACK");
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
const getMyClient = (selopts) => {
|
|
90
|
+
return selopts?.client || getRequestContext()?.client || pool;
|
|
91
91
|
};
|
|
92
92
|
|
|
93
93
|
/**
|
|
@@ -108,7 +108,7 @@ const select = async (tbl, whereObj, selectopts = Object.create(null)) => {
|
|
|
108
108
|
false
|
|
109
109
|
)}`;
|
|
110
110
|
sql_log(sql, values);
|
|
111
|
-
const tq = await (
|
|
111
|
+
const tq = await getMyClient(selectopts).query(sql, values);
|
|
112
112
|
|
|
113
113
|
return tq.rows;
|
|
114
114
|
};
|
|
@@ -127,7 +127,7 @@ const drop_reset_schema = async (schema) => {
|
|
|
127
127
|
COMMENT ON SCHEMA "${schema}" IS 'standard public schema';`;
|
|
128
128
|
sql_log(sql);
|
|
129
129
|
|
|
130
|
-
await
|
|
130
|
+
await getMyClient().query(sql);
|
|
131
131
|
};
|
|
132
132
|
|
|
133
133
|
/**
|
|
@@ -152,7 +152,7 @@ const count = async (tbl, whereObj) => {
|
|
|
152
152
|
FROM pg_catalog.pg_class c
|
|
153
153
|
WHERE c.oid = '"${getTenantSchema()}"."${sqlsanitize(tbl)}"'::regclass`;
|
|
154
154
|
sql_log(sql);
|
|
155
|
-
const tq = await (
|
|
155
|
+
const tq = await getMyClient().query(sql, []);
|
|
156
156
|
const n = +tq.rows[0].int8;
|
|
157
157
|
if (n && n > 10000) return n;
|
|
158
158
|
} catch {
|
|
@@ -164,7 +164,7 @@ WHERE c.oid = '"${getTenantSchema()}"."${sqlsanitize(tbl)}"'::regclass`;
|
|
|
164
164
|
tbl
|
|
165
165
|
)}" ${where}`;
|
|
166
166
|
sql_log(sql, values);
|
|
167
|
-
const tq = await (
|
|
167
|
+
const tq = await getMyClient().query(sql, values);
|
|
168
168
|
|
|
169
169
|
return parseInt(tq.rows[0].count);
|
|
170
170
|
};
|
|
@@ -177,7 +177,7 @@ WHERE c.oid = '"${getTenantSchema()}"."${sqlsanitize(tbl)}"'::regclass`;
|
|
|
177
177
|
const getVersion = async (short) => {
|
|
178
178
|
const sql = `SELECT version();`;
|
|
179
179
|
sql_log(sql);
|
|
180
|
-
const tq = await
|
|
180
|
+
const tq = await getMyClient().query(sql);
|
|
181
181
|
const v = tq.rows[0].version;
|
|
182
182
|
if (short) {
|
|
183
183
|
const ws = v.split(" ");
|
|
@@ -200,7 +200,7 @@ const deleteWhere = async (tbl, whereObj, opts = Object.create(null)) => {
|
|
|
200
200
|
)}" ${where}`;
|
|
201
201
|
sql_log(sql, values);
|
|
202
202
|
|
|
203
|
-
const tq = await (
|
|
203
|
+
const tq = await getMyClient(opts).query(sql, values);
|
|
204
204
|
|
|
205
205
|
return tq.rows;
|
|
206
206
|
};
|
|
@@ -209,7 +209,7 @@ const truncate = async (tbl) => {
|
|
|
209
209
|
const sql = `truncate "${getTenantSchema()}"."${sqlsanitize(tbl)}"`;
|
|
210
210
|
sql_log(sql, []);
|
|
211
211
|
|
|
212
|
-
const tq = await (
|
|
212
|
+
const tq = await getMyClient().query(sql, []);
|
|
213
213
|
|
|
214
214
|
return tq.rows;
|
|
215
215
|
};
|
|
@@ -252,7 +252,7 @@ const insert = async (tbl, obj, opts = Object.create(null)) => {
|
|
|
252
252
|
tbl
|
|
253
253
|
)}" DEFAULT VALUES returning ${opts.noid ? "*" : ppPK(opts.pk_name)}`;
|
|
254
254
|
sql_log(sql, valList);
|
|
255
|
-
const { rows } = await (
|
|
255
|
+
const { rows } = await getMyClient(opts).query(sql, valList);
|
|
256
256
|
if (opts.noid) return;
|
|
257
257
|
else if (conflict && rows.length === 0) return;
|
|
258
258
|
else return rows[0][opts.pk_name || "id"];
|
|
@@ -280,7 +280,7 @@ const update = async (tbl, obj, id, opts = Object.create(null)) => {
|
|
|
280
280
|
tbl
|
|
281
281
|
)}" set ${assigns} where ${ppPK(opts.pk_name)}=$${kvs.length + 1}`;
|
|
282
282
|
sql_log(q, valList);
|
|
283
|
-
await (
|
|
283
|
+
await getMyClient(opts).query(q, valList);
|
|
284
284
|
};
|
|
285
285
|
|
|
286
286
|
/**
|
|
@@ -304,7 +304,7 @@ const updateWhere = async (tbl, obj, whereObj, opts = Object.create(null)) => {
|
|
|
304
304
|
tbl
|
|
305
305
|
)}" set ${assigns} ${where}`;
|
|
306
306
|
sql_log(q, valList);
|
|
307
|
-
await (
|
|
307
|
+
await getMyClient().query(q, valList);
|
|
308
308
|
};
|
|
309
309
|
|
|
310
310
|
/**
|
|
@@ -356,7 +356,7 @@ const reset_sequence = async (tblname, pkname = "id") => {
|
|
|
356
356
|
)}"', '${pkname}'), coalesce(max("${pkname}"),0) + 1, false) FROM "${getTenantSchema()}"."${sqlsanitize(
|
|
357
357
|
tblname
|
|
358
358
|
)}";`;
|
|
359
|
-
await (
|
|
359
|
+
await getMyClient().query(sql);
|
|
360
360
|
};
|
|
361
361
|
|
|
362
362
|
/**
|
|
@@ -375,7 +375,7 @@ const add_unique_constraint = async (table_name, field_names) => {
|
|
|
375
375
|
.map((f) => `"${sqlsanitize(f)}"`)
|
|
376
376
|
.join(",")});`;
|
|
377
377
|
sql_log(sql);
|
|
378
|
-
await
|
|
378
|
+
await getMyClient().query(sql);
|
|
379
379
|
};
|
|
380
380
|
|
|
381
381
|
/**
|
|
@@ -392,7 +392,7 @@ const drop_unique_constraint = async (table_name, field_names) => {
|
|
|
392
392
|
.map((f) => sqlsanitize(f))
|
|
393
393
|
.join("_")}_unique";`;
|
|
394
394
|
sql_log(sql);
|
|
395
|
-
await
|
|
395
|
+
await getMyClient().query(sql);
|
|
396
396
|
};
|
|
397
397
|
|
|
398
398
|
/**
|
|
@@ -409,7 +409,7 @@ const add_index = async (table_name, field_name) => {
|
|
|
409
409
|
table_name
|
|
410
410
|
)}" ("${sqlsanitize(field_name)}");`;
|
|
411
411
|
sql_log(sql);
|
|
412
|
-
await
|
|
412
|
+
await getMyClient().query(sql);
|
|
413
413
|
};
|
|
414
414
|
|
|
415
415
|
/**
|
|
@@ -428,7 +428,7 @@ const add_fts_index = async (table_name, field_expression, language) => {
|
|
|
428
428
|
language || "english"
|
|
429
429
|
}', ${field_expression}));`;
|
|
430
430
|
sql_log(sql);
|
|
431
|
-
await
|
|
431
|
+
await getMyClient().query(sql);
|
|
432
432
|
};
|
|
433
433
|
const drop_fts_index = async (table_name) => {
|
|
434
434
|
// TBD check that there are no problems with lenght of constraint name
|
|
@@ -436,7 +436,7 @@ const drop_fts_index = async (table_name) => {
|
|
|
436
436
|
table_name
|
|
437
437
|
)}_fts_index";`;
|
|
438
438
|
sql_log(sql);
|
|
439
|
-
await
|
|
439
|
+
await getMyClient().query(sql);
|
|
440
440
|
};
|
|
441
441
|
|
|
442
442
|
/**
|
|
@@ -451,7 +451,7 @@ const drop_index = async (table_name, field_name) => {
|
|
|
451
451
|
table_name
|
|
452
452
|
)}_${sqlsanitize(field_name)}_index";`;
|
|
453
453
|
sql_log(sql);
|
|
454
|
-
await
|
|
454
|
+
await getMyClient().query(sql);
|
|
455
455
|
};
|
|
456
456
|
|
|
457
457
|
/**
|
|
@@ -477,7 +477,7 @@ const copyToJson = async (fileStream, tableName, client) => {
|
|
|
477
477
|
const sql = `COPY (SELECT (row_to_json("${sqlsanitize(tableName)}".*) || ',')
|
|
478
478
|
FROM "${getTenantSchema()}"."${sqlsanitize(tableName)}") TO STDOUT`;
|
|
479
479
|
sql_log(sql);
|
|
480
|
-
const stream = (client ||
|
|
480
|
+
const stream = (client || getMyClient()).query(copyStreams.to(sql));
|
|
481
481
|
|
|
482
482
|
return await pipeline(stream, replace("\\\\", "\\"), fileStream);
|
|
483
483
|
};
|
|
@@ -489,7 +489,7 @@ const slugify = (s) =>
|
|
|
489
489
|
.replace(/[^\w-]/g, "");
|
|
490
490
|
|
|
491
491
|
const time = async () => {
|
|
492
|
-
const result = await (
|
|
492
|
+
const result = await getMyClient().query("select now()");
|
|
493
493
|
const row = result.rows[0];
|
|
494
494
|
return new Date(row.now);
|
|
495
495
|
};
|
|
@@ -499,7 +499,7 @@ const time = async () => {
|
|
|
499
499
|
* @returns
|
|
500
500
|
*/
|
|
501
501
|
const listTables = async () => {
|
|
502
|
-
const tq = await
|
|
502
|
+
const tq = await getMyClient().query(
|
|
503
503
|
`SELECT table_name FROM information_schema.tables WHERE table_schema = '${getTenantSchema()}'`
|
|
504
504
|
);
|
|
505
505
|
return tq.rows.map((row) => {
|
|
@@ -512,7 +512,7 @@ const listTables = async () => {
|
|
|
512
512
|
* @returns
|
|
513
513
|
*/
|
|
514
514
|
const listUserDefinedTables = async () => {
|
|
515
|
-
const tq = await
|
|
515
|
+
const tq = await getMyClient().query(
|
|
516
516
|
`SELECT table_name FROM information_schema.tables WHERE table_schema = '${getTenantSchema()}' AND table_name NOT LIKE '_sc_%'`
|
|
517
517
|
);
|
|
518
518
|
return tq.rows.map((row) => {
|
|
@@ -525,7 +525,7 @@ const listUserDefinedTables = async () => {
|
|
|
525
525
|
* @returns
|
|
526
526
|
*/
|
|
527
527
|
const listScTables = async () => {
|
|
528
|
-
const tq = await
|
|
528
|
+
const tq = await getMyClient().query(
|
|
529
529
|
`SELECT table_name FROM information_schema.tables WHERE table_schema = '${getTenantSchema()}' AND table_name LIKE '_sc_%'`
|
|
530
530
|
);
|
|
531
531
|
return tq.rows.map((row) => {
|
|
@@ -533,6 +533,37 @@ const listScTables = async () => {
|
|
|
533
533
|
});
|
|
534
534
|
};
|
|
535
535
|
|
|
536
|
+
/* rules of using this:
|
|
537
|
+
|
|
538
|
+
- no try catch inside unless you rethrow: wouldnt roll back
|
|
539
|
+
- no res.json, res.redirect etc inside (client is released on res finish event)
|
|
540
|
+
- no state.refresh_*() inside: other works wouldnt see updates as they are in transactioon
|
|
541
|
+
- you can use state.refresh_*(true) for update on own worker only
|
|
542
|
+
|
|
543
|
+
*/
|
|
544
|
+
const withTransaction = async (f, onError) => {
|
|
545
|
+
await query("BEGIN;");
|
|
546
|
+
let aborted = false;
|
|
547
|
+
const rollback = async () => {
|
|
548
|
+
aborted = true;
|
|
549
|
+
await query("ROLLBACK;");
|
|
550
|
+
};
|
|
551
|
+
try {
|
|
552
|
+
const result = await f(rollback);
|
|
553
|
+
if (!aborted) await query("COMMIT;");
|
|
554
|
+
return result;
|
|
555
|
+
} catch (error) {
|
|
556
|
+
if (!aborted) await query("ROLLBACK;");
|
|
557
|
+
if (onError) return onError(error);
|
|
558
|
+
else throw error;
|
|
559
|
+
}
|
|
560
|
+
};
|
|
561
|
+
|
|
562
|
+
const query = (text, params) => {
|
|
563
|
+
sql_log(text, params);
|
|
564
|
+
return getMyClient().query(text, params);
|
|
565
|
+
};
|
|
566
|
+
|
|
536
567
|
const postgresExports = {
|
|
537
568
|
pool,
|
|
538
569
|
/**
|
|
@@ -540,10 +571,7 @@ const postgresExports = {
|
|
|
540
571
|
* @param {object} params
|
|
541
572
|
* @returns {object}
|
|
542
573
|
*/
|
|
543
|
-
query
|
|
544
|
-
sql_log(text, params);
|
|
545
|
-
return (client || pool).query(text, params);
|
|
546
|
-
},
|
|
574
|
+
query,
|
|
547
575
|
begin,
|
|
548
576
|
commit,
|
|
549
577
|
rollback,
|
|
@@ -579,6 +607,7 @@ const postgresExports = {
|
|
|
579
607
|
listScTables,
|
|
580
608
|
listUserDefinedTables,
|
|
581
609
|
truncate,
|
|
610
|
+
withTransaction,
|
|
582
611
|
};
|
|
583
612
|
|
|
584
613
|
module.exports = (getConnectObjectPara) => {
|
|
@@ -590,6 +619,9 @@ module.exports = (getConnectObjectPara) => {
|
|
|
590
619
|
getTenantSchema = require("@saltcorn/db-common/tenants")(
|
|
591
620
|
connectObj
|
|
592
621
|
).getTenantSchema;
|
|
622
|
+
getRequestContext = require("@saltcorn/db-common/tenants")(
|
|
623
|
+
connectObj
|
|
624
|
+
).getRequestContext;
|
|
593
625
|
postgresExports.pool = pool;
|
|
594
626
|
} else {
|
|
595
627
|
throw new Error("Unable to retrieve a database connection object.");
|