UNPKG

rawsql-ts

Version:

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

163 lines (162 loc) 6.05 kB
import { SqlComponent, SqlComponentVisitor } from "../models/SqlComponent"; import { ColumnReference } from "../models/ValueComponent"; /** * A comprehensive collector for all ColumnReference instances in SQL query structures. * * This collector extends beyond the capabilities of SelectableColumnCollector by traversing * CTE internal queries, subqueries, and all nested SQL components to collect every column * reference instance in the query tree. It's specifically designed for transformation * scenarios where all column references need to be identified and potentially modified. * * ## Key Differences from SelectableColumnCollector * * | Feature | SelectableColumnCollector | ColumnReferenceCollector | * |---------|---------------------------|---------------------------| * | CTE Internal Scanning | ❌ Skipped | ✅ Included | * | Subquery Traversal | ❌ Limited | ✅ Comprehensive | * | Deduplication | ✅ Yes | ❌ No (preserves all instances) | * | Use Case | Column selection analysis | Column reference transformation | * * ## Supported Query Types * * - **SimpleSelectQuery**: Standard SELECT statements with all clauses * - **BinarySelectQuery**: UNION, INTERSECT, EXCEPT operations * - **Nested CTEs**: WITH clauses and their internal queries * - **Subqueries**: All subquery types in FROM, WHERE, SELECT clauses * - **Complex Expressions**: CASE, functions, binary operations, etc. * * @example * ```typescript * import { ColumnReferenceCollector, SelectQueryParser } from 'rawsql-ts'; * * const sql = ` * WITH user_data AS ( * SELECT id, name FROM users WHERE status = 'active' * ), * order_summary AS ( * SELECT user_data.id, COUNT(*) as order_count * FROM user_data * JOIN orders ON user_data.id = orders.user_id * GROUP BY user_data.id * ) * SELECT * FROM order_summary * `; * * const query = SelectQueryParser.parse(sql); * const collector = new ColumnReferenceCollector(); * const columnRefs = collector.collect(query); * * console.log(`Found ${columnRefs.length} column references:`); * columnRefs.forEach(ref => { * const tableName = ref.namespaces?.[0]?.name || 'NO_TABLE'; * console.log(`- ${tableName}.${ref.column.name}`); * }); * * // Output includes references from: * // - CTE definitions: users.id, users.name, users.status * // - Main query: user_data.id, orders.user_id, etc. * ``` * * @example * ```typescript * // Use for column reference transformation * const columnRefs = collector.collect(query); * * // Update all references to 'old_table' to 'new_table' * columnRefs.forEach(ref => { * if (ref.namespaces?.[0]?.name === 'old_table') { * ref.namespaces[0].name = 'new_table'; * } * }); * ``` * * @since 0.11.16 */ export declare class ColumnReferenceCollector implements SqlComponentVisitor<void> { private handlers; private columnReferences; private visitedNodes; constructor(); /** * Collects all ColumnReference instances from the given SQL query component. * * This method performs a comprehensive traversal of the entire query structure, * including CTE definitions, subqueries, and all expression types to collect * every ColumnReference instance. The returned references are actual instances * from the query tree, allowing for direct modification. * * @param query - The SQL query component to analyze. Can be SimpleSelectQuery, BinarySelectQuery, or any SqlComponent. * @returns An array of all ColumnReference instances found in the query. Each reference maintains its original object identity for modification purposes. * * @example * ```typescript * const collector = new ColumnReferenceCollector(); * const columnRefs = collector.collect(query); * * // Analyze collected references * const tableReferences = new Map<string, number>(); * columnRefs.forEach(ref => { * const tableName = ref.namespaces?.[0]?.name || 'unqualified'; * tableReferences.set(tableName, (tableReferences.get(tableName) || 0) + 1); * }); * * console.log('Table reference counts:', tableReferences); * ``` * * @example * ```typescript * // Transform references during collection * const columnRefs = collector.collect(query); * * // Replace all references to 'old_schema.table' with 'new_schema.table' * columnRefs.forEach(ref => { * if (ref.namespaces?.length === 2 && * ref.namespaces[0].name === 'old_schema' && * ref.namespaces[1].name === 'table') { * ref.namespaces[0].name = 'new_schema'; * } * }); * ``` * * @since 0.11.16 */ collect(query: SqlComponent): ColumnReference[]; private collectFromSimpleQuery; private collectFromSelectClause; private collectFromFromClause; private collectFromSourceExpression; private collectFromValueComponent; visit(component: SqlComponent): void; private visitSimpleSelectQuery; private visitWithClause; private visitCommonTable; private visitSelectClause; private visitFromClause; private visitWhereClause; private visitGroupByClause; private visitHavingClause; private visitOrderByClause; private visitWindowsClause; private visitLimitClause; private visitOffsetClause; private visitFetchClause; private visitForClause; private visitJoinClause; private visitJoinOnClause; private visitJoinUsingClause; private visitSourceExpression; private visitSubQuerySource; private visitColumnReference; private visitBinaryExpression; private visitUnaryExpression; private visitFunctionCall; private visitCaseExpression; private visitCastExpression; private visitBetweenExpression; private visitParenExpression; private visitInlineQuery; private visitArrayExpression; private visitArrayQueryExpression; private visitValueList; private visitWindowFrameExpression; }