Skip to content
Open
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
5 changes: 5 additions & 0 deletions expected/jsquery.out
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
CREATE EXTENSION jsquery;
SHOW server_version \gset
SELECT substring(:'server_version', '\d+')::int < 19 AS server_version_lt_19
\gset
\if :server_version_lt_19
set escape_string_warning=off;
set standard_conforming_strings=on;
\endif
CREATE TABLE test_jsquery (v jsonb);
\copy test_jsquery from 'data/test_jsquery.data'
select ''::jsquery;
Expand Down
5 changes: 5 additions & 0 deletions expected/jsquery_1.out
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
CREATE EXTENSION jsquery;
SHOW server_version \gset
SELECT substring(:'server_version', '\d+')::int < 19 AS server_version_lt_19
\gset
\if :server_version_lt_19
set escape_string_warning=off;
set standard_conforming_strings=on;
\endif
CREATE TABLE test_jsquery (v jsonb);
\copy test_jsquery from 'data/test_jsquery.data'
select ''::jsquery;
Expand Down
3 changes: 3 additions & 0 deletions jsonb_gin_ops.c
Original file line number Diff line number Diff line change
Expand Up @@ -1153,6 +1153,9 @@ gin_extract_jsonb_path_value_internal(Jsonb *jb, int32 *nentries)
case WJB_END_ARRAY:
if (!stack->parent)
break; /* raw scalar array */
#if PG_VERSION_NUM >= 190000
pg_fallthrough;
#endif
/* fall through */
case WJB_END_OBJECT:
/* Pop the stack */
Expand Down
5 changes: 4 additions & 1 deletion jsquery_extract.c
Original file line number Diff line number Diff line change
Expand Up @@ -179,8 +179,11 @@ recursiveExtract(JsQueryItem *jsq, bool not, bool indirect, PathItem *path)
*result->exactValue = e;
return result;
}
/* fall through */
/* jqiEqual with jqiArray follows */
#if PG_VERSION_NUM >= 190000
pg_fallthrough;
#endif
/* fall through */
case jqiIn:
case jqiOverlap:
case jqiContains:
Expand Down
14 changes: 12 additions & 2 deletions jsquery_io.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@ flattenJsQueryParseItem(StringInfo buf, JsQueryParseItem *item, bool onlyCurrent
case jqiKey:
if (onlyCurrentInPath)
elog(ERROR,"Array length should be last in path");
#if PG_VERSION_NUM >= 190000
pg_fallthrough;
#endif
/* fall through */
case jqiString:
appendBinaryStringInfo(buf, (char*)&item->string.len, sizeof(item->string.len));
Expand Down Expand Up @@ -119,7 +122,10 @@ flattenJsQueryParseItem(StringInfo buf, JsQueryParseItem *item, bool onlyCurrent
case jqiIndexArray:
appendBinaryStringInfo(buf, (char*)&item->arrayIndex,
sizeof(item->arrayIndex));
/* FALLTHROUGH */ /* keep svace quiet */
#if PG_VERSION_NUM >= 190000
pg_fallthrough;
#endif
/* FALLTHROUGH */
case jqiAny:
case jqiAnyArray:
case jqiAnyKey:
Expand All @@ -128,6 +134,7 @@ flattenJsQueryParseItem(StringInfo buf, JsQueryParseItem *item, bool onlyCurrent
case jqiAllKey:
if (onlyCurrentInPath)
elog(ERROR,"Array length should be last in path");
break;
case jqiCurrent:
case jqiNull:
break;
Expand Down Expand Up @@ -236,8 +243,11 @@ printJsQueryItem(StringInfo buf, JsQueryItem *v, bool inKey, bool printBracketes
case jqiKey:
if (inKey)
appendStringInfoChar(buf, '.');
/* fall through */
/* follow next */
#if PG_VERSION_NUM >= 190000
pg_fallthrough;
#endif
/* fall through */
case jqiString:
escape_json(buf, jsqGetString(v, NULL));
break;
Expand Down
130 changes: 86 additions & 44 deletions jsquery_op.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,45 +30,88 @@

#include "jsquery.h"

typedef struct ResultAccum {
StringInfo buf;
/* ResultAccum is used to accumulate values in a Jsonb array. */
typedef struct ResultAccum
{
bool missAppend;
JsonbParseState *jbArrayState;
#if PG_VERSION_NUM >= 190000
JsonbInState jbArrayState; /* initialize by zeroing this structure */
#else
JsonbParseState *jbArrayState; /* initialize with NULL */
#endif
} ResultAccum;


static bool recursiveExecute(JsQueryItem *jsq, JsonbValue *jb, JsQueryItem *jsqLeftArg,
ResultAccum *ra);

/*
* Initialize ResultAccum with the opening WJB_BEGIN_ARRAY token.
*/
static void
raInitialize(ResultAccum *ra)
{
Assert(ra);

/* This initialization works for both PG19+ and earlier */
memset(ra, 0, sizeof(*ra));
pushJsonbValue(&ra->jbArrayState, WJB_BEGIN_ARRAY, NULL);
}

/*
* Finalize ResultAccum with the closing WJB_END_ARRAY token, and return the
* resulting Jsonb.
*/
static Jsonb *
raFinalize(ResultAccum *ra)
{
Assert(ra);

#if PG_VERSION_NUM >= 190000
pushJsonbValue(&ra->jbArrayState, WJB_END_ARRAY, NULL);
return JsonbValueToJsonb(ra->jbArrayState.result);
#else
Assert(ra->jbArrayState); /* it's a pointer only before PG19 */
return JsonbValueToJsonb(pushJsonbValue(&ra->jbArrayState, WJB_END_ARRAY, NULL));
#endif
}

/*
* Append one element.
* Note: append only if "ra" is vaild and appendable; otherwise, do nothing.
*/
static void
appendResult(ResultAccum *ra, JsonbValue *jb)
raAppendElement(ResultAccum *ra, JsonbValue *jb)
{
if (ra == NULL || ra->missAppend == true)
return;

if (ra->jbArrayState == NULL)
pushJsonbValue(&ra->jbArrayState, WJB_BEGIN_ARRAY, NULL);
#if PG_VERSION_NUM < 190000
Assert(ra->jbArrayState); /* it's a pointer only before PG19 */
#endif

pushJsonbValue(&ra->jbArrayState, WJB_ELEM, jb);
}

/*
* Iterate over the Jsonb array and append its elements to "ra".
* Note: "ra" must be valid and appendable.
*/
static void
concatResult(ResultAccum *ra, JsonbParseState *a, JsonbParseState *b)
raAppendArray(ResultAccum *ra, Jsonb *array)
{
Jsonb *value;
JsonbIterator *it;
int32 r;
JsonbValue v;

Assert(a);
Assert(b);

ra->jbArrayState = a;
Assert(ra && ra->missAppend == false);
#if PG_VERSION_NUM < 190000
Assert(ra->jbArrayState); /* it's a pointer only before PG19 */
#endif

value = JsonbValueToJsonb(pushJsonbValue(&b, WJB_END_ARRAY, NULL));
it = JsonbIteratorInit(&value->root);
it = JsonbIteratorInit(&array->root);

while((r = JsonbIteratorNext(&it, &v, true)) != WJB_DONE)
while ((r = JsonbIteratorNext(&it, &v, true)) != WJB_DONE)
if (r == WJB_ELEM)
pushJsonbValue(&ra->jbArrayState, WJB_ELEM, &v);
}
Expand Down Expand Up @@ -460,32 +503,35 @@ recursiveExecute(JsQueryItem *jsq, JsonbValue *jb, JsQueryItem *jsqLeftArg,
switch(jsq->type) {
case jqiAnd:
{
JsonbParseState *saveJbArrayState = NULL;
/*
* Accumulate the array in "raTmp" if needed. Don't mess with
* "ra" in case the result turns out to be false.
*/
ResultAccum raTmpData;
ResultAccum *raTmp = NULL;

jsqGetLeftArg(jsq, &elem);
if (ra && ra->missAppend == false)
{
saveJbArrayState = ra->jbArrayState;
ra->jbArrayState = NULL;
/* need to accumulate */
raTmp = &raTmpData;
raInitialize(raTmp);
}

res = recursiveExecute(&elem, jb, jsqLeftArg, ra);
jsqGetLeftArg(jsq, &elem);
res = recursiveExecute(&elem, jb, jsqLeftArg, raTmp);
if (res == true)
{
jsqGetRightArg(jsq, &elem);
res = recursiveExecute(&elem, jb, jsqLeftArg, ra);
res = recursiveExecute(&elem, jb, jsqLeftArg, raTmp);
}

/* Append the array accumulated in "raTmp" to "ra" if needed. */
if (ra && ra->missAppend == false)
{
Jsonb *array = raFinalize(raTmp);

if (res == true)
{
if (saveJbArrayState != NULL)
/* append args lists to current */
concatResult(ra, saveJbArrayState, ra->jbArrayState);
}
else
ra->jbArrayState = saveJbArrayState;
raAppendArray(ra, array);
}

break;
Expand Down Expand Up @@ -525,7 +571,7 @@ recursiveExecute(JsQueryItem *jsq, JsonbValue *jb, JsQueryItem *jsqLeftArg,
{
if (jsqGetNext(jsq, &elem) == false)
{
appendResult(ra, v);
raAppendElement(ra, v);
res = true;
}
else
Expand All @@ -537,7 +583,7 @@ recursiveExecute(JsQueryItem *jsq, JsonbValue *jb, JsQueryItem *jsqLeftArg,
case jqiCurrent:
if (jsqGetNext(jsq, &elem) == false)
{
appendResult(ra, jb);
raAppendElement(ra, jb);
res = true;
}
else if (JsonbType(jb) == jbvScalar)
Expand Down Expand Up @@ -567,7 +613,7 @@ recursiveExecute(JsQueryItem *jsq, JsonbValue *jb, JsQueryItem *jsqLeftArg,
if (jsqGetNext(jsq, &elem) == false)
{
res = true;
appendResult(ra, jb);
raAppendElement(ra, jb);
}
else if (recursiveExecute(&elem, jb, NULL, ra))
res = true;
Expand All @@ -578,7 +624,7 @@ recursiveExecute(JsQueryItem *jsq, JsonbValue *jb, JsQueryItem *jsqLeftArg,
if (jsqGetNext(jsq, &elem) == false)
{
res = true;
appendResult(ra, jb);
raAppendElement(ra, jb);
}
if ((res = recursiveExecute(&elem, jb, NULL, ra)) == true)
{
Expand All @@ -605,7 +651,7 @@ recursiveExecute(JsQueryItem *jsq, JsonbValue *jb, JsQueryItem *jsqLeftArg,

while(ra && (r = JsonbIteratorNext(&it, &v, true)) != WJB_DONE)
if (r == WJB_ELEM)
appendResult(ra, &v);
raAppendElement(ra, &v);

break;
}
Expand Down Expand Up @@ -651,7 +697,7 @@ recursiveExecute(JsQueryItem *jsq, JsonbValue *jb, JsQueryItem *jsqLeftArg,
if (jsqGetNext(jsq, &elem) == false)
{
res = true;
appendResult(ra, v);
raAppendElement(ra, v);
}
else
res = recursiveExecute(&elem, v, NULL, ra);
Expand All @@ -677,7 +723,7 @@ recursiveExecute(JsQueryItem *jsq, JsonbValue *jb, JsQueryItem *jsqLeftArg,

while(ra && (r = JsonbIteratorNext(&it, &v, true)) != WJB_DONE)
if (r == WJB_VALUE)
appendResult(ra, &v);
raAppendElement(ra, &v);

break;
}
Expand Down Expand Up @@ -763,7 +809,7 @@ recursiveExecute(JsQueryItem *jsq, JsonbValue *jb, JsQueryItem *jsqLeftArg,
if (res) {
if (jsqGetNext(jsq, &elem) == false)
{
appendResult(ra, jb);
raAppendElement(ra, jb);
res = true;
}
else
Expand Down Expand Up @@ -842,21 +888,17 @@ json_jsquery_filter(PG_FUNCTION_ARGS)
jbv.val.binary.len = VARSIZE_ANY_EXHDR(jb);

jsqInit(&jsq, jq);
memset(&ra, 0, sizeof(ra));
raInitialize(&ra);

recursiveExecute(&jsq, &jbv, NULL, &ra);

if (ra.jbArrayState)
{
res = JsonbValueToJsonb(
pushJsonbValue(&ra.jbArrayState, WJB_END_ARRAY, NULL)
);
}
res = raFinalize(&ra);

PG_FREE_IF_COPY(jb, 0);
PG_FREE_IF_COPY(jq, 1);

if (res)
/* If array is empty, we must return NULL. */
if (res && JsonContainerSize(&res->root) > 0)
PG_RETURN_JSONB_P(res);

PG_RETURN_NULL();
Expand Down
6 changes: 3 additions & 3 deletions jsquery_scan.l
Original file line number Diff line number Diff line change
Expand Up @@ -248,9 +248,9 @@ static keyword keywords[] = {
};

static int
checkSpecialVal()
checkSpecialVal(void)
{
int res = STRING_P;
int res = STRING_P;
int diff;
keyword *StopLow = keywords,
*StopHigh = keywords + lengthof(keywords),
Expand Down Expand Up @@ -288,7 +288,7 @@ checkSpecialVal()
}

static JsQueryHint
checkHint()
checkHint(void)
{
if (scanstring.len <= 2 || strncmp(scanstring.val, "--", 2) != 0)
return jsqIndexDefault;
Expand Down
Loading