@react-awesome-query-builder/sql
Version:
User-friendly query builder for React. SQL support
305 lines (304 loc) • 11.8 kB
JavaScript
import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
import _defineProperty from "@babel/runtime/helpers/defineProperty";
import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
/* eslint-disable @typescript-eslint/no-redundant-type-constituents, @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access */
import { SqlPrimitiveTypes } from "./conv";
export var processAst = function processAst(sqlAst, meta) {
var _select$columns;
if (sqlAst.type !== "select") {
meta.errors.push("Expected SELECT, but got ".concat(sqlAst.type));
}
var select = sqlAst;
var pWhere = _processLogic(select.where, meta);
var selectExpr = ((_select$columns = select.columns) !== null && _select$columns !== void 0 ? _select$columns : []).find(function (c) {
return c.type === "expr";
});
var pSelectExpr = _processLogic(selectExpr === null || selectExpr === void 0 ? void 0 : selectExpr.expr, meta);
var hasLogic = select.where || (selectExpr === null || selectExpr === void 0 ? void 0 : selectExpr.expr);
if (!hasLogic) {
meta.errors.push("No logic found in WHERE/SELECT");
}
return {
where: pWhere,
select: pSelectExpr
};
};
var _processLogic = function processLogic(logic, meta) {
var not = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
if (!logic) {
return undefined;
}
var ret;
if (logic.type === "function") {
ret = processFunc(logic, meta, not);
} else if (logic.type === "binary_expr") {
if (["AND", "OR"].includes(logic.operator)) {
ret = processConj(logic, meta, not);
} else {
ret = processBinaryOp(logic, meta, not);
}
} else if (logic.type === "unary_expr") {
if (logic.operator === "NOT") {
var subFilter = logic.expr;
ret = _processLogic(subFilter, meta, !not);
if (ret) {
ret.parentheses = true;
}
} else {
meta.errors.push("Unexpected unary operator ".concat(logic.operator));
}
} else if (logic.type === "expr_list") {
ret = processExprList(logic, meta, not);
} else if (logic.type === "case") {
ret = processCase(logic, meta, not);
} else if (logic.type === "column_ref") {
ret = processField(logic, meta, not);
} else if (logic.type === "interval") {
ret = processInterval(logic, meta, not);
} else if (logic.value !== undefined) {
ret = processValue(logic, meta, not);
} else {
// todo: aggr_func (like COUNT)
meta.errors.push("Unexpected logic type ".concat(logic.type));
}
return ret;
};
var processConj = function processConj(expr, meta) {
var not = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
var parentheses = expr.parentheses;
var conj = expr.operator;
// flatize OR/AND
var childrenChain = [_processLogic(expr.left, meta), _processLogic(expr.right, meta)].filter(function (c) {
return !!c;
});
var children = childrenChain.reduce(function (acc, child) {
var _child$children;
var canFlatize = (child === null || child === void 0 ? void 0 : child.conj) === conj && !child.parentheses && !child.not;
var flat = canFlatize ? (_child$children = child.children) !== null && _child$children !== void 0 ? _child$children : [] : [child];
return [].concat(_toConsumableArray(acc), _toConsumableArray(flat));
}, []);
return {
parentheses: parentheses,
not: not,
conj: conj,
children: children
};
};
var processCase = function processCase(expr, meta) {
var not = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
var parentheses = expr.parentheses;
var children = expr.args.map(function (arg) {
if (!["when", "else"].includes(arg.type)) {
meta.errors.push("Unexpected type ".concat(arg.type, " inside CASE"));
}
return {
cond: arg.type === "when" ? _processLogic(arg.cond, meta) : undefined,
result: _processLogic(arg.result, meta)
};
}).filter(function (a) {
return !!a;
});
return {
parentheses: parentheses,
children: children,
_type: "case",
not: not
};
};
var processBinaryOp = function processBinaryOp(expr, meta) {
var not = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
var parentheses = expr.parentheses;
var operator = expr.operator;
var children = [_processLogic(expr.left, meta), _processLogic(expr.right, meta)].filter(function (c) {
return !!c;
});
if (operator === "BETWEEN" || operator === "NOT BETWEEN") {
var _children$1$children;
// flatize BETWEEN
children = [children[0]].concat(_toConsumableArray((_children$1$children = children[1].children) !== null && _children$1$children !== void 0 ? _children$1$children : [])).filter(function (c) {
return !!c;
});
}
return {
parentheses: parentheses,
not: not,
children: children,
operator: operator
};
};
var getExprValue = function getExprValue(expr, meta) {
var not = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
var value = expr.value;
if (expr.type === "boolean" && not) {
value = !value;
}
// todo: date literals?
return value;
};
var getExprStringValue = function getExprStringValue(expr, meta) {
var not = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
var v = getExprValue(expr, meta, not);
return String(v);
};
var processExprList = function processExprList(expr, meta) {
var not = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
var children = expr.value.map(function (ev) {
return _processLogic(ev, meta, false);
}).filter(function (ev) {
return !!ev;
});
var valueTypes = children.map(function (ch) {
return ch.valueType;
}).filter(function (ev) {
return !!ev;
});
var uniqValueTypes = Array.from(new Set(valueTypes));
var oneValueType = valueTypes.length === children.length && uniqValueTypes.length === 1 ? uniqValueTypes[0] : undefined;
var values;
if (oneValueType && SqlPrimitiveTypes[oneValueType]) {
// it's list of primitive values
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
values = children.map(function (ch) {
return ch.value;
});
}
return {
children: children,
not: not,
_type: "expr_list",
oneValueType: oneValueType,
values: values
};
};
var processInterval = function processInterval(expr, meta) {
var _processValue;
var not = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
return _objectSpread(_objectSpread({
_type: "interval"
}, (_processValue = processValue(expr.expr, meta)) !== null && _processValue !== void 0 ? _processValue : {}), {}, {
unit: expr.unit
});
};
var processValue = function processValue(expr, meta) {
var not = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
var valueType = expr.type;
var value = getExprValue(expr, meta, not);
return {
valueType: valueType,
value: value
};
};
var processField = function processField(expr, meta) {
var _expr$table;
var not = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
if (expr.type === "expr") {
return undefined;
}
var parentheses = expr.parentheses;
var field = typeof expr.column === "string" ? expr.column : getExprStringValue(expr.column.expr, meta, not);
var table = (_expr$table = expr.table) !== null && _expr$table !== void 0 ? _expr$table : undefined;
if (field === "") {
// fix for empty string
return {
valueType: "single_quote_string",
value: ""
};
} else {
return {
parentheses: parentheses,
field: field,
table: table
};
}
};
var flatizeTernary = function flatizeTernary(children, meta) {
var flat = [];
function _processTernaryChildren(tern) {
var _tern = _slicedToArray(tern, 3),
cond = _tern[0],
if_val = _tern[1],
else_val = _tern[2];
if (if_val.func === "IF") {
meta.errors.push("Unexpected IF inside IF");
}
flat.push([cond, if_val]);
if ((else_val === null || else_val === void 0 ? void 0 : else_val.func) === "IF") {
_processTernaryChildren(else_val === null || else_val === void 0 ? void 0 : else_val.children);
} else {
flat.push([undefined, else_val]);
}
}
_processTernaryChildren(children);
return flat;
};
var processFunc = function processFunc(expr, meta) {
var not = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
var nameType = expr.name.name[0].type;
var firstName = expr.name.name[0].value;
var getArgs = function getArgs(useNot) {
if (expr.args) {
if (expr.args.type === "expr_list") {
return expr.args.value.map(function (arg) {
return _processLogic(arg, meta, useNot ? not : undefined);
}).filter(function (a) {
return !!a;
});
} else {
meta.errors.push("Unexpected args type for func (".concat(JSON.stringify(expr.name.name), "): ").concat(JSON.stringify(expr.args.type)));
}
}
return [];
};
var ret;
if (nameType === "default" && firstName === "NOT") {
var _expr$args;
if (((_expr$args = expr.args) === null || _expr$args === void 0 ? void 0 : _expr$args.value.length) === 1) {
var args = getArgs(false);
ret = args[0];
// ret.parentheses = true;
ret.not = !ret.not;
if (not) {
ret.not = !ret.not;
}
} else {
var _expr$args2;
meta.errors.push("Unexpected args for func NOT: ".concat(JSON.stringify((_expr$args2 = expr.args) === null || _expr$args2 === void 0 ? void 0 : _expr$args2.value)));
}
} else if (nameType === "default" && firstName === "IFNULL") {
var _args = getArgs(true);
// const defaultValue = args[1].value;
ret = _args[0];
} else if (nameType === "default") {
var flatizeArgs = firstName === "IF";
var _args2 = getArgs(false);
ret = {
func: firstName,
children: _args2,
not: not
};
if (flatizeArgs) {
ret.ternaryChildren = flatizeTernary(_args2, meta);
}
return ret;
} else {
meta.errors.push("Unexpected function name ".concat(JSON.stringify(expr.name.name)));
}
return ret;
};
export var getLogicDescr = function getLogicDescr(logic) {
if ((logic === null || logic === void 0 ? void 0 : logic._type) === "case") {
// const cases = logic.children as {cond: OutLogic, result: OutLogic}[];
return "CASE";
} else if ((logic === null || logic === void 0 ? void 0 : logic._type) === "interval") {
return "INTERVAL ".concat(JSON.stringify(logic.value), " ").concat(logic.unit);
} else if (logic !== null && logic !== void 0 && logic.func) {
return "".concat(logic.func, "()");
} else if (logic !== null && logic !== void 0 && logic.operator) {
return "operator ".concat(logic.operator);
} else if ((logic === null || logic === void 0 ? void 0 : logic._type) === "expr_list") {
return JSON.stringify(logic.values);
}
return JSON.stringify(logic);
};