proto.io 0.0.210 → 0.0.212
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 +142 -78
- package/dist/adapters/storage/progres.js.map +1 -1
- package/dist/adapters/storage/progres.mjs +143 -79
- 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 +11 -12
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +13 -14
- package/dist/index.mjs.map +1 -1
- package/dist/internals/{base-C1ndp06_.d.ts → base-CZGalGrd.d.ts} +2 -2
- package/dist/internals/base-CZGalGrd.d.ts.map +1 -0
- package/dist/internals/{chunk-DF4KyvgB.d.ts → chunk-BsT9SYny.d.ts} +3 -3
- package/dist/internals/chunk-BsT9SYny.d.ts.map +1 -0
- package/dist/internals/{index-DIRjiWPh.d.ts → index-Boxwkqe0.d.ts} +37 -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-Clo9hepf.js → index-DfnPpl1I.js} +23 -10
- package/dist/internals/index-DfnPpl1I.js.map +1 -0
- package/dist/internals/{index-l-Mk0lCc.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-BgSBzm-K.mjs → index-ZPbBr9Db.mjs} +23 -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-C1ndp06_.d.ts.map +0 -1
- package/dist/internals/chunk-DF4KyvgB.d.ts.map +0 -1
- package/dist/internals/index-BgSBzm-K.mjs.map +0 -1
- package/dist/internals/index-Clo9hepf.js.map +0 -1
- package/dist/internals/index-DIRjiWPh.d.ts.map +0 -1
- package/dist/internals/index-l-Mk0lCc.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()}`;
|
|
@@ -409,7 +414,7 @@ class QueryCompiler {
|
|
|
409
414
|
}
|
|
410
415
|
_selectIncludes(className, includes) {
|
|
411
416
|
const _includes = _.pickBy(includes, v => _.isString(v) || (v.type !== 'pointer' && v.type !== 'relation'));
|
|
412
|
-
return _.
|
|
417
|
+
return _.flatMap(_includes, (dataType, colname) => {
|
|
413
418
|
if (!_.isString(dataType) && index.isPrimitive(dataType) && !_.isNil(dataType.default)) {
|
|
414
419
|
return sql `COALESCE(${{ identifier: className }}.${{ identifier: colname }}, ${{ value: dataType.default }}) AS ${{ identifier: colname }}`;
|
|
415
420
|
}
|
|
@@ -430,7 +435,7 @@ class QueryCompiler {
|
|
|
430
435
|
`)}`;
|
|
431
436
|
}
|
|
432
437
|
_selectPopulateMap(context) {
|
|
433
|
-
return _.map(context.populates, (populate, field) => this.dialect.selectPopulate(this, context, populate, field
|
|
438
|
+
return _.map(context.populates, (populate, field) => this.dialect.selectPopulate(this, context, populate, field));
|
|
434
439
|
}
|
|
435
440
|
insert(options, values) {
|
|
436
441
|
const _values = _.map(values, attr => ({
|
|
@@ -568,9 +573,15 @@ class SqlStorage {
|
|
|
568
573
|
const { query, values } = sql.compile(this.dialect);
|
|
569
574
|
return this._query(query, values);
|
|
570
575
|
}
|
|
571
|
-
|
|
576
|
+
_decodeMatchTypes(value, matchType) {
|
|
577
|
+
if (!_.isPlainObject(value))
|
|
578
|
+
return;
|
|
579
|
+
return _.mapValues(value, (v, k) => this.dialect.decodeType(matchType[k], v));
|
|
580
|
+
}
|
|
581
|
+
_decodeShapedObject(dataType, value, matchesType) {
|
|
572
582
|
const result = {};
|
|
573
583
|
for (const { path, type } of index.shapePaths(dataType)) {
|
|
584
|
+
const matchType = _.get(matchesType, path) ?? {};
|
|
574
585
|
if (_.isString(type)) {
|
|
575
586
|
const _value = this.dialect.decodeType(type, _.get(value, path));
|
|
576
587
|
if (!_.isNil(_value))
|
|
@@ -579,17 +590,17 @@ class SqlStorage {
|
|
|
579
590
|
else if (index.isPointer(type)) {
|
|
580
591
|
const _value = _.get(value, path);
|
|
581
592
|
if (_.isPlainObject(_value)) {
|
|
582
|
-
const decoded = this._decodeObject(type.target, _value);
|
|
593
|
+
const decoded = this._decodeObject(type.target, _value, matchType);
|
|
583
594
|
if (decoded.objectId)
|
|
584
595
|
_.set(result, path, decoded);
|
|
585
596
|
}
|
|
586
597
|
}
|
|
587
598
|
else if (index.isRelation(type)) {
|
|
588
599
|
const _value = _.get(value, path);
|
|
589
|
-
if (_.
|
|
590
|
-
_.set(result, path,
|
|
591
|
-
else if (_.
|
|
592
|
-
_.set(result, path,
|
|
600
|
+
if (_.isArray(_value))
|
|
601
|
+
_.set(result, path, _value.map(x => this._decodeObject(type.target, x, matchType)));
|
|
602
|
+
else if (_.isPlainObject(_value))
|
|
603
|
+
_.set(result, path, this._decodeMatchTypes(_value, matchType));
|
|
593
604
|
}
|
|
594
605
|
else {
|
|
595
606
|
const _value = this.dialect.decodeType(type.type, _.get(value, path)) ?? type.default;
|
|
@@ -599,7 +610,7 @@ class SqlStorage {
|
|
|
599
610
|
}
|
|
600
611
|
return result;
|
|
601
612
|
}
|
|
602
|
-
_decodeObject(className, attrs) {
|
|
613
|
+
_decodeObject(className, attrs, matchesType) {
|
|
603
614
|
const fields = this.schema[className].fields;
|
|
604
615
|
const obj = new index.TObject(className);
|
|
605
616
|
const _attrs = {};
|
|
@@ -607,6 +618,7 @@ class SqlStorage {
|
|
|
607
618
|
_.set(_attrs, key, value);
|
|
608
619
|
}
|
|
609
620
|
for (const [key, value] of _.toPairs(_attrs)) {
|
|
621
|
+
const matchType = matchesType[key] ?? {};
|
|
610
622
|
const dataType = fields[key];
|
|
611
623
|
if (!dataType)
|
|
612
624
|
continue;
|
|
@@ -614,20 +626,20 @@ class SqlStorage {
|
|
|
614
626
|
obj[_private.PVK].attributes[key] = this.dialect.decodeType(dataType, value);
|
|
615
627
|
}
|
|
616
628
|
else if (index.isShape(dataType)) {
|
|
617
|
-
obj[_private.PVK].attributes[key] = this._decodeShapedObject(dataType, value);
|
|
629
|
+
obj[_private.PVK].attributes[key] = this._decodeShapedObject(dataType, value, matchType);
|
|
618
630
|
}
|
|
619
631
|
else if (index.isPointer(dataType)) {
|
|
620
632
|
if (_.isPlainObject(value)) {
|
|
621
|
-
const decoded = this._decodeObject(dataType.target, value);
|
|
633
|
+
const decoded = this._decodeObject(dataType.target, value, matchType);
|
|
622
634
|
if (decoded.objectId)
|
|
623
635
|
obj[_private.PVK].attributes[key] = decoded;
|
|
624
636
|
}
|
|
625
637
|
}
|
|
626
638
|
else if (index.isRelation(dataType)) {
|
|
627
|
-
if (_.
|
|
628
|
-
obj[_private.PVK].attributes[key] =
|
|
629
|
-
else if (_.
|
|
630
|
-
obj[_private.PVK].attributes[key] =
|
|
639
|
+
if (_.isArray(value))
|
|
640
|
+
obj[_private.PVK].attributes[key] = value.map(x => this._decodeObject(dataType.target, x, matchType));
|
|
641
|
+
else if (_.isPlainObject(value))
|
|
642
|
+
obj[_private.PVK].attributes[key] = this._decodeMatchTypes(value, matchType);
|
|
631
643
|
}
|
|
632
644
|
else {
|
|
633
645
|
obj[_private.PVK].attributes[key] = this.dialect.decodeType(dataType.type, value) ?? dataType.default;
|
|
@@ -656,6 +668,18 @@ class SqlStorage {
|
|
|
656
668
|
const count = parseInt(_count);
|
|
657
669
|
return _.isFinite(count) ? count : 0;
|
|
658
670
|
}
|
|
671
|
+
_matchesType(options) {
|
|
672
|
+
const types = {};
|
|
673
|
+
for (const [key, match] of _.entries(options.matches)) {
|
|
674
|
+
types[key] = this._matchesType(match);
|
|
675
|
+
}
|
|
676
|
+
for (const [key, group] of _.entries(options.groupMatches)) {
|
|
677
|
+
for (const [field, expr] of _.entries(group)) {
|
|
678
|
+
_.set(types, `${key}.${field}`, random$1.accumulatorKeyTypes[expr.type]);
|
|
679
|
+
}
|
|
680
|
+
}
|
|
681
|
+
return types;
|
|
682
|
+
}
|
|
659
683
|
find(query) {
|
|
660
684
|
const self = this;
|
|
661
685
|
const compiler = self._makeCompiler(false, query.extraFilter);
|
|
@@ -663,7 +687,7 @@ class SqlStorage {
|
|
|
663
687
|
return (async function* () {
|
|
664
688
|
const objects = self.query(_query);
|
|
665
689
|
for await (const object of objects) {
|
|
666
|
-
yield self._decodeObject(query.className, object);
|
|
690
|
+
yield self._decodeObject(query.className, object, self._matchesType(query));
|
|
667
691
|
}
|
|
668
692
|
})();
|
|
669
693
|
}
|
|
@@ -676,7 +700,7 @@ class SqlStorage {
|
|
|
676
700
|
return (async function* () {
|
|
677
701
|
const objects = self.query(_query);
|
|
678
702
|
for await (const object of objects) {
|
|
679
|
-
yield self._decodeObject(query.className, object);
|
|
703
|
+
yield self._decodeObject(query.className, object, self._matchesType(query));
|
|
680
704
|
}
|
|
681
705
|
})();
|
|
682
706
|
}
|
|
@@ -690,7 +714,7 @@ class SqlStorage {
|
|
|
690
714
|
return (async function* () {
|
|
691
715
|
const objects = self.query(query);
|
|
692
716
|
for await (const { _class, ...object } of objects) {
|
|
693
|
-
yield self._decodeObject(_class, object);
|
|
717
|
+
yield self._decodeObject(_class, object, {});
|
|
694
718
|
}
|
|
695
719
|
})();
|
|
696
720
|
}
|
|
@@ -705,29 +729,29 @@ class SqlStorage {
|
|
|
705
729
|
return (async function* () {
|
|
706
730
|
const objects = self.query(_query);
|
|
707
731
|
for await (const object of objects) {
|
|
708
|
-
yield self._decodeObject(query.className, object);
|
|
732
|
+
yield self._decodeObject(query.className, object, self._matchesType(query));
|
|
709
733
|
}
|
|
710
734
|
})();
|
|
711
735
|
}
|
|
712
736
|
async insert(options, values) {
|
|
713
737
|
const compiler = this._makeCompiler(true);
|
|
714
738
|
const result = await this.query(compiler.insert(options, values));
|
|
715
|
-
return _.map(result, x => this._decodeObject(options.className, x));
|
|
739
|
+
return _.map(result, x => this._decodeObject(options.className, x, this._matchesType(options)));
|
|
716
740
|
}
|
|
717
741
|
async update(query, update) {
|
|
718
742
|
const compiler = this._makeCompiler(true, query.extraFilter);
|
|
719
743
|
const updated = await this.query(compiler.update(query, update));
|
|
720
|
-
return _.map(updated, x => this._decodeObject(query.className, x));
|
|
744
|
+
return _.map(updated, x => this._decodeObject(query.className, x, this._matchesType(query)));
|
|
721
745
|
}
|
|
722
746
|
async upsert(query, update, setOnInsert) {
|
|
723
747
|
const compiler = this._makeCompiler(true, query.extraFilter);
|
|
724
748
|
const upserted = await this.query(compiler.upsert(query, update, setOnInsert));
|
|
725
|
-
return _.map(upserted, x => this._decodeObject(query.className, x));
|
|
749
|
+
return _.map(upserted, x => this._decodeObject(query.className, x, this._matchesType(query)));
|
|
726
750
|
}
|
|
727
751
|
async delete(query) {
|
|
728
752
|
const compiler = this._makeCompiler(true, query.extraFilter);
|
|
729
753
|
const deleted = await this.query(compiler.delete(query));
|
|
730
|
-
return _.map(deleted, x => this._decodeObject(query.className, x));
|
|
754
|
+
return _.map(deleted, x => this._decodeObject(query.className, x, this._matchesType(query)));
|
|
731
755
|
}
|
|
732
756
|
}
|
|
733
757
|
|
|
@@ -773,7 +797,15 @@ const _fetchElement = (parent, colname, subpath, dataType) => {
|
|
|
773
797
|
}
|
|
774
798
|
else if (!_.isEmpty(subpath)) {
|
|
775
799
|
const _subpath = sql `${_.map(subpath, x => sql `${{ quote: x.startsWith('$') ? `$${x}` : x }}`)}`;
|
|
776
|
-
|
|
800
|
+
const match = parent.groupMatches?.[colname]?.[subpath[0]];
|
|
801
|
+
if (dataType && index.isRelation(dataType) && subpath.length === 1 && match) {
|
|
802
|
+
return {
|
|
803
|
+
element: sql `${{ identifier: parent.name }}.${{ identifier: `${colname}.${subpath[0]}` }}`,
|
|
804
|
+
json: false,
|
|
805
|
+
dataType: random$1.accumulatorKeyTypes[match.type],
|
|
806
|
+
};
|
|
807
|
+
}
|
|
808
|
+
else if (dataType && index._isTypeof(dataType, ['array', 'string[]', 'relation'])) {
|
|
777
809
|
return {
|
|
778
810
|
element: sql `jsonb_extract_path(to_jsonb(${element}), ${_subpath})`,
|
|
779
811
|
json: true,
|
|
@@ -833,7 +865,7 @@ const _resolvePopulate = (path, populates) => {
|
|
|
833
865
|
const fetchElement = (compiler, parent, field) => {
|
|
834
866
|
if (parent.className) {
|
|
835
867
|
const { dataType, colname, subpath } = resolvePaths(compiler, parent.className, _.toPath(field));
|
|
836
|
-
const { element, json } = _fetchElement(parent, colname, subpath, dataType);
|
|
868
|
+
const { element, json, dataType: _dataType } = _fetchElement(parent, colname, subpath, dataType);
|
|
837
869
|
if (index.isPointer(dataType))
|
|
838
870
|
return { element: sql `${{ identifier: parent.name }}.${{ identifier: `${colname}._id` }}`, dataType };
|
|
839
871
|
const populate = index.isRelation(dataType) && _resolvePopulate(_.toPath(colname), parent.populates);
|
|
@@ -841,7 +873,7 @@ const fetchElement = (compiler, parent, field) => {
|
|
|
841
873
|
return { element, dataType: json ? null : dataType };
|
|
842
874
|
return {
|
|
843
875
|
element,
|
|
844
|
-
dataType: json ? null : dataType,
|
|
876
|
+
dataType: json ? null : _dataType ?? dataType,
|
|
845
877
|
relation: {
|
|
846
878
|
colname,
|
|
847
879
|
target: dataType.target,
|
|
@@ -1181,7 +1213,7 @@ const _encodeJsonValue = (value) => {
|
|
|
1181
1213
|
return sql `jsonb_build_object(${_.map(value, (v, k) => sql `${{ value: k }}, ${_encodeJsonValue(v)}`)})`;
|
|
1182
1214
|
return sql `to_jsonb(${{ value }})`;
|
|
1183
1215
|
};
|
|
1184
|
-
const
|
|
1216
|
+
const _jsonPopulateInclude = (className, colname, dataType) => {
|
|
1185
1217
|
switch (index._typeof(dataType)) {
|
|
1186
1218
|
case 'decimal':
|
|
1187
1219
|
return sql `jsonb_build_object(
|
|
@@ -1896,10 +1928,13 @@ const _selectRelationPopulate = (compiler, parent, populate, field, encode) => {
|
|
|
1896
1928
|
cond = sql `${sql `(${{ quote: parent.className + '$' }} || ${_local('_id')})`} = ANY(${_foreign(populate.colname)})`;
|
|
1897
1929
|
}
|
|
1898
1930
|
return sql `
|
|
1899
|
-
SELECT ${_.compact(_.flatMap(subpaths, ({ path, type }) => [
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
1931
|
+
SELECT ${_.compact(_.flatMap(subpaths, ({ path, type }) => encode ? [
|
|
1932
|
+
_jsonPopulateInclude(populate.name, path, type)
|
|
1933
|
+
] : [
|
|
1934
|
+
...(populate.groupMatches[path] ? _.map(_.keys(populate.groupMatches[path]), k => sql `${{ identifier: populate.name }}.${{ identifier: `${path}.${k}` }}`) : [
|
|
1935
|
+
sql `${{ identifier: populate.name }}.${{ identifier: path }}`
|
|
1936
|
+
]),
|
|
1937
|
+
index.isRelation(type) && sql `${{ identifier: populate.name }}.${{ identifier: `$${path}` }}`,
|
|
1903
1938
|
]))}
|
|
1904
1939
|
FROM ${{ identifier: populate.name }} WHERE ${cond}
|
|
1905
1940
|
${!_.isEmpty(populate.sort) ? sql `ORDER BY ${compiler._encodeSort(populate.sort, { className: populate.className, name: populate.name })}` : sql ``}
|
|
@@ -1908,33 +1943,68 @@ const _selectRelationPopulate = (compiler, parent, populate, field, encode) => {
|
|
|
1908
1943
|
${compiler.selectLock ? compiler.isUpdate ? sql `FOR UPDATE NOWAIT` : sql `FOR SHARE NOWAIT` : sql ``}
|
|
1909
1944
|
`;
|
|
1910
1945
|
};
|
|
1911
|
-
const selectPopulate = (compiler, parent, populate, field
|
|
1946
|
+
const selectPopulate = (compiler, parent, populate, field) => {
|
|
1912
1947
|
if (populate.type === 'relation') {
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
-
|
|
1930
|
-
|
|
1948
|
+
const { groupMatches } = parent;
|
|
1949
|
+
const columns = [
|
|
1950
|
+
sql `${{ identifier: parent.name }}.${{ identifier: field }} AS ${{ identifier: `$${field}` }}`,
|
|
1951
|
+
];
|
|
1952
|
+
if (!_.isEmpty(groupMatches?.[field])) {
|
|
1953
|
+
for (const [key, { type, expr }] of _.entries(groupMatches[field])) {
|
|
1954
|
+
switch (type) {
|
|
1955
|
+
case '$count':
|
|
1956
|
+
columns.push(sql `
|
|
1957
|
+
(
|
|
1958
|
+
SELECT COUNT(*) FROM (
|
|
1959
|
+
${_selectRelationPopulate(compiler, parent, populate, field, false)}
|
|
1960
|
+
) ${{ identifier: populate.name }}
|
|
1961
|
+
) AS ${{ identifier: `${field}.${key}` }}
|
|
1962
|
+
`);
|
|
1963
|
+
break;
|
|
1964
|
+
case '$avg':
|
|
1965
|
+
case '$sum':
|
|
1966
|
+
{
|
|
1967
|
+
const op = {
|
|
1968
|
+
'$avg': 'AVG',
|
|
1969
|
+
'$sum': 'SUM',
|
|
1970
|
+
}[type];
|
|
1971
|
+
if (!expr)
|
|
1972
|
+
throw Error('Invalid expression');
|
|
1973
|
+
const exprs = encodeTypedQueryExpression(compiler, populate, expr);
|
|
1974
|
+
const { sql: value } = (_.includes(['$avg'], type) ? _.find(exprs, e => e.type === 'number') : _.first(exprs)) ?? {};
|
|
1975
|
+
if (!value)
|
|
1976
|
+
throw Error('Invalid expression');
|
|
1977
|
+
columns.push(sql `
|
|
1978
|
+
(
|
|
1979
|
+
SELECT ${{ literal: op }}(${value}) FROM (
|
|
1980
|
+
${_selectRelationPopulate(compiler, parent, populate, field, false)}
|
|
1981
|
+
) ${{ identifier: populate.name }}
|
|
1982
|
+
) AS ${{ identifier: `${field}.${key}` }}
|
|
1983
|
+
`);
|
|
1984
|
+
}
|
|
1985
|
+
break;
|
|
1986
|
+
}
|
|
1987
|
+
}
|
|
1988
|
+
}
|
|
1989
|
+
else {
|
|
1990
|
+
columns.push(sql `
|
|
1991
|
+
ARRAY(
|
|
1992
|
+
SELECT to_jsonb(${{ identifier: populate.name }}) FROM (
|
|
1993
|
+
${_selectRelationPopulate(compiler, parent, populate, field, true)}
|
|
1994
|
+
) ${{ identifier: populate.name }}
|
|
1995
|
+
) AS ${{ identifier: field }}
|
|
1996
|
+
`);
|
|
1997
|
+
}
|
|
1998
|
+
return { columns };
|
|
1931
1999
|
}
|
|
1932
2000
|
const _local = (field) => sql `${{ identifier: parent.name }}.${{ identifier: field }}`;
|
|
1933
2001
|
const _foreign = (field) => sql `${{ identifier: populate.name }}.${{ identifier: field }}`;
|
|
1934
2002
|
const subpaths = resolveSubpaths(compiler, populate);
|
|
1935
2003
|
return {
|
|
1936
2004
|
columns: _.compact(_.flatMap(subpaths, ({ path, type }) => [
|
|
1937
|
-
sql `${{ identifier: populate.name }}.${{ identifier: path }} AS ${{ identifier: `${field}.${path}` }}
|
|
2005
|
+
...populate.groupMatches[path] ? _.map(_.keys(populate.groupMatches[path]), k => sql `${{ identifier: populate.name }}.${{ identifier: `${path}.${k}` }} AS ${{ identifier: `${field}.${path}.${k}` }}`) : [
|
|
2006
|
+
sql `${{ identifier: populate.name }}.${{ identifier: path }} AS ${{ identifier: `${field}.${path}` }}`
|
|
2007
|
+
],
|
|
1938
2008
|
index.isRelation(type) && sql `${{ identifier: populate.name }}.${{ identifier: `$${path}` }} AS ${{ identifier: `$${field}.${path}` }}`,
|
|
1939
2009
|
])),
|
|
1940
2010
|
join: sql `
|
|
@@ -2019,9 +2089,8 @@ const encodePopulate = (compiler, parent, remix) => {
|
|
|
2019
2089
|
parent.filter && compiler._encodeFilter(parent, parent.filter),
|
|
2020
2090
|
compiler.extraFilter && compiler._encodeFilter(parent, compiler.extraFilter(parent.className)),
|
|
2021
2091
|
]);
|
|
2022
|
-
const _populates = _.map(parent.populates, (populate, field) => selectPopulate(compiler, parent, populate, field
|
|
2092
|
+
const _populates = _.map(parent.populates, (populate, field) => selectPopulate(compiler, parent, populate, field));
|
|
2023
2093
|
const _joins = _.compact(_.map(_populates, ({ join }) => join));
|
|
2024
|
-
const _includes = _.pickBy(parent.includes, v => index.isPrimitive(v));
|
|
2025
2094
|
const { joins: _joins2 = [], field: _foreignField = undefined, rows = false, } = parent.foreignField ? encodeForeignField(compiler, {
|
|
2026
2095
|
className: parent.className,
|
|
2027
2096
|
name: parent.name,
|
|
@@ -2035,7 +2104,7 @@ const encodePopulate = (compiler, parent, remix) => {
|
|
|
2035
2104
|
SELECT
|
|
2036
2105
|
${{
|
|
2037
2106
|
literal: [
|
|
2038
|
-
...
|
|
2107
|
+
...compiler._selectIncludes(parent.name, parent.includes),
|
|
2039
2108
|
..._.flatMap(_populates, ({ columns: column }) => column),
|
|
2040
2109
|
..._foreignField ? [sql `${rows ? sql `ARRAY(${_foreignField})` : _foreignField} AS ${{ identifier: parent.colname }}`] : [],
|
|
2041
2110
|
], separator: ',\n'
|
|
@@ -2088,9 +2157,6 @@ const encodeFieldExpression = (compiler, parent, field, expr) => {
|
|
|
2088
2157
|
break;
|
|
2089
2158
|
return sql `${element} ${nullSafeEqual()} ${{ value: expr.value.objectId }}`;
|
|
2090
2159
|
}
|
|
2091
|
-
if (relation && _.includes(parent.countMatches, relation.colname)) {
|
|
2092
|
-
return sql `${element} ${nullSafeEqual()} ${encodeType(colname, 'number', expr.value)}`;
|
|
2093
|
-
}
|
|
2094
2160
|
return sql `${element} ${nullSafeEqual()} ${encodeValue(expr.value)}`;
|
|
2095
2161
|
}
|
|
2096
2162
|
case '$ne':
|
|
@@ -2104,9 +2170,6 @@ const encodeFieldExpression = (compiler, parent, field, expr) => {
|
|
|
2104
2170
|
break;
|
|
2105
2171
|
return sql `${element} ${nullSafeNotEqual()} ${{ value: expr.value.objectId }}`;
|
|
2106
2172
|
}
|
|
2107
|
-
if (relation && _.includes(parent.countMatches, relation.colname)) {
|
|
2108
|
-
return sql `${element} ${nullSafeNotEqual()} ${encodeType(colname, 'number', expr.value)}`;
|
|
2109
|
-
}
|
|
2110
2173
|
return sql `${element} ${nullSafeNotEqual()} ${encodeValue(expr.value)}`;
|
|
2111
2174
|
}
|
|
2112
2175
|
case '$gt':
|
|
@@ -2150,9 +2213,6 @@ const encodeFieldExpression = (compiler, parent, field, expr) => {
|
|
|
2150
2213
|
else if (!_.isString(dataType) && dataType?.type === 'pointer' && expr.value instanceof index.TObject && expr.value.objectId) {
|
|
2151
2214
|
return sql `${element} ${{ literal: op }} ${{ value: expr.value.objectId }}`;
|
|
2152
2215
|
}
|
|
2153
|
-
else if (relation && _.includes(parent.countMatches, relation.colname)) {
|
|
2154
|
-
return sql `${element} ${{ literal: op }} ${encodeType(colname, 'number', expr.value)}`;
|
|
2155
|
-
}
|
|
2156
2216
|
else if (!dataType) {
|
|
2157
2217
|
if (expr.value instanceof Decimal || _.isNumber(expr.value)) {
|
|
2158
2218
|
return sql `(
|
|
@@ -2343,8 +2403,10 @@ const encodeFieldExpression = (compiler, parent, field, expr) => {
|
|
|
2343
2403
|
if (dataType && index._isTypeof(dataType, 'string')) {
|
|
2344
2404
|
return sql `COALESCE(length(${element}), 0) = ${{ value: expr.value }}`;
|
|
2345
2405
|
}
|
|
2346
|
-
if (relation &&
|
|
2347
|
-
|
|
2406
|
+
if (relation && parent.className && parent.groupMatches?.[colname]) {
|
|
2407
|
+
const tempName = `_populate_expr_$${compiler.nextIdx()}`;
|
|
2408
|
+
const populate = _selectRelationPopulate(compiler, { className: parent.className, name: parent.name }, relation.populate, `$${field}`, false);
|
|
2409
|
+
return sql `(SELECT COUNT(*) FROM (${populate}) AS ${{ identifier: tempName }}) = ${{ value: expr.value }}`;
|
|
2348
2410
|
}
|
|
2349
2411
|
if (dataType && index._isTypeof(dataType, ['array', 'string[]', 'vector', 'relation'])) {
|
|
2350
2412
|
return sql `COALESCE(array_length(${element}, 1), 0) = ${{ value: expr.value }}`;
|
|
@@ -2367,8 +2429,10 @@ const encodeFieldExpression = (compiler, parent, field, expr) => {
|
|
|
2367
2429
|
if (dataType && index._isTypeof(dataType, 'string')) {
|
|
2368
2430
|
return sql `COALESCE(length(${element}), 0) ${{ literal: expr.value ? '=' : '<>' }} 0`;
|
|
2369
2431
|
}
|
|
2370
|
-
if (relation &&
|
|
2371
|
-
|
|
2432
|
+
if (relation && parent.className && parent.groupMatches?.[colname]) {
|
|
2433
|
+
const tempName = `_populate_expr_$${compiler.nextIdx()}`;
|
|
2434
|
+
const populate = _selectRelationPopulate(compiler, { className: parent.className, name: parent.name }, relation.populate, `$${field}`, false);
|
|
2435
|
+
return sql `${{ literal: expr.value ? 'NOT EXISTS' : 'EXISTS' }}(SELECT * FROM (${populate}) AS ${{ identifier: tempName }})`;
|
|
2372
2436
|
}
|
|
2373
2437
|
if (dataType && index._isTypeof(dataType, ['array', 'string[]', 'vector', 'relation'])) {
|
|
2374
2438
|
return sql `COALESCE(array_length(${element}, 1), 0) ${{ literal: expr.value ? '=' : '<>' }} 0`;
|