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 17:13:01 Functions: 100.0 % 147 147 144 3 145 2
Baseline: 15 Line coverage date bins:
Baseline Date: 2023-04-08 15:09:40 [..60] days: 88.9 % 9 8 1 1 7
Legend: Lines: hit not hit (60,120] days: 95.9 % 97 93 4 12 76 5
(120,180] days: 100.0 % 4 4 1 3
(180,240] days: 100.0 % 2 2 2
(240..) days: 96.7 % 1936 1872 23 40 1 24 1115 6 727 41 1123
Function coverage date bins:
[..60] days: 100.0 % 1 1 1
(60,120] days: 100.0 % 2 2 2
(240..) days: 51.4 % 280 144 144 136

 Age         Owner                  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
  119 tgl                       507 GNC       16488 : pg_parse_json_or_errsave(JsonLexContext *lex, JsonSemAction *sem,
                                508                 :                          Node *escontext)
                                509                 : {
                                510                 :     JsonParseErrorType result;
                                511                 : 
 1168 rhaas                     512 GIC       16488 :     result = pg_parse_json(lex, sem);
                                513           16392 :     if (result != JSON_SUCCESS)
                                514                 :     {
  119 tgl                       515 GNC         228 :         json_errsave_error(result, lex, escontext);
                                516              15 :         return false;
                                517                 :     }
                                518           16164 :     return true;
                                519                 : }
                                520                 : 
                                521                 : /*
                                522                 :  * makeJsonLexContext
 1168 rhaas                     523 ECB             :  *
                                524                 :  * This is like makeJsonLexContextCstringLen, but it accepts a text value
                                525                 :  * directly.
                                526                 :  */
                                527                 : JsonLexContext *
 1168 rhaas                     528 GIC        5280 : makeJsonLexContext(text *json, bool need_escapes)
 1168 rhaas                     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                 :      */
  118 tgl                       534 GIC        5280 :     json = pg_detoast_datum_packed(json);
                                535                 : 
 1168 rhaas                     536           10560 :     return makeJsonLexContextCstringLen(VARDATA_ANY(json),
                                537            5280 :                                         VARSIZE_ANY_EXHDR(json),
                                538                 :                                         GetDatabaseEncoding(),
 1168 rhaas                     539 ECB             :                                         need_escapes);
                                540                 : }
                                541                 : 
                                542                 : /*
                                543                 :  * SQL function json_object_keys
                                544                 :  *
 3663 andrew                    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
 3304 andrew                    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;
 2029 tgl                       563               9 :         Jsonb      *jb = PG_GETARG_JSONB_P(0);
 3304 andrew                    564               9 :         bool        skipNested = false;
                                565                 :         JsonbIterator *it;
 3304 andrew                    566 ECB             :         JsonbValue  v;
                                567                 :         JsonbIteratorToken r;
                                568                 : 
 3304 andrew                    569 GIC           9 :         if (JB_ROOT_IS_SCALAR(jb))
                                570               3 :             ereport(ERROR,
 3304 andrew                    571 ECB             :                     (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                                572                 :                      errmsg("cannot call %s on a scalar",
                                573                 :                             "jsonb_object_keys")));
 3304 andrew                    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                 : 
 3304 andrew                    583 GIC           3 :         state = palloc(sizeof(OkeysState));
                                584                 : 
 3304 andrew                    585 CBC           3 :         state->result_size = JB_ROOT_COUNT(jb);
                                586               3 :         state->result_count = 0;
 3304 andrew                    587 GIC           3 :         state->sent_count = 0;
                                588               3 :         state->result = palloc(state->result_size * sizeof(char *));
                                589                 : 
 3259 heikki.linnakangas        590               3 :         it = JsonbIteratorInit(&jb->root);
 3304 andrew                    591 ECB             : 
 3304 andrew                    592 CBC          45 :         while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE)
                                593                 :         {
                                594              42 :             skipNested = true;
                                595                 : 
                                596              42 :             if (r == WJB_KEY)
 3304 andrew                    597 ECB             :             {
                                598                 :                 char       *cstr;
                                599                 : 
 3294 tgl                       600 GIC          18 :                 cstr = palloc(v.val.string.len + 1 * sizeof(char));
 3294 tgl                       601 CBC          18 :                 memcpy(cstr, v.val.string.val, v.val.string.len);
 3294 tgl                       602 GIC          18 :                 cstr[v.val.string.len] = '\0';
 3304 andrew                    603 CBC          18 :                 state->result[state->result_count++] = cstr;
                                604                 :             }
 3304 andrew                    605 ECB             :         }
                                606                 : 
 3304 andrew                    607 CBC           3 :         MemoryContextSwitchTo(oldcontext);
 3304 andrew                    608 GIC           3 :         funcctx->user_fctx = (void *) state;
                                609                 :     }
                                610                 : 
 3304 andrew                    611 CBC          21 :     funcctx = SRF_PERCALL_SETUP();
                                612              21 :     state = (OkeysState *) funcctx->user_fctx;
 3304 andrew                    613 ECB             : 
 3304 andrew                    614 CBC          21 :     if (state->sent_count < state->result_count)
                                615                 :     {
 3304 andrew                    616 GIC          18 :         char       *nxt = state->result[state->sent_count++];
                                617                 : 
 3304 andrew                    618 CBC          18 :         SRF_RETURN_NEXT(funcctx, CStringGetTextDatum(nxt));
 3304 andrew                    619 ECB             :     }
                                620                 : 
 3304 andrew                    621 GIC           3 :     SRF_RETURN_DONE(funcctx);
 3304 andrew                    622 ECB             : }
 3663                           623                 : 
                                624                 : /*
 1168 rhaas                     625                 :  * Report a JSON error.
                                626                 :  */
                                627                 : void
  119 tgl                       628 GNC         228 : json_errsave_error(JsonParseErrorType error, JsonLexContext *lex,
                                629                 :                    Node *escontext)
 1168 rhaas                     630 ECB             : {
 1168 rhaas                     631 GIC         228 :     if (error == JSON_UNICODE_HIGH_ESCAPE ||
  119 tgl                       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))
  119 tgl                       643 UNC           0 :             elog(ERROR, "JSON semantic action function did not provide error information");
                                644                 :     }
                                645                 :     else
  119 tgl                       646 GNC         213 :         errsave(escontext,
 1168 rhaas                     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)));
 1168 rhaas                     651 CBC          15 : }
                                652                 : 
 1168 rhaas                     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().
 1168 rhaas                     662 EUB             :  */
                                663                 : static int
 1168 rhaas                     664 GIC         219 : report_json_context(JsonLexContext *lex)
 1168 rhaas                     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 */
  769 tgl                       675 GIC         219 :     line_start = lex->line_start;
                                676             219 :     context_start = line_start;
 1168 rhaas                     677             219 :     context_end = lex->token_terminator;
   27 tgl                       678             219 :     Assert(context_end >= context_start);
                                679                 : 
                                680                 :     /* Advance until we are close enough to context_end */
  592                           681             285 :     while (context_end - context_start >= 50)
                                682                 :     {
 1168 rhaas                     683 ECB             :         /* Advance to next multibyte character */
 1168 rhaas                     684 GIC          66 :         if (IS_HIGHBIT_SET(*context_start))
 1168 rhaas                     685 UIC           0 :             context_start += pg_mblen(context_start);
                                686                 :         else
 1168 rhaas                     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.
 1168 rhaas                     694 ECB             :      */
 1168 rhaas                     695 CBC         219 :     if (context_start - line_start <= 3)
                                696             213 :         context_start = line_start;
 1168 rhaas                     697 ECB             : 
                                698                 :     /* Get a null-terminated copy of the data to present */
 1168 rhaas                     699 GIC         219 :     ctxtlen = context_end - context_start;
 1168 rhaas                     700 CBC         219 :     ctxt = palloc(ctxtlen + 1);
 1168 rhaas                     701 GIC         219 :     memcpy(ctxt, context_start, ctxtlen);
                                702             219 :     ctxt[ctxtlen] = '\0';
 1168 rhaas                     703 ECB             : 
 1168 rhaas                     704 EUB             :     /*
                                705                 :      * Show the context, prefixing "..." if not starting at start of line, and
 1168 rhaas                     706 ECB             :      * suffixing "..." if not ending at end of line.
                                707                 :      */
 1168 rhaas                     708 GIC         219 :     prefix = (context_start > line_start) ? "..." : "";
  592 tgl                       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                 : 
 1110                           713             219 :     return errcontext("JSON data, line %d: %s%s%s",
  769 tgl                       714 ECB             :                       lex->line_number, prefix, ctxt, suffix);
 1168 rhaas                     715                 : }
                                716                 : 
                                717                 : 
 3663 andrew                    718                 : Datum
 3663 andrew                    719 CBC         930 : json_object_keys(PG_FUNCTION_ARGS)
 3663 andrew                    720 ECB             : {
                                721                 :     FuncCallContext *funcctx;
                                722                 :     OkeysState *state;
                                723                 : 
 3663 andrew                    724 GIC         930 :     if (SRF_IS_FIRSTCALL())
                                725                 :     {
 2219 noah                      726              12 :         text       *json = PG_GETARG_TEXT_PP(0);
 3663 andrew                    727 CBC          12 :         JsonLexContext *lex = makeJsonLexContext(json, true);
 3550 peter_e                   728 ECB             :         JsonSemAction *sem;
 3663 andrew                    729                 :         MemoryContext oldcontext;
                                730                 : 
 3663 andrew                    731 GIC          12 :         funcctx = SRF_FIRSTCALL_INIT();
 3663 andrew                    732 CBC          12 :         oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
                                733                 : 
 3550 peter_e                   734 GIC          12 :         state = palloc(sizeof(OkeysState));
                                735              12 :         sem = palloc0(sizeof(JsonSemAction));
                                736                 : 
 3663 andrew                    737              12 :         state->lex = lex;
 3663 andrew                    738 CBC          12 :         state->result_size = 256;
 3663 andrew                    739 GIC          12 :         state->result_count = 0;
                                740              12 :         state->sent_count = 0;
                                741              12 :         state->result = palloc(256 * sizeof(char *));
                                742                 : 
 3663 andrew                    743 CBC          12 :         sem->semstate = (void *) state;
 3663 andrew                    744 GIC          12 :         sem->array_start = okeys_array_start;
 3663 andrew                    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                 : 
 1168 rhaas                     749 GIC          12 :         pg_parse_json_or_ereport(lex, sem);
 3663 andrew                    750 ECB             :         /* keys are now in state->result */
                                751                 : 
 3663 andrew                    752 GIC           6 :         pfree(lex->strval->data);
 3663 andrew                    753 CBC           6 :         pfree(lex->strval);
                                754               6 :         pfree(lex);
 3663 andrew                    755 GIC           6 :         pfree(sem);
 3663 andrew                    756 ECB             : 
 3663 andrew                    757 CBC           6 :         MemoryContextSwitchTo(oldcontext);
                                758               6 :         funcctx->user_fctx = (void *) state;
 3663 andrew                    759 ECB             :     }
                                760                 : 
 3663 andrew                    761 GIC         924 :     funcctx = SRF_PERCALL_SETUP();
 3550 peter_e                   762 CBC         924 :     state = (OkeysState *) funcctx->user_fctx;
 3663 andrew                    763 ECB             : 
 3663 andrew                    764 CBC         924 :     if (state->sent_count < state->result_count)
 3663 andrew                    765 ECB             :     {
 3663 andrew                    766 GIC         918 :         char       *nxt = state->result[state->sent_count++];
                                767                 : 
 3663 andrew                    768 CBC         918 :         SRF_RETURN_NEXT(funcctx, CStringGetTextDatum(nxt));
                                769                 :     }
                                770                 : 
                                771               6 :     SRF_RETURN_DONE(funcctx);
 3663 andrew                    772 ECB             : }
                                773                 : 
                                774                 : static JsonParseErrorType
 3663 andrew                    775 GIC         921 : okeys_object_field_start(void *state, char *fname, bool isnull)
 3663 andrew                    776 ECB             : {
 3550 peter_e                   777 CBC         921 :     OkeysState *_state = (OkeysState *) state;
                                778                 : 
                                779                 :     /* only collecting keys for the top level object */
 3663 andrew                    780             921 :     if (_state->lex->lex_level != 1)
  119 tgl                       781 GNC           3 :         return JSON_SUCCESS;
                                782                 : 
 3663 andrew                    783 ECB             :     /* enlarge result array if necessary */
 3663 andrew                    784 GIC         918 :     if (_state->result_count >= _state->result_size)
 3663 andrew                    785 ECB             :     {
 3663 andrew                    786 GIC           3 :         _state->result_size *= 2;
 3210 tgl                       787 CBC           3 :         _state->result = (char **)
 3663 andrew                    788 GIC           3 :             repalloc(_state->result, sizeof(char *) * _state->result_size);
                                789                 :     }
 3663 andrew                    790 ECB             : 
                                791                 :     /* save a copy of the field name */
 3663 andrew                    792 GIC         918 :     _state->result[_state->result_count++] = pstrdup(fname);
                                793                 : 
  119 tgl                       794 GNC         918 :     return JSON_SUCCESS;
                                795                 : }
 3663 andrew                    796 ECB             : 
                                797                 : static JsonParseErrorType
 3663 andrew                    798 CBC           6 : okeys_array_start(void *state)
                                799                 : {
 3550 peter_e                   800 GIC           6 :     OkeysState *_state = (OkeysState *) state;
 3663 andrew                    801 ECB             : 
                                802                 :     /* top level must be a json object */
 3663 andrew                    803 GIC           6 :     if (_state->lex->lex_level == 0)
                                804               3 :         ereport(ERROR,
 3663 andrew                    805 ECB             :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                                806                 :                  errmsg("cannot call %s on an array",
 3210 tgl                       807                 :                         "json_object_keys")));
                                808                 : 
  119 tgl                       809 GNC           3 :     return JSON_SUCCESS;
 3663 andrew                    810 ECB             : }
                                811                 : 
                                812                 : static JsonParseErrorType
 3663 andrew                    813 GIC         927 : okeys_scalar(void *state, char *token, JsonTokenType tokentype)
                                814                 : {
 3550 peter_e                   815 CBC         927 :     OkeysState *_state = (OkeysState *) state;
                                816                 : 
 3663 andrew                    817 ECB             :     /* top level must be a json object */
 3663 andrew                    818 GIC         927 :     if (_state->lex->lex_level == 0)
                                819               3 :         ereport(ERROR,
                                820                 :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
 3210 tgl                       821 ECB             :                  errmsg("cannot call %s on a scalar",
                                822                 :                         "json_object_keys")));
                                823                 : 
  119 tgl                       824 GNC         924 :     return JSON_SUCCESS;
 3663 andrew                    825 ECB             : }
                                826                 : 
                                827                 : /*
 3304                           828                 :  * json and jsonb getter functions
 3663                           829                 :  * these implement the -> ->> #> and #>> operators
                                830                 :  * and the json{b?}_extract_path*(json, text, ...) functions
                                831                 :  */
                                832                 : 
                                833                 : 
                                834                 : Datum
 3663 andrew                    835 GIC         490 : json_object_field(PG_FUNCTION_ARGS)
                                836                 : {
 2219 noah                      837             490 :     text       *json = PG_GETARG_TEXT_PP(0);
 3152 tgl                       838 CBC         490 :     text       *fname = PG_GETARG_TEXT_PP(1);
 3663 andrew                    839 GIC         490 :     char       *fnamestr = text_to_cstring(fname);
 3210 tgl                       840 ECB             :     text       *result;
                                841                 : 
 3152 tgl                       842 GIC         490 :     result = get_worker(json, &fnamestr, NULL, 1, false);
 3663 andrew                    843 ECB             : 
 3663 andrew                    844 CBC         478 :     if (result != NULL)
 3663 andrew                    845 GIC         391 :         PG_RETURN_TEXT_P(result);
                                846                 :     else
                                847              87 :         PG_RETURN_NULL();
                                848                 : }
 3663 andrew                    849 ECB             : 
                                850                 : Datum
 3304 andrew                    851 GIC       12345 : jsonb_object_field(PG_FUNCTION_ARGS)
                                852                 : {
 2029 tgl                       853           12345 :     Jsonb      *jb = PG_GETARG_JSONB_P(0);
 3234 andrew                    854           12345 :     text       *key = PG_GETARG_TEXT_PP(1);
                                855                 :     JsonbValue *v;
                                856                 :     JsonbValue  vbuf;
                                857                 : 
 3152 tgl                       858           12345 :     if (!JB_ROOT_IS_OBJECT(jb))
                                859              12 :         PG_RETURN_NULL();
 3304 andrew                    860 ECB             : 
 1297 alvherre                  861 GIC       24666 :     v = getKeyJsonValueFromContainer(&jb->root,
 1297 alvherre                  862 CBC       12333 :                                      VARDATA_ANY(key),
                                863           12333 :                                      VARSIZE_ANY_EXHDR(key),
 1297 alvherre                  864 ECB             :                                      &vbuf);
                                865                 : 
 3234 andrew                    866 GIC       12333 :     if (v != NULL)
 2029 tgl                       867 CBC         216 :         PG_RETURN_JSONB_P(JsonbValueToJsonb(v));
                                868                 : 
 3304 andrew                    869           12117 :     PG_RETURN_NULL();
 3304 andrew                    870 ECB             : }
                                871                 : 
 3663                           872                 : Datum
 3663 andrew                    873 GIC         462 : json_object_field_text(PG_FUNCTION_ARGS)
                                874                 : {
 2219 noah                      875             462 :     text       *json = PG_GETARG_TEXT_PP(0);
 3152 tgl                       876 CBC         462 :     text       *fname = PG_GETARG_TEXT_PP(1);
 3663 andrew                    877 GIC         462 :     char       *fnamestr = text_to_cstring(fname);
 3210 tgl                       878 ECB             :     text       *result;
 3663 andrew                    879                 : 
 3152 tgl                       880 GIC         462 :     result = get_worker(json, &fnamestr, NULL, 1, true);
                                881                 : 
 3663 andrew                    882             459 :     if (result != NULL)
 3663 andrew                    883 CBC         441 :         PG_RETURN_TEXT_P(result);
 3663 andrew                    884 ECB             :     else
 3663 andrew                    885 GIC          18 :         PG_RETURN_NULL();
 3663 andrew                    886 ECB             : }
                                887                 : 
 3304                           888                 : Datum
 3304 andrew                    889 GIC          99 : jsonb_object_field_text(PG_FUNCTION_ARGS)
                                890                 : {
 2029 tgl                       891 CBC          99 :     Jsonb      *jb = PG_GETARG_JSONB_P(0);
 3234 andrew                    892              99 :     text       *key = PG_GETARG_TEXT_PP(1);
                                893                 :     JsonbValue *v;
 1297 alvherre                  894 ECB             :     JsonbValue  vbuf;
                                895                 : 
 3152 tgl                       896 GIC          99 :     if (!JB_ROOT_IS_OBJECT(jb))
                                897              12 :         PG_RETURN_NULL();
 3304 andrew                    898 ECB             : 
 1297 alvherre                  899 GIC         174 :     v = getKeyJsonValueFromContainer(&jb->root,
 1297 alvherre                  900 CBC          87 :                                      VARDATA_ANY(key),
                                901              87 :                                      VARSIZE_ANY_EXHDR(key),
 1297 alvherre                  902 ECB             :                                      &vbuf);
                                903                 : 
 1297 alvherre                  904 GIC          87 :     if (v != NULL && v->type != jbvNull)
 1297 alvherre                  905 CBC          72 :         PG_RETURN_TEXT_P(JsonbValueAsText(v));
                                906                 : 
 3304 andrew                    907              15 :     PG_RETURN_NULL();
 3304 andrew                    908 ECB             : }
                                909                 : 
 3663                           910                 : Datum
 3663 andrew                    911 GIC         140 : json_array_element(PG_FUNCTION_ARGS)
                                912                 : {
 2219 noah                      913             140 :     text       *json = PG_GETARG_TEXT_PP(0);
 3663 andrew                    914 CBC         140 :     int         element = PG_GETARG_INT32(1);
                                915                 :     text       *result;
 3663 andrew                    916 ECB             : 
 3152 tgl                       917 CBC         140 :     result = get_worker(json, NULL, &element, 1, false);
                                918                 : 
 3663 andrew                    919 GIC         140 :     if (result != NULL)
                                920             122 :         PG_RETURN_TEXT_P(result);
 3663 andrew                    921 ECB             :     else
 3663 andrew                    922 CBC          18 :         PG_RETURN_NULL();
                                923                 : }
 3663 andrew                    924 ECB             : 
 3304                           925                 : Datum
 3304 andrew                    926 CBC         159 : jsonb_array_element(PG_FUNCTION_ARGS)
                                927                 : {
 2029 tgl                       928 GIC         159 :     Jsonb      *jb = PG_GETARG_JSONB_P(0);
 3304 andrew                    929 CBC         159 :     int         element = PG_GETARG_INT32(1);
 3234 andrew                    930 ECB             :     JsonbValue *v;
                                931                 : 
 3152 tgl                       932 CBC         159 :     if (!JB_ROOT_IS_ARRAY(jb))
 3152 tgl                       933 GIC           9 :         PG_RETURN_NULL();
                                934                 : 
                                935                 :     /* Handle negative subscript */
 2823 andrew                    936 CBC         150 :     if (element < 0)
                                937                 :     {
 2495 rhaas                     938               9 :         uint32      nelements = JB_ROOT_COUNT(jb);
 2823 andrew                    939 ECB             : 
 2823 andrew                    940 GIC           9 :         if (-element > nelements)
                                941               3 :             PG_RETURN_NULL();
 2823 andrew                    942 ECB             :         else
 2823 andrew                    943 GIC           6 :             element += nelements;
 2823 andrew                    944 ECB             :     }
                                945                 : 
 3234 andrew                    946 GIC         147 :     v = getIthJsonbValueFromContainer(&jb->root, element);
 3234 andrew                    947 CBC         147 :     if (v != NULL)
 2029 tgl                       948 GIC         132 :         PG_RETURN_JSONB_P(JsonbValueToJsonb(v));
                                949                 : 
 3304 andrew                    950              15 :     PG_RETURN_NULL();
 3304 andrew                    951 ECB             : }
                                952                 : 
 3663                           953                 : Datum
 3663 andrew                    954 CBC          24 : json_array_element_text(PG_FUNCTION_ARGS)
                                955                 : {
 2219 noah                      956 GIC          24 :     text       *json = PG_GETARG_TEXT_PP(0);
 3663 andrew                    957 CBC          24 :     int         element = PG_GETARG_INT32(1);
 3210 tgl                       958 ECB             :     text       *result;
                                959                 : 
 3152 tgl                       960 GIC          24 :     result = get_worker(json, NULL, &element, 1, true);
 3663 andrew                    961 ECB             : 
 3663 andrew                    962 GIC          24 :     if (result != NULL)
 3663 andrew                    963 CBC          12 :         PG_RETURN_TEXT_P(result);
                                964                 :     else
                                965              12 :         PG_RETURN_NULL();
 3663 andrew                    966 ECB             : }
                                967                 : 
 3304                           968                 : Datum
 3304 andrew                    969 GIC          30 : jsonb_array_element_text(PG_FUNCTION_ARGS)
                                970                 : {
 2029 tgl                       971 CBC          30 :     Jsonb      *jb = PG_GETARG_JSONB_P(0);
 3304 andrew                    972              30 :     int         element = PG_GETARG_INT32(1);
 3234 andrew                    973 ECB             :     JsonbValue *v;
                                974                 : 
 3152 tgl                       975 CBC          30 :     if (!JB_ROOT_IS_ARRAY(jb))
 3152 tgl                       976 GIC           6 :         PG_RETURN_NULL();
                                977                 : 
                                978                 :     /* Handle negative subscript */
 2823 andrew                    979 CBC          24 :     if (element < 0)
                                980                 :     {
 2495 rhaas                     981 LBC           0 :         uint32      nelements = JB_ROOT_COUNT(jb);
 2823 andrew                    982 ECB             : 
 2823 andrew                    983 UIC           0 :         if (-element > nelements)
                                984               0 :             PG_RETURN_NULL();
 2823 andrew                    985 ECB             :         else
 2823 andrew                    986 UIC           0 :             element += nelements;
 2823 andrew                    987 ECB             :     }
                                988                 : 
 3234 andrew                    989 GIC          24 :     v = getIthJsonbValueFromContainer(&jb->root, element);
 3234 andrew                    990 ECB             : 
 1297 alvherre                  991 GIC          24 :     if (v != NULL && v->type != jbvNull)
                                992              12 :         PG_RETURN_TEXT_P(JsonbValueAsText(v));
                                993                 : 
 3304 andrew                    994 CBC          12 :     PG_RETURN_NULL();
                                995                 : }
 3304 andrew                    996 ECB             : 
 3663                           997                 : Datum
 3663 andrew                    998 GIC         144 : json_extract_path(PG_FUNCTION_ARGS)
                                999                 : {
 3152 tgl                      1000 CBC         144 :     return get_path_all(fcinfo, false);
 3663 andrew                   1001 ECB             : }
                               1002                 : 
                               1003                 : Datum
 3663 andrew                   1004 CBC          90 : json_extract_path_text(PG_FUNCTION_ARGS)
                               1005                 : {
 3152 tgl                      1006 GBC          90 :     return get_path_all(fcinfo, true);
                               1007                 : }
 3663 andrew                   1008 EUB             : 
                               1009                 : /*
                               1010                 :  * common routine for extract_path functions
                               1011                 :  */
                               1012                 : static Datum
 3152 tgl                      1013 GIC         234 : get_path_all(FunctionCallInfo fcinfo, bool as_text)
 3663 andrew                   1014 ECB             : {
 2219 noah                     1015 GIC         234 :     text       *json = PG_GETARG_TEXT_PP(0);
 3663 andrew                   1016 CBC         234 :     ArrayType  *path = PG_GETARG_ARRAYTYPE_P(1);
 3663 andrew                   1017 ECB             :     text       *result;
                               1018                 :     Datum      *pathtext;
                               1019                 :     bool       *pathnulls;
                               1020                 :     int         npath;
                               1021                 :     char      **tpath;
                               1022                 :     int        *ipath;
                               1023                 :     int         i;
                               1024                 : 
 3152 tgl                      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                 :      */
 3663 andrew                   1032 GIC         234 :     if (array_contains_nulls(path))
 3152 tgl                      1033               6 :         PG_RETURN_NULL();
                               1034                 : 
  282 peter                    1035 GNC         228 :     deconstruct_array_builtin(path, TEXTOID, &pathtext, &pathnulls, &npath);
                               1036                 : 
 3663 andrew                   1037 CBC         228 :     tpath = palloc(npath * sizeof(char *));
 3663 andrew                   1038 GIC         228 :     ipath = palloc(npath * sizeof(int));
 3663 andrew                   1039 ECB             : 
 3663 andrew                   1040 CBC         624 :     for (i = 0; i < npath; i++)
                               1041                 :     {
 3152 tgl                      1042 GIC         396 :         Assert(!pathnulls[i]);
 3663 andrew                   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                 :          */
 3152 tgl                      1050             396 :         if (*tpath[i] != '\0')
                               1051                 :         {
                               1052                 :             int         ind;
                               1053                 :             char       *endptr;
                               1054                 : 
                               1055             390 :             errno = 0;
  787 tgl                      1056 CBC         390 :             ind = strtoint(tpath[i], &endptr, 10);
                               1057             390 :             if (endptr == tpath[i] || *endptr != '\0' || errno != 0)
 2823 andrew                   1058 GIC         282 :                 ipath[i] = INT_MIN;
  787 tgl                      1059 ECB             :             else
  787 tgl                      1060 GIC         108 :                 ipath[i] = ind;
 3152 tgl                      1061 ECB             :         }
 3663 andrew                   1062                 :         else
 2823 andrew                   1063 GIC           6 :             ipath[i] = INT_MIN;
 3663 andrew                   1064 ECB             :     }
                               1065                 : 
 3152 tgl                      1066 CBC         228 :     result = get_worker(json, tpath, ipath, npath, as_text);
 3663 andrew                   1067 ECB             : 
 3663 andrew                   1068 GIC         228 :     if (result != NULL)
 3260 bruce                    1069             168 :         PG_RETURN_TEXT_P(result);
                               1070                 :     else
 3663 andrew                   1071              60 :         PG_RETURN_NULL();
                               1072                 : }
                               1073                 : 
 3663 andrew                   1074 ECB             : /*
                               1075                 :  * get_worker
                               1076                 :  *
                               1077                 :  * common worker for all the json getter functions
                               1078                 :  *
 3152 tgl                      1079                 :  * json: JSON object (in text form)
                               1080                 :  * tpath[]: field name(s) to extract
 2823 andrew                   1081                 :  * ipath[]: array index(es) (zero-based) to extract, accepts negatives
 3152 tgl                      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
 2823 andrew                   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).
 3663                          1090                 :  */
                               1091                 : static text *
 3663 andrew                   1092 CBC        1344 : get_worker(text *json,
 3663 andrew                   1093 ECB             :            char **tpath,
                               1094                 :            int *ipath,
                               1095                 :            int npath,
                               1096                 :            bool normalize_results)
                               1097                 : {
 3663 andrew                   1098 GIC        1344 :     JsonLexContext *lex = makeJsonLexContext(json, true);
 3152 tgl                      1099            1344 :     JsonSemAction *sem = palloc0(sizeof(JsonSemAction));
                               1100            1344 :     GetState   *state = palloc0(sizeof(GetState));
                               1101                 : 
                               1102            1344 :     Assert(npath >= 0);
                               1103                 : 
 3663 andrew                   1104            1344 :     state->lex = lex;
                               1105                 :     /* is it "_as_text" variant? */
                               1106            1344 :     state->normalize_results = normalize_results;
 3152 tgl                      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)
 3663 andrew                   1114            1314 :         state->pathok[0] = true;
                               1115                 : 
 3663 andrew                   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;
 3152 tgl                      1123            1344 :     if (npath == 0)
 3152 tgl                      1124 ECB             :     {
 3152 tgl                      1125 GIC          30 :         sem->object_start = get_object_start;
 3152 tgl                      1126 CBC          30 :         sem->object_end = get_object_end;
 3152 tgl                      1127 GIC          30 :         sem->array_start = get_array_start;
 3152 tgl                      1128 CBC          30 :         sem->array_end = get_array_end;
                               1129                 :     }
                               1130            1344 :     if (tpath != NULL)
 3663 andrew                   1131 ECB             :     {
 3663 andrew                   1132 CBC        1180 :         sem->object_field_start = get_object_field_start;
                               1133            1180 :         sem->object_field_end = get_object_field_end;
 3663 andrew                   1134 ECB             :     }
 3152 tgl                      1135 CBC        1344 :     if (ipath != NULL)
                               1136                 :     {
                               1137             392 :         sem->array_start = get_array_start;
 3663 andrew                   1138             392 :         sem->array_element_start = get_array_element_start;
 3663 andrew                   1139 GIC         392 :         sem->array_element_end = get_array_element_end;
 3663 andrew                   1140 ECB             :     }
                               1141                 : 
 1168 rhaas                    1142 GIC        1344 :     pg_parse_json_or_ereport(lex, sem);
                               1143                 : 
 3663 andrew                   1144            1329 :     return state->tresult;
                               1145                 : }
 3663 andrew                   1146 ECB             : 
                               1147                 : static JsonParseErrorType
 3663 andrew                   1148 GIC          18 : get_object_start(void *state)
 3663 andrew                   1149 ECB             : {
 3550 peter_e                  1150 CBC          18 :     GetState   *_state = (GetState *) state;
 3152 tgl                      1151              18 :     int         lex_level = _state->lex->lex_level;
 3663 andrew                   1152 ECB             : 
 3152 tgl                      1153 GIC          18 :     if (lex_level == 0 && _state->npath == 0)
 3152 tgl                      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                 :          */
 3152 tgl                      1160 GIC           6 :         _state->result_start = _state->lex->token_start;
 3152 tgl                      1161 ECB             :     }
                               1162                 : 
  119 tgl                      1163 GNC          18 :     return JSON_SUCCESS;
 3663 andrew                   1164 ECB             : }
                               1165                 : 
                               1166                 : static JsonParseErrorType
 3152 tgl                      1167 GIC          18 : get_object_end(void *state)
 3663 andrew                   1168 ECB             : {
 3550 peter_e                  1169 GIC          18 :     GetState   *_state = (GetState *) state;
 3663 andrew                   1170 CBC          18 :     int         lex_level = _state->lex->lex_level;
                               1171                 : 
 3152 tgl                      1172 GIC          18 :     if (lex_level == 0 && _state->npath == 0)
                               1173                 :     {
 3152 tgl                      1174 ECB             :         /* Special case: return the entire object */
 3152 tgl                      1175 GIC           6 :         char       *start = _state->result_start;
 3152 tgl                      1176 CBC           6 :         int         len = _state->lex->prev_token_terminator - start;
 3152 tgl                      1177 ECB             : 
 3152 tgl                      1178 GIC           6 :         _state->tresult = cstring_to_text_with_len(start, len);
 3663 andrew                   1179 ECB             :     }
                               1180                 : 
  119 tgl                      1181 GNC          18 :     return JSON_SUCCESS;
                               1182                 : }
                               1183                 : 
                               1184                 : static JsonParseErrorType
 3152 tgl                      1185 GIC       53456 : get_object_field_start(void *state, char *fname, bool isnull)
                               1186                 : {
                               1187           53456 :     GetState   *_state = (GetState *) state;
 3152 tgl                      1188 CBC       53456 :     bool        get_next = false;
 3152 tgl                      1189 GIC       53456 :     int         lex_level = _state->lex->lex_level;
                               1190                 : 
 3152 tgl                      1191 CBC       53456 :     if (lex_level <= _state->npath &&
 3152 tgl                      1192 GIC       14069 :         _state->pathok[lex_level - 1] &&
                               1193           13949 :         _state->path_names != NULL &&
                               1194           13949 :         _state->path_names[lex_level - 1] != NULL &&
 3152 tgl                      1195 CBC       13949 :         strcmp(fname, _state->path_names[lex_level - 1]) == 0)
                               1196                 :     {
 3663 andrew                   1197            1066 :         if (lex_level < _state->npath)
 3152 tgl                      1198 ECB             :         {
                               1199                 :             /* if not at end of path just mark path ok */
 3663 andrew                   1200 CBC         108 :             _state->pathok[lex_level] = true;
                               1201                 :         }
                               1202                 :         else
 3152 tgl                      1203 ECB             :         {
                               1204                 :             /* end of path, so we want this value */
 3663 andrew                   1205 GIC         958 :             get_next = true;
 3152 tgl                      1206 ECB             :         }
                               1207                 :     }
                               1208                 : 
 3663 andrew                   1209 CBC       53456 :     if (get_next)
                               1210                 :     {
                               1211                 :         /* this object overrides any previous matching object */
 3152 tgl                      1212 GIC         958 :         _state->tresult = NULL;
 3152 tgl                      1213 CBC         958 :         _state->result_start = NULL;
                               1214                 : 
 3663 andrew                   1215             958 :         if (_state->normalize_results &&
                               1216             480 :             _state->lex->token_type == JSON_TOKEN_STRING)
 3663 andrew                   1217 ECB             :         {
                               1218                 :             /* for as_text variants, tell get_scalar to set it for us */
 3663 andrew                   1219 CBC         339 :             _state->next_scalar = true;
 3663 andrew                   1220 ECB             :         }
                               1221                 :         else
                               1222                 :         {
                               1223                 :             /* for non-as_text variants, just note the json starting point */
 3663 andrew                   1224 GIC         619 :             _state->result_start = _state->lex->token_start;
 3663 andrew                   1225 ECB             :         }
                               1226                 :     }
                               1227                 : 
  119 tgl                      1228 GNC       53456 :     return JSON_SUCCESS;
                               1229                 : }
 3663 andrew                   1230 ECB             : 
                               1231                 : static JsonParseErrorType
 3663 andrew                   1232 GIC       53456 : get_object_field_end(void *state, char *fname, bool isnull)
                               1233                 : {
 3550 peter_e                  1234           53456 :     GetState   *_state = (GetState *) state;
 3663 andrew                   1235 CBC       53456 :     bool        get_last = false;
 3663 andrew                   1236 GIC       53456 :     int         lex_level = _state->lex->lex_level;
                               1237                 : 
                               1238                 :     /* same tests as in get_object_field_start */
 3152 tgl                      1239 CBC       53456 :     if (lex_level <= _state->npath &&
 3152 tgl                      1240 GIC       14069 :         _state->pathok[lex_level - 1] &&
                               1241           13949 :         _state->path_names != NULL &&
 3152 tgl                      1242 CBC       13949 :         _state->path_names[lex_level - 1] != NULL &&
                               1243           13949 :         strcmp(fname, _state->path_names[lex_level - 1]) == 0)
                               1244                 :     {
 3663 andrew                   1245            1066 :         if (lex_level < _state->npath)
 3152 tgl                      1246 ECB             :         {
                               1247                 :             /* done with this field so reset pathok */
 3663 andrew                   1248 GIC         108 :             _state->pathok[lex_level] = false;
 3152 tgl                      1249 ECB             :         }
                               1250                 :         else
                               1251                 :         {
                               1252                 :             /* end of path, so we want this value */
 3663 andrew                   1253 GIC         958 :             get_last = true;
 3152 tgl                      1254 ECB             :         }
                               1255                 :     }
                               1256                 : 
                               1257                 :     /* for as_text scalar case, our work is already done */
 3663 andrew                   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
 3663 andrew                   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                 :          */
 3663 andrew                   1265 CBC         619 :         if (isnull && _state->normalize_results)
                               1266              12 :             _state->tresult = (text *) NULL;
                               1267                 :         else
                               1268                 :         {
 3152 tgl                      1269             607 :             char       *start = _state->result_start;
                               1270             607 :             int         len = _state->lex->prev_token_terminator - start;
 3663 andrew                   1271 ECB             : 
 3152 tgl                      1272 CBC         607 :             _state->tresult = cstring_to_text_with_len(start, len);
 3152 tgl                      1273 ECB             :         }
                               1274                 : 
                               1275                 :         /* this should be unnecessary but let's do it for cleanliness: */
 3152 tgl                      1276 GIC         619 :         _state->result_start = NULL;
                               1277                 :     }
                               1278                 : 
  119 tgl                      1279 GNC       53456 :     return JSON_SUCCESS;
 3663 andrew                   1280 ECB             : }
                               1281                 : 
                               1282                 : static JsonParseErrorType
 3663 andrew                   1283 GIC         928 : get_array_start(void *state)
                               1284                 : {
 3550 peter_e                  1285 CBC         928 :     GetState   *_state = (GetState *) state;
 3663 andrew                   1286 GIC         928 :     int         lex_level = _state->lex->lex_level;
                               1287                 : 
 3152 tgl                      1288             928 :     if (lex_level < _state->npath)
                               1289                 :     {
 3152 tgl                      1290 ECB             :         /* Initialize counting of elements in this array */
 3152 tgl                      1291 GIC         257 :         _state->array_cur_index[lex_level] = -1;
                               1292                 : 
                               1293                 :         /* INT_MIN value is reserved to represent invalid subscript */
 2812 andrew                   1294             257 :         if (_state->path_indexes[lex_level] < 0 &&
                               1295              15 :             _state->path_indexes[lex_level] != INT_MIN)
                               1296                 :         {
 2812 andrew                   1297 ECB             :             /* Negative subscript -- convert to positive-wise subscript */
 1168 rhaas                    1298                 :             JsonParseErrorType error;
                               1299                 :             int         nelements;
                               1300                 : 
 1168 rhaas                    1301 CBC           3 :             error = json_count_array_elements(_state->lex, &nelements);
                               1302               3 :             if (error != JSON_SUCCESS)
  119 tgl                      1303 UNC           0 :                 json_errsave_error(error, _state->lex, NULL);
 2812 andrew                   1304 ECB             : 
 2812 andrew                   1305 GIC           3 :             if (-_state->path_indexes[lex_level] <= nelements)
                               1306               3 :                 _state->path_indexes[lex_level] += nelements;
                               1307                 :         }
 3152 tgl                      1308 ECB             :     }
 3152 tgl                      1309 GIC         671 :     else if (lex_level == 0 && _state->npath == 0)
                               1310                 :     {
 3152 tgl                      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                 :          */
 3152 tgl                      1316 GIC           6 :         _state->result_start = _state->lex->token_start;
 3152 tgl                      1317 ECB             :     }
                               1318                 : 
  119 tgl                      1319 GNC         928 :     return JSON_SUCCESS;
 3152 tgl                      1320 ECB             : }
                               1321                 : 
                               1322                 : static JsonParseErrorType
 3152 tgl                      1323 GIC           6 : get_array_end(void *state)
                               1324                 : {
 3152 tgl                      1325 CBC           6 :     GetState   *_state = (GetState *) state;
 3152 tgl                      1326 GIC           6 :     int         lex_level = _state->lex->lex_level;
                               1327                 : 
 3152 tgl                      1328 CBC           6 :     if (lex_level == 0 && _state->npath == 0)
 3152 tgl                      1329 ECB             :     {
                               1330                 :         /* Special case: return the entire array */
 3152 tgl                      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);
 3152 tgl                      1335 ECB             :     }
                               1336                 : 
  119 tgl                      1337 GNC           6 :     return JSON_SUCCESS;
 3663 andrew                   1338 ECB             : }
 3663 andrew                   1339 EUB             : 
                               1340                 : static JsonParseErrorType
 3663 andrew                   1341 CBC         965 : get_array_element_start(void *state, bool isnull)
 3663 andrew                   1342 ECB             : {
 3550 peter_e                  1343 GIC         965 :     GetState   *_state = (GetState *) state;
 3663 andrew                   1344             965 :     bool        get_next = false;
 3663 andrew                   1345 CBC         965 :     int         lex_level = _state->lex->lex_level;
                               1346                 : 
                               1347                 :     /* Update array element counter */
 3152 tgl                      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 &&
 3152 tgl                      1352 CBC         488 :         _state->pathok[lex_level - 1] &&
 3152 tgl                      1353 GIC         488 :         _state->path_indexes != NULL &&
                               1354             488 :         _state->array_cur_index[lex_level - 1] == _state->path_indexes[lex_level - 1])
 3663 andrew                   1355 ECB             :     {
 3152 tgl                      1356 GIC         239 :         if (lex_level < _state->npath)
                               1357                 :         {
                               1358                 :             /* if not at end of path just mark path ok */
 3152 tgl                      1359 CBC          72 :             _state->pathok[lex_level] = true;
                               1360                 :         }
 3152 tgl                      1361 ECB             :         else
                               1362                 :         {
                               1363                 :             /* end of path, so we want this value */
 3152 tgl                      1364 CBC         167 :             get_next = true;
                               1365                 :         }
                               1366                 :     }
 3663 andrew                   1367 ECB             : 
                               1368                 :     /* same logic as for objects */
 3663 andrew                   1369 GIC         965 :     if (get_next)
 3663 andrew                   1370 ECB             :     {
 3152 tgl                      1371 GIC         167 :         _state->tresult = NULL;
                               1372             167 :         _state->result_start = NULL;
 3152 tgl                      1373 ECB             : 
 3663 andrew                   1374 GIC         167 :         if (_state->normalize_results &&
                               1375              30 :             _state->lex->token_type == JSON_TOKEN_STRING)
                               1376                 :         {
 3663 andrew                   1377 CBC           9 :             _state->next_scalar = true;
                               1378                 :         }
 3663 andrew                   1379 ECB             :         else
                               1380                 :         {
 3663 andrew                   1381 CBC         158 :             _state->result_start = _state->lex->token_start;
                               1382                 :         }
                               1383                 :     }
                               1384                 : 
  119 tgl                      1385 GNC         965 :     return JSON_SUCCESS;
 3663 andrew                   1386 ECB             : }
                               1387                 : 
                               1388                 : static JsonParseErrorType
 3663 andrew                   1389 CBC         965 : get_array_element_end(void *state, bool isnull)
 3663 andrew                   1390 ECB             : {
 3550 peter_e                  1391 CBC         965 :     GetState   *_state = (GetState *) state;
 3663 andrew                   1392             965 :     bool        get_last = false;
 3663 andrew                   1393 GIC         965 :     int         lex_level = _state->lex->lex_level;
 3663 andrew                   1394 ECB             : 
                               1395                 :     /* same tests as in get_array_element_start */
 3152 tgl                      1396 GIC         965 :     if (lex_level <= _state->npath &&
 3152 tgl                      1397 CBC         488 :         _state->pathok[lex_level - 1] &&
 3152 tgl                      1398 GIC         488 :         _state->path_indexes != NULL &&
                               1399             488 :         _state->array_cur_index[lex_level - 1] == _state->path_indexes[lex_level - 1])
                               1400                 :     {
 3663 andrew                   1401             239 :         if (lex_level < _state->npath)
 3152 tgl                      1402 ECB             :         {
                               1403                 :             /* done with this element so reset pathok */
 3663 andrew                   1404 GIC          72 :             _state->pathok[lex_level] = false;
                               1405                 :         }
                               1406                 :         else
 3152 tgl                      1407 ECB             :         {
                               1408                 :             /* end of path, so we want this value */
 3663 andrew                   1409 CBC         167 :             get_last = true;
 3152 tgl                      1410 ECB             :         }
                               1411                 :     }
                               1412                 : 
                               1413                 :     /* same logic as for objects */
 3663 andrew                   1414 GIC         965 :     if (get_last && _state->result_start != NULL)
 3663 andrew                   1415 ECB             :     {
 3663 andrew                   1416 GIC         158 :         if (isnull && _state->normalize_results)
                               1417               6 :             _state->tresult = (text *) NULL;
                               1418                 :         else
 3152 tgl                      1419 ECB             :         {
 3152 tgl                      1420 GIC         152 :             char       *start = _state->result_start;
                               1421             152 :             int         len = _state->lex->prev_token_terminator - start;
                               1422                 : 
 3152 tgl                      1423 CBC         152 :             _state->tresult = cstring_to_text_with_len(start, len);
                               1424                 :         }
                               1425                 : 
 3152 tgl                      1426 GIC         158 :         _state->result_start = NULL;
 3663 andrew                   1427 ECB             :     }
                               1428                 : 
  119 tgl                      1429 GNC         965 :     return JSON_SUCCESS;
                               1430                 : }
 3663 andrew                   1431 ECB             : 
                               1432                 : static JsonParseErrorType
 3663 andrew                   1433 CBC       52731 : get_scalar(void *state, char *token, JsonTokenType tokentype)
                               1434                 : {
 3550 peter_e                  1435 GIC       52731 :     GetState   *_state = (GetState *) state;
 3152 tgl                      1436 CBC       52731 :     int         lex_level = _state->lex->lex_level;
 3152 tgl                      1437 ECB             : 
                               1438                 :     /* Check for whole-object match */
 3152 tgl                      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                 :         }
 3152 tgl                      1446 GIC          15 :         else if (_state->normalize_results && tokentype == JSON_TOKEN_NULL)
                               1447                 :         {
                               1448               3 :             _state->tresult = (text *) NULL;
 3152 tgl                      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                 :              */
 3152 tgl                      1457 CBC          12 :             char       *start = _state->lex->input;
 3152 tgl                      1458 GIC          12 :             int         len = _state->lex->prev_token_terminator - start;
                               1459                 : 
 3152 tgl                      1460 CBC          12 :             _state->tresult = cstring_to_text_with_len(start, len);
 3152 tgl                      1461 ECB             :         }
                               1462                 :     }
 3663 andrew                   1463                 : 
 3663 andrew                   1464 GIC       52731 :     if (_state->next_scalar)
                               1465                 :     {
 3663 andrew                   1466 ECB             :         /* a de-escaped text value is wanted, so supply it */
 3663 andrew                   1467 GIC         351 :         _state->tresult = cstring_to_text(token);
                               1468                 :         /* make sure the next call to get_scalar doesn't overwrite it */
 3663 andrew                   1469 CBC         351 :         _state->next_scalar = false;
                               1470                 :     }
                               1471                 : 
  119 tgl                      1472 GNC       52731 :     return JSON_SUCCESS;
                               1473                 : }
                               1474                 : 
 3304 andrew                   1475 ECB             : Datum
 3304 andrew                   1476 GIC         135 : jsonb_extract_path(PG_FUNCTION_ARGS)
 3304 andrew                   1477 ECB             : {
 3152 tgl                      1478 CBC         135 :     return get_jsonb_path_all(fcinfo, false);
                               1479                 : }
                               1480                 : 
 3304 andrew                   1481 ECB             : Datum
 3304 andrew                   1482 GIC          90 : jsonb_extract_path_text(PG_FUNCTION_ARGS)
 3304 andrew                   1483 ECB             : {
 3152 tgl                      1484 GIC          90 :     return get_jsonb_path_all(fcinfo, true);
                               1485                 : }
 3304 andrew                   1486 ECB             : 
                               1487                 : static Datum
 3152 tgl                      1488 CBC         225 : get_jsonb_path_all(FunctionCallInfo fcinfo, bool as_text)
                               1489                 : {
 2029                          1490             225 :     Jsonb      *jb = PG_GETARG_JSONB_P(0);
 3304 andrew                   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                 :     /*
 3152 tgl                      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                 :      */
 3304 andrew                   1505 GIC         225 :     if (array_contains_nulls(path))
 3152 tgl                      1506 CBC           6 :         PG_RETURN_NULL();
                               1507                 : 
  282 peter                    1508 GNC         219 :     deconstruct_array_builtin(path, TEXTOID, &pathtext, &pathnulls, &npath);
                               1509                 : 
  798 akorotkov                1510 CBC         219 :     res = jsonb_get_element(jb, pathtext, npath, &isnull, as_text);
                               1511                 : 
  798 akorotkov                1512 GIC         219 :     if (isnull)
  798 akorotkov                1513 CBC          69 :         PG_RETURN_NULL();
                               1514                 :     else
  798 akorotkov                1515 GIC         150 :         PG_RETURN_DATUM(res);
                               1516                 : }
  798 akorotkov                1517 ECB             : 
                               1518                 : Datum
  798 akorotkov                1519 CBC         315 : jsonb_get_element(Jsonb *jb, Datum *path, int npath, bool *isnull, bool as_text)
                               1520                 : {
  798 akorotkov                1521 GIC         315 :     JsonbContainer *container = &jb->root;
                               1522             315 :     JsonbValue *jbvp = NULL;
  798 akorotkov                1523 ECB             :     int         i;
  798 akorotkov                1524 GIC         315 :     bool        have_object = false,
  798 akorotkov                1525 CBC         315 :                 have_array = false;
                               1526                 : 
  798 akorotkov                1527 GIC         315 :     *isnull = false;
                               1528                 : 
  798 akorotkov                1529 ECB             :     /* Identify whether we have object, array, or scalar at top-level */
 3304 andrew                   1530 GIC         315 :     if (JB_ROOT_IS_OBJECT(jb))
 3304 andrew                   1531 CBC         210 :         have_object = true;
                               1532             105 :     else if (JB_ROOT_IS_ARRAY(jb) && !JB_ROOT_IS_SCALAR(jb))
 3304 andrew                   1533 GIC          63 :         have_array = true;
                               1534                 :     else
                               1535                 :     {
 3152 tgl                      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
 3152 tgl                      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                 :      */
 3152 tgl                      1550 GIC         315 :     if (npath <= 0 && jbvp == NULL)
 3152 tgl                      1551 ECB             :     {
 3152 tgl                      1552 GIC          12 :         if (as_text)
 3152 tgl                      1553 ECB             :         {
  798 akorotkov                1554 CBC           6 :             return PointerGetDatum(cstring_to_text(JsonbToCString(NULL,
                               1555                 :                                                                   container,
                               1556               6 :                                                                   VARSIZE(jb))));
                               1557                 :         }
                               1558                 :         else
                               1559                 :         {
 3152 tgl                      1560 ECB             :             /* not text mode - just hand back the jsonb */
 2029 tgl                      1561 GIC           6 :             PG_RETURN_JSONB_P(jb);
 3152 tgl                      1562 ECB             :         }
                               1563                 :     }
                               1564                 : 
 3304 andrew                   1565 CBC         504 :     for (i = 0; i < npath; i++)
 3304 andrew                   1566 ECB             :     {
 3304 andrew                   1567 GIC         486 :         if (have_object)
 3304 andrew                   1568 ECB             :         {
  118 tgl                      1569 GIC         312 :             text       *subscr = DatumGetTextPP(path[i]);
                               1570                 : 
 1297 alvherre                 1571 CBC         624 :             jbvp = getKeyJsonValueFromContainer(container,
  118 tgl                      1572             312 :                                                 VARDATA_ANY(subscr),
                               1573             312 :                                                 VARSIZE_ANY_EXHDR(subscr),
  798 akorotkov                1574 ECB             :                                                 NULL);
                               1575                 :         }
 3304 andrew                   1576 GIC         174 :         else if (have_array)
 3304 andrew                   1577 ECB             :         {
                               1578                 :             int         lindex;
                               1579                 :             uint32      index;
  798 akorotkov                1580 CBC         135 :             char       *indextext = TextDatumGetCString(path[i]);
                               1581                 :             char       *endptr;
                               1582                 : 
 3152 tgl                      1583 GIC         135 :             errno = 0;
  787                          1584             135 :             lindex = strtoint(indextext, &endptr, 10);
                               1585             135 :             if (endptr == indextext || *endptr != '\0' || errno != 0)
                               1586                 :             {
  798 akorotkov                1587              18 :                 *isnull = true;
                               1588              21 :                 return PointerGetDatum(NULL);
                               1589                 :             }
                               1590                 : 
 2823 andrew                   1591 CBC         117 :             if (lindex >= 0)
                               1592                 :             {
                               1593             105 :                 index = (uint32) lindex;
                               1594                 :             }
 2823 andrew                   1595 ECB             :             else
                               1596                 :             {
                               1597                 :                 /* Handle negative subscript */
                               1598                 :                 uint32      nelements;
                               1599                 : 
                               1600                 :                 /* Container must be array, but make sure */
 2265 tgl                      1601 GIC          12 :                 if (!JsonContainerIsArray(container))
 2823 andrew                   1602 LBC           0 :                     elog(ERROR, "not a jsonb array");
                               1603                 : 
 2265 tgl                      1604 GIC          12 :                 nelements = JsonContainerSize(container);
                               1605                 : 
  787 tgl                      1606 CBC          12 :                 if (lindex == INT_MIN || -lindex > nelements)
                               1607                 :                 {
  798 akorotkov                1608               3 :                     *isnull = true;
  798 akorotkov                1609 GIC           3 :                     return PointerGetDatum(NULL);
  798 akorotkov                1610 ECB             :                 }
                               1611                 :                 else
 2823 andrew                   1612 CBC           9 :                     index = nelements + lindex;
 2823 andrew                   1613 ECB             :             }
                               1614                 : 
 3259 heikki.linnakangas       1615 GIC         114 :             jbvp = getIthJsonbValueFromContainer(container, index);
                               1616                 :         }
 3304 andrew                   1617 ECB             :         else
                               1618                 :         {
                               1619                 :             /* scalar, extraction yields a null */
  798 akorotkov                1620 GIC          39 :             *isnull = true;
  798 akorotkov                1621 CBC          39 :             return PointerGetDatum(NULL);
                               1622                 :         }
                               1623                 : 
 3304 andrew                   1624             426 :         if (jbvp == NULL)
  798 akorotkov                1625 ECB             :         {
  798 akorotkov                1626 CBC          39 :             *isnull = true;
  798 akorotkov                1627 GIC          39 :             return PointerGetDatum(NULL);
  798 akorotkov                1628 ECB             :         }
 3304 andrew                   1629 CBC         387 :         else if (i == npath - 1)
 3304 andrew                   1630 GIC         186 :             break;
                               1631                 : 
 3304 andrew                   1632 CBC         201 :         if (jbvp->type == jbvBinary)
                               1633                 :         {
 1297 alvherre                 1634             186 :             container = jbvp->val.binary.data;
 1297 alvherre                 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));
 1297 alvherre                 1642 CBC          15 :             have_object = false;
 1297 alvherre                 1643 GBC          15 :             have_array = false;
                               1644                 :         }
 3304 andrew                   1645 ECB             :     }
                               1646                 : 
 3304 andrew                   1647 CBC         204 :     if (as_text)
                               1648                 :     {
 3152 tgl                      1649              57 :         if (jbvp->type == jbvNull)
  798 akorotkov                1650 ECB             :         {
  798 akorotkov                1651 GIC          12 :             *isnull = true;
                               1652              12 :             return PointerGetDatum(NULL);
  798 akorotkov                1653 ECB             :         }
                               1654                 : 
  798 akorotkov                1655 GIC          45 :         return PointerGetDatum(JsonbValueAsText(jbvp));
 3304 andrew                   1656 ECB             :     }
                               1657                 :     else
                               1658                 :     {
 1297 alvherre                 1659 GIC         147 :         Jsonb      *res = JsonbValueToJsonb(jbvp);
                               1660                 : 
 3304 andrew                   1661 ECB             :         /* not text mode - just hand back the jsonb */
 2029 tgl                      1662 CBC         147 :         PG_RETURN_JSONB_P(res);
                               1663                 :     }
                               1664                 : }
 3304 andrew                   1665 ECB             : 
                               1666                 : Datum
  798 akorotkov                1667 CBC         123 : jsonb_set_element(Jsonb *jb, Datum *path, int path_len,
  798 akorotkov                1668 ECB             :                   JsonbValue *newval)
                               1669                 : {
                               1670                 :     JsonbValue *res;
  798 akorotkov                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)
  798 akorotkov                1676 LBC           0 :         *newval = newval->val.array.elems[0];
  798 akorotkov                1677 ECB             : 
  798 akorotkov                1678 CBC         123 :     it = JsonbIteratorInit(&jb->root);
                               1679                 : 
  798 akorotkov                1680 GIC         123 :     res = setPath(&it, path, path_nulls, path_len, &state, 0, newval,
                               1681                 :                   JB_PATH_CREATE | JB_PATH_FILL_GAPS |
  798 akorotkov                1682 ECB             :                   JB_PATH_CONSISTENT_POSITION);
                               1683                 : 
  798 akorotkov                1684 CBC          99 :     pfree(path_nulls);
                               1685                 : 
  798 akorotkov                1686 GIC          99 :     PG_RETURN_JSONB_P(JsonbValueToJsonb(res));
                               1687                 : }
  798 akorotkov                1688 ECB             : 
                               1689                 : static void
  798 akorotkov                1690 CBC          54 : push_null_elements(JsonbParseState **ps, int num)
                               1691                 : {
  798 akorotkov                1692 ECB             :     JsonbValue  null;
                               1693                 : 
  798 akorotkov                1694 GIC          54 :     null.type = jbvNull;
                               1695                 : 
  798 akorotkov                1696 CBC         204 :     while (num-- > 0)
  798 akorotkov                1697 GIC         150 :         pushJsonbValue(ps, WJB_ELEM, &null);
                               1698              54 : }
                               1699                 : 
  798 akorotkov                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
  798 akorotkov                1709 GIC          36 : push_path(JsonbParseState **st, int level, Datum *path_elems,
                               1710                 :           bool *path_nulls, int path_len, JsonbValue *newval)
                               1711                 : {
  798 akorotkov                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.
  798 akorotkov                1717 EUB             :      */
  798 akorotkov                1718 GIC          36 :     enum jbvType *tpath = palloc0((path_len - level) * sizeof(enum jbvType));
  798 akorotkov                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                 :      */
  798 akorotkov                1726 GIC         108 :     for (int i = level + 1; i < path_len; i++)
  798 akorotkov                1727 ECB             :     {
                               1728                 :         char       *c,
                               1729                 :                    *badp;
                               1730                 :         int         lindex;
                               1731                 : 
  798 akorotkov                1732 GIC          72 :         if (path_nulls[i])
  798 akorotkov                1733 UIC           0 :             break;
                               1734                 : 
  798 akorotkov                1735 ECB             :         /*
                               1736                 :          * Try to convert to an integer to find out the expected type, object
                               1737                 :          * or array.
                               1738                 :          */
  798 akorotkov                1739 CBC          72 :         c = TextDatumGetCString(path_elems[i]);
  798 akorotkov                1740 GIC          72 :         errno = 0;
  787 tgl                      1741              72 :         lindex = strtoint(c, &badp, 10);
                               1742              72 :         if (badp == c || *badp != '\0' || errno != 0)
                               1743                 :         {
                               1744                 :             /* text, an object is expected */
  798 akorotkov                1745              33 :             newkey.type = jbvString;
  118 tgl                      1746              33 :             newkey.val.string.val = c;
                               1747              33 :             newkey.val.string.len = strlen(c);
                               1748                 : 
  798 akorotkov                1749              33 :             (void) pushJsonbValue(st, WJB_BEGIN_OBJECT, NULL);
  798 akorotkov                1750 CBC          33 :             (void) pushJsonbValue(st, WJB_KEY, &newkey);
                               1751                 : 
  798 akorotkov                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                 : 
  798 akorotkov                1759 CBC          39 :             push_null_elements(st, lindex);
                               1760                 : 
  798 akorotkov                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)
  798 akorotkov                1767 ECB             :     {
  798 akorotkov                1768 GIC          24 :         (void) pushJsonbValue(st, WJB_ELEM, newval);
                               1769                 :     }
                               1770                 :     else
                               1771              12 :         (void) pushJsonbValue(st, WJB_VALUE, newval);
                               1772                 : 
  798 akorotkov                1773 ECB             :     /*
  798 akorotkov                1774 EUB             :      * Close everything up to the last but one level. The last one will be
                               1775                 :      * closed outside of this function.
                               1776                 :      */
  798 akorotkov                1777 GIC         108 :     for (int i = path_len - 1; i > level; i--)
                               1778                 :     {
                               1779              72 :         if (path_nulls[i])
  798 akorotkov                1780 LBC           0 :             break;
  798 akorotkov                1781 ECB             : 
  798 akorotkov                1782 CBC          72 :         if (tpath[i - level] == jbvObject)
                               1783              33 :             (void) pushJsonbValue(st, WJB_END_OBJECT, NULL);
                               1784                 :         else
  798 akorotkov                1785 GIC          39 :             (void) pushJsonbValue(st, WJB_END_ARRAY, NULL);
  798 akorotkov                1786 ECB             :     }
  798 akorotkov                1787 CBC          36 : }
  798 akorotkov                1788 ECB             : 
                               1789                 : /*
 1297 alvherre                 1790                 :  * Return the text representation of the given JsonbValue.
                               1791                 :  */
                               1792                 : static text *
 1297 alvherre                 1793 CBC         210 : JsonbValueAsText(JsonbValue *v)
                               1794                 : {
 1297 alvherre                 1795 GIC         210 :     switch (v->type)
                               1796                 :     {
 1297 alvherre                 1797 UIC           0 :         case jbvNull:
 1297 alvherre                 1798 LBC           0 :             return NULL;
                               1799                 : 
 1297 alvherre                 1800 CBC          12 :         case jbvBool:
 1297 alvherre                 1801 GIC          12 :             return v->val.boolean ?
 1297 alvherre                 1802 CBC          18 :                 cstring_to_text_with_len("true", 4) :
 1297 alvherre                 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,
 1297 alvherre                 1807 ECB             :                                             v->val.string.len);
                               1808                 : 
 1297 alvherre                 1809 CBC          21 :         case jbvNumeric:
                               1810                 :             {
                               1811                 :                 Datum       cstr;
 1297 alvherre                 1812 ECB             : 
 1297 alvherre                 1813 GIC          21 :                 cstr = DirectFunctionCall1(numeric_out,
                               1814                 :                                            PointerGetDatum(v->val.numeric));
                               1815                 : 
                               1816              21 :                 return cstring_to_text(DatumGetCString(cstr));
                               1817                 :             }
 1297 alvherre                 1818 ECB             : 
 1297 alvherre                 1819 GIC          63 :         case jbvBinary:
 1297 alvherre                 1820 ECB             :             {
 1297 alvherre                 1821 EUB             :                 StringInfoData jtext;
                               1822                 : 
 1297 alvherre                 1823 CBC          63 :                 initStringInfo(&jtext);
                               1824              63 :                 (void) JsonbToCString(&jtext, v->val.binary.data,
                               1825                 :                                       v->val.binary.len);
 1297 alvherre                 1826 ECB             : 
 1297 alvherre                 1827 GIC          63 :                 return cstring_to_text_with_len(jtext.data, jtext.len);
 1297 alvherre                 1828 ECB             :             }
                               1829                 : 
 1297 alvherre                 1830 UIC           0 :         default:
                               1831               0 :             elog(ERROR, "unrecognized jsonb type: %d", (int) v->type);
                               1832                 :             return NULL;
                               1833                 :     }
 1297 alvherre                 1834 ECB             : }
                               1835                 : 
 3663 andrew                   1836                 : /*
                               1837                 :  * SQL function json_array_length(json) -> int
 3663 andrew                   1838 EUB             :  */
                               1839                 : Datum
 3663 andrew                   1840 GIC          12 : json_array_length(PG_FUNCTION_ARGS)
 3663 andrew                   1841 ECB             : {
 2219 noah                     1842 CBC          12 :     text       *json = PG_GETARG_TEXT_PP(0);
 3550 peter_e                  1843 ECB             :     AlenState  *state;
 3304 andrew                   1844                 :     JsonLexContext *lex;
                               1845                 :     JsonSemAction *sem;
 3663                          1846                 : 
 3304 andrew                   1847 CBC          12 :     lex = makeJsonLexContext(json, false);
 3550 peter_e                  1848 GIC          12 :     state = palloc0(sizeof(AlenState));
                               1849              12 :     sem = palloc0(sizeof(JsonSemAction));
 3663 andrew                   1850 ECB             : 
                               1851                 :     /* palloc0 does this for us */
                               1852                 : #if 0
                               1853                 :     state->count = 0;
                               1854                 : #endif
 3663 andrew                   1855 GIC          12 :     state->lex = lex;
                               1856                 : 
 3663 andrew                   1857 CBC          12 :     sem->semstate = (void *) state;
 3663 andrew                   1858 GIC          12 :     sem->object_start = alen_object_start;
                               1859              12 :     sem->scalar = alen_scalar;
 3663 andrew                   1860 CBC          12 :     sem->array_element_start = alen_array_element_start;
                               1861                 : 
 1168 rhaas                    1862 GIC          12 :     pg_parse_json_or_ereport(lex, sem);
                               1863                 : 
 3663 andrew                   1864 CBC           6 :     PG_RETURN_INT32(state->count);
 3663 andrew                   1865 ECB             : }
                               1866                 : 
                               1867                 : Datum
 3304 andrew                   1868 CBC         156 : jsonb_array_length(PG_FUNCTION_ARGS)
                               1869                 : {
 2029 tgl                      1870 GIC         156 :     Jsonb      *jb = PG_GETARG_JSONB_P(0);
 3304 andrew                   1871 EUB             : 
 3304 andrew                   1872 GBC         156 :     if (JB_ROOT_IS_SCALAR(jb))
 3304 andrew                   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                 : 
 3304 andrew                   1881 CBC         150 :     PG_RETURN_INT32(JB_ROOT_COUNT(jb));
                               1882                 : }
 3304 andrew                   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                 :  */
 3663                          1888                 : 
                               1889                 : static JsonParseErrorType
 3663 andrew                   1890 CBC           6 : alen_object_start(void *state)
                               1891                 : {
 3550 peter_e                  1892 GIC           6 :     AlenState  *_state = (AlenState *) state;
                               1893                 : 
                               1894                 :     /* json structure check */
 3663 andrew                   1895               6 :     if (_state->lex->lex_level == 0)
 3663 andrew                   1896 CBC           3 :         ereport(ERROR,
                               1897                 :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
 3663 andrew                   1898 ECB             :                  errmsg("cannot get array length of a non-array")));
                               1899                 : 
  119 tgl                      1900 GNC           3 :     return JSON_SUCCESS;
 3663 andrew                   1901 ECB             : }
                               1902                 : 
                               1903                 : static JsonParseErrorType
 3663 andrew                   1904 GIC          24 : alen_scalar(void *state, char *token, JsonTokenType tokentype)
 3663 andrew                   1905 ECB             : {
 3550 peter_e                  1906 GIC          24 :     AlenState  *_state = (AlenState *) state;
 3663 andrew                   1907 ECB             : 
                               1908                 :     /* json structure check */
 3663 andrew                   1909 GIC          24 :     if (_state->lex->lex_level == 0)
                               1910               3 :         ereport(ERROR,
 3663 andrew                   1911 ECB             :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                               1912                 :                  errmsg("cannot get array length of a scalar")));
                               1913                 : 
  119 tgl                      1914 GNC          21 :     return JSON_SUCCESS;
 3663 andrew                   1915 ECB             : }
                               1916                 : 
                               1917                 : static JsonParseErrorType
 3663 andrew                   1918 CBC          21 : alen_array_element_start(void *state, bool isnull)
                               1919                 : {
 3550 peter_e                  1920 GIC          21 :     AlenState  *_state = (AlenState *) state;
 3663 andrew                   1921 ECB             : 
                               1922                 :     /* just count up all the level 1 elements */
 3663 andrew                   1923 GIC          21 :     if (_state->lex->lex_level == 1)
                               1924              15 :         _state->count++;
                               1925                 : 
  119 tgl                      1926 GNC          21 :     return JSON_SUCCESS;
                               1927                 : }
 3663 andrew                   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
 3663 andrew                   1940 GIC           6 : json_each(PG_FUNCTION_ARGS)
                               1941                 : {
 3663 andrew                   1942 CBC           6 :     return each_worker(fcinfo, false);
 3663 andrew                   1943 ECB             : }
                               1944                 : 
                               1945                 : Datum
 3304 andrew                   1946 GIC        6084 : jsonb_each(PG_FUNCTION_ARGS)
 3304 andrew                   1947 ECB             : {
 3210 tgl                      1948 GIC        6084 :     return each_worker_jsonb(fcinfo, "jsonb_each", false);
                               1949                 : }
                               1950                 : 
 3663 andrew                   1951 ECB             : Datum
 3663 andrew                   1952 GIC           6 : json_each_text(PG_FUNCTION_ARGS)
 3663 andrew                   1953 ECB             : {
 3663 andrew                   1954 GIC           6 :     return each_worker(fcinfo, true);
                               1955                 : }
 3663 andrew                   1956 ECB             : 
 3304                          1957                 : Datum
 3304 andrew                   1958 GIC          12 : jsonb_each_text(PG_FUNCTION_ARGS)
                               1959                 : {
 3210 tgl                      1960              12 :     return each_worker_jsonb(fcinfo, "jsonb_each_text", true);
 3304 andrew                   1961 ECB             : }
                               1962                 : 
                               1963                 : static Datum
 3210 tgl                      1964 GIC        6096 : each_worker_jsonb(FunctionCallInfo fcinfo, const char *funcname, bool as_text)
 3663 andrew                   1965 ECB             : {
 2029 tgl                      1966 GIC        6096 :     Jsonb      *jb = PG_GETARG_JSONB_P(0);
 3304 andrew                   1967 ECB             :     ReturnSetInfo *rsi;
                               1968                 :     MemoryContext old_cxt,
                               1969                 :                 tmp_cxt;
 3304 andrew                   1970 CBC        6096 :     bool        skipNested = false;
 3304 andrew                   1971 ECB             :     JsonbIterator *it;
                               1972                 :     JsonbValue  v;
 2737 noah                     1973                 :     JsonbIteratorToken r;
                               1974                 : 
 3304 andrew                   1975 GIC        6096 :     if (!JB_ROOT_IS_OBJECT(jb))
 3304 andrew                   1976 UIC           0 :         ereport(ERROR,
                               1977                 :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                               1978                 :                  errmsg("cannot call %s on a non-object",
                               1979                 :                         funcname)));
                               1980                 : 
 3304 andrew                   1981 GIC        6096 :     rsi = (ReturnSetInfo *) fcinfo->resultinfo;
  173 michael                  1982            6096 :     InitMaterializedSRF(fcinfo, MAT_SRF_BLESS);
                               1983                 : 
 3304 andrew                   1984            6096 :     tmp_cxt = AllocSetContextCreate(CurrentMemoryContext,
                               1985                 :                                     "jsonb_each temporary cxt",
                               1986                 :                                     ALLOCSET_DEFAULT_SIZES);
 3304 andrew                   1987 ECB             : 
 3259 heikki.linnakangas       1988 GIC        6096 :     it = JsonbIteratorInit(&jb->root);
 3304 andrew                   1989 ECB             : 
 3304 andrew                   1990 GIC       47145 :     while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE)
                               1991                 :     {
                               1992           41049 :         skipNested = true;
 3304 andrew                   1993 ECB             : 
 3304 andrew                   1994 GIC       41049 :         if (r == WJB_KEY)
 3304 andrew                   1995 ECB             :         {
                               1996                 :             text       *key;
                               1997                 :             Datum       values[2];
 3304 andrew                   1998 GIC       28857 :             bool        nulls[2] = {false, false};
 3304 andrew                   1999 ECB             : 
                               2000                 :             /* Use the tmp context so we can clean up after each tuple is done */
 3304 andrew                   2001 CBC       28857 :             old_cxt = MemoryContextSwitchTo(tmp_cxt);
                               2002                 : 
 3294 tgl                      2003 GIC       28857 :             key = cstring_to_text_with_len(v.val.string.val, v.val.string.len);
                               2004                 : 
 3304 andrew                   2005 ECB             :             /*
                               2006                 :              * The next thing the iterator fetches should be the value, no
                               2007                 :              * matter what shape it is.
                               2008                 :              */
 3304 andrew                   2009 GIC       28857 :             r = JsonbIteratorNext(&it, &v, skipNested);
 1820 tgl                      2010           28857 :             Assert(r != WJB_DONE);
 3304 andrew                   2011 ECB             : 
 3304 andrew                   2012 GIC       28857 :             values[0] = PointerGetDatum(key);
 3304 andrew                   2013 ECB             : 
 3304 andrew                   2014 GIC       28857 :             if (as_text)
                               2015                 :             {
                               2016              57 :                 if (v.type == jbvNull)
 3304 andrew                   2017 ECB             :                 {
                               2018                 :                     /* a json null is an sql null in text mode */
 3304 andrew                   2019 GIC          12 :                     nulls[1] = true;
                               2020              12 :                     values[1] = (Datum) NULL;
                               2021                 :                 }
 3304 andrew                   2022 ECB             :                 else
 1297 alvherre                 2023 GBC          45 :                     values[1] = PointerGetDatum(JsonbValueAsText(&v));
                               2024                 :             }
                               2025                 :             else
                               2026                 :             {
                               2027                 :                 /* Not in text mode, just return the Jsonb */
 3304 andrew                   2028 CBC       28800 :                 Jsonb      *val = JsonbValueToJsonb(&v);
 3304 andrew                   2029 ECB             : 
 3304 andrew                   2030 GIC       28800 :                 values[1] = PointerGetDatum(val);
 3304 andrew                   2031 ECB             :             }
                               2032                 : 
  398 michael                  2033 GIC       28857 :             tuplestore_putvalues(rsi->setResult, rsi->setDesc, values, nulls);
                               2034                 : 
 3304 andrew                   2035 ECB             :             /* clean up and switch back */
 3304 andrew                   2036 GIC       28857 :             MemoryContextSwitchTo(old_cxt);
 3304 andrew                   2037 CBC       28857 :             MemoryContextReset(tmp_cxt);
                               2038                 :         }
 3304 andrew                   2039 ECB             :     }
                               2040                 : 
 3304 andrew                   2041 CBC        6096 :     MemoryContextDelete(tmp_cxt);
                               2042                 : 
 3304 andrew                   2043 GIC        6096 :     PG_RETURN_NULL();
                               2044                 : }
 3304 andrew                   2045 ECB             : 
                               2046                 : 
                               2047                 : static Datum
 3304 andrew                   2048 CBC          12 : each_worker(FunctionCallInfo fcinfo, bool as_text)
                               2049                 : {
 2219 noah                     2050              12 :     text       *json = PG_GETARG_TEXT_PP(0);
                               2051                 :     JsonLexContext *lex;
                               2052                 :     JsonSemAction *sem;
                               2053                 :     ReturnSetInfo *rsi;
                               2054                 :     EachState  *state;
                               2055                 : 
 3304 andrew                   2056              12 :     lex = makeJsonLexContext(json, true);
 3550 peter_e                  2057              12 :     state = palloc0(sizeof(EachState));
 3550 peter_e                  2058 GIC          12 :     sem = palloc0(sizeof(JsonSemAction));
 3663 andrew                   2059 ECB             : 
 3663 andrew                   2060 GIC          12 :     rsi = (ReturnSetInfo *) fcinfo->resultinfo;
 3663 andrew                   2061 ECB             : 
  173 michael                  2062 GIC          12 :     InitMaterializedSRF(fcinfo, MAT_SRF_BLESS);
  398 michael                  2063 CBC          12 :     state->tuple_store = rsi->setResult;
  398 michael                  2064 GIC          12 :     state->ret_tdesc = rsi->setDesc;
                               2065                 : 
 3663 andrew                   2066 CBC          12 :     sem->semstate = (void *) state;
                               2067              12 :     sem->array_start = each_array_start;
 3663 andrew                   2068 GIC          12 :     sem->scalar = each_scalar;
                               2069              12 :     sem->object_field_start = each_object_field_start;
 3663 andrew                   2070 CBC          12 :     sem->object_field_end = each_object_field_end;
                               2071                 : 
 3663 andrew                   2072 GIC          12 :     state->normalize_results = as_text;
                               2073              12 :     state->next_scalar = false;
                               2074              12 :     state->lex = lex;
 3663 andrew                   2075 CBC          12 :     state->tmp_cxt = AllocSetContextCreate(CurrentMemoryContext,
                               2076                 :                                            "json_each temporary cxt",
 2416 tgl                      2077 ECB             :                                            ALLOCSET_DEFAULT_SIZES);
                               2078                 : 
 1168 rhaas                    2079 GIC          12 :     pg_parse_json_or_ereport(lex, sem);
 3663 andrew                   2080 ECB             : 
 3350 peter_e                  2081 GIC          12 :     MemoryContextDelete(state->tmp_cxt);
                               2082                 : 
 3663 andrew                   2083 CBC          12 :     PG_RETURN_NULL();
 3663 andrew                   2084 ECB             : }
                               2085                 : 
                               2086                 : 
                               2087                 : static JsonParseErrorType
 3663 andrew                   2088 CBC          63 : each_object_field_start(void *state, char *fname, bool isnull)
                               2089                 : {
 3550 peter_e                  2090              63 :     EachState  *_state = (EachState *) state;
                               2091                 : 
                               2092                 :     /* save a pointer to where the value starts */
 3663 andrew                   2093 GIC          63 :     if (_state->lex->lex_level == 1)
                               2094                 :     {
 3663 andrew                   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                 :          */
 3663 andrew                   2100 GIC          51 :         if (_state->normalize_results && _state->lex->token_type == JSON_TOKEN_STRING)
                               2101               6 :             _state->next_scalar = true;
                               2102                 :         else
 3663 andrew                   2103 CBC          45 :             _state->result_start = _state->lex->token_start;
 3663 andrew                   2104 ECB             :     }
                               2105                 : 
  119 tgl                      2106 GNC          63 :     return JSON_SUCCESS;
 3663 andrew                   2107 ECB             : }
                               2108                 : 
                               2109                 : static JsonParseErrorType
 3663 andrew                   2110 GIC          63 : each_object_field_end(void *state, char *fname, bool isnull)
 3663 andrew                   2111 ECB             : {
 3550 peter_e                  2112 CBC          63 :     EachState  *_state = (EachState *) state;
 3663 andrew                   2113 ECB             :     MemoryContext old_cxt;
                               2114                 :     int         len;
                               2115                 :     text       *val;
                               2116                 :     HeapTuple   tuple;
                               2117                 :     Datum       values[2];
 3663 andrew                   2118 CBC          63 :     bool        nulls[2] = {false, false};
 3663 andrew                   2119 ECB             : 
                               2120                 :     /* skip over nested objects */
 3663 andrew                   2121 CBC          63 :     if (_state->lex->lex_level != 1)
  119 tgl                      2122 GNC          12 :         return JSON_SUCCESS;
 3663 andrew                   2123 ECB             : 
                               2124                 :     /* use the tmp context so we can clean up after each tuple is done */
 3663 andrew                   2125 GIC          51 :     old_cxt = MemoryContextSwitchTo(_state->tmp_cxt);
                               2126                 : 
                               2127              51 :     values[0] = CStringGetTextDatum(fname);
 3663 andrew                   2128 ECB             : 
 3663 andrew                   2129 GIC          51 :     if (isnull && _state->normalize_results)
 3663 andrew                   2130 ECB             :     {
 3663 andrew                   2131 GIC           6 :         nulls[1] = true;
 3210 tgl                      2132 CBC           6 :         values[1] = (Datum) 0;
                               2133                 :     }
 3663 andrew                   2134 GIC          45 :     else if (_state->next_scalar)
                               2135                 :     {
                               2136               6 :         values[1] = CStringGetTextDatum(_state->normalized_scalar);
 3663 andrew                   2137 CBC           6 :         _state->next_scalar = false;
                               2138                 :     }
 3663 andrew                   2139 ECB             :     else
                               2140                 :     {
 3304 andrew                   2141 GIC          39 :         len = _state->lex->prev_token_terminator - _state->result_start;
 3304 andrew                   2142 CBC          39 :         val = cstring_to_text_with_len(_state->result_start, len);
 3304 andrew                   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);
 3304 andrew                   2149 ECB             : 
                               2150                 :     /* clean up and switch back */
 3304 andrew                   2151 GIC          51 :     MemoryContextSwitchTo(old_cxt);
 3304 andrew                   2152 CBC          51 :     MemoryContextReset(_state->tmp_cxt);
                               2153                 : 
  119 tgl                      2154 GNC          51 :     return JSON_SUCCESS;
                               2155                 : }
                               2156                 : 
                               2157                 : static JsonParseErrorType
 3304 andrew                   2158 GIC          12 : each_array_start(void *state)
                               2159                 : {
                               2160              12 :     EachState  *_state = (EachState *) state;
 3304 andrew                   2161 ECB             : 
                               2162                 :     /* json structure check */
 3304 andrew                   2163 CBC          12 :     if (_state->lex->lex_level == 0)
 3304 andrew                   2164 UIC           0 :         ereport(ERROR,
                               2165                 :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                               2166                 :                  errmsg("cannot deconstruct an array as an object")));
                               2167                 : 
  119 tgl                      2168 GNC          12 :     return JSON_SUCCESS;
                               2169                 : }
                               2170                 : 
                               2171                 : static JsonParseErrorType
 3304 andrew                   2172 GIC          75 : each_scalar(void *state, char *token, JsonTokenType tokentype)
                               2173                 : {
 3304 andrew                   2174 CBC          75 :     EachState  *_state = (EachState *) state;
 3304 andrew                   2175 ECB             : 
                               2176                 :     /* json structure check */
 3304 andrew                   2177 GIC          75 :     if (_state->lex->lex_level == 0)
 3304 andrew                   2178 LBC           0 :         ereport(ERROR,
                               2179                 :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
 3304 andrew                   2180 ECB             :                  errmsg("cannot deconstruct a scalar")));
                               2181                 : 
                               2182                 :     /* supply de-escaped value if required */
 3304 andrew                   2183 GIC          75 :     if (_state->next_scalar)
 3304 andrew                   2184 CBC           6 :         _state->normalized_scalar = token;
                               2185                 : 
  119 tgl                      2186 GNC          75 :     return JSON_SUCCESS;
 3304 andrew                   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
 3304 andrew                   2198 CBC          18 : jsonb_array_elements(PG_FUNCTION_ARGS)
                               2199                 : {
 3210 tgl                      2200 GIC          18 :     return elements_worker_jsonb(fcinfo, "jsonb_array_elements", false);
 3304 andrew                   2201 ECB             : }
                               2202                 : 
                               2203                 : Datum
 3304 andrew                   2204 GIC           6 : jsonb_array_elements_text(PG_FUNCTION_ARGS)
                               2205                 : {
 3210 tgl                      2206 CBC           6 :     return elements_worker_jsonb(fcinfo, "jsonb_array_elements_text", true);
 3304 andrew                   2207 ECB             : }
                               2208                 : 
 3210 tgl                      2209                 : static Datum
 3210 tgl                      2210 GIC          24 : elements_worker_jsonb(FunctionCallInfo fcinfo, const char *funcname,
                               2211                 :                       bool as_text)
                               2212                 : {
 2029 tgl                      2213 CBC          24 :     Jsonb      *jb = PG_GETARG_JSONB_P(0);
                               2214                 :     ReturnSetInfo *rsi;
 3304 andrew                   2215 ECB             :     MemoryContext old_cxt,
                               2216                 :                 tmp_cxt;
 3304 andrew                   2217 GIC          24 :     bool        skipNested = false;
 3304 andrew                   2218 ECB             :     JsonbIterator *it;
 3304 andrew                   2219 EUB             :     JsonbValue  v;
                               2220                 :     JsonbIteratorToken r;
                               2221                 : 
 3304 andrew                   2222 GIC          24 :     if (JB_ROOT_IS_SCALAR(jb))
 3304 andrew                   2223 LBC           0 :         ereport(ERROR,
                               2224                 :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                               2225                 :                  errmsg("cannot extract elements from a scalar")));
 3304 andrew                   2226 GIC          24 :     else if (!JB_ROOT_IS_ARRAY(jb))
 3304 andrew                   2227 LBC           0 :         ereport(ERROR,
                               2228                 :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
 3304 andrew                   2229 ECB             :                  errmsg("cannot extract elements from an object")));
                               2230                 : 
 3304 andrew                   2231 GIC          24 :     rsi = (ReturnSetInfo *) fcinfo->resultinfo;
 3304 andrew                   2232 ECB             : 
  173 michael                  2233 GBC          24 :     InitMaterializedSRF(fcinfo, MAT_SRF_USE_EXPECTED_DESC | MAT_SRF_BLESS);
                               2234                 : 
 3304 andrew                   2235 GIC          24 :     tmp_cxt = AllocSetContextCreate(CurrentMemoryContext,
                               2236                 :                                     "jsonb_array_elements temporary cxt",
                               2237                 :                                     ALLOCSET_DEFAULT_SIZES);
 3304 andrew                   2238 ECB             : 
 3259 heikki.linnakangas       2239 CBC          24 :     it = JsonbIteratorInit(&jb->root);
                               2240                 : 
 3304 andrew                   2241             162 :     while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE)
                               2242                 :     {
 3304 andrew                   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                 : 
 1297 alvherre                 2253 CBC          90 :             if (as_text)
                               2254                 :             {
 3304 andrew                   2255              42 :                 if (v.type == jbvNull)
                               2256                 :                 {
                               2257                 :                     /* a json null is an sql null in text mode */
 3304 andrew                   2258 GIC           6 :                     nulls[0] = true;
 3304 andrew                   2259 CBC           6 :                     values[0] = (Datum) NULL;
                               2260                 :                 }
 3304 andrew                   2261 ECB             :                 else
 1297 alvherre                 2262 GIC          36 :                     values[0] = PointerGetDatum(JsonbValueAsText(&v));
                               2263                 :             }
                               2264                 :             else
 1297 alvherre                 2265 ECB             :             {
                               2266                 :                 /* Not in text mode, just return the Jsonb */
 1297 alvherre                 2267 GIC          48 :                 Jsonb      *val = JsonbValueToJsonb(&v);
 1297 alvherre                 2268 ECB             : 
 1297 alvherre                 2269 GIC          48 :                 values[0] = PointerGetDatum(val);
                               2270                 :             }
                               2271                 : 
  398 michael                  2272 CBC          90 :             tuplestore_putvalues(rsi->setResult, rsi->setDesc, values, nulls);
                               2273                 : 
                               2274                 :             /* clean up and switch back */
 3304 andrew                   2275 GIC          90 :             MemoryContextSwitchTo(old_cxt);
                               2276              90 :             MemoryContextReset(tmp_cxt);
 3304 andrew                   2277 ECB             :         }
 3304 andrew                   2278 EUB             :     }
                               2279                 : 
 3304 andrew                   2280 GIC          24 :     MemoryContextDelete(tmp_cxt);
 3663 andrew                   2281 ECB             : 
 3304 andrew                   2282 GBC          24 :     PG_RETURN_NULL();
                               2283                 : }
                               2284                 : 
                               2285                 : Datum
 3663 andrew                   2286 CBC         195 : json_array_elements(PG_FUNCTION_ARGS)
                               2287                 : {
 3210 tgl                      2288             195 :     return elements_worker(fcinfo, "json_array_elements", false);
                               2289                 : }
 3357 andrew                   2290 ECB             : 
                               2291                 : Datum
 3357 andrew                   2292 GIC           6 : json_array_elements_text(PG_FUNCTION_ARGS)
                               2293                 : {
 3210 tgl                      2294 CBC           6 :     return elements_worker(fcinfo, "json_array_elements_text", true);
                               2295                 : }
 3357 andrew                   2296 ECB             : 
                               2297                 : static Datum
 3210 tgl                      2298 CBC         201 : elements_worker(FunctionCallInfo fcinfo, const char *funcname, bool as_text)
                               2299                 : {
 2219 noah                     2300             201 :     text       *json = PG_GETARG_TEXT_PP(0);
                               2301                 : 
                               2302                 :     /* elements only needs escaped strings when as_text */
 3357 andrew                   2303             201 :     JsonLexContext *lex = makeJsonLexContext(json, as_text);
                               2304                 :     JsonSemAction *sem;
                               2305                 :     ReturnSetInfo *rsi;
 3550 peter_e                  2306 ECB             :     ElementsState *state;
                               2307                 : 
 3550 peter_e                  2308 CBC         201 :     state = palloc0(sizeof(ElementsState));
 3550 peter_e                  2309 GIC         201 :     sem = palloc0(sizeof(JsonSemAction));
 3663 andrew                   2310 ECB             : 
  173 michael                  2311 GIC         201 :     InitMaterializedSRF(fcinfo, MAT_SRF_USE_EXPECTED_DESC | MAT_SRF_BLESS);
 3663 andrew                   2312             201 :     rsi = (ReturnSetInfo *) fcinfo->resultinfo;
  398 michael                  2313 CBC         201 :     state->tuple_store = rsi->setResult;
                               2314             201 :     state->ret_tdesc = rsi->setDesc;
                               2315                 : 
 3663 andrew                   2316 GIC         201 :     sem->semstate = (void *) state;
 3663 andrew                   2317 CBC         201 :     sem->object_start = elements_object_start;
 3663 andrew                   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                 : 
 3210 tgl                      2322 CBC         201 :     state->function_name = funcname;
 3357 andrew                   2323 GIC         201 :     state->normalize_results = as_text;
 3357 andrew                   2324 CBC         201 :     state->next_scalar = false;
 3663 andrew                   2325 GIC         201 :     state->lex = lex;
                               2326             201 :     state->tmp_cxt = AllocSetContextCreate(CurrentMemoryContext,
 2118 tgl                      2327 ECB             :                                            "json_array_elements temporary cxt",
                               2328                 :                                            ALLOCSET_DEFAULT_SIZES);
                               2329                 : 
 1168 rhaas                    2330 CBC         201 :     pg_parse_json_or_ereport(lex, sem);
 3663 andrew                   2331 ECB             : 
 3350 peter_e                  2332 GIC         201 :     MemoryContextDelete(state->tmp_cxt);
                               2333                 : 
 3663 andrew                   2334             201 :     PG_RETURN_NULL();
 3663 andrew                   2335 ECB             : }
                               2336                 : 
                               2337                 : static JsonParseErrorType
 3663 andrew                   2338 GIC        1014 : elements_array_element_start(void *state, bool isnull)
                               2339                 : {
 3550 peter_e                  2340            1014 :     ElementsState *_state = (ElementsState *) state;
 3663 andrew                   2341 ECB             : 
                               2342                 :     /* save a pointer to where the value starts */
 3663 andrew                   2343 CBC        1014 :     if (_state->lex->lex_level == 1)
                               2344                 :     {
                               2345                 :         /*
                               2346                 :          * next_scalar will be reset in the array_element_end handler, and
 3357 andrew                   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                 :          */
 3357 andrew                   2350 GIC         339 :         if (_state->normalize_results && _state->lex->token_type == JSON_TOKEN_STRING)
                               2351               6 :             _state->next_scalar = true;
                               2352                 :         else
 3357 andrew                   2353 CBC         333 :             _state->result_start = _state->lex->token_start;
                               2354                 :     }
                               2355                 : 
  119 tgl                      2356 GNC        1014 :     return JSON_SUCCESS;
 3663 andrew                   2357 ECB             : }
                               2358                 : 
                               2359                 : static JsonParseErrorType
 3663 andrew                   2360 CBC        1014 : elements_array_element_end(void *state, bool isnull)
                               2361                 : {
 3550 peter_e                  2362 GIC        1014 :     ElementsState *_state = (ElementsState *) state;
                               2363                 :     MemoryContext old_cxt;
                               2364                 :     int         len;
 3663 andrew                   2365 ECB             :     text       *val;
                               2366                 :     HeapTuple   tuple;
                               2367                 :     Datum       values[1];
 3260 bruce                    2368 CBC        1014 :     bool        nulls[1] = {false};
 3663 andrew                   2369 ECB             : 
                               2370                 :     /* skip over nested objects */
 3663 andrew                   2371 CBC        1014 :     if (_state->lex->lex_level != 1)
  119 tgl                      2372 GNC         675 :         return JSON_SUCCESS;
 3663 andrew                   2373 ECB             : 
                               2374                 :     /* use the tmp context so we can clean up after each tuple is done */
 3663 andrew                   2375 CBC         339 :     old_cxt = MemoryContextSwitchTo(_state->tmp_cxt);
 3663 andrew                   2376 ECB             : 
 3357 andrew                   2377 CBC         339 :     if (isnull && _state->normalize_results)
                               2378                 :     {
                               2379               6 :         nulls[0] = true;
                               2380               6 :         values[0] = (Datum) NULL;
 3357 andrew                   2381 ECB             :     }
 3357 andrew                   2382 CBC         333 :     else if (_state->next_scalar)
 3357 andrew                   2383 ECB             :     {
 3357 andrew                   2384 GIC           6 :         values[0] = CStringGetTextDatum(_state->normalized_scalar);
                               2385               6 :         _state->next_scalar = false;
                               2386                 :     }
 3357 andrew                   2387 ECB             :     else
                               2388                 :     {
 3357 andrew                   2389 CBC         327 :         len = _state->lex->prev_token_terminator - _state->result_start;
 3357 andrew                   2390 GIC         327 :         val = cstring_to_text_with_len(_state->result_start, len);
 3357 andrew                   2391 CBC         327 :         values[0] = PointerGetDatum(val);
                               2392                 :     }
                               2393                 : 
 3663 andrew                   2394 GIC         339 :     tuple = heap_form_tuple(_state->ret_tdesc, values, nulls);
 3663 andrew                   2395 ECB             : 
 3663 andrew                   2396 GIC         339 :     tuplestore_puttuple(_state->tuple_store, tuple);
 3663 andrew                   2397 ECB             : 
                               2398                 :     /* clean up and switch back */
 3663 andrew                   2399 GIC         339 :     MemoryContextSwitchTo(old_cxt);
 3663 andrew                   2400 CBC         339 :     MemoryContextReset(_state->tmp_cxt);
                               2401                 : 
  119 tgl                      2402 GNC         339 :     return JSON_SUCCESS;
                               2403                 : }
                               2404                 : 
                               2405                 : static JsonParseErrorType
 3663 andrew                   2406 GIC         858 : elements_object_start(void *state)
                               2407                 : {
 3550 peter_e                  2408             858 :     ElementsState *_state = (ElementsState *) state;
 3663 andrew                   2409 ECB             : 
                               2410                 :     /* json structure check */
 3663 andrew                   2411 GIC         858 :     if (_state->lex->lex_level == 0)
 3663 andrew                   2412 LBC           0 :         ereport(ERROR,
                               2413                 :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                               2414                 :                  errmsg("cannot call %s on a non-array",
 3210 tgl                      2415 ECB             :                         _state->function_name)));
                               2416                 : 
  119 tgl                      2417 GNC         858 :     return JSON_SUCCESS;
                               2418                 : }
                               2419                 : 
                               2420                 : static JsonParseErrorType
 3663 andrew                   2421 CBC       12768 : elements_scalar(void *state, char *token, JsonTokenType tokentype)
                               2422                 : {
 3550 peter_e                  2423           12768 :     ElementsState *_state = (ElementsState *) state;
                               2424                 : 
                               2425                 :     /* json structure check */
 3663 andrew                   2426 GIC       12768 :     if (_state->lex->lex_level == 0)
 3663 andrew                   2427 UIC           0 :         ereport(ERROR,
                               2428                 :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
 3210 tgl                      2429 ECB             :                  errmsg("cannot call %s on a scalar",
                               2430                 :                         _state->function_name)));
                               2431                 : 
 3357 andrew                   2432                 :     /* supply de-escaped value if required */
 3357 andrew                   2433 CBC       12768 :     if (_state->next_scalar)
 3357 andrew                   2434 GIC           6 :         _state->normalized_scalar = token;
                               2435                 : 
  119 tgl                      2436 GNC       12768 :     return JSON_SUCCESS;
                               2437                 : }
 3663 andrew                   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
 3304                          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
 3304 andrew                   2452 CBC         411 : jsonb_populate_record(PG_FUNCTION_ARGS)
 3304 andrew                   2453 ECB             : {
 1731 tgl                      2454 CBC         411 :     return populate_record_worker(fcinfo, "jsonb_populate_record",
                               2455                 :                                   false, true);
                               2456                 : }
 3304 andrew                   2457 ECB             : 
                               2458                 : Datum
 3301 andrew                   2459 CBC          51 : jsonb_to_record(PG_FUNCTION_ARGS)
                               2460                 : {
 1731 tgl                      2461 GIC          51 :     return populate_record_worker(fcinfo, "jsonb_to_record",
 1731 tgl                      2462 ECB             :                                   false, false);
 3301 andrew                   2463                 : }
                               2464                 : 
 3663                          2465                 : Datum
 3663 andrew                   2466 GIC         411 : json_populate_record(PG_FUNCTION_ARGS)
                               2467                 : {
 1731 tgl                      2468             411 :     return populate_record_worker(fcinfo, "json_populate_record",
 1731 tgl                      2469 ECB             :                                   true, true);
                               2470                 : }
 3358 andrew                   2471                 : 
                               2472                 : Datum
 3358 andrew                   2473 GIC          51 : json_to_record(PG_FUNCTION_ARGS)
 3358 andrew                   2474 ECB             : {
 1731 tgl                      2475 GBC          51 :     return populate_record_worker(fcinfo, "json_to_record",
                               2476                 :                                   true, false);
                               2477                 : }
                               2478                 : 
                               2479                 : /* helper function for diagnostics */
 2194 andrew                   2480 ECB             : static void
 2194 andrew                   2481 GIC          78 : populate_array_report_expected_array(PopulateArrayContext *ctx, int ndim)
                               2482                 : {
                               2483              78 :     if (ndim <= 0)
 2194 andrew                   2484 ECB             :     {
 2194 andrew                   2485 GIC          48 :         if (ctx->colname)
 2194 andrew                   2486 CBC          48 :             ereport(ERROR,
                               2487                 :                     (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
                               2488                 :                      errmsg("expected JSON array"),
 2036 peter_e                  2489 ECB             :                      errhint("See the value of key \"%s\".", ctx->colname)));
 2194 andrew                   2490 EUB             :         else
 2194 andrew                   2491 UIC           0 :             ereport(ERROR,
                               2492                 :                     (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
                               2493                 :                      errmsg("expected JSON array")));
                               2494                 :     }
                               2495                 :     else
 2194 andrew                   2496 ECB             :     {
 2153 bruce                    2497                 :         StringInfoData indices;
                               2498                 :         int         i;
 3304 andrew                   2499                 : 
 2194 andrew                   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)
 3358                          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
 2194 andrew                   2514 UIC           0 :             ereport(ERROR,
 2194 andrew                   2515 ECB             :                     (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
                               2516                 :                      errmsg("expected JSON array"),
 2036 peter_e                  2517                 :                      errhint("See the array element %s.",
                               2518                 :                              indices.data)));
                               2519                 :     }
                               2520                 : }
                               2521                 : 
 2194 andrew                   2522                 : /* set the number of dimensions of the populated array when it becomes known */
                               2523                 : static void
 2194 andrew                   2524 CBC         876 : populate_array_assign_ndims(PopulateArrayContext *ctx, int ndims)
                               2525                 : {
                               2526                 :     int         i;
                               2527                 : 
 2194 andrew                   2528 GIC         876 :     Assert(ctx->ndims <= 0);
 3358 andrew                   2529 ECB             : 
 2194 andrew                   2530 GIC         876 :     if (ndims <= 0)
 2194 andrew                   2531 CBC          24 :         populate_array_report_expected_array(ctx, ndims);
                               2532                 : 
 2194 andrew                   2533 GIC         852 :     ctx->ndims = ndims;
                               2534             852 :     ctx->dims = palloc(sizeof(int) * ndims);
                               2535             852 :     ctx->sizes = palloc0(sizeof(int) * ndims);
 3358 andrew                   2536 ECB             : 
 2194 andrew                   2537 GIC        1872 :     for (i = 0; i < ndims; i++)
 2153 bruce                    2538 CBC        1020 :         ctx->dims[i] = -1;       /* dimensions are unknown yet */
 2194 andrew                   2539 GIC         852 : }
                               2540                 : 
                               2541                 : /* check the populated subarray dimension */
                               2542                 : static void
                               2543             753 : populate_array_check_dimension(PopulateArrayContext *ctx, int ndim)
 2194 andrew                   2544 ECB             : {
 2153 bruce                    2545 GIC         753 :     int         dim = ctx->sizes[ndim]; /* current dimension counter */
 3663 andrew                   2546 ECB             : 
 2194 andrew                   2547 GIC         753 :     if (ctx->dims[ndim] == -1)
 2153 bruce                    2548 CBC         561 :         ctx->dims[ndim] = dim;   /* assign dimension if not yet known */
 2194 andrew                   2549             192 :     else if (ctx->dims[ndim] != dim)
 2194 andrew                   2550 GIC          24 :         ereport(ERROR,
                               2551                 :                 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
                               2552                 :                  errmsg("malformed JSON array"),
                               2553                 :                  errdetail("Multidimensional arrays must have "
 2194 andrew                   2554 EUB             :                            "sub-arrays with matching dimensions.")));
                               2555                 : 
                               2556                 :     /* reset the current array dimension size counter */
 2194 andrew                   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 : }
 3663 andrew                   2563 ECB             : 
                               2564                 : static void
 2194 andrew                   2565 CBC        2952 : populate_array_element(PopulateArrayContext *ctx, int ndim, JsValue *jsv)
                               2566                 : {
 2153 bruce                    2567 ECB             :     Datum       element;
                               2568                 :     bool        element_isnull;
                               2569                 : 
 2194 andrew                   2570                 :     /* populate the array element */
 2194 andrew                   2571 CBC        2952 :     element = populate_record_field(ctx->aio->element_info,
 2194 andrew                   2572 GIC        2952 :                                     ctx->aio->element_type,
                               2573            2952 :                                     ctx->aio->element_typmod,
                               2574                 :                                     NULL, ctx->mcxt, PointerGetDatum(NULL),
                               2575                 :                                     jsv, &element_isnull);
                               2576                 : 
 2194 andrew                   2577 GBC        2940 :     accumArrayResult(ctx->astate, element, element_isnull,
 2153 bruce                    2578 GIC        2940 :                      ctx->aio->element_type, ctx->acxt);
                               2579                 : 
 2194 andrew                   2580            2940 :     Assert(ndim > 0);
 2153 bruce                    2581            2940 :     ctx->sizes[ndim - 1]++;      /* increment current dimension counter */
 2194 andrew                   2582            2940 : }
                               2583                 : 
                               2584                 : /* json object start handler for populate_array_json() */
                               2585                 : static JsonParseErrorType
                               2586             324 : populate_array_object_start(void *_state)
 2194 andrew                   2587 ECB             : {
 2194 andrew                   2588 GIC         324 :     PopulateArrayState *state = (PopulateArrayState *) _state;
 2153 bruce                    2589             324 :     int         ndim = state->lex->lex_level;
                               2590                 : 
 2194 andrew                   2591 CBC         324 :     if (state->ctx->ndims <= 0)
 2194 andrew                   2592 GIC         156 :         populate_array_assign_ndims(state->ctx, ndim);
 2194 andrew                   2593 CBC         168 :     else if (ndim < state->ctx->ndims)
                               2594               6 :         populate_array_report_expected_array(state->ctx, ndim);
                               2595                 : 
  119 tgl                      2596 GNC         318 :     return JSON_SUCCESS;
                               2597                 : }
 3663 andrew                   2598 ECB             : 
 2194                          2599                 : /* json array end handler for populate_array_json() */
                               2600                 : static JsonParseErrorType
 2194 andrew                   2601 GIC         576 : populate_array_array_end(void *_state)
 2194 andrew                   2602 ECB             : {
 2153 bruce                    2603 CBC         576 :     PopulateArrayState *state = (PopulateArrayState *) _state;
                               2604             576 :     PopulateArrayContext *ctx = state->ctx;
 2153 bruce                    2605 GIC         576 :     int         ndim = state->lex->lex_level;
                               2606                 : 
 2194 andrew                   2607             576 :     if (ctx->ndims <= 0)
 2194 andrew                   2608 CBC           6 :         populate_array_assign_ndims(ctx, ndim + 1);
                               2609                 : 
                               2610             576 :     if (ndim < ctx->ndims)
 2194 andrew                   2611 GIC         573 :         populate_array_check_dimension(ctx, ndim);
                               2612                 : 
  119 tgl                      2613 GNC         564 :     return JSON_SUCCESS;
 2194 andrew                   2614 ECB             : }
                               2615                 : 
                               2616                 : /* json array element start handler for populate_array_json() */
                               2617                 : static JsonParseErrorType
 2194 andrew                   2618 GIC        1683 : populate_array_element_start(void *_state, bool isnull)
                               2619                 : {
                               2620            1683 :     PopulateArrayState *state = (PopulateArrayState *) _state;
 2153 bruce                    2621            1683 :     int         ndim = state->lex->lex_level;
                               2622                 : 
 2194 andrew                   2623            1683 :     if (state->ctx->ndims <= 0 || ndim == state->ctx->ndims)
 3663 andrew                   2624 ECB             :     {
                               2625                 :         /* remember current array element start */
 2194 andrew                   2626 GIC        1560 :         state->element_start = state->lex->token_start;
 2194 andrew                   2627 CBC        1560 :         state->element_type = state->lex->token_type;
                               2628            1560 :         state->element_scalar = NULL;
 3663 andrew                   2629 ECB             :     }
                               2630                 : 
  119 tgl                      2631 GNC        1683 :     return JSON_SUCCESS;
                               2632                 : }
                               2633                 : 
 2194 andrew                   2634 ECB             : /* json array element end handler for populate_array_json() */
                               2635                 : static JsonParseErrorType
 2194 andrew                   2636 GIC        1656 : populate_array_element_end(void *_state, bool isnull)
                               2637                 : {
 2153 bruce                    2638            1656 :     PopulateArrayState *state = (PopulateArrayState *) _state;
                               2639            1656 :     PopulateArrayContext *ctx = state->ctx;
 2153 bruce                    2640 CBC        1656 :     int         ndim = state->lex->lex_level;
 2194 andrew                   2641 ECB             : 
 2194 andrew                   2642 CBC        1656 :     Assert(ctx->ndims > 0);
                               2643                 : 
 2194 andrew                   2644 GIC        1656 :     if (ndim == ctx->ndims)
                               2645                 :     {
 2194 andrew                   2646 ECB             :         JsValue     jsv;
 3663                          2647                 : 
 2194 andrew                   2648 GIC        1476 :         jsv.is_json = true;
 2194 andrew                   2649 CBC        1476 :         jsv.val.json.type = state->element_type;
 2194 andrew                   2650 ECB             : 
 2194 andrew                   2651 CBC        1476 :         if (isnull)
                               2652                 :         {
 2194 andrew                   2653 GIC         354 :             Assert(jsv.val.json.type == JSON_TOKEN_NULL);
                               2654             354 :             jsv.val.json.str = NULL;
 2194 andrew                   2655 CBC         354 :             jsv.val.json.len = 0;
                               2656                 :         }
                               2657            1122 :         else if (state->element_scalar)
 3304 andrew                   2658 ECB             :         {
 2194 andrew                   2659 GIC         804 :             jsv.val.json.str = state->element_scalar;
 2118 tgl                      2660 CBC         804 :             jsv.val.json.len = -1;  /* null-terminated */
 3304 andrew                   2661 ECB             :         }
                               2662                 :         else
                               2663                 :         {
 2194 andrew                   2664 GIC         318 :             jsv.val.json.str = state->element_start;
 2194 andrew                   2665 CBC         318 :             jsv.val.json.len = (state->lex->prev_token_terminator -
 2194 andrew                   2666 GIC         318 :                                 state->element_start) * sizeof(char);
                               2667                 :         }
                               2668                 : 
                               2669            1476 :         populate_array_element(ctx, ndim, &jsv);
 2194 andrew                   2670 ECB             :     }
                               2671                 : 
  119 tgl                      2672 GNC        1650 :     return JSON_SUCCESS;
                               2673                 : }
 3663 andrew                   2674 ECB             : 
 2194                          2675                 : /* json scalar handler for populate_array_json() */
                               2676                 : static JsonParseErrorType
 2194 andrew                   2677 GIC        1827 : populate_array_scalar(void *_state, char *token, JsonTokenType tokentype)
 2194 andrew                   2678 ECB             : {
 2153 bruce                    2679 CBC        1827 :     PopulateArrayState *state = (PopulateArrayState *) _state;
 2153 bruce                    2680 GIC        1827 :     PopulateArrayContext *ctx = state->ctx;
 2153 bruce                    2681 CBC        1827 :     int         ndim = state->lex->lex_level;
 3663 andrew                   2682 ECB             : 
 2194 andrew                   2683 GIC        1827 :     if (ctx->ndims <= 0)
 2194 andrew                   2684 CBC         288 :         populate_array_assign_ndims(ctx, ndim);
 2194 andrew                   2685 GIC        1539 :     else if (ndim < ctx->ndims)
                               2686               9 :         populate_array_report_expected_array(ctx, ndim);
                               2687                 : 
                               2688            1794 :     if (ndim == ctx->ndims)
 2194 andrew                   2689 ECB             :     {
                               2690                 :         /* remember the scalar element token */
 2194 andrew                   2691 CBC        1158 :         state->element_scalar = token;
 2194 andrew                   2692 ECB             :         /* element_type must already be set in populate_array_element_start() */
 2194 andrew                   2693 GIC        1158 :         Assert(state->element_type == tokentype);
 3663 andrew                   2694 ECB             :     }
                               2695                 : 
  119 tgl                      2696 GNC        1794 :     return JSON_SUCCESS;
                               2697                 : }
                               2698                 : 
 2194 andrew                   2699 ECB             : /* parse a json array and populate array */
                               2700                 : static void
 2194 andrew                   2701 CBC         450 : populate_array_json(PopulateArrayContext *ctx, char *json, int len)
                               2702                 : {
                               2703                 :     PopulateArrayState state;
 2153 bruce                    2704 ECB             :     JsonSemAction sem;
                               2705                 : 
 1166 rhaas                    2706 GIC         450 :     state.lex = makeJsonLexContextCstringLen(json, len, GetDatabaseEncoding(), true);
 2194 andrew                   2707             450 :     state.ctx = ctx;
                               2708                 : 
 2194 andrew                   2709 CBC         450 :     memset(&sem, 0, sizeof(sem));
 2194 andrew                   2710 GIC         450 :     sem.semstate = (void *) &state;
 2194 andrew                   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;
 2194 andrew                   2714 GIC         450 :     sem.array_element_end = populate_array_element_end;
 2194 andrew                   2715 CBC         450 :     sem.scalar = populate_array_scalar;
                               2716                 : 
 1168 rhaas                    2717             450 :     pg_parse_json_or_ereport(state.lex, &sem);
                               2718                 : 
                               2719                 :     /* number of dimensions should be already known */
 2194 andrew                   2720 GIC         393 :     Assert(ctx->ndims > 0 && ctx->dims);
 3211 tgl                      2721 ECB             : 
 2194 andrew                   2722 CBC         393 :     pfree(state.lex);
 3663 andrew                   2723 GIC         393 : }
 3663 andrew                   2724 ECB             : 
                               2725                 : /*
 2194                          2726                 :  * populate_array_dim_jsonb() -- Iterate recursively through jsonb sub-array
 2153 bruce                    2727                 :  *      elements and accumulate result using given ArrayBuildState.
 3663 andrew                   2728                 :  */
                               2729                 : static void
 2118 tgl                      2730 CBC         645 : populate_array_dim_jsonb(PopulateArrayContext *ctx, /* context */
                               2731                 :                          JsonbValue *jbv,   /* jsonb sub-array */
 2118 tgl                      2732 ECB             :                          int ndim)  /* current dimension */
 3663 andrew                   2733                 : {
 2153 bruce                    2734 GIC         645 :     JsonbContainer *jbc = jbv->val.binary.data;
                               2735                 :     JsonbIterator *it;
                               2736                 :     JsonbIteratorToken tok;
 2153 bruce                    2737 ECB             :     JsonbValue  val;
                               2738                 :     JsValue     jsv;
 3663 andrew                   2739                 : 
 2194 andrew                   2740 GIC         645 :     check_stack_depth();
                               2741                 : 
  220 andrew                   2742 CBC         645 :     if (jbv->type != jbvBinary || !JsonContainerIsArray(jbc))
 2194 andrew                   2743 GIC          39 :         populate_array_report_expected_array(ctx, ndim - 1);
                               2744                 : 
  220 andrew                   2745 CBC         606 :     Assert(!JsonContainerIsScalar(jbc));
                               2746                 : 
 2194 andrew                   2747 GIC         606 :     it = JsonbIteratorInit(jbc);
                               2748                 : 
                               2749             606 :     tok = JsonbIteratorNext(&it, &val, true);
 2194 andrew                   2750 CBC         606 :     Assert(tok == WJB_BEGIN_ARRAY);
                               2751                 : 
                               2752             606 :     tok = JsonbIteratorNext(&it, &val, true);
 3663 andrew                   2753 ECB             : 
 2194                          2754                 :     /*
                               2755                 :      * If the number of dimensions is not yet known and we have found end of
 2153 bruce                    2756                 :      * the array, or the first child element is not an array, then assign the
                               2757                 :      * number of dimensions now.
 2194 andrew                   2758                 :      */
 2194 andrew                   2759 CBC         606 :     if (ctx->ndims <= 0 &&
 2194 andrew                   2760 GIC         504 :         (tok == WJB_END_ARRAY ||
 2194 andrew                   2761 CBC         504 :          (tok == WJB_ELEM &&
 2194 andrew                   2762 GIC         504 :           (val.type != jbvBinary ||
                               2763             240 :            !JsonContainerIsArray(val.val.binary.data)))))
 2194 andrew                   2764 CBC         426 :         populate_array_assign_ndims(ctx, ndim);
                               2765                 : 
                               2766             606 :     jsv.is_json = false;
 2194 andrew                   2767 GIC         606 :     jsv.val.jsonb = &val;
                               2768                 : 
 2194 andrew                   2769 ECB             :     /* process all the array elements */
 2194 andrew                   2770 GIC        2244 :     while (tok == WJB_ELEM)
                               2771                 :     {
                               2772                 :         /*
                               2773                 :          * Recurse only if the dimensions of dimensions is still unknown or if
 2153 bruce                    2774 ECB             :          * it is not the innermost dimension.
                               2775                 :          */
 2194 andrew                   2776 GIC        1671 :         if (ctx->ndims > 0 && ndim >= ctx->ndims)
                               2777            1476 :             populate_array_element(ctx, ndim, &jsv);
                               2778                 :         else
 2194 andrew                   2779 ECB             :         {
                               2780                 :             /* populate child sub-array */
 2194 andrew                   2781 GIC         195 :             populate_array_dim_jsonb(ctx, &val, ndim + 1);
 2194 andrew                   2782 ECB             : 
                               2783                 :             /* number of dimensions should be already known */
 2194 andrew                   2784 CBC         180 :             Assert(ctx->ndims > 0 && ctx->dims);
 2194 andrew                   2785 ECB             : 
 2194 andrew                   2786 CBC         180 :             populate_array_check_dimension(ctx, ndim);
 2194 andrew                   2787 ECB             :         }
                               2788                 : 
 2194 andrew                   2789 GIC        1638 :         tok = JsonbIteratorNext(&it, &val, true);
 2194 andrew                   2790 ECB             :     }
                               2791                 : 
 2194 andrew                   2792 GIC         573 :     Assert(tok == WJB_END_ARRAY);
 2194 andrew                   2793 ECB             : 
                               2794                 :     /* free iterator, iterating until WJB_DONE */
 2194 andrew                   2795 CBC         573 :     tok = JsonbIteratorNext(&it, &val, true);
                               2796             573 :     Assert(tok == WJB_DONE && !it);
 2194 andrew                   2797 GIC         573 : }
                               2798                 : 
                               2799                 : /* recursively populate an array from json/jsonb */
                               2800                 : static Datum
 2153 bruce                    2801             900 : populate_array(ArrayIOData *aio,
                               2802                 :                const char *colname,
 2153 bruce                    2803 ECB             :                MemoryContext mcxt,
                               2804                 :                JsValue *jsv)
                               2805                 : {
                               2806                 :     PopulateArrayContext ctx;
                               2807                 :     Datum       result;
                               2808                 :     int        *lbs;
                               2809                 :     int         i;
                               2810                 : 
 2194 andrew                   2811 GIC         900 :     ctx.aio = aio;
                               2812             900 :     ctx.mcxt = mcxt;
 2194 andrew                   2813 CBC         900 :     ctx.acxt = CurrentMemoryContext;
 2194 andrew                   2814 GIC         900 :     ctx.astate = initArrayResult(aio->element_type, ctx.acxt, true);
 2194 andrew                   2815 CBC         900 :     ctx.colname = colname;
 2153 bruce                    2816             900 :     ctx.ndims = 0;              /* unknown yet */
 2194 andrew                   2817 GIC         900 :     ctx.dims = NULL;
 2194 andrew                   2818 CBC         900 :     ctx.sizes = NULL;
                               2819                 : 
                               2820             900 :     if (jsv->is_json)
 2194 andrew                   2821 GIC         450 :         populate_array_json(&ctx, jsv->val.json.str,
 2194 andrew                   2822 CBC         450 :                             jsv->val.json.len >= 0 ? jsv->val.json.len
 2153 bruce                    2823             450 :                             : strlen(jsv->val.json.str));
                               2824                 :     else
 2194 andrew                   2825 ECB             :     {
 2194 andrew                   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                 : 
 2153 bruce                    2832 CBC         786 :     lbs = palloc(sizeof(int) * ctx.ndims);
 2194 andrew                   2833 ECB             : 
 2194 andrew                   2834 CBC        1680 :     for (i = 0; i < ctx.ndims; i++)
                               2835             894 :         lbs[i] = 1;
 2194 andrew                   2836 ECB             : 
 2194 andrew                   2837 CBC         786 :     result = makeMdArrayResult(ctx.astate, ctx.ndims, ctx.dims, lbs,
                               2838                 :                                ctx.acxt, true);
 2194 andrew                   2839 ECB             : 
 2194 andrew                   2840 CBC         786 :     pfree(ctx.dims);
 2194 andrew                   2841 GIC         786 :     pfree(ctx.sizes);
                               2842             786 :     pfree(lbs);
 2194 andrew                   2843 ECB             : 
 2194 andrew                   2844 GIC         786 :     return result;
                               2845                 : }
                               2846                 : 
                               2847                 : static void
                               2848            1884 : JsValueToJsObject(JsValue *jsv, JsObject *jso)
 2194 andrew                   2849 ECB             : {
 2194 andrew                   2850 CBC        1884 :     jso->is_json = jsv->is_json;
                               2851                 : 
 2194 andrew                   2852 GIC        1884 :     if (jsv->is_json)
                               2853                 :     {
 2194 andrew                   2854 ECB             :         /* convert plain-text json into a hash table */
 2194 andrew                   2855 GIC         933 :         jso->val.json_hash =
 2153 bruce                    2856             942 :             get_json_object_as_hash(jsv->val.json.str,
 2153 bruce                    2857 CBC         942 :                                     jsv->val.json.len >= 0
                               2858                 :                                     ? jsv->val.json.len
                               2859             171 :                                     : strlen(jsv->val.json.str),
                               2860                 :                                     "populate_composite");
                               2861                 :     }
 2194 andrew                   2862 ECB             :     else
                               2863                 :     {
 2194 andrew                   2864 GIC         942 :         JsonbValue *jbv = jsv->val.jsonb;
 2194 andrew                   2865 ECB             : 
 2194 andrew                   2866 GIC         942 :         if (jbv->type == jbvBinary &&
                               2867             936 :             JsonContainerIsObject(jbv->val.binary.data))
 2141 tgl                      2868 ECB             :         {
 2194 andrew                   2869 CBC         933 :             jso->val.jsonb_cont = jbv->val.binary.data;
 2141 tgl                      2870 ECB             :         }
                               2871                 :         else
                               2872                 :         {
                               2873                 :             bool        is_scalar;
                               2874                 : 
 2141 tgl                      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",
 2141 tgl                      2884 ECB             :                               "populate_composite")));
                               2885                 :         }
 2194 andrew                   2886                 :     }
 2194 andrew                   2887 CBC        1866 : }
 2194 andrew                   2888 ECB             : 
 1991 tgl                      2889                 : /* acquire or update cached tuple descriptor for a composite type */
                               2890                 : static void
 1991 tgl                      2891 CBC        2283 : update_cached_tupdesc(CompositeIOData *io, MemoryContext mcxt)
                               2892                 : {
 2194 andrew                   2893            2283 :     if (!io->tupdesc ||
 1991 tgl                      2894            1308 :         io->tupdesc->tdtypeid != io->base_typid ||
                               2895            1308 :         io->tupdesc->tdtypmod != io->base_typmod)
 2194 andrew                   2896 ECB             :     {
 1991 tgl                      2897 GIC         975 :         TupleDesc   tupdesc = lookup_rowtype_tupdesc(io->base_typid,
                               2898                 :                                                      io->base_typmod);
 2153 bruce                    2899 ECB             :         MemoryContext oldcxt;
 2194 andrew                   2900                 : 
 2194 andrew                   2901 GIC         975 :         if (io->tupdesc)
 2194 andrew                   2902 UIC           0 :             FreeTupleDesc(io->tupdesc);
 2194 andrew                   2903 ECB             : 
                               2904                 :         /* copy tuple desc without constraints into cache memory context */
 2194 andrew                   2905 CBC         975 :         oldcxt = MemoryContextSwitchTo(mcxt);
 2194 andrew                   2906 GIC         975 :         io->tupdesc = CreateTupleDescCopy(tupdesc);
 2194 andrew                   2907 CBC         975 :         MemoryContextSwitchTo(oldcxt);
 2194 andrew                   2908 ECB             : 
 2194 andrew                   2909 GIC         975 :         ReleaseTupleDesc(tupdesc);
 2194 andrew                   2910 ECB             :     }
 1991 tgl                      2911 GIC        2283 : }
                               2912                 : 
 1991 tgl                      2913 ECB             : /* recursively populate a composite (row type) value from json/jsonb */
                               2914                 : static Datum
 1991 tgl                      2915 CBC        1884 : populate_composite(CompositeIOData *io,
                               2916                 :                    Oid typid,
 1991 tgl                      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 */
 1991 tgl                      2926 GIC        1884 :     update_cached_tupdesc(io, mcxt);
                               2927                 : 
 1991 tgl                      2928 CBC        1884 :     if (isnull)
 1991 tgl                      2929 LBC           0 :         result = (Datum) 0;
 1991 tgl                      2930 ECB             :     else
                               2931                 :     {
                               2932                 :         HeapTupleHeader tuple;
                               2933                 :         JsObject    jso;
                               2934                 : 
                               2935                 :         /* prepare input value */
 1991 tgl                      2936 GIC        1884 :         JsValueToJsObject(jsv, &jso);
 1991 tgl                      2937 ECB             : 
                               2938                 :         /* populate resulting record tuple */
 1991 tgl                      2939 CBC        1866 :         tuple = populate_record(io->tupdesc, &io->record_io,
 1991 tgl                      2940 ECB             :                                 defaultval, mcxt, &jso);
 1991 tgl                      2941 GIC        1704 :         result = HeapTupleHeaderGetDatum(tuple);
 2194 andrew                   2942 ECB             : 
 1991 tgl                      2943 GIC        1704 :         JsObjectFree(&jso);
                               2944                 :     }
                               2945                 : 
                               2946                 :     /*
                               2947                 :      * If it's domain over composite, check domain constraints.  (This should
 1991 tgl                      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                 :      */
 1991 tgl                      2951 CBC        1704 :     if (typid != io->base_typid && typid != RECORDOID)
 1991 tgl                      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
 2194 andrew                   2959            3789 : populate_scalar(ScalarIOData *io, Oid typid, int32 typmod, JsValue *jsv)
 2194 andrew                   2960 ECB             : {
                               2961                 :     Datum       res;
 2194 andrew                   2962 GIC        3789 :     char       *str = NULL;
                               2963            3789 :     char       *json = NULL;
 2194 andrew                   2964 ECB             : 
 2194 andrew                   2965 GIC        3789 :     if (jsv->is_json)
 2194 andrew                   2966 ECB             :     {
 2194 andrew                   2967 CBC        1908 :         int         len = jsv->val.json.len;
 2194 andrew                   2968 ECB             : 
 2194 andrew                   2969 GIC        1908 :         json = jsv->val.json.str;
 2194 andrew                   2970 CBC        1908 :         Assert(json);
 1398 tgl                      2971 GIC        1908 :         if (len >= 0)
                               2972                 :         {
                               2973                 :             /* Need to copy non-null-terminated string */
 2194 andrew                   2974 CBC           6 :             str = palloc(len + 1 * sizeof(char));
 2194 andrew                   2975 GBC           6 :             memcpy(str, json, len);
 2194 andrew                   2976 GIC           6 :             str[len] = '\0';
                               2977                 :         }
 2194 andrew                   2978 ECB             :         else
 1398 tgl                      2979 CBC        1902 :             str = json;         /* string is already null-terminated */
 1398 tgl                      2980 ECB             : 
                               2981                 :         /* If converting to json/jsonb, make string into valid JSON literal */
 1398 tgl                      2982 CBC        1908 :         if ((typid == JSONOID || typid == JSONBOID) &&
 1398 tgl                      2983 GIC         546 :             jsv->val.json.type == JSON_TOKEN_STRING)
 1398 tgl                      2984 ECB             :         {
                               2985                 :             StringInfoData buf;
                               2986                 : 
 1398 tgl                      2987 GIC         177 :             initStringInfo(&buf);
 1398 tgl                      2988 CBC         177 :             escape_json(&buf, str);
                               2989                 :             /* free temporary buffer */
 1398 tgl                      2990 GIC         177 :             if (str != json)
 1398 tgl                      2991 UIC           0 :                 pfree(str);
 1398 tgl                      2992 GIC         177 :             str = buf.data;
                               2993                 :         }
                               2994                 :     }
                               2995                 :     else
                               2996                 :     {
 2194 andrew                   2997            1881 :         JsonbValue *jbv = jsv->val.jsonb;
                               2998                 : 
 2194 andrew                   2999 CBC        1881 :         if (typid == JSONBOID)
                               3000                 :         {
 2153 bruce                    3001              33 :             Jsonb      *jsonb = JsonbValueToJsonb(jbv); /* directly use jsonb */
 2153 bruce                    3002 EUB             : 
 2029 tgl                      3003 GIC          33 :             return JsonbPGetDatum(jsonb);
                               3004                 :         }
                               3005                 :         /* convert jsonb to string for typio call */
 2194 andrew                   3006            1848 :         else if (typid == JSONOID && jbv->type != jbvBinary)
                               3007             486 :         {
                               3008                 :             /*
 2194 andrew                   3009 ECB             :              * Convert scalar jsonb (non-scalars are passed here as jbvBinary)
                               3010                 :              * to json string, preserving quotes around top-level strings.
                               3011                 :              */
 2153 bruce                    3012 CBC         486 :             Jsonb      *jsonb = JsonbValueToJsonb(jbv);
                               3013                 : 
 2194 andrew                   3014             486 :             str = JsonbToCString(NULL, &jsonb->root, VARSIZE(jsonb));
                               3015                 :         }
 2118 tgl                      3016            1362 :         else if (jbv->type == jbvString) /* quotes are stripped */
 2194 andrew                   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)
 2194 andrew                   3024 CBC          42 :             str = JsonbToCString(NULL, jbv->val.binary.data,
 2153 bruce                    3025 ECB             :                                  jbv->val.binary.len);
                               3026                 :         else
 2194 andrew                   3027 LBC           0 :             elog(ERROR, "unrecognized jsonb type: %d", (int) jbv->type);
                               3028                 :     }
                               3029                 : 
 2194 andrew                   3030 GIC        3756 :     res = InputFunctionCall(&io->typiofunc, str, io->typioparam, typmod);
                               3031                 : 
 2194 andrew                   3032 ECB             :     /* free temporary buffer */
 2194 andrew                   3033 GIC        3732 :     if (str != json)
                               3034            2019 :         pfree(str);
 2194 andrew                   3035 ECB             : 
 2194 andrew                   3036 CBC        3732 :     return res;
                               3037                 : }
 2194 andrew                   3038 ECB             : 
                               3039                 : static Datum
 2153 bruce                    3040 CBC        1350 : populate_domain(DomainIOData *io,
                               3041                 :                 Oid typid,
 2153 bruce                    3042 ECB             :                 const char *colname,
                               3043                 :                 MemoryContext mcxt,
                               3044                 :                 JsValue *jsv,
                               3045                 :                 bool isnull)
                               3046                 : {
 2194 andrew                   3047                 :     Datum       res;
                               3048                 : 
 2194 andrew                   3049 CBC        1350 :     if (isnull)
 2194 andrew                   3050 GIC        1314 :         res = (Datum) 0;
                               3051                 :     else
 2194 andrew                   3052 ECB             :     {
 2194 andrew                   3053 GIC          36 :         res = populate_record_field(io->base_io,
                               3054                 :                                     io->base_typid, io->base_typmod,
 2194 andrew                   3055 ECB             :                                     colname, mcxt, PointerGetDatum(NULL),
                               3056                 :                                     jsv, &isnull);
 2194 andrew                   3057 GIC          30 :         Assert(!isnull);
                               3058                 :     }
                               3059                 : 
 2194 andrew                   3060 CBC        1344 :     domain_check(res, isnull, typid, &io->domain_info, mcxt);
 2194 andrew                   3061 ECB             : 
 2194 andrew                   3062 GIC        1320 :     return res;
 2194 andrew                   3063 ECB             : }
 2194 andrew                   3064 EUB             : 
 2194 andrew                   3065 ECB             : /* prepare column metadata cache for the given type */
                               3066                 : static void
 2153 bruce                    3067 GIC       10131 : prepare_column_cache(ColumnIOData *column,
                               3068                 :                      Oid typid,
                               3069                 :                      int32 typmod,
 2153 bruce                    3070 ECB             :                      MemoryContext mcxt,
                               3071                 :                      bool need_scalar)
 2194 andrew                   3072                 : {
                               3073                 :     HeapTuple   tup;
 2153 bruce                    3074                 :     Form_pg_type type;
                               3075                 : 
 2194 andrew                   3076 CBC       10131 :     column->typid = typid;
 2194 andrew                   3077 GIC       10131 :     column->typmod = typmod;
                               3078                 : 
 2194 andrew                   3079 CBC       10131 :     tup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
                               3080           10131 :     if (!HeapTupleIsValid(tup))
 2194 andrew                   3081 UIC           0 :         elog(ERROR, "cache lookup failed for type %u", typid);
                               3082                 : 
 2194 andrew                   3083 GIC       10131 :     type = (Form_pg_type) GETSTRUCT(tup);
                               3084                 : 
 2194 andrew                   3085 CBC       10131 :     if (type->typtype == TYPTYPE_DOMAIN)
                               3086                 :     {
 1991 tgl                      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;
 1991 tgl                      3092 CBC         978 :         int32       base_typmod = typmod;
 1991 tgl                      3093 ECB             : 
 1991 tgl                      3094 CBC         978 :         base_typid = getBaseTypeAndTypmod(typid, &base_typmod);
 1991 tgl                      3095 GIC         978 :         if (get_typtype(base_typid) == TYPTYPE_COMPOSITE)
 1991 tgl                      3096 ECB             :         {
                               3097                 :             /* domain over composite has its own code path */
 1991 tgl                      3098 GIC          36 :             column->typcat = TYPECAT_COMPOSITE_DOMAIN;
                               3099              36 :             column->io.composite.record_io = NULL;
 1991 tgl                      3100 GBC          36 :             column->io.composite.tupdesc = NULL;
 1991 tgl                      3101 GIC          36 :             column->io.composite.base_typid = base_typid;
                               3102              36 :             column->io.composite.base_typmod = base_typmod;
 1991 tgl                      3103 CBC          36 :             column->io.composite.domain_info = NULL;
                               3104                 :         }
                               3105                 :         else
 1991 tgl                      3106 ECB             :         {
                               3107                 :             /* domain over anything else */
 1991 tgl                      3108 GIC         942 :             column->typcat = TYPECAT_DOMAIN;
 1991 tgl                      3109 CBC         942 :             column->io.domain.base_typid = base_typid;
 1991 tgl                      3110 GIC         942 :             column->io.domain.base_typmod = base_typmod;
                               3111             942 :             column->io.domain.base_io =
                               3112             942 :                 MemoryContextAllocZero(mcxt, sizeof(ColumnIOData));
 1991 tgl                      3113 CBC         942 :             column->io.domain.domain_info = NULL;
                               3114                 :         }
                               3115                 :     }
 2194 andrew                   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;
 1991 tgl                      3121            1269 :         column->io.composite.base_typid = typid;
 1991 tgl                      3122 CBC        1269 :         column->io.composite.base_typmod = typmod;
                               3123            1269 :         column->io.composite.domain_info = NULL;
                               3124                 :     }
  851 tgl                      3125 GIC        7884 :     else if (IsTrueArrayType(type))
 2194 andrew                   3126 ECB             :     {
 2194 andrew                   3127 GIC        3750 :         column->typcat = TYPECAT_ARRAY;
                               3128            3750 :         column->io.array.element_info = MemoryContextAllocZero(mcxt,
                               3129                 :                                                                sizeof(ColumnIOData));
 2194 andrew                   3130 CBC        3750 :         column->io.array.element_type = type->typelem;
                               3131                 :         /* array element typemod stored in attribute's typmod */
 2194 andrew                   3132 GIC        3750 :         column->io.array.element_typmod = typmod;
 2194 andrew                   3133 ECB             :     }
                               3134                 :     else
 1991 tgl                      3135                 :     {
 2194 andrew                   3136 GIC        4134 :         column->typcat = TYPECAT_SCALAR;
 1991 tgl                      3137            4134 :         need_scalar = true;
                               3138                 :     }
                               3139                 : 
 1991 tgl                      3140 ECB             :     /* caller can force us to look up scalar_io info even for non-scalars */
 1991 tgl                      3141 GIC       10131 :     if (need_scalar)
                               3142                 :     {
                               3143                 :         Oid         typioproc;
                               3144                 : 
 2194 andrew                   3145            9366 :         getTypeInputInfo(typid, &typioproc, &column->scalar_io.typioparam);
                               3146            9366 :         fmgr_info_cxt(typioproc, &column->scalar_io.typiofunc, mcxt);
                               3147                 :     }
                               3148                 : 
 2194 andrew                   3149 CBC       10131 :     ReleaseSysCache(tup);
                               3150           10131 : }
                               3151                 : 
 2194 andrew                   3152 ECB             : /* recursively populate a record field or an array element from a json/jsonb value */
                               3153                 : static Datum
 2194 andrew                   3154 GBC       17619 : populate_record_field(ColumnIOData *col,
                               3155                 :                       Oid typid,
 2153 bruce                    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                 : 
 2194 andrew                   3165 CBC       17619 :     check_stack_depth();
                               3166                 : 
 1991 tgl                      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                 :      */
 2194 andrew                   3171 CBC       17619 :     if (col->typid != typid || col->typmod != typmod)
 1991 tgl                      3172            9366 :         prepare_column_cache(col, typid, typmod, mcxt, true);
 2194 andrew                   3173 ECB             : 
 2194 andrew                   3174 CBC       17619 :     *isnull = JsValueIsNull(jsv);
 2194 andrew                   3175 ECB             : 
 2194 andrew                   3176 CBC       17619 :     typcat = col->typcat;
                               3177                 : 
                               3178                 :     /* try to convert json string to a non-scalar type through input function */
 2194 andrew                   3179 GIC       17619 :     if (JsValueIsString(jsv) &&
 1991 tgl                      3180            1881 :         (typcat == TYPECAT_ARRAY ||
 1991 tgl                      3181 CBC        1869 :          typcat == TYPECAT_COMPOSITE ||
 1991 tgl                      3182 ECB             :          typcat == TYPECAT_COMPOSITE_DOMAIN))
 2194 andrew                   3183 CBC          24 :         typcat = TYPECAT_SCALAR;
 2194 andrew                   3184 ECB             : 
 1991 tgl                      3185                 :     /* we must perform domain checks for NULLs, otherwise exit immediately */
 1991 tgl                      3186 CBC       17619 :     if (*isnull &&
 1991 tgl                      3187 GIC       10614 :         typcat != TYPECAT_DOMAIN &&
                               3188                 :         typcat != TYPECAT_COMPOSITE_DOMAIN)
 2194 andrew                   3189 CBC       10614 :         return (Datum) 0;
                               3190                 : 
                               3191            7005 :     switch (typcat)
 2194 andrew                   3192 ECB             :     {
 2194 andrew                   3193 CBC        3789 :         case TYPECAT_SCALAR:
                               3194            3789 :             return populate_scalar(&col->scalar_io, typid, typmod, jsv);
 2194 andrew                   3195 ECB             : 
 2194 andrew                   3196 CBC         900 :         case TYPECAT_ARRAY:
 2194 andrew                   3197 GIC         900 :             return populate_array(&col->io.array, colname, mcxt, jsv);
 2194 andrew                   3198 ECB             : 
 2194 andrew                   3199 GIC         966 :         case TYPECAT_COMPOSITE:
 1991 tgl                      3200 ECB             :         case TYPECAT_COMPOSITE_DOMAIN:
 1991 tgl                      3201 CBC         972 :             return populate_composite(&col->io.composite, typid,
                               3202                 :                                       colname, mcxt,
 2194 andrew                   3203             966 :                                       DatumGetPointer(defaultval)
 2194 andrew                   3204 GIC           6 :                                       ? DatumGetHeapTupleHeader(defaultval)
 2194 andrew                   3205 ECB             :                                       : NULL,
 1991 tgl                      3206 GIC         966 :                                       jsv, *isnull);
                               3207                 : 
 2194 andrew                   3208            1350 :         case TYPECAT_DOMAIN:
 2194 andrew                   3209 CBC        1350 :             return populate_domain(&col->io.domain, typid, colname, mcxt,
                               3210            1350 :                                    jsv, *isnull);
                               3211                 : 
 2194 andrew                   3212 UIC           0 :         default:
                               3213               0 :             elog(ERROR, "unrecognized type category '%c'", typcat);
 2194 andrew                   3214 ECB             :             return (Datum) 0;
                               3215                 :     }
                               3216                 : }
                               3217                 : 
                               3218                 : static RecordIOData *
 2194 andrew                   3219 CBC        1071 : allocate_record_info(MemoryContext mcxt, int ncolumns)
                               3220                 : {
                               3221                 :     RecordIOData *data = (RecordIOData *)
 2153 bruce                    3222            1071 :     MemoryContextAlloc(mcxt,
 2153 bruce                    3223 ECB             :                        offsetof(RecordIOData, columns) +
 2153 bruce                    3224 GIC        1071 :                        ncolumns * sizeof(ColumnIOData));
                               3225                 : 
 2194 andrew                   3226            1071 :     data->record_type = InvalidOid;
 2194 andrew                   3227 CBC        1071 :     data->record_typmod = 0;
 2194 andrew                   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;
 2194 andrew                   3238 ECB             : 
 2194 andrew                   3239 GIC       15009 :     if (jsv->is_json)
                               3240                 :     {
                               3241            7518 :         JsonHashEntry *hashentry = hash_search(obj->val.json_hash, field,
                               3242                 :                                                HASH_FIND, NULL);
                               3243                 : 
 2194 andrew                   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
 2194 andrew                   3252 ECB             :     {
 2194 andrew                   3253 CBC        7491 :         jsv->val.jsonb = !obj->val.jsonb_cont ? NULL :
 1297 alvherre                 3254            7491 :             getKeyJsonValueFromContainer(obj->val.jsonb_cont, field, strlen(field),
                               3255                 :                                          NULL);
 2194 andrew                   3256 ECB             : 
 2194 andrew                   3257 GIC        7491 :         return jsv->val.jsonb != NULL;
                               3258                 :     }
 2194 andrew                   3259 ECB             : }
                               3260                 : 
                               3261                 : /* populate a record tuple from json/jsonb value */
                               3262                 : static HeapTupleHeader
 2153 bruce                    3263 GIC        2106 : populate_record(TupleDesc tupdesc,
 2151 peter_e                  3264 ECB             :                 RecordIOData **record_p,
                               3265                 :                 HeapTupleHeader defaultval,
 2153 bruce                    3266                 :                 MemoryContext mcxt,
                               3267                 :                 JsObject *obj)
                               3268                 : {
 2151 peter_e                  3269 CBC        2106 :     RecordIOData *record = *record_p;
 2153 bruce                    3270 ECB             :     Datum      *values;
                               3271                 :     bool       *nulls;
                               3272                 :     HeapTuple   res;
 2153 bruce                    3273 GIC        2106 :     int         ncolumns = tupdesc->natts;
 2153 bruce                    3274 ECB             :     int         i;
                               3275                 : 
 2194 andrew                   3276                 :     /*
 2153 bruce                    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                 :      */
 2194 andrew                   3281 CBC        2106 :     if (defaultval && JsObjectIsEmpty(obj))
                               3282               6 :         return defaultval;
 2194 andrew                   3283 ECB             : 
                               3284                 :     /* (re)allocate metadata cache */
 2194 andrew                   3285 GBC        2100 :     if (record == NULL ||
                               3286            1029 :         record->ncolumns != ncolumns)
 2151 peter_e                  3287 GIC        1071 :         *record_p = record = allocate_record_info(mcxt, ncolumns);
                               3288                 : 
                               3289                 :     /* invalidate metadata cache if the record type has changed */
 2194 andrew                   3290            2100 :     if (record->record_type != tupdesc->tdtypeid ||
                               3291            1029 :         record->record_typmod != tupdesc->tdtypmod)
 2194 andrew                   3292 ECB             :     {
 2194 andrew                   3293 GIC       20199 :         MemSet(record, 0, offsetof(RecordIOData, columns) +
                               3294                 :                ncolumns * sizeof(ColumnIOData));
 2194 andrew                   3295 CBC        1071 :         record->record_type = tupdesc->tdtypeid;
 2194 andrew                   3296 GIC        1071 :         record->record_typmod = tupdesc->tdtypmod;
 2194 andrew                   3297 CBC        1071 :         record->ncolumns = ncolumns;
                               3298                 :     }
 2194 andrew                   3299 ECB             : 
 2194 andrew                   3300 CBC        2100 :     values = (Datum *) palloc(ncolumns * sizeof(Datum));
                               3301            2100 :     nulls = (bool *) palloc(ncolumns * sizeof(bool));
 2194 andrew                   3302 ECB             : 
 2194 andrew                   3303 GIC        2100 :     if (defaultval)
 2194 andrew                   3304 ECB             :     {
                               3305                 :         HeapTupleData tuple;
                               3306                 : 
                               3307                 :         /* Build a temporary HeapTuple control structure */
 2194 andrew                   3308 CBC         216 :         tuple.t_len = HeapTupleHeaderGetDatumLength(defaultval);
 2194 andrew                   3309 GIC         216 :         ItemPointerSetInvalid(&(tuple.t_self));
 2194 andrew                   3310 CBC         216 :         tuple.t_tableOid = InvalidOid;
 2194 andrew                   3311 GIC         216 :         tuple.t_data = defaultval;
 2194 andrew                   3312 ECB             : 
                               3313                 :         /* Break down the tuple into fields */
 2194 andrew                   3314 CBC         216 :         heap_deform_tuple(&tuple, tupdesc, values, nulls);
                               3315                 :     }
                               3316                 :     else
 2194 andrew                   3317 ECB             :     {
 2194 andrew                   3318 CBC       17319 :         for (i = 0; i < ncolumns; ++i)
                               3319                 :         {
                               3320           15435 :             values[i] = (Datum) 0;
 2194 andrew                   3321 GIC       15435 :             nulls[i] = true;
 2194 andrew                   3322 ECB             :         }
                               3323                 :     }
                               3324                 : 
 2194 andrew                   3325 GIC       16941 :     for (i = 0; i < ncolumns; ++i)
 2194 andrew                   3326 ECB             :     {
 2058 andres                   3327 CBC       15009 :         Form_pg_attribute att = TupleDescAttr(tupdesc, i);
 2153 bruce                    3328 GIC       15009 :         char       *colname = NameStr(att->attname);
                               3329           15009 :         JsValue     field = {0};
 2153 bruce                    3330 ECB             :         bool        found;
                               3331                 : 
                               3332                 :         /* Ignore dropped columns in datatype */
 2194 andrew                   3333 GIC       15009 :         if (att->attisdropped)
                               3334                 :         {
 2194 andrew                   3335 UIC           0 :             nulls[i] = true;
 2194 andrew                   3336 CBC         378 :             continue;
                               3337                 :         }
                               3338                 : 
 2194 andrew                   3339 GIC       15009 :         found = JsObjectGetField(obj, colname, &field);
                               3340                 : 
                               3341                 :         /*
 2194 andrew                   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                 :          */
 2194 andrew                   3349 GIC       15009 :         if (defaultval && !found)
                               3350             378 :             continue;
                               3351                 : 
                               3352           14631 :         values[i] = populate_record_field(&record->columns[i],
                               3353                 :                                           att->atttypid,
 2194 andrew                   3354 ECB             :                                           att->atttypmod,
                               3355                 :                                           colname,
                               3356                 :                                           mcxt,
 2194 andrew                   3357 GIC       14631 :                                           nulls[i] ? (Datum) 0 : values[i],
 2194 andrew                   3358 ECB             :                                           &field,
                               3359                 :                                           &nulls[i]);
                               3360                 :     }
                               3361                 : 
 2194 andrew                   3362 GIC        1932 :     res = heap_form_tuple(tupdesc, values, nulls);
 2194 andrew                   3363 ECB             : 
 2194 andrew                   3364 CBC        1932 :     pfree(values);
 2194 andrew                   3365 GIC        1932 :     pfree(nulls);
 2194 andrew                   3366 ECB             : 
 2194 andrew                   3367 GIC        1932 :     return res->t_data;
 2194 andrew                   3368 ECB             : }
                               3369                 : 
 1329 tgl                      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
 1329 tgl                      3376 CBC         765 : get_record_type_from_argument(FunctionCallInfo fcinfo,
                               3377                 :                               const char *funcname,
                               3378                 :                               PopulateRecordCache *cache)
                               3379                 : {
 1329 tgl                      3380 GIC         765 :     cache->argtype = get_fn_expr_argtype(fcinfo->flinfo, 0);
 1329 tgl                      3381 CBC         765 :     prepare_column_cache(&cache->c,
 1329 tgl                      3382 ECB             :                          cache->argtype, -1,
                               3383                 :                          cache->fn_mcxt, false);
 1329 tgl                      3384 CBC         765 :     if (cache->c.typcat != TYPECAT_COMPOSITE &&
 1329 tgl                      3385 GIC          36 :         cache->c.typcat != TYPECAT_COMPOSITE_DOMAIN)
 1329 tgl                      3386 UIC           0 :         ereport(ERROR,
 1329 tgl                      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)));
 1329 tgl                      3391 CBC         765 : }
                               3392                 : 
 1329 tgl                      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
 1329 tgl                      3402 CBC         156 : get_record_type_from_query(FunctionCallInfo fcinfo,
                               3403                 :                            const char *funcname,
                               3404                 :                            PopulateRecordCache *cache)
                               3405                 : {
 1329 tgl                      3406 ECB             :     TupleDesc   tupdesc;
                               3407                 :     MemoryContext old_cxt;
 1329 tgl                      3408 EUB             : 
 1329 tgl                      3409 CBC         156 :     if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
 1329 tgl                      3410 GIC          18 :         ereport(ERROR,
                               3411                 :                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
 1329 tgl                      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                 : 
 1329 tgl                      3419 GIC         138 :     Assert(tupdesc);
                               3420             138 :     cache->argtype = tupdesc->tdtypeid;
                               3421                 : 
 1329 tgl                      3422 ECB             :     /* If we go through this more than once, avoid memory leak */
 1329 tgl                      3423 CBC         138 :     if (cache->c.io.composite.tupdesc)
 1329 tgl                      3424 UIC           0 :         FreeTupleDesc(cache->c.io.composite.tupdesc);
 1329 tgl                      3425 ECB             : 
                               3426                 :     /* Save identified tupdesc */
 1329 tgl                      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;
 1329 tgl                      3430 CBC         138 :     cache->c.io.composite.base_typmod = tupdesc->tdtypmod;
 1329 tgl                      3431 GIC         138 :     MemoryContextSwitchTo(old_cxt);
                               3432             138 : }
                               3433                 : 
                               3434                 : /*
 1731 tgl                      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                 :  */
 2194 andrew                   3438                 : static Datum
 2194 andrew                   3439 GIC         924 : populate_record_worker(FunctionCallInfo fcinfo, const char *funcname,
 1731 tgl                      3440 ECB             :                        bool is_json, bool have_record_arg)
                               3441                 : {
 2194 andrew                   3442 GIC         924 :     int         json_arg_num = have_record_arg ? 1 : 0;
 2153 bruce                    3443             924 :     JsValue     jsv = {0};
                               3444                 :     HeapTupleHeader rec;
                               3445                 :     Datum       rettuple;
                               3446                 :     JsonbValue  jbv;
 2194 andrew                   3447             924 :     MemoryContext fnmcxt = fcinfo->flinfo->fn_mcxt;
                               3448             924 :     PopulateRecordCache *cache = fcinfo->flinfo->fn_extra;
 2194 andrew                   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
 1991 tgl                      3453                 :      * query; so we may not be able to fully resolve a RECORD input type yet.
 2194 andrew                   3454                 :      */
 2194 andrew                   3455 GIC         924 :     if (!cache)
                               3456                 :     {
 2194 andrew                   3457 CBC         720 :         fcinfo->flinfo->fn_extra = cache =
 2153 bruce                    3458             720 :             MemoryContextAllocZero(fnmcxt, sizeof(*cache));
 1329 tgl                      3459 GBC         720 :         cache->fn_mcxt = fnmcxt;
                               3460                 : 
 1991 tgl                      3461 GIC         720 :         if (have_record_arg)
 1329                          3462             618 :             get_record_type_from_argument(fcinfo, funcname, cache);
                               3463                 :         else
 1329 tgl                      3464 CBC         102 :             get_record_type_from_query(fcinfo, funcname, cache);
                               3465                 :     }
                               3466                 : 
                               3467                 :     /* Collect record arg if we have one */
 1329 tgl                      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                 :     {
 1991                          3472              54 :         rec = PG_GETARG_HEAPTUPLEHEADER(0);
                               3473                 : 
                               3474                 :         /*
 1991 tgl                      3475 ECB             :          * When declared arg type is RECORD, identify actual record type from
                               3476                 :          * the tuple itself.
                               3477                 :          */
 1991 tgl                      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);
 1991 tgl                      3482 ECB             :         }
                               3483                 :     }
                               3484                 :     else
                               3485                 :     {
 1991 tgl                      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                 :          */
 1329 tgl                      3492 CBC         768 :         if (cache->argtype == RECORDOID)
 1329 tgl                      3493 ECB             :         {
 1329 tgl                      3494 GIC          12 :             get_record_type_from_query(fcinfo, funcname, cache);
                               3495                 :             /* This can't change argtype, which is important for next time */
 1329 tgl                      3496 CBC           6 :             Assert(cache->argtype == RECORDOID);
 1329 tgl                      3497 EUB             :         }
                               3498                 :     }
                               3499                 : 
 1991 tgl                      3500 ECB             :     /* If no JSON argument, just return the record (if any) unchanged */
 1991 tgl                      3501 CBC         918 :     if (PG_ARGISNULL(json_arg_num))
 1991 tgl                      3502 ECB             :     {
 1991 tgl                      3503 LBC           0 :         if (rec)
                               3504               0 :             PG_RETURN_POINTER(rec);
 1991 tgl                      3505 ECB             :         else
 1991 tgl                      3506 UIC           0 :             PG_RETURN_NULL();
                               3507                 :     }
                               3508                 : 
 1731 tgl                      3509 GIC         918 :     jsv.is_json = is_json;
                               3510                 : 
                               3511             918 :     if (is_json)
 2194 andrew                   3512 ECB             :     {
 2194 andrew                   3513 GIC         459 :         text       *json = PG_GETARG_TEXT_PP(json_arg_num);
                               3514                 : 
 2194 andrew                   3515 CBC         459 :         jsv.val.json.str = VARDATA_ANY(json);
                               3516             459 :         jsv.val.json.len = VARSIZE_ANY_EXHDR(json);
 2153 bruce                    3517 GIC         459 :         jsv.val.json.type = JSON_TOKEN_INVALID; /* not used in
                               3518                 :                                                  * populate_composite() */
                               3519                 :     }
 2194 andrew                   3520 ECB             :     else
                               3521                 :     {
 2029 tgl                      3522 GIC         459 :         Jsonb      *jb = PG_GETARG_JSONB_P(json_arg_num);
                               3523                 : 
 2194 andrew                   3524             459 :         jsv.val.jsonb = &jbv;
                               3525                 : 
                               3526                 :         /* fill binary jsonb value pointing to jb */
                               3527             459 :         jbv.type = jbvBinary;
 2194 andrew                   3528 CBC         459 :         jbv.val.binary.data = &jb->root;
 2194 andrew                   3529 GIC         459 :         jbv.val.binary.len = VARSIZE(jb) - VARHDRSZ;
 2194 andrew                   3530 ECB             :     }
                               3531                 : 
 1991 tgl                      3532 CBC         918 :     rettuple = populate_composite(&cache->c.io.composite, cache->argtype,
                               3533                 :                                   NULL, fnmcxt, rec, &jsv, false);
 2194 andrew                   3534 ECB             : 
 2194 andrew                   3535 CBC         750 :     PG_RETURN_DATUM(rettuple);
                               3536                 : }
 2194 andrew                   3537 ECB             : 
                               3538                 : /*
                               3539                 :  * get_json_object_as_hash
                               3540                 :  *
                               3541                 :  * decompose a json object into a hash table.
                               3542                 :  */
                               3543                 : static HTAB *
 2194 andrew                   3544 GIC         942 : get_json_object_as_hash(char *json, int len, const char *funcname)
 2194 andrew                   3545 ECB             : {
                               3546                 :     HASHCTL     ctl;
                               3547                 :     HTAB       *tab;
                               3548                 :     JHashState *state;
 1166 rhaas                    3549 GIC         942 :     JsonLexContext *lex = makeJsonLexContextCstringLen(json, len, GetDatabaseEncoding(), true);
                               3550                 :     JsonSemAction *sem;
 2194 andrew                   3551 ECB             : 
 2194 andrew                   3552 GIC         942 :     ctl.keysize = NAMEDATALEN;
 2194 andrew                   3553 CBC         942 :     ctl.entrysize = sizeof(JsonHashEntry);
                               3554             942 :     ctl.hcxt = CurrentMemoryContext;
 2194 andrew                   3555 GIC         942 :     tab = hash_create("json object hashtable",
                               3556                 :                       100,
                               3557                 :                       &ctl,
                               3558                 :                       HASH_ELEM | HASH_STRINGS | HASH_CONTEXT);
 2194 andrew                   3559 ECB             : 
 2194 andrew                   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;
 2194 andrew                   3565 CBC         942 :     state->lex = lex;
                               3566                 : 
                               3567             942 :     sem->semstate = (void *) state;
 2194 andrew                   3568 GIC         942 :     sem->array_start = hash_array_start;
 2194 andrew                   3569 CBC         942 :     sem->scalar = hash_scalar;
 2194 andrew                   3570 GIC         942 :     sem->object_field_start = hash_object_field_start;
                               3571             942 :     sem->object_field_end = hash_object_field_end;
                               3572                 : 
 1168 rhaas                    3573             942 :     pg_parse_json_or_ereport(lex, sem);
 2194 andrew                   3574 ECB             : 
 2194 andrew                   3575 GIC         933 :     return tab;
 2194 andrew                   3576 EUB             : }
                               3577                 : 
                               3578                 : static JsonParseErrorType
 2194 andrew                   3579 GBC        3078 : hash_object_field_start(void *state, char *fname, bool isnull)
                               3580                 : {
 2194 andrew                   3581 GIC        3078 :     JHashState *_state = (JHashState *) state;
 2194 andrew                   3582 ECB             : 
 2194 andrew                   3583 GIC        3078 :     if (_state->lex->lex_level > 1)
  119 tgl                      3584 GNC        1158 :         return JSON_SUCCESS;
                               3585                 : 
 2194 andrew                   3586 ECB             :     /* remember token type */
 2194 andrew                   3587 GIC        1920 :     _state->saved_token_type = _state->lex->token_type;
 2194 andrew                   3588 ECB             : 
 2194 andrew                   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 */
 2194 andrew                   3593 GIC         627 :         _state->save_json_start = _state->lex->token_start;
                               3594                 :     }
 3663 andrew                   3595 ECB             :     else
                               3596                 :     {
                               3597                 :         /* must be a scalar */
 3663 andrew                   3598 GIC        1293 :         _state->save_json_start = NULL;
                               3599                 :     }
                               3600                 : 
  119 tgl                      3601 GNC        1920 :     return JSON_SUCCESS;
 3663 andrew                   3602 ECB             : }
                               3603                 : 
                               3604                 : static JsonParseErrorType
 3663 andrew                   3605 GIC        3078 : hash_object_field_end(void *state, char *fname, bool isnull)
                               3606                 : {
 3550 peter_e                  3607 CBC        3078 :     JHashState *_state = (JHashState *) state;
                               3608                 :     JsonHashEntry *hashentry;
                               3609                 :     bool        found;
 3663 andrew                   3610 ECB             : 
                               3611                 :     /*
                               3612                 :      * Ignore nested fields.
                               3613                 :      */
 2594 tgl                      3614 GIC        3078 :     if (_state->lex->lex_level > 1)
  119 tgl                      3615 GNC        1158 :         return JSON_SUCCESS;
                               3616                 : 
                               3617                 :     /*
                               3618                 :      * Ignore field names >= NAMEDATALEN - they can't match a record field.
 3210 tgl                      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                 :      */
 3210 tgl                      3624 CBC        1920 :     if (strlen(fname) >= NAMEDATALEN)
  119 tgl                      3625 UNC           0 :         return JSON_SUCCESS;
                               3626                 : 
 3210 tgl                      3627 CBC        1920 :     hashentry = hash_search(_state->hash, fname, HASH_ENTER, &found);
 3663 andrew                   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                 : 
 2194 andrew                   3634 GIC        1920 :     hashentry->type = _state->saved_token_type;
 2194 andrew                   3635 CBC        1920 :     Assert(isnull == (hashentry->type == JSON_TOKEN_NULL));
 2194 andrew                   3636 ECB             : 
 3663 andrew                   3637 GIC        1920 :     if (_state->save_json_start != NULL)
 3663 andrew                   3638 ECB             :     {
 3663 andrew                   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;
 3663 andrew                   3645 ECB             :     }
                               3646                 :     else
                               3647                 :     {
                               3648                 :         /* must have had a scalar instead */
 3663 andrew                   3649 GIC        1293 :         hashentry->val = _state->saved_scalar;
 3663 andrew                   3650 ECB             :     }
                               3651                 : 
  119 tgl                      3652 GNC        1920 :     return JSON_SUCCESS;
                               3653                 : }
                               3654                 : 
                               3655                 : static JsonParseErrorType
 3663 andrew                   3656 CBC         636 : hash_array_start(void *state)
                               3657                 : {
 3550 peter_e                  3658             636 :     JHashState *_state = (JHashState *) state;
                               3659                 : 
 3663 andrew                   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                 : 
  119 tgl                      3665 GNC         633 :     return JSON_SUCCESS;
 3663 andrew                   3666 ECB             : }
                               3667                 : 
                               3668                 : static JsonParseErrorType
 3663 andrew                   3669 CBC        3690 : hash_scalar(void *state, char *token, JsonTokenType tokentype)
                               3670                 : {
 3550 peter_e                  3671 GIC        3690 :     JHashState *_state = (JHashState *) state;
 3663 andrew                   3672 ECB             : 
 3663 andrew                   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)));
 3663 andrew                   3677 ECB             : 
 3663 andrew                   3678 GIC        3684 :     if (_state->lex->lex_level == 1)
                               3679                 :     {
 3663 andrew                   3680 CBC        1293 :         _state->saved_scalar = token;
                               3681                 :         /* saved_token_type must already be set in hash_object_field_start() */
 2194 andrew                   3682 GIC        1293 :         Assert(_state->saved_token_type == tokentype);
                               3683                 :     }
                               3684                 : 
  119 tgl                      3685 GNC        3684 :     return JSON_SUCCESS;
 3663 andrew                   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
 3304 andrew                   3700 GIC          75 : jsonb_populate_recordset(PG_FUNCTION_ARGS)
                               3701                 : {
 1731 tgl                      3702              75 :     return populate_recordset_worker(fcinfo, "jsonb_populate_recordset",
                               3703                 :                                      false, true);
                               3704                 : }
 3304 andrew                   3705 ECB             : 
 3301 andrew                   3706 EUB             : Datum
 3301 andrew                   3707 GIC           9 : jsonb_to_recordset(PG_FUNCTION_ARGS)
 3301 andrew                   3708 ECB             : {
 1731 tgl                      3709 GIC           9 :     return populate_recordset_worker(fcinfo, "jsonb_to_recordset",
                               3710                 :                                      false, false);
                               3711                 : }
                               3712                 : 
                               3713                 : Datum
 3301 andrew                   3714              78 : json_populate_recordset(PG_FUNCTION_ARGS)
 3301 andrew                   3715 ECB             : {
 1731 tgl                      3716 CBC          78 :     return populate_recordset_worker(fcinfo, "json_populate_recordset",
                               3717                 :                                      true, true);
 3301 andrew                   3718 ECB             : }
                               3719                 : 
                               3720                 : Datum
 3301 andrew                   3721 CBC           9 : json_to_recordset(PG_FUNCTION_ARGS)
                               3722                 : {
 1731 tgl                      3723               9 :     return populate_recordset_worker(fcinfo, "json_to_recordset",
 1731 tgl                      3724 ECB             :                                      true, false);
 3301 andrew                   3725                 : }
                               3726                 : 
                               3727                 : static void
 2194 andrew                   3728 GIC         240 : populate_recordset_record(PopulateRecordsetState *state, JsObject *obj)
                               3729                 : {
 1329 tgl                      3730 CBC         240 :     PopulateRecordCache *cache = state->cache;
                               3731                 :     HeapTupleHeader tuphead;
                               3732                 :     HeapTupleData tuple;
 3304 andrew                   3733 ECB             : 
                               3734                 :     /* acquire/update cached tuple descriptor */
 1991 tgl                      3735 GIC         240 :     update_cached_tupdesc(&cache->c.io.composite, cache->fn_mcxt);
                               3736                 : 
 1991 tgl                      3737 ECB             :     /* replace record fields from json */
 1991 tgl                      3738 GIC         240 :     tuphead = populate_record(cache->c.io.composite.tupdesc,
 1991 tgl                      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 */
 1991 tgl                      3745 GIC         234 :     if (cache->c.typcat == TYPECAT_COMPOSITE_DOMAIN)
 1991 tgl                      3746 CBC          24 :         domain_check(HeapTupleHeaderGetDatum(tuphead), false,
                               3747                 :                      cache->argtype,
                               3748                 :                      &cache->c.io.composite.domain_info,
                               3749                 :                      cache->fn_mcxt);
 1991 tgl                      3750 ECB             : 
                               3751                 :     /* ok, save into tuplestore */
 2194 andrew                   3752 CBC         228 :     tuple.t_len = HeapTupleHeaderGetDatumLength(tuphead);
 2194 andrew                   3753 GIC         228 :     ItemPointerSetInvalid(&(tuple.t_self));
 2194 andrew                   3754 CBC         228 :     tuple.t_tableOid = InvalidOid;
                               3755             228 :     tuple.t_data = tuphead;
                               3756                 : 
 2194 andrew                   3757 GIC         228 :     tuplestore_puttuple(state->tuple_store, &tuple);
 3304                          3758             228 : }
 3304 andrew                   3759 ECB             : 
                               3760                 : /*
 1731 tgl                      3761                 :  * common worker for json{b}_populate_recordset() and json{b}_to_recordset()
                               3762                 :  * is_json and have_record_arg identify the specific function
 3358 andrew                   3763                 :  */
                               3764                 : static Datum
 3210 tgl                      3765 GIC         171 : populate_recordset_worker(FunctionCallInfo fcinfo, const char *funcname,
 1731 tgl                      3766 ECB             :                           bool is_json, bool have_record_arg)
                               3767                 : {
 3260 bruce                    3768 GIC         171 :     int         json_arg_num = have_record_arg ? 1 : 0;
                               3769                 :     ReturnSetInfo *rsi;
                               3770                 :     MemoryContext old_cxt;
                               3771                 :     HeapTupleHeader rec;
 1329 tgl                      3772             171 :     PopulateRecordCache *cache = fcinfo->flinfo->fn_extra;
                               3773                 :     PopulateRecordsetState *state;
                               3774                 : 
 3663 andrew                   3775             171 :     rsi = (ReturnSetInfo *) fcinfo->resultinfo;
                               3776                 : 
  409 michael                  3777             171 :     if (!rsi || !IsA(rsi, ReturnSetInfo))
  409 michael                  3778 UIC           0 :         ereport(ERROR,
                               3779                 :                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                               3780                 :                  errmsg("set-valued function called in context that cannot accept a set")));
  409 michael                  3781 ECB             : 
  409 michael                  3782 GIC         171 :     if (!(rsi->allowedModes & SFRM_Materialize))
 3663 andrew                   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                 : 
 3663 andrew                   3787 GIC         171 :     rsi->returnMode = SFRM_Materialize;
 3663 andrew                   3788 ECB             : 
                               3789                 :     /*
 1991 tgl                      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                 :      */
 1991 tgl                      3794 GIC         171 :     if (!cache)
 1991 tgl                      3795 ECB             :     {
 1991 tgl                      3796 GIC         165 :         fcinfo->flinfo->fn_extra = cache =
 1991 tgl                      3797 CBC         165 :             MemoryContextAllocZero(fcinfo->flinfo->fn_mcxt, sizeof(*cache));
 1991 tgl                      3798 GIC         165 :         cache->fn_mcxt = fcinfo->flinfo->fn_mcxt;
                               3799                 : 
                               3800             165 :         if (have_record_arg)
 1329                          3801             147 :             get_record_type_from_argument(fcinfo, funcname, cache);
 1991 tgl                      3802 ECB             :         else
 1329 tgl                      3803 GIC          18 :             get_record_type_from_query(fcinfo, funcname, cache);
 1991 tgl                      3804 ECB             :     }
                               3805                 : 
                               3806                 :     /* Collect record arg if we have one */
 1329 tgl                      3807 GIC         171 :     if (!have_record_arg)
                               3808              18 :         rec = NULL;             /* it's json{b}_to_recordset() */
 1329 tgl                      3809 CBC         153 :     else if (!PG_ARGISNULL(0))
                               3810                 :     {
 1991                          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.
 1991 tgl                      3816 ECB             :          */
 1991 tgl                      3817 GIC          96 :         if (cache->argtype == RECORDOID)
                               3818                 :         {
 1991 tgl                      3819 CBC          48 :             cache->c.io.composite.base_typid = HeapTupleHeaderGetTypeId(rec);
 1991 tgl                      3820 GIC          48 :             cache->c.io.composite.base_typmod = HeapTupleHeaderGetTypMod(rec);
                               3821                 :         }
                               3822                 :     }
                               3823                 :     else
                               3824                 :     {
                               3825              57 :         rec = NULL;
 3663 andrew                   3826 ECB             : 
 1329 tgl                      3827                 :         /*
                               3828                 :          * When declared arg type is RECORD, identify actual record type from
                               3829                 :          * calling query, or fail if we can't.
                               3830                 :          */
 1329 tgl                      3831 GIC          57 :         if (cache->argtype == RECORDOID)
                               3832                 :         {
 1329 tgl                      3833 CBC          24 :             get_record_type_from_query(fcinfo, funcname, cache);
 1329 tgl                      3834 ECB             :             /* This can't change argtype, which is important for next time */
 1329 tgl                      3835 CBC          12 :             Assert(cache->argtype == RECORDOID);
 1329 tgl                      3836 ECB             :         }
                               3837                 :     }
                               3838                 : 
 3663 andrew                   3839                 :     /* if the json is null send back an empty set */
 3302 andrew                   3840 GIC         159 :     if (PG_ARGISNULL(json_arg_num))
 3302 andrew                   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.
 1599 tgl                      3846 ECB             :      */
 1599 tgl                      3847 GIC         159 :     update_cached_tupdesc(&cache->c.io.composite, cache->fn_mcxt);
                               3848                 : 
 3304 andrew                   3849 CBC         159 :     state = palloc0(sizeof(PopulateRecordsetState));
                               3850                 : 
                               3851                 :     /* make tuplestore in a sufficiently long-lived memory context */
 3304 andrew                   3852 GIC         159 :     old_cxt = MemoryContextSwitchTo(rsi->econtext->ecxt_per_query_memory);
 3304 andrew                   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                 : 
 3210 tgl                      3858             159 :     state->function_name = funcname;
 1991 tgl                      3859 GBC         159 :     state->cache = cache;
 3663 andrew                   3860 GIC         159 :     state->rec = rec;
                               3861                 : 
 1731 tgl                      3862             159 :     if (is_json)
 3304 andrew                   3863 ECB             :     {
 2219 noah                     3864 GBC          81 :         text       *json = PG_GETARG_TEXT_PP(json_arg_num);
                               3865                 :         JsonLexContext *lex;
                               3866                 :         JsonSemAction *sem;
                               3867                 : 
 3304 andrew                   3868 CBC          81 :         sem = palloc0(sizeof(JsonSemAction));
                               3869                 : 
 3304 andrew                   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;
 3304 andrew                   3875 CBC          81 :         sem->scalar = populate_recordset_scalar;
 3304 andrew                   3876 GIC          81 :         sem->object_field_start = populate_recordset_object_field_start;
 3304 andrew                   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;
 3304 andrew                   3882 ECB             : 
 1168 rhaas                    3883 GIC          81 :         pg_parse_json_or_ereport(lex, sem);
 3304 andrew                   3884 ECB             :     }
                               3885                 :     else
                               3886                 :     {
 2029 tgl                      3887 GIC          78 :         Jsonb      *jb = PG_GETARG_JSONB_P(json_arg_num);
 3304 andrew                   3888 ECB             :         JsonbIterator *it;
                               3889                 :         JsonbValue  v;
 3304 andrew                   3890 CBC          78 :         bool        skipNested = false;
                               3891                 :         JsonbIteratorToken r;
 3304 andrew                   3892 ECB             : 
 3304 andrew                   3893 GIC          78 :         if (JB_ROOT_IS_SCALAR(jb) || !JB_ROOT_IS_ARRAY(jb))
 3304 andrew                   3894 UIC           0 :             ereport(ERROR,
                               3895                 :                     (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                               3896                 :                      errmsg("cannot call %s on a non-array",
                               3897                 :                             funcname)));
 3304 andrew                   3898 ECB             : 
 3259 heikki.linnakangas       3899 GIC          78 :         it = JsonbIteratorInit(&jb->root);
 3304 andrew                   3900 ECB             : 
 3304 andrew                   3901 CBC         339 :         while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE)
                               3902                 :         {
 3304 andrew                   3903 GIC         267 :             skipNested = true;
                               3904                 : 
                               3905             267 :             if (r == WJB_ELEM)
 3304 andrew                   3906 ECB             :             {
                               3907                 :                 JsObject    obj;
                               3908                 : 
 2194 andrew                   3909 GIC         117 :                 if (v.type != jbvBinary ||
                               3910             117 :                     !JsonContainerIsObject(v.val.binary.data))
 3304 andrew                   3911 UIC           0 :                     ereport(ERROR,
 3304 andrew                   3912 ECB             :                             (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                               3913                 :                              errmsg("argument of %s must be an array of objects",
 2118 tgl                      3914                 :                                     funcname)));
                               3915                 : 
 2194 andrew                   3916 CBC         117 :                 obj.is_json = false;
 2194 andrew                   3917 GIC         117 :                 obj.val.jsonb_cont = v.val.binary.data;
                               3918                 : 
                               3919             117 :                 populate_recordset_record(state, &obj);
                               3920                 :             }
 3304 andrew                   3921 ECB             :         }
 3304 andrew                   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.
 1731 tgl                      3928 ECB             :      */
 3663 andrew                   3929 GIC         147 :     rsi->setResult = state->tuple_store;
 1731 tgl                      3930 CBC         147 :     rsi->setDesc = CreateTupleDescCopy(cache->c.io.composite.tupdesc);
                               3931                 : 
 3663 andrew                   3932 GIC         147 :     PG_RETURN_NULL();
 3663 andrew                   3933 ECB             : }
                               3934                 : 
                               3935                 : static JsonParseErrorType
 3663 andrew                   3936 GIC         141 : populate_recordset_object_start(void *state)
 3663 andrew                   3937 ECB             : {
 3550 peter_e                  3938 GIC         141 :     PopulateRecordsetState *_state = (PopulateRecordsetState *) state;
 3663 andrew                   3939 CBC         141 :     int         lex_level = _state->lex->lex_level;
 3663 andrew                   3940 ECB             :     HASHCTL     ctl;
                               3941                 : 
                               3942                 :     /* Reject object at top level: we must have an array at level 0 */
 3663 andrew                   3943 CBC         141 :     if (lex_level == 0)
 3663 andrew                   3944 UIC           0 :         ereport(ERROR,
 3663 andrew                   3945 ECB             :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                               3946                 :                  errmsg("cannot call %s on an object",
                               3947                 :                         _state->function_name)));
                               3948                 : 
 3206 tgl                      3949                 :     /* Nested objects require no special processing */
 3211 tgl                      3950 GIC         141 :     if (lex_level > 1)
  119 tgl                      3951 GNC          18 :         return JSON_SUCCESS;
                               3952                 : 
 3211 tgl                      3953 ECB             :     /* Object at level 1: set up a new hash table for this object */
 3663 andrew                   3954 CBC         123 :     ctl.keysize = NAMEDATALEN;
 3550 peter_e                  3955             123 :     ctl.entrysize = sizeof(JsonHashEntry);
 3663 andrew                   3956             123 :     ctl.hcxt = CurrentMemoryContext;
                               3957             123 :     _state->json_hash = hash_create("json object hashtable",
 3663 andrew                   3958 ECB             :                                     100,
                               3959                 :                                     &ctl,
  845 tgl                      3960                 :                                     HASH_ELEM | HASH_STRINGS | HASH_CONTEXT);
                               3961                 : 
  119 tgl                      3962 GNC         123 :     return JSON_SUCCESS;
                               3963                 : }
 3663 andrew                   3964 ECB             : 
                               3965                 : static JsonParseErrorType
 3663 andrew                   3966 CBC         141 : populate_recordset_object_end(void *state)
                               3967                 : {
 3550 peter_e                  3968 GIC         141 :     PopulateRecordsetState *_state = (PopulateRecordsetState *) state;
                               3969                 :     JsObject    obj;
 3663 andrew                   3970 ECB             : 
                               3971                 :     /* Nested objects require no special processing */
 3663 andrew                   3972 GIC         141 :     if (_state->lex->lex_level > 1)
  119 tgl                      3973 GNC          18 :         return JSON_SUCCESS;
                               3974                 : 
 2194 andrew                   3975 GIC         123 :     obj.is_json = true;
 2194 andrew                   3976 CBC         123 :     obj.val.json_hash = _state->json_hash;
 3663 andrew                   3977 EUB             : 
                               3978                 :     /* Otherwise, construct and return a tuple based on this level-1 object */
 2194 andrew                   3979 GIC         123 :     populate_recordset_record(_state, &obj);
                               3980                 : 
                               3981                 :     /* Done with hash for this object */
 2194 andrew                   3982 CBC         117 :     hash_destroy(_state->json_hash);
 3211 tgl                      3983 GIC         117 :     _state->json_hash = NULL;
                               3984                 : 
  119 tgl                      3985 GNC         117 :     return JSON_SUCCESS;
 3663 andrew                   3986 ECB             : }
                               3987                 : 
                               3988                 : static JsonParseErrorType
 3663 andrew                   3989 GIC         150 : populate_recordset_array_element_start(void *state, bool isnull)
 3663 andrew                   3990 ECB             : {
 3550 peter_e                  3991 GIC         150 :     PopulateRecordsetState *_state = (PopulateRecordsetState *) state;
                               3992                 : 
 3663 andrew                   3993             150 :     if (_state->lex->lex_level == 1 &&
 3663 andrew                   3994 CBC         123 :         _state->lex->token_type != JSON_TOKEN_OBJECT_START)
 3663 andrew                   3995 LBC           0 :         ereport(ERROR,
 3663 andrew                   3996 EUB             :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                               3997                 :                  errmsg("argument of %s must be an array of objects",
                               3998                 :                         _state->function_name)));
                               3999                 : 
  119 tgl                      4000 GNC         150 :     return JSON_SUCCESS;
                               4001                 : }
                               4002                 : 
                               4003                 : static JsonParseErrorType
 3663 andrew                   4004 CBC          90 : populate_recordset_array_start(void *state)
                               4005                 : {
 3206 tgl                      4006 ECB             :     /* nothing to do */
  119 tgl                      4007 GNC          90 :     return JSON_SUCCESS;
                               4008                 : }
                               4009                 : 
                               4010                 : static JsonParseErrorType
 3663 andrew                   4011 GIC         258 : populate_recordset_scalar(void *state, char *token, JsonTokenType tokentype)
                               4012                 : {
 3550 peter_e                  4013             258 :     PopulateRecordsetState *_state = (PopulateRecordsetState *) state;
                               4014                 : 
 3663 andrew                   4015             258 :     if (_state->lex->lex_level == 0)
 3663 andrew                   4016 UIC           0 :         ereport(ERROR,
 3663 andrew                   4017 ECB             :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
 3210 tgl                      4018                 :                  errmsg("cannot call %s on a scalar",
                               4019                 :                         _state->function_name)));
 3663 andrew                   4020                 : 
 3663 andrew                   4021 GIC         258 :     if (_state->lex->lex_level == 2)
                               4022             210 :         _state->saved_scalar = token;
                               4023                 : 
  119 tgl                      4024 GNC         258 :     return JSON_SUCCESS;
                               4025                 : }
 3663 andrew                   4026 ECB             : 
                               4027                 : static JsonParseErrorType
 3663 andrew                   4028 CBC         258 : populate_recordset_object_field_start(void *state, char *fname, bool isnull)
 3663 andrew                   4029 ECB             : {
 3550 peter_e                  4030 GIC         258 :     PopulateRecordsetState *_state = (PopulateRecordsetState *) state;
                               4031                 : 
 3663 andrew                   4032             258 :     if (_state->lex->lex_level > 2)
  119 tgl                      4033 GNC          21 :         return JSON_SUCCESS;
 3663 andrew                   4034 EUB             : 
 2194 andrew                   4035 GIC         237 :     _state->saved_token_type = _state->lex->token_type;
                               4036                 : 
 3663                          4037             237 :     if (_state->lex->token_type == JSON_TOKEN_ARRAY_START ||
                               4038             228 :         _state->lex->token_type == JSON_TOKEN_OBJECT_START)
                               4039                 :     {
 3663 andrew                   4040 CBC          27 :         _state->save_json_start = _state->lex->token_start;
 3663 andrew                   4041 ECB             :     }
                               4042                 :     else
                               4043                 :     {
 3663 andrew                   4044 CBC         210 :         _state->save_json_start = NULL;
 3663 andrew                   4045 ECB             :     }
                               4046                 : 
  119 tgl                      4047 GNC         237 :     return JSON_SUCCESS;
 3663 andrew                   4048 ECB             : }
                               4049                 : 
                               4050                 : static JsonParseErrorType
 3663 andrew                   4051 GIC         258 : populate_recordset_object_field_end(void *state, char *fname, bool isnull)
                               4052                 : {
 3550 peter_e                  4053             258 :     PopulateRecordsetState *_state = (PopulateRecordsetState *) state;
 3550 peter_e                  4054 ECB             :     JsonHashEntry *hashentry;
                               4055                 :     bool        found;
                               4056                 : 
                               4057                 :     /*
 3210 tgl                      4058                 :      * Ignore nested fields.
                               4059                 :      */
 3210 tgl                      4060 CBC         258 :     if (_state->lex->lex_level > 2)
  119 tgl                      4061 GNC          21 :         return JSON_SUCCESS;
                               4062                 : 
                               4063                 :     /*
 3210 tgl                      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                 :      */
 3210 tgl                      4070 GIC         237 :     if (strlen(fname) >= NAMEDATALEN)
  119 tgl                      4071 UNC           0 :         return JSON_SUCCESS;
                               4072                 : 
 3210 tgl                      4073 GIC         237 :     hashentry = hash_search(_state->json_hash, fname, HASH_ENTER, &found);
 3663 andrew                   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                 : 
 2194 andrew                   4080 GIC         237 :     hashentry->type = _state->saved_token_type;
 2194 andrew                   4081 CBC         237 :     Assert(isnull == (hashentry->type == JSON_TOKEN_NULL));
                               4082                 : 
 3663                          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));
 3663 andrew                   4087 EUB             : 
 3663 andrew                   4088 GIC          27 :         memcpy(val, _state->save_json_start, len);
                               4089              27 :         val[len] = '\0';
                               4090              27 :         hashentry->val = val;
                               4091                 :     }
 3663 andrew                   4092 ECB             :     else
                               4093                 :     {
                               4094                 :         /* must have had a scalar instead */
 3663 andrew                   4095 GIC         210 :         hashentry->val = _state->saved_scalar;
 3663 andrew                   4096 ECB             :     }
                               4097                 : 
  119 tgl                      4098 GNC         237 :     return JSON_SUCCESS;
                               4099                 : }
                               4100                 : 
 3040 andrew                   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
 3040 andrew                   4111 GIC          18 : sn_object_start(void *state)
                               4112                 : {
                               4113              18 :     StripnullState *_state = (StripnullState *) state;
                               4114                 : 
 3040 andrew                   4115 CBC          18 :     appendStringInfoCharMacro(_state->strval, '{');
                               4116                 : 
  119 tgl                      4117 GNC          18 :     return JSON_SUCCESS;
 3040 andrew                   4118 ECB             : }
                               4119                 : 
                               4120                 : static JsonParseErrorType
 3040 andrew                   4121 GIC          18 : sn_object_end(void *state)
                               4122                 : {
                               4123              18 :     StripnullState *_state = (StripnullState *) state;
 2878 bruce                    4124 ECB             : 
 3040 andrew                   4125 GIC          18 :     appendStringInfoCharMacro(_state->strval, '}');
                               4126                 : 
  119 tgl                      4127 GNC          18 :     return JSON_SUCCESS;
 3040 andrew                   4128 ECB             : }
                               4129                 : 
                               4130                 : static JsonParseErrorType
 3040 andrew                   4131 CBC           9 : sn_array_start(void *state)
                               4132                 : {
                               4133               9 :     StripnullState *_state = (StripnullState *) state;
                               4134                 : 
                               4135               9 :     appendStringInfoCharMacro(_state->strval, '[');
                               4136                 : 
  119 tgl                      4137 GNC           9 :     return JSON_SUCCESS;
 3040 andrew                   4138 ECB             : }
                               4139                 : 
                               4140                 : static JsonParseErrorType
 3040 andrew                   4141 GIC           9 : sn_array_end(void *state)
                               4142                 : {
                               4143               9 :     StripnullState *_state = (StripnullState *) state;
 2878 bruce                    4144 ECB             : 
 3040 andrew                   4145 GIC           9 :     appendStringInfoCharMacro(_state->strval, ']');
                               4146                 : 
  119 tgl                      4147 GNC           9 :     return JSON_SUCCESS;
                               4148                 : }
 3040 andrew                   4149 ECB             : 
                               4150                 : static JsonParseErrorType
 2878 bruce                    4151 GIC          39 : sn_object_field_start(void *state, char *fname, bool isnull)
                               4152                 : {
 3040 andrew                   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;
  119 tgl                      4163 GNC          15 :         return JSON_SUCCESS;
                               4164                 :     }
                               4165                 : 
 3040 andrew                   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.
 3040 andrew                   4172 ECB             :      */
 2878 bruce                    4173 GBC          24 :     escape_json(_state->strval, fname);
                               4174                 : 
 3040 andrew                   4175 CBC          24 :     appendStringInfoCharMacro(_state->strval, ':');
                               4176                 : 
  119 tgl                      4177 GNC          24 :     return JSON_SUCCESS;
                               4178                 : }
                               4179                 : 
                               4180                 : static JsonParseErrorType
 2878 bruce                    4181 GIC          33 : sn_array_element_start(void *state, bool isnull)
                               4182                 : {
 3040 andrew                   4183              33 :     StripnullState *_state = (StripnullState *) state;
 3040 andrew                   4184 ECB             : 
 3040 andrew                   4185 CBC          33 :     if (_state->strval->data[_state->strval->len - 1] != '[')
 3040 andrew                   4186 GIC          24 :         appendStringInfoCharMacro(_state->strval, ',');
                               4187                 : 
  119 tgl                      4188 GNC          33 :     return JSON_SUCCESS;
 3040 andrew                   4189 ECB             : }
                               4190                 : 
                               4191                 : static JsonParseErrorType
 3040 andrew                   4192 CBC          66 : sn_scalar(void *state, char *token, JsonTokenType tokentype)
                               4193                 : {
                               4194              66 :     StripnullState *_state = (StripnullState *) state;
 3040 andrew                   4195 ECB             : 
 3040 andrew                   4196 CBC          66 :     if (_state->skip_next_null)
                               4197                 :     {
 2878 bruce                    4198 GIC          15 :         Assert(tokentype == JSON_TOKEN_NULL);
 3040 andrew                   4199              15 :         _state->skip_next_null = false;
  119 tgl                      4200 GNC          15 :         return JSON_SUCCESS;
 3040 andrew                   4201 ECB             :     }
                               4202                 : 
 3040 andrew                   4203 GIC          51 :     if (tokentype == JSON_TOKEN_STRING)
 3040 andrew                   4204 CBC           3 :         escape_json(_state->strval, token);
                               4205                 :     else
 3040 andrew                   4206 GIC          48 :         appendStringInfoString(_state->strval, token);
                               4207                 : 
  119 tgl                      4208 GNC          51 :     return JSON_SUCCESS;
                               4209                 : }
                               4210                 : 
                               4211                 : /*
                               4212                 :  * SQL function json_strip_nulls(json) -> json
                               4213                 :  */
                               4214                 : Datum
 3040 andrew                   4215 GIC          21 : json_strip_nulls(PG_FUNCTION_ARGS)
                               4216                 : {
 2219 noah                     4217              21 :     text       *json = PG_GETARG_TEXT_PP(0);
                               4218                 :     StripnullState *state;
 3040 andrew                   4219 ECB             :     JsonLexContext *lex;
                               4220                 :     JsonSemAction *sem;
                               4221                 : 
 3040 andrew                   4222 GIC          21 :     lex = makeJsonLexContext(json, true);
 3040 andrew                   4223 CBC          21 :     state = palloc0(sizeof(StripnullState));
 3040 andrew                   4224 GIC          21 :     sem = palloc0(sizeof(JsonSemAction));
 3040 andrew                   4225 ECB             : 
 3040 andrew                   4226 GIC          21 :     state->strval = makeStringInfo();
                               4227              21 :     state->skip_next_null = false;
                               4228              21 :     state->lex = lex;
 3040 andrew                   4229 ECB             : 
 3040 andrew                   4230 GIC          21 :     sem->semstate = (void *) state;
 3040 andrew                   4231 CBC          21 :     sem->object_start = sn_object_start;
 3040 andrew                   4232 GIC          21 :     sem->object_end = sn_object_end;
 3040 andrew                   4233 CBC          21 :     sem->array_start = sn_array_start;
 3040 andrew                   4234 GIC          21 :     sem->array_end = sn_array_end;
 3040 andrew                   4235 CBC          21 :     sem->scalar = sn_scalar;
 3040 andrew                   4236 GIC          21 :     sem->array_element_start = sn_array_element_start;
                               4237              21 :     sem->object_field_start = sn_object_field_start;
                               4238                 : 
 1168 rhaas                    4239 CBC          21 :     pg_parse_json_or_ereport(lex, sem);
                               4240                 : 
 3040 andrew                   4241              21 :     PG_RETURN_TEXT_P(cstring_to_text_with_len(state->strval->data,
                               4242                 :                                               state->strval->len));
 3040 andrew                   4243 ECB             : }
                               4244                 : 
                               4245                 : /*
                               4246                 :  * SQL function jsonb_strip_nulls(jsonb) -> jsonb
                               4247                 :  */
                               4248                 : Datum
 3040 andrew                   4249 CBC          21 : jsonb_strip_nulls(PG_FUNCTION_ARGS)
                               4250                 : {
 2029 tgl                      4251              21 :     Jsonb      *jb = PG_GETARG_JSONB_P(0);
                               4252                 :     JsonbIterator *it;
 3040 andrew                   4253              21 :     JsonbParseState *parseState = NULL;
 3040 andrew                   4254 GIC          21 :     JsonbValue *res = NULL;
 2878 bruce                    4255 ECB             :     JsonbValue  v,
                               4256                 :                 k;
                               4257                 :     JsonbIteratorToken type;
 2878 bruce                    4258 GIC          21 :     bool        last_was_key = false;
 3040 andrew                   4259 ECB             : 
 3040 andrew                   4260 GIC          21 :     if (JB_ROOT_IS_SCALAR(jb))
 3040 andrew                   4261 CBC           9 :         PG_RETURN_POINTER(jb);
                               4262                 : 
                               4263              12 :     it = JsonbIteratorInit(&jb->root);
                               4264                 : 
 3040 andrew                   4265 GIC         162 :     while ((type = JsonbIteratorNext(&it, &v, false)) != WJB_DONE)
                               4266                 :     {
 2878 bruce                    4267             150 :         Assert(!(type == WJB_KEY && last_was_key));
                               4268                 : 
 3040 andrew                   4269             150 :         if (type == WJB_KEY)
 3040 andrew                   4270 ECB             :         {
                               4271                 :             /* stash the key until we know if it has a null value */
 3040 andrew                   4272 GIC          39 :             k = v;
                               4273              39 :             last_was_key = true;
 3040 andrew                   4274 CBC          39 :             continue;
 3040 andrew                   4275 ECB             :         }
                               4276                 : 
 3040 andrew                   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;
 3040 andrew                   4281 ECB             : 
                               4282                 :             /* skip this field if value is null */
 3040 andrew                   4283 CBC          39 :             if (type == WJB_VALUE && v.type == jbvNull)
 3040 andrew                   4284 GIC          15 :                 continue;
 3040 andrew                   4285 ECB             : 
                               4286                 :             /* otherwise, do a delayed push of the key */
 3036 andrew                   4287 GIC          24 :             (void) pushJsonbValue(&parseState, WJB_KEY, &k);
                               4288                 :         }
 3040 andrew                   4289 ECB             : 
 3040 andrew                   4290 GIC          96 :         if (type == WJB_VALUE || type == WJB_ELEM)
 3040 andrew                   4291 CBC          42 :             res = pushJsonbValue(&parseState, type, &v);
                               4292                 :         else
                               4293              54 :             res = pushJsonbValue(&parseState, type, NULL);
 3040 andrew                   4294 ECB             :     }
                               4295                 : 
 3036 andrew                   4296 CBC          12 :     Assert(res != NULL);
                               4297                 : 
 3040 andrew                   4298 GIC          12 :     PG_RETURN_POINTER(JsonbValueToJsonb(res));
                               4299                 : }
 2889 andrew                   4300 ECB             : 
                               4301                 : /*
                               4302                 :  * SQL function jsonb_pretty (jsonb)
                               4303                 :  *
                               4304                 :  * Pretty-printed text for the jsonb
                               4305                 :  */
                               4306                 : Datum
 2889 andrew                   4307 CBC          18 : jsonb_pretty(PG_FUNCTION_ARGS)
 2889 andrew                   4308 ECB             : {
 2029 tgl                      4309 GIC          18 :     Jsonb      *jb = PG_GETARG_JSONB_P(0);
 2889 andrew                   4310              18 :     StringInfo  str = makeStringInfo();
 2889 andrew                   4311 ECB             : 
 2889 andrew                   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                 : }
 2889 andrew                   4316 ECB             : 
                               4317                 : /*
                               4318                 :  * SQL function jsonb_concat (jsonb, jsonb)
                               4319                 :  *
                               4320                 :  * function for || operator
                               4321                 :  */
                               4322                 : Datum
 2889 andrew                   4323 CBC         189 : jsonb_concat(PG_FUNCTION_ARGS)
                               4324                 : {
 2029 tgl                      4325             189 :     Jsonb      *jb1 = PG_GETARG_JSONB_P(0);
 2029 tgl                      4326 GIC         189 :     Jsonb      *jb2 = PG_GETARG_JSONB_P(1);
 2889 andrew                   4327             189 :     JsonbParseState *state = NULL;
                               4328                 :     JsonbValue *res;
                               4329                 :     JsonbIterator *it1,
 2878 bruce                    4330 ECB             :                *it2;
 2889 andrew                   4331                 : 
                               4332                 :     /*
                               4333                 :      * If one of the jsonb is empty, just return the other if it's not scalar
 2495 rhaas                    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
 2765 andrew                   4336                 :      * empty.
                               4337                 :      */
 2765 andrew                   4338 CBC         189 :     if (JB_ROOT_IS_OBJECT(jb1) == JB_ROOT_IS_OBJECT(jb2))
 2765 andrew                   4339 ECB             :     {
 2765 andrew                   4340 CBC         147 :         if (JB_ROOT_COUNT(jb1) == 0 && !JB_ROOT_IS_SCALAR(jb2))
 2029 tgl                      4341              99 :             PG_RETURN_JSONB_P(jb2);
 2765 andrew                   4342              48 :         else if (JB_ROOT_COUNT(jb2) == 0 && !JB_ROOT_IS_SCALAR(jb1))
 2029 tgl                      4343               6 :             PG_RETURN_JSONB_P(jb1);
 2765 andrew                   4344 ECB             :     }
 2889                          4345                 : 
 2889 andrew                   4346 GIC          84 :     it1 = JsonbIteratorInit(&jb1->root);
 2889 andrew                   4347 CBC          84 :     it2 = JsonbIteratorInit(&jb2->root);
                               4348                 : 
                               4349              84 :     res = IteratorConcat(&it1, &it2, &state);
                               4350                 : 
 2876 andrew                   4351 GIC          84 :     Assert(res != NULL);
                               4352                 : 
 2029 tgl                      4353              84 :     PG_RETURN_JSONB_P(JsonbValueToJsonb(res));
                               4354                 : }
                               4355                 : 
                               4356                 : 
 2889 andrew                   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
 2889 andrew                   4364 GIC          90 : jsonb_delete(PG_FUNCTION_ARGS)
                               4365                 : {
 2029 tgl                      4366 CBC          90 :     Jsonb      *in = PG_GETARG_JSONB_P(0);
 2889 andrew                   4367 GIC          90 :     text       *key = PG_GETARG_TEXT_PP(1);
 2889 andrew                   4368 CBC          90 :     char       *keyptr = VARDATA_ANY(key);
                               4369              90 :     int         keylen = VARSIZE_ANY_EXHDR(key);
 2889 andrew                   4370 GIC          90 :     JsonbParseState *state = NULL;
 2889 andrew                   4371 ECB             :     JsonbIterator *it;
                               4372                 :     JsonbValue  v,
 2889 andrew                   4373 CBC          90 :                *res = NULL;
 2889 andrew                   4374 GIC          90 :     bool        skipNested = false;
 2737 noah                     4375 ECB             :     JsonbIteratorToken r;
                               4376                 : 
 2888 andrew                   4377 CBC          90 :     if (JB_ROOT_IS_SCALAR(in))
 2888 andrew                   4378 GIC           3 :         ereport(ERROR,
                               4379                 :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
 2888 andrew                   4380 ECB             :                  errmsg("cannot delete from scalar")));
 2889                          4381                 : 
 2889 andrew                   4382 CBC          87 :     if (JB_ROOT_COUNT(in) == 0)
 2029 tgl                      4383 GIC           6 :         PG_RETURN_JSONB_P(in);
                               4384                 : 
 2889 andrew                   4385 CBC          81 :     it = JsonbIteratorInit(&in->root);
                               4386                 : 
 1820 tgl                      4387 GIC        1074 :     while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE)
 2889 andrew                   4388 ECB             :     {
 2889 andrew                   4389 GIC         993 :         skipNested = true;
                               4390                 : 
 2889 andrew                   4391 CBC         993 :         if ((r == WJB_ELEM || r == WJB_KEY) &&
                               4392             453 :             (v.type == jbvString && keylen == v.val.string.len &&
 2889 andrew                   4393 GIC         147 :              memcmp(keyptr, v.val.string.val, keylen) == 0))
                               4394                 :         {
 2889 andrew                   4395 ECB             :             /* skip corresponding value as well */
 2889 andrew                   4396 GIC          75 :             if (r == WJB_KEY)
 1820 tgl                      4397              75 :                 (void) JsonbIteratorNext(&it, &v, true);
 2889 andrew                   4398 ECB             : 
 2889 andrew                   4399 CBC          75 :             continue;
                               4400                 :         }
 2889 andrew                   4401 ECB             : 
 2889 andrew                   4402 GIC         918 :         res = pushJsonbValue(&state, r, r < WJB_BEGIN_ARRAY ? &v : NULL);
                               4403                 :     }
 2889 andrew                   4404 ECB             : 
 2888 andrew                   4405 GIC          81 :     Assert(res != NULL);
 2889 andrew                   4406 ECB             : 
 2029 tgl                      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.
 2272 magnus                   4415 ECB             :  */
                               4416                 : Datum
 2272 magnus                   4417 CBC           9 : jsonb_delete_array(PG_FUNCTION_ARGS)
 2272 magnus                   4418 ECB             : {
 2029 tgl                      4419 GIC           9 :     Jsonb      *in = PG_GETARG_JSONB_P(0);
 2272 magnus                   4420 CBC           9 :     ArrayType  *keys = PG_GETARG_ARRAYTYPE_P(1);
                               4421                 :     Datum      *keys_elems;
 2272 magnus                   4422 ECB             :     bool       *keys_nulls;
                               4423                 :     int         keys_len;
 2272 magnus                   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                 : 
 2272 magnus                   4431 CBC           9 :     if (ARR_NDIM(keys) > 1)
 2272 magnus                   4432 UIC           0 :         ereport(ERROR,
 2272 magnus                   4433 ECB             :                 (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
                               4434                 :                  errmsg("wrong number of array subscripts")));
                               4435                 : 
 2272 magnus                   4436 GIC           9 :     if (JB_ROOT_IS_SCALAR(in))
 2272 magnus                   4437 UIC           0 :         ereport(ERROR,
                               4438                 :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                               4439                 :                  errmsg("cannot delete from scalar")));
                               4440                 : 
 2272 magnus                   4441 GIC           9 :     if (JB_ROOT_COUNT(in) == 0)
 2029 tgl                      4442 UIC           0 :         PG_RETURN_JSONB_P(in);
                               4443                 : 
  282 peter                    4444 GNC           9 :     deconstruct_array_builtin(keys, TEXTOID, &keys_elems, &keys_nulls, &keys_len);
 2272 magnus                   4445 ECB             : 
 2272 magnus                   4446 GIC           9 :     if (keys_len == 0)
 2029 tgl                      4447 CBC           3 :         PG_RETURN_JSONB_P(in);
 2272 magnus                   4448 ECB             : 
 2272 magnus                   4449 CBC           6 :     it = JsonbIteratorInit(&in->root);
 2272 magnus                   4450 ECB             : 
 1820 tgl                      4451 GIC          45 :     while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE)
                               4452                 :     {
 2272 magnus                   4453 CBC          39 :         skipNested = true;
 2272 magnus                   4454 ECB             : 
 2272 magnus                   4455 GIC          39 :         if ((r == WJB_ELEM || r == WJB_KEY) && v.type == jbvString)
 2272 magnus                   4456 ECB             :         {
                               4457                 :             int         i;
 2272 magnus                   4458 CBC          18 :             bool        found = false;
                               4459                 : 
                               4460              33 :             for (i = 0; i < keys_len; i++)
                               4461                 :             {
                               4462                 :                 char       *keyptr;
                               4463                 :                 int         keylen;
                               4464                 : 
 2272 magnus                   4465 GIC          24 :                 if (keys_nulls[i])
 2272 magnus                   4466 UIC           0 :                     continue;
                               4467                 : 
                               4468                 :                 /* We rely on the array elements not being toasted */
 2272 magnus                   4469 GIC          24 :                 keyptr = VARDATA_ANY(keys_elems[i]);
                               4470              24 :                 keylen = VARSIZE_ANY_EXHDR(keys_elems[i]);
 2272 magnus                   4471 CBC          24 :                 if (keylen == v.val.string.len &&
 2272 magnus                   4472 GIC          24 :                     memcmp(keyptr, v.val.string.val, keylen) == 0)
 2272 magnus                   4473 ECB             :                 {
 2272 magnus                   4474 CBC           9 :                     found = true;
                               4475               9 :                     break;
 2272 magnus                   4476 ECB             :                 }
                               4477                 :             }
 2272 magnus                   4478 GIC          18 :             if (found)
                               4479                 :             {
 2272 magnus                   4480 ECB             :                 /* skip corresponding value as well */
 2272 magnus                   4481 CBC           9 :                 if (r == WJB_KEY)
 1820 tgl                      4482 GIC           9 :                     (void) JsonbIteratorNext(&it, &v, true);
                               4483                 : 
 2272 magnus                   4484 CBC           9 :                 continue;
 2272 magnus                   4485 ECB             :             }
                               4486                 :         }
                               4487                 : 
 2272 magnus                   4488 GIC          30 :         res = pushJsonbValue(&state, r, r < WJB_BEGIN_ARRAY ? &v : NULL);
 2272 magnus                   4489 ECB             :     }
                               4490                 : 
 2272 magnus                   4491 GIC           6 :     Assert(res != NULL);
 2272 magnus                   4492 ECB             : 
 2029 tgl                      4493 GIC           6 :     PG_RETURN_JSONB_P(JsonbValueToJsonb(res));
 2272 magnus                   4494 ECB             : }
                               4495                 : 
 2889 andrew                   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
 2889 andrew                   4504 CBC         129 : jsonb_delete_idx(PG_FUNCTION_ARGS)
                               4505                 : {
 2029 tgl                      4506             129 :     Jsonb      *in = PG_GETARG_JSONB_P(0);
 2889 andrew                   4507 GIC         129 :     int         idx = PG_GETARG_INT32(1);
                               4508             129 :     JsonbParseState *state = NULL;
 2889 andrew                   4509 ECB             :     JsonbIterator *it;
 2737 noah                     4510 GIC         129 :     uint32      i = 0,
                               4511                 :                 n;
 2889 andrew                   4512 ECB             :     JsonbValue  v,
 2889 andrew                   4513 GIC         129 :                *res = NULL;
 2737 noah                     4514 ECB             :     JsonbIteratorToken r;
                               4515                 : 
 2888 andrew                   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                 : 
 2863                          4521             126 :     if (JB_ROOT_IS_OBJECT(in))
                               4522               3 :         ereport(ERROR,
                               4523                 :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
 2677 peter_e                  4524 ECB             :                  errmsg("cannot delete from object using integer index")));
                               4525                 : 
 2889 andrew                   4526 CBC         123 :     if (JB_ROOT_COUNT(in) == 0)
 2029 tgl                      4527               3 :         PG_RETURN_JSONB_P(in);
                               4528                 : 
 2889 andrew                   4529 GIC         120 :     it = JsonbIteratorInit(&in->root);
                               4530                 : 
 2889 andrew                   4531 CBC         120 :     r = JsonbIteratorNext(&it, &v, false);
 2495 rhaas                    4532 GIC         120 :     Assert(r == WJB_BEGIN_ARRAY);
 2823 andrew                   4533             120 :     n = v.val.array.nElems;
 2889 andrew                   4534 ECB             : 
 2889 andrew                   4535 CBC         120 :     if (idx < 0)
                               4536                 :     {
 2889 andrew                   4537 GIC          12 :         if (-idx > n)
 2889 andrew                   4538 CBC           3 :             idx = n;
 2889 andrew                   4539 EUB             :         else
 2889 andrew                   4540 GIC           9 :             idx = n + idx;
                               4541                 :     }
                               4542                 : 
 2889 andrew                   4543 CBC         120 :     if (idx >= n)
 2029 tgl                      4544 GBC           6 :         PG_RETURN_JSONB_P(in);
                               4545                 : 
 2821 andrew                   4546 GIC         114 :     pushJsonbValue(&state, r, NULL);
                               4547                 : 
 1820 tgl                      4548 CBC         378 :     while ((r = JsonbIteratorNext(&it, &v, true)) != WJB_DONE)
 2889 andrew                   4549 EUB             :     {
 2823 andrew                   4550 GIC         264 :         if (r == WJB_ELEM)
 2889 andrew                   4551 ECB             :         {
 2889 andrew                   4552 GIC         150 :             if (i++ == idx)
 2889 andrew                   4553 CBC         114 :                 continue;
 2889 andrew                   4554 ECB             :         }
                               4555                 : 
 2889 andrew                   4556 CBC         150 :         res = pushJsonbValue(&state, r, r < WJB_BEGIN_ARRAY ? &v : NULL);
                               4557                 :     }
 2889 andrew                   4558 ECB             : 
 2878 bruce                    4559 GIC         114 :     Assert(res != NULL);
 2889 andrew                   4560 ECB             : 
 2029 tgl                      4561 GIC         114 :     PG_RETURN_JSONB_P(JsonbValueToJsonb(res));
 2889 andrew                   4562 ECB             : }
                               4563                 : 
                               4564                 : /*
 2870                          4565                 :  * SQL function jsonb_set(jsonb, text[], jsonb, boolean)
                               4566                 :  */
 2889                          4567                 : Datum
 2870 andrew                   4568 GIC         144 : jsonb_set(PG_FUNCTION_ARGS)
                               4569                 : {
 2029 tgl                      4570             144 :     Jsonb      *in = PG_GETARG_JSONB_P(0);
 2889 andrew                   4571             144 :     ArrayType  *path = PG_GETARG_ARRAYTYPE_P(1);
  798 akorotkov                4572 CBC         144 :     Jsonb      *newjsonb = PG_GETARG_JSONB_P(2);
  798 akorotkov                4573 EUB             :     JsonbValue  newval;
 2870 andrew                   4574 GIC         144 :     bool        create = PG_GETARG_BOOL(3);
 2889                          4575             144 :     JsonbValue *res = NULL;
 2889 andrew                   4576 ECB             :     Datum      *path_elems;
                               4577                 :     bool       *path_nulls;
                               4578                 :     int         path_len;
                               4579                 :     JsonbIterator *it;
 2889 andrew                   4580 GIC         144 :     JsonbParseState *st = NULL;
 2889 andrew                   4581 ECB             : 
  798 akorotkov                4582 CBC         144 :     JsonbToJsonbValue(newjsonb, &newval);
                               4583                 : 
 2889 andrew                   4584 GIC         144 :     if (ARR_NDIM(path) > 1)
 2889 andrew                   4585 LBC           0 :         ereport(ERROR,
                               4586                 :                 (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
                               4587                 :                  errmsg("wrong number of array subscripts")));
 2889 andrew                   4588 ECB             : 
 2888 andrew                   4589 CBC         144 :     if (JB_ROOT_IS_SCALAR(in))
 2888 andrew                   4590 GIC           3 :         ereport(ERROR,
 2888 andrew                   4591 ECB             :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                               4592                 :                  errmsg("cannot set path in scalar")));
                               4593                 : 
 2870 andrew                   4594 GIC         141 :     if (JB_ROOT_COUNT(in) == 0 && !create)
 2029 tgl                      4595 CBC           6 :         PG_RETURN_JSONB_P(in);
                               4596                 : 
  282 peter                    4597 GNC         135 :     deconstruct_array_builtin(path, TEXTOID, &path_elems, &path_nulls, &path_len);
                               4598                 : 
 2889 andrew                   4599 CBC         135 :     if (path_len == 0)
 2029 tgl                      4600 UIC           0 :         PG_RETURN_JSONB_P(in);
                               4601                 : 
 2889 andrew                   4602 GIC         135 :     it = JsonbIteratorInit(&in->root);
                               4603                 : 
 2870                          4604             135 :     res = setPath(&it, path_elems, path_nulls, path_len, &st,
                               4605                 :                   0, &newval, create ? JB_PATH_CREATE : JB_PATH_REPLACE);
                               4606                 : 
 2878 bruce                    4607             120 :     Assert(res != NULL);
                               4608                 : 
 2029 tgl                      4609             120 :     PG_RETURN_JSONB_P(JsonbValueToJsonb(res));
 2889 andrew                   4610 ECB             : }
                               4611                 : 
                               4612                 : 
 1178                          4613                 : /*
                               4614                 :  * SQL function jsonb_set_lax(jsonb, text[], jsonb, boolean, text)
                               4615                 :  */
                               4616                 : Datum
 1178 andrew                   4617 GIC          30 : jsonb_set_lax(PG_FUNCTION_ARGS)
                               4618                 : {
 1178 andrew                   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); */
 1060 tgl                      4623                 :     text       *handle_null;
                               4624                 :     char       *handle_val;
                               4625                 : 
 1178 andrew                   4626 GIC          30 :     if (PG_ARGISNULL(0) || PG_ARGISNULL(1) || PG_ARGISNULL(3))
 1178 andrew                   4627 LBC           0 :         PG_RETURN_NULL();
 1178 andrew                   4628 ECB             : 
                               4629                 :     /* could happen if they pass in an explicit NULL */
 1178 andrew                   4630 GIC          30 :     if (PG_ARGISNULL(4))
                               4631               3 :         ereport(ERROR,
 1178 andrew                   4632 ECB             :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
 1175 tgl                      4633                 :                  errmsg("null_value_treatment must be \"delete_key\", \"return_target\", \"use_json_null\", or \"raise_exception\"")));
                               4634                 : 
 1178 andrew                   4635                 :     /* if the new value isn't an SQL NULL just call jsonb_set */
 1060 tgl                      4636 GIC          27 :     if (!PG_ARGISNULL(2))
 1178 andrew                   4637 CBC           6 :         return jsonb_set(fcinfo);
 1178 andrew                   4638 ECB             : 
 1178 andrew                   4639 CBC          21 :     handle_null = PG_GETARG_TEXT_P(4);
 1178 andrew                   4640 GIC          21 :     handle_val = text_to_cstring(handle_null);
 1178 andrew                   4641 ECB             : 
 1060 tgl                      4642 GIC          21 :     if (strcmp(handle_val, "raise_exception") == 0)
 1178 andrew                   4643 ECB             :     {
 1178 andrew                   4644 CBC           3 :         ereport(ERROR,
                               4645                 :                 (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
 1175 tgl                      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 */
 1178 andrew                   4650                 :     }
 1178 andrew                   4651 GIC          18 :     else if (strcmp(handle_val, "use_json_null") == 0)
 1178 andrew                   4652 ECB             :     {
                               4653                 :         Datum       newval;
                               4654                 : 
 1178 andrew                   4655 GIC           9 :         newval = DirectFunctionCall1(jsonb_in, CStringGetDatum("null"));
 1178 andrew                   4656 ECB             : 
 1178 andrew                   4657 GIC           9 :         fcinfo->args[2].value = newval;
 1178 andrew                   4658 CBC           9 :         fcinfo->args[2].isnull = false;
                               4659               9 :         return jsonb_set(fcinfo);
                               4660                 :     }
 1178 andrew                   4661 GIC           9 :     else if (strcmp(handle_val, "delete_key") == 0)
 1178 andrew                   4662 ECB             :     {
 1178 andrew                   4663 GIC           3 :         return jsonb_delete_path(fcinfo);
                               4664                 :     }
 1178 andrew                   4665 CBC           6 :     else if (strcmp(handle_val, "return_target") == 0)
                               4666                 :     {
                               4667               3 :         Jsonb      *in = PG_GETARG_JSONB_P(0);
                               4668                 : 
 1178 andrew                   4669 GIC           3 :         PG_RETURN_JSONB_P(in);
                               4670                 :     }
                               4671                 :     else
                               4672                 :     {
                               4673               3 :         ereport(ERROR,
 1178 andrew                   4674 ECB             :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                               4675                 :                  errmsg("null_value_treatment must be \"delete_key\", \"return_target\", \"use_json_null\", or \"raise_exception\"")));
 1176 tgl                      4676                 :         return (Datum) 0;       /* silence stupider compilers */
 1178 andrew                   4677                 :     }
                               4678                 : }
                               4679                 : 
 2889                          4680                 : /*
 2337 magnus                   4681                 :  * SQL function jsonb_delete_path(jsonb, text[])
                               4682                 :  */
                               4683                 : Datum
 2889 andrew                   4684 GIC          45 : jsonb_delete_path(PG_FUNCTION_ARGS)
                               4685                 : {
 2029 tgl                      4686 CBC          45 :     Jsonb      *in = PG_GETARG_JSONB_P(0);
 2889 andrew                   4687 GIC          45 :     ArrayType  *path = PG_GETARG_ARRAYTYPE_P(1);
 2889 andrew                   4688 CBC          45 :     JsonbValue *res = NULL;
                               4689                 :     Datum      *path_elems;
 2889 andrew                   4690 ECB             :     bool       *path_nulls;
 2889 andrew                   4691 EUB             :     int         path_len;
                               4692                 :     JsonbIterator *it;
 2889 andrew                   4693 GIC          45 :     JsonbParseState *st = NULL;
                               4694                 : 
 2889 andrew                   4695 CBC          45 :     if (ARR_NDIM(path) > 1)
 2889 andrew                   4696 LBC           0 :         ereport(ERROR,
                               4697                 :                 (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
                               4698                 :                  errmsg("wrong number of array subscripts")));
                               4699                 : 
 2888 andrew                   4700 CBC          45 :     if (JB_ROOT_IS_SCALAR(in))
                               4701               3 :         ereport(ERROR,
                               4702                 :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
 2888 andrew                   4703 ECB             :                  errmsg("cannot delete path in scalar")));
                               4704                 : 
 2889 andrew                   4705 CBC          42 :     if (JB_ROOT_COUNT(in) == 0)
 2029 tgl                      4706 GBC           6 :         PG_RETURN_JSONB_P(in);
                               4707                 : 
  282 peter                    4708 GNC          36 :     deconstruct_array_builtin(path, TEXTOID, &path_elems, &path_nulls, &path_len);
 2889 andrew                   4709 ECB             : 
 2889 andrew                   4710 GIC          36 :     if (path_len == 0)
 2029 tgl                      4711 UIC           0 :         PG_RETURN_JSONB_P(in);
 2889 andrew                   4712 ECB             : 
 2889 andrew                   4713 GIC          36 :     it = JsonbIteratorInit(&in->root);
 2889 andrew                   4714 ECB             : 
 2559 teodor                   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                 : 
 2029 tgl                      4720              33 :     PG_RETURN_JSONB_P(JsonbValueToJsonb(res));
                               4721                 : }
 2559 teodor                   4722 ECB             : 
                               4723                 : /*
                               4724                 :  * SQL function jsonb_insert(jsonb, text[], jsonb, boolean)
                               4725                 :  */
                               4726                 : Datum
 2559 teodor                   4727 GIC          66 : jsonb_insert(PG_FUNCTION_ARGS)
                               4728                 : {
 2029 tgl                      4729              66 :     Jsonb      *in = PG_GETARG_JSONB_P(0);
 2559 teodor                   4730              66 :     ArrayType  *path = PG_GETARG_ARRAYTYPE_P(1);
  798 akorotkov                4731 CBC          66 :     Jsonb      *newjsonb = PG_GETARG_JSONB_P(2);
  798 akorotkov                4732 EUB             :     JsonbValue  newval;
 2559 teodor                   4733 GIC          66 :     bool        after = PG_GETARG_BOOL(3);
                               4734              66 :     JsonbValue *res = NULL;
 2559 teodor                   4735 ECB             :     Datum      *path_elems;
                               4736                 :     bool       *path_nulls;
                               4737                 :     int         path_len;
                               4738                 :     JsonbIterator *it;
 2559 teodor                   4739 GIC          66 :     JsonbParseState *st = NULL;
                               4740                 : 
  798 akorotkov                4741 CBC          66 :     JsonbToJsonbValue(newjsonb, &newval);
  798 akorotkov                4742 ECB             : 
 2559 teodor                   4743 GIC          66 :     if (ARR_NDIM(path) > 1)
 2559 teodor                   4744 LBC           0 :         ereport(ERROR,
 2559 teodor                   4745 ECB             :                 (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
                               4746                 :                  errmsg("wrong number of array subscripts")));
                               4747                 : 
 2559 teodor                   4748 GIC          66 :     if (JB_ROOT_IS_SCALAR(in))
 2559 teodor                   4749 LBC           0 :         ereport(ERROR,
                               4750                 :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                               4751                 :                  errmsg("cannot set path in scalar")));
                               4752                 : 
  282 peter                    4753 GNC          66 :     deconstruct_array_builtin(path, TEXTOID, &path_elems, &path_nulls, &path_len);
                               4754                 : 
 2559 teodor                   4755 CBC          66 :     if (path_len == 0)
 2029 tgl                      4756 UIC           0 :         PG_RETURN_JSONB_P(in);
                               4757                 : 
 2559 teodor                   4758 GIC          66 :     it = JsonbIteratorInit(&in->root);
 2559 teodor                   4759 ECB             : 
  798 akorotkov                4760 GIC          66 :     res = setPath(&it, path_elems, path_nulls, path_len, &st, 0, &newval,
 2559 teodor                   4761 ECB             :                   after ? JB_PATH_INSERT_AFTER : JB_PATH_INSERT_BEFORE);
 2889 andrew                   4762                 : 
 2878 bruce                    4763 CBC          60 :     Assert(res != NULL);
                               4764                 : 
 2029 tgl                      4765              60 :     PG_RETURN_JSONB_P(JsonbValueToJsonb(res));
                               4766                 : }
 2889 andrew                   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 *
 2889 andrew                   4776 GIC          84 : IteratorConcat(JsonbIterator **it1, JsonbIterator **it2,
 2889 andrew                   4777 ECB             :                JsonbParseState **state)
                               4778                 : {
                               4779                 :     JsonbValue  v1,
                               4780                 :                 v2,
 2889 andrew                   4781 GIC          84 :                *res = NULL;
                               4782                 :     JsonbIteratorToken r1,
                               4783                 :                 r2,
                               4784                 :                 rk1,
                               4785                 :                 rk2;
                               4786                 : 
  947 tgl                      4787              84 :     rk1 = JsonbIteratorNext(it1, &v1, false);
  947 tgl                      4788 CBC          84 :     rk2 = JsonbIteratorNext(it2, &v2, false);
                               4789                 : 
 2889 andrew                   4790 ECB             :     /*
  839 tgl                      4791                 :      * JsonbIteratorNext reports raw scalars as if they were single-element
                               4792                 :      * arrays; hence we only need consider "object" and "array" cases here.
                               4793                 :      */
 2889 andrew                   4794 GIC          84 :     if (rk1 == WJB_BEGIN_OBJECT && rk2 == WJB_BEGIN_OBJECT)
                               4795                 :     {
                               4796                 :         /*
  839 tgl                      4797 ECB             :          * Both inputs are objects.
                               4798                 :          *
  947                          4799                 :          * Append all the tokens from v1 to res, except last WJB_END_OBJECT
 2889 andrew                   4800 EUB             :          * (because res will not be finished yet).
                               4801                 :          */
  947 tgl                      4802 GIC          15 :         pushJsonbValue(state, rk1, NULL);
 2876 andrew                   4803              87 :         while ((r1 = JsonbIteratorNext(it1, &v1, true)) != WJB_END_OBJECT)
 2870 andrew                   4804 CBC          72 :             pushJsonbValue(state, r1, &v1);
 2889 andrew                   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
  839 tgl                      4809                 :          * automatically override the value from the first object.
 2889 andrew                   4810                 :          */
 1820 tgl                      4811 GIC          78 :         while ((r2 = JsonbIteratorNext(it2, &v2, true)) != WJB_DONE)
 2876 andrew                   4812 CBC          63 :             res = pushJsonbValue(state, r2, r2 != WJB_END_OBJECT ? &v2 : NULL);
                               4813                 :     }
 2889                          4814              69 :     else if (rk1 == WJB_BEGIN_ARRAY && rk2 == WJB_BEGIN_ARRAY)
 2889 andrew                   4815 EUB             :     {
                               4816                 :         /*
  839 tgl                      4817 ECB             :          * Both inputs are arrays.
                               4818                 :          */
  947 tgl                      4819 CBC          27 :         pushJsonbValue(state, rk1, NULL);
                               4820                 : 
 2876 andrew                   4821 GIC          60 :         while ((r1 = JsonbIteratorNext(it1, &v1, true)) != WJB_END_ARRAY)
 2876 andrew                   4822 ECB             :         {
 2876 andrew                   4823 GIC          33 :             Assert(r1 == WJB_ELEM);
 2889 andrew                   4824 CBC          33 :             pushJsonbValue(state, r1, &v1);
                               4825                 :         }
                               4826                 : 
 2870 andrew                   4827 GIC          60 :         while ((r2 = JsonbIteratorNext(it2, &v2, true)) != WJB_END_ARRAY)
                               4828                 :         {
 2876                          4829              33 :             Assert(r2 == WJB_ELEM);
                               4830              33 :             pushJsonbValue(state, WJB_ELEM, &v2);
 2889 andrew                   4831 ECB             :         }
                               4832                 : 
 2876 andrew                   4833 CBC          27 :         res = pushJsonbValue(state, WJB_END_ARRAY, NULL /* signal to sort */ );
 2889 andrew                   4834 ECB             :     }
  839 tgl                      4835 CBC          42 :     else if (rk1 == WJB_BEGIN_OBJECT)
                               4836                 :     {
  839 tgl                      4837 ECB             :         /*
                               4838                 :          * We have object || array.
                               4839                 :          */
  839 tgl                      4840 GIC           9 :         Assert(rk2 == WJB_BEGIN_ARRAY);
                               4841                 : 
 2889 andrew                   4842               9 :         pushJsonbValue(state, WJB_BEGIN_ARRAY, NULL);
 2876 andrew                   4843 ECB             : 
  839 tgl                      4844 GIC           9 :         pushJsonbValue(state, WJB_BEGIN_OBJECT, NULL);
  839 tgl                      4845 CBC          36 :         while ((r1 = JsonbIteratorNext(it1, &v1, true)) != WJB_DONE)
  839 tgl                      4846 GIC          27 :             pushJsonbValue(state, r1, r1 != WJB_END_OBJECT ? &v1 : NULL);
 2889 andrew                   4847 ECB             : 
  839 tgl                      4848 GBC          27 :         while ((r2 = JsonbIteratorNext(it2, &v2, true)) != WJB_DONE)
  839 tgl                      4849 GIC          18 :             res = pushJsonbValue(state, r2, r2 != WJB_END_ARRAY ? &v2 : NULL);
                               4850                 :     }
                               4851                 :     else
 2889 andrew                   4852 ECB             :     {
 2889 andrew                   4853 EUB             :         /*
                               4854                 :          * We have array || object.
                               4855                 :          */
  839 tgl                      4856 GIC          33 :         Assert(rk1 == WJB_BEGIN_ARRAY);
  839 tgl                      4857 CBC          33 :         Assert(rk2 == WJB_BEGIN_OBJECT);
                               4858                 : 
                               4859              33 :         pushJsonbValue(state, WJB_BEGIN_ARRAY, NULL);
  839 tgl                      4860 EUB             : 
  839 tgl                      4861 GIC          48 :         while ((r1 = JsonbIteratorNext(it1, &v1, true)) != WJB_END_ARRAY)
  839 tgl                      4862 CBC          15 :             pushJsonbValue(state, r1, &v1);
                               4863                 : 
                               4864              33 :         pushJsonbValue(state, WJB_BEGIN_OBJECT, NULL);
  839 tgl                      4865 GIC         426 :         while ((r2 = JsonbIteratorNext(it2, &v2, true)) != WJB_DONE)
                               4866             393 :             pushJsonbValue(state, r2, r2 != WJB_END_OBJECT ? &v2 : NULL);
  839 tgl                      4867 ECB             : 
  839 tgl                      4868 GIC          33 :         res = pushJsonbValue(state, WJB_END_ARRAY, NULL);
 2889 andrew                   4869 ECB             :     }
                               4870                 : 
 2889 andrew                   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,
 2559 teodor                   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                 :  *
  798 akorotkov                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 *
 2870 andrew                   4904 GIC         657 : setPath(JsonbIterator **it, Datum *path_elems,
                               4905                 :         bool *path_nulls, int path_len,
  798 akorotkov                4906 ECB             :         JsonbParseState **st, int level, JsonbValue *newval, int op_type)
 2889 andrew                   4907                 : {
                               4908                 :     JsonbValue  v;
                               4909                 :     JsonbIteratorToken r;
                               4910                 :     JsonbValue *res;
                               4911                 : 
 2743 noah                     4912 GIC         657 :     check_stack_depth();
                               4913                 : 
 2744 andrew                   4914             657 :     if (path_nulls[level])
 2573 tgl                      4915 CBC           9 :         ereport(ERROR,
 2573 tgl                      4916 ECB             :                 (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
                               4917                 :                  errmsg("path element at position %d is null",
                               4918                 :                         level + 1)));
                               4919                 : 
 2889 andrew                   4920 GIC         648 :     r = JsonbIteratorNext(it, &v, false);
                               4921                 : 
                               4922             648 :     switch (r)
 2889 andrew                   4923 ECB             :     {
 2889 andrew                   4924 GIC         189 :         case WJB_BEGIN_ARRAY:
  798 akorotkov                4925 ECB             : 
                               4926                 :             /*
  578 peter                    4927                 :              * If instructed complain about attempts to replace within a raw
  798 akorotkov                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                 :              */
  798 akorotkov                4932 GIC         189 :             if ((op_type & JB_PATH_FILL_GAPS) && (level <= path_len - 1) &&
  798 akorotkov                4933 CBC          45 :                 v.val.array.rawScalar)
                               4934               6 :                 ereport(ERROR,
                               4935                 :                         (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                               4936                 :                          errmsg("cannot replace existing key"),
  798 akorotkov                4937 ECB             :                          errdetail("The path assumes key is a composite object, "
                               4938                 :                                    "but it is a scalar value.")));
                               4939                 : 
 2889 andrew                   4940 GIC         183 :             (void) pushJsonbValue(st, r, NULL);
 2870                          4941             183 :             setPathArray(it, path_elems, path_nulls, path_len, st, level,
 2559 teodor                   4942             183 :                          newval, v.val.array.nElems, op_type);
 2889 andrew                   4943             171 :             r = JsonbIteratorNext(it, &v, false);
 2889 andrew                   4944 CBC         171 :             Assert(r == WJB_END_ARRAY);
 2889 andrew                   4945 GIC         171 :             res = pushJsonbValue(st, r, NULL);
 2889 andrew                   4946 CBC         171 :             break;
 2889 andrew                   4947 GIC         444 :         case WJB_BEGIN_OBJECT:
 2889 andrew                   4948 CBC         444 :             (void) pushJsonbValue(st, r, NULL);
 2870                          4949             444 :             setPathObject(it, path_elems, path_nulls, path_len, st, level,
 2559 teodor                   4950             444 :                           newval, v.val.object.nPairs, op_type);
 2889 andrew                   4951 GIC         393 :             r = JsonbIteratorNext(it, &v, true);
 2889 andrew                   4952 CBC         393 :             Assert(r == WJB_END_OBJECT);
                               4953             393 :             res = pushJsonbValue(st, r, NULL);
 2889 andrew                   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
  798 akorotkov                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                 :              */
  798 akorotkov                4964 GIC          15 :             if ((op_type & JB_PATH_FILL_GAPS) && (level <= path_len - 1))
  798 akorotkov                4965 CBC          15 :                 ereport(ERROR,
  798 akorotkov                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                 : 
 2889 andrew                   4971 UIC           0 :             res = pushJsonbValue(st, r, &v);
 2889 andrew                   4972 LBC           0 :             break;
 2889 andrew                   4973 UIC           0 :         default:
 2573 tgl                      4974               0 :             elog(ERROR, "unrecognized iterator result: %d", (int) r);
 2573 tgl                      4975 ECB             :             res = NULL;         /* keep compiler quiet */
                               4976                 :             break;
                               4977                 :     }
                               4978                 : 
 2889 andrew                   4979 GIC         564 :     return res;
                               4980                 : }
                               4981                 : 
                               4982                 : /*
                               4983                 :  * Object walker for setPath
                               4984                 :  */
                               4985                 : static void
 2870                          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                 : {
  118 tgl                      4990             444 :     text       *pathelem = NULL;
                               4991                 :     int         i;
                               4992                 :     JsonbValue  k,
                               4993                 :                 v;
 2889 andrew                   4994             444 :     bool        done = false;
                               4995                 : 
                               4996             444 :     if (level >= path_len || path_nulls[level])
 2889 andrew                   4997 UIC           0 :         done = true;
                               4998                 :     else
                               4999                 :     {
                               5000                 :         /* The path Datum could be toasted, in which case we must detoast it */
  118 tgl                      5001 GIC         444 :         pathelem = DatumGetTextPP(path_elems[level]);
                               5002                 :     }
                               5003                 : 
                               5004                 :     /* empty object is a special case for create */
 2559 teodor                   5005             444 :     if ((npairs == 0) && (op_type & JB_PATH_CREATE_OR_INSERT) &&
                               5006              27 :         (level == path_len - 1))
                               5007                 :     {
 2870 andrew                   5008 ECB             :         JsonbValue  newkey;
                               5009                 : 
 2870 andrew                   5010 GIC           9 :         newkey.type = jbvString;
  118 tgl                      5011               9 :         newkey.val.string.val = VARDATA_ANY(pathelem);
                               5012               9 :         newkey.val.string.len = VARSIZE_ANY_EXHDR(pathelem);
                               5013                 : 
 2870 andrew                   5014               9 :         (void) pushJsonbValue(st, WJB_KEY, &newkey);
  798 akorotkov                5015               9 :         (void) pushJsonbValue(st, WJB_VALUE, newval);
 2870 andrew                   5016 ECB             :     }
                               5017                 : 
 2870 andrew                   5018 CBC        2313 :     for (i = 0; i < npairs; i++)
 2889 andrew                   5019 ECB             :     {
 2737 noah                     5020 GIC        1920 :         JsonbIteratorToken r = JsonbIteratorNext(it, &k, true);
                               5021                 : 
 2889 andrew                   5022            1920 :         Assert(r == WJB_KEY);
                               5023                 : 
 2889 andrew                   5024 CBC        3033 :         if (!done &&
  118 tgl                      5025 GIC        1113 :             k.val.string.len == VARSIZE_ANY_EXHDR(pathelem) &&
  118 tgl                      5026 CBC         564 :             memcmp(k.val.string.val, VARDATA_ANY(pathelem),
 2889 andrew                   5027 GIC         564 :                    k.val.string.len) == 0)
 2889 andrew                   5028 ECB             :         {
  798 akorotkov                5029 GIC         345 :             done = true;
                               5030                 : 
 2889 andrew                   5031             345 :             if (level == path_len - 1)
                               5032                 :             {
                               5033                 :                 /*
                               5034                 :                  * called from jsonb_insert(), it forbids redefining an
                               5035                 :                  * existing value
 2559 teodor                   5036 ECB             :                  */
 2559 teodor                   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                 : 
 2495 rhaas                    5044              78 :                 r = JsonbIteratorNext(it, &v, true);    /* skip value */
 2559 teodor                   5045              78 :                 if (!(op_type & JB_PATH_DELETE))
 2889 andrew                   5046 ECB             :                 {
 2889 andrew                   5047 CBC          57 :                     (void) pushJsonbValue(st, WJB_KEY, &k);
  798 akorotkov                5048              57 :                     (void) pushJsonbValue(st, WJB_VALUE, newval);
 2889 andrew                   5049 ECB             :                 }
                               5050                 :             }
                               5051                 :             else
                               5052                 :             {
 2889 andrew                   5053 CBC         261 :                 (void) pushJsonbValue(st, r, &k);
 2870                          5054             261 :                 setPath(it, path_elems, path_nulls, path_len,
 2559 teodor                   5055 ECB             :                         st, level + 1, newval, op_type);
 2889 andrew                   5056                 :             }
                               5057                 :         }
                               5058                 :         else
                               5059                 :         {
 2559 teodor                   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                 : 
 2870 andrew                   5065              30 :                 newkey.type = jbvString;
  118 tgl                      5066              30 :                 newkey.val.string.val = VARDATA_ANY(pathelem);
                               5067              30 :                 newkey.val.string.len = VARSIZE_ANY_EXHDR(pathelem);
 2870 andrew                   5068 ECB             : 
 2870 andrew                   5069 CBC          30 :                 (void) pushJsonbValue(st, WJB_KEY, &newkey);
  798 akorotkov                5070 GIC          30 :                 (void) pushJsonbValue(st, WJB_VALUE, newval);
                               5071                 :             }
                               5072                 : 
 2889 andrew                   5073            1575 :             (void) pushJsonbValue(st, r, &k);
                               5074            1575 :             r = JsonbIteratorNext(it, &v, false);
 2889 andrew                   5075 GBC        1575 :             (void) pushJsonbValue(st, r, r < WJB_BEGIN_ARRAY ? &v : NULL);
                               5076            1575 :             if (r == WJB_BEGIN_ARRAY || r == WJB_BEGIN_OBJECT)
 2889 andrew                   5077 EUB             :             {
 2878 bruce                    5078 GBC         408 :                 int         walking_level = 1;
                               5079                 : 
 2889 andrew                   5080 GIC        3795 :                 while (walking_level != 0)
                               5081                 :                 {
                               5082            3387 :                     r = JsonbIteratorNext(it, &v, false);
 2889 andrew                   5083 ECB             : 
 2889 andrew                   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);
 2889 andrew                   5090 ECB             :                 }
                               5091                 :             }
                               5092                 :         }
                               5093                 :     }
  798 akorotkov                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                 :      *
  798 akorotkov                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                 :      */
  798 akorotkov                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;
  118 tgl                      5110              24 :         newkey.val.string.val = VARDATA_ANY(pathelem);
  118 tgl                      5111 GIC          24 :         newkey.val.string.len = VARSIZE_ANY_EXHDR(pathelem);
                               5112                 : 
  798 akorotkov                5113              24 :         (void) pushJsonbValue(st, WJB_KEY, &newkey);
  798 akorotkov                5114 CBC          24 :         (void) push_path(st, level, path_elems, path_nulls,
  798 akorotkov                5115 ECB             :                          path_len, newval);
                               5116                 : 
                               5117                 :         /* Result is closed with WJB_END_OBJECT outside of this function */
                               5118                 :     }
 2889 andrew                   5119 CBC         393 : }
                               5120                 : 
                               5121                 : /*
 2870 andrew                   5122 ECB             :  * Array walker for setPath
                               5123                 :  */
 2889                          5124                 : static void
 2870 andrew                   5125 GIC         183 : setPathArray(JsonbIterator **it, Datum *path_elems, bool *path_nulls,
 2870 andrew                   5126 ECB             :              int path_len, JsonbParseState **st, int level,
                               5127                 :              JsonbValue *newval, uint32 nelems, int op_type)
 2889                          5128                 : {
                               5129                 :     JsonbValue  v;
                               5130                 :     int         idx,
                               5131                 :                 i;
 2870 andrew                   5132 GIC         183 :     bool        done = false;
 2889 andrew                   5133 ECB             : 
                               5134                 :     /* pick correct index */
 2889 andrew                   5135 CBC         183 :     if (level < path_len && !path_nulls[level])
 2889 andrew                   5136 GIC         174 :     {
 2573 tgl                      5137             183 :         char       *c = TextDatumGetCString(path_elems[level]);
                               5138                 :         char       *badp;
                               5139                 : 
 2889 andrew                   5140             183 :         errno = 0;
  787 tgl                      5141 CBC         183 :         idx = strtoint(c, &badp, 10);
                               5142             183 :         if (badp == c || *badp != '\0' || errno != 0)
 2573 tgl                      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                 :     }
 2889 andrew                   5148 ECB             :     else
 2870 andrew                   5149 LBC           0 :         idx = nelems;
                               5150                 : 
 2889 andrew                   5151 CBC         174 :     if (idx < 0)
 2889 andrew                   5152 ECB             :     {
 2870 andrew                   5153 GIC          39 :         if (-idx > nelems)
                               5154                 :         {
                               5155                 :             /*
                               5156                 :              * If asked to keep elements position consistent, it's not allowed
  798 akorotkov                5157 ECB             :              * to prepend the array.
                               5158                 :              */
  798 akorotkov                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)));
  798 akorotkov                5164 ECB             :             else
  798 akorotkov                5165 CBC           9 :                 idx = INT_MIN;
                               5166                 :         }
                               5167                 :         else
 2870 andrew                   5168 GIC          27 :             idx = nelems + idx;
 2889 andrew                   5169 ECB             :     }
                               5170                 : 
  798 akorotkov                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                 :      */
  798 akorotkov                5175 GIC         171 :     if (!(op_type & JB_PATH_FILL_GAPS))
                               5176                 :     {
  798 akorotkov                5177 CBC         135 :         if (idx > 0 && idx > nelems)
                               5178              24 :             idx = nelems;
  798 akorotkov                5179 ECB             :     }
 2870 andrew                   5180                 : 
                               5181                 :     /*
 2823                          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                 :      */
 2559 teodor                   5186 CBC         171 :     if ((idx == INT_MIN || nelems == 0) && (level == path_len - 1) &&
 2559 teodor                   5187 GIC          33 :         (op_type & JB_PATH_CREATE_OR_INSERT))
 2870 andrew                   5188 ECB             :     {
 2870 andrew                   5189 CBC          33 :         Assert(newval != NULL);
  798 akorotkov                5190 ECB             : 
  798 akorotkov                5191 CBC          33 :         if (op_type & JB_PATH_FILL_GAPS && nelems == 0 && idx > 0)
  798 akorotkov                5192 GIC           3 :             push_null_elements(st, idx);
  798 akorotkov                5193 ECB             : 
  798 akorotkov                5194 GIC          33 :         (void) pushJsonbValue(st, WJB_ELEM, newval);
                               5195                 : 
 2870 andrew                   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                 : 
 2889                          5204             312 :         if (i == idx && level < path_len)
                               5205                 :         {
  798 akorotkov                5206             108 :             done = true;
                               5207                 : 
 2889 andrew                   5208             108 :             if (level == path_len - 1)
 2889 andrew                   5209 ECB             :             {
 2878 bruce                    5210 GIC          72 :                 r = JsonbIteratorNext(it, &v, true);    /* skip */
                               5211                 : 
 2559 teodor                   5212              72 :                 if (op_type & (JB_PATH_INSERT_BEFORE | JB_PATH_CREATE))
  798 akorotkov                5213 CBC          42 :                     (void) pushJsonbValue(st, WJB_ELEM, newval);
 2559 teodor                   5214 ECB             : 
                               5215                 :                 /*
                               5216                 :                  * We should keep current value only in case of
 2495 rhaas                    5217                 :                  * JB_PATH_INSERT_BEFORE or JB_PATH_INSERT_AFTER because
                               5218                 :                  * otherwise it should be deleted or replaced
                               5219                 :                  */
 2559 teodor                   5220 GIC          72 :                 if (op_type & (JB_PATH_INSERT_AFTER | JB_PATH_INSERT_BEFORE))
                               5221              36 :                     (void) pushJsonbValue(st, r, &v);
                               5222                 : 
 2369 tgl                      5223 CBC          72 :                 if (op_type & (JB_PATH_INSERT_AFTER | JB_PATH_REPLACE))
  798 akorotkov                5224 GIC          18 :                     (void) pushJsonbValue(st, WJB_ELEM, newval);
                               5225                 :             }
                               5226                 :             else
 2870 andrew                   5227              36 :                 (void) setPath(it, path_elems, path_nulls, path_len,
                               5228                 :                                st, level + 1, newval, op_type);
 2889 andrew                   5229 ECB             :         }
                               5230                 :         else
                               5231                 :         {
 2889 andrew                   5232 GIC         204 :             r = JsonbIteratorNext(it, &v, false);
                               5233                 : 
                               5234             204 :             (void) pushJsonbValue(st, r, r < WJB_BEGIN_ARRAY ? &v : NULL);
                               5235                 : 
 2889 andrew                   5236 CBC         204 :             if (r == WJB_BEGIN_ARRAY || r == WJB_BEGIN_OBJECT)
                               5237                 :             {
 2878 bruce                    5238 GIC           3 :                 int         walking_level = 1;
 2889 andrew                   5239 ECB             : 
 2889 andrew                   5240 CBC          12 :                 while (walking_level != 0)
 2889 andrew                   5241 ECB             :                 {
 2889 andrew                   5242 GIC           9 :                     r = JsonbIteratorNext(it, &v, false);
                               5243                 : 
 2889 andrew                   5244 CBC           9 :                     if (r == WJB_BEGIN_ARRAY || r == WJB_BEGIN_OBJECT)
 2889 andrew                   5245 LBC           0 :                         ++walking_level;
 2889 andrew                   5246 CBC           9 :                     if (r == WJB_END_ARRAY || r == WJB_END_OBJECT)
                               5247               3 :                         --walking_level;
                               5248                 : 
 2889 andrew                   5249 GIC           9 :                     (void) pushJsonbValue(st, r, r < WJB_BEGIN_ARRAY ? &v : NULL);
                               5250                 :                 }
                               5251                 :             }
                               5252                 :         }
 2889 andrew                   5253 EUB             :     }
                               5254                 : 
  798 akorotkov                5255 CBC         171 :     if ((op_type & JB_PATH_CREATE_OR_INSERT) && !done && level == path_len - 1)
                               5256                 :     {
  798 akorotkov                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                 :          */
  798 akorotkov                5261 GIC          18 :         if (op_type & JB_PATH_FILL_GAPS && idx > nelems)
                               5262               6 :             push_null_elements(st, idx - nelems);
  798 akorotkov                5263 ECB             : 
  798 akorotkov                5264 CBC          18 :         (void) pushJsonbValue(st, WJB_ELEM, newval);
  798 akorotkov                5265 GIC          18 :         done = true;
                               5266                 :     }
                               5267                 : 
                               5268                 :     /*--
  798 akorotkov                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                 :      */
  798 akorotkov                5278 GIC         171 :     if (!done && (op_type & JB_PATH_FILL_GAPS) && (level < path_len - 1))
  798 akorotkov                5279 ECB             :     {
  798 akorotkov                5280 GIC          12 :         if (idx > 0)
  798 akorotkov                5281 CBC           6 :             push_null_elements(st, idx - nelems);
  798 akorotkov                5282 ECB             : 
  798 akorotkov                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                 :     }
 2889 andrew                   5288             171 : }
                               5289                 : 
 2200 andrew                   5290 ECB             : /*
 1828 teodor                   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
 1828 teodor                   5296 CBC         126 : parse_jsonb_index_flags(Jsonb *jb)
                               5297                 : {
 1809 tgl                      5298 ECB             :     JsonbIterator *it;
                               5299                 :     JsonbValue  v;
                               5300                 :     JsonbIteratorToken type;
 1809 tgl                      5301 GIC         126 :     uint32      flags = 0;
                               5302                 : 
 1828 teodor                   5303             126 :     it = JsonbIteratorInit(&jb->root);
 1828 teodor                   5304 ECB             : 
 1828 teodor                   5305 GIC         126 :     type = JsonbIteratorNext(&it, &v, false);
                               5306                 : 
                               5307                 :     /*
 1809 tgl                      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                 :      */
 1828 teodor                   5312 CBC         126 :     if (type != WJB_BEGIN_ARRAY)
 1828 teodor                   5313 GIC           6 :         ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
 1828 teodor                   5314 ECB             :                         errmsg("wrong flag type, only arrays and scalars are allowed")));
                               5315                 : 
 1828 teodor                   5316 CBC         234 :     while ((type = JsonbIteratorNext(&it, &v, false)) == WJB_ELEM)
 1828 teodor                   5317 ECB             :     {
 1828 teodor                   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                 : 
 1828 teodor                   5324 CBC         174 :         if (v.val.string.len == 3 &&
 1809 tgl                      5325              54 :             pg_strncasecmp(v.val.string.val, "all", 3) == 0)
 1828 teodor                   5326 GIC          42 :             flags |= jtiAll;
 1828 teodor                   5327 CBC          90 :         else if (v.val.string.len == 3 &&
                               5328              12 :                  pg_strncasecmp(v.val.string.val, "key", 3) == 0)
 1828 teodor                   5329 GIC          12 :             flags |= jtiKey;
                               5330              90 :         else if (v.val.string.len == 6 &&
 1164 tgl                      5331 CBC          24 :                  pg_strncasecmp(v.val.string.val, "string", 6) == 0)
 1828 teodor                   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;
 1828 teodor                   5336 CBC          30 :         else if (v.val.string.len == 7 &&
 1828 teodor                   5337 GIC          12 :                  pg_strncasecmp(v.val.string.val, "boolean", 7) == 0)
 1828 teodor                   5338 CBC          12 :             flags |= jtiBool;
                               5339                 :         else
                               5340               6 :             ereport(ERROR,
                               5341                 :                     (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
 1828 teodor                   5342 ECB             :                      errmsg("wrong flag in flag array: \"%s\"",
                               5343                 :                             pnstrdup(v.val.string.val, v.val.string.len)),
 1584 michael                  5344                 :                      errhint("Possible values are: \"string\", \"numeric\", \"boolean\", \"key\", and \"all\".")));
                               5345                 :     }
 1828 teodor                   5346                 : 
                               5347                 :     /* expect end of array now */
 1828 teodor                   5348 CBC         102 :     if (type != WJB_END_ARRAY)
 1828 teodor                   5349 UBC           0 :         elog(ERROR, "unexpected end of flag array");
 1828 teodor                   5350 ECB             : 
                               5351                 :     /* get final WJB_DONE and free iterator */
 1820 tgl                      5352 GIC         102 :     type = JsonbIteratorNext(&it, &v, false);
 1820 tgl                      5353 CBC         102 :     if (type != WJB_DONE)
 1820 tgl                      5354 UIC           0 :         elog(ERROR, "unexpected end of flag array");
                               5355                 : 
 1828 teodor                   5356 GIC         102 :     return flags;
                               5357                 : }
                               5358                 : 
 1828 teodor                   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
 1828 teodor                   5364 GIC          75 : iterate_jsonb_values(Jsonb *jb, uint32 flags, void *state,
 1828 teodor                   5365 ECB             :                      JsonIterateStringValuesAction action)
 2200 andrew                   5366                 : {
                               5367                 :     JsonbIterator *it;
 2153 bruce                    5368                 :     JsonbValue  v;
                               5369                 :     JsonbIteratorToken type;
                               5370                 : 
 2200 andrew                   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                 :     {
 1828 teodor                   5379             747 :         if (type == WJB_KEY)
                               5380                 :         {
                               5381             279 :             if (flags & jtiKey)
 1828 teodor                   5382 CBC          72 :                 action(state, v.val.string.val, v.val.string.len);
                               5383                 : 
                               5384             279 :             continue;
 1828 teodor                   5385 ECB             :         }
 1828 teodor                   5386 GIC         468 :         else if (!(type == WJB_VALUE || type == WJB_ELEM))
 2200 andrew                   5387 ECB             :         {
                               5388                 :             /* do not call callback for composite JsonbValue */
 1828 teodor                   5389 GIC         186 :             continue;
                               5390                 :         }
                               5391                 : 
 1828 teodor                   5392 ECB             :         /* JsonbValue is a value of object or element of array */
 1809 tgl                      5393 GIC         282 :         switch (v.type)
                               5394                 :         {
 1828 teodor                   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:
 1828 teodor                   5400 CBC          84 :                 if (flags & jtiNumeric)
                               5401                 :                 {
                               5402                 :                     char       *val;
                               5403                 : 
 1828 teodor                   5404 GIC          36 :                     val = DatumGetCString(DirectFunctionCall1(numeric_out,
 1809 tgl                      5405 ECB             :                                                               NumericGetDatum(v.val.numeric)));
                               5406                 : 
 1828 teodor                   5407 CBC          36 :                     action(state, val, strlen(val));
 1828 teodor                   5408 GIC          36 :                     pfree(val);
 1828 teodor                   5409 ECB             :                 }
 1828 teodor                   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);
 1828 teodor                   5416 ECB             :                     else
 1828 teodor                   5417 CBC          12 :                         action(state, "false", 5);
                               5418                 :                 }
 1828 teodor                   5419 GIC          78 :                 break;
 1828 teodor                   5420 CBC          45 :             default:
                               5421                 :                 /* do not call callback for composite JsonbValue */
                               5422              45 :                 break;
 2200 andrew                   5423 ECB             :         }
                               5424                 :     }
 2200 andrew                   5425 GIC          75 : }
                               5426                 : 
                               5427                 : /*
 1828 teodor                   5428 ECB             :  * Iterate over json values and elements, specified by flags, and pass them
                               5429                 :  * together with an iteration state to a specified JsonIterateStringValuesAction.
 2200 andrew                   5430                 :  */
                               5431                 : void
 1828 teodor                   5432 CBC          75 : iterate_json_values(text *json, uint32 flags, void *action_state,
 1828 teodor                   5433 ECB             :                     JsonIterateStringValuesAction action)
 2200 andrew                   5434                 : {
 2200 andrew                   5435 CBC          75 :     JsonLexContext *lex = makeJsonLexContext(json, true);
                               5436              75 :     JsonSemAction *sem = palloc0(sizeof(JsonSemAction));
 2153 bruce                    5437              75 :     IterateJsonStringValuesState *state = palloc0(sizeof(IterateJsonStringValuesState));
 2200 andrew                   5438 ECB             : 
 2200 andrew                   5439 CBC          75 :     state->lex = lex;
                               5440              75 :     state->action = action;
                               5441              75 :     state->action_state = action_state;
 1828 teodor                   5442              75 :     state->flags = flags;
                               5443                 : 
 2200 andrew                   5444              75 :     sem->semstate = (void *) state;
 1828 teodor                   5445 GIC          75 :     sem->scalar = iterate_values_scalar;
                               5446              75 :     sem->object_field_start = iterate_values_object_field_start;
                               5447                 : 
 1168 rhaas                    5448              75 :     pg_parse_json_or_ereport(lex, sem);
 2200 andrew                   5449              75 : }
                               5450                 : 
                               5451                 : /*
 1828 teodor                   5452 ECB             :  * An auxiliary function for iterate_json_values to invoke a specified
 1828 teodor                   5453 EUB             :  * JsonIterateStringValuesAction for specified values.
                               5454                 :  */
                               5455                 : static JsonParseErrorType
 1828 teodor                   5456 CBC         282 : iterate_values_scalar(void *state, char *token, JsonTokenType tokentype)
 2200 andrew                   5457 ECB             : {
 2153 bruce                    5458 GBC         282 :     IterateJsonStringValuesState *_state = (IterateJsonStringValuesState *) state;
                               5459                 : 
 1809 tgl                      5460 CBC         282 :     switch (tokentype)
                               5461                 :     {
 1828 teodor                   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)
 1828 teodor                   5468 CBC          36 :                 _state->action(_state->action_state, token, strlen(token));
 1828 teodor                   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;
 1828 teodor                   5475 CBC          45 :         default:
                               5476                 :             /* do not call callback for any other token */
 1828 teodor                   5477 GIC          45 :             break;
                               5478                 :     }
                               5479                 : 
  119 tgl                      5480 GNC         282 :     return JSON_SUCCESS;
                               5481                 : }
                               5482                 : 
                               5483                 : static JsonParseErrorType
 1828 teodor                   5484 GIC         279 : iterate_values_object_field_start(void *state, char *fname, bool isnull)
 1828 teodor                   5485 ECB             : {
 1828 teodor                   5486 GIC         279 :     IterateJsonStringValuesState *_state = (IterateJsonStringValuesState *) state;
 1828 teodor                   5487 ECB             : 
 1828 teodor                   5488 CBC         279 :     if (_state->flags & jtiKey)
                               5489                 :     {
 1809 tgl                      5490              72 :         char       *val = pstrdup(fname);
                               5491                 : 
 1828 teodor                   5492              72 :         _state->action(_state->action_state, val, strlen(val));
                               5493                 :     }
                               5494                 : 
  119 tgl                      5495 GNC         279 :     return JSON_SUCCESS;
                               5496                 : }
 2200 andrew                   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 *
 2200 andrew                   5505 CBC          21 : transform_jsonb_string_values(Jsonb *jsonb, void *action_state,
 2118 tgl                      5506 ECB             :                               JsonTransformStringValuesAction transform_action)
 2200 andrew                   5507                 : {
 2153 bruce                    5508                 :     JsonbIterator *it;
                               5509                 :     JsonbValue  v,
 2153 bruce                    5510 GIC          21 :                *res = NULL;
                               5511                 :     JsonbIteratorToken type;
 2153 bruce                    5512 CBC          21 :     JsonbParseState *st = NULL;
                               5513                 :     text       *out;
 2153 bruce                    5514 GIC          21 :     bool        is_scalar = false;
 2200 andrew                   5515 ECB             : 
 2200 andrew                   5516 CBC          21 :     it = JsonbIteratorInit(&jsonb->root);
 2200 andrew                   5517 GIC          21 :     is_scalar = it->isScalar;
 2200 andrew                   5518 ECB             : 
 2200 andrew                   5519 CBC         228 :     while ((type = JsonbIteratorNext(&it, &v, false)) != WJB_DONE)
 2200 andrew                   5520 ECB             :     {
 2200 andrew                   5521 GIC         207 :         if ((type == WJB_VALUE || type == WJB_ELEM) && v.type == jbvString)
 2200 andrew                   5522 ECB             :         {
 2200 andrew                   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 */
  118 tgl                      5525              57 :             out = pg_detoast_datum_packed(out);
 2200 andrew                   5526 GIC          57 :             v.val.string.val = VARDATA_ANY(out);
 2200 andrew                   5527 CBC          57 :             v.val.string.len = VARSIZE_ANY_EXHDR(out);
                               5528              57 :             res = pushJsonbValue(&st, type, type < WJB_BEGIN_ARRAY ? &v : NULL);
                               5529                 :         }
 2200 andrew                   5530 ECB             :         else
                               5531                 :         {
 2200 andrew                   5532 GIC         243 :             res = pushJsonbValue(&st, type, (type == WJB_KEY ||
 2200 andrew                   5533 CBC          93 :                                              type == WJB_VALUE ||
                               5534                 :                                              type == WJB_ELEM) ? &v : NULL);
                               5535                 :         }
                               5536                 :     }
                               5537                 : 
 2200 andrew                   5538 GIC          21 :     if (res->type == jbvArray)
                               5539               6 :         res->val.array.rawScalar = is_scalar;
 2200 andrew                   5540 ECB             : 
 2200 andrew                   5541 GIC          21 :     return JsonbValueToJsonb(res);
                               5542                 : }
 2200 andrew                   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 *
 2200 andrew                   5552 CBC          21 : transform_json_string_values(text *json, void *action_state,
 2200 andrew                   5553 ECB             :                              JsonTransformStringValuesAction transform_action)
                               5554                 : {
 2200 andrew                   5555 GIC          21 :     JsonLexContext *lex = makeJsonLexContext(json, true);
 2200 andrew                   5556 CBC          21 :     JsonSemAction *sem = palloc0(sizeof(JsonSemAction));
                               5557              21 :     TransformJsonStringValuesState *state = palloc0(sizeof(TransformJsonStringValuesState));
                               5558                 : 
 2200 andrew                   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                 : 
 2200 andrew                   5564 CBC          21 :     sem->semstate = (void *) state;
                               5565              21 :     sem->object_start = transform_string_values_object_start;
 2200 andrew                   5566 GIC          21 :     sem->object_end = transform_string_values_object_end;
 2200 andrew                   5567 CBC          21 :     sem->array_start = transform_string_values_array_start;
 2200 andrew                   5568 GIC          21 :     sem->array_end = transform_string_values_array_end;
 2200 andrew                   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;
 2200 andrew                   5572 ECB             : 
 1168 rhaas                    5573 CBC          21 :     pg_parse_json_or_ereport(lex, sem);
 2200 andrew                   5574 ECB             : 
 2200 andrew                   5575 CBC          21 :     return cstring_to_text_with_len(state->strval->data, state->strval->len);
 2200 andrew                   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
 2200 andrew                   5584 CBC          27 : transform_string_values_object_start(void *state)
                               5585                 : {
 2200 andrew                   5586 GIC          27 :     TransformJsonStringValuesState *_state = (TransformJsonStringValuesState *) state;
 2153 bruce                    5587 ECB             : 
 2200 andrew                   5588 GIC          27 :     appendStringInfoCharMacro(_state->strval, '{');
                               5589                 : 
  119 tgl                      5590 GNC          27 :     return JSON_SUCCESS;
                               5591                 : }
                               5592                 : 
                               5593                 : static JsonParseErrorType
 2200 andrew                   5594 GIC          27 : transform_string_values_object_end(void *state)
 2200 andrew                   5595 ECB             : {
 2200 andrew                   5596 GIC          27 :     TransformJsonStringValuesState *_state = (TransformJsonStringValuesState *) state;
 2153 bruce                    5597 ECB             : 
 2200 andrew                   5598 GIC          27 :     appendStringInfoCharMacro(_state->strval, '}');
                               5599                 : 
  119 tgl                      5600 GNC          27 :     return JSON_SUCCESS;
 2200 andrew                   5601 ECB             : }
                               5602                 : 
                               5603                 : static JsonParseErrorType
 2200 andrew                   5604 GIC          15 : transform_string_values_array_start(void *state)
                               5605                 : {
 2200 andrew                   5606 CBC          15 :     TransformJsonStringValuesState *_state = (TransformJsonStringValuesState *) state;
                               5607                 : 
 2200 andrew                   5608 GIC          15 :     appendStringInfoCharMacro(_state->strval, '[');
                               5609                 : 
  119 tgl                      5610 GNC          15 :     return JSON_SUCCESS;
                               5611                 : }
                               5612                 : 
                               5613                 : static JsonParseErrorType
 2200 andrew                   5614 GIC          15 : transform_string_values_array_end(void *state)
                               5615                 : {
                               5616              15 :     TransformJsonStringValuesState *_state = (TransformJsonStringValuesState *) state;
                               5617                 : 
 2200 andrew                   5618 CBC          15 :     appendStringInfoCharMacro(_state->strval, ']');
                               5619                 : 
  119 tgl                      5620 GNC          15 :     return JSON_SUCCESS;
                               5621                 : }
                               5622                 : 
                               5623                 : static JsonParseErrorType
 2200 andrew                   5624 GIC          57 : transform_string_values_object_field_start(void *state, char *fname, bool isnull)
 2200 andrew                   5625 ECB             : {
 2200 andrew                   5626 GIC          57 :     TransformJsonStringValuesState *_state = (TransformJsonStringValuesState *) state;
 2200 andrew                   5627 ECB             : 
 2200 andrew                   5628 GIC          57 :     if (_state->strval->data[_state->strval->len - 1] != '{')
 2200 andrew                   5629 CBC          33 :         appendStringInfoCharMacro(_state->strval, ',');
                               5630                 : 
 2200 andrew                   5631 ECB             :     /*
                               5632                 :      * Unfortunately we don't have the quoted and escaped string any more, so
                               5633                 :      * we have to re-escape it.
                               5634                 :      */
 2200 andrew                   5635 GIC          57 :     escape_json(_state->strval, fname);
 2200 andrew                   5636 CBC          57 :     appendStringInfoCharMacro(_state->strval, ':');
                               5637                 : 
  119 tgl                      5638 GNC          57 :     return JSON_SUCCESS;
                               5639                 : }
 2200 andrew                   5640 ECB             : 
                               5641                 : static JsonParseErrorType
 2200 andrew                   5642 CBC          24 : transform_string_values_array_element_start(void *state, bool isnull)
 2200 andrew                   5643 ECB             : {
 2200 andrew                   5644 CBC          24 :     TransformJsonStringValuesState *_state = (TransformJsonStringValuesState *) state;
 2200 andrew                   5645 ECB             : 
 2200 andrew                   5646 GIC          24 :     if (_state->strval->data[_state->strval->len - 1] != '[')
                               5647              12 :         appendStringInfoCharMacro(_state->strval, ',');
                               5648                 : 
  119 tgl                      5649 GNC          24 :     return JSON_SUCCESS;
                               5650                 : }
 2200 andrew                   5651 ECB             : 
                               5652                 : static JsonParseErrorType
 2200 andrew                   5653 GIC          60 : transform_string_values_scalar(void *state, char *token, JsonTokenType tokentype)
                               5654                 : {
                               5655              60 :     TransformJsonStringValuesState *_state = (TransformJsonStringValuesState *) state;
                               5656                 : 
 2200 andrew                   5657 CBC          60 :     if (tokentype == JSON_TOKEN_STRING)
 2200 andrew                   5658 ECB             :     {
 2040 peter_e                  5659 GIC          57 :         text       *out = _state->action(_state->action_state, token, strlen(token));
 2153 bruce                    5660 ECB             : 
 2200 andrew                   5661 GIC          57 :         escape_json(_state->strval, text_to_cstring(out));
                               5662                 :     }
                               5663                 :     else
                               5664               3 :         appendStringInfoString(_state->strval, token);
                               5665                 : 
  119 tgl                      5666 GNC          60 :     return JSON_SUCCESS;
                               5667                 : }
                               5668                 : 
                               5669                 : JsonTokenType
    9 alvherre                 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)
    9 alvherre                 5684 UNC           0 :         json_errsave_error(result, lex, NULL);
                               5685                 : 
    9 alvherre                 5686 GNC           9 :     return JSON_TOKEN_INVALID;  /* invalid json */
                               5687                 : }
        

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