rawsql-ts 0.11.14-beta → 0.11.16-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.
- package/dist/esm/index.js +2 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/index.min.js +19 -17
- package/dist/esm/index.min.js.map +4 -4
- package/dist/esm/src/index.d.ts +2 -0
- package/dist/esm/src/index.js +2 -0
- package/dist/esm/src/index.js.map +1 -1
- package/dist/esm/src/transformers/CTEComposer.d.ts +136 -0
- package/dist/esm/src/transformers/CTEComposer.js +298 -0
- package/dist/esm/src/transformers/CTEComposer.js.map +1 -0
- package/dist/esm/src/transformers/CTEQueryDecomposer.d.ts +213 -0
- package/dist/esm/src/transformers/CTEQueryDecomposer.js +360 -0
- package/dist/esm/src/transformers/CTEQueryDecomposer.js.map +1 -0
- package/dist/esm/src/transformers/SqlFormatter.d.ts +39 -21
- package/dist/esm/src/transformers/SqlFormatter.js.map +1 -1
- package/dist/esm/tsconfig.browser.tsbuildinfo +1 -1
- package/dist/index.min.js +19 -17
- package/dist/index.min.js.map +4 -4
- package/dist/src/index.d.ts +2 -0
- package/dist/src/index.js +2 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/transformers/CTEComposer.d.ts +136 -0
- package/dist/src/transformers/CTEComposer.js +302 -0
- package/dist/src/transformers/CTEComposer.js.map +1 -0
- package/dist/src/transformers/CTEQueryDecomposer.d.ts +213 -0
- package/dist/src/transformers/CTEQueryDecomposer.js +369 -0
- package/dist/src/transformers/CTEQueryDecomposer.js.map +1 -0
- package/dist/src/transformers/SqlFormatter.d.ts +39 -21
- package/dist/src/transformers/SqlFormatter.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
import { SimpleSelectQuery } from "../models/SimpleSelectQuery";
|
|
2
|
+
import { SqlFormatterOptions } from "./SqlFormatter";
|
|
3
|
+
/**
|
|
4
|
+
* Interface representing a decomposed CTE with executable query
|
|
5
|
+
* @public
|
|
6
|
+
*/
|
|
7
|
+
export interface DecomposedCTE {
|
|
8
|
+
/** Name of the CTE */
|
|
9
|
+
name: string;
|
|
10
|
+
/** Executable SQL query for this CTE (includes dependencies) */
|
|
11
|
+
query: string;
|
|
12
|
+
/** Array of CTE names that this CTE depends on */
|
|
13
|
+
dependencies: string[];
|
|
14
|
+
/** Array of CTE names that depend on this CTE */
|
|
15
|
+
dependents: string[];
|
|
16
|
+
/** Whether this CTE is recursive */
|
|
17
|
+
isRecursive: boolean;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Options for CTEQueryDecomposer extending SqlFormatterOptions
|
|
21
|
+
* @public
|
|
22
|
+
*/
|
|
23
|
+
export interface CTEDecomposerOptions extends SqlFormatterOptions {
|
|
24
|
+
/** Whether to add comments to decomposed queries showing metadata and dependencies */
|
|
25
|
+
addComments?: boolean;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Decomposes complex CTEs into executable standalone queries
|
|
29
|
+
*
|
|
30
|
+
* This class analyzes Common Table Expressions and generates executable standalone queries
|
|
31
|
+
* for each CTE, making complex CTE debugging easier. It supports:
|
|
32
|
+
* - Recursive CTE detection and handling
|
|
33
|
+
* - Dependency analysis (dependencies and dependents for each CTE)
|
|
34
|
+
* - Configurable SQL formatter options (MySQL, PostgreSQL, custom styles)
|
|
35
|
+
* - Optional comment generation showing CTE metadata and relationships
|
|
36
|
+
* - Comprehensive error handling for circular dependencies
|
|
37
|
+
*
|
|
38
|
+
* @example
|
|
39
|
+
* ```typescript
|
|
40
|
+
* const decomposer = new CTEQueryDecomposer({
|
|
41
|
+
* preset: 'postgres',
|
|
42
|
+
* addComments: true,
|
|
43
|
+
* keywordCase: 'upper'
|
|
44
|
+
* });
|
|
45
|
+
*
|
|
46
|
+
* const query = `
|
|
47
|
+
* with users_data as (select * from users),
|
|
48
|
+
* active_users as (select * from users_data where active = true)
|
|
49
|
+
* select * from active_users
|
|
50
|
+
* `;
|
|
51
|
+
*
|
|
52
|
+
* const decomposed = decomposer.decompose(SelectQueryParser.parse(query));
|
|
53
|
+
* // Returns array of DecomposedCTE objects with executable queries
|
|
54
|
+
* ```
|
|
55
|
+
*
|
|
56
|
+
* @public
|
|
57
|
+
*/
|
|
58
|
+
export declare class CTEQueryDecomposer {
|
|
59
|
+
private static readonly ERROR_MESSAGES;
|
|
60
|
+
private static readonly COMMENT_TEXTS;
|
|
61
|
+
private readonly dependencyAnalyzer;
|
|
62
|
+
private readonly cteCollector;
|
|
63
|
+
private readonly formatter;
|
|
64
|
+
private readonly options;
|
|
65
|
+
/**
|
|
66
|
+
* Creates a new CTEQueryDecomposer instance
|
|
67
|
+
* @param options - Configuration options extending SqlFormatterOptions
|
|
68
|
+
*/
|
|
69
|
+
constructor(options?: CTEDecomposerOptions);
|
|
70
|
+
/**
|
|
71
|
+
* Decomposes CTEs in a query into executable standalone queries
|
|
72
|
+
*
|
|
73
|
+
* This method analyzes the query structure to:
|
|
74
|
+
* 1. Collect all CTEs and analyze their dependencies
|
|
75
|
+
* 2. Detect recursive CTEs and handle them separately
|
|
76
|
+
* 3. Generate executable queries for each CTE including required dependencies
|
|
77
|
+
* 4. Add optional comments with metadata (if addComments option is enabled)
|
|
78
|
+
* 5. Format output according to specified formatter options
|
|
79
|
+
*
|
|
80
|
+
* @param query - The SimpleSelectQuery containing CTEs to decompose
|
|
81
|
+
* @returns Array of decomposed CTEs with executable queries, dependencies, and metadata
|
|
82
|
+
* @throws Error if circular dependencies are detected in non-recursive CTEs
|
|
83
|
+
*
|
|
84
|
+
* @example
|
|
85
|
+
* ```typescript
|
|
86
|
+
* const query = SelectQueryParser.parse(`
|
|
87
|
+
* with base as (select * from users),
|
|
88
|
+
* filtered as (select * from base where active = true)
|
|
89
|
+
* select * from filtered
|
|
90
|
+
* `);
|
|
91
|
+
*
|
|
92
|
+
* const result = decomposer.decompose(query);
|
|
93
|
+
* // Returns:
|
|
94
|
+
* // [
|
|
95
|
+
* // { name: 'base', query: 'select * from users', dependencies: [], ... },
|
|
96
|
+
* // { name: 'filtered', query: 'with base as (...) select * from base where active = true', dependencies: ['base'], ... }
|
|
97
|
+
* // ]
|
|
98
|
+
* ```
|
|
99
|
+
*/
|
|
100
|
+
decompose(query: SimpleSelectQuery): DecomposedCTE[];
|
|
101
|
+
/**
|
|
102
|
+
* Synchronizes edited CTEs back into a unified query and re-decomposes them
|
|
103
|
+
*
|
|
104
|
+
* This method resolves inconsistencies between edited CTEs by:
|
|
105
|
+
* 1. Composing the edited CTEs into a unified query
|
|
106
|
+
* 2. Parsing the unified query to ensure consistency
|
|
107
|
+
* 3. Re-decomposing the synchronized query
|
|
108
|
+
*
|
|
109
|
+
* This is useful when CTEs have been edited independently and may have
|
|
110
|
+
* inconsistencies that need to be resolved through a unified composition.
|
|
111
|
+
*
|
|
112
|
+
* @param editedCTEs - Array of edited CTEs that may have inconsistencies
|
|
113
|
+
* @param rootQuery - The main query that uses the CTEs
|
|
114
|
+
* @returns Array of re-decomposed CTEs with resolved inconsistencies
|
|
115
|
+
* @throws Error if the composed query cannot be parsed or contains errors
|
|
116
|
+
*
|
|
117
|
+
* @example
|
|
118
|
+
* ```typescript
|
|
119
|
+
* // After editing CTEs independently, synchronize them
|
|
120
|
+
* const editedCTEs = [
|
|
121
|
+
* { name: 'users_data', query: 'select * from users where active = true' },
|
|
122
|
+
* { name: 'active_users', query: 'select * from users_data where id >= 1000' }
|
|
123
|
+
* ];
|
|
124
|
+
*
|
|
125
|
+
* const synchronized = decomposer.synchronize(editedCTEs, 'select count(*) from active_users');
|
|
126
|
+
* // Returns re-decomposed CTEs with resolved dependencies
|
|
127
|
+
* ```
|
|
128
|
+
*/
|
|
129
|
+
synchronize(editedCTEs: Array<{
|
|
130
|
+
name: string;
|
|
131
|
+
query: string;
|
|
132
|
+
}>, rootQuery: string): DecomposedCTE[];
|
|
133
|
+
/**
|
|
134
|
+
* Validates circular dependencies for non-recursive CTEs
|
|
135
|
+
* @param hasRecursiveCTEs Whether the query contains recursive CTEs
|
|
136
|
+
* @throws Error if circular dependencies exist in non-recursive CTEs
|
|
137
|
+
*/
|
|
138
|
+
private validateCircularDependencies;
|
|
139
|
+
/**
|
|
140
|
+
* Processes CTE nodes and generates decomposed CTEs
|
|
141
|
+
* @param query Original query
|
|
142
|
+
* @param nodes CTE dependency nodes
|
|
143
|
+
* @param recursiveCTEs List of recursive CTE names
|
|
144
|
+
* @returns Array of decomposed CTEs
|
|
145
|
+
*/
|
|
146
|
+
private processCTENodes;
|
|
147
|
+
/**
|
|
148
|
+
* Creates a decomposed CTE for recursive CTEs
|
|
149
|
+
*/
|
|
150
|
+
private createRecursiveCTE;
|
|
151
|
+
/**
|
|
152
|
+
* Creates a decomposed CTE for standard (non-recursive) CTEs
|
|
153
|
+
*/
|
|
154
|
+
private createStandardCTE;
|
|
155
|
+
/**
|
|
156
|
+
* Builds an executable query for a CTE by including its dependencies
|
|
157
|
+
*/
|
|
158
|
+
private buildExecutableQuery;
|
|
159
|
+
/**
|
|
160
|
+
* Collects all required CTEs for a target CTE in dependency order
|
|
161
|
+
*/
|
|
162
|
+
private collectRequiredCTEs;
|
|
163
|
+
/**
|
|
164
|
+
* Builds WITH clause from required CTEs
|
|
165
|
+
*/
|
|
166
|
+
private buildWithClause;
|
|
167
|
+
/**
|
|
168
|
+
* Finds recursive CTEs in the query
|
|
169
|
+
* @param query The query to analyze
|
|
170
|
+
* @param ctes All CTEs in the query
|
|
171
|
+
* @returns Array of recursive CTE names
|
|
172
|
+
*/
|
|
173
|
+
private findRecursiveCTEs;
|
|
174
|
+
/**
|
|
175
|
+
* Checks if a WITH clause is recursive
|
|
176
|
+
* @param query The query to check
|
|
177
|
+
* @returns true if the query contains WITH RECURSIVE
|
|
178
|
+
*/
|
|
179
|
+
private isRecursiveWithClause;
|
|
180
|
+
/**
|
|
181
|
+
* Adds comments to the query if addComments option is enabled
|
|
182
|
+
* @param query The query string to add comments to
|
|
183
|
+
* @param cteName The name of the CTE
|
|
184
|
+
* @param dependencies Array of dependency names
|
|
185
|
+
* @param dependents Array of dependent names
|
|
186
|
+
* @param isRecursive Whether this is a recursive CTE
|
|
187
|
+
* @returns Query with comments added if enabled, otherwise original query
|
|
188
|
+
*/
|
|
189
|
+
private addCommentsToQuery;
|
|
190
|
+
/**
|
|
191
|
+
* Generates comment lines for a CTE
|
|
192
|
+
* @param cteName The name of the CTE
|
|
193
|
+
* @param dependencies Array of dependency names
|
|
194
|
+
* @param dependents Array of dependent names
|
|
195
|
+
* @param isRecursive Whether this is a recursive CTE
|
|
196
|
+
* @returns Array of comment strings
|
|
197
|
+
*/
|
|
198
|
+
private generateComments;
|
|
199
|
+
/**
|
|
200
|
+
* Adds text comments as SQL comments when AST parsing fails
|
|
201
|
+
* @param query Original query
|
|
202
|
+
* @param cteName The name of the CTE
|
|
203
|
+
* @param dependencies Array of dependency names
|
|
204
|
+
* @param dependents Array of dependent names
|
|
205
|
+
* @param isRecursive Whether this is a recursive CTE
|
|
206
|
+
* @returns Query with text comments prepended
|
|
207
|
+
*/
|
|
208
|
+
private addTextCommentsToQuery;
|
|
209
|
+
/**
|
|
210
|
+
* Extracts the name from a CommonTable
|
|
211
|
+
*/
|
|
212
|
+
private getCTEName;
|
|
213
|
+
}
|
|
@@ -0,0 +1,369 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CTEQueryDecomposer = void 0;
|
|
4
|
+
const CTEDependencyAnalyzer_1 = require("./CTEDependencyAnalyzer");
|
|
5
|
+
const CTECollector_1 = require("./CTECollector");
|
|
6
|
+
const SqlFormatter_1 = require("./SqlFormatter");
|
|
7
|
+
const CommentEditor_1 = require("../utils/CommentEditor");
|
|
8
|
+
const SelectQueryParser_1 = require("../parsers/SelectQueryParser");
|
|
9
|
+
const CTEComposer_1 = require("./CTEComposer");
|
|
10
|
+
/**
|
|
11
|
+
* Decomposes complex CTEs into executable standalone queries
|
|
12
|
+
*
|
|
13
|
+
* This class analyzes Common Table Expressions and generates executable standalone queries
|
|
14
|
+
* for each CTE, making complex CTE debugging easier. It supports:
|
|
15
|
+
* - Recursive CTE detection and handling
|
|
16
|
+
* - Dependency analysis (dependencies and dependents for each CTE)
|
|
17
|
+
* - Configurable SQL formatter options (MySQL, PostgreSQL, custom styles)
|
|
18
|
+
* - Optional comment generation showing CTE metadata and relationships
|
|
19
|
+
* - Comprehensive error handling for circular dependencies
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* ```typescript
|
|
23
|
+
* const decomposer = new CTEQueryDecomposer({
|
|
24
|
+
* preset: 'postgres',
|
|
25
|
+
* addComments: true,
|
|
26
|
+
* keywordCase: 'upper'
|
|
27
|
+
* });
|
|
28
|
+
*
|
|
29
|
+
* const query = `
|
|
30
|
+
* with users_data as (select * from users),
|
|
31
|
+
* active_users as (select * from users_data where active = true)
|
|
32
|
+
* select * from active_users
|
|
33
|
+
* `;
|
|
34
|
+
*
|
|
35
|
+
* const decomposed = decomposer.decompose(SelectQueryParser.parse(query));
|
|
36
|
+
* // Returns array of DecomposedCTE objects with executable queries
|
|
37
|
+
* ```
|
|
38
|
+
*
|
|
39
|
+
* @public
|
|
40
|
+
*/
|
|
41
|
+
class CTEQueryDecomposer {
|
|
42
|
+
/**
|
|
43
|
+
* Creates a new CTEQueryDecomposer instance
|
|
44
|
+
* @param options - Configuration options extending SqlFormatterOptions
|
|
45
|
+
*/
|
|
46
|
+
constructor(options = {}) {
|
|
47
|
+
this.options = options;
|
|
48
|
+
this.dependencyAnalyzer = new CTEDependencyAnalyzer_1.CTEDependencyAnalyzer();
|
|
49
|
+
this.cteCollector = new CTECollector_1.CTECollector();
|
|
50
|
+
this.formatter = new SqlFormatter_1.SqlFormatter(options);
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Decomposes CTEs in a query into executable standalone queries
|
|
54
|
+
*
|
|
55
|
+
* This method analyzes the query structure to:
|
|
56
|
+
* 1. Collect all CTEs and analyze their dependencies
|
|
57
|
+
* 2. Detect recursive CTEs and handle them separately
|
|
58
|
+
* 3. Generate executable queries for each CTE including required dependencies
|
|
59
|
+
* 4. Add optional comments with metadata (if addComments option is enabled)
|
|
60
|
+
* 5. Format output according to specified formatter options
|
|
61
|
+
*
|
|
62
|
+
* @param query - The SimpleSelectQuery containing CTEs to decompose
|
|
63
|
+
* @returns Array of decomposed CTEs with executable queries, dependencies, and metadata
|
|
64
|
+
* @throws Error if circular dependencies are detected in non-recursive CTEs
|
|
65
|
+
*
|
|
66
|
+
* @example
|
|
67
|
+
* ```typescript
|
|
68
|
+
* const query = SelectQueryParser.parse(`
|
|
69
|
+
* with base as (select * from users),
|
|
70
|
+
* filtered as (select * from base where active = true)
|
|
71
|
+
* select * from filtered
|
|
72
|
+
* `);
|
|
73
|
+
*
|
|
74
|
+
* const result = decomposer.decompose(query);
|
|
75
|
+
* // Returns:
|
|
76
|
+
* // [
|
|
77
|
+
* // { name: 'base', query: 'select * from users', dependencies: [], ... },
|
|
78
|
+
* // { name: 'filtered', query: 'with base as (...) select * from base where active = true', dependencies: ['base'], ... }
|
|
79
|
+
* // ]
|
|
80
|
+
* ```
|
|
81
|
+
*/
|
|
82
|
+
decompose(query) {
|
|
83
|
+
const ctes = this.cteCollector.collect(query);
|
|
84
|
+
if (ctes.length === 0) {
|
|
85
|
+
return [];
|
|
86
|
+
}
|
|
87
|
+
const recursiveCTEs = this.findRecursiveCTEs(query, ctes);
|
|
88
|
+
const dependencyGraph = this.dependencyAnalyzer.analyzeDependencies(query);
|
|
89
|
+
this.validateCircularDependencies(recursiveCTEs.length > 0);
|
|
90
|
+
return this.processCTENodes(query, dependencyGraph.nodes, recursiveCTEs);
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Synchronizes edited CTEs back into a unified query and re-decomposes them
|
|
94
|
+
*
|
|
95
|
+
* This method resolves inconsistencies between edited CTEs by:
|
|
96
|
+
* 1. Composing the edited CTEs into a unified query
|
|
97
|
+
* 2. Parsing the unified query to ensure consistency
|
|
98
|
+
* 3. Re-decomposing the synchronized query
|
|
99
|
+
*
|
|
100
|
+
* This is useful when CTEs have been edited independently and may have
|
|
101
|
+
* inconsistencies that need to be resolved through a unified composition.
|
|
102
|
+
*
|
|
103
|
+
* @param editedCTEs - Array of edited CTEs that may have inconsistencies
|
|
104
|
+
* @param rootQuery - The main query that uses the CTEs
|
|
105
|
+
* @returns Array of re-decomposed CTEs with resolved inconsistencies
|
|
106
|
+
* @throws Error if the composed query cannot be parsed or contains errors
|
|
107
|
+
*
|
|
108
|
+
* @example
|
|
109
|
+
* ```typescript
|
|
110
|
+
* // After editing CTEs independently, synchronize them
|
|
111
|
+
* const editedCTEs = [
|
|
112
|
+
* { name: 'users_data', query: 'select * from users where active = true' },
|
|
113
|
+
* { name: 'active_users', query: 'select * from users_data where id >= 1000' }
|
|
114
|
+
* ];
|
|
115
|
+
*
|
|
116
|
+
* const synchronized = decomposer.synchronize(editedCTEs, 'select count(*) from active_users');
|
|
117
|
+
* // Returns re-decomposed CTEs with resolved dependencies
|
|
118
|
+
* ```
|
|
119
|
+
*/
|
|
120
|
+
synchronize(editedCTEs, rootQuery) {
|
|
121
|
+
if (editedCTEs.length === 0) {
|
|
122
|
+
return [];
|
|
123
|
+
}
|
|
124
|
+
// Use CTEComposer to create a unified query, sharing formatter options
|
|
125
|
+
const composerOptions = {
|
|
126
|
+
...this.options,
|
|
127
|
+
// Remove decomposer-specific options
|
|
128
|
+
addComments: undefined
|
|
129
|
+
};
|
|
130
|
+
const composer = new CTEComposer_1.CTEComposer(composerOptions);
|
|
131
|
+
const unifiedQuery = composer.compose(editedCTEs, rootQuery);
|
|
132
|
+
// Parse the unified query
|
|
133
|
+
const parsedQuery = SelectQueryParser_1.SelectQueryParser.parse(unifiedQuery);
|
|
134
|
+
// Re-decompose the synchronized query
|
|
135
|
+
return this.decompose(parsedQuery);
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Validates circular dependencies for non-recursive CTEs
|
|
139
|
+
* @param hasRecursiveCTEs Whether the query contains recursive CTEs
|
|
140
|
+
* @throws Error if circular dependencies exist in non-recursive CTEs
|
|
141
|
+
*/
|
|
142
|
+
validateCircularDependencies(hasRecursiveCTEs) {
|
|
143
|
+
if (this.dependencyAnalyzer.hasCircularDependency() && !hasRecursiveCTEs) {
|
|
144
|
+
throw new Error(CTEQueryDecomposer.ERROR_MESSAGES.CIRCULAR_REFERENCE);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Processes CTE nodes and generates decomposed CTEs
|
|
149
|
+
* @param query Original query
|
|
150
|
+
* @param nodes CTE dependency nodes
|
|
151
|
+
* @param recursiveCTEs List of recursive CTE names
|
|
152
|
+
* @returns Array of decomposed CTEs
|
|
153
|
+
*/
|
|
154
|
+
processCTENodes(query, nodes, recursiveCTEs) {
|
|
155
|
+
const result = [];
|
|
156
|
+
for (const node of nodes) {
|
|
157
|
+
const isRecursive = recursiveCTEs.includes(node.name);
|
|
158
|
+
if (isRecursive) {
|
|
159
|
+
result.push(this.createRecursiveCTE(node, query));
|
|
160
|
+
}
|
|
161
|
+
else {
|
|
162
|
+
result.push(this.createStandardCTE(node, nodes));
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
return result;
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Creates a decomposed CTE for recursive CTEs
|
|
169
|
+
*/
|
|
170
|
+
createRecursiveCTE(node, query) {
|
|
171
|
+
const formattedQuery = this.formatter.format(query).formattedSql;
|
|
172
|
+
const finalQuery = this.addCommentsToQuery(formattedQuery, node.name, [], [], true);
|
|
173
|
+
return {
|
|
174
|
+
name: node.name,
|
|
175
|
+
query: finalQuery,
|
|
176
|
+
dependencies: [],
|
|
177
|
+
dependents: [],
|
|
178
|
+
isRecursive: true
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Creates a decomposed CTE for standard (non-recursive) CTEs
|
|
183
|
+
*/
|
|
184
|
+
createStandardCTE(node, allNodes) {
|
|
185
|
+
const query = this.buildExecutableQuery(node, allNodes);
|
|
186
|
+
const finalQuery = this.addCommentsToQuery(query, node.name, node.dependencies, node.dependents, false);
|
|
187
|
+
return {
|
|
188
|
+
name: node.name,
|
|
189
|
+
query: finalQuery,
|
|
190
|
+
dependencies: [...node.dependencies],
|
|
191
|
+
dependents: [...node.dependents],
|
|
192
|
+
isRecursive: false
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Builds an executable query for a CTE by including its dependencies
|
|
197
|
+
*/
|
|
198
|
+
buildExecutableQuery(targetNode, allNodes) {
|
|
199
|
+
const requiredCTEs = this.collectRequiredCTEs(targetNode, allNodes);
|
|
200
|
+
if (requiredCTEs.length === 0) {
|
|
201
|
+
// No dependencies, just return the CTE's query
|
|
202
|
+
return this.formatter.format(targetNode.cte.query).formattedSql;
|
|
203
|
+
}
|
|
204
|
+
// Build WITH clause with required CTEs
|
|
205
|
+
const withClause = this.buildWithClause(requiredCTEs);
|
|
206
|
+
const mainQuery = this.formatter.format(targetNode.cte.query).formattedSql;
|
|
207
|
+
return `${withClause} ${mainQuery}`;
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Collects all required CTEs for a target CTE in dependency order
|
|
211
|
+
*/
|
|
212
|
+
collectRequiredCTEs(targetNode, allNodes) {
|
|
213
|
+
const visited = new Set();
|
|
214
|
+
const result = [];
|
|
215
|
+
const nodeMap = new Map();
|
|
216
|
+
// Build node lookup map
|
|
217
|
+
for (const node of allNodes) {
|
|
218
|
+
nodeMap.set(node.name, node);
|
|
219
|
+
}
|
|
220
|
+
const collectDependencies = (nodeName) => {
|
|
221
|
+
if (visited.has(nodeName))
|
|
222
|
+
return;
|
|
223
|
+
visited.add(nodeName);
|
|
224
|
+
const node = nodeMap.get(nodeName);
|
|
225
|
+
if (!node)
|
|
226
|
+
return;
|
|
227
|
+
// First collect all dependencies
|
|
228
|
+
for (const depName of node.dependencies) {
|
|
229
|
+
collectDependencies(depName);
|
|
230
|
+
}
|
|
231
|
+
// Then add this node (ensuring dependencies come first)
|
|
232
|
+
if (nodeName !== targetNode.name) {
|
|
233
|
+
result.push(node);
|
|
234
|
+
}
|
|
235
|
+
};
|
|
236
|
+
// Collect dependencies for the target node
|
|
237
|
+
for (const depName of targetNode.dependencies) {
|
|
238
|
+
collectDependencies(depName);
|
|
239
|
+
}
|
|
240
|
+
return result;
|
|
241
|
+
}
|
|
242
|
+
/**
|
|
243
|
+
* Builds WITH clause from required CTEs
|
|
244
|
+
*/
|
|
245
|
+
buildWithClause(requiredCTEs) {
|
|
246
|
+
if (requiredCTEs.length === 0)
|
|
247
|
+
return "";
|
|
248
|
+
const cteDefinitions = requiredCTEs.map(node => {
|
|
249
|
+
const cteName = node.name;
|
|
250
|
+
const cteQuery = this.formatter.format(node.cte.query).formattedSql;
|
|
251
|
+
return `${cteName} as (${cteQuery})`;
|
|
252
|
+
});
|
|
253
|
+
return `with ${cteDefinitions.join(", ")}`;
|
|
254
|
+
}
|
|
255
|
+
/**
|
|
256
|
+
* Finds recursive CTEs in the query
|
|
257
|
+
* @param query The query to analyze
|
|
258
|
+
* @param ctes All CTEs in the query
|
|
259
|
+
* @returns Array of recursive CTE names
|
|
260
|
+
*/
|
|
261
|
+
findRecursiveCTEs(query, ctes) {
|
|
262
|
+
if (!query.withClause || !this.isRecursiveWithClause(query)) {
|
|
263
|
+
return [];
|
|
264
|
+
}
|
|
265
|
+
// For now, assume all CTEs in a RECURSIVE WITH are recursive
|
|
266
|
+
// This is a simplification - in reality, only some CTEs might be recursive
|
|
267
|
+
return ctes.map(cte => this.getCTEName(cte));
|
|
268
|
+
}
|
|
269
|
+
/**
|
|
270
|
+
* Checks if a WITH clause is recursive
|
|
271
|
+
* @param query The query to check
|
|
272
|
+
* @returns true if the query contains WITH RECURSIVE
|
|
273
|
+
*/
|
|
274
|
+
isRecursiveWithClause(query) {
|
|
275
|
+
const queryText = this.formatter.format(query).formattedSql.toLowerCase();
|
|
276
|
+
return queryText.includes('with recursive');
|
|
277
|
+
}
|
|
278
|
+
/**
|
|
279
|
+
* Adds comments to the query if addComments option is enabled
|
|
280
|
+
* @param query The query string to add comments to
|
|
281
|
+
* @param cteName The name of the CTE
|
|
282
|
+
* @param dependencies Array of dependency names
|
|
283
|
+
* @param dependents Array of dependent names
|
|
284
|
+
* @param isRecursive Whether this is a recursive CTE
|
|
285
|
+
* @returns Query with comments added if enabled, otherwise original query
|
|
286
|
+
*/
|
|
287
|
+
addCommentsToQuery(query, cteName, dependencies, dependents, isRecursive) {
|
|
288
|
+
if (this.options.addComments !== true) {
|
|
289
|
+
return query;
|
|
290
|
+
}
|
|
291
|
+
try {
|
|
292
|
+
// Parse the query to add comments to its AST
|
|
293
|
+
const parsedQuery = SelectQueryParser_1.SelectQueryParser.parse(query);
|
|
294
|
+
// Generate comment lines
|
|
295
|
+
const comments = this.generateComments(cteName, dependencies, dependents, isRecursive);
|
|
296
|
+
// Add comments to the root query (this should place them at the beginning)
|
|
297
|
+
comments.forEach(comment => {
|
|
298
|
+
CommentEditor_1.CommentEditor.addComment(parsedQuery, comment);
|
|
299
|
+
});
|
|
300
|
+
// Format with comment export enabled
|
|
301
|
+
const formatterWithComments = new SqlFormatter_1.SqlFormatter({
|
|
302
|
+
...this.options,
|
|
303
|
+
exportComment: true
|
|
304
|
+
});
|
|
305
|
+
return formatterWithComments.format(parsedQuery).formattedSql;
|
|
306
|
+
}
|
|
307
|
+
catch (error) {
|
|
308
|
+
// If parsing fails, return original query with simple text comments
|
|
309
|
+
console.warn(`${CTEQueryDecomposer.ERROR_MESSAGES.PARSING_FAILED}: ${error}`);
|
|
310
|
+
return this.addTextCommentsToQuery(query, cteName, dependencies, dependents, isRecursive);
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
/**
|
|
314
|
+
* Generates comment lines for a CTE
|
|
315
|
+
* @param cteName The name of the CTE
|
|
316
|
+
* @param dependencies Array of dependency names
|
|
317
|
+
* @param dependents Array of dependent names
|
|
318
|
+
* @param isRecursive Whether this is a recursive CTE
|
|
319
|
+
* @returns Array of comment strings
|
|
320
|
+
*/
|
|
321
|
+
generateComments(cteName, dependencies, dependents, isRecursive) {
|
|
322
|
+
const { AUTO_GENERATED, ORIGINAL_CTE, DEPENDENCIES, DEPENDENTS, RECURSIVE_TYPE, NONE } = CTEQueryDecomposer.COMMENT_TEXTS;
|
|
323
|
+
const comments = [];
|
|
324
|
+
comments.push(AUTO_GENERATED);
|
|
325
|
+
comments.push(`${ORIGINAL_CTE} ${cteName}`);
|
|
326
|
+
if (isRecursive) {
|
|
327
|
+
comments.push(RECURSIVE_TYPE);
|
|
328
|
+
}
|
|
329
|
+
const depsText = dependencies.length > 0 ? dependencies.join(", ") : NONE;
|
|
330
|
+
comments.push(`${DEPENDENCIES} ${depsText}`);
|
|
331
|
+
const dependentsText = dependents.length > 0 ? dependents.join(", ") : NONE;
|
|
332
|
+
comments.push(`${DEPENDENTS} ${dependentsText}`);
|
|
333
|
+
return comments;
|
|
334
|
+
}
|
|
335
|
+
/**
|
|
336
|
+
* Adds text comments as SQL comments when AST parsing fails
|
|
337
|
+
* @param query Original query
|
|
338
|
+
* @param cteName The name of the CTE
|
|
339
|
+
* @param dependencies Array of dependency names
|
|
340
|
+
* @param dependents Array of dependent names
|
|
341
|
+
* @param isRecursive Whether this is a recursive CTE
|
|
342
|
+
* @returns Query with text comments prepended
|
|
343
|
+
*/
|
|
344
|
+
addTextCommentsToQuery(query, cteName, dependencies, dependents, isRecursive) {
|
|
345
|
+
const comments = this.generateComments(cteName, dependencies, dependents, isRecursive);
|
|
346
|
+
const commentLines = comments.map(comment => `-- ${comment}`).join('\n');
|
|
347
|
+
return `${commentLines}\n${query}`;
|
|
348
|
+
}
|
|
349
|
+
/**
|
|
350
|
+
* Extracts the name from a CommonTable
|
|
351
|
+
*/
|
|
352
|
+
getCTEName(cte) {
|
|
353
|
+
return cte.aliasExpression.table.name;
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
exports.CTEQueryDecomposer = CTEQueryDecomposer;
|
|
357
|
+
CTEQueryDecomposer.ERROR_MESSAGES = {
|
|
358
|
+
CIRCULAR_REFERENCE: "Circular reference detected in non-recursive CTEs",
|
|
359
|
+
PARSING_FAILED: "Failed to parse query for comment injection"
|
|
360
|
+
};
|
|
361
|
+
CTEQueryDecomposer.COMMENT_TEXTS = {
|
|
362
|
+
AUTO_GENERATED: "Auto-generated by CTE decomposer",
|
|
363
|
+
ORIGINAL_CTE: "Original CTE:",
|
|
364
|
+
DEPENDENCIES: "Dependencies:",
|
|
365
|
+
DEPENDENTS: "Dependents:",
|
|
366
|
+
RECURSIVE_TYPE: "Type: Recursive CTE",
|
|
367
|
+
NONE: "none"
|
|
368
|
+
};
|
|
369
|
+
//# sourceMappingURL=CTEQueryDecomposer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CTEQueryDecomposer.js","sourceRoot":"","sources":["../../../src/transformers/CTEQueryDecomposer.ts"],"names":[],"mappings":";;;AAEA,mEAAyE;AACzE,iDAA8C;AAC9C,iDAAmE;AACnE,0DAAuD;AACvD,oEAAiE;AACjE,+CAA4C;AA4B5C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,MAAa,kBAAkB;IAoB3B;;;OAGG;IACH,YAAY,UAAgC,EAAE;QAC1C,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,kBAAkB,GAAG,IAAI,6CAAqB,EAAE,CAAC;QACtD,IAAI,CAAC,YAAY,GAAG,IAAI,2BAAY,EAAE,CAAC;QACvC,IAAI,CAAC,SAAS,GAAG,IAAI,2BAAY,CAAC,OAAO,CAAC,CAAC;IAC/C,CAAC;IAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA6BG;IACI,SAAS,CAAC,KAAwB;QACrC,MAAM,IAAI,GAAG,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QAC9C,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACpB,OAAO,EAAE,CAAC;QACd,CAAC;QAED,MAAM,aAAa,GAAG,IAAI,CAAC,iBAAiB,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;QAC1D,MAAM,eAAe,GAAG,IAAI,CAAC,kBAAkB,CAAC,mBAAmB,CAAC,KAAK,CAAC,CAAC;QAE3E,IAAI,CAAC,4BAA4B,CAAC,aAAa,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QAE5D,OAAO,IAAI,CAAC,eAAe,CAAC,KAAK,EAAE,eAAe,CAAC,KAAK,EAAE,aAAa,CAAC,CAAC;IAC7E,CAAC;IAED;;;;;;;;;;;;;;;;;;;;;;;;;;;OA2BG;IACI,WAAW,CAAC,UAAgD,EAAE,SAAiB;QAClF,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC1B,OAAO,EAAE,CAAC;QACd,CAAC;QAED,uEAAuE;QACvE,MAAM,eAAe,GAAG;YACpB,GAAG,IAAI,CAAC,OAAO;YACf,qCAAqC;YACrC,WAAW,EAAE,SAAS;SACzB,CAAC;QACF,MAAM,QAAQ,GAAG,IAAI,yBAAW,CAAC,eAAe,CAAC,CAAC;QAClD,MAAM,YAAY,GAAG,QAAQ,CAAC,OAAO,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC;QAE7D,0BAA0B;QAC1B,MAAM,WAAW,GAAG,qCAAiB,CAAC,KAAK,CAAC,YAAY,CAAsB,CAAC;QAE/E,sCAAsC;QACtC,OAAO,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC;IACvC,CAAC;IAED;;;;OAIG;IACK,4BAA4B,CAAC,gBAAyB;QAC1D,IAAI,IAAI,CAAC,kBAAkB,CAAC,qBAAqB,EAAE,IAAI,CAAC,gBAAgB,EAAE,CAAC;YACvE,MAAM,IAAI,KAAK,CAAC,kBAAkB,CAAC,cAAc,CAAC,kBAAkB,CAAC,CAAC;QAC1E,CAAC;IACL,CAAC;IAED;;;;;;OAMG;IACK,eAAe,CACnB,KAAwB,EACxB,KAAgB,EAChB,aAAuB;QAEvB,MAAM,MAAM,GAAoB,EAAE,CAAC;QAEnC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACvB,MAAM,WAAW,GAAG,aAAa,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAEtD,IAAI,WAAW,EAAE,CAAC;gBACd,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,kBAAkB,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC;YACtD,CAAC;iBAAM,CAAC;gBACJ,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC;YACrD,CAAC;QACL,CAAC;QAED,OAAO,MAAM,CAAC;IAClB,CAAC;IAED;;OAEG;IACK,kBAAkB,CAAC,IAAa,EAAE,KAAwB;QAC9D,MAAM,cAAc,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,YAAY,CAAC;QACjE,MAAM,UAAU,GAAG,IAAI,CAAC,kBAAkB,CAAC,cAAc,EAAE,IAAI,CAAC,IAAI,EAAE,EAAE,EAAE,EAAE,EAAE,IAAI,CAAC,CAAC;QAEpF,OAAO;YACH,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,KAAK,EAAE,UAAU;YACjB,YAAY,EAAE,EAAE;YAChB,UAAU,EAAE,EAAE;YACd,WAAW,EAAE,IAAI;SACpB,CAAC;IACN,CAAC;IAED;;OAEG;IACK,iBAAiB,CAAC,IAAa,EAAE,QAAmB;QACxD,MAAM,KAAK,GAAG,IAAI,CAAC,oBAAoB,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;QACxD,MAAM,UAAU,GAAG,IAAI,CAAC,kBAAkB,CAAC,KAAK,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,YAAY,EAAE,IAAI,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;QAExG,OAAO;YACH,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,KAAK,EAAE,UAAU;YACjB,YAAY,EAAE,CAAC,GAAG,IAAI,CAAC,YAAY,CAAC;YACpC,UAAU,EAAE,CAAC,GAAG,IAAI,CAAC,UAAU,CAAC;YAChC,WAAW,EAAE,KAAK;SACrB,CAAC;IACN,CAAC;IAED;;OAEG;IACK,oBAAoB,CAAC,UAAmB,EAAE,QAAmB;QACjE,MAAM,YAAY,GAAG,IAAI,CAAC,mBAAmB,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;QAEpE,IAAI,YAAY,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC5B,+CAA+C;YAC/C,OAAO,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,YAAY,CAAC;QACpE,CAAC;QAED,uCAAuC;QACvC,MAAM,UAAU,GAAG,IAAI,CAAC,eAAe,CAAC,YAAY,CAAC,CAAC;QACtD,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,YAAY,CAAC;QAE3E,OAAO,GAAG,UAAU,IAAI,SAAS,EAAE,CAAC;IACxC,CAAC;IAED;;OAEG;IACK,mBAAmB,CAAC,UAAmB,EAAE,QAAmB;QAChE,MAAM,OAAO,GAAG,IAAI,GAAG,EAAU,CAAC;QAClC,MAAM,MAAM,GAAc,EAAE,CAAC;QAC7B,MAAM,OAAO,GAAG,IAAI,GAAG,EAAmB,CAAC;QAE3C,wBAAwB;QACxB,KAAK,MAAM,IAAI,IAAI,QAAQ,EAAE,CAAC;YAC1B,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QACjC,CAAC;QAED,MAAM,mBAAmB,GAAG,CAAC,QAAgB,EAAE,EAAE;YAC7C,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC;gBAAE,OAAO;YAClC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;YAEtB,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;YACnC,IAAI,CAAC,IAAI;gBAAE,OAAO;YAElB,iCAAiC;YACjC,KAAK,MAAM,OAAO,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;gBACtC,mBAAmB,CAAC,OAAO,CAAC,CAAC;YACjC,CAAC;YAED,wDAAwD;YACxD,IAAI,QAAQ,KAAK,UAAU,CAAC,IAAI,EAAE,CAAC;gBAC/B,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACtB,CAAC;QACL,CAAC,CAAC;QAEF,2CAA2C;QAC3C,KAAK,MAAM,OAAO,IAAI,UAAU,CAAC,YAAY,EAAE,CAAC;YAC5C,mBAAmB,CAAC,OAAO,CAAC,CAAC;QACjC,CAAC;QAED,OAAO,MAAM,CAAC;IAClB,CAAC;IAED;;OAEG;IACK,eAAe,CAAC,YAAuB;QAC3C,IAAI,YAAY,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,EAAE,CAAC;QAEzC,MAAM,cAAc,GAAG,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE;YAC3C,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC;YAC1B,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,YAAY,CAAC;YACpE,OAAO,GAAG,OAAO,QAAQ,QAAQ,GAAG,CAAC;QACzC,CAAC,CAAC,CAAC;QAEH,OAAO,QAAQ,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;IAC/C,CAAC;IAED;;;;;OAKG;IACK,iBAAiB,CAAC,KAAwB,EAAE,IAAmB;QACnE,IAAI,CAAC,KAAK,CAAC,UAAU,IAAI,CAAC,IAAI,CAAC,qBAAqB,CAAC,KAAK,CAAC,EAAE,CAAC;YAC1D,OAAO,EAAE,CAAC;QACd,CAAC;QAED,6DAA6D;QAC7D,2EAA2E;QAC3E,OAAO,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC;IACjD,CAAC;IAED;;;;OAIG;IACK,qBAAqB,CAAC,KAAwB;QAClD,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,YAAY,CAAC,WAAW,EAAE,CAAC;QAC1E,OAAO,SAAS,CAAC,QAAQ,CAAC,gBAAgB,CAAC,CAAC;IAChD,CAAC;IAED;;;;;;;;OAQG;IACK,kBAAkB,CACtB,KAAa,EACb,OAAe,EACf,YAAsB,EACtB,UAAoB,EACpB,WAAoB;QAEpB,IAAI,IAAI,CAAC,OAAO,CAAC,WAAW,KAAK,IAAI,EAAE,CAAC;YACpC,OAAO,KAAK,CAAC;QACjB,CAAC;QAED,IAAI,CAAC;YACD,6CAA6C;YAC7C,MAAM,WAAW,GAAG,qCAAiB,CAAC,KAAK,CAAC,KAAK,CAAsB,CAAC;YAExE,yBAAyB;YACzB,MAAM,QAAQ,GAAG,IAAI,CAAC,gBAAgB,CAAC,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,WAAW,CAAC,CAAC;YAEvF,2EAA2E;YAC3E,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE;gBACvB,6BAAa,CAAC,UAAU,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;YACnD,CAAC,CAAC,CAAC;YAEH,qCAAqC;YACrC,MAAM,qBAAqB,GAAG,IAAI,2BAAY,CAAC;gBAC3C,GAAG,IAAI,CAAC,OAAO;gBACf,aAAa,EAAE,IAAI;aACtB,CAAC,CAAC;YAEH,OAAO,qBAAqB,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,YAAY,CAAC;QAClE,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACb,oEAAoE;YACpE,OAAO,CAAC,IAAI,CAAC,GAAG,kBAAkB,CAAC,cAAc,CAAC,cAAc,KAAK,KAAK,EAAE,CAAC,CAAC;YAC9E,OAAO,IAAI,CAAC,sBAAsB,CAAC,KAAK,EAAE,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,WAAW,CAAC,CAAC;QAC9F,CAAC;IACL,CAAC;IAED;;;;;;;OAOG;IACK,gBAAgB,CACpB,OAAe,EACf,YAAsB,EACtB,UAAoB,EACpB,WAAoB;QAEpB,MAAM,EAAE,cAAc,EAAE,YAAY,EAAE,YAAY,EAAE,UAAU,EAAE,cAAc,EAAE,IAAI,EAAE,GAAG,kBAAkB,CAAC,aAAa,CAAC;QAC1H,MAAM,QAAQ,GAAa,EAAE,CAAC;QAE9B,QAAQ,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QAC9B,QAAQ,CAAC,IAAI,CAAC,GAAG,YAAY,IAAI,OAAO,EAAE,CAAC,CAAC;QAE5C,IAAI,WAAW,EAAE,CAAC;YACd,QAAQ,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QAClC,CAAC;QAED,MAAM,QAAQ,GAAG,YAAY,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QAC1E,QAAQ,CAAC,IAAI,CAAC,GAAG,YAAY,IAAI,QAAQ,EAAE,CAAC,CAAC;QAE7C,MAAM,cAAc,GAAG,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QAC5E,QAAQ,CAAC,IAAI,CAAC,GAAG,UAAU,IAAI,cAAc,EAAE,CAAC,CAAC;QAEjD,OAAO,QAAQ,CAAC;IACpB,CAAC;IAED;;;;;;;;OAQG;IACK,sBAAsB,CAC1B,KAAa,EACb,OAAe,EACf,YAAsB,EACtB,UAAoB,EACpB,WAAoB;QAEpB,MAAM,QAAQ,GAAG,IAAI,CAAC,gBAAgB,CAAC,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,WAAW,CAAC,CAAC;QACvF,MAAM,YAAY,GAAG,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,MAAM,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACzE,OAAO,GAAG,YAAY,KAAK,KAAK,EAAE,CAAC;IACvC,CAAC;IAED;;OAEG;IACK,UAAU,CAAC,GAAgB;QAC/B,OAAO,GAAG,CAAC,eAAe,CAAC,KAAK,CAAC,IAAI,CAAC;IAC1C,CAAC;;AA7YL,gDA8YC;AA7Y2B,iCAAc,GAAG;IACrC,kBAAkB,EAAE,mDAAmD;IACvE,cAAc,EAAE,6CAA6C;CACvD,CAAC;AAEa,gCAAa,GAAG;IACpC,cAAc,EAAE,kCAAkC;IAClD,YAAY,EAAE,eAAe;IAC7B,YAAY,EAAE,eAAe;IAC7B,UAAU,EAAE,aAAa;IACzB,cAAc,EAAE,qBAAqB;IACrC,IAAI,EAAE,MAAM;CACN,CAAC"}
|
|
@@ -10,33 +10,51 @@ export type PresetName = (typeof VALID_PRESETS)[number];
|
|
|
10
10
|
* - 'full-oneline': Entire WITH clause is formatted as one line
|
|
11
11
|
*/
|
|
12
12
|
export type WithClauseStyle = 'standard' | 'cte-oneline' | 'full-oneline';
|
|
13
|
+
/**
|
|
14
|
+
* Options for SqlFormatter configuration
|
|
15
|
+
* @public
|
|
16
|
+
*/
|
|
17
|
+
export interface SqlFormatterOptions {
|
|
18
|
+
/** Database preset for formatting style ('mysql', 'postgres', 'sqlserver', 'sqlite') */
|
|
19
|
+
preset?: PresetName;
|
|
20
|
+
/** Custom identifier escape characters (e.g., {start: '"', end: '"'} for PostgreSQL) */
|
|
21
|
+
identifierEscape?: {
|
|
22
|
+
start: string;
|
|
23
|
+
end: string;
|
|
24
|
+
};
|
|
25
|
+
/** Parameter symbol configuration for SQL parameters */
|
|
26
|
+
parameterSymbol?: string | {
|
|
27
|
+
start: string;
|
|
28
|
+
end: string;
|
|
29
|
+
};
|
|
30
|
+
/** Style for parameter formatting */
|
|
31
|
+
parameterStyle?: 'anonymous' | 'indexed' | 'named';
|
|
32
|
+
/** Number of spaces for indentation */
|
|
33
|
+
indentSize?: number;
|
|
34
|
+
/** Character to use for indentation ('space' or 'tab') */
|
|
35
|
+
indentChar?: IndentCharOption;
|
|
36
|
+
/** Newline character style */
|
|
37
|
+
newline?: NewlineOption;
|
|
38
|
+
/** Case transformation for SQL keywords */
|
|
39
|
+
keywordCase?: 'none' | 'upper' | 'lower';
|
|
40
|
+
/** Style for comma line breaks */
|
|
41
|
+
commaBreak?: CommaBreakStyle;
|
|
42
|
+
/** Style for AND/OR line breaks */
|
|
43
|
+
andBreak?: AndBreakStyle;
|
|
44
|
+
/** Whether to export comments in formatted output */
|
|
45
|
+
exportComment?: boolean;
|
|
46
|
+
/** Whether to only export comments from clause-level keywords */
|
|
47
|
+
strictCommentPlacement?: boolean;
|
|
48
|
+
/** Formatting style for WITH clauses */
|
|
49
|
+
withClauseStyle?: WithClauseStyle;
|
|
50
|
+
}
|
|
13
51
|
/**
|
|
14
52
|
* SqlFormatter class combines parsing and printing of SQL queries into a single interface.
|
|
15
53
|
*/
|
|
16
54
|
export declare class SqlFormatter {
|
|
17
55
|
private parser;
|
|
18
56
|
private printer;
|
|
19
|
-
constructor(options?:
|
|
20
|
-
preset?: PresetName;
|
|
21
|
-
identifierEscape?: {
|
|
22
|
-
start: string;
|
|
23
|
-
end: string;
|
|
24
|
-
};
|
|
25
|
-
parameterSymbol?: string | {
|
|
26
|
-
start: string;
|
|
27
|
-
end: string;
|
|
28
|
-
};
|
|
29
|
-
parameterStyle?: 'anonymous' | 'indexed' | 'named';
|
|
30
|
-
indentSize?: number;
|
|
31
|
-
indentChar?: IndentCharOption;
|
|
32
|
-
newline?: NewlineOption;
|
|
33
|
-
keywordCase?: 'none' | 'upper' | 'lower';
|
|
34
|
-
commaBreak?: CommaBreakStyle;
|
|
35
|
-
andBreak?: AndBreakStyle;
|
|
36
|
-
exportComment?: boolean;
|
|
37
|
-
strictCommentPlacement?: boolean;
|
|
38
|
-
withClauseStyle?: WithClauseStyle;
|
|
39
|
-
}); /**
|
|
57
|
+
constructor(options?: SqlFormatterOptions); /**
|
|
40
58
|
* Formats a SQL query string with the given parameters.
|
|
41
59
|
* @param sqlText The SQL query string to format.
|
|
42
60
|
* @param parameters A dictionary of parameters to replace in the query.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SqlFormatter.js","sourceRoot":"","sources":["../../../src/transformers/SqlFormatter.ts"],"names":[],"mappings":";;;AAAA,wEAA+F;AAC/F,6CAA0E;AAK1E,4CAA4C;AAC/B,QAAA,aAAa,GAAG,CAAC,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,QAAQ,CAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"SqlFormatter.js","sourceRoot":"","sources":["../../../src/transformers/SqlFormatter.ts"],"names":[],"mappings":";;;AAAA,wEAA+F;AAC/F,6CAA0E;AAK1E,4CAA4C;AAC/B,QAAA,aAAa,GAAG,CAAC,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,QAAQ,CAAU,CAAC;AA4CnF;;GAEG;AACH,MAAa,YAAY;IAIrB,YAAY,UAA+B,EAAE;;QAEzC,MAAM,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,6BAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QAE1E,IAAI,OAAO,CAAC,MAAM,IAAI,CAAC,YAAY,EAAE,CAAC;YAClC,MAAM,IAAI,KAAK,CAAC,mBAAmB,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,iCAAiC;QAC3F,CAAC;QAED,MAAM,aAAa,GAAG;YAClB,GAAG,YAAY,EAAE,6BAA6B;YAC9C,gBAAgB,EAAE,MAAA,OAAO,CAAC,gBAAgB,mCAAI,YAAY,aAAZ,YAAY,uBAAZ,YAAY,CAAE,gBAAgB;YAC5E,eAAe,EAAE,MAAA,OAAO,CAAC,eAAe,mCAAI,YAAY,aAAZ,YAAY,uBAAZ,YAAY,CAAE,eAAe;YACzE,cAAc,EAAE,MAAA,OAAO,CAAC,cAAc,mCAAI,YAAY,aAAZ,YAAY,uBAAZ,YAAY,CAAE,cAAc;SACzE,CAAC;QAEF,IAAI,CAAC,MAAM,GAAG,IAAI,yCAAmB,CAAC,aAAa,CAAC,CAAC;QACrD,IAAI,CAAC,OAAO,GAAG,IAAI,uBAAU,CAAC,OAAO,CAAC,CAAC;IAC3C,CAAC,CAAI;;;;;OAKF;IACH,MAAM,CAAC,GAAiB;QACpB,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACjD,MAAM,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAE/C,OAAO,EAAE,YAAY,EAAE,MAAM,EAAE,CAAC;IACpC,CAAC;CACJ;AAjCD,oCAiCC"}
|