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) { }