Skip to content

Commit f1ebe1c

Browse files
committed
correct work for logical expression in ~~
1 parent a2ed982 commit f1ebe1c

File tree

3 files changed

+160
-8
lines changed

3 files changed

+160
-8
lines changed

Diff for: expected/jsquery.out

+84
Original file line numberDiff line numberDiff line change
@@ -1904,6 +1904,90 @@ select '{"a": {"b": 1, "c": 2}, "b": {"d":3}}'::jsonb @@ 'a.g and b.d';
19041904
f
19051905
(1 row)
19061906

1907+
select '{"a": {"b": 1, "c": 2}, "b": {"d":3}}'::jsonb ~~ 'a.b and b.d';
1908+
?column?
1909+
----------
1910+
[1, 3]
1911+
(1 row)
1912+
1913+
select '{"a": {"b": 1, "c": 2}, "b": {"d":3}}'::jsonb ~~ 'a.b and b.c';
1914+
?column?
1915+
----------
1916+
1917+
(1 row)
1918+
1919+
select '{"a": {"b": 1, "c": 2}, "b": {"d":3}}'::jsonb ~~ 'a.b and (b.d or b.c)';
1920+
?column?
1921+
----------
1922+
[1, 3]
1923+
(1 row)
1924+
1925+
select '{"a": {"b": 1, "c": 2}, "b": {"d":3}}'::jsonb ~~ 'a.b and (b.c or b.d)';
1926+
?column?
1927+
----------
1928+
[1, 3]
1929+
(1 row)
1930+
1931+
select '{"a": {"b": 1, "c": 2}, "b": {"d":3}}'::jsonb ~~ 'a.b and a.c and b.d';
1932+
?column?
1933+
-----------
1934+
[1, 2, 3]
1935+
(1 row)
1936+
1937+
select '{"a": {"b": 1, "c": 2}, "b": {"d":3}}'::jsonb ~~ '(a.b or a.c) and b.d';
1938+
?column?
1939+
----------
1940+
[1, 3]
1941+
(1 row)
1942+
1943+
select '{"a": {"b": 1, "c": 2}, "b": {"d":3}}'::jsonb ~~ '(a.e or a.c) and b.d';
1944+
?column?
1945+
----------
1946+
[2, 3]
1947+
(1 row)
1948+
1949+
select '{"a": {"b": 1, "c": 2}, "b": {"d":3}}'::jsonb ~~ '(a.e or a.g) and b.d';
1950+
?column?
1951+
----------
1952+
1953+
(1 row)
1954+
1955+
select '{"a": {"b": 1, "c": 2}, "b": {"d":3}}'::jsonb ~~ 'a.b or (b.d or b.c)';
1956+
?column?
1957+
----------
1958+
[1]
1959+
(1 row)
1960+
1961+
select '{"a": {"b": 1, "c": 2}, "b": {"d":3}}'::jsonb ~~ 'b.d or (a.b or a.c)';
1962+
?column?
1963+
----------
1964+
[3]
1965+
(1 row)
1966+
1967+
select '{"a": {"b": 1, "c": 2}, "b": {"d":3}}'::jsonb ~~ 'b.d or (a.b and a.c)';
1968+
?column?
1969+
----------
1970+
[3]
1971+
(1 row)
1972+
1973+
select '{"a": {"b": 1, "c": 2}, "b": {"d":3}}'::jsonb ~~ 'b.f or (a.b and a.c)';
1974+
?column?
1975+
----------
1976+
[1, 2]
1977+
(1 row)
1978+
1979+
select '{"a": {"b": 1, "c": 2}, "b": {"d":3}}'::jsonb ~~ 'b.d and (a.b and a.c)';
1980+
?column?
1981+
-----------
1982+
[3, 1, 2]
1983+
(1 row)
1984+
1985+
select '{"a": {"b": [6,5,4], "c": 2}, "b": {"d":3}}'::jsonb ~~ 'b.d and (a.b and a.c)';
1986+
?column?
1987+
-------------------
1988+
[3, [6, 5, 4], 2]
1989+
(1 row)
1990+
19071991
--extract entries for index scan
19081992
SELECT gin_debug_query_path_value('NOT NOT NOT x(y(NOT (a=1) and NOT (b=2)) OR NOT NOT (c=3)) and z = 5');
19091993
gin_debug_query_path_value

Diff for: jsquery_op.c

+61-8
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,27 @@ appendResult(ResultAccum *ra, JsonbValue *jb)
5151
pushJsonbValue(&ra->jbArrayState, WJB_ELEM, jb);
5252
}
5353

