rawsql-ts 0.16.0 → 0.17.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 (211) hide show
  1. package/README.md +161 -875
  2. package/dist/esm/index.d.ts +7 -0
  3. package/dist/esm/index.js +7 -0
  4. package/dist/esm/index.js.map +1 -1
  5. package/dist/esm/index.min.js +22 -20
  6. package/dist/esm/index.min.js.map +4 -4
  7. package/dist/esm/models/Clause.d.ts +15 -3
  8. package/dist/esm/models/Clause.js +2 -1
  9. package/dist/esm/models/Clause.js.map +1 -1
  10. package/dist/esm/models/CreateTableQuery.d.ts +3 -0
  11. package/dist/esm/models/CreateTableQuery.js +5 -4
  12. package/dist/esm/models/CreateTableQuery.js.map +1 -1
  13. package/dist/esm/models/DDLStatements.d.ts +71 -0
  14. package/dist/esm/models/DDLStatements.js +63 -0
  15. package/dist/esm/models/DDLStatements.js.map +1 -1
  16. package/dist/esm/models/KeywordTrie.d.ts +2 -3
  17. package/dist/esm/models/KeywordTrie.js +26 -27
  18. package/dist/esm/models/KeywordTrie.js.map +1 -1
  19. package/dist/esm/models/SqlPrintToken.d.ts +1 -0
  20. package/dist/esm/models/SqlPrintToken.js +1 -0
  21. package/dist/esm/models/SqlPrintToken.js.map +1 -1
  22. package/dist/esm/parsers/CheckpointStatementParser.d.ts +8 -0
  23. package/dist/esm/parsers/CheckpointStatementParser.js +14 -0
  24. package/dist/esm/parsers/CheckpointStatementParser.js.map +1 -0
  25. package/dist/esm/parsers/ClusterStatementParser.d.ts +8 -0
  26. package/dist/esm/parsers/ClusterStatementParser.js +14 -0
  27. package/dist/esm/parsers/ClusterStatementParser.js.map +1 -0
  28. package/dist/esm/parsers/CommandExpressionParser.js.map +1 -1
  29. package/dist/esm/parsers/CommentOnParser.d.ts +23 -0
  30. package/dist/esm/parsers/CommentOnParser.js +61 -0
  31. package/dist/esm/parsers/CommentOnParser.js.map +1 -0
  32. package/dist/esm/parsers/CommonTableParser.d.ts +5 -1
  33. package/dist/esm/parsers/CommonTableParser.js +94 -16
  34. package/dist/esm/parsers/CommonTableParser.js.map +1 -1
  35. package/dist/esm/parsers/CreateIndexParser.js +12 -6
  36. package/dist/esm/parsers/CreateIndexParser.js.map +1 -1
  37. package/dist/esm/parsers/CreateTableParser.d.ts +2 -0
  38. package/dist/esm/parsers/CreateTableParser.js +11 -2
  39. package/dist/esm/parsers/CreateTableParser.js.map +1 -1
  40. package/dist/esm/parsers/ExplainStatementParser.js.map +1 -1
  41. package/dist/esm/parsers/FullNameParser.js +35 -3
  42. package/dist/esm/parsers/FullNameParser.js.map +1 -1
  43. package/dist/esm/parsers/OrderByClauseParser.js.map +1 -1
  44. package/dist/esm/parsers/ReindexStatementParser.d.ts +8 -0
  45. package/dist/esm/parsers/ReindexStatementParser.js +14 -0
  46. package/dist/esm/parsers/ReindexStatementParser.js.map +1 -0
  47. package/dist/esm/parsers/SelectQueryParser.js.map +1 -1
  48. package/dist/esm/parsers/SourceParser.js +6 -1
  49. package/dist/esm/parsers/SourceParser.js.map +1 -1
  50. package/dist/esm/parsers/SqlParser.d.ts +12 -2
  51. package/dist/esm/parsers/SqlParser.js +117 -251
  52. package/dist/esm/parsers/SqlParser.js.map +1 -1
  53. package/dist/esm/parsers/SqlPrintTokenParser.d.ts +1 -0
  54. package/dist/esm/parsers/SqlPrintTokenParser.js +32 -4
  55. package/dist/esm/parsers/SqlPrintTokenParser.js.map +1 -1
  56. package/dist/esm/parsers/SqlTokenizer.d.ts +5 -0
  57. package/dist/esm/parsers/SqlTokenizer.js +181 -67
  58. package/dist/esm/parsers/SqlTokenizer.js.map +1 -1
  59. package/dist/esm/parsers/UsingClauseParser.js.map +1 -1
  60. package/dist/esm/parsers/VacuumStatementParser.d.ts +8 -0
  61. package/dist/esm/parsers/VacuumStatementParser.js +14 -0
  62. package/dist/esm/parsers/VacuumStatementParser.js.map +1 -0
  63. package/dist/esm/tokenReaders/CommandTokenReader.js +22 -4
  64. package/dist/esm/tokenReaders/CommandTokenReader.js.map +1 -1
  65. package/dist/esm/tokenReaders/StringSpecifierTokenReader.d.ts +2 -0
  66. package/dist/esm/tokenReaders/StringSpecifierTokenReader.js +30 -13
  67. package/dist/esm/tokenReaders/StringSpecifierTokenReader.js.map +1 -1
  68. package/dist/esm/tokenReaders/TokenReaderManager.d.ts +0 -7
  69. package/dist/esm/tokenReaders/TokenReaderManager.js +16 -48
  70. package/dist/esm/tokenReaders/TokenReaderManager.js.map +1 -1
  71. package/dist/esm/transformers/AliasRenamer.d.ts +1 -0
  72. package/dist/esm/transformers/AliasRenamer.js +7 -1
  73. package/dist/esm/transformers/AliasRenamer.js.map +1 -1
  74. package/dist/esm/transformers/CTECollector.d.ts +5 -2
  75. package/dist/esm/transformers/CTECollector.js +49 -0
  76. package/dist/esm/transformers/CTECollector.js.map +1 -1
  77. package/dist/esm/transformers/CTEDependencyTracer.d.ts +6 -1
  78. package/dist/esm/transformers/CTEDependencyTracer.js +44 -2
  79. package/dist/esm/transformers/CTEDependencyTracer.js.map +1 -1
  80. package/dist/esm/transformers/CTEDisabler.d.ts +6 -0
  81. package/dist/esm/transformers/CTEDisabler.js +19 -0
  82. package/dist/esm/transformers/CTEDisabler.js.map +1 -1
  83. package/dist/esm/transformers/CTERenamer.js +5 -2
  84. package/dist/esm/transformers/CTERenamer.js.map +1 -1
  85. package/dist/esm/transformers/ColumnReferenceCollector.d.ts +4 -0
  86. package/dist/esm/transformers/ColumnReferenceCollector.js +69 -1
  87. package/dist/esm/transformers/ColumnReferenceCollector.js.map +1 -1
  88. package/dist/esm/transformers/DeleteResultSelectConverter.js.map +1 -1
  89. package/dist/esm/transformers/DynamicQueryBuilder.d.ts +87 -11
  90. package/dist/esm/transformers/DynamicQueryBuilder.js +237 -9
  91. package/dist/esm/transformers/DynamicQueryBuilder.js.map +1 -1
  92. package/dist/esm/transformers/ExistsPredicateInjector.d.ts +33 -0
  93. package/dist/esm/transformers/ExistsPredicateInjector.js +294 -0
  94. package/dist/esm/transformers/ExistsPredicateInjector.js.map +1 -0
  95. package/dist/esm/transformers/FixtureCteBuilder.js +5 -2
  96. package/dist/esm/transformers/FixtureCteBuilder.js.map +1 -1
  97. package/dist/esm/transformers/InsertResultSelectConverter.d.ts +1 -0
  98. package/dist/esm/transformers/InsertResultSelectConverter.js +28 -7
  99. package/dist/esm/transformers/InsertResultSelectConverter.js.map +1 -1
  100. package/dist/esm/transformers/LinePrinter.d.ts +4 -2
  101. package/dist/esm/transformers/LinePrinter.js +93 -22
  102. package/dist/esm/transformers/LinePrinter.js.map +1 -1
  103. package/dist/esm/transformers/MergeResultSelectConverter.js.map +1 -1
  104. package/dist/esm/transformers/OptimizeUnusedLeftJoins.d.ts +33 -0
  105. package/dist/esm/transformers/OptimizeUnusedLeftJoins.js +333 -0
  106. package/dist/esm/transformers/OptimizeUnusedLeftJoins.js.map +1 -0
  107. package/dist/esm/transformers/PruneOptionalConditionBranches.d.ts +10 -0
  108. package/dist/esm/transformers/PruneOptionalConditionBranches.js +197 -0
  109. package/dist/esm/transformers/PruneOptionalConditionBranches.js.map +1 -0
  110. package/dist/esm/transformers/SchemaCollector.d.ts +3 -0
  111. package/dist/esm/transformers/SchemaCollector.js +37 -1
  112. package/dist/esm/transformers/SchemaCollector.js.map +1 -1
  113. package/dist/esm/transformers/SelectValueCollector.d.ts +5 -0
  114. package/dist/esm/transformers/SelectValueCollector.js +44 -2
  115. package/dist/esm/transformers/SelectValueCollector.js.map +1 -1
  116. package/dist/esm/transformers/SqlParamInjector.d.ts +5 -1
  117. package/dist/esm/transformers/SqlParamInjector.js +47 -11
  118. package/dist/esm/transformers/SqlParamInjector.js.map +1 -1
  119. package/dist/esm/transformers/SqlPrinter.js +8 -2
  120. package/dist/esm/transformers/SqlPrinter.js.map +1 -1
  121. package/dist/esm/transformers/TableSourceCollector.d.ts +9 -1
  122. package/dist/esm/transformers/TableSourceCollector.js +72 -5
  123. package/dist/esm/transformers/TableSourceCollector.js.map +1 -1
  124. package/dist/esm/transformers/UpdateResultSelectConverter.js.map +1 -1
  125. package/dist/esm/transformers/UpstreamSelectQueryFinder.d.ts +5 -0
  126. package/dist/esm/transformers/UpstreamSelectQueryFinder.js +46 -1
  127. package/dist/esm/transformers/UpstreamSelectQueryFinder.js.map +1 -1
  128. package/dist/esm/utils/CommentUtils.d.ts +1 -0
  129. package/dist/esm/utils/CommentUtils.js +14 -4
  130. package/dist/esm/utils/CommentUtils.js.map +1 -1
  131. package/dist/esm/utils/MultiQuerySplitter.d.ts +7 -11
  132. package/dist/esm/utils/MultiQuerySplitter.js +105 -66
  133. package/dist/esm/utils/MultiQuerySplitter.js.map +1 -1
  134. package/dist/esm/utils/ParameterRemover.d.ts +4 -0
  135. package/dist/esm/utils/ParameterRemover.js +23 -0
  136. package/dist/esm/utils/ParameterRemover.js.map +1 -1
  137. package/dist/esm/utils/ScopeResolver.d.ts +5 -2
  138. package/dist/esm/utils/ScopeResolver.js +37 -18
  139. package/dist/esm/utils/ScopeResolver.js.map +1 -1
  140. package/dist/esm/utils/charLookupTable.d.ts +6 -0
  141. package/dist/esm/utils/charLookupTable.js +9 -1
  142. package/dist/esm/utils/charLookupTable.js.map +1 -1
  143. package/dist/esm/utils/serialTypeNormalization.d.ts +15 -0
  144. package/dist/esm/utils/serialTypeNormalization.js +55 -0
  145. package/dist/esm/utils/serialTypeNormalization.js.map +1 -0
  146. package/dist/esm/utils/stringUtils.js +51 -26
  147. package/dist/esm/utils/stringUtils.js.map +1 -1
  148. package/dist/index.js +2 -0
  149. package/dist/index.js.map +1 -1
  150. package/dist/index.min.js +21 -19
  151. package/dist/index.min.js.map +4 -4
  152. package/dist/models/CreateTableQuery.js +5 -4
  153. package/dist/models/CreateTableQuery.js.map +1 -1
  154. package/dist/models/DDLStatements.js +14 -1
  155. package/dist/models/DDLStatements.js.map +1 -1
  156. package/dist/models/KeywordTrie.js +26 -27
  157. package/dist/models/KeywordTrie.js.map +1 -1
  158. package/dist/models/SqlPrintToken.js +1 -0
  159. package/dist/models/SqlPrintToken.js.map +1 -1
  160. package/dist/parsers/CommentOnParser.js +65 -0
  161. package/dist/parsers/CommentOnParser.js.map +1 -0
  162. package/dist/parsers/CreateIndexParser.js +12 -6
  163. package/dist/parsers/CreateIndexParser.js.map +1 -1
  164. package/dist/parsers/CreateTableParser.js +6 -1
  165. package/dist/parsers/CreateTableParser.js.map +1 -1
  166. package/dist/parsers/FullNameParser.js +35 -3
  167. package/dist/parsers/FullNameParser.js.map +1 -1
  168. package/dist/parsers/SqlParser.js +93 -307
  169. package/dist/parsers/SqlParser.js.map +1 -1
  170. package/dist/parsers/SqlPrintTokenParser.js +27 -3
  171. package/dist/parsers/SqlPrintTokenParser.js.map +1 -1
  172. package/dist/parsers/SqlTokenizer.js +176 -67
  173. package/dist/parsers/SqlTokenizer.js.map +1 -1
  174. package/dist/src/index.d.ts +2 -0
  175. package/dist/src/models/CreateTableQuery.d.ts +3 -0
  176. package/dist/src/models/DDLStatements.d.ts +15 -0
  177. package/dist/src/models/KeywordTrie.d.ts +2 -3
  178. package/dist/src/models/SqlPrintToken.d.ts +1 -0
  179. package/dist/src/parsers/CommentOnParser.d.ts +23 -0
  180. package/dist/src/parsers/CreateTableParser.d.ts +1 -0
  181. package/dist/src/parsers/SqlParser.d.ts +8 -2
  182. package/dist/src/parsers/SqlPrintTokenParser.d.ts +1 -0
  183. package/dist/src/parsers/SqlTokenizer.d.ts +5 -0
  184. package/dist/src/tokenReaders/StringSpecifierTokenReader.d.ts +2 -0
  185. package/dist/src/tokenReaders/TokenReaderManager.d.ts +0 -7
  186. package/dist/src/transformers/DynamicQueryBuilder.d.ts +12 -0
  187. package/dist/src/transformers/LinePrinter.d.ts +4 -2
  188. package/dist/src/transformers/PruneOptionalConditionBranches.d.ts +10 -0
  189. package/dist/src/utils/CommentUtils.d.ts +1 -0
  190. package/dist/src/utils/MultiQuerySplitter.d.ts +7 -11
  191. package/dist/tokenReaders/CommandTokenReader.js +21 -4
  192. package/dist/tokenReaders/CommandTokenReader.js.map +1 -1
  193. package/dist/tokenReaders/StringSpecifierTokenReader.js +30 -13
  194. package/dist/tokenReaders/StringSpecifierTokenReader.js.map +1 -1
  195. package/dist/tokenReaders/TokenReaderManager.js +16 -48
  196. package/dist/tokenReaders/TokenReaderManager.js.map +1 -1
  197. package/dist/transformers/DynamicQueryBuilder.js +24 -2
  198. package/dist/transformers/DynamicQueryBuilder.js.map +1 -1
  199. package/dist/transformers/LinePrinter.js +93 -22
  200. package/dist/transformers/LinePrinter.js.map +1 -1
  201. package/dist/transformers/PruneOptionalConditionBranches.js +201 -0
  202. package/dist/transformers/PruneOptionalConditionBranches.js.map +1 -0
  203. package/dist/tsconfig.browser.tsbuildinfo +1 -1
  204. package/dist/utils/CommentUtils.js +14 -4
  205. package/dist/utils/CommentUtils.js.map +1 -1
  206. package/dist/utils/MultiQuerySplitter.js +105 -66
  207. package/dist/utils/MultiQuerySplitter.js.map +1 -1
  208. package/dist/utils/stringUtils.js +42 -23
  209. package/dist/utils/stringUtils.js.map +1 -1
  210. package/package.json +65 -64
  211. package/LICENSE +0 -21
