UNPKG

rawsql-ts

Version:

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

200 lines (199 loc) 6.05 kB
import { SelectQuery } from "../models/SelectQuery"; import { LineColumn } from "../utils/LexemeCursor"; import { Lexeme } from "../models/Lexeme"; /** * Represents an alias scope within SQL query structure */ export interface AliasScope { type: 'cte' | 'subquery' | 'main'; name?: string; query: SelectQuery; startPosition: number; endPosition: number; } /** * Represents a reference to an alias within the SQL */ export interface AliasReference { lexeme: Lexeme; scope: AliasScope; referenceType: 'definition' | 'usage'; context: 'table' | 'column'; } /** * Options for alias renaming operations */ export interface RenameOptions { scopeType?: 'auto' | 'cte' | 'subquery' | 'main'; dryRun?: boolean; preserveFormatting?: boolean; } /** * Result of alias renaming operation */ export interface RenameResult { success: boolean; originalSql: string; newSql?: string; changes: AliasChange[]; conflicts?: string[]; scope?: AliasScope; } /** * Details of a specific alias change */ export interface AliasChange { oldName: string; newName: string; position: LineColumn; context: 'table' | 'column'; referenceType: 'definition' | 'usage'; } /** * A utility class for renaming table and column aliases in SQL queries. * * This class provides functionality to rename aliases within specific scopes * (CTE, subquery, or main query) based on cursor position from GUI editors. * It automatically detects the appropriate scope and updates all references * to the alias within that scope boundary. * * @example * ```typescript * import { AliasRenamer } from 'rawsql-ts'; * * const sql = ` * SELECT u.name, o.date * FROM users u * JOIN orders o ON u.id = o.user_id * `; * * const renamer = new AliasRenamer(); * * // Rename 'u' to 'user_alias' by selecting it at line 2, column 10 * const result = renamer.renameAlias(sql, { line: 2, column: 10 }, 'user_alias'); * * if (result.success) { * console.log(result.newSql); * // SELECT user_alias.name, o.date * // FROM users user_alias * // JOIN orders o ON user_alias.id = o.user_id * } * ``` * * @since 0.12.0 */ export declare class AliasRenamer { private keywordParser; /** * Creates a new instance of AliasRenamer. */ constructor(); /** * Renames an alias based on the cursor position in GUI editor. * * This method detects the alias at the specified line and column position, * determines its scope (CTE, subquery, or main query), and renames all * references to that alias within the scope boundaries. * * @param sql - The SQL string containing the alias to rename * @param position - Line and column position (1-based) from GUI editor * @param newName - The new name for the alias * @param options - Optional configuration for the rename operation * @returns Result containing success status, modified SQL, and change details * * @example * ```typescript * const sql = "SELECT u.name FROM users u WHERE u.active = true"; * const result = renamer.renameAlias(sql, { line: 1, column: 8 }, 'user_table'); * * if (result.success) { * console.log(result.newSql); * // "SELECT user_table.name FROM users user_table WHERE user_table.active = true" * } * ``` * * @throws {Error} When the SQL cannot be parsed or position is invalid */ renameAlias(sql: string, position: LineColumn, newName: string, options?: RenameOptions): RenameResult; /** * Validates input parameters for alias renaming. */ private validateInputs; /** * Validates that the lexeme represents a valid alias. */ private validateLexemeIsAlias; /** * Detects the scope (CTE, subquery, main query) containing the alias. */ private detectAliasScope; /** * Creates scope for a specific requested type. */ private createScopeForType; /** * Auto-detects the most appropriate scope based on cursor position. */ private autoDetectScope; /** * Detects if the position is within a CTE and returns appropriate scope. */ private detectCTEScope; /** * Detects if the position is within a subquery scope. */ private detectSubqueryScope; /** * Finds a CTE query by name within the parsed AST. */ private findCTEQueryByName; /** * Collects all references to the specified alias within the given scope. */ private collectAliasReferences; /** * Collects table alias references within the scope. */ private collectTableAliasReferences; /** * Collects column alias references (table_alias.column format) within the scope. */ private collectColumnAliasReferences; /** * Creates a lexeme representation from a table source for reference tracking. */ private createLexemeFromTableSource; /** * Creates a lexeme representation from a namespace for reference tracking. */ private createLexemeFromNamespace; /** * Checks for naming conflicts when renaming to the new name. */ private checkNameConflicts; /** * Checks for conflicts with existing table aliases and table names in the scope. */ private checkTableAliasConflicts; /** * Extracts the actual table name from a table source (not the alias). */ private extractTableName; /** * Checks if the new name conflicts with SQL keywords using the existing KeywordTrie. */ private checkKeywordConflicts; /** * Fallback method for basic reserved keyword checking. */ private isBasicReservedKeyword; /** * Prepares change details for the rename operation. */ private prepareChanges; /** * Enhanced SQL text replacement using lexeme-based approach. * This method re-tokenizes the SQL to get accurate position information. */ private performLexemeBasedRename; }