Skip to content

Commit f380320

Browse files
committed
Fix mistic100#641 not-group parsing errors from SQL
1 parent 12450e1 commit f380320

File tree

3 files changed

+93
-1
lines changed

3 files changed

+93
-1
lines changed

src/plugins/not-group/plugin.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,10 +63,27 @@ QueryBuilder.define('not-group', function(options) {
6363
this.on('parseSQLNode.filter', function(e) {
6464
if (e.value.name && e.value.name.toUpperCase() == 'NOT') {
6565
e.value = e.value.arguments.value[0];
66+
67+
// if the there is no sub-group, create one
68+
if (['AND', 'OR'].indexOf(e.value.operation.toUpperCase()) === -1) {
69+
e.value = {
70+
left: e.value,
71+
operation: self.settings.default_condition,
72+
right: null
73+
};
74+
}
75+
6676
e.value.not = true;
6777
}
6878
});
6979

80+
// Request to create sub-group if the "not" flag is set
81+
this.on('sqlGroupsDistinct.filter', function(e, group, data) {
82+
if (data.not) {
83+
e.value = true;
84+
}
85+
});
86+
7087
// Read "not" from parsed SQL
7188
this.on('sqlToGroup.filter', function(e, data) {
7289
e.value.not = !!data.not;

src/plugins/sql-support/plugin.js

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -457,6 +457,10 @@ QueryBuilder.extend(/** @lends module:plugins.SqlSupport.prototype */ {
457457
var curr = out;
458458

459459
(function flatten(data, i) {
460+
if (data === null) {
461+
return;
462+
}
463+
460464
// allow plugins to manually parse or handle special cases
461465
data = self.change('parseSQLNode', data);
462466

@@ -480,7 +484,19 @@ QueryBuilder.extend(/** @lends module:plugins.SqlSupport.prototype */ {
480484
// it's a node
481485
if (['AND', 'OR'].indexOf(data.operation.toUpperCase()) !== -1) {
482486
// create a sub-group if the condition is not the same and it's not the first level
483-
if (i > 0 && curr.condition != data.operation.toUpperCase()) {
487+
488+
/**
489+
* Given an existing group and an AST node, determines if a sub-group must be created
490+
* @event changer:sqlGroupsDistinct
491+
* @memberof module:plugins.SqlSupport
492+
* @param {boolean} create - try by default if the group condition is different
493+
* @param {object} group
494+
* @param {object} AST
495+
* @returns {boolean}
496+
*/
497+
var createGroup = self.change('sqlGroupsDistinct', i > 0 && curr.condition != data.operation.toUpperCase(), curr, data);
498+
499+
if (createGroup) {
484500
/**
485501
* Modifies the group generated from the SQL expression (this is called before the group is filled with rules)
486502
* @event changer:sqlToGroup

tests/plugins.not-group.module.js

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,22 @@ $(function () {
6969
rules,
7070
'Should parse NOT SQL function'
7171
);
72+
73+
$b.queryBuilder('setRulesFromSQL', sql2);
74+
75+
assert.rulesMatch(
76+
$b.queryBuilder('getRules'),
77+
rules2,
78+
'Should parse NOT SQL function with only one rule'
79+
);
80+
81+
$b.queryBuilder('setRulesFromSQL', sql3);
82+
83+
assert.rulesMatch(
84+
$b.queryBuilder('getRules'),
85+
rules3,
86+
'Should parse NOT SQL function with same operation'
87+
);
7288
});
7389

7490
QUnit.test('Mongo export', function (assert) {
@@ -119,6 +135,49 @@ $(function () {
119135

120136
var sql = 'name = \'Mistic\' OR ( NOT ( price < 10.25 AND category IN(\'mo\', \'mu\') ) ) ';
121137

138+
var rules2 = {
139+
condition: 'OR',
140+
rules: [{
141+
id: 'name',
142+
operator: 'equal',
143+
value: 'Mistic'
144+
}, {
145+
condition: 'AND',
146+
not: true,
147+
rules: [{
148+
id: 'price',
149+
operator: 'less',
150+
value: 10.25
151+
}]
152+
}]
153+
};
154+
155+
var sql2 = 'name = \'Mistic\' OR ( NOT ( price < 10.25 ) ) ';
156+
157+
var rules3 = {
158+
condition: 'OR',
159+
rules: [{
160+
id: 'name',
161+
operator: 'equal',
162+
value: 'Mistic'
163+
}, {
164+
condition: 'OR',
165+
not: true,
166+
rules: [{
167+
id: 'price',
168+
operator: 'less',
169+
value: 10.25
170+
}, {
171+
id: 'category',
172+
field: 'category',
173+
operator: 'in',
174+
value: ['mo', 'mu']
175+
}]
176+
}]
177+
};
178+
179+
var sql3 = 'name = \'Mistic\' OR ( NOT ( price < 10.25 OR category IN(\'mo\', \'mu\') ) ) ';
180+
122181
var mongo = {
123182
"$or": [{
124183
"name": "Mistic"

0 commit comments

Comments
 (0)