JsonbValue *
pushJsonbBinary(JsonbParseState **pstate, JsonbContainer *jsonb_container)
{
- JsonbIterator *jsonb_iterator;
- JsonbValue jsonb_iterator_value;
- int32 jsonb_iterator_token;
- JsonbValue *return_jsonb_value = NULL;
+ JsonbIterator *jsonb_iterator;
+ JsonbValue jsonb_iterator_value;
+ int32 jsonb_iterator_token;
+ JsonbValue *return_jsonb_value = NULL;
jsonb_iterator = JsonbIteratorInit((void *)jsonb_container);
while ((jsonb_iterator_token = JsonbIteratorNext(&jsonb_iterator, &jsonb_iterator_value, false)) != WJB_DONE)
JsonbValue *
pushJsonbValueBlind(JsonbParseState **pstate, JsonbIteratorToken jsonb_iterator_token, JsonbValue *jsonb_iterator_value)
{
- JsonbValue *return_jsonb_value = NULL;
+ JsonbValue *return_jsonb_value = NULL;
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);
}
jsonbModifyPath(Jsonb *jsonb_a, ArrayType *array_path, Jsonb *jsonb_b)
{
/* pointers to return jsonb value data and state to be converted to jsonb on return */
- JsonbParseState *state = NULL;
- JsonbValue *return_jsonb_value = NULL;
+ JsonbParseState *state = NULL;
+ JsonbValue *return_jsonb_value = NULL;
/* pointer to iterator for input jsonb */
- 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;
- int32 jsonb_replacement_iterator_token;
+ JsonbIterator *jsonb_iterator;
+ JsonbValue jsonb_iterator_value;
+ int32 jsonb_iterator_token;
+
+ JsonbIterator *jsonb_replacement_iterator;
+ JsonbValue jsonb_replacement_iterator_value;
+ int32 jsonb_replacement_iterator_token;
/*
* array element variables for use during deconstruction
* count is the depth we will be looking from the first matching key
*/
- Datum *datums;
- bool *nulls;
- int32 count;
+ Datum *datums;
+ bool *nulls;
+ int32 count;
/* the current key we are looking for, starting with the first key */
- text *key_on = NULL;
- int32 index_on = 0;
- int32 nest_level = 0;
- int32 array_level = 0;
- int32 skip_level = 0;
- int32 push_nest_level = 0;
- bool push = true;
+ text *key_on = NULL;
+ int32 index_on = 0;
+ int32 nest_level = 0;
+ int32 array_level = 0;
+ int32 skip_level = 0;
+ int32 push_nest_level = 0;
+ bool push = true;
/* assert input_array is a text array type */
Assert(ARR_ELEMTYPE(array_path) == TEXTOID);
{
case WJB_BEGIN_ARRAY:
array_level++;
- break;
+ break;
case WJB_BEGIN_OBJECT:
nest_level++;
- break;
+ break;
case WJB_ELEM:
case WJB_KEY:
/*
if (skip_level == 0 && ((jsonb_iterator_token == WJB_KEY && nest_level-1 == index_on && array_level == 0) ||
(jsonb_iterator_token == WJB_ELEM && nest_level == 0 && array_level == 1)))
{
- if ((jsonb_iterator_value.type == jbvNull && key_on == NULL) ||
- (key_on != NULL && (jsonb_iterator_value.val.string.len == VARSIZE_ANY_EXHDR(key_on)) &&
+ if ((!nulls[index_on] && (jsonb_iterator_value.val.string.len == VARSIZE_ANY_EXHDR(key_on)) &&
(memcmp(jsonb_iterator_value.val.string.val, VARDATA_ANY(key_on), jsonb_iterator_value.val.string.len) == 0)))
{
/* if we have not yet reached the last index in the array / key chain move on and check the next */
index_on++;
if (!nulls[index_on])
key_on = DatumGetTextP(datums[index_on]);
- else
- key_on = NULL;
}
/* if we have reached the last index, the we can modify this level */
else
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))))
- {
- push_nest_level++;
- }
-
- if ((jsonb_replacement_iterator_token == WJB_KEY) ||
- (jsonb_replacement_iterator_token == WJB_VALUE) ||
- (jsonb_replacement_iterator_token == WJB_ELEM) || (push_nest_level != 1))
+ 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)
{
- return_jsonb_value = pushJsonbValueBlind(&state, jsonb_replacement_iterator_token, &jsonb_replacement_iterator_value);
+ return_jsonb_value = pushJsonbValue(&state, WJB_ELEM, &jsonb_replacement_iterator_value);
}
-
- if (((jsonb_last_token == WJB_BEGIN_ARRAY) ||
- (jsonb_last_token == WJB_VALUE)) &&
- (jsonb_replacement_iterator_token == WJB_END_ARRAY))
+ else
{
- push_nest_level--;
+ return_jsonb_value = pushJsonbValue(&state, WJB_KEY, &jsonb_iterator_value);
+ return_jsonb_value = pushJsonbValue(&state, WJB_VALUE, &jsonb_replacement_iterator_value);
}
- 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 or 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);
}
}
}
}
}
}
+ /* switch end */
}
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)
nest_level--;
if (skip_level == nest_level && array_level == 0)
skip_level = 0;
- break;
+ break;
case WJB_END_ARRAY:
array_level--;
if (skip_level == nest_level && array_level == 0)
skip_level = 0;
- break;
+ break;
case WJB_VALUE:
if (skip_level == nest_level)
skip_level = 0;
+ /* switch end */
}
}
- 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);