node-querybuilder
Version:
Modeled after Codeigniter's QueryBuilder. Build and execute queries in a safe and database-agnostic way.
252 lines (209 loc) • 8.8 kB
JavaScript
const QueryBuilder = require('./query_builder.js');
const ERROR = require("../QueryExecError");
const WrapperPromise = require("../WrapperPromise");
// ****************************************************************************
// QueryBuilder "Query Execution" methods.
// ****************************************************************************
class QueryExec extends QueryBuilder {
constructor() {
super();
}
_exec(sql, cb) {
if (Object.prototype.toString.call(this._connection) === Object.prototype.toString.call({})) {
this._connection.query(sql, (err, results) => {
// Standardize some important properties
if (!err && results && !Array.isArray(results)) {
// Insert ID
if (results.hasOwnProperty('insertId')) {
results.insert_id = results.insertId || null;
}
// Affected Rows
if (results.hasOwnProperty('affectedRows')) {
results.affected_rows = results.affectedRows;
}
// Changed Rows
if (results.hasOwnProperty('changedRows')) {
results.changed_rows = results.changedRows;
}
}
cb(err, results);
});
} else {
throw ERROR.NO_CONN_OBJ_ERR;
}
}
query(sql, cb) {
if (!cb || typeof cb !== "function") return new WrapperPromise(sql, this._exec.bind(this)).promisify();
this._exec(sql, cb);
}
count(table, cb) {
if (typeof table === 'function' && typeof cb !== 'function') {
table = null;
cb = table;
}
const sql = this._count(table);
this.reset_query(sql);
const handler = (err, row) => {
if (!err) {
if (typeof callback !== "function") {
this.resolve(row[0].numrows);
return;
}
cb(err, row[0].numrows);
}
else {
if (typeof callback !== "function") {
this.reject(err);
return;
}
cb(err, row);
}
}
if (typeof cb !== "function") return new WrapperPromise(sql, this._exec.bind(this), handler).promisify();
this._exec(sql, handler);
}
get(table, cb, conn) {
// The table parameter is optional, it could be the cb...
if (typeof table === 'function' && typeof cb !== 'function') {
cb = table;
}
const sql = this._get(table);
this.reset_query(sql);
if (typeof cb !== "function") return new WrapperPromise(sql, this._exec.bind(this)).promisify();
this._exec(sql, cb);
}
get_where(table, where, cb) {
if (typeof table !== 'string' && !Array.isArray(table)) {
throw ERROR.FIRST_PARAM_OF_GET_WHERE_ERR;
}
if (Object.prototype.toString.call(where) !== Object.prototype.toString.call({})) {
throw ERROR.SECOND_PARAM_OF_GET_WHERE_ERR;
}
const sql = this._get_where(table, where);
this.reset_query(sql);
if (typeof cb !== "function") return new WrapperPromise(sql, this._exec.bind(this)).promisify();
this._exec(sql, cb);
}
insert(table, set, cb, ignore, suffix) {
const sql = this._insert(table, set, ignore, suffix);
this.reset_query(sql);
if (typeof cb !== "function") return new WrapperPromise(sql, this._exec.bind(this)).promisify();
this._exec(sql, cb);
}
insert_ignore(table, set, on_dupe, cb) {
if (typeof on_dupe === 'function') {
cb = on_dupe;
on_dupe = null;
}
const sql = this._insert_ignore(table, set, on_dupe);
this.reset_query(sql);
if (typeof cb !== "function") return new WrapperPromise(sql, this._exec.bind(this)).promisify();
this._exec(sql, cb);
}
insert_batch(table, set, ignore, on_dupe, cb) {
if (typeof ignore === 'function') {
cb = ignore;
ignore = null;
}
else if (typeof on_dupe === 'function') {
cb = on_dupe;
on_dupe = null;
}
const sql = this._insert_batch(table, set, ignore, on_dupe);
this.reset_query(sql);
if (typeof cb !== "function") return new WrapperPromise(sql, this._exec.bind(this)).promisify();
this._exec(sql, cb);
}
update(table, set, where, cb) {
// The where parameter is optional, it could be the cb...
if (typeof where === 'function' && typeof cb !== 'function') {
cb = where;
where = null;
}
else if (typeof where === 'undefined' || where === false || (where !== null && typeof where === 'object' && Object.keys(where).length === 0)) {
where = null;
}
const sql = this._update(table, set, where);
this.reset_query(sql);
if (typeof cb !== "function") return new WrapperPromise(sql, this._exec.bind(this)).promisify();
this._exec(sql, cb);
}
// TODO: Write this complicated-ass function
update_batch(table, set, index, where, cb) {
// The where parameter is optional, it could be the cb...
if (typeof where === 'function' && typeof cb !== 'function') {
cb = where;
where = null;
}
else if (typeof where === 'undefined' || where === false || (where !== null && typeof where === 'object' && Object.keys(where).length === 0)) {
where = null;
}
const sqls = this._update_batch(table, set, index, where);
const results = null;
const errors = [];
// Execute each batch of (at least) 100
const handler = (resolve, reject) => {
(function next_batch() {
const sql = sqls.shift();
this.reset_query(sql);
this._exec(sql, (err, res) => {
if (!err) {
if (null === results) {
results = res;
} else {
results.affected_rows += res.affected_rows;
results.changed_rows += res.changed_rows;
}
} else {
errors.push(err);
}
if (sqls.length > 0) {
setTimeout(next_batch, 0);
} else {
if ((!cb || typeof cb !== 'function') && (typeof resolve === 'function' && typeof reject === 'function')) {
if (Array.isArray(errors) && errors.length > 0) return reject(new Error(errors.join("\n\n")));
return resolve(results);
} else if (cb && typeof cb === 'function') {
return cb(errors, results);
} else {
throw ERRORS.NO_VALID_RESULTS_HANDLER;
}
}
});
})();
};
if (!cb || cb !== 'function') {
return new Promise(handler);
} else {
handler();
}
}
delete(table, where, cb) {
if (typeof where === 'function' && typeof cb !== 'function') {
cb = where;
where = undefined;
}
if (typeof table === 'function' && typeof cb !== 'function') {
cb = table;
table = undefined;
where = undefined;
}
const sql = this._delete(table, where);
this.reset_query(sql);
if (typeof cb !== "function") return new WrapperPromise(sql, this._exec.bind(this)).promisify();
this._exec(sql, cb);
}
empty_table(table, cb) {
const sql = this._empty_table(table, cb);
this.reset_query(sql);
if (typeof cb !== "function") return new WrapperPromise(sql, this._exec.bind(this)).promisify();
this._exec(sql, cb);
}
truncate(table, cb) {
const sql = this._truncate(table, cb);
this.reset_query(sql);
if (typeof cb !== "function") return new WrapperPromise(sql, this._exec.bind(this)).promisify();
this._exec(sql, cb);
}
}
module.exports = QueryExec;