rawsql-ts
Version:
High-performance SQL parser and AST analyzer written in TypeScript. Provides fast parsing and advanced transformation capabilities.
137 lines • 5.44 kB
JavaScript
import { CreateTableQuery } from "../models/CreateTableQuery";
import { InsertQuery } from "../models/InsertQuery";
import { TokenType } from "../models/Lexeme";
import { ValuesQuery } from "../models/ValuesQuery";
import { TableSource } from "../models/Clause";
import { FullNameParser } from "../parsers/FullNameParser";
import { SelectQueryParser } from "../parsers/SelectQueryParser";
import { SqlParser } from "../parsers/SqlParser";
import { SqlTokenizer } from "../parsers/SqlTokenizer";
export class SelectBodyExtractor {
static extract(input) {
if (typeof input === "string") {
return this.extractFromSql(input);
}
return this.extractFromStatement(input);
}
static extractFromSql(sql) {
const lexemes = new SqlTokenizer(sql).readLexemes();
if (this.isCreateViewStatement(lexemes)) {
return this.extractCreateViewFromLexemes(lexemes);
}
return this.extractFromStatement(SqlParser.parse(sql));
}
static extractFromStatement(statement) {
if (statement instanceof CreateTableQuery) {
const targetName = this.createTableTargetName(statement);
if (!statement.asSelectQuery) {
return this.unsupported(targetName);
}
return {
supported: true,
kind: "create-table-as",
targetName,
selectQuery: statement.asSelectQuery
};
}
if (statement instanceof InsertQuery) {
const targetName = this.insertTargetName(statement);
if (!statement.selectQuery || statement.selectQuery instanceof ValuesQuery) {
return this.unsupported(targetName);
}
return {
supported: true,
kind: "insert-select",
targetName,
selectQuery: statement.selectQuery
};
}
return {
supported: false,
kind: null,
targetName: null,
selectQuery: null,
reason: "Statement type is not supported."
};
}
static extractCreateViewFromLexemes(lexemes) {
var _a, _b, _c, _d, _e, _f;
let idx = 0;
idx++; // CREATE
const materialized = ((_a = lexemes[idx]) === null || _a === void 0 ? void 0 : _a.value.toLowerCase()) === "materialized";
if (materialized) {
idx++;
}
if (((_b = lexemes[idx]) === null || _b === void 0 ? void 0 : _b.value.toLowerCase()) !== "view") {
return this.unsupported(null, "Statement type is not supported.");
}
idx++;
if (((_c = lexemes[idx]) === null || _c === void 0 ? void 0 : _c.value.toLowerCase()) === "if not exists") {
idx++;
}
const targetResult = FullNameParser.parseFromLexeme(lexemes, idx);
idx = targetResult.newIndex;
const targetName = [...((_d = targetResult.namespaces) !== null && _d !== void 0 ? _d : []), targetResult.name.name].join(".");
if (((_e = lexemes[idx]) === null || _e === void 0 ? void 0 : _e.type) === TokenType.OpenParen) {
idx = this.consumeBalancedParentheses(lexemes, idx);
}
if (((_f = lexemes[idx]) === null || _f === void 0 ? void 0 : _f.value.toLowerCase()) !== "as") {
return this.unsupported(targetName);
}
idx++;
const selectResult = SelectQueryParser.parseFromLexeme(lexemes, idx);
return {
supported: true,
kind: materialized ? "create-materialized-view" : "create-view",
targetName,
selectQuery: selectResult.value
};
}
static isCreateViewStatement(lexemes) {
var _a, _b, _c;
if (((_a = lexemes[0]) === null || _a === void 0 ? void 0 : _a.value.toLowerCase()) !== "create") {
return false;
}
const second = (_b = lexemes[1]) === null || _b === void 0 ? void 0 : _b.value.toLowerCase();
const third = (_c = lexemes[2]) === null || _c === void 0 ? void 0 : _c.value.toLowerCase();
return second === "view" || (second === "materialized" && third === "view");
}
static consumeBalancedParentheses(lexemes, index) {
let idx = index;
let depth = 0;
while (idx < lexemes.length) {
if (lexemes[idx].type === TokenType.OpenParen) {
depth++;
}
else if (lexemes[idx].type === TokenType.CloseParen) {
depth--;
if (depth === 0) {
return idx + 1;
}
}
idx++;
}
return idx;
}
static createTableTargetName(query) {
var _a;
return [...((_a = query.namespaces) !== null && _a !== void 0 ? _a : []), query.tableName.name].join(".");
}
static insertTargetName(query) {
const source = query.insertClause.source;
if (source.datasource instanceof TableSource) {
return source.datasource.getSourceName();
}
return source.getAliasName();
}
static unsupported(targetName, reason = "No embedded SELECT body found.") {
return {
supported: false,
kind: null,
targetName,
selectQuery: null,
reason
};
}
}
//# sourceMappingURL=SelectBodyExtractor.js.map