@xuda.io/xuda-dbs-plugin-xuda 1.0.319 → 1.0.320
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/server.mjs +41 -3
- package/studio.mjs +24 -8
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xuda.io/xuda-dbs-plugin-xuda",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.320",
|
|
4
4
|
"description": "Xuda Database Socket for Xuda's proprietary structure powered by CouchDB",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"pub": "npm version patch --force && npm publish --access public"
|
package/server.mjs
CHANGED
|
@@ -558,9 +558,23 @@ const query_db = async function (e, db, app_id_reference, table_obj) {
|
|
|
558
558
|
}
|
|
559
559
|
};
|
|
560
560
|
|
|
561
|
+
// A COUNT must span the WHOLE result set, not the current page. `opt` carries
|
|
562
|
+
// the page limit/skip, so counting body.docs.length under them could never
|
|
563
|
+
// exceed one page. Ask for ids only (unless count_data's index-grouping
|
|
564
|
+
// branch needs the field data) and cap the scan so a pathological table
|
|
565
|
+
// cannot stall the request.
|
|
566
|
+
const COUNT_SCAN_CAP = 100000;
|
|
567
|
+
const find_opt = e.count
|
|
568
|
+
? Object.assign({}, opt, {
|
|
569
|
+
limit: COUNT_SCAN_CAP,
|
|
570
|
+
skip: 0,
|
|
571
|
+
fields: e.indexId ? opt.fields : ['_id'],
|
|
572
|
+
})
|
|
573
|
+
: opt;
|
|
574
|
+
|
|
561
575
|
try {
|
|
562
576
|
try {
|
|
563
|
-
const doc = await db.find(
|
|
577
|
+
const doc = await db.find(find_opt);
|
|
564
578
|
if (doc?.warning?.includes('No matching index found')) {
|
|
565
579
|
await create_mango_index_for_selector();
|
|
566
580
|
}
|
|
@@ -591,7 +605,7 @@ const query_db = async function (e, db, app_id_reference, table_obj) {
|
|
|
591
605
|
try {
|
|
592
606
|
const result = await db.createIndex(mango_index_obj);
|
|
593
607
|
|
|
594
|
-
const doc = await db.find(
|
|
608
|
+
const doc = await db.find(find_opt);
|
|
595
609
|
return await done(doc);
|
|
596
610
|
} catch (err) {
|
|
597
611
|
return { code: -1, data: err.message };
|
|
@@ -719,7 +733,31 @@ const query_db = async function (e, db, app_id_reference, table_obj) {
|
|
|
719
733
|
return await runtime_get_query_data();
|
|
720
734
|
}
|
|
721
735
|
|
|
722
|
-
|
|
736
|
+
// A COUNT must answer "how many rows match THIS query", not "how many rows are
|
|
737
|
+
// in the table". count_tables() reads the db_table_counts reduce view keyed by
|
|
738
|
+
// table_id alone, so it ignores the selector completely — and `filter_from` is
|
|
739
|
+
// only ever set for dataSourceFilterModelType==='index', so every MONGO-filtered
|
|
740
|
+
// count landed here and came back with the whole-table total. Live symptom: a
|
|
741
|
+
// filtered question list returned its correct rows while rows_found stayed 837,
|
|
742
|
+
// so the pager kept offering 168 pages over an empty/short result set.
|
|
743
|
+
// Keep the cheap view for a genuinely UNFILTERED count; anything carrying a
|
|
744
|
+
// selector is counted through Mango against that same selector.
|
|
745
|
+
const _has_filter_value = function (v) {
|
|
746
|
+
if (v === undefined || v === null || v === '') return false;
|
|
747
|
+
try {
|
|
748
|
+
const o = typeof v === 'string' ? JSON.parse(v) : v;
|
|
749
|
+
return !_.isEmpty(o);
|
|
750
|
+
} catch (err) {
|
|
751
|
+
return true; // present but unparseable — assume it filters; never over-count
|
|
752
|
+
}
|
|
753
|
+
};
|
|
754
|
+
const _count_is_filtered =
|
|
755
|
+
!!e.filter_from ||
|
|
756
|
+
_has_filter_value(e.filterModelMongo) ||
|
|
757
|
+
_has_filter_value(e.filterModelUserMongo) ||
|
|
758
|
+
_has_filter_value(e.filterModelNative);
|
|
759
|
+
|
|
760
|
+
if (e.count && !_count_is_filtered) {
|
|
723
761
|
return await count_tables();
|
|
724
762
|
}
|
|
725
763
|
|
package/studio.mjs
CHANGED
|
@@ -180,6 +180,20 @@ const get_cast_val = async function (source, attributeP, typeP, valP) {
|
|
|
180
180
|
return xu_cast(typeP, valP, success, fail);
|
|
181
181
|
};
|
|
182
182
|
|
|
183
|
+
const get_json_value = function (value, fallback) {
|
|
184
|
+
if (typeof value === 'undefined' || value === null || value === '') {
|
|
185
|
+
return fallback;
|
|
186
|
+
}
|
|
187
|
+
if (typeof value === 'string') {
|
|
188
|
+
try {
|
|
189
|
+
return JSON.parse(value);
|
|
190
|
+
} catch (err) {
|
|
191
|
+
return fallback;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
return value;
|
|
195
|
+
};
|
|
196
|
+
|
|
183
197
|
const get_opt = function (e, table_obj) {
|
|
184
198
|
var limit = 99999;
|
|
185
199
|
var skip = 0;
|
|
@@ -244,9 +258,9 @@ const get_opt = function (e, table_obj) {
|
|
|
244
258
|
opt.sort = sort;
|
|
245
259
|
}
|
|
246
260
|
|
|
247
|
-
let _sortModel = e?.sortModel
|
|
248
|
-
if (
|
|
249
|
-
_sortModel =
|
|
261
|
+
let _sortModel = get_json_value(e?.sortModel, []);
|
|
262
|
+
if (!Array.isArray(_sortModel)) {
|
|
263
|
+
_sortModel = [];
|
|
250
264
|
}
|
|
251
265
|
|
|
252
266
|
if (_sortModel.length) {
|
|
@@ -288,7 +302,7 @@ const get_opt = function (e, table_obj) {
|
|
|
288
302
|
opt.fields[key] = 'udfData.data.' + val;
|
|
289
303
|
}
|
|
290
304
|
|
|
291
|
-
if (!e?.sortModel || !
|
|
305
|
+
if (!e?.sortModel || !_sortModel.length) {
|
|
292
306
|
// added 2021 09 10
|
|
293
307
|
if (opt.sort) {
|
|
294
308
|
for (const [key, val] of Object.entries(opt.sort)) {
|
|
@@ -372,14 +386,16 @@ const get_opt = function (e, table_obj) {
|
|
|
372
386
|
return recursiveReplace(query);
|
|
373
387
|
}
|
|
374
388
|
|
|
375
|
-
|
|
376
|
-
|
|
389
|
+
const filterModelMongo = get_json_value(e.filterModelMongo, {});
|
|
390
|
+
if (e.dataSourceFilterModelType === 'query' && !_.isEmpty(filterModelMongo)) {
|
|
391
|
+
selector_new['$and'] = [replaceRegexOptions(replaceKeysInQuery(filterModelMongo))];
|
|
377
392
|
}
|
|
378
|
-
|
|
393
|
+
const filterModelUserMongo = get_json_value(e.filterModelUserMongo, {});
|
|
394
|
+
if (!_.isEmpty(filterModelUserMongo)) {
|
|
379
395
|
if (!selector_new['$and']) {
|
|
380
396
|
selector_new['$and'] = [];
|
|
381
397
|
}
|
|
382
|
-
selector_new['$and'].push(replaceRegexOptions(replaceKeysInQuery(
|
|
398
|
+
selector_new['$and'].push(replaceRegexOptions(replaceKeysInQuery(filterModelUserMongo)));
|
|
383
399
|
}
|
|
384
400
|
|
|
385
401
|
if (e.dataSourceFilterModelType === 'index') {
|