UNPKG

rawsql-ts

Version:

[beta]High-performance SQL parser and AST analyzer written in TypeScript. Provides fast parsing and advanced transformation capabilities.

137 lines (136 loc) 4.97 kB
import { SqlFormatterOptions } from "./SqlFormatter"; /** * Interface representing an edited CTE with simplified structure * @public */ export interface EditedCTE { /** Name of the CTE */ name: string; /** SQL query for this CTE, may contain WITH clause from editing */ query: string; } /** * Options for CTEComposer extending SqlFormatterOptions * @public */ export interface CTEComposerOptions extends SqlFormatterOptions { /** Whether to validate the composed query against a schema */ validateSchema?: boolean; /** Table to columns mapping for schema validation (required if validateSchema is true) */ schema?: Record<string, string[]>; } /** * Composes edited CTEs back into a unified SQL query * * Takes CTEs that were individually edited after decomposition and reconstructs them * into a proper WITH clause structure. This completes the CTE debugging workflow: * 1. Use CTEQueryDecomposer to break down complex CTEs * 2. Edit individual CTEs to fix issues * 3. Use CTEComposer to reconstruct the unified query * * @example * ```typescript * // After decomposing and editing CTEs * const composer = new CTEComposer({ * preset: 'postgres', * validateSchema: true, * schema: { users: ['id', 'name', 'active'] } * }); * * const editedCTEs = [ * { name: 'base_data', query: 'select * from users where active = true' }, * { name: 'filtered_data', query: 'select * from base_data where region = "US"' } * ]; * * const composedSQL = composer.compose(editedCTEs, 'select * from filtered_data'); * // Dependencies are automatically analyzed and sorted * // Result: "with base_data as (...), filtered_data as (...) select * from filtered_data" * ``` * * @public */ export declare class CTEComposer { private readonly formatter; private readonly options; private readonly dependencyAnalyzer; private knownCTENames; /** * Creates a new CTEComposer instance * @param options - Configuration options extending SqlFormatterOptions */ constructor(options?: CTEComposerOptions); /** * Compose edited CTEs and root query into a unified SQL query * * This method: * 1. Extracts pure SELECT queries from edited CTEs (removes any WITH clauses) * 2. Builds a temporary query to analyze dependencies automatically * 3. Sorts CTEs by dependency order using topological sort * 4. Validates schema if options.validateSchema is enabled * 5. Applies formatter options for consistent output * 6. Constructs the final WITH clause with proper recursive handling * * @param editedCTEs - Array of edited CTEs with name and query only * @param rootQuery - The main query that uses the CTEs (without WITH clause) * @returns Composed SQL query with properly structured WITH clause * @throws Error if schema validation fails or circular dependencies are detected * * @example * ```typescript * const editedCTEs = [ * { name: 'base_data', query: 'select * from users where active = true' }, * { name: 'filtered_data', query: 'select * from base_data where region = "US"' } * ]; * * const result = composer.compose(editedCTEs, 'select count(*) from filtered_data'); * // Dependencies automatically analyzed and sorted * // Result: "with base_data as (...), filtered_data as (...) select count(*) from filtered_data" * ``` */ compose(editedCTEs: EditedCTE[], rootQuery: string): string; /** * Extract pure SELECT query from a query that may contain WITH clause * If query contains WITH with known CTEs, extract main SELECT and ignore old definitions * If query contains WITH with unknown CTEs, preserve entire query * @param query The query that may contain WITH clause * @param cteName The name of the CTE to extract (if query contains WITH) * @returns Pure SELECT query without WITH clause, or entire query if it contains new sub-CTEs */ private extractPureQuery; /** * Get list of known CTE names from current composition context */ private getKnownCTENames; /** * Extract CTE name from CommonTable */ private getCTEName; /** * Extract CTE definition using regex as fallback */ private extractCTEWithRegex; /** * Build a temporary query for dependency analysis */ private buildTempQueryForAnalysis; /** * Sort CTEs by dependencies using dependency graph */ private sortCTEsByDependencies; /** * Detect if any CTEs are recursive by analyzing original queries */ private detectRecursiveFromOriginalQueries; /** * Detect if any CTEs are recursive */ private detectRecursiveCTEs; /** * Validate the composed query against schema */ private validateComposedQuery; /** * Apply formatting to the final query */ private formatFinalQuery; }