rhombic
Version:
SQL parsing, lineage extraction and manipulation
90 lines • 4.27 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.FilterTreeVisitor = void 0;
const SqlParser_1 = require("../SqlParser");
const FilterTree_1 = require("../FilterTree");
const getImageFromChildren_1 = require("../utils/getImageFromChildren");
const booleanExpression_1 = require("../utils/booleanExpression");
const booleanExpressionValue_1 = require("../utils/booleanExpressionValue");
const Visitor = SqlParser_1.parser.getBaseCstVisitorConstructorWithDefaults();
/**
* Visitor to extract filter tree on the `WHERE` statement
*/
class FilterTreeVisitor extends Visitor {
constructor() {
super(...arguments);
this.tree = [{ type: "operator", closeParentheses: [], openParentheses: [] }];
this.parenthesisCount = 0;
this.parenthesisToClose = [];
}
getOperator(expressionValue) {
if (booleanExpressionValue_1.isBinaryOperation(expressionValue)) {
return expressionValue.BinaryOperator[0].image.toLowerCase();
}
if (booleanExpressionValue_1.isMultivalOperation(expressionValue)) {
return expressionValue.MultivalOperator[0].image.toLowerCase();
}
if (booleanExpressionValue_1.isUnaryOperation(expressionValue) && expressionValue.IsNotNull) {
return expressionValue.IsNotNull[0].image.toLowerCase();
}
if (booleanExpressionValue_1.isUnaryOperation(expressionValue) && expressionValue.IsNull) {
return expressionValue.IsNull[0].image.toLowerCase();
}
return "="; // This is just to make typescript happy, this case is not possible with the actual grammar
}
getValue(expressionValue) {
if (booleanExpressionValue_1.isBinaryOperation(expressionValue)) {
return getImageFromChildren_1.getImageFromChildren(expressionValue.valueExpression[0].children);
}
if (booleanExpressionValue_1.isMultivalOperation(expressionValue)) {
return expressionValue.valueExpression.map(i => getImageFromChildren_1.getImageFromChildren(i.children)).join(", ");
}
return undefined;
}
booleanExpression(ctx) {
if (booleanExpression_1.isParenthesesContext(ctx)) {
// Flag open parenthese
const startOperatorNode = this.tree[this.tree.length - 1];
if (FilterTree_1.isOperator(startOperatorNode)) {
this.parenthesisToClose.push(this.parenthesisCount);
startOperatorNode.openParentheses.unshift(this.parenthesisCount++);
}
// Visit inside
this.booleanExpression(ctx.booleanExpression[0].children);
// Flag close parenthese
const endOperatorNode = this.tree[this.tree.length - 1];
if (FilterTree_1.isOperator(endOperatorNode)) {
endOperatorNode.closeParentheses.push(this.parenthesisToClose.shift() || 0);
}
}
else {
// Add predicate + operator on each value
ctx.booleanExpressionValue.forEach(predicate => {
if (!booleanExpressionValue_1.hasColumnPrimary(predicate.children))
return;
this.tree.push({
type: "predicate",
dimension: predicate.children.columnPrimary[0].children.Identifier.map(i => i.image).join("."),
operator: this.getOperator(predicate.children),
value: this.getValue(predicate.children)
});
this.tree.push({
type: "operator",
openParentheses: [],
closeParentheses: []
});
});
}
// Deal with `AND`/`OR`
if (booleanExpression_1.isAndOrContext(ctx)) {
const lastOperatorNode = this.tree[this.tree.length - 1];
if (FilterTree_1.isOperator(lastOperatorNode)) {
lastOperatorNode.operator = ctx.Or ? "or" : "and";
}
// Visit alternative node
this.booleanExpression(ctx.booleanExpression[ctx.booleanExpression.length - 1].children);
}
}
}
exports.FilterTreeVisitor = FilterTreeVisitor;
//# sourceMappingURL=FilterTreeVisitor.js.map