proto.io 0.0.216 → 0.0.217
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.mjs +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 +5 -3
- package/dist/adapters/storage/progres.js +474 -111
- package/dist/adapters/storage/progres.js.map +1 -1
- package/dist/adapters/storage/progres.mjs +474 -111
- package/dist/adapters/storage/progres.mjs.map +1 -1
- package/dist/client.d.ts +3 -3
- package/dist/client.js +1 -7
- package/dist/client.js.map +1 -1
- package/dist/client.mjs +2 -2
- package/dist/client.mjs.map +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.js +3 -9
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +4 -4
- package/dist/index.mjs.map +1 -1
- package/dist/internals/{base-BO3ZP6EF.d.ts → base-CWnOBKD5.d.ts} +2 -2
- package/dist/internals/base-CWnOBKD5.d.ts.map +1 -0
- package/dist/internals/{chunk-DDkLpKXp.d.ts → chunk-CNNSQpRF.d.ts} +3 -3
- package/dist/internals/chunk-CNNSQpRF.d.ts.map +1 -0
- package/dist/internals/{index-CYhA8SU8.d.ts → index-BRIlS3mY.d.ts} +3 -9
- package/dist/internals/index-BRIlS3mY.d.ts.map +1 -0
- package/dist/internals/{index-HdMgLYtD.d.ts → index-Bs8n7Q8f.d.ts} +55 -18
- package/dist/internals/index-Bs8n7Q8f.d.ts.map +1 -0
- package/dist/internals/{index-DF2AfSGK.mjs → index-DfqABzjr.mjs} +134 -141
- package/dist/internals/index-DfqABzjr.mjs.map +1 -0
- package/dist/internals/{index-DfnPpl1I.js → index-DylUjD_1.js} +133 -146
- package/dist/internals/index-DylUjD_1.js.map +1 -0
- package/dist/internals/{validator-LNgZGT_l.mjs → validator-CEcBF4Cn.mjs} +728 -27
- package/dist/internals/validator-CEcBF4Cn.mjs.map +1 -0
- package/dist/internals/{validator-BBjOdLiT.js → validator-mcBCJP4P.js} +734 -27
- package/dist/internals/validator-mcBCJP4P.js.map +1 -0
- package/package.json +1 -1
- package/dist/internals/base-BO3ZP6EF.d.ts.map +0 -1
- package/dist/internals/chunk-DDkLpKXp.d.ts.map +0 -1
- package/dist/internals/index-CYhA8SU8.d.ts.map +0 -1
- package/dist/internals/index-DF2AfSGK.mjs.map +0 -1
- package/dist/internals/index-DfnPpl1I.js.map +0 -1
- package/dist/internals/index-HdMgLYtD.d.ts.map +0 -1
- package/dist/internals/validator-BBjOdLiT.js.map +0 -1
- package/dist/internals/validator-LNgZGT_l.mjs.map +0 -1
|
@@ -5,7 +5,7 @@ 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 { r as resolveColumn, b as resolveDataType$1, d as QueryCoditionalSelector, e as QueryFieldSelector, f as QueryExpressionSelector, g as
|
|
8
|
+
import { r as resolveColumn, b as resolveDataType$1, d as QueryCoditionalSelector, e as QueryFieldSelector, f as QueryExpressionSelector, g as QueryArrayExpression, h as QueryValueExpression, i as QueryKeyExpression, j as QueryCoditionalExpression, k as QueryComparisonExpression, l as QueryNotExpression, m as QueryDistanceExpression, n as QueryZeroParamExpression, o as QueryUnaryExpression, p as QueryBinaryExpression, q as QueryListExpression, s as QueryTernaryExpression, t as QueryCondExpression, Q as QueryValidator, u as QueryZeroParamAccumulator, v as QueryUnaryAccumulator, w as QueryPercentileAccumulator, c as QuerySelector, F as FieldSelectorExpression } from '../../internals/validator-CEcBF4Cn.mjs';
|
|
9
9
|
import '@o2ter/crypto-js';
|
|
10
10
|
import { c as PROTO_EVENT } from '../../internals/const-Dkp7Nsv5.mjs';
|
|
11
11
|
import { g as generateId } from '../../internals/random-CYjWDvex.mjs';
|
|
@@ -409,7 +409,7 @@ class QueryCompiler {
|
|
|
409
409
|
return this.dialect.encodeFieldExpression(this, parent, filter.field, filter.expr);
|
|
410
410
|
}
|
|
411
411
|
if (filter instanceof QueryExpressionSelector) {
|
|
412
|
-
return this.dialect.
|
|
412
|
+
return this.dialect.encodeBooleanExpression(this, parent, filter.expr);
|
|
413
413
|
}
|
|
414
414
|
}
|
|
415
415
|
_selectIncludes(className, includes) {
|
|
@@ -424,7 +424,7 @@ class QueryCompiler {
|
|
|
424
424
|
_encodeSort(sort, parent) {
|
|
425
425
|
if (_.isArray(sort)) {
|
|
426
426
|
return sql `${_.map(sort, ({ expr, order }) => {
|
|
427
|
-
const _expr = this.dialect.
|
|
427
|
+
const _expr = this.dialect.encodeSortExpression(this, parent, expr);
|
|
428
428
|
if (!_expr)
|
|
429
429
|
throw Error('Invalid expression');
|
|
430
430
|
return sql `${_expr} ${{ literal: order === 1 ? 'ASC' : 'DESC' }}`;
|
|
@@ -704,7 +704,7 @@ const decodeType = (type, value) => {
|
|
|
704
704
|
};
|
|
705
705
|
|
|
706
706
|
//
|
|
707
|
-
//
|
|
707
|
+
// types.ts
|
|
708
708
|
//
|
|
709
709
|
// The MIT License
|
|
710
710
|
// Copyright (c) 2021 - 2025 O2ter Limited. All rights reserved.
|
|
@@ -727,7 +727,8 @@ const decodeType = (type, value) => {
|
|
|
727
727
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
728
728
|
// THE SOFTWARE.
|
|
729
729
|
//
|
|
730
|
-
const
|
|
730
|
+
const _PrimitiveValue = ['boolean', 'number', 'decimal', 'string', 'date'];
|
|
731
|
+
const isArrayExpr = (expr) => {
|
|
731
732
|
if (expr instanceof QueryArrayExpression)
|
|
732
733
|
return true;
|
|
733
734
|
if (expr instanceof QueryValueExpression)
|
|
@@ -741,62 +742,428 @@ const arrayLength = (expr) => {
|
|
|
741
742
|
return _.isArray(expr.value) ? expr.value.length : 0;
|
|
742
743
|
return 0;
|
|
743
744
|
};
|
|
744
|
-
const
|
|
745
|
+
const mapExpr = (expr, callback) => {
|
|
745
746
|
if (expr instanceof QueryArrayExpression)
|
|
746
747
|
return _.map(expr.exprs, x => callback(x));
|
|
747
748
|
if (expr instanceof QueryValueExpression)
|
|
748
749
|
return _.isArray(expr.value) ? _.map(expr.value, x => callback(new QueryValueExpression(x))) : [];
|
|
749
750
|
return [];
|
|
750
751
|
};
|
|
751
|
-
const
|
|
752
|
+
const zipExpr = (lhs, rhs) => {
|
|
753
|
+
const result = [];
|
|
754
|
+
for (const [l, r] of _.zip(lhs, rhs)) {
|
|
755
|
+
if (!l || !r)
|
|
756
|
+
return;
|
|
757
|
+
if (l.type === r.type)
|
|
758
|
+
result.push([l, r]);
|
|
759
|
+
else if (l.type === 'number' && r.type === 'decimal')
|
|
760
|
+
result.push([l, { type: 'decimal', sql: sql `CAST((${r.sql}) AS DECIMAL)` }]);
|
|
761
|
+
else if (l.type === 'decimal' && r.type === 'number')
|
|
762
|
+
result.push([{ type: 'decimal', sql: sql `CAST((${l.sql}) AS DECIMAL)` }, r]);
|
|
763
|
+
else
|
|
764
|
+
return;
|
|
765
|
+
}
|
|
766
|
+
return result;
|
|
767
|
+
};
|
|
768
|
+
const typeCastExpr = (expr, type) => {
|
|
769
|
+
if (!expr)
|
|
770
|
+
return;
|
|
771
|
+
if (expr.type === type)
|
|
772
|
+
return expr;
|
|
773
|
+
if (expr.type === 'number' && type === 'decimal')
|
|
774
|
+
return { type, sql: sql `CAST((${expr.sql}) AS DECIMAL)` };
|
|
775
|
+
if (expr.type === 'decimal' && type === 'number')
|
|
776
|
+
return { type, sql: sql `CAST((${expr.sql}) AS DOUBLE PRECISION)` };
|
|
777
|
+
};
|
|
778
|
+
|
|
779
|
+
//
|
|
780
|
+
// vector.ts
|
|
781
|
+
//
|
|
782
|
+
// The MIT License
|
|
783
|
+
// Copyright (c) 2021 - 2025 O2ter Limited. All rights reserved.
|
|
784
|
+
//
|
|
785
|
+
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
786
|
+
// of this software and associated documentation files (the "Software"), to deal
|
|
787
|
+
// in the Software without restriction, including without limitation the rights
|
|
788
|
+
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
789
|
+
// copies of the Software, and to permit persons to whom the Software is
|
|
790
|
+
// furnished to do so, subject to the following conditions:
|
|
791
|
+
//
|
|
792
|
+
// The above copyright notice and this permission notice shall be included in
|
|
793
|
+
// all copies or substantial portions of the Software.
|
|
794
|
+
//
|
|
795
|
+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
796
|
+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
797
|
+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
798
|
+
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
799
|
+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
800
|
+
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
801
|
+
// THE SOFTWARE.
|
|
802
|
+
//
|
|
803
|
+
const encodeVectorExpression = (compiler, parent, exprs) => {
|
|
804
|
+
if (exprs.length === 1) {
|
|
805
|
+
const [expr] = exprs;
|
|
806
|
+
if (expr instanceof QueryKeyExpression) {
|
|
807
|
+
const { element, dataType } = fetchElement(compiler, parent, expr.key);
|
|
808
|
+
if (!dataType || !isVector(dataType))
|
|
809
|
+
throw Error('Invalid expression');
|
|
810
|
+
return { sql: element, dimension: dataType.dimension };
|
|
811
|
+
}
|
|
812
|
+
if (expr instanceof QueryValueExpression) {
|
|
813
|
+
if (!_.isArray(expr.value) || !_.every(expr.value, x => _.isFinite(x)))
|
|
814
|
+
throw Error('Invalid expression');
|
|
815
|
+
return { sql: sql `${{ value: expr.value }}::DOUBLE PRECISION[]`, dimension: expr.value.length };
|
|
816
|
+
}
|
|
817
|
+
}
|
|
818
|
+
const result = _.compact(_.map(exprs, x => typeCastExpr(encodeTypedQueryExpression(compiler, parent, x), 'number')?.sql));
|
|
819
|
+
if (result.length !== exprs.length)
|
|
820
|
+
throw Error('Invalid expression');
|
|
821
|
+
return { sql: sql `ARRAY[${_.map(result, x => sql `COALESCE(${x}, 0)`)}]`, dimension: result.length };
|
|
822
|
+
};
|
|
823
|
+
const encodeDistanceQueryExpression = (compiler, parent, expr) => {
|
|
824
|
+
const { sql: left, dimension: d1 } = encodeVectorExpression(compiler, parent, expr.left);
|
|
825
|
+
const { sql: right, dimension: d2 } = encodeVectorExpression(compiler, parent, expr.right);
|
|
826
|
+
if (d1 !== d2)
|
|
827
|
+
throw Error('Invalid expression');
|
|
828
|
+
const operatorMap = {
|
|
829
|
+
'$distance': sql `<->`,
|
|
830
|
+
'$innerProduct': sql `<#>`,
|
|
831
|
+
'$negInnerProduct': sql `<#>`,
|
|
832
|
+
'$cosineDistance': sql `<=>`,
|
|
833
|
+
'$rectilinearDistance': sql `<+>`,
|
|
834
|
+
};
|
|
835
|
+
const _expr = sql `
|
|
836
|
+
CAST(
|
|
837
|
+
${left} AS VECTOR(${{ literal: `${d1}` }})
|
|
838
|
+
)
|
|
839
|
+
${operatorMap[expr.type]}
|
|
840
|
+
CAST(
|
|
841
|
+
${right} AS VECTOR(${{ literal: `${d2}` }})
|
|
842
|
+
)
|
|
843
|
+
`;
|
|
844
|
+
return expr.type === '$innerProduct' ? sql `-1 * (${_expr})` : _expr;
|
|
845
|
+
};
|
|
846
|
+
|
|
847
|
+
//
|
|
848
|
+
// index.ts
|
|
849
|
+
//
|
|
850
|
+
// The MIT License
|
|
851
|
+
// Copyright (c) 2021 - 2025 O2ter Limited. All rights reserved.
|
|
852
|
+
//
|
|
853
|
+
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
854
|
+
// of this software and associated documentation files (the "Software"), to deal
|
|
855
|
+
// in the Software without restriction, including without limitation the rights
|
|
856
|
+
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
857
|
+
// copies of the Software, and to permit persons to whom the Software is
|
|
858
|
+
// furnished to do so, subject to the following conditions:
|
|
859
|
+
//
|
|
860
|
+
// The above copyright notice and this permission notice shall be included in
|
|
861
|
+
// all copies or substantial portions of the Software.
|
|
862
|
+
//
|
|
863
|
+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
864
|
+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
865
|
+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
866
|
+
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
867
|
+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
868
|
+
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
869
|
+
// THE SOFTWARE.
|
|
870
|
+
//
|
|
752
871
|
const encodeTypedQueryExpression = (compiler, parent, expr) => {
|
|
753
872
|
if (expr instanceof QueryKeyExpression) {
|
|
754
873
|
const { element, dataType } = fetchElement(compiler, parent, expr.key);
|
|
755
874
|
const _dataType = dataType ? _typeof(dataType) : null;
|
|
756
|
-
if (_dataType
|
|
757
|
-
return
|
|
758
|
-
|
|
759
|
-
{ type: 'decimal', sql: sql `CAST((${element}) AS DECIMAL)` },
|
|
760
|
-
];
|
|
761
|
-
}
|
|
762
|
-
else if (_dataType === 'decimal') {
|
|
763
|
-
return [
|
|
764
|
-
{ type: 'decimal', sql: element },
|
|
765
|
-
{ type: 'number', sql: element },
|
|
766
|
-
];
|
|
767
|
-
}
|
|
768
|
-
else if (_dataType && _PrimitiveValue.includes(_dataType)) {
|
|
769
|
-
return [{ type: _dataType, sql: element }];
|
|
770
|
-
}
|
|
875
|
+
if (!_dataType || !_PrimitiveValue.includes(_dataType))
|
|
876
|
+
return;
|
|
877
|
+
return { type: _dataType, sql: element };
|
|
771
878
|
}
|
|
772
879
|
if (expr instanceof QueryValueExpression) {
|
|
773
880
|
if (_.isBoolean(expr.value))
|
|
774
|
-
return
|
|
881
|
+
return { type: 'boolean', sql: sql `${{ value: expr.value }}` };
|
|
775
882
|
if (_.isNumber(expr.value))
|
|
776
|
-
return
|
|
777
|
-
{ type: 'number', sql: sql `${{ value: expr.value }}` },
|
|
778
|
-
{ type: 'decimal', sql: sql `CAST(${{ quote: (new Decimal(expr.value)).toString() }} AS DECIMAL)` },
|
|
779
|
-
];
|
|
883
|
+
return { type: 'number', sql: sql `${{ value: expr.value }}` };
|
|
780
884
|
if (expr.value instanceof Decimal)
|
|
781
|
-
return
|
|
782
|
-
{ type: 'decimal', sql: sql `CAST(${{ quote: expr.value.toString() }} AS DECIMAL)` },
|
|
783
|
-
{ type: 'number', sql: sql `${{ value: expr.value.toNumber() }}` },
|
|
784
|
-
];
|
|
885
|
+
return { type: 'decimal', sql: sql `CAST(${{ quote: expr.value.toString() }} AS DECIMAL)` };
|
|
785
886
|
if (_.isString(expr.value))
|
|
786
|
-
return
|
|
887
|
+
return { type: 'string', sql: sql `${{ value: expr.value }}` };
|
|
787
888
|
if (_.isDate(expr.value))
|
|
788
|
-
return
|
|
889
|
+
return { type: 'date', sql: sql `${{ value: expr.value }}` };
|
|
789
890
|
}
|
|
790
891
|
if (expr instanceof QueryCoditionalExpression ||
|
|
791
892
|
expr instanceof QueryComparisonExpression ||
|
|
792
893
|
expr instanceof QueryNotExpression) {
|
|
793
894
|
const value = encodeBooleanExpression(compiler, parent, expr);
|
|
794
895
|
if (value)
|
|
795
|
-
return
|
|
896
|
+
return { type: 'boolean', sql: value };
|
|
796
897
|
}
|
|
797
898
|
if (expr instanceof QueryDistanceExpression) {
|
|
798
899
|
const value = encodeDistanceQueryExpression(compiler, parent, expr);
|
|
799
|
-
return
|
|
900
|
+
return { type: 'number', sql: value };
|
|
901
|
+
}
|
|
902
|
+
if (expr instanceof QueryZeroParamExpression) {
|
|
903
|
+
switch (expr.type) {
|
|
904
|
+
case '$rand': return { type: 'number', sql: sql `RANDOM()` };
|
|
905
|
+
case '$now': return { type: 'date', sql: sql `CAST(NOW() AS TIMESTAMP(3) WITH TIME ZONE)` };
|
|
906
|
+
}
|
|
907
|
+
}
|
|
908
|
+
if (expr instanceof QueryUnaryExpression) {
|
|
909
|
+
const value = encodeTypedQueryExpression(compiler, parent, expr.expr);
|
|
910
|
+
if (!value)
|
|
911
|
+
return;
|
|
912
|
+
switch (expr.type) {
|
|
913
|
+
case '$abs':
|
|
914
|
+
case '$neg':
|
|
915
|
+
case '$sqrt':
|
|
916
|
+
case '$cbrt':
|
|
917
|
+
case '$ceil':
|
|
918
|
+
case '$floor':
|
|
919
|
+
case '$round':
|
|
920
|
+
case '$exp':
|
|
921
|
+
case '$ln':
|
|
922
|
+
case '$log10':
|
|
923
|
+
case '$sin':
|
|
924
|
+
case '$cos':
|
|
925
|
+
case '$tan':
|
|
926
|
+
case '$asin':
|
|
927
|
+
case '$acos':
|
|
928
|
+
case '$atan':
|
|
929
|
+
case '$asinh':
|
|
930
|
+
case '$acosh':
|
|
931
|
+
case '$atanh':
|
|
932
|
+
case '$sinh':
|
|
933
|
+
case '$cosh':
|
|
934
|
+
case '$tanh':
|
|
935
|
+
case '$degrees':
|
|
936
|
+
case '$radians':
|
|
937
|
+
case '$sign':
|
|
938
|
+
{
|
|
939
|
+
const op = {
|
|
940
|
+
'$abs': 'ABS',
|
|
941
|
+
'$neg': '-',
|
|
942
|
+
'$sqrt': 'SQRT',
|
|
943
|
+
'$cbrt': 'CBRT',
|
|
944
|
+
'$ceil': 'CEIL',
|
|
945
|
+
'$floor': 'FLOOR',
|
|
946
|
+
'$round': 'ROUND',
|
|
947
|
+
'$exp': 'EXP',
|
|
948
|
+
'$ln': 'LN',
|
|
949
|
+
'$log10': 'LOG10',
|
|
950
|
+
'$sin': 'SIN',
|
|
951
|
+
'$cos': 'COS',
|
|
952
|
+
'$tan': 'TAN',
|
|
953
|
+
'$asin': 'ASIN',
|
|
954
|
+
'$acos': 'ACOS',
|
|
955
|
+
'$atan': 'ATAN',
|
|
956
|
+
'$asinh': 'ASINH',
|
|
957
|
+
'$acosh': 'ACOSH',
|
|
958
|
+
'$atanh': 'ATANH',
|
|
959
|
+
'$sinh': 'SINH',
|
|
960
|
+
'$cosh': 'COSH',
|
|
961
|
+
'$tanh': 'TANH',
|
|
962
|
+
'$degrees': 'DEGREES',
|
|
963
|
+
'$radians': 'RADIANS',
|
|
964
|
+
'$sign': 'SIGN',
|
|
965
|
+
}[expr.type];
|
|
966
|
+
if (!_.includes(['number', 'decimal'], value.type))
|
|
967
|
+
return;
|
|
968
|
+
return { type: 'number', sql: sql `${{ literal: op }}(${value.sql})` };
|
|
969
|
+
}
|
|
970
|
+
case '$log2':
|
|
971
|
+
if (!_.includes(['number', 'decimal'], value.type))
|
|
972
|
+
return;
|
|
973
|
+
return { type: value.type, sql: sql `(LOG(${value.sql}) / LOG(2))` };
|
|
974
|
+
case '$size':
|
|
975
|
+
if (!_.includes(['string', 'string[]', 'array'], value.type))
|
|
976
|
+
return;
|
|
977
|
+
return { type: 'number', sql: sql `LENGTH(${value.sql})` };
|
|
978
|
+
case '$lower':
|
|
979
|
+
case '$upper':
|
|
980
|
+
{
|
|
981
|
+
const op = {
|
|
982
|
+
'$lower': 'LOWER',
|
|
983
|
+
'$upper': 'UPPER',
|
|
984
|
+
}[expr.type];
|
|
985
|
+
if (value.type !== 'string')
|
|
986
|
+
return;
|
|
987
|
+
return { type: 'string', sql: sql `${{ literal: op }}(${value.sql})` };
|
|
988
|
+
}
|
|
989
|
+
}
|
|
990
|
+
}
|
|
991
|
+
if (expr instanceof QueryBinaryExpression) {
|
|
992
|
+
const left = encodeTypedQueryExpression(compiler, parent, expr.left);
|
|
993
|
+
const right = encodeTypedQueryExpression(compiler, parent, expr.right);
|
|
994
|
+
if (!left || !right)
|
|
995
|
+
return;
|
|
996
|
+
switch (expr.type) {
|
|
997
|
+
case '$divide':
|
|
998
|
+
case '$subtract':
|
|
999
|
+
{
|
|
1000
|
+
const op = {
|
|
1001
|
+
'$divide': '/',
|
|
1002
|
+
'$subtract': '-',
|
|
1003
|
+
}[expr.type];
|
|
1004
|
+
if (left.type === right.type) {
|
|
1005
|
+
return { type: left.type, sql: sql `(${left.sql}) ${{ literal: op }} (${right.sql})` };
|
|
1006
|
+
}
|
|
1007
|
+
if (left.type === 'decimal' && right.type === 'number') {
|
|
1008
|
+
return { type: 'decimal', sql: sql `CAST((${left.sql}) AS DECIMAL) ${{ literal: op }} (${right.sql})` };
|
|
1009
|
+
}
|
|
1010
|
+
if (left.type === 'number' && right.type === 'decimal') {
|
|
1011
|
+
return { type: 'decimal', sql: sql `(${left.sql}) ${{ literal: op }} CAST((${right.sql}) AS DECIMAL)` };
|
|
1012
|
+
}
|
|
1013
|
+
}
|
|
1014
|
+
break;
|
|
1015
|
+
case '$log':
|
|
1016
|
+
{
|
|
1017
|
+
if (left.type === right.type) {
|
|
1018
|
+
return { type: left.type, sql: sql `(LOG(${left.sql}) / LOG(${right.sql}))` };
|
|
1019
|
+
}
|
|
1020
|
+
if (left.type === 'decimal' && right.type === 'number') {
|
|
1021
|
+
return { type: 'decimal', sql: sql `(LOG(${left.sql}) / LOG(CAST((${right.sql}) AS DECIMAL)))` };
|
|
1022
|
+
}
|
|
1023
|
+
if (left.type === 'number' && right.type === 'decimal') {
|
|
1024
|
+
return { type: 'decimal', sql: sql `(LOG(CAST((${left.sql}) AS DECIMAL) / LOG(${right.sql}))` };
|
|
1025
|
+
}
|
|
1026
|
+
}
|
|
1027
|
+
break;
|
|
1028
|
+
case '$pow':
|
|
1029
|
+
case '$atan2':
|
|
1030
|
+
{
|
|
1031
|
+
const op = {
|
|
1032
|
+
'$pow': 'POWER',
|
|
1033
|
+
'$atan2': 'ATAN2',
|
|
1034
|
+
}[expr.type];
|
|
1035
|
+
if (left.type === right.type) {
|
|
1036
|
+
return { type: left.type, sql: sql `${{ literal: op }}((${left.sql}), (${right.sql}))` };
|
|
1037
|
+
}
|
|
1038
|
+
if (left.type === 'decimal' && right.type === 'number') {
|
|
1039
|
+
return { type: 'decimal', sql: sql `${{ literal: op }}((${left.sql}), CAST((${right.sql}) AS DECIMAL))` };
|
|
1040
|
+
}
|
|
1041
|
+
if (left.type === 'number' && right.type === 'decimal') {
|
|
1042
|
+
return { type: 'decimal', sql: sql `${{ literal: op }}(CAST((${left.sql}) AS DECIMAL), (${right.sql}))` };
|
|
1043
|
+
}
|
|
1044
|
+
}
|
|
1045
|
+
break;
|
|
1046
|
+
case '$trim':
|
|
1047
|
+
case '$ltrim':
|
|
1048
|
+
case '$rtrim':
|
|
1049
|
+
{
|
|
1050
|
+
const op = {
|
|
1051
|
+
'$trim': 'TRIM',
|
|
1052
|
+
'$ltrim': 'LTRIM',
|
|
1053
|
+
'$rtrim': 'RTRIM',
|
|
1054
|
+
}[expr.type];
|
|
1055
|
+
if (left?.type !== 'string' || right?.type !== 'string')
|
|
1056
|
+
return;
|
|
1057
|
+
return { type: 'string', sql: sql `${{ literal: op }}(${left.sql}, ${right.sql})` };
|
|
1058
|
+
}
|
|
1059
|
+
case '$first':
|
|
1060
|
+
case '$last':
|
|
1061
|
+
{
|
|
1062
|
+
if (!_.includes(['number', 'decimal'], right.type))
|
|
1063
|
+
return;
|
|
1064
|
+
if (left?.type === 'string') {
|
|
1065
|
+
const op = {
|
|
1066
|
+
'$first': 'LEFT',
|
|
1067
|
+
'$last': 'RIGHT',
|
|
1068
|
+
}[expr.type];
|
|
1069
|
+
return { type: 'string', sql: sql `${{ literal: op }}(${left.sql}, ${right.sql})` };
|
|
1070
|
+
}
|
|
1071
|
+
}
|
|
1072
|
+
break;
|
|
1073
|
+
case '$ldrop':
|
|
1074
|
+
case '$rdrop':
|
|
1075
|
+
{
|
|
1076
|
+
if (!_.includes(['number', 'decimal'], right.type))
|
|
1077
|
+
return;
|
|
1078
|
+
if (left?.type === 'string') {
|
|
1079
|
+
const op = {
|
|
1080
|
+
'$ldrop': 'RIGHT',
|
|
1081
|
+
'$rdrop': 'LEFT',
|
|
1082
|
+
}[expr.type];
|
|
1083
|
+
return { type: 'string', sql: sql `${{ literal: op }}(${left.sql}, -(${right.sql}))` };
|
|
1084
|
+
}
|
|
1085
|
+
}
|
|
1086
|
+
break;
|
|
1087
|
+
}
|
|
1088
|
+
}
|
|
1089
|
+
if (expr instanceof QueryListExpression) {
|
|
1090
|
+
const values = _.compact(_.map(expr.exprs, x => encodeTypedQueryExpression(compiler, parent, x)));
|
|
1091
|
+
if (values.length !== expr.exprs.length)
|
|
1092
|
+
return;
|
|
1093
|
+
switch (expr.type) {
|
|
1094
|
+
case '$add':
|
|
1095
|
+
case '$multiply':
|
|
1096
|
+
{
|
|
1097
|
+
const op = {
|
|
1098
|
+
'$add': '+',
|
|
1099
|
+
'$multiply': '*',
|
|
1100
|
+
}[expr.type];
|
|
1101
|
+
if (_.every(values, x => x.type === 'number')) {
|
|
1102
|
+
return { type: 'number', sql: sql `${{ literal: _.map(values, x => x.sql), separator: ` ${op} ` }}` };
|
|
1103
|
+
}
|
|
1104
|
+
if (_.every(values, x => x.type === 'number' || x.type === 'decimal')) {
|
|
1105
|
+
return { type: 'decimal', sql: sql `${{ literal: _.map(values, x => x.type === 'decimal' ? x.sql : sql `CAST((${x.sql}) AS DECIMAL)`), separator: ` ${op} ` }}` };
|
|
1106
|
+
}
|
|
1107
|
+
}
|
|
1108
|
+
break;
|
|
1109
|
+
case '$ifNull':
|
|
1110
|
+
{
|
|
1111
|
+
const type = values[0].type;
|
|
1112
|
+
if (_.every(values, x => x.type === type)) {
|
|
1113
|
+
return { type, sql: sql `COALESCE(${{ literal: _.map(values, x => x.sql) }})` };
|
|
1114
|
+
}
|
|
1115
|
+
}
|
|
1116
|
+
break;
|
|
1117
|
+
case '$concat':
|
|
1118
|
+
{
|
|
1119
|
+
if (_.every(values, x => x.type === 'string')) {
|
|
1120
|
+
return { type: 'string', sql: sql `CONCAT(${{ literal: _.map(values, x => x.sql) }})` };
|
|
1121
|
+
}
|
|
1122
|
+
}
|
|
1123
|
+
break;
|
|
1124
|
+
}
|
|
1125
|
+
}
|
|
1126
|
+
if (expr instanceof QueryTernaryExpression) {
|
|
1127
|
+
const first = encodeTypedQueryExpression(compiler, parent, expr.first);
|
|
1128
|
+
const second = encodeTypedQueryExpression(compiler, parent, expr.second);
|
|
1129
|
+
const last = encodeTypedQueryExpression(compiler, parent, expr.last);
|
|
1130
|
+
if (!first || !second || !last)
|
|
1131
|
+
return;
|
|
1132
|
+
switch (expr.type) {
|
|
1133
|
+
case '$lpad':
|
|
1134
|
+
case '$rpad':
|
|
1135
|
+
{
|
|
1136
|
+
const op = {
|
|
1137
|
+
'$lpad': 'LPAD',
|
|
1138
|
+
'$rpad': 'RPAD',
|
|
1139
|
+
}[expr.type];
|
|
1140
|
+
if (first?.type !== 'string' || last?.type !== 'string')
|
|
1141
|
+
return;
|
|
1142
|
+
if (!_.includes(['number', 'decimal'], second.type))
|
|
1143
|
+
return;
|
|
1144
|
+
return { type: 'string', sql: sql `${{ literal: op }}(${first.sql}, ${second.sql}, ${last.sql})` };
|
|
1145
|
+
}
|
|
1146
|
+
}
|
|
1147
|
+
}
|
|
1148
|
+
if (expr instanceof QueryCondExpression) {
|
|
1149
|
+
const branches = _.flatMap(_.map(expr.branch, x => ({
|
|
1150
|
+
case: encodeTypedQueryExpression(compiler, parent, x.case),
|
|
1151
|
+
then: encodeTypedQueryExpression(compiler, parent, x.then),
|
|
1152
|
+
})), x => x.case && x.then ? ({ case: x.case, then: x.then }) : []);
|
|
1153
|
+
if (branches.length !== expr.branch.length)
|
|
1154
|
+
return;
|
|
1155
|
+
const defaultCase = encodeTypedQueryExpression(compiler, parent, expr.default);
|
|
1156
|
+
if (!defaultCase)
|
|
1157
|
+
return;
|
|
1158
|
+
if (!_.every(branches, x => x.case.type === 'boolean' && x.then.type === defaultCase.type))
|
|
1159
|
+
return;
|
|
1160
|
+
return {
|
|
1161
|
+
type: defaultCase.type,
|
|
1162
|
+
sql: sql `CASE ${{
|
|
1163
|
+
literal: _.map(branches, x => sql `WHEN (${x.case.sql}) THEN (${x.then.sql})`),
|
|
1164
|
+
separator: ' '
|
|
1165
|
+
}} ELSE (${defaultCase.sql}) END`,
|
|
1166
|
+
};
|
|
800
1167
|
}
|
|
801
1168
|
};
|
|
802
1169
|
const encodeJsonQueryExpression = (compiler, parent, expr) => {
|
|
@@ -822,57 +1189,19 @@ const encodeJsonQueryExpression = (compiler, parent, expr) => {
|
|
|
822
1189
|
if (expr instanceof QueryArrayExpression) {
|
|
823
1190
|
return sql `jsonb_build_array(${_.map(expr.exprs, x => encodeJsonQueryExpression(compiler, parent, x))})`;
|
|
824
1191
|
}
|
|
825
|
-
const
|
|
826
|
-
if (!
|
|
1192
|
+
const typed = encodeTypedQueryExpression(compiler, parent, expr);
|
|
1193
|
+
if (!typed)
|
|
827
1194
|
throw Error('Invalid expression');
|
|
828
|
-
|
|
829
|
-
}
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
return { sql: element, dimension: dataType.dimension };
|
|
838
|
-
}
|
|
839
|
-
if (expr instanceof QueryValueExpression) {
|
|
840
|
-
if (!_.isArray(expr.value) || !_.every(expr.value, x => _.isFinite(x)))
|
|
841
|
-
throw Error('Invalid expression');
|
|
842
|
-
return { sql: sql `${{ value: expr.value }}::DOUBLE PRECISION[]`, dimension: expr.value.length };
|
|
843
|
-
}
|
|
1195
|
+
switch (typed.type) {
|
|
1196
|
+
case 'boolean': return sql `to_jsonb(${typed.sql})`;
|
|
1197
|
+
case 'number': return sql `to_jsonb(${typed.sql})`;
|
|
1198
|
+
case 'decimal': return sql `jsonb_build_object('$decimal', CAST(${typed.sql} AS TEXT))`;
|
|
1199
|
+
case 'string': return sql `to_jsonb(${typed.sql})`;
|
|
1200
|
+
case 'date': return sql `jsonb_build_object(
|
|
1201
|
+
'$date', to_char(${typed.sql} AT TIME ZONE 'UTC', 'YYYY-MM-DD"T"HH24:MI:SS.MS"Z"')
|
|
1202
|
+
)`;
|
|
1203
|
+
default: throw Error('Invalid expression');
|
|
844
1204
|
}
|
|
845
|
-
const result = _.map(exprs, x => _.find(encodeTypedQueryExpression(compiler, parent, x), e => e.type === 'number')?.sql);
|
|
846
|
-
if (_.some(result, x => _.isNil(x)))
|
|
847
|
-
throw Error('Invalid expression');
|
|
848
|
-
return { sql: sql `ARRAY[${_.map(result, x => sql `COALESCE(${x}, 0)`)}]`, dimension: result.length };
|
|
849
|
-
};
|
|
850
|
-
const encodeDistanceQueryExpression = (compiler, parent, expr) => {
|
|
851
|
-
const { sql: left, dimension: d1 } = encodeVectorExpression(compiler, parent, expr.left);
|
|
852
|
-
const { sql: right, dimension: d2 } = encodeVectorExpression(compiler, parent, expr.right);
|
|
853
|
-
if (d1 !== d2)
|
|
854
|
-
throw Error('Invalid expression');
|
|
855
|
-
const operatorMap = {
|
|
856
|
-
'$distance': sql `<->`,
|
|
857
|
-
'$innerProduct': sql `<#>`,
|
|
858
|
-
'$negInnerProduct': sql `<#>`,
|
|
859
|
-
'$cosineDistance': sql `<=>`,
|
|
860
|
-
'$rectilinearDistance': sql `<+>`,
|
|
861
|
-
};
|
|
862
|
-
const _expr = sql `
|
|
863
|
-
CAST(
|
|
864
|
-
${left} AS VECTOR(${{ literal: `${d1}` }})
|
|
865
|
-
)
|
|
866
|
-
${operatorMap[expr.type]}
|
|
867
|
-
CAST(
|
|
868
|
-
${right} AS VECTOR(${{ literal: `${d2}` }})
|
|
869
|
-
)
|
|
870
|
-
`;
|
|
871
|
-
return expr.type === '$innerProduct' ? sql `-1 * (${_expr})` : _expr;
|
|
872
|
-
};
|
|
873
|
-
const matchType = (first, second) => {
|
|
874
|
-
const found = _.find(first, l => _.some(second, r => l.type === r.type));
|
|
875
|
-
return found ? [found, _.find(second, r => r.type === found.type)] : undefined;
|
|
876
1205
|
};
|
|
877
1206
|
const encodeBooleanExpression = (compiler, parent, expr) => {
|
|
878
1207
|
if (expr instanceof QueryCoditionalExpression) {
|
|
@@ -894,23 +1223,29 @@ const encodeBooleanExpression = (compiler, parent, expr) => {
|
|
|
894
1223
|
'$lt': sql `<`,
|
|
895
1224
|
'$lte': sql `<=`,
|
|
896
1225
|
};
|
|
897
|
-
if (
|
|
898
|
-
|
|
1226
|
+
if (isArrayExpr(expr.left) &&
|
|
1227
|
+
isArrayExpr(expr.right) &&
|
|
899
1228
|
arrayLength(expr.left) === arrayLength(expr.right)) {
|
|
900
|
-
const _left =
|
|
901
|
-
const _right =
|
|
902
|
-
const
|
|
903
|
-
if (
|
|
904
|
-
const [l, r] = _.unzip(
|
|
1229
|
+
const _left = mapExpr(expr.left, x => encodeTypedQueryExpression(compiler, parent, x));
|
|
1230
|
+
const _right = mapExpr(expr.right, x => encodeTypedQueryExpression(compiler, parent, x));
|
|
1231
|
+
const zipped = zipExpr(_left, _right) ?? [];
|
|
1232
|
+
if (_left.length === zipped.length) {
|
|
1233
|
+
const [l, r] = _.unzip(zipped);
|
|
905
1234
|
return sql `(${_.map(l, x => x.sql)}) ${operatorMap[expr.type]} (${_.map(r, x => x.sql)})`;
|
|
906
1235
|
}
|
|
907
1236
|
}
|
|
908
1237
|
const _left = encodeTypedQueryExpression(compiler, parent, expr.left);
|
|
909
1238
|
const _right = encodeTypedQueryExpression(compiler, parent, expr.right);
|
|
910
1239
|
if (_left && _right) {
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
1240
|
+
if (_left.type === _right.type) {
|
|
1241
|
+
return sql `(${_left.sql}) ${operatorMap[expr.type]} (${_right.sql})`;
|
|
1242
|
+
}
|
|
1243
|
+
if (_left.type === 'decimal' && _right.type === 'number') {
|
|
1244
|
+
return sql `CAST((${_left.sql}) AS DOUBLE PRECISION) ${operatorMap[expr.type]} (${_right.sql})`;
|
|
1245
|
+
}
|
|
1246
|
+
if (_left.type === 'number' && _right.type === 'decimal') {
|
|
1247
|
+
return sql `(${_left.sql}) ${operatorMap[expr.type]} CAST((${_right.sql}) AS DOUBLE PRECISION)`;
|
|
1248
|
+
}
|
|
914
1249
|
}
|
|
915
1250
|
const _left2 = encodeJsonQueryExpression(compiler, parent, expr.left);
|
|
916
1251
|
const _right2 = encodeJsonQueryExpression(compiler, parent, expr.right);
|
|
@@ -922,12 +1257,6 @@ const encodeBooleanExpression = (compiler, parent, expr) => {
|
|
|
922
1257
|
}
|
|
923
1258
|
throw Error('Invalid expression');
|
|
924
1259
|
};
|
|
925
|
-
const encodeQueryExpression = (compiler, parent, expr) => {
|
|
926
|
-
if (expr instanceof QueryDistanceExpression) {
|
|
927
|
-
return encodeDistanceQueryExpression(compiler, parent, expr);
|
|
928
|
-
}
|
|
929
|
-
return encodeBooleanExpression(compiler, parent, expr);
|
|
930
|
-
};
|
|
931
1260
|
|
|
932
1261
|
//
|
|
933
1262
|
// storage.ts
|
|
@@ -1094,13 +1423,18 @@ class SqlStorage {
|
|
|
1094
1423
|
const self = this;
|
|
1095
1424
|
const compiler = self._makeCompiler(false, query.extraFilter);
|
|
1096
1425
|
const _matchesType = self._matchesType(compiler, query);
|
|
1097
|
-
const _query = compiler._selectQuery({ ...query, sort: {} }, ({ fetchName }) =>
|
|
1098
|
-
|
|
1426
|
+
const _query = compiler._selectQuery({ ...query, sort: {} }, ({ fetchName }) => {
|
|
1427
|
+
if (!opts?.weight)
|
|
1428
|
+
return { sort: sql `ORDER BY ${self.dialect.random()}` };
|
|
1429
|
+
const weight = encodeTypedQueryExpression(compiler, {
|
|
1099
1430
|
name: fetchName,
|
|
1100
1431
|
className: query.className,
|
|
1101
1432
|
groupMatches: query.groupMatches,
|
|
1102
|
-
}, opts.weight)
|
|
1103
|
-
|
|
1433
|
+
}, opts.weight);
|
|
1434
|
+
if (!weight)
|
|
1435
|
+
throw Error('Invalid expression');
|
|
1436
|
+
return { sort: sql `ORDER BY ${self.dialect.random(weight.sql)}` };
|
|
1437
|
+
});
|
|
1104
1438
|
return (async function* () {
|
|
1105
1439
|
const objects = self.query(_query);
|
|
1106
1440
|
for await (const object of objects) {
|
|
@@ -1979,7 +2313,7 @@ const selectPopulate = (compiler, parent, populate, field) => {
|
|
|
1979
2313
|
];
|
|
1980
2314
|
if (!_.isEmpty(groupMatches?.[field])) {
|
|
1981
2315
|
for (const [key, expr] of _.entries(groupMatches[field])) {
|
|
1982
|
-
if (expr instanceof
|
|
2316
|
+
if (expr instanceof QueryZeroParamAccumulator) {
|
|
1983
2317
|
switch (expr.type) {
|
|
1984
2318
|
case '$count':
|
|
1985
2319
|
columns.push(sql `
|
|
@@ -1992,11 +2326,10 @@ const selectPopulate = (compiler, parent, populate, field) => {
|
|
|
1992
2326
|
break;
|
|
1993
2327
|
}
|
|
1994
2328
|
}
|
|
1995
|
-
else if (expr instanceof
|
|
2329
|
+
else if (expr instanceof QueryUnaryAccumulator) {
|
|
1996
2330
|
if (!expr.expr)
|
|
1997
2331
|
throw Error('Invalid expression');
|
|
1998
|
-
const
|
|
1999
|
-
const value = _.first(exprs)?.sql;
|
|
2332
|
+
const { sql: value } = encodeTypedQueryExpression(compiler, populate, expr.expr) ?? {};
|
|
2000
2333
|
if (!value)
|
|
2001
2334
|
throw Error('Invalid expression');
|
|
2002
2335
|
switch (expr.type) {
|
|
@@ -2039,8 +2372,7 @@ const selectPopulate = (compiler, parent, populate, field) => {
|
|
|
2039
2372
|
}[expr.mode];
|
|
2040
2373
|
if (!expr.input)
|
|
2041
2374
|
throw Error('Invalid expression');
|
|
2042
|
-
const
|
|
2043
|
-
const value = _.first(exprs)?.sql;
|
|
2375
|
+
const { sql: value } = encodeTypedQueryExpression(compiler, populate, expr.input) ?? {};
|
|
2044
2376
|
if (!value)
|
|
2045
2377
|
throw Error('Invalid expression');
|
|
2046
2378
|
columns.push(sql `
|
|
@@ -2628,6 +2960,36 @@ const encodeFieldExpression = (compiler, parent, field, expr) => {
|
|
|
2628
2960
|
throw Error('Invalid expression');
|
|
2629
2961
|
};
|
|
2630
2962
|
|
|
2963
|
+
//
|
|
2964
|
+
// index.ts
|
|
2965
|
+
//
|
|
2966
|
+
// The MIT License
|
|
2967
|
+
// Copyright (c) 2021 - 2025 O2ter Limited. All rights reserved.
|
|
2968
|
+
//
|
|
2969
|
+
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
2970
|
+
// of this software and associated documentation files (the "Software"), to deal
|
|
2971
|
+
// in the Software without restriction, including without limitation the rights
|
|
2972
|
+
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
2973
|
+
// copies of the Software, and to permit persons to whom the Software is
|
|
2974
|
+
// furnished to do so, subject to the following conditions:
|
|
2975
|
+
//
|
|
2976
|
+
// The above copyright notice and this permission notice shall be included in
|
|
2977
|
+
// all copies or substantial portions of the Software.
|
|
2978
|
+
//
|
|
2979
|
+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
2980
|
+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
2981
|
+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
2982
|
+
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
2983
|
+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
2984
|
+
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
2985
|
+
// THE SOFTWARE.
|
|
2986
|
+
//
|
|
2987
|
+
const encodeSortExpression = (compiler, parent, expr) => {
|
|
2988
|
+
if (expr instanceof QueryDistanceExpression) {
|
|
2989
|
+
return encodeDistanceQueryExpression(compiler, parent, expr);
|
|
2990
|
+
}
|
|
2991
|
+
};
|
|
2992
|
+
|
|
2631
2993
|
//
|
|
2632
2994
|
// relation.ts
|
|
2633
2995
|
//
|
|
@@ -2699,7 +3061,8 @@ const PostgresDialect = {
|
|
|
2699
3061
|
updateOperation,
|
|
2700
3062
|
selectPopulate,
|
|
2701
3063
|
encodeFieldExpression,
|
|
2702
|
-
|
|
3064
|
+
encodeBooleanExpression,
|
|
3065
|
+
encodeSortExpression,
|
|
2703
3066
|
encodePopulate,
|
|
2704
3067
|
encodeRelation,
|
|
2705
3068
|
encodeSortKey,
|