Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit ff7bbb0

Browse files
committedMay 9, 2014
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.
1 parent d3c72e2 commit ff7bbb0

File tree

1 file changed

+187
-191
lines changed

1 file changed

+187
-191
lines changed
 

‎src/backend/utils/adt/jsonb_util.c

Lines changed: 187 additions & 191 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ static JsonbParseState *pushState(JsonbParseState **pstate);
6868
static void appendKey(JsonbParseState *pstate, JsonbValue *scalarVal);
6969
static void appendValue(JsonbParseState *pstate, JsonbValue *scalarVal);
7070
static void appendElement(JsonbParseState *pstate, JsonbValue *scalarVal);
71-
static int lengthCompareJsonbStringValue(const void *a, const void *b, void *arg);
71+
static int lengthCompareJsonbStringValue(const void *a, const void *b);
7272
static int lengthCompareJsonbPair(const void *a, const void *b, void *arg);
7373
static void uniqueifyJsonbObject(JsonbValue *object);
7474

@@ -329,7 +329,7 @@ findJsonbValueFromContainer(JsonbContainer *container, uint32 flags,
329329
candidate.val.string.val = data + JBE_OFF(*entry);
330330
candidate.val.string.len = JBE_LEN(*entry);
331331

332-
difference = lengthCompareJsonbStringValue(&candidate, key, NULL);
332+
difference = lengthCompareJsonbStringValue(&candidate, key);
333333

334334
if (difference == 0)
335335
{
@@ -533,6 +533,86 @@ pushJsonbValue(JsonbParseState **pstate, JsonbIteratorToken seq,
533533
return result;
534534
}
535535

536+
/*
537+
* pushJsonbValue() worker: Iteration-like forming of Jsonb
538+
*/
539+
static JsonbParseState *
540+
pushState(JsonbParseState **pstate)
541+
{
542+
JsonbParseState *ns = palloc(sizeof(JsonbParseState));
543+
544+
ns->next = *pstate;
545+
return ns;
546+
}
547+
548+
/*
549+
* pushJsonbValue() worker: Append a pair key to state when generating a Jsonb
550+
*/
551+
static void
552+
appendKey(JsonbParseState *pstate, JsonbValue *string)
553+
{
554+
JsonbValue *object = &pstate->contVal;
555+
556+
Assert(object->type == jbvObject);
557+
Assert(string->type == jbvString);
558+
559+
if (object->val.object.nPairs >= JSONB_MAX_PAIRS)
560+
ereport(ERROR,
561+
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
562+
errmsg("number of jsonb object pairs exceeds the maximum allowed (%zu)",
563+
JSONB_MAX_PAIRS)));
564+
565+
if (object->val.object.nPairs >= pstate->size)
566+
{
567+
pstate->size *= 2;
568+
object->val.object.pairs = repalloc(object->val.object.pairs,
569+
sizeof(JsonbPair) * pstate->size);
570+
}
571+
572+
object->val.object.pairs[object->val.object.nPairs].key = *string;
573+
object->val.object.pairs[object->val.object.nPairs].order = object->val.object.nPairs;
574+
}
575+
576+
/*
577+
* pushJsonbValue() worker: Append a pair value to state when generating a
578+
* Jsonb
579+
*/
580+
static void
581+
appendValue(JsonbParseState *pstate, JsonbValue *scalarVal)
582+
{
583+
JsonbValue *object = &pstate->contVal;
584+
585+
Assert(object->type == jbvObject);
586+
587+
object->val.object.pairs[object->val.object.nPairs++].value = *scalarVal;
588+
}
589+
590+
/*
591+
* pushJsonbValue() worker: Append an element to state when generating a Jsonb
592+
*/
593+
static void
594+
appendElement(JsonbParseState *pstate, JsonbValue *scalarVal)
595+
{
596+
JsonbValue *array = &pstate->contVal;
597+
598+
Assert(array->type == jbvArray);
599+
600+
if (array->val.array.nElems >= JSONB_MAX_ELEMS)
601+
ereport(ERROR,
602+
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
603+
errmsg("number of jsonb array elements exceeds the maximum allowed (%zu)",
604+
JSONB_MAX_ELEMS)));
605+
606+
if (array->val.array.nElems >= pstate->size)
607+
{
608+
pstate->size *= 2;
609+
array->val.array.elems = repalloc(array->val.array.elems,
610+
sizeof(JsonbValue) * pstate->size);
611+
}
612+
613+
array->val.array.elems[array->val.array.nElems++] = *scalarVal;
614+
}
615+
536616
/*
537617
* Given a JsonbContainer, expand to JsonbIterator to iterate over items
538618
* fully expanded to in-memory representation for manipulation.
@@ -709,6 +789,101 @@ JsonbIteratorNext(JsonbIterator **it, JsonbValue *val, bool skipNested)
709789
return -1;
710790
}
711791

792+
/*
793+
* Initialize an iterator for iterating all elements in a container.
794+
*/
795+
static void
796+
iteratorFromContainer(JsonbIterator *it, JsonbContainer *container)
797+
{
798+
it->containerType = container->header & (JB_FARRAY | JB_FOBJECT);
799+
it->nElems = container->header & JB_CMASK;
800+
it->buffer = (char *) container;
801+
802+
/* Array starts just after header */
803+
it->meta = container->children;
804+
it->state = jbi_start;
805+
806+
switch (it->containerType)
807+
{
808+
case JB_FARRAY:
809+
it->dataProper =
810+
(char *) it->meta + it->nElems * sizeof(JEntry);
811+
it->isScalar = (container->header & JB_FSCALAR) != 0;
812+
/* This is either a "raw scalar", or an array */
813+
Assert(!it->isScalar || it->nElems == 1);
814+
break;
815+
case JB_FOBJECT:
816+
817+
/*
818+
* Offset reflects that nElems indicates JsonbPairs in an object.
819+
* Each key and each value contain Jentry metadata just the same.
820+
*/
821+
it->dataProper =
822+
(char *) it->meta + it->nElems * sizeof(JEntry) * 2;
823+
break;
824+
default:
825+
elog(ERROR, "unknown type of jsonb container");
826+
}
827+
}
828+
829+
/*
830+
* JsonbIteratorNext() worker
831+
*
832+
* Returns bool indicating if v was a non-jbvBinary container, and thus if
833+
* further recursion is required by caller (according to its skipNested
834+
* preference). If it is required, we set the caller's iterator for further
835+
* recursion into the nested value. If we're going to skip nested items, just
836+
* set v to a jbvBinary value, but don't set caller's iterator.
837+
*
838+
* Unlike with containers (either in this function or in any
839+
* JsonbIteratorNext() infrastructure), we fully convert from what is
840+
* ultimately a Jsonb on-disk representation, to a JsonbValue in-memory
841+
* representation (for scalar values only). JsonbIteratorNext() initializes
842+
* container Jsonbvalues, but without a sane private buffer. For scalar values
843+
* it has to be done for real (even if we don't actually allocate more memory
844+
* to do this. The point is that our JsonbValues scalars can be passed around
845+
* anywhere).
846+
*/
847+
static bool
848+
formIterIsContainer(JsonbIterator **it, JsonbValue *val, JEntry *ent,
849+
bool skipNested)
850+
{
851+
fillJsonbValue(ent, (*it)->dataProper, val);
852+
853+
if (IsAJsonbScalar(val) || skipNested)
854+
return false;
855+
else
856+
{
857+
/*
858+
* It's a container type, so setup caller's iterator to point to
859+
* that, and return indication of that.
860+
*
861+
* Get child iterator.
862+
*/
863+
JsonbIterator *child = palloc(sizeof(JsonbIterator));
864+
865+
iteratorFromContainer(child, val->val.binary.data);
866+
867+
child->parent = *it;
868+
*it = child;
869+
870+
return true;
871+
}
872+
}
873+
874+
/*
875+
* JsonbIteratorNext() worker: Return parent, while freeing memory for current
876+
* iterator
877+
*/
878+
static JsonbIterator *
879+
freeAndGetParent(JsonbIterator *it)
880+
{
881+
JsonbIterator *v = it->parent;
882+
883+
pfree(it);
884+
return v;
885+
}
886+
712887
/*
713888
* Worker for "contains" operator's function
714889
*
@@ -1015,7 +1190,7 @@ compareJsonbScalarValue(JsonbValue *aScalar, JsonbValue *bScalar)
10151190
case jbvNull:
10161191
return 0;
10171192
case jbvString:
1018-
return lengthCompareJsonbStringValue(aScalar, bScalar, NULL);
1193+
return lengthCompareJsonbStringValue(aScalar, bScalar);
10191194
case jbvNumeric:
10201195
return DatumGetInt32(DirectFunctionCall2(numeric_cmp,
10211196
PointerGetDatum(aScalar->val.numeric),
@@ -1059,7 +1234,7 @@ lexicalCompareJsonbStringValue(const void *a, const void *b)
10591234
*/
10601235

