UNPKG

@jakub.knejzlik/ts-query

Version:

TypeScript implementation of SQL builder

295 lines (294 loc) 10.8 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Cond = exports.Conditions = exports.Condition = void 0; const Expression_1 = require("./Expression"); const Query_1 = require("./Query"); class Condition { toSQL(flavor) { throw new Error("Method not implemented."); } toJSON() { throw new Error("Method not implemented."); } serialize() { return JSON.stringify(this.toJSON()); } static fromJSON(json) { switch (json.type) { case "BinaryCondition": return BinaryCondition.fromJSON(json); case "LogicalCondition": return LogicalCondition.fromJSON(json); case "BetweenCondition": return BetweenCondition.fromJSON(json); case "InCondition": return InCondition.fromJSON(json); case "NotInCondition": return NotInCondition.fromJSON(json); case "NullCondition": return NullCondition.fromJSON(json); case "LikeCondition": return LikeCondition.fromJSON(json); case "ColumnComparisonCondition": return ColumnComparisonCondition.fromJSON(json); default: throw new Error(`Unknown condition type: ${json.type} (${JSON.stringify(json)})`); } } static deserialize(value) { if (typeof value === "string") { try { return Condition.fromJSON(JSON.parse(value)); } catch (_a) { return null; } } return value; } } exports.Condition = Condition; class BinaryCondition extends Condition { constructor(key, value, operator) { super(); this.key = Query_1.Q.expr(key); this.value = Query_1.Q.value(value); this.operator = operator; } toSQL(flavor) { return `${this.key.toSQL(flavor)} ${this.operator} ${this.value.toSQL(flavor)}`; } // serialization toJSON() { return { type: "BinaryCondition", key: this.key.serialize(), value: this.value.serialize(), operator: this.operator, }; } static fromJSON(json) { return new BinaryCondition(Expression_1.ExpressionBase.deserialize(json.key), Expression_1.ExpressionBase.deserializeValue(json.value), json.operator); } } class LogicalCondition extends Condition { constructor(conditions, operator) { super(); this.conditions = conditions; this.operator = operator; } toSQL(flavor) { return `(${this.conditions .map((c) => c.toSQL(flavor)) .join(` ${this.operator} `)})`; } // serialization toJSON() { return { type: "LogicalCondition", conditions: this.conditions.map((condition) => condition.toJSON()), operator: this.operator, }; } static fromJSON(json) { const conditions = json.conditions.map(Condition.fromJSON); return new LogicalCondition(conditions, json.operator); } } class BetweenCondition extends Condition { constructor(key, from, to) { super(); this.key = Query_1.Q.expr(key); this.from = Query_1.Q.expr(from); this.to = Query_1.Q.expr(to); } toSQL(flavor) { return `${this.key.toSQL(flavor)} BETWEEN ${this.from.toSQL(flavor)} AND ${this.to.toSQL(flavor)}`; } // serialization toJSON() { return { type: "BetweenCondition", key: this.key.serialize(), from: this.from.serialize(), to: this.to.serialize(), }; } static fromJSON(json) { return new BetweenCondition(Expression_1.ExpressionBase.deserialize(json.key), Expression_1.ExpressionBase.deserializeValue(json.from), Expression_1.ExpressionBase.deserializeValue(json.to)); } } class InCondition extends Condition { constructor(key, values) { super(); this.key = Query_1.Q.expr(key); this.values = values.map((v) => Query_1.Q.exprValue(v)); } toSQL(flavor) { return `${this.key.toSQL(flavor)} IN (${this.values .map((v) => v.toSQL(flavor)) .join(", ")})`; } // serialization toJSON() { return { type: "InCondition", key: this.key.serialize(), values: this.values.map((v) => v.serialize()), }; } static fromJSON(json) { return new InCondition(Expression_1.ExpressionBase.deserialize(json.key), json.values.map(Expression_1.ExpressionBase.deserializeValue)); } } class NotInCondition extends Condition { constructor(key, values) { super(); this.key = Query_1.Q.expr(key); this.values = values.map((v) => Query_1.Q.expr(v)); } toSQL(flavor) { return `${this.key.toSQL(flavor)} NOT IN (${this.values .map((v) => v.toSQL(flavor)) .join(", ")})`; } // serialization toJSON() { return { type: "NotInCondition", key: this.key.serialize(), values: this.values.map((v) => v.serialize()), }; } static fromJSON(json) { return new NotInCondition(Expression_1.ExpressionBase.deserialize(json.key), json.values.map(Expression_1.ExpressionBase.deserializeValue)); } } class NullCondition extends Condition { constructor(key, isNull) { super(); this.key = Query_1.Q.expr(key); this.isNull = isNull; } toSQL(flavor) { return `${this.key.toSQL(flavor)} IS ${this.isNull ? "" : "NOT "}NULL`; } // serialization toJSON() { return { type: "NullCondition", key: this.key.serialize(), isNull: this.isNull, }; } static fromJSON(json) { return new NullCondition(Expression_1.ExpressionBase.deserialize(json.key), json.isNull); } } class LikeCondition extends Condition { constructor(key, pattern, isLike) { super(); this.key = Query_1.Q.expr(key); this.pattern = pattern; this.isLike = isLike; } toSQL(flavor) { return `${this.key.toSQL(flavor)} ${this.isLike ? "" : "NOT "}LIKE \'${this.pattern}\'`; } // serialization toJSON() { return { type: "LikeCondition", key: this.key.serialize(), pattern: this.pattern, isLike: this.isLike, }; } static fromJSON(json) { return new LikeCondition(Expression_1.ExpressionBase.deserialize(json.key), json.pattern, json.isLike); } } class ColumnComparisonCondition extends Condition { constructor(leftKey, rightKey, operator) { super(); this.leftKey = Query_1.Q.expr(leftKey); this.rightKey = Query_1.Q.expr(rightKey); this.operator = operator; } toSQL(flavor) { return `${this.leftKey.toSQL(flavor)} ${this.operator} ${this.rightKey.toSQL(flavor)}`; } // serialization toJSON() { return { type: "ColumnComparisonCondition", leftKey: this.leftKey.serialize(), rightKey: this.rightKey.serialize(), operator: this.operator, }; } static fromJSON(json) { return new ColumnComparisonCondition(Expression_1.ExpressionBase.deserialize(json.leftKey), Expression_1.ExpressionBase.deserialize(json.rightKey), json.operator); } } exports.Conditions = { fromString: (column, value) => { const str = `${value}`; if (str.indexOf(">=") === 0) { return exports.Conditions.greaterThanOrEqual(column, str.substring(2)); } if (str.indexOf("<=") === 0) { return exports.Conditions.lessThanOrEqual(column, str.substring(2)); } if (str.indexOf(">") === 0) { return exports.Conditions.greaterThan(column, str.substring(1)); } if (str.indexOf("<") === 0) { return exports.Conditions.lessThan(column, str.substring(1)); } if (str.indexOf("~") === 0) { return exports.Conditions.or([ exports.Conditions.like(column, `${str.substring(1)}%`), exports.Conditions.like(column, `% ${str.substring(1)}%`), ]); } if (str.indexOf("!~") === 0) { return exports.Conditions.and([ exports.Conditions.notLike(column, `${str.substring(2)}%`), exports.Conditions.notLike(column, `% ${str.substring(2)}%`), ]); } if (str.indexOf("!") === 0) { return exports.Conditions.notEqual(column, `${str.substring(1)}%`); } return exports.Conditions.equal(column, str); }, equal: (key, value) => new BinaryCondition(key, value, "="), notEqual: (key, value) => new BinaryCondition(key, value, "!="), greaterThan: (key, value) => new BinaryCondition(key, value, ">"), lessThan: (key, value) => new BinaryCondition(key, value, "<"), greaterThanOrEqual: (key, value) => new BinaryCondition(key, value, ">="), lessThanOrEqual: (key, value) => new BinaryCondition(key, value, "<="), between: (key, values) => new BetweenCondition(key, Query_1.Q.exprValue(values[0]), Query_1.Q.exprValue(values[1])), in: (key, values) => values && values.length > 0 ? new InCondition(key, values) : null, notIn: (key, values) => new NotInCondition(key, values), and: (conditions) => { const _c = (conditions || []).filter((c) => c !== null); return _c.length > 0 ? new LogicalCondition(_c, "AND") : null; }, or: (conditions) => { const _c = (conditions || []).filter((c) => c !== null); return _c.length > 0 ? new LogicalCondition(_c, "OR") : null; }, null: (key) => new NullCondition(key, true), notNull: (key) => new NullCondition(key, false), like: (key, pattern) => new LikeCondition(key, pattern, true), notLike: (key, pattern) => new LikeCondition(key, pattern, false), columnEqual: (leftKey, rightKey) => new ColumnComparisonCondition(leftKey, rightKey, "="), columnNotEqual: (leftKey, rightKey) => new ColumnComparisonCondition(leftKey, rightKey, "!="), columnGreaterThan: (leftKey, rightKey) => new ColumnComparisonCondition(leftKey, rightKey, ">"), columnLessThan: (leftKey, rightKey) => new ColumnComparisonCondition(leftKey, rightKey, "<"), columnGreaterThanOrEqual: (leftKey, rightKey) => new ColumnComparisonCondition(leftKey, rightKey, ">="), columnLessThanOrEqual: (leftKey, rightKey) => new ColumnComparisonCondition(leftKey, rightKey, "<="), }; exports.Cond = exports.Conditions;