UNPKG

rawsql-ts

Version:

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

94 lines 4.55 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.AnalyzeStatementParser = void 0; const SqlTokenizer_1 = require("./SqlTokenizer"); const DDLStatements_1 = require("../models/DDLStatements"); const Lexeme_1 = require("../models/Lexeme"); const FullNameParser_1 = require("./FullNameParser"); const ValueComponent_1 = require("../models/ValueComponent"); /** * Parses ANALYZE statements. */ class AnalyzeStatementParser { static parse(sql) { const tokenizer = new SqlTokenizer_1.SqlTokenizer(sql); const lexemes = tokenizer.readLexemes(); const result = this.parseFromLexeme(lexemes, 0); if (result.newIndex < lexemes.length) { throw new Error(`[AnalyzeStatementParser] Unexpected token "${lexemes[result.newIndex].value}" after ANALYZE statement.`); } return result.value; } static parseFromLexeme(lexemes, index) { var _a, _b, _c, _d, _e; let idx = index; if (((_a = lexemes[idx]) === null || _a === void 0 ? void 0 : _a.value.toLowerCase()) !== "analyze") { throw new Error(`[AnalyzeStatementParser] Expected ANALYZE at index ${idx}.`); } idx++; // Capture optional VERBOSE modifier immediately after ANALYZE. let verbose = false; if (((_b = lexemes[idx]) === null || _b === void 0 ? void 0 : _b.value.toLowerCase()) === "verbose") { verbose = true; idx++; } // Parse optional target relation name if present. let target = null; if (this.canStartQualifiedName(lexemes[idx])) { const { namespaces, name, newIndex } = FullNameParser_1.FullNameParser.parseFromLexeme(lexemes, idx); target = new ValueComponent_1.QualifiedName(namespaces, name); idx = newIndex; } // Parse optional column list guarded by parentheses. let columns = null; if (((_c = lexemes[idx]) === null || _c === void 0 ? void 0 : _c.type) & Lexeme_1.TokenType.OpenParen) { if (!target) { throw new Error("[AnalyzeStatementParser] Column list requires a target relation before '('."); } idx++; // consume '(' columns = []; // Loop through comma-separated column identifiers until closing parenthesis. while (idx < lexemes.length) { if (lexemes[idx].type & Lexeme_1.TokenType.CloseParen) { if (columns.length === 0) { throw new Error("[AnalyzeStatementParser] Column list must include at least one column identifier."); } idx++; // consume ')' break; } const { name, newIndex } = FullNameParser_1.FullNameParser.parseFromLexeme(lexemes, idx); columns.push(name); idx = newIndex; if (((_d = lexemes[idx]) === null || _d === void 0 ? void 0 : _d.type) & Lexeme_1.TokenType.Comma) { idx++; continue; } if (((_e = lexemes[idx]) === null || _e === void 0 ? void 0 : _e.type) & Lexeme_1.TokenType.CloseParen) { idx++; // consume ')' break; } throw new Error(`[AnalyzeStatementParser] Expected ',' or ')' after column identifier at index ${idx}.`); } if (columns === null || columns.length === 0) { throw new Error("[AnalyzeStatementParser] Column list cannot be empty."); } } // Reject trailing identifiers when no target was provided. if (!target && lexemes[idx] && !(lexemes[idx].type & Lexeme_1.TokenType.CloseParen)) { throw new Error(`[AnalyzeStatementParser] Unexpected token "${lexemes[idx].value}" after ANALYZE clause.`); } const statement = new DDLStatements_1.AnalyzeStatement({ verbose, target, columns }); return { value: statement, newIndex: idx }; } static canStartQualifiedName(lexeme) { if (!lexeme) { return false; } if (lexeme.type & (Lexeme_1.TokenType.Identifier | Lexeme_1.TokenType.Command | Lexeme_1.TokenType.Function | Lexeme_1.TokenType.Type)) { return true; } return (lexeme.type & Lexeme_1.TokenType.OpenBracket) !== 0; } } exports.AnalyzeStatementParser = AnalyzeStatementParser; //# sourceMappingURL=AnalyzeStatementParser.js.map