UNPKG

rawsql-ts

Version:

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

202 lines 9.56 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ConditionDeduplicationOptimizer = void 0; const Clause_1 = require("../models/Clause"); const SelectQuery_1 = require("../models/SelectQuery"); const ValueComponent_1 = require("../models/ValueComponent"); const TopLevelAndConditionDeduper_1 = require("./TopLevelAndConditionDeduper"); class ConditionDeduplicationOptimizer { constructor() { this.visited = new WeakSet(); this.applied = []; } optimize(query, options) { this.visited = new WeakSet(); this.applied = []; if (!query) { return { query: null, applied: [] }; } this.visitSelectQuery(query, "root", options); return { query, applied: [...this.applied] }; } visitSelectQuery(query, scopeId, options) { var _a, _b, _c, _d, _e, _f, _g, _h; if (this.visited.has(query)) { return; } this.visited.add(query); if (query instanceof SelectQuery_1.BinarySelectQuery) { this.visitSelectQuery(query.left, `${scopeId}.left`, options); this.visitSelectQuery(query.right, `${scopeId}.right`, options); return; } if (!(query instanceof SelectQuery_1.SimpleSelectQuery)) { return; } for (const cte of (_b = (_a = query.withClause) === null || _a === void 0 ? void 0 : _a.tables) !== null && _b !== void 0 ? _b : []) { const cteQuery = cte.query; if (cteQuery instanceof SelectQuery_1.SimpleSelectQuery || cteQuery instanceof SelectQuery_1.BinarySelectQuery) { this.visitSelectQuery(cteQuery, `${scopeId}.cte:${cte.getSourceAliasName()}`, options); } } for (const item of query.selectClause.items) { this.visitValueComponent(item.value, `${scopeId}.select`, options); } if (query.fromClause) { this.visitSourceExpression(query.fromClause.source, `${scopeId}.from`, options); for (const join of (_c = query.fromClause.joins) !== null && _c !== void 0 ? _c : []) { const joinScope = `${scopeId}.join:${(_d = join.source.getAliasName()) !== null && _d !== void 0 ? _d : "unknown"}`; this.visitSourceExpression(join.source, joinScope, options); if (join.condition instanceof Clause_1.JoinOnClause) { join.condition.condition = this.dedupeCondition(join.condition.condition, `${joinScope}.on`, "Removed a duplicate top-level AND condition from a JOIN ON clause.", options); this.visitValueComponent(join.condition.condition, `${joinScope}.on`, options); } } } if (query.whereClause) { query.whereClause = new Clause_1.WhereClause(this.dedupeCondition(query.whereClause.condition, `${scopeId}.where`, "Removed a duplicate top-level AND condition from a WHERE clause.", options)); this.visitValueComponent(query.whereClause.condition, `${scopeId}.where`, options); } if (query.havingClause) { query.havingClause = new Clause_1.HavingClause(this.dedupeCondition(query.havingClause.condition, `${scopeId}.having`, "Removed a duplicate top-level AND condition from a HAVING clause.", options)); this.visitValueComponent(query.havingClause.condition, `${scopeId}.having`, options); } for (const item of (_f = (_e = query.groupByClause) === null || _e === void 0 ? void 0 : _e.grouping) !== null && _f !== void 0 ? _f : []) { this.visitValueComponent(item, `${scopeId}.group_by`, options); } for (const item of (_h = (_g = query.orderByClause) === null || _g === void 0 ? void 0 : _g.order) !== null && _h !== void 0 ? _h : []) { if (item instanceof Clause_1.OrderByItem) { this.visitValueComponent(item.value, `${scopeId}.order_by`, options); } else { this.visitValueComponent(item, `${scopeId}.order_by`, options); } } } visitSourceExpression(source, scopeId, options) { const datasource = source.datasource; if (datasource instanceof Clause_1.SubQuerySource) { this.visitSelectQuery(datasource.query, `${scopeId}.subquery`, options); return; } if (datasource instanceof Clause_1.ParenSource) { const nested = datasource.source; if (nested instanceof Clause_1.SubQuerySource) { this.visitSelectQuery(nested.query, `${scopeId}.subquery`, options); } return; } if (datasource instanceof Clause_1.FunctionSource && datasource.argument) { this.visitValueComponent(datasource.argument, `${scopeId}.function`, options); } } visitValueComponent(value, scopeId, options) { if (this.visited.has(value)) { return; } this.visited.add(value); if (value instanceof ValueComponent_1.InlineQuery) { this.visitSelectQuery(value.selectQuery, `${scopeId}.inline_query`, options); return; } if (value instanceof ValueComponent_1.ArrayQueryExpression) { this.visitSelectQuery(value.query, `${scopeId}.array_query`, options); return; } if (value instanceof ValueComponent_1.ParenExpression) { this.visitValueComponent(value.expression, scopeId, options); return; } if (value instanceof ValueComponent_1.BinaryExpression) { this.visitValueComponent(value.left, scopeId, options); this.visitValueComponent(value.right, scopeId, options); return; } if (value instanceof ValueComponent_1.UnaryExpression) { this.visitValueComponent(value.expression, scopeId, options); return; } if (value instanceof ValueComponent_1.FunctionCall) { if (value.argument) { this.visitValueComponent(value.argument, scopeId, options); } if (value.filterCondition) { this.visitValueComponent(value.filterCondition, `${scopeId}.filter`, options); } return; } if (value instanceof ValueComponent_1.CastExpression) { this.visitValueComponent(value.input, scopeId, options); if (value.castType.argument) { this.visitValueComponent(value.castType.argument, scopeId, options); } return; } if (value instanceof ValueComponent_1.CaseExpression) { if (value.condition) { this.visitValueComponent(value.condition, scopeId, options); } for (const item of value.switchCase.cases) { this.visitValueComponent(item.key, scopeId, options); this.visitValueComponent(item.value, scopeId, options); } if (value.switchCase.elseValue) { this.visitValueComponent(value.switchCase.elseValue, scopeId, options); } return; } if (value instanceof ValueComponent_1.BetweenExpression) { this.visitValueComponent(value.expression, scopeId, options); this.visitValueComponent(value.lower, scopeId, options); this.visitValueComponent(value.upper, scopeId, options); return; } if (value instanceof ValueComponent_1.JsonPredicateExpression) { this.visitValueComponent(value.expression, scopeId, options); return; } if (value instanceof ValueComponent_1.ArrayExpression) { this.visitValueComponent(value.expression, scopeId, options); return; } if (value instanceof ValueComponent_1.ArrayIndexExpression) { this.visitValueComponent(value.array, scopeId, options); this.visitValueComponent(value.index, scopeId, options); return; } if (value instanceof ValueComponent_1.ArraySliceExpression) { this.visitValueComponent(value.array, scopeId, options); if (value.startIndex) { this.visitValueComponent(value.startIndex, scopeId, options); } if (value.endIndex) { this.visitValueComponent(value.endIndex, scopeId, options); } return; } if (value instanceof ValueComponent_1.ValueList || value instanceof ValueComponent_1.TupleExpression) { value.values.forEach(item => this.visitValueComponent(item, scopeId, options)); return; } if (value instanceof ValueComponent_1.TypeValue && value.argument) { this.visitValueComponent(value.argument, scopeId, options); } } dedupeCondition(condition, scopeId, reason, options) { const result = (0, TopLevelAndConditionDeduper_1.dedupeTopLevelAndConditionsWithMetadata)(condition, options); for (const conditionSql of result.removedConditionSql) { this.applied.push({ kind: "dedupe_condition", conditionSql, scopeId, reason }); } return result.expression; } } exports.ConditionDeduplicationOptimizer = ConditionDeduplicationOptimizer; //# sourceMappingURL=ConditionDeduplicationOptimizer.js.map