10611236
/*
1062-
* Rervere 'len' bytes, at the end of the buffer, enlarging it if necessary.
1237+
* Reserve 'len' bytes, at the end of the buffer, enlarging it if necessary.
10631238
* Returns the offset to the reserved area. The caller is expected to copy
10641239
* the data to the reserved area later with copyToBuffer()
10651240
*/
@@ -1367,181 +1542,6 @@ convertJsonbScalar(convertState *buffer, JEntry *jentry, JsonbValue *scalarVal)
13671542
}
13681543
}
13691544

1370-
/*
1371-
* Initialize an iterator for iterating all elements in a container.
1372-
*/
1373-
static void
1374-
iteratorFromContainer(JsonbIterator *it, JsonbContainer *container)
1375-
{
1376-
it->containerType = container->header & (JB_FARRAY | JB_FOBJECT);
1377-
it->nElems = container->header & JB_CMASK;
1378-
it->buffer = (char *) container;
1379-
1380-
/* Array starts just after header */
1381-
it->meta = container->children;
1382-
it->state = jbi_start;
1383-
1384-
switch (it->containerType)
1385-
{
1386-
case JB_FARRAY:
1387-
it->dataProper =
1388-
(char *) it->meta + it->nElems * sizeof(JEntry);
1389-
it->isScalar = (container->header & JB_FSCALAR) != 0;
1390-
/* This is either a "raw scalar", or an array */
1391-
Assert(!it->isScalar || it->nElems == 1);
1392-
break;
1393-
case JB_FOBJECT:
1394-
1395-
/*
1396-
* Offset reflects that nElems indicates JsonbPairs in an object.
1397-
* Each key and each value contain Jentry metadata just the same.
1398-
*/
1399-
it->dataProper =
1400-
(char *) it->meta + it->nElems * sizeof(JEntry) * 2;
1401-
break;
1402-
default:
1403-
elog(ERROR, "unknown type of jsonb container");
1404-
}
1405-
}
1406-
1407-
/*
1408-
* JsonbIteratorNext() worker
1409-
*
1410-
* Returns bool indicating if v was a non-jbvBinary container, and thus if
1411-
* further recursion is required by caller (according to its skipNested
1412-
* preference). If it is required, we set the caller's iterator for further
1413-
* recursion into the nested value. If we're going to skip nested items, just
1414-
* set v to a jbvBinary value, but don't set caller's iterator.
1415-
*
1416-
* Unlike with containers (either in this function or in any
1417-
* JsonbIteratorNext() infrastructure), we fully convert from what is
1418-
* ultimately a Jsonb on-disk representation, to a JsonbValue in-memory
1419-
* representation (for scalar values only). JsonbIteratorNext() initializes
1420-
* container Jsonbvalues, but without a sane private buffer. For scalar values
1421-
* it has to be done for real (even if we don't actually allocate more memory
1422-
* to do this. The point is that our JsonbValues scalars can be passed around
1423-
* anywhere).
1424-
*/
1425-
static bool
1426-
formIterIsContainer(JsonbIterator **it, JsonbValue *val, JEntry *ent,
1427-
bool skipNested)
1428-
{
1429-
fillJsonbValue(ent, (*it)->dataProper, val);
1430-
1431-
if (IsAJsonbScalar(val) || skipNested)
1432-
return false;
1433-
else
1434-
{
1435-
/*
1436-
* It's a container type, so setup caller's iterator to point to
1437-
* that, and return indication of that.
1438-
*
1439-
* Get child iterator.
1440-
*/
1441-
JsonbIterator *child = palloc(sizeof(JsonbIterator));
1442-
1443-
iteratorFromContainer(child, val->val.binary.data);
1444-
1445-
child->parent = *it;
1446-
*it = child;
1447-
1448-
return true;
1449-
}
1450-
}
1451-
1452-
/*
1453-
* JsonbIteratorNext() worker: Return parent, while freeing memory for current
1454-
* iterator
1455-
*/
1456-
static JsonbIterator *
1457-
freeAndGetParent(JsonbIterator *it)
1458-
{
1459-
JsonbIterator *v = it->parent;
1460-
1461-
pfree(it);
1462-
return v;
1463-
}
1464-
1465-
/*
1466-
* pushJsonbValue() worker: Iteration-like forming of Jsonb
1467-
*/
1468-
static JsonbParseState *
1469-
pushState(JsonbParseState **pstate)
1470-
{
1471-
JsonbParseState *ns = palloc(sizeof(JsonbParseState));
1472-
1473-
ns->next = *pstate;
1474-
return ns;
1475-
}
1476-
1477-
/*
1478-
* pushJsonbValue() worker: Append a pair key to state when generating a Jsonb
1479-
*/
1480-
static void
1481-
appendKey(JsonbParseState *pstate, JsonbValue *string)
1482-
{
1483-
JsonbValue *object = &pstate->contVal;
1484-
1485-
Assert(object->type == jbvObject);
1486-
Assert(string->type == jbvString);
1487-
1488-
if (object->val.object.nPairs >= JSONB_MAX_PAIRS)
1489-
ereport(ERROR,
1490-
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
1491-
errmsg("number of jsonb object pairs exceeds the maximum allowed (%zu)",
1492-
JSONB_MAX_PAIRS)));
1493-
1494-
if (object->val.object.nPairs >= pstate->size)
1495-
{
1496-
pstate->size *= 2;
1497-
object->val.object.pairs = repalloc(object->val.object.pairs,
1498-
sizeof(JsonbPair) * pstate->size);
1499-
}
1500-
1501-
object->val.object.pairs[object->val.object.nPairs].key = *string;
1502-
object->val.object.pairs[object->val.object.nPairs].order = object->val.object.nPairs;
1503-
}
1504-
1505-
/*
1506-
* pushJsonbValue() worker: Append a pair value to state when generating a
1507-
* Jsonb
1508-
*/
1509-
static void
1510-
appendValue(JsonbParseState *pstate, JsonbValue *scalarVal)
1511-
{
1512-
JsonbValue *object = &pstate->contVal;
1513-
1514-
Assert(object->type == jbvObject);
1515-
1516-
object->val.object.pairs[object->val.object.nPairs++].value = *scalarVal;
1517-
}
1518-
1519-
/*
1520-
* pushJsonbValue() worker: Append an element to state when generating a Jsonb
1521-
*/
1522-
static void
1523-
appendElement(JsonbParseState *pstate, JsonbValue *scalarVal)
1524-
{
1525-
JsonbValue *array = &pstate->contVal;
1526-
1527-
Assert(array->type == jbvArray);
1528-
1529-
if (array->val.array.nElems >= JSONB_MAX_ELEMS)
1530-
ereport(ERROR,
1531-
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
1532-
errmsg("number of jsonb array elements exceeds the maximum allowed (%zu)",
1533-
JSONB_MAX_ELEMS)));
1534-
1535-
if (array->val.array.nElems >= pstate->size)
1536-
{
1537-
pstate->size *= 2;
1538-
array->val.array.elems = repalloc(array->val.array.elems,
1539-
sizeof(JsonbValue) * pstate->size);
1540-
}
1541-
1542-
array->val.array.elems[array->val.array.nElems++] = *scalarVal;
1543-
}
1544-
15451545
/*
15461546
* Compare two jbvString JsonbValue values, a and b.
15471547
*
@@ -1553,13 +1553,9 @@ appendElement(JsonbParseState *pstate, JsonbValue *scalarVal)
15531553
*
15541554
* a and b are first sorted based on their length. If a tie-breaker is
15551555
* required, only then do we consider string binary equality.
1556-
*
1557-
* Third argument 'binequal' may point to a bool. If it's set, *binequal is set
1558-
* to true iff a and b have full binary equality, since some callers have an
1559-
* interest in whether the two values are equal or merely equivalent.
15601556
*/
15611557
static int
1562-
lengthCompareJsonbStringValue(const void *a, const void *b, void *binequal)
1558+
lengthCompareJsonbStringValue(const void *a, const void *b)
15631559
{
15641560
const JsonbValue *va = (const JsonbValue *) a;
15651561
const JsonbValue *vb = (const JsonbValue *) b;
@@ -1571,8 +1567,6 @@ lengthCompareJsonbStringValue(const void *a, const void *b, void *binequal)
15711567
if (va->val.string.len == vb->val.string.len)
15721568
{
15731569
res = memcmp(va->val.string.val, vb->val.string.val, va->val.string.len);
1574-
if (res == 0 && binequal)
1575-
*((bool *) binequal) = true;
15761570
}
15771571
else
15781572
{
@@ -1585,9 +1579,9 @@ lengthCompareJsonbStringValue(const void *a, const void *b, void *binequal)
15851579
/*
15861580
* qsort_arg() comparator to compare JsonbPair values.
15871581
*
1588-
* Function implemented in terms of lengthCompareJsonbStringValue(), and thus the
1589-
* same "arg setting" hack will be applied here in respect of the pair's key
1590-
* values.
1582+
* Third argument 'binequal' may point to a bool. If it's set, *binequal is set
1583+
* to true iff a and b have full binary equality, since some callers have an
1584+
* interest in whether the two values are equal or merely equivalent.
15911585
*
15921586
* N.B: String comparisons here are "length-wise"
15931587
*
@@ -1600,7 +1594,9 @@ lengthCompareJsonbPair(const void *a, const void *b, void *binequal)
16001594
const JsonbPair *pb = (const JsonbPair *) b;
16011595
int res;
16021596

1603-
res = lengthCompareJsonbStringValue(&pa->key, &pb->key, binequal);
1597+
res = lengthCompareJsonbStringValue(&pa->key, &pb->key);
1598+
if (res == 0 && binequal)
1599+
*((bool *) binequal) = true;
16041600

16051601
/*
16061602
* Guarantee keeping order of equal pair. Unique algorithm will prefer
@@ -1634,7 +1630,7 @@ uniqueifyJsonbObject(JsonbValue *object)
16341630
while (ptr - object->val.object.pairs < object->val.object.nPairs)
16351631
{
16361632
/* Avoid copying over duplicate */
1637-
if (lengthCompareJsonbStringValue(ptr, res, NULL) != 0)
1633+
if (lengthCompareJsonbStringValue(ptr, res) != 0)
16381634
{
16391635
res++;
16401636
if (ptr != res)

0 commit comments

Comments
 (0)
Please sign in to comment.