UNPKG

rawsql-ts

Version:

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

69 lines 3.66 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.SourceExpressionParser = void 0; const Clause_1 = require("../models/Clause"); const SqlTokenizer_1 = require("./SqlTokenizer"); const Lexeme_1 = require("../models/Lexeme"); const SourceParser_1 = require("./SourceParser"); const SourceAliasExpressionParser_1 = require("./SourceAliasExpressionParser"); class SourceExpressionParser { /** * Parse SQL string to SourceExpression (e.g. "table", "table as t", "schema.table t") */ static parse(query) { const tokenizer = new SqlTokenizer_1.SqlTokenizer(query); const lexemes = tokenizer.readLexmes(); const result = this.parseFromLexeme(lexemes, 0); if (result.newIndex < lexemes.length) { throw new Error(`Syntax error: Unexpected token "${lexemes[result.newIndex].value}" at position ${result.newIndex}. The source expression is complete but there are additional tokens.`); } return result.value; } static parseTableSourceFromLexemes(lexemes, index) { const result = SourceParser_1.SourceParser.parseTableSourceFromLexemes(lexemes, index); // No alias for table source const sourceExpr = new Clause_1.SourceExpression(result.value, null); return { value: sourceExpr, newIndex: result.newIndex }; } // Parse from lexeme array (was: parse) static parseFromLexeme(lexemes, index) { let idx = index; const sourceResult = SourceParser_1.SourceParser.parseFromLexeme(lexemes, idx); idx = sourceResult.newIndex; if (idx < lexemes.length) { if (lexemes[idx].value === "as") { idx++; const aliasResult = SourceAliasExpressionParser_1.SourceAliasExpressionParser.parseFromLexeme(lexemes, idx); idx = aliasResult.newIndex; const sourceExpr = new Clause_1.SourceExpression(sourceResult.value, aliasResult.value); return { value: sourceExpr, newIndex: idx }; } /** * Explanation: * Source aliases are typically identified as TokenType.Identifier. * However, when the 'AS' keyword is omitted and column alias names are specified, * they may sometimes be classified as TokenType.Function. * Since the TokenReader's responsibility is to perform coarse-grained classification, * the parser must interpret subsequent 'Function' tokens as source alias expressions * when they follow a source definition. * Example: * SQL: select t.* from (values(1)) t(id) * Explanation: The alias 't' and its column alias 'id' are parsed as a source alias expression. */ if (idx < lexemes.length && this.isTokenTypeAliasCandidate(lexemes[idx].type)) { const aliasResult = SourceAliasExpressionParser_1.SourceAliasExpressionParser.parseFromLexeme(lexemes, idx); idx = aliasResult.newIndex; const sourceExpr = new Clause_1.SourceExpression(sourceResult.value, aliasResult.value); return { value: sourceExpr, newIndex: idx }; } } // no alias const expr = new Clause_1.SourceExpression(sourceResult.value, null); return { value: expr, newIndex: idx }; } static isTokenTypeAliasCandidate(type) { return (type & Lexeme_1.TokenType.Identifier) !== 0 || (type & Lexeme_1.TokenType.Function) !== 0; } } exports.SourceExpressionParser = SourceExpressionParser; //# sourceMappingURL=SourceExpressionParser.js.map