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