Completed server-side device paging support.

Ylian Saint-Hilaire committed Aug 31, 2022 at 14:16 UTC 26f134c95d3753fd7a94e3f09258e5e6e70cac9e
2 files changed +90 -8
db.js
+79 -4
@@ -1212,8 +1212,15 @@ module.exports.CreateDB = function (parent, func) {
1212 conn.query(query, args)
1213 .then(function (rows) {
1214 conn.release();
1215 - const docs = [];
1216 - 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))); } }
1215 + var docs = [];
1216 + for (var i in rows) {
1217 + if (rows[i].doc) {
1218 + docs.push(performTypedRecordDecrypt((typeof rows[i].doc == 'object') ? rows[i].doc : JSON.parse(rows[i].doc)));
1219 + } else if ((rows.length == 1) && (rows[i]['COUNT(doc)'] != null)) {
1220 + // This is a SELECT COUNT() operation
1221 + docs = parseInt(rows[i]['COUNT(doc)']);
1222 + }
1223 + }
1224 if (func) try { func(null, docs); } catch (ex) { console.log('SQLERR1', ex); }
1225 })
1226 .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) {
1231 if (func) try { func(error); } catch (ex) { console.log('SQLERR4', ex); }
1232 } else {
1233 var docs = [];
1227 - for (var i in results) { if (results[i].doc) { docs.push(JSON.parse(results[i].doc)); } }
1234 + for (var i in results) {
1235 + if (results[i].doc) {
1236 + docs.push(JSON.parse(results[i].doc));
1237 + } else if ((results.length == 1) && (results[i]['COUNT(doc)'] != null)) {
1238 + // This is a SELECT COUNT() operation
1239 + docs = results[i]['COUNT(doc)'];
1240 + }
1241 + }
1242 if (func) { try { func(null, docs); } catch (ex) { console.log('SQLERR5', ex); } }
1243 }
1244 });
@@ -1237,7 +1251,18 @@ module.exports.CreateDB = function (parent, func) {
1251 var docs = [];
1252 if ((results.command == 'INSERT') && (results.rows != null) && (results.rows.length == 1)) { docs = results.rows[0]; }
1253 else if (results.command == 'SELECT') {
1240 - 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); } } }
1254 + for (var i in results.rows) {
1255 + if (results.rows[i].doc) {
1256 + if (typeof results.rows[i].doc == 'string') {
1257 + docs.push(JSON.parse(results.rows[i].doc));
1258 + } else {
1259 + docs.push(results.rows[i].doc);
1260 + }
1261 + } else if (results.rows[i].count && (results.rows.length == 1)) {
1262 + // This is a SELECT COUNT() operation
1263 + docs = parseInt(results.rows[i].count);
1264 + }
1265 + }
1266 }
1267 if (func) { try { func(null, docs, results); } catch (ex) { console.log('SQLERR5', ex); } }
1268 }
@@ -1350,6 +1375,23 @@ module.exports.CreateDB = function (parent, func) {
1375 }
1376 }
1377 };
1378 + obj.CountAllTypeNoTypeFieldMeshFiltered = function (meshes, extrasids, domain, type, id, func) {
1379 + if (id && (id != '')) {
1380 + 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) {
1381 + func(err, (err == null) ? docs[0]['COUNT(doc)'] : null);
1382 + });
1383 + } else {
1384 + if (extrasids == null) {
1385 + sqlDbQuery('SELECT COUNT(doc) FROM main WHERE (type = $1) AND (domain = $2) AND (extra IN (' + dbMergeSqlArray(meshes) + '))', [type, domain], function (err, docs) {
1386 + func(err, (err == null) ? docs[0]['COUNT(doc)'] : null);
1387 + });
1388 + } else {
1389 + 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) {
1390 + func(err, (err == null) ? docs[0]['COUNT(doc)'] : null);
1391 + });
1392 + }
1393 + }
1394 + };
1395 obj.GetAllTypeNodeFiltered = function (nodes, domain, type, id, func) {
1396 if (id && (id != '')) {
1397 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) {
1835 }
1836 }
1837 };
1838 + obj.CountAllTypeNoTypeFieldMeshFiltered = function (meshes, extrasids, domain, type, id, func) {
1839 + if (id && (id != '')) {
1840 + 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); });
1841 + } else {
1842 + if (extrasids == null) {
1843 + 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);
1844 + } else {
1845 + 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); });
1846 + }
1847 + }
1848 + };
1849 obj.GetAllTypeNodeFiltered = function (nodes, domain, type, id, func) {
1850 if (id && (id != '')) {
1851 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) {
2012 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)); });
2013 }
2014 };
2015 + obj.CountAllTypeNoTypeFieldMeshFiltered = function (meshes, extrasids, domain, type, id, func) {
2016 + 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.
2017 + 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.
2018 + if (id && (id != '')) {
2019 + 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); });
2020 + } else {
2021 + 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); });
2022 + }
2023 + };
2024 obj.GetAllTypeNodeFiltered = function (nodes, domain, type, id, func) {
2025 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.
2026 if (id && (id != '')) {
@@ -2197,6 +2259,19 @@ module.exports.CreateDB = function (parent, func) {
2259 f.toArray(function (err, docs) { func(err, performTypedRecordDecrypt(docs)); });
2260 }
2261 };
2262 + obj.CountAllTypeNoTypeFieldMeshFiltered = function (meshes, extrasids, domain, type, id, func) {
2263 + if (extrasids == null) {
2264 + const x = { type: type, domain: domain, meshid: { $in: meshes } };
2265 + if (id) { x._id = id; }
2266 + var f = obj.file.find(x, { type: 0 });
2267 + f.count(function (err, count) { func(err, count); });
2268 + } else {
2269 + const x = { type: type, domain: domain, $or: [{ meshid: { $in: meshes } }, { _id: { $in: extrasids } }] };
2270 + if (id) { x._id = id; }
2271 + var f = obj.file.find(x, { type: 0 });
2272 + f.count(function (err, count) { func(err, count); });
2273 + }
2274 + };
2275 obj.GetAllTypeNodeFiltered = function (nodes, domain, type, id, func) {
2276 var x = { type: type, domain: domain, nodeid: { $in: nodes } };
2277 if (id) { x._id = id; }
meshuser.js
+11 -4
@@ -734,7 +734,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
734 if (obj.visibleDevices != null) { obj.visibleDevices = {}; }
735 for (i in docs) {
736 // Check device links, if a link points to an unknown user, remove it.
737 - parent.cleanDevice(docs[i]);
737 + parent.cleanDevice(docs[i]); // TODO: This will make the total device count incorrect and will affect device paging.
738
739 // If we are paging, add the device to the page here
740 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
820 response.totalcount = obj.deviceSkip + nodeCount;
821 try { ws.send(JSON.stringify(response)); } catch (ex) { }
822 } else {
823 - // TODO
824 - //console.log('response.totalcount', '???');
825 - try { ws.send(JSON.stringify(response)); } catch (ex) { }
823 + // Ask the database for the total device count
824 + if (db.CountAllTypeNoTypeFieldMeshFiltered) {
825 + db.CountAllTypeNoTypeFieldMeshFiltered(links, extraids, domain.id, 'node', command.id, function (err, count) {
826 + if ((err == null) && (typeof response.totalcount == 'number')) { response.totalcount = count; }
827 + try { ws.send(JSON.stringify(response)); } catch (ex) { }
828 + });
829 + } else {
830 + // The database does not support device counting
831 + try { ws.send(JSON.stringify(response)); } catch (ex) { }
832 + }
833 }
834 } else {
835 try { ws.send(JSON.stringify(response)); } catch (ex) { }