UNPKG

rawsql-ts

Version:

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

374 lines 13.3 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.NamedQueryDefinitionExtractor = void 0; const Clause_1 = require("../models/Clause"); const DeleteQuery_1 = require("../models/DeleteQuery"); const InsertQuery_1 = require("../models/InsertQuery"); const MergeQuery_1 = require("../models/MergeQuery"); const SelectQuery_1 = require("../models/SelectQuery"); const UpdateQuery_1 = require("../models/UpdateQuery"); const ValueComponent_1 = require("../models/ValueComponent"); const SelectQueryWithClauseHelper_1 = require("../utils/SelectQueryWithClauseHelper"); /** * Extracts named query definitions, starting with CTE definitions from `WITH` clauses. * * @remarks Definitions are emitted in SQL source order. For nested CTEs, the outer * CTE definition is emitted when its name is encountered, then definitions inside * that CTE body are emitted before later sibling CTE definitions. */ class NamedQueryDefinitionExtractor { constructor() { this.definitions = []; this.visited = new Set(); } /** * Extract named query definitions from an AST component. */ static extract(input) { if (!input) { return []; } const extractor = new NamedQueryDefinitionExtractor(); extractor.visit(input); return extractor.definitions; } visit(value) { if (!value || typeof value !== "object") { return; } if (this.visited.has(value)) { return; } this.visited.add(value); if (value instanceof Clause_1.WithClause) { this.visitWithClause(value); return; } if (value instanceof Clause_1.CommonTable) { this.visitCommonTable(value); return; } if (value instanceof SelectQuery_1.SimpleSelectQuery || value instanceof SelectQuery_1.BinarySelectQuery || value instanceof SelectQuery_1.ValuesQuery) { this.visitSelectQuery(value); return; } if (value instanceof InsertQuery_1.InsertQuery) { this.visitInsertQuery(value); return; } if (value instanceof UpdateQuery_1.UpdateQuery) { this.visitUpdateQuery(value); return; } if (value instanceof DeleteQuery_1.DeleteQuery) { this.visitDeleteQuery(value); return; } if (value instanceof MergeQuery_1.MergeQuery) { this.visitMergeQuery(value); return; } if (this.visitKnownValueComponent(value)) { return; } if (this.visitKnownSqlComponent(value)) { return; } if (Array.isArray(value)) { for (const item of value) { this.visit(item); } return; } for (const key of Object.keys(value)) { this.visit(value[key]); } } visitSelectQuery(query, includeWith = true) { if (query instanceof SelectQuery_1.SimpleSelectQuery) { this.visitSimpleSelectQuery(query, includeWith); return; } if (query instanceof SelectQuery_1.BinarySelectQuery) { this.visitSelectQuery(query.left, includeWith); this.visitSelectQuery(query.right); return; } if (query instanceof SelectQuery_1.ValuesQuery) { if (includeWith) { this.visit(query.withClause); } this.visit(query.tuples); } } visitSimpleSelectQuery(query, includeWith) { if (includeWith) { this.visit(query.withClause); } this.visit(query.selectClause); this.visit(query.fromClause); this.visit(query.whereClause); this.visit(query.groupByClause); this.visit(query.havingClause); this.visit(query.windowClause); this.visit(query.orderByClause); this.visit(query.limitClause); this.visit(query.offsetClause); this.visit(query.fetchClause); this.visit(query.forClause); } visitInsertQuery(query) { const withClause = SelectQueryWithClauseHelper_1.SelectQueryWithClauseHelper.getWithClause(query.selectQuery); this.visit(withClause); this.visit(query.insertClause); if (query.selectQuery) { this.visitSelectQuery(query.selectQuery, false); } this.visit(query.onConflictClause); this.visit(query.returningClause); } visitUpdateQuery(query) { this.visit(query.withClause); this.visit(query.updateClause); this.visit(query.setClause); this.visit(query.fromClause); this.visit(query.whereClause); this.visit(query.returningClause); } visitDeleteQuery(query) { this.visit(query.withClause); this.visit(query.deleteClause); this.visit(query.usingClause); this.visit(query.whereClause); this.visit(query.returningClause); } visitMergeQuery(query) { this.visit(query.withClause); this.visit(query.target); this.visit(query.source); this.visit(query.onCondition); this.visit(query.whenClauses); this.visit(query.returningClause); } visitWithClause(withClause) { for (const commonTable of withClause.tables) { this.visitCommonTable(commonTable, withClause.recursive); } } visitCommonTable(commonTable, recursive) { const definition = { name: commonTable.getSourceAliasName(), query: commonTable.query, range: null, nameRange: null }; if (recursive !== undefined) { definition.recursive = recursive; } this.definitions.push(definition); this.visit(commonTable.query); } visitKnownSqlComponent(value) { if (value instanceof Clause_1.SelectClause) { this.visit(value.distinct); this.visit(value.hints); this.visit(value.items); return true; } if (value instanceof Clause_1.SelectItem) { this.visit(value.value); return true; } if (value instanceof Clause_1.FromClause) { this.visit(value.source); this.visit(value.joins); return true; } if (value instanceof Clause_1.JoinClause) { this.visit(value.source); this.visit(value.condition); return true; } if (value instanceof Clause_1.JoinOnClause || value instanceof Clause_1.JoinUsingClause) { this.visit(value.condition); return true; } if (value instanceof Clause_1.SourceExpression) { this.visit(value.datasource); return true; } if (value instanceof Clause_1.SubQuerySource) { this.visitSelectQuery(value.query); return true; } if (value instanceof Clause_1.FunctionSource) { this.visit(value.argument); return true; } if (value instanceof Clause_1.ParenSource) { this.visit(value.source); return true; } if (value instanceof Clause_1.WhereClause || value instanceof Clause_1.HavingClause) { this.visit(value.condition); return true; } if (value instanceof Clause_1.LimitClause) { this.visit(value.value); return true; } if (value instanceof Clause_1.GroupByClause) { this.visit(value.grouping); return true; } if (value instanceof Clause_1.WindowsClause) { this.visit(value.windows); return true; } if (value instanceof Clause_1.WindowFrameClause) { this.visit(value.expression); return true; } if (value instanceof Clause_1.OrderByClause) { this.visit(value.order); return true; } if (value instanceof Clause_1.OrderByItem) { this.visit(value.value); return true; } if (value instanceof Clause_1.ReturningClause) { this.visit(value.items); return true; } if (value instanceof Clause_1.OnConflictClause) { this.visit(value.setClause); this.visit(value.whereClause); this.visit(value.forClause); return true; } if (value instanceof Clause_1.SetClause) { for (const item of value.items) { this.visit(item.value); } return true; } if (value instanceof Clause_1.UpdateClause || value instanceof Clause_1.DeleteClause || value instanceof Clause_1.InsertClause) { this.visit(value.source); return true; } if (value instanceof Clause_1.UsingClause) { this.visit(value.sources); return true; } if (value instanceof MergeQuery_1.MergeWhenClause) { this.visit(value.condition); this.visit(value.action); return true; } if (value instanceof MergeQuery_1.MergeUpdateAction) { this.visit(value.setClause); this.visit(value.whereClause); return true; } if (value instanceof MergeQuery_1.MergeDeleteAction) { this.visit(value.whereClause); return true; } if (value instanceof MergeQuery_1.MergeInsertAction) { this.visit(value.values); return true; } return false; } visitKnownValueComponent(value) { if (value instanceof ValueComponent_1.ValueList || value instanceof ValueComponent_1.TupleExpression) { this.visit(value.values); return true; } if (value instanceof ValueComponent_1.FunctionCall) { this.visit(value.argument); this.visit(value.internalOrderBy); this.visit(value.withinGroup); this.visit(value.filterCondition); this.visit(value.over); return true; } if (value instanceof ValueComponent_1.WindowFrameExpression) { this.visit(value.partition); this.visit(value.order); this.visit(value.frameSpec); return true; } if (value instanceof ValueComponent_1.WindowFrameSpec) { this.visit(value.startBound); this.visit(value.endBound); return true; } if (value instanceof ValueComponent_1.WindowFrameBoundaryValue) { this.visit(value.value); return true; } if (value instanceof ValueComponent_1.UnaryExpression || value instanceof ValueComponent_1.ParenExpression || value instanceof ValueComponent_1.ArrayExpression || value instanceof ValueComponent_1.JsonPredicateExpression) { this.visit(value.expression); return true; } if (value instanceof ValueComponent_1.BinaryExpression) { this.visit(value.left); this.visit(value.right); return true; } if (value instanceof ValueComponent_1.SwitchCaseArgument) { this.visit(value.cases); this.visit(value.elseValue); return true; } if (value instanceof ValueComponent_1.CaseKeyValuePair) { this.visit(value.key); this.visit(value.value); return true; } if (value instanceof ValueComponent_1.CastExpression) { this.visit(value.input); this.visit(value.castType); return true; } if (value instanceof ValueComponent_1.CaseExpression) { this.visit(value.condition); this.visit(value.switchCase); return true; } if (value instanceof ValueComponent_1.ArrayQueryExpression) { this.visitSelectQuery(value.query); return true; } if (value instanceof ValueComponent_1.InlineQuery) { this.visitSelectQuery(value.selectQuery); return true; } if (value instanceof ValueComponent_1.BetweenExpression) { this.visit(value.expression); this.visit(value.lower); this.visit(value.upper); return true; } if (value instanceof ValueComponent_1.TypeValue) { this.visit(value.argument); return true; } if (value instanceof ValueComponent_1.ArraySliceExpression) { this.visit(value.array); this.visit(value.startIndex); this.visit(value.endIndex); return true; } if (value instanceof ValueComponent_1.ArrayIndexExpression) { this.visit(value.array); this.visit(value.index); return true; } return false; } } exports.NamedQueryDefinitionExtractor = NamedQueryDefinitionExtractor; //# sourceMappingURL=NamedQueryDefinitionExtractor.js.map