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