LCOV - differential code coverage report
Current view: top level - src/backend/utils/adt - jsonfuncs.c (source / functions) Coverage Total Hit UNC LBC UIC UBC GBC GIC GNC CBC EUB ECB DUB DCB
Current: Differential Code Coverage HEAD vs 15 Lines: 96.6 % 2048 1979 5 23 40 1 25 1131 89 734 42 1183 1 39
Current Date: 2023-04-08 15:15:32 Functions: 100.0 % 147 147 144 3 145 2
Baseline: 15
Baseline Date: 2023-04-08 15:09:40
Legend: Lines: hit not hit

           TLA  Line data    Source code
       1                 : /*-------------------------------------------------------------------------
       2                 :  *
       3                 :  * jsonfuncs.c
       4                 :  *      Functions to process JSON data types.
       5                 :  *
       6                 :  * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
       7                 :  * Portions Copyright (c) 1994, Regents of the University of California
       8                 :  *
       9                 :  * IDENTIFICATION
      10                 :  *    src/backend/utils/adt/jsonfuncs.c
      11                 :  *
      12                 :  *-------------------------------------------------------------------------
      13                 :  */
      14                 : 
      15                 : #include "postgres.h"
      16                 : 
      17                 : #include <limits.h>
      18                 : 
      19                 : #include "access/htup_details.h"
      20                 : #include "catalog/pg_type.h"
      21                 : #include "common/jsonapi.h"
      22                 : #include "common/string.h"
      23                 : #include "fmgr.h"
      24                 : #include "funcapi.h"
      25                 : #include "lib/stringinfo.h"
      26                 : #include "mb/pg_wchar.h"
      27                 : #include "miscadmin.h"
      28                 : #include "nodes/miscnodes.h"
      29                 : #include "utils/array.h"
      30                 : #include "utils/builtins.h"
      31                 : #include "utils/fmgroids.h"
      32                 : #include "utils/hsearch.h"
      33                 : #include "utils/json.h"
      34                 : #include "utils/jsonb.h"
      35                 : #include "utils/jsonfuncs.h"
      36                 : #include "utils/lsyscache.h"
      37                 : #include "utils/memutils.h"
      38                 : #include "utils/syscache.h"
      39                 : #include "utils/typcache.h"
      40                 : 
      41                 : /* Operations available for setPath */
      42                 : #define JB_PATH_CREATE                  0x0001
      43                 : #define JB_PATH_DELETE                  0x0002
      44                 : #define JB_PATH_REPLACE                 0x0004
      45                 : #define JB_PATH_INSERT_BEFORE           0x0008
      46                 : #define JB_PATH_INSERT_AFTER            0x0010
      47                 : #define JB_PATH_CREATE_OR_INSERT \
      48                 :     (JB_PATH_INSERT_BEFORE | JB_PATH_INSERT_AFTER | JB_PATH_CREATE)
      49                 : #define JB_PATH_FILL_GAPS               0x0020
      50                 : #define JB_PATH_CONSISTENT_POSITION     0x0040
      51                 : 
      52                 : /* state for json_object_keys */
      53                 : typedef struct OkeysState
      54                 : {
      55                 :     JsonLexContext *lex;
      56                 :     char      **result;
      57                 :     int         result_size;
      58                 :     int         result_count;
      59                 :     int         sent_count;
      60                 : } OkeysState;
      61                 : 
      62                 : /* state for iterate_json_values function */
      63                 : typedef struct IterateJsonStringValuesState
      64                 : {
      65                 :     JsonLexContext *lex;
      66                 :     JsonIterateStringValuesAction action;   /* an action that will be applied
      67                 :                                              * to each json value */
      68                 :     void       *action_state;   /* any necessary context for iteration */
      69                 :     uint32      flags;          /* what kind of elements from a json we want
      70                 :                                  * to iterate */
      71                 : } IterateJsonStringValuesState;
      72                 : 
      73                 : /* state for transform_json_string_values function */
      74                 : typedef struct TransformJsonStringValuesState
      75                 : {
      76                 :     JsonLexContext *lex;
      77                 :     StringInfo  strval;         /* resulting json */
      78                 :     JsonTransformStringValuesAction action; /* an action that will be applied
      79                 :                                              * to each json value */
      80                 :     void       *action_state;   /* any necessary context for transformation */
      81                 : } TransformJsonStringValuesState;
      82                 : 
      83                 : /* state for json_get* functions */
      84                 : typedef struct GetState
      85                 : {
      86                 :     JsonLexContext *lex;
      87                 :     text       *tresult;
      88                 :     char       *result_start;
      89                 :     bool        normalize_results;
      90                 :     bool        next_scalar;
      91                 :     int         npath;          /* length of each path-related array */
      92                 :     char      **path_names;     /* field name(s) being sought */
      93                 :     int        *path_indexes;   /* array index(es) being sought */
      94                 :     bool       *pathok;         /* is path matched to current depth? */
      95                 :     int        *array_cur_index;    /* current element index at each path
      96                 :                                      * level */
      97                 : } GetState;
      98                 : 
      99                 : /* state for json_array_length */
     100                 : typedef struct AlenState
     101                 : {
     102                 :     JsonLexContext *lex;
     103                 :     int         count;
     104                 : } AlenState;
     105                 : 
     106                 : /* state for json_each */
     107                 : typedef struct EachState
     108                 : {
     109                 :     JsonLexContext *lex;
     110                 :     Tuplestorestate *tuple_store;
     111                 :     TupleDesc   ret_tdesc;
     112                 :     MemoryContext tmp_cxt;
     113                 :     char       *result_start;
     114                 :     bool        normalize_results;
     115                 :     bool        next_scalar;
     116                 :     char       *normalized_scalar;
     117                 : } EachState;
     118                 : 
     119                 : /* state for json_array_elements */
     120                 : typedef struct ElementsState
     121                 : {
     122                 :     JsonLexContext *lex;
     123                 :     const char *function_name;
     124                 :     Tuplestorestate *tuple_store;
     125                 :     TupleDesc   ret_tdesc;
     126                 :     MemoryContext tmp_cxt;
     127                 :     char       *result_start;
     128                 :     bool        normalize_results;
     129                 :     bool        next_scalar;
     130                 :     char       *normalized_scalar;
     131                 : } ElementsState;
     132                 : 
     133                 : /* state for get_json_object_as_hash */
     134                 : typedef struct JHashState
     135                 : {
     136                 :     JsonLexContext *lex;
     137                 :     const char *function_name;
     138                 :     HTAB       *hash;
     139                 :     char       *saved_scalar;
     140                 :     char       *save_json_start;
     141                 :     JsonTokenType saved_token_type;
     142                 : } JHashState;
     143                 : 
     144                 : /* hashtable element */
     145                 : typedef struct JsonHashEntry
     146                 : {
     147                 :     char        fname[NAMEDATALEN]; /* hash key (MUST BE FIRST) */
     148                 :     char       *val;
     149                 :     JsonTokenType type;
     150                 : } JsonHashEntry;
     151                 : 
     152                 : /* structure to cache type I/O metadata needed for populate_scalar() */
     153                 : typedef struct ScalarIOData
     154                 : {
     155                 :     Oid         typioparam;
     156                 :     FmgrInfo    typiofunc;
     157                 : } ScalarIOData;
     158                 : 
     159                 : /* these two structures are used recursively */
     160                 : typedef struct ColumnIOData ColumnIOData;
     161                 : typedef struct RecordIOData RecordIOData;
     162                 : 
     163                 : /* structure to cache metadata needed for populate_array() */
     164                 : typedef struct ArrayIOData
     165                 : {
     166                 :     ColumnIOData *element_info; /* metadata cache */
     167                 :     Oid         element_type;   /* array element type id */
     168                 :     int32       element_typmod; /* array element type modifier */
     169                 : } ArrayIOData;
     170                 : 
     171                 : /* structure to cache metadata needed for populate_composite() */
     172                 : typedef struct CompositeIOData
     173                 : {
     174                 :     /*
     175                 :      * We use pointer to a RecordIOData here because variable-length struct
     176                 :      * RecordIOData can't be used directly in ColumnIOData.io union
     177                 :      */
     178                 :     RecordIOData *record_io;    /* metadata cache for populate_record() */
     179                 :     TupleDesc   tupdesc;        /* cached tuple descriptor */
     180                 :     /* these fields differ from target type only if domain over composite: */
     181                 :     Oid         base_typid;     /* base type id */
     182                 :     int32       base_typmod;    /* base type modifier */
     183                 :     /* this field is used only if target type is domain over composite: */
     184                 :     void       *domain_info;    /* opaque cache for domain checks */
     185                 : } CompositeIOData;
     186                 : 
     187                 : /* structure to cache metadata needed for populate_domain() */
     188                 : typedef struct DomainIOData
     189                 : {
     190                 :     ColumnIOData *base_io;      /* metadata cache */
     191                 :     Oid         base_typid;     /* base type id */
     192                 :     int32       base_typmod;    /* base type modifier */
     193                 :     void       *domain_info;    /* opaque cache for domain checks */
     194                 : } DomainIOData;
     195                 : 
     196                 : /* enumeration type categories */
     197                 : typedef enum TypeCat
     198                 : {
     199                 :     TYPECAT_SCALAR = 's',
     200                 :     TYPECAT_ARRAY = 'a',
     201                 :     TYPECAT_COMPOSITE = 'c',
     202                 :     TYPECAT_COMPOSITE_DOMAIN = 'C',
     203                 :     TYPECAT_DOMAIN = 'd'
     204                 : } TypeCat;
     205                 : 
     206                 : /* these two are stolen from hstore / record_out, used in populate_record* */
     207                 : 
     208                 : /* structure to cache record metadata needed for populate_record_field() */
     209                 : struct ColumnIOData
     210                 : {
     211                 :     Oid         typid;          /* column type id */
     212                 :     int32       typmod;         /* column type modifier */
     213                 :     TypeCat     typcat;         /* column type category */
     214                 :     ScalarIOData scalar_io;     /* metadata cache for direct conversion
     215                 :                                  * through input function */
     216                 :     union
     217                 :     {
     218                 :         ArrayIOData array;
     219                 :         CompositeIOData composite;
     220                 :         DomainIOData domain;
     221                 :     }           io;             /* metadata cache for various column type
     222                 :                                  * categories */
     223                 : };
     224                 : 
     225                 : /* structure to cache record metadata needed for populate_record() */
     226                 : struct RecordIOData
     227                 : {
     228                 :     Oid         record_type;
     229                 :     int32       record_typmod;
     230                 :     int         ncolumns;
     231                 :     ColumnIOData columns[FLEXIBLE_ARRAY_MEMBER];
     232                 : };
     233                 : 
     234                 : /* per-query cache for populate_record_worker and populate_recordset_worker */
     235                 : typedef struct PopulateRecordCache
     236                 : {
     237                 :     Oid         argtype;        /* declared type of the record argument */
     238                 :     ColumnIOData c;             /* metadata cache for populate_composite() */
     239                 :     MemoryContext fn_mcxt;      /* where this is stored */
     240                 : } PopulateRecordCache;
     241                 : 
     242                 : /* per-call state for populate_recordset */
     243                 : typedef struct PopulateRecordsetState
     244                 : {
     245                 :     JsonLexContext *lex;
     246                 :     const char *function_name;
     247                 :     HTAB       *json_hash;
     248                 :     char       *saved_scalar;
     249                 :     char       *save_json_start;
     250                 :     JsonTokenType saved_token_type;
     251                 :     Tuplestorestate *tuple_store;
     252                 :     HeapTupleHeader rec;
     253                 :     PopulateRecordCache *cache;
     254                 : } PopulateRecordsetState;
     255                 : 
     256                 : /* common data for populate_array_json() and populate_array_dim_jsonb() */
     257                 : typedef struct PopulateArrayContext
     258                 : {
     259                 :     ArrayBuildState *astate;    /* array build state */
     260                 :     ArrayIOData *aio;           /* metadata cache */
     261                 :     MemoryContext acxt;         /* array build memory context */
     262                 :     MemoryContext mcxt;         /* cache memory context */
     263                 :     const char *colname;        /* for diagnostics only */
     264                 :     int        *dims;           /* dimensions */
     265                 :     int        *sizes;          /* current dimension counters */
     266                 :     int         ndims;          /* number of dimensions */
     267                 : } PopulateArrayContext;
     268                 : 
     269                 : /* state for populate_array_json() */
     270                 : typedef struct PopulateArrayState
     271                 : {
     272                 :     JsonLexContext *lex;        /* json lexer */
     273                 :     PopulateArrayContext *ctx;  /* context */
     274                 :     char       *element_start;  /* start of the current array element */
     275                 :     char       *element_scalar; /* current array element token if it is a
     276                 :                                  * scalar */
     277                 :     JsonTokenType element_type; /* current array element type */
     278                 : } PopulateArrayState;
     279                 : 
     280                 : /* state for json_strip_nulls */
     281                 : typedef struct StripnullState
     282                 : {
     283                 :     JsonLexContext *lex;
     284                 :     StringInfo  strval;
     285                 :     bool        skip_next_null;
     286                 : } StripnullState;
     287                 : 
     288                 : /* structure for generalized json/jsonb value passing */
     289                 : typedef struct JsValue
     290                 : {
     291                 :     bool        is_json;        /* json/jsonb */
     292                 :     union
     293                 :     {
     294                 :         struct
     295                 :         {
     296                 :             char       *str;    /* json string */
     297                 :             int         len;    /* json string length or -1 if null-terminated */
     298                 :             JsonTokenType type; /* json type */
     299                 :         }           json;       /* json value */
     300                 : 
     301                 :         JsonbValue *jsonb;      /* jsonb value */
     302                 :     }           val;
     303                 : } JsValue;
     304                 : 
     305                 : typedef struct JsObject
     306                 : {
     307                 :     bool        is_json;        /* json/jsonb */
     308                 :     union
     309                 :     {
     310                 :         HTAB       *json_hash;
     311                 :         JsonbContainer *jsonb_cont;
     312                 :     }           val;
     313                 : } JsObject;
     314                 : 
     315                 : /* useful macros for testing JsValue properties */
     316                 : #define JsValueIsNull(jsv) \
     317                 :     ((jsv)->is_json ?  \
     318                 :         (!(jsv)->val.json.str || (jsv)->val.json.type == JSON_TOKEN_NULL) : \
     319                 :         (!(jsv)->val.jsonb || (jsv)->val.jsonb->type == jbvNull))
     320                 : 
     321                 : #define JsValueIsString(jsv) \
     322                 :     ((jsv)->is_json ? (jsv)->val.json.type == JSON_TOKEN_STRING \
     323                 :         : ((jsv)->val.jsonb && (jsv)->val.jsonb->type == jbvString))
     324                 : 
     325                 : #define JsObjectIsEmpty(jso) \
     326                 :     ((jso)->is_json \
     327                 :         ? hash_get_num_entries((jso)->val.json_hash) == 0 \
     328                 :         : ((jso)->val.jsonb_cont == NULL || \
     329                 :            JsonContainerSize((jso)->val.jsonb_cont) == 0))
     330                 : 
     331                 : #define JsObjectFree(jso) \
     332                 :     do { \
     333                 :         if ((jso)->is_json) \
     334                 :             hash_destroy((jso)->val.json_hash); \
     335                 :     } while (0)
     336                 : 
     337                 : static int  report_json_context(JsonLexContext *lex);
     338                 : 
     339                 : /* semantic action functions for json_object_keys */
     340                 : static JsonParseErrorType okeys_object_field_start(void *state, char *fname, bool isnull);
     341                 : static JsonParseErrorType okeys_array_start(void *state);
     342                 : static JsonParseErrorType okeys_scalar(void *state, char *token, JsonTokenType tokentype);
     343                 : 
     344                 : /* semantic action functions for json_get* functions */
     345                 : static JsonParseErrorType get_object_start(void *state);
     346                 : static JsonParseErrorType get_object_end(void *state);
     347                 : static JsonParseErrorType get_object_field_start(void *state, char *fname, bool isnull);
     348                 : static JsonParseErrorType get_object_field_end(void *state, char *fname, bool isnull);
     349                 : static JsonParseErrorType get_array_start(void *state);
     350                 : static JsonParseErrorType get_array_end(void *state);
     351                 : static JsonParseErrorType get_array_element_start(void *state, bool isnull);
     352                 : static JsonParseErrorType get_array_element_end(void *state, bool isnull);
     353                 : static JsonParseErrorType get_scalar(void *state, char *token, JsonTokenType tokentype);
     354                 : 
     355                 : /* common worker function for json getter functions */
     356                 : static Datum get_path_all(FunctionCallInfo fcinfo, bool as_text);
     357                 : static text *get_worker(text *json, char **tpath, int *ipath, int npath,
     358                 :                         bool normalize_results);
     359                 : static Datum get_jsonb_path_all(FunctionCallInfo fcinfo, bool as_text);
     360                 : static text *JsonbValueAsText(JsonbValue *v);
     361                 : 
     362                 : /* semantic action functions for json_array_length */
     363                 : static JsonParseErrorType alen_object_start(void *state);
     364                 : static JsonParseErrorType alen_scalar(void *state, char *token, JsonTokenType tokentype);
     365                 : static JsonParseErrorType alen_array_element_start(void *state, bool isnull);
     366                 : 
     367                 : /* common workers for json{b}_each* functions */
     368                 : static Datum each_worker(FunctionCallInfo fcinfo, bool as_text);
     369                 : static Datum each_worker_jsonb(FunctionCallInfo fcinfo, const char *funcname,
     370                 :                                bool as_text);
     371                 : 
     372                 : /* semantic action functions for json_each */
     373                 : static JsonParseErrorType each_object_field_start(void *state, char *fname, bool isnull);
     374                 : static JsonParseErrorType each_object_field_end(void *state, char *fname, bool isnull);
     375                 : static JsonParseErrorType each_array_start(void *state);
     376                 : static JsonParseErrorType each_scalar(void *state, char *token, JsonTokenType tokentype);
     377                 : 
     378                 : /* common workers for json{b}_array_elements_* functions */
     379                 : static Datum elements_worker(FunctionCallInfo fcinfo, const char *funcname,
     380                 :                              bool as_text);
     381                 : static Datum elements_worker_jsonb(FunctionCallInfo fcinfo, const char *funcname,
     382                 :                                    bool as_text);
     383                 : 
     384                 : /* semantic action functions for json_array_elements */
     385                 : static JsonParseErrorType elements_object_start(void *state);
     386                 : static JsonParseErrorType elements_array_element_start(void *state, bool isnull);
     387                 : static JsonParseErrorType elements_array_element_end(void *state, bool isnull);
     388                 : static JsonParseErrorType elements_scalar(void *state, char *token, JsonTokenType tokentype);
     389                 : 
     390                 : /* turn a json object into a hash table */
     391                 : static HTAB *get_json_object_as_hash(char *json, int len, const char *funcname);
     392                 : 
     393                 : /* semantic actions for populate_array_json */
     394                 : static JsonParseErrorType populate_array_object_start(void *_state);
     395                 : static JsonParseErrorType populate_array_array_end(void *_state);
     396                 : static JsonParseErrorType populate_array_element_start(void *_state, bool isnull);
     397                 : static JsonParseErrorType populate_array_element_end(void *_state, bool isnull);
     398                 : static JsonParseErrorType populate_array_scalar(void *_state, char *token, JsonTokenType tokentype);
     399                 : 
     400                 : /* semantic action functions for get_json_object_as_hash */
     401                 : static JsonParseErrorType hash_object_field_start(void *state, char *fname, bool isnull);
     402                 : static JsonParseErrorType hash_object_field_end(void *state, char *fname, bool isnull);
     403                 : static JsonParseErrorType hash_array_start(void *state);
     404                 : static JsonParseErrorType hash_scalar(void *state, char *token, JsonTokenType tokentype);
     405                 : 
     406                 : /* semantic action functions for populate_recordset */
     407                 : static JsonParseErrorType populate_recordset_object_field_start(void *state, char *fname, bool isnull);
     408                 : static JsonParseErrorType populate_recordset_object_field_end(void *state, char *fname, bool isnull);
     409                 : static JsonParseErrorType populate_recordset_scalar(void *state, char *token, JsonTokenType tokentype);
     410                 : static JsonParseErrorType populate_recordset_object_start(void *state);
     411                 : static JsonParseErrorType populate_recordset_object_end(void *state);
     412                 : static JsonParseErrorType populate_recordset_array_start(void *state);
     413                 : static JsonParseErrorType populate_recordset_array_element_start(void *state, bool isnull);
     414                 : 
     415                 : /* semantic action functions for json_strip_nulls */
     416                 : static JsonParseErrorType sn_object_start(void *state);
     417                 : static JsonParseErrorType sn_object_end(void *state);
     418                 : static JsonParseErrorType sn_array_start(void *state);
     419                 : static JsonParseErrorType sn_array_end(void *state);
     420                 : static JsonParseErrorType sn_object_field_start(void *state, char *fname, bool isnull);
     421                 : static JsonParseErrorType sn_array_element_start(void *state, bool isnull);
     422                 : static JsonParseErrorType sn_scalar(void *state, char *token, JsonTokenType tokentype);
     423                 : 
     424                 : /* worker functions for populate_record, to_record, populate_recordset and to_recordset */
     425                 : static Datum populate_recordset_worker(FunctionCallInfo fcinfo, const char *funcname,
     426                 :                                        bool is_json, bool have_record_arg);
     427                 : static Datum populate_record_worker(FunctionCallInfo fcinfo, const char *funcname,
     428                 :                                     bool is_json, bool have_record_arg);
     429                 : 
     430                 : /* helper functions for populate_record[set] */
     431                 : static HeapTupleHeader populate_record(TupleDesc tupdesc, RecordIOData **record_p,
     432                 :                                        HeapTupleHeader defaultval, MemoryContext mcxt,
     433                 :                                        JsObject *obj);
     434                 : static void get_record_type_from_argument(FunctionCallInfo fcinfo,
     435                 :                                           const char *funcname,
     436                 :                                           PopulateRecordCache *cache);
     437                 : static void get_record_type_from_query(FunctionCallInfo fcinfo,
     438                 :                                        const char *funcname,
     439                 :                                        PopulateRecordCache *cache);
     440                 : static void JsValueToJsObject(JsValue *jsv, JsObject *jso);
     441                 : static Datum populate_composite(CompositeIOData *io, Oid typid,
     442                 :                                 const char *colname, MemoryContext mcxt,
     443                 :                                 HeapTupleHeader defaultval, JsValue *jsv, bool isnull);
     444                 : static Datum populate_scalar(ScalarIOData *io, Oid typid, int32 typmod, JsValue *jsv);
     445                 : static void prepare_column_cache(ColumnIOData *column, Oid typid, int32 typmod,
     446                 :                                  MemoryContext mcxt, bool need_scalar);
     447                 : static Datum populate_record_field(ColumnIOData *col, Oid typid, int32 typmod,
     448                 :                                    const char *colname, MemoryContext mcxt, Datum defaultval,
     449                 :                                    JsValue *jsv, bool *isnull);
     450                 : static RecordIOData *allocate_record_info(MemoryContext mcxt, int ncolumns);
     451                 : static bool JsObjectGetField(JsObject *obj, char *field, JsValue *jsv);
     452                 : static void populate_recordset_record(PopulateRecordsetState *state, JsObject *obj);
     453                 : static void populate_array_json(PopulateArrayContext *ctx, char *json, int len);
     454                 : static void populate_array_dim_jsonb(PopulateArrayContext *ctx, JsonbValue *jbv,
     455                 :                                      int ndim);
     456                 : static void populate_array_report_expected_array(PopulateArrayContext *ctx, int ndim);
     457                 : static void populate_array_assign_ndims(PopulateArrayContext *ctx, int ndims);
     458                 : static void populate_array_check_dimension(PopulateArrayContext *ctx, int ndim);
     459                 : static void populate_array_element(PopulateArrayContext *ctx, int ndim, JsValue *jsv);
     460                 : static Datum populate_array(ArrayIOData *aio, const char *colname,
     461                 :                             MemoryContext mcxt, JsValue *jsv);
     462                 : static Datum populate_domain(DomainIOData *io, Oid typid, const char *colname,
     463                 :                              MemoryContext mcxt, JsValue *jsv, bool isnull);
     464                 : 
     465                 : /* functions supporting jsonb_delete, jsonb_set and jsonb_concat */
     466                 : static JsonbValue *IteratorConcat(JsonbIterator **it1, JsonbIterator **it2,
     467                 :                                   JsonbParseState **state);
     468                 : static JsonbValue *setPath(JsonbIterator **it, Datum *path_elems,
     469                 :                            bool *path_nulls, int path_len,
     470                 :                            JsonbParseState **st, int level, JsonbValue *newval,
     471                 :                            int op_type);
     472                 : static void setPathObject(JsonbIterator **it, Datum *path_elems,
     473                 :                           bool *path_nulls, int path_len, JsonbParseState **st,
     474                 :                           int level,
     475                 :                           JsonbValue *newval, uint32 npairs, int op_type);
     476                 : static void setPathArray(JsonbIterator **it, Datum *path_elems,
     477                 :                          bool *path_nulls, int path_len, JsonbParseState **st,
     478                 :                          int level,
     479                 :                          JsonbValue *newval, uint32 nelems, int op_type);
     480                 : 
     481                 : /* function supporting iterate_json_values */
     482                 : static JsonParseErrorType iterate_values_scalar(void *state, char *token, JsonTokenType tokentype);
     483                 : static JsonParseErrorType iterate_values_object_field_start(void *state, char *fname, bool isnull);
     484                 : 
     485                 : /* functions supporting transform_json_string_values */
     486                 : static JsonParseErrorType transform_string_values_object_start(void *state);
     487                 : static JsonParseErrorType transform_string_values_object_end(void *state);
     488                 : static JsonParseErrorType transform_string_values_array_start(void *state);
     489                 : static JsonParseErrorType transform_string_values_array_end(void *state);
     490                 : static JsonParseErrorType transform_string_values_object_field_start(void *state, char *fname, bool isnull);
     491                 : static JsonParseErrorType transform_string_values_array_element_start(void *state, bool isnull);
     492                 : static JsonParseErrorType transform_string_values_scalar(void *state, char *token, JsonTokenType tokentype);
     493                 : 
     494                 : 
     495                 : /*
     496                 :  * pg_parse_json_or_errsave
     497                 :  *
     498                 :  * This function is like pg_parse_json, except that it does not return a
     499                 :  * JsonParseErrorType. Instead, in case of any failure, this function will
     500                 :  * save error data into *escontext if that's an ErrorSaveContext, otherwise
     501                 :  * ereport(ERROR).
     502                 :  *
     503                 :  * Returns a boolean indicating success or failure (failure will only be
     504                 :  * returned when escontext is an ErrorSaveContext).
     505                 :  */
     506                 : bool
     507 GNC       16488 : pg_parse_json_or_errsave(JsonLexContext *lex, JsonSemAction *sem,
     508                 :                          Node *escontext)
     509                 : {
     510                 :     JsonParseErrorType result;
     511                 : 
     512 GIC       16488 :     result = pg_parse_json(lex, sem);
     513           16392 :     if (result != JSON_SUCCESS)
     514                 :     {
     515 GNC         228 :         json_errsave_error(result, lex, escontext);
     516              15 :         return false;
     517                 :     }
     518           16164 :     return true;
     519                 : }
     520                 : 
     521                 : /*
     522                 :  * makeJsonLexContext
     523 ECB             :  *
     524                 :  * This is like makeJsonLexContextCstringLen, but it accepts a text value
     525                 :  * directly.
     526                 :  */
     527                 : JsonLexContext *
     528 GIC        5280 : makeJsonLexContext(text *json, bool need_escapes)
     529 ECB             : {
     530                 :     /*
     531                 :      * Most callers pass a detoasted datum, but it's not clear that they all
     532                 :      * do.  pg_detoast_datum_packed() is cheap insurance.
     533                 :      */
     534 GIC        5280 :     json = pg_detoast_datum_packed(json);
     535                 : 
     536           10560 :     return makeJsonLexContextCstringLen(VARDATA_ANY(json),
     537            5280 :                                         VARSIZE_ANY_EXHDR(json),
     538                 :                                         GetDatabaseEncoding(),
     539 ECB             :                                         need_escapes);
     540                 : }
     541                 : 
     542                 : /*
     543                 :  * SQL function json_object_keys
     544                 :  *
     545                 :  * Returns the set of keys for the object argument.
     546                 :  *
     547                 :  * This SRF operates in value-per-call mode. It processes the
     548                 :  * object during the first call, and the keys are simply stashed
     549                 :  * in an array, whose size is expanded as necessary. This is probably
     550                 :  * safe enough for a list of keys of a single object, since they are
     551                 :  * limited in size to NAMEDATALEN and the number of keys is unlikely to
     552                 :  * be so huge that it has major memory implications.
     553                 :  */
     554                 : Datum
     555 GIC          27 : jsonb_object_keys(PG_FUNCTION_ARGS)
     556                 : {
     557                 :     FuncCallContext *funcctx;
     558                 :     OkeysState *state;
     559                 : 
     560              27 :     if (SRF_IS_FIRSTCALL())
     561                 :     {
     562                 :         MemoryContext oldcontext;
     563               9 :         Jsonb      *jb = PG_GETARG_JSONB_P(0);
     564               9 :         bool        skipNested = false;
     565                 :         JsonbIterator *it;
     566 ECB             :         JsonbValue  v;
     567                 :         JsonbIteratorToken r;
     568                 : 
     569 GIC           9 :         if (JB_ROOT_IS_SCALAR(jb))
     570               3 :             ereport(ERROR,
     571 ECB             :                     (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
     572                 :                      errmsg("cannot call %s on a scalar",
     573                 :                             "jsonb_object_keys")));
     574 CBC           6 :         else if (JB_ROOT_IS_ARRAY(jb))
     575               3 :             ereport(ERROR,
     576                 :                     (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
     577                 :                      errmsg("cannot call %s on an array",
     578                 :                             "jsonb_object_keys")));
     579                 : 
     580               3 :         funcctx = SRF_FIRSTCALL_INIT();
     581               3 :         oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
     582                 : 
     583 GIC           3 :         state = palloc(sizeof(OkeysState));
     584                 : 
     585 CBC           3 :         state->result_size = JB_ROOT_COUNT(jb);
     586               3 :         state->result_count = 0;
     587 GIC           3 :         state->sent_count = 0;
     588               3 :         state->result = palloc(state->result_size * sizeof(char *));
     589                 : 
     590               3 :         it = JsonbIteratorInit(&jb->root);
     591 ECB             : 
     592 CBC          45 :         while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE)
     593                 :         {
     594              42 :             skipNested = true;
     595                 : 
     596              42 :             if (r == WJB_KEY)
     597 ECB             :             {
     598                 :                 char       *cstr;
     599                 : 
     600 GIC          18 :                 cstr = palloc(v.val.string.len + 1 * sizeof(char));
     601 CBC          18 :                 memcpy(cstr, v.val.string.val, v.val.string.len);
     602 GIC          18 :                 cstr[v.val.string.len] = '\0';
     603 CBC          18 :                 state->result[state->result_count++] = cstr;
     604                 :             }
     605 ECB             :         }
     606                 : 
     607 CBC           3 :         MemoryContextSwitchTo(oldcontext);
     608 GIC           3 :         funcctx->user_fctx = (void *) state;
     609                 :     }
     610                 : 
     611 CBC          21 :     funcctx = SRF_PERCALL_SETUP();
     612              21 :     state = (OkeysState *) funcctx->user_fctx;
     613 ECB             : 
     614 CBC          21 :     if (state->sent_count < state->result_count)
     615                 :     {
     616 GIC          18 :         char       *nxt = state->result[state->sent_count++];
     617                 : 
     618 CBC          18 :         SRF_RETURN_NEXT(funcctx, CStringGetTextDatum(nxt));
     619 ECB             :     }
     620                 : 
     621 GIC           3 :     SRF_RETURN_DONE(funcctx);
     622 ECB             : }
     623                 : 
     624                 : /*
     625                 :  * Report a JSON error.
     626                 :  */
     627                 : void
     628 GNC         228 : json_errsave_error(JsonParseErrorType error, JsonLexContext *lex,
     629                 :                    Node *escontext)
     630 ECB             : {
     631 GIC         228 :     if (error == JSON_UNICODE_HIGH_ESCAPE ||
     632 GNC         228 :         error == JSON_UNICODE_UNTRANSLATABLE ||
     633                 :         error == JSON_UNICODE_CODE_POINT_ZERO)
     634              12 :         errsave(escontext,
     635                 :                 (errcode(ERRCODE_UNTRANSLATABLE_CHARACTER),
     636                 :                  errmsg("unsupported Unicode escape sequence"),
     637                 :                  errdetail_internal("%s", json_errdetail(error, lex)),
     638                 :                  report_json_context(lex)));
     639             216 :     else if (error == JSON_SEM_ACTION_FAILED)
     640                 :     {
     641                 :         /* semantic action function had better have reported something */
     642               3 :         if (!SOFT_ERROR_OCCURRED(escontext))
     643 UNC           0 :             elog(ERROR, "JSON semantic action function did not provide error information");
     644                 :     }
     645                 :     else
     646 GNC         213 :         errsave(escontext,
     647 ECB             :                 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
     648                 :                  errmsg("invalid input syntax for type %s", "json"),
     649                 :                  errdetail_internal("%s", json_errdetail(error, lex)),
     650                 :                  report_json_context(lex)));
     651 CBC          15 : }
     652                 : 
     653 ECB             : /*
     654                 :  * Report a CONTEXT line for bogus JSON input.
     655                 :  *
     656                 :  * lex->token_terminator must be set to identify the spot where we detected
     657                 :  * the error.  Note that lex->token_start might be NULL, in case we recognized
     658                 :  * error at EOF.
     659                 :  *
     660                 :  * The return value isn't meaningful, but we make it non-void so that this
     661                 :  * can be invoked inside ereport().
     662 EUB             :  */
     663                 : static int
     664 GIC         219 : report_json_context(JsonLexContext *lex)
     665 ECB             : {
     666                 :     const char *context_start;
     667                 :     const char *context_end;
     668                 :     const char *line_start;
     669                 :     char       *ctxt;
     670                 :     int         ctxtlen;
     671                 :     const char *prefix;
     672                 :     const char *suffix;
     673                 : 
     674                 :     /* Choose boundaries for the part of the input we will display */
     675 GIC         219 :     line_start = lex->line_start;
     676             219 :     context_start = line_start;
     677             219 :     context_end = lex->token_terminator;
     678             219 :     Assert(context_end >= context_start);
     679                 : 
     680                 :     /* Advance until we are close enough to context_end */
     681             285 :     while (context_end - context_start >= 50)
     682                 :     {
     683 ECB             :         /* Advance to next multibyte character */
     684 GIC          66 :         if (IS_HIGHBIT_SET(*context_start))
     685 UIC           0 :             context_start += pg_mblen(context_start);
     686                 :         else
     687 GIC          66 :             context_start++;
     688                 :     }
     689                 : 
     690                 :     /*
     691                 :      * We add "..." to indicate that the excerpt doesn't start at the
     692                 :      * beginning of the line ... but if we're within 3 characters of the
     693                 :      * beginning of the line, we might as well just show the whole line.
     694 ECB             :      */
     695 CBC         219 :     if (context_start - line_start <= 3)
     696             213 :         context_start = line_start;
     697 ECB             : 
     698                 :     /* Get a null-terminated copy of the data to present */
     699 GIC         219 :     ctxtlen = context_end - context_start;
     700 CBC         219 :     ctxt = palloc(ctxtlen + 1);
     701 GIC         219 :     memcpy(ctxt, context_start, ctxtlen);
     702             219 :     ctxt[ctxtlen] = '\0';
     703 ECB             : 
     704 EUB             :     /*
     705                 :      * Show the context, prefixing "..." if not starting at start of line, and
     706 ECB             :      * suffixing "..." if not ending at end of line.
     707                 :      */
     708 GIC         219 :     prefix = (context_start > line_start) ? "..." : "";
     709             627 :     suffix = (lex->token_type != JSON_TOKEN_END &&
     710             189 :               context_end - lex->input < lex->input_length &&
     711             408 :               *context_end != '\n' && *context_end != '\r') ? "..." : "";
     712                 : 
     713             219 :     return errcontext("JSON data, line %d: %s%s%s",
     714 ECB             :                       lex->line_number, prefix, ctxt, suffix);
     715                 : }
     716                 : 
     717                 : 
     718                 : Datum
     719 CBC         930 : json_object_keys(PG_FUNCTION_ARGS)
     720 ECB             : {
     721                 :     FuncCallContext *funcctx;
     722                 :     OkeysState *state;
     723                 : 
     724 GIC         930 :     if (SRF_IS_FIRSTCALL())
     725                 :     {
     726              12 :         text       *json = PG_GETARG_TEXT_PP(0);
     727 CBC          12 :         JsonLexContext *lex = makeJsonLexContext(json, true);
     728 ECB             :         JsonSemAction *sem;
     729                 :         MemoryContext oldcontext;
     730                 : 
     731 GIC          12 :         funcctx = SRF_FIRSTCALL_INIT();
     732 CBC          12 :         oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
     733                 : 
     734 GIC          12 :         state = palloc(sizeof(OkeysState));
     735              12 :         sem = palloc0(sizeof(JsonSemAction));
     736                 : 
     737              12 :         state->lex = lex;
     738 CBC          12 :         state->result_size = 256;
     739 GIC          12 :         state->result_count = 0;
     740              12 :         state->sent_count = 0;
     741              12 :         state->result = palloc(256 * sizeof(char *));
     742                 : 
     743 CBC          12 :         sem->semstate = (void *) state;
     744 GIC          12 :         sem->array_start = okeys_array_start;
     745 CBC          12 :         sem->scalar = okeys_scalar;
     746              12 :         sem->object_field_start = okeys_object_field_start;
     747                 :         /* remainder are all NULL, courtesy of palloc0 above */
     748                 : 
     749 GIC          12 :         pg_parse_json_or_ereport(lex, sem);
     750 ECB             :         /* keys are now in state->result */
     751                 : 
     752 GIC           6 :         pfree(lex->strval->data);
     753 CBC           6 :         pfree(lex->strval);
     754               6 :         pfree(lex);
     755 GIC           6 :         pfree(sem);
     756 ECB             : 
     757 CBC           6 :         MemoryContextSwitchTo(oldcontext);
     758               6 :         funcctx->user_fctx = (void *) state;
     759 ECB             :     }
     760                 : 
     761 GIC         924 :     funcctx = SRF_PERCALL_SETUP();
     762 CBC         924 :     state = (OkeysState *) funcctx->user_fctx;
     763 ECB             : 
     764 CBC         924 :     if (state->sent_count < state->result_count)
     765 ECB             :     {
     766 GIC         918 :         char       *nxt = state->result[state->sent_count++];
     767                 : 
     768 CBC         918 :         SRF_RETURN_NEXT(funcctx, CStringGetTextDatum(nxt));
     769                 :     }
     770                 : 
     771               6 :     SRF_RETURN_DONE(funcctx);
     772 ECB             : }
     773                 : 
     774                 : static JsonParseErrorType
     775 GIC         921 : okeys_object_field_start(void *state, char *fname, bool isnull)
     776 ECB             : {
     777 CBC         921 :     OkeysState *_state = (OkeysState *) state;
     778                 : 
     779                 :     /* only collecting keys for the top level object */
     780             921 :     if (_state->lex->lex_level != 1)
     781 GNC           3 :         return JSON_SUCCESS;
     782                 : 
     783 ECB             :     /* enlarge result array if necessary */
     784 GIC         918 :     if (_state->result_count >= _state->result_size)
     785 ECB             :     {
     786 GIC           3 :         _state->result_size *= 2;
     787 CBC           3 :         _state->result = (char **)
     788 GIC           3 :             repalloc(_state->result, sizeof(char *) * _state->result_size);
     789                 :     }
     790 ECB             : 
     791                 :     /* save a copy of the field name */
     792 GIC         918 :     _state->result[_state->result_count++] = pstrdup(fname);
     793                 : 
     794 GNC         918 :     return JSON_SUCCESS;
     795                 : }
     796 ECB             : 
     797                 : static JsonParseErrorType
     798 CBC           6 : okeys_array_start(void *state)
     799                 : {
     800 GIC           6 :     OkeysState *_state = (OkeysState *) state;
     801 ECB             : 
     802                 :     /* top level must be a json object */
     803 GIC           6 :     if (_state->lex->lex_level == 0)
     804               3 :         ereport(ERROR,
     805 ECB             :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
     806                 :                  errmsg("cannot call %s on an array",
     807                 :                         "json_object_keys")));
     808                 : 
     809 GNC           3 :     return JSON_SUCCESS;
     810 ECB             : }
     811                 : 
     812                 : static JsonParseErrorType
     813 GIC         927 : okeys_scalar(void *state, char *token, JsonTokenType tokentype)
     814                 : {
     815 CBC         927 :     OkeysState *_state = (OkeysState *) state;
     816                 : 
     817 ECB             :     /* top level must be a json object */
     818 GIC         927 :     if (_state->lex->lex_level == 0)
     819               3 :         ereport(ERROR,
     820                 :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
     821 ECB             :                  errmsg("cannot call %s on a scalar",
     822                 :                         "json_object_keys")));
     823                 : 
     824 GNC         924 :     return JSON_SUCCESS;
     825 ECB             : }
     826                 : 
     827                 : /*
     828                 :  * json and jsonb getter functions
     829                 :  * these implement the -> ->> #> and #>> operators
     830                 :  * and the json{b?}_extract_path*(json, text, ...) functions
     831                 :  */
     832                 : 
     833                 : 
     834                 : Datum
     835 GIC         490 : json_object_field(PG_FUNCTION_ARGS)
     836                 : {
     837             490 :     text       *json = PG_GETARG_TEXT_PP(0);
     838 CBC         490 :     text       *fname = PG_GETARG_TEXT_PP(1);
     839 GIC         490 :     char       *fnamestr = text_to_cstring(fname);
     840 ECB             :     text       *result;
     841                 : 
     842 GIC         490 :     result = get_worker(json, &fnamestr, NULL, 1, false);
     843 ECB             : 
     844 CBC         478 :     if (result != NULL)
     845 GIC         391 :         PG_RETURN_TEXT_P(result);
     846                 :     else
     847              87 :         PG_RETURN_NULL();
     848                 : }
     849 ECB             : 
     850                 : Datum
     851 GIC       12345 : jsonb_object_field(PG_FUNCTION_ARGS)
     852                 : {
     853           12345 :     Jsonb      *jb = PG_GETARG_JSONB_P(0);
     854           12345 :     text       *key = PG_GETARG_TEXT_PP(1);
     855                 :     JsonbValue *v;
     856                 :     JsonbValue  vbuf;
     857                 : 
     858           12345 :     if (!JB_ROOT_IS_OBJECT(jb))
     859              12 :         PG_RETURN_NULL();
     860 ECB             : 
     861 GIC       24666 :     v = getKeyJsonValueFromContainer(&jb->root,
     862 CBC       12333 :                                      VARDATA_ANY(key),
     863           12333 :                                      VARSIZE_ANY_EXHDR(key),
     864 ECB             :                                      &vbuf);
     865                 : 
     866 GIC       12333 :     if (v != NULL)
     867 CBC         216 :         PG_RETURN_JSONB_P(JsonbValueToJsonb(v));
     868                 : 
     869           12117 :     PG_RETURN_NULL();
     870 ECB             : }
     871                 : 
     872                 : Datum
     873 GIC         462 : json_object_field_text(PG_FUNCTION_ARGS)
     874                 : {
     875             462 :     text       *json = PG_GETARG_TEXT_PP(0);
     876 CBC         462 :     text       *fname = PG_GETARG_TEXT_PP(1);
     877 GIC         462 :     char       *fnamestr = text_to_cstring(fname);
     878 ECB             :     text       *result;
     879                 : 
     880 GIC         462 :     result = get_worker(json, &fnamestr, NULL, 1, true);
     881                 : 
     882             459 :     if (result != NULL)
     883 CBC         441 :         PG_RETURN_TEXT_P(result);
     884 ECB             :     else
     885 GIC          18 :         PG_RETURN_NULL();
     886 ECB             : }
     887                 : 
     888                 : Datum
     889 GIC          99 : jsonb_object_field_text(PG_FUNCTION_ARGS)
     890                 : {
     891 CBC          99 :     Jsonb      *jb = PG_GETARG_JSONB_P(0);
     892              99 :     text       *key = PG_GETARG_TEXT_PP(1);
     893                 :     JsonbValue *v;
     894 ECB             :     JsonbValue  vbuf;
     895                 : 
     896 GIC          99 :     if (!JB_ROOT_IS_OBJECT(jb))
     897              12 :         PG_RETURN_NULL();
     898 ECB             : 
     899 GIC         174 :     v = getKeyJsonValueFromContainer(&jb->root,
     900 CBC          87 :                                      VARDATA_ANY(key),
     901              87 :                                      VARSIZE_ANY_EXHDR(key),
     902 ECB             :                                      &vbuf);
     903                 : 
     904 GIC          87 :     if (v != NULL && v->type != jbvNull)
     905 CBC          72 :         PG_RETURN_TEXT_P(JsonbValueAsText(v));
     906                 : 
     907              15 :     PG_RETURN_NULL();
     908 ECB             : }
     909                 : 
     910                 : Datum
     911 GIC         140 : json_array_element(PG_FUNCTION_ARGS)
     912                 : {
     913             140 :     text       *json = PG_GETARG_TEXT_PP(0);
     914 CBC         140 :     int         element = PG_GETARG_INT32(1);
     915                 :     text       *result;
     916 ECB             : 
     917 CBC         140 :     result = get_worker(json, NULL, &element, 1, false);
     918                 : 
     919 GIC         140 :     if (result != NULL)
     920             122 :         PG_RETURN_TEXT_P(result);
     921 ECB             :     else
     922 CBC          18 :         PG_RETURN_NULL();
     923                 : }
     924 ECB             : 
     925                 : Datum
     926 CBC         159 : jsonb_array_element(PG_FUNCTION_ARGS)
     927                 : {
     928 GIC         159 :     Jsonb      *jb = PG_GETARG_JSONB_P(0);
     929 CBC         159 :     int         element = PG_GETARG_INT32(1);
     930 ECB             :     JsonbValue *v;
     931                 : 
     932 CBC         159 :     if (!JB_ROOT_IS_ARRAY(jb))
     933 GIC           9 :         PG_RETURN_NULL();
     934                 : 
     935                 :     /* Handle negative subscript */
     936 CBC         150 :     if (element < 0)
     937                 :     {
     938               9 :         uint32      nelements = JB_ROOT_COUNT(jb);
     939 ECB             : 
     940 GIC           9 :         if (-element > nelements)
     941               3 :             PG_RETURN_NULL();
     942 ECB             :         else
     943 GIC           6 :             element += nelements;
     944 ECB             :     }
     945                 : 
     946 GIC         147 :     v = getIthJsonbValueFromContainer(&jb->root, element);
     947 CBC         147 :     if (v != NULL)
     948 GIC         132 :         PG_RETURN_JSONB_P(JsonbValueToJsonb(v));
     949                 : 
     950              15 :     PG_RETURN_NULL();
     951 ECB             : }
     952                 : 
     953                 : Datum
     954 CBC          24 : json_array_element_text(PG_FUNCTION_ARGS)
     955                 : {
     956 GIC          24 :     text       *json = PG_GETARG_TEXT_PP(0);
     957 CBC          24 :     int         element = PG_GETARG_INT32(1);
     958 ECB             :     text       *result;
     959                 : 
     960 GIC          24 :     result = get_worker(json, NULL, &element, 1, true);
     961 ECB             : 
     962 GIC          24 :     if (result != NULL)
     963 CBC          12 :         PG_RETURN_TEXT_P(result);
     964                 :     else
     965              12 :         PG_RETURN_NULL();
     966 ECB             : }
     967                 : 
     968                 : Datum
     969 GIC          30 : jsonb_array_element_text(PG_FUNCTION_ARGS)
     970                 : {
     971 CBC          30 :     Jsonb      *jb = PG_GETARG_JSONB_P(0);
     972              30 :     int         element = PG_GETARG_INT32(1);
     973 ECB             :     JsonbValue *v;
     974                 : 
     975 CBC          30 :     if (!JB_ROOT_IS_ARRAY(jb))
     976 GIC           6 :         PG_RETURN_NULL();
     977                 : 
     978                 :     /* Handle negative subscript */
     979 CBC          24 :     if (element < 0)
     980                 :     {
     981 LBC           0 :         uint32      nelements = JB_ROOT_COUNT(jb);
     982 ECB             : 
     983 UIC           0 :         if (-element > nelements)
     984               0 :             PG_RETURN_NULL();
     985 ECB             :         else
     986 UIC           0 :             element += nelements;
     987 ECB             :     }
     988                 : 
     989 GIC          24 :     v = getIthJsonbValueFromContainer(&jb->root, element);
     990 ECB             : 
     991 GIC          24 :     if (v != NULL && v->type != jbvNull)
     992              12 :         PG_RETURN_TEXT_P(JsonbValueAsText(v));
     993                 : 
     994 CBC          12 :     PG_RETURN_NULL();
     995                 : }
     996 ECB             : 
     997                 : Datum
     998 GIC         144 : json_extract_path(PG_FUNCTION_ARGS)
     999                 : {
    1000 CBC         144 :     return get_path_all(fcinfo, false);
    1001 ECB             : }
    1002                 : 
    1003                 : Datum
    1004 CBC          90 : json_extract_path_text(PG_FUNCTION_ARGS)
    1005                 : {
    1006 GBC          90 :     return get_path_all(fcinfo, true);
    1007                 : }
    1008 EUB             : 
    1009                 : /*
    1010                 :  * common routine for extract_path functions
    1011                 :  */
    1012                 : static Datum
    1013 GIC         234 : get_path_all(FunctionCallInfo fcinfo, bool as_text)
    1014 ECB             : {
    1015 GIC         234 :     text       *json = PG_GETARG_TEXT_PP(0);
    1016 CBC         234 :     ArrayType  *path = PG_GETARG_ARRAYTYPE_P(1);
    1017 ECB             :     text       *result;
    1018                 :     Datum      *pathtext;
    1019                 :     bool       *pathnulls;
    1020                 :     int         npath;
    1021                 :     char      **tpath;
    1022                 :     int        *ipath;
    1023                 :     int         i;
    1024                 : 
    1025                 :     /*
    1026                 :      * If the array contains any null elements, return NULL, on the grounds
    1027                 :      * that you'd have gotten NULL if any RHS value were NULL in a nested
    1028                 :      * series of applications of the -> operator.  (Note: because we also
    1029                 :      * return NULL for error cases such as no-such-field, this is true
    1030                 :      * regardless of the contents of the rest of the array.)
    1031                 :      */
    1032 GIC         234 :     if (array_contains_nulls(path))
    1033               6 :         PG_RETURN_NULL();
    1034                 : 
    1035 GNC         228 :     deconstruct_array_builtin(path, TEXTOID, &pathtext, &pathnulls, &npath);
    1036                 : 
    1037 CBC         228 :     tpath = palloc(npath * sizeof(char *));
    1038 GIC         228 :     ipath = palloc(npath * sizeof(int));
    1039 ECB             : 
    1040 CBC         624 :     for (i = 0; i < npath; i++)
    1041                 :     {
    1042 GIC         396 :         Assert(!pathnulls[i]);
    1043             396 :         tpath[i] = TextDatumGetCString(pathtext[i]);
    1044                 : 
    1045                 :         /*
    1046                 :          * we have no idea at this stage what structure the document is so
    1047                 :          * just convert anything in the path that we can to an integer and set
    1048                 :          * all the other integers to INT_MIN which will never match.
    1049                 :          */
    1050             396 :         if (*tpath[i] != '\0')
    1051                 :         {
    1052                 :             int         ind;
    1053                 :             char       *endptr;
    1054                 : 
    1055             390 :             errno = 0;
    1056 CBC         390 :             ind = strtoint(tpath[i], &endptr, 10);
    1057             390 :             if (endptr == tpath[i] || *endptr != '\0' || errno != 0)
    1058 GIC         282 :                 ipath[i] = INT_MIN;
    1059 ECB             :             else
    1060 GIC         108 :                 ipath[i] = ind;
    1061 ECB             :         }
    1062                 :         else
    1063 GIC           6 :             ipath[i] = INT_MIN;
    1064 ECB             :     }
    1065                 : 
    1066 CBC         228 :     result = get_worker(json, tpath, ipath, npath, as_text);
    1067 ECB             : 
    1068 GIC         228 :     if (result != NULL)
    1069             168 :         PG_RETURN_TEXT_P(result);
    1070                 :     else
    1071              60 :         PG_RETURN_NULL();
    1072                 : }
    1073                 : 
    1074 ECB             : /*
    1075                 :  * get_worker
    1076                 :  *
    1077                 :  * common worker for all the json getter functions
    1078                 :  *
    1079                 :  * json: JSON object (in text form)
    1080                 :  * tpath[]: field name(s) to extract
    1081                 :  * ipath[]: array index(es) (zero-based) to extract, accepts negatives
    1082                 :  * npath: length of tpath[] and/or ipath[]
    1083                 :  * normalize_results: true to de-escape string and null scalars
    1084                 :  *
    1085                 :  * tpath can be NULL, or any one tpath[] entry can be NULL, if an object
    1086                 :  * field is not to be matched at that nesting level.  Similarly, ipath can
    1087                 :  * be NULL, or any one ipath[] entry can be INT_MIN if an array element is
    1088                 :  * not to be matched at that nesting level (a json datum should never be
    1089                 :  * large enough to have -INT_MIN elements due to MaxAllocSize restriction).
    1090                 :  */
    1091                 : static text *
    1092 CBC        1344 : get_worker(text *json,
    1093 ECB             :            char **tpath,
    1094                 :            int *ipath,
    1095                 :            int npath,
    1096                 :            bool normalize_results)
    1097                 : {
    1098 GIC        1344 :     JsonLexContext *lex = makeJsonLexContext(json, true);
    1099            1344 :     JsonSemAction *sem = palloc0(sizeof(JsonSemAction));
    1100            1344 :     GetState   *state = palloc0(sizeof(GetState));
    1101                 : 
    1102            1344 :     Assert(npath >= 0);
    1103                 : 
    1104            1344 :     state->lex = lex;
    1105                 :     /* is it "_as_text" variant? */
    1106            1344 :     state->normalize_results = normalize_results;
    1107            1344 :     state->npath = npath;
    1108            1344 :     state->path_names = tpath;
    1109            1344 :     state->path_indexes = ipath;
    1110            1344 :     state->pathok = palloc0(sizeof(bool) * npath);
    1111            1344 :     state->array_cur_index = palloc(sizeof(int) * npath);
    1112                 : 
    1113            1344 :     if (npath > 0)
    1114            1314 :         state->pathok[0] = true;
    1115                 : 
    1116 CBC        1344 :     sem->semstate = (void *) state;
    1117                 : 
    1118                 :     /*
    1119                 :      * Not all variants need all the semantic routines. Only set the ones that
    1120                 :      * are actually needed for maximum efficiency.
    1121                 :      */
    1122            1344 :     sem->scalar = get_scalar;
    1123            1344 :     if (npath == 0)
    1124 ECB             :     {
    1125 GIC          30 :         sem->object_start = get_object_start;
    1126 CBC          30 :         sem->object_end = get_object_end;
    1127 GIC          30 :         sem->array_start = get_array_start;
    1128 CBC          30 :         sem->array_end = get_array_end;
    1129                 :     }
    1130            1344 :     if (tpath != NULL)
    1131 ECB             :     {
    1132 CBC        1180 :         sem->object_field_start = get_object_field_start;
    1133            1180 :         sem->object_field_end = get_object_field_end;
    1134 ECB             :     }
    1135 CBC        1344 :     if (ipath != NULL)
    1136                 :     {
    1137             392 :         sem->array_start = get_array_start;
    1138             392 :         sem->array_element_start = get_array_element_start;
    1139 GIC         392 :         sem->array_element_end = get_array_element_end;
    1140 ECB             :     }
    1141                 : 
    1142 GIC        1344 :     pg_parse_json_or_ereport(lex, sem);
    1143                 : 
    1144            1329 :     return state->tresult;
    1145                 : }
    1146 ECB             : 
    1147                 : static JsonParseErrorType
    1148 GIC          18 : get_object_start(void *state)
    1149 ECB             : {
    1150 CBC          18 :     GetState   *_state = (GetState *) state;
    1151              18 :     int         lex_level = _state->lex->lex_level;
    1152 ECB             : 
    1153 GIC          18 :     if (lex_level == 0 && _state->npath == 0)
    1154 ECB             :     {
    1155                 :         /*
    1156                 :          * Special case: we should match the entire object.  We only need this
    1157                 :          * at outermost level because at nested levels the match will have
    1158                 :          * been started by the outer field or array element callback.
    1159                 :          */
    1160 GIC           6 :         _state->result_start = _state->lex->token_start;
    1161 ECB             :     }
    1162                 : 
    1163 GNC          18 :     return JSON_SUCCESS;
    1164 ECB             : }
    1165                 : 
    1166                 : static JsonParseErrorType
    1167 GIC          18 : get_object_end(void *state)
    1168 ECB             : {
    1169 GIC          18 :     GetState   *_state = (GetState *) state;
    1170 CBC          18 :     int         lex_level = _state->lex->lex_level;
    1171                 : 
    1172 GIC          18 :     if (lex_level == 0 && _state->npath == 0)
    1173                 :     {
    1174 ECB             :         /* Special case: return the entire object */
    1175 GIC           6 :         char       *start = _state->result_start;
    1176 CBC           6 :         int         len = _state->lex->prev_token_terminator - start;
    1177 ECB             : 
    1178 GIC           6 :         _state->tresult = cstring_to_text_with_len(start, len);
    1179 ECB             :     }
    1180                 : 
    1181 GNC          18 :     return JSON_SUCCESS;
    1182                 : }
    1183                 : 
    1184                 : static JsonParseErrorType
    1185 GIC       53456 : get_object_field_start(void *state, char *fname, bool isnull)
    1186                 : {
    1187           53456 :     GetState   *_state = (GetState *) state;
    1188 CBC       53456 :     bool        get_next = false;
    1189 GIC       53456 :     int         lex_level = _state->lex->lex_level;
    1190                 : 
    1191 CBC       53456 :     if (lex_level <= _state->npath &&
    1192 GIC       14069 :         _state->pathok[lex_level - 1] &&
    1193           13949 :         _state->path_names != NULL &&
    1194           13949 :         _state->path_names[lex_level - 1] != NULL &&
    1195 CBC       13949 :         strcmp(fname, _state->path_names[lex_level - 1]) == 0)
    1196                 :     {
    1197            1066 :         if (lex_level < _state->npath)
    1198 ECB             :         {
    1199                 :             /* if not at end of path just mark path ok */
    1200 CBC         108 :             _state->pathok[lex_level] = true;
    1201                 :         }
    1202                 :         else
    1203 ECB             :         {
    1204                 :             /* end of path, so we want this value */
    1205 GIC         958 :             get_next = true;
    1206 ECB             :         }
    1207                 :     }
    1208                 : 
    1209 CBC       53456 :     if (get_next)
    1210                 :     {
    1211                 :         /* this object overrides any previous matching object */
    1212 GIC         958 :         _state->tresult = NULL;
    1213 CBC         958 :         _state->result_start = NULL;
    1214                 : 
    1215             958 :         if (_state->normalize_results &&
    1216             480 :             _state->lex->token_type == JSON_TOKEN_STRING)
    1217 ECB             :         {
    1218                 :             /* for as_text variants, tell get_scalar to set it for us */
    1219 CBC         339 :             _state->next_scalar = true;
    1220 ECB             :         }
    1221                 :         else
    1222                 :         {
    1223                 :             /* for non-as_text variants, just note the json starting point */
    1224 GIC         619 :             _state->result_start = _state->lex->token_start;
    1225 ECB             :         }
    1226                 :     }
    1227                 : 
    1228 GNC       53456 :     return JSON_SUCCESS;
    1229                 : }
    1230 ECB             : 
    1231                 : static JsonParseErrorType
    1232 GIC       53456 : get_object_field_end(void *state, char *fname, bool isnull)
    1233                 : {
    1234           53456 :     GetState   *_state = (GetState *) state;
    1235 CBC       53456 :     bool        get_last = false;
    1236 GIC       53456 :     int         lex_level = _state->lex->lex_level;
    1237                 : 
    1238                 :     /* same tests as in get_object_field_start */
    1239 CBC       53456 :     if (lex_level <= _state->npath &&
    1240 GIC       14069 :         _state->pathok[lex_level - 1] &&
    1241           13949 :         _state->path_names != NULL &&
    1242 CBC       13949 :         _state->path_names[lex_level - 1] != NULL &&
    1243           13949 :         strcmp(fname, _state->path_names[lex_level - 1]) == 0)
    1244                 :     {
    1245            1066 :         if (lex_level < _state->npath)
    1246 ECB             :         {
    1247                 :             /* done with this field so reset pathok */
    1248 GIC         108 :             _state->pathok[lex_level] = false;
    1249 ECB             :         }
    1250                 :         else
    1251                 :         {
    1252                 :             /* end of path, so we want this value */
    1253 GIC         958 :             get_last = true;
    1254 ECB             :         }
    1255                 :     }
    1256                 : 
    1257                 :     /* for as_text scalar case, our work is already done */
    1258 CBC       53456 :     if (get_last && _state->result_start != NULL)
    1259                 :     {
    1260                 :         /*
    1261                 :          * make a text object from the string from the previously noted json
    1262 ECB             :          * start up to the end of the previous token (the lexer is by now
    1263                 :          * ahead of us on whatever came after what we're interested in).
    1264                 :          */
    1265 CBC         619 :         if (isnull && _state->normalize_results)
    1266              12 :             _state->tresult = (text *) NULL;
    1267                 :         else
    1268                 :         {
    1269             607 :             char       *start = _state->result_start;
    1270             607 :             int         len = _state->lex->prev_token_terminator - start;
    1271 ECB             : 
    1272 CBC         607 :             _state->tresult = cstring_to_text_with_len(start, len);
    1273 ECB             :         }
    1274                 : 
    1275                 :         /* this should be unnecessary but let's do it for cleanliness: */
    1276 GIC         619 :         _state->result_start = NULL;
    1277                 :     }
    1278                 : 
    1279 GNC       53456 :     return JSON_SUCCESS;
    1280 ECB             : }
    1281                 : 
    1282                 : static JsonParseErrorType
    1283 GIC         928 : get_array_start(void *state)
    1284                 : {
    1285 CBC         928 :     GetState   *_state = (GetState *) state;
    1286 GIC         928 :     int         lex_level = _state->lex->lex_level;
    1287                 : 
    1288             928 :     if (lex_level < _state->npath)
    1289                 :     {
    1290 ECB             :         /* Initialize counting of elements in this array */
    1291 GIC         257 :         _state->array_cur_index[lex_level] = -1;
    1292                 : 
    1293                 :         /* INT_MIN value is reserved to represent invalid subscript */
    1294             257 :         if (_state->path_indexes[lex_level] < 0 &&
    1295              15 :             _state->path_indexes[lex_level] != INT_MIN)
    1296                 :         {
    1297 ECB             :             /* Negative subscript -- convert to positive-wise subscript */
    1298                 :             JsonParseErrorType error;
    1299                 :             int         nelements;
    1300                 : 
    1301 CBC           3 :             error = json_count_array_elements(_state->lex, &nelements);
    1302               3 :             if (error != JSON_SUCCESS)
    1303 UNC           0 :                 json_errsave_error(error, _state->lex, NULL);
    1304 ECB             : 
    1305 GIC           3 :             if (-_state->path_indexes[lex_level] <= nelements)
    1306               3 :                 _state->path_indexes[lex_level] += nelements;
    1307                 :         }
    1308 ECB             :     }
    1309 GIC         671 :     else if (lex_level == 0 && _state->npath == 0)
    1310                 :     {
    1311 ECB             :         /*
    1312                 :          * Special case: we should match the entire array.  We only need this
    1313                 :          * at the outermost level because at nested levels the match will have
    1314                 :          * been started by the outer field or array element callback.
    1315                 :          */
    1316 GIC           6 :         _state->result_start = _state->lex->token_start;
    1317 ECB             :     }
    1318                 : 
    1319 GNC         928 :     return JSON_SUCCESS;
    1320 ECB             : }
    1321                 : 
    1322                 : static JsonParseErrorType
    1323 GIC           6 : get_array_end(void *state)
    1324                 : {
    1325 CBC           6 :     GetState   *_state = (GetState *) state;
    1326 GIC           6 :     int         lex_level = _state->lex->lex_level;
    1327                 : 
    1328 CBC           6 :     if (lex_level == 0 && _state->npath == 0)
    1329 ECB             :     {
    1330                 :         /* Special case: return the entire array */
    1331 GIC           6 :         char       *start = _state->result_start;
    1332               6 :         int         len = _state->lex->prev_token_terminator - start;
    1333                 : 
    1334               6 :         _state->tresult = cstring_to_text_with_len(start, len);
    1335 ECB             :     }
    1336                 : 
    1337 GNC           6 :     return JSON_SUCCESS;
    1338 ECB             : }
    1339 EUB             : 
    1340                 : static JsonParseErrorType
    1341 CBC         965 : get_array_element_start(void *state, bool isnull)
    1342 ECB             : {
    1343 GIC         965 :     GetState   *_state = (GetState *) state;
    1344             965 :     bool        get_next = false;
    1345 CBC         965 :     int         lex_level = _state->lex->lex_level;
    1346                 : 
    1347                 :     /* Update array element counter */
    1348 GIC         965 :     if (lex_level <= _state->npath)
    1349             488 :         _state->array_cur_index[lex_level - 1]++;
    1350                 : 
    1351             965 :     if (lex_level <= _state->npath &&
    1352 CBC         488 :         _state->pathok[lex_level - 1] &&
    1353 GIC         488 :         _state->path_indexes != NULL &&
    1354             488 :         _state->array_cur_index[lex_level - 1] == _state->path_indexes[lex_level - 1])
    1355 ECB             :     {
    1356 GIC         239 :         if (lex_level < _state->npath)
    1357                 :         {
    1358                 :             /* if not at end of path just mark path ok */
    1359 CBC          72 :             _state->pathok[lex_level] = true;
    1360                 :         }
    1361 ECB             :         else
    1362                 :         {
    1363                 :             /* end of path, so we want this value */
    1364 CBC         167 :             get_next = true;
    1365                 :         }
    1366                 :     }
    1367 ECB             : 
    1368                 :     /* same logic as for objects */
    1369 GIC         965 :     if (get_next)
    1370 ECB             :     {
    1371 GIC         167 :         _state->tresult = NULL;
    1372             167 :         _state->result_start = NULL;
    1373 ECB             : 
    1374 GIC         167 :         if (_state->normalize_results &&
    1375              30 :             _state->lex->token_type == JSON_TOKEN_STRING)
    1376                 :         {
    1377 CBC           9 :             _state->next_scalar = true;
    1378                 :         }
    1379 ECB             :         else
    1380                 :         {
    1381 CBC         158 :             _state->result_start = _state->lex->token_start;
    1382                 :         }
    1383                 :     }
    1384                 : 
    1385 GNC         965 :     return JSON_SUCCESS;
    1386 ECB             : }
    1387                 : 
    1388                 : static JsonParseErrorType
    1389 CBC         965 : get_array_element_end(void *state, bool isnull)
    1390 ECB             : {
    1391 CBC         965 :     GetState   *_state = (GetState *) state;
    1392             965 :     bool        get_last = false;
    1393 GIC         965 :     int         lex_level = _state->lex->lex_level;
    1394 ECB             : 
    1395                 :     /* same tests as in get_array_element_start */
    1396 GIC         965 :     if (lex_level <= _state->npath &&
    1397 CBC         488 :         _state->pathok[lex_level - 1] &&
    1398 GIC         488 :         _state->path_indexes != NULL &&
    1399             488 :         _state->array_cur_index[lex_level - 1] == _state->path_indexes[lex_level - 1])
    1400                 :     {
    1401             239 :         if (lex_level < _state->npath)
    1402 ECB             :         {
    1403                 :             /* done with this element so reset pathok */
    1404 GIC          72 :             _state->pathok[lex_level] = false;
    1405                 :         }
    1406                 :         else
    1407 ECB             :         {
    1408                 :             /* end of path, so we want this value */
    1409 CBC         167 :             get_last = true;
    1410 ECB             :         }
    1411                 :     }
    1412                 : 
    1413                 :     /* same logic as for objects */
    1414 GIC         965 :     if (get_last && _state->result_start != NULL)
    1415 ECB             :     {
    1416 GIC         158 :         if (isnull && _state->normalize_results)
    1417               6 :             _state->tresult = (text *) NULL;
    1418                 :         else
    1419 ECB             :         {
    1420 GIC         152 :             char       *start = _state->result_start;
    1421             152 :             int         len = _state->lex->prev_token_terminator - start;
    1422                 : 
    1423 CBC         152 :             _state->tresult = cstring_to_text_with_len(start, len);
    1424                 :         }
    1425                 : 
    1426 GIC         158 :         _state->result_start = NULL;
    1427 ECB             :     }
    1428                 : 
    1429 GNC         965 :     return JSON_SUCCESS;
    1430                 : }
    1431 ECB             : 
    1432                 : static JsonParseErrorType
    1433 CBC       52731 : get_scalar(void *state, char *token, JsonTokenType tokentype)
    1434                 : {
    1435 GIC       52731 :     GetState   *_state = (GetState *) state;
    1436 CBC       52731 :     int         lex_level = _state->lex->lex_level;
    1437 ECB             : 
    1438                 :     /* Check for whole-object match */
    1439 CBC       52731 :     if (lex_level == 0 && _state->npath == 0)
    1440                 :     {
    1441              18 :         if (_state->normalize_results && tokentype == JSON_TOKEN_STRING)
    1442                 :         {
    1443                 :             /* we want the de-escaped string */
    1444               3 :             _state->next_scalar = true;
    1445                 :         }
    1446 GIC          15 :         else if (_state->normalize_results && tokentype == JSON_TOKEN_NULL)
    1447                 :         {
    1448               3 :             _state->tresult = (text *) NULL;
    1449 ECB             :         }
    1450                 :         else
    1451                 :         {
    1452                 :             /*
    1453                 :              * This is a bit hokey: we will suppress whitespace after the
    1454                 :              * scalar token, but not whitespace before it.  Probably not worth
    1455                 :              * doing our own space-skipping to avoid that.
    1456                 :              */
    1457 CBC          12 :             char       *start = _state->lex->input;
    1458 GIC          12 :             int         len = _state->lex->prev_token_terminator - start;
    1459                 : 
    1460 CBC          12 :             _state->tresult = cstring_to_text_with_len(start, len);
    1461 ECB             :         }
    1462                 :     }
    1463                 : 
    1464 GIC       52731 :     if (_state->next_scalar)
    1465                 :     {
    1466 ECB             :         /* a de-escaped text value is wanted, so supply it */
    1467 GIC         351 :         _state->tresult = cstring_to_text(token);
    1468                 :         /* make sure the next call to get_scalar doesn't overwrite it */
    1469 CBC         351 :         _state->next_scalar = false;
    1470                 :     }
    1471                 : 
    1472 GNC       52731 :     return JSON_SUCCESS;
    1473                 : }
    1474                 : 
    1475 ECB             : Datum
    1476 GIC         135 : jsonb_extract_path(PG_FUNCTION_ARGS)
    1477 ECB             : {
    1478 CBC         135 :     return get_jsonb_path_all(fcinfo, false);
    1479                 : }
    1480                 : 
    1481 ECB             : Datum
    1482 GIC          90 : jsonb_extract_path_text(PG_FUNCTION_ARGS)
    1483 ECB             : {
    1484 GIC          90 :     return get_jsonb_path_all(fcinfo, true);
    1485                 : }
    1486 ECB             : 
    1487                 : static Datum
    1488 CBC         225 : get_jsonb_path_all(FunctionCallInfo fcinfo, bool as_text)
    1489                 : {
    1490             225 :     Jsonb      *jb = PG_GETARG_JSONB_P(0);
    1491 GIC         225 :     ArrayType  *path = PG_GETARG_ARRAYTYPE_P(1);
    1492                 :     Datum      *pathtext;
    1493                 :     bool       *pathnulls;
    1494                 :     bool        isnull;
    1495                 :     int         npath;
    1496                 :     Datum       res;
    1497                 : 
    1498                 :     /*
    1499 ECB             :      * If the array contains any null elements, return NULL, on the grounds
    1500                 :      * that you'd have gotten NULL if any RHS value were NULL in a nested
    1501                 :      * series of applications of the -> operator.  (Note: because we also
    1502                 :      * return NULL for error cases such as no-such-field, this is true
    1503                 :      * regardless of the contents of the rest of the array.)
    1504                 :      */
    1505 GIC         225 :     if (array_contains_nulls(path))
    1506 CBC           6 :         PG_RETURN_NULL();
    1507                 : 
    1508 GNC         219 :     deconstruct_array_builtin(path, TEXTOID, &pathtext, &pathnulls, &npath);
    1509                 : 
    1510 CBC         219 :     res = jsonb_get_element(jb, pathtext, npath, &isnull, as_text);
    1511                 : 
    1512 GIC         219 :     if (isnull)
    1513 CBC          69 :         PG_RETURN_NULL();
    1514                 :     else
    1515 GIC         150 :         PG_RETURN_DATUM(res);
    1516                 : }
    1517 ECB             : 
    1518                 : Datum
    1519 CBC         315 : jsonb_get_element(Jsonb *jb, Datum *path, int npath, bool *isnull, bool as_text)
    1520                 : {
    1521 GIC         315 :     JsonbContainer *container = &jb->root;
    1522             315 :     JsonbValue *jbvp = NULL;
    1523 ECB             :     int         i;
    1524 GIC         315 :     bool        have_object = false,
    1525 CBC         315 :                 have_array = false;
    1526                 : 
    1527 GIC         315 :     *isnull = false;
    1528                 : 
    1529 ECB             :     /* Identify whether we have object, array, or scalar at top-level */
    1530 GIC         315 :     if (JB_ROOT_IS_OBJECT(jb))
    1531 CBC         210 :         have_object = true;
    1532             105 :     else if (JB_ROOT_IS_ARRAY(jb) && !JB_ROOT_IS_SCALAR(jb))
    1533 GIC          63 :         have_array = true;
    1534                 :     else
    1535                 :     {
    1536              42 :         Assert(JB_ROOT_IS_ARRAY(jb) && JB_ROOT_IS_SCALAR(jb));
    1537                 :         /* Extract the scalar value, if it is what we'll return */
    1538              42 :         if (npath <= 0)
    1539              18 :             jbvp = getIthJsonbValueFromContainer(container, 0);
    1540                 :     }
    1541                 : 
    1542                 :     /*
    1543                 :      * If the array is empty, return the entire LHS object, on the grounds
    1544                 :      * that we should do zero field or element extractions.  For the
    1545                 :      * non-scalar case we can just hand back the object without much work. For
    1546 ECB             :      * the scalar case, fall through and deal with the value below the loop.
    1547                 :      * (This inconsistency arises because there's no easy way to generate a
    1548                 :      * JsonbValue directly for root-level containers.)
    1549                 :      */
    1550 GIC         315 :     if (npath <= 0 && jbvp == NULL)
    1551 ECB             :     {
    1552 GIC          12 :         if (as_text)
    1553 ECB             :         {
    1554 CBC           6 :             return PointerGetDatum(cstring_to_text(JsonbToCString(NULL,
    1555                 :                                                                   container,
    1556               6 :                                                                   VARSIZE(jb))));
    1557                 :         }
    1558                 :         else
    1559                 :         {
    1560 ECB             :             /* not text mode - just hand back the jsonb */
    1561 GIC           6 :             PG_RETURN_JSONB_P(jb);
    1562 ECB             :         }
    1563                 :     }
    1564                 : 
    1565 CBC         504 :     for (i = 0; i < npath; i++)
    1566 ECB             :     {
    1567 GIC         486 :         if (have_object)
    1568 ECB             :         {
    1569 GIC         312 :             text       *subscr = DatumGetTextPP(path[i]);
    1570                 : 
    1571 CBC         624 :             jbvp = getKeyJsonValueFromContainer(container,
    1572             312 :                                                 VARDATA_ANY(subscr),
    1573             312 :                                                 VARSIZE_ANY_EXHDR(subscr),
    1574 ECB             :                                                 NULL);
    1575                 :         }
    1576 GIC         174 :         else if (have_array)
    1577 ECB             :         {
    1578                 :             int         lindex;
    1579                 :             uint32      index;
    1580 CBC         135 :             char       *indextext = TextDatumGetCString(path[i]);
    1581                 :             char       *endptr;
    1582                 : 
    1583 GIC         135 :             errno = 0;
    1584             135 :             lindex = strtoint(indextext, &endptr, 10);
    1585             135 :             if (endptr == indextext || *endptr != '\0' || errno != 0)
    1586                 :             {
    1587              18 :                 *isnull = true;
    1588              21 :                 return PointerGetDatum(NULL);
    1589                 :             }
    1590                 : 
    1591 CBC         117 :             if (lindex >= 0)
    1592                 :             {
    1593             105 :                 index = (uint32) lindex;
    1594                 :             }
    1595 ECB             :             else
    1596                 :             {
    1597                 :                 /* Handle negative subscript */
    1598                 :                 uint32      nelements;
    1599                 : 
    1600                 :                 /* Container must be array, but make sure */
    1601 GIC          12 :                 if (!JsonContainerIsArray(container))
    1602 LBC           0 :                     elog(ERROR, "not a jsonb array");
    1603                 : 
    1604 GIC          12 :                 nelements = JsonContainerSize(container);
    1605                 : 
    1606 CBC          12 :                 if (lindex == INT_MIN || -lindex > nelements)
    1607                 :                 {
    1608               3 :                     *isnull = true;
    1609 GIC           3 :                     return PointerGetDatum(NULL);
    1610 ECB             :                 }
    1611                 :                 else
    1612 CBC           9 :                     index = nelements + lindex;
    1613 ECB             :             }
    1614                 : 
    1615 GIC         114 :             jbvp = getIthJsonbValueFromContainer(container, index);
    1616                 :         }
    1617 ECB             :         else
    1618                 :         {
    1619                 :             /* scalar, extraction yields a null */
    1620 GIC          39 :             *isnull = true;
    1621 CBC          39 :             return PointerGetDatum(NULL);
    1622                 :         }
    1623                 : 
    1624             426 :         if (jbvp == NULL)
    1625 ECB             :         {
    1626 CBC          39 :             *isnull = true;
    1627 GIC          39 :             return PointerGetDatum(NULL);
    1628 ECB             :         }
    1629 CBC         387 :         else if (i == npath - 1)
    1630 GIC         186 :             break;
    1631                 : 
    1632 CBC         201 :         if (jbvp->type == jbvBinary)
    1633                 :         {
    1634             186 :             container = jbvp->val.binary.data;
    1635 GIC         186 :             have_object = JsonContainerIsObject(container);
    1636             186 :             have_array = JsonContainerIsArray(container);
    1637             186 :             Assert(!JsonContainerIsScalar(container));
    1638                 :         }
    1639                 :         else
    1640                 :         {
    1641              15 :             Assert(IsAJsonbScalar(jbvp));
    1642 CBC          15 :             have_object = false;
    1643 GBC          15 :             have_array = false;
    1644                 :         }
    1645 ECB             :     }
    1646                 : 
    1647 CBC         204 :     if (as_text)
    1648                 :     {
    1649              57 :         if (jbvp->type == jbvNull)
    1650 ECB             :         {
    1651 GIC          12 :             *isnull = true;
    1652              12 :             return PointerGetDatum(NULL);
    1653 ECB             :         }
    1654                 : 
    1655 GIC          45 :         return PointerGetDatum(JsonbValueAsText(jbvp));
    1656 ECB             :     }
    1657                 :     else
    1658                 :     {
    1659 GIC         147 :         Jsonb      *res = JsonbValueToJsonb(jbvp);
    1660                 : 
    1661 ECB             :         /* not text mode - just hand back the jsonb */
    1662 CBC         147 :         PG_RETURN_JSONB_P(res);
    1663                 :     }
    1664                 : }
    1665 ECB             : 
    1666                 : Datum
    1667 CBC         123 : jsonb_set_element(Jsonb *jb, Datum *path, int path_len,
    1668 ECB             :                   JsonbValue *newval)
    1669                 : {
    1670                 :     JsonbValue *res;
    1671 CBC         123 :     JsonbParseState *state = NULL;
    1672                 :     JsonbIterator *it;
    1673             123 :     bool       *path_nulls = palloc0(path_len * sizeof(bool));
    1674                 : 
    1675             123 :     if (newval->type == jbvArray && newval->val.array.rawScalar)
    1676 LBC           0 :         *newval = newval->val.array.elems[0];
    1677 ECB             : 
    1678 CBC         123 :     it = JsonbIteratorInit(&jb->root);
    1679                 : 
    1680 GIC         123 :     res = setPath(&it, path, path_nulls, path_len, &state, 0, newval,
    1681                 :                   JB_PATH_CREATE | JB_PATH_FILL_GAPS |
    1682 ECB             :                   JB_PATH_CONSISTENT_POSITION);
    1683                 : 
    1684 CBC          99 :     pfree(path_nulls);
    1685                 : 
    1686 GIC          99 :     PG_RETURN_JSONB_P(JsonbValueToJsonb(res));
    1687                 : }
    1688 ECB             : 
    1689                 : static void
    1690 CBC          54 : push_null_elements(JsonbParseState **ps, int num)
    1691                 : {
    1692 ECB             :     JsonbValue  null;
    1693                 : 
    1694 GIC          54 :     null.type = jbvNull;
    1695                 : 
    1696 CBC         204 :     while (num-- > 0)
    1697 GIC         150 :         pushJsonbValue(ps, WJB_ELEM, &null);
    1698              54 : }
    1699                 : 
    1700 ECB             : /*
    1701                 :  * Prepare a new structure containing nested empty objects and arrays
    1702                 :  * corresponding to the specified path, and assign a new value at the end of
    1703                 :  * this path. E.g. the path [a][0][b] with the new value 1 will produce the
    1704                 :  * structure {a: [{b: 1}]}.
    1705                 :  *
    1706                 :  * Caller is responsible to make sure such path does not exist yet.
    1707                 :  */
    1708                 : static void
    1709 GIC          36 : push_path(JsonbParseState **st, int level, Datum *path_elems,
    1710                 :           bool *path_nulls, int path_len, JsonbValue *newval)
    1711                 : {
    1712 ECB             :     /*
    1713                 :      * tpath contains expected type of an empty jsonb created at each level
    1714                 :      * higher or equal than the current one, either jbvObject or jbvArray.
    1715                 :      * Since it contains only information about path slice from level to the
    1716                 :      * end, the access index must be normalized by level.
    1717 EUB             :      */
    1718 GIC          36 :     enum jbvType *tpath = palloc0((path_len - level) * sizeof(enum jbvType));
    1719 ECB             :     JsonbValue  newkey;
    1720                 : 
    1721                 :     /*
    1722                 :      * Create first part of the chain with beginning tokens. For the current
    1723                 :      * level WJB_BEGIN_OBJECT/WJB_BEGIN_ARRAY was already created, so start
    1724                 :      * with the next one.
    1725                 :      */
    1726 GIC         108 :     for (int i = level + 1; i < path_len; i++)
    1727 ECB             :     {
    1728                 :         char       *c,
    1729                 :                    *badp;
    1730                 :         int         lindex;
    1731                 : 
    1732 GIC          72 :         if (path_nulls[i])
    1733 UIC           0 :             break;
    1734                 : 
    1735 ECB             :         /*
    1736                 :          * Try to convert to an integer to find out the expected type, object
    1737                 :          * or array.
    1738                 :          */
    1739 CBC          72 :         c = TextDatumGetCString(path_elems[i]);
    1740 GIC          72 :         errno = 0;
    1741              72 :         lindex = strtoint(c, &badp, 10);
    1742              72 :         if (badp == c || *badp != '\0' || errno != 0)
    1743                 :         {
    1744                 :             /* text, an object is expected */
    1745              33 :             newkey.type = jbvString;
    1746              33 :             newkey.val.string.val = c;
    1747              33 :             newkey.val.string.len = strlen(c);
    1748                 : 
    1749              33 :             (void) pushJsonbValue(st, WJB_BEGIN_OBJECT, NULL);
    1750 CBC          33 :             (void) pushJsonbValue(st, WJB_KEY, &newkey);
    1751                 : 
    1752 GIC          33 :             tpath[i - level] = jbvObject;
    1753                 :         }
    1754                 :         else
    1755                 :         {
    1756                 :             /* integer, an array is expected */
    1757              39 :             (void) pushJsonbValue(st, WJB_BEGIN_ARRAY, NULL);
    1758                 : 
    1759 CBC          39 :             push_null_elements(st, lindex);
    1760                 : 
    1761 GIC          39 :             tpath[i - level] = jbvArray;
    1762                 :         }
    1763                 :     }
    1764                 : 
    1765                 :     /* Insert an actual value for either an object or array */
    1766              36 :     if (tpath[(path_len - level) - 1] == jbvArray)
    1767 ECB             :     {
    1768 GIC          24 :         (void) pushJsonbValue(st, WJB_ELEM, newval);
    1769                 :     }
    1770                 :     else
    1771              12 :         (void) pushJsonbValue(st, WJB_VALUE, newval);
    1772                 : 
    1773 ECB             :     /*
    1774 EUB             :      * Close everything up to the last but one level. The last one will be
    1775                 :      * closed outside of this function.
    1776                 :      */
    1777 GIC         108 :     for (int i = path_len - 1; i > level; i--)
    1778                 :     {
    1779              72 :         if (path_nulls[i])
    1780 LBC           0 :             break;
    1781 ECB             : 
    1782 CBC          72 :         if (tpath[i - level] == jbvObject)
    1783              33 :             (void) pushJsonbValue(st, WJB_END_OBJECT, NULL);
    1784                 :         else
    1785 GIC          39 :             (void) pushJsonbValue(st, WJB_END_ARRAY, NULL);
    1786 ECB             :     }
    1787 CBC          36 : }
    1788 ECB             : 
    1789                 : /*
    1790                 :  * Return the text representation of the given JsonbValue.
    1791                 :  */
    1792                 : static text *
    1793 CBC         210 : JsonbValueAsText(JsonbValue *v)
    1794                 : {
    1795 GIC         210 :     switch (v->type)
    1796                 :     {
    1797 UIC           0 :         case jbvNull:
    1798 LBC           0 :             return NULL;
    1799                 : 
    1800 CBC          12 :         case jbvBool:
    1801 GIC          12 :             return v->val.boolean ?
    1802 CBC          18 :                 cstring_to_text_with_len("true", 4) :
    1803 GIC           6 :                 cstring_to_text_with_len("false", 5);
    1804                 : 
    1805             114 :         case jbvString:
    1806             114 :             return cstring_to_text_with_len(v->val.string.val,
    1807 ECB             :                                             v->val.string.len);
    1808                 : 
    1809 CBC          21 :         case jbvNumeric:
    1810                 :             {
    1811                 :                 Datum       cstr;
    1812 ECB             : 
    1813 GIC          21 :                 cstr = DirectFunctionCall1(numeric_out,
    1814                 :                                            PointerGetDatum(v->val.numeric));
    1815                 : 
    1816              21 :                 return cstring_to_text(DatumGetCString(cstr));
    1817                 :             }
    1818 ECB             : 
    1819 GIC          63 :         case jbvBinary:
    1820 ECB             :             {
    1821 EUB             :                 StringInfoData jtext;
    1822                 : 
    1823 CBC          63 :                 initStringInfo(&jtext);
    1824              63 :                 (void) JsonbToCString(&jtext, v->val.binary.data,
    1825                 :                                       v->val.binary.len);
    1826 ECB             : 
    1827 GIC          63 :                 return cstring_to_text_with_len(jtext.data, jtext.len);
    1828 ECB             :             }
    1829                 : 
    1830 UIC           0 :         default:
    1831               0 :             elog(ERROR, "unrecognized jsonb type: %d", (int) v->type);
    1832                 :             return NULL;
    1833                 :     }
    1834 ECB             : }
    1835                 : 
    1836                 : /*
    1837                 :  * SQL function json_array_length(json) -> int
    1838 EUB             :  */
    1839                 : Datum
    1840 GIC          12 : json_array_length(PG_FUNCTION_ARGS)
    1841 ECB             : {
    1842 CBC          12 :     text       *json = PG_GETARG_TEXT_PP(0);
    1843 ECB             :     AlenState  *state;
    1844                 :     JsonLexContext *lex;
    1845                 :     JsonSemAction *sem;
    1846                 : 
    1847 CBC          12 :     lex = makeJsonLexContext(json, false);
    1848 GIC          12 :     state = palloc0(sizeof(AlenState));
    1849              12 :     sem = palloc0(sizeof(JsonSemAction));
    1850 ECB             : 
    1851                 :     /* palloc0 does this for us */
    1852                 : #if 0
    1853                 :     state->count = 0;
    1854                 : #endif
    1855 GIC          12 :     state->lex = lex;
    1856                 : 
    1857 CBC          12 :     sem->semstate = (void *) state;
    1858 GIC          12 :     sem->object_start = alen_object_start;
    1859              12 :     sem->scalar = alen_scalar;
    1860 CBC          12 :     sem->array_element_start = alen_array_element_start;
    1861                 : 
    1862 GIC          12 :     pg_parse_json_or_ereport(lex, sem);
    1863                 : 
    1864 CBC           6 :     PG_RETURN_INT32(state->count);
    1865 ECB             : }
    1866                 : 
    1867                 : Datum
    1868 CBC         156 : jsonb_array_length(PG_FUNCTION_ARGS)
    1869                 : {
    1870 GIC         156 :     Jsonb      *jb = PG_GETARG_JSONB_P(0);
    1871 EUB             : 
    1872 GBC         156 :     if (JB_ROOT_IS_SCALAR(jb))
    1873 GIC           3 :         ereport(ERROR,
    1874                 :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    1875                 :                  errmsg("cannot get array length of a scalar")));
    1876             153 :     else if (!JB_ROOT_IS_ARRAY(jb))
    1877               3 :         ereport(ERROR,
    1878                 :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    1879                 :                  errmsg("cannot get array length of a non-array")));
    1880                 : 
    1881 CBC         150 :     PG_RETURN_INT32(JB_ROOT_COUNT(jb));
    1882                 : }
    1883 ECB             : 
    1884                 : /*
    1885                 :  * These next two checks ensure that the json is an array (since it can't be
    1886                 :  * a scalar or an object).
    1887                 :  */
    1888                 : 
    1889                 : static JsonParseErrorType
    1890 CBC           6 : alen_object_start(void *state)
    1891                 : {
    1892 GIC           6 :     AlenState  *_state = (AlenState *) state;
    1893                 : 
    1894                 :     /* json structure check */
    1895               6 :     if (_state->lex->lex_level == 0)
    1896 CBC           3 :         ereport(ERROR,
    1897                 :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    1898 ECB             :                  errmsg("cannot get array length of a non-array")));
    1899                 : 
    1900 GNC           3 :     return JSON_SUCCESS;
    1901 ECB             : }
    1902                 : 
    1903                 : static JsonParseErrorType
    1904 GIC          24 : alen_scalar(void *state, char *token, JsonTokenType tokentype)
    1905 ECB             : {
    1906 GIC          24 :     AlenState  *_state = (AlenState *) state;
    1907 ECB             : 
    1908                 :     /* json structure check */
    1909 GIC          24 :     if (_state->lex->lex_level == 0)
    1910               3 :         ereport(ERROR,
    1911 ECB             :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    1912                 :                  errmsg("cannot get array length of a scalar")));
    1913                 : 
    1914 GNC          21 :     return JSON_SUCCESS;
    1915 ECB             : }
    1916                 : 
    1917                 : static JsonParseErrorType
    1918 CBC          21 : alen_array_element_start(void *state, bool isnull)
    1919                 : {
    1920 GIC          21 :     AlenState  *_state = (AlenState *) state;
    1921 ECB             : 
    1922                 :     /* just count up all the level 1 elements */
    1923 GIC          21 :     if (_state->lex->lex_level == 1)
    1924              15 :         _state->count++;
    1925                 : 
    1926 GNC          21 :     return JSON_SUCCESS;
    1927                 : }
    1928 ECB             : 
    1929                 : /*
    1930                 :  * SQL function json_each and json_each_text
    1931                 :  *
    1932                 :  * decompose a json object into key value pairs.
    1933                 :  *
    1934                 :  * Unlike json_object_keys() these SRFs operate in materialize mode,
    1935                 :  * stashing results into a Tuplestore object as they go.
    1936                 :  * The construction of tuples is done using a temporary memory context
    1937                 :  * that is cleared out after each tuple is built.
    1938                 :  */
    1939                 : Datum
    1940 GIC           6 : json_each(PG_FUNCTION_ARGS)
    1941                 : {
    1942 CBC           6 :     return each_worker(fcinfo, false);
    1943 ECB             : }
    1944                 : 
    1945                 : Datum
    1946 GIC        6084 : jsonb_each(PG_FUNCTION_ARGS)
    1947 ECB             : {
    1948 GIC        6084 :     return each_worker_jsonb(fcinfo, "jsonb_each", false);
    1949                 : }
    1950                 : 
    1951 ECB             : Datum
    1952 GIC           6 : json_each_text(PG_FUNCTION_ARGS)
    1953 ECB             : {
    1954 GIC           6 :     return each_worker(fcinfo, true);
    1955                 : }
    1956 ECB             : 
    1957                 : Datum
    1958 GIC          12 : jsonb_each_text(PG_FUNCTION_ARGS)
    1959                 : {
    1960              12 :     return each_worker_jsonb(fcinfo, "jsonb_each_text", true);
    1961 ECB             : }
    1962                 : 
    1963                 : static Datum
    1964 GIC        6096 : each_worker_jsonb(FunctionCallInfo fcinfo, const char *funcname, bool as_text)
    1965 ECB             : {
    1966 GIC        6096 :     Jsonb      *jb = PG_GETARG_JSONB_P(0);
    1967 ECB             :     ReturnSetInfo *rsi;
    1968                 :     MemoryContext old_cxt,
    1969                 :                 tmp_cxt;
    1970 CBC        6096 :     bool        skipNested = false;
    1971 ECB             :     JsonbIterator *it;
    1972                 :     JsonbValue  v;
    1973                 :     JsonbIteratorToken r;
    1974                 : 
    1975 GIC        6096 :     if (!JB_ROOT_IS_OBJECT(jb))
    1976 UIC           0 :         ereport(ERROR,
    1977                 :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    1978                 :                  errmsg("cannot call %s on a non-object",
    1979                 :                         funcname)));
    1980                 : 
    1981 GIC        6096 :     rsi = (ReturnSetInfo *) fcinfo->resultinfo;
    1982            6096 :     InitMaterializedSRF(fcinfo, MAT_SRF_BLESS);
    1983                 : 
    1984            6096 :     tmp_cxt = AllocSetContextCreate(CurrentMemoryContext,
    1985                 :                                     "jsonb_each temporary cxt",
    1986                 :                                     ALLOCSET_DEFAULT_SIZES);
    1987 ECB             : 
    1988 GIC        6096 :     it = JsonbIteratorInit(&jb->root);
    1989 ECB             : 
    1990 GIC       47145 :     while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE)
    1991                 :     {
    1992           41049 :         skipNested = true;
    1993 ECB             : 
    1994 GIC       41049 :         if (r == WJB_KEY)
    1995 ECB             :         {
    1996                 :             text       *key;
    1997                 :             Datum       values[2];
    1998 GIC       28857 :             bool        nulls[2] = {false, false};
    1999 ECB             : 
    2000                 :             /* Use the tmp context so we can clean up after each tuple is done */
    2001 CBC       28857 :             old_cxt = MemoryContextSwitchTo(tmp_cxt);
    2002                 : 
    2003 GIC       28857 :             key = cstring_to_text_with_len(v.val.string.val, v.val.string.len);
    2004                 : 
    2005 ECB             :             /*
    2006                 :              * The next thing the iterator fetches should be the value, no
    2007                 :              * matter what shape it is.
    2008                 :              */
    2009 GIC       28857 :             r = JsonbIteratorNext(&it, &v, skipNested);
    2010           28857 :             Assert(r != WJB_DONE);
    2011 ECB             : 
    2012 GIC       28857 :             values[0] = PointerGetDatum(key);
    2013 ECB             : 
    2014 GIC       28857 :             if (as_text)
    2015                 :             {
    2016              57 :                 if (v.type == jbvNull)
    2017 ECB             :                 {
    2018                 :                     /* a json null is an sql null in text mode */
    2019 GIC          12 :                     nulls[1] = true;
    2020              12 :                     values[1] = (Datum) NULL;
    2021                 :                 }
    2022 ECB             :                 else
    2023 GBC          45 :                     values[1] = PointerGetDatum(JsonbValueAsText(&v));
    2024                 :             }
    2025                 :             else
    2026                 :             {
    2027                 :                 /* Not in text mode, just return the Jsonb */
    2028 CBC       28800 :                 Jsonb      *val = JsonbValueToJsonb(&v);
    2029 ECB             : 
    2030 GIC       28800 :                 values[1] = PointerGetDatum(val);
    2031 ECB             :             }
    2032                 : 
    2033 GIC       28857 :             tuplestore_putvalues(rsi->setResult, rsi->setDesc, values, nulls);
    2034                 : 
    2035 ECB             :             /* clean up and switch back */
    2036 GIC       28857 :             MemoryContextSwitchTo(old_cxt);
    2037 CBC       28857 :             MemoryContextReset(tmp_cxt);
    2038                 :         }
    2039 ECB             :     }
    2040                 : 
    2041 CBC        6096 :     MemoryContextDelete(tmp_cxt);
    2042                 : 
    2043 GIC        6096 :     PG_RETURN_NULL();
    2044                 : }
    2045 ECB             : 
    2046                 : 
    2047                 : static Datum
    2048 CBC          12 : each_worker(FunctionCallInfo fcinfo, bool as_text)
    2049                 : {
    2050              12 :     text       *json = PG_GETARG_TEXT_PP(0);
    2051                 :     JsonLexContext *lex;
    2052                 :     JsonSemAction *sem;
    2053                 :     ReturnSetInfo *rsi;
    2054                 :     EachState  *state;
    2055                 : 
    2056              12 :     lex = makeJsonLexContext(json, true);
    2057              12 :     state = palloc0(sizeof(EachState));
    2058 GIC          12 :     sem = palloc0(sizeof(JsonSemAction));
    2059 ECB             : 
    2060 GIC          12 :     rsi = (ReturnSetInfo *) fcinfo->resultinfo;
    2061 ECB             : 
    2062 GIC          12 :     InitMaterializedSRF(fcinfo, MAT_SRF_BLESS);
    2063 CBC          12 :     state->tuple_store = rsi->setResult;
    2064 GIC          12 :     state->ret_tdesc = rsi->setDesc;
    2065                 : 
    2066 CBC          12 :     sem->semstate = (void *) state;
    2067              12 :     sem->array_start = each_array_start;
    2068 GIC          12 :     sem->scalar = each_scalar;
    2069              12 :     sem->object_field_start = each_object_field_start;
    2070 CBC          12 :     sem->object_field_end = each_object_field_end;
    2071                 : 
    2072 GIC          12 :     state->normalize_results = as_text;
    2073              12 :     state->next_scalar = false;
    2074              12 :     state->lex = lex;
    2075 CBC          12 :     state->tmp_cxt = AllocSetContextCreate(CurrentMemoryContext,
    2076                 :                                            "json_each temporary cxt",
    2077 ECB             :                                            ALLOCSET_DEFAULT_SIZES);
    2078                 : 
    2079 GIC          12 :     pg_parse_json_or_ereport(lex, sem);
    2080 ECB             : 
    2081 GIC          12 :     MemoryContextDelete(state->tmp_cxt);
    2082                 : 
    2083 CBC          12 :     PG_RETURN_NULL();
    2084 ECB             : }
    2085                 : 
    2086                 : 
    2087                 : static JsonParseErrorType
    2088 CBC          63 : each_object_field_start(void *state, char *fname, bool isnull)
    2089                 : {
    2090              63 :     EachState  *_state = (EachState *) state;
    2091                 : 
    2092                 :     /* save a pointer to where the value starts */
    2093 GIC          63 :     if (_state->lex->lex_level == 1)
    2094                 :     {
    2095 ECB             :         /*
    2096                 :          * next_scalar will be reset in the object_field_end handler, and
    2097                 :          * since we know the value is a scalar there is no danger of it being
    2098                 :          * on while recursing down the tree.
    2099                 :          */
    2100 GIC          51 :         if (_state->normalize_results && _state->lex->token_type == JSON_TOKEN_STRING)
    2101               6 :             _state->next_scalar = true;
    2102                 :         else
    2103 CBC          45 :             _state->result_start = _state->lex->token_start;
    2104 ECB             :     }
    2105                 : 
    2106 GNC          63 :     return JSON_SUCCESS;
    2107 ECB             : }
    2108                 : 
    2109                 : static JsonParseErrorType
    2110 GIC          63 : each_object_field_end(void *state, char *fname, bool isnull)
    2111 ECB             : {
    2112 CBC          63 :     EachState  *_state = (EachState *) state;
    2113 ECB             :     MemoryContext old_cxt;
    2114                 :     int         len;
    2115                 :     text       *val;
    2116                 :     HeapTuple   tuple;
    2117                 :     Datum       values[2];
    2118 CBC          63 :     bool        nulls[2] = {false, false};
    2119 ECB             : 
    2120                 :     /* skip over nested objects */
    2121 CBC          63 :     if (_state->lex->lex_level != 1)
    2122 GNC          12 :         return JSON_SUCCESS;
    2123 ECB             : 
    2124                 :     /* use the tmp context so we can clean up after each tuple is done */
    2125 GIC          51 :     old_cxt = MemoryContextSwitchTo(_state->tmp_cxt);
    2126                 : 
    2127              51 :     values[0] = CStringGetTextDatum(fname);
    2128 ECB             : 
    2129 GIC          51 :     if (isnull && _state->normalize_results)
    2130 ECB             :     {
    2131 GIC           6 :         nulls[1] = true;
    2132 CBC           6 :         values[1] = (Datum) 0;
    2133                 :     }
    2134 GIC          45 :     else if (_state->next_scalar)
    2135                 :     {
    2136               6 :         values[1] = CStringGetTextDatum(_state->normalized_scalar);
    2137 CBC           6 :         _state->next_scalar = false;
    2138                 :     }
    2139 ECB             :     else
    2140                 :     {
    2141 GIC          39 :         len = _state->lex->prev_token_terminator - _state->result_start;
    2142 CBC          39 :         val = cstring_to_text_with_len(_state->result_start, len);
    2143 GIC          39 :         values[1] = PointerGetDatum(val);
    2144                 :     }
    2145                 : 
    2146              51 :     tuple = heap_form_tuple(_state->ret_tdesc, values, nulls);
    2147                 : 
    2148              51 :     tuplestore_puttuple(_state->tuple_store, tuple);
    2149 ECB             : 
    2150                 :     /* clean up and switch back */
    2151 GIC          51 :     MemoryContextSwitchTo(old_cxt);
    2152 CBC          51 :     MemoryContextReset(_state->tmp_cxt);
    2153                 : 
    2154 GNC          51 :     return JSON_SUCCESS;
    2155                 : }
    2156                 : 
    2157                 : static JsonParseErrorType
    2158 GIC          12 : each_array_start(void *state)
    2159                 : {
    2160              12 :     EachState  *_state = (EachState *) state;
    2161 ECB             : 
    2162                 :     /* json structure check */
    2163 CBC          12 :     if (_state->lex->lex_level == 0)
    2164 UIC           0 :         ereport(ERROR,
    2165                 :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    2166                 :                  errmsg("cannot deconstruct an array as an object")));
    2167                 : 
    2168 GNC          12 :     return JSON_SUCCESS;
    2169                 : }
    2170                 : 
    2171                 : static JsonParseErrorType
    2172 GIC          75 : each_scalar(void *state, char *token, JsonTokenType tokentype)
    2173                 : {
    2174 CBC          75 :     EachState  *_state = (EachState *) state;
    2175 ECB             : 
    2176                 :     /* json structure check */
    2177 GIC          75 :     if (_state->lex->lex_level == 0)
    2178 LBC           0 :         ereport(ERROR,
    2179                 :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    2180 ECB             :                  errmsg("cannot deconstruct a scalar")));
    2181                 : 
    2182                 :     /* supply de-escaped value if required */
    2183 GIC          75 :     if (_state->next_scalar)
    2184 CBC           6 :         _state->normalized_scalar = token;
    2185                 : 
    2186 GNC          75 :     return JSON_SUCCESS;
    2187 ECB             : }
    2188                 : 
    2189                 : /*
    2190                 :  * SQL functions json_array_elements and json_array_elements_text
    2191                 :  *
    2192                 :  * get the elements from a json array
    2193                 :  *
    2194                 :  * a lot of this processing is similar to the json_each* functions
    2195                 :  */
    2196                 : 
    2197                 : Datum
    2198 CBC          18 : jsonb_array_elements(PG_FUNCTION_ARGS)
    2199                 : {
    2200 GIC          18 :     return elements_worker_jsonb(fcinfo, "jsonb_array_elements", false);
    2201 ECB             : }
    2202                 : 
    2203                 : Datum
    2204 GIC           6 : jsonb_array_elements_text(PG_FUNCTION_ARGS)
    2205                 : {
    2206 CBC           6 :     return elements_worker_jsonb(fcinfo, "jsonb_array_elements_text", true);
    2207 ECB             : }
    2208                 : 
    2209                 : static Datum
    2210 GIC          24 : elements_worker_jsonb(FunctionCallInfo fcinfo, const char *funcname,
    2211                 :                       bool as_text)
    2212                 : {
    2213 CBC          24 :     Jsonb      *jb = PG_GETARG_JSONB_P(0);
    2214                 :     ReturnSetInfo *rsi;
    2215 ECB             :     MemoryContext old_cxt,
    2216                 :                 tmp_cxt;
    2217 GIC          24 :     bool        skipNested = false;
    2218 ECB             :     JsonbIterator *it;
    2219 EUB             :     JsonbValue  v;
    2220                 :     JsonbIteratorToken r;
    2221                 : 
    2222 GIC          24 :     if (JB_ROOT_IS_SCALAR(jb))
    2223 LBC           0 :         ereport(ERROR,
    2224                 :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    2225                 :                  errmsg("cannot extract elements from a scalar")));
    2226 GIC          24 :     else if (!JB_ROOT_IS_ARRAY(jb))
    2227 LBC           0 :         ereport(ERROR,
    2228                 :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    2229 ECB             :                  errmsg("cannot extract elements from an object")));
    2230                 : 
    2231 GIC          24 :     rsi = (ReturnSetInfo *) fcinfo->resultinfo;
    2232 ECB             : 
    2233 GBC          24 :     InitMaterializedSRF(fcinfo, MAT_SRF_USE_EXPECTED_DESC | MAT_SRF_BLESS);
    2234                 : 
    2235 GIC          24 :     tmp_cxt = AllocSetContextCreate(CurrentMemoryContext,
    2236                 :                                     "jsonb_array_elements temporary cxt",
    2237                 :                                     ALLOCSET_DEFAULT_SIZES);
    2238 ECB             : 
    2239 CBC          24 :     it = JsonbIteratorInit(&jb->root);
    2240                 : 
    2241             162 :     while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE)
    2242                 :     {
    2243 GIC         138 :         skipNested = true;
    2244                 : 
    2245             138 :         if (r == WJB_ELEM)
    2246                 :         {
    2247                 :             Datum       values[1];
    2248              90 :             bool        nulls[1] = {false};
    2249                 : 
    2250                 :             /* use the tmp context so we can clean up after each tuple is done */
    2251              90 :             old_cxt = MemoryContextSwitchTo(tmp_cxt);
    2252                 : 
    2253 CBC          90 :             if (as_text)
    2254                 :             {
    2255              42 :                 if (v.type == jbvNull)
    2256                 :                 {
    2257                 :                     /* a json null is an sql null in text mode */
    2258 GIC           6 :                     nulls[0] = true;
    2259 CBC           6 :                     values[0] = (Datum) NULL;
    2260                 :                 }
    2261 ECB             :                 else
    2262 GIC          36 :                     values[0] = PointerGetDatum(JsonbValueAsText(&v));
    2263                 :             }
    2264                 :             else
    2265 ECB             :             {
    2266                 :                 /* Not in text mode, just return the Jsonb */
    2267 GIC          48 :                 Jsonb      *val = JsonbValueToJsonb(&v);
    2268 ECB             : 
    2269 GIC          48 :                 values[0] = PointerGetDatum(val);
    2270                 :             }
    2271                 : 
    2272 CBC          90 :             tuplestore_putvalues(rsi->setResult, rsi->setDesc, values, nulls);
    2273                 : 
    2274                 :             /* clean up and switch back */
    2275 GIC          90 :             MemoryContextSwitchTo(old_cxt);
    2276              90 :             MemoryContextReset(tmp_cxt);
    2277 ECB             :         }
    2278 EUB             :     }
    2279                 : 
    2280 GIC          24 :     MemoryContextDelete(tmp_cxt);
    2281 ECB             : 
    2282 GBC          24 :     PG_RETURN_NULL();
    2283                 : }
    2284                 : 
    2285                 : Datum
    2286 CBC         195 : json_array_elements(PG_FUNCTION_ARGS)
    2287                 : {
    2288             195 :     return elements_worker(fcinfo, "json_array_elements", false);
    2289                 : }
    2290 ECB             : 
    2291                 : Datum
    2292 GIC           6 : json_array_elements_text(PG_FUNCTION_ARGS)
    2293                 : {
    2294 CBC           6 :     return elements_worker(fcinfo, "json_array_elements_text", true);
    2295                 : }
    2296 ECB             : 
    2297                 : static Datum
    2298 CBC         201 : elements_worker(FunctionCallInfo fcinfo, const char *funcname, bool as_text)
    2299                 : {
    2300             201 :     text       *json = PG_GETARG_TEXT_PP(0);
    2301                 : 
    2302                 :     /* elements only needs escaped strings when as_text */
    2303             201 :     JsonLexContext *lex = makeJsonLexContext(json, as_text);
    2304                 :     JsonSemAction *sem;
    2305                 :     ReturnSetInfo *rsi;
    2306 ECB             :     ElementsState *state;
    2307                 : 
    2308 CBC         201 :     state = palloc0(sizeof(ElementsState));
    2309 GIC         201 :     sem = palloc0(sizeof(JsonSemAction));
    2310 ECB             : 
    2311 GIC         201 :     InitMaterializedSRF(fcinfo, MAT_SRF_USE_EXPECTED_DESC | MAT_SRF_BLESS);
    2312             201 :     rsi = (ReturnSetInfo *) fcinfo->resultinfo;
    2313 CBC         201 :     state->tuple_store = rsi->setResult;
    2314             201 :     state->ret_tdesc = rsi->setDesc;
    2315                 : 
    2316 GIC         201 :     sem->semstate = (void *) state;
    2317 CBC         201 :     sem->object_start = elements_object_start;
    2318 GIC         201 :     sem->scalar = elements_scalar;
    2319             201 :     sem->array_element_start = elements_array_element_start;
    2320             201 :     sem->array_element_end = elements_array_element_end;
    2321                 : 
    2322 CBC         201 :     state->function_name = funcname;
    2323 GIC         201 :     state->normalize_results = as_text;
    2324 CBC         201 :     state->next_scalar = false;
    2325 GIC         201 :     state->lex = lex;
    2326             201 :     state->tmp_cxt = AllocSetContextCreate(CurrentMemoryContext,
    2327 ECB             :                                            "json_array_elements temporary cxt",
    2328                 :                                            ALLOCSET_DEFAULT_SIZES);
    2329                 : 
    2330 CBC         201 :     pg_parse_json_or_ereport(lex, sem);
    2331 ECB             : 
    2332 GIC         201 :     MemoryContextDelete(state->tmp_cxt);
    2333                 : 
    2334             201 :     PG_RETURN_NULL();
    2335 ECB             : }
    2336                 : 
    2337                 : static JsonParseErrorType
    2338 GIC        1014 : elements_array_element_start(void *state, bool isnull)
    2339                 : {
    2340            1014 :     ElementsState *_state = (ElementsState *) state;
    2341 ECB             : 
    2342                 :     /* save a pointer to where the value starts */
    2343 CBC        1014 :     if (_state->lex->lex_level == 1)
    2344                 :     {
    2345                 :         /*
    2346                 :          * next_scalar will be reset in the array_element_end handler, and
    2347 ECB             :          * since we know the value is a scalar there is no danger of it being
    2348                 :          * on while recursing down the tree.
    2349                 :          */
    2350 GIC         339 :         if (_state->normalize_results && _state->lex->token_type == JSON_TOKEN_STRING)
    2351               6 :             _state->next_scalar = true;
    2352                 :         else
    2353 CBC         333 :             _state->result_start = _state->lex->token_start;
    2354                 :     }
    2355                 : 
    2356 GNC        1014 :     return JSON_SUCCESS;
    2357 ECB             : }
    2358                 : 
    2359                 : static JsonParseErrorType
    2360 CBC        1014 : elements_array_element_end(void *state, bool isnull)
    2361                 : {
    2362 GIC        1014 :     ElementsState *_state = (ElementsState *) state;
    2363                 :     MemoryContext old_cxt;
    2364                 :     int         len;
    2365 ECB             :     text       *val;
    2366                 :     HeapTuple   tuple;
    2367                 :     Datum       values[1];
    2368 CBC        1014 :     bool        nulls[1] = {false};
    2369 ECB             : 
    2370                 :     /* skip over nested objects */
    2371 CBC        1014 :     if (_state->lex->lex_level != 1)
    2372 GNC         675 :         return JSON_SUCCESS;
    2373 ECB             : 
    2374                 :     /* use the tmp context so we can clean up after each tuple is done */
    2375 CBC         339 :     old_cxt = MemoryContextSwitchTo(_state->tmp_cxt);
    2376 ECB             : 
    2377 CBC         339 :     if (isnull && _state->normalize_results)
    2378                 :     {
    2379               6 :         nulls[0] = true;
    2380               6 :         values[0] = (Datum) NULL;
    2381 ECB             :     }
    2382 CBC         333 :     else if (_state->next_scalar)
    2383 ECB             :     {
    2384 GIC           6 :         values[0] = CStringGetTextDatum(_state->normalized_scalar);
    2385               6 :         _state->next_scalar = false;
    2386                 :     }
    2387 ECB             :     else
    2388                 :     {
    2389 CBC         327 :         len = _state->lex->prev_token_terminator - _state->result_start;
    2390 GIC         327 :         val = cstring_to_text_with_len(_state->result_start, len);
    2391 CBC         327 :         values[0] = PointerGetDatum(val);
    2392                 :     }
    2393                 : 
    2394 GIC         339 :     tuple = heap_form_tuple(_state->ret_tdesc, values, nulls);
    2395 ECB             : 
    2396 GIC         339 :     tuplestore_puttuple(_state->tuple_store, tuple);
    2397 ECB             : 
    2398                 :     /* clean up and switch back */
    2399 GIC         339 :     MemoryContextSwitchTo(old_cxt);
    2400 CBC         339 :     MemoryContextReset(_state->tmp_cxt);
    2401                 : 
    2402 GNC         339 :     return JSON_SUCCESS;
    2403                 : }
    2404                 : 
    2405                 : static JsonParseErrorType
    2406 GIC         858 : elements_object_start(void *state)
    2407                 : {
    2408             858 :     ElementsState *_state = (ElementsState *) state;
    2409 ECB             : 
    2410                 :     /* json structure check */
    2411 GIC         858 :     if (_state->lex->lex_level == 0)
    2412 LBC           0 :         ereport(ERROR,
    2413                 :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    2414                 :                  errmsg("cannot call %s on a non-array",
    2415 ECB             :                         _state->function_name)));
    2416                 : 
    2417 GNC         858 :     return JSON_SUCCESS;
    2418                 : }
    2419                 : 
    2420                 : static JsonParseErrorType
    2421 CBC       12768 : elements_scalar(void *state, char *token, JsonTokenType tokentype)
    2422                 : {
    2423           12768 :     ElementsState *_state = (ElementsState *) state;
    2424                 : 
    2425                 :     /* json structure check */
    2426 GIC       12768 :     if (_state->lex->lex_level == 0)
    2427 UIC           0 :         ereport(ERROR,
    2428                 :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    2429 ECB             :                  errmsg("cannot call %s on a scalar",
    2430                 :                         _state->function_name)));
    2431                 : 
    2432                 :     /* supply de-escaped value if required */
    2433 CBC       12768 :     if (_state->next_scalar)
    2434 GIC           6 :         _state->normalized_scalar = token;
    2435                 : 
    2436 GNC       12768 :     return JSON_SUCCESS;
    2437                 : }
    2438 ECB             : 
    2439                 : /*
    2440                 :  * SQL function json_populate_record
    2441                 :  *
    2442                 :  * set fields in a record from the argument json
    2443                 :  *
    2444                 :  * Code adapted shamelessly from hstore's populate_record
    2445                 :  * which is in turn partly adapted from record_out.
    2446                 :  *
    2447                 :  * The json is decomposed into a hash table, in which each
    2448                 :  * field in the record is then looked up by name. For jsonb
    2449                 :  * we fetch the values direct from the object.
    2450                 :  */
    2451                 : Datum
    2452 CBC         411 : jsonb_populate_record(PG_FUNCTION_ARGS)
    2453 ECB             : {
    2454 CBC         411 :     return populate_record_worker(fcinfo, "jsonb_populate_record",
    2455                 :                                   false, true);
    2456                 : }
    2457 ECB             : 
    2458                 : Datum
    2459 CBC          51 : jsonb_to_record(PG_FUNCTION_ARGS)
    2460                 : {
    2461 GIC          51 :     return populate_record_worker(fcinfo, "jsonb_to_record",
    2462 ECB             :                                   false, false);
    2463                 : }
    2464                 : 
    2465                 : Datum
    2466 GIC         411 : json_populate_record(PG_FUNCTION_ARGS)
    2467                 : {
    2468             411 :     return populate_record_worker(fcinfo, "json_populate_record",
    2469 ECB             :                                   true, true);
    2470                 : }
    2471                 : 
    2472                 : Datum
    2473 GIC          51 : json_to_record(PG_FUNCTION_ARGS)
    2474 ECB             : {
    2475 GBC          51 :     return populate_record_worker(fcinfo, "json_to_record",
    2476                 :                                   true, false);
    2477                 : }
    2478                 : 
    2479                 : /* helper function for diagnostics */
    2480 ECB             : static void
    2481 GIC          78 : populate_array_report_expected_array(PopulateArrayContext *ctx, int ndim)
    2482                 : {
    2483              78 :     if (ndim <= 0)
    2484 ECB             :     {
    2485 GIC          48 :         if (ctx->colname)
    2486 CBC          48 :             ereport(ERROR,
    2487                 :                     (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
    2488                 :                      errmsg("expected JSON array"),
    2489 ECB             :                      errhint("See the value of key \"%s\".", ctx->colname)));
    2490 EUB             :         else
    2491 UIC           0 :             ereport(ERROR,
    2492                 :                     (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
    2493                 :                      errmsg("expected JSON array")));
    2494                 :     }
    2495                 :     else
    2496 ECB             :     {
    2497                 :         StringInfoData indices;
    2498                 :         int         i;
    2499                 : 
    2500 GIC          30 :         initStringInfo(&indices);
    2501                 : 
    2502              30 :         Assert(ctx->ndims > 0 && ndim < ctx->ndims);
    2503                 : 
    2504              60 :         for (i = 0; i < ndim; i++)
    2505              30 :             appendStringInfo(&indices, "[%d]", ctx->sizes[i]);
    2506                 : 
    2507              30 :         if (ctx->colname)
    2508              30 :             ereport(ERROR,
    2509                 :                     (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
    2510                 :                      errmsg("expected JSON array"),
    2511                 :                      errhint("See the array element %s of key \"%s\".",
    2512                 :                              indices.data, ctx->colname)));
    2513                 :         else
    2514 UIC           0 :             ereport(ERROR,
    2515 ECB             :                     (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
    2516                 :                      errmsg("expected JSON array"),
    2517                 :                      errhint("See the array element %s.",
    2518                 :                              indices.data)));
    2519                 :     }
    2520                 : }
    2521                 : 
    2522                 : /* set the number of dimensions of the populated array when it becomes known */
    2523                 : static void
    2524 CBC         876 : populate_array_assign_ndims(PopulateArrayContext *ctx, int ndims)
    2525                 : {
    2526                 :     int         i;
    2527                 : 
    2528 GIC         876 :     Assert(ctx->ndims <= 0);
    2529 ECB             : 
    2530 GIC         876 :     if (ndims <= 0)
    2531 CBC          24 :         populate_array_report_expected_array(ctx, ndims);
    2532                 : 
    2533 GIC         852 :     ctx->ndims = ndims;
    2534             852 :     ctx->dims = palloc(sizeof(int) * ndims);
    2535             852 :     ctx->sizes = palloc0(sizeof(int) * ndims);
    2536 ECB             : 
    2537 GIC        1872 :     for (i = 0; i < ndims; i++)
    2538 CBC        1020 :         ctx->dims[i] = -1;       /* dimensions are unknown yet */
    2539 GIC         852 : }
    2540                 : 
    2541                 : /* check the populated subarray dimension */
    2542                 : static void
    2543             753 : populate_array_check_dimension(PopulateArrayContext *ctx, int ndim)
    2544 ECB             : {
    2545 GIC         753 :     int         dim = ctx->sizes[ndim]; /* current dimension counter */
    2546 ECB             : 
    2547 GIC         753 :     if (ctx->dims[ndim] == -1)
    2548 CBC         561 :         ctx->dims[ndim] = dim;   /* assign dimension if not yet known */
    2549             192 :     else if (ctx->dims[ndim] != dim)
    2550 GIC          24 :         ereport(ERROR,
    2551                 :                 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
    2552                 :                  errmsg("malformed JSON array"),
    2553                 :                  errdetail("Multidimensional arrays must have "
    2554 EUB             :                            "sub-arrays with matching dimensions.")));
    2555                 : 
    2556                 :     /* reset the current array dimension size counter */
    2557 GIC         729 :     ctx->sizes[ndim] = 0;
    2558                 : 
    2559                 :     /* increment the parent dimension counter if it is a nested sub-array */
    2560             729 :     if (ndim > 0)
    2561             336 :         ctx->sizes[ndim - 1]++;
    2562             729 : }
    2563 ECB             : 
    2564                 : static void
    2565 CBC        2952 : populate_array_element(PopulateArrayContext *ctx, int ndim, JsValue *jsv)
    2566                 : {
    2567 ECB             :     Datum       element;
    2568                 :     bool        element_isnull;
    2569                 : 
    2570                 :     /* populate the array element */
    2571 CBC        2952 :     element = populate_record_field(ctx->aio->element_info,
    2572 GIC        2952 :                                     ctx->aio->element_type,
    2573            2952 :                                     ctx->aio->element_typmod,
    2574                 :                                     NULL, ctx->mcxt, PointerGetDatum(NULL),
    2575                 :                                     jsv, &element_isnull);
    2576                 : 
    2577 GBC        2940 :     accumArrayResult(ctx->astate, element, element_isnull,
    2578 GIC        2940 :                      ctx->aio->element_type, ctx->acxt);
    2579                 : 
    2580            2940 :     Assert(ndim > 0);
    2581            2940 :     ctx->sizes[ndim - 1]++;      /* increment current dimension counter */
    2582            2940 : }
    2583                 : 
    2584                 : /* json object start handler for populate_array_json() */
    2585                 : static JsonParseErrorType
    2586             324 : populate_array_object_start(void *_state)
    2587 ECB             : {
    2588 GIC         324 :     PopulateArrayState *state = (PopulateArrayState *) _state;
    2589             324 :     int         ndim = state->lex->lex_level;
    2590                 : 
    2591 CBC         324 :     if (state->ctx->ndims <= 0)
    2592 GIC         156 :         populate_array_assign_ndims(state->ctx, ndim);
    2593 CBC         168 :     else if (ndim < state->ctx->ndims)
    2594               6 :         populate_array_report_expected_array(state->ctx, ndim);
    2595                 : 
    2596 GNC         318 :     return JSON_SUCCESS;
    2597                 : }
    2598 ECB             : 
    2599                 : /* json array end handler for populate_array_json() */
    2600                 : static JsonParseErrorType
    2601 GIC         576 : populate_array_array_end(void *_state)
    2602 ECB             : {
    2603 CBC         576 :     PopulateArrayState *state = (PopulateArrayState *) _state;
    2604             576 :     PopulateArrayContext *ctx = state->ctx;
    2605 GIC         576 :     int         ndim = state->lex->lex_level;
    2606                 : 
    2607             576 :     if (ctx->ndims <= 0)
    2608 CBC           6 :         populate_array_assign_ndims(ctx, ndim + 1);
    2609                 : 
    2610             576 :     if (ndim < ctx->ndims)
    2611 GIC         573 :         populate_array_check_dimension(ctx, ndim);
    2612                 : 
    2613 GNC         564 :     return JSON_SUCCESS;
    2614 ECB             : }
    2615                 : 
    2616                 : /* json array element start handler for populate_array_json() */
    2617                 : static JsonParseErrorType
    2618 GIC        1683 : populate_array_element_start(void *_state, bool isnull)
    2619                 : {
    2620            1683 :     PopulateArrayState *state = (PopulateArrayState *) _state;
    2621            1683 :     int         ndim = state->lex->lex_level;
    2622                 : 
    2623            1683 :     if (state->ctx->ndims <= 0 || ndim == state->ctx->ndims)
    2624 ECB             :     {
    2625                 :         /* remember current array element start */
    2626 GIC        1560 :         state->element_start = state->lex->token_start;
    2627 CBC        1560 :         state->element_type = state->lex->token_type;
    2628            1560 :         state->element_scalar = NULL;
    2629 ECB             :     }
    2630                 : 
    2631 GNC        1683 :     return JSON_SUCCESS;
    2632                 : }
    2633                 : 
    2634 ECB             : /* json array element end handler for populate_array_json() */
    2635                 : static JsonParseErrorType
    2636 GIC        1656 : populate_array_element_end(void *_state, bool isnull)
    2637                 : {
    2638            1656 :     PopulateArrayState *state = (PopulateArrayState *) _state;
    2639            1656 :     PopulateArrayContext *ctx = state->ctx;
    2640 CBC        1656 :     int         ndim = state->lex->lex_level;
    2641 ECB             : 
    2642 CBC        1656 :     Assert(ctx->ndims > 0);
    2643                 : 
    2644 GIC        1656 :     if (ndim == ctx->ndims)
    2645                 :     {
    2646 ECB             :         JsValue     jsv;
    2647                 : 
    2648 GIC        1476 :         jsv.is_json = true;
    2649 CBC        1476 :         jsv.val.json.type = state->element_type;
    2650 ECB             : 
    2651 CBC        1476 :         if (isnull)
    2652                 :         {
    2653 GIC         354 :             Assert(jsv.val.json.type == JSON_TOKEN_NULL);
    2654             354 :             jsv.val.json.str = NULL;
    2655 CBC         354 :             jsv.val.json.len = 0;
    2656                 :         }
    2657            1122 :         else if (state->element_scalar)
    2658 ECB             :         {
    2659 GIC         804 :             jsv.val.json.str = state->element_scalar;
    2660 CBC         804 :             jsv.val.json.len = -1;  /* null-terminated */
    2661 ECB             :         }
    2662                 :         else
    2663                 :         {
    2664 GIC         318 :             jsv.val.json.str = state->element_start;
    2665 CBC         318 :             jsv.val.json.len = (state->lex->prev_token_terminator -
    2666 GIC         318 :                                 state->element_start) * sizeof(char);
    2667                 :         }
    2668                 : 
    2669            1476 :         populate_array_element(ctx, ndim, &jsv);
    2670 ECB             :     }
    2671                 : 
    2672 GNC        1650 :     return JSON_SUCCESS;
    2673                 : }
    2674 ECB             : 
    2675                 : /* json scalar handler for populate_array_json() */
    2676                 : static JsonParseErrorType
    2677 GIC        1827 : populate_array_scalar(void *_state, char *token, JsonTokenType tokentype)
    2678 ECB             : {
    2679 CBC        1827 :     PopulateArrayState *state = (PopulateArrayState *) _state;
    2680 GIC        1827 :     PopulateArrayContext *ctx = state->ctx;
    2681 CBC        1827 :     int         ndim = state->lex->lex_level;
    2682 ECB             : 
    2683 GIC        1827 :     if (ctx->ndims <= 0)
    2684 CBC         288 :         populate_array_assign_ndims(ctx, ndim);
    2685 GIC        1539 :     else if (ndim < ctx->ndims)
    2686               9 :         populate_array_report_expected_array(ctx, ndim);
    2687                 : 
    2688            1794 :     if (ndim == ctx->ndims)
    2689 ECB             :     {
    2690                 :         /* remember the scalar element token */
    2691 CBC        1158 :         state->element_scalar = token;
    2692 ECB             :         /* element_type must already be set in populate_array_element_start() */
    2693 GIC        1158 :         Assert(state->element_type == tokentype);
    2694 ECB             :     }
    2695                 : 
    2696 GNC        1794 :     return JSON_SUCCESS;
    2697                 : }
    2698                 : 
    2699 ECB             : /* parse a json array and populate array */
    2700                 : static void
    2701 CBC         450 : populate_array_json(PopulateArrayContext *ctx, char *json, int len)
    2702                 : {
    2703                 :     PopulateArrayState state;
    2704 ECB             :     JsonSemAction sem;
    2705                 : 
    2706 GIC         450 :     state.lex = makeJsonLexContextCstringLen(json, len, GetDatabaseEncoding(), true);
    2707             450 :     state.ctx = ctx;
    2708                 : 
    2709 CBC         450 :     memset(&sem, 0, sizeof(sem));
    2710 GIC         450 :     sem.semstate = (void *) &state;
    2711 CBC         450 :     sem.object_start = populate_array_object_start;
    2712             450 :     sem.array_end = populate_array_array_end;
    2713             450 :     sem.array_element_start = populate_array_element_start;
    2714 GIC         450 :     sem.array_element_end = populate_array_element_end;
    2715 CBC         450 :     sem.scalar = populate_array_scalar;
    2716                 : 
    2717             450 :     pg_parse_json_or_ereport(state.lex, &sem);
    2718                 : 
    2719                 :     /* number of dimensions should be already known */
    2720 GIC         393 :     Assert(ctx->ndims > 0 && ctx->dims);
    2721 ECB             : 
    2722 CBC         393 :     pfree(state.lex);
    2723 GIC         393 : }
    2724 ECB             : 
    2725                 : /*
    2726                 :  * populate_array_dim_jsonb() -- Iterate recursively through jsonb sub-array
    2727                 :  *      elements and accumulate result using given ArrayBuildState.
    2728                 :  */
    2729                 : static void
    2730 CBC         645 : populate_array_dim_jsonb(PopulateArrayContext *ctx, /* context */
    2731                 :                          JsonbValue *jbv,   /* jsonb sub-array */
    2732 ECB             :                          int ndim)  /* current dimension */
    2733                 : {
    2734 GIC         645 :     JsonbContainer *jbc = jbv->val.binary.data;
    2735                 :     JsonbIterator *it;
    2736                 :     JsonbIteratorToken tok;
    2737 ECB             :     JsonbValue  val;
    2738                 :     JsValue     jsv;
    2739                 : 
    2740 GIC         645 :     check_stack_depth();
    2741                 : 
    2742 CBC         645 :     if (jbv->type != jbvBinary || !JsonContainerIsArray(jbc))
    2743 GIC          39 :         populate_array_report_expected_array(ctx, ndim - 1);
    2744                 : 
    2745 CBC         606 :     Assert(!JsonContainerIsScalar(jbc));
    2746                 : 
    2747 GIC         606 :     it = JsonbIteratorInit(jbc);
    2748                 : 
    2749             606 :     tok = JsonbIteratorNext(&it, &val, true);
    2750 CBC         606 :     Assert(tok == WJB_BEGIN_ARRAY);
    2751                 : 
    2752             606 :     tok = JsonbIteratorNext(&it, &val, true);
    2753 ECB             : 
    2754                 :     /*
    2755                 :      * If the number of dimensions is not yet known and we have found end of
    2756                 :      * the array, or the first child element is not an array, then assign the
    2757                 :      * number of dimensions now.
    2758                 :      */
    2759 CBC         606 :     if (ctx->ndims <= 0 &&
    2760 GIC         504 :         (tok == WJB_END_ARRAY ||
    2761 CBC         504 :          (tok == WJB_ELEM &&
    2762 GIC         504 :           (val.type != jbvBinary ||
    2763             240 :            !JsonContainerIsArray(val.val.binary.data)))))
    2764 CBC         426 :         populate_array_assign_ndims(ctx, ndim);
    2765                 : 
    2766             606 :     jsv.is_json = false;
    2767 GIC         606 :     jsv.val.jsonb = &val;
    2768                 : 
    2769 ECB             :     /* process all the array elements */
    2770 GIC        2244 :     while (tok == WJB_ELEM)
    2771                 :     {
    2772                 :         /*
    2773                 :          * Recurse only if the dimensions of dimensions is still unknown or if
    2774 ECB             :          * it is not the innermost dimension.
    2775                 :          */
    2776 GIC        1671 :         if (ctx->ndims > 0 && ndim >= ctx->ndims)
    2777            1476 :             populate_array_element(ctx, ndim, &jsv);
    2778                 :         else
    2779 ECB             :         {
    2780                 :             /* populate child sub-array */
    2781 GIC         195 :             populate_array_dim_jsonb(ctx, &val, ndim + 1);
    2782 ECB             : 
    2783                 :             /* number of dimensions should be already known */
    2784 CBC         180 :             Assert(ctx->ndims > 0 && ctx->dims);
    2785 ECB             : 
    2786 CBC         180 :             populate_array_check_dimension(ctx, ndim);
    2787 ECB             :         }
    2788                 : 
    2789 GIC        1638 :         tok = JsonbIteratorNext(&it, &val, true);
    2790 ECB             :     }
    2791                 : 
    2792 GIC         573 :     Assert(tok == WJB_END_ARRAY);
    2793 ECB             : 
    2794                 :     /* free iterator, iterating until WJB_DONE */
    2795 CBC         573 :     tok = JsonbIteratorNext(&it, &val, true);
    2796             573 :     Assert(tok == WJB_DONE && !it);
    2797 GIC         573 : }
    2798                 : 
    2799                 : /* recursively populate an array from json/jsonb */
    2800                 : static Datum
    2801             900 : populate_array(ArrayIOData *aio,
    2802                 :                const char *colname,
    2803 ECB             :                MemoryContext mcxt,
    2804                 :                JsValue *jsv)
    2805                 : {
    2806                 :     PopulateArrayContext ctx;
    2807                 :     Datum       result;
    2808                 :     int        *lbs;
    2809                 :     int         i;
    2810                 : 
    2811 GIC         900 :     ctx.aio = aio;
    2812             900 :     ctx.mcxt = mcxt;
    2813 CBC         900 :     ctx.acxt = CurrentMemoryContext;
    2814 GIC         900 :     ctx.astate = initArrayResult(aio->element_type, ctx.acxt, true);
    2815 CBC         900 :     ctx.colname = colname;
    2816             900 :     ctx.ndims = 0;              /* unknown yet */
    2817 GIC         900 :     ctx.dims = NULL;
    2818 CBC         900 :     ctx.sizes = NULL;
    2819                 : 
    2820             900 :     if (jsv->is_json)
    2821 GIC         450 :         populate_array_json(&ctx, jsv->val.json.str,
    2822 CBC         450 :                             jsv->val.json.len >= 0 ? jsv->val.json.len
    2823             450 :                             : strlen(jsv->val.json.str));
    2824                 :     else
    2825 ECB             :     {
    2826 GIC         450 :         populate_array_dim_jsonb(&ctx, jsv->val.jsonb, 1);
    2827             393 :         ctx.dims[0] = ctx.sizes[0];
    2828                 :     }
    2829                 : 
    2830             786 :     Assert(ctx.ndims > 0);
    2831                 : 
    2832 CBC         786 :     lbs = palloc(sizeof(int) * ctx.ndims);
    2833 ECB             : 
    2834 CBC        1680 :     for (i = 0; i < ctx.ndims; i++)
    2835             894 :         lbs[i] = 1;
    2836 ECB             : 
    2837 CBC         786 :     result = makeMdArrayResult(ctx.astate, ctx.ndims, ctx.dims, lbs,
    2838                 :                                ctx.acxt, true);
    2839 ECB             : 
    2840 CBC         786 :     pfree(ctx.dims);
    2841 GIC         786 :     pfree(ctx.sizes);
    2842             786 :     pfree(lbs);
    2843 ECB             : 
    2844 GIC         786 :     return result;
    2845                 : }
    2846                 : 
    2847                 : static void
    2848            1884 : JsValueToJsObject(JsValue *jsv, JsObject *jso)
    2849 ECB             : {
    2850 CBC        1884 :     jso->is_json = jsv->is_json;
    2851                 : 
    2852 GIC        1884 :     if (jsv->is_json)
    2853                 :     {
    2854 ECB             :         /* convert plain-text json into a hash table */
    2855 GIC         933 :         jso->val.json_hash =
    2856             942 :             get_json_object_as_hash(jsv->val.json.str,
    2857 CBC         942 :                                     jsv->val.json.len >= 0
    2858                 :                                     ? jsv->val.json.len
    2859             171 :                                     : strlen(jsv->val.json.str),
    2860                 :                                     "populate_composite");
    2861                 :     }
    2862 ECB             :     else
    2863                 :     {
    2864 GIC         942 :         JsonbValue *jbv = jsv->val.jsonb;
    2865 ECB             : 
    2866 GIC         942 :         if (jbv->type == jbvBinary &&
    2867             936 :             JsonContainerIsObject(jbv->val.binary.data))
    2868 ECB             :         {
    2869 CBC         933 :             jso->val.jsonb_cont = jbv->val.binary.data;
    2870 ECB             :         }
    2871                 :         else
    2872                 :         {
    2873                 :             bool        is_scalar;
    2874                 : 
    2875 GIC          12 :             is_scalar = IsAJsonbScalar(jbv) ||
    2876               3 :                 (jbv->type == jbvBinary &&
    2877               3 :                  JsonContainerIsScalar(jbv->val.binary.data));
    2878               9 :             ereport(ERROR,
    2879                 :                     (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    2880                 :                      is_scalar
    2881                 :                      ? errmsg("cannot call %s on a scalar",
    2882                 :                               "populate_composite")
    2883                 :                      : errmsg("cannot call %s on an array",
    2884 ECB             :                               "populate_composite")));
    2885                 :         }
    2886                 :     }
    2887 CBC        1866 : }
    2888 ECB             : 
    2889                 : /* acquire or update cached tuple descriptor for a composite type */
    2890                 : static void
    2891 CBC        2283 : update_cached_tupdesc(CompositeIOData *io, MemoryContext mcxt)
    2892                 : {
    2893            2283 :     if (!io->tupdesc ||
    2894            1308 :         io->tupdesc->tdtypeid != io->base_typid ||
    2895            1308 :         io->tupdesc->tdtypmod != io->base_typmod)
    2896 ECB             :     {
    2897 GIC         975 :         TupleDesc   tupdesc = lookup_rowtype_tupdesc(io->base_typid,
    2898                 :                                                      io->base_typmod);
    2899 ECB             :         MemoryContext oldcxt;
    2900                 : 
    2901 GIC         975 :         if (io->tupdesc)
    2902 UIC           0 :             FreeTupleDesc(io->tupdesc);
    2903 ECB             : 
    2904                 :         /* copy tuple desc without constraints into cache memory context */
    2905 CBC         975 :         oldcxt = MemoryContextSwitchTo(mcxt);
    2906 GIC         975 :         io->tupdesc = CreateTupleDescCopy(tupdesc);
    2907 CBC         975 :         MemoryContextSwitchTo(oldcxt);
    2908 ECB             : 
    2909 GIC         975 :         ReleaseTupleDesc(tupdesc);
    2910 ECB             :     }
    2911 GIC        2283 : }
    2912                 : 
    2913 ECB             : /* recursively populate a composite (row type) value from json/jsonb */
    2914                 : static Datum
    2915 CBC        1884 : populate_composite(CompositeIOData *io,
    2916                 :                    Oid typid,
    2917 ECB             :                    const char *colname,
    2918                 :                    MemoryContext mcxt,
    2919                 :                    HeapTupleHeader defaultval,
    2920                 :                    JsValue *jsv,
    2921                 :                    bool isnull)
    2922                 : {
    2923                 :     Datum       result;
    2924                 : 
    2925                 :     /* acquire/update cached tuple descriptor */
    2926 GIC        1884 :     update_cached_tupdesc(io, mcxt);
    2927                 : 
    2928 CBC        1884 :     if (isnull)
    2929 LBC           0 :         result = (Datum) 0;
    2930 ECB             :     else
    2931                 :     {
    2932                 :         HeapTupleHeader tuple;
    2933                 :         JsObject    jso;
    2934                 : 
    2935                 :         /* prepare input value */
    2936 GIC        1884 :         JsValueToJsObject(jsv, &jso);
    2937 ECB             : 
    2938                 :         /* populate resulting record tuple */
    2939 CBC        1866 :         tuple = populate_record(io->tupdesc, &io->record_io,
    2940 ECB             :                                 defaultval, mcxt, &jso);
    2941 GIC        1704 :         result = HeapTupleHeaderGetDatum(tuple);
    2942 ECB             : 
    2943 GIC        1704 :         JsObjectFree(&jso);
    2944                 :     }
    2945                 : 
    2946                 :     /*
    2947                 :      * If it's domain over composite, check domain constraints.  (This should
    2948 ECB             :      * probably get refactored so that we can see the TYPECAT value, but for
    2949                 :      * now, we can tell by comparing typid to base_typid.)
    2950                 :      */
    2951 CBC        1704 :     if (typid != io->base_typid && typid != RECORDOID)
    2952 GIC          18 :         domain_check(result, isnull, typid, &io->domain_info, mcxt);
    2953                 : 
    2954            1698 :     return result;
    2955                 : }
    2956                 : 
    2957                 : /* populate non-null scalar value from json/jsonb value */
    2958                 : static Datum
    2959            3789 : populate_scalar(ScalarIOData *io, Oid typid, int32 typmod, JsValue *jsv)
    2960 ECB             : {
    2961                 :     Datum       res;
    2962 GIC        3789 :     char       *str = NULL;
    2963            3789 :     char       *json = NULL;
    2964 ECB             : 
    2965 GIC        3789 :     if (jsv->is_json)
    2966 ECB             :     {
    2967 CBC        1908 :         int         len = jsv->val.json.len;
    2968 ECB             : 
    2969 GIC        1908 :         json = jsv->val.json.str;
    2970 CBC        1908 :         Assert(json);
    2971 GIC        1908 :         if (len >= 0)
    2972                 :         {
    2973                 :             /* Need to copy non-null-terminated string */
    2974 CBC           6 :             str = palloc(len + 1 * sizeof(char));
    2975 GBC           6 :             memcpy(str, json, len);
    2976 GIC           6 :             str[len] = '\0';
    2977                 :         }
    2978 ECB             :         else
    2979 CBC        1902 :             str = json;         /* string is already null-terminated */
    2980 ECB             : 
    2981                 :         /* If converting to json/jsonb, make string into valid JSON literal */
    2982 CBC        1908 :         if ((typid == JSONOID || typid == JSONBOID) &&
    2983 GIC         546 :             jsv->val.json.type == JSON_TOKEN_STRING)
    2984 ECB             :         {
    2985                 :             StringInfoData buf;
    2986                 : 
    2987 GIC         177 :             initStringInfo(&buf);
    2988 CBC         177 :             escape_json(&buf, str);
    2989                 :             /* free temporary buffer */
    2990 GIC         177 :             if (str != json)
    2991 UIC           0 :                 pfree(str);
    2992 GIC         177 :             str = buf.data;
    2993                 :         }
    2994                 :     }
    2995                 :     else
    2996                 :     {
    2997            1881 :         JsonbValue *jbv = jsv->val.jsonb;
    2998                 : 
    2999 CBC        1881 :         if (typid == JSONBOID)
    3000                 :         {
    3001              33 :             Jsonb      *jsonb = JsonbValueToJsonb(jbv); /* directly use jsonb */
    3002 EUB             : 
    3003 GIC          33 :             return JsonbPGetDatum(jsonb);
    3004                 :         }
    3005                 :         /* convert jsonb to string for typio call */
    3006            1848 :         else if (typid == JSONOID && jbv->type != jbvBinary)
    3007             486 :         {
    3008                 :             /*
    3009 ECB             :              * Convert scalar jsonb (non-scalars are passed here as jbvBinary)
    3010                 :              * to json string, preserving quotes around top-level strings.
    3011                 :              */
    3012 CBC         486 :             Jsonb      *jsonb = JsonbValueToJsonb(jbv);
    3013                 : 
    3014             486 :             str = JsonbToCString(NULL, &jsonb->root, VARSIZE(jsonb));
    3015                 :         }
    3016            1362 :         else if (jbv->type == jbvString) /* quotes are stripped */
    3017 GIC         771 :             str = pnstrdup(jbv->val.string.val, jbv->val.string.len);
    3018             591 :         else if (jbv->type == jbvBool)
    3019               3 :             str = pstrdup(jbv->val.boolean ? "true" : "false");
    3020             588 :         else if (jbv->type == jbvNumeric)
    3021             546 :             str = DatumGetCString(DirectFunctionCall1(numeric_out,
    3022                 :                                                       PointerGetDatum(jbv->val.numeric)));
    3023              42 :         else if (jbv->type == jbvBinary)
    3024 CBC          42 :             str = JsonbToCString(NULL, jbv->val.binary.data,
    3025 ECB             :                                  jbv->val.binary.len);
    3026                 :         else
    3027 LBC           0 :             elog(ERROR, "unrecognized jsonb type: %d", (int) jbv->type);
    3028                 :     }
    3029                 : 
    3030 GIC        3756 :     res = InputFunctionCall(&io->typiofunc, str, io->typioparam, typmod);
    3031                 : 
    3032 ECB             :     /* free temporary buffer */
    3033 GIC        3732 :     if (str != json)
    3034            2019 :         pfree(str);
    3035 ECB             : 
    3036 CBC        3732 :     return res;
    3037                 : }
    3038 ECB             : 
    3039                 : static Datum
    3040 CBC        1350 : populate_domain(DomainIOData *io,
    3041                 :                 Oid typid,
    3042 ECB             :                 const char *colname,
    3043                 :                 MemoryContext mcxt,
    3044                 :                 JsValue *jsv,
    3045                 :                 bool isnull)
    3046                 : {
    3047                 :     Datum       res;
    3048                 : 
    3049 CBC        1350 :     if (isnull)
    3050 GIC        1314 :         res = (Datum) 0;
    3051                 :     else
    3052 ECB             :     {
    3053 GIC          36 :         res = populate_record_field(io->base_io,
    3054                 :                                     io->base_typid, io->base_typmod,
    3055 ECB             :                                     colname, mcxt, PointerGetDatum(NULL),
    3056                 :                                     jsv, &isnull);
    3057 GIC          30 :         Assert(!isnull);
    3058                 :     }
    3059                 : 
    3060 CBC        1344 :     domain_check(res, isnull, typid, &io->domain_info, mcxt);
    3061 ECB             : 
    3062 GIC        1320 :     return res;
    3063 ECB             : }
    3064 EUB             : 
    3065 ECB             : /* prepare column metadata cache for the given type */
    3066                 : static void
    3067 GIC       10131 : prepare_column_cache(ColumnIOData *column,
    3068                 :                      Oid typid,
    3069                 :                      int32 typmod,
    3070 ECB             :                      MemoryContext mcxt,
    3071                 :                      bool need_scalar)
    3072                 : {
    3073                 :     HeapTuple   tup;
    3074                 :     Form_pg_type type;
    3075                 : 
    3076 CBC       10131 :     column->typid = typid;
    3077 GIC       10131 :     column->typmod = typmod;
    3078                 : 
    3079 CBC       10131 :     tup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
    3080           10131 :     if (!HeapTupleIsValid(tup))
    3081 UIC           0 :         elog(ERROR, "cache lookup failed for type %u", typid);
    3082                 : 
    3083 GIC       10131 :     type = (Form_pg_type) GETSTRUCT(tup);
    3084                 : 
    3085 CBC       10131 :     if (type->typtype == TYPTYPE_DOMAIN)
    3086                 :     {
    3087 ECB             :         /*
    3088                 :          * We can move directly to the bottom base type; domain_check() will
    3089                 :          * take care of checking all constraints for a stack of domains.
    3090                 :          */
    3091                 :         Oid         base_typid;
    3092 CBC         978 :         int32       base_typmod = typmod;
    3093 ECB             : 
    3094 CBC         978 :         base_typid = getBaseTypeAndTypmod(typid, &base_typmod);
    3095 GIC         978 :         if (get_typtype(base_typid) == TYPTYPE_COMPOSITE)
    3096 ECB             :         {
    3097                 :             /* domain over composite has its own code path */
    3098 GIC          36 :             column->typcat = TYPECAT_COMPOSITE_DOMAIN;
    3099              36 :             column->io.composite.record_io = NULL;
    3100 GBC          36 :             column->io.composite.tupdesc = NULL;
    3101 GIC          36 :             column->io.composite.base_typid = base_typid;
    3102              36 :             column->io.composite.base_typmod = base_typmod;
    3103 CBC          36 :             column->io.composite.domain_info = NULL;
    3104                 :         }
    3105                 :         else
    3106 ECB             :         {
    3107                 :             /* domain over anything else */
    3108 GIC         942 :             column->typcat = TYPECAT_DOMAIN;
    3109 CBC         942 :             column->io.domain.base_typid = base_typid;
    3110 GIC         942 :             column->io.domain.base_typmod = base_typmod;
    3111             942 :             column->io.domain.base_io =
    3112             942 :                 MemoryContextAllocZero(mcxt, sizeof(ColumnIOData));
    3113 CBC         942 :             column->io.domain.domain_info = NULL;
    3114                 :         }
    3115                 :     }
    3116 GIC        9153 :     else if (type->typtype == TYPTYPE_COMPOSITE || typid == RECORDOID)
    3117                 :     {
    3118            1269 :         column->typcat = TYPECAT_COMPOSITE;
    3119            1269 :         column->io.composite.record_io = NULL;
    3120            1269 :         column->io.composite.tupdesc = NULL;
    3121            1269 :         column->io.composite.base_typid = typid;
    3122 CBC        1269 :         column->io.composite.base_typmod = typmod;
    3123            1269 :         column->io.composite.domain_info = NULL;
    3124                 :     }
    3125 GIC        7884 :     else if (IsTrueArrayType(type))
    3126 ECB             :     {
    3127 GIC        3750 :         column->typcat = TYPECAT_ARRAY;
    3128            3750 :         column->io.array.element_info = MemoryContextAllocZero(mcxt,
    3129                 :                                                                sizeof(ColumnIOData));
    3130 CBC        3750 :         column->io.array.element_type = type->typelem;
    3131                 :         /* array element typemod stored in attribute's typmod */
    3132 GIC        3750 :         column->io.array.element_typmod = typmod;
    3133 ECB             :     }
    3134                 :     else
    3135                 :     {
    3136 GIC        4134 :         column->typcat = TYPECAT_SCALAR;
    3137            4134 :         need_scalar = true;
    3138                 :     }
    3139                 : 
    3140 ECB             :     /* caller can force us to look up scalar_io info even for non-scalars */
    3141 GIC       10131 :     if (need_scalar)
    3142                 :     {
    3143                 :         Oid         typioproc;
    3144                 : 
    3145            9366 :         getTypeInputInfo(typid, &typioproc, &column->scalar_io.typioparam);
    3146            9366 :         fmgr_info_cxt(typioproc, &column->scalar_io.typiofunc, mcxt);
    3147                 :     }
    3148                 : 
    3149 CBC       10131 :     ReleaseSysCache(tup);
    3150           10131 : }
    3151                 : 
    3152 ECB             : /* recursively populate a record field or an array element from a json/jsonb value */
    3153                 : static Datum
    3154 GBC       17619 : populate_record_field(ColumnIOData *col,
    3155                 :                       Oid typid,
    3156 ECB             :                       int32 typmod,
    3157                 :                       const char *colname,
    3158                 :                       MemoryContext mcxt,
    3159                 :                       Datum defaultval,
    3160                 :                       JsValue *jsv,
    3161                 :                       bool *isnull)
    3162                 : {
    3163                 :     TypeCat     typcat;
    3164                 : 
    3165 CBC       17619 :     check_stack_depth();
    3166                 : 
    3167 ECB             :     /*
    3168                 :      * Prepare column metadata cache for the given type.  Force lookup of the
    3169                 :      * scalar_io data so that the json string hack below will work.
    3170                 :      */
    3171 CBC       17619 :     if (col->typid != typid || col->typmod != typmod)
    3172            9366 :         prepare_column_cache(col, typid, typmod, mcxt, true);
    3173 ECB             : 
    3174 CBC       17619 :     *isnull = JsValueIsNull(jsv);
    3175 ECB             : 
    3176 CBC       17619 :     typcat = col->typcat;
    3177                 : 
    3178                 :     /* try to convert json string to a non-scalar type through input function */
    3179 GIC       17619 :     if (JsValueIsString(jsv) &&
    3180            1881 :         (typcat == TYPECAT_ARRAY ||
    3181 CBC        1869 :          typcat == TYPECAT_COMPOSITE ||
    3182 ECB             :          typcat == TYPECAT_COMPOSITE_DOMAIN))
    3183 CBC          24 :         typcat = TYPECAT_SCALAR;
    3184 ECB             : 
    3185                 :     /* we must perform domain checks for NULLs, otherwise exit immediately */
    3186 CBC       17619 :     if (*isnull &&
    3187 GIC       10614 :         typcat != TYPECAT_DOMAIN &&
    3188                 :         typcat != TYPECAT_COMPOSITE_DOMAIN)
    3189 CBC       10614 :         return (Datum) 0;
    3190                 : 
    3191            7005 :     switch (typcat)
    3192 ECB             :     {
    3193 CBC        3789 :         case TYPECAT_SCALAR:
    3194            3789 :             return populate_scalar(&col->scalar_io, typid, typmod, jsv);
    3195 ECB             : 
    3196 CBC         900 :         case TYPECAT_ARRAY:
    3197 GIC         900 :             return populate_array(&col->io.array, colname, mcxt, jsv);
    3198 ECB             : 
    3199 GIC         966 :         case TYPECAT_COMPOSITE:
    3200 ECB             :         case TYPECAT_COMPOSITE_DOMAIN:
    3201 CBC         972 :             return populate_composite(&col->io.composite, typid,
    3202                 :                                       colname, mcxt,
    3203             966 :                                       DatumGetPointer(defaultval)
    3204 GIC           6 :                                       ? DatumGetHeapTupleHeader(defaultval)
    3205 ECB             :                                       : NULL,
    3206 GIC         966 :                                       jsv, *isnull);
    3207                 : 
    3208            1350 :         case TYPECAT_DOMAIN:
    3209 CBC        1350 :             return populate_domain(&col->io.domain, typid, colname, mcxt,
    3210            1350 :                                    jsv, *isnull);
    3211                 : 
    3212 UIC           0 :         default:
    3213               0 :             elog(ERROR, "unrecognized type category '%c'", typcat);
    3214 ECB             :             return (Datum) 0;
    3215                 :     }
    3216                 : }
    3217                 : 
    3218                 : static RecordIOData *
    3219 CBC        1071 : allocate_record_info(MemoryContext mcxt, int ncolumns)
    3220                 : {
    3221                 :     RecordIOData *data = (RecordIOData *)
    3222            1071 :     MemoryContextAlloc(mcxt,
    3223 ECB             :                        offsetof(RecordIOData, columns) +
    3224 GIC        1071 :                        ncolumns * sizeof(ColumnIOData));
    3225                 : 
    3226            1071 :     data->record_type = InvalidOid;
    3227 CBC        1071 :     data->record_typmod = 0;
    3228 GIC        1071 :     data->ncolumns = ncolumns;
    3229           19089 :     MemSet(data->columns, 0, sizeof(ColumnIOData) * ncolumns);
    3230                 : 
    3231            1071 :     return data;
    3232                 : }
    3233                 : 
    3234                 : static bool
    3235           15009 : JsObjectGetField(JsObject *obj, char *field, JsValue *jsv)
    3236                 : {
    3237           15009 :     jsv->is_json = obj->is_json;
    3238 ECB             : 
    3239 GIC       15009 :     if (jsv->is_json)
    3240                 :     {
    3241            7518 :         JsonHashEntry *hashentry = hash_search(obj->val.json_hash, field,
    3242                 :                                                HASH_FIND, NULL);
    3243                 : 
    3244 CBC        7518 :         jsv->val.json.type = hashentry ? hashentry->type : JSON_TOKEN_NULL;
    3245            7518 :         jsv->val.json.str = jsv->val.json.type == JSON_TOKEN_NULL ? NULL :
    3246                 :             hashentry->val;
    3247            7518 :         jsv->val.json.len = jsv->val.json.str ? -1 : 0; /* null-terminated */
    3248                 : 
    3249            7518 :         return hashentry != NULL;
    3250                 :     }
    3251                 :     else
    3252 ECB             :     {
    3253 CBC        7491 :         jsv->val.jsonb = !obj->val.jsonb_cont ? NULL :
    3254            7491 :             getKeyJsonValueFromContainer(obj->val.jsonb_cont, field, strlen(field),
    3255                 :                                          NULL);
    3256 ECB             : 
    3257 GIC        7491 :         return jsv->val.jsonb != NULL;
    3258                 :     }
    3259 ECB             : }
    3260                 : 
    3261                 : /* populate a record tuple from json/jsonb value */
    3262                 : static HeapTupleHeader
    3263 GIC        2106 : populate_record(TupleDesc tupdesc,
    3264 ECB             :                 RecordIOData **record_p,
    3265                 :                 HeapTupleHeader defaultval,
    3266                 :                 MemoryContext mcxt,
    3267                 :                 JsObject *obj)
    3268                 : {
    3269 CBC        2106 :     RecordIOData *record = *record_p;
    3270 ECB             :     Datum      *values;
    3271                 :     bool       *nulls;
    3272                 :     HeapTuple   res;
    3273 GIC        2106 :     int         ncolumns = tupdesc->natts;
    3274 ECB             :     int         i;
    3275                 : 
    3276                 :     /*
    3277                 :      * if the input json is empty, we can only skip the rest if we were passed
    3278                 :      * in a non-null record, since otherwise there may be issues with domain
    3279                 :      * nulls.
    3280                 :      */
    3281 CBC        2106 :     if (defaultval && JsObjectIsEmpty(obj))
    3282               6 :         return defaultval;
    3283 ECB             : 
    3284                 :     /* (re)allocate metadata cache */
    3285 GBC        2100 :     if (record == NULL ||
    3286            1029 :         record->ncolumns != ncolumns)
    3287 GIC        1071 :         *record_p = record = allocate_record_info(mcxt, ncolumns);
    3288                 : 
    3289                 :     /* invalidate metadata cache if the record type has changed */
    3290            2100 :     if (record->record_type != tupdesc->tdtypeid ||
    3291            1029 :         record->record_typmod != tupdesc->tdtypmod)
    3292 ECB             :     {
    3293 GIC       20199 :         MemSet(record, 0, offsetof(RecordIOData, columns) +
    3294                 :                ncolumns * sizeof(ColumnIOData));
    3295 CBC        1071 :         record->record_type = tupdesc->tdtypeid;
    3296 GIC        1071 :         record->record_typmod = tupdesc->tdtypmod;
    3297 CBC        1071 :         record->ncolumns = ncolumns;
    3298                 :     }
    3299 ECB             : 
    3300 CBC        2100 :     values = (Datum *) palloc(ncolumns * sizeof(Datum));
    3301            2100 :     nulls = (bool *) palloc(ncolumns * sizeof(bool));
    3302 ECB             : 
    3303 GIC        2100 :     if (defaultval)
    3304 ECB             :     {
    3305                 :         HeapTupleData tuple;
    3306                 : 
    3307                 :         /* Build a temporary HeapTuple control structure */
    3308 CBC         216 :         tuple.t_len = HeapTupleHeaderGetDatumLength(defaultval);
    3309 GIC         216 :         ItemPointerSetInvalid(&(tuple.t_self));
    3310 CBC         216 :         tuple.t_tableOid = InvalidOid;
    3311 GIC         216 :         tuple.t_data = defaultval;
    3312 ECB             : 
    3313                 :         /* Break down the tuple into fields */
    3314 CBC         216 :         heap_deform_tuple(&tuple, tupdesc, values, nulls);
    3315                 :     }
    3316                 :     else
    3317 ECB             :     {
    3318 CBC       17319 :         for (i = 0; i < ncolumns; ++i)
    3319                 :         {
    3320           15435 :             values[i] = (Datum) 0;
    3321 GIC       15435 :             nulls[i] = true;
    3322 ECB             :         }
    3323                 :     }
    3324                 : 
    3325 GIC       16941 :     for (i = 0; i < ncolumns; ++i)
    3326 ECB             :     {
    3327 CBC       15009 :         Form_pg_attribute att = TupleDescAttr(tupdesc, i);
    3328 GIC       15009 :         char       *colname = NameStr(att->attname);
    3329           15009 :         JsValue     field = {0};
    3330 ECB             :         bool        found;
    3331                 : 
    3332                 :         /* Ignore dropped columns in datatype */
    3333 GIC       15009 :         if (att->attisdropped)
    3334                 :         {
    3335 UIC           0 :             nulls[i] = true;
    3336 CBC         378 :             continue;
    3337                 :         }
    3338                 : 
    3339 GIC       15009 :         found = JsObjectGetField(obj, colname, &field);
    3340                 : 
    3341                 :         /*
    3342 ECB             :          * we can't just skip here if the key wasn't found since we might have
    3343                 :          * a domain to deal with. If we were passed in a non-null record
    3344                 :          * datum, we assume that the existing values are valid (if they're
    3345                 :          * not, then it's not our fault), but if we were passed in a null,
    3346                 :          * then every field which we don't populate needs to be run through
    3347                 :          * the input function just in case it's a domain type.
    3348                 :          */
    3349 GIC       15009 :         if (defaultval && !found)
    3350             378 :             continue;
    3351                 : 
    3352           14631 :         values[i] = populate_record_field(&record->columns[i],
    3353                 :                                           att->atttypid,
    3354 ECB             :                                           att->atttypmod,
    3355                 :                                           colname,
    3356                 :                                           mcxt,
    3357 GIC       14631 :                                           nulls[i] ? (Datum) 0 : values[i],
    3358 ECB             :                                           &field,
    3359                 :                                           &nulls[i]);
    3360                 :     }
    3361                 : 
    3362 GIC        1932 :     res = heap_form_tuple(tupdesc, values, nulls);
    3363 ECB             : 
    3364 CBC        1932 :     pfree(values);
    3365 GIC        1932 :     pfree(nulls);
    3366 ECB             : 
    3367 GIC        1932 :     return res->t_data;
    3368 ECB             : }
    3369                 : 
    3370                 : /*
    3371                 :  * Setup for json{b}_populate_record{set}: result type will be same as first
    3372                 :  * argument's type --- unless first argument is "null::record", which we can't
    3373                 :  * extract type info from; we handle that later.
    3374                 :  */
    3375                 : static void
    3376 CBC         765 : get_record_type_from_argument(FunctionCallInfo fcinfo,
    3377                 :                               const char *funcname,
    3378                 :                               PopulateRecordCache *cache)
    3379                 : {
    3380 GIC         765 :     cache->argtype = get_fn_expr_argtype(fcinfo->flinfo, 0);
    3381 CBC         765 :     prepare_column_cache(&cache->c,
    3382 ECB             :                          cache->argtype, -1,
    3383                 :                          cache->fn_mcxt, false);
    3384 CBC         765 :     if (cache->c.typcat != TYPECAT_COMPOSITE &&
    3385 GIC          36 :         cache->c.typcat != TYPECAT_COMPOSITE_DOMAIN)
    3386 UIC           0 :         ereport(ERROR,
    3387 ECB             :                 (errcode(ERRCODE_DATATYPE_MISMATCH),
    3388                 :         /* translator: %s is a function name, eg json_to_record */
    3389                 :                  errmsg("first argument of %s must be a row type",
    3390                 :                         funcname)));
    3391 CBC         765 : }
    3392                 : 
    3393 ECB             : /*
    3394                 :  * Setup for json{b}_to_record{set}: result type is specified by calling
    3395                 :  * query.  We'll also use this code for json{b}_populate_record{set},
    3396                 :  * if we discover that the first argument is a null of type RECORD.
    3397                 :  *
    3398                 :  * Here it is syntactically impossible to specify the target type
    3399                 :  * as domain-over-composite.
    3400                 :  */
    3401                 : static void
    3402 CBC         156 : get_record_type_from_query(FunctionCallInfo fcinfo,
    3403                 :                            const char *funcname,
    3404                 :                            PopulateRecordCache *cache)
    3405                 : {
    3406 ECB             :     TupleDesc   tupdesc;
    3407                 :     MemoryContext old_cxt;
    3408 EUB             : 
    3409 CBC         156 :     if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
    3410 GIC          18 :         ereport(ERROR,
    3411                 :                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
    3412 ECB             :         /* translator: %s is a function name, eg json_to_record */
    3413                 :                  errmsg("could not determine row type for result of %s",
    3414                 :                         funcname),
    3415                 :                  errhint("Provide a non-null record argument, "
    3416                 :                          "or call the function in the FROM clause "
    3417                 :                          "using a column definition list.")));
    3418                 : 
    3419 GIC         138 :     Assert(tupdesc);
    3420             138 :     cache->argtype = tupdesc->tdtypeid;
    3421                 : 
    3422 ECB             :     /* If we go through this more than once, avoid memory leak */
    3423 CBC         138 :     if (cache->c.io.composite.tupdesc)
    3424 UIC           0 :         FreeTupleDesc(cache->c.io.composite.tupdesc);
    3425 ECB             : 
    3426                 :     /* Save identified tupdesc */
    3427 GIC         138 :     old_cxt = MemoryContextSwitchTo(cache->fn_mcxt);
    3428             138 :     cache->c.io.composite.tupdesc = CreateTupleDescCopy(tupdesc);
    3429             138 :     cache->c.io.composite.base_typid = tupdesc->tdtypeid;
    3430 CBC         138 :     cache->c.io.composite.base_typmod = tupdesc->tdtypmod;
    3431 GIC         138 :     MemoryContextSwitchTo(old_cxt);
    3432             138 : }
    3433                 : 
    3434                 : /*
    3435 ECB             :  * common worker for json{b}_populate_record() and json{b}_to_record()
    3436                 :  * is_json and have_record_arg identify the specific function
    3437                 :  */
    3438                 : static Datum
    3439 GIC         924 : populate_record_worker(FunctionCallInfo fcinfo, const char *funcname,
    3440 ECB             :                        bool is_json, bool have_record_arg)
    3441                 : {
    3442 GIC         924 :     int         json_arg_num = have_record_arg ? 1 : 0;
    3443             924 :     JsValue     jsv = {0};
    3444                 :     HeapTupleHeader rec;
    3445                 :     Datum       rettuple;
    3446                 :     JsonbValue  jbv;
    3447             924 :     MemoryContext fnmcxt = fcinfo->flinfo->fn_mcxt;
    3448             924 :     PopulateRecordCache *cache = fcinfo->flinfo->fn_extra;
    3449 ECB             : 
    3450                 :     /*
    3451                 :      * If first time through, identify input/result record type.  Note that
    3452                 :      * this stanza looks only at fcinfo context, which can't change during the
    3453                 :      * query; so we may not be able to fully resolve a RECORD input type yet.
    3454                 :      */
    3455 GIC         924 :     if (!cache)
    3456                 :     {
    3457 CBC         720 :         fcinfo->flinfo->fn_extra = cache =
    3458             720 :             MemoryContextAllocZero(fnmcxt, sizeof(*cache));
    3459 GBC         720 :         cache->fn_mcxt = fnmcxt;
    3460                 : 
    3461 GIC         720 :         if (have_record_arg)
    3462             618 :             get_record_type_from_argument(fcinfo, funcname, cache);
    3463                 :         else
    3464 CBC         102 :             get_record_type_from_query(fcinfo, funcname, cache);
    3465                 :     }
    3466                 : 
    3467                 :     /* Collect record arg if we have one */
    3468 GIC         924 :     if (!have_record_arg)
    3469             102 :         rec = NULL;             /* it's json{b}_to_record() */
    3470             822 :     else if (!PG_ARGISNULL(0))
    3471                 :     {
    3472              54 :         rec = PG_GETARG_HEAPTUPLEHEADER(0);
    3473                 : 
    3474                 :         /*
    3475 ECB             :          * When declared arg type is RECORD, identify actual record type from
    3476                 :          * the tuple itself.
    3477                 :          */
    3478 GIC          54 :         if (cache->argtype == RECORDOID)
    3479                 :         {
    3480               6 :             cache->c.io.composite.base_typid = HeapTupleHeaderGetTypeId(rec);
    3481               6 :             cache->c.io.composite.base_typmod = HeapTupleHeaderGetTypMod(rec);
    3482 ECB             :         }
    3483                 :     }
    3484                 :     else
    3485                 :     {
    3486 GIC         768 :         rec = NULL;
    3487                 : 
    3488                 :         /*
    3489                 :          * When declared arg type is RECORD, identify actual record type from
    3490                 :          * calling query, or fail if we can't.
    3491                 :          */
    3492 CBC         768 :         if (cache->argtype == RECORDOID)
    3493 ECB             :         {
    3494 GIC          12 :             get_record_type_from_query(fcinfo, funcname, cache);
    3495                 :             /* This can't change argtype, which is important for next time */
    3496 CBC           6 :             Assert(cache->argtype == RECORDOID);
    3497 EUB             :         }
    3498                 :     }
    3499                 : 
    3500 ECB             :     /* If no JSON argument, just return the record (if any) unchanged */
    3501 CBC         918 :     if (PG_ARGISNULL(json_arg_num))
    3502 ECB             :     {
    3503 LBC           0 :         if (rec)
    3504               0 :             PG_RETURN_POINTER(rec);
    3505 ECB             :         else
    3506 UIC           0 :             PG_RETURN_NULL();
    3507                 :     }
    3508                 : 
    3509 GIC         918 :     jsv.is_json = is_json;
    3510                 : 
    3511             918 :     if (is_json)
    3512 ECB             :     {
    3513 GIC         459 :         text       *json = PG_GETARG_TEXT_PP(json_arg_num);
    3514                 : 
    3515 CBC         459 :         jsv.val.json.str = VARDATA_ANY(json);
    3516             459 :         jsv.val.json.len = VARSIZE_ANY_EXHDR(json);
    3517 GIC         459 :         jsv.val.json.type = JSON_TOKEN_INVALID; /* not used in
    3518                 :                                                  * populate_composite() */
    3519                 :     }
    3520 ECB             :     else
    3521                 :     {
    3522 GIC         459 :         Jsonb      *jb = PG_GETARG_JSONB_P(json_arg_num);
    3523                 : 
    3524             459 :         jsv.val.jsonb = &jbv;
    3525                 : 
    3526                 :         /* fill binary jsonb value pointing to jb */
    3527             459 :         jbv.type = jbvBinary;
    3528 CBC         459 :         jbv.val.binary.data = &jb->root;
    3529 GIC         459 :         jbv.val.binary.len = VARSIZE(jb) - VARHDRSZ;
    3530 ECB             :     }
    3531                 : 
    3532 CBC         918 :     rettuple = populate_composite(&cache->c.io.composite, cache->argtype,
    3533                 :                                   NULL, fnmcxt, rec, &jsv, false);
    3534 ECB             : 
    3535 CBC         750 :     PG_RETURN_DATUM(rettuple);
    3536                 : }
    3537 ECB             : 
    3538                 : /*
    3539                 :  * get_json_object_as_hash
    3540                 :  *
    3541                 :  * decompose a json object into a hash table.
    3542                 :  */
    3543                 : static HTAB *
    3544 GIC         942 : get_json_object_as_hash(char *json, int len, const char *funcname)
    3545 ECB             : {
    3546                 :     HASHCTL     ctl;
    3547                 :     HTAB       *tab;
    3548                 :     JHashState *state;
    3549 GIC         942 :     JsonLexContext *lex = makeJsonLexContextCstringLen(json, len, GetDatabaseEncoding(), true);
    3550                 :     JsonSemAction *sem;
    3551 ECB             : 
    3552 GIC         942 :     ctl.keysize = NAMEDATALEN;
    3553 CBC         942 :     ctl.entrysize = sizeof(JsonHashEntry);
    3554             942 :     ctl.hcxt = CurrentMemoryContext;
    3555 GIC         942 :     tab = hash_create("json object hashtable",
    3556                 :                       100,
    3557                 :                       &ctl,
    3558                 :                       HASH_ELEM | HASH_STRINGS | HASH_CONTEXT);
    3559 ECB             : 
    3560 GIC         942 :     state = palloc0(sizeof(JHashState));
    3561             942 :     sem = palloc0(sizeof(JsonSemAction));
    3562                 : 
    3563             942 :     state->function_name = funcname;
    3564             942 :     state->hash = tab;
    3565 CBC         942 :     state->lex = lex;
    3566                 : 
    3567             942 :     sem->semstate = (void *) state;
    3568 GIC         942 :     sem->array_start = hash_array_start;
    3569 CBC         942 :     sem->scalar = hash_scalar;
    3570 GIC         942 :     sem->object_field_start = hash_object_field_start;
    3571             942 :     sem->object_field_end = hash_object_field_end;
    3572                 : 
    3573             942 :     pg_parse_json_or_ereport(lex, sem);
    3574 ECB             : 
    3575 GIC         933 :     return tab;
    3576 EUB             : }
    3577                 : 
    3578                 : static JsonParseErrorType
    3579 GBC        3078 : hash_object_field_start(void *state, char *fname, bool isnull)
    3580                 : {
    3581 GIC        3078 :     JHashState *_state = (JHashState *) state;
    3582 ECB             : 
    3583 GIC        3078 :     if (_state->lex->lex_level > 1)
    3584 GNC        1158 :         return JSON_SUCCESS;
    3585                 : 
    3586 ECB             :     /* remember token type */
    3587 GIC        1920 :     _state->saved_token_type = _state->lex->token_type;
    3588 ECB             : 
    3589 CBC        1920 :     if (_state->lex->token_type == JSON_TOKEN_ARRAY_START ||
    3590            1470 :         _state->lex->token_type == JSON_TOKEN_OBJECT_START)
    3591                 :     {
    3592                 :         /* remember start position of the whole text of the subobject */
    3593 GIC         627 :         _state->save_json_start = _state->lex->token_start;
    3594                 :     }
    3595 ECB             :     else
    3596                 :     {
    3597                 :         /* must be a scalar */
    3598 GIC        1293 :         _state->save_json_start = NULL;
    3599                 :     }
    3600                 : 
    3601 GNC        1920 :     return JSON_SUCCESS;
    3602 ECB             : }
    3603                 : 
    3604                 : static JsonParseErrorType
    3605 GIC        3078 : hash_object_field_end(void *state, char *fname, bool isnull)
    3606                 : {
    3607 CBC        3078 :     JHashState *_state = (JHashState *) state;
    3608                 :     JsonHashEntry *hashentry;
    3609                 :     bool        found;
    3610 ECB             : 
    3611                 :     /*
    3612                 :      * Ignore nested fields.
    3613                 :      */
    3614 GIC        3078 :     if (_state->lex->lex_level > 1)
    3615 GNC        1158 :         return JSON_SUCCESS;
    3616                 : 
    3617                 :     /*
    3618                 :      * Ignore field names >= NAMEDATALEN - they can't match a record field.
    3619 ECB             :      * (Note: without this test, the hash code would truncate the string at
    3620                 :      * NAMEDATALEN-1, and could then match against a similarly-truncated
    3621                 :      * record field name.  That would be a reasonable behavior, but this code
    3622                 :      * has previously insisted on exact equality, so we keep this behavior.)
    3623                 :      */
    3624 CBC        1920 :     if (strlen(fname) >= NAMEDATALEN)
    3625 UNC           0 :         return JSON_SUCCESS;
    3626                 : 
    3627 CBC        1920 :     hashentry = hash_search(_state->hash, fname, HASH_ENTER, &found);
    3628 ECB             : 
    3629                 :     /*
    3630                 :      * found being true indicates a duplicate. We don't do anything about
    3631                 :      * that, a later field with the same name overrides the earlier field.
    3632                 :      */
    3633                 : 
    3634 GIC        1920 :     hashentry->type = _state->saved_token_type;
    3635 CBC        1920 :     Assert(isnull == (hashentry->type == JSON_TOKEN_NULL));
    3636 ECB             : 
    3637 GIC        1920 :     if (_state->save_json_start != NULL)
    3638 ECB             :     {
    3639 CBC         627 :         int         len = _state->lex->prev_token_terminator - _state->save_json_start;
    3640             627 :         char       *val = palloc((len + 1) * sizeof(char));
    3641                 : 
    3642             627 :         memcpy(val, _state->save_json_start, len);
    3643             627 :         val[len] = '\0';
    3644             627 :         hashentry->val = val;
    3645 ECB             :     }
    3646                 :     else
    3647                 :     {
    3648                 :         /* must have had a scalar instead */
    3649 GIC        1293 :         hashentry->val = _state->saved_scalar;
    3650 ECB             :     }
    3651                 : 
    3652 GNC        1920 :     return JSON_SUCCESS;
    3653                 : }
    3654                 : 
    3655                 : static JsonParseErrorType
    3656 CBC         636 : hash_array_start(void *state)
    3657                 : {
    3658             636 :     JHashState *_state = (JHashState *) state;
    3659                 : 
    3660             636 :     if (_state->lex->lex_level == 0)
    3661               3 :         ereport(ERROR,
    3662                 :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    3663                 :                  errmsg("cannot call %s on an array", _state->function_name)));
    3664                 : 
    3665 GNC         633 :     return JSON_SUCCESS;
    3666 ECB             : }
    3667                 : 
    3668                 : static JsonParseErrorType
    3669 CBC        3690 : hash_scalar(void *state, char *token, JsonTokenType tokentype)
    3670                 : {
    3671 GIC        3690 :     JHashState *_state = (JHashState *) state;
    3672 ECB             : 
    3673 GIC        3690 :     if (_state->lex->lex_level == 0)
    3674               6 :         ereport(ERROR,
    3675                 :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    3676                 :                  errmsg("cannot call %s on a scalar", _state->function_name)));
    3677 ECB             : 
    3678 GIC        3684 :     if (_state->lex->lex_level == 1)
    3679                 :     {
    3680 CBC        1293 :         _state->saved_scalar = token;
    3681                 :         /* saved_token_type must already be set in hash_object_field_start() */
    3682 GIC        1293 :         Assert(_state->saved_token_type == tokentype);
    3683                 :     }
    3684                 : 
    3685 GNC        3684 :     return JSON_SUCCESS;
    3686 ECB             : }
    3687                 : 
    3688                 : 
    3689                 : /*
    3690                 :  * SQL function json_populate_recordset
    3691                 :  *
    3692                 :  * set fields in a set of records from the argument json,
    3693                 :  * which must be an array of objects.
    3694                 :  *
    3695                 :  * similar to json_populate_record, but the tuple-building code
    3696                 :  * is pushed down into the semantic action handlers so it's done
    3697                 :  * per object in the array.
    3698                 :  */
    3699                 : Datum
    3700 GIC          75 : jsonb_populate_recordset(PG_FUNCTION_ARGS)
    3701                 : {
    3702              75 :     return populate_recordset_worker(fcinfo, "jsonb_populate_recordset",
    3703                 :                                      false, true);
    3704                 : }
    3705 ECB             : 
    3706 EUB             : Datum
    3707 GIC           9 : jsonb_to_recordset(PG_FUNCTION_ARGS)
    3708 ECB             : {
    3709 GIC           9 :     return populate_recordset_worker(fcinfo, "jsonb_to_recordset",
    3710                 :                                      false, false);
    3711                 : }
    3712                 : 
    3713                 : Datum
    3714              78 : json_populate_recordset(PG_FUNCTION_ARGS)
    3715 ECB             : {
    3716 CBC          78 :     return populate_recordset_worker(fcinfo, "json_populate_recordset",
    3717                 :                                      true, true);
    3718 ECB             : }
    3719                 : 
    3720                 : Datum
    3721 CBC           9 : json_to_recordset(PG_FUNCTION_ARGS)
    3722                 : {
    3723               9 :     return populate_recordset_worker(fcinfo, "json_to_recordset",
    3724 ECB             :                                      true, false);
    3725                 : }
    3726                 : 
    3727                 : static void
    3728 GIC         240 : populate_recordset_record(PopulateRecordsetState *state, JsObject *obj)
    3729                 : {
    3730 CBC         240 :     PopulateRecordCache *cache = state->cache;
    3731                 :     HeapTupleHeader tuphead;
    3732                 :     HeapTupleData tuple;
    3733 ECB             : 
    3734                 :     /* acquire/update cached tuple descriptor */
    3735 GIC         240 :     update_cached_tupdesc(&cache->c.io.composite, cache->fn_mcxt);
    3736                 : 
    3737 ECB             :     /* replace record fields from json */
    3738 GIC         240 :     tuphead = populate_record(cache->c.io.composite.tupdesc,
    3739 ECB             :                               &cache->c.io.composite.record_io,
    3740                 :                               state->rec,
    3741                 :                               cache->fn_mcxt,
    3742                 :                               obj);
    3743                 : 
    3744                 :     /* if it's domain over composite, check domain constraints */
    3745 GIC         234 :     if (cache->c.typcat == TYPECAT_COMPOSITE_DOMAIN)
    3746 CBC          24 :         domain_check(HeapTupleHeaderGetDatum(tuphead), false,
    3747                 :                      cache->argtype,
    3748                 :                      &cache->c.io.composite.domain_info,
    3749                 :                      cache->fn_mcxt);
    3750 ECB             : 
    3751                 :     /* ok, save into tuplestore */
    3752 CBC         228 :     tuple.t_len = HeapTupleHeaderGetDatumLength(tuphead);
    3753 GIC         228 :     ItemPointerSetInvalid(&(tuple.t_self));
    3754 CBC         228 :     tuple.t_tableOid = InvalidOid;
    3755             228 :     tuple.t_data = tuphead;
    3756                 : 
    3757 GIC         228 :     tuplestore_puttuple(state->tuple_store, &tuple);
    3758             228 : }
    3759 ECB             : 
    3760                 : /*
    3761                 :  * common worker for json{b}_populate_recordset() and json{b}_to_recordset()
    3762                 :  * is_json and have_record_arg identify the specific function
    3763                 :  */
    3764                 : static Datum
    3765 GIC         171 : populate_recordset_worker(FunctionCallInfo fcinfo, const char *funcname,
    3766 ECB             :                           bool is_json, bool have_record_arg)
    3767                 : {
    3768 GIC         171 :     int         json_arg_num = have_record_arg ? 1 : 0;
    3769                 :     ReturnSetInfo *rsi;
    3770                 :     MemoryContext old_cxt;
    3771                 :     HeapTupleHeader rec;
    3772             171 :     PopulateRecordCache *cache = fcinfo->flinfo->fn_extra;
    3773                 :     PopulateRecordsetState *state;
    3774                 : 
    3775             171 :     rsi = (ReturnSetInfo *) fcinfo->resultinfo;
    3776                 : 
    3777             171 :     if (!rsi || !IsA(rsi, ReturnSetInfo))
    3778 UIC           0 :         ereport(ERROR,
    3779                 :                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
    3780                 :                  errmsg("set-valued function called in context that cannot accept a set")));
    3781 ECB             : 
    3782 GIC         171 :     if (!(rsi->allowedModes & SFRM_Materialize))
    3783 LBC           0 :         ereport(ERROR,
    3784                 :                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
    3785                 :                  errmsg("materialize mode required, but it is not allowed in this context")));
    3786                 : 
    3787 GIC         171 :     rsi->returnMode = SFRM_Materialize;
    3788 ECB             : 
    3789                 :     /*
    3790                 :      * If first time through, identify input/result record type.  Note that
    3791                 :      * this stanza looks only at fcinfo context, which can't change during the
    3792                 :      * query; so we may not be able to fully resolve a RECORD input type yet.
    3793                 :      */
    3794 GIC         171 :     if (!cache)
    3795 ECB             :     {
    3796 GIC         165 :         fcinfo->flinfo->fn_extra = cache =
    3797 CBC         165 :             MemoryContextAllocZero(fcinfo->flinfo->fn_mcxt, sizeof(*cache));
    3798 GIC         165 :         cache->fn_mcxt = fcinfo->flinfo->fn_mcxt;
    3799                 : 
    3800             165 :         if (have_record_arg)
    3801             147 :             get_record_type_from_argument(fcinfo, funcname, cache);
    3802 ECB             :         else
    3803 GIC          18 :             get_record_type_from_query(fcinfo, funcname, cache);
    3804 ECB             :     }
    3805                 : 
    3806                 :     /* Collect record arg if we have one */
    3807 GIC         171 :     if (!have_record_arg)
    3808              18 :         rec = NULL;             /* it's json{b}_to_recordset() */
    3809 CBC         153 :     else if (!PG_ARGISNULL(0))
    3810                 :     {
    3811              96 :         rec = PG_GETARG_HEAPTUPLEHEADER(0);
    3812                 : 
    3813                 :         /*
    3814                 :          * When declared arg type is RECORD, identify actual record type from
    3815                 :          * the tuple itself.
    3816 ECB             :          */
    3817 GIC          96 :         if (cache->argtype == RECORDOID)
    3818                 :         {
    3819 CBC          48 :             cache->c.io.composite.base_typid = HeapTupleHeaderGetTypeId(rec);
    3820 GIC          48 :             cache->c.io.composite.base_typmod = HeapTupleHeaderGetTypMod(rec);
    3821                 :         }
    3822                 :     }
    3823                 :     else
    3824                 :     {
    3825              57 :         rec = NULL;
    3826 ECB             : 
    3827                 :         /*
    3828                 :          * When declared arg type is RECORD, identify actual record type from
    3829                 :          * calling query, or fail if we can't.
    3830                 :          */
    3831 GIC          57 :         if (cache->argtype == RECORDOID)
    3832                 :         {
    3833 CBC          24 :             get_record_type_from_query(fcinfo, funcname, cache);
    3834 ECB             :             /* This can't change argtype, which is important for next time */
    3835 CBC          12 :             Assert(cache->argtype == RECORDOID);
    3836 ECB             :         }
    3837                 :     }
    3838                 : 
    3839                 :     /* if the json is null send back an empty set */
    3840 GIC         159 :     if (PG_ARGISNULL(json_arg_num))
    3841 UIC           0 :         PG_RETURN_NULL();
    3842                 : 
    3843                 :     /*
    3844                 :      * Forcibly update the cached tupdesc, to ensure we have the right tupdesc
    3845                 :      * to return even if the JSON contains no rows.
    3846 ECB             :      */
    3847 GIC         159 :     update_cached_tupdesc(&cache->c.io.composite, cache->fn_mcxt);
    3848                 : 
    3849 CBC         159 :     state = palloc0(sizeof(PopulateRecordsetState));
    3850                 : 
    3851                 :     /* make tuplestore in a sufficiently long-lived memory context */
    3852 GIC         159 :     old_cxt = MemoryContextSwitchTo(rsi->econtext->ecxt_per_query_memory);
    3853 CBC         159 :     state->tuple_store = tuplestore_begin_heap(rsi->allowedModes &
    3854                 :                                                SFRM_Materialize_Random,
    3855                 :                                                false, work_mem);
    3856             159 :     MemoryContextSwitchTo(old_cxt);
    3857                 : 
    3858             159 :     state->function_name = funcname;
    3859 GBC         159 :     state->cache = cache;
    3860 GIC         159 :     state->rec = rec;
    3861                 : 
    3862             159 :     if (is_json)
    3863 ECB             :     {
    3864 GBC          81 :         text       *json = PG_GETARG_TEXT_PP(json_arg_num);
    3865                 :         JsonLexContext *lex;
    3866                 :         JsonSemAction *sem;
    3867                 : 
    3868 CBC          81 :         sem = palloc0(sizeof(JsonSemAction));
    3869                 : 
    3870 GIC          81 :         lex = makeJsonLexContext(json, true);
    3871                 : 
    3872              81 :         sem->semstate = (void *) state;
    3873              81 :         sem->array_start = populate_recordset_array_start;
    3874              81 :         sem->array_element_start = populate_recordset_array_element_start;
    3875 CBC          81 :         sem->scalar = populate_recordset_scalar;
    3876 GIC          81 :         sem->object_field_start = populate_recordset_object_field_start;
    3877 CBC          81 :         sem->object_field_end = populate_recordset_object_field_end;
    3878              81 :         sem->object_start = populate_recordset_object_start;
    3879              81 :         sem->object_end = populate_recordset_object_end;
    3880                 : 
    3881              81 :         state->lex = lex;
    3882 ECB             : 
    3883 GIC          81 :         pg_parse_json_or_ereport(lex, sem);
    3884 ECB             :     }
    3885                 :     else
    3886                 :     {
    3887 GIC          78 :         Jsonb      *jb = PG_GETARG_JSONB_P(json_arg_num);
    3888 ECB             :         JsonbIterator *it;
    3889                 :         JsonbValue  v;
    3890 CBC          78 :         bool        skipNested = false;
    3891                 :         JsonbIteratorToken r;
    3892 ECB             : 
    3893 GIC          78 :         if (JB_ROOT_IS_SCALAR(jb) || !JB_ROOT_IS_ARRAY(jb))
    3894 UIC           0 :             ereport(ERROR,
    3895                 :                     (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    3896                 :                      errmsg("cannot call %s on a non-array",
    3897                 :                             funcname)));
    3898 ECB             : 
    3899 GIC          78 :         it = JsonbIteratorInit(&jb->root);
    3900 ECB             : 
    3901 CBC         339 :         while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE)
    3902                 :         {
    3903 GIC         267 :             skipNested = true;
    3904                 : 
    3905             267 :             if (r == WJB_ELEM)
    3906 ECB             :             {
    3907                 :                 JsObject    obj;
    3908                 : 
    3909 GIC         117 :                 if (v.type != jbvBinary ||
    3910             117 :                     !JsonContainerIsObject(v.val.binary.data))
    3911 UIC           0 :                     ereport(ERROR,
    3912 ECB             :                             (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    3913                 :                              errmsg("argument of %s must be an array of objects",
    3914                 :                                     funcname)));
    3915                 : 
    3916 CBC         117 :                 obj.is_json = false;
    3917 GIC         117 :                 obj.val.jsonb_cont = v.val.binary.data;
    3918                 : 
    3919             117 :                 populate_recordset_record(state, &obj);
    3920                 :             }
    3921 ECB             :         }
    3922 EUB             :     }
    3923                 : 
    3924                 :     /*
    3925                 :      * Note: we must copy the cached tupdesc because the executor will free
    3926                 :      * the passed-back setDesc, but we want to hang onto the cache in case
    3927                 :      * we're called again in the same query.
    3928 ECB             :      */
    3929 GIC         147 :     rsi->setResult = state->tuple_store;
    3930 CBC         147 :     rsi->setDesc = CreateTupleDescCopy(cache->c.io.composite.tupdesc);
    3931                 : 
    3932 GIC         147 :     PG_RETURN_NULL();
    3933 ECB             : }
    3934                 : 
    3935                 : static JsonParseErrorType
    3936 GIC         141 : populate_recordset_object_start(void *state)
    3937 ECB             : {
    3938 GIC         141 :     PopulateRecordsetState *_state = (PopulateRecordsetState *) state;
    3939 CBC         141 :     int         lex_level = _state->lex->lex_level;
    3940 ECB             :     HASHCTL     ctl;
    3941                 : 
    3942                 :     /* Reject object at top level: we must have an array at level 0 */
    3943 CBC         141 :     if (lex_level == 0)
    3944 UIC           0 :         ereport(ERROR,
    3945 ECB             :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    3946                 :                  errmsg("cannot call %s on an object",
    3947                 :                         _state->function_name)));
    3948                 : 
    3949                 :     /* Nested objects require no special processing */
    3950 GIC         141 :     if (lex_level > 1)
    3951 GNC          18 :         return JSON_SUCCESS;
    3952                 : 
    3953 ECB             :     /* Object at level 1: set up a new hash table for this object */
    3954 CBC         123 :     ctl.keysize = NAMEDATALEN;
    3955             123 :     ctl.entrysize = sizeof(JsonHashEntry);
    3956             123 :     ctl.hcxt = CurrentMemoryContext;
    3957             123 :     _state->json_hash = hash_create("json object hashtable",
    3958 ECB             :                                     100,
    3959                 :                                     &ctl,
    3960                 :                                     HASH_ELEM | HASH_STRINGS | HASH_CONTEXT);
    3961                 : 
    3962 GNC         123 :     return JSON_SUCCESS;
    3963                 : }
    3964 ECB             : 
    3965                 : static JsonParseErrorType
    3966 CBC         141 : populate_recordset_object_end(void *state)
    3967                 : {
    3968 GIC         141 :     PopulateRecordsetState *_state = (PopulateRecordsetState *) state;
    3969                 :     JsObject    obj;
    3970 ECB             : 
    3971                 :     /* Nested objects require no special processing */
    3972 GIC         141 :     if (_state->lex->lex_level > 1)
    3973 GNC          18 :         return JSON_SUCCESS;
    3974                 : 
    3975 GIC         123 :     obj.is_json = true;
    3976 CBC         123 :     obj.val.json_hash = _state->json_hash;
    3977 EUB             : 
    3978                 :     /* Otherwise, construct and return a tuple based on this level-1 object */
    3979 GIC         123 :     populate_recordset_record(_state, &obj);
    3980                 : 
    3981                 :     /* Done with hash for this object */
    3982 CBC         117 :     hash_destroy(_state->json_hash);
    3983 GIC         117 :     _state->json_hash = NULL;
    3984                 : 
    3985 GNC         117 :     return JSON_SUCCESS;
    3986 ECB             : }
    3987                 : 
    3988                 : static JsonParseErrorType
    3989 GIC         150 : populate_recordset_array_element_start(void *state, bool isnull)
    3990 ECB             : {
    3991 GIC         150 :     PopulateRecordsetState *_state = (PopulateRecordsetState *) state;
    3992                 : 
    3993             150 :     if (_state->lex->lex_level == 1 &&
    3994 CBC         123 :         _state->lex->token_type != JSON_TOKEN_OBJECT_START)
    3995 LBC           0 :         ereport(ERROR,
    3996 EUB             :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    3997                 :                  errmsg("argument of %s must be an array of objects",
    3998                 :                         _state->function_name)));
    3999                 : 
    4000 GNC         150 :     return JSON_SUCCESS;
    4001                 : }
    4002                 : 
    4003                 : static JsonParseErrorType
    4004 CBC          90 : populate_recordset_array_start(void *state)
    4005                 : {
    4006 ECB             :     /* nothing to do */
    4007 GNC          90 :     return JSON_SUCCESS;
    4008                 : }
    4009                 : 
    4010                 : static JsonParseErrorType
    4011 GIC         258 : populate_recordset_scalar(void *state, char *token, JsonTokenType tokentype)
    4012                 : {
    4013             258 :     PopulateRecordsetState *_state = (PopulateRecordsetState *) state;
    4014                 : 
    4015             258 :     if (_state->lex->lex_level == 0)
    4016 UIC           0 :         ereport(ERROR,
    4017 ECB             :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    4018                 :                  errmsg("cannot call %s on a scalar",
    4019                 :                         _state->function_name)));
    4020                 : 
    4021 GIC         258 :     if (_state->lex->lex_level == 2)
    4022             210 :         _state->saved_scalar = token;
    4023                 : 
    4024 GNC         258 :     return JSON_SUCCESS;
    4025                 : }
    4026 ECB             : 
    4027                 : static JsonParseErrorType
    4028 CBC         258 : populate_recordset_object_field_start(void *state, char *fname, bool isnull)
    4029 ECB             : {
    4030 GIC         258 :     PopulateRecordsetState *_state = (PopulateRecordsetState *) state;
    4031                 : 
    4032             258 :     if (_state->lex->lex_level > 2)
    4033 GNC          21 :         return JSON_SUCCESS;
    4034 EUB             : 
    4035 GIC         237 :     _state->saved_token_type = _state->lex->token_type;
    4036                 : 
    4037             237 :     if (_state->lex->token_type == JSON_TOKEN_ARRAY_START ||
    4038             228 :         _state->lex->token_type == JSON_TOKEN_OBJECT_START)
    4039                 :     {
    4040 CBC          27 :         _state->save_json_start = _state->lex->token_start;
    4041 ECB             :     }
    4042                 :     else
    4043                 :     {
    4044 CBC         210 :         _state->save_json_start = NULL;
    4045 ECB             :     }
    4046                 : 
    4047 GNC         237 :     return JSON_SUCCESS;
    4048 ECB             : }
    4049                 : 
    4050                 : static JsonParseErrorType
    4051 GIC         258 : populate_recordset_object_field_end(void *state, char *fname, bool isnull)
    4052                 : {
    4053             258 :     PopulateRecordsetState *_state = (PopulateRecordsetState *) state;
    4054 ECB             :     JsonHashEntry *hashentry;
    4055                 :     bool        found;
    4056                 : 
    4057                 :     /*
    4058                 :      * Ignore nested fields.
    4059                 :      */
    4060 CBC         258 :     if (_state->lex->lex_level > 2)
    4061 GNC          21 :         return JSON_SUCCESS;
    4062                 : 
    4063                 :     /*
    4064 ECB             :      * Ignore field names >= NAMEDATALEN - they can't match a record field.
    4065                 :      * (Note: without this test, the hash code would truncate the string at
    4066                 :      * NAMEDATALEN-1, and could then match against a similarly-truncated
    4067                 :      * record field name.  That would be a reasonable behavior, but this code
    4068                 :      * has previously insisted on exact equality, so we keep this behavior.)
    4069                 :      */
    4070 GIC         237 :     if (strlen(fname) >= NAMEDATALEN)
    4071 UNC           0 :         return JSON_SUCCESS;
    4072                 : 
    4073 GIC         237 :     hashentry = hash_search(_state->json_hash, fname, HASH_ENTER, &found);
    4074 ECB             : 
    4075                 :     /*
    4076                 :      * found being true indicates a duplicate. We don't do anything about
    4077                 :      * that, a later field with the same name overrides the earlier field.
    4078                 :      */
    4079                 : 
    4080 GIC         237 :     hashentry->type = _state->saved_token_type;
    4081 CBC         237 :     Assert(isnull == (hashentry->type == JSON_TOKEN_NULL));
    4082                 : 
    4083             237 :     if (_state->save_json_start != NULL)
    4084                 :     {
    4085              27 :         int         len = _state->lex->prev_token_terminator - _state->save_json_start;
    4086              27 :         char       *val = palloc((len + 1) * sizeof(char));
    4087 EUB             : 
    4088 GIC          27 :         memcpy(val, _state->save_json_start, len);
    4089              27 :         val[len] = '\0';
    4090              27 :         hashentry->val = val;
    4091                 :     }
    4092 ECB             :     else
    4093                 :     {
    4094                 :         /* must have had a scalar instead */
    4095 GIC         210 :         hashentry->val = _state->saved_scalar;
    4096 ECB             :     }
    4097                 : 
    4098 GNC         237 :     return JSON_SUCCESS;
    4099                 : }
    4100                 : 
    4101 ECB             : /*
    4102                 :  * Semantic actions for json_strip_nulls.
    4103                 :  *
    4104                 :  * Simply repeat the input on the output unless we encounter
    4105                 :  * a null object field. State for this is set when the field
    4106                 :  * is started and reset when the scalar action (which must be next)
    4107                 :  * is called.
    4108                 :  */
    4109                 : 
    4110                 : static JsonParseErrorType
    4111 GIC          18 : sn_object_start(void *state)
    4112                 : {
    4113              18 :     StripnullState *_state = (StripnullState *) state;
    4114                 : 
    4115 CBC          18 :     appendStringInfoCharMacro(_state->strval, '{');
    4116                 : 
    4117 GNC          18 :     return JSON_SUCCESS;
    4118 ECB             : }
    4119                 : 
    4120                 : static JsonParseErrorType
    4121 GIC          18 : sn_object_end(void *state)
    4122                 : {
    4123              18 :     StripnullState *_state = (StripnullState *) state;
    4124 ECB             : 
    4125 GIC          18 :     appendStringInfoCharMacro(_state->strval, '}');
    4126                 : 
    4127 GNC          18 :     return JSON_SUCCESS;
    4128 ECB             : }
    4129                 : 
    4130                 : static JsonParseErrorType
    4131 CBC           9 : sn_array_start(void *state)
    4132                 : {
    4133               9 :     StripnullState *_state = (StripnullState *) state;
    4134                 : 
    4135               9 :     appendStringInfoCharMacro(_state->strval, '[');
    4136                 : 
    4137 GNC           9 :     return JSON_SUCCESS;
    4138 ECB             : }
    4139                 : 
    4140                 : static JsonParseErrorType
    4141 GIC           9 : sn_array_end(void *state)
    4142                 : {
    4143               9 :     StripnullState *_state = (StripnullState *) state;
    4144 ECB             : 
    4145 GIC           9 :     appendStringInfoCharMacro(_state->strval, ']');
    4146                 : 
    4147 GNC           9 :     return JSON_SUCCESS;
    4148                 : }
    4149 ECB             : 
    4150                 : static JsonParseErrorType
    4151 GIC          39 : sn_object_field_start(void *state, char *fname, bool isnull)
    4152                 : {
    4153 CBC          39 :     StripnullState *_state = (StripnullState *) state;
    4154                 : 
    4155              39 :     if (isnull)
    4156                 :     {
    4157                 :         /*
    4158                 :          * The next thing must be a scalar or isnull couldn't be true, so
    4159                 :          * there is no danger of this state being carried down into a nested
    4160                 :          * object or array. The flag will be reset in the scalar action.
    4161                 :          */
    4162              15 :         _state->skip_next_null = true;
    4163 GNC          15 :         return JSON_SUCCESS;
    4164                 :     }
    4165                 : 
    4166 GIC          24 :     if (_state->strval->data[_state->strval->len - 1] != '{')
    4167              12 :         appendStringInfoCharMacro(_state->strval, ',');
    4168                 : 
    4169                 :     /*
    4170                 :      * Unfortunately we don't have the quoted and escaped string any more, so
    4171                 :      * we have to re-escape it.
    4172 ECB             :      */
    4173 GBC          24 :     escape_json(_state->strval, fname);
    4174                 : 
    4175 CBC          24 :     appendStringInfoCharMacro(_state->strval, ':');
    4176                 : 
    4177 GNC          24 :     return JSON_SUCCESS;
    4178                 : }
    4179                 : 
    4180                 : static JsonParseErrorType
    4181 GIC          33 : sn_array_element_start(void *state, bool isnull)
    4182                 : {
    4183              33 :     StripnullState *_state = (StripnullState *) state;
    4184 ECB             : 
    4185 CBC          33 :     if (_state->strval->data[_state->strval->len - 1] != '[')
    4186 GIC          24 :         appendStringInfoCharMacro(_state->strval, ',');
    4187                 : 
    4188 GNC          33 :     return JSON_SUCCESS;
    4189 ECB             : }
    4190                 : 
    4191                 : static JsonParseErrorType
    4192 CBC          66 : sn_scalar(void *state, char *token, JsonTokenType tokentype)
    4193                 : {
    4194              66 :     StripnullState *_state = (StripnullState *) state;
    4195 ECB             : 
    4196 CBC          66 :     if (_state->skip_next_null)
    4197                 :     {
    4198 GIC          15 :         Assert(tokentype == JSON_TOKEN_NULL);
    4199              15 :         _state->skip_next_null = false;
    4200 GNC          15 :         return JSON_SUCCESS;
    4201 ECB             :     }
    4202                 : 
    4203 GIC          51 :     if (tokentype == JSON_TOKEN_STRING)
    4204 CBC           3 :         escape_json(_state->strval, token);
    4205                 :     else
    4206 GIC          48 :         appendStringInfoString(_state->strval, token);
    4207                 : 
    4208 GNC          51 :     return JSON_SUCCESS;
    4209                 : }
    4210                 : 
    4211                 : /*
    4212                 :  * SQL function json_strip_nulls(json) -> json
    4213                 :  */
    4214                 : Datum
    4215 GIC          21 : json_strip_nulls(PG_FUNCTION_ARGS)
    4216                 : {
    4217              21 :     text       *json = PG_GETARG_TEXT_PP(0);
    4218                 :     StripnullState *state;
    4219 ECB             :     JsonLexContext *lex;
    4220                 :     JsonSemAction *sem;
    4221                 : 
    4222 GIC          21 :     lex = makeJsonLexContext(json, true);
    4223 CBC          21 :     state = palloc0(sizeof(StripnullState));
    4224 GIC          21 :     sem = palloc0(sizeof(JsonSemAction));
    4225 ECB             : 
    4226 GIC          21 :     state->strval = makeStringInfo();
    4227              21 :     state->skip_next_null = false;
    4228              21 :     state->lex = lex;
    4229 ECB             : 
    4230 GIC          21 :     sem->semstate = (void *) state;
    4231 CBC          21 :     sem->object_start = sn_object_start;
    4232 GIC          21 :     sem->object_end = sn_object_end;
    4233 CBC          21 :     sem->array_start = sn_array_start;
    4234 GIC          21 :     sem->array_end = sn_array_end;
    4235 CBC          21 :     sem->scalar = sn_scalar;
    4236 GIC          21 :     sem->array_element_start = sn_array_element_start;
    4237              21 :     sem->object_field_start = sn_object_field_start;
    4238                 : 
    4239 CBC          21 :     pg_parse_json_or_ereport(lex, sem);
    4240                 : 
    4241              21 :     PG_RETURN_TEXT_P(cstring_to_text_with_len(state->strval->data,
    4242                 :                                               state->strval->len));
    4243 ECB             : }
    4244                 : 
    4245                 : /*
    4246                 :  * SQL function jsonb_strip_nulls(jsonb) -> jsonb
    4247                 :  */
    4248                 : Datum
    4249 CBC          21 : jsonb_strip_nulls(PG_FUNCTION_ARGS)
    4250                 : {
    4251              21 :     Jsonb      *jb = PG_GETARG_JSONB_P(0);
    4252                 :     JsonbIterator *it;
    4253              21 :     JsonbParseState *parseState = NULL;
    4254 GIC          21 :     JsonbValue *res = NULL;
    4255 ECB             :     JsonbValue  v,
    4256                 :                 k;
    4257                 :     JsonbIteratorToken type;
    4258 GIC          21 :     bool        last_was_key = false;
    4259 ECB             : 
    4260 GIC          21 :     if (JB_ROOT_IS_SCALAR(jb))
    4261 CBC           9 :         PG_RETURN_POINTER(jb);
    4262                 : 
    4263              12 :     it = JsonbIteratorInit(&jb->root);
    4264                 : 
    4265 GIC         162 :     while ((type = JsonbIteratorNext(&it, &v, false)) != WJB_DONE)
    4266                 :     {
    4267             150 :         Assert(!(type == WJB_KEY && last_was_key));
    4268                 : 
    4269             150 :         if (type == WJB_KEY)
    4270 ECB             :         {
    4271                 :             /* stash the key until we know if it has a null value */
    4272 GIC          39 :             k = v;
    4273              39 :             last_was_key = true;
    4274 CBC          39 :             continue;
    4275 ECB             :         }
    4276                 : 
    4277 GIC         111 :         if (last_was_key)
    4278                 :         {
    4279                 :             /* if the last element was a key this one can't be */
    4280              39 :             last_was_key = false;
    4281 ECB             : 
    4282                 :             /* skip this field if value is null */
    4283 CBC          39 :             if (type == WJB_VALUE && v.type == jbvNull)
    4284 GIC          15 :                 continue;
    4285 ECB             : 
    4286                 :             /* otherwise, do a delayed push of the key */
    4287 GIC          24 :             (void) pushJsonbValue(&parseState, WJB_KEY, &k);
    4288                 :         }
    4289 ECB             : 
    4290 GIC          96 :         if (type == WJB_VALUE || type == WJB_ELEM)
    4291 CBC          42 :             res = pushJsonbValue(&parseState, type, &v);
    4292                 :         else
    4293              54 :             res = pushJsonbValue(&parseState, type, NULL);
    4294 ECB             :     }
    4295                 : 
    4296 CBC          12 :     Assert(res != NULL);
    4297                 : 
    4298 GIC          12 :     PG_RETURN_POINTER(JsonbValueToJsonb(res));
    4299                 : }
    4300 ECB             : 
    4301                 : /*
    4302                 :  * SQL function jsonb_pretty (jsonb)
    4303                 :  *
    4304                 :  * Pretty-printed text for the jsonb
    4305                 :  */
    4306                 : Datum
    4307 CBC          18 : jsonb_pretty(PG_FUNCTION_ARGS)
    4308 ECB             : {
    4309 GIC          18 :     Jsonb      *jb = PG_GETARG_JSONB_P(0);
    4310              18 :     StringInfo  str = makeStringInfo();
    4311 ECB             : 
    4312 CBC          18 :     JsonbToCStringIndent(str, &jb->root, VARSIZE(jb));
    4313                 : 
    4314              18 :     PG_RETURN_TEXT_P(cstring_to_text_with_len(str->data, str->len));
    4315                 : }
    4316 ECB             : 
    4317                 : /*
    4318                 :  * SQL function jsonb_concat (jsonb, jsonb)
    4319                 :  *
    4320                 :  * function for || operator
    4321                 :  */
    4322                 : Datum
    4323 CBC         189 : jsonb_concat(PG_FUNCTION_ARGS)
    4324                 : {
    4325             189 :     Jsonb      *jb1 = PG_GETARG_JSONB_P(0);
    4326 GIC         189 :     Jsonb      *jb2 = PG_GETARG_JSONB_P(1);
    4327             189 :     JsonbParseState *state = NULL;
    4328                 :     JsonbValue *res;
    4329                 :     JsonbIterator *it1,
    4330 ECB             :                *it2;
    4331                 : 
    4332                 :     /*
    4333                 :      * If one of the jsonb is empty, just return the other if it's not scalar
    4334                 :      * and both are of the same kind.  If it's a scalar or they are of
    4335                 :      * different kinds we need to perform the concatenation even if one is
    4336                 :      * empty.
    4337                 :      */
    4338 CBC         189 :     if (JB_ROOT_IS_OBJECT(jb1) == JB_ROOT_IS_OBJECT(jb2))
    4339 ECB             :     {
    4340 CBC         147 :         if (JB_ROOT_COUNT(jb1) == 0 && !JB_ROOT_IS_SCALAR(jb2))
    4341              99 :             PG_RETURN_JSONB_P(jb2);
    4342              48 :         else if (JB_ROOT_COUNT(jb2) == 0 && !JB_ROOT_IS_SCALAR(jb1))
    4343               6 :             PG_RETURN_JSONB_P(jb1);
    4344 ECB             :     }
    4345                 : 
    4346 GIC          84 :     it1 = JsonbIteratorInit(&jb1->root);
    4347 CBC          84 :     it2 = JsonbIteratorInit(&jb2->root);
    4348                 : 
    4349              84 :     res = IteratorConcat(&it1, &it2, &state);
    4350                 : 
    4351 GIC          84 :     Assert(res != NULL);
    4352                 : 
    4353              84 :     PG_RETURN_JSONB_P(JsonbValueToJsonb(res));
    4354                 : }
    4355                 : 
    4356                 : 
    4357 ECB             : /*
    4358                 :  * SQL function jsonb_delete (jsonb, text)
    4359                 :  *
    4360                 :  * return a copy of the jsonb with the indicated item
    4361                 :  * removed.
    4362                 :  */
    4363                 : Datum
    4364 GIC          90 : jsonb_delete(PG_FUNCTION_ARGS)
    4365                 : {
    4366 CBC          90 :     Jsonb      *in = PG_GETARG_JSONB_P(0);
    4367 GIC          90 :     text       *key = PG_GETARG_TEXT_PP(1);
    4368 CBC          90 :     char       *keyptr = VARDATA_ANY(key);
    4369              90 :     int         keylen = VARSIZE_ANY_EXHDR(key);
    4370 GIC          90 :     JsonbParseState *state = NULL;
    4371 ECB             :     JsonbIterator *it;
    4372                 :     JsonbValue  v,
    4373 CBC          90 :                *res = NULL;
    4374 GIC          90 :     bool        skipNested = false;
    4375 ECB             :     JsonbIteratorToken r;
    4376                 : 
    4377 CBC          90 :     if (JB_ROOT_IS_SCALAR(in))
    4378 GIC           3 :         ereport(ERROR,
    4379                 :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    4380 ECB             :                  errmsg("cannot delete from scalar")));
    4381                 : 
    4382 CBC          87 :     if (JB_ROOT_COUNT(in) == 0)
    4383 GIC           6 :         PG_RETURN_JSONB_P(in);
    4384                 : 
    4385 CBC          81 :     it = JsonbIteratorInit(&in->root);
    4386                 : 
    4387 GIC        1074 :     while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE)
    4388 ECB             :     {
    4389 GIC         993 :         skipNested = true;
    4390                 : 
    4391 CBC         993 :         if ((r == WJB_ELEM || r == WJB_KEY) &&
    4392             453 :             (v.type == jbvString && keylen == v.val.string.len &&
    4393 GIC         147 :              memcmp(keyptr, v.val.string.val, keylen) == 0))
    4394                 :         {
    4395 ECB             :             /* skip corresponding value as well */
    4396 GIC          75 :             if (r == WJB_KEY)
    4397              75 :                 (void) JsonbIteratorNext(&it, &v, true);
    4398 ECB             : 
    4399 CBC          75 :             continue;
    4400                 :         }
    4401 ECB             : 
    4402 GIC         918 :         res = pushJsonbValue(&state, r, r < WJB_BEGIN_ARRAY ? &v : NULL);
    4403                 :     }
    4404 ECB             : 
    4405 GIC          81 :     Assert(res != NULL);
    4406 ECB             : 
    4407 GIC          81 :     PG_RETURN_JSONB_P(JsonbValueToJsonb(res));
    4408                 : }
    4409                 : 
    4410                 : /*
    4411                 :  * SQL function jsonb_delete (jsonb, variadic text[])
    4412                 :  *
    4413                 :  * return a copy of the jsonb with the indicated items
    4414                 :  * removed.
    4415 ECB             :  */
    4416                 : Datum
    4417 CBC           9 : jsonb_delete_array(PG_FUNCTION_ARGS)
    4418 ECB             : {
    4419 GIC           9 :     Jsonb      *in = PG_GETARG_JSONB_P(0);
    4420 CBC           9 :     ArrayType  *keys = PG_GETARG_ARRAYTYPE_P(1);
    4421                 :     Datum      *keys_elems;
    4422 ECB             :     bool       *keys_nulls;
    4423                 :     int         keys_len;
    4424 GIC           9 :     JsonbParseState *state = NULL;
    4425                 :     JsonbIterator *it;
    4426                 :     JsonbValue  v,
    4427               9 :                *res = NULL;
    4428               9 :     bool        skipNested = false;
    4429                 :     JsonbIteratorToken r;
    4430                 : 
    4431 CBC           9 :     if (ARR_NDIM(keys) > 1)
    4432 UIC           0 :         ereport(ERROR,
    4433 ECB             :                 (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
    4434                 :                  errmsg("wrong number of array subscripts")));
    4435                 : 
    4436 GIC           9 :     if (JB_ROOT_IS_SCALAR(in))
    4437 UIC           0 :         ereport(ERROR,
    4438                 :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    4439                 :                  errmsg("cannot delete from scalar")));
    4440                 : 
    4441 GIC           9 :     if (JB_ROOT_COUNT(in) == 0)
    4442 UIC           0 :         PG_RETURN_JSONB_P(in);
    4443                 : 
    4444 GNC           9 :     deconstruct_array_builtin(keys, TEXTOID, &keys_elems, &keys_nulls, &keys_len);
    4445 ECB             : 
    4446 GIC           9 :     if (keys_len == 0)
    4447 CBC           3 :         PG_RETURN_JSONB_P(in);
    4448 ECB             : 
    4449 CBC           6 :     it = JsonbIteratorInit(&in->root);
    4450 ECB             : 
    4451 GIC          45 :     while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE)
    4452                 :     {
    4453 CBC          39 :         skipNested = true;
    4454 ECB             : 
    4455 GIC          39 :         if ((r == WJB_ELEM || r == WJB_KEY) && v.type == jbvString)
    4456 ECB             :         {
    4457                 :             int         i;
    4458 CBC          18 :             bool        found = false;
    4459                 : 
    4460              33 :             for (i = 0; i < keys_len; i++)
    4461                 :             {
    4462                 :                 char       *keyptr;
    4463                 :                 int         keylen;
    4464                 : 
    4465 GIC          24 :                 if (keys_nulls[i])
    4466 UIC           0 :                     continue;
    4467                 : 
    4468                 :                 /* We rely on the array elements not being toasted */
    4469 GIC          24 :                 keyptr = VARDATA_ANY(keys_elems[i]);
    4470              24 :                 keylen = VARSIZE_ANY_EXHDR(keys_elems[i]);
    4471 CBC          24 :                 if (keylen == v.val.string.len &&
    4472 GIC          24 :                     memcmp(keyptr, v.val.string.val, keylen) == 0)
    4473 ECB             :                 {
    4474 CBC           9 :                     found = true;
    4475               9 :                     break;
    4476 ECB             :                 }
    4477                 :             }
    4478 GIC          18 :             if (found)
    4479                 :             {
    4480 ECB             :                 /* skip corresponding value as well */
    4481 CBC           9 :                 if (r == WJB_KEY)
    4482 GIC           9 :                     (void) JsonbIteratorNext(&it, &v, true);
    4483                 : 
    4484 CBC           9 :                 continue;
    4485 ECB             :             }
    4486                 :         }
    4487                 : 
    4488 GIC          30 :         res = pushJsonbValue(&state, r, r < WJB_BEGIN_ARRAY ? &v : NULL);
    4489 ECB             :     }
    4490                 : 
    4491 GIC           6 :     Assert(res != NULL);
    4492 ECB             : 
    4493 GIC           6 :     PG_RETURN_JSONB_P(JsonbValueToJsonb(res));
    4494 ECB             : }
    4495                 : 
    4496                 : /*
    4497                 :  * SQL function jsonb_delete (jsonb, int)
    4498                 :  *
    4499                 :  * return a copy of the jsonb with the indicated item
    4500                 :  * removed. Negative int means count back from the
    4501                 :  * end of the items.
    4502                 :  */
    4503                 : Datum
    4504 CBC         129 : jsonb_delete_idx(PG_FUNCTION_ARGS)
    4505                 : {
    4506             129 :     Jsonb      *in = PG_GETARG_JSONB_P(0);
    4507 GIC         129 :     int         idx = PG_GETARG_INT32(1);
    4508             129 :     JsonbParseState *state = NULL;
    4509 ECB             :     JsonbIterator *it;
    4510 GIC         129 :     uint32      i = 0,
    4511                 :                 n;
    4512 ECB             :     JsonbValue  v,
    4513 GIC         129 :                *res = NULL;
    4514 ECB             :     JsonbIteratorToken r;
    4515                 : 
    4516 GIC         129 :     if (JB_ROOT_IS_SCALAR(in))
    4517               3 :         ereport(ERROR,
    4518                 :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    4519                 :                  errmsg("cannot delete from scalar")));
    4520                 : 
    4521             126 :     if (JB_ROOT_IS_OBJECT(in))
    4522               3 :         ereport(ERROR,
    4523                 :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    4524 ECB             :                  errmsg("cannot delete from object using integer index")));
    4525                 : 
    4526 CBC         123 :     if (JB_ROOT_COUNT(in) == 0)
    4527               3 :         PG_RETURN_JSONB_P(in);
    4528                 : 
    4529 GIC         120 :     it = JsonbIteratorInit(&in->root);
    4530                 : 
    4531 CBC         120 :     r = JsonbIteratorNext(&it, &v, false);
    4532 GIC         120 :     Assert(r == WJB_BEGIN_ARRAY);
    4533             120 :     n = v.val.array.nElems;
    4534 ECB             : 
    4535 CBC         120 :     if (idx < 0)
    4536                 :     {
    4537 GIC          12 :         if (-idx > n)
    4538 CBC           3 :             idx = n;
    4539 EUB             :         else
    4540 GIC           9 :             idx = n + idx;
    4541                 :     }
    4542                 : 
    4543 CBC         120 :     if (idx >= n)
    4544 GBC           6 :         PG_RETURN_JSONB_P(in);
    4545                 : 
    4546 GIC         114 :     pushJsonbValue(&state, r, NULL);
    4547                 : 
    4548 CBC         378 :     while ((r = JsonbIteratorNext(&it, &v, true)) != WJB_DONE)
    4549 EUB             :     {
    4550 GIC         264 :         if (r == WJB_ELEM)
    4551 ECB             :         {
    4552 GIC         150 :             if (i++ == idx)
    4553 CBC         114 :                 continue;
    4554 ECB             :         }
    4555                 : 
    4556 CBC         150 :         res = pushJsonbValue(&state, r, r < WJB_BEGIN_ARRAY ? &v : NULL);
    4557                 :     }
    4558 ECB             : 
    4559 GIC         114 :     Assert(res != NULL);
    4560 ECB             : 
    4561 GIC         114 :     PG_RETURN_JSONB_P(JsonbValueToJsonb(res));
    4562 ECB             : }
    4563                 : 
    4564                 : /*
    4565                 :  * SQL function jsonb_set(jsonb, text[], jsonb, boolean)
    4566                 :  */
    4567                 : Datum
    4568 GIC         144 : jsonb_set(PG_FUNCTION_ARGS)
    4569                 : {
    4570             144 :     Jsonb      *in = PG_GETARG_JSONB_P(0);
    4571             144 :     ArrayType  *path = PG_GETARG_ARRAYTYPE_P(1);
    4572 CBC         144 :     Jsonb      *newjsonb = PG_GETARG_JSONB_P(2);
    4573 EUB             :     JsonbValue  newval;
    4574 GIC         144 :     bool        create = PG_GETARG_BOOL(3);
    4575             144 :     JsonbValue *res = NULL;
    4576 ECB             :     Datum      *path_elems;
    4577                 :     bool       *path_nulls;
    4578                 :     int         path_len;
    4579                 :     JsonbIterator *it;
    4580 GIC         144 :     JsonbParseState *st = NULL;
    4581 ECB             : 
    4582 CBC         144 :     JsonbToJsonbValue(newjsonb, &newval);
    4583                 : 
    4584 GIC         144 :     if (ARR_NDIM(path) > 1)
    4585 LBC           0 :         ereport(ERROR,
    4586                 :                 (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
    4587                 :                  errmsg("wrong number of array subscripts")));
    4588 ECB             : 
    4589 CBC         144 :     if (JB_ROOT_IS_SCALAR(in))
    4590 GIC           3 :         ereport(ERROR,
    4591 ECB             :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    4592                 :                  errmsg("cannot set path in scalar")));
    4593                 : 
    4594 GIC         141 :     if (JB_ROOT_COUNT(in) == 0 && !create)
    4595 CBC           6 :         PG_RETURN_JSONB_P(in);
    4596                 : 
    4597 GNC         135 :     deconstruct_array_builtin(path, TEXTOID, &path_elems, &path_nulls, &path_len);
    4598                 : 
    4599 CBC         135 :     if (path_len == 0)
    4600 UIC           0 :         PG_RETURN_JSONB_P(in);
    4601                 : 
    4602 GIC         135 :     it = JsonbIteratorInit(&in->root);
    4603                 : 
    4604             135 :     res = setPath(&it, path_elems, path_nulls, path_len, &st,
    4605                 :                   0, &newval, create ? JB_PATH_CREATE : JB_PATH_REPLACE);
    4606                 : 
    4607             120 :     Assert(res != NULL);
    4608                 : 
    4609             120 :     PG_RETURN_JSONB_P(JsonbValueToJsonb(res));
    4610 ECB             : }
    4611                 : 
    4612                 : 
    4613                 : /*
    4614                 :  * SQL function jsonb_set_lax(jsonb, text[], jsonb, boolean, text)
    4615                 :  */
    4616                 : Datum
    4617 GIC          30 : jsonb_set_lax(PG_FUNCTION_ARGS)
    4618                 : {
    4619 ECB             :     /* Jsonb       *in = PG_GETARG_JSONB_P(0); */
    4620                 :     /* ArrayType  *path = PG_GETARG_ARRAYTYPE_P(1); */
    4621                 :     /* Jsonb      *newval = PG_GETARG_JSONB_P(2); */
    4622                 :     /* bool     create = PG_GETARG_BOOL(3); */
    4623                 :     text       *handle_null;
    4624                 :     char       *handle_val;
    4625                 : 
    4626 GIC          30 :     if (PG_ARGISNULL(0) || PG_ARGISNULL(1) || PG_ARGISNULL(3))
    4627 LBC           0 :         PG_RETURN_NULL();
    4628 ECB             : 
    4629                 :     /* could happen if they pass in an explicit NULL */
    4630 GIC          30 :     if (PG_ARGISNULL(4))
    4631               3 :         ereport(ERROR,
    4632 ECB             :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    4633                 :                  errmsg("null_value_treatment must be \"delete_key\", \"return_target\", \"use_json_null\", or \"raise_exception\"")));
    4634                 : 
    4635                 :     /* if the new value isn't an SQL NULL just call jsonb_set */
    4636 GIC          27 :     if (!PG_ARGISNULL(2))
    4637 CBC           6 :         return jsonb_set(fcinfo);
    4638 ECB             : 
    4639 CBC          21 :     handle_null = PG_GETARG_TEXT_P(4);
    4640 GIC          21 :     handle_val = text_to_cstring(handle_null);
    4641 ECB             : 
    4642 GIC          21 :     if (strcmp(handle_val, "raise_exception") == 0)
    4643 ECB             :     {
    4644 CBC           3 :         ereport(ERROR,
    4645                 :                 (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
    4646 ECB             :                  errmsg("JSON value must not be null"),
    4647                 :                  errdetail("Exception was raised because null_value_treatment is \"raise_exception\"."),
    4648                 :                  errhint("To avoid, either change the null_value_treatment argument or ensure that an SQL NULL is not passed.")));
    4649                 :         return (Datum) 0;       /* silence stupider compilers */
    4650                 :     }
    4651 GIC          18 :     else if (strcmp(handle_val, "use_json_null") == 0)
    4652 ECB             :     {
    4653                 :         Datum       newval;
    4654                 : 
    4655 GIC           9 :         newval = DirectFunctionCall1(jsonb_in, CStringGetDatum("null"));
    4656 ECB             : 
    4657 GIC           9 :         fcinfo->args[2].value = newval;
    4658 CBC           9 :         fcinfo->args[2].isnull = false;
    4659               9 :         return jsonb_set(fcinfo);
    4660                 :     }
    4661 GIC           9 :     else if (strcmp(handle_val, "delete_key") == 0)
    4662 ECB             :     {
    4663 GIC           3 :         return jsonb_delete_path(fcinfo);
    4664                 :     }
    4665 CBC           6 :     else if (strcmp(handle_val, "return_target") == 0)
    4666                 :     {
    4667               3 :         Jsonb      *in = PG_GETARG_JSONB_P(0);
    4668                 : 
    4669 GIC           3 :         PG_RETURN_JSONB_P(in);
    4670                 :     }
    4671                 :     else
    4672                 :     {
    4673               3 :         ereport(ERROR,
    4674 ECB             :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    4675                 :                  errmsg("null_value_treatment must be \"delete_key\", \"return_target\", \"use_json_null\", or \"raise_exception\"")));
    4676                 :         return (Datum) 0;       /* silence stupider compilers */
    4677                 :     }
    4678                 : }
    4679                 : 
    4680                 : /*
    4681                 :  * SQL function jsonb_delete_path(jsonb, text[])
    4682                 :  */
    4683                 : Datum
    4684 GIC          45 : jsonb_delete_path(PG_FUNCTION_ARGS)
    4685                 : {
    4686 CBC          45 :     Jsonb      *in = PG_GETARG_JSONB_P(0);
    4687 GIC          45 :     ArrayType  *path = PG_GETARG_ARRAYTYPE_P(1);
    4688 CBC          45 :     JsonbValue *res = NULL;
    4689                 :     Datum      *path_elems;
    4690 ECB             :     bool       *path_nulls;
    4691 EUB             :     int         path_len;
    4692                 :     JsonbIterator *it;
    4693 GIC          45 :     JsonbParseState *st = NULL;
    4694                 : 
    4695 CBC          45 :     if (ARR_NDIM(path) > 1)
    4696 LBC           0 :         ereport(ERROR,
    4697                 :                 (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
    4698                 :                  errmsg("wrong number of array subscripts")));
    4699                 : 
    4700 CBC          45 :     if (JB_ROOT_IS_SCALAR(in))
    4701               3 :         ereport(ERROR,
    4702                 :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    4703 ECB             :                  errmsg("cannot delete path in scalar")));
    4704                 : 
    4705 CBC          42 :     if (JB_ROOT_COUNT(in) == 0)
    4706 GBC           6 :         PG_RETURN_JSONB_P(in);
    4707                 : 
    4708 GNC          36 :     deconstruct_array_builtin(path, TEXTOID, &path_elems, &path_nulls, &path_len);
    4709 ECB             : 
    4710 GIC          36 :     if (path_len == 0)
    4711 UIC           0 :         PG_RETURN_JSONB_P(in);
    4712 ECB             : 
    4713 GIC          36 :     it = JsonbIteratorInit(&in->root);
    4714 ECB             : 
    4715 GIC          36 :     res = setPath(&it, path_elems, path_nulls, path_len, &st,
    4716                 :                   0, NULL, JB_PATH_DELETE);
    4717                 : 
    4718              33 :     Assert(res != NULL);
    4719                 : 
    4720              33 :     PG_RETURN_JSONB_P(JsonbValueToJsonb(res));
    4721                 : }
    4722 ECB             : 
    4723                 : /*
    4724                 :  * SQL function jsonb_insert(jsonb, text[], jsonb, boolean)
    4725                 :  */
    4726                 : Datum
    4727 GIC          66 : jsonb_insert(PG_FUNCTION_ARGS)
    4728                 : {
    4729              66 :     Jsonb      *in = PG_GETARG_JSONB_P(0);
    4730              66 :     ArrayType  *path = PG_GETARG_ARRAYTYPE_P(1);
    4731 CBC          66 :     Jsonb      *newjsonb = PG_GETARG_JSONB_P(2);
    4732 EUB             :     JsonbValue  newval;
    4733 GIC          66 :     bool        after = PG_GETARG_BOOL(3);
    4734              66 :     JsonbValue *res = NULL;
    4735 ECB             :     Datum      *path_elems;
    4736                 :     bool       *path_nulls;
    4737                 :     int         path_len;
    4738                 :     JsonbIterator *it;
    4739 GIC          66 :     JsonbParseState *st = NULL;
    4740                 : 
    4741 CBC          66 :     JsonbToJsonbValue(newjsonb, &newval);
    4742 ECB             : 
    4743 GIC          66 :     if (ARR_NDIM(path) > 1)
    4744 LBC           0 :         ereport(ERROR,
    4745 ECB             :                 (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
    4746                 :                  errmsg("wrong number of array subscripts")));
    4747                 : 
    4748 GIC          66 :     if (JB_ROOT_IS_SCALAR(in))
    4749 LBC           0 :         ereport(ERROR,
    4750                 :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    4751                 :                  errmsg("cannot set path in scalar")));
    4752                 : 
    4753 GNC          66 :     deconstruct_array_builtin(path, TEXTOID, &path_elems, &path_nulls, &path_len);
    4754                 : 
    4755 CBC          66 :     if (path_len == 0)
    4756 UIC           0 :         PG_RETURN_JSONB_P(in);
    4757                 : 
    4758 GIC          66 :     it = JsonbIteratorInit(&in->root);
    4759 ECB             : 
    4760 GIC          66 :     res = setPath(&it, path_elems, path_nulls, path_len, &st, 0, &newval,
    4761 ECB             :                   after ? JB_PATH_INSERT_AFTER : JB_PATH_INSERT_BEFORE);
    4762                 : 
    4763 CBC          60 :     Assert(res != NULL);
    4764                 : 
    4765              60 :     PG_RETURN_JSONB_P(JsonbValueToJsonb(res));
    4766                 : }
    4767 ECB             : 
    4768                 : /*
    4769                 :  * Iterate over all jsonb objects and merge them into one.
    4770                 :  * The logic of this function copied from the same hstore function,
    4771                 :  * except the case, when it1 & it2 represents jbvObject.
    4772                 :  * In that case we just append the content of it2 to it1 without any
    4773                 :  * verifications.
    4774                 :  */
    4775                 : static JsonbValue *
    4776 GIC          84 : IteratorConcat(JsonbIterator **it1, JsonbIterator **it2,
    4777 ECB             :                JsonbParseState **state)
    4778                 : {
    4779                 :     JsonbValue  v1,
    4780                 :                 v2,
    4781 GIC          84 :                *res = NULL;
    4782                 :     JsonbIteratorToken r1,
    4783                 :                 r2,
    4784                 :                 rk1,
    4785                 :                 rk2;
    4786                 : 
    4787              84 :     rk1 = JsonbIteratorNext(it1, &v1, false);
    4788 CBC          84 :     rk2 = JsonbIteratorNext(it2, &v2, false);
    4789                 : 
    4790 ECB             :     /*
    4791                 :      * JsonbIteratorNext reports raw scalars as if they were single-element
    4792                 :      * arrays; hence we only need consider "object" and "array" cases here.
    4793                 :      */
    4794 GIC          84 :     if (rk1 == WJB_BEGIN_OBJECT && rk2 == WJB_BEGIN_OBJECT)
    4795                 :     {
    4796                 :         /*
    4797 ECB             :          * Both inputs are objects.
    4798                 :          *
    4799                 :          * Append all the tokens from v1 to res, except last WJB_END_OBJECT
    4800 EUB             :          * (because res will not be finished yet).
    4801                 :          */
    4802 GIC          15 :         pushJsonbValue(state, rk1, NULL);
    4803              87 :         while ((r1 = JsonbIteratorNext(it1, &v1, true)) != WJB_END_OBJECT)
    4804 CBC          72 :             pushJsonbValue(state, r1, &v1);
    4805 ECB             : 
    4806                 :         /*
    4807                 :          * Append all the tokens from v2 to res, including last WJB_END_OBJECT
    4808                 :          * (the concatenation will be completed).  Any duplicate keys will
    4809                 :          * automatically override the value from the first object.
    4810                 :          */
    4811 GIC          78 :         while ((r2 = JsonbIteratorNext(it2, &v2, true)) != WJB_DONE)
    4812 CBC          63 :             res = pushJsonbValue(state, r2, r2 != WJB_END_OBJECT ? &v2 : NULL);
    4813                 :     }
    4814              69 :     else if (rk1 == WJB_BEGIN_ARRAY && rk2 == WJB_BEGIN_ARRAY)
    4815 EUB             :     {
    4816                 :         /*
    4817 ECB             :          * Both inputs are arrays.
    4818                 :          */
    4819 CBC          27 :         pushJsonbValue(state, rk1, NULL);
    4820                 : 
    4821 GIC          60 :         while ((r1 = JsonbIteratorNext(it1, &v1, true)) != WJB_END_ARRAY)
    4822 ECB             :         {
    4823 GIC          33 :             Assert(r1 == WJB_ELEM);
    4824 CBC          33 :             pushJsonbValue(state, r1, &v1);
    4825                 :         }
    4826                 : 
    4827 GIC          60 :         while ((r2 = JsonbIteratorNext(it2, &v2, true)) != WJB_END_ARRAY)
    4828                 :         {
    4829              33 :             Assert(r2 == WJB_ELEM);
    4830              33 :             pushJsonbValue(state, WJB_ELEM, &v2);
    4831 ECB             :         }
    4832                 : 
    4833 CBC          27 :         res = pushJsonbValue(state, WJB_END_ARRAY, NULL /* signal to sort */ );
    4834 ECB             :     }
    4835 CBC          42 :     else if (rk1 == WJB_BEGIN_OBJECT)
    4836                 :     {
    4837 ECB             :         /*
    4838                 :          * We have object || array.
    4839                 :          */
    4840 GIC           9 :         Assert(rk2 == WJB_BEGIN_ARRAY);
    4841                 : 
    4842               9 :         pushJsonbValue(state, WJB_BEGIN_ARRAY, NULL);
    4843 ECB             : 
    4844 GIC           9 :         pushJsonbValue(state, WJB_BEGIN_OBJECT, NULL);
    4845 CBC          36 :         while ((r1 = JsonbIteratorNext(it1, &v1, true)) != WJB_DONE)
    4846 GIC          27 :             pushJsonbValue(state, r1, r1 != WJB_END_OBJECT ? &v1 : NULL);
    4847 ECB             : 
    4848 GBC          27 :         while ((r2 = JsonbIteratorNext(it2, &v2, true)) != WJB_DONE)
    4849 GIC          18 :             res = pushJsonbValue(state, r2, r2 != WJB_END_ARRAY ? &v2 : NULL);
    4850                 :     }
    4851                 :     else
    4852 ECB             :     {
    4853 EUB             :         /*
    4854                 :          * We have array || object.
    4855                 :          */
    4856 GIC          33 :         Assert(rk1 == WJB_BEGIN_ARRAY);
    4857 CBC          33 :         Assert(rk2 == WJB_BEGIN_OBJECT);
    4858                 : 
    4859              33 :         pushJsonbValue(state, WJB_BEGIN_ARRAY, NULL);
    4860 EUB             : 
    4861 GIC          48 :         while ((r1 = JsonbIteratorNext(it1, &v1, true)) != WJB_END_ARRAY)
    4862 CBC          15 :             pushJsonbValue(state, r1, &v1);
    4863                 : 
    4864              33 :         pushJsonbValue(state, WJB_BEGIN_OBJECT, NULL);
    4865 GIC         426 :         while ((r2 = JsonbIteratorNext(it2, &v2, true)) != WJB_DONE)
    4866             393 :             pushJsonbValue(state, r2, r2 != WJB_END_OBJECT ? &v2 : NULL);
    4867 ECB             : 
    4868 GIC          33 :         res = pushJsonbValue(state, WJB_END_ARRAY, NULL);
    4869 ECB             :     }
    4870                 : 
    4871 GIC          84 :     return res;
    4872                 : }
    4873                 : 
    4874                 : /*
    4875                 :  * Do most of the heavy work for jsonb_set/jsonb_insert
    4876                 :  *
    4877                 :  * If JB_PATH_DELETE bit is set in op_type, the element is to be removed.
    4878                 :  *
    4879                 :  * If any bit mentioned in JB_PATH_CREATE_OR_INSERT is set in op_type,
    4880 ECB             :  * we create the new value if the key or array index does not exist.
    4881                 :  *
    4882                 :  * Bits JB_PATH_INSERT_BEFORE and JB_PATH_INSERT_AFTER in op_type
    4883                 :  * behave as JB_PATH_CREATE if new value is inserted in JsonbObject.
    4884                 :  *
    4885                 :  * If JB_PATH_FILL_GAPS bit is set, this will change an assignment logic in
    4886                 :  * case if target is an array. The assignment index will not be restricted by
    4887                 :  * number of elements in the array, and if there are any empty slots between
    4888                 :  * last element of the array and a new one they will be filled with nulls. If
    4889                 :  * the index is negative, it still will be considered an index from the end
    4890                 :  * of the array. Of a part of the path is not present and this part is more
    4891                 :  * than just one last element, this flag will instruct to create the whole
    4892                 :  * chain of corresponding objects and insert the value.
    4893                 :  *
    4894                 :  * JB_PATH_CONSISTENT_POSITION for an array indicates that the caller wants to
    4895                 :  * keep values with fixed indices. Indices for existing elements could be
    4896                 :  * changed (shifted forward) in case if the array is prepended with a new value
    4897                 :  * and a negative index out of the range, so this behavior will be prevented
    4898                 :  * and return an error.
    4899                 :  *
    4900                 :  * All path elements before the last must already exist
    4901                 :  * whatever bits in op_type are set, or nothing is done.
    4902                 :  */
    4903                 : static JsonbValue *
    4904 GIC         657 : setPath(JsonbIterator **it, Datum *path_elems,
    4905                 :         bool *path_nulls, int path_len,
    4906 ECB             :         JsonbParseState **st, int level, JsonbValue *newval, int op_type)
    4907                 : {
    4908                 :     JsonbValue  v;
    4909                 :     JsonbIteratorToken r;
    4910                 :     JsonbValue *res;
    4911                 : 
    4912 GIC         657 :     check_stack_depth();
    4913                 : 
    4914             657 :     if (path_nulls[level])
    4915 CBC           9 :         ereport(ERROR,
    4916 ECB             :                 (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
    4917                 :                  errmsg("path element at position %d is null",
    4918                 :                         level + 1)));
    4919                 : 
    4920 GIC         648 :     r = JsonbIteratorNext(it, &v, false);
    4921                 : 
    4922             648 :     switch (r)
    4923 ECB             :     {
    4924 GIC         189 :         case WJB_BEGIN_ARRAY:
    4925 ECB             : 
    4926                 :             /*
    4927                 :              * If instructed complain about attempts to replace within a raw
    4928                 :              * scalar value. This happens even when current level is equal to
    4929                 :              * path_len, because the last path key should also correspond to
    4930                 :              * an object or an array, not raw scalar.
    4931                 :              */
    4932 GIC         189 :             if ((op_type & JB_PATH_FILL_GAPS) && (level <= path_len - 1) &&
    4933 CBC          45 :                 v.val.array.rawScalar)
    4934               6 :                 ereport(ERROR,
    4935                 :                         (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    4936                 :                          errmsg("cannot replace existing key"),
    4937 ECB             :                          errdetail("The path assumes key is a composite object, "
    4938                 :                                    "but it is a scalar value.")));
    4939                 : 
    4940 GIC         183 :             (void) pushJsonbValue(st, r, NULL);
    4941             183 :             setPathArray(it, path_elems, path_nulls, path_len, st, level,
    4942             183 :                          newval, v.val.array.nElems, op_type);
    4943             171 :             r = JsonbIteratorNext(it, &v, false);
    4944 CBC         171 :             Assert(r == WJB_END_ARRAY);
    4945 GIC         171 :             res = pushJsonbValue(st, r, NULL);
    4946 CBC         171 :             break;
    4947 GIC         444 :         case WJB_BEGIN_OBJECT:
    4948 CBC         444 :             (void) pushJsonbValue(st, r, NULL);
    4949             444 :             setPathObject(it, path_elems, path_nulls, path_len, st, level,
    4950             444 :                           newval, v.val.object.nPairs, op_type);
    4951 GIC         393 :             r = JsonbIteratorNext(it, &v, true);
    4952 CBC         393 :             Assert(r == WJB_END_OBJECT);
    4953             393 :             res = pushJsonbValue(st, r, NULL);
    4954 GIC         393 :             break;
    4955              15 :         case WJB_ELEM:
    4956                 :         case WJB_VALUE:
    4957                 : 
    4958                 :             /*
    4959                 :              * If instructed complain about attempts to replace within a
    4960 ECB             :              * scalar value. This happens even when current level is equal to
    4961                 :              * path_len, because the last path key should also correspond to
    4962                 :              * an object or an array, not an element or value.
    4963                 :              */
    4964 GIC          15 :             if ((op_type & JB_PATH_FILL_GAPS) && (level <= path_len - 1))
    4965 CBC          15 :                 ereport(ERROR,
    4966 ECB             :                         (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    4967                 :                          errmsg("cannot replace existing key"),
    4968                 :                          errdetail("The path assumes key is a composite object, "
    4969                 :                                    "but it is a scalar value.")));
    4970                 : 
    4971 UIC           0 :             res = pushJsonbValue(st, r, &v);
    4972 LBC           0 :             break;
    4973 UIC           0 :         default:
    4974               0 :             elog(ERROR, "unrecognized iterator result: %d", (int) r);
    4975 ECB             :             res = NULL;         /* keep compiler quiet */
    4976                 :             break;
    4977                 :     }
    4978                 : 
    4979 GIC         564 :     return res;
    4980                 : }
    4981                 : 
    4982                 : /*
    4983                 :  * Object walker for setPath
    4984                 :  */
    4985                 : static void
    4986             444 : setPathObject(JsonbIterator **it, Datum *path_elems, bool *path_nulls,
    4987                 :               int path_len, JsonbParseState **st, int level,
    4988                 :               JsonbValue *newval, uint32 npairs, int op_type)
    4989                 : {
    4990             444 :     text       *pathelem = NULL;
    4991                 :     int         i;
    4992                 :     JsonbValue  k,
    4993                 :                 v;
    4994             444 :     bool        done = false;
    4995                 : 
    4996             444 :     if (level >= path_len || path_nulls[level])
    4997 UIC           0 :         done = true;
    4998                 :     else
    4999                 :     {
    5000                 :         /* The path Datum could be toasted, in which case we must detoast it */
    5001 GIC         444 :         pathelem = DatumGetTextPP(path_elems[level]);
    5002                 :     }
    5003                 : 
    5004                 :     /* empty object is a special case for create */
    5005             444 :     if ((npairs == 0) && (op_type & JB_PATH_CREATE_OR_INSERT) &&
    5006              27 :         (level == path_len - 1))
    5007                 :     {
    5008 ECB             :         JsonbValue  newkey;
    5009                 : 
    5010 GIC           9 :         newkey.type = jbvString;
    5011               9 :         newkey.val.string.val = VARDATA_ANY(pathelem);
    5012               9 :         newkey.val.string.len = VARSIZE_ANY_EXHDR(pathelem);
    5013                 : 
    5014               9 :         (void) pushJsonbValue(st, WJB_KEY, &newkey);
    5015               9 :         (void) pushJsonbValue(st, WJB_VALUE, newval);
    5016 ECB             :     }
    5017                 : 
    5018 CBC        2313 :     for (i = 0; i < npairs; i++)
    5019 ECB             :     {
    5020 GIC        1920 :         JsonbIteratorToken r = JsonbIteratorNext(it, &k, true);
    5021                 : 
    5022            1920 :         Assert(r == WJB_KEY);
    5023                 : 
    5024 CBC        3033 :         if (!done &&
    5025 GIC        1113 :             k.val.string.len == VARSIZE_ANY_EXHDR(pathelem) &&
    5026 CBC         564 :             memcmp(k.val.string.val, VARDATA_ANY(pathelem),
    5027 GIC         564 :                    k.val.string.len) == 0)
    5028 ECB             :         {
    5029 GIC         345 :             done = true;
    5030                 : 
    5031             345 :             if (level == path_len - 1)
    5032                 :             {
    5033                 :                 /*
    5034                 :                  * called from jsonb_insert(), it forbids redefining an
    5035                 :                  * existing value
    5036 ECB             :                  */
    5037 CBC          84 :                 if (op_type & (JB_PATH_INSERT_BEFORE | JB_PATH_INSERT_AFTER))
    5038               6 :                     ereport(ERROR,
    5039                 :                             (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    5040                 :                              errmsg("cannot replace existing key"),
    5041                 :                              errhint("Try using the function jsonb_set "
    5042                 :                                      "to replace key value.")));
    5043                 : 
    5044              78 :                 r = JsonbIteratorNext(it, &v, true);    /* skip value */
    5045              78 :                 if (!(op_type & JB_PATH_DELETE))
    5046 ECB             :                 {
    5047 CBC          57 :                     (void) pushJsonbValue(st, WJB_KEY, &k);
    5048              57 :                     (void) pushJsonbValue(st, WJB_VALUE, newval);
    5049 ECB             :                 }
    5050                 :             }
    5051                 :             else
    5052                 :             {
    5053 CBC         261 :                 (void) pushJsonbValue(st, r, &k);
    5054             261 :                 setPath(it, path_elems, path_nulls, path_len,
    5055 ECB             :                         st, level + 1, newval, op_type);
    5056                 :             }
    5057                 :         }
    5058                 :         else
    5059                 :         {
    5060 GIC        1575 :             if ((op_type & JB_PATH_CREATE_OR_INSERT) && !done &&
    5061             168 :                 level == path_len - 1 && i == npairs - 1)
    5062                 :             {
    5063                 :                 JsonbValue  newkey;
    5064                 : 
    5065              30 :                 newkey.type = jbvString;
    5066              30 :                 newkey.val.string.val = VARDATA_ANY(pathelem);
    5067              30 :                 newkey.val.string.len = VARSIZE_ANY_EXHDR(pathelem);
    5068 ECB             : 
    5069 CBC          30 :                 (void) pushJsonbValue(st, WJB_KEY, &newkey);
    5070 GIC          30 :                 (void) pushJsonbValue(st, WJB_VALUE, newval);
    5071                 :             }
    5072                 : 
    5073            1575 :             (void) pushJsonbValue(st, r, &k);
    5074            1575 :             r = JsonbIteratorNext(it, &v, false);
    5075 GBC        1575 :             (void) pushJsonbValue(st, r, r < WJB_BEGIN_ARRAY ? &v : NULL);
    5076            1575 :             if (r == WJB_BEGIN_ARRAY || r == WJB_BEGIN_OBJECT)
    5077 EUB             :             {
    5078 GBC         408 :                 int         walking_level = 1;
    5079                 : 
    5080 GIC        3795 :                 while (walking_level != 0)
    5081                 :                 {
    5082            3387 :                     r = JsonbIteratorNext(it, &v, false);
    5083 ECB             : 
    5084 GIC        3387 :                     if (r == WJB_BEGIN_ARRAY || r == WJB_BEGIN_OBJECT)
    5085             132 :                         ++walking_level;
    5086            3387 :                     if (r == WJB_END_ARRAY || r == WJB_END_OBJECT)
    5087             540 :                         --walking_level;
    5088                 : 
    5089            3387 :                     (void) pushJsonbValue(st, r, r < WJB_BEGIN_ARRAY ? &v : NULL);
    5090 ECB             :                 }
    5091                 :             }
    5092                 :         }
    5093                 :     }
    5094                 : 
    5095                 :     /*--
    5096                 :      * If we got here there are only few possibilities:
    5097                 :      * - no target path was found, and an open object with some keys/values was
    5098                 :      *   pushed into the state
    5099                 :      * - an object is empty, only WJB_BEGIN_OBJECT is pushed
    5100                 :      *
    5101 EUB             :      * In both cases if instructed to create the path when not present,
    5102                 :      * generate the whole chain of empty objects and insert the new value
    5103                 :      * there.
    5104                 :      */
    5105 CBC         393 :     if (!done && (op_type & JB_PATH_FILL_GAPS) && (level < path_len - 1))
    5106                 :     {
    5107                 :         JsonbValue  newkey;
    5108                 : 
    5109              24 :         newkey.type = jbvString;
    5110              24 :         newkey.val.string.val = VARDATA_ANY(pathelem);
    5111 GIC          24 :         newkey.val.string.len = VARSIZE_ANY_EXHDR(pathelem);
    5112                 : 
    5113              24 :         (void) pushJsonbValue(st, WJB_KEY, &newkey);
    5114 CBC          24 :         (void) push_path(st, level, path_elems, path_nulls,
    5115 ECB             :                          path_len, newval);
    5116                 : 
    5117                 :         /* Result is closed with WJB_END_OBJECT outside of this function */
    5118                 :     }
    5119 CBC         393 : }
    5120                 : 
    5121                 : /*
    5122 ECB             :  * Array walker for setPath
    5123                 :  */
    5124                 : static void
    5125 GIC         183 : setPathArray(JsonbIterator **it, Datum *path_elems, bool *path_nulls,
    5126 ECB             :              int path_len, JsonbParseState **st, int level,
    5127                 :              JsonbValue *newval, uint32 nelems, int op_type)
    5128                 : {
    5129                 :     JsonbValue  v;
    5130                 :     int         idx,
    5131                 :                 i;
    5132 GIC         183 :     bool        done = false;
    5133 ECB             : 
    5134                 :     /* pick correct index */
    5135 CBC         183 :     if (level < path_len && !path_nulls[level])
    5136 GIC         174 :     {
    5137             183 :         char       *c = TextDatumGetCString(path_elems[level]);
    5138                 :         char       *badp;
    5139                 : 
    5140             183 :         errno = 0;
    5141 CBC         183 :         idx = strtoint(c, &badp, 10);
    5142             183 :         if (badp == c || *badp != '\0' || errno != 0)
    5143 GIC           9 :             ereport(ERROR,
    5144                 :                     (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
    5145                 :                      errmsg("path element at position %d is not an integer: \"%s\"",
    5146                 :                             level + 1, c)));
    5147                 :     }
    5148 ECB             :     else
    5149 LBC           0 :         idx = nelems;
    5150                 : 
    5151 CBC         174 :     if (idx < 0)
    5152 ECB             :     {
    5153 GIC          39 :         if (-idx > nelems)
    5154                 :         {
    5155                 :             /*
    5156                 :              * If asked to keep elements position consistent, it's not allowed
    5157 ECB             :              * to prepend the array.
    5158                 :              */
    5159 GIC          12 :             if (op_type & JB_PATH_CONSISTENT_POSITION)
    5160               3 :                 ereport(ERROR,
    5161                 :                         (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    5162                 :                          errmsg("path element at position %d is out of range: %d",
    5163                 :                                 level + 1, idx)));
    5164 ECB             :             else
    5165 CBC           9 :                 idx = INT_MIN;
    5166                 :         }
    5167                 :         else
    5168 GIC          27 :             idx = nelems + idx;
    5169 ECB             :     }
    5170                 : 
    5171                 :     /*
    5172                 :      * Filling the gaps means there are no limits on the positive index are
    5173                 :      * imposed, we can set any element. Otherwise limit the index by nelems.
    5174                 :      */
    5175 GIC         171 :     if (!(op_type & JB_PATH_FILL_GAPS))
    5176                 :     {
    5177 CBC         135 :         if (idx > 0 && idx > nelems)
    5178              24 :             idx = nelems;
    5179 ECB             :     }
    5180                 : 
    5181                 :     /*
    5182                 :      * if we're creating, and idx == INT_MIN, we prepend the new value to the
    5183                 :      * array also if the array is empty - in which case we don't really care
    5184                 :      * what the idx value is
    5185                 :      */
    5186 CBC         171 :     if ((idx == INT_MIN || nelems == 0) && (level == path_len - 1) &&
    5187 GIC          33 :         (op_type & JB_PATH_CREATE_OR_INSERT))
    5188 ECB             :     {
    5189 CBC          33 :         Assert(newval != NULL);
    5190 ECB             : 
    5191 CBC          33 :         if (op_type & JB_PATH_FILL_GAPS && nelems == 0 && idx > 0)
    5192 GIC           3 :             push_null_elements(st, idx);
    5193 ECB             : 
    5194 GIC          33 :         (void) pushJsonbValue(st, WJB_ELEM, newval);
    5195                 : 
    5196              33 :         done = true;
    5197                 :     }
    5198                 : 
    5199                 :     /* iterate over the array elements */
    5200             483 :     for (i = 0; i < nelems; i++)
    5201                 :     {
    5202                 :         JsonbIteratorToken r;
    5203                 : 
    5204             312 :         if (i == idx && level < path_len)
    5205                 :         {
    5206             108 :             done = true;
    5207                 : 
    5208             108 :             if (level == path_len - 1)
    5209 ECB             :             {
    5210 GIC          72 :                 r = JsonbIteratorNext(it, &v, true);    /* skip */
    5211                 : 
    5212              72 :                 if (op_type & (JB_PATH_INSERT_BEFORE | JB_PATH_CREATE))
    5213 CBC          42 :                     (void) pushJsonbValue(st, WJB_ELEM, newval);
    5214 ECB             : 
    5215                 :                 /*
    5216                 :                  * We should keep current value only in case of
    5217                 :                  * JB_PATH_INSERT_BEFORE or JB_PATH_INSERT_AFTER because
    5218                 :                  * otherwise it should be deleted or replaced
    5219                 :                  */
    5220 GIC          72 :                 if (op_type & (JB_PATH_INSERT_AFTER | JB_PATH_INSERT_BEFORE))
    5221              36 :                     (void) pushJsonbValue(st, r, &v);
    5222                 : 
    5223 CBC          72 :                 if (op_type & (JB_PATH_INSERT_AFTER | JB_PATH_REPLACE))
    5224 GIC          18 :                     (void) pushJsonbValue(st, WJB_ELEM, newval);
    5225                 :             }
    5226                 :             else
    5227              36 :                 (void) setPath(it, path_elems, path_nulls, path_len,
    5228                 :                                st, level + 1, newval, op_type);
    5229 ECB             :         }
    5230                 :         else
    5231                 :         {
    5232 GIC         204 :             r = JsonbIteratorNext(it, &v, false);
    5233                 : 
    5234             204 :             (void) pushJsonbValue(st, r, r < WJB_BEGIN_ARRAY ? &v : NULL);
    5235                 : 
    5236 CBC         204 :             if (r == WJB_BEGIN_ARRAY || r == WJB_BEGIN_OBJECT)
    5237                 :             {
    5238 GIC           3 :                 int         walking_level = 1;
    5239 ECB             : 
    5240 CBC          12 :                 while (walking_level != 0)
    5241 ECB             :                 {
    5242 GIC           9 :                     r = JsonbIteratorNext(it, &v, false);
    5243                 : 
    5244 CBC           9 :                     if (r == WJB_BEGIN_ARRAY || r == WJB_BEGIN_OBJECT)
    5245 LBC           0 :                         ++walking_level;
    5246 CBC           9 :                     if (r == WJB_END_ARRAY || r == WJB_END_OBJECT)
    5247               3 :                         --walking_level;
    5248                 : 
    5249 GIC           9 :                     (void) pushJsonbValue(st, r, r < WJB_BEGIN_ARRAY ? &v : NULL);
    5250                 :                 }
    5251                 :             }
    5252                 :         }
    5253 EUB             :     }
    5254                 : 
    5255 CBC         171 :     if ((op_type & JB_PATH_CREATE_OR_INSERT) && !done && level == path_len - 1)
    5256                 :     {
    5257 ECB             :         /*
    5258                 :          * If asked to fill the gaps, idx could be bigger than nelems, so
    5259                 :          * prepend the new element with nulls if that's the case.
    5260                 :          */
    5261 GIC          18 :         if (op_type & JB_PATH_FILL_GAPS && idx > nelems)
    5262               6 :             push_null_elements(st, idx - nelems);
    5263 ECB             : 
    5264 CBC          18 :         (void) pushJsonbValue(st, WJB_ELEM, newval);
    5265 GIC          18 :         done = true;
    5266                 :     }
    5267                 : 
    5268                 :     /*--
    5269 ECB             :      * If we got here there are only few possibilities:
    5270                 :      * - no target path was found, and an open array with some keys/values was
    5271                 :      *   pushed into the state
    5272                 :      * - an array is empty, only WJB_BEGIN_ARRAY is pushed
    5273                 :      *
    5274                 :      * In both cases if instructed to create the path when not present,
    5275                 :      * generate the whole chain of empty objects and insert the new value
    5276                 :      * there.
    5277                 :      */
    5278 GIC         171 :     if (!done && (op_type & JB_PATH_FILL_GAPS) && (level < path_len - 1))
    5279 ECB             :     {
    5280 GIC          12 :         if (idx > 0)
    5281 CBC           6 :             push_null_elements(st, idx - nelems);
    5282 ECB             : 
    5283 GIC          12 :         (void) push_path(st, level, path_elems, path_nulls,
    5284                 :                          path_len, newval);
    5285                 : 
    5286                 :         /* Result is closed with WJB_END_OBJECT outside of this function */
    5287                 :     }
    5288             171 : }
    5289                 : 
    5290 ECB             : /*
    5291                 :  * Parse information about what elements of a jsonb document we want to iterate
    5292                 :  * in functions iterate_json(b)_values. This information is presented in jsonb
    5293                 :  * format, so that it can be easily extended in the future.
    5294                 :  */
    5295                 : uint32
    5296 CBC         126 : parse_jsonb_index_flags(Jsonb *jb)
    5297                 : {
    5298 ECB             :     JsonbIterator *it;
    5299                 :     JsonbValue  v;
    5300                 :     JsonbIteratorToken type;
    5301 GIC         126 :     uint32      flags = 0;
    5302                 : 
    5303             126 :     it = JsonbIteratorInit(&jb->root);
    5304 ECB             : 
    5305 GIC         126 :     type = JsonbIteratorNext(&it, &v, false);
    5306                 : 
    5307                 :     /*
    5308 ECB             :      * We iterate over array (scalar internally is represented as array, so,
    5309                 :      * we will accept it too) to check all its elements.  Flag names are
    5310                 :      * chosen the same as jsonb_typeof uses.
    5311                 :      */
    5312 CBC         126 :     if (type != WJB_BEGIN_ARRAY)
    5313 GIC           6 :         ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    5314 ECB             :                         errmsg("wrong flag type, only arrays and scalars are allowed")));
    5315                 : 
    5316 CBC         234 :     while ((type = JsonbIteratorNext(&it, &v, false)) == WJB_ELEM)
    5317 ECB             :     {
    5318 GIC         132 :         if (v.type != jbvString)
    5319              12 :             ereport(ERROR,
    5320                 :                     (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    5321                 :                      errmsg("flag array element is not a string"),
    5322                 :                      errhint("Possible values are: \"string\", \"numeric\", \"boolean\", \"key\", and \"all\".")));
    5323                 : 
    5324 CBC         174 :         if (v.val.string.len == 3 &&
    5325              54 :             pg_strncasecmp(v.val.string.val, "all", 3) == 0)
    5326 GIC          42 :             flags |= jtiAll;
    5327 CBC          90 :         else if (v.val.string.len == 3 &&
    5328              12 :                  pg_strncasecmp(v.val.string.val, "key", 3) == 0)
    5329 GIC          12 :             flags |= jtiKey;
    5330              90 :         else if (v.val.string.len == 6 &&
    5331 CBC          24 :                  pg_strncasecmp(v.val.string.val, "string", 6) == 0)
    5332 GIC          24 :             flags |= jtiString;
    5333              78 :         else if (v.val.string.len == 7 &&
    5334              36 :                  pg_strncasecmp(v.val.string.val, "numeric", 7) == 0)
    5335              24 :             flags |= jtiNumeric;
    5336 CBC          30 :         else if (v.val.string.len == 7 &&
    5337 GIC          12 :                  pg_strncasecmp(v.val.string.val, "boolean", 7) == 0)
    5338 CBC          12 :             flags |= jtiBool;
    5339                 :         else
    5340               6 :             ereport(ERROR,
    5341                 :                     (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    5342 ECB             :                      errmsg("wrong flag in flag array: \"%s\"",
    5343                 :                             pnstrdup(v.val.string.val, v.val.string.len)),
    5344                 :                      errhint("Possible values are: \"string\", \"numeric\", \"boolean\", \"key\", and \"all\".")));
    5345                 :     }
    5346                 : 
    5347                 :     /* expect end of array now */
    5348 CBC         102 :     if (type != WJB_END_ARRAY)
    5349 UBC           0 :         elog(ERROR, "unexpected end of flag array");
    5350 ECB             : 
    5351                 :     /* get final WJB_DONE and free iterator */
    5352 GIC         102 :     type = JsonbIteratorNext(&it, &v, false);
    5353 CBC         102 :     if (type != WJB_DONE)
    5354 UIC           0 :         elog(ERROR, "unexpected end of flag array");
    5355                 : 
    5356 GIC         102 :     return flags;
    5357                 : }
    5358                 : 
    5359 ECB             : /*
    5360                 :  * Iterate over jsonb values or elements, specified by flags, and pass them
    5361                 :  * together with an iteration state to a specified JsonIterateStringValuesAction.
    5362                 :  */
    5363                 : void
    5364 GIC          75 : iterate_jsonb_values(Jsonb *jb, uint32 flags, void *state,
    5365 ECB             :                      JsonIterateStringValuesAction action)
    5366                 : {
    5367                 :     JsonbIterator *it;
    5368                 :     JsonbValue  v;
    5369                 :     JsonbIteratorToken type;
    5370                 : 
    5371 GIC          75 :     it = JsonbIteratorInit(&jb->root);
    5372                 : 
    5373                 :     /*
    5374                 :      * Just recursively iterating over jsonb and call callback on all
    5375                 :      * corresponding elements
    5376                 :      */
    5377             822 :     while ((type = JsonbIteratorNext(&it, &v, false)) != WJB_DONE)
    5378                 :     {
    5379             747 :         if (type == WJB_KEY)
    5380                 :         {
    5381             279 :             if (flags & jtiKey)
    5382 CBC          72 :                 action(state, v.val.string.val, v.val.string.len);
    5383                 : 
    5384             279 :             continue;
    5385 ECB             :         }
    5386 GIC         468 :         else if (!(type == WJB_VALUE || type == WJB_ELEM))
    5387 ECB             :         {
    5388                 :             /* do not call callback for composite JsonbValue */
    5389 GIC         186 :             continue;
    5390                 :         }
    5391                 : 
    5392 ECB             :         /* JsonbValue is a value of object or element of array */
    5393 GIC         282 :         switch (v.type)
    5394                 :         {
    5395              75 :             case jbvString:
    5396              75 :                 if (flags & jtiString)
    5397              54 :                     action(state, v.val.string.val, v.val.string.len);
    5398              75 :                 break;
    5399              84 :             case jbvNumeric:
    5400 CBC          84 :                 if (flags & jtiNumeric)
    5401                 :                 {
    5402                 :                     char       *val;
    5403                 : 
    5404 GIC          36 :                     val = DatumGetCString(DirectFunctionCall1(numeric_out,
    5405 ECB             :                                                               NumericGetDatum(v.val.numeric)));
    5406                 : 
    5407 CBC          36 :                     action(state, val, strlen(val));
    5408 GIC          36 :                     pfree(val);
    5409 ECB             :                 }
    5410 GIC          84 :                 break;
    5411              78 :             case jbvBool:
    5412              78 :                 if (flags & jtiBool)
    5413                 :                 {
    5414              24 :                     if (v.val.boolean)
    5415              12 :                         action(state, "true", 4);
    5416 ECB             :                     else
    5417 CBC          12 :                         action(state, "false", 5);
    5418                 :                 }
    5419 GIC          78 :                 break;
    5420 CBC          45 :             default:
    5421                 :                 /* do not call callback for composite JsonbValue */
    5422              45 :                 break;
    5423 ECB             :         }
    5424                 :     }
    5425 GIC          75 : }
    5426                 : 
    5427                 : /*
    5428 ECB             :  * Iterate over json values and elements, specified by flags, and pass them
    5429                 :  * together with an iteration state to a specified JsonIterateStringValuesAction.
    5430                 :  */
    5431                 : void
    5432 CBC          75 : iterate_json_values(text *json, uint32 flags, void *action_state,
    5433 ECB             :                     JsonIterateStringValuesAction action)
    5434                 : {
    5435 CBC          75 :     JsonLexContext *lex = makeJsonLexContext(json, true);
    5436              75 :     JsonSemAction *sem = palloc0(sizeof(JsonSemAction));
    5437              75 :     IterateJsonStringValuesState *state = palloc0(sizeof(IterateJsonStringValuesState));
    5438 ECB             : 
    5439 CBC          75 :     state->lex = lex;
    5440              75 :     state->action = action;
    5441              75 :     state->action_state = action_state;
    5442              75 :     state->flags = flags;
    5443                 : 
    5444              75 :     sem->semstate = (void *) state;
    5445 GIC          75 :     sem->scalar = iterate_values_scalar;
    5446              75 :     sem->object_field_start = iterate_values_object_field_start;
    5447                 : 
    5448              75 :     pg_parse_json_or_ereport(lex, sem);
    5449              75 : }
    5450                 : 
    5451                 : /*
    5452 ECB             :  * An auxiliary function for iterate_json_values to invoke a specified
    5453 EUB             :  * JsonIterateStringValuesAction for specified values.
    5454                 :  */
    5455                 : static JsonParseErrorType
    5456 CBC         282 : iterate_values_scalar(void *state, char *token, JsonTokenType tokentype)
    5457 ECB             : {
    5458 GBC         282 :     IterateJsonStringValuesState *_state = (IterateJsonStringValuesState *) state;
    5459                 : 
    5460 CBC         282 :     switch (tokentype)
    5461                 :     {
    5462 GIC          75 :         case JSON_TOKEN_STRING:
    5463              75 :             if (_state->flags & jtiString)
    5464              54 :                 _state->action(_state->action_state, token, strlen(token));
    5465              75 :             break;
    5466              84 :         case JSON_TOKEN_NUMBER:
    5467              84 :             if (_state->flags & jtiNumeric)
    5468 CBC          36 :                 _state->action(_state->action_state, token, strlen(token));
    5469 GIC          84 :             break;
    5470              78 :         case JSON_TOKEN_TRUE:
    5471                 :         case JSON_TOKEN_FALSE:
    5472              78 :             if (_state->flags & jtiBool)
    5473              24 :                 _state->action(_state->action_state, token, strlen(token));
    5474              78 :             break;
    5475 CBC          45 :         default:
    5476                 :             /* do not call callback for any other token */
    5477 GIC          45 :             break;
    5478                 :     }
    5479                 : 
    5480 GNC         282 :     return JSON_SUCCESS;
    5481                 : }
    5482                 : 
    5483                 : static JsonParseErrorType
    5484 GIC         279 : iterate_values_object_field_start(void *state, char *fname, bool isnull)
    5485 ECB             : {
    5486 GIC         279 :     IterateJsonStringValuesState *_state = (IterateJsonStringValuesState *) state;
    5487 ECB             : 
    5488 CBC         279 :     if (_state->flags & jtiKey)
    5489                 :     {
    5490              72 :         char       *val = pstrdup(fname);
    5491                 : 
    5492              72 :         _state->action(_state->action_state, val, strlen(val));
    5493                 :     }
    5494                 : 
    5495 GNC         279 :     return JSON_SUCCESS;
    5496                 : }
    5497 ECB             : 
    5498                 : /*
    5499                 :  * Iterate over a jsonb, and apply a specified JsonTransformStringValuesAction
    5500                 :  * to every string value or element. Any necessary context for a
    5501                 :  * JsonTransformStringValuesAction can be passed in the action_state variable.
    5502                 :  * Function returns a copy of an original jsonb object with transformed values.
    5503                 :  */
    5504                 : Jsonb *
    5505 CBC          21 : transform_jsonb_string_values(Jsonb *jsonb, void *action_state,
    5506 ECB             :                               JsonTransformStringValuesAction transform_action)
    5507                 : {
    5508                 :     JsonbIterator *it;
    5509                 :     JsonbValue  v,
    5510 GIC          21 :                *res = NULL;
    5511                 :     JsonbIteratorToken type;
    5512 CBC          21 :     JsonbParseState *st = NULL;
    5513                 :     text       *out;
    5514 GIC          21 :     bool        is_scalar = false;
    5515 ECB             : 
    5516 CBC          21 :     it = JsonbIteratorInit(&jsonb->root);
    5517 GIC          21 :     is_scalar = it->isScalar;
    5518 ECB             : 
    5519 CBC         228 :     while ((type = JsonbIteratorNext(&it, &v, false)) != WJB_DONE)
    5520 ECB             :     {
    5521 GIC         207 :         if ((type == WJB_VALUE || type == WJB_ELEM) && v.type == jbvString)
    5522 ECB             :         {
    5523 CBC          57 :             out = transform_action(action_state, v.val.string.val, v.val.string.len);
    5524                 :             /* out is probably not toasted, but let's be sure */
    5525              57 :             out = pg_detoast_datum_packed(out);
    5526 GIC          57 :             v.val.string.val = VARDATA_ANY(out);
    5527 CBC          57 :             v.val.string.len = VARSIZE_ANY_EXHDR(out);
    5528              57 :             res = pushJsonbValue(&st, type, type < WJB_BEGIN_ARRAY ? &v : NULL);
    5529                 :         }
    5530 ECB             :         else
    5531                 :         {
    5532 GIC         243 :             res = pushJsonbValue(&st, type, (type == WJB_KEY ||
    5533 CBC          93 :                                              type == WJB_VALUE ||
    5534                 :                                              type == WJB_ELEM) ? &v : NULL);
    5535                 :         }
    5536                 :     }
    5537                 : 
    5538 GIC          21 :     if (res->type == jbvArray)
    5539               6 :         res->val.array.rawScalar = is_scalar;
    5540 ECB             : 
    5541 GIC          21 :     return JsonbValueToJsonb(res);
    5542                 : }
    5543 ECB             : 
    5544                 : /*
    5545                 :  * Iterate over a json, and apply a specified JsonTransformStringValuesAction
    5546                 :  * to every string value or element. Any necessary context for a
    5547                 :  * JsonTransformStringValuesAction can be passed in the action_state variable.
    5548                 :  * Function returns a StringInfo, which is a copy of an original json with
    5549                 :  * transformed values.
    5550                 :  */
    5551                 : text *
    5552 CBC          21 : transform_json_string_values(text *json, void *action_state,
    5553 ECB             :                              JsonTransformStringValuesAction transform_action)
    5554                 : {
    5555 GIC          21 :     JsonLexContext *lex = makeJsonLexContext(json, true);
    5556 CBC          21 :     JsonSemAction *sem = palloc0(sizeof(JsonSemAction));
    5557              21 :     TransformJsonStringValuesState *state = palloc0(sizeof(TransformJsonStringValuesState));
    5558                 : 
    5559 GIC          21 :     state->lex = lex;
    5560              21 :     state->strval = makeStringInfo();
    5561              21 :     state->action = transform_action;
    5562              21 :     state->action_state = action_state;
    5563                 : 
    5564 CBC          21 :     sem->semstate = (void *) state;
    5565              21 :     sem->object_start = transform_string_values_object_start;
    5566 GIC          21 :     sem->object_end = transform_string_values_object_end;
    5567 CBC          21 :     sem->array_start = transform_string_values_array_start;
    5568 GIC          21 :     sem->array_end = transform_string_values_array_end;
    5569 CBC          21 :     sem->scalar = transform_string_values_scalar;
    5570              21 :     sem->array_element_start = transform_string_values_array_element_start;
    5571              21 :     sem->object_field_start = transform_string_values_object_field_start;
    5572 ECB             : 
    5573 CBC          21 :     pg_parse_json_or_ereport(lex, sem);
    5574 ECB             : 
    5575 CBC          21 :     return cstring_to_text_with_len(state->strval->data, state->strval->len);
    5576 ECB             : }
    5577                 : 
    5578                 : /*
    5579                 :  * Set of auxiliary functions for transform_json_string_values to invoke a
    5580                 :  * specified JsonTransformStringValuesAction for all values and left everything
    5581                 :  * else untouched.
    5582                 :  */
    5583                 : static JsonParseErrorType
    5584 CBC          27 : transform_string_values_object_start(void *state)
    5585                 : {
    5586 GIC          27 :     TransformJsonStringValuesState *_state = (TransformJsonStringValuesState *) state;
    5587 ECB             : 
    5588 GIC          27 :     appendStringInfoCharMacro(_state->strval, '{');
    5589                 : 
    5590 GNC          27 :     return JSON_SUCCESS;
    5591                 : }
    5592                 : 
    5593                 : static JsonParseErrorType
    5594 GIC          27 : transform_string_values_object_end(void *state)
    5595 ECB             : {
    5596 GIC          27 :     TransformJsonStringValuesState *_state = (TransformJsonStringValuesState *) state;
    5597 ECB             : 
    5598 GIC          27 :     appendStringInfoCharMacro(_state->strval, '}');
    5599                 : 
    5600 GNC          27 :     return JSON_SUCCESS;
    5601 ECB             : }
    5602                 : 
    5603                 : static JsonParseErrorType
    5604 GIC          15 : transform_string_values_array_start(void *state)
    5605                 : {
    5606 CBC          15 :     TransformJsonStringValuesState *_state = (TransformJsonStringValuesState *) state;
    5607                 : 
    5608 GIC          15 :     appendStringInfoCharMacro(_state->strval, '[');
    5609                 : 
    5610 GNC          15 :     return JSON_SUCCESS;
    5611                 : }
    5612                 : 
    5613                 : static JsonParseErrorType
    5614 GIC          15 : transform_string_values_array_end(void *state)
    5615                 : {
    5616              15 :     TransformJsonStringValuesState *_state = (TransformJsonStringValuesState *) state;
    5617                 : 
    5618 CBC          15 :     appendStringInfoCharMacro(_state->strval, ']');
    5619                 : 
    5620 GNC          15 :     return JSON_SUCCESS;
    5621                 : }
    5622                 : 
    5623                 : static JsonParseErrorType
    5624 GIC          57 : transform_string_values_object_field_start(void *state, char *fname, bool isnull)
    5625 ECB             : {
    5626 GIC          57 :     TransformJsonStringValuesState *_state = (TransformJsonStringValuesState *) state;
    5627 ECB             : 
    5628 GIC          57 :     if (_state->strval->data[_state->strval->len - 1] != '{')
    5629 CBC          33 :         appendStringInfoCharMacro(_state->strval, ',');
    5630                 : 
    5631 ECB             :     /*
    5632                 :      * Unfortunately we don't have the quoted and escaped string any more, so
    5633                 :      * we have to re-escape it.
    5634                 :      */
    5635 GIC          57 :     escape_json(_state->strval, fname);
    5636 CBC          57 :     appendStringInfoCharMacro(_state->strval, ':');
    5637                 : 
    5638 GNC          57 :     return JSON_SUCCESS;
    5639                 : }
    5640 ECB             : 
    5641                 : static JsonParseErrorType
    5642 CBC          24 : transform_string_values_array_element_start(void *state, bool isnull)
    5643 ECB             : {
    5644 CBC          24 :     TransformJsonStringValuesState *_state = (TransformJsonStringValuesState *) state;
    5645 ECB             : 
    5646 GIC          24 :     if (_state->strval->data[_state->strval->len - 1] != '[')
    5647              12 :         appendStringInfoCharMacro(_state->strval, ',');
    5648                 : 
    5649 GNC          24 :     return JSON_SUCCESS;
    5650                 : }
    5651 ECB             : 
    5652                 : static JsonParseErrorType
    5653 GIC          60 : transform_string_values_scalar(void *state, char *token, JsonTokenType tokentype)
    5654                 : {
    5655              60 :     TransformJsonStringValuesState *_state = (TransformJsonStringValuesState *) state;
    5656                 : 
    5657 CBC          60 :     if (tokentype == JSON_TOKEN_STRING)
    5658 ECB             :     {
    5659 GIC          57 :         text       *out = _state->action(_state->action_state, token, strlen(token));
    5660 ECB             : 
    5661 GIC          57 :         escape_json(_state->strval, text_to_cstring(out));
    5662                 :     }
    5663                 :     else
    5664               3 :         appendStringInfoString(_state->strval, token);
    5665                 : 
    5666 GNC          60 :     return JSON_SUCCESS;
    5667                 : }
    5668                 : 
    5669                 : JsonTokenType
    5670             336 : json_get_first_token(text *json, bool throw_error)
    5671                 : {
    5672                 :     JsonLexContext *lex;
    5673                 :     JsonParseErrorType result;
    5674                 : 
    5675             336 :     lex = makeJsonLexContext(json, false);
    5676                 : 
    5677                 :     /* Lex exactly one token from the input and check its type. */
    5678             336 :     result = json_lex(lex);
    5679                 : 
    5680             336 :     if (result == JSON_SUCCESS)
    5681             327 :         return lex->token_type;
    5682                 : 
    5683               9 :     if (throw_error)
    5684 UNC           0 :         json_errsave_error(result, lex, NULL);
    5685                 : 
    5686 GNC           9 :     return JSON_TOKEN_INVALID;  /* invalid json */
    5687                 : }
        

Generated by: LCOV version v1.16-55-g56c0a2a