From 2e971b3fa82a26fa54463385275a669a88dcdc11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gera=20G=2E=20G=C3=BCiles?= Date: Tue, 20 Oct 2026 11:11:42 +0200 Subject: [PATCH 1/2] added autoqueryjson() - added `QueryBuilder.autoqueryjson($, column, schema, [defsort], [maxlimit])` that works like `autoquery()` but for properties stored in a JSON column; the builder uses the neutral name `json:column:property:type` and the database adapter translates it into SQL --- changelog.txt | 1 + querybuilder.js | 84 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 85 insertions(+) diff --git a/changelog.txt b/changelog.txt index 11a42f6..9c853a8 100644 --- a/changelog.txt +++ b/changelog.txt @@ -8,6 +8,7 @@ - fixed string slug method - changed `max-age` header to `5 minutes` - fixed `attachmentfs()` in the mail: the file of the storage is read as a Buffer and the message is completed (it threw a `TypeError` and the SMTP connection stayed open) +- added `QueryBuilder.autoqueryjson($, column, schema, [defsort], [maxlimit])` that works like `autoquery()` but for properties stored in a JSON column; the builder uses the neutral name `json:column:property:type` and the database adapter translates it into SQL ======================== 0.0.99 diff --git a/querybuilder.js b/querybuilder.js index d319514..a871279 100644 --- a/querybuilder.js +++ b/querybuilder.js @@ -1,3 +1,4 @@ +const REG_JSONKEY = /[^a-z0-9_]/i; const REG_FIELDS_CLEANER = /"|`|\||'|\s/g; var CACHE = {}; @@ -1318,6 +1319,89 @@ QBP.autoquery = function(query, schema, defsort, maxlimit) { return t; }; +// Works like autoquery() but for properties stored in a JSON column +// Usage: .autoqueryjson($, 'data', 'id,name,email,age:Number,dtcreated:Date,tags:[string]', 'dtcreated_desc', 100) +// The builder doesn't generate any SQL. Fields, filters and sorting use the neutral name "json:column:property:type" +// and each database adapter translates it into its own syntax. +QBP.autoqueryjson = function($, column, schema, defsort, maxlimit) { + + var t = this; + var query = $ && $.query && typeof($.query) === 'object' ? $.query : ($ || {}); + + if (!column || REG_JSONKEY.test(column)) + throw new Error('QueryBuilder.autoqueryjson(): invalid column name "' + column + '"'); + + var key = 'QBJ' + column + '|' + schema; + var allowed = CACHE[key]; + + if (!allowed) { + + var fields = {}; + var filter = []; + + for (var field of schema.split(',').trim()) { + + var k = field.split(':').trim(); + var name = k[0]; + + if (!name || REG_JSONKEY.test(name)) + continue; + + var type = (k[1] || 'string').toLowerCase(); + fields[name] = 'json:' + column + ':' + name + ':' + type; + filter.push({ name: name, type: type }); + } + + allowed = CACHE[key] = { fields: fields, filter: filter }; + } + + var fieldscount = 0; + + if (!t.options.fields) + t.options.fields = []; + + if (query.fields) { + for (var field of query.fields.replace(REG_FIELDS_CLEANER, '').split(',')) { + if (allowed.fields[field]) { + t.options.fields.push(allowed.fields[field]); + fieldscount++; + } + } + } + + if (!fieldscount) { + for (var item of allowed.filter) + t.options.fields.push(allowed.fields[item.name]); + } + + for (var item of allowed.filter) + t.gridfilter(item.name, query, item.type, allowed.fields[item.name]); + + if (query.sort) { + + var count = 0; + + for (var item of query.sort.split(',')) { + var index = item.lastIndexOf('_'); + var name = index === -1 ? item : item.substring(0, index); + + if (!allowed.fields[name]) + continue; + + t.sort(allowed.fields[name], index !== -1 && item.substring(index + 1).toLowerCase() === 'desc'); + count++; + } + + if (!count && defsort) + t.gridsort(defsort, allowed.fields); + + } else if (defsort) + t.gridsort(defsort, allowed.fields); + + maxlimit && t.paginate(query.page, query.limit, maxlimit); + return t; +}; + QBP.query = function(value) { this.filter.push({ type: 'query', value: value }); return this; From 3105cb6acede8cdede2b1ba30aa4f64b6361e308 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gera=20G=2E=20G=C3=BCiles?= Date: Tue, 20 Oct 2026 11:27:07 +0200 Subject: [PATCH 2/2] added: autoqueryjson(); fixed: autoquery() sorting without a direction suffix --- querybuilder.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/querybuilder.js b/querybuilder.js index a871279..00c391a 100644 --- a/querybuilder.js +++ b/querybuilder.js @@ -1305,7 +1305,7 @@ QBP.autoquery = function(query, schema, defsort, maxlimit) { if ((skipped && skipped[name]) || (!allowed.meta[name])) continue; - t.sort(allowed.fields[name], item[index + 1] === 'd'); + t.sort(allowed.fields[name], index !== -1 && item.substring(index + 1).toLowerCase() === 'desc'); count++; }