sedk-mysql
Version:
Simple SQL builder and validator for MySQL
206 lines • 10.3 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Expression = exports.ExpressionType = void 0;
const operators_1 = require("../operators");
const binder_1 = require("../binder");
const SelectItemInfo_1 = require("../SelectItemInfo");
const database_1 = require("../database");
const errors_1 = require("../errors");
const Operand_1 = require("./Operand");
const types_1 = require("./types");
const Condition_1 = require("./Condition");
var ExpressionType;
(function (ExpressionType) {
ExpressionType[ExpressionType["NOT_EXIST"] = 0] = "NOT_EXIST";
ExpressionType[ExpressionType["NULL"] = 1] = "NULL";
ExpressionType[ExpressionType["BOOLEAN"] = 2] = "BOOLEAN";
ExpressionType[ExpressionType["NUMBER"] = 3] = "NUMBER";
ExpressionType[ExpressionType["TEXT"] = 4] = "TEXT";
ExpressionType[ExpressionType["DATE"] = 5] = "DATE";
// TODO: make this type more specific like array of number, array of text, etc.
ExpressionType[ExpressionType["ARRAY"] = 6] = "ARRAY";
})(ExpressionType || (exports.ExpressionType = ExpressionType = {}));
class Expression {
constructor(con) {
this.leftOperand = new Operand_1.Operand(con.left, con.notLeft);
this.operator = con.operator;
this.rightOperand = con.right !== undefined
? new Operand_1.Operand(con.right, con.notRight)
: undefined;
if (this.rightOperand === undefined || this.rightOperand.type === ExpressionType.NOT_EXIST) {
this.type = this.leftOperand.type;
}
else if (con.operator !== undefined) {
this.type = Expression.getResultExpressionType(this.leftOperand, con.operator, this.rightOperand);
}
else {
throw new Error('Error while calculate Expression Type, failed to create object Expression');
}
}
getStmt(data, artifacts, binderStore) {
if (this.operator !== undefined && this.rightOperand !== undefined) {
return `(${this.leftOperand.getStmt(data, artifacts, binderStore)} ${this.operator.toString()} ${this.rightOperand.getStmt(data, artifacts, binderStore)})`;
}
return this.leftOperand.getStmt(data, artifacts, binderStore);
}
as(alias) {
return new SelectItemInfo_1.SelectItemInfo(this, alias);
}
eq(value) {
return new Condition_1.Condition({
leftExpression: this,
operator: operators_1.ComparisonOperator.Equal,
rightExpression: Expression.getSimpleExp(value),
});
}
eq$(value) {
const binder = new binder_1.Binder(value);
return new Condition_1.Condition({
leftExpression: this,
operator: operators_1.ComparisonOperator.Equal,
rightExpression: Expression.getSimpleExp(binder),
});
}
ne(value) {
return new Condition_1.Condition({
leftExpression: this,
operator: operators_1.ComparisonOperator.NotEqual,
rightExpression: Expression.getSimpleExp(value),
});
}
ne$(value) {
const binder = new binder_1.Binder(value);
return new Condition_1.Condition({
leftExpression: this,
operator: operators_1.ComparisonOperator.NotEqual,
rightExpression: Expression.getSimpleExp(binder),
});
}
isEq(value) {
const qualifier = value === null ? operators_1.NullOperator.Is : operators_1.ComparisonOperator.Equal;
return new Condition_1.Condition({
leftExpression: this,
operator: qualifier,
rightExpression: Expression.getSimpleExp(value),
});
}
isEq$(value) {
const qualifier = value === null ? operators_1.NullOperator.Is : operators_1.ComparisonOperator.Equal;
const binder = new binder_1.Binder(value);
return new Condition_1.Condition({
leftExpression: this,
operator: qualifier,
rightExpression: Expression.getSimpleExp(binder),
});
}
isNe(value) {
const qualifier = value === null ? operators_1.NullOperator.IsNot : operators_1.ComparisonOperator.NotEqual;
return new Condition_1.Condition({
leftExpression: this,
operator: qualifier,
rightExpression: Expression.getSimpleExp(value),
});
}
isNe$(value) {
const qualifier = value === null ? operators_1.NullOperator.IsNot : operators_1.ComparisonOperator.NotEqual;
const binder = new binder_1.Binder(value);
return new Condition_1.Condition({
leftExpression: this,
operator: qualifier,
rightExpression: Expression.getSimpleExp(binder),
});
}
getColumns() {
var _a;
const columns = [];
const left = this.leftOperand.value;
if (left instanceof database_1.Column)
columns.push(left);
else if (left instanceof Expression)
columns.push(...left.getColumns());
const right = (_a = this.rightOperand) === null || _a === void 0 ? void 0 : _a.value;
if (right instanceof database_1.Column)
columns.push(right);
else if (right instanceof Expression)
columns.push(...right.getColumns());
return columns;
}
static getSimpleExp(left, notLeft = false) {
return new Expression({ left, notLeft, notRight: false });
}
static getComplexExp(left, operator, right) {
return new Expression({ left, operator, right, notLeft: false, notRight: false });
}
static getResultExpressionType(left, operator, right) {
if ((0, operators_1.isArithmeticOperator)(operator)) {
if ((left.type === ExpressionType.NULL && right.type === ExpressionType.NUMBER)
|| (left.type === ExpressionType.NUMBER && right.type === ExpressionType.NULL))
return ExpressionType.NULL;
if (left.type === ExpressionType.NUMBER && right.type === ExpressionType.NUMBER)
return ExpressionType.NUMBER;
if (((left.type === ExpressionType.TEXT && (0, types_1.isTextNumber)(left.value)) && right.type === ExpressionType.NUMBER)
|| (left.type === ExpressionType.NUMBER && (right.type === ExpressionType.TEXT && (0, types_1.isTextNumber)(right.value))))
return ExpressionType.NUMBER;
Expression.throwInvalidTypeError(left.type, operator, right.type);
}
if ((0, operators_1.isBitwiseOperator)(operator)) {
if (left.type === ExpressionType.NUMBER && right.type === ExpressionType.NUMBER)
return ExpressionType.NUMBER;
if (left.type === ExpressionType.NUMBER && (right.type === ExpressionType.TEXT && (0, types_1.isTextNumber)(right.value))
|| right.type === ExpressionType.NUMBER && (left.type === ExpressionType.TEXT && (0, types_1.isTextNumber)(left.value)))
return ExpressionType.NUMBER;
Expression.throwInvalidTypeError(left.type, operator, right.type);
}
if ((0, operators_1.isComparisonOperator)(operator)) {
if (Expression.isListComparisonOperator(operator)) {
// TODO: check the values of the right same type of the left
if (right.type === ExpressionType.ARRAY)
return ExpressionType.BOOLEAN;
Expression.throwInvalidTypeError(left.type, operator, right.type);
}
else {
if (left.type === ExpressionType.NULL || right.type === ExpressionType.NULL)
return ExpressionType.NULL;
if (left.type === right.type)
return ExpressionType.BOOLEAN;
if (left.type === ExpressionType.BOOLEAN && (right.type === ExpressionType.TEXT && (0, types_1.isTextBoolean)(right.value))
|| right.type === ExpressionType.BOOLEAN && (left.type === ExpressionType.TEXT && (0, types_1.isTextBoolean)(left.value)))
return ExpressionType.BOOLEAN;
if (left.type === ExpressionType.NUMBER && (right.type === ExpressionType.TEXT && (0, types_1.isTextNumber)(right.value))
|| right.type === ExpressionType.NUMBER && (left.type === ExpressionType.TEXT && (0, types_1.isTextNumber)(left.value)))
return ExpressionType.BOOLEAN;
}
Expression.throwInvalidTypeError(left.type, operator, right.type);
}
if ((0, operators_1.isNullOperator)(operator)) {
if (right.type === ExpressionType.NULL)
return ExpressionType.BOOLEAN;
if (right.type === ExpressionType.BOOLEAN) {
if (left.type === ExpressionType.NULL || ExpressionType.BOOLEAN)
return ExpressionType.BOOLEAN;
if (left.type === ExpressionType.TEXT && (0, types_1.isTextBoolean)(left.value))
return ExpressionType.BOOLEAN;
}
Expression.throwInvalidTypeError(left.type, operator, right.type);
}
if ((0, operators_1.isTextOperator)(operator)) {
if (left.type === ExpressionType.NULL || right.type === ExpressionType.NULL)
return ExpressionType.NULL;
if (left.type === ExpressionType.TEXT
&& (right.type === ExpressionType.TEXT || right.type === ExpressionType.NUMBER))
return ExpressionType.TEXT;
if (left.type === ExpressionType.NUMBER && right.type === ExpressionType.TEXT)
return ExpressionType.TEXT;
Expression.throwInvalidTypeError(left.type, operator, right.type);
}
throw new Error(`Function "getResultExpressionType" does not support operator: "${operator}"`);
}
static throwInvalidTypeError(leftType, operator, rightType) {
throw new errors_1.InvalidExpressionError(`You can not have "${ExpressionType[leftType]}" and "${ExpressionType[rightType]}" with operator "${operator}"`);
}
static isListComparisonOperator(operator) {
return [operators_1.ComparisonOperator.In, operators_1.ComparisonOperator.NotIn].includes(operator);
}
}
exports.Expression = Expression;
//# sourceMappingURL=Expression.js.map