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
|
@@ -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()}`;
|
|
@@ -300,7 +305,11 @@ class QueryCompiler {
|
|
|
300
305
|
) AS ${{ identifier: fetchName }}
|
|
301
306
|
${!_.isEmpty(filter) ? sql `WHERE ${{ literal: _.map(filter, x => sql `(${x})`), separator: ' AND ' }}` : sql ``}
|
|
302
307
|
${_options?.sort ? _options?.sort : sql ``}
|
|
303
|
-
${!_.isEmpty(query.sort) ? sql `ORDER BY ${this._encodeSort(query.sort, {
|
|
308
|
+
${!_.isEmpty(query.sort) ? sql `ORDER BY ${this._encodeSort(query.sort, {
|
|
309
|
+
name: fetchName,
|
|
310
|
+
className: query.className,
|
|
311
|
+
groupMatches: query.groupMatches,
|
|
312
|
+
})}` : sql ``}
|
|
304
313
|
${query.limit ? sql `LIMIT ${{ literal: `${query.limit}` }}` : sql ``}
|
|
305
314
|
${query.skip ? sql `OFFSET ${{ literal: `${query.skip}` }}` : sql ``}
|
|
306
315
|
`,
|
|
@@ -405,7 +414,7 @@ class QueryCompiler {
|
|
|
405
414
|
}
|
|
406
415
|
_selectIncludes(className, includes) {
|
|
407
416
|
const _includes = _.pickBy(includes, v => _.isString(v) || (v.type !== 'pointer' && v.type !== 'relation'));
|
|
408
|
-
return _.
|
|
417
|
+
return _.flatMap(_includes, (dataType, colname) => {
|
|
409
418
|
if (!_.isString(dataType) && isPrimitive(dataType) && !_.isNil(dataType.default)) {
|
|
410
419
|
return sql `COALESCE(${{ identifier: className }}.${{ identifier: colname }}, ${{ value: dataType.default }}) AS ${{ identifier: colname }}`;
|
|
411
420
|
}
|
|
@@ -426,7 +435,7 @@ class QueryCompiler {
|
|
|
426
435
|
`)}`;
|
|
427
436
|
}
|
|
428
437
|
_selectPopulateMap(context) {
|
|
429
|
-
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));
|
|
430
439
|
}
|
|
431
440
|
insert(options, values) {
|
|
432
441
|
const _values = _.map(values, attr => ({
|
|
@@ -564,9 +573,15 @@ class SqlStorage {
|
|
|
564
573
|
const { query, values } = sql.compile(this.dialect);
|
|
565
574
|
return this._query(query, values);
|
|
566
575
|
}
|
|
567
|
-
|
|
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) {
|
|
568
582
|
const result = {};
|
|
569
583
|
for (const { path, type } of shapePaths(dataType)) {
|
|
584
|
+
const matchType = _.get(matchesType, path) ?? {};
|
|
570
585
|
if (_.isString(type)) {
|
|
571
586
|
const _value = this.dialect.decodeType(type, _.get(value, path));
|
|
572
587
|
if (!_.isNil(_value))
|
|
@@ -575,17 +590,17 @@ class SqlStorage {
|
|
|
575
590
|
else if (isPointer(type)) {
|
|
576
591
|
const _value = _.get(value, path);
|
|
577
592
|
if (_.isPlainObject(_value)) {
|
|
578
|
-
const decoded = this._decodeObject(type.target, _value);
|
|
593
|
+
const decoded = this._decodeObject(type.target, _value, matchType);
|
|
579
594
|
if (decoded.objectId)
|
|
580
595
|
_.set(result, path, decoded);
|
|
581
596
|
}
|
|
582
597
|
}
|
|
583
598
|
else if (isRelation(type)) {
|
|
584
599
|
const _value = _.get(value, path);
|
|
585
|
-
if (_.
|
|
586
|
-
_.set(result, path,
|
|
587
|
-
else if (_.
|
|
588
|
-
_.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));
|
|
589
604
|
}
|
|
590
605
|
else {
|
|
591
606
|
const _value = this.dialect.decodeType(type.type, _.get(value, path)) ?? type.default;
|
|
@@ -595,7 +610,7 @@ class SqlStorage {
|
|
|
595
610
|
}
|
|
596
611
|
return result;
|
|
597
612
|
}
|
|
598
|
-
_decodeObject(className, attrs) {
|
|
613
|
+
_decodeObject(className, attrs, matchesType) {
|
|
599
614
|
const fields = this.schema[className].fields;
|
|
600
615
|
const obj = new TObject(className);
|
|
601
616
|
const _attrs = {};
|
|
@@ -603,6 +618,7 @@ class SqlStorage {
|
|
|
603
618
|
_.set(_attrs, key, value);
|
|
604
619
|
}
|
|
605
620
|
for (const [key, value] of _.toPairs(_attrs)) {
|
|
621
|
+
const matchType = matchesType[key] ?? {};
|
|
606
622
|
const dataType = fields[key];
|
|
607
623
|
if (!dataType)
|
|
608
624
|
continue;
|
|
@@ -610,20 +626,20 @@ class SqlStorage {
|
|
|
610
626
|
obj[PVK].attributes[key] = this.dialect.decodeType(dataType, value);
|
|
611
627
|
}
|
|
612
628
|
else if (isShape(dataType)) {
|
|
613
|
-
obj[PVK].attributes[key] = this._decodeShapedObject(dataType, value);
|
|
629
|
+
obj[PVK].attributes[key] = this._decodeShapedObject(dataType, value, matchType);
|
|
614
630
|
}
|
|
615
631
|
else if (isPointer(dataType)) {
|
|
616
632
|
if (_.isPlainObject(value)) {
|
|
617
|
-
const decoded = this._decodeObject(dataType.target, value);
|
|
633
|
+
const decoded = this._decodeObject(dataType.target, value, matchType);
|
|
618
634
|
if (decoded.objectId)
|
|
619
635
|
obj[PVK].attributes[key] = decoded;
|
|
620
636
|
}
|
|
621
637
|
}
|
|
622
638
|
else if (isRelation(dataType)) {
|
|
623
|
-
if (_.
|
|
624
|
-
obj[PVK].attributes[key] =
|
|
625
|
-
else if (_.
|
|
626
|
-
obj[PVK].attributes[key] =
|
|
639
|
+
if (_.isArray(value))
|
|
640
|
+
obj[PVK].attributes[key] = value.map(x => this._decodeObject(dataType.target, x, matchType));
|
|
641
|
+
else if (_.isPlainObject(value))
|
|
642
|
+
obj[PVK].attributes[key] = this._decodeMatchTypes(value, matchType);
|
|
627
643
|
}
|
|
628
644
|
else {
|
|
629
645
|
obj[PVK].attributes[key] = this.dialect.decodeType(dataType.type, value) ?? dataType.default;
|
|
@@ -652,6 +668,18 @@ class SqlStorage {
|
|
|
652
668
|
const count = parseInt(_count);
|
|
653
669
|
return _.isFinite(count) ? count : 0;
|
|
654
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}`, accumulatorKeyTypes[expr.type]);
|
|
679
|
+
}
|
|
680
|
+
}
|
|
681
|
+
return types;
|
|
682
|
+
}
|
|
655
683
|
find(query) {
|
|
656
684
|
const self = this;
|
|
657
685
|
const compiler = self._makeCompiler(false, query.extraFilter);
|
|
@@ -659,7 +687,7 @@ class SqlStorage {
|
|
|
659
687
|
return (async function* () {
|
|
660
688
|
const objects = self.query(_query);
|
|
661
689
|
for await (const object of objects) {
|
|
662
|
-
yield self._decodeObject(query.className, object);
|
|
690
|
+
yield self._decodeObject(query.className, object, self._matchesType(query));
|
|
663
691
|
}
|
|
664
692
|
})();
|
|
665
693
|
}
|
|
@@ -672,7 +700,7 @@ class SqlStorage {
|
|
|
672
700
|
return (async function* () {
|
|
673
701
|
const objects = self.query(_query);
|
|
674
702
|
for await (const object of objects) {
|
|
675
|
-
yield self._decodeObject(query.className, object);
|
|
703
|
+
yield self._decodeObject(query.className, object, self._matchesType(query));
|
|
676
704
|
}
|
|
677
705
|
})();
|
|
678
706
|
}
|
|
@@ -686,7 +714,7 @@ class SqlStorage {
|
|
|
686
714
|
return (async function* () {
|
|
687
715
|
const objects = self.query(query);
|
|
688
716
|
for await (const { _class, ...object } of objects) {
|
|
689
|
-
yield self._decodeObject(_class, object);
|
|
717
|
+
yield self._decodeObject(_class, object, {});
|
|
690
718
|
}
|
|
691
719
|
})();
|
|
692
720
|
}
|
|
@@ -701,29 +729,29 @@ class SqlStorage {
|
|
|
701
729
|
return (async function* () {
|
|
702
730
|
const objects = self.query(_query);
|
|
703
731
|
for await (const object of objects) {
|
|
704
|
-
yield self._decodeObject(query.className, object);
|
|
732
|
+
yield self._decodeObject(query.className, object, self._matchesType(query));
|
|
705
733
|
}
|
|
706
734
|
})();
|
|
707
735
|
}
|
|
708
736
|
async insert(options, values) {
|
|
709
737
|
const compiler = this._makeCompiler(true);
|
|
710
738
|
const result = await this.query(compiler.insert(options, values));
|
|
711
|
-
return _.map(result, x => this._decodeObject(options.className, x));
|
|
739
|
+
return _.map(result, x => this._decodeObject(options.className, x, this._matchesType(options)));
|
|
712
740
|
}
|
|
713
741
|
async update(query, update) {
|
|
714
742
|
const compiler = this._makeCompiler(true, query.extraFilter);
|
|
715
743
|
const updated = await this.query(compiler.update(query, update));
|
|
716
|
-
return _.map(updated, x => this._decodeObject(query.className, x));
|
|
744
|
+
return _.map(updated, x => this._decodeObject(query.className, x, this._matchesType(query)));
|
|
717
745
|
}
|
|
718
746
|
async upsert(query, update, setOnInsert) {
|
|
719
747
|
const compiler = this._makeCompiler(true, query.extraFilter);
|
|
720
748
|
const upserted = await this.query(compiler.upsert(query, update, setOnInsert));
|
|
721
|
-
return _.map(upserted, x => this._decodeObject(query.className, x));
|
|
749
|
+
return _.map(upserted, x => this._decodeObject(query.className, x, this._matchesType(query)));
|
|
722
750
|
}
|
|
723
751
|
async delete(query) {
|
|
724
752
|
const compiler = this._makeCompiler(true, query.extraFilter);
|
|
725
753
|
const deleted = await this.query(compiler.delete(query));
|
|
726
|
-
return _.map(deleted, x => this._decodeObject(query.className, x));
|
|
754
|
+
return _.map(deleted, x => this._decodeObject(query.className, x, this._matchesType(query)));
|
|
727
755
|
}
|
|
728
756
|
}
|
|
729
757
|
|
|
@@ -769,7 +797,15 @@ const _fetchElement = (parent, colname, subpath, dataType) => {
|
|
|
769
797
|
}
|
|
770
798
|
else if (!_.isEmpty(subpath)) {
|
|
771
799
|
const _subpath = sql `${_.map(subpath, x => sql `${{ quote: x.startsWith('$') ? `$${x}` : x }}`)}`;
|
|
772
|
-
|
|
800
|
+
const match = parent.groupMatches?.[colname]?.[subpath[0]];
|
|
801
|
+
if (dataType && isRelation(dataType) && subpath.length === 1 && match) {
|
|
802
|
+
return {
|
|
803
|
+
element: sql `${{ identifier: parent.name }}.${{ identifier: `${colname}.${subpath[0]}` }}`,
|
|
804
|
+
json: false,
|
|
805
|
+
dataType: accumulatorKeyTypes[match.type],
|
|
806
|
+
};
|
|
807
|
+
}
|
|
808
|
+
else if (dataType && _isTypeof(dataType, ['array', 'string[]', 'relation'])) {
|
|
773
809
|
return {
|
|
774
810
|
element: sql `jsonb_extract_path(to_jsonb(${element}), ${_subpath})`,
|
|
775
811
|
json: true,
|
|
@@ -829,7 +865,7 @@ const _resolvePopulate = (path, populates) => {
|
|
|
829
865
|
const fetchElement = (compiler, parent, field) => {
|
|
830
866
|
if (parent.className) {
|
|
831
867
|
const { dataType, colname, subpath } = resolvePaths(compiler, parent.className, _.toPath(field));
|
|
832
|
-
const { element, json } = _fetchElement(parent, colname, subpath, dataType);
|
|
868
|
+
const { element, json, dataType: _dataType } = _fetchElement(parent, colname, subpath, dataType);
|
|
833
869
|
if (isPointer(dataType))
|
|
834
870
|
return { element: sql `${{ identifier: parent.name }}.${{ identifier: `${colname}._id` }}`, dataType };
|
|
835
871
|
const populate = isRelation(dataType) && _resolvePopulate(_.toPath(colname), parent.populates);
|
|
@@ -837,7 +873,7 @@ const fetchElement = (compiler, parent, field) => {
|
|
|
837
873
|
return { element, dataType: json ? null : dataType };
|
|
838
874
|
return {
|
|
839
875
|
element,
|
|
840
|
-
dataType: json ? null : dataType,
|
|
876
|
+
dataType: json ? null : _dataType ?? dataType,
|
|
841
877
|
relation: {
|
|
842
878
|
colname,
|
|
843
879
|
target: dataType.target,
|
|
@@ -1177,7 +1213,7 @@ const _encodeJsonValue = (value) => {
|
|
|
1177
1213
|
return sql `jsonb_build_object(${_.map(value, (v, k) => sql `${{ value: k }}, ${_encodeJsonValue(v)}`)})`;
|
|
1178
1214
|
return sql `to_jsonb(${{ value }})`;
|
|
1179
1215
|
};
|
|
1180
|
-
const
|
|
1216
|
+
const _jsonPopulateInclude = (className, colname, dataType) => {
|
|
1181
1217
|
switch (_typeof(dataType)) {
|
|
1182
1218
|
case 'decimal':
|
|
1183
1219
|
return sql `jsonb_build_object(
|
|
@@ -1892,45 +1928,83 @@ const _selectRelationPopulate = (compiler, parent, populate, field, encode) => {
|
|
|
1892
1928
|
cond = sql `${sql `(${{ quote: parent.className + '$' }} || ${_local('_id')})`} = ANY(${_foreign(populate.colname)})`;
|
|
1893
1929
|
}
|
|
1894
1930
|
return sql `
|
|
1895
|
-
SELECT ${_.compact(_.flatMap(subpaths, ({ path, type }) => [
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
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
|
+
isRelation(type) && sql `${{ identifier: populate.name }}.${{ identifier: `$${path}` }}`,
|
|
1899
1938
|
]))}
|
|
1900
1939
|
FROM ${{ identifier: populate.name }} WHERE ${cond}
|
|
1901
|
-
${!_.isEmpty(populate.sort) ? sql `ORDER BY ${compiler._encodeSort(populate.sort,
|
|
1940
|
+
${!_.isEmpty(populate.sort) ? sql `ORDER BY ${compiler._encodeSort(populate.sort, populate)}` : sql ``}
|
|
1902
1941
|
${populate.limit ? sql `LIMIT ${{ literal: `${populate.limit}` }}` : sql ``}
|
|
1903
1942
|
${populate.skip ? sql `OFFSET ${{ literal: `${populate.skip}` }}` : sql ``}
|
|
1904
1943
|
${compiler.selectLock ? compiler.isUpdate ? sql `FOR UPDATE NOWAIT` : sql `FOR SHARE NOWAIT` : sql ``}
|
|
1905
1944
|
`;
|
|
1906
1945
|
};
|
|
1907
|
-
const selectPopulate = (compiler, parent, populate, field
|
|
1946
|
+
const selectPopulate = (compiler, parent, populate, field) => {
|
|
1908
1947
|
if (populate.type === 'relation') {
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
|
|
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 };
|
|
1927
1999
|
}
|
|
1928
2000
|
const _local = (field) => sql `${{ identifier: parent.name }}.${{ identifier: field }}`;
|
|
1929
2001
|
const _foreign = (field) => sql `${{ identifier: populate.name }}.${{ identifier: field }}`;
|
|
1930
2002
|
const subpaths = resolveSubpaths(compiler, populate);
|
|
1931
2003
|
return {
|
|
1932
2004
|
columns: _.compact(_.flatMap(subpaths, ({ path, type }) => [
|
|
1933
|
-
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
|
+
],
|
|
1934
2008
|
isRelation(type) && sql `${{ identifier: populate.name }}.${{ identifier: `$${path}` }} AS ${{ identifier: `$${field}.${path}` }}`,
|
|
1935
2009
|
])),
|
|
1936
2010
|
join: sql `
|
|
@@ -2015,9 +2089,8 @@ const encodePopulate = (compiler, parent, remix) => {
|
|
|
2015
2089
|
parent.filter && compiler._encodeFilter(parent, parent.filter),
|
|
2016
2090
|
compiler.extraFilter && compiler._encodeFilter(parent, compiler.extraFilter(parent.className)),
|
|
2017
2091
|
]);
|
|
2018
|
-
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));
|
|
2019
2093
|
const _joins = _.compact(_.map(_populates, ({ join }) => join));
|
|
2020
|
-
const _includes = _.pickBy(parent.includes, v => isPrimitive(v));
|
|
2021
2094
|
const { joins: _joins2 = [], field: _foreignField = undefined, rows = false, } = parent.foreignField ? encodeForeignField(compiler, {
|
|
2022
2095
|
className: parent.className,
|
|
2023
2096
|
name: parent.name,
|
|
@@ -2031,7 +2104,7 @@ const encodePopulate = (compiler, parent, remix) => {
|
|
|
2031
2104
|
SELECT
|
|
2032
2105
|
${{
|
|
2033
2106
|
literal: [
|
|
2034
|
-
...
|
|
2107
|
+
...compiler._selectIncludes(parent.name, parent.includes),
|
|
2035
2108
|
..._.flatMap(_populates, ({ columns: column }) => column),
|
|
2036
2109
|
..._foreignField ? [sql `${rows ? sql `ARRAY(${_foreignField})` : _foreignField} AS ${{ identifier: parent.colname }}`] : [],
|
|
2037
2110
|
], separator: ',\n'
|
|
@@ -2084,9 +2157,6 @@ const encodeFieldExpression = (compiler, parent, field, expr) => {
|
|
|
2084
2157
|
break;
|
|
2085
2158
|
return sql `${element} ${nullSafeEqual()} ${{ value: expr.value.objectId }}`;
|
|
2086
2159
|
}
|
|
2087
|
-
if (relation && _.includes(parent.countMatches, relation.colname)) {
|
|
2088
|
-
return sql `${element} ${nullSafeEqual()} ${encodeType(colname, 'number', expr.value)}`;
|
|
2089
|
-
}
|
|
2090
2160
|
return sql `${element} ${nullSafeEqual()} ${encodeValue(expr.value)}`;
|
|
2091
2161
|
}
|
|
2092
2162
|
case '$ne':
|
|
@@ -2100,9 +2170,6 @@ const encodeFieldExpression = (compiler, parent, field, expr) => {
|
|
|
2100
2170
|
break;
|
|
2101
2171
|
return sql `${element} ${nullSafeNotEqual()} ${{ value: expr.value.objectId }}`;
|
|
2102
2172
|
}
|
|
2103
|
-
if (relation && _.includes(parent.countMatches, relation.colname)) {
|
|
2104
|
-
return sql `${element} ${nullSafeNotEqual()} ${encodeType(colname, 'number', expr.value)}`;
|
|
2105
|
-
}
|
|
2106
2173
|
return sql `${element} ${nullSafeNotEqual()} ${encodeValue(expr.value)}`;
|
|
2107
2174
|
}
|
|
2108
2175
|
case '$gt':
|
|
@@ -2146,9 +2213,6 @@ const encodeFieldExpression = (compiler, parent, field, expr) => {
|
|
|
2146
2213
|
else if (!_.isString(dataType) && dataType?.type === 'pointer' && expr.value instanceof TObject && expr.value.objectId) {
|
|
2147
2214
|
return sql `${element} ${{ literal: op }} ${{ value: expr.value.objectId }}`;
|
|
2148
2215
|
}
|
|
2149
|
-
else if (relation && _.includes(parent.countMatches, relation.colname)) {
|
|
2150
|
-
return sql `${element} ${{ literal: op }} ${encodeType(colname, 'number', expr.value)}`;
|
|
2151
|
-
}
|
|
2152
2216
|
else if (!dataType) {
|
|
2153
2217
|
if (expr.value instanceof Decimal || _.isNumber(expr.value)) {
|
|
2154
2218
|
return sql `(
|
|
@@ -2339,8 +2403,10 @@ const encodeFieldExpression = (compiler, parent, field, expr) => {
|
|
|
2339
2403
|
if (dataType && _isTypeof(dataType, 'string')) {
|
|
2340
2404
|
return sql `COALESCE(length(${element}), 0) = ${{ value: expr.value }}`;
|
|
2341
2405
|
}
|
|
2342
|
-
if (relation &&
|
|
2343
|
-
|
|
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 }}`;
|
|
2344
2410
|
}
|
|
2345
2411
|
if (dataType && _isTypeof(dataType, ['array', 'string[]', 'vector', 'relation'])) {
|
|
2346
2412
|
return sql `COALESCE(array_length(${element}, 1), 0) = ${{ value: expr.value }}`;
|
|
@@ -2363,8 +2429,10 @@ const encodeFieldExpression = (compiler, parent, field, expr) => {
|
|
|
2363
2429
|
if (dataType && _isTypeof(dataType, 'string')) {
|
|
2364
2430
|
return sql `COALESCE(length(${element}), 0) ${{ literal: expr.value ? '=' : '<>' }} 0`;
|
|
2365
2431
|
}
|
|
2366
|
-
if (relation &&
|
|
2367
|
-
|
|
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 }})`;
|
|
2368
2436
|
}
|
|
2369
2437
|
if (dataType && _isTypeof(dataType, ['array', 'string[]', 'vector', 'relation'])) {
|
|
2370
2438
|
return sql `COALESCE(array_length(${element}, 1), 0) ${{ literal: expr.value ? '=' : '<>' }} 0`;
|