LCOV - differential code coverage report
Current view: top level - src/backend/utils/adt - jsonb.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: 89.1 % 902 804 19 25 42 12 24 405 81 294 56 450 6 35
Current Date: 2023-04-08 15:15:32 Functions: 94.6 % 56 53 1 2 38 15 2 51 1 2
Baseline: 15
Baseline Date: 2023-04-08 15:09:40
Legend: Lines: hit not hit

           TLA  Line data    Source code
       1                 : /*-------------------------------------------------------------------------
       2                 :  *
       3                 :  * jsonb.c
       4                 :  *      I/O routines for jsonb type
       5                 :  *
       6                 :  * Copyright (c) 2014-2023, PostgreSQL Global Development Group
       7                 :  *
       8                 :  * IDENTIFICATION
       9                 :  *    src/backend/utils/adt/jsonb.c
      10                 :  *
      11                 :  *-------------------------------------------------------------------------
      12                 :  */
      13                 : #include "postgres.h"
      14                 : 
      15                 : #include "access/htup_details.h"
      16                 : #include "access/transam.h"
      17                 : #include "catalog/pg_proc.h"
      18                 : #include "catalog/pg_type.h"
      19                 : #include "funcapi.h"
      20                 : #include "libpq/pqformat.h"
      21                 : #include "miscadmin.h"
      22                 : #include "parser/parse_coerce.h"
      23                 : #include "utils/builtins.h"
      24                 : #include "utils/date.h"
      25                 : #include "utils/datetime.h"
      26                 : #include "utils/json.h"
      27                 : #include "utils/jsonb.h"
      28                 : #include "utils/jsonfuncs.h"
      29                 : #include "utils/lsyscache.h"
      30                 : #include "utils/syscache.h"
      31                 : #include "utils/typcache.h"
      32                 : 
      33                 : typedef struct JsonbInState
      34                 : {
      35                 :     JsonbParseState *parseState;
      36                 :     JsonbValue *res;
      37                 :     Node       *escontext;
      38                 : } JsonbInState;
      39                 : 
      40                 : /* unlike with json categories, we need to treat json and jsonb differently */
      41                 : typedef enum                    /* type categories for datum_to_jsonb */
      42                 : {
      43                 :     JSONBTYPE_NULL,             /* null, so we didn't bother to identify */
      44                 :     JSONBTYPE_BOOL,             /* boolean (built-in types only) */
      45                 :     JSONBTYPE_NUMERIC,          /* numeric (ditto) */
      46                 :     JSONBTYPE_DATE,             /* we use special formatting for datetimes */
      47                 :     JSONBTYPE_TIMESTAMP,        /* we use special formatting for timestamp */
      48                 :     JSONBTYPE_TIMESTAMPTZ,      /* ... and timestamptz */
      49                 :     JSONBTYPE_JSON,             /* JSON */
      50                 :     JSONBTYPE_JSONB,            /* JSONB */
      51                 :     JSONBTYPE_ARRAY,            /* array */
      52                 :     JSONBTYPE_COMPOSITE,        /* composite */
      53                 :     JSONBTYPE_JSONCAST,         /* something with an explicit cast to JSON */
      54                 :     JSONBTYPE_OTHER             /* all else */
      55                 : } JsonbTypeCategory;
      56                 : 
      57                 : typedef struct JsonbAggState
      58                 : {
      59                 :     JsonbInState *res;
      60                 :     JsonbTypeCategory key_category;
      61                 :     Oid         key_output_func;
      62                 :     JsonbTypeCategory val_category;
      63                 :     Oid         val_output_func;
      64                 : } JsonbAggState;
      65                 : 
      66                 : static inline Datum jsonb_from_cstring(char *json, int len, Node *escontext);
      67                 : static bool checkStringLen(size_t len, Node *escontext);
      68                 : static JsonParseErrorType jsonb_in_object_start(void *pstate);
      69                 : static JsonParseErrorType jsonb_in_object_end(void *pstate);
      70                 : static JsonParseErrorType jsonb_in_array_start(void *pstate);
      71                 : static JsonParseErrorType jsonb_in_array_end(void *pstate);
      72                 : static JsonParseErrorType jsonb_in_object_field_start(void *pstate, char *fname, bool isnull);
      73                 : static void jsonb_put_escaped_value(StringInfo out, JsonbValue *scalarVal);
      74                 : static JsonParseErrorType jsonb_in_scalar(void *pstate, char *token, JsonTokenType tokentype);
      75                 : static void jsonb_categorize_type(Oid typoid,
      76                 :                                   JsonbTypeCategory *tcategory,
      77                 :                                   Oid *outfuncoid);
      78                 : static void composite_to_jsonb(Datum composite, JsonbInState *result);
      79                 : static void array_dim_to_jsonb(JsonbInState *result, int dim, int ndims, int *dims,
      80                 :                                Datum *vals, bool *nulls, int *valcount,
      81                 :                                JsonbTypeCategory tcategory, Oid outfuncoid);
      82                 : static void array_to_jsonb_internal(Datum array, JsonbInState *result);
      83                 : static void jsonb_categorize_type(Oid typoid,
      84                 :                                   JsonbTypeCategory *tcategory,
      85                 :                                   Oid *outfuncoid);
      86                 : static void datum_to_jsonb(Datum val, bool is_null, JsonbInState *result,
      87                 :                            JsonbTypeCategory tcategory, Oid outfuncoid,
      88                 :                            bool key_scalar);
      89                 : static void add_jsonb(Datum val, bool is_null, JsonbInState *result,
      90                 :                       Oid val_type, bool key_scalar);
      91                 : static JsonbParseState *clone_parse_state(JsonbParseState *state);
      92                 : static char *JsonbToCStringWorker(StringInfo out, JsonbContainer *in, int estimated_len, bool indent);
      93                 : static void add_indent(StringInfo out, bool indent, int level);
      94                 : 
      95                 : /*
      96                 :  * jsonb type input function
      97                 :  */
      98                 : Datum
      99 GIC       10821 : jsonb_in(PG_FUNCTION_ARGS)
     100                 : {
     101 CBC       10821 :     char       *json = PG_GETARG_CSTRING(0);
     102                 : 
     103 GNC       10821 :     return jsonb_from_cstring(json, strlen(json), fcinfo->context);
     104                 : }
     105 ECB             : 
     106                 : /*
     107                 :  * jsonb type recv function
     108                 :  *
     109                 :  * The type is sent as text in binary mode, so this is almost the same
     110                 :  * as the input function, but it's prefixed with a version number so we
     111                 :  * can change the binary format sent in future if necessary. For now,
     112                 :  * only version 1 is supported.
     113                 :  */
     114                 : Datum
     115 UIC           0 : jsonb_recv(PG_FUNCTION_ARGS)
     116                 : {
     117 UBC           0 :     StringInfo  buf = (StringInfo) PG_GETARG_POINTER(0);
     118 UIC           0 :     int         version = pq_getmsgint(buf, 1);
     119 EUB             :     char       *str;
     120                 :     int         nbytes;
     121                 : 
     122 UIC           0 :     if (version == 1)
     123               0 :         str = pq_getmsgtext(buf, buf->len - buf->cursor, &nbytes);
     124 EUB             :     else
     125 UBC           0 :         elog(ERROR, "unsupported jsonb version number %d", version);
     126                 : 
     127 UNC           0 :     return jsonb_from_cstring(str, nbytes, NULL);
     128                 : }
     129 EUB             : 
     130                 : /*
     131                 :  * jsonb type output function
     132                 :  */
     133                 : Datum
     134 GIC        9383 : jsonb_out(PG_FUNCTION_ARGS)
     135                 : {
     136 CBC        9383 :     Jsonb      *jb = PG_GETARG_JSONB_P(0);
     137                 :     char       *out;
     138 ECB             : 
     139 GIC        9383 :     out = JsonbToCString(NULL, &jb->root, VARSIZE(jb));
     140                 : 
     141 CBC        9383 :     PG_RETURN_CSTRING(out);
     142                 : }
     143 ECB             : 
     144                 : /*
     145                 :  * jsonb type send function
     146                 :  *
     147                 :  * Just send jsonb as a version number, then a string of text
     148                 :  */
     149                 : Datum
     150 UIC           0 : jsonb_send(PG_FUNCTION_ARGS)
     151                 : {
     152 UBC           0 :     Jsonb      *jb = PG_GETARG_JSONB_P(0);
     153                 :     StringInfoData buf;
     154               0 :     StringInfo  jtext = makeStringInfo();
     155 UIC           0 :     int         version = 1;
     156 EUB             : 
     157 UBC           0 :     (void) JsonbToCString(jtext, &jb->root, VARSIZE(jb));
     158                 : 
     159               0 :     pq_begintypsend(&buf);
     160 UIC           0 :     pq_sendint8(&buf, version);
     161 UBC           0 :     pq_sendtext(&buf, jtext->data, jtext->len);
     162               0 :     pfree(jtext->data);
     163               0 :     pfree(jtext);
     164 EUB             : 
     165 UBC           0 :     PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
     166                 : }
     167 EUB             : 
     168                 : /*
     169                 :  * Get the type name of a jsonb container.
     170                 :  */
     171                 : static const char *
     172 GIC         153 : JsonbContainerTypeName(JsonbContainer *jbc)
     173                 : {
     174 ECB             :     JsonbValue  scalar;
     175                 : 
     176 GIC         153 :     if (JsonbExtractScalar(jbc, &scalar))
     177              33 :         return JsonbTypeName(&scalar);
     178 CBC         120 :     else if (JsonContainerIsArray(jbc))
     179              51 :         return "array";
     180              69 :     else if (JsonContainerIsObject(jbc))
     181              69 :         return "object";
     182 ECB             :     else
     183                 :     {
     184 UIC           0 :         elog(ERROR, "invalid jsonb container type: 0x%08x", jbc->header);
     185                 :         return "unknown";
     186 EUB             :     }
     187                 : }
     188                 : 
     189                 : /*
     190                 :  * Get the type name of a jsonb value.
     191                 :  */
     192                 : const char *
     193 GNC         138 : JsonbTypeName(JsonbValue *val)
     194                 : {
     195             138 :     switch (val->type)
     196                 :     {
     197 CBC          12 :         case jbvBinary:
     198 GNC          12 :             return JsonbContainerTypeName(val->val.binary.data);
     199 LBC           0 :         case jbvObject:
     200               0 :             return "object";
     201 UBC           0 :         case jbvArray:
     202               0 :             return "array";
     203 GBC          45 :         case jbvNumeric:
     204              45 :             return "number";
     205 CBC          15 :         case jbvString:
     206              15 :             return "string";
     207              18 :         case jbvBool:
     208              18 :             return "boolean";
     209              12 :         case jbvNull:
     210              12 :             return "null";
     211              36 :         case jbvDatetime:
     212 GNC          36 :             switch (val->val.datetime.typid)
     213 ECB             :             {
     214 CBC           6 :                 case DATEOID:
     215 GIC           6 :                     return "date";
     216 CBC           6 :                 case TIMEOID:
     217               6 :                     return "time without time zone";
     218               9 :                 case TIMETZOID:
     219               9 :                     return "time with time zone";
     220               6 :                 case TIMESTAMPOID:
     221               6 :                     return "timestamp without time zone";
     222               9 :                 case TIMESTAMPTZOID:
     223               9 :                     return "timestamp with time zone";
     224 LBC           0 :                 default:
     225               0 :                     elog(ERROR, "unrecognized jsonb value datetime type: %d",
     226                 :                          val->val.datetime.typid);
     227 EUB             :             }
     228                 :             return "unknown";
     229 UIC           0 :         default:
     230 UNC           0 :             elog(ERROR, "unrecognized jsonb value type: %d", val->type);
     231 EUB             :             return "unknown";
     232                 :     }
     233                 : }
     234                 : 
     235                 : /*
     236                 :  * SQL function jsonb_typeof(jsonb) -> text
     237                 :  *
     238                 :  * This function is here because the analog json function is in json.c, since
     239                 :  * it uses the json parser internals not exposed elsewhere.
     240                 :  */
     241                 : Datum
     242 GIC         141 : jsonb_typeof(PG_FUNCTION_ARGS)
     243                 : {
     244 CBC         141 :     Jsonb      *in = PG_GETARG_JSONB_P(0);
     245 GIC         141 :     const char *result = JsonbContainerTypeName(&in->root);
     246 ECB             : 
     247 CBC         141 :     PG_RETURN_TEXT_P(cstring_to_text(result));
     248                 : }
     249 ECB             : 
     250                 : /*
     251                 :  * jsonb_from_cstring
     252                 :  *
     253                 :  * Turns json string into a jsonb Datum.
     254                 :  *
     255                 :  * Uses the json parser (with hooks) to construct a jsonb.
     256                 :  *
     257                 :  * If escontext points to an ErrorSaveContext, errors are reported there
     258                 :  * instead of being thrown.
     259                 :  */
     260                 : static inline Datum
     261 GNC       10821 : jsonb_from_cstring(char *json, int len, Node *escontext)
     262                 : {
     263                 :     JsonLexContext *lex;
     264                 :     JsonbInState state;
     265                 :     JsonSemAction sem;
     266 ECB             : 
     267 GIC       10821 :     memset(&state, 0, sizeof(state));
     268           10821 :     memset(&sem, 0, sizeof(sem));
     269           10821 :     lex = makeJsonLexContextCstringLen(json, len, GetDatabaseEncoding(), true);
     270                 : 
     271 GNC       10821 :     state.escontext = escontext;
     272 GIC       10821 :     sem.semstate = (void *) &state;
     273 ECB             : 
     274 CBC       10821 :     sem.object_start = jsonb_in_object_start;
     275           10821 :     sem.array_start = jsonb_in_array_start;
     276 GIC       10821 :     sem.object_end = jsonb_in_object_end;
     277 CBC       10821 :     sem.array_end = jsonb_in_array_end;
     278           10821 :     sem.scalar = jsonb_in_scalar;
     279 GIC       10821 :     sem.object_field_start = jsonb_in_object_field_start;
     280 ECB             : 
     281 GNC       10821 :     if (!pg_parse_json_or_errsave(lex, &sem, escontext))
     282               9 :         return (Datum) 0;
     283 ECB             : 
     284                 :     /* after parsing, the item member has the composed jsonb structure */
     285 CBC       10695 :     PG_RETURN_POINTER(JsonbValueToJsonb(state.res));
     286 ECB             : }
     287                 : 
     288                 : static bool
     289 GNC       35123 : checkStringLen(size_t len, Node *escontext)
     290                 : {
     291 GIC       35123 :     if (len > JENTRY_OFFLENMASK)
     292 UNC           0 :         ereturn(escontext, false,
     293                 :                 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
     294                 :                  errmsg("string too long to represent as jsonb string"),
     295                 :                  errdetail("Due to an implementation restriction, jsonb strings cannot exceed %d bytes.",
     296 ECB             :                            JENTRY_OFFLENMASK)));
     297                 : 
     298 GNC       35123 :     return true;
     299 EUB             : }
     300                 : 
     301                 : static JsonParseErrorType
     302 GIC       12330 : jsonb_in_object_start(void *pstate)
     303                 : {
     304           12330 :     JsonbInState *_state = (JsonbInState *) pstate;
     305 ECB             : 
     306 GIC       12330 :     _state->res = pushJsonbValue(&_state->parseState, WJB_BEGIN_OBJECT, NULL);
     307                 : 
     308 GNC       12330 :     return JSON_SUCCESS;
     309                 : }
     310                 : 
     311                 : static JsonParseErrorType
     312 GIC       10319 : jsonb_in_object_end(void *pstate)
     313 ECB             : {
     314 GIC       10319 :     JsonbInState *_state = (JsonbInState *) pstate;
     315 ECB             : 
     316 GIC       10319 :     _state->res = pushJsonbValue(&_state->parseState, WJB_END_OBJECT, NULL);
     317                 : 
     318 GNC       10319 :     return JSON_SUCCESS;
     319 ECB             : }
     320                 : 
     321                 : static JsonParseErrorType
     322 GIC        5185 : jsonb_in_array_start(void *pstate)
     323 ECB             : {
     324 GIC        5185 :     JsonbInState *_state = (JsonbInState *) pstate;
     325 ECB             : 
     326 GIC        5185 :     _state->res = pushJsonbValue(&_state->parseState, WJB_BEGIN_ARRAY, NULL);
     327                 : 
     328 GNC        5185 :     return JSON_SUCCESS;
     329 ECB             : }
     330                 : 
     331                 : static JsonParseErrorType
     332 GIC        2979 : jsonb_in_array_end(void *pstate)
     333                 : {
     334            2979 :     JsonbInState *_state = (JsonbInState *) pstate;
     335 ECB             : 
     336 GIC        2979 :     _state->res = pushJsonbValue(&_state->parseState, WJB_END_ARRAY, NULL);
     337                 : 
     338 GNC        2979 :     return JSON_SUCCESS;
     339 ECB             : }
     340                 : 
     341                 : static JsonParseErrorType
     342 GIC       23806 : jsonb_in_object_field_start(void *pstate, char *fname, bool isnull)
     343 ECB             : {
     344 GIC       23806 :     JsonbInState *_state = (JsonbInState *) pstate;
     345                 :     JsonbValue  v;
     346                 : 
     347 CBC       23806 :     Assert(fname != NULL);
     348 GIC       23806 :     v.type = jbvString;
     349 GNC       23806 :     v.val.string.len = strlen(fname);
     350           23806 :     if (!checkStringLen(v.val.string.len, _state->escontext))
     351 UNC           0 :         return JSON_SEM_ACTION_FAILED;
     352 GIC       23806 :     v.val.string.val = fname;
     353 ECB             : 
     354 GIC       23806 :     _state->res = pushJsonbValue(&_state->parseState, WJB_KEY, &v);
     355                 : 
     356 GNC       23806 :     return JSON_SUCCESS;
     357 ECB             : }
     358                 : 
     359                 : static void
     360 GIC       50532 : jsonb_put_escaped_value(StringInfo out, JsonbValue *scalarVal)
     361 ECB             : {
     362 GIC       50532 :     switch (scalarVal->type)
     363 ECB             :     {
     364 GIC         464 :         case jbvNull:
     365             464 :             appendBinaryStringInfo(out, "null", 4);
     366 CBC         464 :             break;
     367           34323 :         case jbvString:
     368           34323 :             escape_json(out, pnstrdup(scalarVal->val.string.val, scalarVal->val.string.len));
     369           34323 :             break;
     370 GBC        9645 :         case jbvNumeric:
     371 CBC        9645 :             appendStringInfoString(out,
     372 GIC        9645 :                                    DatumGetCString(DirectFunctionCall1(numeric_out,
     373 ECB             :                                                                        PointerGetDatum(scalarVal->val.numeric))));
     374 GIC        9645 :             break;
     375 CBC        6100 :         case jbvBool:
     376 GIC        6100 :             if (scalarVal->val.boolean)
     377            2876 :                 appendBinaryStringInfo(out, "true", 4);
     378                 :             else
     379 CBC        3224 :                 appendBinaryStringInfo(out, "false", 5);
     380 GIC        6100 :             break;
     381 LBC           0 :         default:
     382 UIC           0 :             elog(ERROR, "unknown jsonb scalar type");
     383 ECB             :     }
     384 CBC       50532 : }
     385 ECB             : 
     386                 : /*
     387                 :  * For jsonb we always want the de-escaped value - that's what's in token
     388                 :  */
     389                 : static JsonParseErrorType
     390 CBC       26289 : jsonb_in_scalar(void *pstate, char *token, JsonTokenType tokentype)
     391 ECB             : {
     392 GIC       26289 :     JsonbInState *_state = (JsonbInState *) pstate;
     393 ECB             :     JsonbValue  v;
     394                 :     Datum       numd;
     395                 : 
     396 CBC       26289 :     switch (tokentype)
     397                 :     {
     398 ECB             : 
     399 CBC       10822 :         case JSON_TOKEN_STRING:
     400 GBC       10822 :             Assert(token != NULL);
     401           10822 :             v.type = jbvString;
     402 GNC       10822 :             v.val.string.len = strlen(token);
     403           10822 :             if (!checkStringLen(v.val.string.len, _state->escontext))
     404 UNC           0 :                 return JSON_SEM_ACTION_FAILED;
     405 CBC       10822 :             v.val.string.val = token;
     406 GIC       10822 :             break;
     407           11311 :         case JSON_TOKEN_NUMBER:
     408                 : 
     409                 :             /*
     410                 :              * No need to check size of numeric values, because maximum
     411 ECB             :              * numeric size is well below the JsonbValue restriction
     412                 :              */
     413 CBC       11311 :             Assert(token != NULL);
     414 GIC       11311 :             v.type = jbvNumeric;
     415 GNC       11311 :             if (!DirectInputFunctionCallSafe(numeric_in, token,
     416                 :                                              InvalidOid, -1,
     417           11311 :                                              _state->escontext,
     418                 :                                              &numd))
     419               3 :                 return JSON_SEM_ACTION_FAILED;
     420 GIC       11308 :             v.val.numeric = DatumGetNumeric(numd);
     421 CBC       11308 :             break;
     422            1630 :         case JSON_TOKEN_TRUE:
     423            1630 :             v.type = jbvBool;
     424            1630 :             v.val.boolean = true;
     425            1630 :             break;
     426 GBC        1616 :         case JSON_TOKEN_FALSE:
     427 CBC        1616 :             v.type = jbvBool;
     428            1616 :             v.val.boolean = false;
     429            1616 :             break;
     430 GIC         910 :         case JSON_TOKEN_NULL:
     431             910 :             v.type = jbvNull;
     432             910 :             break;
     433 UIC           0 :         default:
     434                 :             /* should not be possible */
     435 LBC           0 :             elog(ERROR, "invalid json token type");
     436 ECB             :             break;
     437                 :     }
     438                 : 
     439 CBC       26286 :     if (_state->parseState == NULL)
     440                 :     {
     441 ECB             :         /* single scalar */
     442                 :         JsonbValue  va;
     443                 : 
     444 CBC        1139 :         va.type = jbvArray;
     445            1139 :         va.val.array.rawScalar = true;
     446            1139 :         va.val.array.nElems = 1;
     447 ECB             : 
     448 CBC        1139 :         _state->res = pushJsonbValue(&_state->parseState, WJB_BEGIN_ARRAY, &va);
     449            1139 :         _state->res = pushJsonbValue(&_state->parseState, WJB_ELEM, &v);
     450            1139 :         _state->res = pushJsonbValue(&_state->parseState, WJB_END_ARRAY, NULL);
     451 ECB             :     }
     452                 :     else
     453                 :     {
     454 CBC       25147 :         JsonbValue *o = &_state->parseState->contVal;
     455 EUB             : 
     456 GIC       25147 :         switch (o->type)
     457 EUB             :         {
     458 GIC        5317 :             case jbvArray:
     459            5317 :                 _state->res = pushJsonbValue(&_state->parseState, WJB_ELEM, &v);
     460            5317 :                 break;
     461 CBC       19830 :             case jbvObject:
     462 GIC       19830 :                 _state->res = pushJsonbValue(&_state->parseState, WJB_VALUE, &v);
     463           19830 :                 break;
     464 UIC           0 :             default:
     465               0 :                 elog(ERROR, "unexpected parent of nested structure");
     466 ECB             :         }
     467                 :     }
     468                 : 
     469 GNC       26286 :     return JSON_SUCCESS;
     470 ECB             : }
     471                 : 
     472                 : /*
     473                 :  * JsonbToCString
     474                 :  *     Converts jsonb value to a C-string.
     475                 :  *
     476                 :  * If 'out' argument is non-null, the resulting C-string is stored inside the
     477                 :  * StringBuffer.  The resulting string is always returned.
     478                 :  *
     479                 :  * A typical case for passing the StringInfo in rather than NULL is where the
     480                 :  * caller wants access to the len attribute without having to call strlen, e.g.
     481                 :  * if they are converting it to a text* object.
     482                 :  */
     483                 : char *
     484 CBC        9980 : JsonbToCString(StringInfo out, JsonbContainer *in, int estimated_len)
     485 ECB             : {
     486 CBC        9980 :     return JsonbToCStringWorker(out, in, estimated_len, false);
     487 ECB             : }
     488 EUB             : 
     489                 : /*
     490                 :  * same thing but with indentation turned on
     491                 :  */
     492                 : char *
     493 CBC          18 : JsonbToCStringIndent(StringInfo out, JsonbContainer *in, int estimated_len)
     494                 : {
     495 GIC          18 :     return JsonbToCStringWorker(out, in, estimated_len, true);
     496                 : }
     497                 : 
     498                 : /*
     499                 :  * common worker for above two functions
     500                 :  */
     501                 : static char *
     502            9998 : JsonbToCStringWorker(StringInfo out, JsonbContainer *in, int estimated_len, bool indent)
     503                 : {
     504            9998 :     bool        first = true;
     505                 :     JsonbIterator *it;
     506                 :     JsonbValue  v;
     507            9998 :     JsonbIteratorToken type = WJB_DONE;
     508 CBC        9998 :     int         level = 0;
     509 GIC        9998 :     bool        redo_switch = false;
     510 ECB             : 
     511                 :     /* If we are indenting, don't add a space after a comma */
     512 GIC        9998 :     int         ispaces = indent ? 1 : 2;
     513                 : 
     514                 :     /*
     515                 :      * Don't indent the very first item. This gets set to the indent flag at
     516                 :      * the bottom of the loop.
     517 ECB             :      */
     518 GIC        9998 :     bool        use_indent = false;
     519 CBC        9998 :     bool        raw_scalar = false;
     520 GIC        9998 :     bool        last_was_key = false;
     521                 : 
     522            9998 :     if (out == NULL)
     523            9917 :         out = makeStringInfo();
     524                 : 
     525            9998 :     enlargeStringInfo(out, (estimated_len >= 0) ? estimated_len : 64);
     526 ECB             : 
     527 GIC        9998 :     it = JsonbIteratorInit(in);
     528 ECB             : 
     529 GIC      122236 :     while (redo_switch ||
     530           60743 :            ((type = JsonbIteratorNext(&it, &v, false)) != WJB_DONE))
     531 ECB             :     {
     532 CBC       51495 :         redo_switch = false;
     533           51495 :         switch (type)
     534                 :         {
     535 GIC        5138 :             case WJB_BEGIN_ARRAY:
     536 CBC        5138 :                 if (!first)
     537 GIC          54 :                     appendBinaryStringInfo(out, ", ", ispaces);
     538                 : 
     539            5138 :                 if (!v.val.array.rawScalar)
     540                 :                 {
     541            1260 :                     add_indent(out, use_indent && !last_was_key, level);
     542 CBC        1260 :                     appendStringInfoCharMacro(out, '[');
     543 ECB             :                 }
     544                 :                 else
     545 GIC        3878 :                     raw_scalar = true;
     546 ECB             : 
     547 CBC        5138 :                 first = true;
     548 GIC        5138 :                 level++;
     549 CBC        5138 :                 break;
     550 GIC        6276 :             case WJB_BEGIN_OBJECT:
     551 CBC        6276 :                 if (!first)
     552 GIC         167 :                     appendBinaryStringInfo(out, ", ", ispaces);
     553 ECB             : 
     554 CBC        6276 :                 add_indent(out, use_indent && !last_was_key, level);
     555 GIC        6276 :                 appendStringInfoCharMacro(out, '{');
     556 ECB             : 
     557 CBC        6276 :                 first = true;
     558 GIC        6276 :                 level++;
     559 CBC        6276 :                 break;
     560           22615 :             case WJB_KEY:
     561           22615 :                 if (!first)
     562 GIC       16882 :                     appendBinaryStringInfo(out, ", ", ispaces);
     563 CBC       22615 :                 first = true;
     564                 : 
     565           22615 :                 add_indent(out, use_indent, level);
     566 ECB             : 
     567                 :                 /* json rules guarantee this is a string */
     568 GIC       22615 :                 jsonb_put_escaped_value(out, &v);
     569 CBC       22615 :                 appendBinaryStringInfo(out, ": ", 2);
     570                 : 
     571           22615 :                 type = JsonbIteratorNext(&it, &v, false);
     572           22615 :                 if (type == WJB_VALUE)
     573 ECB             :                 {
     574 CBC       21865 :                     first = false;
     575           21865 :                     jsonb_put_escaped_value(out, &v);
     576 ECB             :                 }
     577                 :                 else
     578                 :                 {
     579 CBC         750 :                     Assert(type == WJB_BEGIN_OBJECT || type == WJB_BEGIN_ARRAY);
     580                 : 
     581 ECB             :                     /*
     582                 :                      * We need to rerun the current switch() since we need to
     583                 :                      * output the object which we just got from the iterator
     584                 :                      * before calling the iterator again.
     585                 :                      */
     586 CBC         750 :                     redo_switch = true;
     587 ECB             :                 }
     588 GIC       22615 :                 break;
     589 CBC        6052 :             case WJB_ELEM:
     590 GIC        6052 :                 if (!first)
     591            1411 :                     appendBinaryStringInfo(out, ", ", ispaces);
     592 CBC        6052 :                 first = false;
     593 ECB             : 
     594 GIC        6052 :                 if (!raw_scalar)
     595 CBC        2174 :                     add_indent(out, use_indent, level);
     596            6052 :                 jsonb_put_escaped_value(out, &v);
     597 GIC        6052 :                 break;
     598 CBC        5138 :             case WJB_END_ARRAY:
     599            5138 :                 level--;
     600 GIC        5138 :                 if (!raw_scalar)
     601                 :                 {
     602            1260 :                     add_indent(out, use_indent, level);
     603 CBC        1260 :                     appendStringInfoCharMacro(out, ']');
     604                 :                 }
     605 GIC        5138 :                 first = false;
     606            5138 :                 break;
     607            6276 :             case WJB_END_OBJECT:
     608            6276 :                 level--;
     609            6276 :                 add_indent(out, use_indent, level);
     610 CBC        6276 :                 appendStringInfoCharMacro(out, '}');
     611 GIC        6276 :                 first = false;
     612 CBC        6276 :                 break;
     613 LBC           0 :             default:
     614               0 :                 elog(ERROR, "unknown jsonb iterator token type");
     615 ECB             :         }
     616 CBC       51495 :         use_indent = indent;
     617 GIC       51495 :         last_was_key = redo_switch;
     618 ECB             :     }
     619                 : 
     620 CBC        9998 :     Assert(level == 0);
     621 ECB             : 
     622 CBC        9998 :     return out->data;
     623 ECB             : }
     624                 : 
     625                 : static void
     626 CBC       39861 : add_indent(StringInfo out, bool indent, int level)
     627 ECB             : {
     628 GIC       39861 :     if (indent)
     629 ECB             :     {
     630 CBC         783 :         appendStringInfoCharMacro(out, '\n');
     631 GNC         783 :         appendStringInfoSpaces(out, level * 4);
     632 ECB             :     }
     633 CBC       39861 : }
     634 EUB             : 
     635                 : 
     636                 : /*
     637 ECB             :  * Determine how we want to render values of a given type in datum_to_jsonb.
     638                 :  *
     639                 :  * Given the datatype OID, return its JsonbTypeCategory, as well as the type's
     640                 :  * output function OID.  If the returned category is JSONBTYPE_JSONCAST,
     641                 :  * we return the OID of the relevant cast function instead.
     642                 :  */
     643                 : static void
     644 GIC        1148 : jsonb_categorize_type(Oid typoid,
     645                 :                       JsonbTypeCategory *tcategory,
     646                 :                       Oid *outfuncoid)
     647 ECB             : {
     648                 :     bool        typisvarlena;
     649                 : 
     650                 :     /* Look through any domain */
     651 CBC        1148 :     typoid = getBaseType(typoid);
     652 ECB             : 
     653 GIC        1148 :     *outfuncoid = InvalidOid;
     654 ECB             : 
     655                 :     /*
     656                 :      * We need to get the output function for everything except date and
     657                 :      * timestamp types, booleans, array and composite types, json and jsonb,
     658                 :      * and non-builtin types where there's a cast to json. In this last case
     659                 :      * we return the oid of the cast function instead.
     660                 :      */
     661                 : 
     662 GIC        1148 :     switch (typoid)
     663                 :     {
     664              24 :         case BOOLOID:
     665 CBC          24 :             *tcategory = JSONBTYPE_BOOL;
     666 GIC          24 :             break;
     667                 : 
     668             317 :         case INT2OID:
     669                 :         case INT4OID:
     670                 :         case INT8OID:
     671                 :         case FLOAT4OID:
     672 ECB             :         case FLOAT8OID:
     673                 :         case NUMERICOID:
     674 CBC         317 :             getTypeOutputInfo(typoid, outfuncoid, &typisvarlena);
     675 GIC         317 :             *tcategory = JSONBTYPE_NUMERIC;
     676             317 :             break;
     677                 : 
     678               9 :         case DATEOID:
     679               9 :             *tcategory = JSONBTYPE_DATE;
     680               9 :             break;
     681                 : 
     682               9 :         case TIMESTAMPOID:
     683 CBC           9 :             *tcategory = JSONBTYPE_TIMESTAMP;
     684 GIC           9 :             break;
     685 ECB             : 
     686 CBC          12 :         case TIMESTAMPTZOID:
     687              12 :             *tcategory = JSONBTYPE_TIMESTAMPTZ;
     688 GIC          12 :             break;
     689 ECB             : 
     690 GIC         183 :         case JSONBOID:
     691             183 :             *tcategory = JSONBTYPE_JSONB;
     692             183 :             break;
     693                 : 
     694              21 :         case JSONOID:
     695 CBC          21 :             *tcategory = JSONBTYPE_JSON;
     696              21 :             break;
     697 ECB             : 
     698 GIC         573 :         default:
     699 ECB             :             /* Check for arrays and composites */
     700 CBC         573 :             if (OidIsValid(get_element_type(typoid)) || typoid == ANYARRAYOID
     701             516 :                 || typoid == ANYCOMPATIBLEARRAYOID || typoid == RECORDARRAYOID)
     702 GIC          57 :                 *tcategory = JSONBTYPE_ARRAY;
     703 CBC         516 :             else if (type_is_rowtype(typoid))   /* includes RECORDOID */
     704              36 :                 *tcategory = JSONBTYPE_COMPOSITE;
     705 ECB             :             else
     706                 :             {
     707                 :                 /* It's probably the general case ... */
     708 CBC         480 :                 *tcategory = JSONBTYPE_OTHER;
     709 ECB             : 
     710                 :                 /*
     711                 :                  * but first let's look for a cast to json (note: not to
     712                 :                  * jsonb) if it's not built-in.
     713                 :                  */
     714 GIC         480 :                 if (typoid >= FirstNormalObjectId)
     715 ECB             :                 {
     716                 :                     Oid         castfunc;
     717                 :                     CoercionPathType ctype;
     718                 : 
     719 LBC           0 :                     ctype = find_coercion_pathway(JSONOID, typoid,
     720                 :                                                   COERCION_EXPLICIT, &castfunc);
     721               0 :                     if (ctype == COERCION_PATH_FUNC && OidIsValid(castfunc))
     722 ECB             :                     {
     723 LBC           0 :                         *tcategory = JSONBTYPE_JSONCAST;
     724               0 :                         *outfuncoid = castfunc;
     725 ECB             :                     }
     726                 :                     else
     727                 :                     {
     728                 :                         /* not a cast type, so just get the usual output func */
     729 LBC           0 :                         getTypeOutputInfo(typoid, outfuncoid, &typisvarlena);
     730                 :                     }
     731                 :                 }
     732                 :                 else
     733                 :                 {
     734                 :                     /* any other builtin type */
     735 CBC         480 :                     getTypeOutputInfo(typoid, outfuncoid, &typisvarlena);
     736                 :                 }
     737 GIC         480 :                 break;
     738                 :             }
     739                 :     }
     740 GBC        1148 : }
     741                 : 
     742 EUB             : /*
     743                 :  * Turn a Datum into jsonb, adding it to the result JsonbInState.
     744                 :  *
     745                 :  * tcategory and outfuncoid are from a previous call to json_categorize_type,
     746                 :  * except that if is_null is true then they can be invalid.
     747                 :  *
     748                 :  * If key_scalar is true, the value is stored as a key, so insist
     749                 :  * it's of an acceptable type, and force it to be a jbvString.
     750                 :  *
     751                 :  * Note: currently, we assume that result->escontext is NULL and errors
     752                 :  * will be thrown.
     753                 :  */
     754                 : static void
     755 GIC        1499 : datum_to_jsonb(Datum val, bool is_null, JsonbInState *result,
     756                 :                JsonbTypeCategory tcategory, Oid outfuncoid,
     757                 :                bool key_scalar)
     758                 : {
     759 ECB             :     char       *outputstr;
     760                 :     bool        numeric_error;
     761                 :     JsonbValue  jb;
     762 GIC        1499 :     bool        scalar_jsonb = false;
     763                 : 
     764 CBC        1499 :     check_stack_depth();
     765                 : 
     766                 :     /* Convert val to a JsonbValue in jb (in most cases) */
     767 GIC        1499 :     if (is_null)
     768                 :     {
     769              96 :         Assert(!key_scalar);
     770              96 :         jb.type = jbvNull;
     771                 :     }
     772            1403 :     else if (key_scalar &&
     773             397 :              (tcategory == JSONBTYPE_ARRAY ||
     774             394 :               tcategory == JSONBTYPE_COMPOSITE ||
     775             391 :               tcategory == JSONBTYPE_JSON ||
     776             391 :               tcategory == JSONBTYPE_JSONB ||
     777                 :               tcategory == JSONBTYPE_JSONCAST))
     778                 :     {
     779 CBC          12 :         ereport(ERROR,
     780                 :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
     781                 :                  errmsg("key value must be scalar, not array, composite, or json")));
     782                 :     }
     783                 :     else
     784                 :     {
     785 GIC        1391 :         if (tcategory == JSONBTYPE_JSONCAST)
     786 LBC           0 :             val = OidFunctionCall1(outfuncoid, val);
     787                 : 
     788 CBC        1391 :         switch (tcategory)
     789                 :         {
     790 GIC          54 :             case JSONBTYPE_ARRAY:
     791 CBC          54 :                 array_to_jsonb_internal(val, result);
     792 GIC          54 :                 break;
     793 CBC          96 :             case JSONBTYPE_COMPOSITE:
     794              96 :                 composite_to_jsonb(val, result);
     795 GIC          96 :                 break;
     796 CBC          24 :             case JSONBTYPE_BOOL:
     797              24 :                 if (key_scalar)
     798 ECB             :                 {
     799 LBC           0 :                     outputstr = DatumGetBool(val) ? "true" : "false";
     800               0 :                     jb.type = jbvString;
     801 UIC           0 :                     jb.val.string.len = strlen(outputstr);
     802               0 :                     jb.val.string.val = outputstr;
     803 ECB             :                 }
     804                 :                 else
     805                 :                 {
     806 GIC          24 :                     jb.type = jbvBool;
     807              24 :                     jb.val.boolean = DatumGetBool(val);
     808                 :                 }
     809 CBC          24 :                 break;
     810 GBC         488 :             case JSONBTYPE_NUMERIC:
     811 GIC         488 :                 outputstr = OidOutputFunctionCall(outfuncoid, val);
     812 CBC         488 :                 if (key_scalar)
     813                 :                 {
     814 ECB             :                     /* always quote keys */
     815 CBC         106 :                     jb.type = jbvString;
     816             106 :                     jb.val.string.len = strlen(outputstr);
     817             106 :                     jb.val.string.val = outputstr;
     818 ECB             :                 }
     819                 :                 else
     820                 :                 {
     821                 :                     /*
     822                 :                      * Make it numeric if it's a valid JSON number, otherwise
     823 EUB             :                      * a string. Invalid numeric output will always have an
     824                 :                      * 'N' or 'n' in it (I think).
     825                 :                      */
     826 GBC         764 :                     numeric_error = (strchr(outputstr, 'N') != NULL ||
     827 GIC         382 :                                      strchr(outputstr, 'n') != NULL);
     828             382 :                     if (!numeric_error)
     829                 :                     {
     830 ECB             :                         Datum       numd;
     831                 : 
     832 GIC         382 :                         jb.type = jbvNumeric;
     833 CBC         382 :                         numd = DirectFunctionCall3(numeric_in,
     834 ECB             :                                                    CStringGetDatum(outputstr),
     835                 :                                                    ObjectIdGetDatum(InvalidOid),
     836                 :                                                    Int32GetDatum(-1));
     837 GIC         382 :                         jb.val.numeric = DatumGetNumeric(numd);
     838             382 :                         pfree(outputstr);
     839 ECB             :                     }
     840                 :                     else
     841                 :                     {
     842 UIC           0 :                         jb.type = jbvString;
     843               0 :                         jb.val.string.len = strlen(outputstr);
     844               0 :                         jb.val.string.val = outputstr;
     845                 :                     }
     846                 :                 }
     847 GIC         488 :                 break;
     848               9 :             case JSONBTYPE_DATE:
     849               9 :                 jb.type = jbvString;
     850 CBC           9 :                 jb.val.string.val = JsonEncodeDateTime(NULL, val,
     851 ECB             :                                                        DATEOID, NULL);
     852 CBC           9 :                 jb.val.string.len = strlen(jb.val.string.val);
     853 GIC           9 :                 break;
     854               9 :             case JSONBTYPE_TIMESTAMP:
     855               9 :                 jb.type = jbvString;
     856 CBC           9 :                 jb.val.string.val = JsonEncodeDateTime(NULL, val,
     857 ECB             :                                                        TIMESTAMPOID, NULL);
     858 GIC           9 :                 jb.val.string.len = strlen(jb.val.string.val);
     859               9 :                 break;
     860              12 :             case JSONBTYPE_TIMESTAMPTZ:
     861 CBC          12 :                 jb.type = jbvString;
     862              12 :                 jb.val.string.val = JsonEncodeDateTime(NULL, val,
     863                 :                                                        TIMESTAMPTZOID, NULL);
     864 GIC          12 :                 jb.val.string.len = strlen(jb.val.string.val);
     865              12 :                 break;
     866 GBC          18 :             case JSONBTYPE_JSONCAST:
     867 EUB             :             case JSONBTYPE_JSON:
     868                 :                 {
     869                 :                     /* parse the json right into the existing result object */
     870                 :                     JsonLexContext *lex;
     871 ECB             :                     JsonSemAction sem;
     872 CBC          18 :                     text       *json = DatumGetTextPP(val);
     873 ECB             : 
     874 CBC          18 :                     lex = makeJsonLexContext(json, true);
     875                 : 
     876              18 :                     memset(&sem, 0, sizeof(sem));
     877 ECB             : 
     878 CBC          18 :                     sem.semstate = (void *) result;
     879 ECB             : 
     880 CBC          18 :                     sem.object_start = jsonb_in_object_start;
     881 GIC          18 :                     sem.array_start = jsonb_in_array_start;
     882 CBC          18 :                     sem.object_end = jsonb_in_object_end;
     883              18 :                     sem.array_end = jsonb_in_array_end;
     884              18 :                     sem.scalar = jsonb_in_scalar;
     885              18 :                     sem.object_field_start = jsonb_in_object_field_start;
     886 ECB             : 
     887 GIC          18 :                     pg_parse_json_or_ereport(lex, &sem);
     888 ECB             :                 }
     889 CBC          18 :                 break;
     890             186 :             case JSONBTYPE_JSONB:
     891                 :                 {
     892 GIC         186 :                     Jsonb      *jsonb = DatumGetJsonbP(val);
     893                 :                     JsonbIterator *it;
     894                 : 
     895             186 :                     it = JsonbIteratorInit(&jsonb->root);
     896 ECB             : 
     897 GIC         186 :                     if (JB_ROOT_IS_SCALAR(jsonb))
     898 ECB             :                     {
     899 GIC         108 :                         (void) JsonbIteratorNext(&it, &jb, true);
     900 CBC         108 :                         Assert(jb.type == jbvArray);
     901 GIC         108 :                         (void) JsonbIteratorNext(&it, &jb, true);
     902 CBC         108 :                         scalar_jsonb = true;
     903                 :                     }
     904 ECB             :                     else
     905                 :                     {
     906                 :                         JsonbIteratorToken type;
     907                 : 
     908 CBC        3630 :                         while ((type = JsonbIteratorNext(&it, &jb, false))
     909            3630 :                                != WJB_DONE)
     910                 :                         {
     911            3552 :                             if (type == WJB_END_ARRAY || type == WJB_END_OBJECT ||
     912 GIC        2853 :                                 type == WJB_BEGIN_ARRAY || type == WJB_BEGIN_OBJECT)
     913 CBC         930 :                                 result->res = pushJsonbValue(&result->parseState,
     914 ECB             :                                                              type, NULL);
     915                 :                             else
     916 CBC        2622 :                                 result->res = pushJsonbValue(&result->parseState,
     917                 :                                                              type, &jb);
     918                 :                         }
     919 ECB             :                     }
     920                 :                 }
     921 CBC         186 :                 break;
     922 GIC         495 :             default:
     923 CBC         495 :                 outputstr = OidOutputFunctionCall(outfuncoid, val);
     924             495 :                 jb.type = jbvString;
     925 GNC         495 :                 jb.val.string.len = strlen(outputstr);
     926             495 :                 (void) checkStringLen(jb.val.string.len, NULL);
     927 CBC         495 :                 jb.val.string.val = outputstr;
     928 GIC         495 :                 break;
     929                 :         }
     930                 :     }
     931                 : 
     932                 :     /* Now insert jb into result, unless we did it recursively */
     933 CBC        1487 :     if (!is_null && !scalar_jsonb &&
     934             741 :         tcategory >= JSONBTYPE_JSON && tcategory <= JSONBTYPE_JSONCAST)
     935                 :     {
     936 ECB             :         /* work has been done recursively */
     937 CBC         246 :         return;
     938 ECB             :     }
     939 GIC        1241 :     else if (result->parseState == NULL)
     940                 :     {
     941 ECB             :         /* single root scalar */
     942                 :         JsonbValue  va;
     943                 : 
     944 GIC         255 :         va.type = jbvArray;
     945             255 :         va.val.array.rawScalar = true;
     946 CBC         255 :         va.val.array.nElems = 1;
     947 ECB             : 
     948 CBC         255 :         result->res = pushJsonbValue(&result->parseState, WJB_BEGIN_ARRAY, &va);
     949             255 :         result->res = pushJsonbValue(&result->parseState, WJB_ELEM, &jb);
     950             255 :         result->res = pushJsonbValue(&result->parseState, WJB_END_ARRAY, NULL);
     951 ECB             :     }
     952                 :     else
     953                 :     {
     954 GIC         986 :         JsonbValue *o = &result->parseState->contVal;
     955                 : 
     956             986 :         switch (o->type)
     957                 :         {
     958 CBC         237 :             case jbvArray:
     959             237 :                 result->res = pushJsonbValue(&result->parseState, WJB_ELEM, &jb);
     960 GIC         237 :                 break;
     961             749 :             case jbvObject:
     962 CBC         749 :                 result->res = pushJsonbValue(&result->parseState,
     963                 :                                              key_scalar ? WJB_KEY : WJB_VALUE,
     964 ECB             :                                              &jb);
     965 GIC         749 :                 break;
     966 UIC           0 :             default:
     967               0 :                 elog(ERROR, "unexpected parent of nested structure");
     968                 :         }
     969 ECB             :     }
     970                 : }
     971                 : 
     972                 : /*
     973                 :  * Process a single dimension of an array.
     974                 :  * If it's the innermost dimension, output the values, otherwise call
     975                 :  * ourselves recursively to process the next dimension.
     976                 :  */
     977                 : static void
     978 GIC          54 : array_dim_to_jsonb(JsonbInState *result, int dim, int ndims, int *dims, Datum *vals,
     979 ECB             :                    bool *nulls, int *valcount, JsonbTypeCategory tcategory,
     980                 :                    Oid outfuncoid)
     981                 : {
     982                 :     int         i;
     983                 : 
     984 CBC          54 :     Assert(dim < ndims);
     985 ECB             : 
     986 CBC          54 :     result->res = pushJsonbValue(&result->parseState, WJB_BEGIN_ARRAY, NULL);
     987 ECB             : 
     988 GIC         198 :     for (i = 1; i <= dims[dim]; i++)
     989                 :     {
     990 CBC         144 :         if (dim + 1 == ndims)
     991 EUB             :         {
     992 GBC         144 :             datum_to_jsonb(vals[*valcount], nulls[*valcount], result, tcategory,
     993                 :                            outfuncoid, false);
     994 GIC         144 :             (*valcount)++;
     995                 :         }
     996                 :         else
     997                 :         {
     998 UIC           0 :             array_dim_to_jsonb(result, dim + 1, ndims, dims, vals, nulls,
     999                 :                                valcount, tcategory, outfuncoid);
    1000                 :         }
    1001                 :     }
    1002                 : 
    1003 CBC          54 :     result->res = pushJsonbValue(&result->parseState, WJB_END_ARRAY, NULL);
    1004 GIC          54 : }
    1005                 : 
    1006                 : /*
    1007                 :  * Turn an array into JSON.
    1008                 :  */
    1009 ECB             : static void
    1010 GIC          54 : array_to_jsonb_internal(Datum array, JsonbInState *result)
    1011 ECB             : {
    1012 GIC          54 :     ArrayType  *v = DatumGetArrayTypeP(array);
    1013 CBC          54 :     Oid         element_type = ARR_ELEMTYPE(v);
    1014                 :     int        *dim;
    1015 ECB             :     int         ndim;
    1016                 :     int         nitems;
    1017 CBC          54 :     int         count = 0;
    1018                 :     Datum      *elements;
    1019 ECB             :     bool       *nulls;
    1020                 :     int16       typlen;
    1021                 :     bool        typbyval;
    1022                 :     char        typalign;
    1023 EUB             :     JsonbTypeCategory tcategory;
    1024                 :     Oid         outfuncoid;
    1025                 : 
    1026 GIC          54 :     ndim = ARR_NDIM(v);
    1027              54 :     dim = ARR_DIMS(v);
    1028 CBC          54 :     nitems = ArrayGetNItems(ndim, dim);
    1029 ECB             : 
    1030 GIC          54 :     if (nitems <= 0)
    1031                 :     {
    1032 UIC           0 :         result->res = pushJsonbValue(&result->parseState, WJB_BEGIN_ARRAY, NULL);
    1033               0 :         result->res = pushJsonbValue(&result->parseState, WJB_END_ARRAY, NULL);
    1034               0 :         return;
    1035 ECB             :     }
    1036                 : 
    1037 CBC          54 :     get_typlenbyvalalign(element_type,
    1038 ECB             :                          &typlen, &typbyval, &typalign);
    1039                 : 
    1040 GIC          54 :     jsonb_categorize_type(element_type,
    1041                 :                           &tcategory, &outfuncoid);
    1042 ECB             : 
    1043 GIC          54 :     deconstruct_array(v, element_type, typlen, typbyval,
    1044                 :                       typalign, &elements, &nulls,
    1045                 :                       &nitems);
    1046                 : 
    1047              54 :     array_dim_to_jsonb(result, 0, ndim, dim, elements, nulls, &count, tcategory,
    1048                 :                        outfuncoid);
    1049                 : 
    1050              54 :     pfree(elements);
    1051 CBC          54 :     pfree(nulls);
    1052 ECB             : }
    1053                 : 
    1054                 : /*
    1055                 :  * Turn a composite / record into JSON.
    1056                 :  */
    1057 EUB             : static void
    1058 GBC          96 : composite_to_jsonb(Datum composite, JsonbInState *result)
    1059 EUB             : {
    1060                 :     HeapTupleHeader td;
    1061                 :     Oid         tupType;
    1062 ECB             :     int32       tupTypmod;
    1063                 :     TupleDesc   tupdesc;
    1064                 :     HeapTupleData tmptup,
    1065                 :                *tuple;
    1066                 :     int         i;
    1067                 : 
    1068 CBC          96 :     td = DatumGetHeapTupleHeader(composite);
    1069                 : 
    1070                 :     /* Extract rowtype info and find a tupdesc */
    1071 GIC          96 :     tupType = HeapTupleHeaderGetTypeId(td);
    1072 CBC          96 :     tupTypmod = HeapTupleHeaderGetTypMod(td);
    1073 GIC          96 :     tupdesc = lookup_rowtype_tupdesc(tupType, tupTypmod);
    1074                 : 
    1075 ECB             :     /* Build a temporary HeapTuple control structure */
    1076 CBC          96 :     tmptup.t_len = HeapTupleHeaderGetDatumLength(td);
    1077 GIC          96 :     tmptup.t_data = td;
    1078              96 :     tuple = &tmptup;
    1079                 : 
    1080              96 :     result->res = pushJsonbValue(&result->parseState, WJB_BEGIN_OBJECT, NULL);
    1081                 : 
    1082             294 :     for (i = 0; i < tupdesc->natts; i++)
    1083 ECB             :     {
    1084                 :         Datum       val;
    1085                 :         bool        isnull;
    1086                 :         char       *attname;
    1087                 :         JsonbTypeCategory tcategory;
    1088                 :         Oid         outfuncoid;
    1089                 :         JsonbValue  v;
    1090 GIC         198 :         Form_pg_attribute att = TupleDescAttr(tupdesc, i);
    1091                 : 
    1092             198 :         if (att->attisdropped)
    1093 LBC           0 :             continue;
    1094                 : 
    1095 GIC         198 :         attname = NameStr(att->attname);
    1096 ECB             : 
    1097 CBC         198 :         v.type = jbvString;
    1098 ECB             :         /* don't need checkStringLen here - can't exceed maximum name length */
    1099 GIC         198 :         v.val.string.len = strlen(attname);
    1100             198 :         v.val.string.val = attname;
    1101 ECB             : 
    1102 CBC         198 :         result->res = pushJsonbValue(&result->parseState, WJB_KEY, &v);
    1103 ECB             : 
    1104 GIC         198 :         val = heap_getattr(tuple, i + 1, tupdesc, &isnull);
    1105 ECB             : 
    1106 GIC         198 :         if (isnull)
    1107 ECB             :         {
    1108 GIC          15 :             tcategory = JSONBTYPE_NULL;
    1109              15 :             outfuncoid = InvalidOid;
    1110                 :         }
    1111                 :         else
    1112             183 :             jsonb_categorize_type(att->atttypid, &tcategory, &outfuncoid);
    1113                 : 
    1114             198 :         datum_to_jsonb(val, isnull, result, tcategory, outfuncoid, false);
    1115 ECB             :     }
    1116                 : 
    1117 CBC          96 :     result->res = pushJsonbValue(&result->parseState, WJB_END_OBJECT, NULL);
    1118 GBC          96 :     ReleaseTupleDesc(tupdesc);
    1119 GIC          96 : }
    1120 ECB             : 
    1121                 : /*
    1122                 :  * Append JSON text for "val" to "result".
    1123                 :  *
    1124                 :  * This is just a thin wrapper around datum_to_jsonb.  If the same type will be
    1125                 :  * printed many times, avoid using this; better to do the jsonb_categorize_type
    1126                 :  * lookups only once.
    1127                 :  */
    1128                 : 
    1129                 : static void
    1130 GIC         809 : add_jsonb(Datum val, bool is_null, JsonbInState *result,
    1131 ECB             :           Oid val_type, bool key_scalar)
    1132                 : {
    1133                 :     JsonbTypeCategory tcategory;
    1134                 :     Oid         outfuncoid;
    1135                 : 
    1136 GIC         809 :     if (val_type == InvalidOid)
    1137 LBC           0 :         ereport(ERROR,
    1138                 :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    1139 ECB             :                  errmsg("could not determine input data type")));
    1140                 : 
    1141 GIC         809 :     if (is_null)
    1142 ECB             :     {
    1143 CBC          39 :         tcategory = JSONBTYPE_NULL;
    1144              39 :         outfuncoid = InvalidOid;
    1145                 :     }
    1146                 :     else
    1147 GIC         770 :         jsonb_categorize_type(val_type,
    1148                 :                               &tcategory, &outfuncoid);
    1149                 : 
    1150             809 :     datum_to_jsonb(val, is_null, result, tcategory, outfuncoid, key_scalar);
    1151             797 : }
    1152                 : 
    1153                 : /*
    1154                 :  * Is the given type immutable when coming out of a JSONB context?
    1155                 :  *
    1156                 :  * At present, datetimes are all considered mutable, because they
    1157                 :  * depend on timezone.  XXX we should also drill down into objects and
    1158                 :  * arrays, but do not.
    1159                 :  */
    1160                 : bool
    1161 UNC           0 : to_jsonb_is_immutable(Oid typoid)
    1162                 : {
    1163                 :     JsonbTypeCategory tcategory;
    1164                 :     Oid         outfuncoid;
    1165                 : 
    1166               0 :     jsonb_categorize_type(typoid, &tcategory, &outfuncoid);
    1167                 : 
    1168               0 :     switch (tcategory)
    1169                 :     {
    1170               0 :         case JSONBTYPE_NULL:
    1171                 :         case JSONBTYPE_BOOL:
    1172                 :         case JSONBTYPE_JSON:
    1173                 :         case JSONBTYPE_JSONB:
    1174               0 :             return true;
    1175                 : 
    1176               0 :         case JSONBTYPE_DATE:
    1177                 :         case JSONBTYPE_TIMESTAMP:
    1178                 :         case JSONBTYPE_TIMESTAMPTZ:
    1179               0 :             return false;
    1180                 : 
    1181               0 :         case JSONBTYPE_ARRAY:
    1182               0 :             return false;       /* TODO recurse into elements */
    1183                 : 
    1184               0 :         case JSONBTYPE_COMPOSITE:
    1185               0 :             return false;       /* TODO recurse into fields */
    1186                 : 
    1187               0 :         case JSONBTYPE_NUMERIC:
    1188                 :         case JSONBTYPE_JSONCAST:
    1189                 :         case JSONBTYPE_OTHER:
    1190               0 :             return func_volatile(outfuncoid) == PROVOLATILE_IMMUTABLE;
    1191                 :     }
    1192                 : 
    1193               0 :     return false;               /* not reached */
    1194                 : }
    1195                 : 
    1196                 : /*
    1197                 :  * SQL function to_jsonb(anyvalue)
    1198 ECB             :  */
    1199                 : Datum
    1200 GIC          42 : to_jsonb(PG_FUNCTION_ARGS)
    1201                 : {
    1202              42 :     Datum       val = PG_GETARG_DATUM(0);
    1203              42 :     Oid         val_type = get_fn_expr_argtype(fcinfo->flinfo, 0);
    1204 ECB             :     JsonbInState result;
    1205 EUB             :     JsonbTypeCategory tcategory;
    1206                 :     Oid         outfuncoid;
    1207                 : 
    1208 GIC          42 :     if (val_type == InvalidOid)
    1209 LBC           0 :         ereport(ERROR,
    1210                 :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    1211 ECB             :                  errmsg("could not determine input data type")));
    1212                 : 
    1213 GIC          42 :     jsonb_categorize_type(val_type,
    1214                 :                           &tcategory, &outfuncoid);
    1215 ECB             : 
    1216 GIC          42 :     memset(&result, 0, sizeof(JsonbInState));
    1217                 : 
    1218 CBC          42 :     datum_to_jsonb(val, false, &result, tcategory, outfuncoid, false);
    1219 ECB             : 
    1220 GIC          42 :     PG_RETURN_POINTER(JsonbValueToJsonb(result.res));
    1221                 : }
    1222                 : 
    1223                 : Datum
    1224 GNC         199 : jsonb_build_object_worker(int nargs, Datum *args, bool *nulls, Oid *types,
    1225                 :                           bool absent_on_null, bool unique_keys)
    1226                 : {
    1227                 :     int         i;
    1228                 :     JsonbInState result;
    1229                 : 
    1230 GBC         199 :     if (nargs % 2 != 0)
    1231 GIC           9 :         ereport(ERROR,
    1232 EUB             :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    1233                 :                  errmsg("argument list must have even number of elements"),
    1234                 :         /* translator: %s is a SQL function name */
    1235                 :                  errhint("The arguments of %s must consist of alternating keys and values.",
    1236                 :                          "jsonb_build_object()")));
    1237                 : 
    1238 GBC         190 :     memset(&result, 0, sizeof(JsonbInState));
    1239                 : 
    1240             190 :     result.res = pushJsonbValue(&result.parseState, WJB_BEGIN_OBJECT, NULL);
    1241 GNC         190 :     result.parseState->unique_keys = unique_keys;
    1242             190 :     result.parseState->skip_nulls = absent_on_null;
    1243 EUB             : 
    1244 GIC         504 :     for (i = 0; i < nargs; i += 2)
    1245 EUB             :     {
    1246                 :         /* process key */
    1247                 :         bool        skip;
    1248                 : 
    1249 GIC         335 :         if (nulls[i])
    1250 GBC           9 :             ereport(ERROR,
    1251                 :                     (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    1252                 :                      errmsg("argument %d: key must not be null", i + 1)));
    1253 EUB             : 
    1254                 :         /* skip null values if absent_on_null */
    1255 GNC         326 :         skip = absent_on_null && nulls[i + 1];
    1256                 : 
    1257                 :         /* we need to save skipped keys for the key uniqueness check */
    1258             326 :         if (skip && !unique_keys)
    1259               4 :             continue;
    1260                 : 
    1261 GIC         322 :         add_jsonb(args[i], false, &result, types[i], true);
    1262                 : 
    1263                 :         /* process value */
    1264             310 :         add_jsonb(args[i + 1], nulls[i + 1], &result, types[i + 1], false);
    1265                 :     }
    1266                 : 
    1267 CBC         169 :     result.res = pushJsonbValue(&result.parseState, WJB_END_OBJECT, NULL);
    1268                 : 
    1269 GNC         160 :     return JsonbPGetDatum(JsonbValueToJsonb(result.res));
    1270                 : }
    1271                 : 
    1272                 : /*
    1273                 :  * SQL function jsonb_build_object(variadic "any")
    1274                 :  */
    1275                 : Datum
    1276             168 : jsonb_build_object(PG_FUNCTION_ARGS)
    1277                 : {
    1278                 :     Datum      *args;
    1279                 :     bool       *nulls;
    1280                 :     Oid        *types;
    1281                 : 
    1282                 :     /* build argument values to build the object */
    1283             168 :     int         nargs = extract_variadic_args(fcinfo, 0, true,
    1284                 :                                               &args, &types, &nulls);
    1285                 : 
    1286             168 :     if (nargs < 0)
    1287               3 :         PG_RETURN_NULL();
    1288                 : 
    1289             165 :     PG_RETURN_DATUM(jsonb_build_object_worker(nargs, args, nulls, types, false, false));
    1290 ECB             : }
    1291                 : 
    1292                 : /*
    1293                 :  * degenerate case of jsonb_build_object where it gets 0 arguments.
    1294                 :  */
    1295                 : Datum
    1296 GBC           3 : jsonb_build_object_noargs(PG_FUNCTION_ARGS)
    1297                 : {
    1298                 :     JsonbInState result;
    1299                 : 
    1300 CBC           3 :     memset(&result, 0, sizeof(JsonbInState));
    1301                 : 
    1302 GIC           3 :     (void) pushJsonbValue(&result.parseState, WJB_BEGIN_OBJECT, NULL);
    1303 CBC           3 :     result.res = pushJsonbValue(&result.parseState, WJB_END_OBJECT, NULL);
    1304                 : 
    1305               3 :     PG_RETURN_POINTER(JsonbValueToJsonb(result.res));
    1306                 : }
    1307 ECB             : 
    1308                 : Datum
    1309 GNC          88 : jsonb_build_array_worker(int nargs, Datum *args, bool *nulls, Oid *types,
    1310                 :                          bool absent_on_null)
    1311                 : {
    1312                 :     int         i;
    1313                 :     JsonbInState result;
    1314                 : 
    1315 CBC          88 :     memset(&result, 0, sizeof(JsonbInState));
    1316 ECB             : 
    1317 CBC          88 :     result.res = pushJsonbValue(&result.parseState, WJB_BEGIN_ARRAY, NULL);
    1318                 : 
    1319             277 :     for (i = 0; i < nargs; i++)
    1320                 :     {
    1321 GNC         189 :         if (absent_on_null && nulls[i])
    1322              12 :             continue;
    1323                 : 
    1324 GIC         177 :         add_jsonb(args[i], nulls[i], &result, types[i], false);
    1325                 :     }
    1326                 : 
    1327              88 :     result.res = pushJsonbValue(&result.parseState, WJB_END_ARRAY, NULL);
    1328                 : 
    1329 GNC          88 :     return JsonbPGetDatum(JsonbValueToJsonb(result.res));
    1330 ECB             : }
    1331                 : 
    1332                 : /*
    1333                 :  * SQL function jsonb_build_array(variadic "any")
    1334                 :  */
    1335                 : Datum
    1336 GNC          75 : jsonb_build_array(PG_FUNCTION_ARGS)
    1337                 : {
    1338                 :     Datum      *args;
    1339                 :     bool       *nulls;
    1340                 :     Oid        *types;
    1341                 : 
    1342                 :     /* build argument values to build the object */
    1343              75 :     int         nargs = extract_variadic_args(fcinfo, 0, true,
    1344                 :                                               &args, &types, &nulls);
    1345                 : 
    1346              75 :     if (nargs < 0)
    1347               3 :         PG_RETURN_NULL();
    1348                 : 
    1349              72 :     PG_RETURN_DATUM(jsonb_build_array_worker(nargs, args, nulls, types, false));
    1350                 : }
    1351                 : 
    1352                 : 
    1353                 : /*
    1354                 :  * degenerate case of jsonb_build_array where it gets 0 arguments.
    1355                 :  */
    1356 ECB             : Datum
    1357 GIC           3 : jsonb_build_array_noargs(PG_FUNCTION_ARGS)
    1358                 : {
    1359 ECB             :     JsonbInState result;
    1360                 : 
    1361 GIC           3 :     memset(&result, 0, sizeof(JsonbInState));
    1362 ECB             : 
    1363 GIC           3 :     (void) pushJsonbValue(&result.parseState, WJB_BEGIN_ARRAY, NULL);
    1364               3 :     result.res = pushJsonbValue(&result.parseState, WJB_END_ARRAY, NULL);
    1365 ECB             : 
    1366 GIC           3 :     PG_RETURN_POINTER(JsonbValueToJsonb(result.res));
    1367                 : }
    1368 ECB             : 
    1369                 : 
    1370                 : /*
    1371                 :  * SQL function jsonb_object(text[])
    1372                 :  *
    1373                 :  * take a one or two dimensional array of text as name value pairs
    1374                 :  * for a jsonb object.
    1375                 :  *
    1376                 :  */
    1377                 : Datum
    1378 GIC          21 : jsonb_object(PG_FUNCTION_ARGS)
    1379                 : {
    1380              21 :     ArrayType  *in_array = PG_GETARG_ARRAYTYPE_P(0);
    1381              21 :     int         ndims = ARR_NDIM(in_array);
    1382                 :     Datum      *in_datums;
    1383                 :     bool       *in_nulls;
    1384 ECB             :     int         in_count,
    1385                 :                 count,
    1386                 :                 i;
    1387                 :     JsonbInState result;
    1388                 : 
    1389 GIC          21 :     memset(&result, 0, sizeof(JsonbInState));
    1390 ECB             : 
    1391 GIC          21 :     (void) pushJsonbValue(&result.parseState, WJB_BEGIN_OBJECT, NULL);
    1392                 : 
    1393              21 :     switch (ndims)
    1394                 :     {
    1395               3 :         case 0:
    1396               3 :             goto close_object;
    1397 ECB             :             break;
    1398                 : 
    1399 GIC           6 :         case 1:
    1400               6 :             if ((ARR_DIMS(in_array)[0]) % 2)
    1401 CBC           3 :                 ereport(ERROR,
    1402                 :                         (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
    1403 ECB             :                          errmsg("array must have even number of elements")));
    1404 CBC           3 :             break;
    1405                 : 
    1406               9 :         case 2:
    1407 GIC           9 :             if ((ARR_DIMS(in_array)[1]) != 2)
    1408               6 :                 ereport(ERROR,
    1409                 :                         (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
    1410 ECB             :                          errmsg("array must have two columns")));
    1411 GIC           3 :             break;
    1412                 : 
    1413               3 :         default:
    1414               3 :             ereport(ERROR,
    1415                 :                     (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
    1416 ECB             :                      errmsg("wrong number of array subscripts")));
    1417                 :     }
    1418                 : 
    1419 GNC           6 :     deconstruct_array_builtin(in_array, TEXTOID, &in_datums, &in_nulls, &in_count);
    1420 ECB             : 
    1421 CBC           6 :     count = in_count / 2;
    1422                 : 
    1423              30 :     for (i = 0; i < count; ++i)
    1424                 :     {
    1425                 :         JsonbValue  v;
    1426 ECB             :         char       *str;
    1427                 :         int         len;
    1428                 : 
    1429 GIC          24 :         if (in_nulls[i * 2])
    1430 UIC           0 :             ereport(ERROR,
    1431                 :                     (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
    1432                 :                      errmsg("null value not allowed for object key")));
    1433                 : 
    1434 GIC          24 :         str = TextDatumGetCString(in_datums[i * 2]);
    1435 CBC          24 :         len = strlen(str);
    1436                 : 
    1437 GIC          24 :         v.type = jbvString;
    1438                 : 
    1439              24 :         v.val.string.len = len;
    1440              24 :         v.val.string.val = str;
    1441                 : 
    1442 CBC          24 :         (void) pushJsonbValue(&result.parseState, WJB_KEY, &v);
    1443                 : 
    1444 GIC          24 :         if (in_nulls[i * 2 + 1])
    1445 ECB             :         {
    1446 CBC           6 :             v.type = jbvNull;
    1447                 :         }
    1448 ECB             :         else
    1449                 :         {
    1450 GIC          18 :             str = TextDatumGetCString(in_datums[i * 2 + 1]);
    1451              18 :             len = strlen(str);
    1452                 : 
    1453              18 :             v.type = jbvString;
    1454                 : 
    1455              18 :             v.val.string.len = len;
    1456 CBC          18 :             v.val.string.val = str;
    1457                 :         }
    1458                 : 
    1459 GIC          24 :         (void) pushJsonbValue(&result.parseState, WJB_VALUE, &v);
    1460 ECB             :     }
    1461                 : 
    1462 CBC           6 :     pfree(in_datums);
    1463               6 :     pfree(in_nulls);
    1464                 : 
    1465               9 : close_object:
    1466 GIC           9 :     result.res = pushJsonbValue(&result.parseState, WJB_END_OBJECT, NULL);
    1467                 : 
    1468               9 :     PG_RETURN_POINTER(JsonbValueToJsonb(result.res));
    1469                 : }
    1470                 : 
    1471                 : /*
    1472                 :  * SQL function jsonb_object(text[], text[])
    1473                 :  *
    1474                 :  * take separate name and value arrays of text to construct a jsonb object
    1475                 :  * pairwise.
    1476                 :  */
    1477 ECB             : Datum
    1478 GIC          21 : jsonb_object_two_arg(PG_FUNCTION_ARGS)
    1479 ECB             : {
    1480 CBC          21 :     ArrayType  *key_array = PG_GETARG_ARRAYTYPE_P(0);
    1481 GIC          21 :     ArrayType  *val_array = PG_GETARG_ARRAYTYPE_P(1);
    1482              21 :     int         nkdims = ARR_NDIM(key_array);
    1483              21 :     int         nvdims = ARR_NDIM(val_array);
    1484                 :     Datum      *key_datums,
    1485                 :                *val_datums;
    1486                 :     bool       *key_nulls,
    1487                 :                *val_nulls;
    1488 ECB             :     int         key_count,
    1489                 :                 val_count,
    1490                 :                 i;
    1491                 :     JsonbInState result;
    1492                 : 
    1493 GIC          21 :     memset(&result, 0, sizeof(JsonbInState));
    1494 ECB             : 
    1495 CBC          21 :     (void) pushJsonbValue(&result.parseState, WJB_BEGIN_OBJECT, NULL);
    1496                 : 
    1497 GIC          21 :     if (nkdims > 1 || nkdims != nvdims)
    1498 CBC           3 :         ereport(ERROR,
    1499 ECB             :                 (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
    1500                 :                  errmsg("wrong number of array subscripts")));
    1501                 : 
    1502 GIC          18 :     if (nkdims == 0)
    1503 CBC           3 :         goto close_object;
    1504                 : 
    1505 GNC          15 :     deconstruct_array_builtin(key_array, TEXTOID, &key_datums, &key_nulls, &key_count);
    1506              15 :     deconstruct_array_builtin(val_array, TEXTOID, &val_datums, &val_nulls, &val_count);
    1507 ECB             : 
    1508 CBC          15 :     if (key_count != val_count)
    1509 GIC           6 :         ereport(ERROR,
    1510                 :                 (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
    1511                 :                  errmsg("mismatched array dimensions")));
    1512                 : 
    1513 CBC          39 :     for (i = 0; i < key_count; ++i)
    1514                 :     {
    1515 ECB             :         JsonbValue  v;
    1516                 :         char       *str;
    1517                 :         int         len;
    1518                 : 
    1519 GIC          33 :         if (key_nulls[i])
    1520               3 :             ereport(ERROR,
    1521                 :                     (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
    1522                 :                      errmsg("null value not allowed for object key")));
    1523 ECB             : 
    1524 GBC          30 :         str = TextDatumGetCString(key_datums[i]);
    1525 GIC          30 :         len = strlen(str);
    1526                 : 
    1527              30 :         v.type = jbvString;
    1528 ECB             : 
    1529 CBC          30 :         v.val.string.len = len;
    1530 GIC          30 :         v.val.string.val = str;
    1531 ECB             : 
    1532 GIC          30 :         (void) pushJsonbValue(&result.parseState, WJB_KEY, &v);
    1533 ECB             : 
    1534 CBC          30 :         if (val_nulls[i])
    1535                 :         {
    1536 LBC           0 :             v.type = jbvNull;
    1537                 :         }
    1538 ECB             :         else
    1539                 :         {
    1540 CBC          30 :             str = TextDatumGetCString(val_datums[i]);
    1541 GIC          30 :             len = strlen(str);
    1542                 : 
    1543              30 :             v.type = jbvString;
    1544 ECB             : 
    1545 CBC          30 :             v.val.string.len = len;
    1546 GIC          30 :             v.val.string.val = str;
    1547 ECB             :         }
    1548                 : 
    1549 CBC          30 :         (void) pushJsonbValue(&result.parseState, WJB_VALUE, &v);
    1550 ECB             :     }
    1551                 : 
    1552 GIC           6 :     pfree(key_datums);
    1553 CBC           6 :     pfree(key_nulls);
    1554 GIC           6 :     pfree(val_datums);
    1555               6 :     pfree(val_nulls);
    1556 ECB             : 
    1557 CBC           9 : close_object:
    1558 GIC           9 :     result.res = pushJsonbValue(&result.parseState, WJB_END_OBJECT, NULL);
    1559 ECB             : 
    1560 CBC           9 :     PG_RETURN_POINTER(JsonbValueToJsonb(result.res));
    1561                 : }
    1562 ECB             : 
    1563                 : 
    1564                 : /*
    1565                 :  * shallow clone of a parse state, suitable for use in aggregate
    1566                 :  * final functions that will only append to the values rather than
    1567                 :  * change them.
    1568                 :  */
    1569                 : static JsonbParseState *
    1570 GIC          57 : clone_parse_state(JsonbParseState *state)
    1571                 : {
    1572 ECB             :     JsonbParseState *result,
    1573                 :                *icursor,
    1574                 :                *ocursor;
    1575                 : 
    1576 CBC          57 :     if (state == NULL)
    1577 LBC           0 :         return NULL;
    1578                 : 
    1579 GIC          57 :     result = palloc(sizeof(JsonbParseState));
    1580              57 :     icursor = state;
    1581              57 :     ocursor = result;
    1582                 :     for (;;)
    1583                 :     {
    1584              57 :         ocursor->contVal = icursor->contVal;
    1585              57 :         ocursor->size = icursor->size;
    1586 GNC          57 :         ocursor->unique_keys = icursor->unique_keys;
    1587              57 :         ocursor->skip_nulls = icursor->skip_nulls;
    1588 GIC          57 :         icursor = icursor->next;
    1589 CBC          57 :         if (icursor == NULL)
    1590 GIC          57 :             break;
    1591 LBC           0 :         ocursor->next = palloc(sizeof(JsonbParseState));
    1592 UIC           0 :         ocursor = ocursor->next;
    1593 ECB             :     }
    1594 CBC          57 :     ocursor->next = NULL;
    1595                 : 
    1596 GIC          57 :     return result;
    1597                 : }
    1598 ECB             : 
    1599                 : static Datum
    1600 GNC         183 : jsonb_agg_transfn_worker(FunctionCallInfo fcinfo, bool absent_on_null)
    1601 ECB             : {
    1602                 :     MemoryContext oldcontext,
    1603                 :                 aggcontext;
    1604                 :     JsonbAggState *state;
    1605                 :     JsonbInState elem;
    1606                 :     Datum       val;
    1607                 :     JsonbInState *result;
    1608 GIC         183 :     bool        single_scalar = false;
    1609                 :     JsonbIterator *it;
    1610                 :     Jsonb      *jbelem;
    1611 ECB             :     JsonbValue  v;
    1612                 :     JsonbIteratorToken type;
    1613                 : 
    1614 GIC         183 :     if (!AggCheckCallContext(fcinfo, &aggcontext))
    1615                 :     {
    1616 ECB             :         /* cannot be called directly because of internal-type argument */
    1617 LBC           0 :         elog(ERROR, "jsonb_agg_transfn called in non-aggregate context");
    1618                 :     }
    1619 ECB             : 
    1620                 :     /* set up the accumulator on the first go round */
    1621                 : 
    1622 CBC         183 :     if (PG_ARGISNULL(0))
    1623                 :     {
    1624              33 :         Oid         arg_type = get_fn_expr_argtype(fcinfo->flinfo, 1);
    1625                 : 
    1626              33 :         if (arg_type == InvalidOid)
    1627 UIC           0 :             ereport(ERROR,
    1628 EUB             :                     (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    1629                 :                      errmsg("could not determine input data type")));
    1630                 : 
    1631 GIC          33 :         oldcontext = MemoryContextSwitchTo(aggcontext);
    1632 CBC          33 :         state = palloc(sizeof(JsonbAggState));
    1633              33 :         result = palloc0(sizeof(JsonbInState));
    1634 GIC          33 :         state->res = result;
    1635 CBC          33 :         result->res = pushJsonbValue(&result->parseState,
    1636                 :                                      WJB_BEGIN_ARRAY, NULL);
    1637              33 :         MemoryContextSwitchTo(oldcontext);
    1638 ECB             : 
    1639 GIC          33 :         jsonb_categorize_type(arg_type, &state->val_category,
    1640                 :                               &state->val_output_func);
    1641 ECB             :     }
    1642                 :     else
    1643                 :     {
    1644 CBC         150 :         state = (JsonbAggState *) PG_GETARG_POINTER(0);
    1645             150 :         result = state->res;
    1646 ECB             :     }
    1647                 : 
    1648 GNC         183 :     if (absent_on_null && PG_ARGISNULL(1))
    1649              39 :         PG_RETURN_POINTER(state);
    1650                 : 
    1651                 :     /* turn the argument into jsonb in the normal function context */
    1652 ECB             : 
    1653 CBC         144 :     val = PG_ARGISNULL(1) ? (Datum) 0 : PG_GETARG_DATUM(1);
    1654                 : 
    1655             144 :     memset(&elem, 0, sizeof(JsonbInState));
    1656                 : 
    1657 GIC         144 :     datum_to_jsonb(val, PG_ARGISNULL(1), &elem, state->val_category,
    1658                 :                    state->val_output_func, false);
    1659                 : 
    1660             144 :     jbelem = JsonbValueToJsonb(elem.res);
    1661                 : 
    1662                 :     /* switch to the aggregate context for accumulation operations */
    1663                 : 
    1664             144 :     oldcontext = MemoryContextSwitchTo(aggcontext);
    1665 ECB             : 
    1666 GIC         144 :     it = JsonbIteratorInit(&jbelem->root);
    1667                 : 
    1668             984 :     while ((type = JsonbIteratorNext(&it, &v, false)) != WJB_DONE)
    1669                 :     {
    1670             840 :         switch (type)
    1671 ECB             :         {
    1672 GBC         114 :             case WJB_BEGIN_ARRAY:
    1673 GIC         114 :                 if (v.val.array.rawScalar)
    1674 CBC          72 :                     single_scalar = true;
    1675 ECB             :                 else
    1676 CBC          42 :                     result->res = pushJsonbValue(&result->parseState,
    1677                 :                                                  type, NULL);
    1678 GIC         114 :                 break;
    1679 CBC         114 :             case WJB_END_ARRAY:
    1680             114 :                 if (!single_scalar)
    1681              42 :                     result->res = pushJsonbValue(&result->parseState,
    1682 ECB             :                                                  type, NULL);
    1683 CBC         114 :                 break;
    1684             180 :             case WJB_BEGIN_OBJECT:
    1685 ECB             :             case WJB_END_OBJECT:
    1686 GBC         180 :                 result->res = pushJsonbValue(&result->parseState,
    1687 EUB             :                                              type, NULL);
    1688 GIC         180 :                 break;
    1689 CBC         432 :             case WJB_ELEM:
    1690                 :             case WJB_KEY:
    1691 ECB             :             case WJB_VALUE:
    1692 GIC         432 :                 if (v.type == jbvString)
    1693                 :                 {
    1694                 :                     /* copy string values in the aggregate context */
    1695 CBC         186 :                     char       *buf = palloc(v.val.string.len + 1);
    1696                 : 
    1697 GIC         186 :                     snprintf(buf, v.val.string.len + 1, "%s", v.val.string.val);
    1698             186 :                     v.val.string.val = buf;
    1699                 :                 }
    1700             246 :                 else if (v.type == jbvNumeric)
    1701                 :                 {
    1702                 :                     /* same for numeric */
    1703 CBC         204 :                     v.val.numeric =
    1704 GIC         204 :                         DatumGetNumeric(DirectFunctionCall1(numeric_uplus,
    1705                 :                                                             NumericGetDatum(v.val.numeric)));
    1706                 :                 }
    1707             432 :                 result->res = pushJsonbValue(&result->parseState,
    1708                 :                                              type, &v);
    1709 CBC         432 :                 break;
    1710 UIC           0 :             default:
    1711               0 :                 elog(ERROR, "unknown jsonb iterator token type");
    1712 EUB             :         }
    1713                 :     }
    1714                 : 
    1715 GIC         144 :     MemoryContextSwitchTo(oldcontext);
    1716                 : 
    1717 CBC         144 :     PG_RETURN_POINTER(state);
    1718                 : }
    1719 ECB             : 
    1720                 : /*
    1721                 :  * jsonb_agg aggregate function
    1722                 :  */
    1723                 : Datum
    1724 GNC          72 : jsonb_agg_transfn(PG_FUNCTION_ARGS)
    1725                 : {
    1726              72 :     return jsonb_agg_transfn_worker(fcinfo, false);
    1727                 : }
    1728                 : 
    1729                 : /*
    1730                 :  * jsonb_agg_strict aggregate function
    1731                 :  */
    1732                 : Datum
    1733             111 : jsonb_agg_strict_transfn(PG_FUNCTION_ARGS)
    1734                 : {
    1735             111 :     return jsonb_agg_transfn_worker(fcinfo, true);
    1736                 : }
    1737                 : 
    1738                 : Datum
    1739 CBC          36 : jsonb_agg_finalfn(PG_FUNCTION_ARGS)
    1740 EUB             : {
    1741                 :     JsonbAggState *arg;
    1742                 :     JsonbInState result;
    1743                 :     Jsonb      *out;
    1744 ECB             : 
    1745                 :     /* cannot be called directly because of internal-type argument */
    1746 CBC          36 :     Assert(AggCheckCallContext(fcinfo, NULL));
    1747 ECB             : 
    1748 CBC          36 :     if (PG_ARGISNULL(0))
    1749 GIC           3 :         PG_RETURN_NULL();       /* returns null iff no input values */
    1750 ECB             : 
    1751 GIC          33 :     arg = (JsonbAggState *) PG_GETARG_POINTER(0);
    1752 ECB             : 
    1753                 :     /*
    1754                 :      * We need to do a shallow clone of the argument in case the final
    1755                 :      * function is called more than once, so we avoid changing the argument. A
    1756                 :      * shallow clone is sufficient as we aren't going to change any of the
    1757                 :      * values, just add the final array end marker.
    1758                 :      */
    1759 GNC          33 :     memset(&result, 0, sizeof(JsonbInState));
    1760                 : 
    1761 GIC          33 :     result.parseState = clone_parse_state(arg->res->parseState);
    1762 ECB             : 
    1763 CBC          33 :     result.res = pushJsonbValue(&result.parseState,
    1764                 :                                 WJB_END_ARRAY, NULL);
    1765                 : 
    1766 GIC          33 :     out = JsonbValueToJsonb(result.res);
    1767 ECB             : 
    1768 GIC          33 :     PG_RETURN_POINTER(out);
    1769 ECB             : }
    1770                 : 
    1771                 : static Datum
    1772 GNC          96 : jsonb_object_agg_transfn_worker(FunctionCallInfo fcinfo,
    1773                 :                                 bool absent_on_null, bool unique_keys)
    1774                 : {
    1775                 :     MemoryContext oldcontext,
    1776 ECB             :                 aggcontext;
    1777                 :     JsonbInState elem;
    1778                 :     JsonbAggState *state;
    1779                 :     Datum       val;
    1780                 :     JsonbInState *result;
    1781                 :     bool        single_scalar;
    1782                 :     JsonbIterator *it;
    1783                 :     Jsonb      *jbkey,
    1784                 :                *jbval;
    1785                 :     JsonbValue  v;
    1786                 :     JsonbIteratorToken type;
    1787                 :     bool        skip;
    1788                 : 
    1789 CBC          96 :     if (!AggCheckCallContext(fcinfo, &aggcontext))
    1790                 :     {
    1791 ECB             :         /* cannot be called directly because of internal-type argument */
    1792 LBC           0 :         elog(ERROR, "jsonb_object_agg_transfn called in non-aggregate context");
    1793 ECB             :     }
    1794                 : 
    1795                 :     /* set up the accumulator on the first go round */
    1796                 : 
    1797 CBC          96 :     if (PG_ARGISNULL(0))
    1798                 :     {
    1799 ECB             :         Oid         arg_type;
    1800                 : 
    1801 CBC          33 :         oldcontext = MemoryContextSwitchTo(aggcontext);
    1802              33 :         state = palloc(sizeof(JsonbAggState));
    1803 GIC          33 :         result = palloc0(sizeof(JsonbInState));
    1804              33 :         state->res = result;
    1805 CBC          33 :         result->res = pushJsonbValue(&result->parseState,
    1806                 :                                      WJB_BEGIN_OBJECT, NULL);
    1807 GNC          33 :         result->parseState->unique_keys = unique_keys;
    1808              33 :         result->parseState->skip_nulls = absent_on_null;
    1809                 : 
    1810 GIC          33 :         MemoryContextSwitchTo(oldcontext);
    1811 ECB             : 
    1812 GIC          33 :         arg_type = get_fn_expr_argtype(fcinfo->flinfo, 1);
    1813 ECB             : 
    1814 CBC          33 :         if (arg_type == InvalidOid)
    1815 UIC           0 :             ereport(ERROR,
    1816 ECB             :                     (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    1817                 :                      errmsg("could not determine input data type")));
    1818                 : 
    1819 CBC          33 :         jsonb_categorize_type(arg_type, &state->key_category,
    1820 ECB             :                               &state->key_output_func);
    1821                 : 
    1822 GIC          33 :         arg_type = get_fn_expr_argtype(fcinfo->flinfo, 2);
    1823 ECB             : 
    1824 GIC          33 :         if (arg_type == InvalidOid)
    1825 LBC           0 :             ereport(ERROR,
    1826 EUB             :                     (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    1827                 :                      errmsg("could not determine input data type")));
    1828                 : 
    1829 GIC          33 :         jsonb_categorize_type(arg_type, &state->val_category,
    1830                 :                               &state->val_output_func);
    1831 ECB             :     }
    1832                 :     else
    1833                 :     {
    1834 GIC          63 :         state = (JsonbAggState *) PG_GETARG_POINTER(0);
    1835              63 :         result = state->res;
    1836                 :     }
    1837                 : 
    1838                 :     /* turn the argument into jsonb in the normal function context */
    1839                 : 
    1840 CBC          96 :     if (PG_ARGISNULL(1))
    1841 GIC           9 :         ereport(ERROR,
    1842 ECB             :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    1843                 :                  errmsg("field name must not be null")));
    1844                 : 
    1845                 :     /*
    1846                 :      * Skip null values if absent_on_null unless key uniqueness check is
    1847                 :      * needed (because we must save keys in this case).
    1848                 :      */
    1849 GNC          87 :     skip = absent_on_null && PG_ARGISNULL(2);
    1850                 : 
    1851              87 :     if (skip && !unique_keys)
    1852               6 :         PG_RETURN_POINTER(state);
    1853                 : 
    1854 GIC          81 :     val = PG_GETARG_DATUM(1);
    1855                 : 
    1856              81 :     memset(&elem, 0, sizeof(JsonbInState));
    1857                 : 
    1858 CBC          81 :     datum_to_jsonb(val, false, &elem, state->key_category,
    1859                 :                    state->key_output_func, true);
    1860 ECB             : 
    1861 GIC          81 :     jbkey = JsonbValueToJsonb(elem.res);
    1862                 : 
    1863              81 :     val = PG_ARGISNULL(2) ? (Datum) 0 : PG_GETARG_DATUM(2);
    1864 ECB             : 
    1865 GIC          81 :     memset(&elem, 0, sizeof(JsonbInState));
    1866                 : 
    1867              81 :     datum_to_jsonb(val, PG_ARGISNULL(2), &elem, state->val_category,
    1868                 :                    state->val_output_func, false);
    1869                 : 
    1870              81 :     jbval = JsonbValueToJsonb(elem.res);
    1871 ECB             : 
    1872 GIC          81 :     it = JsonbIteratorInit(&jbkey->root);
    1873 ECB             : 
    1874                 :     /* switch to the aggregate context for accumulation operations */
    1875                 : 
    1876 CBC          81 :     oldcontext = MemoryContextSwitchTo(aggcontext);
    1877                 : 
    1878                 :     /*
    1879                 :      * keys should be scalar, and we should have already checked for that
    1880                 :      * above when calling datum_to_jsonb, so we only need to look for these
    1881                 :      * things.
    1882                 :      */
    1883                 : 
    1884             318 :     while ((type = JsonbIteratorNext(&it, &v, false)) != WJB_DONE)
    1885                 :     {
    1886             240 :         switch (type)
    1887                 :         {
    1888              81 :             case WJB_BEGIN_ARRAY:
    1889 GIC          81 :                 if (!v.val.array.rawScalar)
    1890 UIC           0 :                     elog(ERROR, "unexpected structure for key");
    1891 CBC          81 :                 break;
    1892 GIC          81 :             case WJB_ELEM:
    1893 CBC          81 :                 if (v.type == jbvString)
    1894                 :                 {
    1895                 :                     /* copy string values in the aggregate context */
    1896 GIC          81 :                     char       *buf = palloc(v.val.string.len + 1);
    1897 ECB             : 
    1898 GIC          81 :                     snprintf(buf, v.val.string.len + 1, "%s", v.val.string.val);
    1899              81 :                     v.val.string.val = buf;
    1900                 :                 }
    1901                 :                 else
    1902                 :                 {
    1903 UIC           0 :                     ereport(ERROR,
    1904                 :                             (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    1905                 :                              errmsg("object keys must be strings")));
    1906                 :                 }
    1907 GIC          81 :                 result->res = pushJsonbValue(&result->parseState,
    1908                 :                                              WJB_KEY, &v);
    1909                 : 
    1910 GNC          81 :                 if (skip)
    1911                 :                 {
    1912               3 :                     v.type = jbvNull;
    1913               3 :                     result->res = pushJsonbValue(&result->parseState,
    1914                 :                                                  WJB_VALUE, &v);
    1915               3 :                     MemoryContextSwitchTo(oldcontext);
    1916               3 :                     PG_RETURN_POINTER(state);
    1917                 :                 }
    1918                 : 
    1919 GIC          78 :                 break;
    1920              78 :             case WJB_END_ARRAY:
    1921              78 :                 break;
    1922 UIC           0 :             default:
    1923               0 :                 elog(ERROR, "unexpected structure for key");
    1924 ECB             :                 break;
    1925                 :         }
    1926                 :     }
    1927 EUB             : 
    1928 GIC          78 :     it = JsonbIteratorInit(&jbval->root);
    1929                 : 
    1930              78 :     single_scalar = false;
    1931                 : 
    1932 ECB             :     /*
    1933                 :      * values can be anything, including structured and null, so we treat them
    1934                 :      * as in json_agg_transfn, except that single scalars are always pushed as
    1935                 :      * WJB_VALUE items.
    1936                 :      */
    1937                 : 
    1938 CBC         339 :     while ((type = JsonbIteratorNext(&it, &v, false)) != WJB_DONE)
    1939 ECB             :     {
    1940 CBC         261 :         switch (type)
    1941                 :         {
    1942              69 :             case WJB_BEGIN_ARRAY:
    1943              69 :                 if (v.val.array.rawScalar)
    1944 GIC          69 :                     single_scalar = true;
    1945 ECB             :                 else
    1946 UIC           0 :                     result->res = pushJsonbValue(&result->parseState,
    1947 ECB             :                                                  type, NULL);
    1948 GIC          69 :                 break;
    1949 CBC          69 :             case WJB_END_ARRAY:
    1950 GBC          69 :                 if (!single_scalar)
    1951 UIC           0 :                     result->res = pushJsonbValue(&result->parseState,
    1952                 :                                                  type, NULL);
    1953 GIC          69 :                 break;
    1954 CBC          18 :             case WJB_BEGIN_OBJECT:
    1955                 :             case WJB_END_OBJECT:
    1956 GIC          18 :                 result->res = pushJsonbValue(&result->parseState,
    1957 ECB             :                                              type, NULL);
    1958 GIC          18 :                 break;
    1959 CBC         105 :             case WJB_ELEM:
    1960 EUB             :             case WJB_KEY:
    1961                 :             case WJB_VALUE:
    1962 GIC         105 :                 if (v.type == jbvString)
    1963                 :                 {
    1964 ECB             :                     /* copy string values in the aggregate context */
    1965 GIC          54 :                     char       *buf = palloc(v.val.string.len + 1);
    1966                 : 
    1967              54 :                     snprintf(buf, v.val.string.len + 1, "%s", v.val.string.val);
    1968              54 :                     v.val.string.val = buf;
    1969 ECB             :                 }
    1970 CBC          51 :                 else if (v.type == jbvNumeric)
    1971                 :                 {
    1972                 :                     /* same for numeric */
    1973 GIC          39 :                     v.val.numeric =
    1974              39 :                         DatumGetNumeric(DirectFunctionCall1(numeric_uplus,
    1975 ECB             :                                                             NumericGetDatum(v.val.numeric)));
    1976                 :                 }
    1977 GIC         105 :                 result->res = pushJsonbValue(&result->parseState,
    1978                 :                                              single_scalar ? WJB_VALUE : type,
    1979                 :                                              &v);
    1980             105 :                 break;
    1981 UIC           0 :             default:
    1982               0 :                 elog(ERROR, "unknown jsonb iterator token type");
    1983                 :         }
    1984 ECB             :     }
    1985                 : 
    1986 CBC          78 :     MemoryContextSwitchTo(oldcontext);
    1987 ECB             : 
    1988 GIC          78 :     PG_RETURN_POINTER(state);
    1989 ECB             : }
    1990                 : 
    1991                 : /*
    1992                 :  * jsonb_object_agg aggregate function
    1993                 :  */
    1994                 : Datum
    1995 GNC          66 : jsonb_object_agg_transfn(PG_FUNCTION_ARGS)
    1996                 : {
    1997              66 :     return jsonb_object_agg_transfn_worker(fcinfo, false, false);
    1998                 : }
    1999                 : 
    2000                 : 
    2001                 : /*
    2002                 :  * jsonb_object_agg_strict aggregate function
    2003                 :  */
    2004                 : Datum
    2005              12 : jsonb_object_agg_strict_transfn(PG_FUNCTION_ARGS)
    2006                 : {
    2007              12 :     return jsonb_object_agg_transfn_worker(fcinfo, true, false);
    2008                 : }
    2009                 : 
    2010                 : /*
    2011                 :  * jsonb_object_agg_unique aggregate function
    2012                 :  */
    2013                 : Datum
    2014               9 : jsonb_object_agg_unique_transfn(PG_FUNCTION_ARGS)
    2015                 : {
    2016               9 :     return jsonb_object_agg_transfn_worker(fcinfo, false, true);
    2017                 : }
    2018                 : 
    2019                 : /*
    2020                 :  * jsonb_object_agg_unique_strict aggregate function
    2021                 :  */
    2022                 : Datum
    2023               9 : jsonb_object_agg_unique_strict_transfn(PG_FUNCTION_ARGS)
    2024                 : {
    2025               9 :     return jsonb_object_agg_transfn_worker(fcinfo, true, true);
    2026                 : }
    2027                 : 
    2028 ECB             : Datum
    2029 GIC          27 : jsonb_object_agg_finalfn(PG_FUNCTION_ARGS)
    2030 ECB             : {
    2031                 :     JsonbAggState *arg;
    2032                 :     JsonbInState result;
    2033                 :     Jsonb      *out;
    2034                 : 
    2035                 :     /* cannot be called directly because of internal-type argument */
    2036 GIC          27 :     Assert(AggCheckCallContext(fcinfo, NULL));
    2037 ECB             : 
    2038 GIC          27 :     if (PG_ARGISNULL(0))
    2039 CBC           3 :         PG_RETURN_NULL();       /* returns null iff no input values */
    2040                 : 
    2041 GIC          24 :     arg = (JsonbAggState *) PG_GETARG_POINTER(0);
    2042 ECB             : 
    2043                 :     /*
    2044                 :      * We need to do a shallow clone of the argument's res field in case the
    2045                 :      * final function is called more than once, so we avoid changing the
    2046                 :      * aggregate state value.  A shallow clone is sufficient as we aren't
    2047                 :      * going to change any of the values, just add the final object end
    2048                 :      * marker.
    2049                 :      */
    2050 GNC          24 :     memset(&result, 0, sizeof(JsonbInState));
    2051                 : 
    2052 GIC          24 :     result.parseState = clone_parse_state(arg->res->parseState);
    2053                 : 
    2054              24 :     result.res = pushJsonbValue(&result.parseState,
    2055                 :                                 WJB_END_OBJECT, NULL);
    2056                 : 
    2057 CBC          18 :     out = JsonbValueToJsonb(result.res);
    2058                 : 
    2059              18 :     PG_RETURN_POINTER(out);
    2060                 : }
    2061 ECB             : 
    2062                 : 
    2063 EUB             : /*
    2064 ECB             :  * Extract scalar value from raw-scalar pseudo-array jsonb.
    2065                 :  */
    2066                 : bool
    2067 GIC       95340 : JsonbExtractScalar(JsonbContainer *jbc, JsonbValue *res)
    2068                 : {
    2069 ECB             :     JsonbIterator *it;
    2070                 :     JsonbIteratorToken tok PG_USED_FOR_ASSERTS_ONLY;
    2071                 :     JsonbValue  tmp;
    2072                 : 
    2073 GIC       95340 :     if (!JsonContainerIsArray(jbc) || !JsonContainerIsScalar(jbc))
    2074                 :     {
    2075                 :         /* inform caller about actual type of container */
    2076 GBC       94890 :         res->type = (JsonContainerIsArray(jbc)) ? jbvArray : jbvObject;
    2077 GIC       94890 :         return false;
    2078                 :     }
    2079                 : 
    2080 ECB             :     /*
    2081                 :      * A root scalar is stored as an array of one element, so we get the array
    2082                 :      * and then its first (and only) member.
    2083                 :      */
    2084 GIC         450 :     it = JsonbIteratorInit(jbc);
    2085 ECB             : 
    2086 CBC         450 :     tok = JsonbIteratorNext(&it, &tmp, true);
    2087 GIC         450 :     Assert(tok == WJB_BEGIN_ARRAY);
    2088 CBC         450 :     Assert(tmp.val.array.nElems == 1 && tmp.val.array.rawScalar);
    2089 ECB             : 
    2090 GIC         450 :     tok = JsonbIteratorNext(&it, res, true);
    2091             450 :     Assert(tok == WJB_ELEM);
    2092 CBC         450 :     Assert(IsAJsonbScalar(res));
    2093 ECB             : 
    2094 CBC         450 :     tok = JsonbIteratorNext(&it, &tmp, true);
    2095 GBC         450 :     Assert(tok == WJB_END_ARRAY);
    2096 EUB             : 
    2097 GIC         450 :     tok = JsonbIteratorNext(&it, &tmp, true);
    2098             450 :     Assert(tok == WJB_DONE);
    2099                 : 
    2100             450 :     return true;
    2101 ECB             : }
    2102                 : 
    2103                 : /*
    2104                 :  * Emit correct, translatable cast error message
    2105                 :  */
    2106                 : static void
    2107 GIC          12 : cannotCastJsonbValue(enum jbvType type, const char *sqltype)
    2108                 : {
    2109                 :     static const struct
    2110                 :     {
    2111 ECB             :         enum jbvType type;
    2112                 :         const char *msg;
    2113                 :     }
    2114                 :                 messages[] =
    2115                 :     {
    2116                 :         {jbvNull, gettext_noop("cannot cast jsonb null to type %s")},
    2117                 :         {jbvString, gettext_noop("cannot cast jsonb string to type %s")},
    2118                 :         {jbvNumeric, gettext_noop("cannot cast jsonb numeric to type %s")},
    2119 EUB             :         {jbvBool, gettext_noop("cannot cast jsonb boolean to type %s")},
    2120                 :         {jbvArray, gettext_noop("cannot cast jsonb array to type %s")},
    2121 ECB             :         {jbvObject, gettext_noop("cannot cast jsonb object to type %s")},
    2122                 :         {jbvBinary, gettext_noop("cannot cast jsonb array or object to type %s")}
    2123                 :     };
    2124 EUB             :     int         i;
    2125                 : 
    2126 CBC          54 :     for (i = 0; i < lengthof(messages); i++)
    2127              54 :         if (messages[i].type == type)
    2128 GIC          12 :             ereport(ERROR,
    2129 ECB             :                     (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    2130                 :                      errmsg(messages[i].msg, sqltype)));
    2131                 : 
    2132                 :     /* should be unreachable */
    2133 UIC           0 :     elog(ERROR, "unknown jsonb type: %d", (int) type);
    2134                 : }
    2135 ECB             : 
    2136                 : Datum
    2137 GIC           6 : jsonb_bool(PG_FUNCTION_ARGS)
    2138 ECB             : {
    2139 GIC           6 :     Jsonb      *in = PG_GETARG_JSONB_P(0);
    2140 ECB             :     JsonbValue  v;
    2141                 : 
    2142 GIC           6 :     if (!JsonbExtractScalar(&in->root, &v) || v.type != jbvBool)
    2143 CBC           3 :         cannotCastJsonbValue(v.type, "boolean");
    2144                 : 
    2145 GIC           3 :     PG_FREE_IF_COPY(in, 0);
    2146 ECB             : 
    2147 CBC           3 :     PG_RETURN_BOOL(v.val.boolean);
    2148                 : }
    2149                 : 
    2150 ECB             : Datum
    2151 GIC          12 : jsonb_numeric(PG_FUNCTION_ARGS)
    2152                 : {
    2153 CBC          12 :     Jsonb      *in = PG_GETARG_JSONB_P(0);
    2154 EUB             :     JsonbValue  v;
    2155                 :     Numeric     retValue;
    2156                 : 
    2157 GIC          12 :     if (!JsonbExtractScalar(&in->root, &v) || v.type != jbvNumeric)
    2158               3 :         cannotCastJsonbValue(v.type, "numeric");
    2159 ECB             : 
    2160                 :     /*
    2161                 :      * v.val.numeric points into jsonb body, so we need to make a copy to
    2162                 :      * return
    2163                 :      */
    2164 GIC           9 :     retValue = DatumGetNumericCopy(NumericGetDatum(v.val.numeric));
    2165                 : 
    2166               9 :     PG_FREE_IF_COPY(in, 0);
    2167                 : 
    2168 CBC           9 :     PG_RETURN_NUMERIC(retValue);
    2169                 : }
    2170 ECB             : 
    2171                 : Datum
    2172 GIC           6 : jsonb_int2(PG_FUNCTION_ARGS)
    2173                 : {
    2174               6 :     Jsonb      *in = PG_GETARG_JSONB_P(0);
    2175                 :     JsonbValue  v;
    2176                 :     Datum       retValue;
    2177                 : 
    2178 CBC           6 :     if (!JsonbExtractScalar(&in->root, &v) || v.type != jbvNumeric)
    2179 UIC           0 :         cannotCastJsonbValue(v.type, "smallint");
    2180 ECB             : 
    2181 GIC           6 :     retValue = DirectFunctionCall1(numeric_int2,
    2182                 :                                    NumericGetDatum(v.val.numeric));
    2183                 : 
    2184               6 :     PG_FREE_IF_COPY(in, 0);
    2185                 : 
    2186               6 :     PG_RETURN_DATUM(retValue);
    2187 ECB             : }
    2188                 : 
    2189                 : Datum
    2190 GIC          12 : jsonb_int4(PG_FUNCTION_ARGS)
    2191                 : {
    2192              12 :     Jsonb      *in = PG_GETARG_JSONB_P(0);
    2193                 :     JsonbValue  v;
    2194                 :     Datum       retValue;
    2195                 : 
    2196 CBC          12 :     if (!JsonbExtractScalar(&in->root, &v) || v.type != jbvNumeric)
    2197 GIC           3 :         cannotCastJsonbValue(v.type, "integer");
    2198 ECB             : 
    2199 GIC           9 :     retValue = DirectFunctionCall1(numeric_int4,
    2200                 :                                    NumericGetDatum(v.val.numeric));
    2201                 : 
    2202 CBC           9 :     PG_FREE_IF_COPY(in, 0);
    2203                 : 
    2204 GIC           9 :     PG_RETURN_DATUM(retValue);
    2205                 : }
    2206                 : 
    2207                 : Datum
    2208              24 : jsonb_int8(PG_FUNCTION_ARGS)
    2209 ECB             : {
    2210 GIC          24 :     Jsonb      *in = PG_GETARG_JSONB_P(0);
    2211 ECB             :     JsonbValue  v;
    2212                 :     Datum       retValue;
    2213                 : 
    2214 CBC          24 :     if (!JsonbExtractScalar(&in->root, &v) || v.type != jbvNumeric)
    2215 UIC           0 :         cannotCastJsonbValue(v.type, "bigint");
    2216                 : 
    2217 GIC          24 :     retValue = DirectFunctionCall1(numeric_int8,
    2218                 :                                    NumericGetDatum(v.val.numeric));
    2219                 : 
    2220              24 :     PG_FREE_IF_COPY(in, 0);
    2221                 : 
    2222              24 :     PG_RETURN_DATUM(retValue);
    2223 ECB             : }
    2224                 : 
    2225                 : Datum
    2226 GIC           6 : jsonb_float4(PG_FUNCTION_ARGS)
    2227 ECB             : {
    2228 GIC           6 :     Jsonb      *in = PG_GETARG_JSONB_P(0);
    2229                 :     JsonbValue  v;
    2230 ECB             :     Datum       retValue;
    2231                 : 
    2232 CBC           6 :     if (!JsonbExtractScalar(&in->root, &v) || v.type != jbvNumeric)
    2233 UIC           0 :         cannotCastJsonbValue(v.type, "real");
    2234                 : 
    2235 GIC           6 :     retValue = DirectFunctionCall1(numeric_float4,
    2236                 :                                    NumericGetDatum(v.val.numeric));
    2237                 : 
    2238               6 :     PG_FREE_IF_COPY(in, 0);
    2239                 : 
    2240 CBC           6 :     PG_RETURN_DATUM(retValue);
    2241                 : }
    2242                 : 
    2243                 : Datum
    2244 GIC          12 : jsonb_float8(PG_FUNCTION_ARGS)
    2245                 : {
    2246 CBC          12 :     Jsonb      *in = PG_GETARG_JSONB_P(0);
    2247                 :     JsonbValue  v;
    2248                 :     Datum       retValue;
    2249 ECB             : 
    2250 CBC          12 :     if (!JsonbExtractScalar(&in->root, &v) || v.type != jbvNumeric)
    2251 GIC           3 :         cannotCastJsonbValue(v.type, "double precision");
    2252                 : 
    2253               9 :     retValue = DirectFunctionCall1(numeric_float8,
    2254                 :                                    NumericGetDatum(v.val.numeric));
    2255                 : 
    2256               9 :     PG_FREE_IF_COPY(in, 0);
    2257 ECB             : 
    2258 GIC           9 :     PG_RETURN_DATUM(retValue);
    2259 ECB             : }
        

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