UNPKG

node-querybuilder

Version:

Modeled after Codeigniter's QueryBuilder. Build and execute queries in a safe and database-agnostic way.

259 lines (218 loc) 9.43 kB
const Request = require('tedious').Request; 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({})) { const request = new Request(sql, (err, count, results) => { // Standardize some important properties if (!err && results && Array.isArray(results)) { if (results.length === 0) { results = {insert_id: null, affected_rows: 0, changed_rows: 0}; // Affected & Changed Rows if (count) { results.affected_rows = count; // Only set changed rows on an update if (/^update\s/i.test(sql)) results.changed_rows = count; } } else { const data = results.map(row => row.map(col => ({[col.metadata.colName]: col.value})).reduce((l,r) => Object.assign(l,r))) if (/^insert\s/i.test(sql)) { results = {insert_id: data, affected_rows: (count ? count : 0), changed_rows: 0}; } else { results = data; } } } cb(err, results); }); if (!this._connection) { this._connection.connect(err => { if (err) return cb(err, null); this._connection.execSql(request); }); } else { //console.log("connection object2: ", this._connection); this._connection.execSql(request); } } else { throw new Error("No connection object supplied to the Query Exec Library!"); } } 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) { throw new Error("insert_ignore(): This feature is currently unsupported in the MSSQL driver."); // if (typeof on_dupe === 'function') { // cb = on_dupe; // on_dupe = null; // } // const sql = this._insert_ignore(table,set,on_dupe); // this.reset_query(sql); // 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; } if (ignore) throw new Error("QE insert_batch(): INSERT IGNORE is currently unsupported on the MSSQL driver."); if (suffix) throw new Error("QE insert_batch(): 'on_dupe' string (4th parameter) is currently unsupported on the MSSQL driver."); const sql = this._insert_batch(table, set); 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 { return cb(errors, results); } }); })(); }; 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;