@jakub.knejzlik/ts-query
Version:
TypeScript implementation of SQL builder
247 lines (246 loc) • 8.82 kB
JavaScript
"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;