rawsql-ts 0.11.14-beta → 0.11.15-beta

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 (31) hide show
  1. package/dist/esm/index.js +2 -0
  2. package/dist/esm/index.js.map +1 -1
  3. package/dist/esm/index.min.js +19 -17
  4. package/dist/esm/index.min.js.map +4 -4
  5. package/dist/esm/src/index.d.ts +2 -0
  6. package/dist/esm/src/index.js +2 -0
  7. package/dist/esm/src/index.js.map +1 -1
  8. package/dist/esm/src/transformers/CTEComposer.d.ts +136 -0
  9. package/dist/esm/src/transformers/CTEComposer.js +298 -0
  10. package/dist/esm/src/transformers/CTEComposer.js.map +1 -0
  11. package/dist/esm/src/transformers/CTEQueryDecomposer.d.ts +213 -0
  12. package/dist/esm/src/transformers/CTEQueryDecomposer.js +360 -0
  13. package/dist/esm/src/transformers/CTEQueryDecomposer.js.map +1 -0
  14. package/dist/esm/src/transformers/SqlFormatter.d.ts +39 -21
  15. package/dist/esm/src/transformers/SqlFormatter.js.map +1 -1
  16. package/dist/esm/tsconfig.browser.tsbuildinfo +1 -1
  17. package/dist/index.min.js +19 -17
  18. package/dist/index.min.js.map +4 -4
  19. package/dist/src/index.d.ts +2 -0
  20. package/dist/src/index.js +2 -0
  21. package/dist/src/index.js.map +1 -1
  22. package/dist/src/transformers/CTEComposer.d.ts +136 -0
  23. package/dist/src/transformers/CTEComposer.js +302 -0
  24. package/dist/src/transformers/CTEComposer.js.map +1 -0
  25. package/dist/src/transformers/CTEQueryDecomposer.d.ts +213 -0
  26. package/dist/src/transformers/CTEQueryDecomposer.js +369 -0
  27. package/dist/src/transformers/CTEQueryDecomposer.js.map +1 -0
  28. package/dist/src/transformers/SqlFormatter.d.ts +39 -21
  29. package/dist/src/transformers/SqlFormatter.js.map +1 -1
  30. package/dist/tsconfig.tsbuildinfo +1 -1
  31. package/package.json +1 -1
@@ -10,6 +10,8 @@ export * from './transformers/CTECollector';
10
10
  export * from './transformers/CTENormalizer';
11
11
  export * from './transformers/CTEDisabler';
12
12
  export * from './transformers/CTEDependencyAnalyzer';
13
+ export * from './transformers/CTEQueryDecomposer';
14
+ export * from './transformers/CTEComposer';
13
15
  export * from './transformers/Formatter';
14
16
  export * from './transformers/SqlFormatter';
15
17
  export * from './transformers/PostgresJsonQueryBuilder';
package/dist/src/index.js CHANGED
@@ -28,6 +28,8 @@ __exportStar(require("./transformers/CTECollector"), exports);
28
28
  __exportStar(require("./transformers/CTENormalizer"), exports);
29
29
  __exportStar(require("./transformers/CTEDisabler"), exports);
30
30
  __exportStar(require("./transformers/CTEDependencyAnalyzer"), exports);
31
+ __exportStar(require("./transformers/CTEQueryDecomposer"), exports);
32
+ __exportStar(require("./transformers/CTEComposer"), exports);
31
33
  __exportStar(require("./transformers/Formatter"), exports);
32
34
  __exportStar(require("./transformers/SqlFormatter"), exports);
