proto.io 0.0.163 → 0.0.165
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/dist/adapters/file/database.d.ts +2 -2
- package/dist/adapters/file/database.js.map +1 -1
- package/dist/adapters/file/database.mjs +2 -2
- package/dist/adapters/file/database.mjs.map +1 -1
- package/dist/adapters/file/filesystem.d.ts +2 -2
- package/dist/adapters/file/filesystem.js.map +1 -1
- package/dist/adapters/file/filesystem.mjs.map +1 -1
- package/dist/adapters/file/google-cloud-storage.d.ts +2 -2
- package/dist/adapters/file/google-cloud-storage.js.map +1 -1
- package/dist/adapters/file/google-cloud-storage.mjs.map +1 -1
- package/dist/adapters/storage/progres.d.ts +16 -13
- package/dist/adapters/storage/progres.js +138 -82
- package/dist/adapters/storage/progres.js.map +1 -1
- package/dist/adapters/storage/progres.mjs +140 -84
- package/dist/adapters/storage/progres.mjs.map +1 -1
- package/dist/client.d.ts +3 -3
- package/dist/client.mjs +3 -3
- package/dist/index.d.ts +7 -12
- package/dist/index.js +24 -23
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +28 -27
- package/dist/index.mjs.map +1 -1
- package/dist/internals/{index-ByfpVHca.mjs → index-BYbMU-Ao.mjs} +2 -2
- package/dist/internals/{index-ByfpVHca.mjs.map → index-BYbMU-Ao.mjs.map} +1 -1
- package/dist/internals/{index-S5Bq-KsU.mjs → index-BejQNqvC.mjs} +2 -2
- package/dist/internals/{index-S5Bq-KsU.mjs.map → index-BejQNqvC.mjs.map} +1 -1
- package/dist/internals/{index-BoP4kl2R.mjs → index-BibByOcU.mjs} +2 -2
- package/dist/internals/{index-BoP4kl2R.mjs.map → index-BibByOcU.mjs.map} +1 -1
- package/dist/internals/index-BqFdBhFc.js.map +1 -1
- package/dist/internals/index-CSNRyhjB.js.map +1 -1
- package/dist/internals/index-CVutVPmd.js.map +1 -1
- package/dist/internals/{index-BeV63sFw.d.ts → index-DaDfXlay.d.ts} +2 -2
- package/dist/internals/index-DaDfXlay.d.ts.map +1 -0
- package/dist/internals/index-Dz3jvqxZ.js.map +1 -1
- package/dist/internals/{index-YdOGTHp1.d.ts → index-RPh4TX0T.d.ts} +3 -2
- package/dist/internals/index-RPh4TX0T.d.ts.map +1 -0
- package/dist/internals/{index-BsuUdR0W.d.ts → index-bCACA0cS.d.ts} +2 -2
- package/dist/internals/index-bCACA0cS.d.ts.map +1 -0
- package/dist/internals/index-be1VYBY2.mjs.map +1 -1
- package/dist/internals/{random-w8WDYQEe.mjs → random-B1P0EZO5.mjs} +5 -10
- package/dist/internals/random-B1P0EZO5.mjs.map +1 -0
- package/dist/internals/{random-uT4D0y_q.js → random-q0PeamQE.js} +3 -8
- package/dist/internals/random-q0PeamQE.js.map +1 -0
- package/package.json +20 -20
- package/dist/internals/index-BeV63sFw.d.ts.map +0 -1
- package/dist/internals/index-BsuUdR0W.d.ts.map +0 -1
- package/dist/internals/index-YdOGTHp1.d.ts.map +0 -1
- package/dist/internals/random-uT4D0y_q.js.map +0 -1
- package/dist/internals/random-w8WDYQEe.mjs.map +0 -1
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import _ from 'lodash';
|
|
2
|
-
import { i as isPointer, a as isRelation, b as isShape, d as decodeUpdateOp, s as shapePaths, e as isPrimitive, T as TObject, f as isVector, _ as
|
|
2
|
+
import { i as isPointer, a as isRelation, b as isShape, d as decodeUpdateOp, s as shapePaths, e as isPrimitive, T as TObject, f as isVector, _ as _encodeValue, g as _decodeValue, h as dimensionOf, j as _typeof } from '../../internals/index-BYbMU-Ao.mjs';
|
|
3
3
|
import { Pool, types } from 'pg';
|
|
4
4
|
import QueryStream from 'pg-query-stream';
|
|
5
5
|
import { asyncStream } from '@o2ter/utils-js';
|
|
6
6
|
import Decimal from 'decimal.js';
|
|
7
7
|
import { escapeLiteral, escapeIdentifier } from 'pg/lib/utils';
|
|
8
|
-
import { a as QueryCoditionalSelector, b as QueryFieldSelector, c as QueryExpressionSelector, d as QueryDistanceExpression, e as QueryCoditionalExpression, f as QueryComparisonExpression, g as QueryNotExpression, h as QueryArrayExpression, i as QueryValueExpression, j as QueryKeyExpression, Q as QuerySelector, F as FieldSelectorExpression } from '../../internals/index-
|
|
8
|
+
import { a as QueryCoditionalSelector, b as QueryFieldSelector, c as QueryExpressionSelector, d as QueryDistanceExpression, e as QueryCoditionalExpression, f as QueryComparisonExpression, g as QueryNotExpression, h as QueryArrayExpression, i as QueryValueExpression, j as QueryKeyExpression, Q as QuerySelector, F as FieldSelectorExpression } from '../../internals/index-BejQNqvC.mjs';
|
|
9
9
|
import '@o2ter/crypto-js';
|
|
10
|
-
import { r as resolveColumn, a as resolveDataType, g as generateId, Q as QueryValidator } from '../../internals/random-
|
|
10
|
+
import { r as resolveColumn, a as resolveDataType, g as generateId, Q as QueryValidator } from '../../internals/random-B1P0EZO5.mjs';
|
|
11
11
|
import { P as PVK } from '../../internals/private-BUpLAMZi.mjs';
|
|
12
12
|
|
|
13
13
|
//
|
|
@@ -112,7 +112,8 @@ class SQL {
|
|
|
112
112
|
query += dialect.boolean(value.value);
|
|
113
113
|
}
|
|
114
114
|
else if (_.isString(value.value)) {
|
|
115
|
-
query += `${dialect.
|
|
115
|
+
query += `${dialect.placeholder(nextIdx())}::TEXT`;
|
|
116
|
+
values.push(value.value);
|
|
116
117
|
}
|
|
117
118
|
else if (_.isSafeInteger(value.value)) {
|
|
118
119
|
query += `${value.value}`;
|
|
@@ -219,12 +220,14 @@ class QueryCompiler {
|
|
|
219
220
|
dialect;
|
|
220
221
|
selectLock;
|
|
221
222
|
isUpdate;
|
|
223
|
+
extraFilter;
|
|
222
224
|
idx = 0;
|
|
223
|
-
constructor(
|
|
224
|
-
this.schema = schema;
|
|
225
|
-
this.dialect = dialect;
|
|
226
|
-
this.selectLock = selectLock;
|
|
227
|
-
this.isUpdate = isUpdate;
|
|
225
|
+
constructor(options) {
|
|
226
|
+
this.schema = options.schema;
|
|
227
|
+
this.dialect = options.dialect;
|
|
228
|
+
this.selectLock = options.selectLock;
|
|
229
|
+
this.isUpdate = options.isUpdate;
|
|
230
|
+
this.extraFilter = options.extraFilter;
|
|
228
231
|
}
|
|
229
232
|
nextIdx() {
|
|
230
233
|
return this.idx++;
|
|
@@ -281,11 +284,11 @@ class QueryCompiler {
|
|
|
281
284
|
}
|
|
282
285
|
_baseSelectQuery(query, options) {
|
|
283
286
|
const context = this._makeContext(query);
|
|
284
|
-
const _stages = _.mapValues(context.populates, (populate) => this.dialect.encodePopulate(this,
|
|
287
|
+
const _stages = _.mapValues(context.populates, (populate) => this.dialect.encodePopulate(this, populate));
|
|
285
288
|
const stages = _.fromPairs(_.flatMap(_.values(_stages), (p) => _.toPairs(p)));
|
|
286
289
|
const fetchName = `_fetch_$${query.className.toLowerCase()}`;
|
|
287
290
|
const parent = { className: query.className, name: fetchName };
|
|
288
|
-
const baseFilter = this._encodeFilter(
|
|
291
|
+
const baseFilter = this._encodeFilter(parent, query.filter);
|
|
289
292
|
const populates = this._selectPopulateMap(context, query.className, fetchName);
|
|
290
293
|
const joins = _.compact(_.map(populates, ({ join }) => join));
|
|
291
294
|
const includes = {
|
|
@@ -299,7 +302,7 @@ class QueryCompiler {
|
|
|
299
302
|
const filter = _.compact([
|
|
300
303
|
baseFilter,
|
|
301
304
|
_options?.extraFilter,
|
|
302
|
-
query.relatedBy && this.dialect.encodeRelation(this,
|
|
305
|
+
query.relatedBy && this.dialect.encodeRelation(this, parent, query.relatedBy),
|
|
303
306
|
]);
|
|
304
307
|
return {
|
|
305
308
|
stages,
|
|
@@ -320,9 +323,9 @@ class QueryCompiler {
|
|
|
320
323
|
`,
|
|
321
324
|
};
|
|
322
325
|
}
|
|
323
|
-
_refetch(name, query
|
|
326
|
+
_refetch(name, query) {
|
|
324
327
|
const _context = this._encodeIncludes(query.className, query.includes, query.matches);
|
|
325
|
-
const populates = _.mapValues(_context.populates, (populate) => this.dialect.encodePopulate(this,
|
|
328
|
+
const populates = _.mapValues(_context.populates, (populate) => this.dialect.encodePopulate(this, populate, { className: query.className, name }));
|
|
326
329
|
const stages = _.fromPairs(_.flatMap(_.values(populates), (p) => _.toPairs(p)));
|
|
327
330
|
const _populates = this._selectPopulateMap(_context, query.className, name);
|
|
328
331
|
const _joins = _.compact(_.map(_populates, ({ join }) => join));
|
|
@@ -393,8 +396,8 @@ class QueryCompiler {
|
|
|
393
396
|
}
|
|
394
397
|
return result;
|
|
395
398
|
}
|
|
396
|
-
_encodeCoditionalSelector(parent, filter
|
|
397
|
-
const queries = _.compact(_.map(filter.exprs, x => this._encodeFilter(
|
|
399
|
+
_encodeCoditionalSelector(parent, filter) {
|
|
400
|
+
const queries = _.compact(_.map(filter.exprs, x => this._encodeFilter(parent, x)));
|
|
398
401
|
if (_.isEmpty(queries))
|
|
399
402
|
return;
|
|
400
403
|
switch (filter.type) {
|
|
@@ -403,12 +406,12 @@ class QueryCompiler {
|
|
|
403
406
|
case '$or': return sql `(${{ literal: _.map(queries, x => sql `(${x})`), separator: ' OR ' }})`;
|
|
404
407
|
}
|
|
405
408
|
}
|
|
406
|
-
_encodeFilter(
|
|
409
|
+
_encodeFilter(parent, filter) {
|
|
407
410
|
if (filter instanceof QueryCoditionalSelector) {
|
|
408
|
-
return this._encodeCoditionalSelector(parent, filter
|
|
411
|
+
return this._encodeCoditionalSelector(parent, filter);
|
|
409
412
|
}
|
|
410
413
|
if (filter instanceof QueryFieldSelector) {
|
|
411
|
-
return this.dialect.encodeFieldExpression(this,
|
|
414
|
+
return this.dialect.encodeFieldExpression(this, parent, filter.field, filter.expr);
|
|
412
415
|
}
|
|
413
416
|
if (filter instanceof QueryExpressionSelector) {
|
|
414
417
|
return this.dialect.encodeQueryExpression(this, parent, filter.expr);
|
|
@@ -449,7 +452,7 @@ class QueryCompiler {
|
|
|
449
452
|
});
|
|
450
453
|
const name = `_insert_$${options.className.toLowerCase()}`;
|
|
451
454
|
const context = this._makeContext(options);
|
|
452
|
-
const populates = _.mapValues(context.populates, (populate) => this.dialect.encodePopulate(this,
|
|
455
|
+
const populates = _.mapValues(context.populates, (populate) => this.dialect.encodePopulate(this, populate));
|
|
453
456
|
const stages = _.fromPairs(_.flatMap(_.values(populates), (p) => _.toPairs(p)));
|
|
454
457
|
const _populates = this._selectPopulateMap(context, options.className, name);
|
|
455
458
|
const joins = _.compact(_.map(_populates, ({ join }) => join));
|
|
@@ -484,7 +487,7 @@ class QueryCompiler {
|
|
|
484
487
|
`;
|
|
485
488
|
}
|
|
486
489
|
updateOne(query, update) {
|
|
487
|
-
return this._modifyQuery({ ...query, limit: 1 }, (fetchName
|
|
490
|
+
return this._modifyQuery({ ...query, limit: 1 }, (fetchName) => {
|
|
488
491
|
const name = `_update_$${query.className.toLowerCase()}`;
|
|
489
492
|
return sql `
|
|
490
493
|
, ${{ identifier: name }} AS (
|
|
@@ -494,7 +497,7 @@ class QueryCompiler {
|
|
|
494
497
|
WHERE ${{ identifier: query.className }}._id IN (SELECT ${{ identifier: fetchName }}._id FROM ${{ identifier: fetchName }})
|
|
495
498
|
RETURNING *
|
|
496
499
|
)
|
|
497
|
-
${this._refetch(name, query
|
|
500
|
+
${this._refetch(name, query)}
|
|
498
501
|
`;
|
|
499
502
|
});
|
|
500
503
|
}
|
|
@@ -503,7 +506,7 @@ class QueryCompiler {
|
|
|
503
506
|
..._defaultInsertOpts(query),
|
|
504
507
|
...this._encodeObjectAttrs(query.className, setOnInsert),
|
|
505
508
|
});
|
|
506
|
-
return this._modifyQuery({ ...query, limit: 1 }, (fetchName
|
|
509
|
+
return this._modifyQuery({ ...query, limit: 1 }, (fetchName) => {
|
|
507
510
|
const updateName = `_update_$${query.className.toLowerCase()}`;
|
|
508
511
|
const insertName = `_insert_$${query.className.toLowerCase()}`;
|
|
509
512
|
const upsertName = `_upsert_$${query.className.toLowerCase()}`;
|
|
@@ -527,7 +530,7 @@ class QueryCompiler {
|
|
|
527
530
|
UNION
|
|
528
531
|
SELECT * FROM ${{ identifier: insertName }}
|
|
529
532
|
)
|
|
530
|
-
${this._refetch(upsertName, query
|
|
533
|
+
${this._refetch(upsertName, query)}
|
|
531
534
|
`;
|
|
532
535
|
});
|
|
533
536
|
}
|
|
@@ -662,12 +665,21 @@ class SqlStorage {
|
|
|
662
665
|
}
|
|
663
666
|
return obj;
|
|
664
667
|
}
|
|
668
|
+
_makeCompiler(isUpdate, extraFilter) {
|
|
669
|
+
return new QueryCompiler({
|
|
670
|
+
schema: this.schema,
|
|
671
|
+
dialect: this.dialect,
|
|
672
|
+
selectLock: this.selectLock(),
|
|
673
|
+
isUpdate,
|
|
674
|
+
extraFilter,
|
|
675
|
+
});
|
|
676
|
+
}
|
|
665
677
|
async explain(query) {
|
|
666
|
-
const compiler =
|
|
678
|
+
const compiler = this._makeCompiler(false, query.extraFilter);
|
|
667
679
|
return this._explain(compiler, query);
|
|
668
680
|
}
|
|
669
681
|
async count(query) {
|
|
670
|
-
const compiler =
|
|
682
|
+
const compiler = this._makeCompiler(false, query.extraFilter);
|
|
671
683
|
const [{ count: _count }] = await this.query(compiler._selectQuery(query, {
|
|
672
684
|
select: sql `COUNT(*) AS count`,
|
|
673
685
|
}));
|
|
@@ -676,7 +688,7 @@ class SqlStorage {
|
|
|
676
688
|
}
|
|
677
689
|
find(query) {
|
|
678
690
|
const self = this;
|
|
679
|
-
const compiler =
|
|
691
|
+
const compiler = self._makeCompiler(false, query.extraFilter);
|
|
680
692
|
const _query = compiler._selectQuery(query);
|
|
681
693
|
return (async function* () {
|
|
682
694
|
const objects = self.query(_query);
|
|
@@ -687,7 +699,7 @@ class SqlStorage {
|
|
|
687
699
|
}
|
|
688
700
|
random(query, opts) {
|
|
689
701
|
const self = this;
|
|
690
|
-
const compiler =
|
|
702
|
+
const compiler = self._makeCompiler(false, query.extraFilter);
|
|
691
703
|
const _query = compiler._selectQuery({ ...query, sort: {} }, {
|
|
692
704
|
sort: sql `ORDER BY ${self.dialect.random(opts ?? {})}`,
|
|
693
705
|
});
|
|
@@ -714,7 +726,7 @@ class SqlStorage {
|
|
|
714
726
|
}
|
|
715
727
|
nonrefs(query) {
|
|
716
728
|
const self = this;
|
|
717
|
-
const compiler =
|
|
729
|
+
const compiler = self._makeCompiler(false, query.extraFilter);
|
|
718
730
|
const _query = compiler._selectQuery(query, ({ fetchName }) => ({
|
|
719
731
|
extraFilter: sql `
|
|
720
732
|
NOT EXISTS (${this._refs(this.schema, query.className, ['_id'], sql `(${{ quote: query.className + '$' }} || ${{ identifier: fetchName }}.${{ identifier: '_id' }})`)})
|
|
@@ -728,32 +740,32 @@ class SqlStorage {
|
|
|
728
740
|
})();
|
|
729
741
|
}
|
|
730
742
|
async insert(options, attrs) {
|
|
731
|
-
const compiler =
|
|
743
|
+
const compiler = this._makeCompiler(true);
|
|
732
744
|
const result = _.first(await this.query(compiler.insert(options, attrs)));
|
|
733
745
|
return _.isNil(result) ? undefined : this._decodeObject(options.className, result);
|
|
734
746
|
}
|
|
735
747
|
async insertMany(options, values) {
|
|
736
|
-
const compiler =
|
|
748
|
+
const compiler = this._makeCompiler(true);
|
|
737
749
|
const result = await this.query(compiler.insertMany(options, values));
|
|
738
750
|
return result.length;
|
|
739
751
|
}
|
|
740
752
|
async updateOne(query, update) {
|
|
741
|
-
const compiler =
|
|
753
|
+
const compiler = this._makeCompiler(true, query.extraFilter);
|
|
742
754
|
const updated = _.first(await this.query(compiler.updateOne(query, update)));
|
|
743
755
|
return _.isNil(updated) ? undefined : this._decodeObject(query.className, updated);
|
|
744
756
|
}
|
|
745
757
|
async upsertOne(query, update, setOnInsert) {
|
|
746
|
-
const compiler =
|
|
758
|
+
const compiler = this._makeCompiler(true, query.extraFilter);
|
|
747
759
|
const upserted = _.first(await this.query(compiler.upsertOne(query, update, setOnInsert)));
|
|
748
760
|
return _.isNil(upserted) ? undefined : this._decodeObject(query.className, upserted);
|
|
749
761
|
}
|
|
750
762
|
async deleteOne(query) {
|
|
751
|
-
const compiler =
|
|
763
|
+
const compiler = this._makeCompiler(true, query.extraFilter);
|
|
752
764
|
const deleted = _.first(await this.query(compiler.deleteOne(query)));
|
|
753
765
|
return _.isNil(deleted) ? undefined : this._decodeObject(query.className, deleted);
|
|
754
766
|
}
|
|
755
767
|
async deleteMany(query) {
|
|
756
|
-
const compiler =
|
|
768
|
+
const compiler = this._makeCompiler(true, query.extraFilter);
|
|
757
769
|
const deleted = await this.query(compiler.deleteMany(query));
|
|
758
770
|
return deleted.length;
|
|
759
771
|
}
|
|
@@ -1109,10 +1121,55 @@ class PostgresClientDriver {
|
|
|
1109
1121
|
});
|
|
1110
1122
|
}
|
|
1111
1123
|
}
|
|
1124
|
+
class PostgresPubSub {
|
|
1125
|
+
client;
|
|
1126
|
+
subscribers = {};
|
|
1127
|
+
channels = [];
|
|
1128
|
+
constructor(client) {
|
|
1129
|
+
this.client = client;
|
|
1130
|
+
(async () => {
|
|
1131
|
+
try {
|
|
1132
|
+
(await client).on('notification', ({ channel, payload }) => {
|
|
1133
|
+
if (!payload)
|
|
1134
|
+
return;
|
|
1135
|
+
try {
|
|
1136
|
+
const _payload = _decodeValue(JSON.parse(payload));
|
|
1137
|
+
for (const subscriber of this.subscribers[_.toUpper(channel)]) {
|
|
1138
|
+
subscriber(_payload);
|
|
1139
|
+
}
|
|
1140
|
+
}
|
|
1141
|
+
catch (e) {
|
|
1142
|
+
console.error(`Unknown payload: ${e}`);
|
|
1143
|
+
}
|
|
1144
|
+
});
|
|
1145
|
+
}
|
|
1146
|
+
catch (e) {
|
|
1147
|
+
console.error(e);
|
|
1148
|
+
}
|
|
1149
|
+
})();
|
|
1150
|
+
}
|
|
1151
|
+
async shutdown() {
|
|
1152
|
+
(await this.client).release();
|
|
1153
|
+
}
|
|
1154
|
+
async listen(channel) {
|
|
1155
|
+
this.channels.push(channel);
|
|
1156
|
+
await (await this.client).query(`LISTEN ${channel}`);
|
|
1157
|
+
}
|
|
1158
|
+
subscribe(channel, callback) {
|
|
1159
|
+
if (_.isNil(this.subscribers[channel]))
|
|
1160
|
+
this.subscribers[channel] = [];
|
|
1161
|
+
this.subscribers[channel].push(callback);
|
|
1162
|
+
return () => {
|
|
1163
|
+
this.subscribers[channel] = this.subscribers[channel].filter(x => x !== callback);
|
|
1164
|
+
};
|
|
1165
|
+
}
|
|
1166
|
+
isEmpty() {
|
|
1167
|
+
return _.every(_.values(this.subscribers), x => _.isEmpty(x));
|
|
1168
|
+
}
|
|
1169
|
+
}
|
|
1112
1170
|
class PostgresDriver extends PostgresClientDriver {
|
|
1113
1171
|
database;
|
|
1114
1172
|
pubsub;
|
|
1115
|
-
subscribers = [];
|
|
1116
1173
|
constructor(config) {
|
|
1117
1174
|
if (_.isEmpty(config))
|
|
1118
1175
|
throw Error('Invalid postgre config.');
|
|
@@ -1125,26 +1182,11 @@ class PostgresDriver extends PostgresClientDriver {
|
|
|
1125
1182
|
await this._release_pubsub();
|
|
1126
1183
|
await this.database.end();
|
|
1127
1184
|
}
|
|
1128
|
-
|
|
1185
|
+
_init_pubsub() {
|
|
1129
1186
|
if (this.pubsub)
|
|
1130
1187
|
return;
|
|
1131
1188
|
try {
|
|
1132
|
-
this.pubsub = this.database.connect();
|
|
1133
|
-
const pubsub = await this.pubsub;
|
|
1134
|
-
pubsub.on('notification', ({ channel, payload }) => {
|
|
1135
|
-
if (_.toUpper(channel) !== PROTO_POSTGRES_MSG || !payload)
|
|
1136
|
-
return;
|
|
1137
|
-
try {
|
|
1138
|
-
const _payload = _decodeValue(JSON.parse(payload));
|
|
1139
|
-
for (const subscriber of this.subscribers) {
|
|
1140
|
-
subscriber(_payload);
|
|
1141
|
-
}
|
|
1142
|
-
}
|
|
1143
|
-
catch (e) {
|
|
1144
|
-
console.error(`Unknown payload: ${e}`);
|
|
1145
|
-
}
|
|
1146
|
-
});
|
|
1147
|
-
await pubsub.query(`LISTEN ${PROTO_POSTGRES_MSG}`);
|
|
1189
|
+
this.pubsub = new PostgresPubSub(this.database.connect());
|
|
1148
1190
|
}
|
|
1149
1191
|
catch (e) {
|
|
1150
1192
|
console.error(e);
|
|
@@ -1153,18 +1195,22 @@ class PostgresDriver extends PostgresClientDriver {
|
|
|
1153
1195
|
async _release_pubsub() {
|
|
1154
1196
|
const pubsub = this.pubsub;
|
|
1155
1197
|
this.pubsub = undefined;
|
|
1156
|
-
await
|
|
1198
|
+
await pubsub?.shutdown();
|
|
1157
1199
|
}
|
|
1158
|
-
|
|
1200
|
+
_subscribe(channel, callback) {
|
|
1159
1201
|
this._init_pubsub();
|
|
1160
|
-
this.
|
|
1202
|
+
if (!_.includes(this.pubsub.channels, channel))
|
|
1203
|
+
this.pubsub.listen(channel);
|
|
1204
|
+
const release = this.pubsub.subscribe(channel, callback);
|
|
1161
1205
|
return () => {
|
|
1162
|
-
|
|
1163
|
-
if (
|
|
1206
|
+
release();
|
|
1207
|
+
if (this.pubsub?.isEmpty())
|
|
1164
1208
|
this._release_pubsub();
|
|
1165
|
-
}
|
|
1166
1209
|
};
|
|
1167
1210
|
}
|
|
1211
|
+
subscribe(callback) {
|
|
1212
|
+
return this._subscribe(PROTO_POSTGRES_MSG, callback);
|
|
1213
|
+
}
|
|
1168
1214
|
}
|
|
1169
1215
|
|
|
1170
1216
|
//
|
|
@@ -1852,7 +1898,7 @@ const encodeQueryExpression = (compiler, parent, expr) => {
|
|
|
1852
1898
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
1853
1899
|
// THE SOFTWARE.
|
|
1854
1900
|
//
|
|
1855
|
-
const encodeFieldExpression = (compiler,
|
|
1901
|
+
const encodeFieldExpression = (compiler, parent, field, expr) => {
|
|
1856
1902
|
const [colname] = _.toPath(field);
|
|
1857
1903
|
const { element, dataType, relation } = fetchElement(compiler, parent, field);
|
|
1858
1904
|
const encodeValue = (value) => dataType ? encodeType(colname, dataType, value) : _encodeJsonValue(_encodeValue(value));
|
|
@@ -2081,7 +2127,7 @@ const encodeFieldExpression = (compiler, context, parent, field, expr) => {
|
|
|
2081
2127
|
{
|
|
2082
2128
|
if (!(expr.value instanceof FieldSelectorExpression))
|
|
2083
2129
|
break;
|
|
2084
|
-
return sql `NOT (${encodeFieldExpression(compiler,
|
|
2130
|
+
return sql `NOT (${encodeFieldExpression(compiler, parent, field, expr.value)})`;
|
|
2085
2131
|
}
|
|
2086
2132
|
case '$pattern':
|
|
2087
2133
|
{
|
|
@@ -2173,7 +2219,7 @@ const encodeFieldExpression = (compiler, context, parent, field, expr) => {
|
|
|
2173
2219
|
if (!(expr.value instanceof QuerySelector))
|
|
2174
2220
|
break;
|
|
2175
2221
|
const tempName = `_expr_$${compiler.nextIdx()}`;
|
|
2176
|
-
const filter = compiler._encodeFilter(
|
|
2222
|
+
const filter = compiler._encodeFilter({ name: tempName, className: relation?.target }, expr.value);
|
|
2177
2223
|
if (!filter)
|
|
2178
2224
|
break;
|
|
2179
2225
|
if (relation) {
|
|
@@ -2200,7 +2246,7 @@ const encodeFieldExpression = (compiler, context, parent, field, expr) => {
|
|
|
2200
2246
|
if (!(expr.value instanceof QuerySelector))
|
|
2201
2247
|
break;
|
|
2202
2248
|
const tempName = `_expr_$${compiler.nextIdx()}`;
|
|
2203
|
-
const filter = compiler._encodeFilter(
|
|
2249
|
+
const filter = compiler._encodeFilter({ name: tempName, className: relation?.target }, expr.value);
|
|
2204
2250
|
if (!filter)
|
|
2205
2251
|
break;
|
|
2206
2252
|
if (relation) {
|
|
@@ -2294,31 +2340,36 @@ const selectPopulate = (compiler, parent, populate, field) => {
|
|
|
2294
2340
|
const _local = (field) => sql `${{ identifier: parent.name }}.${{ identifier: field }}`;
|
|
2295
2341
|
const _foreign = (field) => sql `${{ identifier: populate.name }}.${{ identifier: field }}`;
|
|
2296
2342
|
const subpaths = resolveSubpaths(compiler, populate);
|
|
2343
|
+
const cond = [];
|
|
2344
|
+
if (compiler.extraFilter) {
|
|
2345
|
+
const filter = compiler.extraFilter(populate.className);
|
|
2346
|
+
cond.push(compiler._encodeFilter(populate, filter));
|
|
2347
|
+
}
|
|
2297
2348
|
if (populate.type === 'pointer') {
|
|
2349
|
+
cond.push(sql `${sql `(${{ quote: populate.className + '$' }} || ${_foreign('_id')})`} = ${_local(field)}`);
|
|
2298
2350
|
return {
|
|
2299
2351
|
columns: _.map(subpaths, ({ path }) => sql `${{ identifier: populate.name }}.${{ identifier: path }} AS ${{ identifier: `${field}.${path}` }}`),
|
|
2300
2352
|
join: sql `
|
|
2301
2353
|
LEFT JOIN ${{ identifier: populate.name }}
|
|
2302
|
-
ON ${
|
|
2354
|
+
ON ${{ literal: _.map(_.compact(cond), x => sql `(${x})`), separator: ' AND ' }}
|
|
2303
2355
|
`,
|
|
2304
2356
|
};
|
|
2305
2357
|
}
|
|
2306
|
-
let cond;
|
|
2307
2358
|
if (_.isNil(populate.foreignField)) {
|
|
2308
|
-
cond
|
|
2359
|
+
cond.push(sql `${sql `(${{ quote: populate.className + '$' }} || ${_foreign('_id')})`} = ANY(${_local(field)})`);
|
|
2309
2360
|
}
|
|
2310
2361
|
else if (_isPointer(compiler.schema, populate.className, populate.foreignField)) {
|
|
2311
|
-
cond
|
|
2362
|
+
cond.push(sql `${sql `(${{ quote: parent.className + '$' }} || ${_local('_id')})`} = ${_foreign(populate.colname)}`);
|
|
2312
2363
|
}
|
|
2313
2364
|
else {
|
|
2314
|
-
cond
|
|
2365
|
+
cond.push(sql `${sql `(${{ quote: parent.className + '$' }} || ${_local('_id')})`} = ANY(${_foreign(populate.colname)})`);
|
|
2315
2366
|
}
|
|
2316
2367
|
return {
|
|
2317
2368
|
columns: [sql `
|
|
2318
2369
|
ARRAY(
|
|
2319
2370
|
SELECT to_jsonb(${{ identifier: populate.name }}) FROM (
|
|
2320
2371
|
SELECT ${_.map(subpaths, ({ path, type }) => _encodePopulateInclude(populate.name, path, type))}
|
|
2321
|
-
FROM ${{ identifier: populate.name }} WHERE ${cond}
|
|
2372
|
+
FROM ${{ identifier: populate.name }} WHERE ${{ literal: _.map(_.compact(cond), x => sql `(${x})`), separator: ' AND ' }}
|
|
2322
2373
|
${!_.isEmpty(populate.sort) ? sql `ORDER BY ${compiler._encodeSort(populate.sort, { className: populate.className, name: populate.name })}` : sql ``}
|
|
2323
2374
|
${populate.limit ? sql `LIMIT ${{ literal: `${populate.limit}` }}` : sql ``}
|
|
2324
2375
|
${populate.skip ? sql `OFFSET ${{ literal: `${populate.skip}` }}` : sql ``}
|
|
@@ -2331,13 +2382,13 @@ const selectPopulate = (compiler, parent, populate, field) => {
|
|
|
2331
2382
|
const encodeRemix = (parent, remix) => sql `${remix?.className === parent.className ? sql `
|
|
2332
2383
|
(SELECT * FROM ${{ identifier: remix.name }} UNION SELECT * FROM ${{ identifier: parent.className }})
|
|
2333
2384
|
` : { identifier: parent.className }}`;
|
|
2334
|
-
const encodeForeignField = (compiler,
|
|
2385
|
+
const encodeForeignField = (compiler, parent, foreignField, remix) => {
|
|
2335
2386
|
const { paths: [colname, ...subpath], dataType } = resolveColumn(compiler.schema, parent.className, foreignField);
|
|
2336
2387
|
const tempName = `_populate_$${compiler.nextIdx()}`;
|
|
2337
2388
|
const _local = (field) => sql `${{ identifier: parent.name }}.${{ identifier: field }}`;
|
|
2338
2389
|
const _foreign = (field) => sql `${{ identifier: tempName }}.${{ identifier: field }}`;
|
|
2339
2390
|
if (_.isEmpty(subpath) && isRelation(dataType) && dataType.foreignField) {
|
|
2340
|
-
const { joins, field, rows, array } = encodeForeignField(compiler,
|
|
2391
|
+
const { joins, field, rows, array } = encodeForeignField(compiler, { className: dataType.target, name: tempName }, dataType.foreignField, remix);
|
|
2341
2392
|
return {
|
|
2342
2393
|
joins: [],
|
|
2343
2394
|
field: sql `(
|
|
@@ -2360,27 +2411,32 @@ const encodeForeignField = (compiler, context, parent, foreignField, remix) => {
|
|
|
2360
2411
|
}
|
|
2361
2412
|
if (!isPointer(dataType) && !isRelation(dataType))
|
|
2362
2413
|
throw Error(`Invalid path: ${foreignField}`);
|
|
2363
|
-
const { joins, field, rows, array } = encodeForeignField(compiler,
|
|
2414
|
+
const { joins, field, rows, array } = encodeForeignField(compiler, { className: dataType.target, name: tempName }, subpath.join('.'), remix);
|
|
2415
|
+
const cond = [];
|
|
2416
|
+
if (compiler.extraFilter) {
|
|
2417
|
+
const filter = compiler.extraFilter(dataType.target);
|
|
2418
|
+
cond.push(compiler._encodeFilter({ className: dataType.target, name: tempName }, filter));
|
|
2419
|
+
}
|
|
2364
2420
|
if (isPointer(dataType)) {
|
|
2421
|
+
cond.push(sql `${sql `(${{ quote: dataType.target + '$' }} || ${_foreign('_id')})`} = ${_local(colname)}`);
|
|
2365
2422
|
return {
|
|
2366
2423
|
joins: [sql `
|
|
2367
2424
|
LEFT JOIN ${encodeRemix({ className: dataType.target }, remix)} AS ${{ identifier: tempName }}
|
|
2368
|
-
ON ${
|
|
2425
|
+
ON ${{ literal: _.map(_.compact(cond), x => sql `(${x})`), separator: ' AND ' }}
|
|
2369
2426
|
`, ...joins],
|
|
2370
2427
|
field,
|
|
2371
2428
|
array,
|
|
2372
2429
|
rows,
|
|
2373
2430
|
};
|
|
2374
2431
|
}
|
|
2375
|
-
let cond;
|
|
2376
2432
|
if (_.isNil(dataType.foreignField)) {
|
|
2377
|
-
cond
|
|
2433
|
+
cond.push(sql `${sql `(${{ quote: dataType.target + '$' }} || ${_foreign('_id')})`} = ANY(${_local(colname)})`);
|
|
2378
2434
|
}
|
|
2379
2435
|
else if (_isPointer(compiler.schema, dataType.target, dataType.foreignField)) {
|
|
2380
|
-
cond
|
|
2436
|
+
cond.push(sql `${sql `(${{ quote: parent.className + '$' }} || ${_local('_id')})`} = ${_foreign(dataType.foreignField)}`);
|
|
2381
2437
|
}
|
|
2382
2438
|
else {
|
|
2383
|
-
cond
|
|
2439
|
+
cond.push(sql `${sql `(${{ quote: parent.className + '$' }} || ${_local('_id')})`} = ANY(${_foreign(dataType.foreignField)})`);
|
|
2384
2440
|
}
|
|
2385
2441
|
return {
|
|
2386
2442
|
joins: [],
|
|
@@ -2388,23 +2444,23 @@ const encodeForeignField = (compiler, context, parent, foreignField, remix) => {
|
|
|
2388
2444
|
SELECT ${array ? sql `UNNEST(${field})` : field}
|
|
2389
2445
|
FROM ${encodeRemix({ className: dataType.target }, remix)} AS ${{ identifier: tempName }}
|
|
2390
2446
|
${!_.isEmpty(joins) ? { literal: joins, separator: '\n' } : sql ``}
|
|
2391
|
-
WHERE ${cond}
|
|
2447
|
+
WHERE ${{ literal: _.map(_.compact(cond), x => sql `(${x})`), separator: ' AND ' }}
|
|
2392
2448
|
)`,
|
|
2393
2449
|
array: false,
|
|
2394
2450
|
rows: true,
|
|
2395
2451
|
};
|
|
2396
2452
|
};
|
|
2397
|
-
const encodePopulate = (compiler,
|
|
2398
|
-
const _filter = compiler._encodeFilter(
|
|
2453
|
+
const encodePopulate = (compiler, parent, remix) => {
|
|
2454
|
+
const _filter = parent.filter && compiler._encodeFilter(parent, parent.filter);
|
|
2399
2455
|
const _populates = _.map(parent.populates, (populate, field) => selectPopulate(compiler, parent, populate, field));
|
|
2400
2456
|
const _joins = _.compact(_.map(_populates, ({ join }) => join));
|
|
2401
2457
|
const _includes = _.pickBy(parent.includes, v => isPrimitive(v));
|
|
2402
|
-
const { joins: _joins2 = [], field: _foreignField = undefined, rows = false, } = parent.foreignField ? encodeForeignField(compiler,
|
|
2458
|
+
const { joins: _joins2 = [], field: _foreignField = undefined, rows = false, } = parent.foreignField ? encodeForeignField(compiler, {
|
|
2403
2459
|
className: parent.className,
|
|
2404
2460
|
name: parent.name,
|
|
2405
2461
|
}, parent.foreignField, remix) : {};
|
|
2406
2462
|
return _.reduce(parent.populates, (acc, populate) => ({
|
|
2407
|
-
...encodePopulate(compiler,
|
|
2463
|
+
...encodePopulate(compiler, populate, remix),
|
|
2408
2464
|
...acc,
|
|
2409
2465
|
}), {
|
|
2410
2466
|
[parent.name]: sql `
|
|
@@ -2449,11 +2505,11 @@ const encodePopulate = (compiler, context, parent, remix) => {
|
|
|
2449
2505
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
2450
2506
|
// THE SOFTWARE.
|
|
2451
2507
|
//
|
|
2452
|
-
const encodeRelation = (compiler,
|
|
2508
|
+
const encodeRelation = (compiler, parent, relatedBy) => {
|
|
2453
2509
|
const name = `_relation_$${relatedBy.className.toLowerCase()}`;
|
|
2454
2510
|
const _local = (field) => sql `${{ identifier: parent.name }}.${{ identifier: field }}`;
|
|
2455
2511
|
const _foreign = (field) => sql `${{ identifier: name }}.${{ identifier: field }}`;
|
|
2456
|
-
const { joins, field } = encodeForeignField(compiler,
|
|
2512
|
+
const { joins, field } = encodeForeignField(compiler, { className: relatedBy.className, name }, relatedBy.key);
|
|
2457
2513
|
return sql `EXISTS (
|
|
2458
2514
|
SELECT 1
|
|
2459
2515
|
FROM ${{ identifier: relatedBy.className }} AS ${{ identifier: name }}
|