UNPKG

rawsql-ts

Version:

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

117 lines 5.16 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.JoinClauseParser = void 0; const Clause_1 = require("../models/Clause"); const Lexeme_1 = require("../models/Lexeme"); const CommandTokenReader_1 = require("../tokenReaders/CommandTokenReader"); const SourceExpressionParser_1 = require("./SourceExpressionParser"); const JoinOnClauseParser_1 = require("./JoinOnClauseParser"); const JoinUsingClauseParser_1 = require("./JoinUsingClauseParser"); class JoinClauseParser { static tryParse(lexemes, index) { let idx = index; const joins = []; while (this.isJoinCommand(lexemes, idx)) { const joinClause = this.parseJoinClause(lexemes, idx); joins.push(joinClause.value); idx = joinClause.newIndex; } if (joins.length > 0) { return { value: joins, newIndex: idx }; } return null; } static isJoinKeyword(value) { // Although performance is not ideal, // we use keyword token reader to centralize keyword management const result = CommandTokenReader_1.joinkeywordParser.parse(value, 0); if (result) { return true; } return false; } static parseLateral(lexemes, index) { let idx = index; if (idx < lexemes.length && lexemes[idx].value === 'lateral') { // Skip 'lateral' keyword idx++; return { value: true, newIndex: idx }; } return { value: false, newIndex: idx }; } static isJoinCommand(lexemes, index) { if (index >= lexemes.length) { return false; } if (lexemes[index].type & Lexeme_1.TokenType.Comma || this.isJoinKeyword(lexemes[index].value) === true) { return true; } return false; } static parseJoinClause(lexemes, index) { let idx = index; // Extract JOIN keyword and comments const { joinType, joinComments, newIndex: joinIndex } = this.parseJoinKeyword(lexemes, idx); idx = joinIndex; // Parse lateral join const lateralResult = this.parseLateral(lexemes, idx); const lateral = lateralResult.value; idx = lateralResult.newIndex; // Parse the source expression to join with const sourceResult = SourceExpressionParser_1.SourceExpressionParser.parseFromLexeme(lexemes, idx); idx = sourceResult.newIndex; // Try to parse join condition (ON or USING) const joinClause = this.parseJoinCondition(lexemes, idx, joinType, sourceResult.value, lateral, joinComments); if (joinClause) { return joinClause; } // Natural join (no condition) const naturalJoinClause = new Clause_1.JoinClause(joinType, sourceResult.value, null, lateral); this.applyJoinComments(naturalJoinClause, joinComments); return { value: naturalJoinClause, newIndex: idx }; } // Extract JOIN keyword and its comments static parseJoinKeyword(lexemes, index) { const joinType = lexemes[index].value === "," ? "cross join" : lexemes[index].value; const joinComments = this.extractJoinKeywordComments(lexemes[index]); return { joinType, joinComments, newIndex: index + 1 }; } // Extract comments from JOIN keyword token static extractJoinKeywordComments(token) { return { positioned: token.positionedComments && token.positionedComments.length > 0 ? token.positionedComments : null, legacy: token.comments && token.comments.length > 0 ? token.comments : null }; } // Parse join condition (ON or USING) static parseJoinCondition(lexemes, index, joinType, sourceValue, lateral, joinComments) { if (index >= lexemes.length) return null; // Try JoinOnClauseParser const onResult = JoinOnClauseParser_1.JoinOnClauseParser.tryParse(lexemes, index); if (onResult) { const joinClause = new Clause_1.JoinClause(joinType, sourceValue, onResult.value, lateral); this.applyJoinComments(joinClause, joinComments); return { value: joinClause, newIndex: onResult.newIndex }; } // Try JoinUsingClauseParser const usingResult = JoinUsingClauseParser_1.JoinUsingClauseParser.tryParse(lexemes, index); if (usingResult) { const joinClause = new Clause_1.JoinClause(joinType, sourceValue, usingResult.value, lateral); this.applyJoinComments(joinClause, joinComments); return { value: joinClause, newIndex: usingResult.newIndex }; } return null; } // Apply comments to JoinClause directly (no collection then assignment) static applyJoinComments(joinClause, joinComments) { if (joinComments.positioned) { joinClause.joinKeywordPositionedComments = joinComments.positioned; } else if (joinComments.legacy) { joinClause.joinKeywordComments = joinComments.legacy; } } } exports.JoinClauseParser = JoinClauseParser; //# sourceMappingURL=JoinClauseParser.js.map