@@ -1,3 +1,14 @@
1
+ var __rest = (this && this.__rest) || function (s, e) {
2
+ var t = {};
3
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
4
+ t[p] = s[p];
5
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
6
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
7
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
8
+ t[p[i]] = s[p[i]];
9
+ }
10
+ return t;
11
+ };
1
12
  import { SelectQueryParser } from "../parsers/SelectQueryParser";
2
13
  import { SqlParamInjector } from "./SqlParamInjector";
3
14
  import { SqlSortInjector } from "./SqlSortInjector";
@@ -6,6 +17,10 @@ import { PostgresJsonQueryBuilder } from "./PostgresJsonQueryBuilder";
6
17
  import { QueryBuilder } from "./QueryBuilder";
7
18
  import { SqlParameterBinder } from "./SqlParameterBinder";
8
19
  import { ParameterDetector } from "../utils/ParameterDetector";
20
+ import { ColumnReference } from "../models/ValueComponent";
21
+ import { injectExistsPredicates } from "./ExistsPredicateInjector";
22
+ import { optimizeUnusedLeftJoinsToFixedPoint, optimizeUnusedCtesToFixedPoint } from "./OptimizeUnusedLeftJoins";
23
+ import { pruneOptionalConditionBranches } from "./PruneOptionalConditionBranches";
9
24
  /**
10
25
  * DynamicQueryBuilder combines SQL parsing with dynamic condition injection (filters, sorts, paging, JSON serialization).
11
26
  *
@@ -16,11 +31,19 @@ import { ParameterDetector } from "../utils/ParameterDetector";
16
31
  */
