From e5190c9b206f8108a59e854497559ffa9e961286 Mon Sep 17 00:00:00 2001 From: Tomas Bures Date: Sat, 15 Apr 2017 08:24:58 -0400 Subject: [PATCH] Code de-duplication of list and filter methods. The common functionality moved to table-helpers.js This should make developing new table-based views easier. --- lib/models/campaigns.js | 244 +++--------------------------------- lib/models/lists.js | 21 +--- lib/models/subscriptions.js | 103 ++------------- lib/models/templates.js | 21 +--- lib/models/triggers.js | 69 +--------- lib/table-helpers.js | 100 +++++++++++++++ 6 files changed, 137 insertions(+), 421 deletions(-) create mode 100644 lib/table-helpers.js diff --git a/lib/models/campaigns.js b/lib/models/campaigns.js index fca3b4c7..1bcabcc8 100644 --- a/lib/models/campaigns.js +++ b/lib/models/campaigns.js @@ -14,186 +14,40 @@ let mailer = require('../mailer'); let humanize = require('humanize'); let _ = require('../translate')._; let util = require('util'); +let tableHelpers = require('../table-helpers'); let allowedKeys = ['description', 'from', 'address', 'reply_to', 'subject', 'editor_name', 'editor_data', 'template', 'source_url', 'list', 'segment', 'html', 'text', 'tracking_disabled']; module.exports.list = (start, limit, callback) => { - db.getConnection((err, connection) => { - if (err) { - return callback(err); - } - - connection.query('SELECT SQL_CALC_FOUND_ROWS * FROM campaigns ORDER BY scheduled DESC LIMIT ? OFFSET ?', [limit, start], (err, rows) => { - if (err) { - connection.release(); - return callback(err); - } - connection.query('SELECT FOUND_ROWS() AS total', (err, total) => { - connection.release(); - if (err) { - return callback(err); - } - return callback(null, rows, total && total[0] && total[0].total); - }); - }); - }); + tableHelpers.list('campaigns', 'scheduled', start, limit, callback); }; module.exports.filter = (request, parent, callback) => { - let columns = ['#', 'name', 'description', 'status', 'created']; - let processQuery = queryData => { - - db.getConnection((err, connection) => { - if (err) { - return callback(err); - } - - let query = 'SELECT COUNT(id) AS total FROM `campaigns`'; - let values = []; - - if (queryData.where) { - query += ' WHERE ' + queryData.where; - values = values.concat(queryData.values || []); - } - - connection.query(query, values, (err, total) => { - if (err) { - connection.release(); - return callback(err); - } - total = total && total[0] && total[0].total || 0; - - let ordering = []; - - if (request.order && request.order.length) { - - request.order.forEach(order => { - let orderField = columns[Number(order.column)]; - let orderDirection = (order.dir || '').toString().toLowerCase() === 'desc' ? 'DESC' : 'ASC'; - if (orderField) { - ordering.push('`' + orderField + '` ' + orderDirection); - } - }); - } - - if (!ordering.length) { - ordering.push('`created` DESC'); - } - - let args = [Number(request.length) || 50, Number(request.start) || 0]; - let query; - - if (request.search && request.search.value) { - query = 'SELECT SQL_CALC_FOUND_ROWS * FROM `campaigns` WHERE name LIKE ? ' + (queryData.where ? ' AND (' + queryData.where + ')' : '') + ' ORDER BY ' + ordering.join(', ') + ' LIMIT ? OFFSET ?'; - - let searchVal = '%' + request.search.value.replace(/\\/g, '\\\\').replace(/([%_])/g, '\\$1') + '%'; - args = [searchVal].concat(queryData.values || []).concat(args); - } else { - query = 'SELECT SQL_CALC_FOUND_ROWS * FROM `campaigns` WHERE 1 ' + (queryData.where ? ' AND (' + queryData.where + ')' : '') + ' ORDER BY ' + ordering.join(', ') + ' LIMIT ? OFFSET ?'; - args = [].concat(queryData.values || []).concat(args); - } - - connection.query(query, args, (err, rows) => { - if (err) { - connection.release(); - return callback(err); - } - connection.query('SELECT FOUND_ROWS() AS total', (err, filteredTotal) => { - connection.release(); - if (err) { - return callback(err); - } - - let subscriptions = rows.map(row => tools.convertKeys(row)); - - filteredTotal = filteredTotal && filteredTotal[0] && filteredTotal[0].total || 0; - return callback(null, subscriptions, total, filteredTotal); - }); - }); - }); - }); - }; - + let queryData; if (parent) { - processQuery({ + queryData = { // only find normal and RSS parent campaigns at this point where: '`parent`=?', values: [parent] - }); + }; } else { - - processQuery({ + queryData = { // only find normal and RSS parent campaigns at this point where: '`type` IN (?,?,?)', values: [1, 2, 4] - }); + }; } + + tableHelpers.filter('campaigns', request, ['#', 'name', 'description', 'status', 'created'], ['name'], 'created DESC', queryData, callback); }; module.exports.filterClickedSubscribers = (campaign, linkId, request, columns, callback) => { - db.getConnection((err, connection) => { - if (err) { - return callback(err); - } + let queryData = { + where: 'campaign_tracker__' + campaign.id + '.list=? AND campaign_tracker__' + campaign.id + '.link=?', + values: [campaign.list, linkId] + }; - let query = 'SELECT COUNT(`subscription__' + campaign.list + '`.`id`) AS total FROM `subscription__' + campaign.list + '` JOIN `campaign_tracker__' + campaign.id + '` ON `campaign_tracker__' + campaign.id + '`.`list`=? AND `campaign_tracker__' + campaign.id + '`.`subscriber`=`subscription__' + campaign.list + '`.`id` AND `campaign_tracker__' + campaign.id + '`.`link`=?'; - let values = [campaign.list, linkId]; - - connection.query(query, values, (err, total) => { - if (err) { - connection.release(); - return callback(err); - } - total = total && total[0] && total[0].total || 0; - - let ordering = []; - - if (request.order && request.order.length) { - - request.order.forEach(order => { - let orderField = columns[Number(order.column)]; - let orderDirection = (order.dir || '').toString().toLowerCase() === 'desc' ? 'DESC' : 'ASC'; - if (orderField) { - ordering.push('`' + orderField + '` ' + orderDirection); - } - }); - } - - if (!ordering.length) { - ordering.push('`email` ASC'); - } - - let args = [Number(request.length) || 50, Number(request.start) || 0]; - - if (request.search && request.search.value) { - query = 'SELECT SQL_CALC_FOUND_ROWS * FROM `subscription__' + campaign.list + '` JOIN `campaign_tracker__' + campaign.id + '` ON `campaign_tracker__' + campaign.id + '`.`list`=? AND `campaign_tracker__' + campaign.id + '`.`subscriber`=`subscription__' + campaign.list + '`.`id` AND `campaign_tracker__' + campaign.id + '`.`link`=? WHERE email LIKE ? OR first_name LIKE ? OR last_name LIKE ? ORDER BY ' + ordering.join(', ') + ' LIMIT ? OFFSET ?'; - - let searchVal = '%' + request.search.value.replace(/\\/g, '\\\\').replace(/([%_])/g, '\\$1') + '%'; - args = values.concat([searchVal, searchVal, searchVal]).concat(args); - } else { - query = 'SELECT SQL_CALC_FOUND_ROWS * FROM `subscription__' + campaign.list + '` JOIN `campaign_tracker__' + campaign.id + '` ON `campaign_tracker__' + campaign.id + '`.`list`=? AND `campaign_tracker__' + campaign.id + '`.`subscriber`=`subscription__' + campaign.list + '`.`id` AND `campaign_tracker__' + campaign.id + '`.`link`=? ORDER BY ' + ordering.join(', ') + ' LIMIT ? OFFSET ?'; - args = values.concat(args); - } - - connection.query(query, args, (err, rows) => { - if (err) { - connection.release(); - return callback(err); - } - connection.query('SELECT FOUND_ROWS() AS total', (err, filteredTotal) => { - connection.release(); - if (err) { - return callback(err); - } - - let subscriptions = rows.map(row => tools.convertKeys(row)); - - filteredTotal = filteredTotal && filteredTotal[0] && filteredTotal[0].total || 0; - return callback(null, subscriptions, total, filteredTotal); - }); - }); - }); - }); + tableHelpers.filter('subscription__' + campaign.list + ' JOIN campaign_tracker__' + campaign.id + ' ON campaign_tracker__' + campaign.id + '.subscriber=subscription__' + campaign.list + '.id', request, columns, ['email', 'first_name', 'last_name'], 'email ASC', queryData, callback); }; module.exports.statsClickedSubscribersByColumn = (campaign, linkId, request, column, limit, callback) => { @@ -233,72 +87,12 @@ module.exports.statsClickedSubscribersByColumn = (campaign, linkId, request, col }; module.exports.filterStatusSubscribers = (campaign, status, request, columns, callback) => { - db.getConnection((err, connection) => { - if (err) { - return callback(err); - } - - status = Number(status) || 0; - let query = 'SELECT COUNT(`subscription__' + campaign.list + '`.`id`) AS total FROM `subscription__' + campaign.list + '` JOIN `campaign__' + campaign.id + '` ON `campaign__' + campaign.id + '`.`list`=? AND `campaign__' + campaign.id + '`.`segment`=? AND `campaign__' + campaign.id + '`.`subscription`=`subscription__' + campaign.list + '`.`id` WHERE `campaign__' + campaign.id + '`.`status`=?'; - let values = [campaign.list, campaign.segment && campaign.segment.id || 0, status]; - - connection.query(query, values, (err, total) => { - if (err) { - - connection.release(); - return callback(err); - } - total = total && total[0] && total[0].total || 0; - - let ordering = []; - - if (request.order && request.order.length) { - - request.order.forEach(order => { - let orderField = columns[Number(order.column)]; - let orderDirection = (order.dir || '').toString().toLowerCase() === 'desc' ? 'DESC' : 'ASC'; - if (orderField) { - ordering.push('`' + orderField + '` ' + orderDirection); - } - }); - } - - if (!ordering.length) { - ordering.push('`email` ASC'); - } - - let args = [Number(request.length) || 50, Number(request.start) || 0]; - - if (request.search && request.search.value) { - query = 'SELECT SQL_CALC_FOUND_ROWS * FROM `subscription__' + campaign.list + '` JOIN `campaign__' + campaign.id + '` ON `campaign__' + campaign.id + '`.`list`=? AND `campaign__' + campaign.id + '`.`segment`=? AND `campaign__' + campaign.id + '`.`subscription`=`subscription__' + campaign.list + '`.`id` WHERE `campaign__' + campaign.id + '`.`status`=? AND (email LIKE ? OR first_name LIKE ? OR last_name LIKE ?) ORDER BY ' + ordering.join(', ') + ' LIMIT ? OFFSET ?'; - - let searchVal = '%' + request.search.value.replace(/\\/g, '\\\\').replace(/([%_])/g, '\\$1') + '%'; - args = values.concat([searchVal, searchVal, searchVal]).concat(args); - } else { - query = 'SELECT SQL_CALC_FOUND_ROWS * FROM `subscription__' + campaign.list + '` JOIN `campaign__' + campaign.id + '` ON `campaign__' + campaign.id + '`.`list`=? AND `campaign__' + campaign.id + '`.`segment`=? AND `campaign__' + campaign.id + '`.`subscription`=`subscription__' + campaign.list + '`.`id` WHERE `campaign__' + campaign.id + '`.`status`=? ORDER BY ' + ordering.join(', ') + ' LIMIT ? OFFSET ?'; - args = values.concat(args); - } - - connection.query(query, args, (err, rows) => { - if (err) { - connection.release(); - return callback(err); - } - connection.query('SELECT FOUND_ROWS() AS total', (err, filteredTotal) => { - connection.release(); - if (err) { - return callback(err); - } - - let subscriptions = rows.map(row => tools.convertKeys(row)); - - filteredTotal = filteredTotal && filteredTotal[0] && filteredTotal[0].total || 0; - return callback(null, subscriptions, total, filteredTotal); - }); - }); - }); - }); + let queryData = { + where: 'campaign__' + campaign.id + '.list=? AND campaign__' + campaign.id + '.segment=? AND campaign__' + campaign.id + '.status=?', + values: [campaign.list, campaign.segment && campaign.segment.id || 0, status] + }; + tableHelpers.filter('subscription__' + campaign.list + ' JOIN campaign__' + campaign.id + ' ON campaign__' + campaign.id + '.subscription=subscription__' + campaign.list + '.id', request, columns, ['email', 'first_name', 'last_name'], 'email ASC', queryData, callback); }; module.exports.getByCid = (cid, callback) => { diff --git a/lib/models/lists.js b/lib/models/lists.js index def0f713..feaadd08 100644 --- a/lib/models/lists.js +++ b/lib/models/lists.js @@ -5,29 +5,12 @@ let tools = require('../tools'); let shortid = require('shortid'); let segments = require('./segments'); let _ = require('../translate')._; +let tableHelpers = require('../table-helpers'); let allowedKeys = ['description', 'default_form', 'public_subscribe']; module.exports.list = (start, limit, callback) => { - db.getConnection((err, connection) => { - if (err) { - return callback(err); - } - - connection.query('SELECT SQL_CALC_FOUND_ROWS * FROM lists ORDER BY name LIMIT ? OFFSET ?', [limit, start], (err, rows) => { - if (err) { - connection.release(); - return callback(err); - } - connection.query('SELECT FOUND_ROWS() AS total', (err, total) => { - connection.release(); - if (err) { - return callback(err); - } - return callback(null, rows, total && total[0] && total[0].total); - }); - }); - }); + tableHelpers.list('lists', 'name', start, limit, callback); }; module.exports.quicklist = callback => { diff --git a/lib/models/subscriptions.js b/lib/models/subscriptions.js index 33641063..7d0b83ee 100644 --- a/lib/models/subscriptions.js +++ b/lib/models/subscriptions.js @@ -13,6 +13,7 @@ let urllib = require('url'); let log = require('npmlog'); let _ = require('../translate')._; let util = require('util'); +let tableHelpers = require('../table-helpers'); module.exports.list = (listId, start, limit, callback) => { listId = Number(listId) || 0; @@ -20,26 +21,11 @@ module.exports.list = (listId, start, limit, callback) => { return callback(new Error('Missing List ID')); } - db.getConnection((err, connection) => { - if (err) { - return callback(err); + tableHelpers.list('subscription__' + listId, 'email', start, limit, (err, rows, total) => { + if (!err) { + rows = rows.map(row => tools.convertKeys(row)); } - - connection.query('SELECT SQL_CALC_FOUND_ROWS * FROM `subscription__' + listId + '` ORDER BY email LIMIT ? OFFSET ?', [limit, start], (err, rows) => { - if (err) { - connection.release(); - return callback(err); - } - connection.query('SELECT FOUND_ROWS() AS total', (err, total) => { - connection.release(); - if (err) { - return callback(err); - } - - let subscriptions = rows.map(row => tools.convertKeys(row)); - return callback(null, subscriptions, total && total[0] && total[0].total); - }); - }); + return callback(err, rows, total); }); }; @@ -80,7 +66,6 @@ module.exports.listTestUsers = (listId, callback) => { }); }; - module.exports.filter = (listId, request, columns, segmentId, callback) => { listId = Number(listId) || 0; segmentId = Number(segmentId) || 0; @@ -89,88 +74,16 @@ module.exports.filter = (listId, request, columns, segmentId, callback) => { return callback(new Error(_('Missing List ID'))); } - let processQuery = queryData => { - - db.getConnection((err, connection) => { - if (err) { - return callback(err); - } - - let query = 'SELECT COUNT(id) AS total FROM `subscription__' + listId + '`'; - let values = []; - - if (queryData.where) { - query += ' WHERE ' + queryData.where; - values = values.concat(queryData.values || []); - } - - connection.query(query, values, (err, total) => { - if (err) { - connection.release(); - return callback(err); - } - total = total && total[0] && total[0].total || 0; - - let ordering = []; - - if (request.order && request.order.length) { - - request.order.forEach(order => { - let orderField = columns[Number(order.column)]; - let orderDirection = (order.dir || '').toString().toLowerCase() === 'desc' ? 'DESC' : 'ASC'; - if (orderField) { - ordering.push('`' + orderField + '` ' + orderDirection); - } - }); - } - - if (!ordering.length) { - ordering.push('`email` ASC'); - } - - let args = [Number(request.length) || 50, Number(request.start) || 0]; - let query; - - if (request.search && request.search.value) { - query = 'SELECT SQL_CALC_FOUND_ROWS * FROM `subscription__' + listId + '` WHERE email LIKE ? OR first_name LIKE ? OR last_name LIKE ? ' + (queryData.where ? ' AND (' + queryData.where + ')' : '') + ' ORDER BY ' + ordering.join(', ') + ' LIMIT ? OFFSET ?'; - - let searchVal = '%' + request.search.value.replace(/\\/g, '\\\\').replace(/([%_])/g, '\\$1') + '%'; - args = [searchVal, searchVal, searchVal].concat(queryData.values || []).concat(args); - } else { - query = 'SELECT SQL_CALC_FOUND_ROWS * FROM `subscription__' + listId + '` WHERE 1 ' + (queryData.where ? ' AND (' + queryData.where + ')' : '') + ' ORDER BY ' + ordering.join(', ') + ' LIMIT ? OFFSET ?'; - args = [].concat(queryData.values || []).concat(args); - } - - connection.query(query, args, (err, rows) => { - if (err) { - connection.release(); - return callback(err); - } - connection.query('SELECT FOUND_ROWS() AS total', (err, filteredTotal) => { - connection.release(); - if (err) { - return callback(err); - } - - let subscriptions = rows.map(row => tools.convertKeys(row)); - - filteredTotal = filteredTotal && filteredTotal[0] && filteredTotal[0].total || 0; - return callback(null, subscriptions, total, filteredTotal); - }); - }); - }); - }); - }; - if (segmentId) { segments.getQuery(segmentId, false, (err, queryData) => { if (err) { return callback(err); } - processQuery(queryData); + + tableHelpers.filter('subscription__' + listId, request, columns, ['email', 'first_name', 'last_name'], 'email ASC', queryData, callback); }); } else { - processQuery(false); + tableHelpers.filter('subscription__' + listId, request, columns, ['email', 'first_name', 'last_name'], 'email ASC', null, callback); } }; diff --git a/lib/models/templates.js b/lib/models/templates.js index 4171ebb1..48fde524 100644 --- a/lib/models/templates.js +++ b/lib/models/templates.js @@ -3,29 +3,12 @@ let db = require('../db'); let tools = require('../tools'); let _ = require('../translate')._; +let tableHelpers = require('../table-helpers'); let allowedKeys = ['description', 'editor_name', 'editor_data', 'html', 'text']; module.exports.list = (start, limit, callback) => { - db.getConnection((err, connection) => { - if (err) { - return callback(err); - } - - connection.query('SELECT SQL_CALC_FOUND_ROWS * FROM templates ORDER BY name LIMIT ? OFFSET ?', [limit, start], (err, rows) => { - if (err) { - connection.release(); - return callback(err); - } - connection.query('SELECT FOUND_ROWS() AS total', (err, total) => { - connection.release(); - if (err) { - return callback(err); - } - return callback(null, rows, total && total[0] && total[0].total); - }); - }); - }); + tableHelpers.list('templates', 'name', start, limit, callback); }; module.exports.quicklist = callback => { diff --git a/lib/models/triggers.js b/lib/models/triggers.js index cd682cda..a3658240 100644 --- a/lib/models/triggers.js +++ b/lib/models/triggers.js @@ -5,6 +5,7 @@ let db = require('../db'); let lists = require('./lists'); let util = require('util'); let _ = require('../translate')._; +let tableHelpers = require('../table-helpers'); module.exports.defaultColumns = [{ column: 'created', @@ -339,70 +340,12 @@ module.exports.delete = (id, callback) => { }; module.exports.filterSubscribers = (trigger, request, columns, callback) => { - db.getConnection((err, connection) => { - if (err) { - return callback(err); - } - - let query = 'SELECT COUNT(`subscription__' + trigger.list + '`.`id`) AS total FROM `subscription__' + trigger.list + '` JOIN `trigger__' + trigger.id + '` ON `trigger__' + trigger.id + '`.`list`=? AND `trigger__' + trigger.id + '`.`subscription`=`subscription__' + trigger.list + '`.`id`'; - let values = [trigger.list]; - - connection.query(query, values, (err, total) => { - if (err) { - connection.release(); - return callback(err); - } - total = total && total[0] && total[0].total || 0; - - let ordering = []; - - if (request.order && request.order.length) { - - request.order.forEach(order => { - let orderField = columns[Number(order.column)]; - let orderDirection = (order.dir || '').toString().toLowerCase() === 'desc' ? 'DESC' : 'ASC'; - if (orderField) { - ordering.push('`' + orderField + '` ' + orderDirection); - } - }); - } - - if (!ordering.length) { - ordering.push('`email` ASC'); - } - - let args = [Number(request.length) || 50, Number(request.start) || 0]; - - if (request.search && request.search.value) { - query = 'SELECT SQL_CALC_FOUND_ROWS * FROM `subscription__' + trigger.list + '` JOIN `trigger__' + trigger.id + '` ON `trigger__' + trigger.id + '`.`list`=? AND `trigger__' + trigger.id + '`.`subscription`=`subscription__' + trigger.list + '`.`id AND (email LIKE ? OR first_name LIKE ? OR last_name LIKE ?) ORDER BY ' + ordering.join(', ') + ' LIMIT ? OFFSET ?'; - - let searchVal = '%' + request.search.value.replace(/\\/g, '\\\\').replace(/([%_])/g, '\\$1') + '%'; - args = values.concat([searchVal, searchVal, searchVal]).concat(args); - } else { - query = 'SELECT SQL_CALC_FOUND_ROWS * FROM `subscription__' + trigger.list + '` JOIN `trigger__' + trigger.id + '` ON `trigger__' + trigger.id + '`.`list`=? AND `trigger__' + trigger.id + '`.`subscription`=`subscription__' + trigger.list + '`.`id` ORDER BY ' + ordering.join(', ') + ' LIMIT ? OFFSET ?'; - args = values.concat(args); - } - - connection.query(query, args, (err, rows) => { - if (err) { - connection.release(); - return callback(err); - } - connection.query('SELECT FOUND_ROWS() AS total', (err, filteredTotal) => { - connection.release(); - if (err) { - return callback(err); - } - - let subscriptions = rows.map(row => tools.convertKeys(row)); - - filteredTotal = filteredTotal && filteredTotal[0] && filteredTotal[0].total || 0; - return callback(null, subscriptions, total, filteredTotal); - }); - }); - }); - }); + let queryData = { + where: 'trigger__' + trigger.id + '.list=?', + values: [trigger.list] + }; + tableHelpers.filter('subscription__' + trigger.list + ' JOIN trigger__' + trigger.id + ' ON trigger__' + trigger.id + '.subscription=subscription__' + trigger.list + '.id', request, columns, ['email', 'first_name', 'last_name'], 'email ASC', queryData, callback); }; function createTriggerTable(id, callback) { diff --git a/lib/table-helpers.js b/lib/table-helpers.js new file mode 100644 index 00000000..245e54b1 --- /dev/null +++ b/lib/table-helpers.js @@ -0,0 +1,100 @@ +'use strict'; + +let db = require('./db'); +let tools = require('./tools'); +let log = require('npmlog'); + +module.exports.list = (source, orderBy, start, limit, callback) => { + db.getConnection((err, connection) => { + if (err) { + return callback(err); + } + + connection.query('SELECT SQL_CALC_FOUND_ROWS * FROM ' + source + ' ORDER BY ' + orderBy + ' DESC LIMIT ? OFFSET ?', [limit, start], (err, rows) => { + if (err) { + connection.release(); + return callback(err); + } + connection.query('SELECT FOUND_ROWS() AS total', (err, total) => { + connection.release(); + if (err) { + return callback(err); + } + return callback(null, rows, total && total[0] && total[0].total); + }); + }); + }); +}; + + +module.exports.filter = (source, request, columns, searchFields, defaultOrdering, queryData, callback) => { + db.getConnection((err, connection) => { + if (err) { + return callback(err); + } + + let query = 'SELECT COUNT(*) AS total FROM ' + source; + let values = []; + + if (queryData) { + query += ' WHERE ' + queryData.where; + values = values.concat(queryData.values || []); + } + + connection.query(query, values, (err, total) => { + if (err) { + connection.release(); + return callback(err); + } + total = total && total[0] && total[0].total || 0; + + let ordering = []; + + if (request.order && request.order.length) { + + request.order.forEach(order => { + let orderField = columns[Number(order.column)]; + let orderDirection = (order.dir || '').toString().toLowerCase() === 'desc' ? 'DESC' : 'ASC'; + if (orderField) { + ordering.push('`' + orderField + '` ' + orderDirection); + } + }); + } + + if (!ordering.length) { + ordering.push(defaultOrdering); + } + + let searchWhere = ''; + let searchArgs = []; + + if (request.search && request.search.value) { + let searchVal = '%' + request.search.value.replace(/\\/g, '\\\\').replace(/([%_])/g, '\\$1') + '%'; + + searchWhere = searchFields.map(field => field + ' LIKE ?').join(' OR '); + searchArgs = searchFields.map(field => searchVal) + } + + let query = 'SELECT SQL_CALC_FOUND_ROWS * FROM ' + source +' WHERE ' + (searchWhere ? '(' + searchWhere + ')': '1') + (queryData ? ' AND (' + queryData.where + ')' : '') + ' ORDER BY ' + ordering.join(', ') + ' LIMIT ? OFFSET ?'; + let args = searchArgs.concat(queryData ? queryData.values : []).concat([Number(request.length) || 50, Number(request.start) || 0]); + + connection.query(query, args, (err, rows) => { + if (err) { + connection.release(); + return callback(err); + } + connection.query('SELECT FOUND_ROWS() AS total', (err, filteredTotal) => { + connection.release(); + if (err) { + return callback(err); + } + + rows = rows.map(row => tools.convertKeys(row)); + + filteredTotal = filteredTotal && filteredTotal[0] && filteredTotal[0].total || 0; + return callback(null, rows, total, filteredTotal); + }); + }); + }); + }); +};