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
|
@@ -5,9 +5,9 @@ import QueryStream from 'pg-query-stream';
|
|
|
5
5
|
import { asyncStream, IteratorPool } 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
|
|
8
|
+
import { a as QueryCoditionalSelector, b as QueryFieldSelector, c as QueryExpressionSelector, d as QueryDistanceExpression, e as QueryKeyExpression, f as QueryValueExpression, g as QueryCoditionalExpression, h as QueryComparisonExpression, i as QueryNotExpression, j as QueryArrayExpression, Q as QuerySelector, F as FieldSelectorExpression } from '../../internals/index-DG9HHO_U.mjs';
|
|
9
9
|
import '@o2ter/crypto-js';
|
|
10
|
-
import { r as resolveColumn, a as resolveDataType$1, g as generateId, Q as QueryValidator } from '../../internals/random-
|
|
10
|
+
import { r as resolveColumn, a as resolveDataType$1, g as generateId, b as accumulatorKeyTypes, Q as QueryValidator } from '../../internals/random-CufRbivU.mjs';
|
|
11
11
|
import { c as PROTO_EVENT } from '../../internals/const-Dkp7Nsv5.mjs';
|
|
12
12
|
import { P as PVK } from '../../internals/private-CNw40LZ7.mjs';
|
|
13
13
|
|
|
@@ -214,12 +214,12 @@ class QueryCompiler {
|
|
|
214
214
|
_encodeIncludes(query) {
|
|
215
215
|
const names = {};
|
|
216
216
|
const populates = {};
|
|
217
|
-
const
|
|
217
|
+
const groupMatches = {};
|
|
218
218
|
for (const include of query.includes) {
|
|
219
219
|
const { paths: [colname, ...subpath], dataType } = resolveColumn(this.schema, query.className, include);
|
|
220
220
|
names[colname] = dataType;
|
|
221
|
-
if (isRelation(dataType) && _.
|
|
222
|
-
|
|
221
|
+
if (isRelation(dataType) && !_.isNil(query.groupMatches[colname]))
|
|
222
|
+
groupMatches[colname] = query.groupMatches[colname];
|
|
223
223
|
if (isPointer(dataType) || isRelation(dataType)) {
|
|
224
224
|
if (_.isEmpty(subpath))
|
|
225
225
|
throw Error(`Invalid path: ${include}`);
|
|
@@ -250,21 +250,26 @@ class QueryCompiler {
|
|
|
250
250
|
}
|
|
251
251
|
for (const [colname, populate] of _.toPairs(populates)) {
|
|
252
252
|
const _matches = query.matches[colname];
|
|
253
|
-
const { includes, populates,
|
|
253
|
+
const { includes, populates, groupMatches } = this._encodeIncludes({
|
|
254
254
|
className: populate.className,
|
|
255
255
|
includes: populate.subpaths,
|
|
256
256
|
matches: _matches.matches,
|
|
257
|
-
|
|
258
|
-
..._.
|
|
259
|
-
..._matches.
|
|
260
|
-
|
|
257
|
+
groupMatches: {
|
|
258
|
+
..._.mapKeys(_.pickBy(query.groupMatches, (x, k) => _.startsWith(k, `${colname}.`)), (x, k) => k.slice(colname.length + 1)),
|
|
259
|
+
..._matches.groupMatches ?? {},
|
|
260
|
+
},
|
|
261
261
|
});
|
|
262
262
|
populate.sort = _encodeSorting(includes, populates, _matches.sort);
|
|
263
263
|
populate.includes = includes;
|
|
264
264
|
populate.populates = populates;
|
|
265
|
-
populate.
|
|
265
|
+
populate.groupMatches = groupMatches;
|
|
266
266
|
}
|
|
267
|
-
return {
|
|
267
|
+
return {
|
|
268
|
+
className: query.className,
|
|
269
|
+
includes: names,
|
|
270
|
+
populates,
|
|
271
|
+
groupMatches,
|
|
272
|
+
};
|
|
268
273
|
}
|
|
269
274
|
_baseSelectQuery(query, options) {
|
|
270
275
|
const fetchName = `_fetch_$${query.className.toLowerCase()}`;
|
|
@@ -405,7 +410,7 @@ class QueryCompiler {
|
|
|
405
410
|
}
|
|
406
411
|
_selectIncludes(className, includes) {
|
|
407
412
|
const _includes = _.pickBy(includes, v => _.isString(v) || (v.type !== 'pointer' && v.type !== 'relation'));
|
|
408
|
-
return _.
|
|
413
|
+
return _.flatMap(_includes, (dataType, colname) => {
|
|
409
414
|
if (!_.isString(dataType) && isPrimitive(dataType) && !_.isNil(dataType.default)) {
|
|
410
415
|
return sql `COALESCE(${{ identifier: className }}.${{ identifier: colname }}, ${{ value: dataType.default }}) AS ${{ identifier: colname }}`;
|
|
411
416
|
}
|
|
@@ -426,7 +431,7 @@ class QueryCompiler {
|
|
|
426
431
|
`)}`;
|
|
427
432
|
}
|
|
428
433
|
_selectPopulateMap(context) {
|
|
429
|
-
return _.map(context.populates, (populate, field) => this.dialect.selectPopulate(this, context, populate, field
|
|
434
|
+
return _.map(context.populates, (populate, field) => this.dialect.selectPopulate(this, context, populate, field));
|
|
430
435
|
}
|
|
431
436
|
insert(options, values) {
|
|
432
437
|
const _values = _.map(values, attr => ({
|
|
@@ -564,9 +569,15 @@ class SqlStorage {
|
|
|
564
569
|
const { query, values } = sql.compile(this.dialect);
|
|
565
570
|
return this._query(query, values);
|
|
566
571
|
}
|
|
567
|
-
|
|
572
|
+
_decodeMatchTypes(value, matchType) {
|
|
573
|
+
if (!_.isPlainObject(value))
|
|
574
|
+
return;
|
|
575
|
+
return _.mapValues(value, (v, k) => this.dialect.decodeType(matchType[k], v));
|
|
576
|
+
}
|
|
577
|
+
_decodeShapedObject(dataType, value, matchesType) {
|
|
568
578
|
const result = {};
|
|
569
579
|
for (const { path, type } of shapePaths(dataType)) {
|
|
580
|
+
const matchType = _.get(matchesType, path) ?? {};
|
|
570
581
|
if (_.isString(type)) {
|
|
571
582
|
const _value = this.dialect.decodeType(type, _.get(value, path));
|
|
572
583
|
if (!_.isNil(_value))
|
|
@@ -575,17 +586,17 @@ class SqlStorage {
|
|
|
575
586
|
else if (isPointer(type)) {
|
|
576
587
|
const _value = _.get(value, path);
|
|
577
588
|
if (_.isPlainObject(_value)) {
|
|
578
|
-
const decoded = this._decodeObject(type.target, _value);
|
|
589
|
+
const decoded = this._decodeObject(type.target, _value, matchType);
|
|
579
590
|
if (decoded.objectId)
|
|
580
591
|
_.set(result, path, decoded);
|
|
581
592
|
}
|
|
582
593
|
}
|
|
583
594
|
else if (isRelation(type)) {
|
|
584
595
|
const _value = _.get(value, path);
|
|
585
|
-
if (_.
|
|
586
|
-
_.set(result, path,
|
|
587
|
-
else if (_.
|
|
588
|
-
_.set(result, path,
|
|
596
|
+
if (_.isArray(_value))
|
|
597
|
+
_.set(result, path, _value.map(x => this._decodeObject(type.target, x, matchType)));
|
|
598
|
+
else if (_.isPlainObject(_value))
|
|
599
|
+
_.set(result, path, this._decodeMatchTypes(_value, matchType));
|
|
589
600
|
}
|
|
590
601
|
else {
|
|
591
602
|
const _value = this.dialect.decodeType(type.type, _.get(value, path)) ?? type.default;
|
|
@@ -595,7 +606,7 @@ class SqlStorage {
|
|
|
595
606
|
}
|
|
596
607
|
return result;
|
|
597
608
|
}
|
|
598
|
-
_decodeObject(className, attrs) {
|
|
609
|
+
_decodeObject(className, attrs, matchesType) {
|
|
599
610
|
const fields = this.schema[className].fields;
|
|
600
611
|
const obj = new TObject(className);
|
|
601
612
|
const _attrs = {};
|
|
@@ -603,6 +614,7 @@ class SqlStorage {
|
|
|
603
614
|
_.set(_attrs, key, value);
|
|
604
615
|
}
|
|
605
616
|
for (const [key, value] of _.toPairs(_attrs)) {
|
|
617
|
+
const matchType = matchesType[key] ?? {};
|
|
606
618
|
const dataType = fields[key];
|
|
607
619
|
if (!dataType)
|
|
608
620
|
continue;
|
|
@@ -610,20 +622,20 @@ class SqlStorage {
|
|
|
610
622
|
obj[PVK].attributes[key] = this.dialect.decodeType(dataType, value);
|
|
611
623
|
}
|
|
612
624
|
else if (isShape(dataType)) {
|
|
613
|
-
obj[PVK].attributes[key] = this._decodeShapedObject(dataType, value);
|
|
625
|
+
obj[PVK].attributes[key] = this._decodeShapedObject(dataType, value, matchType);
|
|
614
626
|
}
|
|
615
627
|
else if (isPointer(dataType)) {
|
|
616
628
|
if (_.isPlainObject(value)) {
|
|
617
|
-
const decoded = this._decodeObject(dataType.target, value);
|
|
629
|
+
const decoded = this._decodeObject(dataType.target, value, matchType);
|
|
618
630
|
if (decoded.objectId)
|
|
619
631
|
obj[PVK].attributes[key] = decoded;
|
|
620
632
|
}
|
|
621
633
|
}
|
|
622
634
|
else if (isRelation(dataType)) {
|
|
623
|
-
if (_.
|
|
624
|
-
obj[PVK].attributes[key] =
|
|
625
|
-
else if (_.
|
|
626
|
-
obj[PVK].attributes[key] =
|
|
635
|
+
if (_.isArray(value))
|
|
636
|
+
obj[PVK].attributes[key] = value.map(x => this._decodeObject(dataType.target, x, matchType));
|
|
637
|
+
else if (_.isPlainObject(value))
|
|
638
|
+
obj[PVK].attributes[key] = this._decodeMatchTypes(value, matchType);
|
|
627
639
|
}
|
|
628
640
|
else {
|
|
629
641
|
obj[PVK].attributes[key] = this.dialect.decodeType(dataType.type, value) ?? dataType.default;
|
|
@@ -652,6 +664,18 @@ class SqlStorage {
|
|
|
652
664
|
const count = parseInt(_count);
|
|
653
665
|
return _.isFinite(count) ? count : 0;
|
|
654
666
|
}
|
|
667
|
+
_matchesType(options) {
|
|
668
|
+
const types = {};
|
|
669
|
+
for (const [key, match] of _.entries(options.matches)) {
|
|
670
|
+
types[key] = this._matchesType(match);
|
|
671
|
+
}
|
|
672
|
+
for (const [key, group] of _.entries(options.groupMatches)) {
|
|
673
|
+
for (const [field, expr] of _.entries(group)) {
|
|
674
|
+
_.set(types, `${key}.${field}`, accumulatorKeyTypes[expr.type]);
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
return types;
|
|
678
|
+
}
|
|
655
679
|
find(query) {
|
|
656
680
|
const self = this;
|
|
657
681
|
const compiler = self._makeCompiler(false, query.extraFilter);
|
|
@@ -659,7 +683,7 @@ class SqlStorage {
|
|
|
659
683
|
return (async function* () {
|
|
660
684
|
const objects = self.query(_query);
|
|
661
685
|
for await (const object of objects) {
|
|
662
|
-
yield self._decodeObject(query.className, object);
|
|
686
|
+
yield self._decodeObject(query.className, object, self._matchesType(query));
|
|
663
687
|
}
|
|
664
688
|
})();
|
|
665
689
|
}
|
|
@@ -672,7 +696,7 @@ class SqlStorage {
|
|
|
672
696
|
return (async function* () {
|
|
673
697
|
const objects = self.query(_query);
|
|
674
698
|
for await (const object of objects) {
|
|
675
|
-
yield self._decodeObject(query.className, object);
|
|
699
|
+
yield self._decodeObject(query.className, object, self._matchesType(query));
|
|
676
700
|
}
|
|
677
701
|
})();
|
|
678
702
|
}
|
|
@@ -686,7 +710,7 @@ class SqlStorage {
|
|
|
686
710
|
return (async function* () {
|
|
687
711
|
const objects = self.query(query);
|
|
688
712
|
for await (const { _class, ...object } of objects) {
|
|
689
|
-
yield self._decodeObject(_class, object);
|
|
713
|
+
yield self._decodeObject(_class, object, {});
|
|
690
714
|
}
|
|
691
715
|
})();
|
|
692
716
|
}
|
|
@@ -701,29 +725,29 @@ class SqlStorage {
|
|
|
701
725
|
return (async function* () {
|
|
702
726
|
const objects = self.query(_query);
|
|
703
727
|
for await (const object of objects) {
|
|
704
|
-
yield self._decodeObject(query.className, object);
|
|
728
|
+
yield self._decodeObject(query.className, object, self._matchesType(query));
|
|
705
729
|
}
|
|
706
730
|
})();
|
|
707
731
|
}
|
|
708
732
|
async insert(options, values) {
|
|
709
733
|
const compiler = this._makeCompiler(true);
|
|
710
734
|
const result = await this.query(compiler.insert(options, values));
|
|
711
|
-
return _.map(result, x => this._decodeObject(options.className, x));
|
|
735
|
+
return _.map(result, x => this._decodeObject(options.className, x, this._matchesType(options)));
|
|
712
736
|
}
|
|
713
737
|
async update(query, update) {
|
|
714
738
|
const compiler = this._makeCompiler(true, query.extraFilter);
|
|
715
739
|
const updated = await this.query(compiler.update(query, update));
|
|
716
|
-
return _.map(updated, x => this._decodeObject(query.className, x));
|
|
740
|
+
return _.map(updated, x => this._decodeObject(query.className, x, this._matchesType(query)));
|
|
717
741
|
}
|
|
718
742
|
async upsert(query, update, setOnInsert) {
|
|
719
743
|
const compiler = this._makeCompiler(true, query.extraFilter);
|
|
720
744
|
const upserted = await this.query(compiler.upsert(query, update, setOnInsert));
|
|
721
|
-
return _.map(upserted, x => this._decodeObject(query.className, x));
|
|
745
|
+
return _.map(upserted, x => this._decodeObject(query.className, x, this._matchesType(query)));
|
|
722
746
|
}
|
|
723
747
|
async delete(query) {
|
|
724
748
|
const compiler = this._makeCompiler(true, query.extraFilter);
|
|
725
749
|
const deleted = await this.query(compiler.delete(query));
|
|
726
|
-
return _.map(deleted, x => this._decodeObject(query.className, x));
|
|
750
|
+
return _.map(deleted, x => this._decodeObject(query.className, x, this._matchesType(query)));
|
|
727
751
|
}
|
|
728
752
|
}
|
|
729
753
|
|
|
@@ -769,7 +793,15 @@ const _fetchElement = (parent, colname, subpath, dataType) => {
|
|
|
769
793
|
}
|
|
770
794
|
else if (!_.isEmpty(subpath)) {
|
|
771
795
|
const _subpath = sql `${_.map(subpath, x => sql `${{ quote: x.startsWith('$') ? `$${x}` : x }}`)}`;
|
|
772
|
-
|
|
796
|
+
const match = parent.groupMatches?.[colname]?.[subpath[0]];
|
|
797
|
+
if (dataType && isRelation(dataType) && subpath.length === 1 && match) {
|
|
798
|
+
return {
|
|
799
|
+
element: sql `${{ identifier: parent.name }}.${{ identifier: `${colname}.${subpath[0]}` }}`,
|
|
800
|
+
json: false,
|
|
801
|
+
dataType: accumulatorKeyTypes[match.type],
|
|
802
|
+
};
|
|
803
|
+
}
|
|
804
|
+
else if (dataType && _isTypeof(dataType, ['array', 'string[]', 'relation'])) {
|
|
773
805
|
return {
|
|
774
806
|
element: sql `jsonb_extract_path(to_jsonb(${element}), ${_subpath})`,
|
|
775
807
|
json: true,
|
|
@@ -829,7 +861,7 @@ const _resolvePopulate = (path, populates) => {
|
|
|
829
861
|
const fetchElement = (compiler, parent, field) => {
|
|
830
862
|
if (parent.className) {
|
|
831
863
|
const { dataType, colname, subpath } = resolvePaths(compiler, parent.className, _.toPath(field));
|
|
832
|
-
const { element, json } = _fetchElement(parent, colname, subpath, dataType);
|
|
864
|
+
const { element, json, dataType: _dataType } = _fetchElement(parent, colname, subpath, dataType);
|
|
833
865
|
if (isPointer(dataType))
|
|
834
866
|
return { element: sql `${{ identifier: parent.name }}.${{ identifier: `${colname}._id` }}`, dataType };
|
|
835
867
|
const populate = isRelation(dataType) && _resolvePopulate(_.toPath(colname), parent.populates);
|
|
@@ -837,7 +869,7 @@ const fetchElement = (compiler, parent, field) => {
|
|
|
837
869
|
return { element, dataType: json ? null : dataType };
|
|
838
870
|
return {
|
|
839
871
|
element,
|
|
840
|
-
dataType: json ? null : dataType,
|
|
872
|
+
dataType: json ? null : _dataType ?? dataType,
|
|
841
873
|
relation: {
|
|
842
874
|
colname,
|
|
843
875
|
target: dataType.target,
|
|
@@ -1177,7 +1209,7 @@ const _encodeJsonValue = (value) => {
|
|
|
1177
1209
|
return sql `jsonb_build_object(${_.map(value, (v, k) => sql `${{ value: k }}, ${_encodeJsonValue(v)}`)})`;
|
|
1178
1210
|
return sql `to_jsonb(${{ value }})`;
|
|
1179
1211
|
};
|
|
1180
|
-
const
|
|
1212
|
+
const _jsonPopulateInclude = (className, colname, dataType) => {
|
|
1181
1213
|
switch (_typeof(dataType)) {
|
|
1182
1214
|
case 'decimal':
|
|
1183
1215
|
return sql `jsonb_build_object(
|
|
@@ -1892,10 +1924,13 @@ const _selectRelationPopulate = (compiler, parent, populate, field, encode) => {
|
|
|
1892
1924
|
cond = sql `${sql `(${{ quote: parent.className + '$' }} || ${_local('_id')})`} = ANY(${_foreign(populate.colname)})`;
|
|
1893
1925
|
}
|
|
1894
1926
|
return sql `
|
|
1895
|
-
SELECT ${_.compact(_.flatMap(subpaths, ({ path, type }) => [
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1927
|
+
SELECT ${_.compact(_.flatMap(subpaths, ({ path, type }) => encode ? [
|
|
1928
|
+
_jsonPopulateInclude(populate.name, path, type)
|
|
1929
|
+
] : [
|
|
1930
|
+
...(populate.groupMatches[path] ? _.map(_.keys(populate.groupMatches[path]), k => sql `${{ identifier: populate.name }}.${{ identifier: `${path}.${k}` }}`) : [
|
|
1931
|
+
sql `${{ identifier: populate.name }}.${{ identifier: path }}`
|
|
1932
|
+
]),
|
|
1933
|
+
isRelation(type) && sql `${{ identifier: populate.name }}.${{ identifier: `$${path}` }}`,
|
|
1899
1934
|
]))}
|
|
1900
1935
|
FROM ${{ identifier: populate.name }} WHERE ${cond}
|
|
1901
1936
|
${!_.isEmpty(populate.sort) ? sql `ORDER BY ${compiler._encodeSort(populate.sort, { className: populate.className, name: populate.name })}` : sql ``}
|
|
@@ -1904,33 +1939,68 @@ const _selectRelationPopulate = (compiler, parent, populate, field, encode) => {
|
|
|
1904
1939
|
${compiler.selectLock ? compiler.isUpdate ? sql `FOR UPDATE NOWAIT` : sql `FOR SHARE NOWAIT` : sql ``}
|
|
1905
1940
|
`;
|
|
1906
1941
|
};
|
|
1907
|
-
const selectPopulate = (compiler, parent, populate, field
|
|
1942
|
+
const selectPopulate = (compiler, parent, populate, field) => {
|
|
1908
1943
|
if (populate.type === 'relation') {
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
|
|
1944
|
+
const { groupMatches } = parent;
|
|
1945
|
+
const columns = [
|
|
1946
|
+
sql `${{ identifier: parent.name }}.${{ identifier: field }} AS ${{ identifier: `$${field}` }}`,
|
|
1947
|
+
];
|
|
1948
|
+
if (!_.isEmpty(groupMatches?.[field])) {
|
|
1949
|
+
for (const [key, { type, expr }] of _.entries(groupMatches[field])) {
|
|
1950
|
+
switch (type) {
|
|
1951
|
+
case '$count':
|
|
1952
|
+
columns.push(sql `
|
|
1953
|
+
(
|
|
1954
|
+
SELECT COUNT(*) FROM (
|
|
1955
|
+
${_selectRelationPopulate(compiler, parent, populate, field, false)}
|
|
1956
|
+
) ${{ identifier: populate.name }}
|
|
1957
|
+
) AS ${{ identifier: `${field}.${key}` }}
|
|
1958
|
+
`);
|
|
1959
|
+
break;
|
|
1960
|
+
case '$avg':
|
|
1961
|
+
case '$sum':
|
|
1962
|
+
{
|
|
1963
|
+
const op = {
|
|
1964
|
+
'$avg': 'AVG',
|
|
1965
|
+
'$sum': 'SUM',
|
|
1966
|
+
}[type];
|
|
1967
|
+
if (!expr)
|
|
1968
|
+
throw Error('Invalid expression');
|
|
1969
|
+
const exprs = encodeTypedQueryExpression(compiler, populate, expr);
|
|
1970
|
+
const { sql: value } = (_.includes(['$avg'], type) ? _.find(exprs, e => e.type === 'number') : _.first(exprs)) ?? {};
|
|
1971
|
+
if (!value)
|
|
1972
|
+
throw Error('Invalid expression');
|
|
1973
|
+
columns.push(sql `
|
|
1974
|
+
(
|
|
1975
|
+
SELECT ${{ literal: op }}(${value}) FROM (
|
|
1976
|
+
${_selectRelationPopulate(compiler, parent, populate, field, false)}
|
|
1977
|
+
) ${{ identifier: populate.name }}
|
|
1978
|
+
) AS ${{ identifier: `${field}.${key}` }}
|
|
1979
|
+
`);
|
|
1980
|
+
}
|
|
1981
|
+
break;
|
|
1982
|
+
}
|
|
1983
|
+
}
|
|
1984
|
+
}
|
|
1985
|
+
else {
|
|
1986
|
+
columns.push(sql `
|
|
1987
|
+
ARRAY(
|
|
1988
|
+
SELECT to_jsonb(${{ identifier: populate.name }}) FROM (
|
|
1989
|
+
${_selectRelationPopulate(compiler, parent, populate, field, true)}
|
|
1990
|
+
) ${{ identifier: populate.name }}
|
|
1991
|
+
) AS ${{ identifier: field }}
|
|
1992
|
+
`);
|
|
1993
|
+
}
|
|
1994
|
+
return { columns };
|
|
1927
1995
|
}
|
|
1928
1996
|
const _local = (field) => sql `${{ identifier: parent.name }}.${{ identifier: field }}`;
|
|
1929
1997
|
const _foreign = (field) => sql `${{ identifier: populate.name }}.${{ identifier: field }}`;
|
|
1930
1998
|
const subpaths = resolveSubpaths(compiler, populate);
|
|
1931
1999
|
return {
|
|
1932
2000
|
columns: _.compact(_.flatMap(subpaths, ({ path, type }) => [
|
|
1933
|
-
sql `${{ identifier: populate.name }}.${{ identifier: path }} AS ${{ identifier: `${field}.${path}` }}
|
|
2001
|
+
...populate.groupMatches[path] ? _.map(_.keys(populate.groupMatches[path]), k => sql `${{ identifier: populate.name }}.${{ identifier: `${path}.${k}` }} AS ${{ identifier: `${field}.${path}.${k}` }}`) : [
|
|
2002
|
+
sql `${{ identifier: populate.name }}.${{ identifier: path }} AS ${{ identifier: `${field}.${path}` }}`
|
|
2003
|
+
],
|
|
1934
2004
|
isRelation(type) && sql `${{ identifier: populate.name }}.${{ identifier: `$${path}` }} AS ${{ identifier: `$${field}.${path}` }}`,
|
|
1935
2005
|
])),
|
|
1936
2006
|
join: sql `
|
|
@@ -2015,9 +2085,8 @@ const encodePopulate = (compiler, parent, remix) => {
|
|
|
2015
2085
|
parent.filter && compiler._encodeFilter(parent, parent.filter),
|
|
2016
2086
|
compiler.extraFilter && compiler._encodeFilter(parent, compiler.extraFilter(parent.className)),
|
|
2017
2087
|
]);
|
|
2018
|
-
const _populates = _.map(parent.populates, (populate, field) => selectPopulate(compiler, parent, populate, field
|
|
2088
|
+
const _populates = _.map(parent.populates, (populate, field) => selectPopulate(compiler, parent, populate, field));
|
|
2019
2089
|
const _joins = _.compact(_.map(_populates, ({ join }) => join));
|
|
2020
|
-
const _includes = _.pickBy(parent.includes, v => isPrimitive(v));
|
|
2021
2090
|
const { joins: _joins2 = [], field: _foreignField = undefined, rows = false, } = parent.foreignField ? encodeForeignField(compiler, {
|
|
2022
2091
|
className: parent.className,
|
|
2023
2092
|
name: parent.name,
|
|
@@ -2031,7 +2100,7 @@ const encodePopulate = (compiler, parent, remix) => {
|
|
|
2031
2100
|
SELECT
|
|
2032
2101
|
${{
|
|
2033
2102
|
literal: [
|
|
2034
|
-
...
|
|
2103
|
+
...compiler._selectIncludes(parent.name, parent.includes),
|
|
2035
2104
|
..._.flatMap(_populates, ({ columns: column }) => column),
|
|
2036
2105
|
..._foreignField ? [sql `${rows ? sql `ARRAY(${_foreignField})` : _foreignField} AS ${{ identifier: parent.colname }}`] : [],
|
|
2037
2106
|
], separator: ',\n'
|
|
@@ -2084,9 +2153,6 @@ const encodeFieldExpression = (compiler, parent, field, expr) => {
|
|
|
2084
2153
|
break;
|
|
2085
2154
|
return sql `${element} ${nullSafeEqual()} ${{ value: expr.value.objectId }}`;
|
|
2086
2155
|
}
|
|
2087
|
-
if (relation && _.includes(parent.countMatches, relation.colname)) {
|
|
2088
|
-
return sql `${element} ${nullSafeEqual()} ${encodeType(colname, 'number', expr.value)}`;
|
|
2089
|
-
}
|
|
2090
2156
|
return sql `${element} ${nullSafeEqual()} ${encodeValue(expr.value)}`;
|
|
2091
2157
|
}
|
|
2092
2158
|
case '$ne':
|
|
@@ -2100,9 +2166,6 @@ const encodeFieldExpression = (compiler, parent, field, expr) => {
|
|
|
2100
2166
|
break;
|
|
2101
2167
|
return sql `${element} ${nullSafeNotEqual()} ${{ value: expr.value.objectId }}`;
|
|
2102
2168
|
}
|
|
2103
|
-
if (relation && _.includes(parent.countMatches, relation.colname)) {
|
|
2104
|
-
return sql `${element} ${nullSafeNotEqual()} ${encodeType(colname, 'number', expr.value)}`;
|
|
2105
|
-
}
|
|
2106
2169
|
return sql `${element} ${nullSafeNotEqual()} ${encodeValue(expr.value)}`;
|
|
2107
2170
|
}
|
|
2108
2171
|
case '$gt':
|
|
@@ -2146,9 +2209,6 @@ const encodeFieldExpression = (compiler, parent, field, expr) => {
|
|
|
2146
2209
|
else if (!_.isString(dataType) && dataType?.type === 'pointer' && expr.value instanceof TObject && expr.value.objectId) {
|
|
2147
2210
|
return sql `${element} ${{ literal: op }} ${{ value: expr.value.objectId }}`;
|
|
2148
2211
|
}
|
|
2149
|
-
else if (relation && _.includes(parent.countMatches, relation.colname)) {
|
|
2150
|
-
return sql `${element} ${{ literal: op }} ${encodeType(colname, 'number', expr.value)}`;
|
|
2151
|
-
}
|
|
2152
2212
|
else if (!dataType) {
|
|
2153
2213
|
if (expr.value instanceof Decimal || _.isNumber(expr.value)) {
|
|
2154
2214
|
return sql `(
|
|
@@ -2339,8 +2399,10 @@ const encodeFieldExpression = (compiler, parent, field, expr) => {
|
|
|
2339
2399
|
if (dataType && _isTypeof(dataType, 'string')) {
|
|
2340
2400
|
return sql `COALESCE(length(${element}), 0) = ${{ value: expr.value }}`;
|
|
2341
2401
|
}
|
|
2342
|
-
if (relation &&
|
|
2343
|
-
|
|
2402
|
+
if (relation && parent.className && parent.groupMatches?.[colname]) {
|
|
2403
|
+
const tempName = `_populate_expr_$${compiler.nextIdx()}`;
|
|
2404
|
+
const populate = _selectRelationPopulate(compiler, { className: parent.className, name: parent.name }, relation.populate, `$${field}`, false);
|
|
2405
|
+
return sql `(SELECT COUNT(*) FROM (${populate}) AS ${{ identifier: tempName }}) = ${{ value: expr.value }}`;
|
|
2344
2406
|
}
|
|
2345
2407
|
if (dataType && _isTypeof(dataType, ['array', 'string[]', 'vector', 'relation'])) {
|
|
2346
2408
|
return sql `COALESCE(array_length(${element}, 1), 0) = ${{ value: expr.value }}`;
|
|
@@ -2363,8 +2425,10 @@ const encodeFieldExpression = (compiler, parent, field, expr) => {
|
|
|
2363
2425
|
if (dataType && _isTypeof(dataType, 'string')) {
|
|
2364
2426
|
return sql `COALESCE(length(${element}), 0) ${{ literal: expr.value ? '=' : '<>' }} 0`;
|
|
2365
2427
|
}
|
|
2366
|
-
if (relation &&
|
|
2367
|
-
|
|
2428
|
+
if (relation && parent.className && parent.groupMatches?.[colname]) {
|
|
2429
|
+
const tempName = `_populate_expr_$${compiler.nextIdx()}`;
|
|
2430
|
+
const populate = _selectRelationPopulate(compiler, { className: parent.className, name: parent.name }, relation.populate, `$${field}`, false);
|
|
2431
|
+
return sql `${{ literal: expr.value ? 'NOT EXISTS' : 'EXISTS' }}(SELECT * FROM (${populate}) AS ${{ identifier: tempName }})`;
|
|
2368
2432
|
}
|
|
2369
2433
|
if (dataType && _isTypeof(dataType, ['array', 'string[]', 'vector', 'relation'])) {
|
|
2370
2434
|
return sql `COALESCE(array_length(${element}, 1), 0) ${{ literal: expr.value ? '=' : '<>' }} 0`;
|