jsonbadger 0.5.0 → 0.6.0

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 (123) hide show
  1. package/README.md +36 -18
  2. package/docs/api/connection.md +144 -0
  3. package/docs/api/delta-tracker.md +106 -0
  4. package/docs/api/document.md +77 -0
  5. package/docs/api/field-types.md +329 -0
  6. package/docs/api/index.md +35 -0
  7. package/docs/api/model.md +392 -0
  8. package/docs/api/query-builder.md +81 -0
  9. package/docs/api/schema.md +204 -0
  10. package/docs/architecture-flow.md +397 -0
  11. package/docs/examples.md +495 -218
  12. package/docs/jsonb-ops.md +171 -0
  13. package/docs/lifecycle/model-compilation.md +111 -0
  14. package/docs/lifecycle.md +146 -0
  15. package/docs/query-translation.md +11 -10
  16. package/package.json +10 -3
  17. package/src/connection/connect.js +12 -17
  18. package/src/connection/connection.js +128 -0
  19. package/src/connection/server-capabilities.js +60 -59
  20. package/src/constants/defaults.js +32 -19
  21. package/src/constants/{id-strategies.js → id-strategy.js} +28 -29
  22. package/src/constants/intake-mode.js +8 -0
  23. package/src/debug/debug-logger.js +17 -15
  24. package/src/errors/model-overwrite-error.js +25 -0
  25. package/src/errors/query-error.js +25 -23
  26. package/src/errors/validation-error.js +25 -23
  27. package/src/field-types/base-field-type.js +137 -140
  28. package/src/field-types/builtins/advanced.js +365 -365
  29. package/src/field-types/builtins/index.js +579 -585
  30. package/src/field-types/field-type-namespace.js +9 -0
  31. package/src/field-types/registry.js +149 -122
  32. package/src/index.js +26 -36
  33. package/src/migration/ensure-index.js +157 -154
  34. package/src/migration/ensure-schema.js +27 -15
  35. package/src/migration/ensure-table.js +44 -31
  36. package/src/migration/schema-indexes-resolver.js +8 -6
  37. package/src/model/document-instance.js +29 -540
  38. package/src/model/document.js +60 -0
  39. package/src/model/factory/constants.js +36 -0
  40. package/src/model/factory/index.js +58 -0
  41. package/src/model/model.js +875 -0
  42. package/src/model/operations/delete-one.js +39 -0
  43. package/src/model/operations/insert-one.js +35 -0
  44. package/src/model/operations/query-builder.js +132 -0
  45. package/src/model/operations/update-one.js +333 -0
  46. package/src/model/state.js +34 -0
  47. package/src/schema/field-definition-parser.js +213 -218
  48. package/src/schema/path-introspection.js +87 -82
  49. package/src/schema/schema-compiler.js +126 -212
  50. package/src/schema/schema.js +621 -138
  51. package/src/sql/index.js +17 -0
  52. package/src/sql/jsonb/ops.js +153 -0
  53. package/src/{query → sql/jsonb}/path-parser.js +54 -43
  54. package/src/sql/jsonb/read/elem-match.js +133 -0
  55. package/src/{query → sql/jsonb/read}/operators/contains.js +13 -7
  56. package/src/sql/jsonb/read/operators/elem-match.js +9 -0
  57. package/src/{query → sql/jsonb/read}/operators/has-all-keys.js +17 -11
  58. package/src/{query → sql/jsonb/read}/operators/has-any-keys.js +18 -11
  59. package/src/sql/jsonb/read/operators/has-key.js +12 -0
  60. package/src/{query → sql/jsonb/read}/operators/jsonpath-exists.js +22 -15
  61. package/src/{query → sql/jsonb/read}/operators/jsonpath-match.js +22 -15
  62. package/src/{query → sql/jsonb/read}/operators/size.js +23 -16
  63. package/src/sql/parameter-binder.js +18 -13
  64. package/src/sql/read/build-count-query.js +12 -0
  65. package/src/sql/read/build-find-query.js +25 -0
  66. package/src/sql/read/limit-skip.js +21 -0
  67. package/src/sql/read/sort.js +85 -0
  68. package/src/sql/read/where/base-fields.js +310 -0
  69. package/src/sql/read/where/casting.js +90 -0
  70. package/src/sql/read/where/context.js +79 -0
  71. package/src/sql/read/where/field-clause.js +58 -0
  72. package/src/sql/read/where/index.js +38 -0
  73. package/src/sql/read/where/operator-entries.js +29 -0
  74. package/src/{query → sql/read/where}/operators/all.js +16 -10
  75. package/src/sql/read/where/operators/eq.js +12 -0
  76. package/src/{query → sql/read/where}/operators/gt.js +23 -16
  77. package/src/{query → sql/read/where}/operators/gte.js +23 -16
  78. package/src/{query → sql/read/where}/operators/in.js +18 -12
  79. package/src/sql/read/where/operators/index.js +40 -0
  80. package/src/{query → sql/read/where}/operators/lt.js +23 -16
  81. package/src/{query → sql/read/where}/operators/lte.js +23 -16
  82. package/src/sql/read/where/operators/ne.js +12 -0
  83. package/src/{query → sql/read/where}/operators/nin.js +18 -12
  84. package/src/{query → sql/read/where}/operators/regex.js +14 -8
  85. package/src/sql/read/where/operators.js +126 -0
  86. package/src/sql/read/where/text-operators.js +83 -0
  87. package/src/sql/run.js +46 -0
  88. package/src/sql/write/build-delete-query.js +33 -0
  89. package/src/sql/write/build-insert-query.js +42 -0
  90. package/src/sql/write/build-update-query.js +65 -0
  91. package/src/utils/assert.js +34 -27
  92. package/src/utils/delta-tracker/.archive/1 tracker-redesign-codex-v2.md +250 -0
  93. package/src/utils/delta-tracker/.archive/1 tracker-redesign-gemini.md +101 -0
  94. package/src/utils/delta-tracker/.archive/2 evaluation by gemini.txt +65 -0
  95. package/src/utils/delta-tracker/.archive/2 evaluation by grok.txt +39 -0
  96. package/src/utils/delta-tracker/.archive/3 gemini evaluate grok.txt +37 -0
  97. package/src/utils/delta-tracker/.archive/3 grok evaluate gemini.txt +63 -0
  98. package/src/utils/delta-tracker/.archive/4 gemini veredict.txt +16 -0
  99. package/src/utils/delta-tracker/.archive/index.1.js +587 -0
  100. package/src/utils/delta-tracker/.archive/index.2.js +612 -0
  101. package/src/utils/delta-tracker/index.js +592 -0
  102. package/src/utils/dirty-tracker/inline.js +335 -0
  103. package/src/utils/dirty-tracker/instance.js +414 -0
  104. package/src/utils/dirty-tracker/static.js +343 -0
  105. package/src/utils/json-safe.js +13 -9
  106. package/src/utils/object-path.js +227 -33
  107. package/src/utils/object.js +408 -168
  108. package/src/utils/string.js +55 -0
  109. package/src/utils/value.js +169 -30
  110. package/docs/api.md +0 -152
  111. package/src/connection/disconnect.js +0 -16
  112. package/src/connection/pool-store.js +0 -46
  113. package/src/model/model-factory.js +0 -555
  114. package/src/query/limit-skip-compiler.js +0 -31
  115. package/src/query/operators/elem-match.js +0 -3
  116. package/src/query/operators/eq.js +0 -6
  117. package/src/query/operators/has-key.js +0 -6
  118. package/src/query/operators/index.js +0 -60
  119. package/src/query/operators/ne.js +0 -6
  120. package/src/query/query-builder.js +0 -93
  121. package/src/query/sort-compiler.js +0 -30
  122. package/src/query/where-compiler.js +0 -477
  123. package/src/sql/sql-runner.js +0 -31
