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
@@ -1,11 +1,11 @@
1
1
  import _ from 'lodash';
2
- import { a as isRelation, i as isPointer, b as isShape, e as decodeUpdateOp, s as shapePaths, c as isPrimitive, T as TObject, _ as _encodeValue, f as dimensionOf, g as _decodeValue, h as _typeof, j as isVector, k as _isTypeof } from '../../internals/index-BzDsTt4R.mjs';
2
+ import { a as isRelation, i as isPointer, b as isShape, e as decodeUpdateOp, s as shapePaths, c as isPrimitive, T as TObject, _ as _encodeValue, f as dimensionOf, g as _decodeValue, h as _typeof, j as isVector, k as _isTypeof } from '../../internals/index-gWcE22mf.mjs';
3
3
  import { Pool, types } from 'pg';
4
4
  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 QueryKeyExpression, h as QueryValueExpression, i as QueryCoditionalExpression, j as QueryComparisonExpression, k as QueryNotExpression, l as QueryDistanceExpression, m as QueryArrayExpression, Q as QueryValidator, n as QueryNoParamAccumulator, o as QueryExprAccumulator, p as QueryPercentileAccumulator, c as QuerySelector, F as FieldSelectorExpression } from '../../internals/validator-LNgZGT_l.mjs';
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-DX2nXeQo.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';
@@ -185,12 +185,12 @@ const _encodeSorting = (includes, populates, sort) => {
185
185
  return sorting;
186
186
  };
187
187
  const _defaultInsertOpts = (options) => {
188
- const objectId = generateId(options.objectIdSize);
188
+ const id = generateId(options.objectIdSize);
189
189
  return {
190
- _id: sql `${{ value: objectId }}`,
190
+ _id: sql `${{ value: id }}`,
191
191
  ...options.className === 'User' ? {
192
- _rperm: sql `${{ value: [objectId] }}`,
193
- _wperm: sql `${{ value: [objectId] }}`,
192
+ _rperm: sql `${{ value: [id] }}`,
193
+ _wperm: sql `${{ value: [id] }}`,
194
194
  } : {},
195
195
  };
196
196
  };