33
35
  __exportStar(require("./transformers/PostgresJsonQueryBuilder"), exports);
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAAA,oCAAoC;AACpC,8DAA4C;AAC5C,8DAA4C;AAE5C,6DAA2C;AAC3C,uDAAqC;AACrC,0DAAwC;AACxC,uDAAqC;AACrC,oDAAkC;AAClC,kDAAgC;AAEhC,8DAA4C;AAC5C,+DAA6C;AAC7C,6DAA2C;AAC3C,uEAAqD;AACrD,2DAAyC;AACzC,8DAA4C;AAC5C,0EAAwD;AACxD,8DAA4C,CAAC,0BAA0B;AACvE,sEAAoD;AACpD,2EAAyD;AACzD,qEAAmD;AACnD,sEAAoD;AACpD,sEAAoD;AACpD,qEAAmD;AACnD,gFAQ+C;AAN3C,mIAAA,yBAAyB,OAAA;AACzB,oIAAA,0BAA0B,OAAA;AAM9B,wEAM2C;AALvC,6DAA6D;AAC7D,wHAAA,kBAAkB,OAAA;AAClB,yHAAA,mBAAmB,OAAA;AACnB,qHAAA,eAAe,OAAA;AACf,oHAAA,cAAc,OAAA;AAGlB,qEAAqE;AACrE,wEAAqE;AAA5D,sHAAA,gBAAgB,OAAA;AACzB,2EAAyD;AACzD,iFAA+D;AAE/D,iEAA+C;AAC/C,2EAAyD;AACzD,kEAAgD;AAChD,iEAA+C;AAC/C,uEAAqD;AACrD,qEAAmD;AAEnD,6DAA2C;AAC3C,8DAA4C;AAC5C,wDAAsC;AACtC,wDAAsC;AACtC,uDAAqC;AAGrC,oEAAoE"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAAA,oCAAoC;AACpC,8DAA4C;AAC5C,8DAA4C;AAE5C,6DAA2C;AAC3C,uDAAqC;AACrC,0DAAwC;AACxC,uDAAqC;AACrC,oDAAkC;AAClC,kDAAgC;AAEhC,8DAA4C;AAC5C,+DAA6C;AAC7C,6DAA2C;AAC3C,uEAAqD;AACrD,oEAAkD;AAClD,6DAA2C;AAC3C,2DAAyC;AACzC,8DAA4C;AAC5C,0EAAwD;AACxD,8DAA4C,CAAC,0BAA0B;AACvE,sEAAoD;AACpD,2EAAyD;AACzD,qEAAmD;AACnD,sEAAoD;AACpD,sEAAoD;AACpD,qEAAmD;AACnD,gFAQ+C;AAN3C,mIAAA,yBAAyB,OAAA;AACzB,oIAAA,0BAA0B,OAAA;AAM9B,wEAM2C;AALvC,6DAA6D;AAC7D,wHAAA,kBAAkB,OAAA;AAClB,yHAAA,mBAAmB,OAAA;AACnB,qHAAA,eAAe,OAAA;AACf,oHAAA,cAAc,OAAA;AAGlB,qEAAqE;AACrE,wEAAqE;AAA5D,sHAAA,gBAAgB,OAAA;AACzB,2EAAyD;AACzD,iFAA+D;AAE/D,iEAA+C;AAC/C,2EAAyD;AACzD,kEAAgD;AAChD,iEAA+C;AAC/C,uEAAqD;AACrD,qEAAmD;AAEnD,6DAA2C;AAC3C,8DAA4C;AAC5C,wDAAsC;AACtC,wDAAsC;AACtC,uDAAqC;AAGrC,oEAAoE"}
@@ -0,0 +1,136 @@
1
+ import { SqlFormatterOptions } from "./SqlFormatter";
2
+ /**
3
+ * Interface representing an edited CTE with simplified structure
4
+ * @public
5
+ */
6
+ export interface EditedCTE {
7
+ /** Name of the CTE */
8
+ name: string;
9
+ /** SQL query for this CTE, may contain WITH clause from editing */
10
+ query: string;
11
+ }
12
+ /**
13
+ * Options for CTEComposer extending SqlFormatterOptions
14
+ * @public
15
+ */
16
+ export interface CTEComposerOptions extends SqlFormatterOptions {
17
+ /** Whether to validate the composed query against a schema */
18
+ validateSchema?: boolean;
19
+ /** Table to columns mapping for schema validation (required if validateSchema is true) */
20
+ schema?: Record<string, string[]>;
21
+ }
22
+ /**
23
+ * Composes edited CTEs back into a unified SQL query
24
+ *
25
+ * Takes CTEs that were individually edited after decomposition and reconstructs them
26
+ * into a proper WITH clause structure. This completes the CTE debugging workflow:
27
+ * 1. Use CTEQueryDecomposer to break down complex CTEs
28
+ * 2. Edit individual CTEs to fix issues
29
+ * 3. Use CTEComposer to reconstruct the unified query
30
+ *
31
+ * @example
32
+ * ```typescript
33
+ * // After decomposing and editing CTEs
34
+ * const composer = new CTEComposer({
35
+ * preset: 'postgres',
36
+ * validateSchema: true,
37
+ * schema: { users: ['id', 'name', 'active'] }
38
+ * });
39
+ *
40
+ * const editedCTEs = [
41
+ * { name: 'base_data', query: 'select * from users where active = true' },
42
+ * { name: 'filtered_data', query: 'select * from base_data where region = "US"' }
43
+ * ];
44
+ *
45
+ * const composedSQL = composer.compose(editedCTEs, 'select * from filtered_data');
46
+ * // Dependencies are automatically analyzed and sorted
47
+ * // Result: "with base_data as (...), filtered_data as (...) select * from filtered_data"
48
+ * ```
49
+ *
50
+ * @public
51
+ */
52
+ export declare class CTEComposer {
53
+ private readonly formatter;
54
+ private readonly options;
55
+ private readonly dependencyAnalyzer;
56
+ private knownCTENames;
57
+ /**
58
+ * Creates a new CTEComposer instance
59
+ * @param options - Configuration options extending SqlFormatterOptions
60
+ */
61
+ constructor(options?: CTEComposerOptions);
62
+ /**
63
+ * Compose edited CTEs and root query into a unified SQL query
64
+ *
65
+ * This method:
66
+ * 1. Extracts pure SELECT queries from edited CTEs (removes any WITH clauses)
67
+ * 2. Builds a temporary query to analyze dependencies automatically
68
+ * 3. Sorts CTEs by dependency order using topological sort
69
+ * 4. Validates schema if options.validateSchema is enabled
70
+ * 5. Applies formatter options for consistent output
71
+ * 6. Constructs the final WITH clause with proper recursive handling
72
+ *
73
+ * @param editedCTEs - Array of edited CTEs with name and query only
74
+ * @param rootQuery - The main query that uses the CTEs (without WITH clause)
75
+ * @returns Composed SQL query with properly structured WITH clause
76
+ * @throws Error if schema validation fails or circular dependencies are detected
77
+ *
78
+ * @example
79
+ * ```typescript
80
+ * const editedCTEs = [
81
+ * { name: 'base_data', query: 'select * from users where active = true' },
82
+ * { name: 'filtered_data', query: 'select * from base_data where region = "US"' }
83
+ * ];
84
+ *
85
+ * const result = composer.compose(editedCTEs, 'select count(*) from filtered_data');
86
+ * // Dependencies automatically analyzed and sorted
87
+ * // Result: "with base_data as (...), filtered_data as (...) select count(*) from filtered_data"
88
+ * ```
89
+ */
90
+ compose(editedCTEs: EditedCTE[], rootQuery: string): string;
91
+ /**
92
+ * Extract pure SELECT query from a query that may contain WITH clause
93
+ * If query contains WITH with known CTEs, extract main SELECT and ignore old definitions
94
+ * If query contains WITH with unknown CTEs, preserve entire query
95
+ * @param query The query that may contain WITH clause
96
+ * @param cteName The name of the CTE to extract (if query contains WITH)
97
+ * @returns Pure SELECT query without WITH clause, or entire query if it contains new sub-CTEs
98
+ */
99
+ private extractPureQuery;
100
+ /**
101
+ * Get list of known CTE names from current composition context
102
+ */
103
+ private getKnownCTENames;
104
+ /**
105
+ * Extract CTE name from CommonTable
106
+ */
107
+ private getCTEName;
108
+ /**
109
+ * Extract CTE definition using regex as fallback
110
+ */
111
+ private extractCTEWithRegex;
112
+ /**
113
+ * Build a temporary query for dependency analysis
114
+ */
115
+ private buildTempQueryForAnalysis;
116
+ /**
117
+ * Sort CTEs by dependencies using dependency graph
118
+ */
119
+ private sortCTEsByDependencies;
120
+ /**
121
+ * Detect if any CTEs are recursive by analyzing original queries
122
+ */
123
+ private detectRecursiveFromOriginalQueries;
124
+ /**
125
+ * Detect if any CTEs are recursive
126
+ */
127
+ private detectRecursiveCTEs;
128
+ /**
129
+ * Validate the composed query against schema
130
+ */
131
+ private validateComposedQuery;
132
+ /**
133
+ * Apply formatting to the final query
134
+ */
135
+ private formatFinalQuery;
136
+ }
@@ -0,0 +1,302 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CTEComposer = void 0;
4
+ const SimpleSelectQuery_1 = require("../models/SimpleSelectQuery");
5
+ const SelectQueryParser_1 = require("../parsers/SelectQueryParser");
6
+ const SqlFormatter_1 = require("./SqlFormatter");
7
+ const SqlSchemaValidator_1 = require("../utils/SqlSchemaValidator");
8
+ const CTEDependencyAnalyzer_1 = require("./CTEDependencyAnalyzer");
9
+ /**
10
+ * Composes edited CTEs back into a unified SQL query
11
+ *
12
+ * Takes CTEs that were individually edited after decomposition and reconstructs them
13
+ * into a proper WITH clause structure. This completes the CTE debugging workflow:
14
+ * 1. Use CTEQueryDecomposer to break down complex CTEs
15
+ * 2. Edit individual CTEs to fix issues
16
+ * 3. Use CTEComposer to reconstruct the unified query
17
+ *
18
+ * @example
19
+ * ```typescript
20
+ * // After decomposing and editing CTEs
21
+ * const composer = new CTEComposer({
22
+ * preset: 'postgres',
23
+ * validateSchema: true,
24
+ * schema: { users: ['id', 'name', 'active'] }
25
+ * });
26
+ *
27
+ * const editedCTEs = [
28
+ * { name: 'base_data', query: 'select * from users where active = true' },
29
+ * { name: 'filtered_data', query: 'select * from base_data where region = "US"' }
30
+ * ];
31
+ *
32
+ * const composedSQL = composer.compose(editedCTEs, 'select * from filtered_data');
33
+ * // Dependencies are automatically analyzed and sorted
34
+ * // Result: "with base_data as (...), filtered_data as (...) select * from filtered_data"
35
+ * ```
36
+ *
37
+ * @public
38
+ */
39
+ class CTEComposer {
40
+ /**
41
+ * Creates a new CTEComposer instance
42
+ * @param options - Configuration options extending SqlFormatterOptions
43
+ */
44
+ constructor(options = {}) {
45
+ this.knownCTENames = [];
46
+ this.options = options;
47
+ this.formatter = new SqlFormatter_1.SqlFormatter(options);
48
+ this.dependencyAnalyzer = new CTEDependencyAnalyzer_1.CTEDependencyAnalyzer();
49
+ }
50
+ /**
51
+ * Compose edited CTEs and root query into a unified SQL query
52
+ *
53
+ * This method:
54
+ * 1. Extracts pure SELECT queries from edited CTEs (removes any WITH clauses)
55
+ * 2. Builds a temporary query to analyze dependencies automatically
56
+ * 3. Sorts CTEs by dependency order using topological sort
57
+ * 4. Validates schema if options.validateSchema is enabled
58
+ * 5. Applies formatter options for consistent output
59
+ * 6. Constructs the final WITH clause with proper recursive handling
60
+ *
61
+ * @param editedCTEs - Array of edited CTEs with name and query only
62
+ * @param rootQuery - The main query that uses the CTEs (without WITH clause)
63
+ * @returns Composed SQL query with properly structured WITH clause
64
+ * @throws Error if schema validation fails or circular dependencies are detected
65
+ *
66
+ * @example
67
+ * ```typescript
68
+ * const editedCTEs = [
69
+ * { name: 'base_data', query: 'select * from users where active = true' },
70
+ * { name: 'filtered_data', query: 'select * from base_data where region = "US"' }
71
+ * ];
72
+ *
73
+ * const result = composer.compose(editedCTEs, 'select count(*) from filtered_data');
74
+ * // Dependencies automatically analyzed and sorted
75
+ * // Result: "with base_data as (...), filtered_data as (...) select count(*) from filtered_data"
76
+ * ```
77
+ */
78
+ compose(editedCTEs, rootQuery) {
79
+ if (editedCTEs.length === 0) {
80
+ return rootQuery;
81
+ }
82
+ // Set known CTE names for WITH clause filtering
83
+ this.knownCTENames = editedCTEs.map(cte => cte.name);
84
+ // Extract pure queries and detect recursion
85
+ const pureQueries = editedCTEs.map(cte => ({
86
+ name: cte.name,
87
+ query: this.extractPureQuery(cte.query, cte.name)
88
+ }));
89
+ // Build temporary query to analyze dependencies
90
+ const tempQuery = this.buildTempQueryForAnalysis(pureQueries, rootQuery);
91
+ // Analyze dependencies
92
+ const dependencyGraph = this.dependencyAnalyzer.analyzeDependencies(tempQuery);
93
+ // Sort CTEs by dependencies
94
+ const sortedCTEs = this.sortCTEsByDependencies(pureQueries, dependencyGraph);
95
+ // Check for recursive CTEs by analyzing original queries
96
+ const isRecursive = this.detectRecursiveFromOriginalQueries(editedCTEs);
97
+ // Special handling for recursive CTEs: Current implementation preserves recursive CTEs as-is
98
+ // This is expected behavior for now as recursive CTEs require complex handling
99
+ // Build WITH clause with sorted CTEs
100
+ const cteDefinitions = sortedCTEs.map(cte => {
101
+ return `${cte.name} as (${cte.query})`;
102
+ });
103
+ const withKeyword = isRecursive ? "with recursive" : "with";
104
+ const composedQuery = `${withKeyword} ${cteDefinitions.join(", ")} ${rootQuery}`;
105
+ // Validate schema if requested
106
+ if (this.options.validateSchema && this.options.schema) {
107
+ this.validateComposedQuery(composedQuery);
108
+ }
109
+ // Apply formatting if options specify it
110
+ return this.formatFinalQuery(composedQuery);
111
+ }
112
+ /**
113
+ * Extract pure SELECT query from a query that may contain WITH clause
114
+ * If query contains WITH with known CTEs, extract main SELECT and ignore old definitions
115
+ * If query contains WITH with unknown CTEs, preserve entire query
116
+ * @param query The query that may contain WITH clause
117
+ * @param cteName The name of the CTE to extract (if query contains WITH)
118
+ * @returns Pure SELECT query without WITH clause, or entire query if it contains new sub-CTEs
119
+ */
120
+ extractPureQuery(query, cteName) {
121
+ // Simple regex to check if query starts with WITH
122
+ const withPattern = /^\s*with\s+/i;
123
+ if (!withPattern.test(query)) {
124
+ return query;
125
+ }
126
+ // Check if this is a recursive CTE by looking for "WITH RECURSIVE"
127
+ const recursivePattern = /^\s*with\s+recursive\s+/i;
128
+ if (recursivePattern.test(query)) {
129
+ // For recursive CTEs, preserve the entire query as-is
130
+ return query;
131
+ }
132
+ // Parse the query to check what CTEs are defined in the WITH clause
133
+ try {
134
+ const parsed = SelectQueryParser_1.SelectQueryParser.parse(query);
135
+ if (parsed.withClause && parsed.withClause.tables) {
136
+ // Check if WITH clause contains only known CTEs from our composition
137
+ const knownCTENames = this.getKnownCTENames();
138
+ const withCTENames = parsed.withClause.tables.map(cte => this.getCTEName(cte));
139
+ // If all CTEs in WITH clause are known (old definitions), extract main SELECT
140
+ const hasOnlyKnownCTEs = withCTENames.every(name => knownCTENames.includes(name));
141
+ if (hasOnlyKnownCTEs) {
142
+ // Remove WITH clause and format just the main query
143
+ const queryWithoutWith = new SimpleSelectQuery_1.SimpleSelectQuery({
144
+ selectClause: parsed.selectClause,
145
+ fromClause: parsed.fromClause,
146
+ whereClause: parsed.whereClause,
147
+ groupByClause: parsed.groupByClause,
148
+ havingClause: parsed.havingClause,
149
+ orderByClause: parsed.orderByClause,
150
+ windowClause: parsed.windowClause,
151
+ limitClause: parsed.limitClause,
152
+ offsetClause: parsed.offsetClause,
153
+ fetchClause: parsed.fetchClause,
154
+ forClause: parsed.forClause,
155
+ withClause: undefined // withClause removed
156
+ });
157
+ // Use a formatter without quotes for extraction to preserve original format
158
+ const extractFormatter = new SqlFormatter_1.SqlFormatter({
159
+ identifierEscape: { start: "", end: "" }
160
+ });
161
+ return extractFormatter.format(queryWithoutWith).formattedSql;
162
+ }
163
+ }
164
+ }
165
+ catch (error) {
166
+ // If parsing fails, fall through to preserve entire query
167
+ }
168
+ // If query contains WITH clause with unknown CTEs, preserve it like a recursive CTE
169
+ // This handles the case where user edited a CTE and added new sub-CTEs
170
+ return query;
171
+ }
172
+ /**
173
+ * Get list of known CTE names from current composition context
174
+ */
175
+ getKnownCTENames() {
176
+ // This will be set during composition to track known CTE names
177
+ return this.knownCTENames || [];
178
+ }
179
+ /**
180
+ * Extract CTE name from CommonTable
181
+ */
182
+ getCTEName(cte) {
183
+ return cte.aliasExpression.table.name;
184
+ }
185
+ /**
186
+ * Extract CTE definition using regex as fallback
187
+ */
188
+ extractCTEWithRegex(query, cteName) {
189
+ // More robust regex to extract CTE definition
190
+ // Pattern: cteName as (...) accounting for nested parentheses
191
+ const ctePattern = new RegExp(`${cteName}\\s+as\\s*\\(`, 'i');
192
+ const match = query.match(ctePattern);
193
+ if (!match) {
194
+ return query;
195
+ }
196
+ // Find the start of the CTE definition (after "as (")
197
+ const startIndex = match.index + match[0].length;
198
+ // Use parentheses counting to find the end of the CTE definition
199
+ let parenCount = 1;
200
+ let endIndex = startIndex;
201
+ while (endIndex < query.length && parenCount > 0) {
202
+ const char = query[endIndex];
203
+ if (char === '(') {
204
+ parenCount++;
205
+ }
206
+ else if (char === ')') {
207
+ parenCount--;
208
+ }
209
+ endIndex++;
210
+ }
211
+ if (parenCount === 0) {
212
+ // Extract the content between parentheses
213
+ const cteDefinition = query.substring(startIndex, endIndex - 1).trim();
214
+ return cteDefinition;
215
+ }
216
+ return query;
217
+ }
218
+ /**
219
+ * Build a temporary query for dependency analysis
220
+ */
221
+ buildTempQueryForAnalysis(pureQueries, rootQuery) {
222
+ const cteDefinitions = pureQueries.map(cte => `${cte.name} as (${cte.query})`);
223
+ const tempSql = `with ${cteDefinitions.join(", ")} ${rootQuery}`;
224
+ try {
225
+ return SelectQueryParser_1.SelectQueryParser.parse(tempSql);
226
+ }
227
+ catch (error) {
228
+ throw new Error(`Failed to parse temporary query for dependency analysis: ${error}`);
229
+ }
230
+ }
231
+ /**
232
+ * Sort CTEs by dependencies using dependency graph
233
+ */
234
+ sortCTEsByDependencies(pureQueries, dependencyGraph) {
235
+ // Create a map for quick lookup
236
+ const queryMap = new Map();
237
+ pureQueries.forEach(cte => queryMap.set(cte.name, cte.query));
238
+ // Return CTEs in dependency order
239
+ return dependencyGraph.nodes.map(node => ({
240
+ name: node.name,
241
+ query: queryMap.get(node.name) || ""
242
+ })).filter(cte => cte.query !== "");
243
+ }
244
+ /**
245
+ * Detect if any CTEs are recursive by analyzing original queries
246
+ */
247
+ detectRecursiveFromOriginalQueries(editedCTEs) {
248
+ // Check if any of the original queries contain "with recursive"
249
+ return editedCTEs.some(cte => {
250
+ const queryLower = cte.query.toLowerCase();
251
+ return queryLower.includes('with recursive');
252
+ });
253
+ }
254
+ /**
255
+ * Detect if any CTEs are recursive
256
+ */
257
+ detectRecursiveCTEs(query) {
258
+ if (!query.withClause)
259
+ return false;
260
+ // Check if the query text contains "recursive"
261
+ const queryText = this.formatter.format(query).formattedSql.toLowerCase();
262
+ return queryText.includes('with recursive');
263
+ }
264
+ /**
265
+ * Validate the composed query against schema
266
+ */
267
+ validateComposedQuery(composedQuery) {
268
+ try {
269
+ const parsed = SelectQueryParser_1.SelectQueryParser.parse(composedQuery);
270
+ // Convert schema to TableSchema format
271
+ const tableSchemas = Object.entries(this.options.schema).map(([name, columns]) => ({
272
+ name,
273
+ columns
274
+ }));
275
+ SqlSchemaValidator_1.SqlSchemaValidator.validate(parsed, tableSchemas);
276
+ }
277
+ catch (error) {
278
+ if (error instanceof Error) {
279
+ throw new Error(`Schema validation failed: ${error.message}`);
280
+ }
281
+ throw error;
282
+ }
283
+ }
284
+ /**
285
+ * Apply formatting to the final query
286
+ */
287
+ formatFinalQuery(composedQuery) {
288
+ if (this.options.preset || this.options.keywordCase) {
289
+ try {
290
+ const parsed = SelectQueryParser_1.SelectQueryParser.parse(composedQuery);
291
+ return this.formatter.format(parsed).formattedSql;
292
+ }
293
+ catch (error) {
294
+ // If parsing fails, return unformatted query
295
+ return composedQuery;
296
+ }
297
+ }
298
+ return composedQuery;
299
+ }
300
+ }
301
+ exports.CTEComposer = CTEComposer;
302
+ //# sourceMappingURL=CTEComposer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CTEComposer.js","sourceRoot":"","sources":["../../../src/transformers/CTEComposer.ts"],"names":[],"mappings":"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"}