UNPKG

rawsql-ts

Version:

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

113 lines 4.87 kB
import { JoinClause } from "../models/Clause"; import { TokenType } from "../models/Lexeme"; import { joinkeywordParser } from "../tokenReaders/CommandTokenReader"; import { SourceExpressionParser } from "./SourceExpressionParser"; import { JoinOnClauseParser } from "./JoinOnClauseParser"; import { JoinUsingClauseParser } from "./JoinUsingClauseParser"; export 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 = 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 & 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.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 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.tryParse(lexemes, index); if (onResult) { const joinClause = new JoinClause(joinType, sourceValue, onResult.value, lateral); this.applyJoinComments(joinClause, joinComments); return { value: joinClause, newIndex: onResult.newIndex }; } // Try JoinUsingClauseParser const usingResult = JoinUsingClauseParser.tryParse(lexemes, index); if (usingResult) { const joinClause = new 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; } } } //# sourceMappingURL=JoinClauseParser.js.map