rawsql-ts
Version:
[beta]High-performance SQL parser and AST analyzer written in TypeScript. Provides fast parsing and advanced transformation capabilities.
83 lines • 3.54 kB
JavaScript
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;
// Get the join type
const joinType = lexemes[idx].value === "," ? "cross join" : lexemes[idx].value;
idx++;
// Check for 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;
if (idx < lexemes.length) {
// JoinOnClauseParser
const onResult = JoinOnClauseParser_1.JoinOnClauseParser.tryParse(lexemes, idx);
if (onResult) {
const joinClause = new Clause_1.JoinClause(joinType, sourceResult.value, onResult.value, lateral);
return { value: joinClause, newIndex: onResult.newIndex };
}
// JoinUsingClauseParser
const usingResult = JoinUsingClauseParser_1.JoinUsingClauseParser.tryParse(lexemes, idx);
if (usingResult) {
const joinClause = new Clause_1.JoinClause(joinType, sourceResult.value, usingResult.value, lateral);
return { value: joinClause, newIndex: usingResult.newIndex };
}
}
// If we reach the end of the input, we can treat it as a natural join
const joinClause = new Clause_1.JoinClause(joinType, sourceResult.value, null, lateral);
return { value: joinClause, newIndex: idx };
}
}
exports.JoinClauseParser = JoinClauseParser;
//# sourceMappingURL=JoinClauseParser.js.map
;