@sqb/builder
Version:
Extensible multi-dialect SQL query builder written with TypeScript
298 lines (297 loc) • 8.89 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.SelectQuery = void 0;
const putil_varhelpers_1 = require("putil-varhelpers");
const enums_js_1 = require("../enums.js");
const helpers_js_1 = require("../helpers.js");
const field_expression_js_1 = require("../sql-objects/field-expression.js");
const group_column_js_1 = require("../sql-objects/group-column.js");
const op_and_js_1 = require("../sql-objects/operators/op-and.js");
const order_column_js_1 = require("../sql-objects/order-column.js");
const table_name_js_1 = require("../sql-objects/table-name.js");
const typeguards_js_1 = require("../typeguards.js");
const query_js_1 = require("./query.js");
class SelectQuery extends query_js_1.Query {
_tables;
_columns;
_joins;
_where;
_groupBy;
_orderBy;
_limit;
_offset;
_alias;
_distinct;
constructor(...column) {
super();
if (column.length)
this.addColumn(...column);
}
get _type() {
return enums_js_1.SerializationType.SELECT_QUERY;
}
/**
* Adds columns to query.
*/
addColumn(...column) {
const self = this;
this._columns = this._columns || [];
for (const arg of column) {
if (!arg)
continue;
if (Array.isArray(arg))
self.addColumn(...arg);
else
this._columns.push((0, typeguards_js_1.isSerializable)(arg) ? arg : new field_expression_js_1.FieldExpression(arg));
}
return this;
}
/**
* Defines "from" part of query.
*/
from(...table) {
this._tables = [];
for (const arg of table) {
if (!arg)
continue;
this._tables.push(typeof arg === 'string' ? new table_name_js_1.TableName(arg) : arg);
}
return this;
}
/**
* Adds "join" statements to query
*/
join(...join) {
this._joins = this._joins || [];
for (const arg of join) {
if (!arg)
continue;
if (!(0, typeguards_js_1.isJoinStatement)(arg))
throw new TypeError('Join statement required');
this._joins.push(arg);
}
return this;
}
/**
* Defines "where" part of query
*/
where(...condition) {
this._where = this._where || new op_and_js_1.OpAnd();
this._where.add(...condition);
return this;
}
/**
* Defines "where" part of query
*/
groupBy(...field) {
this._groupBy = this._groupBy || [];
for (const arg of field) {
if (!arg)
continue;
this._groupBy.push(typeof arg === 'string' ? new group_column_js_1.GroupColumn(arg) : arg);
}
return this;
}
/**
* Defines "order by" part of query.
*/
orderBy(...field) {
this._orderBy = this._orderBy || [];
for (const arg of field) {
if (!arg)
continue;
this._orderBy.push(typeof arg === 'string' ? new order_column_js_1.OrderColumn(arg) : arg);
}
return this;
}
/**
* Sets alias for sub-select queries
*/
as(alias) {
this._alias = alias;
return this;
}
/**
* Sets limit for query
*/
limit(limit) {
this._limit = (0, putil_varhelpers_1.coerceToInt)(limit);
return this;
}
/**
* Sets offset for query
*/
offset(offset) {
this._offset = (0, putil_varhelpers_1.coerceToInt)(offset);
return this;
}
/**
* Enables distinct mode
*/
distinct() {
this._distinct = true;
return this;
}
onFetch(listener) {
this.on('fetch', listener);
return this;
}
onceFetch(listener) {
this.once('fetch', listener);
return this;
}
/**
* Performs serialization
*/
_serialize(ctx) {
const o = {
columns: this.__serializeSelectColumns(ctx),
from: this.__serializeFrom(ctx),
join: this.__serializeJoins(ctx),
where: this.__serializeWhere(ctx),
groupBy: this.__serializeGroupColumns(ctx),
orderBy: this.__serializeOrderColumns(ctx),
limit: this._limit,
offset: this._offset,
};
return ctx.serialize(this._type, o, () => {
let out = 'select';
if (this._distinct)
out += ' distinct';
// columns part
/* istanbul ignore else */
if (o.columns) {
out +=
o.columns.indexOf('\n') >= 0
? '\n\t' + o.columns + '\b'
: ' ' + o.columns;
}
// from part
if (o.from) {
out +=
(o.columns.length > 60 || o.columns.indexOf('\n') >= 0 ? '\n' : ' ') +
o.from;
}
// join part
if (o.join)
out += '\n' + o.join;
// where part
if (o.where)
out += '\n' + o.where;
// group by part
if (o.groupBy)
out += '\n' + o.groupBy;
// order by part
if (o.orderBy)
out += '\n' + o.orderBy;
return out;
});
}
/**
*
*/
__serializeSelectColumns(ctx) {
const arr = [];
if (this._columns) {
for (const t of this._columns) {
const s = ctx.anyToSQL(t);
// t._serialize(ctx);
if (s) {
if (t instanceof SelectQuery) {
if (!t._alias)
throw new TypeError('Alias required for sub-select in columns');
arr.push(s + ' ' + t._alias);
}
else
arr.push(s);
}
}
}
return ctx.serialize(enums_js_1.SerializationType.SELECT_QUERY_COLUMNS, arr, () => (0, helpers_js_1.printArray)(arr) || '*');
}
/**
*
*/
__serializeFrom(ctx) {
const arr = [];
if (this._tables) {
for (const t of this._tables) {
const s = t._serialize(ctx);
/* istanbul ignore else */
if (s) {
if (t instanceof SelectQuery) {
if (!t._alias)
throw new TypeError('Alias required for sub-select in "from"');
arr.push('\n\t(' + s + ') ' + t._alias);
}
else
arr.push(s);
}
}
}
return ctx.serialize(enums_js_1.SerializationType.SELECT_QUERY_FROM, arr, () => {
const s = arr.join(',');
return s ? 'from' + (s.substring(0, 1) !== '\n' ? ' ' : '') + s : '';
});
}
/**
*
*/
__serializeJoins(ctx) {
const arr = [];
if (this._joins) {
for (const t of this._joins) {
const s = t._serialize(ctx);
/* istanbul ignore else */
if (s)
arr.push(s);
}
}
return ctx.serialize(enums_js_1.SerializationType.SELECT_QUERY_JOIN, arr, () => arr.join('\n'));
}
/**
*
*/
__serializeWhere(ctx) {
if (!this._where)
return '';
const s = this._where._serialize(ctx);
return ctx.serialize(enums_js_1.SerializationType.CONDITIONS_BLOCK, s, () =>
/* istanbul ignore next */
s ? 'where ' + s : '');
}
/**
*
*/
__serializeGroupColumns(ctx) {
const arr = [];
if (this._groupBy) {
for (const t of this._groupBy) {
const s = t._serialize(ctx);
/* istanbul ignore else */
if (s)
arr.push(s);
}
}
return ctx.serialize(enums_js_1.SerializationType.SELECT_QUERY_GROUPBY, arr, () => {
const s = (0, helpers_js_1.printArray)(arr);
return s ? 'group by ' + s : '';
});
}
__serializeOrderColumns(ctx) {
const arr = [];
if (this._orderBy) {
for (const t of this._orderBy) {
const s = t._serialize(ctx);
/* istanbul ignore else */
if (s)
arr.push(s);
}
}
return ctx.serialize(enums_js_1.SerializationType.SELECT_QUERY_ORDERBY, arr, () => {
const s = (0, helpers_js_1.printArray)(arr);
return s ? 'order by ' + s : '';
});
}
}
exports.SelectQuery = SelectQuery;