OSDN Git Service

Change the way to treat nested json-objects
authorKyotaro Horiguchi <horiguchi.kyotaro@lab.ntt.co.jp>
Fri, 26 Aug 2016 04:47:54 +0000 (13:47 +0900)
committerKyotaro Horiguchi <horiguchi.kyotaro@lab.ntt.co.jp>
Fri, 26 Aug 2016 04:47:54 +0000 (13:47 +0900)
Previously the text converting parser assumes that all JSON object are
Plan or a children of Plans but Target Tables breaks the
assumption. This patch changes the way to detect the end of a Plan (or
a child of Plans) cleaner so that it can handle JSON objects other
than Plan.

pgsp_json.c
pgsp_json_int.h
pgsp_json_text.c

index d6c0078..c18981a 100644 (file)
@@ -934,7 +934,7 @@ xml_ofstart(void *state, char *fname, bool isnull)
         * There's no problem if P_Plan appears recursively.
         */
        if (p && (p->tag == P_Plan || p->tag == P_Triggers))
-               ctx->processing = p->tag;
+               ctx->section = p->tag;
 
        appendStringInfoChar(ctx->dest, '\n');
        appendStringInfoSpaces(ctx->dest, (ctx->level + 1) * INDENT_STEP);
@@ -986,7 +986,7 @@ xml_aestart(void *state, bool isnull)
        ctx->level++;
        if (bms_is_member(ctx->level, ctx->not_item))
        {
-               if (ctx->processing == P_Plan)
+               if (ctx->section == P_Plan)
                        tag = "<Plan>";
                else
                        tag = "<Trigger>";
@@ -1012,7 +1012,7 @@ xml_aeend(void *state, bool isnull)
 
        if (bms_is_member(ctx->level, ctx->not_item))
        {
-               if (ctx->processing == P_Plan)
+               if (ctx->section == P_Plan)
                        tag = "</Plan>";
                else
                        tag = "</Trigger>";
index dc2ce3a..16f6a4a 100644 (file)
@@ -127,7 +127,8 @@ typedef struct
        char       *org_string;         /* What to parse */
 
        /* Working variables used internally in parser */
-       int                     level;                  /* Next (indent) level */
+       int                     level;                  /* Next (indent or object) level */
+       Bitmapset  *plan_levels;        /* Level list for Plan objects */
        Bitmapset  *first;                      /* Bitmap set holds whether the first element
                                                                 * has been processed for each level */
        Bitmapset  *not_item;           /* Bitmap set holds whether the node name at
@@ -136,7 +137,7 @@ typedef struct
                                                                 * the result */
        bool            last_elem_is_object; /* True if the last processed element
                                                                 * was not an object */
-       pgsp_prop_tags  processing;     /* Tag of the word under processing */
+       pgsp_prop_tags  section;        /* Tag of the word under processing */
        char       *fname;                      /* Field name*/
        char       *wbuf;                       /* Working buffer */
        int                     wbuflen;                /* Length of the working buffer */
index 6389dcc..0c47654 100644 (file)
@@ -581,26 +581,26 @@ static void
 json_text_objstart(void *state)
 {
        pgspParserContext *ctx = (pgspParserContext *)state;
-       clear_nodeval(ctx->nodevals);
        ctx->level++;
 }
+
 static void
 json_text_objend(void *state)
 {
        pgspParserContext *ctx = (pgspParserContext *)state;
-       switch (ctx->processing)
+
+       /* Print current node if the object is a P_Plan or a child of P_Plans */
+       if (bms_is_member(ctx->level - 1, ctx->plan_levels))
        {
-               case P_Plan:
-                       print_current_node(ctx);
-                       break;
-               case P_Triggers:
-                       print_current_trig_node(ctx);
-                       break;
-               default:
-                       break;
+               print_current_node(ctx);
+               clear_nodeval(ctx->nodevals);
+       }
+       else if (ctx->section == P_Triggers)
+       {
+               print_current_trig_node(ctx);
+               clear_nodeval(ctx->nodevals);
        }
 
-       clear_nodeval(ctx->nodevals);
        ctx->last_elem_is_object = true;
        ctx->level--;
 }
@@ -622,16 +622,27 @@ json_text_ofstart(void *state, char *fname, bool isnull)
        }
        else
        {
-               /* Print node immediately if next level of Plan/Plans comes */
+               /*
+                * Print node immediately if the next level of Plan/Plans comes. The
+                * plan construct is tail-recursive so this doesn't harm.
+                */
                if (p->tag == P_Plan || p->tag == P_Plans)
                {
                        print_current_node(ctx);
                        clear_nodeval(ctx->nodevals);
                }
 
+               /*
+                * This paser prints partial result at the end of every P_Plan object,
+                * which includes elements in P_Plans list.
+                */
+               if (p->tag == P_Plan || p->tag == P_Plans)
+                       ctx->plan_levels = bms_add_member(ctx->plan_levels, ctx->level);
+               else
+                       ctx->plan_levels = bms_del_member(ctx->plan_levels, ctx->level);
                
                if (p->tag == P_Plan || p->tag == P_Triggers)
-                       ctx->processing = p->tag;
+                       ctx->section = p->tag;
                ctx->setter = p->setter;
        }
 }