17
32
  export class DynamicQueryBuilder {
18
33
  /**
19
- * Creates a new DynamicQueryBuilder instance
20
- * @param tableColumnResolver Optional function to resolve table columns for wildcard queries
34
+ * Creates a new DynamicQueryBuilder instance.
35
+ * Accepts either the legacy table resolver or an options object that can provide schema metadata.
36
+ *
37
+ * @param resolverOrOptions Optional resolver or configuration object
21
38
  */
22
- constructor(tableColumnResolver) {
23
- this.tableColumnResolver = tableColumnResolver;
39
+ constructor(resolverOrOptions) {
40
+ if (typeof resolverOrOptions === "function") {
41
+ this.tableColumnResolver = resolverOrOptions;
42
+ }
43
+ else if (resolverOrOptions) {
44
+ this.tableColumnResolver = resolverOrOptions.tableColumnResolver;
45
+ this.defaultSchemaInfo = resolverOrOptions.schemaInfo;
46
+ }
24
47
  }
25
48
  /**
26
49
  * Builds a SelectQuery from SQL content with dynamic conditions.
@@ -43,6 +66,7 @@ export class DynamicQueryBuilder {
43
66
  * ```
44
67
  */
45
68
  buildQuery(sqlContent, options = {}) {
69
+ var _a;
46
70
  // Parse the base SQL
47
71
  let parsedQuery;
48
72
  try {
@@ -61,12 +85,19 @@ export class DynamicQueryBuilder {
61
85
  const parameterBinder = new SqlParameterBinder({ requireAllParameters: false });
62
86
  modifiedQuery = parameterBinder.bind(modifiedQuery, hardcodedParams);
63
87
  }
64
- // Apply dynamic filtering only if there are non-hardcoded filters
65
- if (Object.keys(dynamicFilters).length > 0) {
88
+ // Extract and remove any column-anchored EXISTS filters before injecting traditional ones.
89
+ const { filters: cleanedFilters, instructions: existsInstructions } = this.extractExistsInstructions(dynamicFilters);
90
+ if (Object.keys(cleanedFilters).length > 0) {
66
91
  const paramInjector = new SqlParamInjector(this.tableColumnResolver);
67
92
  // Ensure we have a SimpleSelectQuery for the injector
68
93
  const simpleQuery = QueryBuilder.buildSimpleQuery(modifiedQuery);
69
- modifiedQuery = paramInjector.inject(simpleQuery, dynamicFilters);
94
+ modifiedQuery = paramInjector.inject(simpleQuery, cleanedFilters);
95
+ }
96
+ if (existsInstructions.length > 0) {
97
+ modifiedQuery = injectExistsPredicates(modifiedQuery, existsInstructions, {
98
+ tableColumnResolver: this.tableColumnResolver,
99
+ strict: !!options.existsStrict
100
+ });
70
101
  }
71
102
  }
72
103
  // 2. Apply sorting second (after filtering to sort smaller dataset)
@@ -75,7 +106,8 @@ export class DynamicQueryBuilder {
75
106
  // Ensure we have a SimpleSelectQuery for the injector
76
107
  const simpleQuery = QueryBuilder.buildSimpleQuery(modifiedQuery);
77
108
  modifiedQuery = sortInjector.inject(simpleQuery, options.sort);
78
- } // 3. Apply pagination third (after filtering and sorting)
109
+ }
110
+ // 3. Apply pagination third (after filtering and sorting)
79
111
  if (options.paging) {
80
112
  const { page = 1, pageSize } = options.paging;
81
113
  if (pageSize !== undefined) {
@@ -86,7 +118,23 @@ export class DynamicQueryBuilder {
86
118
  modifiedQuery = paginationInjector.inject(simpleQuery, paginationOptions);
87
119
  }
88
120
  }
89
- // 4. Apply serialization last (transform the final query structure to JSON)
121
+ // 4. Apply column projection filters before any optimizer passes.
122
+ modifiedQuery = this.applyColumnFilters(modifiedQuery, options);
123
+ // 5. Prune supported truthful optional branches before structural optimizers.
124
+ const optionalConditionParameters = this.resolveOptionalConditionPruningParameters(options);
125
+ if (Object.keys(optionalConditionParameters).length > 0) {
126
+ modifiedQuery = pruneOptionalConditionBranches(modifiedQuery, optionalConditionParameters);
127
+ }
128
+ // 6. Remove unused LEFT JOINs when asked before serialization.
129
+ const effectiveSchemaInfo = (_a = options.schemaInfo) !== null && _a !== void 0 ? _a : this.defaultSchemaInfo;
130
+ if (options.removeUnusedLeftJoins && (effectiveSchemaInfo === null || effectiveSchemaInfo === void 0 ? void 0 : effectiveSchemaInfo.length)) {
131
+ modifiedQuery = optimizeUnusedLeftJoinsToFixedPoint(modifiedQuery, effectiveSchemaInfo);
132
+ }
133
+ // 7. Remove unused CTEs before serialization when requested.
134
+ if (options.removeUnusedCtes) {
135
+ modifiedQuery = optimizeUnusedCtesToFixedPoint(modifiedQuery);
136
+ }
137
+ // Apply serialization last (transform the final query structure to JSON)
90
138
  // Note: boolean values are handled at RawSqlClient level for auto-loading
91
139
  if (options.serialize && typeof options.serialize === 'object') {
92
140
  const jsonBuilder = new PostgresJsonQueryBuilder();
@@ -96,6 +144,186 @@ export class DynamicQueryBuilder {
96
144
  }
97
145
  return modifiedQuery;
98
146
  }
147
+ resolveOptionalConditionPruningParameters(options) {
148
+ if (options.optionalConditionParameters) {
149
+ return options.optionalConditionParameters;
150
+ }
151
+ if (!options.optionalConditionParameterStates) {
152
+ return {};
153
+ }
154
+ const legacyParameters = {};
155
+ // Preserve backward compatibility for the state-map API while the value-based API becomes the primary entry point.
156
+ for (const [parameterName, state] of Object.entries(options.optionalConditionParameterStates)) {
157
+ legacyParameters[parameterName] = state === 'absent'
158
+ ? null
159
+ : '__RAWSQL_OPTIONAL_CONDITION_PRESENT__';
160
+ }
161
+ return legacyParameters;
162
+ }
163
+ extractExistsInstructions(filters) {
164
+ const cleanedFilters = {};
165
+ const instructions = [];
166
+ for (const [key, value] of Object.entries(filters)) {
167
+ if (key === "$exists" || key === "$notExists") {
168
+ // Multi-anchor metadata arrives as arrays keyed by the special markers.
169
+ if (!this.isMultiColumnDefinitionArray(value)) {
170
+ throw new Error(`'${key}' must be an array of EXISTS definitions.`);
171
+ }
172
+ this.handleMultiAnchorDefinitions(key, value, instructions);
173
+ continue;
174
+ }
175
+ if (this.isFilterConditionObject(value)) {
176
+ const { leftover, exists, notExists } = this.splitExistsProperties(value);
177
+ if (exists) {
178
+ instructions.push(this.createExistsInstruction([key], exists, "exists"));
179
+ }
180
+ if (notExists) {
181
+ instructions.push(this.createExistsInstruction([key], notExists, "notExists"));
182
+ }
183
+ if (leftover) {
184
+ cleanedFilters[key] = leftover;
185
+ }
186
+ continue;
187
+ }
188
+ if (this.isMultiColumnDefinitionArray(value)) {
189
+ continue;
190
+ }
191
+ cleanedFilters[key] = value;
192
+ }
193
+ return { filters: cleanedFilters, instructions };
194
+ }
195
+ handleMultiAnchorDefinitions(key, definitions, instructions) {
196
+ // Build instructions for each multi-anchor definition in the batch.
197
+ for (const definition of definitions) {
198
+ if (!definition.on || definition.on.length === 0) {
199
+ throw new Error(`Every ${key} instruction must specify an "on" array.`);
200
+ }
201
+ instructions.push(this.createExistsInstruction(definition.on, definition, key === "$notExists" ? "notExists" : "exists"));
202
+ }
203
+ }
204
+ splitExistsProperties(value) {
205
+ const { exists, notExists } = value, rest = __rest(value, ["exists", "notExists"]);
206
+ const hasRemaining = Object.keys(rest).length > 0;
207
+ return {
208
+ leftover: hasRemaining ? rest : undefined,
209
+ exists: exists,
210
+ notExists: notExists
211
+ };
212
+ }
213
+ isFilterConditionObject(value) {
214
+ return value !== null && typeof value === "object" && !Array.isArray(value);
215
+ }
216
+ isMultiColumnDefinitionArray(value) {
217
+ return Array.isArray(value) && value.every(entry => this.isMultiColumnDefinition(entry));
218
+ }
219
+ isMultiColumnDefinition(value) {
220
+ if (!value || typeof value !== "object") {
221
+ return false;
222
+ }
223
+ const candidate = value;
224
+ return (Array.isArray(candidate.on) &&
225
+ candidate.on.length > 0 &&
226
+ candidate.on.every(column => typeof column === "string") &&
227
+ typeof candidate.sql === "string");
228
+ }
229
+ createExistsInstruction(anchors, definition, mode) {
230
+ if (!definition.sql || typeof definition.sql !== "string") {
231
+ throw new Error("EXISTS definition must include a SQL string.");
232
+ }
233
+ return {
234
+ mode,
235
+ anchorColumns: anchors,
236
+ sql: definition.sql,
237
+ params: definition.params
238
+ };
239
+ }
240
+ applyColumnFilters(query, options) {
241
+ const hasIncludeFilters = Array.isArray(options.includeColumns) && options.includeColumns.length > 0;
242
+ const hasExcludeFilters = Array.isArray(options.excludeColumns) && options.excludeColumns.length > 0;
243
+ if (!hasIncludeFilters && !hasExcludeFilters) {
244
+ return query;
245
+ }
246
+ if (hasIncludeFilters && hasExcludeFilters) {
247
+ throw new Error("includeColumns and excludeColumns cannot be used together.");
248
+ }
249
+ const simpleQuery = QueryBuilder.buildSimpleQuery(query);
250
+ const metadata = simpleQuery.selectClause.items.map(item => {
251
+ const name = this.getSelectItemName(item);
252
+ return {
253
+ item,
254
+ normalized: name ? this.normalizeColumnIdentifier(name) : null
255
+ };
256
+ });
257
+ const availableColumns = new Set(metadata
258
+ .map(entry => entry.normalized)
259
+ .filter((name) => name !== null));
260
+ const includeFilters = hasIncludeFilters ? this.normalizeColumnList(options.includeColumns) : null;
261
+ const excludeFilters = hasExcludeFilters ? this.normalizeColumnList(options.excludeColumns) : null;
262
+ const includeSet = includeFilters ? new Set(includeFilters.map(entry => entry.normalized)) : null;
263
+ const excludeSet = excludeFilters ? new Set(excludeFilters.map(entry => entry.normalized)) : null;
264
+ if (includeFilters) {
265
+ const missing = includeFilters.filter(entry => !availableColumns.has(entry.normalized));
266
+ if (missing.length > 0) {
267
+ throw new Error(`Column${missing.length === 1 ? "" : "s"} not found in SELECT clause: ${missing
268
+ .map(entry => `'${entry.original}'`)
269
+ .join(", ")}.`);
270
+ }
271
+ }
272
+ if (excludeFilters) {
273
+ const missing = excludeFilters.filter(entry => !availableColumns.has(entry.normalized));
274
+ if (missing.length > 0) {
275
+ throw new Error(`Column${missing.length === 1 ? "" : "s"} not found in SELECT clause: ${missing
276
+ .map(entry => `'${entry.original}'`)
277
+ .join(", ")}.`);
278
+ }
279
+ }
280
+ const filteredItems = metadata
281
+ .filter(entry => {
282
+ if (!entry.normalized) {
283
+ return true;
284
+ }
285
+ if (includeSet) {
286
+ return includeSet.has(entry.normalized);
287
+ }
288
+ if (excludeSet) {
289
+ return !excludeSet.has(entry.normalized);
290
+ }
291
+ return true;
292
+ })
293
+ .map(entry => entry.item);
294
+ if (filteredItems.length === 0) {
295
+ throw new Error("Column filtering removed every SELECT item.");
296
+ }
297
+ simpleQuery.selectClause.items = filteredItems;
298
+ return simpleQuery;
299
+ }
300
+ normalizeColumnList(columns) {
301
+ return columns.map(column => {
302
+ if (typeof column !== "string") {
303
+ throw new Error("Column filters must be strings.");
304
+ }
305
+ const trimmed = column.trim();
306
+ if (trimmed === "") {
307
+ throw new Error("Column filters must not be empty.");
308
+ }
309
+ return {
310
+ normalized: this.normalizeColumnIdentifier(trimmed),
311
+ original: trimmed
312
+ };
313
+ });
314
+ }
315
+ normalizeColumnIdentifier(value) {
316
+ return value.trim().toLowerCase();
317
+ }
318
+ getSelectItemName(item) {
319
+ if (item.identifier) {
320
+ return item.identifier.name;
321
+ }
322
+ if (item.value instanceof ColumnReference) {
323
+ return item.value.column.name;
324
+ }
325
+ return null;
326
+ }
99
327
  /**
100
328
  * Builds a SelectQuery with only filtering applied.
101
329
  * Convenience method for when you only need dynamic WHERE conditions.
@@ -1 +1 @@
1
- {"version":3,"file":"DynamicQueryBuilder.js","sourceRoot":"","sources":["../../../src/transformers/DynamicQueryBuilder.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"DynamicQueryBuilder.js","sourceRoot":"","sources":["../../../src/transformers/DynamicQueryBuilder.ts"],"names":[],"mappings":";;;;;;;;;;;AACA,OAAO,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AACjE,OAAO,EAAE,gBAAgB,EAAuB,MAAM,oBAAoB,CAAC;AAC3E,OAAO,EAAE,eAAe,EAAkB,MAAM,mBAAmB,CAAC;AACpE,OAAO,EAAE,qBAAqB,EAAqB,MAAM,yBAAyB,CAAC;AACnF,OAAO,EAAE,wBAAwB,EAAe,MAAM,4BAA4B,CAAC;AACnF,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AAC/D,OAAO,EAAE,eAAe,EAAqB,MAAM,0BAA0B,CAAC;AAE9E,OAAO,EAEH,sBAAsB,EAEzB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAEH,mCAAmC,EACnC,8BAA8B,EACjC,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAGH,8BAA8B,EACjC,MAAM,kCAAkC,CAAC;AA+J1C;;;;;;;GAOG;AACH,MAAM,OAAO,mBAAmB;IAI5B;;;;;OAKG;IACH,YACI,iBAAkF;QAElF,IAAI,OAAO,iBAAiB,KAAK,UAAU,EAAE,CAAC;YAC1C,IAAI,CAAC,mBAAmB,GAAG,iBAAiB,CAAC;QACjD,CAAC;aAAM,IAAI,iBAAiB,EAAE,CAAC;YAC3B,IAAI,CAAC,mBAAmB,GAAG,iBAAiB,CAAC,mBAAmB,CAAC;YACjE,IAAI,CAAC,iBAAiB,GAAG,iBAAiB,CAAC,UAAU,CAAC;QAC1D,CAAC;IACL,CAAC;IAED;;;;;;;;;;;;;;;;;;;OAmBG;IACH,UAAU,CAAC,UAAkB,EAAE,UAA6B,EAAE;;QAC1D,qBAAqB;QACrB,IAAI,WAA8B,CAAC;QACnC,IAAI,CAAC;YACD,WAAW,GAAG,iBAAiB,CAAC,KAAK,CAAC,UAAU,CAAsB,CAAC;QAC3E,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACb,MAAM,IAAI,KAAK,CAAC,wBAAwB,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,EAAE,CAAC,CAAC;QACxG,CAAC;QAED,mDAAmD;QACnD,IAAI,aAAa,GAAgB,WAAW,CAAC;QAE7C,wEAAwE;QACxE,IAAI,OAAO,CAAC,MAAM,IAAI,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC3D,MAAM,EAAE,eAAe,EAAE,cAAc,EAAE,GAAG,iBAAiB,CAAC,eAAe,CAAC,aAAa,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;YAE7G,yCAAyC;YACzC,IAAI,MAAM,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC1C,MAAM,eAAe,GAAG,IAAI,kBAAkB,CAAC,EAAE,oBAAoB,EAAE,KAAK,EAAE,CAAC,CAAC;gBAChF,aAAa,GAAG,eAAe,CAAC,IAAI,CAAC,aAAa,EAAE,eAAe,CAAC,CAAC;YACzE,CAAC;YAED,2FAA2F;YAC3F,MAAM,EAAE,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,kBAAkB,EAAE,GAAG,IAAI,CAAC,yBAAyB,CAAC,cAAc,CAAC,CAAC;YAErH,IAAI,MAAM,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACzC,MAAM,aAAa,GAAG,IAAI,gBAAgB,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC;gBACrE,sDAAsD;gBACtD,MAAM,WAAW,GAAG,YAAY,CAAC,gBAAgB,CAAC,aAAa,CAAC,CAAC;gBACjE,aAAa,GAAG,aAAa,CAAC,MAAM,CAAC,WAAW,EAAE,cAAc,CAAC,CAAC;YACtE,CAAC;YAED,IAAI,kBAAkB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAChC,aAAa,GAAG,sBAAsB,CAAC,aAAa,EAAE,kBAAkB,EAAE;oBACtE,mBAAmB,EAAE,IAAI,CAAC,mBAAmB;oBAC7C,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,YAAY;iBACjC,CAAC,CAAC;YACP,CAAC;QACL,CAAC;QAED,oEAAoE;QACpE,IAAI,OAAO,CAAC,IAAI,IAAI,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACvD,MAAM,YAAY,GAAG,IAAI,eAAe,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC;YACnE,sDAAsD;YACtD,MAAM,WAAW,GAAG,YAAY,CAAC,gBAAgB,CAAC,aAAa,CAAC,CAAC;YACjE,aAAa,GAAG,YAAY,CAAC,MAAM,CAAC,WAAW,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;QACnE,CAAC;QAED,0DAA0D;QAC1D,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;YACjB,MAAM,EAAE,IAAI,GAAG,CAAC,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC;YAC9C,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;gBACzB,MAAM,kBAAkB,GAAG,IAAI,qBAAqB,EAAE,CAAC;gBACvD,MAAM,iBAAiB,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;gBAC7C,sDAAsD;gBACtD,MAAM,WAAW,GAAG,YAAY,CAAC,gBAAgB,CAAC,aAAa,CAAC,CAAC;gBACjE,aAAa,GAAG,kBAAkB,CAAC,MAAM,CAAC,WAAW,EAAE,iBAAiB,CAAC,CAAC;YAC9E,CAAC;QACL,CAAC;QACD,kEAAkE;QAClE,aAAa,GAAG,IAAI,CAAC,kBAAkB,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC;QAChE,8EAA8E;QAC9E,MAAM,2BAA2B,GAAG,IAAI,CAAC,yCAAyC,CAAC,OAAO,CAAC,CAAC;QAC5F,IAAI,MAAM,CAAC,IAAI,CAAC,2BAA2B,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACtD,aAAa,GAAG,8BAA8B,CAAC,aAAa,EAAE,2BAA2B,CAAC,CAAC;QAC/F,CAAC;QACD,+DAA+D;QAC/D,MAAM,mBAAmB,GAAG,MAAA,OAAO,CAAC,UAAU,mCAAI,IAAI,CAAC,iBAAiB,CAAC;QACzE,IAAI,OAAO,CAAC,qBAAqB,KAAI,mBAAmB,aAAnB,mBAAmB,uBAAnB,mBAAmB,CAAE,MAAM,CAAA,EAAE,CAAC;YAC/D,aAAa,GAAG,mCAAmC,CAAC,aAAa,EAAE,mBAAmB,CAAC,CAAC;QAC5F,CAAC;QACD,6DAA6D;QAC7D,IAAI,OAAO,CAAC,gBAAgB,EAAE,CAAC;YAC3B,aAAa,GAAG,8BAA8B,CAAC,aAAa,CAAC,CAAC;QAClE,CAAC;QACD,yEAAyE;QACzE,0EAA0E;QAC1E,IAAI,OAAO,CAAC,SAAS,IAAI,OAAO,OAAO,CAAC,SAAS,KAAK,QAAQ,EAAE,CAAC;YAC7D,MAAM,WAAW,GAAG,IAAI,wBAAwB,EAAE,CAAC;YACnD,0DAA0D;YAC1D,MAAM,WAAW,GAAG,YAAY,CAAC,gBAAgB,CAAC,aAAa,CAAC,CAAC;YACjE,aAAa,GAAG,WAAW,CAAC,cAAc,CAAC,WAAW,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC;QAC/E,CAAC;QAED,OAAO,aAAa,CAAC;IACzB,CAAC;IAEO,yCAAyC,CAAC,OAA0B;QACxE,IAAI,OAAO,CAAC,2BAA2B,EAAE,CAAC;YACtC,OAAO,OAAO,CAAC,2BAA2B,CAAC;QAC/C,CAAC;QAED,IAAI,CAAC,OAAO,CAAC,gCAAgC,EAAE,CAAC;YAC5C,OAAO,EAAE,CAAC;QACd,CAAC;QAED,MAAM,gBAAgB,GAAuC,EAAE,CAAC;QAEhE,mHAAmH;QACnH,KAAK,MAAM,CAAC,aAAa,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,gCAAgC,CAAC,EAAE,CAAC;YAC5F,gBAAgB,CAAC,aAAa,CAAC,GAAG,KAAK,KAAK,QAAQ;gBAChD,CAAC,CAAC,IAAI;gBACN,CAAC,CAAC,uCAAuC,CAAC;QAClD,CAAC;QAED,OAAO,gBAAgB,CAAC;IAC5B,CAAC;IACO,yBAAyB,CAAC,OAA6C;QAC3E,MAAM,cAAc,GAAwC,EAAE,CAAC;QAC/D,MAAM,YAAY,GAAwB,EAAE,CAAC;QAE7C,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;YACjD,IAAI,GAAG,KAAK,SAAS,IAAI,GAAG,KAAK,YAAY,EAAE,CAAC;gBAC5C,wEAAwE;gBACxE,IAAI,CAAC,IAAI,CAAC,4BAA4B,CAAC,KAAK,CAAC,EAAE,CAAC;oBAC5C,MAAM,IAAI,KAAK,CAAC,IAAI,GAAG,2CAA2C,CAAC,CAAC;gBACxE,CAAC;gBACD,IAAI,CAAC,4BAA4B,CAAC,GAAG,EAAE,KAAK,EAAE,YAAY,CAAC,CAAC;gBAC5D,SAAS;YACb,CAAC;YAED,IAAI,IAAI,CAAC,uBAAuB,CAAC,KAAK,CAAC,EAAE,CAAC;gBACtC,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,GAAG,IAAI,CAAC,qBAAqB,CAAC,KAAK,CAAC,CAAC;gBAE1E,IAAI,MAAM,EAAE,CAAC;oBACT,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAC,GAAG,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC;gBAC7E,CAAC;gBACD,IAAI,SAAS,EAAE,CAAC;oBACZ,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAC,GAAG,CAAC,EAAE,SAAS,EAAE,WAAW,CAAC,CAAC,CAAC;gBACnF,CAAC;gBAED,IAAI,QAAQ,EAAE,CAAC;oBACX,cAAc,CAAC,GAAG,CAAC,GAAG,QAAQ,CAAC;gBACnC,CAAC;gBACD,SAAS;YACb,CAAC;YAED,IAAI,IAAI,CAAC,4BAA4B,CAAC,KAAK,CAAC,EAAE,CAAC;gBAC3C,SAAS;YACb,CAAC;YACD,cAAc,CAAC,GAAG,CAAC,GAAG,KAA4B,CAAC;QACvD,CAAC;QAED,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,CAAC;IACrD,CAAC;IAEO,4BAA4B,CAChC,GAA6B,EAC7B,WAA0C,EAC1C,YAAiC;QAEjC,oEAAoE;QACpE,KAAK,MAAM,UAAU,IAAI,WAAW,EAAE,CAAC;YACnC,IAAI,CAAC,UAAU,CAAC,EAAE,IAAI,UAAU,CAAC,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBAC/C,MAAM,IAAI,KAAK,CAAC,SAAS,GAAG,0CAA0C,CAAC,CAAC;YAC5E,CAAC;YACD,YAAY,CAAC,IAAI,CACb,IAAI,CAAC,uBAAuB,CACxB,UAAU,CAAC,EAAE,EACb,UAAU,EACV,GAAG,KAAK,YAAY,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,QAAQ,CAChD,CACJ,CAAC;QACN,CAAC;IACL,CAAC;IAEO,qBAAqB,CAAC,KAA4B;QACtD,MAAM,EAAE,MAAM,EAAE,SAAS,KAAc,KAAK,EAAd,IAAI,UAAK,KAAK,EAAtC,uBAA8B,CAAQ,CAAC;QAC7C,MAAM,YAAY,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC;QAClD,OAAO;YACH,QAAQ,EAAE,YAAY,CAAC,CAAC,CAAE,IAA4B,CAAC,CAAC,CAAC,SAAS;YAClE,MAAM,EAAE,MAA8C;YACtD,SAAS,EAAE,SAAiD;SAC/D,CAAC;IACN,CAAC;IAEO,uBAAuB,CAAC,KAA2B;QACvD,OAAO,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IAChF,CAAC;IAEO,4BAA4B,CAAC,KAA2B;QAC5D,OAAO,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,CAAC,uBAAuB,CAAC,KAAK,CAAC,CAAC,CAAC;IAC7F,CAAC;IAEO,uBAAuB,CAAC,KAAc;QAC1C,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;YACtC,OAAO,KAAK,CAAC;QACjB,CAAC;QACD,MAAM,SAAS,GAAG,KAAoC,CAAC;QACvD,OAAO,CACH,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC;YAC3B,SAAS,CAAC,EAAE,CAAC,MAAM,GAAG,CAAC;YACvB,SAAS,CAAC,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,OAAO,MAAM,KAAK,QAAQ,CAAC;YACxD,OAAO,SAAS,CAAC,GAAG,KAAK,QAAQ,CACpC,CAAC;IACN,CAAC;IAEO,uBAAuB,CAC3B,OAAiB,EACjB,UAAoC,EACpC,IAA4B;QAE5B,IAAI,CAAC,UAAU,CAAC,GAAG,IAAI,OAAO,UAAU,CAAC,GAAG,KAAK,QAAQ,EAAE,CAAC;YACxD,MAAM,IAAI,KAAK,CAAC,8CAA8C,CAAC,CAAC;QACpE,CAAC;QACD,OAAO;YACH,IAAI;YACJ,aAAa,EAAE,OAAO;YACtB,GAAG,EAAE,UAAU,CAAC,GAAG;YACnB,MAAM,EAAE,UAAU,CAAC,MAAM;SAC5B,CAAC;IACN,CAAC;IAEO,kBAAkB,CAAC,KAAkB,EAAE,OAA0B;QACrE,MAAM,iBAAiB,GAAG,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,cAAc,CAAC,IAAI,OAAO,CAAC,cAAc,CAAC,MAAM,GAAG,CAAC,CAAC;QACrG,MAAM,iBAAiB,GAAG,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,cAAc,CAAC,IAAI,OAAO,CAAC,cAAc,CAAC,MAAM,GAAG,CAAC,CAAC;QAErG,IAAI,CAAC,iBAAiB,IAAI,CAAC,iBAAiB,EAAE,CAAC;YAC3C,OAAO,KAAK,CAAC;QACjB,CAAC;QAED,IAAI,iBAAiB,IAAI,iBAAiB,EAAE,CAAC;YACzC,MAAM,IAAI,KAAK,CAAC,4DAA4D,CAAC,CAAC;QAClF,CAAC;QAED,MAAM,WAAW,GAAG,YAAY,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC;QACzD,MAAM,QAAQ,GAAG,WAAW,CAAC,YAAY,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE;YACvD,MAAM,IAAI,GAAG,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC;YAC1C,OAAO;gBACH,IAAI;gBACJ,UAAU,EAAE,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,yBAAyB,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI;aACjE,CAAC;QACN,CAAC,CAAC,CAAC;QAEH,MAAM,gBAAgB,GAAG,IAAI,GAAG,CAC5B,QAAQ;aACH,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,UAAU,CAAC;aAC9B,MAAM,CAAC,CAAC,IAAI,EAAkB,EAAE,CAAC,IAAI,KAAK,IAAI,CAAC,CACvD,CAAC;QAEF,MAAM,cAAc,GAAG,iBAAiB,CAAC,CAAC,CAAC,IAAI,CAAC,mBAAmB,CAAC,OAAO,CAAC,cAAe,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QACpG,MAAM,cAAc,GAAG,iBAAiB,CAAC,CAAC,CAAC,IAAI,CAAC,mBAAmB,CAAC,OAAO,CAAC,cAAe,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QAEpG,MAAM,UAAU,GAAG,cAAc,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,cAAc,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QAClG,MAAM,UAAU,GAAG,cAAc,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,cAAc,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QAElG,IAAI,cAAc,EAAE,CAAC;YACjB,MAAM,OAAO,GAAG,cAAc,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,gBAAgB,CAAC,GAAG,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC;YACxF,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACrB,MAAM,IAAI,KAAK,CACX,SAAS,OAAO,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,gCAAgC,OAAO;qBAC1E,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,KAAK,CAAC,QAAQ,GAAG,CAAC;qBACnC,IAAI,CAAC,IAAI,CAAC,GAAG,CACrB,CAAC;YACN,CAAC;QACL,CAAC;QAED,IAAI,cAAc,EAAE,CAAC;YACjB,MAAM,OAAO,GAAG,cAAc,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,gBAAgB,CAAC,GAAG,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC;YACxF,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACrB,MAAM,IAAI,KAAK,CACX,SAAS,OAAO,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,gCAAgC,OAAO;qBAC1E,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,KAAK,CAAC,QAAQ,GAAG,CAAC;qBACnC,IAAI,CAAC,IAAI,CAAC,GAAG,CACrB,CAAC;YACN,CAAC;QACL,CAAC;QAED,MAAM,aAAa,GAAG,QAAQ;aACzB,MAAM,CAAC,KAAK,CAAC,EAAE;YACZ,IAAI,CAAC,KAAK,CAAC,UAAU,EAAE,CAAC;gBACpB,OAAO,IAAI,CAAC;YAChB,CAAC;YACD,IAAI,UAAU,EAAE,CAAC;gBACb,OAAO,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;YAC5C,CAAC;YACD,IAAI,UAAU,EAAE,CAAC;gBACb,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;YAC7C,CAAC;YACD,OAAO,IAAI,CAAC;QAChB,CAAC,CAAC;aACD,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAE9B,IAAI,aAAa,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC7B,MAAM,IAAI,KAAK,CAAC,6CAA6C,CAAC,CAAC;QACnE,CAAC;QAED,WAAW,CAAC,YAAY,CAAC,KAAK,GAAG,aAAa,CAAC;QAC/C,OAAO,WAAW,CAAC;IACvB,CAAC;IAEO,mBAAmB,CAAC,OAAiB;QACzC,OAAO,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE;YACxB,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE,CAAC;gBAC7B,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAC;YACvD,CAAC;YACD,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC;YAC9B,IAAI,OAAO,KAAK,EAAE,EAAE,CAAC;gBACjB,MAAM,IAAI,KAAK,CAAC,mCAAmC,CAAC,CAAC;YACzD,CAAC;YACD,OAAO;gBACH,UAAU,EAAE,IAAI,CAAC,yBAAyB,CAAC,OAAO,CAAC;gBACnD,QAAQ,EAAE,OAAO;aACpB,CAAC;QACN,CAAC,CAAC,CAAC;IACP,CAAC;IAEO,yBAAyB,CAAC,KAAa;QAC3C,OAAO,KAAK,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IACtC,CAAC;IAEO,iBAAiB,CAAC,IAAgB;QACtC,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YAClB,OAAO,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;QAChC,CAAC;QACD,IAAI,IAAI,CAAC,KAAK,YAAY,eAAe,EAAE,CAAC;YACxC,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC;QAClC,CAAC;QACD,OAAO,IAAI,CAAC;IAChB,CAAC;IAED;;;;;;;OAOG;IACH,kBAAkB,CAAC,UAAkB,EAAE,MAAwB;QAC3D,OAAO,IAAI,CAAC,UAAU,CAAC,UAAU,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;IACnD,CAAC;IAED;;;;;;;OAOG;IACH,gBAAgB,CAAC,UAAkB,EAAE,IAAoB;QACrD,OAAO,IAAI,CAAC,UAAU,CAAC,UAAU,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;IACjD,CAAC,CAAI;;;;;;;OAOF;IACH,mBAAmB,CAAC,UAAkB,EAAE,MAAyB;QAC7D,OAAO,IAAI,CAAC,UAAU,CAAC,UAAU,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;IACnD,CAAC;IAED;;;;;;;OAOG;IACH,oBAAoB,CAAC,UAAkB,EAAE,SAAsB;QAC3D,OAAO,IAAI,CAAC,UAAU,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,CAAC,CAAC;IACtD,CAAC;IAED;;;;;;;OAOG;IACH,WAAW,CAAC,UAAkB;QAC1B,IAAI,CAAC;YACD,iBAAiB,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;YACpC,OAAO,IAAI,CAAC;QAChB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACb,MAAM,IAAI,KAAK,CAAC,gBAAgB,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,EAAE,CAAC,CAAC;QAChG,CAAC;IACL,CAAC;CACJ"}
@@ -0,0 +1,33 @@
1
+ import { SelectQuery } from "../models/SelectQuery";
2
+ import { SqlParameterValue } from "../models/ValueComponent";
3
+ /**
4
+ * Represents an EXISTS / NOT EXISTS instruction derived from filter metadata.
5
+ */
6
+ export interface ExistsInstruction {
7
+ mode: "exists" | "notExists";
8
+ anchorColumns: string[];
9
+ sql: string;
10
+ params?: Record<string, SqlParameterValue>;
11
+ }
12
+ /**
13
+ * Configuration that controls how EXISTS predicates are injected.
14
+ */
15
+ export interface ExistsPredicateOptions {
16
+ tableColumnResolver?: (tableName: string) => string[];
17
+ strict?: boolean;
18
+ }
19
+ /**
20
+ * Describes a correlated subquery that renders an EXISTS/NOT EXISTS predicate.
21
+ */
22
+ export interface ExistsSubqueryDefinition {
23
+ /** SQL that references the `$c#` placeholders for the anchor columns. */
24
+ sql: string;
25
+ /** Optional named parameters that the subquery requires. */
26
+ params?: Record<string, SqlParameterValue>;
27
+ }
28
+ /**
29
+ * Injects EXISTS/NOT EXISTS predicates into the provided SelectQuery.
30
+ * Each instruction is evaluated independently so failures can be skipped
31
+ * when `strict` is false.
32
+ */
33
+ export declare function injectExistsPredicates(query: SelectQuery, instructions: ExistsInstruction[], options?: ExistsPredicateOptions): SelectQuery;
@@ -0,0 +1,294 @@
1
+ import { BinarySelectQuery, SimpleSelectQuery } from "../models/SelectQuery";
2
+ import { ColumnReference, InlineQuery, UnaryExpression } from "../models/ValueComponent";
3
+ import { TableSource } from "../models/Clause";
4
+ import { InsertQuery } from "../models/InsertQuery";
5
+ import { UpdateQuery } from "../models/UpdateQuery";
6
+ import { DeleteQuery } from "../models/DeleteQuery";
7
+ import { QueryBuilder } from "./QueryBuilder";
8
+ import { SelectableColumnCollector, DuplicateDetectionMode } from "./SelectableColumnCollector";
9
+ import { UpstreamSelectQueryFinder } from "./UpstreamSelectQueryFinder";
10
+ import { SqlFormatter } from "./SqlFormatter";
11
+ import { SelectQueryParser } from "../parsers/SelectQueryParser";
12
+ /**
13
+ * Injects EXISTS/NOT EXISTS predicates into the provided SelectQuery.
14
+ * Each instruction is evaluated independently so failures can be skipped
15
+ * when `strict` is false.
16
+ */
17
+ export function injectExistsPredicates(query, instructions, options = {}) {
18
+ if (instructions.length === 0) {
19
+ return query;
20
+ }
21
+ const simpleQuery = QueryBuilder.buildSimpleQuery(query);
22
+ const resolver = new ColumnReferenceResolver(options.tableColumnResolver);
23
+ const formatter = new SqlFormatter();
24
+ const strictMode = !!options.strict;
25
+ for (const instruction of instructions) {
26
+ try {
27
+ applyInstruction(simpleQuery, instruction, resolver, formatter);
28
+ }
29
+ catch (error) {
30
+ if (strictMode) {
31
+ throw error;
32
+ }
33
+ }
34
+ }
35
+ return simpleQuery;
36
+ }
37
+ function applyInstruction(query, instruction, resolver, formatter) {
38
+ if (instruction.anchorColumns.length === 0) {
39
+ throw new Error("EXISTS instruction requires at least one anchor column.");
40
+ }
41
+ const resolvedColumns = instruction.anchorColumns.map(column => {
42
+ const columnRef = resolver.resolve(query, column);
43
+ if (!columnRef) {
44
+ throw new Error(`Unable to resolve anchor column '${column}'.`);
45
+ }
46
+ return columnRef;
47
+ });
48
+ const formattedColumns = resolvedColumns.map(component => formatter.format(component).formattedSql);
49
+ const placeholderSql = substitutePlaceholders(instruction.sql, formattedColumns);
50
+ const normalizedSql = placeholderSql.trim();
51
+ enforceSqlConstraints(normalizedSql);
52
+ const subquery = SelectQueryParser.parse(normalizedSql);
53
+ if (instruction.params) {
54
+ bindSubqueryParameters(subquery, instruction.params);
55
+ }
56
+ const existsExpression = new UnaryExpression("exists", new InlineQuery(subquery));
57
+ const predicate = instruction.mode === "exists"
58
+ ? existsExpression
59
+ : new UnaryExpression("not", existsExpression);
60
+ query.appendWhere(predicate);
61
+ }
62
+ function substitutePlaceholders(sql, formattedColumns) {
63
+ const usedIndexes = new Set();
64
+ const replaced = sql.replace(/\$c(\d+)/g, (_, indexDigits) => {
65
+ const index = Number(indexDigits);
66
+ if (!Number.isInteger(index)) {
67
+ throw new Error(`Invalid placeholder '$c${indexDigits}' in EXISTS SQL.`);
68
+ }
69
+ if (index < 0 || index >= formattedColumns.length) {
70
+ throw new Error(`Placeholder '$c${index}' references a missing anchor column.`);
71
+ }
72
+ usedIndexes.add(index);
73
+ return formattedColumns[index];
74
+ });
75
+ for (let i = 0; i < formattedColumns.length; i++) {
76
+ if (!usedIndexes.has(i)) {
77
+ throw new Error(`Missing placeholder '$c${i}' for anchor column.`);
78
+ }
79
+ }
80
+ return replaced;
81
+ }
82
+ function enforceSqlConstraints(sql) {
83
+ if (!sql) {
84
+ throw new Error("EXISTS SQL must not be empty.");
85
+ }
86
+ if (sql.includes(";")) {
87
+ throw new Error("EXISTS SQL must not contain semicolons or multiple statements.");
88
+ }
89
+ if (/\blateral\b/i.test(sql)) {
90
+ throw new Error("LATERAL is not supported in column-anchored EXISTS filters.");
91
+ }
92
+ }
93
+ function bindSubqueryParameters(query, params) {
94
+ for (const [name, value] of Object.entries(params)) {
95
+ query.setParameter(name, value);
96
+ }
97
+ }
98
+ class ColumnReferenceResolver {
99
+ constructor(tableColumnResolver) {
100
+ this.tableColumnResolver = tableColumnResolver;
101
+ this.finder = new UpstreamSelectQueryFinder(this.tableColumnResolver);
102
+ this.collector = new SelectableColumnCollector(this.tableColumnResolver, false, DuplicateDetectionMode.FullName, { upstream: true });
103
+ }
104
+ resolve(query, columnName) {
105
+ var _a;
106
+ const parsed = this.parseQualifiedColumnName(columnName);
107
+ const searchColumn = (_a = parsed === null || parsed === void 0 ? void 0 : parsed.column) !== null && _a !== void 0 ? _a : columnName;
108
+ const targetTable = parsed === null || parsed === void 0 ? void 0 : parsed.table;
109
+ const candidateQueries = this.finder.find(query, searchColumn);
110
+ for (const candidate of candidateQueries) {
111
+ const columns = this.collectColumns(candidate);
112
+ const match = this.findMatchingColumn(columns, searchColumn, targetTable, candidate);
113
+ if (match) {
114
+ return match.value;
115
+ }
116
+ }
117
+ return null;
118
+ }
119
+ collectColumns(query) {
120
+ const columnEntries = this.collector.collect(query);
121
+ const cteColumns = this.collectCTEColumns(query);
122
+ return [...columnEntries, ...cteColumns];
123
+ }
124
+ findMatchingColumn(columns, searchColumn, targetTable, query) {
125
+ const normalizedSearch = this.normalizeColumnName(searchColumn);
126
+ for (const entry of columns) {
127
+ const normalizedEntry = this.normalizeColumnName(entry.name);
128
+ if (normalizedEntry !== normalizedSearch)
129
+ continue;
130
+ if (targetTable) {
131
+ if (this.matchesTable(entry.value, targetTable, query)) {
132
+ return entry;
133
+ }
134
+ continue;
135
+ }
136
+ return entry;
137
+ }
138
+ return null;
139
+ }
140
+ matchesTable(value, targetTable, query) {
141
+ if (!(value instanceof ColumnReference)) {
142
+ return false;
143
+ }
144
+ const namespace = value.getNamespace();
145
+ if (!namespace) {
146
+ return false;
147
+ }
148
+ const normalizedTarget = this.normalizeString(targetTable);
149
+ const mapping = this.buildTableMapping(query);
150
+ const aliasKey = namespace.toLowerCase();
151
+ const mappedRealTable = mapping.aliasToRealTable.get(aliasKey);
152
+ if (mappedRealTable && this.normalizeString(mappedRealTable) === normalizedTarget) {
153
+ return true;
154
+ }
155
+ if (this.normalizeString(namespace) === normalizedTarget) {
156
+ return true;
157
+ }
158
+ const aliasFromTarget = mapping.realTableToAlias.get(normalizedTarget);
159
+ if (aliasFromTarget && aliasFromTarget.toLowerCase() === aliasKey) {
160
+ return true;
161
+ }
162
+ return false;
163
+ }
164
+ collectCTEColumns(query) {
165
+ const results = [];
166
+ if (!query.withClause) {
167
+ return results;
168
+ }
169
+ for (const cte of query.withClause.tables) {
170
+ try {
171
+ const nestedColumns = this.collectColumnsFromCteQuery(cte.query);
172
+ results.push(...nestedColumns);
173
+ }
174
+ catch (_a) {
175
+ // Skip problematic CTEs to keep resolution best-effort.
176
+ }
177
+ }
178
+ return results;
179
+ }
180
+ collectColumnsFromCteQuery(query) {
181
+ if (!this.isSelectQuery(query)) {
182
+ return this.collectColumnsFromReturning(query);
183
+ }
184
+ return this.collectColumnsFromSelectQuery(query);
185
+ }
186
+ collectColumnsFromSelectQuery(query) {
187
+ if (query instanceof SimpleSelectQuery) {
188
+ return this.collector.collect(query);
189
+ }
190
+ if (query instanceof BinarySelectQuery) {
191
+ return this.collectColumnsFromSelectQuery(query.left);
192
+ }
193
+ return [];
194
+ }
195
+ collectColumnsFromReturning(query) {
196
+ if (query instanceof InsertQuery || query instanceof UpdateQuery || query instanceof DeleteQuery) {
197
+ return this.extractReturningColumns(query.returningClause);
198
+ }
199
+ return [];
200
+ }
201
+ extractReturningColumns(returningClause) {
202
+ var _a, _b;
203
+ if (!returningClause) {
204
+ return [];
205
+ }
206
+ const columns = [];
207
+ for (const item of returningClause.items) {
208
+ const columnName = (_b = (_a = item.identifier) === null || _a === void 0 ? void 0 : _a.name) !== null && _b !== void 0 ? _b : this.extractColumnName(item);
209
+ if (columnName) {
210
+ columns.push({ name: columnName, value: item.value });
211
+ }
212
+ }
213
+ return columns;
214
+ }
215
+ extractColumnName(item) {
216
+ if (item.identifier) {
217
+ return item.identifier.name;
218
+ }
219
+ if (item.value instanceof ColumnReference) {
220
+ return item.value.column.name;
221
+ }
222
+ return null;
223
+ }
224
+ buildTableMapping(query) {
225
+ var _a, _b;
226
+ const aliasToRealMap = new Map();
227
+ const realToAliasMap = new Map();
228
+ const collectFromClause = (fromClause) => {
229
+ if (!fromClause)
230
+ return;
231
+ this.processSourceForMapping(fromClause.source, aliasToRealMap, realToAliasMap);
232
+ if (fromClause.joins) {
233
+ for (const join of fromClause.joins) {
234
+ this.processSourceForMapping(join.source, aliasToRealMap, realToAliasMap);
235
+ }
236
+ }
237
+ };
238
+ collectFromClause((_a = query.fromClause) !== null && _a !== void 0 ? _a : undefined);
239
+ if (query.withClause) {
240
+ for (const cte of query.withClause.tables) {
241
+ const alias = (_b = cte.getSourceAliasName()) === null || _b === void 0 ? void 0 : _b.toLowerCase();
242
+ if (alias) {
243
+ aliasToRealMap.set(alias, alias);
244
+ realToAliasMap.set(alias, alias);
245
+ }
246
+ }
247
+ }
248
+ return {
249
+ aliasToRealTable: aliasToRealMap,
250
+ realTableToAlias: realToAliasMap
251
+ };
252
+ }
253
+ processSourceForMapping(source, aliasToReal, realToAlias) {
254
+ var _a, _b;
255
+ try {
256
+ if (source.datasource instanceof TableSource) {
257
+ const realName = source.datasource.getSourceName();
258
+ const aliasName = ((_b = (_a = source.aliasExpression) === null || _a === void 0 ? void 0 : _a.table) === null || _b === void 0 ? void 0 : _b.name) || realName;
259
+ if (realName && aliasName) {
260
+ aliasToReal.set(aliasName.toLowerCase(), realName);
261
+ realToAlias.set(realName.toLowerCase(), aliasName);
262
+ if (aliasName.toLowerCase() === realName.toLowerCase()) {
263
+ aliasToReal.set(realName.toLowerCase(), realName);
264
+ }
265
+ }
266
+ }
267
+ }
268
+ catch (_c) {
269
+ // Ignore mapping issues while continuing best-effort column resolution.
270
+ }
271
+ }
272
+ parseQualifiedColumnName(columnName) {
273
+ const parts = columnName.split(".");
274
+ if (parts.length === 2 && parts[0].trim() && parts[1].trim()) {
275
+ return {
276
+ table: parts[0].trim(),
277
+ column: parts[1].trim()
278
+ };
279
+ }
280
+ return null;
281
+ }
282
+ normalizeColumnName(name) {
283
+ var _a;
284
+ const columnPart = name.includes(".") ? (_a = name.split(".").pop()) !== null && _a !== void 0 ? _a : name : name;
285
+ return this.normalizeString(columnPart);
286
+ }
287
+ normalizeString(value) {
288
+ return value.toLowerCase();
289
+ }
290
+ isSelectQuery(query) {
291
+ return "__selectQueryType" in query && query.__selectQueryType === "SelectQuery";
292
+ }
293
+ }
294
+ //# sourceMappingURL=ExistsPredicateInjector.js.map