@@ -0,0 +1,38 @@
1
+ /*
2
+ * MODULE RESPONSIBILITY
3
+ * Compile one read-query filter object into SQL and bound params.
4
+ */
5
+ import {create_parameter_state} from '#src/sql/parameter-binder.js';
6
+
7
+ import {create_compile_context} from '#src/sql/read/where/context.js';
8
+ import {compile_field_clause} from '#src/sql/read/where/field-clause.js';
9
+
10
+ function where_compiler(query_filter, compile_options, start_index) {
11
+ const filter_object = query_filter ?? {};
12
+ const compile_context = create_compile_context(compile_options);
13
+ const parameter_state = create_parameter_state(start_index);
14
+ const filter_entries = Object.entries(filter_object);
15
+ const clause_list = [];
16
+ let entry_index = 0;
17
+
18
+ while(entry_index < filter_entries.length) {
19
+ const entry_pair = filter_entries[entry_index];
20
+ const path_value = entry_pair[0];
21
+ const comparison_value = entry_pair[1];
22
+ const clause = compile_field_clause(path_value, comparison_value, compile_context, parameter_state);
23
+
24
+ if(clause) {
25
+ clause_list.push(clause);
26
+ }
27
+
28
+ entry_index += 1;
29
+ }
30
+
31
+ return {
32
+ sql: clause_list.length > 0 ? clause_list.join(' AND ') : 'TRUE',
33
+ params: parameter_state.params,
34
+ next_index: parameter_state.current_index
35
+ };
36
+ }
37
+
38
+ export default where_compiler;
@@ -0,0 +1,29 @@
1
+ /*
2
+ * MODULE RESPONSIBILITY
3
+ * Iterate operator entries and compile their clause fragments.
4
+ */
5
+ function compile_operator_entry_clauses(operator_definition, compile_operator_clause) {
6
+ const clause_list = [];
7
+ const operator_entries = Object.entries(operator_definition);
8
+ let entry_index = 0;
9
+
10
+ while(entry_index < operator_entries.length) {
11
+ const operator_entry = operator_entries[entry_index];
12
+ const operator_name = operator_entry[0];
13
+ const operator_value = operator_entry[1];
14
+
15
+ if(operator_name === '$options') {
16
+ entry_index += 1;
17
+ continue;
18
+ }
19
+
20
+ clause_list.push(compile_operator_clause(operator_name, operator_value));
21
+ entry_index += 1;
22
+ }
23
+
24
+ return clause_list;
25
+ }
26
+
27
+ export {
28
+ compile_operator_entry_clauses
29
+ };
@@ -1,10 +1,16 @@
1
- import {bind_parameter} from '#src/sql/parameter-binder.js';
2
- import {jsonb_stringify} from '#src/utils/json.js';
3
- import {to_array} from '#src/utils/array.js';
4
-
5
- export default function all_operator(jsonb_expression, comparison_value, parameter_state) {
6
- const value_list = to_array(comparison_value);
7
- const placeholder = bind_parameter(parameter_state, jsonb_stringify(value_list));
8
-
9
- return jsonb_expression + ' @> ' + placeholder + '::jsonb';
10
- }
1
+ /*
2
+ * MODULE RESPONSIBILITY
3
+ * Compile the SQL fragment for the $all read-query operator.
4
+ */
5
+ import {bind_parameter} from '#src/sql/parameter-binder.js';
6
+ import {jsonb_stringify} from '#src/utils/json.js';
7
+ import {to_array} from '#src/utils/array.js';
8
+
9
+ function all_operator(jsonb_expression, comparison_value, parameter_state) {
10
+ const value_list = to_array(comparison_value);
11
+ const placeholder = bind_parameter(parameter_state, jsonb_stringify(value_list));
12
+
13
+ return jsonb_expression + ' @> ' + placeholder + '::jsonb';
14
+ }
15
+
16
+ export default all_operator;
@@ -0,0 +1,12 @@
1
+ /*
2
+ * MODULE RESPONSIBILITY
3
+ * Compile the SQL fragment for the $eq read-query operator.
4
+ */
5
+ import {bind_parameter} from '#src/sql/parameter-binder.js';
6
+
7
+ function eq_operator(sql_expression, comparison_value, parameter_state) {
8
+ const placeholder = bind_parameter(parameter_state, String(comparison_value));
9
+ return sql_expression + ' = ' + placeholder;
10
+ }
11
+
12
+ export default eq_operator;
@@ -1,16 +1,23 @@
1
- import QueryError from '#src/errors/query-error.js';
2
- import {bind_parameter} from '#src/sql/parameter-binder.js';
3
- import {is_nan} from '#src/utils/value.js';
4
-
5
- export default function gt_operator(sql_expression, comparison_value, parameter_state) {
6
- if(is_nan(comparison_value)) {
7
- throw new QueryError('Invalid value for $gt operator', {
8
- operator: '$gt',
9
- value: comparison_value
10
- });
11
- }
12
-
13
- const numeric_value = typeof comparison_value === 'bigint' ? comparison_value.toString() : Number(comparison_value);
14
- const placeholder = bind_parameter(parameter_state, numeric_value);
15
- return '(' + sql_expression + ')::numeric > ' + placeholder;
16
- }
1
+ /*
2
+ * MODULE RESPONSIBILITY
3
+ * Compile the SQL fragment for the $gt read-query operator.
4
+ */
5
+ import QueryError from '#src/errors/query-error.js';
6
+ import {bind_parameter} from '#src/sql/parameter-binder.js';
7
+ import {is_nan} from '#src/utils/value.js';
8
+
9
+ function gt_operator(sql_expression, comparison_value, parameter_state) {
10
+ if(is_nan(comparison_value)) {
11
+ throw new QueryError('Invalid value for $gt operator', {
12
+ operator: '$gt',
13
+ value: comparison_value
14
+ });
15
+ }
16
+
17
+ const numeric_value = typeof comparison_value === 'bigint' ? comparison_value.toString() : Number(comparison_value);
18
+ const placeholder = bind_parameter(parameter_state, numeric_value);
19
+
20
+ return '(' + sql_expression + ')::numeric > ' + placeholder;
21
+ }
22
+
23
+ export default gt_operator;
@@ -1,16 +1,23 @@
1
- import QueryError from '#src/errors/query-error.js';
2
- import {bind_parameter} from '#src/sql/parameter-binder.js';
3
- import {is_nan} from '#src/utils/value.js';
4
-
5
- export default function gte_operator(sql_expression, comparison_value, parameter_state) {
6
- if(is_nan(comparison_value)) {
7
- throw new QueryError('Invalid value for $gte operator', {
8
- operator: '$gte',
9
- value: comparison_value
10
- });
11
- }
12
-
13
- const numeric_value = typeof comparison_value === 'bigint' ? comparison_value.toString() : Number(comparison_value);
14
- const placeholder = bind_parameter(parameter_state, numeric_value);
15
- return '(' + sql_expression + ')::numeric >= ' + placeholder;
16
- }
1
+ /*
2
+ * MODULE RESPONSIBILITY
3
+ * Compile the SQL fragment for the $gte read-query operator.
4
+ */
5
+ import QueryError from '#src/errors/query-error.js';
6
+ import {bind_parameter} from '#src/sql/parameter-binder.js';
7
+ import {is_nan} from '#src/utils/value.js';
8
+
9
+ function gte_operator(sql_expression, comparison_value, parameter_state) {
10
+ if(is_nan(comparison_value)) {
11
+ throw new QueryError('Invalid value for $gte operator', {
12
+ operator: '$gte',
13
+ value: comparison_value
14
+ });
15
+ }
16
+
17
+ const numeric_value = typeof comparison_value === 'bigint' ? comparison_value.toString() : Number(comparison_value);
18
+ const placeholder = bind_parameter(parameter_state, numeric_value);
19
+
20
+ return '(' + sql_expression + ')::numeric >= ' + placeholder;
21
+ }
22
+
23
+ export default gte_operator;
@@ -1,12 +1,18 @@
1
- import {bind_parameter} from '#src/sql/parameter-binder.js';
2
- import {to_array} from '#src/utils/array.js';
3
-
4
- export default function in_operator(sql_expression, comparison_value, parameter_state) {
5
- const value_list = to_array(comparison_value);
6
- const normalized_values = value_list.map(function map_value(current_value) {
7
- return String(current_value);
8
- });
9
- const placeholder = bind_parameter(parameter_state, normalized_values);
10
-
11
- return sql_expression + ' = ANY(' + placeholder + '::text[])';
12
- }
1
+ /*
2
+ * MODULE RESPONSIBILITY
3
+ * Compile the SQL fragment for the $in read-query operator.
4
+ */
5
+ import {bind_parameter} from '#src/sql/parameter-binder.js';
6
+ import {to_array} from '#src/utils/array.js';
7
+
8
+ function in_operator(sql_expression, comparison_value, parameter_state) {
9
+ const value_list = to_array(comparison_value);
10
+ const normalized_values = value_list.map(function map_value(current_value) {
11
+ return String(current_value);
12
+ });
13
+ const placeholder = bind_parameter(parameter_state, normalized_values);
14
+
15
+ return sql_expression + ' = ANY(' + placeholder + '::text[])';
16
+ }
17
+
18
+ export default in_operator;
@@ -0,0 +1,40 @@
1
+ /*
2
+ * MODULE RESPONSIBILITY
3
+ * Expose the read-query operator fragment registry.
4
+ */
5
+ import all_operator from './all.js';
6
+ import eq_operator from './eq.js';
7
+ import gt_operator from './gt.js';
8
+ import gte_operator from './gte.js';
9
+ import in_operator from './in.js';
10
+ import lt_operator from './lt.js';
11
+ import lte_operator from './lte.js';
12
+ import ne_operator from './ne.js';
13
+ import nin_operator from './nin.js';
14
+ import regex_operator from './regex.js';
15
+
16
+ export {
17
+ all_operator,
18
+ eq_operator,
19
+ gt_operator,
20
+ gte_operator,
21
+ in_operator,
22
+ lt_operator,
23
+ lte_operator,
24
+ ne_operator,
25
+ nin_operator,
26
+ regex_operator
27
+ };
28
+
29
+ export default {
30
+ all_operator,
31
+ eq_operator,
32
+ gt_operator,
33
+ gte_operator,
34
+ in_operator,
35
+ lt_operator,
36
+ lte_operator,
37
+ ne_operator,
38
+ nin_operator,
39
+ regex_operator
40
+ };
@@ -1,16 +1,23 @@
1
- import QueryError from '#src/errors/query-error.js';
2
- import {bind_parameter} from '#src/sql/parameter-binder.js';
3
- import {is_nan} from '#src/utils/value.js';
4
-
5
- export default function lt_operator(sql_expression, comparison_value, parameter_state) {
6
- if(is_nan(comparison_value)) {
7
- throw new QueryError('Invalid value for $lt operator', {
8
- operator: '$lt',
9
- value: comparison_value
10
- });
11
- }
12
-
13
- const numeric_value = typeof comparison_value === 'bigint' ? comparison_value.toString() : Number(comparison_value);
14
- const placeholder = bind_parameter(parameter_state, numeric_value);
15
- return '(' + sql_expression + ')::numeric < ' + placeholder;
16
- }
1
+ /*
2
+ * MODULE RESPONSIBILITY
3
+ * Compile the SQL fragment for the $lt read-query operator.
4
+ */
5
+ import QueryError from '#src/errors/query-error.js';
6
+ import {bind_parameter} from '#src/sql/parameter-binder.js';
7
+ import {is_nan} from '#src/utils/value.js';
8
+
9
+ function lt_operator(sql_expression, comparison_value, parameter_state) {
10
+ if(is_nan(comparison_value)) {
11
+ throw new QueryError('Invalid value for $lt operator', {
12
+ operator: '$lt',
13
+ value: comparison_value
14
+ });
15
+ }
16
+
17
+ const numeric_value = typeof comparison_value === 'bigint' ? comparison_value.toString() : Number(comparison_value);
18
+ const placeholder = bind_parameter(parameter_state, numeric_value);
19
+
20
+ return '(' + sql_expression + ')::numeric < ' + placeholder;
21
+ }
22
+
23
+ export default lt_operator;
@@ -1,16 +1,23 @@
1
- import QueryError from '#src/errors/query-error.js';
2
- import {bind_parameter} from '#src/sql/parameter-binder.js';
3
- import {is_nan} from '#src/utils/value.js';
4
-
5
- export default function lte_operator(sql_expression, comparison_value, parameter_state) {
6
- if(is_nan(comparison_value)) {
7
- throw new QueryError('Invalid value for $lte operator', {
8
- operator: '$lte',
9
- value: comparison_value
10
- });
11
- }
12
-
13
- const numeric_value = typeof comparison_value === 'bigint' ? comparison_value.toString() : Number(comparison_value);
14
- const placeholder = bind_parameter(parameter_state, numeric_value);
15
- return '(' + sql_expression + ')::numeric <= ' + placeholder;
16
- }
1
+ /*
2
+ * MODULE RESPONSIBILITY
3
+ * Compile the SQL fragment for the $lte read-query operator.
4
+ */
5
+ import QueryError from '#src/errors/query-error.js';
6
+ import {bind_parameter} from '#src/sql/parameter-binder.js';
7
+ import {is_nan} from '#src/utils/value.js';
8
+
9
+ function lte_operator(sql_expression, comparison_value, parameter_state) {
10
+ if(is_nan(comparison_value)) {
11
+ throw new QueryError('Invalid value for $lte operator', {
12
+ operator: '$lte',
13
+ value: comparison_value
14
+ });
15
+ }
16
+
17
+ const numeric_value = typeof comparison_value === 'bigint' ? comparison_value.toString() : Number(comparison_value);
18
+ const placeholder = bind_parameter(parameter_state, numeric_value);
19
+
20
+ return '(' + sql_expression + ')::numeric <= ' + placeholder;
21
+ }
22
+
23
+ export default lte_operator;
@@ -0,0 +1,12 @@
1
+ /*
2
+ * MODULE RESPONSIBILITY
3
+ * Compile the SQL fragment for the $ne read-query operator.
4
+ */
5
+ import {bind_parameter} from '#src/sql/parameter-binder.js';
6
+
7
+ function ne_operator(sql_expression, comparison_value, parameter_state) {
8
+ const placeholder = bind_parameter(parameter_state, String(comparison_value));
9
+ return sql_expression + ' != ' + placeholder;
10
+ }
11
+
12
+ export default ne_operator;
@@ -1,12 +1,18 @@
1
- import {bind_parameter} from '#src/sql/parameter-binder.js';
2
- import {to_array} from '#src/utils/array.js';
3
-
4
- export default function nin_operator(sql_expression, comparison_value, parameter_state) {
5
- const value_list = to_array(comparison_value);
6
- const normalized_values = value_list.map(function map_value(current_value) {
7
- return String(current_value);
8
- });
9
- const placeholder = bind_parameter(parameter_state, normalized_values);
10
-
11
- return 'NOT (' + sql_expression + ' = ANY(' + placeholder + '::text[]))';
12
- }
1
+ /*
2
+ * MODULE RESPONSIBILITY
3
+ * Compile the SQL fragment for the $nin read-query operator.
4
+ */
5
+ import {bind_parameter} from '#src/sql/parameter-binder.js';
6
+ import {to_array} from '#src/utils/array.js';
7
+
8
+ function nin_operator(sql_expression, comparison_value, parameter_state) {
9
+ const value_list = to_array(comparison_value);
10
+ const normalized_values = value_list.map(function map_value(current_value) {
11
+ return String(current_value);
12
+ });
13
+ const placeholder = bind_parameter(parameter_state, normalized_values);
14
+
15
+ return 'NOT (' + sql_expression + ' = ANY(' + placeholder + '::text[]))';
16
+ }
17
+
18
+ export default nin_operator;
@@ -1,8 +1,14 @@
1
- import {bind_parameter} from '#src/sql/parameter-binder.js';
2
-
3
- export default function regex_operator(sql_expression, pattern_value, option_value, parameter_state) {
4
- const regex_operator_value = option_value && option_value.indexOf('i') >= 0 ? '~*' : '~';
5
- const placeholder = bind_parameter(parameter_state, String(pattern_value));
6
-
7
- return sql_expression + ' ' + regex_operator_value + ' ' + placeholder;
8
- }
1
+ /*
2
+ * MODULE RESPONSIBILITY
3
+ * Compile the SQL fragment for the $regex read-query operator.
4
+ */
5
+ import {bind_parameter} from '#src/sql/parameter-binder.js';
6
+
7
+ function regex_operator(sql_expression, pattern_value, option_value, parameter_state) {
8
+ const regex_operator_value = option_value && option_value.indexOf('i') >= 0 ? '~*' : '~';
9
+ const placeholder = bind_parameter(parameter_state, String(pattern_value));
10
+
11
+ return sql_expression + ' ' + regex_operator_value + ' ' + placeholder;
12
+ }
13
+
14
+ export default regex_operator;
@@ -0,0 +1,126 @@
1
+ /*
2
+ * MODULE RESPONSIBILITY
3
+ * Compile operator-style read-query objects into SQL predicates.
4
+ */
5
+ import {
6
+ all_operator
7
+ } from '#src/sql/read/where/operators/index.js';
8
+ import contains_operator from '#src/sql/jsonb/read/operators/contains.js';
9
+ import has_all_keys_operator from '#src/sql/jsonb/read/operators/has-all-keys.js';
10
+ import has_any_keys_operator from '#src/sql/jsonb/read/operators/has-any-keys.js';
11
+ import has_key_operator from '#src/sql/jsonb/read/operators/has-key.js';
12
+ import jsonpath_exists_operator from '#src/sql/jsonb/read/operators/jsonpath-exists.js';
13
+ import jsonpath_match_operator from '#src/sql/jsonb/read/operators/jsonpath-match.js';
14
+ import size_operator from '#src/sql/jsonb/read/operators/size.js';
15
+ import {build_json_expression, build_text_expression, parse_path} from '#src/sql/jsonb/path-parser.js';
16
+
17
+ import QueryError from '#src/errors/query-error.js';
18
+
19
+ import {cast_operator_value} from '#src/sql/read/where/casting.js';
20
+ import {is_array_root} from '#src/sql/read/where/context.js';
21
+ import {compile_nested_array_operator} from '#src/sql/jsonb/read/elem-match.js';
22
+ import {compile_operator_entry_clauses} from '#src/sql/read/where/operator-entries.js';
23
+ import {compile_text_operator} from '#src/sql/read/where/text-operators.js';
24
+
25
+ import {build_nested_object} from '#src/utils/object-path.js';
26
+
27
+ function compile_operator_object(path_value, operator_definition, compile_context, parameter_state) {
28
+ const path_info = parse_path(path_value);
29
+ const regex_options = operator_definition.$options || '';
30
+ const has_array_path = is_array_root(compile_context, path_info.root_path) && path_info.child_segments.length > 0;
31
+
32
+ const clause_list = compile_operator_entry_clauses(operator_definition, function (operator_name, operator_value) {
33
+ if(has_array_path) {
34
+ return compile_nested_array_operator(
35
+ operator_name,
36
+ operator_value,
37
+ regex_options,
38
+ path_info,
39
+ compile_context.data_column_reference,
40
+ parameter_state
41
+ );
42
+ }
43
+
44
+ return compile_standard_operator({
45
+ name: operator_name,
46
+ value: operator_value,
47
+ regex_options,
48
+ path_value,
49
+ compile_context,
50
+ parameter_state
51
+ });
52
+ });
53
+
54
+ return clause_list.join(' AND ');
55
+ }
56
+
57
+ function compile_standard_operator(context) {
58
+ const {
59
+ name,
60
+ value,
61
+ regex_options,
62
+ path_value,
63
+ compile_context,
64
+ parameter_state
65
+ } = context;
66
+
67
+ const data_column_reference = compile_context.data_column_reference;
68
+ const text_expression = build_text_expression(data_column_reference, path_value);
69
+ const json_expression = build_json_expression(data_column_reference, path_value);
70
+ const casted_value = cast_operator_value(path_value, name, value, compile_context);
71
+ const text_operator_clause = compile_text_operator({
72
+ name,
73
+ value,
74
+ casted_value,
75
+ regex_options,
76
+ text_expression,
77
+ parameter_state,
78
+ error_message: 'Unsupported operator'
79
+ });
80
+
81
+ if(text_operator_clause) {
82
+ return text_operator_clause;
83
+ }
84
+
85
+ if(name === '$contains') {
86
+ const nested_object = build_nested_object(path_value, value);
87
+ return contains_operator(data_column_reference, nested_object, parameter_state);
88
+ }
89
+
90
+ if(name === '$has_key') {
91
+ return has_key_operator(json_expression, value, parameter_state);
92
+ }
93
+
94
+ if(name === '$has_any_keys') {
95
+ return has_any_keys_operator(json_expression, value, parameter_state);
96
+ }
97
+
98
+ if(name === '$has_all_keys') {
99
+ return has_all_keys_operator(json_expression, value, parameter_state);
100
+ }
101
+
102
+ if(name === '$json_path_exists') {
103
+ return jsonpath_exists_operator(json_expression, value, parameter_state);
104
+ }
105
+
106
+ if(name === '$json_path_match') {
107
+ return jsonpath_match_operator(json_expression, value, parameter_state);
108
+ }
109
+
110
+ if(name === '$all') {
111
+ return all_operator(json_expression, casted_value, parameter_state);
112
+ }
113
+
114
+ if(name === '$size') {
115
+ return size_operator(json_expression, value, parameter_state);
116
+ }
117
+
118
+ throw new QueryError('Unsupported operator: ' + name, {
119
+ operator: name,
120
+ path: path_value
121
+ });
122
+ }
123
+
124
+ export {
125
+ compile_operator_object
126
+ };
@@ -0,0 +1,83 @@
1
+ /*
2
+ * MODULE RESPONSIBILITY
3
+ * Compile scalar and text read-query operators into SQL predicates.
4
+ */
5
+ import {
6
+ eq_operator,
7
+ gt_operator,
8
+ gte_operator,
9
+ in_operator,
10
+ lt_operator,
11
+ lte_operator,
12
+ ne_operator,
13
+ nin_operator,
14
+ regex_operator
15
+ } from '#src/sql/read/where/operators/index.js';
16
+
17
+ /**
18
+ * Compile one scalar comparison operator into a SQL predicate.
19
+ *
20
+ * @param {object} operator_context
21
+ * @param {string} operator_context.name
22
+ * @param {*} operator_context.value
23
+ * @param {*} [operator_context.casted_value]
24
+ * @param {*} operator_context.regex_options
25
+ * @param {string} operator_context.text_expression
26
+ * @param {object} operator_context.parameter_state
27
+ * @param {string} operator_context.error_message
28
+ * @returns {string|null}
29
+ * @throws {QueryError}
30
+ */
31
+ function compile_text_operator(operator_context) {
32
+ const {
33
+ name,
34
+ value,
35
+ casted_value = value,
36
+ regex_options,
37
+ text_expression,
38
+ parameter_state,
39
+ error_message
40
+ } = operator_context;
41
+
42
+ if(name === '$eq') {
43
+ return eq_operator(text_expression, casted_value, parameter_state);
44
+ }
45
+
46
+ if(name === '$ne') {
47
+ return ne_operator(text_expression, casted_value, parameter_state);
48
+ }
49
+
50
+ if(name === '$gt') {
51
+ return gt_operator(text_expression, casted_value, parameter_state);
52
+ }
53
+
54
+ if(name === '$gte') {
55
+ return gte_operator(text_expression, casted_value, parameter_state);
56
+ }
57
+
58
+ if(name === '$lt') {
59
+ return lt_operator(text_expression, casted_value, parameter_state);
60
+ }
61
+
62
+ if(name === '$lte') {
63
+ return lte_operator(text_expression, casted_value, parameter_state);
64
+ }
65
+
66
+ if(name === '$in') {
67
+ return in_operator(text_expression, casted_value, parameter_state);
68
+ }
69
+
70
+ if(name === '$nin') {
71
+ return nin_operator(text_expression, casted_value, parameter_state);
72
+ }
73
+
74
+ if(name === '$regex') {
75
+ return regex_operator(text_expression, value, regex_options, parameter_state);
76
+ }
77
+
78
+ return null;
79
+ }
80
+
81
+ export {
82
+ compile_text_operator
83
+ };