rawsql-ts
Version:
[beta]High-performance SQL parser and AST analyzer written in TypeScript. Provides fast parsing and advanced transformation capabilities.
84 lines • 3.41 kB
JavaScript
import { FetchClause, FetchType, FetchUnit, FetchExpression } from "../models/Clause";
import { LiteralValue } from "../models/ValueComponent";
import { ValueParser } from "./ValueParser";
export class FetchClauseParser {
/**
* Parses a FETCH clause from a lexeme array starting at the given index.
* Supports syntax like: FETCH [FIRST|NEXT] <count> ROWS ONLY
* @param lexemes The array of lexemes
* @param index The starting index
* @returns { value: FetchSpecification, newIndex: number }
*/
static parseFromLexeme(lexemes, index) {
let idx = index;
if (lexemes[idx].value !== 'fetch') {
throw new Error(`Syntax error at position ${idx}: Expected 'FETCH' keyword but found "${lexemes[idx].value}".`);
}
idx++;
if (idx >= lexemes.length) {
throw new Error(`Syntax error: Unexpected end of input after 'FETCH' keyword.`);
}
const fetchExprResult = FetchExpressionParser.parseFromLexeme(lexemes, idx);
const fetchExpr = fetchExprResult.value;
idx = fetchExprResult.newIndex;
return { value: new FetchClause(fetchExpr), newIndex: idx };
}
}
// FetchExpressionParser: parses FETCH [FIRST|NEXT] <count> ROWS ONLY ...
export class FetchExpressionParser {
/**
* Parses a FETCH expression (not the whole clause, just the fetch part)
*/
static parseFromLexeme(lexemes, index) {
let idx = index;
let type;
const typeToken = lexemes[idx].value;
if (typeToken === 'first') {
type = FetchType.First;
}
else if (typeToken === 'next') {
type = FetchType.Next;
}
else {
throw new Error(`Syntax error at position ${idx}: Expected 'FIRST' or 'NEXT' after 'FETCH' but found "${lexemes[idx].value}".`);
}
idx++;
if (idx >= lexemes.length) {
throw new Error(`Syntax error: Unexpected end of input after 'FETCH FIRST|NEXT'.`);
}
let count = null;
let unit = null;
// Omitted count notation
if (lexemes[idx].value === 'row only' || lexemes[idx].value === 'rows only') {
count = new LiteralValue(1);
unit = FetchUnit.RowsOnly;
idx++;
return { value: new FetchExpression(type, count, unit), newIndex: idx };
}
// <count>
const countResult = ValueParser.parseFromLexeme(lexemes, idx);
count = countResult.value;
idx = countResult.newIndex;
if (idx >= lexemes.length) {
throw new Error(`Syntax error: Unexpected end of input after 'FETCH FIRST|NEXT <count>'.`);
}
// ROWS ONLY (or other unit)
if (lexemes[idx].value === 'rows only') {
unit = FetchUnit.RowsOnly;
idx++;
}
else if (lexemes[idx].value === 'percent') {
unit = FetchUnit.Percent;
idx++;
}
else if (lexemes[idx].value === 'percent with ties') {
unit = FetchUnit.PercentWithTies;
idx++;
}
if (!unit) {
throw new Error(`Syntax error: Expected 'ROWS ONLY', 'PERCENT', or 'PERCENT WITH TIES' after 'FETCH FIRST|NEXT <count>'.`);
}
return { value: new FetchExpression(type, count, unit), newIndex: idx };
}
}
//# sourceMappingURL=FetchClauseParser.js.map