mirror of
https://github.com/postgres/postgres.git
synced 2025-06-05 00:02:04 -04:00
Minor cleanup of jsonb_util.c
Move the functions around to group related functions together. Remove binequal argument from lengthCompareJsonbStringValue, moving that responsibility to lengthCompareJsonbPair. Fix typo in comment.
This commit is contained in:
parent
d3c72e23df
commit
ff7bbb0176
@ -68,7 +68,7 @@ static JsonbParseState *pushState(JsonbParseState **pstate);
|
|||||||
static void appendKey(JsonbParseState *pstate, JsonbValue *scalarVal);
|
static void appendKey(JsonbParseState *pstate, JsonbValue *scalarVal);
|
||||||
static void appendValue(JsonbParseState *pstate, JsonbValue *scalarVal);
|
static void appendValue(JsonbParseState *pstate, JsonbValue *scalarVal);
|
||||||
static void appendElement(JsonbParseState *pstate, JsonbValue *scalarVal);
|
static void appendElement(JsonbParseState *pstate, JsonbValue *scalarVal);
|
||||||
static int lengthCompareJsonbStringValue(const void *a, const void *b, void *arg);
|
static int lengthCompareJsonbStringValue(const void *a, const void *b);
|
||||||
static int lengthCompareJsonbPair(const void *a, const void *b, void *arg);
|
static int lengthCompareJsonbPair(const void *a, const void *b, void *arg);
|
||||||
static void uniqueifyJsonbObject(JsonbValue *object);
|
static void uniqueifyJsonbObject(JsonbValue *object);
|
||||||
|
|
||||||
@ -329,7 +329,7 @@ findJsonbValueFromContainer(JsonbContainer *container, uint32 flags,
|
|||||||
candidate.val.string.val = data + JBE_OFF(*entry);
|
candidate.val.string.val = data + JBE_OFF(*entry);
|
||||||
candidate.val.string.len = JBE_LEN(*entry);
|
candidate.val.string.len = JBE_LEN(*entry);
|
||||||
|
|
||||||
difference = lengthCompareJsonbStringValue(&candidate, key, NULL);
|
difference = lengthCompareJsonbStringValue(&candidate, key);
|
||||||
|
|
||||||
if (difference == 0)
|
if (difference == 0)
|
||||||
{
|
{
|
||||||
@ -533,6 +533,86 @@ pushJsonbValue(JsonbParseState **pstate, JsonbIteratorToken seq,
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* pushJsonbValue() worker: Iteration-like forming of Jsonb
|
||||||
|
*/
|
||||||
|
static JsonbParseState *
|
||||||
|
pushState(JsonbParseState **pstate)
|
||||||
|
{
|
||||||
|
JsonbParseState *ns = palloc(sizeof(JsonbParseState));
|
||||||
|
|
||||||
|
ns->next = *pstate;
|
||||||
|
return ns;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* pushJsonbValue() worker: Append a pair key to state when generating a Jsonb
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
appendKey(JsonbParseState *pstate, JsonbValue *string)
|
||||||
|
{
|
||||||
|
JsonbValue *object = &pstate->contVal;
|
||||||
|
|
||||||
|
Assert(object->type == jbvObject);
|
||||||
|
Assert(string->type == jbvString);
|
||||||
|
|
||||||
|
if (object->val.object.nPairs >= JSONB_MAX_PAIRS)
|
||||||
|
ereport(ERROR,
|
||||||
|
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
|
||||||
|
errmsg("number of jsonb object pairs exceeds the maximum allowed (%zu)",
|
||||||
|
JSONB_MAX_PAIRS)));
|
||||||
|
|
||||||
|
if (object->val.object.nPairs >= pstate->size)
|
||||||
|
{
|
||||||
|
pstate->size *= 2;
|
||||||
|
object->val.object.pairs = repalloc(object->val.object.pairs,
|
||||||
|
sizeof(JsonbPair) * pstate->size);
|
||||||
|
}
|
||||||
|
|
||||||
|
object->val.object.pairs[object->val.object.nPairs].key = *string;
|
||||||
|
object->val.object.pairs[object->val.object.nPairs].order = object->val.object.nPairs;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* pushJsonbValue() worker: Append a pair value to state when generating a
|
||||||
|
* Jsonb
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
appendValue(JsonbParseState *pstate, JsonbValue *scalarVal)
|
||||||
|
{
|
||||||
|
JsonbValue *object = &pstate->contVal;
|
||||||
|
|
||||||
|
Assert(object->type == jbvObject);
|
||||||
|
|
||||||
|
object->val.object.pairs[object->val.object.nPairs++].value = *scalarVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* pushJsonbValue() worker: Append an element to state when generating a Jsonb
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
appendElement(JsonbParseState *pstate, JsonbValue *scalarVal)
|
||||||
|
{
|
||||||
|
JsonbValue *array = &pstate->contVal;
|
||||||
|
|
||||||
|
Assert(array->type == jbvArray);
|
||||||
|
|
||||||
|
if (array->val.array.nElems >= JSONB_MAX_ELEMS)
|
||||||
|
ereport(ERROR,
|
||||||
|
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
|
||||||
|
errmsg("number of jsonb array elements exceeds the maximum allowed (%zu)",
|
||||||
|
JSONB_MAX_ELEMS)));
|
||||||
|
|
||||||
|
if (array->val.array.nElems >= pstate->size)
|
||||||
|
{
|
||||||
|
pstate->size *= 2;
|
||||||
|
array->val.array.elems = repalloc(array->val.array.elems,
|
||||||
|
sizeof(JsonbValue) * pstate->size);
|
||||||
|
}
|
||||||
|
|
||||||
|
array->val.array.elems[array->val.array.nElems++] = *scalarVal;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Given a JsonbContainer, expand to JsonbIterator to iterate over items
|
* Given a JsonbContainer, expand to JsonbIterator to iterate over items
|
||||||
* fully expanded to in-memory representation for manipulation.
|
* fully expanded to in-memory representation for manipulation.
|
||||||
@ -709,6 +789,101 @@ JsonbIteratorNext(JsonbIterator **it, JsonbValue *val, bool skipNested)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize an iterator for iterating all elements in a container.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
iteratorFromContainer(JsonbIterator *it, JsonbContainer *container)
|
||||||
|
{
|
||||||
|
it->containerType = container->header & (JB_FARRAY | JB_FOBJECT);
|
||||||
|
it->nElems = container->header & JB_CMASK;
|
||||||
|
it->buffer = (char *) container;
|
||||||
|
|
||||||
|
/* Array starts just after header */
|
||||||
|
it->meta = container->children;
|
||||||
|
it->state = jbi_start;
|
||||||
|
|
||||||
|
switch (it->containerType)
|
||||||
|
{
|
||||||
|
case JB_FARRAY:
|
||||||
|
it->dataProper =
|
||||||
|
(char *) it->meta + it->nElems * sizeof(JEntry);
|
||||||
|
it->isScalar = (container->header & JB_FSCALAR) != 0;
|
||||||
|
/* This is either a "raw scalar", or an array */
|
||||||
|
Assert(!it->isScalar || it->nElems == 1);
|
||||||
|
break;
|
||||||
|
case JB_FOBJECT:
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Offset reflects that nElems indicates JsonbPairs in an object.
|
||||||
|
* Each key and each value contain Jentry metadata just the same.
|
||||||
|
*/
|
||||||
|
it->dataProper =
|
||||||
|
(char *) it->meta + it->nElems * sizeof(JEntry) * 2;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
elog(ERROR, "unknown type of jsonb container");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* JsonbIteratorNext() worker
|
||||||
|
*
|
||||||
|
* Returns bool indicating if v was a non-jbvBinary container, and thus if
|
||||||
|
* further recursion is required by caller (according to its skipNested
|
||||||
|
* preference). If it is required, we set the caller's iterator for further
|
||||||
|
* recursion into the nested value. If we're going to skip nested items, just
|
||||||
|
* set v to a jbvBinary value, but don't set caller's iterator.
|
||||||
|
*
|
||||||
|
* Unlike with containers (either in this function or in any
|
||||||
|
* JsonbIteratorNext() infrastructure), we fully convert from what is
|
||||||
|
* ultimately a Jsonb on-disk representation, to a JsonbValue in-memory
|
||||||
|
* representation (for scalar values only). JsonbIteratorNext() initializes
|
||||||
|
* container Jsonbvalues, but without a sane private buffer. For scalar values
|
||||||
|
* it has to be done for real (even if we don't actually allocate more memory
|
||||||
|
* to do this. The point is that our JsonbValues scalars can be passed around
|
||||||
|
* anywhere).
|
||||||
|
*/
|
||||||
|
static bool
|
||||||
|
formIterIsContainer(JsonbIterator **it, JsonbValue *val, JEntry *ent,
|
||||||
|
bool skipNested)
|
||||||
|
{
|
||||||
|
fillJsonbValue(ent, (*it)->dataProper, val);
|
||||||
|
|
||||||
|
if (IsAJsonbScalar(val) || skipNested)
|
||||||
|
return false;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* It's a container type, so setup caller's iterator to point to
|
||||||
|
* that, and return indication of that.
|
||||||
|
*
|
||||||
|
* Get child iterator.
|
||||||
|
*/
|
||||||
|
JsonbIterator *child = palloc(sizeof(JsonbIterator));
|
||||||
|
|
||||||
|
iteratorFromContainer(child, val->val.binary.data);
|
||||||
|
|
||||||
|
child->parent = *it;
|
||||||
|
*it = child;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* JsonbIteratorNext() worker: Return parent, while freeing memory for current
|
||||||
|
* iterator
|
||||||
|
*/
|
||||||
|
static JsonbIterator *
|
||||||
|
freeAndGetParent(JsonbIterator *it)
|
||||||
|
{
|
||||||
|
JsonbIterator *v = it->parent;
|
||||||
|
|
||||||
|
pfree(it);
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Worker for "contains" operator's function
|
* Worker for "contains" operator's function
|
||||||
*
|
*
|
||||||
@ -1015,7 +1190,7 @@ compareJsonbScalarValue(JsonbValue *aScalar, JsonbValue *bScalar)
|
|||||||
case jbvNull:
|
case jbvNull:
|
||||||
return 0;
|
return 0;
|
||||||
case jbvString:
|
case jbvString:
|
||||||
return lengthCompareJsonbStringValue(aScalar, bScalar, NULL);
|
return lengthCompareJsonbStringValue(aScalar, bScalar);
|
||||||
case jbvNumeric:
|
case jbvNumeric:
|
||||||
return DatumGetInt32(DirectFunctionCall2(numeric_cmp,
|
return DatumGetInt32(DirectFunctionCall2(numeric_cmp,
|
||||||
PointerGetDatum(aScalar->val.numeric),
|
PointerGetDatum(aScalar->val.numeric),
|
||||||
@ -1059,7 +1234,7 @@ lexicalCompareJsonbStringValue(const void *a, const void *b)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Rervere 'len' bytes, at the end of the buffer, enlarging it if necessary.
|
* Reserve 'len' bytes, at the end of the buffer, enlarging it if necessary.
|
||||||
* Returns the offset to the reserved area. The caller is expected to copy
|
* Returns the offset to the reserved area. The caller is expected to copy
|
||||||
* the data to the reserved area later with copyToBuffer()
|
* the data to the reserved area later with copyToBuffer()
|
||||||
*/
|
*/
|
||||||
@ -1367,181 +1542,6 @@ convertJsonbScalar(convertState *buffer, JEntry *jentry, JsonbValue *scalarVal)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Initialize an iterator for iterating all elements in a container.
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
iteratorFromContainer(JsonbIterator *it, JsonbContainer *container)
|
|
||||||
{
|
|
||||||
it->containerType = container->header & (JB_FARRAY | JB_FOBJECT);
|
|
||||||
it->nElems = container->header & JB_CMASK;
|
|
||||||
it->buffer = (char *) container;
|
|
||||||
|
|
||||||
/* Array starts just after header */
|
|
||||||
it->meta = container->children;
|
|
||||||
it->state = jbi_start;
|
|
||||||
|
|
||||||
switch (it->containerType)
|
|
||||||
{
|
|
||||||
case JB_FARRAY:
|
|
||||||
it->dataProper =
|
|
||||||
(char *) it->meta + it->nElems * sizeof(JEntry);
|
|
||||||
it->isScalar = (container->header & JB_FSCALAR) != 0;
|
|
||||||
/* This is either a "raw scalar", or an array */
|
|
||||||
Assert(!it->isScalar || it->nElems == 1);
|
|
||||||
break;
|
|
||||||
case JB_FOBJECT:
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Offset reflects that nElems indicates JsonbPairs in an object.
|
|
||||||
* Each key and each value contain Jentry metadata just the same.
|
|
||||||
*/
|
|
||||||
it->dataProper =
|
|
||||||
(char *) it->meta + it->nElems * sizeof(JEntry) * 2;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
elog(ERROR, "unknown type of jsonb container");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* JsonbIteratorNext() worker
|
|
||||||
*
|
|
||||||
* Returns bool indicating if v was a non-jbvBinary container, and thus if
|
|
||||||
* further recursion is required by caller (according to its skipNested
|
|
||||||
* preference). If it is required, we set the caller's iterator for further
|
|
||||||
* recursion into the nested value. If we're going to skip nested items, just
|
|
||||||
* set v to a jbvBinary value, but don't set caller's iterator.
|
|
||||||
*
|
|
||||||
* Unlike with containers (either in this function or in any
|
|
||||||
* JsonbIteratorNext() infrastructure), we fully convert from what is
|
|
||||||
* ultimately a Jsonb on-disk representation, to a JsonbValue in-memory
|
|
||||||
* representation (for scalar values only). JsonbIteratorNext() initializes
|
|
||||||
* container Jsonbvalues, but without a sane private buffer. For scalar values
|
|
||||||
* it has to be done for real (even if we don't actually allocate more memory
|
|
||||||
* to do this. The point is that our JsonbValues scalars can be passed around
|
|
||||||
* anywhere).
|
|
||||||
*/
|
|
||||||
static bool
|
|
||||||
formIterIsContainer(JsonbIterator **it, JsonbValue *val, JEntry *ent,
|
|
||||||
bool skipNested)
|
|
||||||
{
|
|
||||||
fillJsonbValue(ent, (*it)->dataProper, val);
|
|
||||||
|
|
||||||
if (IsAJsonbScalar(val) || skipNested)
|
|
||||||
return false;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* It's a container type, so setup caller's iterator to point to
|
|
||||||
* that, and return indication of that.
|
|
||||||
*
|
|
||||||
* Get child iterator.
|
|
||||||
*/
|
|
||||||
JsonbIterator *child = palloc(sizeof(JsonbIterator));
|
|
||||||
|
|
||||||
iteratorFromContainer(child, val->val.binary.data);
|
|
||||||
|
|
||||||
child->parent = *it;
|
|
||||||
*it = child;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* JsonbIteratorNext() worker: Return parent, while freeing memory for current
|
|
||||||
* iterator
|
|
||||||
*/
|
|
||||||
static JsonbIterator *
|
|
||||||
freeAndGetParent(JsonbIterator *it)
|
|
||||||
{
|
|
||||||
JsonbIterator *v = it->parent;
|
|
||||||
|
|
||||||
pfree(it);
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* pushJsonbValue() worker: Iteration-like forming of Jsonb
|
|
||||||
*/
|
|
||||||
static JsonbParseState *
|
|
||||||
pushState(JsonbParseState **pstate)
|
|
||||||
{
|
|
||||||
JsonbParseState *ns = palloc(sizeof(JsonbParseState));
|
|
||||||
|
|
||||||
ns->next = *pstate;
|
|
||||||
return ns;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* pushJsonbValue() worker: Append a pair key to state when generating a Jsonb
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
appendKey(JsonbParseState *pstate, JsonbValue *string)
|
|
||||||
{
|
|
||||||
JsonbValue *object = &pstate->contVal;
|
|
||||||
|
|
||||||
Assert(object->type == jbvObject);
|
|
||||||
Assert(string->type == jbvString);
|
|
||||||
|
|
||||||
if (object->val.object.nPairs >= JSONB_MAX_PAIRS)
|
|
||||||
ereport(ERROR,
|
|
||||||
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
|
|
||||||
errmsg("number of jsonb object pairs exceeds the maximum allowed (%zu)",
|
|
||||||
JSONB_MAX_PAIRS)));
|
|
||||||
|
|
||||||
if (object->val.object.nPairs >= pstate->size)
|
|
||||||
{
|
|
||||||
pstate->size *= 2;
|
|
||||||
object->val.object.pairs = repalloc(object->val.object.pairs,
|
|
||||||
sizeof(JsonbPair) * pstate->size);
|
|
||||||
}
|
|
||||||
|
|
||||||
object->val.object.pairs[object->val.object.nPairs].key = *string;
|
|
||||||
object->val.object.pairs[object->val.object.nPairs].order = object->val.object.nPairs;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* pushJsonbValue() worker: Append a pair value to state when generating a
|
|
||||||
* Jsonb
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
appendValue(JsonbParseState *pstate, JsonbValue *scalarVal)
|
|
||||||
{
|
|
||||||
JsonbValue *object = &pstate->contVal;
|
|
||||||
|
|
||||||
Assert(object->type == jbvObject);
|
|
||||||
|
|
||||||
object->val.object.pairs[object->val.object.nPairs++].value = *scalarVal;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* pushJsonbValue() worker: Append an element to state when generating a Jsonb
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
appendElement(JsonbParseState *pstate, JsonbValue *scalarVal)
|
|
||||||
{
|
|
||||||
JsonbValue *array = &pstate->contVal;
|
|
||||||
|
|
||||||
Assert(array->type == jbvArray);
|
|
||||||
|
|
||||||
if (array->val.array.nElems >= JSONB_MAX_ELEMS)
|
|
||||||
ereport(ERROR,
|
|
||||||
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
|
|
||||||
errmsg("number of jsonb array elements exceeds the maximum allowed (%zu)",
|
|
||||||
JSONB_MAX_ELEMS)));
|
|
||||||
|
|
||||||
if (array->val.array.nElems >= pstate->size)
|
|
||||||
{
|
|
||||||
pstate->size *= 2;
|
|
||||||
array->val.array.elems = repalloc(array->val.array.elems,
|
|
||||||
sizeof(JsonbValue) * pstate->size);
|
|
||||||
}
|
|
||||||
|
|
||||||
array->val.array.elems[array->val.array.nElems++] = *scalarVal;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Compare two jbvString JsonbValue values, a and b.
|
* Compare two jbvString JsonbValue values, a and b.
|
||||||
*
|
*
|
||||||
@ -1553,13 +1553,9 @@ appendElement(JsonbParseState *pstate, JsonbValue *scalarVal)
|
|||||||
*
|
*
|
||||||
* a and b are first sorted based on their length. If a tie-breaker is
|
* a and b are first sorted based on their length. If a tie-breaker is
|
||||||
* required, only then do we consider string binary equality.
|
* required, only then do we consider string binary equality.
|
||||||
*
|
|
||||||
* Third argument 'binequal' may point to a bool. If it's set, *binequal is set
|
|
||||||
* to true iff a and b have full binary equality, since some callers have an
|
|
||||||
* interest in whether the two values are equal or merely equivalent.
|
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
lengthCompareJsonbStringValue(const void *a, const void *b, void *binequal)
|
lengthCompareJsonbStringValue(const void *a, const void *b)
|
||||||
{
|
{
|
||||||
const JsonbValue *va = (const JsonbValue *) a;
|
const JsonbValue *va = (const JsonbValue *) a;
|
||||||
const JsonbValue *vb = (const JsonbValue *) b;
|
const JsonbValue *vb = (const JsonbValue *) b;
|
||||||
@ -1571,8 +1567,6 @@ lengthCompareJsonbStringValue(const void *a, const void *b, void *binequal)
|
|||||||
if (va->val.string.len == vb->val.string.len)
|
if (va->val.string.len == vb->val.string.len)
|
||||||
{
|
{
|
||||||
res = memcmp(va->val.string.val, vb->val.string.val, va->val.string.len);
|
res = memcmp(va->val.string.val, vb->val.string.val, va->val.string.len);
|
||||||
if (res == 0 && binequal)
|
|
||||||
*((bool *) binequal) = true;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -1585,9 +1579,9 @@ lengthCompareJsonbStringValue(const void *a, const void *b, void *binequal)
|
|||||||
/*
|
/*
|
||||||
* qsort_arg() comparator to compare JsonbPair values.
|
* qsort_arg() comparator to compare JsonbPair values.
|
||||||
*
|
*
|
||||||
* Function implemented in terms of lengthCompareJsonbStringValue(), and thus the
|
* Third argument 'binequal' may point to a bool. If it's set, *binequal is set
|
||||||
* same "arg setting" hack will be applied here in respect of the pair's key
|
* to true iff a and b have full binary equality, since some callers have an
|
||||||
* values.
|
* interest in whether the two values are equal or merely equivalent.
|
||||||
*
|
*
|
||||||
* N.B: String comparisons here are "length-wise"
|
* N.B: String comparisons here are "length-wise"
|
||||||
*
|
*
|
||||||
@ -1600,7 +1594,9 @@ lengthCompareJsonbPair(const void *a, const void *b, void *binequal)
|
|||||||
const JsonbPair *pb = (const JsonbPair *) b;
|
const JsonbPair *pb = (const JsonbPair *) b;
|
||||||
int res;
|
int res;
|
||||||
|
|
||||||
res = lengthCompareJsonbStringValue(&pa->key, &pb->key, binequal);
|
res = lengthCompareJsonbStringValue(&pa->key, &pb->key);
|
||||||
|
if (res == 0 && binequal)
|
||||||
|
*((bool *) binequal) = true;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Guarantee keeping order of equal pair. Unique algorithm will prefer
|
* Guarantee keeping order of equal pair. Unique algorithm will prefer
|
||||||
@ -1634,7 +1630,7 @@ uniqueifyJsonbObject(JsonbValue *object)
|
|||||||
while (ptr - object->val.object.pairs < object->val.object.nPairs)
|
while (ptr - object->val.object.pairs < object->val.object.nPairs)
|
||||||
{
|
{
|
||||||
/* Avoid copying over duplicate */
|
/* Avoid copying over duplicate */
|
||||||
if (lengthCompareJsonbStringValue(ptr, res, NULL) != 0)
|
if (lengthCompareJsonbStringValue(ptr, res) != 0)
|
||||||
{
|
{
|
||||||
res++;
|
res++;
|
||||||
if (ptr != res)
|
if (ptr != res)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user