@@ -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.encodeQueryExpression(this, parent, filter.expr);
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.encodeQueryExpression(this, parent, expr);
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' }}`;
@@ -628,12 +628,12 @@ const encodeType = (colname, dataType, value) => {
628
628
  break;
629
629
  return sql `ARRAY[${_.map(value, x => _encodeJsonValue(_encodeValue(x)))}]::JSONB[]`;
630
630
  case 'pointer':
631
- if (value instanceof TObject && value.objectId)
632
- return sql `${{ value: `${value.className}$${value.objectId}` }}`;
631
+ if (value instanceof TObject && value.id)
632
+ return sql `${{ value: `${value.className}$${value.id}` }}`;
633
633
  break;
634
634
  case 'relation':
635
- if (_.isArray(value) && _.every(value, x => x instanceof TObject && x.objectId)) {
636
- return sql `${{ value: _.uniq(_.map(value, (x) => `${x.className}$${x.objectId}`)) }}`;
635
+ if (_.isArray(value) && _.every(value, x => x instanceof TObject && x.id)) {
636
+ return sql `${{ value: _.uniq(_.map(value, (x) => `${x.className}$${x.id}`)) }}`;
637
637
  }
638
638
  break;
639
639
  }
@@ -704,7 +704,7 @@ const decodeType = (type, value) => {
704
704
  };
705
705
 
706
706
  //
707
- // expressions.ts
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 isArrayExpression = (expr) => {
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 mapExpression = (expr, callback) => {
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 _PrimitiveValue = ['boolean', 'number', 'decimal', 'string', 'date'];
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 === 'number') {
757
- return [
758
- { type: 'number', sql: element },
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 [{ type: 'boolean', sql: sql `${{ value: expr.value }}` }];
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 [{ type: 'string', sql: sql `${{ value: expr.value }}` }];
887
+ return { type: 'string', sql: sql `${{ value: expr.value }}` };
787
888
  if (_.isDate(expr.value))
788
- return [{ type: 'date', sql: sql `${{ value: expr.value }}` }];
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 [{ type: 'boolean', sql: value }];
896
+ return { type: 'boolean', sql: value };
796
897
  }
797
898
  if (expr instanceof QueryDistanceExpression) {
798
899
  const value = encodeDistanceQueryExpression(compiler, parent, expr);
799
- return [{ type: 'number', sql: value }];
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 value = encodeQueryExpression(compiler, parent, expr);
826
- if (!value)
1192
+ const typed = encodeTypedQueryExpression(compiler, parent, expr);
1193
+ if (!typed)
827
1194
  throw Error('Invalid expression');
828
- return sql `to_jsonb(${value})`;
829
- };
830
- const encodeVectorExpression = (compiler, parent, exprs) => {
831
- if (exprs.length === 1) {
832
- const [expr] = exprs;
833
- if (expr instanceof QueryKeyExpression) {
834
- const { element, dataType } = fetchElement(compiler, parent, expr.key);
835
- if (!dataType || !isVector(dataType))
836
- throw Error('Invalid expression');
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 (isArrayExpression(expr.left) &&
898
- isArrayExpression(expr.right) &&
1226
+ if (isArrayExpr(expr.left) &&
1227
+ isArrayExpr(expr.right) &&
899
1228
  arrayLength(expr.left) === arrayLength(expr.right)) {
900
- const _left = mapExpression(expr.left, x => encodeTypedQueryExpression(compiler, parent, x));
901
- const _right = mapExpression(expr.right, x => encodeTypedQueryExpression(compiler, parent, x));
902
- const mapped = _.compact(_.map(_.zip(_left, _right), ([l, r]) => matchType(l, r)));
903
- if (mapped.length === _left.length) {
904
- const [l, r] = _.unzip(mapped);
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
- const matched = matchType(_left, _right);
912
- if (matched)
913
- return sql `${matched[0].sql} ${operatorMap[expr.type]} ${matched[1].sql}`;
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
@@ -984,7 +1313,7 @@ class SqlStorage {
984
1313
  const _value = _.get(value, path);
985
1314
  if (_.isPlainObject(_value)) {
986
1315
  const decoded = this._decodeObject(type.target, _value, matchType);
987
- if (decoded.objectId)
1316
+ if (decoded.id)
988
1317
  _.set(result, path, decoded);
989
1318
  }
990
1319
  }
@@ -1024,7 +1353,7 @@ class SqlStorage {
1024
1353
  else if (isPointer(dataType)) {
1025
1354
  if (_.isPlainObject(value)) {
1026
1355
  const decoded = this._decodeObject(dataType.target, value, matchType);
1027
- if (decoded.objectId)
1356
+ if (decoded.id)
1028
1357
  obj[PVK].attributes[key] = decoded;
1029
1358
  }
1030
1359
  }
@@ -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
- sort: sql `ORDER BY ${self.dialect.random(opts?.weight ? _.first(encodeTypedQueryExpression(compiler, {
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))?.sql : undefined)}`,
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) {
@@ -1112,7 +1446,7 @@ class SqlStorage {
1112
1446
  const self = this;
1113
1447
  const query = sql `
1114
1448
  SELECT *
1115
- FROM (${this._refs(_.pick(this.schema, classNames), object.className, TObject.defaultKeys, sql `${{ value: `${object.className}$${object.objectId}` }}`)}) AS "$"
1449
+ FROM (${this._refs(_.pick(this.schema, classNames), object.className, TObject.defaultKeys, sql `${{ value: `${object.className}$${object.id}` }}`)}) AS "$"
1116
1450
  ${_.isNil(roles) ? sql `` : sql `WHERE ${{ identifier: '$' }}.${{ identifier: '_rperm' }} && ${{ value: roles }}`}
1117
1451
  `;
1118
1452
  return (async function* () {
@@ -1703,25 +2037,25 @@ const updateOperation = (paths, dataType, operation) => {
1703
2037
  case '$addToSet':
1704
2038
  case '$push':
1705
2039
  {
1706
- if (!_.isArray(value) || !_.every(value, x => x instanceof TObject && x.objectId))
2040
+ if (!_.isArray(value) || !_.every(value, x => x instanceof TObject && x.id))
1707
2041
  break;
1708
- const objectIds = _.uniq(_.map(value, (x) => `${x.className}$${x.objectId}`));
2042
+ const ids = _.uniq(_.map(value, (x) => `${x.className}$${x.id}`));
1709
2043
  return sql `ARRAY(
1710
2044
  SELECT DISTINCT "$"
1711
- FROM UNNEST(${{ identifier: column }} || ARRAY[${_.map(objectIds, (x) => sql `${{ value: x }}`)}]) "$"
2045
+ FROM UNNEST(${{ identifier: column }} || ARRAY[${_.map(ids, (x) => sql `${{ value: x }}`)}]) "$"
1712
2046
  RIGHT JOIN ${{ identifier: dataType.target }} ON "$" = (${{ quote: dataType.target + '$' }} || ${{ identifier: dataType.target }}._id)
1713
2047
  )`;
1714
2048
  }
1715
2049
  case '$removeAll':
1716
2050
  {
1717
- if (!_.isArray(value) || !_.every(value, x => x instanceof TObject && x.objectId))
2051
+ if (!_.isArray(value) || !_.every(value, x => x instanceof TObject && x.id))
1718
2052
  break;
1719
- const objectIds = _.uniq(_.map(value, (x) => `${x.className}$${x.objectId}`));
2053
+ const ids = _.uniq(_.map(value, (x) => `${x.className}$${x.id}`));
1720
2054
  return sql `ARRAY(
1721
2055
  SELECT "$"
1722
2056
  FROM UNNEST(${{ identifier: column }}) "$"
1723
2057
  RIGHT JOIN ${{ identifier: dataType.target }} ON "$" = (${{ quote: dataType.target + '$' }} || ${{ identifier: dataType.target }}._id)
1724
- WHERE "$" NOT IN (${_.map(objectIds, (x) => sql `${{ value: x }}`)})
2058
+ WHERE "$" NOT IN (${_.map(ids, (x) => sql `${{ value: x }}`)})
1725
2059
  )`;
1726
2060
  }
1727
2061
  }
@@ -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 QueryNoParamAccumulator) {
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 QueryExprAccumulator) {
2329
+ else if (expr instanceof QueryUnaryAccumulator) {
1996
2330
  if (!expr.expr)
1997
2331
  throw Error('Invalid expression');
1998
- const exprs = encodeTypedQueryExpression(compiler, populate, expr.expr);
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 exprs = encodeTypedQueryExpression(compiler, populate, expr.input);
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 `
@@ -2223,9 +2555,9 @@ const encodeFieldExpression = (compiler, parent, field, expr) => {
2223
2555
  if (_.isNil(expr.value))
2224
2556
  return sql `${element} IS NULL`;
2225
2557
  if (!_.isString(dataType) && dataType?.type === 'pointer') {
2226
- if (!(expr.value instanceof TObject) || dataType.target !== expr.value.className || !expr.value.objectId)
2558
+ if (!(expr.value instanceof TObject) || dataType.target !== expr.value.className || !expr.value.id)
2227
2559
  break;
2228
- return sql `${element} ${nullSafeEqual()} ${{ value: expr.value.objectId }}`;
2560
+ return sql `${element} ${nullSafeEqual()} ${{ value: expr.value.id }}`;
2229
2561
  }
2230
2562
  return sql `${element} ${nullSafeEqual()} ${encodeValue(expr.value)}`;
2231
2563
  }
@@ -2236,9 +2568,9 @@ const encodeFieldExpression = (compiler, parent, field, expr) => {
2236
2568
  if (_.isNil(expr.value))
2237
2569
  return sql `${element} IS NOT NULL`;
2238
2570
  if (!_.isString(dataType) && dataType?.type === 'pointer') {
2239
- if (!(expr.value instanceof TObject) || dataType.target !== expr.value.className || !expr.value.objectId)
2571
+ if (!(expr.value instanceof TObject) || dataType.target !== expr.value.className || !expr.value.id)
2240
2572
  break;
2241
- return sql `${element} ${nullSafeNotEqual()} ${{ value: expr.value.objectId }}`;
2573
+ return sql `${element} ${nullSafeNotEqual()} ${{ value: expr.value.id }}`;
2242
2574
  }
2243
2575
  return sql `${element} ${nullSafeNotEqual()} ${encodeValue(expr.value)}`;
2244
2576
  }
@@ -2280,8 +2612,8 @@ const encodeFieldExpression = (compiler, parent, field, expr) => {
2280
2612
  return sql `${element} ${{ literal: op }} ${encodeValue(expr.value)}`;
2281
2613
  }
2282
2614
  }
2283
- else if (!_.isString(dataType) && dataType?.type === 'pointer' && expr.value instanceof TObject && expr.value.objectId) {
2284
- return sql `${element} ${{ literal: op }} ${{ value: expr.value.objectId }}`;
2615
+ else if (!_.isString(dataType) && dataType?.type === 'pointer' && expr.value instanceof TObject && expr.value.id) {
2616
+ return sql `${element} ${{ literal: op }} ${{ value: expr.value.id }}`;
2285
2617
  }
2286
2618
  else if (!dataType) {
2287
2619
  if (expr.value instanceof Decimal || _.isNumber(expr.value)) {
@@ -2317,9 +2649,9 @@ const encodeFieldExpression = (compiler, parent, field, expr) => {
2317
2649
  if (!_.isString(dataType) && dataType?.type === 'pointer') {
2318
2650
  if (_.isNil(value))
2319
2651
  return sql `${element} IS NULL`;
2320
- if (!(value instanceof TObject) || dataType.target !== value.className || !value.objectId)
2652
+ if (!(value instanceof TObject) || dataType.target !== value.className || !value.id)
2321
2653
  break;
2322
- return sql `${element} ${nullSafeEqual()} ${{ value: value.objectId }}`;
2654
+ return sql `${element} ${nullSafeEqual()} ${{ value: value.id }}`;
2323
2655
  }
2324
2656
  return sql `${element} ${nullSafeEqual()} ${encodeValue(value)}`;
2325
2657
  }
@@ -2327,12 +2659,12 @@ const encodeFieldExpression = (compiler, parent, field, expr) => {
2327
2659
  const containsNil = _.some(expr.value, x => _.isNil(x));
2328
2660
  const values = _.filter(expr.value, x => !_.isNil(x));
2329
2661
  if (!_.isString(dataType) && dataType?.type === 'pointer') {
2330
- if (!_.every(values, x => x instanceof TObject && dataType.target === x.className && x.objectId))
2662
+ if (!_.every(values, x => x instanceof TObject && dataType.target === x.className && x.id))
2331
2663
  break;
2332
2664
  if (containsNil) {
2333
- return sql `${element} IS NULL OR ${element} IN (${_.map(values, (x) => sql `${{ value: x.objectId }}`)})`;
2665
+ return sql `${element} IS NULL OR ${element} IN (${_.map(values, (x) => sql `${{ value: x.id }}`)})`;
2334
2666
  }
2335
- return sql `${element} IN (${_.map(values, (x) => sql `${{ value: x.objectId }}`)})`;
2667
+ return sql `${element} IN (${_.map(values, (x) => sql `${{ value: x.id }}`)})`;
2336
2668
  }
2337
2669
  if (containsNil) {
2338
2670
  return sql `${element} IS NULL OR ${element} IN (${_.map(values, x => encodeValue(x))})`;
@@ -2353,9 +2685,9 @@ const encodeFieldExpression = (compiler, parent, field, expr) => {
2353
2685
  if (!_.isString(dataType) && dataType?.type === 'pointer') {
2354
2686
  if (_.isNil(value))
2355
2687
  return sql `${element} IS NOT NULL`;
2356
- if (!(value instanceof TObject) || dataType.target !== value.className || !value.objectId)
2688
+ if (!(value instanceof TObject) || dataType.target !== value.className || !value.id)
2357
2689
  break;
2358
- return sql `${element} ${nullSafeNotEqual()} ${{ value: value.objectId }}`;
2690
+ return sql `${element} ${nullSafeNotEqual()} ${{ value: value.id }}`;
2359
2691
  }
2360
2692
  return sql `${element} ${nullSafeNotEqual()} ${encodeValue(value)}`;
2361
2693
  }
@@ -2363,12 +2695,12 @@ const encodeFieldExpression = (compiler, parent, field, expr) => {
2363
2695
  const containsNil = _.some(expr.value, x => _.isNil(x));
2364
2696
  const values = _.filter(expr.value, x => !_.isNil(x));
2365
2697
  if (!_.isString(dataType) && dataType?.type === 'pointer') {
2366
- if (!_.every(values, x => x instanceof TObject && dataType.target === x.className && x.objectId))
2698
+ if (!_.every(values, x => x instanceof TObject && dataType.target === x.className && x.id))
2367
2699
  break;
2368
2700
  if (containsNil) {
2369
- return sql `${element} IS NOT NULL AND ${element} NOT IN (${_.map(values, (x) => sql `${{ value: x.objectId }}`)})`;
2701
+ return sql `${element} IS NOT NULL AND ${element} NOT IN (${_.map(values, (x) => sql `${{ value: x.id }}`)})`;
2370
2702
  }
2371
- return sql `${element} NOT IN (${_.map(values, (x) => sql `${{ value: x.objectId }}`)})`;
2703
+ return sql `${element} NOT IN (${_.map(values, (x) => sql `${{ value: x.id }}`)})`;
2372
2704
  }
2373
2705
  if (containsNil) {
2374
2706
  return sql `${element} IS NOT NULL AND ${element} NOT IN (${_.map(values, x => encodeValue(x))})`;
@@ -2398,14 +2730,14 @@ const encodeFieldExpression = (compiler, parent, field, expr) => {
2398
2730
  return sql `${element} ${{ literal: op }} ${{ value: _encodeValue(expr.value) }}`;
2399
2731
  }
2400
2732
  if (relation && parent.className) {
2401
- if (!_.every(expr.value, x => x instanceof TObject && relation.target === x.className && x.objectId))
2733
+ if (!_.every(expr.value, x => x instanceof TObject && relation.target === x.className && x.id))
2402
2734
  break;
2403
2735
  const tempName = `_populate_expr_$${compiler.nextIdx()}`;
2404
2736
  const populate = _selectRelationPopulate(compiler, { className: parent.className, name: parent.name }, relation.populate, `$${field}`, false);
2405
2737
  return sql `ARRAY(
2406
2738
  SELECT ${{ identifier: '_id' }}
2407
2739
  FROM (${populate}) AS ${{ identifier: tempName }}
2408
- ) ${{ literal: op }} ARRAY[${_.map(expr.value, (x) => sql `${{ value: x.objectId }}`)}]::TEXT[]`;
2740
+ ) ${{ literal: op }} ARRAY[${_.map(expr.value, (x) => sql `${{ value: x.id }}`)}]::TEXT[]`;
2409
2741
  }
2410
2742
  if (!dataType) {
2411
2743
  return sql `jsonb_typeof(${element}) ${nullSafeEqual()} 'array' AND ${element} ${{ literal: op }} ${_encodeJsonValue(_encodeValue(expr.value))}`;
@@ -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
  //
@@ -2661,7 +3023,7 @@ const encodeRelation = (compiler, parent, relatedBy) => {
2661
3023
  SELECT 1
2662
3024
  FROM ${{ identifier: relatedBy.className }} AS ${{ identifier: name }}
2663
3025
  ${!_.isEmpty(joins) ? { literal: joins, separator: '\n' } : sql ``}
2664
- WHERE ${_foreign('_id')} = ${{ value: relatedBy.objectId }} AND ${sql `(${{ quote: parent.className + '$' }} || ${_local('_id')})`} = ANY(${field})
3026
+ WHERE ${_foreign('_id')} = ${{ value: relatedBy.id }} AND ${sql `(${{ quote: parent.className + '$' }} || ${_local('_id')})`} = ANY(${field})
2665
3027
  )`;
2666
3028
  };
2667
3029
 
@@ -2699,7 +3061,8 @@ const PostgresDialect = {
2699
3061
  updateOperation,
2700
3062
  selectPopulate,
2701
3063
  encodeFieldExpression,
2702
- encodeQueryExpression,
3064
+ encodeBooleanExpression,
3065
+ encodeSortExpression,
2703
3066
  encodePopulate,
2704
3067
  encodeRelation,
2705
3068
  encodeSortKey,