UNPKG

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
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