54+
static void
55+
concatResult(ResultAccum *ra, JsonbParseState *a, JsonbParseState *b)
56+
{
57+
Jsonb *value;
58+
JsonbIterator *it;
59+
int32 r;
60+
JsonbValue v;
61+
62+
Assert(a);
63+
Assert(b);
64+
65+
ra->jbArrayState = a;
66+
67+
value = JsonbValueToJsonb(pushJsonbValue(&b, WJB_END_ARRAY, NULL));
68+
it = JsonbIteratorInit(&value->root);
69+
70+
while((r = JsonbIteratorNext(&it, &v, true)) != WJB_DONE)
71+
if (r == WJB_ELEM)
72+
pushJsonbValue(&ra->jbArrayState, WJB_ELEM, &v);
73+
}
74+
5475
static int
5576
compareNumeric(Numeric a, Numeric b)
5677
{
@@ -435,14 +456,37 @@ recursiveExecute(JsQueryItem *jsq, JsonbValue *jb, JsQueryItem *jsqLeftArg,
435456

436457
switch(jsq->type) {
437458
case jqiAnd:
438-
jsqGetLeftArg(jsq, &elem);
439-
res = recursiveExecute(&elem, jb, jsqLeftArg, ra);
440-
if (res == true)
441459
{
442-
jsqGetRightArg(jsq, &elem);
460+
JsonbParseState *saveJbArrayState = NULL;
461+
462+
jsqGetLeftArg(jsq, &elem);
463+
if (ra && ra->missAppend == false)
464+
{
465+
saveJbArrayState = ra->jbArrayState;
466+
ra->jbArrayState = NULL;
467+
}
468+
443469
res = recursiveExecute(&elem, jb, jsqLeftArg, ra);
470+
if (res == true)
471+
{
472+
jsqGetRightArg(jsq, &elem);
473+
res = recursiveExecute(&elem, jb, jsqLeftArg, ra);
474+
}
475+
476+
if (ra && ra->missAppend == false)
477+
{
478+
if (res == true)
479+
{
480+
if (saveJbArrayState != NULL)
481+
/* append args lists to current */
482+
concatResult(ra, saveJbArrayState, ra->jbArrayState);
483+
}
484+
else
485+
ra->jbArrayState = saveJbArrayState;
486+
}
487+
488+
break;
444489
}
445-
break;
446490
case jqiOr:
447491
jsqGetLeftArg(jsq, &elem);
448492
res = recursiveExecute(&elem, jb, jsqLeftArg, ra);
@@ -453,9 +497,18 @@ recursiveExecute(JsQueryItem *jsq, JsonbValue *jb, JsQueryItem *jsqLeftArg,
453497
}
454498
break;
455499
case jqiNot:
456-
jsqGetArg(jsq, &elem);
457-
res = !recursiveExecute(&elem, jb, jsqLeftArg, ra);
458-
break;
500+
{
501+
bool saveMissAppend = (ra) ? ra->missAppend : true;
502+
503+
jsqGetArg(jsq, &elem);
504+
if (ra)
505+
ra->missAppend = true;
506+
res = !recursiveExecute(&elem, jb, jsqLeftArg, ra);
507+
if (ra)
508+
ra->missAppend = saveMissAppend;
509+
510+
break;
511+
}
459512
case jqiKey:
460513
if (JsonbType(jb) == jbvObject) {
461514
JsonbValue *v, key;

Diff for: sql/jsquery.sql

+15
Original file line numberDiff line numberDiff line change
@@ -378,6 +378,21 @@ select '{"a": {"b": 1, "c": 2}, "b": {"d":3}}'::jsonb @@ 'a.c and b.d';
378378
select '{"a": {"b": 1, "c": 2}, "b": {"d":3}}'::jsonb @@ 'a.c and b.b';
379379
select '{"a": {"b": 1, "c": 2}, "b": {"d":3}}'::jsonb @@ 'a.g and b.d';
380380

381+
select '{"a": {"b": 1, "c": 2}, "b": {"d":3}}'::jsonb ~~ 'a.b and b.d';
382+
select '{"a": {"b": 1, "c": 2}, "b": {"d":3}}'::jsonb ~~ 'a.b and b.c';
383+
select '{"a": {"b": 1, "c": 2}, "b": {"d":3}}'::jsonb ~~ 'a.b and (b.d or b.c)';
384+
select '{"a": {"b": 1, "c": 2}, "b": {"d":3}}'::jsonb ~~ 'a.b and (b.c or b.d)';
385+
select '{"a": {"b": 1, "c": 2}, "b": {"d":3}}'::jsonb ~~ 'a.b and a.c and b.d';
386+
select '{"a": {"b": 1, "c": 2}, "b": {"d":3}}'::jsonb ~~ '(a.b or a.c) and b.d';
387+
select '{"a": {"b": 1, "c": 2}, "b": {"d":3}}'::jsonb ~~ '(a.e or a.c) and b.d';
388+
select '{"a": {"b": 1, "c": 2}, "b": {"d":3}}'::jsonb ~~ '(a.e or a.g) and b.d';
389+
select '{"a": {"b": 1, "c": 2}, "b": {"d":3}}'::jsonb ~~ 'a.b or (b.d or b.c)';
390+
select '{"a": {"b": 1, "c": 2}, "b": {"d":3}}'::jsonb ~~ 'b.d or (a.b or a.c)';
391+
select '{"a": {"b": 1, "c": 2}, "b": {"d":3}}'::jsonb ~~ 'b.d or (a.b and a.c)';
392+
select '{"a": {"b": 1, "c": 2}, "b": {"d":3}}'::jsonb ~~ 'b.f or (a.b and a.c)';
393+
select '{"a": {"b": 1, "c": 2}, "b": {"d":3}}'::jsonb ~~ 'b.d and (a.b and a.c)';
394+
select '{"a": {"b": [6,5,4], "c": 2}, "b": {"d":3}}'::jsonb ~~ 'b.d and (a.b and a.c)';
395+
381396
--extract entries for index scan
382397

383398
SELECT gin_debug_query_path_value('NOT NOT NOT x(y(NOT (a=1) and NOT (b=2)) OR NOT NOT (c=3)) and z = 5');

0 commit comments

Comments
 (0)