proto.io 0.0.211 → 0.0.213
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/aliyun-oss.d.ts +3 -3
- package/dist/adapters/file/database.d.ts +2 -2
- package/dist/adapters/file/database.js +1 -1
- 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 +3 -3
- package/dist/adapters/file/google-cloud-storage.d.ts +3 -3
- package/dist/adapters/storage/progres.d.ts +8 -6
- package/dist/adapters/storage/progres.js +148 -80
- package/dist/adapters/storage/progres.js.map +1 -1
- package/dist/adapters/storage/progres.mjs +149 -81
- package/dist/adapters/storage/progres.mjs.map +1 -1
- package/dist/client.d.ts +3 -3
- package/dist/client.js +1 -1
- package/dist/client.mjs +2 -2
- package/dist/index.d.ts +3 -3
- package/dist/index.js +8 -8
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +10 -10
- package/dist/index.mjs.map +1 -1
- package/dist/internals/{base-BCWOHUaQ.d.ts → base-CZGalGrd.d.ts} +2 -2
- package/dist/internals/base-CZGalGrd.d.ts.map +1 -0
- package/dist/internals/{chunk-2pKgkO5-.d.ts → chunk-BsT9SYny.d.ts} +3 -3
- package/dist/internals/chunk-BsT9SYny.d.ts.map +1 -0
- package/dist/internals/{index-lTzbCO8S.d.ts → index-Boxwkqe0.d.ts} +32 -15
- package/dist/internals/index-Boxwkqe0.d.ts.map +1 -0
- package/dist/internals/{index-DPPLcZx8.mjs → index-DG9HHO_U.mjs} +2 -2
- package/dist/internals/{index-DPPLcZx8.mjs.map → index-DG9HHO_U.mjs.map} +1 -1
- package/dist/internals/{index-Btxxs0KS.js → index-DfnPpl1I.js} +16 -10
- package/dist/internals/index-DfnPpl1I.js.map +1 -0
- package/dist/internals/{index-8AdKlZUU.d.ts → index-NF-U_3zG.d.ts} +2 -2
- package/dist/internals/index-NF-U_3zG.d.ts.map +1 -0
- package/dist/internals/{index-CoeDMG5V.mjs → index-ZPbBr9Db.mjs} +16 -10
- package/dist/internals/index-ZPbBr9Db.mjs.map +1 -0
- package/dist/internals/{random-ycCeBd0S.mjs → random-CufRbivU.mjs} +121 -19
- package/dist/internals/random-CufRbivU.mjs.map +1 -0
- package/dist/internals/{random-CyU_Y2Ay.js → random-DzvxbWAc.js} +161 -58
- package/dist/internals/random-DzvxbWAc.js.map +1 -0
- package/package.json +1 -1
- package/dist/internals/base-BCWOHUaQ.d.ts.map +0 -1
- package/dist/internals/chunk-2pKgkO5-.d.ts.map +0 -1
- package/dist/internals/index-8AdKlZUU.d.ts.map +0 -1
- package/dist/internals/index-Btxxs0KS.js.map +0 -1
- package/dist/internals/index-CoeDMG5V.mjs.map +0 -1
- package/dist/internals/index-lTzbCO8S.d.ts.map +0 -1
- package/dist/internals/random-CyU_Y2Ay.js.map +0 -1
- package/dist/internals/random-ycCeBd0S.mjs.map +0 -1
|
@@ -11,7 +11,7 @@ var Decimal = require('decimal.js');
|
|
|
11
11
|
var utils = require('pg/lib/utils');
|
|
12
12
|
var index$1 = require('../../internals/index-D8O7SinR.js');
|
|
13
13
|
require('@o2ter/crypto-js');
|
|
14
|
-
var random$1 = require('../../internals/random-
|
|
14
|
+
var random$1 = require('../../internals/random-DzvxbWAc.js');
|
|
15
15
|
var _const = require('../../internals/const-C3I6cfav.js');
|
|
16
16
|
var _private = require('../../internals/private-Ciddhure.js');
|
|
17
17
|
|
|
@@ -218,12 +218,12 @@ class QueryCompiler {
|
|
|
218
218
|
_encodeIncludes(query) {
|
|
219
219
|
const names = {};
|
|
220
220
|
const populates = {};
|
|
221
|
-
const
|
|
221
|
+
const groupMatches = {};
|
|
222
222
|
for (const include of query.includes) {
|
|
223
223
|
const { paths: [colname, ...subpath], dataType } = random$1.resolveColumn(this.schema, query.className, include);
|
|
224
224
|
names[colname] = dataType;
|
|
225
|
-
if (index.isRelation(dataType) && _.
|
|
226
|
-
|
|
225
|
+
if (index.isRelation(dataType) && !_.isNil(query.groupMatches[colname]))
|
|
226
|
+
groupMatches[colname] = query.groupMatches[colname];
|
|
227
227
|
if (index.isPointer(dataType) || index.isRelation(dataType)) {
|
|
228
228
|
if (_.isEmpty(subpath))
|
|
229
229
|
throw Error(`Invalid path: ${include}`);
|
|
@@ -254,21 +254,26 @@ class QueryCompiler {
|
|
|
254
254
|
}
|
|
255
255
|
for (const [colname, populate] of _.toPairs(populates)) {
|
|
256
256
|
const _matches = query.matches[colname];
|
|
257
|
-
const { includes, populates,
|
|
257
|
+
const { includes, populates, groupMatches } = this._encodeIncludes({
|
|
258
258
|
className: populate.className,
|
|
259
259
|
includes: populate.subpaths,
|
|
260
260
|
matches: _matches.matches,
|
|
261
|
-
|
|
262
|
-
..._.
|
|
263
|
-
..._matches.
|
|
264
|
-
|
|
261
|
+
groupMatches: {
|
|
262
|
+
..._.mapKeys(_.pickBy(query.groupMatches, (x, k) => _.startsWith(k, `${colname}.`)), (x, k) => k.slice(colname.length + 1)),
|
|
263
|
+
..._matches.groupMatches ?? {},
|
|
264
|
+
},
|
|
265
265
|
});
|
|
266
266
|
populate.sort = _encodeSorting(includes, populates, _matches.sort);
|
|
267
267
|
populate.includes = includes;
|
|
268
268
|
populate.populates = populates;
|
|
269
|
-
populate.
|
|
269
|
+
populate.groupMatches = groupMatches;
|
|
270
270
|
}
|
|
271
|
-
return {
|
|
271
|
+
return {
|
|
272
|
+
className: query.className,
|
|
273
|
+
includes: names,
|
|
274
|
+
populates,
|
|
275
|
+
groupMatches,
|
|
276
|
+
};
|
|
272
277
|
}
|
|
273
278
|
_baseSelectQuery(query, options) {
|
|
274
279
|
const fetchName = `_fetch_$${query.className.toLowerCase()}`;
|
|
@@ -304,7 +309,11 @@ class QueryCompiler {
|
|
|
304
309
|
) AS ${{ identifier: fetchName }}
|
|
305
310
|
${!_.isEmpty(filter) ? sql `WHERE ${{ literal: _.map(filter, x => sql `(${x})`), separator: ' AND ' }}` : sql ``}
|
|
306
311
|
${_options?.sort ? _options?.sort : sql ``}
|
|
307
|
-
${!_.isEmpty(query.sort) ? sql `ORDER BY ${this._encodeSort(query.sort, {
|
|
312
|
+
${!_.isEmpty(query.sort) ? sql `ORDER BY ${this._encodeSort(query.sort, {
|
|
313
|
+
name: fetchName,
|
|
314
|
+
className: query.className,
|
|
315
|
+
groupMatches: query.groupMatches,
|
|
316
|
+
})}` : sql ``}
|
|
308
317
|
${query.limit ? sql `LIMIT ${{ literal: `${query.limit}` }}` : sql ``}
|
|
309
318
|
${query.skip ? sql `OFFSET ${{ literal: `${query.skip}` }}` : sql ``}
|
|
310
319
|
`,
|
|
@@ -409,7 +418,7 @@ class QueryCompiler {
|
|
|
409
418
|
}
|
|
410
419
|
_selectIncludes(className, includes) {
|
|
411
420
|
const _includes = _.pickBy(includes, v => _.isString(v) || (v.type !== 'pointer' && v.type !== 'relation'));
|
|
412
|
-
return _.
|
|
421
|
+
return _.flatMap(_includes, (dataType, colname) => {
|
|
413
422
|
if (!_.isString(dataType) && index.isPrimitive(dataType) && !_.isNil(dataType.default)) {
|
|
414
423
|
return sql `COALESCE(${{ identifier: className }}.${{ identifier: colname }}, ${{ value: dataType.default }}) AS ${{ identifier: colname }}`;
|
|
415
424
|
}
|
|
@@ -430,7 +439,7 @@ class QueryCompiler {
|
|
|
430
439
|
`)}`;
|
|
431
440
|
}
|
|
432
441
|
_selectPopulateMap(context) {
|
|
433
|
-
return _.map(context.populates, (populate, field) => this.dialect.selectPopulate(this, context, populate, field
|
|
442
|
+
return _.map(context.populates, (populate, field) => this.dialect.selectPopulate(this, context, populate, field));
|
|
434
443
|
}
|
|
435
444
|
insert(options, values) {
|
|
436
445
|
const _values = _.map(values, attr => ({
|
|
@@ -568,9 +577,15 @@ class SqlStorage {
|
|
|
568
577
|
const { query, values } = sql.compile(this.dialect);
|
|
569
578
|
return this._query(query, values);
|
|
570
579
|
}
|
|
571
|
-
|
|
580
|
+
_decodeMatchTypes(value, matchType) {
|
|
581
|
+
if (!_.isPlainObject(value))
|
|
582
|
+
return;
|
|
583
|
+
return _.mapValues(value, (v, k) => this.dialect.decodeType(matchType[k], v));
|
|
584
|
+
}
|
|
585
|
+
_decodeShapedObject(dataType, value, matchesType) {
|
|
572
586
|
const result = {};
|
|
573
587
|
for (const { path, type } of index.shapePaths(dataType)) {
|
|
588
|
+
const matchType = _.get(matchesType, path) ?? {};
|
|
574
589
|
if (_.isString(type)) {
|
|
575
590
|
const _value = this.dialect.decodeType(type, _.get(value, path));
|
|
576
591
|
if (!_.isNil(_value))
|
|
@@ -579,17 +594,17 @@ class SqlStorage {
|
|
|
579
594
|
else if (index.isPointer(type)) {
|
|
580
595
|
const _value = _.get(value, path);
|
|
581
596
|
if (_.isPlainObject(_value)) {
|
|
582
|
-
const decoded = this._decodeObject(type.target, _value);
|
|
597
|
+
const decoded = this._decodeObject(type.target, _value, matchType);
|
|
583
598
|
if (decoded.objectId)
|
|
584
599
|
_.set(result, path, decoded);
|
|
585
600
|
}
|
|
586
601
|
}
|
|
587
602
|
else if (index.isRelation(type)) {
|
|
588
603
|
const _value = _.get(value, path);
|
|
589
|
-
if (_.
|
|
590
|
-
_.set(result, path,
|
|
591
|
-
else if (_.
|
|
592
|
-
_.set(result, path,
|
|
604
|
+
if (_.isArray(_value))
|
|
605
|
+
_.set(result, path, _value.map(x => this._decodeObject(type.target, x, matchType)));
|
|
606
|
+
else if (_.isPlainObject(_value))
|
|
607
|
+
_.set(result, path, this._decodeMatchTypes(_value, matchType));
|
|
593
608
|
}
|
|
594
609
|
else {
|
|
595
610
|
const _value = this.dialect.decodeType(type.type, _.get(value, path)) ?? type.default;
|
|
@@ -599,7 +614,7 @@ class SqlStorage {
|
|
|
599
614
|
}
|
|
600
615
|
return result;
|
|
601
616
|
}
|
|
602
|
-
_decodeObject(className, attrs) {
|
|
617
|
+
_decodeObject(className, attrs, matchesType) {
|
|
603
618
|
const fields = this.schema[className].fields;
|
|
604
619
|
const obj = new index.TObject(className);
|
|
605
620
|
const _attrs = {};
|
|
@@ -607,6 +622,7 @@ class SqlStorage {
|
|
|
607
622
|
_.set(_attrs, key, value);
|
|
608
623
|
}
|
|
609
624
|
for (const [key, value] of _.toPairs(_attrs)) {
|
|
625
|
+
const matchType = matchesType[key] ?? {};
|
|
610
626
|
const dataType = fields[key];
|
|
611
627
|
if (!dataType)
|
|
612
628
|
continue;
|
|
@@ -614,20 +630,20 @@ class SqlStorage {
|
|
|
614
630
|
obj[_private.PVK].attributes[key] = this.dialect.decodeType(dataType, value);
|
|
615
631
|
}
|
|
616
632
|
else if (index.isShape(dataType)) {
|
|
617
|
-
obj[_private.PVK].attributes[key] = this._decodeShapedObject(dataType, value);
|
|
633
|
+
obj[_private.PVK].attributes[key] = this._decodeShapedObject(dataType, value, matchType);
|
|
618
634
|
}
|
|
619
635
|
else if (index.isPointer(dataType)) {
|
|
620
636
|
if (_.isPlainObject(value)) {
|
|
621
|
-
const decoded = this._decodeObject(dataType.target, value);
|
|
637
|
+
const decoded = this._decodeObject(dataType.target, value, matchType);
|
|
622
638
|
if (decoded.objectId)
|
|
623
639
|
obj[_private.PVK].attributes[key] = decoded;
|
|
624
640
|
}
|
|
625
641
|
}
|
|
626
642
|
else if (index.isRelation(dataType)) {
|
|
627
|
-
if (_.
|
|
628
|
-
obj[_private.PVK].attributes[key] =
|
|
629
|
-
else if (_.
|
|
630
|
-
obj[_private.PVK].attributes[key] =
|
|
643
|
+
if (_.isArray(value))
|
|
644
|
+
obj[_private.PVK].attributes[key] = value.map(x => this._decodeObject(dataType.target, x, matchType));
|
|
645
|
+
else if (_.isPlainObject(value))
|
|
646
|
+
obj[_private.PVK].attributes[key] = this._decodeMatchTypes(value, matchType);
|
|
631
647
|
}
|
|
632
648
|
else {
|
|
633
649
|
obj[_private.PVK].attributes[key] = this.dialect.decodeType(dataType.type, value) ?? dataType.default;
|
|
@@ -656,6 +672,18 @@ class SqlStorage {
|
|
|
656
672
|
const count = parseInt(_count);
|
|
657
673
|
return _.isFinite(count) ? count : 0;
|
|
658
674
|
}
|
|
675
|
+
_matchesType(options) {
|
|
676
|
+
const types = {};
|
|
677
|
+
for (const [key, match] of _.entries(options.matches)) {
|
|
678
|
+
types[key] = this._matchesType(match);
|
|
679
|
+
}
|
|
680
|
+
for (const [key, group] of _.entries(options.groupMatches)) {
|
|
681
|
+
for (const [field, expr] of _.entries(group)) {
|
|
682
|
+
_.set(types, `${key}.${field}`, random$1.accumulatorKeyTypes[expr.type]);
|
|
683
|
+
}
|
|
684
|
+
}
|
|
685
|
+
return types;
|
|
686
|
+
}
|
|
659
687
|
find(query) {
|
|
660
688
|
const self = this;
|
|
661
689
|
const compiler = self._makeCompiler(false, query.extraFilter);
|
|
@@ -663,7 +691,7 @@ class SqlStorage {
|
|
|
663
691
|
return (async function* () {
|
|
664
692
|
const objects = self.query(_query);
|
|
665
693
|
for await (const object of objects) {
|
|
666
|
-
yield self._decodeObject(query.className, object);
|
|
694
|
+
yield self._decodeObject(query.className, object, self._matchesType(query));
|
|
667
695
|
}
|
|
668
696
|
})();
|
|
669
697
|
}
|
|
@@ -676,7 +704,7 @@ class SqlStorage {
|
|
|
676
704
|
return (async function* () {
|
|
677
705
|
const objects = self.query(_query);
|
|
678
706
|
for await (const object of objects) {
|
|
679
|
-
yield self._decodeObject(query.className, object);
|
|
707
|
+
yield self._decodeObject(query.className, object, self._matchesType(query));
|
|
680
708
|
}
|
|
681
709
|
})();
|
|
682
710
|
}
|
|
@@ -690,7 +718,7 @@ class SqlStorage {
|
|
|
690
718
|
return (async function* () {
|
|
691
719
|
const objects = self.query(query);
|
|
692
720
|
for await (const { _class, ...object } of objects) {
|
|
693
|
-
yield self._decodeObject(_class, object);
|
|
721
|
+
yield self._decodeObject(_class, object, {});
|
|
694
722
|
}
|
|
695
723
|
})();
|
|
696
724
|
}
|
|
@@ -705,29 +733,29 @@ class SqlStorage {
|
|
|
705
733
|
return (async function* () {
|
|
706
734
|
const objects = self.query(_query);
|
|
707
735
|
for await (const object of objects) {
|
|
708
|
-
yield self._decodeObject(query.className, object);
|
|
736
|
+
yield self._decodeObject(query.className, object, self._matchesType(query));
|
|
709
737
|
}
|
|
710
738
|
})();
|
|
711
739
|
}
|
|
712
740
|
async insert(options, values) {
|
|
713
741
|
const compiler = this._makeCompiler(true);
|
|
714
742
|
const result = await this.query(compiler.insert(options, values));
|
|
715
|
-
return _.map(result, x => this._decodeObject(options.className, x));
|
|
743
|
+
return _.map(result, x => this._decodeObject(options.className, x, this._matchesType(options)));
|
|
716
744
|
}
|
|
717
745
|
async update(query, update) {
|
|
718
746
|
const compiler = this._makeCompiler(true, query.extraFilter);
|
|
719
747
|
const updated = await this.query(compiler.update(query, update));
|
|
720
|
-
return _.map(updated, x => this._decodeObject(query.className, x));
|
|
748
|
+
return _.map(updated, x => this._decodeObject(query.className, x, this._matchesType(query)));
|
|
721
749
|
}
|
|
722
750
|
async upsert(query, update, setOnInsert) {
|
|
723
751
|
const compiler = this._makeCompiler(true, query.extraFilter);
|
|
724
752
|
const upserted = await this.query(compiler.upsert(query, update, setOnInsert));
|
|
725
|
-
return _.map(upserted, x => this._decodeObject(query.className, x));
|
|
753
|
+
return _.map(upserted, x => this._decodeObject(query.className, x, this._matchesType(query)));
|
|
726
754
|
}
|
|
727
755
|
async delete(query) {
|
|
728
756
|
const compiler = this._makeCompiler(true, query.extraFilter);
|
|
729
757
|
const deleted = await this.query(compiler.delete(query));
|
|
730
|
-
return _.map(deleted, x => this._decodeObject(query.className, x));
|
|
758
|
+
return _.map(deleted, x => this._decodeObject(query.className, x, this._matchesType(query)));
|
|
731
759
|
}
|
|
732
760
|
}
|
|
733
761
|
|
|
@@ -773,7 +801,15 @@ const _fetchElement = (parent, colname, subpath, dataType) => {
|
|
|
773
801
|
}
|
|
774
802
|
else if (!_.isEmpty(subpath)) {
|
|
775
803
|
const _subpath = sql `${_.map(subpath, x => sql `${{ quote: x.startsWith('$') ? `$${x}` : x }}`)}`;
|
|
776
|
-
|
|
804
|
+
const match = parent.groupMatches?.[colname]?.[subpath[0]];
|
|
805
|
+
if (dataType && index.isRelation(dataType) && subpath.length === 1 && match) {
|
|
806
|
+
return {
|
|
807
|
+
element: sql `${{ identifier: parent.name }}.${{ identifier: `${colname}.${subpath[0]}` }}`,
|
|
808
|
+
json: false,
|
|
809
|
+
dataType: random$1.accumulatorKeyTypes[match.type],
|
|
810
|
+
};
|
|
811
|
+
}
|
|
812
|
+
else if (dataType && index._isTypeof(dataType, ['array', 'string[]', 'relation'])) {
|
|
777
813
|
return {
|
|
778
814
|
element: sql `jsonb_extract_path(to_jsonb(${element}), ${_subpath})`,
|
|
779
815
|
json: true,
|
|
@@ -833,7 +869,7 @@ const _resolvePopulate = (path, populates) => {
|
|
|
833
869
|
const fetchElement = (compiler, parent, field) => {
|
|
834
870
|
if (parent.className) {
|
|
835
871
|
const { dataType, colname, subpath } = resolvePaths(compiler, parent.className, _.toPath(field));
|
|
836
|
-
const { element, json } = _fetchElement(parent, colname, subpath, dataType);
|
|
872
|
+
const { element, json, dataType: _dataType } = _fetchElement(parent, colname, subpath, dataType);
|
|
837
873
|
if (index.isPointer(dataType))
|
|
838
874
|
return { element: sql `${{ identifier: parent.name }}.${{ identifier: `${colname}._id` }}`, dataType };
|
|
839
875
|
const populate = index.isRelation(dataType) && _resolvePopulate(_.toPath(colname), parent.populates);
|
|
@@ -841,7 +877,7 @@ const fetchElement = (compiler, parent, field) => {
|
|
|
841
877
|
return { element, dataType: json ? null : dataType };
|
|
842
878
|
return {
|
|
843
879
|
element,
|
|
844
|
-
dataType: json ? null : dataType,
|
|
880
|
+
dataType: json ? null : _dataType ?? dataType,
|
|
845
881
|
relation: {
|
|
846
882
|
colname,
|
|
847
883
|
target: dataType.target,
|
|
@@ -1181,7 +1217,7 @@ const _encodeJsonValue = (value) => {
|
|
|
1181
1217
|
return sql `jsonb_build_object(${_.map(value, (v, k) => sql `${{ value: k }}, ${_encodeJsonValue(v)}`)})`;
|
|
1182
1218
|
return sql `to_jsonb(${{ value }})`;
|
|
1183
1219
|
};
|
|
1184
|
-
const
|
|
1220
|
+
const _jsonPopulateInclude = (className, colname, dataType) => {
|
|
1185
1221
|
switch (index._typeof(dataType)) {
|
|
1186
1222
|
case 'decimal':
|
|
1187
1223
|
return sql `jsonb_build_object(
|
|
@@ -1896,45 +1932,83 @@ const _selectRelationPopulate = (compiler, parent, populate, field, encode) => {
|
|
|
1896
1932
|
cond = sql `${sql `(${{ quote: parent.className + '$' }} || ${_local('_id')})`} = ANY(${_foreign(populate.colname)})`;
|
|
1897
1933
|
}
|
|
1898
1934
|
return sql `
|
|
1899
|
-
SELECT ${_.compact(_.flatMap(subpaths, ({ path, type }) => [
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
1935
|
+
SELECT ${_.compact(_.flatMap(subpaths, ({ path, type }) => encode ? [
|
|
1936
|
+
_jsonPopulateInclude(populate.name, path, type)
|
|
1937
|
+
] : [
|
|
1938
|
+
...(populate.groupMatches[path] ? _.map(_.keys(populate.groupMatches[path]), k => sql `${{ identifier: populate.name }}.${{ identifier: `${path}.${k}` }}`) : [
|
|
1939
|
+
sql `${{ identifier: populate.name }}.${{ identifier: path }}`
|
|
1940
|
+
]),
|
|
1941
|
+
index.isRelation(type) && sql `${{ identifier: populate.name }}.${{ identifier: `$${path}` }}`,
|
|
1903
1942
|
]))}
|
|
1904
1943
|
FROM ${{ identifier: populate.name }} WHERE ${cond}
|
|
1905
|
-
${!_.isEmpty(populate.sort) ? sql `ORDER BY ${compiler._encodeSort(populate.sort,
|
|
1944
|
+
${!_.isEmpty(populate.sort) ? sql `ORDER BY ${compiler._encodeSort(populate.sort, populate)}` : sql ``}
|
|
1906
1945
|
${populate.limit ? sql `LIMIT ${{ literal: `${populate.limit}` }}` : sql ``}
|
|
1907
1946
|
${populate.skip ? sql `OFFSET ${{ literal: `${populate.skip}` }}` : sql ``}
|
|
1908
1947
|
${compiler.selectLock ? compiler.isUpdate ? sql `FOR UPDATE NOWAIT` : sql `FOR SHARE NOWAIT` : sql ``}
|
|
1909
1948
|
`;
|
|
1910
1949
|
};
|
|
1911
|
-
const selectPopulate = (compiler, parent, populate, field
|
|
1950
|
+
const selectPopulate = (compiler, parent, populate, field) => {
|
|
1912
1951
|
if (populate.type === 'relation') {
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
-
|
|
1930
|
-
|
|
1952
|
+
const { groupMatches } = parent;
|
|
1953
|
+
const columns = [
|
|
1954
|
+
sql `${{ identifier: parent.name }}.${{ identifier: field }} AS ${{ identifier: `$${field}` }}`,
|
|
1955
|
+
];
|
|
1956
|
+
if (!_.isEmpty(groupMatches?.[field])) {
|
|
1957
|
+
for (const [key, { type, expr }] of _.entries(groupMatches[field])) {
|
|
1958
|
+
switch (type) {
|
|
1959
|
+
case '$count':
|
|
1960
|
+
columns.push(sql `
|
|
1961
|
+
(
|
|
1962
|
+
SELECT COUNT(*) FROM (
|
|
1963
|
+
${_selectRelationPopulate(compiler, parent, populate, field, false)}
|
|
1964
|
+
) ${{ identifier: populate.name }}
|
|
1965
|
+
) AS ${{ identifier: `${field}.${key}` }}
|
|
1966
|
+
`);
|
|
1967
|
+
break;
|
|
1968
|
+
case '$avg':
|
|
1969
|
+
case '$sum':
|
|
1970
|
+
{
|
|
1971
|
+
const op = {
|
|
1972
|
+
'$avg': 'AVG',
|
|
1973
|
+
'$sum': 'SUM',
|
|
1974
|
+
}[type];
|
|
1975
|
+
if (!expr)
|
|
1976
|
+
throw Error('Invalid expression');
|
|
1977
|
+
const exprs = encodeTypedQueryExpression(compiler, populate, expr);
|
|
1978
|
+
const { sql: value } = (_.includes(['$avg'], type) ? _.find(exprs, e => e.type === 'number') : _.first(exprs)) ?? {};
|
|
1979
|
+
if (!value)
|
|
1980
|
+
throw Error('Invalid expression');
|
|
1981
|
+
columns.push(sql `
|
|
1982
|
+
(
|
|
1983
|
+
SELECT ${{ literal: op }}(${value}) FROM (
|
|
1984
|
+
${_selectRelationPopulate(compiler, parent, populate, field, false)}
|
|
1985
|
+
) ${{ identifier: populate.name }}
|
|
1986
|
+
) AS ${{ identifier: `${field}.${key}` }}
|
|
1987
|
+
`);
|
|
1988
|
+
}
|
|
1989
|
+
break;
|
|
1990
|
+
}
|
|
1991
|
+
}
|
|
1992
|
+
}
|
|
1993
|
+
else {
|
|
1994
|
+
columns.push(sql `
|
|
1995
|
+
ARRAY(
|
|
1996
|
+
SELECT to_jsonb(${{ identifier: populate.name }}) FROM (
|
|
1997
|
+
${_selectRelationPopulate(compiler, parent, populate, field, true)}
|
|
1998
|
+
) ${{ identifier: populate.name }}
|
|
1999
|
+
) AS ${{ identifier: field }}
|
|
2000
|
+
`);
|
|
2001
|
+
}
|
|
2002
|
+
return { columns };
|
|
1931
2003
|
}
|
|
1932
2004
|
const _local = (field) => sql `${{ identifier: parent.name }}.${{ identifier: field }}`;
|
|
1933
2005
|
const _foreign = (field) => sql `${{ identifier: populate.name }}.${{ identifier: field }}`;
|
|
1934
2006
|
const subpaths = resolveSubpaths(compiler, populate);
|
|
1935
2007
|
return {
|
|
1936
2008
|
columns: _.compact(_.flatMap(subpaths, ({ path, type }) => [
|
|
1937
|
-
sql `${{ identifier: populate.name }}.${{ identifier: path }} AS ${{ identifier: `${field}.${path}` }}
|
|
2009
|
+
...populate.groupMatches[path] ? _.map(_.keys(populate.groupMatches[path]), k => sql `${{ identifier: populate.name }}.${{ identifier: `${path}.${k}` }} AS ${{ identifier: `${field}.${path}.${k}` }}`) : [
|
|
2010
|
+
sql `${{ identifier: populate.name }}.${{ identifier: path }} AS ${{ identifier: `${field}.${path}` }}`
|
|
2011
|
+
],
|
|
1938
2012
|
index.isRelation(type) && sql `${{ identifier: populate.name }}.${{ identifier: `$${path}` }} AS ${{ identifier: `$${field}.${path}` }}`,
|
|
1939
2013
|
])),
|
|
1940
2014
|
join: sql `
|
|
@@ -2019,9 +2093,8 @@ const encodePopulate = (compiler, parent, remix) => {
|
|
|
2019
2093
|
parent.filter && compiler._encodeFilter(parent, parent.filter),
|
|
2020
2094
|
compiler.extraFilter && compiler._encodeFilter(parent, compiler.extraFilter(parent.className)),
|
|
2021
2095
|
]);
|
|
2022
|
-
const _populates = _.map(parent.populates, (populate, field) => selectPopulate(compiler, parent, populate, field
|
|
2096
|
+
const _populates = _.map(parent.populates, (populate, field) => selectPopulate(compiler, parent, populate, field));
|
|
2023
2097
|
const _joins = _.compact(_.map(_populates, ({ join }) => join));
|
|
2024
|
-
const _includes = _.pickBy(parent.includes, v => index.isPrimitive(v));
|
|
2025
2098
|
const { joins: _joins2 = [], field: _foreignField = undefined, rows = false, } = parent.foreignField ? encodeForeignField(compiler, {
|
|
2026
2099
|
className: parent.className,
|
|
2027
2100
|
name: parent.name,
|
|
@@ -2035,7 +2108,7 @@ const encodePopulate = (compiler, parent, remix) => {
|
|
|
2035
2108
|
SELECT
|
|
2036
2109
|
${{
|
|
2037
2110
|
literal: [
|
|
2038
|
-
...
|
|
2111
|
+
...compiler._selectIncludes(parent.name, parent.includes),
|
|
2039
2112
|
..._.flatMap(_populates, ({ columns: column }) => column),
|
|
2040
2113
|
..._foreignField ? [sql `${rows ? sql `ARRAY(${_foreignField})` : _foreignField} AS ${{ identifier: parent.colname }}`] : [],
|
|
2041
2114
|
], separator: ',\n'
|
|
@@ -2088,9 +2161,6 @@ const encodeFieldExpression = (compiler, parent, field, expr) => {
|
|
|
2088
2161
|
break;
|
|
2089
2162
|
return sql `${element} ${nullSafeEqual()} ${{ value: expr.value.objectId }}`;
|
|
2090
2163
|
}
|
|
2091
|
-
if (relation && _.includes(parent.countMatches, relation.colname)) {
|
|
2092
|
-
return sql `${element} ${nullSafeEqual()} ${encodeType(colname, 'number', expr.value)}`;
|
|
2093
|
-
}
|
|
2094
2164
|
return sql `${element} ${nullSafeEqual()} ${encodeValue(expr.value)}`;
|
|
2095
2165
|
}
|
|
2096
2166
|
case '$ne':
|
|
@@ -2104,9 +2174,6 @@ const encodeFieldExpression = (compiler, parent, field, expr) => {
|
|
|
2104
2174
|
break;
|
|
2105
2175
|
return sql `${element} ${nullSafeNotEqual()} ${{ value: expr.value.objectId }}`;
|
|
2106
2176
|
}
|
|
2107
|
-
if (relation && _.includes(parent.countMatches, relation.colname)) {
|
|
2108
|
-
return sql `${element} ${nullSafeNotEqual()} ${encodeType(colname, 'number', expr.value)}`;
|
|
2109
|
-
}
|
|
2110
2177
|
return sql `${element} ${nullSafeNotEqual()} ${encodeValue(expr.value)}`;
|
|
2111
2178
|
}
|
|
2112
2179
|
case '$gt':
|
|
@@ -2150,9 +2217,6 @@ const encodeFieldExpression = (compiler, parent, field, expr) => {
|
|
|
2150
2217
|
else if (!_.isString(dataType) && dataType?.type === 'pointer' && expr.value instanceof index.TObject && expr.value.objectId) {
|
|
2151
2218
|
return sql `${element} ${{ literal: op }} ${{ value: expr.value.objectId }}`;
|
|
2152
2219
|
}
|
|
2153
|
-
else if (relation && _.includes(parent.countMatches, relation.colname)) {
|
|
2154
|
-
return sql `${element} ${{ literal: op }} ${encodeType(colname, 'number', expr.value)}`;
|
|
2155
|
-
}
|
|
2156
2220
|
else if (!dataType) {
|
|
2157
2221
|
if (expr.value instanceof Decimal || _.isNumber(expr.value)) {
|
|
2158
2222
|
return sql `(
|
|
@@ -2343,8 +2407,10 @@ const encodeFieldExpression = (compiler, parent, field, expr) => {
|
|
|
2343
2407
|
if (dataType && index._isTypeof(dataType, 'string')) {
|
|
2344
2408
|
return sql `COALESCE(length(${element}), 0) = ${{ value: expr.value }}`;
|
|
2345
2409
|
}
|
|
2346
|
-
if (relation &&
|
|
2347
|
-
|
|
2410
|
+
if (relation && parent.className && parent.groupMatches?.[colname]) {
|
|
2411
|
+
const tempName = `_populate_expr_$${compiler.nextIdx()}`;
|
|
2412
|
+
const populate = _selectRelationPopulate(compiler, { className: parent.className, name: parent.name }, relation.populate, `$${field}`, false);
|
|
2413
|
+
return sql `(SELECT COUNT(*) FROM (${populate}) AS ${{ identifier: tempName }}) = ${{ value: expr.value }}`;
|
|
2348
2414
|
}
|
|
2349
2415
|
if (dataType && index._isTypeof(dataType, ['array', 'string[]', 'vector', 'relation'])) {
|
|
2350
2416
|
return sql `COALESCE(array_length(${element}, 1), 0) = ${{ value: expr.value }}`;
|
|
@@ -2367,8 +2433,10 @@ const encodeFieldExpression = (compiler, parent, field, expr) => {
|
|
|
2367
2433
|
if (dataType && index._isTypeof(dataType, 'string')) {
|
|
2368
2434
|
return sql `COALESCE(length(${element}), 0) ${{ literal: expr.value ? '=' : '<>' }} 0`;
|
|
2369
2435
|
}
|
|
2370
|
-
if (relation &&
|
|
2371
|
-
|
|
2436
|
+
if (relation && parent.className && parent.groupMatches?.[colname]) {
|
|
2437
|
+
const tempName = `_populate_expr_$${compiler.nextIdx()}`;
|
|
2438
|
+
const populate = _selectRelationPopulate(compiler, { className: parent.className, name: parent.name }, relation.populate, `$${field}`, false);
|
|
2439
|
+
return sql `${{ literal: expr.value ? 'NOT EXISTS' : 'EXISTS' }}(SELECT * FROM (${populate}) AS ${{ identifier: tempName }})`;
|
|
2372
2440
|
}
|
|
2373
2441
|
if (dataType && index._isTypeof(dataType, ['array', 'string[]', 'vector', 'relation'])) {
|
|
2374
2442
|
return sql `COALESCE(array_length(${element}, 1), 0) ${{ literal: expr.value ? '=' : '<>' }} 0`;
|