X-Git-Url: https://git.8kb.co.uk/?p=postgresql%2Fpg_jsonb_opx;a=blobdiff_plain;f=jsonb_utilsx.c;fp=jsonb_utilsx.c;h=f7a3de978356f1d7b5f0f787d83deb88e88dfedb;hp=a08829c21f9ff4cfbaa84a7caf71401ce03d295a;hb=b2272ef16fe0e6aa9b769f4517e9fe7177e3f444;hpb=bf6318c60bd05043800c698a6b14f6aaa17a4824 diff --git a/jsonb_utilsx.c b/jsonb_utilsx.c index a08829c..f7a3de9 100755 --- a/jsonb_utilsx.c +++ b/jsonb_utilsx.c @@ -40,8 +40,7 @@ pushJsonbValueBlind(JsonbParseState **pstate, JsonbIteratorToken jsonb_iterator_ if ((jsonb_iterator_token == WJB_KEY) || (jsonb_iterator_token == WJB_VALUE) || - (jsonb_iterator_token == WJB_ELEM) || - (jsonb_iterator_token == WJB_BEGIN_ARRAY && jsonb_iterator_value->val.array.rawScalar)) + (jsonb_iterator_token == WJB_ELEM)) { return_jsonb_value = pushJsonbValue(pstate, jsonb_iterator_token, jsonb_iterator_value); } @@ -62,7 +61,6 @@ jsonbModifyPath(Jsonb *jsonb_a, ArrayType *array_path, Jsonb *jsonb_b) JsonbIterator *jsonb_iterator; JsonbValue jsonb_iterator_value; int32 jsonb_iterator_token; - int32 jsonb_last_token = 0; JsonbIterator *jsonb_replacement_iterator; JsonbValue jsonb_replacement_iterator_value; @@ -155,35 +153,45 @@ jsonbModifyPath(Jsonb *jsonb_a, ArrayType *array_path, Jsonb *jsonb_b) if (jsonb_b != NULL) { jsonb_replacement_iterator = JsonbIteratorInit(&jsonb_b->root); - while ((jsonb_replacement_iterator_token = JsonbIteratorNext(&jsonb_replacement_iterator, &jsonb_replacement_iterator_value, false)) != WJB_DONE) + /* if the replacement value is a scalar then it will replace the current element or value */ + if (JB_ROOT_IS_SCALAR(jsonb_b)) { - if (((jsonb_last_token == jsonb_replacement_iterator_token) && - (jsonb_last_token != WJB_VALUE)) || - ((jsonb_last_token == WJB_VALUE) && - ((jsonb_replacement_iterator_token == WJB_BEGIN_OBJECT) || - (jsonb_replacement_iterator_token == WJB_BEGIN_ARRAY)))) + jsonb_replacement_iterator_token = JsonbIteratorNext(&jsonb_replacement_iterator, &jsonb_replacement_iterator_value, false); + jsonb_replacement_iterator_token = JsonbIteratorNext(&jsonb_replacement_iterator, &jsonb_replacement_iterator_value, false); + + if (jsonb_iterator_token == WJB_ELEM) { - push_nest_level++; + return_jsonb_value = pushJsonbValue(&state, WJB_ELEM, &jsonb_replacement_iterator_value); } - - if ((jsonb_replacement_iterator_token == WJB_KEY) || - (jsonb_replacement_iterator_token == WJB_VALUE) || - (jsonb_replacement_iterator_token == WJB_ELEM) || (push_nest_level != 1)) + else { - return_jsonb_value = pushJsonbValueBlind(&state, jsonb_replacement_iterator_token, &jsonb_replacement_iterator_value); + return_jsonb_value = pushJsonbValue(&state, WJB_KEY, &jsonb_iterator_value); + return_jsonb_value = pushJsonbValue(&state, WJB_VALUE, &jsonb_replacement_iterator_value); } - - if (((jsonb_last_token == WJB_BEGIN_ARRAY) || - (jsonb_last_token == WJB_VALUE)) && - (jsonb_replacement_iterator_token == WJB_END_ARRAY)) - { - push_nest_level--; - } - else if (((jsonb_last_token == WJB_BEGIN_OBJECT) || - (jsonb_last_token == WJB_VALUE)) && - (jsonb_replacement_iterator_token == WJB_END_OBJECT)) + } + /* otherwise assume this is the replacement for the whole element /key-value pair */ + else { + while ((jsonb_replacement_iterator_token = JsonbIteratorNext(&jsonb_replacement_iterator, &jsonb_replacement_iterator_value, false)) != WJB_DONE) { - push_nest_level--; + if (push_nest_level == 0 && jsonb_iterator_token == WJB_KEY && jsonb_replacement_iterator_token == WJB_BEGIN_ARRAY) + { + return_jsonb_value = pushJsonbValue(&state, WJB_KEY, &jsonb_iterator_value); + } + + if ((jsonb_replacement_iterator_token == WJB_BEGIN_OBJECT) || (jsonb_replacement_iterator_token == WJB_BEGIN_ARRAY)) + push_nest_level++; + + if ((push_nest_level > 1) || + (jsonb_iterator_token == WJB_ELEM && jsonb_replacement_iterator_token != WJB_BEGIN_ARRAY && jsonb_replacement_iterator_token != WJB_END_ARRAY) || + (jsonb_iterator_token == WJB_KEY && jsonb_replacement_iterator_token != WJB_BEGIN_OBJECT && jsonb_replacement_iterator_token != WJB_END_OBJECT)) + { + return_jsonb_value = pushJsonbValueBlind(&state, jsonb_replacement_iterator_token, &jsonb_replacement_iterator_value); + } + + if ((jsonb_replacement_iterator_token == WJB_END_OBJECT || jsonb_replacement_iterator_token == WJB_END_ARRAY)) + push_nest_level--; + + Assert(push_nest_level >= 0); } } } @@ -199,7 +207,6 @@ jsonbModifyPath(Jsonb *jsonb_a, ArrayType *array_path, Jsonb *jsonb_b) if (push && (skip_level == 0 || nest_level < skip_level)) { return_jsonb_value = pushJsonbValueBlind(&state, jsonb_iterator_token, &jsonb_iterator_value); - jsonb_last_token = jsonb_iterator_token; } switch (jsonb_iterator_token) @@ -220,9 +227,12 @@ jsonbModifyPath(Jsonb *jsonb_a, ArrayType *array_path, Jsonb *jsonb_b) } } - if (return_jsonb_value->type == jbvArray && return_jsonb_value->val.array.rawScalar && return_jsonb_value->val.array.nElems == 0) + if (return_jsonb_value->type == jbvArray) { - return_jsonb_value->val.array.rawScalar = false; + if (return_jsonb_value->val.array.rawScalar && return_jsonb_value->val.array.nElems == 0) + return_jsonb_value->val.array.rawScalar = false; + else if (JB_ROOT_IS_SCALAR(jsonb_a) && !return_jsonb_value->val.array.rawScalar && return_jsonb_value->val.array.nElems == 1) + return_jsonb_value->val.array.rawScalar = true; } return JsonbValueToJsonb(return_jsonb_value);