rawsql-ts
Version:
High-performance SQL parser and AST analyzer written in TypeScript. Provides fast parsing and advanced transformation capabilities.
66 lines • 2.5 kB
JavaScript
import { WhereClause } from "../models/Clause";
import { BinaryExpression, ParenExpression } from "../models/ValueComponent";
import { formatSqlComponent } from "./SqlComponentFormatter";
// API output shape review: this internal helper keeps optimizer result sql/query shape unchanged;
// formatSqlComponent is used only as a caller-configurable canonical key for exact duplicate detection.
const unwrapParens = (expression) => {
let candidate = expression;
while (candidate instanceof ParenExpression) {
candidate = candidate.expression;
}
return candidate;
};
const isAndExpression = (expression) => {
const candidate = unwrapParens(expression);
return candidate instanceof BinaryExpression
&& candidate.operator.value.trim().toLowerCase() === "and";
};
const collectTopLevelAndTerms = (expression) => {
const candidate = unwrapParens(expression);
if (!isAndExpression(candidate)) {
return [expression];
}
return [
...collectTopLevelAndTerms(candidate.left),
...collectTopLevelAndTerms(candidate.right)
];
};
export const dedupeTopLevelAndConditionsWithMetadata = (expression, options) => {
const terms = collectTopLevelAndTerms(expression);
if (terms.length < 2) {
return { expression, removedConditionSql: [] };
}
const seen = new Set();
const uniqueTerms = [];
const removedConditionSql = [];
for (const term of terms) {
const key = formatSqlComponent(unwrapParens(term), options);
if (seen.has(key)) {
removedConditionSql.push(key);
continue;
}
seen.add(key);
uniqueTerms.push(term);
}
if (uniqueTerms.length === terms.length) {
return { expression, removedConditionSql: [] };
}
let rebuilt = uniqueTerms[0];
for (let index = 1; index < uniqueTerms.length; index += 1) {
rebuilt = new BinaryExpression(rebuilt, "and", uniqueTerms[index]);
}
return {
expression: rebuilt,
removedConditionSql
};
};
export const dedupeTopLevelAndConditions = (expression, options) => {
return dedupeTopLevelAndConditionsWithMetadata(expression, options).expression;
};
export const dedupeWhereTopLevelAndConditions = (query, options) => {
if (!query.whereClause) {
return;
}
query.whereClause = new WhereClause(dedupeTopLevelAndConditions(query.whereClause.condition, options));
};
//# sourceMappingURL=TopLevelAndConditionDeduper.js.map