UNPKG

rawsql-ts

Version:

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

239 lines 10.6 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ClauseScopedColumnReferenceCollector = void 0; const Clause_1 = require("../models/Clause"); const SimpleSelectQuery_1 = require("../models/SimpleSelectQuery"); const ValueComponent_1 = require("../models/ValueComponent"); /** * Collects ColumnReference nodes grouped by the root SimpleSelectQuery clause that owns them. * * Subquery and CTE bodies are intentionally not traversed because they have their own query-body * ownership. Use ColumnReferenceCollector when comprehensive tree traversal is required. */ class ClauseScopedColumnReferenceCollector { collect(query) { if (!(query instanceof SimpleSelectQuery_1.SimpleSelectQuery)) { throw new Error("ClauseScopedColumnReferenceCollector requires a SimpleSelectQuery."); } const result = this.createEmptyResult(); this.collectFromSelectClause(query.selectClause, result); this.collectFromJoinClauses(query, result); if (query.whereClause) { this.collectFromWhereClause(query.whereClause, result); } if (query.groupByClause) { this.collectFromGroupByClause(query.groupByClause, result); } if (query.havingClause) { this.collectFromHavingClause(query.havingClause, result); } if (query.orderByClause) { this.collectFromOrderByClause(query.orderByClause, "orderBy", result); } if (query.windowClause) { this.collectFromWindowsClause(query.windowClause, result); } if (query.limitClause) { this.collectFromLimitClause(query.limitClause, result); } if (query.offsetClause) { this.collectFromOffsetClause(query.offsetClause, result); } if (query.fetchClause) { this.collectFromFetchClause(query.fetchClause, result); } return result; } createEmptyResult() { return { select: [], where: [], joinOn: [], groupBy: [], having: [], orderBy: [], window: [], limitOffset: [], }; } collectFromSelectClause(clause, result) { if (clause.distinct instanceof Clause_1.DistinctOn) { this.collectFromValueComponent(clause.distinct.value, "select", result); } for (const item of clause.items) { this.collectFromValueComponent(item.value, "select", result); } } collectFromJoinClauses(query, result) { var _a; if (!((_a = query.fromClause) === null || _a === void 0 ? void 0 : _a.joins)) { return; } for (const join of query.fromClause.joins) { if (join.condition instanceof Clause_1.JoinOnClause || join.condition instanceof Clause_1.JoinUsingClause) { this.collectFromValueComponent(join.condition.condition, "joinOn", result); } } } collectFromWhereClause(clause, result) { this.collectFromValueComponent(clause.condition, "where", result); } collectFromGroupByClause(clause, result) { for (const item of clause.grouping) { this.collectFromValueComponent(item, "groupBy", result); } } collectFromHavingClause(clause, result) { this.collectFromValueComponent(clause.condition, "having", result); } collectFromOrderByClause(clause, target, result) { for (const item of clause.order) { if (item instanceof Clause_1.OrderByItem) { this.collectFromValueComponent(item.value, target, result); } else { this.collectFromValueComponent(item, target, result); } } } collectFromLimitClause(clause, result) { this.collectFromValueComponent(clause.value, "limitOffset", result); } collectFromOffsetClause(clause, result) { this.collectFromValueComponent(clause.value, "limitOffset", result); } collectFromFetchClause(clause, result) { this.collectFromValueComponent(clause.expression.count, "limitOffset", result); } collectFromWindowsClause(clause, result) { for (const window of clause.windows) { this.collectFromWindowFrameExpression(window.expression, "window", result); } } collectFromValueComponent(value, target, result, expression = value) { if (value instanceof ValueComponent_1.ColumnReference) { result[target].push(this.createInfo(value, target, expression)); return; } if (value instanceof ValueComponent_1.BinaryExpression) { this.collectFromValueComponent(value.left, target, result, value); this.collectFromValueComponent(value.right, target, result, value); } else if (value instanceof ValueComponent_1.UnaryExpression) { this.collectFromValueComponent(value.expression, target, result, value); } else if (value instanceof ValueComponent_1.FunctionCall) { this.collectFromFunctionCall(value, target, result); } else if (value instanceof ValueComponent_1.CaseExpression) { if (value.condition) { this.collectFromValueComponent(value.condition, target, result, value); } for (const pair of value.switchCase.cases) { this.collectFromValueComponent(pair.key, target, result, value); this.collectFromValueComponent(pair.value, target, result, value); } if (value.switchCase.elseValue) { this.collectFromValueComponent(value.switchCase.elseValue, target, result, value); } } else if (value instanceof ValueComponent_1.ParenExpression) { this.collectFromValueComponent(value.expression, target, result, value); } else if (value instanceof ValueComponent_1.CastExpression) { this.collectFromValueComponent(value.input, target, result, value); } else if (value instanceof ValueComponent_1.BetweenExpression) { this.collectFromValueComponent(value.expression, target, result, value); this.collectFromValueComponent(value.lower, target, result, value); this.collectFromValueComponent(value.upper, target, result, value); } else if (value instanceof ValueComponent_1.JsonPredicateExpression) { this.collectFromValueComponent(value.expression, target, result, value); } else if (value instanceof ValueComponent_1.ArrayExpression) { this.collectFromValueComponent(value.expression, target, result, value); } else if (value instanceof ValueComponent_1.ArraySliceExpression) { this.collectFromValueComponent(value.array, target, result, value); if (value.startIndex) { this.collectFromValueComponent(value.startIndex, target, result, value); } if (value.endIndex) { this.collectFromValueComponent(value.endIndex, target, result, value); } } else if (value instanceof ValueComponent_1.ArrayIndexExpression) { this.collectFromValueComponent(value.array, target, result, value); this.collectFromValueComponent(value.index, target, result, value); } else if (value instanceof ValueComponent_1.ValueList) { for (const item of value.values) { this.collectFromValueComponent(item, target, result, value); } } else if (value instanceof ValueComponent_1.TupleExpression) { for (const item of value.values) { this.collectFromValueComponent(item, target, result, value); } } else if (value instanceof ValueComponent_1.TypeValue && value.argument) { this.collectFromValueComponent(value.argument, target, result, value); } else if (value instanceof ValueComponent_1.InlineQuery || value instanceof ValueComponent_1.ArrayQueryExpression) { return; } } collectFromFunctionCall(value, target, result) { if (value.argument) { this.collectFromValueComponent(value.argument, target, result, value); } if (value.filterCondition) { this.collectFromValueComponent(value.filterCondition, target, result, value); } if (value.withinGroup) { this.collectFromOrderByClause(value.withinGroup, target, result); } if (value.internalOrderBy) { this.collectFromOrderByClause(value.internalOrderBy, target, result); } if (value.over instanceof ValueComponent_1.WindowFrameExpression) { this.collectFromWindowFrameExpression(value.over, target, result); } } collectFromWindowFrameExpression(value, target, result) { if (value.partition) { this.collectFromValueComponent(value.partition.value, target, result); } if (value.order) { this.collectFromOrderByClause(value.order, target, result); } if (value.frameSpec) { if (value.frameSpec.startBound instanceof ValueComponent_1.WindowFrameBoundaryValue) { this.collectFromValueComponent(value.frameSpec.startBound.value, target, result); } if (value.frameSpec.endBound instanceof ValueComponent_1.WindowFrameBoundaryValue) { this.collectFromValueComponent(value.frameSpec.endBound.value, target, result); } } } createInfo(reference, clause, expression) { var _a, _b; const namespaces = (_b = (_a = reference.namespaces) === null || _a === void 0 ? void 0 : _a.map(namespace => namespace.name)) !== null && _b !== void 0 ? _b : []; const columnName = this.getNameText(reference.qualifiedName.name); return { clause, reference, qualifiedName: reference.qualifiedName.toString(), namespaces, namespace: namespaces.length > 0 ? namespaces.join(".") : null, column: columnName, expression, }; } getNameText(name) { return name instanceof ValueComponent_1.IdentifierString ? name.name : name.value; } } exports.ClauseScopedColumnReferenceCollector = ClauseScopedColumnReferenceCollector; //# sourceMappingURL=ClauseScopedColumnReferenceCollector.js.map