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