Introduce convenience macros to hide JsonbContainer header accesses better.
authorTom Lane
Wed, 25 Jan 2017 18:28:38 +0000 (13:28 -0500)
committerTom Lane
Wed, 25 Jan 2017 18:28:38 +0000 (13:28 -0500)
This improves readability a bit and may make future improvements easier.

In passing, make sure that the JB_ROOT_IS_XXX macros deliver boolean (0/1)
results; the previous coding was a bug hazard, though no actual bugs are
known.

Nikita Glukhov, extended a bit by me

Discussion: https://postgr.es/m/9e21a39c-c1d7-b9b5-44a0-c5345a5029f6@postgrespro.ru

src/backend/utils/adt/jsonb_util.c
src/backend/utils/adt/jsonfuncs.c
src/include/utils/jsonb.h

index 11a139503836e534ae8a3700e9443e138e44c30c..0d2abb35b96afcbc5a85946f341a5667e98fad36 100644 (file)
@@ -328,7 +328,7 @@ findJsonbValueFromContainer(JsonbContainer *container, uint32 flags,
                            JsonbValue *key)
 {
    JEntry     *children = container->children;
-   int         count = (container->header & JB_CMASK);
+   int         count = JsonContainerSize(container);
    JsonbValue *result;
 
    Assert((flags & ~(JB_FARRAY | JB_FOBJECT)) == 0);
@@ -339,7 +339,7 @@ findJsonbValueFromContainer(JsonbContainer *container, uint32 flags,
 
    result = palloc(sizeof(JsonbValue));
 
-   if (flags & JB_FARRAY & container->header)
+   if ((flags & JB_FARRAY) && JsonContainerIsArray(container))
    {
        char       *base_addr = (char *) (children + count);
        uint32      offset = 0;
@@ -358,7 +358,7 @@ findJsonbValueFromContainer(JsonbContainer *container, uint32 flags,
            JBE_ADVANCE_OFFSET(offset, children[i]);
        }
    }
-   else if (flags & JB_FOBJECT & container->header)
+   else if ((flags & JB_FOBJECT) && JsonContainerIsObject(container))
    {
        /* Since this is an object, account for *Pairs* of Jentrys */
        char       *base_addr = (char *) (children + count * 2);
@@ -422,10 +422,10 @@ getIthJsonbValueFromContainer(JsonbContainer *container, uint32 i)
    char       *base_addr;
    uint32      nelements;
 
-   if ((container->header & JB_FARRAY) == 0)
+   if (!JsonContainerIsArray(container))
        elog(ERROR, "not a jsonb array");
 
-   nelements = container->header & JB_CMASK;
+   nelements = JsonContainerSize(container);
    base_addr = (char *) &container->children[nelements];
 
    if (i >= nelements)
@@ -904,7 +904,7 @@ iteratorFromContainer(JsonbContainer *container, JsonbIterator *parent)
    it = palloc(sizeof(JsonbIterator));
    it->container = container;
    it->parent = parent;
-   it->nElems = container->header & JB_CMASK;
+   it->nElems = JsonContainerSize(container);
 
    /* Array starts just after header */
    it->children = container->children;
@@ -914,7 +914,7 @@ iteratorFromContainer(JsonbContainer *container, JsonbIterator *parent)
        case JB_FARRAY:
            it->dataProper =
                (char *) it->children + it->nElems * sizeof(JEntry);
-           it->isScalar = (container->header & JB_FSCALAR) != 0;
+           it->isScalar = JsonContainerIsScalar(container);
            /* This is either a "raw scalar", or an array */
            Assert(!it->isScalar || it->nElems == 1);
 
index a75df62d2a0d3f1caa1dd6ccc7b3b678c8579eb8..6a7aab2f432e44d70520f1725bb14463f94ac293 100644 (file)
@@ -1266,10 +1266,10 @@ get_jsonb_path_all(FunctionCallInfo fcinfo, bool as_text)
                uint32      nelements;
 
                /* Container must be array, but make sure */
-               if ((container->header & JB_FARRAY) == 0)
+               if (!JsonContainerIsArray(container))
                    elog(ERROR, "not a jsonb array");
 
-               nelements = container->header & JB_CMASK;
+               nelements = JsonContainerSize(container);
 
                if (-lindex > nelements)
                    PG_RETURN_NULL();
index e402b9e3a703698d43710de2c04fe077cac0a597..411e158d6c13c4d01b9f15f4ed6d37830560bb13 100644 (file)
@@ -205,6 +205,12 @@ typedef struct JsonbContainer
 #define JB_FOBJECT             0x20000000
 #define JB_FARRAY              0x40000000
 
+/* convenience macros for accessing a JsonbContainer struct */
+#define JsonContainerSize(jc)      ((jc)->header & JB_CMASK)
+#define JsonContainerIsScalar(jc)  (((jc)->header & JB_FSCALAR) != 0)
+#define JsonContainerIsObject(jc)  (((jc)->header & JB_FOBJECT) != 0)
+#define JsonContainerIsArray(jc)   (((jc)->header & JB_FARRAY) != 0)
+
 /* The top-level on-disk format for a jsonb datum. */
 typedef struct
 {
@@ -213,10 +219,10 @@ typedef struct
 } Jsonb;
 
 /* convenience macros for accessing the root container in a Jsonb datum */
-#define JB_ROOT_COUNT(jbp_)        ( *(uint32*) VARDATA(jbp_) & JB_CMASK)
-#define JB_ROOT_IS_SCALAR(jbp_) ( *(uint32*) VARDATA(jbp_) & JB_FSCALAR)
-#define JB_ROOT_IS_OBJECT(jbp_) ( *(uint32*) VARDATA(jbp_) & JB_FOBJECT)
-#define JB_ROOT_IS_ARRAY(jbp_) ( *(uint32*) VARDATA(jbp_) & JB_FARRAY)
+#define JB_ROOT_COUNT(jbp_)        (*(uint32 *) VARDATA(jbp_) & JB_CMASK)
+#define JB_ROOT_IS_SCALAR(jbp_) ((*(uint32 *) VARDATA(jbp_) & JB_FSCALAR) != 0)
+#define JB_ROOT_IS_OBJECT(jbp_) ((*(uint32 *) VARDATA(jbp_) & JB_FOBJECT) != 0)
+#define JB_ROOT_IS_ARRAY(jbp_) ((*(uint32 *) VARDATA(jbp_) & JB_FARRAY) != 0)
 
 
 enum jbvType
@@ -241,7 +247,7 @@ enum jbvType
  */
 struct JsonbValue
 {
-   enum jbvType    type;           /* Influences sort order */
+   enum jbvType type;          /* Influences sort order */
 
    union
    {