Commit da43b0d4 authored by Tristan Cavelier's avatar Tristan Cavelier

Queries: Fix some parsing/serialization issues

- fixes query toString inconsistent output
- change serialization behavior
  ( a:b OR a:c ) -> a:( b OR c )
  a:( b OR c )   -> a:( b OR c )
- rename simpleQuerySetKey to querySetKey
  as it also applies on complex queries.
parent 8143c5a8
...@@ -105,7 +105,7 @@ case 12: ...@@ -105,7 +105,7 @@ case 12:
this.$ = $$[$0-1]; this.$ = $$[$0-1];
break; break;
case 13: case 13:
simpleQuerySetKey($$[$0], $$[$0-2]); this.$ = $$[$0]; querySetKey($$[$0], $$[$0-2]); this.$ = $$[$0];
break; break;
case 15: case 15:
$$[$0].operator = $$[$0-1] ; this.$ = $$[$0]; $$[$0].operator = $$[$0-1] ; this.$ = $$[$0];
......
...@@ -61,7 +61,7 @@ boolean_expression ...@@ -61,7 +61,7 @@ boolean_expression
expression expression
: LEFT_PARENTHESE search_text RIGHT_PARENTHESE { $$ = $2; } : LEFT_PARENTHESE search_text RIGHT_PARENTHESE { $$ = $2; }
| WORD DEFINITION expression { simpleQuerySetKey($3, $1); $$ = $3; } | WORD DEFINITION expression { querySetKey($3, $1); $$ = $3; }
| value { $$ = $1; } | value { $$ = $1; }
; ;
......
...@@ -58,11 +58,11 @@ var arrayExtend = function () { ...@@ -58,11 +58,11 @@ var arrayExtend = function () {
} }
return {type:"complex",operator:operator,query_list:query_list2}; return {type:"complex",operator:operator,query_list:query_list2};
}, simpleQuerySetKey = function (query, key) { }, querySetKey = function (query, key) {
var i; var i;
if (query.type === "complex") { if (query.type === "complex") {
for (i = 0; i < query.query_list.length; ++i) { for (i = 0; i < query.query_list.length; ++i) {
simpleQuerySetKey (query.query_list[i],key); querySetKey(query.query_list[i], key);
} }
return true; return true;
} }
......
...@@ -573,21 +573,8 @@ ...@@ -573,21 +573,8 @@
* #crossLink "Query/toString:method" * #crossLink "Query/toString:method"
*/ */
ComplexQuery.prototype.toString = function () { ComplexQuery.prototype.toString = function () {
var str_list = [], this_operator = this.operator; /*global objectToSearchText */
if (this.operator === "NOT") { return objectToSearchText(this.toJSON());
str_list.push("NOT (");
str_list.push(this.query_list[0].toString());
str_list.push(")");
return str_list.join(" ");
}
this.query_list.forEach(function (query) {
str_list.push("(");
str_list.push(query.toString());
str_list.push(")");
str_list.push(this_operator);
});
str_list.length -= 1;
return str_list.join(" ");
}; };
/** /**
...@@ -686,21 +673,60 @@ ...@@ -686,21 +673,60 @@
}; };
function objectToSearchText(query) { function objectToSearchText(query) {
var str_list = []; var i = 0,
if (query.type === "complex") { query_list = null,
str_list.push("("); string_list = null,
(query.query_list || []).forEach(function (sub_query) { operator = "",
str_list.push(objectToSearchText(sub_query)); common_key = "";
str_list.push(query.operator);
});
str_list.length -= 1;
str_list.push(")");
return str_list.join(" ");
}
if (query.type === "simple") { if (query.type === "simple") {
return (query.key ? query.key + ": " : "") + return (query.key ? query.key + ": " : "") +
(query.operator || "") + ' "' + query.value + '"'; (query.operator || "") + ' "' + query.value + '"';
} }
if (query.type === "complex") {
query_list = query.query_list;
if (!query_list || query_list.length === 0) {
return "";
}
operator = query.operator || "";
if (operator === "NOT") {
// fallback to AND operator if several queries are given
// i.e. `NOT ( a AND b )`
return "NOT ( " + objectToSearchText(
{type: "complex", operator: "AND", query_list: query_list}
) + " )";
}
if (query_list.length === 1) {
return objectToSearchText(query_list[0]);
}
common_key = query_list[i].key;
for (i = 1; i < query_list.length; i += 1) {
if (query_list[i].type !== "simple" ||
query_list[i].key !== common_key) {
break;
}
}
string_list = [];
if (i === query_list.length) {
for (i = 0; i < query_list.length; i += 1) {
string_list.push(
(query_list[i].operator || "") +
' "' + query_list[i].value + '"'
);
}
} else {
common_key = "";
for (i = 0; i < query_list.length; i += 1) {
string_list.push(objectToSearchText(query_list[i]));
}
}
if (string_list.length > 1) {
return (common_key ? common_key + ": " : "") +
"( " + string_list.join(" " + operator + " ") + " )";
}
return (common_key ? common_key + ": " : "") +
string_list[0];
}
throw new TypeError("This object is not a query"); throw new TypeError("This object is not a query");
} }
...@@ -868,8 +894,7 @@ ...@@ -868,8 +894,7 @@
* #crossLink "Query/toString:method" * #crossLink "Query/toString:method"
*/ */
SimpleQuery.prototype.toString = function () { SimpleQuery.prototype.toString = function () {
return (this.key ? this.key + ":" : "") + return objectToSearchText(this.toJSON());
(this.operator ? " " + this.operator : "") + ' "' + this.value + '"';
}; };
/** /**
......
...@@ -1666,7 +1666,7 @@ ...@@ -1666,7 +1666,7 @@
test("extract complex AND single local_roles", function () { test("extract complex AND single local_roles", function () {
var search_url = domain + "?mode=search&" + var search_url = domain + "?mode=search&" +
"query=%28%20portal_type%3A%20%20%22Person%22%20%29&" + "query=portal_type%3A%20%20%22Person%22&" +
"select_list=destination&select_list=source&limit=5&" + "select_list=destination&select_list=source&limit=5&" +
"local_roles=Assignee", "local_roles=Assignee",
search_hateoas = JSON.stringify({ search_hateoas = JSON.stringify({
...@@ -1770,7 +1770,7 @@ ...@@ -1770,7 +1770,7 @@
test("extract sub multiple local_roles", function () { test("extract sub multiple local_roles", function () {
var search_url = domain + "?mode=search&" + var search_url = domain + "?mode=search&" +
"query=%28%20portal_type%3A%20%20%22Person%22%20%29&" + "query=portal_type%3A%20%20%22Person%22&" +
"select_list=destination&select_list=source&limit=5&" + "select_list=destination&select_list=source&limit=5&" +
"local_roles=Assignee&local_roles=Assignor", "local_roles=Assignee&local_roles=Assignor",
search_hateoas = JSON.stringify({ search_hateoas = JSON.stringify({
...@@ -1875,7 +1875,7 @@ ...@@ -1875,7 +1875,7 @@
test("extract complex AND single domains", function () { test("extract complex AND single domains", function () {
var search_url = domain + "?mode=search&" + var search_url = domain + "?mode=search&" +
"query=%28%20portal_type%3A%20%20%22Person%22%20%29&" + "query=portal_type%3A%20%20%22Person%22&" +
"select_list=destination&select_list=source&limit=5&" + "select_list=destination&select_list=source&limit=5&" +
"selection_domain=%7B%22group%22%3A%22bar%2Ffoo%22%7D", "selection_domain=%7B%22group%22%3A%22bar%2Ffoo%22%7D",
search_hateoas = JSON.stringify({ search_hateoas = JSON.stringify({
......
...@@ -321,10 +321,44 @@ ...@@ -321,10 +321,44 @@
"NOT(a:=b OR c:% AND d:<2)" "NOT(a:=b OR c:% AND d:<2)"
) )
).toString(), ).toString(),
"NOT ( ( a: = \"b\" ) OR ( ( c: \"%\" ) AND ( d: < \"2\" ) ) )", "NOT ( ( a: = \"b\" OR ( c: \"%\" AND d: < \"2\" ) ) )",
"create(create(\"NOT(a:=b OR c:% AND d:<2)\")).toString();" "create(create(\"NOT(a:=b OR c:% AND d:<2)\")).toString();"
); );
deepEqual(
jIO.QueryFactory.create(jIO.Query.objectToSearchText(jsoned)).toJSON(),
jsoned,
"create( objectToSearchText(create(\"NOT(a:=b OR c:% AND d:<2)\")" +
".toJSON()) ).toJSON()"
);
deepEqual(
jIO.QueryFactory.create("a:(b OR c)").toString(),
"a: ( \"b\" OR \"c\" )",
"create( \"a:(b OR c)\" ).toString()"
);
deepEqual(
jIO.QueryFactory.create("(a:b OR a:c)").toString(),
"a: ( \"b\" OR \"c\" )",
"create( \"(a:b OR a:c)\" ).toString()"
);
deepEqual(
jIO.QueryFactory.create({
"type": "complex",
"query_list": [{
"type": "simple",
"value": "a"
}, {
"type": "simple",
"value": "b"
}]
}).toString(),
"( \"a\" \"b\" )",
"{complex query without operator}.toString()"
);
}); });
test('Docs with space, tab, and newline', function () { test('Docs with space, tab, and newline', function () {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment