Skip to content

Commit

Permalink
refactor: query builder and add support for subqueries
Browse files Browse the repository at this point in the history
  • Loading branch information
AxiosLeo committed Feb 8, 2024
1 parent 90837c2 commit e014788
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 4 deletions.
4 changes: 3 additions & 1 deletion index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,9 @@ export type QueryOperatorOptions = QueryOperatorBaseOptions & {
}

export declare class Query {
constructor(operator?: OperatorType);
options: QueryOperatorOptions;

constructor(operator?: OperatorType, alias?: string | null);

table(tableName: string, alias: string | null): this;

Expand Down
29 changes: 27 additions & 2 deletions src/builder.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,21 @@ class Builder {
}
// eslint-disable-next-line no-fallthrough
case 'select': {
emit(tmp, `SELECT ${options.attrs ? options.attrs.map((a) => this._buildFieldKey(a)).join(',') : '*'} FROM ${this._buildTables(options.tables)}`);
options.attrs = options.attrs || [];
const attrs = options.attrs.map((attr) => {
if (attr instanceof Function) {
const query = attr();
const builder = new Builder(query.options);
let s = `(${builder.sql})`;
if (query.alias) {
return query.alias.indexOf(' ') > -1 ? s + ' ' + this._buildFieldKey(query.alias)
: s + ' AS ' + this._buildFieldKey(query.alias);
}
return s;
}
return attr;
});
emit(tmp, `SELECT ${attrs.length ? attrs.map((a) => this._buildFieldKey(a)).join(',') : '*'} FROM ${this._buildTables(options.tables)}`);
emit(tmp, this._buildJoins(options.joins));
emit(tmp, this._buildContidion(options.conditions));
emit(tmp, this._buildOrders(options.orders));
Expand Down Expand Up @@ -199,6 +213,11 @@ class Builder {
}

_buildConditionValues(val) {
if (is.string(val)) {
if (val.startsWith('`') && val.endsWith('`')) {
return val;
}
}
if (val instanceof Query) {
const builder = new Builder(val.options);
this.values = this.values.concat(builder.values);
Expand Down Expand Up @@ -263,7 +282,13 @@ class Builder {
return `(${this._buildContidion(c.value, '')})`;
}
let res = this._buildConditionValues(c.value);
return res ? `${this._buildFieldKey(c.key)} ${c.opt} (${res})` : `${this._buildFieldKey(c.key)} ${c.opt} ?`;
if (!is.empty(res)) {
if (res.startsWith('`') && res.endsWith('`')) {
return `${this._buildFieldKey(c.key)} ${c.opt} ${res}`;
}
return `${this._buildFieldKey(c.key)} ${c.opt} (${res})`;
}
return `${this._buildFieldKey(c.key)} ${c.opt} ?`;
}).join('')}`;
}
return sql;
Expand Down
3 changes: 2 additions & 1 deletion src/query.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
'use strict';

class Query {
constructor(operator = 'select') {
constructor(operator = 'select', alias = null) {
this.options = {
driver: 'mysql',
queryHandler: null,
Expand All @@ -16,6 +16,7 @@ class Query {
suffix: null,
transaction: false
};
this.alias = alias || null;
}

table(tableName, alias) {
Expand Down
10 changes: 10 additions & 0 deletions tests/query.tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -159,4 +159,14 @@ describe('query test case', () => {
const query = hanlder.table('users', 'u').attr(...[]).where('id', 1).whereConditions().limit(2).offset(1);
expect(query.buildSql('select').sql).to.be.equal('SELECT * FROM `users` AS `u` WHERE `id` = ? LIMIT 2 OFFSET 1');
});

it('attr is sub query', () => {
let sql = hanlder.table('orgs', 's1')
.attr('s1.id', 's1.name', 's1.parent_id', () => {
const query = new Query('count', '> 0 AS has_children');
query.table('orgs', 's2').where('s2.parent_id', '`s1`.`id`');
return query;
}).buildSql('select').sql;
expect(sql).to.be.equal('SELECT `s1`.`id`,`s1`.`name`,`s1`.`parent_id`,(SELECT COUNT(*) AS count FROM `orgs` AS `s2` WHERE `s2`.`parent_id` = `s1`.`id`) > 0 AS `has_children` FROM `orgs` AS `s1`');
});
});

0 comments on commit e014788

Please sign in to comment.