Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
86 changes: 85 additions & 1 deletion querybuilder.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
const REG_JSONKEY = /[^a-z0-9_]/i;
const REG_FIELDS_CLEANER = /"|`|\||'|\s/g;

var CACHE = {};
Expand Down Expand Up @@ -1304,7 +1305,90 @@ 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++;
}

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;
};

// 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++;
}

Expand Down
Loading