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
TypeScript
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;
}