UNPKG

@jakub.knejzlik/ts-query

Version:

TypeScript implementation of SQL builder

247 lines (246 loc) 8.82 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.UpdateMutation = exports.InsertMutation = exports.DeleteMutation = exports.MutationBase = void 0; const Condition_1 = require("./Condition"); const Expression_1 = require("./Expression"); const Query_1 = require("./Query"); const mysql_1 = require("./flavors/mysql"); const interfaces_1 = require("./interfaces"); class MutationBase { constructor(table, alias) { this._table = new Query_1.Table(table, alias); } getTableNames() { return [this._table.getTableName()]; } clone() { const clone = new this.constructor(); clone._table = this._table.clone(); return clone; } static deserialize(json) { const parsed = JSON.parse(json); switch (parsed.type) { case interfaces_1.OperationType.DELETE: return DeleteMutation.fromJSON(parsed); case interfaces_1.OperationType.INSERT: return InsertMutation.fromJSON(parsed); case interfaces_1.OperationType.UPDATE: return UpdateMutation.fromJSON(parsed); default: throw new Error("Unknown mutation type"); } } } exports.MutationBase = MutationBase; class DeleteMutation extends MutationBase { constructor() { super(...arguments); this._where = []; } getOperationType() { return interfaces_1.MetadataOperationType.DELETE; } clone() { const clone = super.clone(); clone._where = [...this._where]; return clone; } where(condition) { const clone = this.clone(); clone._where.push(condition); return clone; } toSQL(flavor = new mysql_1.MySQLFlavor(), options, transformed = false) { if ((options === null || options === void 0 ? void 0 : options.transformDeleteMutation) && !transformed) { return options.transformDeleteMutation(this).toSQL(flavor, options, true); } let sql = `DELETE FROM ${this._table.toSQL(flavor)}`; if (this._where.length) { sql += ` WHERE ${this._where .map((condition) => condition.toSQL(flavor)) .join(" AND ")}`; } return sql; } serialize() { return JSON.stringify(this.toJSON()); } toJSON() { return { type: interfaces_1.OperationType.DELETE, table: this._table.toJSON(), where: this._where.map((condition) => condition.toJSON()), }; } static fromJSON({ table, where }) { const deleteMutation = new DeleteMutation(table.source, table.alias); deleteMutation._where = where.map((condition) => Condition_1.Condition.fromJSON(condition)); return deleteMutation; } } exports.DeleteMutation = DeleteMutation; class InsertMutation extends MutationBase { getOperationType() { return interfaces_1.MetadataOperationType.INSERT; } clone() { const clone = super.clone(); clone._values = this._values && [...this._values]; return clone; } removeAllValues() { const clone = this.clone(); clone._values = undefined; return clone; } allValues() { return this._values; } values(values) { var _a; const clone = this.clone(); if (clone._selectWithColumns) throw new Error("select already set"); clone._values = [...((_a = clone._values) !== null && _a !== void 0 ? _a : []), ...values]; return clone; } select(query, columns) { const clone = this.clone(); if (clone._values) throw new Error("values already set"); clone._selectWithColumns = [query, columns]; return clone; } toSQL(flavor = new mysql_1.MySQLFlavor(), options, transformed = false) { if ((options === null || options === void 0 ? void 0 : options.transformInsertMutation) && !transformed) { return options.transformInsertMutation(this).toSQL(flavor, options, true); } if (this._values) { return `INSERT INTO ${this._table.toSQL(flavor)} (${Object.keys(this._values[0]) .map((k) => flavor.escapeColumn(k)) .join(", ")}) VALUES ${this._values .map((value) => `(${Object.values(value) .map((v) => flavor.escapeValue(v)) .join(", ")})`) .join(", ")}`; } if (this._selectWithColumns) { const [query, columns] = this._selectWithColumns; return `INSERT INTO ${this._table.toSQL(flavor)}${columns ? ` (${columns.map((k) => flavor.escapeColumn(k)).join(", ")})` : ""} ${query.toSQL(flavor)}`; } throw new Error("values or select must be set for insert query"); } serialize() { return JSON.stringify(this.toJSON()); } toJSON() { return { type: interfaces_1.OperationType.INSERT, table: this._table.toJSON(), values: this._values, select: this._selectWithColumns && [ this._selectWithColumns[0].toJSON(), this._selectWithColumns[1], ], }; } static fromJSON({ table, values, select }) { const insertMutation = new InsertMutation(table.source, table.alias); insertMutation._values = values; if (select) { insertMutation._selectWithColumns = [ Query_1.SelectQuery.fromJSON(select[0]), select[1], ]; } return insertMutation; } } exports.InsertMutation = InsertMutation; class UpdateMutation extends MutationBase { constructor() { super(...arguments); this._values = {}; this._where = []; } getOperationType() { return interfaces_1.MetadataOperationType.UPDATE; } clone() { const clone = super.clone(); clone._values = Object.assign({}, this._values); clone._where = [...this._where]; return clone; } set(values) { const clone = this.clone(); const _values = {}; for (const [key, value] of Object.entries(values)) { if (value === null) { _values[key] = Query_1.Q.null(); continue; } if (value instanceof Query_1.SelectQuery) { _values[key] = value; continue; } _values[key] = value instanceof Expression_1.Expression ? value : Query_1.Q.exprValue(value); } clone._values = Object.assign(Object.assign({}, clone._values), _values); return clone; } where(condition) { const clone = this.clone(); clone._where.push(condition); return clone; } toSQL(flavor = new mysql_1.MySQLFlavor(), options, transformed = false) { if ((options === null || options === void 0 ? void 0 : options.transformUpdateMutation) && !transformed) { return options.transformUpdateMutation(this).toSQL(flavor, options, true); } if (!this._values) throw new Error("No values to update"); let sql = `UPDATE ${this._table.toSQL(flavor)} SET ${Object.entries(this._values) .map(([key, value]) => { return `${flavor.escapeColumn(key)} = ${value instanceof Query_1.SelectQuery ? `(${value.toSQL(flavor)})` : value.toSQL(flavor)}`; }) .join(", ")}`; if (this._where.length) { sql += ` WHERE ${this._where .map((condition) => condition.toSQL(flavor)) .join(" AND ")}`; } return sql; } serialize() { return JSON.stringify(this.toJSON()); } toJSON() { const _values = {}; for (const [key, value] of Object.entries(this._values)) { _values[key] = value.serialize(); } return { type: interfaces_1.OperationType.UPDATE, table: this._table.toJSON(), values: _values, where: this._where.map((condition) => condition.toJSON()), }; } static fromJSON({ table, values, where }) { const updateMutation = new UpdateMutation(table.source, table.alias); const _values = {}; for (const [key, value] of Object.entries(values)) { _values[key] = Query_1.Q.deserializeRaw(value); } updateMutation._values = _values; updateMutation._where = where.map((condition) => Condition_1.Condition.fromJSON(condition)); return updateMutation; } } exports.UpdateMutation = UpdateMutation;