From 26f134c95d3753fd7a94e3f09258e5e6e70cac9e Mon Sep 17 00:00:00 2001 From: Ylian Saint-Hilaire Date: Wed, 31 Aug 2022 14:16:59 -0700 Subject: [PATCH] Completed server-side device paging support. --- db.js | 83 ++++++++++++++++++++++++++++++++++++++++++++++++++--- meshuser.js | 15 +++++++--- 2 files changed, 90 insertions(+), 8 deletions(-) diff --git a/db.js b/db.js index a323c27b..37d30ec7 100644 --- a/db.js +++ b/db.js @@ -1212,8 +1212,15 @@ module.exports.CreateDB = function (parent, func) { conn.query(query, args) .then(function (rows) { conn.release(); - const docs = []; - for (var i in rows) { if (rows[i].doc) { docs.push(performTypedRecordDecrypt((typeof rows[i].doc == 'object') ? rows[i].doc : JSON.parse(rows[i].doc))); } } + var docs = []; + for (var i in rows) { + if (rows[i].doc) { + docs.push(performTypedRecordDecrypt((typeof rows[i].doc == 'object') ? rows[i].doc : JSON.parse(rows[i].doc))); + } else if ((rows.length == 1) && (rows[i]['COUNT(doc)'] != null)) { + // This is a SELECT COUNT() operation + docs = parseInt(rows[i]['COUNT(doc)']); + } + } if (func) try { func(null, docs); } catch (ex) { console.log('SQLERR1', ex); } }) .catch(function (err) { conn.release(); if (func) try { func(err); } catch (ex) { console.log('SQLERR2', ex); } }); @@ -1224,7 +1231,14 @@ module.exports.CreateDB = function (parent, func) { if (func) try { func(error); } catch (ex) { console.log('SQLERR4', ex); } } else { var docs = []; - for (var i in results) { if (results[i].doc) { docs.push(JSON.parse(results[i].doc)); } } + for (var i in results) { + if (results[i].doc) { + docs.push(JSON.parse(results[i].doc)); + } else if ((results.length == 1) && (results[i]['COUNT(doc)'] != null)) { + // This is a SELECT COUNT() operation + docs = results[i]['COUNT(doc)']; + } + } if (func) { try { func(null, docs); } catch (ex) { console.log('SQLERR5', ex); } } } }); @@ -1237,7 +1251,18 @@ module.exports.CreateDB = function (parent, func) { var docs = []; if ((results.command == 'INSERT') && (results.rows != null) && (results.rows.length == 1)) { docs = results.rows[0]; } else if (results.command == 'SELECT') { - for (var i in results.rows) { if (results.rows[i].doc) { if (typeof results.rows[i].doc == 'string') { docs.push(JSON.parse(results.rows[i].doc)); } else { docs.push(results.rows[i].doc); } } } + for (var i in results.rows) { + if (results.rows[i].doc) { + if (typeof results.rows[i].doc == 'string') { + docs.push(JSON.parse(results.rows[i].doc)); + } else { + docs.push(results.rows[i].doc); + } + } else if (results.rows[i].count && (results.rows.length == 1)) { + // This is a SELECT COUNT() operation + docs = parseInt(results.rows[i].count); + } + } } if (func) { try { func(null, docs, results); } catch (ex) { console.log('SQLERR5', ex); } } } @@ -1350,6 +1375,23 @@ module.exports.CreateDB = function (parent, func) { } } }; + obj.CountAllTypeNoTypeFieldMeshFiltered = function (meshes, extrasids, domain, type, id, func) { + if (id && (id != '')) { + sqlDbQuery('SELECT COUNT(doc) FROM main WHERE (id = $1) AND (type = $2) AND (domain = $3) AND (extra IN (' + dbMergeSqlArray(meshes) + '))', [id, type, domain], function (err, docs) { + func(err, (err == null) ? docs[0]['COUNT(doc)'] : null); + }); + } else { + if (extrasids == null) { + sqlDbQuery('SELECT COUNT(doc) FROM main WHERE (type = $1) AND (domain = $2) AND (extra IN (' + dbMergeSqlArray(meshes) + '))', [type, domain], function (err, docs) { + func(err, (err == null) ? docs[0]['COUNT(doc)'] : null); + }); + } else { + sqlDbQuery('SELECT COUNT(doc) FROM main WHERE (type = $1) AND (domain = $2) AND ((extra IN (' + dbMergeSqlArray(meshes) + ')) OR (id IN (' + dbMergeSqlArray(extrasids) + ')))', [type, domain], function (err, docs) { + func(err, (err == null) ? docs[0]['COUNT(doc)'] : null); + }); + } + } + }; obj.GetAllTypeNodeFiltered = function (nodes, domain, type, id, func) { if (id && (id != '')) { sqlDbQuery('SELECT doc FROM main WHERE (id = $1) AND (type = $2) AND (domain = $3) AND (extra IN (' + dbMergeSqlArray(nodes) + '))', [id, type, domain], function (err, docs) { @@ -1793,6 +1835,17 @@ module.exports.CreateDB = function (parent, func) { } } }; + obj.CountAllTypeNoTypeFieldMeshFiltered = function (meshes, extrasids, domain, type, id, func) { + if (id && (id != '')) { + sqlDbQuery('SELECT COUNT(doc) FROM main WHERE (id = $1) AND (type = $2) AND (domain = $3) AND (extra = ANY ($4))', [id, type, domain, meshes], function (err, docs) { func(err, docs); }); + } else { + if (extrasids == null) { + sqlDbQuery('SELECT COUNT(doc) FROM main WHERE (type = $1) AND (domain = $2) AND (extra = ANY ($3))', [type, domain, meshes], function (err, docs) { func(err, docs); }, true); + } else { + sqlDbQuery('SELECT COUNT(doc) FROM main WHERE (type = $1) AND (domain = $2) AND ((extra = ANY ($3)) OR (id = ANY ($4)))', [type, domain, meshes, extrasids], function (err, docs) { func(err, docs); }); + } + } + }; obj.GetAllTypeNodeFiltered = function (nodes, domain, type, id, func) { if (id && (id != '')) { sqlDbQuery('SELECT doc FROM main WHERE (id = $1) AND (type = $2) AND (domain = $3) AND (extra = ANY ($4))', [id, type, domain, nodes], function (err, docs) { if (err == null) { for (var i in docs) { delete docs[i].type } } func(err, performTypedRecordDecrypt(docs)); }); @@ -1959,6 +2012,15 @@ module.exports.CreateDB = function (parent, func) { sqlDbQuery('SELECT doc FROM main WHERE type = ? AND domain = ? AND (extra IN (?) OR id IN (?)) LIMIT ? OFFSET ?', [type, domain, meshes, extrasids, limit, skip], function (err, docs) { if (err == null) { for (var i in docs) { delete docs[i].type } } func(err, performTypedRecordDecrypt(docs)); }); } }; + obj.CountAllTypeNoTypeFieldMeshFiltered = function (meshes, extrasids, domain, type, id, func) { + if ((meshes == null) || (meshes.length == 0)) { meshes = ''; } // MySQL can't handle a query with IN() on an empty array, we have to use an empty string instead. + if ((extrasids == null) || (extrasids.length == 0)) { extrasids = ''; } // MySQL can't handle a query with IN() on an empty array, we have to use an empty string instead. + if (id && (id != '')) { + sqlDbQuery('SELECT COUNT(doc) FROM main WHERE id = ? AND type = ? AND domain = ? AND extra IN (?)', [id, type, domain, meshes], function (err, docs) { func(err, docs); }); + } else { + sqlDbQuery('SELECT COUNT(doc) FROM main WHERE type = ? AND domain = ? AND (extra IN (?) OR id IN (?))', [type, domain, meshes, extrasids], function (err, docs) { func(err, docs); }); + } + }; obj.GetAllTypeNodeFiltered = function (nodes, domain, type, id, func) { if ((nodes == null) || (nodes.length == 0)) { nodes = ''; } // MySQL can't handle a query with IN() on an empty array, we have to use an empty string instead. if (id && (id != '')) { @@ -2197,6 +2259,19 @@ module.exports.CreateDB = function (parent, func) { f.toArray(function (err, docs) { func(err, performTypedRecordDecrypt(docs)); }); } }; + obj.CountAllTypeNoTypeFieldMeshFiltered = function (meshes, extrasids, domain, type, id, func) { + if (extrasids == null) { + const x = { type: type, domain: domain, meshid: { $in: meshes } }; + if (id) { x._id = id; } + var f = obj.file.find(x, { type: 0 }); + f.count(function (err, count) { func(err, count); }); + } else { + const x = { type: type, domain: domain, $or: [{ meshid: { $in: meshes } }, { _id: { $in: extrasids } }] }; + if (id) { x._id = id; } + var f = obj.file.find(x, { type: 0 }); + f.count(function (err, count) { func(err, count); }); + } + }; obj.GetAllTypeNodeFiltered = function (nodes, domain, type, id, func) { var x = { type: type, domain: domain, nodeid: { $in: nodes } }; if (id) { x._id = id; } diff --git a/meshuser.js b/meshuser.js index a60b2932..bf2945e5 100644 --- a/meshuser.js +++ b/meshuser.js @@ -734,7 +734,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use if (obj.visibleDevices != null) { obj.visibleDevices = {}; } for (i in docs) { // Check device links, if a link points to an unknown user, remove it. - parent.cleanDevice(docs[i]); + parent.cleanDevice(docs[i]); // TODO: This will make the total device count incorrect and will affect device paging. // If we are paging, add the device to the page here if (obj.visibleDevices != null) { obj.visibleDevices[docs[i]._id] = 1; } @@ -820,9 +820,16 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use response.totalcount = obj.deviceSkip + nodeCount; try { ws.send(JSON.stringify(response)); } catch (ex) { } } else { - // TODO - //console.log('response.totalcount', '???'); - try { ws.send(JSON.stringify(response)); } catch (ex) { } + // Ask the database for the total device count + if (db.CountAllTypeNoTypeFieldMeshFiltered) { + db.CountAllTypeNoTypeFieldMeshFiltered(links, extraids, domain.id, 'node', command.id, function (err, count) { + if ((err == null) && (typeof response.totalcount == 'number')) { response.totalcount = count; } + try { ws.send(JSON.stringify(response)); } catch (ex) { } + }); + } else { + // The database does not support device counting + try { ws.send(JSON.stringify(response)); } catch (ex) { } + } } } else { try { ws.send(JSON.stringify(response)); } catch (ex) { }