rawsql-ts
Version:
High-performance SQL parser and AST analyzer written in TypeScript. Provides fast parsing and advanced transformation capabilities.
74 lines • 3.24 kB
JavaScript
import { WhereClause } from "../models/Clause";
import { BinaryExpression, ColumnReference, ParenExpression } from "../models/ValueComponent";
import { ValueParser } from "../parsers/ValueParser";
import { formatSqlComponent } from "./SqlComponentFormatter";
export const normalizeIdentifier = (value) => value.trim().toLowerCase();
const isCaseSensitiveIdentifier = (value) => /[A-Z]/.test(value.trim());
export const identifiersEqual = (left, right) => {
const trimmedLeft = left.trim();
const trimmedRight = right.trim();
return isCaseSensitiveIdentifier(trimmedLeft) || isCaseSensitiveIdentifier(trimmedRight)
? trimmedLeft === trimmedRight
: trimmedLeft.toLowerCase() === trimmedRight.toLowerCase();
};
export const unwrapParens = (expression) => {
let candidate = expression;
while (candidate instanceof ParenExpression) {
candidate = candidate.expression;
}
return candidate;
};
export const isBinaryOperator = (expression, operator) => {
const candidate = unwrapParens(expression);
return candidate instanceof BinaryExpression
&& candidate.operator.value.trim().toLowerCase() === operator;
};
export const collectTopLevelAndTerms = (expression) => {
const candidate = unwrapParens(expression);
if (!isBinaryOperator(candidate, "and")) {
return [expression];
}
return [
...collectTopLevelAndTerms(candidate.left),
...collectTopLevelAndTerms(candidate.right)
];
};
export const rebuildWhereWithoutTerms = (query, termsToRemove) => {
if (!query.whereClause || termsToRemove.size === 0) {
return;
}
const remaining = collectTopLevelAndTerms(query.whereClause.condition)
.filter(term => !termsToRemove.has(term));
if (remaining.length === 0) {
query.whereClause = null;
return;
}
let rebuilt = remaining[0];
for (let index = 1; index < remaining.length; index += 1) {
rebuilt = new BinaryExpression(rebuilt, "and", remaining[index]);
}
query.whereClause = new WhereClause(rebuilt);
};
// API output shape review: this helper preserves the existing AST -> SQL -> AST clone path used by callers without changing public result.sql/result.query shapes.
export const cloneValueComponent = (expression, options) => {
return ValueParser.parse(formatSqlComponent(expression, options));
};
export const cloneColumnReference = (reference) => {
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 : null;
return new ColumnReference(namespaces, reference.column.name);
};
export const columnReferenceText = (reference) => {
const namespace = reference.getNamespace();
return namespace ? `${namespace}.${reference.column.name}` : reference.column.name;
};
export const sameColumnReference = (left, right) => {
return identifiersEqual(left.column.name, right.column.name)
&& identifiersEqual(left.getNamespace(), right.getNamespace());
};
export const appendUnique = (items, value) => {
if (!items.includes(value)) {
items.push(value);
}
};
//# sourceMappingURL=PredicateExpressionUtils.js.map