proto.io 0.0.216 → 0.0.218

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.
Files changed (52) hide show
  1. package/dist/adapters/file/aliyun-oss.d.ts +3 -3
  2. package/dist/adapters/file/database.d.ts +2 -2
  3. package/dist/adapters/file/database.js +2 -2
  4. package/dist/adapters/file/database.mjs +2 -2
  5. package/dist/adapters/file/filesystem.d.ts +3 -3
  6. package/dist/adapters/file/google-cloud-storage.d.ts +3 -3
  7. package/dist/adapters/storage/progres.d.ts +5 -3
  8. package/dist/adapters/storage/progres.js +511 -148
  9. package/dist/adapters/storage/progres.js.map +1 -1
  10. package/dist/adapters/storage/progres.mjs +511 -148
  11. package/dist/adapters/storage/progres.mjs.map +1 -1
  12. package/dist/client.d.ts +3 -3
  13. package/dist/client.js +2 -8
  14. package/dist/client.js.map +1 -1
  15. package/dist/client.mjs +3 -3
  16. package/dist/client.mjs.map +1 -1
  17. package/dist/index.d.ts +3 -3
  18. package/dist/index.js +28 -34
  19. package/dist/index.js.map +1 -1
  20. package/dist/index.mjs +29 -29
  21. package/dist/index.mjs.map +1 -1
  22. package/dist/internals/{base-BO3ZP6EF.d.ts → base-CqeIQTE9.d.ts} +2 -2
  23. package/dist/internals/base-CqeIQTE9.d.ts.map +1 -0
  24. package/dist/internals/{chunk-DDkLpKXp.d.ts → chunk-CLKTwfRe.d.ts} +3 -3
  25. package/dist/internals/chunk-CLKTwfRe.d.ts.map +1 -0
  26. package/dist/internals/{index-B8TESzd9.js → index-CLKTEIj0.js} +2 -2
  27. package/dist/internals/index-CLKTEIj0.js.map +1 -0
  28. package/dist/internals/{index-DF2AfSGK.mjs → index-CZ5fKgiJ.mjs} +159 -166
  29. package/dist/internals/index-CZ5fKgiJ.mjs.map +1 -0
  30. package/dist/internals/{index-CYhA8SU8.d.ts → index-Ci8d33k-.d.ts} +3 -9
  31. package/dist/internals/index-Ci8d33k-.d.ts.map +1 -0
  32. package/dist/internals/{index-HdMgLYtD.d.ts → index-DQHWdslW.d.ts} +59 -22
  33. package/dist/internals/index-DQHWdslW.d.ts.map +1 -0
  34. package/dist/internals/{index-BzDsTt4R.mjs → index-gWcE22mf.mjs} +2 -2
  35. package/dist/internals/index-gWcE22mf.mjs.map +1 -0
  36. package/dist/internals/{index-DfnPpl1I.js → index-xHeu-AjT.js} +158 -171
  37. package/dist/internals/index-xHeu-AjT.js.map +1 -0
  38. package/dist/internals/{validator-BBjOdLiT.js → validator-B5yHpyvb.js} +743 -36
  39. package/dist/internals/validator-B5yHpyvb.js.map +1 -0
  40. package/dist/internals/{validator-LNgZGT_l.mjs → validator-DX2nXeQo.mjs} +736 -35
  41. package/dist/internals/validator-DX2nXeQo.mjs.map +1 -0
  42. package/package.json +2 -2
  43. package/dist/internals/base-BO3ZP6EF.d.ts.map +0 -1
  44. package/dist/internals/chunk-DDkLpKXp.d.ts.map +0 -1
  45. package/dist/internals/index-B8TESzd9.js.map +0 -1
  46. package/dist/internals/index-BzDsTt4R.mjs.map +0 -1
  47. package/dist/internals/index-CYhA8SU8.d.ts.map +0 -1
  48. package/dist/internals/index-DF2AfSGK.mjs.map +0 -1
  49. package/dist/internals/index-DfnPpl1I.js.map +0 -1
  50. package/dist/internals/index-HdMgLYtD.d.ts.map +0 -1
  51. package/dist/internals/validator-BBjOdLiT.js.map +0 -1
  52. package/dist/internals/validator-LNgZGT_l.mjs.map +0 -1
@@ -3,13 +3,13 @@
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
5
  var _ = require('lodash');
6
- var index = require('../../internals/index-B8TESzd9.js');
6
+ var index = require('../../internals/index-CLKTEIj0.js');
7
7
  var pg = require('pg');
8
8
  var QueryStream = require('pg-query-stream');
9
9
  var utilsJs = require('@o2ter/utils-js');
10
10
  var Decimal = require('decimal.js');
11
11
  var utils = require('pg/lib/utils');
12
- var validator = require('../../internals/validator-BBjOdLiT.js');
12
+ var validator = require('../../internals/validator-B5yHpyvb.js');
13
13
  require('@o2ter/crypto-js');
14
14
  var _const = require('../../internals/const-C3I6cfav.js');
15
15
  var random$1 = require('../../internals/random-nkOQ9U6S.js');
@@ -189,12 +189,12 @@ const _encodeSorting = (includes, populates, sort) => {
189
189
  return sorting;
190
190
  };
191
191
  const _defaultInsertOpts = (options) => {
192
- const objectId = random$1.generateId(options.objectIdSize);
192
+ const id = random$1.generateId(options.objectIdSize);
193
193
  return {
194
- _id: sql `${{ value: objectId }}`,
194
+ _id: sql `${{ value: id }}`,
195
195
  ...options.className === 'User' ? {
196
- _rperm: sql `${{ value: [objectId] }}`,
197
- _wperm: sql `${{ value: [objectId] }}`,
196
+ _rperm: sql `${{ value: [id] }}`,
197
+ _wperm: sql `${{ value: [id] }}`,
198
198
  } : {},
199
199
  };
200
200
  };
@@ -413,7 +413,7 @@ class QueryCompiler {
413
413
  return this.dialect.encodeFieldExpression(this, parent, filter.field, filter.expr);
414
414
  }
415
415
  if (filter instanceof validator.QueryExpressionSelector) {
416
- return this.dialect.encodeQueryExpression(this, parent, filter.expr);
416
+ return this.dialect.encodeBooleanExpression(this, parent, filter.expr);
417
417
  }
418
418
  }
