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 17:13:01 Functions: 94.6 % 56 53 1 2 38 15 2 51 1 2
Baseline: 15 Line coverage date bins:
Baseline Date: 2023-04-08 15:09:40 [..60] days: 77.8 % 63 49 14 49 1
Legend: Lines: hit not hit (60,120] days: 86.2 % 29 25 4 25
(180,240] days: 92.3 % 13 12 1 4 4 4 4
(240..) days: 90.1 % 797 718 25 42 12 24 401 3 290 52 386
Function coverage date bins:
[..60] days: 92.3 % 13 12 1 12
(60,120] days: 100.0 % 2 2 2
(180,240] days: 100.0 % 1 1 1
(240..) days: 44.7 % 85 38 2 38 2 43

 Age         Owner                  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
 3304 andrew                     99 GIC       10821 : jsonb_in(PG_FUNCTION_ARGS)
                                100                 : {
 3304 andrew                    101 CBC       10821 :     char       *json = PG_GETARG_CSTRING(0);
                                102                 : 
  119 tgl                       103 GNC       10821 :     return jsonb_from_cstring(json, strlen(json), fcinfo->context);
                                104                 : }
 3304 andrew                    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
 3304 andrew                    115 UIC           0 : jsonb_recv(PG_FUNCTION_ARGS)
                                116                 : {
 3304 andrew                    117 UBC           0 :     StringInfo  buf = (StringInfo) PG_GETARG_POINTER(0);
 3304 andrew                    118 UIC           0 :     int         version = pq_getmsgint(buf, 1);
 3304 andrew                    119 EUB             :     char       *str;
                                120                 :     int         nbytes;
                                121                 : 
 3304 andrew                    122 UIC           0 :     if (version == 1)
                                123               0 :         str = pq_getmsgtext(buf, buf->len - buf->cursor, &nbytes);
 3304 andrew                    124 EUB             :     else
 3259 heikki.linnakangas        125 UBC           0 :         elog(ERROR, "unsupported jsonb version number %d", version);
                                126                 : 
  119 tgl                       127 UNC           0 :     return jsonb_from_cstring(str, nbytes, NULL);
                                128                 : }
 3304 andrew                    129 EUB             : 
                                130                 : /*
                                131                 :  * jsonb type output function
                                132                 :  */
                                133                 : Datum
 3304 andrew                    134 GIC        9383 : jsonb_out(PG_FUNCTION_ARGS)
                                135                 : {
 2029 tgl                       136 CBC        9383 :     Jsonb      *jb = PG_GETARG_JSONB_P(0);
                                137                 :     char       *out;
 3304 andrew                    138 ECB             : 
 3259 heikki.linnakangas        139 GIC        9383 :     out = JsonbToCString(NULL, &jb->root, VARSIZE(jb));
                                140                 : 
 3304 andrew                    141 CBC        9383 :     PG_RETURN_CSTRING(out);
                                142                 : }
 3304 andrew                    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
 3304 andrew                    150 UIC           0 : jsonb_send(PG_FUNCTION_ARGS)
                                151                 : {
 2029 tgl                       152 UBC           0 :     Jsonb      *jb = PG_GETARG_JSONB_P(0);
                                153                 :     StringInfoData buf;
 3304 andrew                    154               0 :     StringInfo  jtext = makeStringInfo();
 3304 andrew                    155 UIC           0 :     int         version = 1;
 3304 andrew                    156 EUB             : 
 3259 heikki.linnakangas        157 UBC           0 :     (void) JsonbToCString(jtext, &jb->root, VARSIZE(jb));
                                158                 : 
 3304 andrew                    159               0 :     pq_begintypsend(&buf);
 2006 andres                    160 UIC           0 :     pq_sendint8(&buf, version);
 3304 andrew                    161 UBC           0 :     pq_sendtext(&buf, jtext->data, jtext->len);
                                162               0 :     pfree(jtext->data);
                                163               0 :     pfree(jtext);
 3304 andrew                    164 EUB             : 
 3304 andrew                    165 UBC           0 :     PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
                                166                 : }
 3304 andrew                    167 EUB             : 
                                168                 : /*
                                169                 :  * Get the type name of a jsonb container.
                                170                 :  */
                                171                 : static const char *
 1485 akorotkov                 172 GIC         153 : JsonbContainerTypeName(JsonbContainer *jbc)
                                173                 : {
 1485 akorotkov                 174 ECB             :     JsonbValue  scalar;
                                175                 : 
 1485 akorotkov                 176 GIC         153 :     if (JsonbExtractScalar(jbc, &scalar))
                                177              33 :         return JsonbTypeName(&scalar);
 1485 akorotkov                 178 CBC         120 :     else if (JsonContainerIsArray(jbc))
                                179              51 :         return "array";
                                180              69 :     else if (JsonContainerIsObject(jbc))
                                181              69 :         return "object";
 1485 akorotkov                 182 ECB             :     else
                                183                 :     {
 1485 akorotkov                 184 UIC           0 :         elog(ERROR, "invalid jsonb container type: 0x%08x", jbc->header);
                                185                 :         return "unknown";
 1485 akorotkov                 186 EUB             :     }
                                187                 : }
                                188                 : 
                                189                 : /*
                                190                 :  * Get the type name of a jsonb value.
                                191                 :  */
                                192                 : const char *
  201 pg                        193 GNC         138 : JsonbTypeName(JsonbValue *val)
                                194                 : {
                                195             138 :     switch (val->type)
                                196                 :     {
 1485 akorotkov                 197 CBC          12 :         case jbvBinary:
  201 pg                        198 GNC          12 :             return JsonbContainerTypeName(val->val.binary.data);
 1485 akorotkov                 199 LBC           0 :         case jbvObject:
                                200               0 :             return "object";
 1485 akorotkov                 201 UBC           0 :         case jbvArray:
                                202               0 :             return "array";
 1485 akorotkov                 203 GBC          45 :         case jbvNumeric:
                                204              45 :             return "number";
 1485 akorotkov                 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";
 1292                           211              36 :         case jbvDatetime:
  201 pg                        212 GNC          36 :             switch (val->val.datetime.typid)
 1292 akorotkov                 213 ECB             :             {
 1292 akorotkov                 214 CBC           6 :                 case DATEOID:
 1292 akorotkov                 215 GIC           6 :                     return "date";
 1292 akorotkov                 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";
 1292 akorotkov                 224 LBC           0 :                 default:
                                225               0 :                     elog(ERROR, "unrecognized jsonb value datetime type: %d",
                                226                 :                          val->val.datetime.typid);
 1292 akorotkov                 227 EUB             :             }
                                228                 :             return "unknown";
 1485 akorotkov                 229 UIC           0 :         default:
  201 pg                        230 UNC           0 :             elog(ERROR, "unrecognized jsonb value type: %d", val->type);
 1485 akorotkov                 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
 3304 andrew                    242 GIC         141 : jsonb_typeof(PG_FUNCTION_ARGS)
                                243                 : {
 2029 tgl                       244 CBC         141 :     Jsonb      *in = PG_GETARG_JSONB_P(0);
 1485 akorotkov                 245 GIC         141 :     const char *result = JsonbContainerTypeName(&in->root);
 3304 andrew                    246 ECB             : 
 3304 andrew                    247 CBC         141 :     PG_RETURN_TEXT_P(cstring_to_text(result));
                                248                 : }
 3304 andrew                    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
  119 tgl                       261 GNC       10821 : jsonb_from_cstring(char *json, int len, Node *escontext)
                                262                 : {
                                263                 :     JsonLexContext *lex;
                                264                 :     JsonbInState state;
                                265                 :     JsonSemAction sem;
 3304 andrew                    266 ECB             : 
 3304 andrew                    267 GIC       10821 :     memset(&state, 0, sizeof(state));
                                268           10821 :     memset(&sem, 0, sizeof(sem));
 1166 rhaas                     269           10821 :     lex = makeJsonLexContextCstringLen(json, len, GetDatabaseEncoding(), true);
                                270                 : 
  119 tgl                       271 GNC       10821 :     state.escontext = escontext;
 3304 andrew                    272 GIC       10821 :     sem.semstate = (void *) &state;
 3304 andrew                    273 ECB             : 
 3304 andrew                    274 CBC       10821 :     sem.object_start = jsonb_in_object_start;
                                275           10821 :     sem.array_start = jsonb_in_array_start;
 3304 andrew                    276 GIC       10821 :     sem.object_end = jsonb_in_object_end;
 3304 andrew                    277 CBC       10821 :     sem.array_end = jsonb_in_array_end;
                                278           10821 :     sem.scalar = jsonb_in_scalar;
 3304 andrew                    279 GIC       10821 :     sem.object_field_start = jsonb_in_object_field_start;
 3304 andrew                    280 ECB             : 
  119 tgl                       281 GNC       10821 :     if (!pg_parse_json_or_errsave(lex, &sem, escontext))
                                282               9 :         return (Datum) 0;
 3304 andrew                    283 ECB             : 
                                284                 :     /* after parsing, the item member has the composed jsonb structure */
 3304 andrew                    285 CBC       10695 :     PG_RETURN_POINTER(JsonbValueToJsonb(state.res));
 3304 andrew                    286 ECB             : }
                                287                 : 
                                288                 : static bool
  119 tgl                       289 GNC       35123 : checkStringLen(size_t len, Node *escontext)
                                290                 : {
 3114 tgl                       291 GIC       35123 :     if (len > JENTRY_OFFLENMASK)
  119 tgl                       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.",
 3114 tgl                       296 ECB             :                            JENTRY_OFFLENMASK)));
                                297                 : 
  119 tgl                       298 GNC       35123 :     return true;
 3304 andrew                    299 EUB             : }
                                300                 : 
                                301                 : static JsonParseErrorType
 3304 andrew                    302 GIC       12330 : jsonb_in_object_start(void *pstate)
                                303                 : {
                                304           12330 :     JsonbInState *_state = (JsonbInState *) pstate;
 3304 andrew                    305 ECB             : 
 3304 andrew                    306 GIC       12330 :     _state->res = pushJsonbValue(&_state->parseState, WJB_BEGIN_OBJECT, NULL);
                                307                 : 
  119 tgl                       308 GNC       12330 :     return JSON_SUCCESS;
                                309                 : }
                                310                 : 
                                311                 : static JsonParseErrorType
 3304 andrew                    312 GIC       10319 : jsonb_in_object_end(void *pstate)
 3304 andrew                    313 ECB             : {
 3304 andrew                    314 GIC       10319 :     JsonbInState *_state = (JsonbInState *) pstate;
 3304 andrew                    315 ECB             : 
 3304 andrew                    316 GIC       10319 :     _state->res = pushJsonbValue(&_state->parseState, WJB_END_OBJECT, NULL);
                                317                 : 
  119 tgl                       318 GNC       10319 :     return JSON_SUCCESS;
 3304 andrew                    319 ECB             : }
                                320                 : 
                                321                 : static JsonParseErrorType
 3304 andrew                    322 GIC        5185 : jsonb_in_array_start(void *pstate)
 3304 andrew                    323 ECB             : {
 3304 andrew                    324 GIC        5185 :     JsonbInState *_state = (JsonbInState *) pstate;
 3304 andrew                    325 ECB             : 
 3304 andrew                    326 GIC        5185 :     _state->res = pushJsonbValue(&_state->parseState, WJB_BEGIN_ARRAY, NULL);
                                327                 : 
  119 tgl                       328 GNC        5185 :     return JSON_SUCCESS;
 3304 andrew                    329 ECB             : }
                                330                 : 
                                331                 : static JsonParseErrorType
 3304 andrew                    332 GIC        2979 : jsonb_in_array_end(void *pstate)
                                333                 : {
                                334            2979 :     JsonbInState *_state = (JsonbInState *) pstate;
 3304 andrew                    335 ECB             : 
 3304 andrew                    336 GIC        2979 :     _state->res = pushJsonbValue(&_state->parseState, WJB_END_ARRAY, NULL);
                                337                 : 
  119 tgl                       338 GNC        2979 :     return JSON_SUCCESS;
 3304 andrew                    339 ECB             : }
                                340                 : 
                                341                 : static JsonParseErrorType
 3304 andrew                    342 GIC       23806 : jsonb_in_object_field_start(void *pstate, char *fname, bool isnull)
 3304 andrew                    343 ECB             : {
 3304 andrew                    344 GIC       23806 :     JsonbInState *_state = (JsonbInState *) pstate;
                                345                 :     JsonbValue  v;
                                346                 : 
 3260 bruce                     347 CBC       23806 :     Assert(fname != NULL);
 3304 andrew                    348 GIC       23806 :     v.type = jbvString;
  119 tgl                       349 GNC       23806 :     v.val.string.len = strlen(fname);
                                350           23806 :     if (!checkStringLen(v.val.string.len, _state->escontext))
  119 tgl                       351 UNC           0 :         return JSON_SEM_ACTION_FAILED;
 3257 heikki.linnakangas        352 GIC       23806 :     v.val.string.val = fname;
 3304 andrew                    353 ECB             : 
 3304 andrew                    354 GIC       23806 :     _state->res = pushJsonbValue(&_state->parseState, WJB_KEY, &v);
                                355                 : 
  119 tgl                       356 GNC       23806 :     return JSON_SUCCESS;
 3304 andrew                    357 ECB             : }
                                358                 : 
                                359                 : static void
 3260 bruce                     360 GIC       50532 : jsonb_put_escaped_value(StringInfo out, JsonbValue *scalarVal)
 3304 andrew                    361 ECB             : {
 3304 andrew                    362 GIC       50532 :     switch (scalarVal->type)
 3304 andrew                    363 ECB             :     {
 3304 andrew                    364 GIC         464 :         case jbvNull:
                                365             464 :             appendBinaryStringInfo(out, "null", 4);
 3304 andrew                    366 CBC         464 :             break;
                                367           34323 :         case jbvString:
 3294 tgl                       368           34323 :             escape_json(out, pnstrdup(scalarVal->val.string.val, scalarVal->val.string.len));
 3304 andrew                    369           34323 :             break;
 3304 andrew                    370 GBC        9645 :         case jbvNumeric:
 3304 andrew                    371 CBC        9645 :             appendStringInfoString(out,
 2118 tgl                       372 GIC        9645 :                                    DatumGetCString(DirectFunctionCall1(numeric_out,
 2118 tgl                       373 ECB             :                                                                        PointerGetDatum(scalarVal->val.numeric))));
 3304 andrew                    374 GIC        9645 :             break;
 3304 andrew                    375 CBC        6100 :         case jbvBool:
 3294 tgl                       376 GIC        6100 :             if (scalarVal->val.boolean)
 3304 andrew                    377            2876 :                 appendBinaryStringInfo(out, "true", 4);
                                378                 :             else
 3304 andrew                    379 CBC        3224 :                 appendBinaryStringInfo(out, "false", 5);
 3304 andrew                    380 GIC        6100 :             break;
 3304 andrew                    381 LBC           0 :         default:
 3304 andrew                    382 UIC           0 :             elog(ERROR, "unknown jsonb scalar type");
 3304 andrew                    383 ECB             :     }
 3304 andrew                    384 CBC       50532 : }
 3304 andrew                    385 ECB             : 
                                386                 : /*
                                387                 :  * For jsonb we always want the de-escaped value - that's what's in token
                                388                 :  */
                                389                 : static JsonParseErrorType
 3304 andrew                    390 CBC       26289 : jsonb_in_scalar(void *pstate, char *token, JsonTokenType tokentype)
 3304 andrew                    391 ECB             : {
 3304 andrew                    392 GIC       26289 :     JsonbInState *_state = (JsonbInState *) pstate;
 3304 andrew                    393 ECB             :     JsonbValue  v;
 1803 tgl                       394                 :     Datum       numd;
 3304 andrew                    395                 : 
 3304 andrew                    396 CBC       26289 :     switch (tokentype)
                                397                 :     {
 3304 andrew                    398 ECB             : 
 3304 andrew                    399 CBC       10822 :         case JSON_TOKEN_STRING:
 3260 bruce                     400 GBC       10822 :             Assert(token != NULL);
 3304 andrew                    401           10822 :             v.type = jbvString;
  119 tgl                       402 GNC       10822 :             v.val.string.len = strlen(token);
                                403           10822 :             if (!checkStringLen(v.val.string.len, _state->escontext))
  119 tgl                       404 UNC           0 :                 return JSON_SEM_ACTION_FAILED;
 3257 heikki.linnakangas        405 CBC       10822 :             v.val.string.val = token;
 3304 andrew                    406 GIC       10822 :             break;
                                407           11311 :         case JSON_TOKEN_NUMBER:
                                408                 : 
                                409                 :             /*
                                410                 :              * No need to check size of numeric values, because maximum
 3260 bruce                     411 ECB             :              * numeric size is well below the JsonbValue restriction
                                412                 :              */
 3260 bruce                     413 CBC       11311 :             Assert(token != NULL);
 3304 andrew                    414 GIC       11311 :             v.type = jbvNumeric;
  119 tgl                       415 GNC       11311 :             if (!DirectInputFunctionCallSafe(numeric_in, token,
                                416                 :                                              InvalidOid, -1,
                                417           11311 :                                              _state->escontext,
                                418                 :                                              &numd))
                                419               3 :                 return JSON_SEM_ACTION_FAILED;
 1803 tgl                       420 GIC       11308 :             v.val.numeric = DatumGetNumeric(numd);
 3304 andrew                    421 CBC       11308 :             break;
                                422            1630 :         case JSON_TOKEN_TRUE:
                                423            1630 :             v.type = jbvBool;
 3294 tgl                       424            1630 :             v.val.boolean = true;
 3304 andrew                    425            1630 :             break;
 3304 andrew                    426 GBC        1616 :         case JSON_TOKEN_FALSE:
 3304 andrew                    427 CBC        1616 :             v.type = jbvBool;
 3294 tgl                       428            1616 :             v.val.boolean = false;
 3304 andrew                    429            1616 :             break;
 3304 andrew                    430 GIC         910 :         case JSON_TOKEN_NULL:
                                431             910 :             v.type = jbvNull;
                                432             910 :             break;
 3304 andrew                    433 UIC           0 :         default:
                                434                 :             /* should not be possible */
 3304 andrew                    435 LBC           0 :             elog(ERROR, "invalid json token type");
 3304 andrew                    436 ECB             :             break;
                                437                 :     }
                                438                 : 
 3304 andrew                    439 CBC       26286 :     if (_state->parseState == NULL)
                                440                 :     {
 3304 andrew                    441 ECB             :         /* single scalar */
                                442                 :         JsonbValue  va;
                                443                 : 
 3304 andrew                    444 CBC        1139 :         va.type = jbvArray;
 3294 tgl                       445            1139 :         va.val.array.rawScalar = true;
                                446            1139 :         va.val.array.nElems = 1;
 3304 andrew                    447 ECB             : 
 3304 andrew                    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);
 3304 andrew                    451 ECB             :     }
                                452                 :     else
                                453                 :     {
 3304 andrew                    454 CBC       25147 :         JsonbValue *o = &_state->parseState->contVal;
 3304 andrew                    455 EUB             : 
 3304 andrew                    456 GIC       25147 :         switch (o->type)
 3304 andrew                    457 EUB             :         {
 3304 andrew                    458 GIC        5317 :             case jbvArray:
                                459            5317 :                 _state->res = pushJsonbValue(&_state->parseState, WJB_ELEM, &v);
                                460            5317 :                 break;
 3304 andrew                    461 CBC       19830 :             case jbvObject:
 3304 andrew                    462 GIC       19830 :                 _state->res = pushJsonbValue(&_state->parseState, WJB_VALUE, &v);
                                463           19830 :                 break;
 3304 andrew                    464 UIC           0 :             default:
                                465               0 :                 elog(ERROR, "unexpected parent of nested structure");
 3304 andrew                    466 ECB             :         }
                                467                 :     }
                                468                 : 
  119 tgl                       469 GNC       26286 :     return JSON_SUCCESS;
 3304 andrew                    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 *
 3259 heikki.linnakangas        484 CBC        9980 : JsonbToCString(StringInfo out, JsonbContainer *in, int estimated_len)
 2889 andrew                    485 ECB             : {
 2889 andrew                    486 CBC        9980 :     return JsonbToCStringWorker(out, in, estimated_len, false);
 2889 andrew                    487 ECB             : }
 2889 andrew                    488 EUB             : 
                                489                 : /*
                                490                 :  * same thing but with indentation turned on
                                491                 :  */
                                492                 : char *
 2889 andrew                    493 CBC          18 : JsonbToCStringIndent(StringInfo out, JsonbContainer *in, int estimated_len)
                                494                 : {
 2889 andrew                    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                 : {
 3304                           504            9998 :     bool        first = true;
                                505                 :     JsonbIterator *it;
                                506                 :     JsonbValue  v;
 2737 noah                      507            9998 :     JsonbIteratorToken type = WJB_DONE;
 3304 andrew                    508 CBC        9998 :     int         level = 0;
 3304 andrew                    509 GIC        9998 :     bool        redo_switch = false;
 2878 bruce                     510 ECB             : 
                                511                 :     /* If we are indenting, don't add a space after a comma */
 2889 andrew                    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.
 2889 andrew                    517 ECB             :      */
 2878 bruce                     518 GIC        9998 :     bool        use_indent = false;
 2878 bruce                     519 CBC        9998 :     bool        raw_scalar = false;
 2878 bruce                     520 GIC        9998 :     bool        last_was_key = false;
                                521                 : 
 3304 andrew                    522            9998 :     if (out == NULL)
                                523            9917 :         out = makeStringInfo();
                                524                 : 
                                525            9998 :     enlargeStringInfo(out, (estimated_len >= 0) ? estimated_len : 64);
 3304 andrew                    526 ECB             : 
 3304 andrew                    527 GIC        9998 :     it = JsonbIteratorInit(in);
 3304 andrew                    528 ECB             : 
 3304 andrew                    529 GIC      122236 :     while (redo_switch ||
                                530           60743 :            ((type = JsonbIteratorNext(&it, &v, false)) != WJB_DONE))
 3304 andrew                    531 ECB             :     {
 3304 andrew                    532 CBC       51495 :         redo_switch = false;
                                533           51495 :         switch (type)
                                534                 :         {
 3304 andrew                    535 GIC        5138 :             case WJB_BEGIN_ARRAY:
 3304 andrew                    536 CBC        5138 :                 if (!first)
 2889 andrew                    537 GIC          54 :                     appendBinaryStringInfo(out, ", ", ispaces);
                                538                 : 
 3294 tgl                       539            5138 :                 if (!v.val.array.rawScalar)
                                540                 :                 {
 2889 andrew                    541            1260 :                     add_indent(out, use_indent && !last_was_key, level);
 2889 andrew                    542 CBC        1260 :                     appendStringInfoCharMacro(out, '[');
 2889 andrew                    543 ECB             :                 }
                                544                 :                 else
 2889 andrew                    545 GIC        3878 :                     raw_scalar = true;
 2889 andrew                    546 ECB             : 
 2889 andrew                    547 CBC        5138 :                 first = true;
 3304 andrew                    548 GIC        5138 :                 level++;
 3304 andrew                    549 CBC        5138 :                 break;
 3304 andrew                    550 GIC        6276 :             case WJB_BEGIN_OBJECT:
 3304 andrew                    551 CBC        6276 :                 if (!first)
 2889 andrew                    552 GIC         167 :                     appendBinaryStringInfo(out, ", ", ispaces);
 2889 andrew                    553 ECB             : 
 2889 andrew                    554 CBC        6276 :                 add_indent(out, use_indent && !last_was_key, level);
 3304 andrew                    555 GIC        6276 :                 appendStringInfoCharMacro(out, '{');
 3304 andrew                    556 ECB             : 
 2889 andrew                    557 CBC        6276 :                 first = true;
 3304 andrew                    558 GIC        6276 :                 level++;
 3304 andrew                    559 CBC        6276 :                 break;
                                560           22615 :             case WJB_KEY:
                                561           22615 :                 if (!first)
 2889 andrew                    562 GIC       16882 :                     appendBinaryStringInfo(out, ", ", ispaces);
 3304 andrew                    563 CBC       22615 :                 first = true;
                                564                 : 
 2889                           565           22615 :                 add_indent(out, use_indent, level);
 2889 andrew                    566 ECB             : 
                                567                 :                 /* json rules guarantee this is a string */
 3304 andrew                    568 GIC       22615 :                 jsonb_put_escaped_value(out, &v);
 3304 andrew                    569 CBC       22615 :                 appendBinaryStringInfo(out, ": ", 2);
                                570                 : 
                                571           22615 :                 type = JsonbIteratorNext(&it, &v, false);
                                572           22615 :                 if (type == WJB_VALUE)
 3304 andrew                    573 ECB             :                 {
 3304 andrew                    574 CBC       21865 :                     first = false;
                                575           21865 :                     jsonb_put_escaped_value(out, &v);
 3304 andrew                    576 ECB             :                 }
                                577                 :                 else
                                578                 :                 {
 3304 andrew                    579 CBC         750 :                     Assert(type == WJB_BEGIN_OBJECT || type == WJB_BEGIN_ARRAY);
                                580                 : 
 3304 andrew                    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                 :                      */
 3304 andrew                    586 CBC         750 :                     redo_switch = true;
 3304 andrew                    587 ECB             :                 }
 3304 andrew                    588 GIC       22615 :                 break;
 3304 andrew                    589 CBC        6052 :             case WJB_ELEM:
 3304 andrew                    590 GIC        6052 :                 if (!first)
 2889                           591            1411 :                     appendBinaryStringInfo(out, ", ", ispaces);
 2889 andrew                    592 CBC        6052 :                 first = false;
 3304 andrew                    593 ECB             : 
 2878 bruce                     594 GIC        6052 :                 if (!raw_scalar)
 2889 andrew                    595 CBC        2174 :                     add_indent(out, use_indent, level);
 3304                           596            6052 :                 jsonb_put_escaped_value(out, &v);
 3304 andrew                    597 GIC        6052 :                 break;
 3304 andrew                    598 CBC        5138 :             case WJB_END_ARRAY:
                                599            5138 :                 level--;
 2878 bruce                     600 GIC        5138 :                 if (!raw_scalar)
                                601                 :                 {
 2889 andrew                    602            1260 :                     add_indent(out, use_indent, level);
 2889 andrew                    603 CBC        1260 :                     appendStringInfoCharMacro(out, ']');
                                604                 :                 }
 3304 andrew                    605 GIC        5138 :                 first = false;
                                606            5138 :                 break;
                                607            6276 :             case WJB_END_OBJECT:
                                608            6276 :                 level--;
 2889                           609            6276 :                 add_indent(out, use_indent, level);
 3304 andrew                    610 CBC        6276 :                 appendStringInfoCharMacro(out, '}');
 3304 andrew                    611 GIC        6276 :                 first = false;
 3304 andrew                    612 CBC        6276 :                 break;
 3304 andrew                    613 LBC           0 :             default:
 2963 alvherre                  614               0 :                 elog(ERROR, "unknown jsonb iterator token type");
 3304 andrew                    615 ECB             :         }
 2889 andrew                    616 CBC       51495 :         use_indent = indent;
 2889 andrew                    617 GIC       51495 :         last_was_key = redo_switch;
 3304 andrew                    618 ECB             :     }
                                619                 : 
 3304 andrew                    620 CBC        9998 :     Assert(level == 0);
 3304 andrew                    621 ECB             : 
 3304 andrew                    622 CBC        9998 :     return out->data;
 3304 andrew                    623 ECB             : }
 3040                           624                 : 
                                625                 : static void
 2889 andrew                    626 CBC       39861 : add_indent(StringInfo out, bool indent, int level)
 2889 andrew                    627 ECB             : {
 2889 andrew                    628 GIC       39861 :     if (indent)
 2889 andrew                    629 ECB             :     {
 2889 andrew                    630 CBC         783 :         appendStringInfoCharMacro(out, '\n');
   79 drowley                   631 GNC         783 :         appendStringInfoSpaces(out, level * 4);
 2889 andrew                    632 ECB             :     }
 2889 andrew                    633 CBC       39861 : }
 2889 andrew                    634 EUB             : 
 3040                           635                 : 
                                636                 : /*
 3040 andrew                    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,
 2877 tgl                       641                 :  * we return the OID of the relevant cast function instead.
                                642                 :  */
  220 andrew                    643                 : static void
 3040 andrew                    644 GIC        1148 : jsonb_categorize_type(Oid typoid,
                                645                 :                       JsonbTypeCategory *tcategory,
                                646                 :                       Oid *outfuncoid)
 3040 andrew                    647 ECB             : {
                                648                 :     bool        typisvarlena;
                                649                 : 
                                650                 :     /* Look through any domain */
 3040 andrew                    651 CBC        1148 :     typoid = getBaseType(typoid);
 3040 andrew                    652 ECB             : 
 3040 andrew                    653 GIC        1148 :     *outfuncoid = InvalidOid;
 3040 andrew                    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                 : 
 3040 andrew                    662 GIC        1148 :     switch (typoid)
                                663                 :     {
                                664              24 :         case BOOLOID:
 3040 andrew                    665 CBC          24 :             *tcategory = JSONBTYPE_BOOL;
 3040 andrew                    666 GIC          24 :             break;
                                667                 : 
                                668             317 :         case INT2OID:
                                669                 :         case INT4OID:
                                670                 :         case INT8OID:
                                671                 :         case FLOAT4OID:
 3040 andrew                    672 ECB             :         case FLOAT8OID:
                                673                 :         case NUMERICOID:
 3040 andrew                    674 CBC         317 :             getTypeOutputInfo(typoid, outfuncoid, &typisvarlena);
 3040 andrew                    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:
 3040 andrew                    683 CBC           9 :             *tcategory = JSONBTYPE_TIMESTAMP;
 3040 andrew                    684 GIC           9 :             break;
 3040 andrew                    685 ECB             : 
 3040 andrew                    686 CBC          12 :         case TIMESTAMPTZOID:
                                687              12 :             *tcategory = JSONBTYPE_TIMESTAMPTZ;
 3040 andrew                    688 GIC          12 :             break;
 3040 andrew                    689 ECB             : 
 3040 andrew                    690 GIC         183 :         case JSONBOID:
                                691             183 :             *tcategory = JSONBTYPE_JSONB;
                                692             183 :             break;
                                693                 : 
                                694              21 :         case JSONOID:
 3040 andrew                    695 CBC          21 :             *tcategory = JSONBTYPE_JSON;
                                696              21 :             break;
 3040 andrew                    697 ECB             : 
 3040 andrew                    698 GIC         573 :         default:
 3040 andrew                    699 ECB             :             /* Check for arrays and composites */
 2237 andrew                    700 CBC         573 :             if (OidIsValid(get_element_type(typoid)) || typoid == ANYARRAYOID
 1116 tgl                       701             516 :                 || typoid == ANYCOMPATIBLEARRAYOID || typoid == RECORDARRAYOID)
 3040 andrew                    702 GIC          57 :                 *tcategory = JSONBTYPE_ARRAY;
 2153 bruce                     703 CBC         516 :             else if (type_is_rowtype(typoid))   /* includes RECORDOID */
 3040 andrew                    704              36 :                 *tcategory = JSONBTYPE_COMPOSITE;
 3040 andrew                    705 ECB             :             else
                                706                 :             {
                                707                 :                 /* It's probably the general case ... */
 3040 andrew                    708 CBC         480 :                 *tcategory = JSONBTYPE_OTHER;
 3040 andrew                    709 ECB             : 
                                710                 :                 /*
 2878 bruce                     711                 :                  * but first let's look for a cast to json (note: not to
                                712                 :                  * jsonb) if it's not built-in.
 3040 andrew                    713                 :                  */
 3040 andrew                    714 GIC         480 :                 if (typoid >= FirstNormalObjectId)
 3040 andrew                    715 ECB             :                 {
 2878 bruce                     716                 :                     Oid         castfunc;
 3040 andrew                    717                 :                     CoercionPathType ctype;
                                718                 : 
 3040 andrew                    719 LBC           0 :                     ctype = find_coercion_pathway(JSONOID, typoid,
                                720                 :                                                   COERCION_EXPLICIT, &castfunc);
                                721               0 :                     if (ctype == COERCION_PATH_FUNC && OidIsValid(castfunc))
 3040 andrew                    722 ECB             :                     {
 3040 andrew                    723 LBC           0 :                         *tcategory = JSONBTYPE_JSONCAST;
                                724               0 :                         *outfuncoid = castfunc;
 3040 andrew                    725 ECB             :                     }
                                726                 :                     else
                                727                 :                     {
                                728                 :                         /* not a cast type, so just get the usual output func */
 3040 andrew                    729 LBC           0 :                         getTypeOutputInfo(typoid, outfuncoid, &typisvarlena);
                                730                 :                     }
                                731                 :                 }
                                732                 :                 else
                                733                 :                 {
                                734                 :                     /* any other builtin type */
 3040 andrew                    735 CBC         480 :                     getTypeOutputInfo(typoid, outfuncoid, &typisvarlena);
                                736                 :                 }
 3040 andrew                    737 GIC         480 :                 break;
                                738                 :             }
                                739                 :     }
 3040 andrew                    740 GBC        1148 : }
                                741                 : 
 3040 andrew                    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
 3040 andrew                    755 GIC        1499 : datum_to_jsonb(Datum val, bool is_null, JsonbInState *result,
                                756                 :                JsonbTypeCategory tcategory, Oid outfuncoid,
                                757                 :                bool key_scalar)
                                758                 : {
 3040 andrew                    759 ECB             :     char       *outputstr;
                                760                 :     bool        numeric_error;
                                761                 :     JsonbValue  jb;
 3040 andrew                    762 GIC        1499 :     bool        scalar_jsonb = false;
                                763                 : 
 2743 noah                      764 CBC        1499 :     check_stack_depth();
                                765                 : 
                                766                 :     /* Convert val to a JsonbValue in jb (in most cases) */
 3040 andrew                    767 GIC        1499 :     if (is_null)
                                768                 :     {
 2816                           769              96 :         Assert(!key_scalar);
 3040                           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                 :     {
 3040 andrew                    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                 :     {
 3040 andrew                    785 GIC        1391 :         if (tcategory == JSONBTYPE_JSONCAST)
 3040 andrew                    786 LBC           0 :             val = OidFunctionCall1(outfuncoid, val);
                                787                 : 
 3040 andrew                    788 CBC        1391 :         switch (tcategory)
                                789                 :         {
 3040 andrew                    790 GIC          54 :             case JSONBTYPE_ARRAY:
 3040 andrew                    791 CBC          54 :                 array_to_jsonb_internal(val, result);
 3040 andrew                    792 GIC          54 :                 break;
 3040 andrew                    793 CBC          96 :             case JSONBTYPE_COMPOSITE:
                                794              96 :                 composite_to_jsonb(val, result);
 3040 andrew                    795 GIC          96 :                 break;
 3040 andrew                    796 CBC          24 :             case JSONBTYPE_BOOL:
                                797              24 :                 if (key_scalar)
 3040 andrew                    798 ECB             :                 {
 3040 andrew                    799 LBC           0 :                     outputstr = DatumGetBool(val) ? "true" : "false";
                                800               0 :                     jb.type = jbvString;
 3040 andrew                    801 UIC           0 :                     jb.val.string.len = strlen(outputstr);
                                802               0 :                     jb.val.string.val = outputstr;
 3040 andrew                    803 ECB             :                 }
                                804                 :                 else
                                805                 :                 {
 3040 andrew                    806 GIC          24 :                     jb.type = jbvBool;
                                807              24 :                     jb.val.boolean = DatumGetBool(val);
                                808                 :                 }
 3040 andrew                    809 CBC          24 :                 break;
 3040 andrew                    810 GBC         488 :             case JSONBTYPE_NUMERIC:
 3040 andrew                    811 GIC         488 :                 outputstr = OidOutputFunctionCall(outfuncoid, val);
 3040 andrew                    812 CBC         488 :                 if (key_scalar)
                                813                 :                 {
 3040 andrew                    814 ECB             :                     /* always quote keys */
 3040 andrew                    815 CBC         106 :                     jb.type = jbvString;
                                816             106 :                     jb.val.string.len = strlen(outputstr);
                                817             106 :                     jb.val.string.val = outputstr;
 3040 andrew                    818 ECB             :                 }
                                819                 :                 else
                                820                 :                 {
                                821                 :                     /*
                                822                 :                      * Make it numeric if it's a valid JSON number, otherwise
 3040 andrew                    823 EUB             :                      * a string. Invalid numeric output will always have an
                                824                 :                      * 'N' or 'n' in it (I think).
                                825                 :                      */
 3040 andrew                    826 GBC         764 :                     numeric_error = (strchr(outputstr, 'N') != NULL ||
 3040 andrew                    827 GIC         382 :                                      strchr(outputstr, 'n') != NULL);
                                828             382 :                     if (!numeric_error)
                                829                 :                     {
 1803 tgl                       830 ECB             :                         Datum       numd;
 3040 andrew                    831                 : 
 1803 tgl                       832 GIC         382 :                         jb.type = jbvNumeric;
 1803 tgl                       833 CBC         382 :                         numd = DirectFunctionCall3(numeric_in,
 1803 tgl                       834 ECB             :                                                    CStringGetDatum(outputstr),
                                835                 :                                                    ObjectIdGetDatum(InvalidOid),
                                836                 :                                                    Int32GetDatum(-1));
 1803 tgl                       837 GIC         382 :                         jb.val.numeric = DatumGetNumeric(numd);
 3040 andrew                    838             382 :                         pfree(outputstr);
 3040 andrew                    839 ECB             :                     }
                                840                 :                     else
                                841                 :                     {
 3040 andrew                    842 UIC           0 :                         jb.type = jbvString;
                                843               0 :                         jb.val.string.len = strlen(outputstr);
                                844               0 :                         jb.val.string.val = outputstr;
                                845                 :                     }
                                846                 :                 }
 3040 andrew                    847 GIC         488 :                 break;
 2878 bruce                     848               9 :             case JSONBTYPE_DATE:
 1909 andrew                    849               9 :                 jb.type = jbvString;
 1292 akorotkov                 850 CBC           9 :                 jb.val.string.val = JsonEncodeDateTime(NULL, val,
 1292 akorotkov                 851 ECB             :                                                        DATEOID, NULL);
 1909 andrew                    852 CBC           9 :                 jb.val.string.len = strlen(jb.val.string.val);
 2878 bruce                     853 GIC           9 :                 break;
 3040 andrew                    854               9 :             case JSONBTYPE_TIMESTAMP:
 1909                           855               9 :                 jb.type = jbvString;
 1292 akorotkov                 856 CBC           9 :                 jb.val.string.val = JsonEncodeDateTime(NULL, val,
 1292 akorotkov                 857 ECB             :                                                        TIMESTAMPOID, NULL);
 1909 andrew                    858 GIC           9 :                 jb.val.string.len = strlen(jb.val.string.val);
 3040                           859               9 :                 break;
                                860              12 :             case JSONBTYPE_TIMESTAMPTZ:
 1909 andrew                    861 CBC          12 :                 jb.type = jbvString;
 1292 akorotkov                 862              12 :                 jb.val.string.val = JsonEncodeDateTime(NULL, val,
                                863                 :                                                        TIMESTAMPTZOID, NULL);
 1909 andrew                    864 GIC          12 :                 jb.val.string.len = strlen(jb.val.string.val);
 3040                           865              12 :                 break;
 3040 andrew                    866 GBC          18 :             case JSONBTYPE_JSONCAST:
 3040 andrew                    867 EUB             :             case JSONBTYPE_JSON:
                                868                 :                 {
                                869                 :                     /* parse the json right into the existing result object */
                                870                 :                     JsonLexContext *lex;
 3040 andrew                    871 ECB             :                     JsonSemAction sem;
 2219 noah                      872 CBC          18 :                     text       *json = DatumGetTextPP(val);
 3040 andrew                    873 ECB             : 
 3040 andrew                    874 CBC          18 :                     lex = makeJsonLexContext(json, true);
                                875                 : 
                                876              18 :                     memset(&sem, 0, sizeof(sem));
 3040 andrew                    877 ECB             : 
 3040 andrew                    878 CBC          18 :                     sem.semstate = (void *) result;
 3040 andrew                    879 ECB             : 
 3040 andrew                    880 CBC          18 :                     sem.object_start = jsonb_in_object_start;
 3040 andrew                    881 GIC          18 :                     sem.array_start = jsonb_in_array_start;
 3040 andrew                    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;
 3040 andrew                    886 ECB             : 
 1168 rhaas                     887 GIC          18 :                     pg_parse_json_or_ereport(lex, &sem);
 3040 andrew                    888 ECB             :                 }
 3040 andrew                    889 CBC          18 :                 break;
                                890             186 :             case JSONBTYPE_JSONB:
                                891                 :                 {
 2029 tgl                       892 GIC         186 :                     Jsonb      *jsonb = DatumGetJsonbP(val);
                                893                 :                     JsonbIterator *it;
                                894                 : 
 3040 andrew                    895             186 :                     it = JsonbIteratorInit(&jsonb->root);
 3040 andrew                    896 ECB             : 
 3040 andrew                    897 GIC         186 :                     if (JB_ROOT_IS_SCALAR(jsonb))
 3040 andrew                    898 ECB             :                     {
 3040 andrew                    899 GIC         108 :                         (void) JsonbIteratorNext(&it, &jb, true);
 3040 andrew                    900 CBC         108 :                         Assert(jb.type == jbvArray);
 3040 andrew                    901 GIC         108 :                         (void) JsonbIteratorNext(&it, &jb, true);
 3040 andrew                    902 CBC         108 :                         scalar_jsonb = true;
                                903                 :                     }
 3040 andrew                    904 ECB             :                     else
                                905                 :                     {
 2737 noah                      906                 :                         JsonbIteratorToken type;
                                907                 : 
 3040 andrew                    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 ||
 3040 andrew                    912 GIC        2853 :                                 type == WJB_BEGIN_ARRAY || type == WJB_BEGIN_OBJECT)
 3040 andrew                    913 CBC         930 :                                 result->res = pushJsonbValue(&result->parseState,
 3040 andrew                    914 ECB             :                                                              type, NULL);
                                915                 :                             else
 3040 andrew                    916 CBC        2622 :                                 result->res = pushJsonbValue(&result->parseState,
                                917                 :                                                              type, &jb);
                                918                 :                         }
 3040 andrew                    919 ECB             :                     }
                                920                 :                 }
 3040 andrew                    921 CBC         186 :                 break;
 3040 andrew                    922 GIC         495 :             default:
 3040 andrew                    923 CBC         495 :                 outputstr = OidOutputFunctionCall(outfuncoid, val);
                                924             495 :                 jb.type = jbvString;
  119 tgl                       925 GNC         495 :                 jb.val.string.len = strlen(outputstr);
                                926             495 :                 (void) checkStringLen(jb.val.string.len, NULL);
 3040 andrew                    927 CBC         495 :                 jb.val.string.val = outputstr;
 3040 andrew                    928 GIC         495 :                 break;
                                929                 :         }
                                930                 :     }
                                931                 : 
                                932                 :     /* Now insert jb into result, unless we did it recursively */
 2733 tgl                       933 CBC        1487 :     if (!is_null && !scalar_jsonb &&
                                934             741 :         tcategory >= JSONBTYPE_JSON && tcategory <= JSONBTYPE_JSONCAST)
                                935                 :     {
 3040 andrew                    936 ECB             :         /* work has been done recursively */
 3040 andrew                    937 CBC         246 :         return;
 3040 andrew                    938 ECB             :     }
 3040 andrew                    939 GIC        1241 :     else if (result->parseState == NULL)
                                940                 :     {
 3040 andrew                    941 ECB             :         /* single root scalar */
                                942                 :         JsonbValue  va;
                                943                 : 
 3040 andrew                    944 GIC         255 :         va.type = jbvArray;
                                945             255 :         va.val.array.rawScalar = true;
 3040 andrew                    946 CBC         255 :         va.val.array.nElems = 1;
 3040 andrew                    947 ECB             : 
 3040 andrew                    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);
 3040 andrew                    951 ECB             :     }
                                952                 :     else
                                953                 :     {
 3040 andrew                    954 GIC         986 :         JsonbValue *o = &result->parseState->contVal;
                                955                 : 
                                956             986 :         switch (o->type)
                                957                 :         {
 3040 andrew                    958 CBC         237 :             case jbvArray:
                                959             237 :                 result->res = pushJsonbValue(&result->parseState, WJB_ELEM, &jb);
 3040 andrew                    960 GIC         237 :                 break;
                                961             749 :             case jbvObject:
 3040 andrew                    962 CBC         749 :                 result->res = pushJsonbValue(&result->parseState,
                                963                 :                                              key_scalar ? WJB_KEY : WJB_VALUE,
 3040 andrew                    964 ECB             :                                              &jb);
 3040 andrew                    965 GIC         749 :                 break;
 3040 andrew                    966 UIC           0 :             default:
                                967               0 :                 elog(ERROR, "unexpected parent of nested structure");
                                968                 :         }
 3040 andrew                    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
 3040 andrew                    978 GIC          54 : array_dim_to_jsonb(JsonbInState *result, int dim, int ndims, int *dims, Datum *vals,
 3040 andrew                    979 ECB             :                    bool *nulls, int *valcount, JsonbTypeCategory tcategory,
                                980                 :                    Oid outfuncoid)
                                981                 : {
                                982                 :     int         i;
                                983                 : 
 3040 andrew                    984 CBC          54 :     Assert(dim < ndims);
 3040 andrew                    985 ECB             : 
 3040 andrew                    986 CBC          54 :     result->res = pushJsonbValue(&result->parseState, WJB_BEGIN_ARRAY, NULL);
 3040 andrew                    987 ECB             : 
 3040 andrew                    988 GIC         198 :     for (i = 1; i <= dims[dim]; i++)
                                989                 :     {
 3040 andrew                    990 CBC         144 :         if (dim + 1 == ndims)
 3040 andrew                    991 EUB             :         {
 3040 andrew                    992 GBC         144 :             datum_to_jsonb(vals[*valcount], nulls[*valcount], result, tcategory,
                                993                 :                            outfuncoid, false);
 3040 andrew                    994 GIC         144 :             (*valcount)++;
                                995                 :         }
                                996                 :         else
                                997                 :         {
 3040 andrew                    998 UIC           0 :             array_dim_to_jsonb(result, dim + 1, ndims, dims, vals, nulls,
                                999                 :                                valcount, tcategory, outfuncoid);
                               1000                 :         }
                               1001                 :     }
                               1002                 : 
 3040 andrew                   1003 CBC          54 :     result->res = pushJsonbValue(&result->parseState, WJB_END_ARRAY, NULL);
 3040 andrew                   1004 GIC          54 : }
                               1005                 : 
                               1006                 : /*
                               1007                 :  * Turn an array into JSON.
                               1008                 :  */
 3040 andrew                   1009 ECB             : static void
 3040 andrew                   1010 GIC          54 : array_to_jsonb_internal(Datum array, JsonbInState *result)
 3040 andrew                   1011 ECB             : {
 3040 andrew                   1012 GIC          54 :     ArrayType  *v = DatumGetArrayTypeP(array);
 3040 andrew                   1013 CBC          54 :     Oid         element_type = ARR_ELEMTYPE(v);
                               1014                 :     int        *dim;
 3040 andrew                   1015 ECB             :     int         ndim;
                               1016                 :     int         nitems;
 3040 andrew                   1017 CBC          54 :     int         count = 0;
                               1018                 :     Datum      *elements;
 3040 andrew                   1019 ECB             :     bool       *nulls;
                               1020                 :     int16       typlen;
                               1021                 :     bool        typbyval;
                               1022                 :     char        typalign;
 3040 andrew                   1023 EUB             :     JsonbTypeCategory tcategory;
                               1024                 :     Oid         outfuncoid;
                               1025                 : 
 3040 andrew                   1026 GIC          54 :     ndim = ARR_NDIM(v);
                               1027              54 :     dim = ARR_DIMS(v);
 3040 andrew                   1028 CBC          54 :     nitems = ArrayGetNItems(ndim, dim);
 3040 andrew                   1029 ECB             : 
 3040 andrew                   1030 GIC          54 :     if (nitems <= 0)
                               1031                 :     {
 3040 andrew                   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;
 3040 andrew                   1035 ECB             :     }
                               1036                 : 
 3040 andrew                   1037 CBC          54 :     get_typlenbyvalalign(element_type,
 3040 andrew                   1038 ECB             :                          &typlen, &typbyval, &typalign);
                               1039                 : 
 3040 andrew                   1040 GIC          54 :     jsonb_categorize_type(element_type,
                               1041                 :                           &tcategory, &outfuncoid);
 3040 andrew                   1042 ECB             : 
 3040 andrew                   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);
 3040 andrew                   1051 CBC          54 :     pfree(nulls);
 3040 andrew                   1052 ECB             : }
                               1053                 : 
                               1054                 : /*
                               1055                 :  * Turn a composite / record into JSON.
                               1056                 :  */
 3040 andrew                   1057 EUB             : static void
 3040 andrew                   1058 GBC          96 : composite_to_jsonb(Datum composite, JsonbInState *result)
 3040 andrew                   1059 EUB             : {
                               1060                 :     HeapTupleHeader td;
                               1061                 :     Oid         tupType;
 3040 andrew                   1062 ECB             :     int32       tupTypmod;
                               1063                 :     TupleDesc   tupdesc;
                               1064                 :     HeapTupleData tmptup,
                               1065                 :                *tuple;
                               1066                 :     int         i;
                               1067                 : 
 3040 andrew                   1068 CBC          96 :     td = DatumGetHeapTupleHeader(composite);
                               1069                 : 
                               1070                 :     /* Extract rowtype info and find a tupdesc */
 3040 andrew                   1071 GIC          96 :     tupType = HeapTupleHeaderGetTypeId(td);
 3040 andrew                   1072 CBC          96 :     tupTypmod = HeapTupleHeaderGetTypMod(td);
 3040 andrew                   1073 GIC          96 :     tupdesc = lookup_rowtype_tupdesc(tupType, tupTypmod);
                               1074                 : 
 3040 andrew                   1075 ECB             :     /* Build a temporary HeapTuple control structure */
 3040 andrew                   1076 CBC          96 :     tmptup.t_len = HeapTupleHeaderGetDatumLength(td);
 3040 andrew                   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++)
 3040 andrew                   1083 ECB             :     {
                               1084                 :         Datum       val;
                               1085                 :         bool        isnull;
                               1086                 :         char       *attname;
                               1087                 :         JsonbTypeCategory tcategory;
                               1088                 :         Oid         outfuncoid;
                               1089                 :         JsonbValue  v;
 2058 andres                   1090 GIC         198 :         Form_pg_attribute att = TupleDescAttr(tupdesc, i);
                               1091                 : 
                               1092             198 :         if (att->attisdropped)
 3040 andrew                   1093 LBC           0 :             continue;
                               1094                 : 
 2058 andres                   1095 GIC         198 :         attname = NameStr(att->attname);
 3040 andrew                   1096 ECB             : 
 3040 andrew                   1097 CBC         198 :         v.type = jbvString;
 3040 andrew                   1098 ECB             :         /* don't need checkStringLen here - can't exceed maximum name length */
 3040 andrew                   1099 GIC         198 :         v.val.string.len = strlen(attname);
                               1100             198 :         v.val.string.val = attname;
 3040 andrew                   1101 ECB             : 
 3040 andrew                   1102 CBC         198 :         result->res = pushJsonbValue(&result->parseState, WJB_KEY, &v);
 3040 andrew                   1103 ECB             : 
 3040 andrew                   1104 GIC         198 :         val = heap_getattr(tuple, i + 1, tupdesc, &isnull);
 3040 andrew                   1105 ECB             : 
 3040 andrew                   1106 GIC         198 :         if (isnull)
 3040 andrew                   1107 ECB             :         {
 3040 andrew                   1108 GIC          15 :             tcategory = JSONBTYPE_NULL;
                               1109              15 :             outfuncoid = InvalidOid;
                               1110                 :         }
                               1111                 :         else
 2058 andres                   1112             183 :             jsonb_categorize_type(att->atttypid, &tcategory, &outfuncoid);
                               1113                 : 
 3040 andrew                   1114             198 :         datum_to_jsonb(val, isnull, result, tcategory, outfuncoid, false);
 3040 andrew                   1115 ECB             :     }
                               1116                 : 
 3040 andrew                   1117 CBC          96 :     result->res = pushJsonbValue(&result->parseState, WJB_END_OBJECT, NULL);
 3040 andrew                   1118 GBC          96 :     ReleaseTupleDesc(tupdesc);
 3040 andrew                   1119 GIC          96 : }
 3040 andrew                   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
 3040 andrew                   1130 GIC         809 : add_jsonb(Datum val, bool is_null, JsonbInState *result,
 3040 andrew                   1131 ECB             :           Oid val_type, bool key_scalar)
                               1132                 : {
                               1133                 :     JsonbTypeCategory tcategory;
                               1134                 :     Oid         outfuncoid;
                               1135                 : 
 3040 andrew                   1136 GIC         809 :     if (val_type == InvalidOid)
 3040 andrew                   1137 LBC           0 :         ereport(ERROR,
                               1138                 :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
 3040 andrew                   1139 ECB             :                  errmsg("could not determine input data type")));
                               1140                 : 
 3040 andrew                   1141 GIC         809 :     if (is_null)
 3040 andrew                   1142 ECB             :     {
 3040 andrew                   1143 CBC          39 :         tcategory = JSONBTYPE_NULL;
                               1144              39 :         outfuncoid = InvalidOid;
                               1145                 :     }
                               1146                 :     else
 3040 andrew                   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
   11 alvherre                 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)
 3040 andrew                   1198 ECB             :  */
                               1199                 : Datum
 3040 andrew                   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);
  220 andrew                   1204 ECB             :     JsonbInState result;
 3040 andrew                   1205 EUB             :     JsonbTypeCategory tcategory;
                               1206                 :     Oid         outfuncoid;
                               1207                 : 
 3040 andrew                   1208 GIC          42 :     if (val_type == InvalidOid)
 3040 andrew                   1209 LBC           0 :         ereport(ERROR,
                               1210                 :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
 3040 andrew                   1211 ECB             :                  errmsg("could not determine input data type")));
                               1212                 : 
 3040 andrew                   1213 GIC          42 :     jsonb_categorize_type(val_type,
                               1214                 :                           &tcategory, &outfuncoid);
 3040 andrew                   1215 ECB             : 
  220 andrew                   1216 GIC          42 :     memset(&result, 0, sizeof(JsonbInState));
                               1217                 : 
  220 andrew                   1218 CBC          42 :     datum_to_jsonb(val, false, &result, tcategory, outfuncoid, false);
  220 andrew                   1219 ECB             : 
  220 andrew                   1220 GIC          42 :     PG_RETURN_POINTER(JsonbValueToJsonb(result.res));
                               1221                 : }
                               1222                 : 
                               1223                 : Datum
   11 alvherre                 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                 : 
 3040 andrew                   1230 GBC         199 :     if (nargs % 2 != 0)
 3040 andrew                   1231 GIC           9 :         ereport(ERROR,
 3040 andrew                   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 */
 1446 alvherre                 1235                 :                  errhint("The arguments of %s must consist of alternating keys and values.",
                               1236                 :                          "jsonb_build_object()")));
 3040 andrew                   1237                 : 
 3040 andrew                   1238 GBC         190 :     memset(&result, 0, sizeof(JsonbInState));
                               1239                 : 
                               1240             190 :     result.res = pushJsonbValue(&result.parseState, WJB_BEGIN_OBJECT, NULL);
   11 alvherre                 1241 GNC         190 :     result.parseState->unique_keys = unique_keys;
                               1242             190 :     result.parseState->skip_nulls = absent_on_null;
 3040 andrew                   1243 EUB             : 
 3040 andrew                   1244 GIC         504 :     for (i = 0; i < nargs; i += 2)
 3040 andrew                   1245 EUB             :     {
                               1246                 :         /* process key */
                               1247                 :         bool        skip;
                               1248                 : 
 1992 andrew                   1249 GIC         335 :         if (nulls[i])
 3040 andrew                   1250 GBC           9 :             ereport(ERROR,
                               1251                 :                     (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                               1252                 :                      errmsg("argument %d: key must not be null", i + 1)));
 3040 andrew                   1253 EUB             : 
                               1254                 :         /* skip null values if absent_on_null */
   11 alvherre                 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                 : 
 1992 andrew                   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                 : 
 3040 andrew                   1267 CBC         169 :     result.res = pushJsonbValue(&result.parseState, WJB_END_OBJECT, NULL);
                               1268                 : 
   11 alvherre                 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));
 3040 andrew                   1290 ECB             : }
                               1291                 : 
                               1292                 : /*
                               1293                 :  * degenerate case of jsonb_build_object where it gets 0 arguments.
                               1294                 :  */
                               1295                 : Datum
 3040 andrew                   1296 GBC           3 : jsonb_build_object_noargs(PG_FUNCTION_ARGS)
                               1297                 : {
                               1298                 :     JsonbInState result;
                               1299                 : 
 3040 andrew                   1300 CBC           3 :     memset(&result, 0, sizeof(JsonbInState));
                               1301                 : 
 3036 andrew                   1302 GIC           3 :     (void) pushJsonbValue(&result.parseState, WJB_BEGIN_OBJECT, NULL);
 3040 andrew                   1303 CBC           3 :     result.res = pushJsonbValue(&result.parseState, WJB_END_OBJECT, NULL);
                               1304                 : 
                               1305               3 :     PG_RETURN_POINTER(JsonbValueToJsonb(result.res));
                               1306                 : }
 3040 andrew                   1307 ECB             : 
  402                          1308                 : Datum
   11 alvherre                 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                 : 
  220 andrew                   1315 CBC          88 :     memset(&result, 0, sizeof(JsonbInState));
  220 andrew                   1316 ECB             : 
  220 andrew                   1317 CBC          88 :     result.res = pushJsonbValue(&result.parseState, WJB_BEGIN_ARRAY, NULL);
                               1318                 : 
                               1319             277 :     for (i = 0; i < nargs; i++)
                               1320                 :     {
   11 alvherre                 1321 GNC         189 :         if (absent_on_null && nulls[i])
                               1322              12 :             continue;
                               1323                 : 
  220 andrew                   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                 : 
   11 alvherre                 1329 GNC          88 :     return JsonbPGetDatum(JsonbValueToJsonb(result.res));
   11 alvherre                 1330 ECB             : }
                               1331                 : 
                               1332                 : /*
                               1333                 :  * SQL function jsonb_build_array(variadic "any")
                               1334                 :  */
                               1335                 : Datum
   11 alvherre                 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                 :  */
 3040 andrew                   1356 ECB             : Datum
 3040 andrew                   1357 GIC           3 : jsonb_build_array_noargs(PG_FUNCTION_ARGS)
                               1358                 : {
 3040 andrew                   1359 ECB             :     JsonbInState result;
                               1360                 : 
 3040 andrew                   1361 GIC           3 :     memset(&result, 0, sizeof(JsonbInState));
 3040 andrew                   1362 ECB             : 
 3036 andrew                   1363 GIC           3 :     (void) pushJsonbValue(&result.parseState, WJB_BEGIN_ARRAY, NULL);
 3040                          1364               3 :     result.res = pushJsonbValue(&result.parseState, WJB_END_ARRAY, NULL);
 3040 andrew                   1365 ECB             : 
 3040 andrew                   1366 GIC           3 :     PG_RETURN_POINTER(JsonbValueToJsonb(result.res));
                               1367                 : }
 3040 andrew                   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
 3040 andrew                   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;
 3040 andrew                   1384 ECB             :     int         in_count,
                               1385                 :                 count,
                               1386                 :                 i;
                               1387                 :     JsonbInState result;
                               1388                 : 
 3040 andrew                   1389 GIC          21 :     memset(&result, 0, sizeof(JsonbInState));
 3040 andrew                   1390 ECB             : 
 3036 andrew                   1391 GIC          21 :     (void) pushJsonbValue(&result.parseState, WJB_BEGIN_OBJECT, NULL);
                               1392                 : 
 3040                          1393              21 :     switch (ndims)
                               1394                 :     {
                               1395               3 :         case 0:
                               1396               3 :             goto close_object;
 3040 andrew                   1397 ECB             :             break;
                               1398                 : 
 3040 andrew                   1399 GIC           6 :         case 1:
                               1400               6 :             if ((ARR_DIMS(in_array)[0]) % 2)
 3040 andrew                   1401 CBC           3 :                 ereport(ERROR,
                               1402                 :                         (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
 3040 andrew                   1403 ECB             :                          errmsg("array must have even number of elements")));
 3040 andrew                   1404 CBC           3 :             break;
                               1405                 : 
                               1406               9 :         case 2:
 3040 andrew                   1407 GIC           9 :             if ((ARR_DIMS(in_array)[1]) != 2)
                               1408               6 :                 ereport(ERROR,
                               1409                 :                         (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
 3040 andrew                   1410 ECB             :                          errmsg("array must have two columns")));
 3040 andrew                   1411 GIC           3 :             break;
                               1412                 : 
                               1413               3 :         default:
                               1414               3 :             ereport(ERROR,
                               1415                 :                     (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
 3040 andrew                   1416 ECB             :                      errmsg("wrong number of array subscripts")));
                               1417                 :     }
                               1418                 : 
  282 peter                    1419 GNC           6 :     deconstruct_array_builtin(in_array, TEXTOID, &in_datums, &in_nulls, &in_count);
 3040 andrew                   1420 ECB             : 
 3040 andrew                   1421 CBC           6 :     count = in_count / 2;
                               1422                 : 
                               1423              30 :     for (i = 0; i < count; ++i)
                               1424                 :     {
                               1425                 :         JsonbValue  v;
 3040 andrew                   1426 ECB             :         char       *str;
                               1427                 :         int         len;
                               1428                 : 
 3040 andrew                   1429 GIC          24 :         if (in_nulls[i * 2])
 3040 andrew                   1430 UIC           0 :             ereport(ERROR,
                               1431                 :                     (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
                               1432                 :                      errmsg("null value not allowed for object key")));
                               1433                 : 
 3040 andrew                   1434 GIC          24 :         str = TextDatumGetCString(in_datums[i * 2]);
 3040 andrew                   1435 CBC          24 :         len = strlen(str);
                               1436                 : 
 3040 andrew                   1437 GIC          24 :         v.type = jbvString;
                               1438                 : 
                               1439              24 :         v.val.string.len = len;
                               1440              24 :         v.val.string.val = str;
                               1441                 : 
 3036 andrew                   1442 CBC          24 :         (void) pushJsonbValue(&result.parseState, WJB_KEY, &v);
                               1443                 : 
 3040 andrew                   1444 GIC          24 :         if (in_nulls[i * 2 + 1])
 3040 andrew                   1445 ECB             :         {
 3040 andrew                   1446 CBC           6 :             v.type = jbvNull;
                               1447                 :         }
 3040 andrew                   1448 ECB             :         else
                               1449                 :         {
 3040 andrew                   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;
 3040 andrew                   1456 CBC          18 :             v.val.string.val = str;
                               1457                 :         }
                               1458                 : 
 3036 andrew                   1459 GIC          24 :         (void) pushJsonbValue(&result.parseState, WJB_VALUE, &v);
 3040 andrew                   1460 ECB             :     }
                               1461                 : 
 3040 andrew                   1462 CBC           6 :     pfree(in_datums);
                               1463               6 :     pfree(in_nulls);
                               1464                 : 
                               1465               9 : close_object:
 3040 andrew                   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                 :  */
 3040 andrew                   1477 ECB             : Datum
 3040 andrew                   1478 GIC          21 : jsonb_object_two_arg(PG_FUNCTION_ARGS)
 3040 andrew                   1479 ECB             : {
 3040 andrew                   1480 CBC          21 :     ArrayType  *key_array = PG_GETARG_ARRAYTYPE_P(0);
 3040 andrew                   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;
 3040 andrew                   1488 ECB             :     int         key_count,
                               1489                 :                 val_count,
                               1490                 :                 i;
                               1491                 :     JsonbInState result;
                               1492                 : 
 3040 andrew                   1493 GIC          21 :     memset(&result, 0, sizeof(JsonbInState));
 3040 andrew                   1494 ECB             : 
 3036 andrew                   1495 CBC          21 :     (void) pushJsonbValue(&result.parseState, WJB_BEGIN_OBJECT, NULL);
                               1496                 : 
 3040 andrew                   1497 GIC          21 :     if (nkdims > 1 || nkdims != nvdims)
 3040 andrew                   1498 CBC           3 :         ereport(ERROR,
 3040 andrew                   1499 ECB             :                 (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
                               1500                 :                  errmsg("wrong number of array subscripts")));
                               1501                 : 
 3040 andrew                   1502 GIC          18 :     if (nkdims == 0)
 2604 andrew                   1503 CBC           3 :         goto close_object;
                               1504                 : 
  282 peter                    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);
 3040 andrew                   1507 ECB             : 
 3040 andrew                   1508 CBC          15 :     if (key_count != val_count)
 3040 andrew                   1509 GIC           6 :         ereport(ERROR,
                               1510                 :                 (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
                               1511                 :                  errmsg("mismatched array dimensions")));
                               1512                 : 
 3040 andrew                   1513 CBC          39 :     for (i = 0; i < key_count; ++i)
                               1514                 :     {
 3040 andrew                   1515 ECB             :         JsonbValue  v;
                               1516                 :         char       *str;
                               1517                 :         int         len;
                               1518                 : 
 3040 andrew                   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")));
 3040 andrew                   1523 ECB             : 
 3040 andrew                   1524 GBC          30 :         str = TextDatumGetCString(key_datums[i]);
 3040 andrew                   1525 GIC          30 :         len = strlen(str);
                               1526                 : 
                               1527              30 :         v.type = jbvString;
 3040 andrew                   1528 ECB             : 
 3040 andrew                   1529 CBC          30 :         v.val.string.len = len;
 3040 andrew                   1530 GIC          30 :         v.val.string.val = str;
 3040 andrew                   1531 ECB             : 
 3036 andrew                   1532 GIC          30 :         (void) pushJsonbValue(&result.parseState, WJB_KEY, &v);
 3040 andrew                   1533 ECB             : 
 3040 andrew                   1534 CBC          30 :         if (val_nulls[i])
                               1535                 :         {
 3040 andrew                   1536 LBC           0 :             v.type = jbvNull;
                               1537                 :         }
 3040 andrew                   1538 ECB             :         else
                               1539                 :         {
 3040 andrew                   1540 CBC          30 :             str = TextDatumGetCString(val_datums[i]);
 3040 andrew                   1541 GIC          30 :             len = strlen(str);
                               1542                 : 
                               1543              30 :             v.type = jbvString;
 3040 andrew                   1544 ECB             : 
 3040 andrew                   1545 CBC          30 :             v.val.string.len = len;
 3040 andrew                   1546 GIC          30 :             v.val.string.val = str;
 3040 andrew                   1547 ECB             :         }
                               1548                 : 
 3036 andrew                   1549 CBC          30 :         (void) pushJsonbValue(&result.parseState, WJB_VALUE, &v);
 3040 andrew                   1550 ECB             :     }
                               1551                 : 
 3040 andrew                   1552 GIC           6 :     pfree(key_datums);
 3040 andrew                   1553 CBC           6 :     pfree(key_nulls);
 3040 andrew                   1554 GIC           6 :     pfree(val_datums);
                               1555               6 :     pfree(val_nulls);
 3040 andrew                   1556 ECB             : 
 2604 andrew                   1557 CBC           9 : close_object:
 2604 andrew                   1558 GIC           9 :     result.res = pushJsonbValue(&result.parseState, WJB_END_OBJECT, NULL);
 2604 andrew                   1559 ECB             : 
 3040 andrew                   1560 CBC           9 :     PG_RETURN_POINTER(JsonbValueToJsonb(result.res));
                               1561                 : }
 3040 andrew                   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 *
 2878 bruce                    1570 GIC          57 : clone_parse_state(JsonbParseState *state)
                               1571                 : {
 2878 bruce                    1572 ECB             :     JsonbParseState *result,
                               1573                 :                *icursor,
                               1574                 :                *ocursor;
 3040 andrew                   1575                 : 
 3040 andrew                   1576 CBC          57 :     if (state == NULL)
 3040 andrew                   1577 LBC           0 :         return NULL;
                               1578                 : 
 3040 andrew                   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;
   11 alvherre                 1586 GNC          57 :         ocursor->unique_keys = icursor->unique_keys;
                               1587              57 :         ocursor->skip_nulls = icursor->skip_nulls;
 3040 andrew                   1588 GIC          57 :         icursor = icursor->next;
 3040 andrew                   1589 CBC          57 :         if (icursor == NULL)
 3040 andrew                   1590 GIC          57 :             break;
 2878 bruce                    1591 LBC           0 :         ocursor->next = palloc(sizeof(JsonbParseState));
 3040 andrew                   1592 UIC           0 :         ocursor = ocursor->next;
 3040 andrew                   1593 ECB             :     }
 3040 andrew                   1594 CBC          57 :     ocursor->next = NULL;
                               1595                 : 
 3040 andrew                   1596 GIC          57 :     return result;
                               1597                 : }
 3040 andrew                   1598 ECB             : 
                               1599                 : static Datum
   11 alvherre                 1600 GNC         183 : jsonb_agg_transfn_worker(FunctionCallInfo fcinfo, bool absent_on_null)
 3040 andrew                   1601 ECB             : {
                               1602                 :     MemoryContext oldcontext,
                               1603                 :                 aggcontext;
                               1604                 :     JsonbAggState *state;
                               1605                 :     JsonbInState elem;
                               1606                 :     Datum       val;
                               1607                 :     JsonbInState *result;
 3040 andrew                   1608 GIC         183 :     bool        single_scalar = false;
                               1609                 :     JsonbIterator *it;
                               1610                 :     Jsonb      *jbelem;
 3040 andrew                   1611 ECB             :     JsonbValue  v;
 2963 alvherre                 1612                 :     JsonbIteratorToken type;
                               1613                 : 
 3040 andrew                   1614 GIC         183 :     if (!AggCheckCallContext(fcinfo, &aggcontext))
                               1615                 :     {
 3040 andrew                   1616 ECB             :         /* cannot be called directly because of internal-type argument */
 3040 andrew                   1617 LBC           0 :         elog(ERROR, "jsonb_agg_transfn called in non-aggregate context");
                               1618                 :     }
 3040 andrew                   1619 ECB             : 
                               1620                 :     /* set up the accumulator on the first go round */
                               1621                 : 
 3040 andrew                   1622 CBC         183 :     if (PG_ARGISNULL(0))
                               1623                 :     {
 2733 tgl                      1624              33 :         Oid         arg_type = get_fn_expr_argtype(fcinfo->flinfo, 1);
                               1625                 : 
 2760 andrew                   1626              33 :         if (arg_type == InvalidOid)
 2760 andrew                   1627 UIC           0 :             ereport(ERROR,
 2760 andrew                   1628 EUB             :                     (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                               1629                 :                      errmsg("could not determine input data type")));
                               1630                 : 
 2760 andrew                   1631 GIC          33 :         oldcontext = MemoryContextSwitchTo(aggcontext);
 2760 andrew                   1632 CBC          33 :         state = palloc(sizeof(JsonbAggState));
 3040                          1633              33 :         result = palloc0(sizeof(JsonbInState));
 2760 andrew                   1634 GIC          33 :         state->res = result;
 3040 andrew                   1635 CBC          33 :         result->res = pushJsonbValue(&result->parseState,
                               1636                 :                                      WJB_BEGIN_ARRAY, NULL);
 2760                          1637              33 :         MemoryContextSwitchTo(oldcontext);
 3040 andrew                   1638 ECB             : 
 2760 andrew                   1639 GIC          33 :         jsonb_categorize_type(arg_type, &state->val_category,
                               1640                 :                               &state->val_output_func);
 3040 andrew                   1641 ECB             :     }
                               1642                 :     else
                               1643                 :     {
 2760 andrew                   1644 CBC         150 :         state = (JsonbAggState *) PG_GETARG_POINTER(0);
                               1645             150 :         result = state->res;
 3040 andrew                   1646 ECB             :     }
                               1647                 : 
   11 alvherre                 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 */
 2760 andrew                   1652 ECB             : 
 2760 andrew                   1653 CBC         144 :     val = PG_ARGISNULL(1) ? (Datum) 0 : PG_GETARG_DATUM(1);
                               1654                 : 
                               1655             144 :     memset(&elem, 0, sizeof(JsonbInState));
                               1656                 : 
 2760 andrew                   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);
 2760 andrew                   1665 ECB             : 
 3040 andrew                   1666 GIC         144 :     it = JsonbIteratorInit(&jbelem->root);
                               1667                 : 
                               1668             984 :     while ((type = JsonbIteratorNext(&it, &v, false)) != WJB_DONE)
                               1669                 :     {
                               1670             840 :         switch (type)
 3040 andrew                   1671 ECB             :         {
 3040 andrew                   1672 GBC         114 :             case WJB_BEGIN_ARRAY:
 3040 andrew                   1673 GIC         114 :                 if (v.val.array.rawScalar)
 3040 andrew                   1674 CBC          72 :                     single_scalar = true;
 3040 andrew                   1675 ECB             :                 else
 3040 andrew                   1676 CBC          42 :                     result->res = pushJsonbValue(&result->parseState,
                               1677                 :                                                  type, NULL);
 3040 andrew                   1678 GIC         114 :                 break;
 3040 andrew                   1679 CBC         114 :             case WJB_END_ARRAY:
                               1680             114 :                 if (!single_scalar)
                               1681              42 :                     result->res = pushJsonbValue(&result->parseState,
 3040 andrew                   1682 ECB             :                                                  type, NULL);
 3040 andrew                   1683 CBC         114 :                 break;
                               1684             180 :             case WJB_BEGIN_OBJECT:
 3040 andrew                   1685 ECB             :             case WJB_END_OBJECT:
 3040 andrew                   1686 GBC         180 :                 result->res = pushJsonbValue(&result->parseState,
 3040 andrew                   1687 EUB             :                                              type, NULL);
 3040 andrew                   1688 GIC         180 :                 break;
 3040 andrew                   1689 CBC         432 :             case WJB_ELEM:
                               1690                 :             case WJB_KEY:
 3040 andrew                   1691 ECB             :             case WJB_VALUE:
 3040 andrew                   1692 GIC         432 :                 if (v.type == jbvString)
                               1693                 :                 {
                               1694                 :                     /* copy string values in the aggregate context */
 2931 heikki.linnakangas       1695 CBC         186 :                     char       *buf = palloc(v.val.string.len + 1);
                               1696                 : 
 3040 andrew                   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 */
 2878 bruce                    1703 CBC         204 :                     v.val.numeric =
 2118 tgl                      1704 GIC         204 :                         DatumGetNumeric(DirectFunctionCall1(numeric_uplus,
                               1705                 :                                                             NumericGetDatum(v.val.numeric)));
                               1706                 :                 }
 3040 andrew                   1707             432 :                 result->res = pushJsonbValue(&result->parseState,
                               1708                 :                                              type, &v);
 3040 andrew                   1709 CBC         432 :                 break;
 2963 alvherre                 1710 UIC           0 :             default:
                               1711               0 :                 elog(ERROR, "unknown jsonb iterator token type");
 3040 andrew                   1712 EUB             :         }
                               1713                 :     }
                               1714                 : 
 3040 andrew                   1715 GIC         144 :     MemoryContextSwitchTo(oldcontext);
                               1716                 : 
 2760 andrew                   1717 CBC         144 :     PG_RETURN_POINTER(state);
                               1718                 : }
 3040 andrew                   1719 ECB             : 
                               1720                 : /*
                               1721                 :  * jsonb_agg aggregate function
                               1722                 :  */
                               1723                 : Datum
   11 alvherre                 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
 3040 andrew                   1739 CBC          36 : jsonb_agg_finalfn(PG_FUNCTION_ARGS)
 3040 andrew                   1740 EUB             : {
                               1741                 :     JsonbAggState *arg;
                               1742                 :     JsonbInState result;
                               1743                 :     Jsonb      *out;
 3040 andrew                   1744 ECB             : 
                               1745                 :     /* cannot be called directly because of internal-type argument */
 3040 andrew                   1746 CBC          36 :     Assert(AggCheckCallContext(fcinfo, NULL));
 3040 andrew                   1747 ECB             : 
 3040 andrew                   1748 CBC          36 :     if (PG_ARGISNULL(0))
 3040 andrew                   1749 GIC           3 :         PG_RETURN_NULL();       /* returns null iff no input values */
 3040 andrew                   1750 ECB             : 
 2760 andrew                   1751 GIC          33 :     arg = (JsonbAggState *) PG_GETARG_POINTER(0);
 3040 andrew                   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                 :      */
  119 tgl                      1759 GNC          33 :     memset(&result, 0, sizeof(JsonbInState));
                               1760                 : 
 2760 andrew                   1761 GIC          33 :     result.parseState = clone_parse_state(arg->res->parseState);
 3040 andrew                   1762 ECB             : 
 3040 andrew                   1763 CBC          33 :     result.res = pushJsonbValue(&result.parseState,
                               1764                 :                                 WJB_END_ARRAY, NULL);
                               1765                 : 
 3040 andrew                   1766 GIC          33 :     out = JsonbValueToJsonb(result.res);
 3040 andrew                   1767 ECB             : 
 3040 andrew                   1768 GIC          33 :     PG_RETURN_POINTER(out);
 3040 andrew                   1769 ECB             : }
                               1770                 : 
                               1771                 : static Datum
   11 alvherre                 1772 GNC          96 : jsonb_object_agg_transfn_worker(FunctionCallInfo fcinfo,
                               1773                 :                                 bool absent_on_null, bool unique_keys)
                               1774                 : {
                               1775                 :     MemoryContext oldcontext,
 3040 andrew                   1776 ECB             :                 aggcontext;
                               1777                 :     JsonbInState elem;
 2760                          1778                 :     JsonbAggState *state;
                               1779                 :     Datum       val;
 3040                          1780                 :     JsonbInState *result;
                               1781                 :     bool        single_scalar;
                               1782                 :     JsonbIterator *it;
                               1783                 :     Jsonb      *jbkey,
                               1784                 :                *jbval;
                               1785                 :     JsonbValue  v;
 2963 alvherre                 1786                 :     JsonbIteratorToken type;
                               1787                 :     bool        skip;
                               1788                 : 
 3040 andrew                   1789 CBC          96 :     if (!AggCheckCallContext(fcinfo, &aggcontext))
                               1790                 :     {
 3040 andrew                   1791 ECB             :         /* cannot be called directly because of internal-type argument */
 3040 andrew                   1792 LBC           0 :         elog(ERROR, "jsonb_object_agg_transfn called in non-aggregate context");
 3040 andrew                   1793 ECB             :     }
                               1794                 : 
                               1795                 :     /* set up the accumulator on the first go round */
                               1796                 : 
 2760 andrew                   1797 CBC          96 :     if (PG_ARGISNULL(0))
                               1798                 :     {
 2733 tgl                      1799 ECB             :         Oid         arg_type;
                               1800                 : 
 2760 andrew                   1801 CBC          33 :         oldcontext = MemoryContextSwitchTo(aggcontext);
                               1802              33 :         state = palloc(sizeof(JsonbAggState));
 2760 andrew                   1803 GIC          33 :         result = palloc0(sizeof(JsonbInState));
                               1804              33 :         state->res = result;
 2760 andrew                   1805 CBC          33 :         result->res = pushJsonbValue(&result->parseState,
                               1806                 :                                      WJB_BEGIN_OBJECT, NULL);
   11 alvherre                 1807 GNC          33 :         result->parseState->unique_keys = unique_keys;
                               1808              33 :         result->parseState->skip_nulls = absent_on_null;
                               1809                 : 
 2760 andrew                   1810 GIC          33 :         MemoryContextSwitchTo(oldcontext);
 2760 andrew                   1811 ECB             : 
 2760 andrew                   1812 GIC          33 :         arg_type = get_fn_expr_argtype(fcinfo->flinfo, 1);
 2760 andrew                   1813 ECB             : 
 2760 andrew                   1814 CBC          33 :         if (arg_type == InvalidOid)
 2760 andrew                   1815 UIC           0 :             ereport(ERROR,
 2760 andrew                   1816 ECB             :                     (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                               1817                 :                      errmsg("could not determine input data type")));
                               1818                 : 
 2760 andrew                   1819 CBC          33 :         jsonb_categorize_type(arg_type, &state->key_category,
 2760 andrew                   1820 ECB             :                               &state->key_output_func);
                               1821                 : 
 2760 andrew                   1822 GIC          33 :         arg_type = get_fn_expr_argtype(fcinfo->flinfo, 2);
 2760 andrew                   1823 ECB             : 
 2760 andrew                   1824 GIC          33 :         if (arg_type == InvalidOid)
 2760 andrew                   1825 LBC           0 :             ereport(ERROR,
 2760 andrew                   1826 EUB             :                     (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                               1827                 :                      errmsg("could not determine input data type")));
                               1828                 : 
 2760 andrew                   1829 GIC          33 :         jsonb_categorize_type(arg_type, &state->val_category,
                               1830                 :                               &state->val_output_func);
 2760 andrew                   1831 ECB             :     }
                               1832                 :     else
                               1833                 :     {
 2760 andrew                   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                 : 
 2816 andrew                   1840 CBC          96 :     if (PG_ARGISNULL(1))
 2816 andrew                   1841 GIC           9 :         ereport(ERROR,
 2816 andrew                   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                 :      */
   11 alvherre                 1849 GNC          87 :     skip = absent_on_null && PG_ARGISNULL(2);
                               1850                 : 
                               1851              87 :     if (skip && !unique_keys)
                               1852               6 :         PG_RETURN_POINTER(state);
                               1853                 : 
 2816 andrew                   1854 GIC          81 :     val = PG_GETARG_DATUM(1);
                               1855                 : 
 3040                          1856              81 :     memset(&elem, 0, sizeof(JsonbInState));
                               1857                 : 
 2760 andrew                   1858 CBC          81 :     datum_to_jsonb(val, false, &elem, state->key_category,
                               1859                 :                    state->key_output_func, true);
 3040 andrew                   1860 ECB             : 
 3040 andrew                   1861 GIC          81 :     jbkey = JsonbValueToJsonb(elem.res);
                               1862                 : 
                               1863              81 :     val = PG_ARGISNULL(2) ? (Datum) 0 : PG_GETARG_DATUM(2);
 3040 andrew                   1864 ECB             : 
 3040 andrew                   1865 GIC          81 :     memset(&elem, 0, sizeof(JsonbInState));
                               1866                 : 
 2760                          1867              81 :     datum_to_jsonb(val, PG_ARGISNULL(2), &elem, state->val_category,
                               1868                 :                    state->val_output_func, false);
                               1869                 : 
 3040                          1870              81 :     jbval = JsonbValueToJsonb(elem.res);
 3040 andrew                   1871 ECB             : 
 2760 andrew                   1872 GIC          81 :     it = JsonbIteratorInit(&jbkey->root);
 2760 andrew                   1873 ECB             : 
 3040                          1874                 :     /* switch to the aggregate context for accumulation operations */
                               1875                 : 
 3040 andrew                   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:
 3040 andrew                   1889 GIC          81 :                 if (!v.val.array.rawScalar)
 3040 andrew                   1890 UIC           0 :                     elog(ERROR, "unexpected structure for key");
 3040 andrew                   1891 CBC          81 :                 break;
 3040 andrew                   1892 GIC          81 :             case WJB_ELEM:
 3040 andrew                   1893 CBC          81 :                 if (v.type == jbvString)
                               1894                 :                 {
                               1895                 :                     /* copy string values in the aggregate context */
 2931 heikki.linnakangas       1896 GIC          81 :                     char       *buf = palloc(v.val.string.len + 1);
 2878 bruce                    1897 ECB             : 
 3040 andrew                   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                 :                 {
 3040 andrew                   1903 UIC           0 :                     ereport(ERROR,
                               1904                 :                             (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                               1905                 :                              errmsg("object keys must be strings")));
                               1906                 :                 }
 3040 andrew                   1907 GIC          81 :                 result->res = pushJsonbValue(&result->parseState,
                               1908                 :                                              WJB_KEY, &v);
                               1909                 : 
   11 alvherre                 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                 : 
 3040 andrew                   1919 GIC          78 :                 break;
                               1920              78 :             case WJB_END_ARRAY:
                               1921              78 :                 break;
 3040 andrew                   1922 UIC           0 :             default:
                               1923               0 :                 elog(ERROR, "unexpected structure for key");
 3040 andrew                   1924 ECB             :                 break;
                               1925                 :         }
                               1926                 :     }
 3040 andrew                   1927 EUB             : 
 3040 andrew                   1928 GIC          78 :     it = JsonbIteratorInit(&jbval->root);
                               1929                 : 
                               1930              78 :     single_scalar = false;
                               1931                 : 
 3040 andrew                   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                 : 
 3040 andrew                   1938 CBC         339 :     while ((type = JsonbIteratorNext(&it, &v, false)) != WJB_DONE)
 3040 andrew                   1939 ECB             :     {
 3040 andrew                   1940 CBC         261 :         switch (type)
                               1941                 :         {
                               1942              69 :             case WJB_BEGIN_ARRAY:
                               1943              69 :                 if (v.val.array.rawScalar)
 3040 andrew                   1944 GIC          69 :                     single_scalar = true;
 3040 andrew                   1945 ECB             :                 else
 3040 andrew                   1946 UIC           0 :                     result->res = pushJsonbValue(&result->parseState,
 3040 andrew                   1947 ECB             :                                                  type, NULL);
 3040 andrew                   1948 GIC          69 :                 break;
 3040 andrew                   1949 CBC          69 :             case WJB_END_ARRAY:
 3040 andrew                   1950 GBC          69 :                 if (!single_scalar)
 3040 andrew                   1951 UIC           0 :                     result->res = pushJsonbValue(&result->parseState,
                               1952                 :                                                  type, NULL);
 3040 andrew                   1953 GIC          69 :                 break;
 3040 andrew                   1954 CBC          18 :             case WJB_BEGIN_OBJECT:
                               1955                 :             case WJB_END_OBJECT:
 3040 andrew                   1956 GIC          18 :                 result->res = pushJsonbValue(&result->parseState,
 3040 andrew                   1957 ECB             :                                              type, NULL);
 3040 andrew                   1958 GIC          18 :                 break;
 3040 andrew                   1959 CBC         105 :             case WJB_ELEM:
 3040 andrew                   1960 EUB             :             case WJB_KEY:
                               1961                 :             case WJB_VALUE:
 3040 andrew                   1962 GIC         105 :                 if (v.type == jbvString)
                               1963                 :                 {
 2963 alvherre                 1964 ECB             :                     /* copy string values in the aggregate context */
 2931 heikki.linnakangas       1965 GIC          54 :                     char       *buf = palloc(v.val.string.len + 1);
                               1966                 : 
 3040 andrew                   1967              54 :                     snprintf(buf, v.val.string.len + 1, "%s", v.val.string.val);
                               1968              54 :                     v.val.string.val = buf;
 3040 andrew                   1969 ECB             :                 }
 3040 andrew                   1970 CBC          51 :                 else if (v.type == jbvNumeric)
                               1971                 :                 {
                               1972                 :                     /* same for numeric */
 3040 andrew                   1973 GIC          39 :                     v.val.numeric =
 2118 tgl                      1974              39 :                         DatumGetNumeric(DirectFunctionCall1(numeric_uplus,
 2118 tgl                      1975 ECB             :                                                             NumericGetDatum(v.val.numeric)));
 3040 andrew                   1976                 :                 }
 3040 andrew                   1977 GIC         105 :                 result->res = pushJsonbValue(&result->parseState,
                               1978                 :                                              single_scalar ? WJB_VALUE : type,
                               1979                 :                                              &v);
                               1980             105 :                 break;
 2963 alvherre                 1981 UIC           0 :             default:
                               1982               0 :                 elog(ERROR, "unknown jsonb iterator token type");
                               1983                 :         }
 3040 andrew                   1984 ECB             :     }
                               1985                 : 
 3040 andrew                   1986 CBC          78 :     MemoryContextSwitchTo(oldcontext);
 3040 andrew                   1987 ECB             : 
 2760 andrew                   1988 GIC          78 :     PG_RETURN_POINTER(state);
 3040 andrew                   1989 ECB             : }
                               1990                 : 
                               1991                 : /*
                               1992                 :  * jsonb_object_agg aggregate function
                               1993                 :  */
                               1994                 : Datum
   11 alvherre                 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                 : 
 3040 andrew                   2028 ECB             : Datum
 3040 andrew                   2029 GIC          27 : jsonb_object_agg_finalfn(PG_FUNCTION_ARGS)
 3040 andrew                   2030 ECB             : {
                               2031                 :     JsonbAggState *arg;
                               2032                 :     JsonbInState result;
                               2033                 :     Jsonb      *out;
                               2034                 : 
                               2035                 :     /* cannot be called directly because of internal-type argument */
 3040 andrew                   2036 GIC          27 :     Assert(AggCheckCallContext(fcinfo, NULL));
 3040 andrew                   2037 ECB             : 
 3040 andrew                   2038 GIC          27 :     if (PG_ARGISNULL(0))
 3040 andrew                   2039 CBC           3 :         PG_RETURN_NULL();       /* returns null iff no input values */
                               2040                 : 
 2760 andrew                   2041 GIC          24 :     arg = (JsonbAggState *) PG_GETARG_POINTER(0);
 3040 andrew                   2042 ECB             : 
                               2043                 :     /*
 2760                          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
 2733 tgl                      2048                 :      * marker.
                               2049                 :      */
  119 tgl                      2050 GNC          24 :     memset(&result, 0, sizeof(JsonbInState));
                               2051                 : 
 2760 andrew                   2052 GIC          24 :     result.parseState = clone_parse_state(arg->res->parseState);
                               2053                 : 
 3040                          2054              24 :     result.res = pushJsonbValue(&result.parseState,
                               2055                 :                                 WJB_END_OBJECT, NULL);
                               2056                 : 
 3040 andrew                   2057 CBC          18 :     out = JsonbValueToJsonb(result.res);
                               2058                 : 
                               2059              18 :     PG_RETURN_POINTER(out);
                               2060                 : }
 1837 teodor                   2061 ECB             : 
                               2062                 : 
 1837 teodor                   2063 EUB             : /*
 1837 teodor                   2064 ECB             :  * Extract scalar value from raw-scalar pseudo-array jsonb.
                               2065                 :  */
 1485 akorotkov                2066                 : bool
 1837 teodor                   2067 GIC       95340 : JsonbExtractScalar(JsonbContainer *jbc, JsonbValue *res)
                               2068                 : {
 1837 teodor                   2069 ECB             :     JsonbIterator *it;
                               2070                 :     JsonbIteratorToken tok PG_USED_FOR_ASSERTS_ONLY;
                               2071                 :     JsonbValue  tmp;
                               2072                 : 
 1837 teodor                   2073 GIC       95340 :     if (!JsonContainerIsArray(jbc) || !JsonContainerIsScalar(jbc))
                               2074                 :     {
                               2075                 :         /* inform caller about actual type of container */
 1796 teodor                   2076 GBC       94890 :         res->type = (JsonContainerIsArray(jbc)) ? jbvArray : jbvObject;
 1796 teodor                   2077 GIC       94890 :         return false;
                               2078                 :     }
                               2079                 : 
 1837 teodor                   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                 :      */
 1837 teodor                   2084 GIC         450 :     it = JsonbIteratorInit(jbc);
 1837 teodor                   2085 ECB             : 
 1837 teodor                   2086 CBC         450 :     tok = JsonbIteratorNext(&it, &tmp, true);
 1837 teodor                   2087 GIC         450 :     Assert(tok == WJB_BEGIN_ARRAY);
 1837 teodor                   2088 CBC         450 :     Assert(tmp.val.array.nElems == 1 && tmp.val.array.rawScalar);
 1837 teodor                   2089 ECB             : 
 1837 teodor                   2090 GIC         450 :     tok = JsonbIteratorNext(&it, res, true);
 1809 tgl                      2091             450 :     Assert(tok == WJB_ELEM);
 1837 teodor                   2092 CBC         450 :     Assert(IsAJsonbScalar(res));
 1837 teodor                   2093 ECB             : 
 1837 teodor                   2094 CBC         450 :     tok = JsonbIteratorNext(&it, &tmp, true);
 1809 tgl                      2095 GBC         450 :     Assert(tok == WJB_END_ARRAY);
 1837 teodor                   2096 EUB             : 
 1837 teodor                   2097 GIC         450 :     tok = JsonbIteratorNext(&it, &tmp, true);
                               2098             450 :     Assert(tok == WJB_DONE);
                               2099                 : 
 1796                          2100             450 :     return true;
 1796 teodor                   2101 ECB             : }
                               2102                 : 
                               2103                 : /*
                               2104                 :  * Emit correct, translatable cast error message
                               2105                 :  */
                               2106                 : static void
 1796 teodor                   2107 GIC          12 : cannotCastJsonbValue(enum jbvType type, const char *sqltype)
                               2108                 : {
                               2109                 :     static const struct
                               2110                 :     {
 1744 andrew                   2111 ECB             :         enum jbvType type;
                               2112                 :         const char *msg;
 1796 teodor                   2113                 :     }
                               2114                 :                 messages[] =
                               2115                 :     {
 1744 andrew                   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")},
 1744 andrew                   2119 EUB             :         {jbvBool, gettext_noop("cannot cast jsonb boolean to type %s")},
                               2120                 :         {jbvArray, gettext_noop("cannot cast jsonb array to type %s")},
 1744 andrew                   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")}
 1796 teodor                   2123                 :     };
 1744 andrew                   2124 EUB             :     int         i;
                               2125                 : 
 1744 andrew                   2126 CBC          54 :     for (i = 0; i < lengthof(messages); i++)
 1796 teodor                   2127              54 :         if (messages[i].type == type)
 1796 teodor                   2128 GIC          12 :             ereport(ERROR,
 1796 teodor                   2129 ECB             :                     (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                               2130                 :                      errmsg(messages[i].msg, sqltype)));
                               2131                 : 
                               2132                 :     /* should be unreachable */
 1744 andrew                   2133 UIC           0 :     elog(ERROR, "unknown jsonb type: %d", (int) type);
                               2134                 : }
 1837 teodor                   2135 ECB             : 
                               2136                 : Datum
 1837 teodor                   2137 GIC           6 : jsonb_bool(PG_FUNCTION_ARGS)
 1837 teodor                   2138 ECB             : {
 1837 teodor                   2139 GIC           6 :     Jsonb      *in = PG_GETARG_JSONB_P(0);
 1837 teodor                   2140 ECB             :     JsonbValue  v;
                               2141                 : 
 1837 teodor                   2142 GIC           6 :     if (!JsonbExtractScalar(&in->root, &v) || v.type != jbvBool)
 1796 teodor                   2143 CBC           3 :         cannotCastJsonbValue(v.type, "boolean");
                               2144                 : 
 1837 teodor                   2145 GIC           3 :     PG_FREE_IF_COPY(in, 0);
 1837 teodor                   2146 ECB             : 
 1837 teodor                   2147 CBC           3 :     PG_RETURN_BOOL(v.val.boolean);
                               2148                 : }
                               2149                 : 
 1837 teodor                   2150 ECB             : Datum
 1837 teodor                   2151 GIC          12 : jsonb_numeric(PG_FUNCTION_ARGS)
                               2152                 : {
 1837 teodor                   2153 CBC          12 :     Jsonb      *in = PG_GETARG_JSONB_P(0);
 1837 teodor                   2154 EUB             :     JsonbValue  v;
                               2155                 :     Numeric     retValue;
                               2156                 : 
 1837 teodor                   2157 GIC          12 :     if (!JsonbExtractScalar(&in->root, &v) || v.type != jbvNumeric)
 1796                          2158               3 :         cannotCastJsonbValue(v.type, "numeric");
 1837 teodor                   2159 ECB             : 
                               2160                 :     /*
 1809 tgl                      2161                 :      * v.val.numeric points into jsonb body, so we need to make a copy to
                               2162                 :      * return
                               2163                 :      */
 1837 teodor                   2164 GIC           9 :     retValue = DatumGetNumericCopy(NumericGetDatum(v.val.numeric));
                               2165                 : 
                               2166               9 :     PG_FREE_IF_COPY(in, 0);
                               2167                 : 
 1837 teodor                   2168 CBC           9 :     PG_RETURN_NUMERIC(retValue);
                               2169                 : }
 1837 teodor                   2170 ECB             : 
                               2171                 : Datum
 1837 teodor                   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                 : 
 1837 teodor                   2178 CBC           6 :     if (!JsonbExtractScalar(&in->root, &v) || v.type != jbvNumeric)
 1796 teodor                   2179 UIC           0 :         cannotCastJsonbValue(v.type, "smallint");
 1837 teodor                   2180 ECB             : 
 1837 teodor                   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);
 1837 teodor                   2187 ECB             : }
                               2188                 : 
                               2189                 : Datum
 1837 teodor                   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                 : 
 1837 teodor                   2196 CBC          12 :     if (!JsonbExtractScalar(&in->root, &v) || v.type != jbvNumeric)
 1796 teodor                   2197 GIC           3 :         cannotCastJsonbValue(v.type, "integer");
 1837 teodor                   2198 ECB             : 
 1837 teodor                   2199 GIC           9 :     retValue = DirectFunctionCall1(numeric_int4,
                               2200                 :                                    NumericGetDatum(v.val.numeric));
                               2201                 : 
 1837 teodor                   2202 CBC           9 :     PG_FREE_IF_COPY(in, 0);
                               2203                 : 
 1837 teodor                   2204 GIC           9 :     PG_RETURN_DATUM(retValue);
                               2205                 : }
                               2206                 : 
                               2207                 : Datum
                               2208              24 : jsonb_int8(PG_FUNCTION_ARGS)
 1837 teodor                   2209 ECB             : {
 1837 teodor                   2210 GIC          24 :     Jsonb      *in = PG_GETARG_JSONB_P(0);
 1809 tgl                      2211 ECB             :     JsonbValue  v;
 1837 teodor                   2212                 :     Datum       retValue;
                               2213                 : 
 1837 teodor                   2214 CBC          24 :     if (!JsonbExtractScalar(&in->root, &v) || v.type != jbvNumeric)
 1796 teodor                   2215 UIC           0 :         cannotCastJsonbValue(v.type, "bigint");
                               2216                 : 
 1837 teodor                   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);
 1837 teodor                   2223 ECB             : }
                               2224                 : 
                               2225                 : Datum
 1837 teodor                   2226 GIC           6 : jsonb_float4(PG_FUNCTION_ARGS)
 1837 teodor                   2227 ECB             : {
 1837 teodor                   2228 GIC           6 :     Jsonb      *in = PG_GETARG_JSONB_P(0);
                               2229                 :     JsonbValue  v;
 1837 teodor                   2230 ECB             :     Datum       retValue;
                               2231                 : 
 1837 teodor                   2232 CBC           6 :     if (!JsonbExtractScalar(&in->root, &v) || v.type != jbvNumeric)
 1796 teodor                   2233 UIC           0 :         cannotCastJsonbValue(v.type, "real");
                               2234                 : 
 1837 teodor                   2235 GIC           6 :     retValue = DirectFunctionCall1(numeric_float4,
                               2236                 :                                    NumericGetDatum(v.val.numeric));
                               2237                 : 
                               2238               6 :     PG_FREE_IF_COPY(in, 0);
                               2239                 : 
 1837 teodor                   2240 CBC           6 :     PG_RETURN_DATUM(retValue);
                               2241                 : }
                               2242                 : 
                               2243                 : Datum
 1837 teodor                   2244 GIC          12 : jsonb_float8(PG_FUNCTION_ARGS)
                               2245                 : {
 1837 teodor                   2246 CBC          12 :     Jsonb      *in = PG_GETARG_JSONB_P(0);
                               2247                 :     JsonbValue  v;
                               2248                 :     Datum       retValue;
 1837 teodor                   2249 ECB             : 
 1837 teodor                   2250 CBC          12 :     if (!JsonbExtractScalar(&in->root, &v) || v.type != jbvNumeric)
 1796 teodor                   2251 GIC           3 :         cannotCastJsonbValue(v.type, "double precision");
                               2252                 : 
 1837                          2253               9 :     retValue = DirectFunctionCall1(numeric_float8,
                               2254                 :                                    NumericGetDatum(v.val.numeric));
                               2255                 : 
                               2256               9 :     PG_FREE_IF_COPY(in, 0);
 1837 teodor                   2257 ECB             : 
 1837 teodor                   2258 GIC           9 :     PG_RETURN_DATUM(retValue);
 1837 teodor                   2259 ECB             : }
        

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