419
419
  _selectIncludes(className, includes) {
@@ -428,7 +428,7 @@ class QueryCompiler {
428
428
  _encodeSort(sort, parent) {
429
429
  if (_.isArray(sort)) {
430
430
  return sql `${_.map(sort, ({ expr, order }) => {
431
- const _expr = this.dialect.encodeQueryExpression(this, parent, expr);
431
+ const _expr = this.dialect.encodeSortExpression(this, parent, expr);
432
432
  if (!_expr)
433
433
  throw Error('Invalid expression');
434
434
  return sql `${_expr} ${{ literal: order === 1 ? 'ASC' : 'DESC' }}`;
@@ -632,12 +632,12 @@ const encodeType = (colname, dataType, value) => {
632
632
  break;
633
633
  return sql `ARRAY[${_.map(value, x => _encodeJsonValue(index._encodeValue(x)))}]::JSONB[]`;
634
634
  case 'pointer':
635
- if (value instanceof index.TObject && value.objectId)
636
- return sql `${{ value: `${value.className}$${value.objectId}` }}`;
635
+ if (value instanceof index.TObject && value.id)
636
+ return sql `${{ value: `${value.className}$${value.id}` }}`;
637
637
  break;
638
638
  case 'relation':
639
- if (_.isArray(value) && _.every(value, x => x instanceof index.TObject && x.objectId)) {
640
- return sql `${{ value: _.uniq(_.map(value, (x) => `${x.className}$${x.objectId}`)) }}`;
639
+ if (_.isArray(value) && _.every(value, x => x instanceof index.TObject && x.id)) {
640
+ return sql `${{ value: _.uniq(_.map(value, (x) => `${x.className}$${x.id}`)) }}`;
641
641
  }
642
642
  break;
643
643
  }
@@ -708,7 +708,7 @@ const decodeType = (type, value) => {
708
708
  };
709
709
 
710
710
  //
711
- // expressions.ts
711
+ // types.ts
712
712
  //
713
713
  // The MIT License
714
714
  // Copyright (c) 2021 - 2025 O2ter Limited. All rights reserved.
@@ -731,7 +731,8 @@ const decodeType = (type, value) => {
731
731
  // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
732
732
  // THE SOFTWARE.
733
733
  //
734
- const isArrayExpression = (expr) => {
734
+ const _PrimitiveValue = ['boolean', 'number', 'decimal', 'string', 'date'];
735
+ const isArrayExpr = (expr) => {
735
736
  if (expr instanceof validator.QueryArrayExpression)
736
737
  return true;
737
738
  if (expr instanceof validator.QueryValueExpression)
@@ -745,62 +746,428 @@ const arrayLength = (expr) => {
745
746
  return _.isArray(expr.value) ? expr.value.length : 0;
746
747
  return 0;
747
748
  };
748
- const mapExpression = (expr, callback) => {
749
+ const mapExpr = (expr, callback) => {
749
750
  if (expr instanceof validator.QueryArrayExpression)
750
751
  return _.map(expr.exprs, x => callback(x));
751
752
  if (expr instanceof validator.QueryValueExpression)
752
753
  return _.isArray(expr.value) ? _.map(expr.value, x => callback(new validator.QueryValueExpression(x))) : [];
753
754
  return [];
754
755
  };
755
- const _PrimitiveValue = ['boolean', 'number', 'decimal', 'string', 'date'];
756
+ const zipExpr = (lhs, rhs) => {
757
+ const result = [];
758
+ for (const [l, r] of _.zip(lhs, rhs)) {
759
+ if (!l || !r)
760
+ return;
761
+ if (l.type === r.type)
762
+ result.push([l, r]);
763
+ else if (l.type === 'number' && r.type === 'decimal')
764
+ result.push([l, { type: 'decimal', sql: sql `CAST((${r.sql}) AS DECIMAL)` }]);
765
+ else if (l.type === 'decimal' && r.type === 'number')
766
+ result.push([{ type: 'decimal', sql: sql `CAST((${l.sql}) AS DECIMAL)` }, r]);
767
+ else
768
+ return;
769
+ }
770
+ return result;
771
+ };
772
+ const typeCastExpr = (expr, type) => {
773
+ if (!expr)
774
+ return;
775
+ if (expr.type === type)
776
+ return expr;
777
+ if (expr.type === 'number' && type === 'decimal')
778
+ return { type, sql: sql `CAST((${expr.sql}) AS DECIMAL)` };
779
+ if (expr.type === 'decimal' && type === 'number')
780
+ return { type, sql: sql `CAST((${expr.sql}) AS DOUBLE PRECISION)` };
781
+ };
782
+
783
+ //
784
+ // vector.ts
785
+ //
786
+ // The MIT License
787
+ // Copyright (c) 2021 - 2025 O2ter Limited. All rights reserved.
788
+ //
789
+ // Permission is hereby granted, free of charge, to any person obtaining a copy
790
+ // of this software and associated documentation files (the "Software"), to deal
791
+ // in the Software without restriction, including without limitation the rights
792
+ // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
793
+ // copies of the Software, and to permit persons to whom the Software is
794
+ // furnished to do so, subject to the following conditions:
795
+ //
796
+ // The above copyright notice and this permission notice shall be included in
797
+ // all copies or substantial portions of the Software.
798
+ //
799
+ // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
800
+ // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
801
+ // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
802
+ // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
803
+ // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
804
+ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
805
+ // THE SOFTWARE.
806
+ //
807
+ const encodeVectorExpression = (compiler, parent, exprs) => {
808
+ if (exprs.length === 1) {
809
+ const [expr] = exprs;
810
+ if (expr instanceof validator.QueryKeyExpression) {
811
+ const { element, dataType } = fetchElement(compiler, parent, expr.key);
812
+ if (!dataType || !index.isVector(dataType))
813
+ throw Error('Invalid expression');
814
+ return { sql: element, dimension: dataType.dimension };
815
+ }
816
+ if (expr instanceof validator.QueryValueExpression) {
817
+ if (!_.isArray(expr.value) || !_.every(expr.value, x => _.isFinite(x)))
818
+ throw Error('Invalid expression');
819
+ return { sql: sql `${{ value: expr.value }}::DOUBLE PRECISION[]`, dimension: expr.value.length };
820
+ }
821
+ }
822
+ const result = _.compact(_.map(exprs, x => typeCastExpr(encodeTypedQueryExpression(compiler, parent, x), 'number')?.sql));
823
+ if (result.length !== exprs.length)
824
+ throw Error('Invalid expression');
825
+ return { sql: sql `ARRAY[${_.map(result, x => sql `COALESCE(${x}, 0)`)}]`, dimension: result.length };
826
+ };
827
+ const encodeDistanceQueryExpression = (compiler, parent, expr) => {
828
+ const { sql: left, dimension: d1 } = encodeVectorExpression(compiler, parent, expr.left);
829
+ const { sql: right, dimension: d2 } = encodeVectorExpression(compiler, parent, expr.right);
830
+ if (d1 !== d2)
831
+ throw Error('Invalid expression');
832
+ const operatorMap = {
833
+ '$distance': sql `<->`,
834
+ '$innerProduct': sql `<#>`,
835
+ '$negInnerProduct': sql `<#>`,
836
+ '$cosineDistance': sql `<=>`,
837
+ '$rectilinearDistance': sql `<+>`,
838
+ };
839
+ const _expr = sql `
840
+ CAST(
841
+ ${left} AS VECTOR(${{ literal: `${d1}` }})
842
+ )
843
+ ${operatorMap[expr.type]}
844
+ CAST(
845
+ ${right} AS VECTOR(${{ literal: `${d2}` }})
846
+ )
847
+ `;
848
+ return expr.type === '$innerProduct' ? sql `-1 * (${_expr})` : _expr;
849
+ };
850
+
851
+ //
852
+ // index.ts
853
+ //
854
+ // The MIT License
855
+ // Copyright (c) 2021 - 2025 O2ter Limited. All rights reserved.
856
+ //
857
+ // Permission is hereby granted, free of charge, to any person obtaining a copy
858
+ // of this software and associated documentation files (the "Software"), to deal
859
+ // in the Software without restriction, including without limitation the rights
860
+ // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
861
+ // copies of the Software, and to permit persons to whom the Software is
862
+ // furnished to do so, subject to the following conditions:
863
+ //
864
+ // The above copyright notice and this permission notice shall be included in
865
+ // all copies or substantial portions of the Software.
866
+ //
867
+ // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
868
+ // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
869
+ // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
870
+ // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
871
+ // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
872
+ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
873
+ // THE SOFTWARE.
874
+ //
756
875
  const encodeTypedQueryExpression = (compiler, parent, expr) => {
757
876
  if (expr instanceof validator.QueryKeyExpression) {
758
877
  const { element, dataType } = fetchElement(compiler, parent, expr.key);
759
878
  const _dataType = dataType ? index._typeof(dataType) : null;
760
- if (_dataType === 'number') {
761
- return [
762
- { type: 'number', sql: element },
763
- { type: 'decimal', sql: sql `CAST((${element}) AS DECIMAL)` },
764
- ];
765
- }
766
- else if (_dataType === 'decimal') {
767
- return [
768
- { type: 'decimal', sql: element },
769
- { type: 'number', sql: element },
770
- ];
771
- }
772
- else if (_dataType && _PrimitiveValue.includes(_dataType)) {
773
- return [{ type: _dataType, sql: element }];
774
- }
879
+ if (!_dataType || !_PrimitiveValue.includes(_dataType))
880
+ return;
881
+ return { type: _dataType, sql: element };
775
882
  }
776
883
  if (expr instanceof validator.QueryValueExpression) {
777
884
  if (_.isBoolean(expr.value))
778
- return [{ type: 'boolean', sql: sql `${{ value: expr.value }}` }];
885
+ return { type: 'boolean', sql: sql `${{ value: expr.value }}` };
779
886
  if (_.isNumber(expr.value))
780
- return [
781
- { type: 'number', sql: sql `${{ value: expr.value }}` },
782
- { type: 'decimal', sql: sql `CAST(${{ quote: (new Decimal(expr.value)).toString() }} AS DECIMAL)` },
783
- ];
887
+ return { type: 'number', sql: sql `${{ value: expr.value }}` };
784
888
  if (expr.value instanceof Decimal)
785
- return [
786
- { type: 'decimal', sql: sql `CAST(${{ quote: expr.value.toString() }} AS DECIMAL)` },
787
- { type: 'number', sql: sql `${{ value: expr.value.toNumber() }}` },
788
- ];
889
+ return { type: 'decimal', sql: sql `CAST(${{ quote: expr.value.toString() }} AS DECIMAL)` };
789
890
  if (_.isString(expr.value))
790
- return [{ type: 'string', sql: sql `${{ value: expr.value }}` }];
891
+ return { type: 'string', sql: sql `${{ value: expr.value }}` };
791
892
  if (_.isDate(expr.value))
792
- return [{ type: 'date', sql: sql `${{ value: expr.value }}` }];
893
+ return { type: 'date', sql: sql `${{ value: expr.value }}` };
793
894
  }
794
895
  if (expr instanceof validator.QueryCoditionalExpression ||
795
896
  expr instanceof validator.QueryComparisonExpression ||
796
897
  expr instanceof validator.QueryNotExpression) {
797
898
  const value = encodeBooleanExpression(compiler, parent, expr);
798
899
  if (value)
799
- return [{ type: 'boolean', sql: value }];
900
+ return { type: 'boolean', sql: value };
800
901
  }
801
902
  if (expr instanceof validator.QueryDistanceExpression) {
802
903
  const value = encodeDistanceQueryExpression(compiler, parent, expr);
803
- return [{ type: 'number', sql: value }];
904
+ return { type: 'number', sql: value };
905
+ }
906
+ if (expr instanceof validator.QueryZeroParamExpression) {
907
+ switch (expr.type) {
908
+ case '$rand': return { type: 'number', sql: sql `RANDOM()` };
909
+ case '$now': return { type: 'date', sql: sql `CAST(NOW() AS TIMESTAMP(3) WITH TIME ZONE)` };
910
+ }
911
+ }
912
+ if (expr instanceof validator.QueryUnaryExpression) {
913
+ const value = encodeTypedQueryExpression(compiler, parent, expr.expr);
914
+ if (!value)
915
+ return;
916
+ switch (expr.type) {
917
+ case '$abs':
918
+ case '$neg':
919
+ case '$sqrt':
920
+ case '$cbrt':
921
+ case '$ceil':
922
+ case '$floor':
923
+ case '$round':
924
+ case '$exp':
925
+ case '$ln':
926
+ case '$log10':
927
+ case '$sin':
928
+ case '$cos':
929
+ case '$tan':
930
+ case '$asin':
931
+ case '$acos':
932
+ case '$atan':
933
+ case '$asinh':
934
+ case '$acosh':
935
+ case '$atanh':
936
+ case '$sinh':
937
+ case '$cosh':
938
+ case '$tanh':
939
+ case '$degrees':
940
+ case '$radians':
941
+ case '$sign':
942
+ {
943
+ const op = {
944
+ '$abs': 'ABS',
945
+ '$neg': '-',
946
+ '$sqrt': 'SQRT',
947
+ '$cbrt': 'CBRT',
948
+ '$ceil': 'CEIL',
949
+ '$floor': 'FLOOR',
950
+ '$round': 'ROUND',
951
+ '$exp': 'EXP',
952
+ '$ln': 'LN',
953
+ '$log10': 'LOG10',
954
+ '$sin': 'SIN',
955
+ '$cos': 'COS',
956
+ '$tan': 'TAN',
957
+ '$asin': 'ASIN',
958
+ '$acos': 'ACOS',
959
+ '$atan': 'ATAN',
960
+ '$asinh': 'ASINH',
961
+ '$acosh': 'ACOSH',
962
+ '$atanh': 'ATANH',
963
+ '$sinh': 'SINH',
964
+ '$cosh': 'COSH',
965
+ '$tanh': 'TANH',
966
+ '$degrees': 'DEGREES',
967
+ '$radians': 'RADIANS',
968
+ '$sign': 'SIGN',
969
+ }[expr.type];
970
+ if (!_.includes(['number', 'decimal'], value.type))
971
+ return;
972
+ return { type: 'number', sql: sql `${{ literal: op }}(${value.sql})` };
973
+ }
974
+ case '$log2':
975
+ if (!_.includes(['number', 'decimal'], value.type))
976
+ return;
977
+ return { type: value.type, sql: sql `(LOG(${value.sql}) / LOG(2))` };
978
+ case '$size':
979
+ if (!_.includes(['string', 'string[]', 'array'], value.type))
980
+ return;
981
+ return { type: 'number', sql: sql `LENGTH(${value.sql})` };
982
+ case '$lower':
983
+ case '$upper':
984
+ {
985
+ const op = {
986
+ '$lower': 'LOWER',
987
+ '$upper': 'UPPER',
988
+ }[expr.type];
989
+ if (value.type !== 'string')
990
+ return;
991
+ return { type: 'string', sql: sql `${{ literal: op }}(${value.sql})` };
992
+ }
993
+ }
994
+ }
995
+ if (expr instanceof validator.QueryBinaryExpression) {
996
+ const left = encodeTypedQueryExpression(compiler, parent, expr.left);
997
+ const right = encodeTypedQueryExpression(compiler, parent, expr.right);
998
+ if (!left || !right)
999
+ return;
1000
+ switch (expr.type) {
1001
+ case '$divide':
1002
+ case '$subtract':
1003
+ {
1004
+ const op = {
1005
+ '$divide': '/',
1006
+ '$subtract': '-',
1007
+ }[expr.type];
1008
+ if (left.type === right.type) {
1009
+ return { type: left.type, sql: sql `(${left.sql}) ${{ literal: op }} (${right.sql})` };
1010
+ }
1011
+ if (left.type === 'decimal' && right.type === 'number') {
1012
+ return { type: 'decimal', sql: sql `CAST((${left.sql}) AS DECIMAL) ${{ literal: op }} (${right.sql})` };
1013
+ }
1014
+ if (left.type === 'number' && right.type === 'decimal') {
1015
+ return { type: 'decimal', sql: sql `(${left.sql}) ${{ literal: op }} CAST((${right.sql}) AS DECIMAL)` };
1016
+ }
1017
+ }
1018
+ break;
1019
+ case '$log':
1020
+ {
1021
+ if (left.type === right.type) {
1022
+ return { type: left.type, sql: sql `(LOG(${left.sql}) / LOG(${right.sql}))` };
1023
+ }
1024
+ if (left.type === 'decimal' && right.type === 'number') {
1025
+ return { type: 'decimal', sql: sql `(LOG(${left.sql}) / LOG(CAST((${right.sql}) AS DECIMAL)))` };
1026
+ }
1027
+ if (left.type === 'number' && right.type === 'decimal') {
1028
+ return { type: 'decimal', sql: sql `(LOG(CAST((${left.sql}) AS DECIMAL) / LOG(${right.sql}))` };
1029
+ }
1030
+ }
1031
+ break;
1032
+ case '$pow':
1033
+ case '$atan2':
1034
+ {
1035
+ const op = {
1036
+ '$pow': 'POWER',
1037
+ '$atan2': 'ATAN2',
1038
+ }[expr.type];
1039
+ if (left.type === right.type) {
1040
+ return { type: left.type, sql: sql `${{ literal: op }}((${left.sql}), (${right.sql}))` };
1041
+ }
1042
+ if (left.type === 'decimal' && right.type === 'number') {
1043
+ return { type: 'decimal', sql: sql `${{ literal: op }}((${left.sql}), CAST((${right.sql}) AS DECIMAL))` };
1044
+ }
1045
+ if (left.type === 'number' && right.type === 'decimal') {
1046
+ return { type: 'decimal', sql: sql `${{ literal: op }}(CAST((${left.sql}) AS DECIMAL), (${right.sql}))` };
1047
+ }
1048
+ }
1049
+ break;
1050
+ case '$trim':
1051
+ case '$ltrim':
1052
+ case '$rtrim':
1053
+ {
1054
+ const op = {
1055
+ '$trim': 'TRIM',
1056
+ '$ltrim': 'LTRIM',
1057
+ '$rtrim': 'RTRIM',
1058
+ }[expr.type];
1059
+ if (left?.type !== 'string' || right?.type !== 'string')
1060
+ return;
1061
+ return { type: 'string', sql: sql `${{ literal: op }}(${left.sql}, ${right.sql})` };
1062
+ }
1063
+ case '$first':
1064
+ case '$last':
1065
+ {
1066
+ if (!_.includes(['number', 'decimal'], right.type))
1067
+ return;
1068
+ if (left?.type === 'string') {
1069
+ const op = {
1070
+ '$first': 'LEFT',
1071
+ '$last': 'RIGHT',
1072
+ }[expr.type];
1073
+ return { type: 'string', sql: sql `${{ literal: op }}(${left.sql}, ${right.sql})` };
1074
+ }
1075
+ }
1076
+ break;
1077
+ case '$ldrop':
1078
+ case '$rdrop':
1079
+ {
1080
+ if (!_.includes(['number', 'decimal'], right.type))
1081
+ return;
1082
+ if (left?.type === 'string') {
1083
+ const op = {
1084
+ '$ldrop': 'RIGHT',
1085
+ '$rdrop': 'LEFT',
1086
+ }[expr.type];
1087
+ return { type: 'string', sql: sql `${{ literal: op }}(${left.sql}, -(${right.sql}))` };
1088
+ }
1089
+ }
1090
+ break;
1091
+ }
1092
+ }
1093
+ if (expr instanceof validator.QueryListExpression) {
1094
+ const values = _.compact(_.map(expr.exprs, x => encodeTypedQueryExpression(compiler, parent, x)));
1095
+ if (values.length !== expr.exprs.length)
1096
+ return;
1097
+ switch (expr.type) {
1098
+ case '$add':
1099
+ case '$multiply':
1100
+ {
1101
+ const op = {
1102
+ '$add': '+',
1103
+ '$multiply': '*',
1104
+ }[expr.type];
1105
+ if (_.every(values, x => x.type === 'number')) {
1106
+ return { type: 'number', sql: sql `${{ literal: _.map(values, x => x.sql), separator: ` ${op} ` }}` };
1107
+ }
1108
+ if (_.every(values, x => x.type === 'number' || x.type === 'decimal')) {
1109
+ return { type: 'decimal', sql: sql `${{ literal: _.map(values, x => x.type === 'decimal' ? x.sql : sql `CAST((${x.sql}) AS DECIMAL)`), separator: ` ${op} ` }}` };
1110
+ }
1111
+ }
1112
+ break;
1113
+ case '$ifNull':
1114
+ {
1115
+ const type = values[0].type;
1116
+ if (_.every(values, x => x.type === type)) {
1117
+ return { type, sql: sql `COALESCE(${{ literal: _.map(values, x => x.sql) }})` };
1118
+ }
1119
+ }
1120
+ break;
1121
+ case '$concat':
1122
+ {
1123
+ if (_.every(values, x => x.type === 'string')) {
1124
+ return { type: 'string', sql: sql `CONCAT(${{ literal: _.map(values, x => x.sql) }})` };
1125
+ }
1126
+ }
1127
+ break;
1128
+ }
1129
+ }
1130
+ if (expr instanceof validator.QueryTernaryExpression) {
1131
+ const first = encodeTypedQueryExpression(compiler, parent, expr.first);
1132
+ const second = encodeTypedQueryExpression(compiler, parent, expr.second);
1133
+ const last = encodeTypedQueryExpression(compiler, parent, expr.last);
1134
+ if (!first || !second || !last)
1135
+ return;
1136
+ switch (expr.type) {
1137
+ case '$lpad':
1138
+ case '$rpad':
1139
+ {
1140
+ const op = {
1141
+ '$lpad': 'LPAD',
1142
+ '$rpad': 'RPAD',
1143
+ }[expr.type];
1144
+ if (first?.type !== 'string' || last?.type !== 'string')
1145
+ return;
1146
+ if (!_.includes(['number', 'decimal'], second.type))
1147
+ return;
1148
+ return { type: 'string', sql: sql `${{ literal: op }}(${first.sql}, ${second.sql}, ${last.sql})` };
1149
+ }
1150
+ }
1151
+ }
1152
+ if (expr instanceof validator.QueryCondExpression) {
1153
+ const branches = _.flatMap(_.map(expr.branch, x => ({
1154
+ case: encodeTypedQueryExpression(compiler, parent, x.case),
1155
+ then: encodeTypedQueryExpression(compiler, parent, x.then),
1156
+ })), x => x.case && x.then ? ({ case: x.case, then: x.then }) : []);
1157
+ if (branches.length !== expr.branch.length)
1158
+ return;
1159
+ const defaultCase = encodeTypedQueryExpression(compiler, parent, expr.default);
1160
+ if (!defaultCase)
1161
+ return;
1162
+ if (!_.every(branches, x => x.case.type === 'boolean' && x.then.type === defaultCase.type))
1163
+ return;
1164
+ return {
1165
+ type: defaultCase.type,
1166
+ sql: sql `CASE ${{
1167
+ literal: _.map(branches, x => sql `WHEN (${x.case.sql}) THEN (${x.then.sql})`),
1168
+ separator: ' '
1169
+ }} ELSE (${defaultCase.sql}) END`,
1170
+ };
804
1171
  }
805
1172
  };
806
1173
  const encodeJsonQueryExpression = (compiler, parent, expr) => {
@@ -826,57 +1193,19 @@ const encodeJsonQueryExpression = (compiler, parent, expr) => {
826
1193
  if (expr instanceof validator.QueryArrayExpression) {
827
1194
  return sql `jsonb_build_array(${_.map(expr.exprs, x => encodeJsonQueryExpression(compiler, parent, x))})`;
828
1195
  }
829
- const value = encodeQueryExpression(compiler, parent, expr);
830
- if (!value)
1196
+ const typed = encodeTypedQueryExpression(compiler, parent, expr);
1197
+ if (!typed)
831
1198
  throw Error('Invalid expression');
832
- return sql `to_jsonb(${value})`;
833
- };
834
- const encodeVectorExpression = (compiler, parent, exprs) => {
835
- if (exprs.length === 1) {
836
- const [expr] = exprs;
837
- if (expr instanceof validator.QueryKeyExpression) {
838
- const { element, dataType } = fetchElement(compiler, parent, expr.key);
839
- if (!dataType || !index.isVector(dataType))
840
- throw Error('Invalid expression');
841
- return { sql: element, dimension: dataType.dimension };
842
- }
843
- if (expr instanceof validator.QueryValueExpression) {
844
- if (!_.isArray(expr.value) || !_.every(expr.value, x => _.isFinite(x)))
845
- throw Error('Invalid expression');
846
- return { sql: sql `${{ value: expr.value }}::DOUBLE PRECISION[]`, dimension: expr.value.length };
847
- }
1199
+ switch (typed.type) {
1200
+ case 'boolean': return sql `to_jsonb(${typed.sql})`;
1201
+ case 'number': return sql `to_jsonb(${typed.sql})`;
1202
+ case 'decimal': return sql `jsonb_build_object('$decimal', CAST(${typed.sql} AS TEXT))`;
1203
+ case 'string': return sql `to_jsonb(${typed.sql})`;
1204
+ case 'date': return sql `jsonb_build_object(
1205
+ '$date', to_char(${typed.sql} AT TIME ZONE 'UTC', 'YYYY-MM-DD"T"HH24:MI:SS.MS"Z"')
1206
+ )`;
1207
+ default: throw Error('Invalid expression');
848
1208
  }
849
- const result = _.map(exprs, x => _.find(encodeTypedQueryExpression(compiler, parent, x), e => e.type === 'number')?.sql);
850
- if (_.some(result, x => _.isNil(x)))
851
- throw Error('Invalid expression');
852
- return { sql: sql `ARRAY[${_.map(result, x => sql `COALESCE(${x}, 0)`)}]`, dimension: result.length };
853
- };
854
- const encodeDistanceQueryExpression = (compiler, parent, expr) => {
855
- const { sql: left, dimension: d1 } = encodeVectorExpression(compiler, parent, expr.left);
856
- const { sql: right, dimension: d2 } = encodeVectorExpression(compiler, parent, expr.right);
857
- if (d1 !== d2)
858
- throw Error('Invalid expression');
859
- const operatorMap = {
860
- '$distance': sql `<->`,
861
- '$innerProduct': sql `<#>`,
862
- '$negInnerProduct': sql `<#>`,
863
- '$cosineDistance': sql `<=>`,
864
- '$rectilinearDistance': sql `<+>`,
865
- };
866
- const _expr = sql `
867
- CAST(
868
- ${left} AS VECTOR(${{ literal: `${d1}` }})
869
- )
870
- ${operatorMap[expr.type]}
871
- CAST(
872
- ${right} AS VECTOR(${{ literal: `${d2}` }})
873
- )
874
- `;
875
- return expr.type === '$innerProduct' ? sql `-1 * (${_expr})` : _expr;
876
- };
877
- const matchType = (first, second) => {
878
- const found = _.find(first, l => _.some(second, r => l.type === r.type));
879
- return found ? [found, _.find(second, r => r.type === found.type)] : undefined;
880
1209
  };
881
1210
  const encodeBooleanExpression = (compiler, parent, expr) => {
882
1211
  if (expr instanceof validator.QueryCoditionalExpression) {
@@ -898,23 +1227,29 @@ const encodeBooleanExpression = (compiler, parent, expr) => {
898
1227
  '$lt': sql `<`,
899
1228
  '$lte': sql `<=`,
900
1229
  };
901
- if (isArrayExpression(expr.left) &&
902
- isArrayExpression(expr.right) &&
1230
+ if (isArrayExpr(expr.left) &&
1231
+ isArrayExpr(expr.right) &&
903
1232
  arrayLength(expr.left) === arrayLength(expr.right)) {
904
- const _left = mapExpression(expr.left, x => encodeTypedQueryExpression(compiler, parent, x));
905
- const _right = mapExpression(expr.right, x => encodeTypedQueryExpression(compiler, parent, x));
906
- const mapped = _.compact(_.map(_.zip(_left, _right), ([l, r]) => matchType(l, r)));
907
- if (mapped.length === _left.length) {
908
- const [l, r] = _.unzip(mapped);
1233
+ const _left = mapExpr(expr.left, x => encodeTypedQueryExpression(compiler, parent, x));
1234
+ const _right = mapExpr(expr.right, x => encodeTypedQueryExpression(compiler, parent, x));
1235
+ const zipped = zipExpr(_left, _right) ?? [];
1236
+ if (_left.length === zipped.length) {
1237
+ const [l, r] = _.unzip(zipped);
909
1238
  return sql `(${_.map(l, x => x.sql)}) ${operatorMap[expr.type]} (${_.map(r, x => x.sql)})`;
910
1239
  }
911
1240
  }
912
1241
  const _left = encodeTypedQueryExpression(compiler, parent, expr.left);
913
1242
  const _right = encodeTypedQueryExpression(compiler, parent, expr.right);
914
1243
  if (_left && _right) {
915
- const matched = matchType(_left, _right);
916
- if (matched)
917
- return sql `${matched[0].sql} ${operatorMap[expr.type]} ${matched[1].sql}`;
1244
+ if (_left.type === _right.type) {
1245
+ return sql `(${_left.sql}) ${operatorMap[expr.type]} (${_right.sql})`;
1246
+ }
1247
+ if (_left.type === 'decimal' && _right.type === 'number') {
1248
+ return sql `CAST((${_left.sql}) AS DOUBLE PRECISION) ${operatorMap[expr.type]} (${_right.sql})`;
1249
+ }
1250
+ if (_left.type === 'number' && _right.type === 'decimal') {
1251
+ return sql `(${_left.sql}) ${operatorMap[expr.type]} CAST((${_right.sql}) AS DOUBLE PRECISION)`;
1252
+ }
918
1253
  }
919
1254
  const _left2 = encodeJsonQueryExpression(compiler, parent, expr.left);
920
1255
  const _right2 = encodeJsonQueryExpression(compiler, parent, expr.right);
@@ -926,12 +1261,6 @@ const encodeBooleanExpression = (compiler, parent, expr) => {
926
1261
  }
927
1262
  throw Error('Invalid expression');
928
1263
  };
929
- const encodeQueryExpression = (compiler, parent, expr) => {
930
- if (expr instanceof validator.QueryDistanceExpression) {
931
- return encodeDistanceQueryExpression(compiler, parent, expr);
932
- }
933
- return encodeBooleanExpression(compiler, parent, expr);
934
- };
935
1264
 
936
1265
  //
937
1266
  // storage.ts
@@ -988,7 +1317,7 @@ class SqlStorage {
988
1317
  const _value = _.get(value, path);
989
1318
  if (_.isPlainObject(_value)) {
990
1319
  const decoded = this._decodeObject(type.target, _value, matchType);
991
- if (decoded.objectId)
1320
+ if (decoded.id)
992
1321
  _.set(result, path, decoded);
993
1322
  }
994
1323
  }
@@ -1028,7 +1357,7 @@ class SqlStorage {
1028
1357
  else if (index.isPointer(dataType)) {
1029
1358
  if (_.isPlainObject(value)) {
1030
1359
  const decoded = this._decodeObject(dataType.target, value, matchType);
1031
- if (decoded.objectId)
1360
+ if (decoded.id)
1032
1361
  obj[_private.PVK].attributes[key] = decoded;
1033
1362
  }
1034
1363
  }
@@ -1098,13 +1427,18 @@ class SqlStorage {
1098
1427
  const self = this;
1099
1428
  const compiler = self._makeCompiler(false, query.extraFilter);
1100
1429
  const _matchesType = self._matchesType(compiler, query);
1101
- const _query = compiler._selectQuery({ ...query, sort: {} }, ({ fetchName }) => ({
1102
- sort: sql `ORDER BY ${self.dialect.random(opts?.weight ? _.first(encodeTypedQueryExpression(compiler, {
1430
+ const _query = compiler._selectQuery({ ...query, sort: {} }, ({ fetchName }) => {
1431
+ if (!opts?.weight)
1432
+ return { sort: sql `ORDER BY ${self.dialect.random()}` };
1433
+ const weight = encodeTypedQueryExpression(compiler, {
1103
1434
  name: fetchName,
1104
1435
  className: query.className,
1105
1436
  groupMatches: query.groupMatches,
1106
- }, opts.weight))?.sql : undefined)}`,
1107
- }));
1437
+ }, opts.weight);
1438
+ if (!weight)
1439
+ throw Error('Invalid expression');
1440
+ return { sort: sql `ORDER BY ${self.dialect.random(weight.sql)}` };
1441
+ });
1108
1442
  return (async function* () {
1109
1443
  const objects = self.query(_query);
1110
1444
  for await (const object of objects) {
@@ -1116,7 +1450,7 @@ class SqlStorage {
1116
1450
  const self = this;
1117
1451
  const query = sql `
1118
1452
  SELECT *
1119
- FROM (${this._refs(_.pick(this.schema, classNames), object.className, index.TObject.defaultKeys, sql `${{ value: `${object.className}$${object.objectId}` }}`)}) AS "$"
1453
+ FROM (${this._refs(_.pick(this.schema, classNames), object.className, index.TObject.defaultKeys, sql `${{ value: `${object.className}$${object.id}` }}`)}) AS "$"
1120
1454
  ${_.isNil(roles) ? sql `` : sql `WHERE ${{ identifier: '$' }}.${{ identifier: '_rperm' }} && ${{ value: roles }}`}
1121
1455
  `;
1122
1456
  return (async function* () {
@@ -1707,25 +2041,25 @@ const updateOperation = (paths, dataType, operation) => {
1707
2041
  case '$addToSet':
1708
2042
  case '$push':
1709
2043
  {
1710
- if (!_.isArray(value) || !_.every(value, x => x instanceof index.TObject && x.objectId))
2044
+ if (!_.isArray(value) || !_.every(value, x => x instanceof index.TObject && x.id))
1711
2045
  break;
1712
- const objectIds = _.uniq(_.map(value, (x) => `${x.className}$${x.objectId}`));
2046
+ const ids = _.uniq(_.map(value, (x) => `${x.className}$${x.id}`));
1713
2047
  return sql `ARRAY(
1714
2048
  SELECT DISTINCT "$"
1715
- FROM UNNEST(${{ identifier: column }} || ARRAY[${_.map(objectIds, (x) => sql `${{ value: x }}`)}]) "$"
2049
+ FROM UNNEST(${{ identifier: column }} || ARRAY[${_.map(ids, (x) => sql `${{ value: x }}`)}]) "$"
1716
2050
  RIGHT JOIN ${{ identifier: dataType.target }} ON "$" = (${{ quote: dataType.target + '$' }} || ${{ identifier: dataType.target }}._id)
1717
2051
  )`;
1718
2052
  }
1719
2053
  case '$removeAll':
1720
2054
  {
1721
- if (!_.isArray(value) || !_.every(value, x => x instanceof index.TObject && x.objectId))
2055
+ if (!_.isArray(value) || !_.every(value, x => x instanceof index.TObject && x.id))
1722
2056
  break;
1723
- const objectIds = _.uniq(_.map(value, (x) => `${x.className}$${x.objectId}`));
2057
+ const ids = _.uniq(_.map(value, (x) => `${x.className}$${x.id}`));
1724
2058
  return sql `ARRAY(
1725
2059
  SELECT "$"
1726
2060
  FROM UNNEST(${{ identifier: column }}) "$"
1727
2061
  RIGHT JOIN ${{ identifier: dataType.target }} ON "$" = (${{ quote: dataType.target + '$' }} || ${{ identifier: dataType.target }}._id)
1728
- WHERE "$" NOT IN (${_.map(objectIds, (x) => sql `${{ value: x }}`)})
2062
+ WHERE "$" NOT IN (${_.map(ids, (x) => sql `${{ value: x }}`)})
1729
2063
  )`;
1730
2064
  }
1731
2065
  }
@@ -1983,7 +2317,7 @@ const selectPopulate = (compiler, parent, populate, field) => {
1983
2317
  ];
1984
2318
  if (!_.isEmpty(groupMatches?.[field])) {
1985
2319
  for (const [key, expr] of _.entries(groupMatches[field])) {
1986
- if (expr instanceof validator.QueryNoParamAccumulator) {
2320
+ if (expr instanceof validator.QueryZeroParamAccumulator) {
1987
2321
  switch (expr.type) {
1988
2322
  case '$count':
1989
2323
  columns.push(sql `
@@ -1996,11 +2330,10 @@ const selectPopulate = (compiler, parent, populate, field) => {
1996
2330
  break;
1997
2331
  }
1998
2332
  }
1999
- else if (expr instanceof validator.QueryExprAccumulator) {
2333
+ else if (expr instanceof validator.QueryUnaryAccumulator) {
2000
2334
  if (!expr.expr)
2001
2335
  throw Error('Invalid expression');
2002
- const exprs = encodeTypedQueryExpression(compiler, populate, expr.expr);
2003
- const value = _.first(exprs)?.sql;
2336
+ const { sql: value } = encodeTypedQueryExpression(compiler, populate, expr.expr) ?? {};
2004
2337
  if (!value)
2005
2338
  throw Error('Invalid expression');
2006
2339
  switch (expr.type) {
@@ -2043,8 +2376,7 @@ const selectPopulate = (compiler, parent, populate, field) => {
2043
2376
  }[expr.mode];
2044
2377
  if (!expr.input)
2045
2378
  throw Error('Invalid expression');
2046
- const exprs = encodeTypedQueryExpression(compiler, populate, expr.input);
2047
- const value = _.first(exprs)?.sql;
2379
+ const { sql: value } = encodeTypedQueryExpression(compiler, populate, expr.input) ?? {};
2048
2380
  if (!value)
2049
2381
  throw Error('Invalid expression');
2050
2382
  columns.push(sql `
@@ -2227,9 +2559,9 @@ const encodeFieldExpression = (compiler, parent, field, expr) => {
2227
2559
  if (_.isNil(expr.value))
2228
2560
  return sql `${element} IS NULL`;
2229
2561
  if (!_.isString(dataType) && dataType?.type === 'pointer') {
2230
- if (!(expr.value instanceof index.TObject) || dataType.target !== expr.value.className || !expr.value.objectId)
2562
+ if (!(expr.value instanceof index.TObject) || dataType.target !== expr.value.className || !expr.value.id)
2231
2563
  break;
2232
- return sql `${element} ${nullSafeEqual()} ${{ value: expr.value.objectId }}`;
2564
+ return sql `${element} ${nullSafeEqual()} ${{ value: expr.value.id }}`;
2233
2565
  }
2234
2566
  return sql `${element} ${nullSafeEqual()} ${encodeValue(expr.value)}`;
2235
2567
  }
@@ -2240,9 +2572,9 @@ const encodeFieldExpression = (compiler, parent, field, expr) => {
2240
2572
  if (_.isNil(expr.value))
2241
2573
  return sql `${element} IS NOT NULL`;
2242
2574
  if (!_.isString(dataType) && dataType?.type === 'pointer') {
2243
- if (!(expr.value instanceof index.TObject) || dataType.target !== expr.value.className || !expr.value.objectId)
2575
+ if (!(expr.value instanceof index.TObject) || dataType.target !== expr.value.className || !expr.value.id)
2244
2576
  break;
2245
- return sql `${element} ${nullSafeNotEqual()} ${{ value: expr.value.objectId }}`;
2577
+ return sql `${element} ${nullSafeNotEqual()} ${{ value: expr.value.id }}`;
2246
2578
  }
2247
2579
  return sql `${element} ${nullSafeNotEqual()} ${encodeValue(expr.value)}`;
2248
2580
  }
@@ -2284,8 +2616,8 @@ const encodeFieldExpression = (compiler, parent, field, expr) => {
2284
2616
  return sql `${element} ${{ literal: op }} ${encodeValue(expr.value)}`;
2285
2617
  }
2286
2618
  }
2287
- else if (!_.isString(dataType) && dataType?.type === 'pointer' && expr.value instanceof index.TObject && expr.value.objectId) {
2288
- return sql `${element} ${{ literal: op }} ${{ value: expr.value.objectId }}`;
2619
+ else if (!_.isString(dataType) && dataType?.type === 'pointer' && expr.value instanceof index.TObject && expr.value.id) {
2620
+ return sql `${element} ${{ literal: op }} ${{ value: expr.value.id }}`;
2289
2621
  }
2290
2622
  else if (!dataType) {
2291
2623
  if (expr.value instanceof Decimal || _.isNumber(expr.value)) {
@@ -2321,9 +2653,9 @@ const encodeFieldExpression = (compiler, parent, field, expr) => {
2321
2653
  if (!_.isString(dataType) && dataType?.type === 'pointer') {
2322
2654
  if (_.isNil(value))
2323
2655
  return sql `${element} IS NULL`;
2324
- if (!(value instanceof index.TObject) || dataType.target !== value.className || !value.objectId)
2656
+ if (!(value instanceof index.TObject) || dataType.target !== value.className || !value.id)
2325
2657
  break;
2326
- return sql `${element} ${nullSafeEqual()} ${{ value: value.objectId }}`;
2658
+ return sql `${element} ${nullSafeEqual()} ${{ value: value.id }}`;
2327
2659
  }
2328
2660
  return sql `${element} ${nullSafeEqual()} ${encodeValue(value)}`;
2329
2661
  }
@@ -2331,12 +2663,12 @@ const encodeFieldExpression = (compiler, parent, field, expr) => {
2331
2663
  const containsNil = _.some(expr.value, x => _.isNil(x));
2332
2664
  const values = _.filter(expr.value, x => !_.isNil(x));
2333
2665
  if (!_.isString(dataType) && dataType?.type === 'pointer') {
2334
- if (!_.every(values, x => x instanceof index.TObject && dataType.target === x.className && x.objectId))
2666
+ if (!_.every(values, x => x instanceof index.TObject && dataType.target === x.className && x.id))
2335
2667
  break;
2336
2668
  if (containsNil) {
2337
- return sql `${element} IS NULL OR ${element} IN (${_.map(values, (x) => sql `${{ value: x.objectId }}`)})`;
2669
+ return sql `${element} IS NULL OR ${element} IN (${_.map(values, (x) => sql `${{ value: x.id }}`)})`;
2338
2670
  }
2339
- return sql `${element} IN (${_.map(values, (x) => sql `${{ value: x.objectId }}`)})`;
2671
+ return sql `${element} IN (${_.map(values, (x) => sql `${{ value: x.id }}`)})`;
2340
2672
  }
2341
2673
  if (containsNil) {
2342
2674
  return sql `${element} IS NULL OR ${element} IN (${_.map(values, x => encodeValue(x))})`;
@@ -2357,9 +2689,9 @@ const encodeFieldExpression = (compiler, parent, field, expr) => {
2357
2689
  if (!_.isString(dataType) && dataType?.type === 'pointer') {
2358
2690
  if (_.isNil(value))
2359
2691
  return sql `${element} IS NOT NULL`;
2360
- if (!(value instanceof index.TObject) || dataType.target !== value.className || !value.objectId)
2692
+ if (!(value instanceof index.TObject) || dataType.target !== value.className || !value.id)
2361
2693
  break;
2362
- return sql `${element} ${nullSafeNotEqual()} ${{ value: value.objectId }}`;
2694
+ return sql `${element} ${nullSafeNotEqual()} ${{ value: value.id }}`;
2363
2695
  }
2364
2696
  return sql `${element} ${nullSafeNotEqual()} ${encodeValue(value)}`;
2365
2697
  }
@@ -2367,12 +2699,12 @@ const encodeFieldExpression = (compiler, parent, field, expr) => {
2367
2699
  const containsNil = _.some(expr.value, x => _.isNil(x));
2368
2700
  const values = _.filter(expr.value, x => !_.isNil(x));
2369
2701
  if (!_.isString(dataType) && dataType?.type === 'pointer') {
2370
- if (!_.every(values, x => x instanceof index.TObject && dataType.target === x.className && x.objectId))
2702
+ if (!_.every(values, x => x instanceof index.TObject && dataType.target === x.className && x.id))
2371
2703
  break;
2372
2704
  if (containsNil) {
2373
- return sql `${element} IS NOT NULL AND ${element} NOT IN (${_.map(values, (x) => sql `${{ value: x.objectId }}`)})`;
2705
+ return sql `${element} IS NOT NULL AND ${element} NOT IN (${_.map(values, (x) => sql `${{ value: x.id }}`)})`;
2374
2706
  }
2375
- return sql `${element} NOT IN (${_.map(values, (x) => sql `${{ value: x.objectId }}`)})`;
2707
+ return sql `${element} NOT IN (${_.map(values, (x) => sql `${{ value: x.id }}`)})`;
2376
2708
  }
2377
2709
  if (containsNil) {
2378
2710
  return sql `${element} IS NOT NULL AND ${element} NOT IN (${_.map(values, x => encodeValue(x))})`;
@@ -2402,14 +2734,14 @@ const encodeFieldExpression = (compiler, parent, field, expr) => {
2402
2734
  return sql `${element} ${{ literal: op }} ${{ value: index._encodeValue(expr.value) }}`;
2403
2735
  }
2404
2736
  if (relation && parent.className) {
2405
- if (!_.every(expr.value, x => x instanceof index.TObject && relation.target === x.className && x.objectId))
2737
+ if (!_.every(expr.value, x => x instanceof index.TObject && relation.target === x.className && x.id))
2406
2738
  break;
2407
2739
  const tempName = `_populate_expr_$${compiler.nextIdx()}`;
2408
2740
  const populate = _selectRelationPopulate(compiler, { className: parent.className, name: parent.name }, relation.populate, `$${field}`, false);
2409
2741
  return sql `ARRAY(
2410
2742
  SELECT ${{ identifier: '_id' }}
2411
2743
  FROM (${populate}) AS ${{ identifier: tempName }}
2412
- ) ${{ literal: op }} ARRAY[${_.map(expr.value, (x) => sql `${{ value: x.objectId }}`)}]::TEXT[]`;
2744
+ ) ${{ literal: op }} ARRAY[${_.map(expr.value, (x) => sql `${{ value: x.id }}`)}]::TEXT[]`;
2413
2745
  }
2414
2746
  if (!dataType) {
2415
2747
  return sql `jsonb_typeof(${element}) ${nullSafeEqual()} 'array' AND ${element} ${{ literal: op }} ${_encodeJsonValue(index._encodeValue(expr.value))}`;
@@ -2632,6 +2964,36 @@ const encodeFieldExpression = (compiler, parent, field, expr) => {
2632
2964
  throw Error('Invalid expression');
2633
2965
  };
2634
2966
 
2967
+ //
2968
+ // index.ts
2969
+ //
2970
+ // The MIT License
2971
+ // Copyright (c) 2021 - 2025 O2ter Limited. All rights reserved.
2972
+ //
2973
+ // Permission is hereby granted, free of charge, to any person obtaining a copy
2974
+ // of this software and associated documentation files (the "Software"), to deal
2975
+ // in the Software without restriction, including without limitation the rights
2976
+ // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
2977
+ // copies of the Software, and to permit persons to whom the Software is
2978
+ // furnished to do so, subject to the following conditions:
2979
+ //
2980
+ // The above copyright notice and this permission notice shall be included in
2981
+ // all copies or substantial portions of the Software.
2982
+ //
2983
+ // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
2984
+ // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2985
+ // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
2986
+ // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
2987
+ // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
2988
+ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
2989
+ // THE SOFTWARE.
2990
+ //
2991
+ const encodeSortExpression = (compiler, parent, expr) => {
2992
+ if (expr instanceof validator.QueryDistanceExpression) {
2993
+ return encodeDistanceQueryExpression(compiler, parent, expr);
2994
+ }
2995
+ };
2996
+
2635
2997
  //
2636
2998
  // relation.ts
2637
2999
  //
@@ -2665,7 +3027,7 @@ const encodeRelation = (compiler, parent, relatedBy) => {
2665
3027
  SELECT 1
2666
3028
  FROM ${{ identifier: relatedBy.className }} AS ${{ identifier: name }}
2667
3029
  ${!_.isEmpty(joins) ? { literal: joins, separator: '\n' } : sql ``}
2668
- WHERE ${_foreign('_id')} = ${{ value: relatedBy.objectId }} AND ${sql `(${{ quote: parent.className + '$' }} || ${_local('_id')})`} = ANY(${field})
3030
+ WHERE ${_foreign('_id')} = ${{ value: relatedBy.id }} AND ${sql `(${{ quote: parent.className + '$' }} || ${_local('_id')})`} = ANY(${field})
2669
3031
  )`;
2670
3032
  };
2671
3033
 
@@ -2703,7 +3065,8 @@ const PostgresDialect = {
2703
3065
  updateOperation,
2704
3066
  selectPopulate,
2705
3067
  encodeFieldExpression,
2706
- encodeQueryExpression,
3068
+ encodeBooleanExpression,
3069
+ encodeSortExpression,
2707
3070
  encodePopulate,
2708
3071
  encodeRelation,
2709
3072
  encodeSortKey,