PostgreSQL Source Code git master
jsonb.c File Reference
#include "postgres.h"
#include "access/htup_details.h"
#include "catalog/pg_proc.h"
#include "catalog/pg_type.h"
#include "funcapi.h"
#include "libpq/pqformat.h"
#include "miscadmin.h"
#include "utils/builtins.h"
#include "utils/json.h"
#include "utils/jsonb.h"
#include "utils/jsonfuncs.h"
#include "utils/lsyscache.h"
#include "utils/typcache.h"
Include dependency graph for jsonb.c:

Go to the source code of this file.

Data Structures

struct  JsonbInState
 
struct  JsonbAggState
 

Typedefs

typedef struct JsonbInState JsonbInState
 
typedef struct JsonbAggState JsonbAggState
 

Functions

static Datum jsonb_from_cstring (char *json, int len, bool unique_keys, Node *escontext)
 
static bool checkStringLen (size_t len, Node *escontext)
 
static JsonParseErrorType jsonb_in_object_start (void *pstate)
 
static JsonParseErrorType jsonb_in_object_end (void *pstate)
 
static JsonParseErrorType jsonb_in_array_start (void *pstate)
 
static JsonParseErrorType jsonb_in_array_end (void *pstate)
 
static JsonParseErrorType jsonb_in_object_field_start (void *pstate, char *fname, bool isnull)
 
static void jsonb_put_escaped_value (StringInfo out, JsonbValue *scalarVal)
 
static JsonParseErrorType jsonb_in_scalar (void *pstate, char *token, JsonTokenType tokentype)
 
static void composite_to_jsonb (Datum composite, JsonbInState *result)
 
static void array_dim_to_jsonb (JsonbInState *result, int dim, int ndims, int *dims, const Datum *vals, const bool *nulls, int *valcount, JsonTypeCategory tcategory, Oid outfuncoid)
 
static void array_to_jsonb_internal (Datum array, JsonbInState *result)
 
static void datum_to_jsonb_internal (Datum val, bool is_null, JsonbInState *result, JsonTypeCategory tcategory, Oid outfuncoid, bool key_scalar)
 
static void add_jsonb (Datum val, bool is_null, JsonbInState *result, Oid val_type, bool key_scalar)
 
static JsonbParseStateclone_parse_state (JsonbParseState *state)
 
static char * JsonbToCStringWorker (StringInfo out, JsonbContainer *in, int estimated_len, bool indent)
 
static void add_indent (StringInfo out, bool indent, int level)
 
Datum jsonb_in (PG_FUNCTION_ARGS)
 
Datum jsonb_recv (PG_FUNCTION_ARGS)
 
Datum jsonb_out (PG_FUNCTION_ARGS)
 
Datum jsonb_send (PG_FUNCTION_ARGS)
 
Datum jsonb_from_text (text *js, bool unique_keys)
 
static const char * JsonbContainerTypeName (JsonbContainer *jbc)
 
const char * JsonbTypeName (JsonbValue *val)
 
Datum jsonb_typeof (PG_FUNCTION_ARGS)
 
char * JsonbToCString (StringInfo out, JsonbContainer *in, int estimated_len)
 
char * JsonbToCStringIndent (StringInfo out, JsonbContainer *in, int estimated_len)
 
bool to_jsonb_is_immutable (Oid typoid)
 
Datum to_jsonb (PG_FUNCTION_ARGS)
 
Datum datum_to_jsonb (Datum val, JsonTypeCategory tcategory, Oid outfuncoid)
 
Datum jsonb_build_object_worker (int nargs, const Datum *args, const bool *nulls, const Oid *types, bool absent_on_null, bool unique_keys)
 
Datum jsonb_build_object (PG_FUNCTION_ARGS)
 
Datum jsonb_build_object_noargs (PG_FUNCTION_ARGS)
 
Datum jsonb_build_array_worker (int nargs, const Datum *args, const bool *nulls, const Oid *types, bool absent_on_null)
 
Datum jsonb_build_array (PG_FUNCTION_ARGS)
 
Datum jsonb_build_array_noargs (PG_FUNCTION_ARGS)
 
Datum jsonb_object (PG_FUNCTION_ARGS)
 
Datum jsonb_object_two_arg (PG_FUNCTION_ARGS)
 
static Datum jsonb_agg_transfn_worker (FunctionCallInfo fcinfo, bool absent_on_null)
 
Datum jsonb_agg_transfn (PG_FUNCTION_ARGS)
 
Datum jsonb_agg_strict_transfn (PG_FUNCTION_ARGS)
 
Datum jsonb_agg_finalfn (PG_FUNCTION_ARGS)
 
static Datum jsonb_object_agg_transfn_worker (FunctionCallInfo fcinfo, bool absent_on_null, bool unique_keys)
 
Datum jsonb_object_agg_transfn (PG_FUNCTION_ARGS)
 
Datum jsonb_object_agg_strict_transfn (PG_FUNCTION_ARGS)
 
Datum jsonb_object_agg_unique_transfn (PG_FUNCTION_ARGS)
 
Datum jsonb_object_agg_unique_strict_transfn (PG_FUNCTION_ARGS)
 
Datum jsonb_object_agg_finalfn (PG_FUNCTION_ARGS)
 
bool JsonbExtractScalar (JsonbContainer *jbc, JsonbValue *res)
 
static void cannotCastJsonbValue (enum jbvType type, const char *sqltype)
 
Datum jsonb_bool (PG_FUNCTION_ARGS)
 
Datum jsonb_numeric (PG_FUNCTION_ARGS)
 
Datum jsonb_int2 (PG_FUNCTION_ARGS)
 
Datum jsonb_int4 (PG_FUNCTION_ARGS)
 
Datum jsonb_int8 (PG_FUNCTION_ARGS)
 
Datum jsonb_float4 (PG_FUNCTION_ARGS)
 
Datum jsonb_float8 (PG_FUNCTION_ARGS)
 
char * JsonbUnquote (Jsonb *jb)
 

Typedef Documentation

◆ JsonbAggState

typedef struct JsonbAggState JsonbAggState

◆ JsonbInState

typedef struct JsonbInState JsonbInState

Function Documentation

◆ add_indent()

static void add_indent ( StringInfo  out,
bool  indent,
int  level 
)
static

Definition at line 615 of file jsonb.c.

616{
617 if (indent)
618 {
619 appendStringInfoCharMacro(out, '\n');
620 appendStringInfoSpaces(out, level * 4);
621 }
622}
void appendStringInfoSpaces(StringInfo str, int count)
Definition: stringinfo.c:260
#define appendStringInfoCharMacro(str, ch)
Definition: stringinfo.h:231

References appendStringInfoCharMacro, and appendStringInfoSpaces().

Referenced by JsonbToCStringWorker().

◆ add_jsonb()

static void add_jsonb ( Datum  val,
bool  is_null,
JsonbInState result,
Oid  val_type,
bool  key_scalar 
)
static

Definition at line 1016 of file jsonb.c.

1018{
1019 JsonTypeCategory tcategory;
1020 Oid outfuncoid;
1021
1022 if (val_type == InvalidOid)
1023 ereport(ERROR,
1024 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1025 errmsg("could not determine input data type")));
1026
1027 if (is_null)
1028 {
1029 tcategory = JSONTYPE_NULL;
1030 outfuncoid = InvalidOid;
1031 }
1032 else
1033 json_categorize_type(val_type, true,
1034 &tcategory, &outfuncoid);
1035
1036 datum_to_jsonb_internal(val, is_null, result, tcategory, outfuncoid,
1037 key_scalar);
1038}
int errcode(int sqlerrcode)
Definition: elog.c:853
int errmsg(const char *fmt,...)
Definition: elog.c:1070
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:149
long val
Definition: informix.c:689
static void datum_to_jsonb_internal(Datum val, bool is_null, JsonbInState *result, JsonTypeCategory tcategory, Oid outfuncoid, bool key_scalar)
Definition: jsonb.c:638
void json_categorize_type(Oid typoid, bool is_jsonb, JsonTypeCategory *tcategory, Oid *outfuncoid)
Definition: jsonfuncs.c:5976
JsonTypeCategory
Definition: jsonfuncs.h:69
@ JSONTYPE_NULL
Definition: jsonfuncs.h:70
#define InvalidOid
Definition: postgres_ext.h:37
unsigned int Oid
Definition: postgres_ext.h:32

References datum_to_jsonb_internal(), ereport, errcode(), errmsg(), ERROR, InvalidOid, json_categorize_type(), JSONTYPE_NULL, and val.

Referenced by jsonb_build_array_worker(), and jsonb_build_object_worker().

◆ array_dim_to_jsonb()

static void array_dim_to_jsonb ( JsonbInState result,
int  dim,
int  ndims,
int *  dims,
const Datum vals,
const bool *  nulls,
int *  valcount,
JsonTypeCategory  tcategory,
Oid  outfuncoid 
)
static

Definition at line 862 of file jsonb.c.

865{
866 int i;
867
868 Assert(dim < ndims);
869
870 result->res = pushJsonbValue(&result->parseState, WJB_BEGIN_ARRAY, NULL);
871
872 for (i = 1; i <= dims[dim]; i++)
873 {
874 if (dim + 1 == ndims)
875 {
876 datum_to_jsonb_internal(vals[*valcount], nulls[*valcount], result, tcategory,
877 outfuncoid, false);
878 (*valcount)++;
879 }
880 else
881 {
882 array_dim_to_jsonb(result, dim + 1, ndims, dims, vals, nulls,
883 valcount, tcategory, outfuncoid);
884 }
885 }
886
887 result->res = pushJsonbValue(&result->parseState, WJB_END_ARRAY, NULL);
888}
#define Assert(condition)
Definition: c.h:815
int i
Definition: isn.c:72
static void array_dim_to_jsonb(JsonbInState *result, int dim, int ndims, int *dims, const Datum *vals, const bool *nulls, int *valcount, JsonTypeCategory tcategory, Oid outfuncoid)
Definition: jsonb.c:862
@ WJB_END_ARRAY
Definition: jsonb.h:27
@ WJB_BEGIN_ARRAY
Definition: jsonb.h:26
JsonbValue * pushJsonbValue(JsonbParseState **pstate, JsonbIteratorToken seq, JsonbValue *jbval)
Definition: jsonb_util.c:573
JsonbParseState * parseState
Definition: jsonb.c:30
JsonbValue * res
Definition: jsonb.c:31

References array_dim_to_jsonb(), Assert, datum_to_jsonb_internal(), i, JsonbInState::parseState, pushJsonbValue(), JsonbInState::res, WJB_BEGIN_ARRAY, and WJB_END_ARRAY.

Referenced by array_dim_to_jsonb(), and array_to_jsonb_internal().

◆ array_to_jsonb_internal()

static void array_to_jsonb_internal ( Datum  array,
JsonbInState result 
)
static

Definition at line 894 of file jsonb.c.

895{
896 ArrayType *v = DatumGetArrayTypeP(array);
897 Oid element_type = ARR_ELEMTYPE(v);
898 int *dim;
899 int ndim;
900 int nitems;
901 int count = 0;
902 Datum *elements;
903 bool *nulls;
904 int16 typlen;
905 bool typbyval;
906 char typalign;
907 JsonTypeCategory tcategory;
908 Oid outfuncoid;
909
910 ndim = ARR_NDIM(v);
911 dim = ARR_DIMS(v);
912 nitems = ArrayGetNItems(ndim, dim);
913
914 if (nitems <= 0)
915 {
916 result->res = pushJsonbValue(&result->parseState, WJB_BEGIN_ARRAY, NULL);
917 result->res = pushJsonbValue(&result->parseState, WJB_END_ARRAY, NULL);
918 return;
919 }
920
921 get_typlenbyvalalign(element_type,
922 &typlen, &typbyval, &typalign);
923
924 json_categorize_type(element_type, true,
925 &tcategory, &outfuncoid);
926
927 deconstruct_array(v, element_type, typlen, typbyval,
928 typalign, &elements, &nulls,
929 &nitems);
930
931 array_dim_to_jsonb(result, 0, ndim, dim, elements, nulls, &count, tcategory,
932 outfuncoid);
933
934 pfree(elements);
935 pfree(nulls);
936}
#define ARR_NDIM(a)
Definition: array.h:290
#define DatumGetArrayTypeP(X)
Definition: array.h:261
#define ARR_ELEMTYPE(a)
Definition: array.h:292
#define ARR_DIMS(a)
Definition: array.h:294
void deconstruct_array(ArrayType *array, Oid elmtype, int elmlen, bool elmbyval, char elmalign, Datum **elemsp, bool **nullsp, int *nelemsp)
Definition: arrayfuncs.c:3631
int ArrayGetNItems(int ndim, const int *dims)
Definition: arrayutils.c:57
int16_t int16
Definition: c.h:483
#define nitems(x)
Definition: indent.h:31
void get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval, char *typalign)
Definition: lsyscache.c:2271
void pfree(void *pointer)
Definition: mcxt.c:1521
char typalign
Definition: pg_type.h:176
uintptr_t Datum
Definition: postgres.h:69

References ARR_DIMS, ARR_ELEMTYPE, ARR_NDIM, array_dim_to_jsonb(), ArrayGetNItems(), DatumGetArrayTypeP, deconstruct_array(), get_typlenbyvalalign(), json_categorize_type(), nitems, JsonbInState::parseState, pfree(), pushJsonbValue(), JsonbInState::res, typalign, WJB_BEGIN_ARRAY, and WJB_END_ARRAY.

Referenced by datum_to_jsonb_internal().

◆ cannotCastJsonbValue()

static void cannotCastJsonbValue ( enum jbvType  type,
const char *  sqltype 
)
static

Definition at line 2008 of file jsonb.c.

2009{
2010 static const struct
2011 {
2012 enum jbvType type;
2013 const char *msg;
2014 }
2015 messages[] =
2016 {
2017 {jbvNull, gettext_noop("cannot cast jsonb null to type %s")},
2018 {jbvString, gettext_noop("cannot cast jsonb string to type %s")},
2019 {jbvNumeric, gettext_noop("cannot cast jsonb numeric to type %s")},
2020 {jbvBool, gettext_noop("cannot cast jsonb boolean to type %s")},
2021 {jbvArray, gettext_noop("cannot cast jsonb array to type %s")},
2022 {jbvObject, gettext_noop("cannot cast jsonb object to type %s")},
2023 {jbvBinary, gettext_noop("cannot cast jsonb array or object to type %s")}
2024 };
2025 int i;
2026
2027 for (i = 0; i < lengthof(messages); i++)
2028 if (messages[i].type == type)
2029 ereport(ERROR,
2030 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2031 errmsg(messages[i].msg, sqltype)));
2032
2033 /* should be unreachable */
2034 elog(ERROR, "unknown jsonb type: %d", (int) type);
2035}
#define gettext_noop(x)
Definition: c.h:1153
#define lengthof(array)
Definition: c.h:745
#define elog(elevel,...)
Definition: elog.h:225
jbvType
Definition: jsonb.h:226
@ jbvObject
Definition: jsonb.h:234
@ jbvNumeric
Definition: jsonb.h:230
@ jbvBool
Definition: jsonb.h:231
@ jbvArray
Definition: jsonb.h:233
@ jbvBinary
Definition: jsonb.h:236
@ jbvNull
Definition: jsonb.h:228
@ jbvString
Definition: jsonb.h:229
const char * type

References elog, ereport, errcode(), errmsg(), ERROR, gettext_noop, i, jbvArray, jbvBinary, jbvBool, jbvNull, jbvNumeric, jbvObject, jbvString, lengthof, and type.

Referenced by jsonb_bool(), jsonb_float4(), jsonb_float8(), jsonb_int2(), jsonb_int4(), jsonb_int8(), and jsonb_numeric().

◆ checkStringLen()

static bool checkStringLen ( size_t  len,
Node escontext 
)
static

Definition at line 277 of file jsonb.c.

278{
280 ereturn(escontext, false,
281 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
282 errmsg("string too long to represent as jsonb string"),
283 errdetail("Due to an implementation restriction, jsonb strings cannot exceed %d bytes.",
285
286 return true;
287}
int errdetail(const char *fmt,...)
Definition: elog.c:1203
#define ereturn(context, dummy_value,...)
Definition: elog.h:277
#define JENTRY_OFFLENMASK
Definition: jsonb.h:138
const void size_t len

References ereturn, errcode(), errdetail(), errmsg(), JENTRY_OFFLENMASK, and len.

Referenced by datum_to_jsonb_internal(), jsonb_in_object_field_start(), and jsonb_in_scalar().

◆ clone_parse_state()

static JsonbParseState * clone_parse_state ( JsonbParseState state)
static

Definition at line 1471 of file jsonb.c.

1472{
1473 JsonbParseState *result,
1474 *icursor,
1475 *ocursor;
1476
1477 if (state == NULL)
1478 return NULL;
1479
1480 result = palloc(sizeof(JsonbParseState));
1481 icursor = state;
1482 ocursor = result;
1483 for (;;)
1484 {
1485 ocursor->contVal = icursor->contVal;
1486 ocursor->size = icursor->size;
1487 ocursor->unique_keys = icursor->unique_keys;
1488 ocursor->skip_nulls = icursor->skip_nulls;
1489 icursor = icursor->next;
1490 if (icursor == NULL)
1491 break;
1492 ocursor->next = palloc(sizeof(JsonbParseState));
1493 ocursor = ocursor->next;
1494 }
1495 ocursor->next = NULL;
1496
1497 return result;
1498}
void * palloc(Size size)
Definition: mcxt.c:1317
bool unique_keys
Definition: jsonb.h:324
struct JsonbParseState * next
Definition: jsonb.h:323
bool skip_nulls
Definition: jsonb.h:325
JsonbValue contVal
Definition: jsonb.h:321
Definition: regguts.h:323

References JsonbParseState::contVal, JsonbParseState::next, palloc(), JsonbParseState::size, JsonbParseState::skip_nulls, and JsonbParseState::unique_keys.

Referenced by jsonb_agg_finalfn(), and jsonb_object_agg_finalfn().

◆ composite_to_jsonb()

static void composite_to_jsonb ( Datum  composite,
JsonbInState result 
)
static

Definition at line 942 of file jsonb.c.

943{
945 Oid tupType;
946 int32 tupTypmod;
947 TupleDesc tupdesc;
948 HeapTupleData tmptup,
949 *tuple;
950 int i;
951
952 td = DatumGetHeapTupleHeader(composite);
953
954 /* Extract rowtype info and find a tupdesc */
955 tupType = HeapTupleHeaderGetTypeId(td);
956 tupTypmod = HeapTupleHeaderGetTypMod(td);
957 tupdesc = lookup_rowtype_tupdesc(tupType, tupTypmod);
958
959 /* Build a temporary HeapTuple control structure */
961 tmptup.t_data = td;
962 tuple = &tmptup;
963
964 result->res = pushJsonbValue(&result->parseState, WJB_BEGIN_OBJECT, NULL);
965
966 for (i = 0; i < tupdesc->natts; i++)
967 {
968 Datum val;
969 bool isnull;
970 char *attname;
971 JsonTypeCategory tcategory;
972 Oid outfuncoid;
973 JsonbValue v;
974 Form_pg_attribute att = TupleDescAttr(tupdesc, i);
975
976 if (att->attisdropped)
977 continue;
978
979 attname = NameStr(att->attname);
980
981 v.type = jbvString;
982 /* don't need checkStringLen here - can't exceed maximum name length */
983 v.val.string.len = strlen(attname);
984 v.val.string.val = attname;
985
986 result->res = pushJsonbValue(&result->parseState, WJB_KEY, &v);
987
988 val = heap_getattr(tuple, i + 1, tupdesc, &isnull);
989
990 if (isnull)
991 {
992 tcategory = JSONTYPE_NULL;
993 outfuncoid = InvalidOid;
994 }
995 else
996 json_categorize_type(att->atttypid, true, &tcategory,
997 &outfuncoid);
998
999 datum_to_jsonb_internal(val, isnull, result, tcategory, outfuncoid,
1000 false);
1001 }
1002
1003 result->res = pushJsonbValue(&result->parseState, WJB_END_OBJECT, NULL);
1004 ReleaseTupleDesc(tupdesc);
1005}
#define NameStr(name)
Definition: c.h:703
int32_t int32
Definition: c.h:484
#define DatumGetHeapTupleHeader(X)
Definition: fmgr.h:295
static Datum heap_getattr(HeapTuple tup, int attnum, TupleDesc tupleDesc, bool *isnull)
Definition: htup_details.h:903
static int32 HeapTupleHeaderGetTypMod(const HeapTupleHeaderData *tup)
Definition: htup_details.h:516
static uint32 HeapTupleHeaderGetDatumLength(const HeapTupleHeaderData *tup)
Definition: htup_details.h:492
static Oid HeapTupleHeaderGetTypeId(const HeapTupleHeaderData *tup)
Definition: htup_details.h:504
@ WJB_KEY
Definition: jsonb.h:23
@ WJB_END_OBJECT
Definition: jsonb.h:29
@ WJB_BEGIN_OBJECT
Definition: jsonb.h:28
NameData attname
Definition: pg_attribute.h:41
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:200
uint32 t_len
Definition: htup.h:64
HeapTupleHeader t_data
Definition: htup.h:68
enum jbvType type
Definition: jsonb.h:255
char * val
Definition: jsonb.h:264
#define ReleaseTupleDesc(tupdesc)
Definition: tupdesc.h:212
static FormData_pg_attribute * TupleDescAttr(TupleDesc tupdesc, int i)
Definition: tupdesc.h:153
TupleDesc lookup_rowtype_tupdesc(Oid type_id, int32 typmod)
Definition: typcache.c:1920

References attname, datum_to_jsonb_internal(), DatumGetHeapTupleHeader, heap_getattr(), HeapTupleHeaderGetDatumLength(), HeapTupleHeaderGetTypeId(), HeapTupleHeaderGetTypMod(), i, InvalidOid, jbvString, json_categorize_type(), JSONTYPE_NULL, lookup_rowtype_tupdesc(), NameStr, TupleDescData::natts, JsonbInState::parseState, pushJsonbValue(), ReleaseTupleDesc, JsonbInState::res, HeapTupleData::t_data, HeapTupleData::t_len, TupleDescAttr(), JsonbValue::type, JsonbValue::val, val, WJB_BEGIN_OBJECT, WJB_END_OBJECT, and WJB_KEY.

Referenced by datum_to_jsonb_internal().

◆ datum_to_jsonb()

Datum datum_to_jsonb ( Datum  val,
JsonTypeCategory  tcategory,
Oid  outfuncoid 
)

Definition at line 1112 of file jsonb.c.

1113{
1114 JsonbInState result;
1115
1116 memset(&result, 0, sizeof(JsonbInState));
1117
1118 datum_to_jsonb_internal(val, false, &result, tcategory, outfuncoid,
1119 false);
1120
1121 return JsonbPGetDatum(JsonbValueToJsonb(result.res));
1122}
static Datum JsonbPGetDatum(const Jsonb *p)
Definition: jsonb.h:386
Jsonb * JsonbValueToJsonb(JsonbValue *val)
Definition: jsonb_util.c:92

References datum_to_jsonb_internal(), JsonbPGetDatum(), JsonbValueToJsonb(), JsonbInState::res, and val.

Referenced by ExecEvalJsonConstructor(), and to_jsonb().

◆ datum_to_jsonb_internal()

static void datum_to_jsonb_internal ( Datum  val,
bool  is_null,
JsonbInState result,
JsonTypeCategory  tcategory,
Oid  outfuncoid,
bool  key_scalar 
)
static

Definition at line 638 of file jsonb.c.

641{
642 char *outputstr;
643 bool numeric_error;
644 JsonbValue jb;
645 bool scalar_jsonb = false;
646
648
649 /* Convert val to a JsonbValue in jb (in most cases) */
650 if (is_null)
651 {
652 Assert(!key_scalar);
653 jb.type = jbvNull;
654 }
655 else if (key_scalar &&
656 (tcategory == JSONTYPE_ARRAY ||
657 tcategory == JSONTYPE_COMPOSITE ||
658 tcategory == JSONTYPE_JSON ||
659 tcategory == JSONTYPE_JSONB ||
660 tcategory == JSONTYPE_JSON))
661 {
663 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
664 errmsg("key value must be scalar, not array, composite, or json")));
665 }
666 else
667 {
668 if (tcategory == JSONTYPE_CAST)
669 val = OidFunctionCall1(outfuncoid, val);
670
671 switch (tcategory)
672 {
673 case JSONTYPE_ARRAY:
675 break;
677 composite_to_jsonb(val, result);
678 break;
679 case JSONTYPE_BOOL:
680 if (key_scalar)
681 {
682 outputstr = DatumGetBool(val) ? "true" : "false";
683 jb.type = jbvString;
684 jb.val.string.len = strlen(outputstr);
685 jb.val.string.val = outputstr;
686 }
687 else
688 {
689 jb.type = jbvBool;
690 jb.val.boolean = DatumGetBool(val);
691 }
692 break;
693 case JSONTYPE_NUMERIC:
694 outputstr = OidOutputFunctionCall(outfuncoid, val);
695 if (key_scalar)
696 {
697 /* always quote keys */
698 jb.type = jbvString;
699 jb.val.string.len = strlen(outputstr);
700 jb.val.string.val = outputstr;
701 }
702 else
703 {
704 /*
705 * Make it numeric if it's a valid JSON number, otherwise
706 * a string. Invalid numeric output will always have an
707 * 'N' or 'n' in it (I think).
708 */
709 numeric_error = (strchr(outputstr, 'N') != NULL ||
710 strchr(outputstr, 'n') != NULL);
711 if (!numeric_error)
712 {
713 Datum numd;
714
715 jb.type = jbvNumeric;
717 CStringGetDatum(outputstr),
719 Int32GetDatum(-1));
720 jb.val.numeric = DatumGetNumeric(numd);
721 pfree(outputstr);
722 }
723 else
724 {
725 jb.type = jbvString;
726 jb.val.string.len = strlen(outputstr);
727 jb.val.string.val = outputstr;
728 }
729 }
730 break;
731 case JSONTYPE_DATE:
732 jb.type = jbvString;
733 jb.val.string.val = JsonEncodeDateTime(NULL, val,
734 DATEOID, NULL);
735 jb.val.string.len = strlen(jb.val.string.val);
736 break;
738 jb.type = jbvString;
739 jb.val.string.val = JsonEncodeDateTime(NULL, val,
740 TIMESTAMPOID, NULL);
741 jb.val.string.len = strlen(jb.val.string.val);
742 break;
744 jb.type = jbvString;
745 jb.val.string.val = JsonEncodeDateTime(NULL, val,
746 TIMESTAMPTZOID, NULL);
747 jb.val.string.len = strlen(jb.val.string.val);
748 break;
749 case JSONTYPE_CAST:
750 case JSONTYPE_JSON:
751 {
752 /* parse the json right into the existing result object */
753 JsonLexContext lex;
755 text *json = DatumGetTextPP(val);
756
757 makeJsonLexContext(&lex, json, true);
758
759 memset(&sem, 0, sizeof(sem));
760
761 sem.semstate = result;
762
769
771 freeJsonLexContext(&lex);
772 }
773 break;
774 case JSONTYPE_JSONB:
775 {
776 Jsonb *jsonb = DatumGetJsonbP(val);
777 JsonbIterator *it;
778
779 it = JsonbIteratorInit(&jsonb->root);
780
781 if (JB_ROOT_IS_SCALAR(jsonb))
782 {
783 (void) JsonbIteratorNext(&it, &jb, true);
784 Assert(jb.type == jbvArray);
785 (void) JsonbIteratorNext(&it, &jb, true);
786 scalar_jsonb = true;
787 }
788 else
789 {
791
792 while ((type = JsonbIteratorNext(&it, &jb, false))
793 != WJB_DONE)
794 {
795 if (type == WJB_END_ARRAY || type == WJB_END_OBJECT ||
797 result->res = pushJsonbValue(&result->parseState,
798 type, NULL);
799 else
800 result->res = pushJsonbValue(&result->parseState,
801 type, &jb);
802 }
803 }
804 }
805 break;
806 default:
807 outputstr = OidOutputFunctionCall(outfuncoid, val);
808 jb.type = jbvString;
809 jb.val.string.len = strlen(outputstr);
810 (void) checkStringLen(jb.val.string.len, NULL);
811 jb.val.string.val = outputstr;
812 break;
813 }
814 }
815
816 /* Now insert jb into result, unless we did it recursively */
817 if (!is_null && !scalar_jsonb &&
818 tcategory >= JSONTYPE_JSON && tcategory <= JSONTYPE_CAST)
819 {
820 /* work has been done recursively */
821 return;
822 }
823 else if (result->parseState == NULL)
824 {
825 /* single root scalar */
826 JsonbValue va;
827
828 va.type = jbvArray;
829 va.val.array.rawScalar = true;
830 va.val.array.nElems = 1;
831
832 result->res = pushJsonbValue(&result->parseState, WJB_BEGIN_ARRAY, &va);
833 result->res = pushJsonbValue(&result->parseState, WJB_ELEM, &jb);
834 result->res = pushJsonbValue(&result->parseState, WJB_END_ARRAY, NULL);
835 }
836 else
837 {
838 JsonbValue *o = &result->parseState->contVal;
839
840 switch (o->type)
841 {
842 case jbvArray:
843 result->res = pushJsonbValue(&result->parseState, WJB_ELEM, &jb);
844 break;
845 case jbvObject:
846 result->res = pushJsonbValue(&result->parseState,
847 key_scalar ? WJB_KEY : WJB_VALUE,
848 &jb);
849 break;
850 default:
851 elog(ERROR, "unexpected parent of nested structure");
852 }
853 }
854}
Datum numeric_in(PG_FUNCTION_ARGS)
Definition: numeric.c:637
char * OidOutputFunctionCall(Oid functionId, Datum val)
Definition: fmgr.c:1763
#define OidFunctionCall1(functionId, arg1)
Definition: fmgr.h:679
#define DatumGetTextPP(X)
Definition: fmgr.h:292
#define DirectFunctionCall3(func, arg1, arg2, arg3)
Definition: fmgr.h:645
char * JsonEncodeDateTime(char *buf, Datum value, Oid typid, const int *tzp)
Definition: json.c:310
void freeJsonLexContext(JsonLexContext *lex)
Definition: jsonapi.c:687
static JsonParseErrorType jsonb_in_object_start(void *pstate)
Definition: jsonb.c:290
static JsonParseErrorType jsonb_in_array_end(void *pstate)
Definition: jsonb.c:321
static JsonParseErrorType jsonb_in_object_field_start(void *pstate, char *fname, bool isnull)
Definition: jsonb.c:331
static void array_to_jsonb_internal(Datum array, JsonbInState *result)
Definition: jsonb.c:894
static void composite_to_jsonb(Datum composite, JsonbInState *result)
Definition: jsonb.c:942
static JsonParseErrorType jsonb_in_array_start(void *pstate)
Definition: jsonb.c:311
static JsonParseErrorType jsonb_in_object_end(void *pstate)
Definition: jsonb.c:301
static JsonParseErrorType jsonb_in_scalar(void *pstate, char *token, JsonTokenType tokentype)
Definition: jsonb.c:379
static bool checkStringLen(size_t len, Node *escontext)
Definition: jsonb.c:277
static Jsonb * DatumGetJsonbP(Datum d)
Definition: jsonb.h:374
#define JB_ROOT_IS_SCALAR(jbp_)
Definition: jsonb.h:220
JsonbIteratorToken
Definition: jsonb.h:21
@ WJB_DONE
Definition: jsonb.h:22
@ WJB_VALUE
Definition: jsonb.h:24
@ WJB_ELEM
Definition: jsonb.h:25
JsonbIterator * JsonbIteratorInit(JsonbContainer *container)
Definition: jsonb_util.c:824
JsonbIteratorToken JsonbIteratorNext(JsonbIterator **it, JsonbValue *val, bool skipNested)
Definition: jsonb_util.c:860
JsonLexContext * makeJsonLexContext(JsonLexContext *lex, text *json, bool need_escapes)
Definition: jsonfuncs.c:539
#define pg_parse_json_or_ereport(lex, sem)
Definition: jsonfuncs.h:47
@ JSONTYPE_JSON
Definition: jsonfuncs.h:76
@ JSONTYPE_TIMESTAMP
Definition: jsonfuncs.h:74
@ JSONTYPE_NUMERIC
Definition: jsonfuncs.h:72
@ JSONTYPE_DATE
Definition: jsonfuncs.h:73
@ JSONTYPE_BOOL
Definition: jsonfuncs.h:71
@ JSONTYPE_CAST
Definition: jsonfuncs.h:80
@ JSONTYPE_COMPOSITE
Definition: jsonfuncs.h:79
@ JSONTYPE_ARRAY
Definition: jsonfuncs.h:78
@ JSONTYPE_TIMESTAMPTZ
Definition: jsonfuncs.h:75
@ JSONTYPE_JSONB
Definition: jsonfuncs.h:77
static Numeric DatumGetNumeric(Datum X)
Definition: numeric.h:61
static bool DatumGetBool(Datum X)
Definition: postgres.h:95
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:257
static Datum CStringGetDatum(const char *X)
Definition: postgres.h:355
static Datum Int32GetDatum(int32 X)
Definition: postgres.h:217
void check_stack_depth(void)
Definition: stack_depth.c:95
json_struct_action array_end
Definition: jsonapi.h:157
json_struct_action object_start
Definition: jsonapi.h:154
json_ofield_action object_field_start
Definition: jsonapi.h:158
json_scalar_action scalar
Definition: jsonapi.h:162
void * semstate
Definition: jsonapi.h:153
json_struct_action array_start
Definition: jsonapi.h:156
json_struct_action object_end
Definition: jsonapi.h:155
Definition: jsonb.h:213
JsonbContainer root
Definition: jsonb.h:215
Definition: c.h:644
static JsonSemAction sem

References JsonSemAction::array_end, JsonSemAction::array_start, array_to_jsonb_internal(), Assert, check_stack_depth(), checkStringLen(), composite_to_jsonb(), JsonbParseState::contVal, CStringGetDatum(), DatumGetBool(), DatumGetJsonbP(), DatumGetNumeric(), DatumGetTextPP, DirectFunctionCall3, elog, ereport, errcode(), errmsg(), ERROR, freeJsonLexContext(), Int32GetDatum(), InvalidOid, JB_ROOT_IS_SCALAR, jbvArray, jbvBool, jbvNull, jbvNumeric, jbvObject, jbvString, jsonb_in_array_end(), jsonb_in_array_start(), jsonb_in_object_end(), jsonb_in_object_field_start(), jsonb_in_object_start(), jsonb_in_scalar(), JsonbIteratorInit(), JsonbIteratorNext(), JsonEncodeDateTime(), JSONTYPE_ARRAY, JSONTYPE_BOOL, JSONTYPE_CAST, JSONTYPE_COMPOSITE, JSONTYPE_DATE, JSONTYPE_JSON, JSONTYPE_JSONB, JSONTYPE_NUMERIC, JSONTYPE_TIMESTAMP, JSONTYPE_TIMESTAMPTZ, makeJsonLexContext(), numeric_in(), JsonSemAction::object_end, JsonSemAction::object_field_start, JsonSemAction::object_start, ObjectIdGetDatum(), OidFunctionCall1, OidOutputFunctionCall(), JsonbInState::parseState, pfree(), pg_parse_json_or_ereport, pushJsonbValue(), JsonbInState::res, Jsonb::root, JsonSemAction::scalar, sem, JsonSemAction::semstate, type, JsonbValue::type, JsonbValue::val, val, WJB_BEGIN_ARRAY, WJB_BEGIN_OBJECT, WJB_DONE, WJB_ELEM, WJB_END_ARRAY, WJB_END_OBJECT, WJB_KEY, and WJB_VALUE.

Referenced by add_jsonb(), array_dim_to_jsonb(), composite_to_jsonb(), datum_to_jsonb(), jsonb_agg_transfn_worker(), and jsonb_object_agg_transfn_worker().

◆ jsonb_agg_finalfn()

Datum jsonb_agg_finalfn ( PG_FUNCTION_ARGS  )

Definition at line 1640 of file jsonb.c.

1641{
1643 JsonbInState result;
1644 Jsonb *out;
1645
1646 /* cannot be called directly because of internal-type argument */
1647 Assert(AggCheckCallContext(fcinfo, NULL));
1648
1649 if (PG_ARGISNULL(0))
1650 PG_RETURN_NULL(); /* returns null iff no input values */
1651
1653
1654 /*
1655 * We need to do a shallow clone of the argument in case the final
1656 * function is called more than once, so we avoid changing the argument. A
1657 * shallow clone is sufficient as we aren't going to change any of the
1658 * values, just add the final array end marker.
1659 */
1660 memset(&result, 0, sizeof(JsonbInState));
1661
1662 result.parseState = clone_parse_state(arg->res->parseState);
1663
1664 result.res = pushJsonbValue(&result.parseState,
1665 WJB_END_ARRAY, NULL);
1666
1667 out = JsonbValueToJsonb(result.res);
1668
1669 PG_RETURN_POINTER(out);
1670}
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:276
#define PG_ARGISNULL(n)
Definition: fmgr.h:209
#define PG_RETURN_NULL()
Definition: fmgr.h:345
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:361
static JsonbParseState * clone_parse_state(JsonbParseState *state)
Definition: jsonb.c:1471
int AggCheckCallContext(FunctionCallInfo fcinfo, MemoryContext *aggcontext)
Definition: nodeAgg.c:4504
void * arg

References AggCheckCallContext(), arg, Assert, clone_parse_state(), JsonbValueToJsonb(), JsonbInState::parseState, PG_ARGISNULL, PG_GETARG_POINTER, PG_RETURN_NULL, PG_RETURN_POINTER, pushJsonbValue(), JsonbInState::res, and WJB_END_ARRAY.

◆ jsonb_agg_strict_transfn()

Datum jsonb_agg_strict_transfn ( PG_FUNCTION_ARGS  )

Definition at line 1634 of file jsonb.c.

1635{
1636 return jsonb_agg_transfn_worker(fcinfo, true);
1637}
static Datum jsonb_agg_transfn_worker(FunctionCallInfo fcinfo, bool absent_on_null)
Definition: jsonb.c:1501

References jsonb_agg_transfn_worker().

◆ jsonb_agg_transfn()

Datum jsonb_agg_transfn ( PG_FUNCTION_ARGS  )

Definition at line 1625 of file jsonb.c.

1626{
1627 return jsonb_agg_transfn_worker(fcinfo, false);
1628}

References jsonb_agg_transfn_worker().

◆ jsonb_agg_transfn_worker()

static Datum jsonb_agg_transfn_worker ( FunctionCallInfo  fcinfo,
bool  absent_on_null 
)
static

Definition at line 1501 of file jsonb.c.

1502{
1503 MemoryContext oldcontext,
1504 aggcontext;
1506 JsonbInState elem;
1507 Datum val;
1508 JsonbInState *result;
1509 bool single_scalar = false;
1510 JsonbIterator *it;
1511 Jsonb *jbelem;
1512 JsonbValue v;
1514
1515 if (!AggCheckCallContext(fcinfo, &aggcontext))
1516 {
1517 /* cannot be called directly because of internal-type argument */
1518 elog(ERROR, "jsonb_agg_transfn called in non-aggregate context");
1519 }
1520
1521 /* set up the accumulator on the first go round */
1522
1523 if (PG_ARGISNULL(0))
1524 {
1525 Oid arg_type = get_fn_expr_argtype(fcinfo->flinfo, 1);
1526
1527 if (arg_type == InvalidOid)
1528 ereport(ERROR,
1529 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1530 errmsg("could not determine input data type")));
1531
1532 oldcontext = MemoryContextSwitchTo(aggcontext);
1533 state = palloc(sizeof(JsonbAggState));
1534 result = palloc0(sizeof(JsonbInState));
1535 state->res = result;
1536 result->res = pushJsonbValue(&result->parseState,
1537 WJB_BEGIN_ARRAY, NULL);
1538 MemoryContextSwitchTo(oldcontext);
1539
1540 json_categorize_type(arg_type, true, &state->val_category,
1541 &state->val_output_func);
1542 }
1543 else
1544 {
1546 result = state->res;
1547 }
1548
1549 if (absent_on_null && PG_ARGISNULL(1))
1551
1552 /* turn the argument into jsonb in the normal function context */
1553
1554 val = PG_ARGISNULL(1) ? (Datum) 0 : PG_GETARG_DATUM(1);
1555
1556 memset(&elem, 0, sizeof(JsonbInState));
1557
1558 datum_to_jsonb_internal(val, PG_ARGISNULL(1), &elem, state->val_category,
1559 state->val_output_func, false);
1560
1561 jbelem = JsonbValueToJsonb(elem.res);
1562
1563 /* switch to the aggregate context for accumulation operations */
1564
1565 oldcontext = MemoryContextSwitchTo(aggcontext);
1566
1567 it = JsonbIteratorInit(&jbelem->root);
1568
1569 while ((type = JsonbIteratorNext(&it, &v, false)) != WJB_DONE)
1570 {
1571 switch (type)
1572 {
1573 case WJB_BEGIN_ARRAY:
1574 if (v.val.array.rawScalar)
1575 single_scalar = true;
1576 else
1577 result->res = pushJsonbValue(&result->parseState,
1578 type, NULL);
1579 break;
1580 case WJB_END_ARRAY:
1581 if (!single_scalar)
1582 result->res = pushJsonbValue(&result->parseState,
1583 type, NULL);
1584 break;
1585 case WJB_BEGIN_OBJECT:
1586 case WJB_END_OBJECT:
1587 result->res = pushJsonbValue(&result->parseState,
1588 type, NULL);
1589 break;
1590 case WJB_ELEM:
1591 case WJB_KEY:
1592 case WJB_VALUE:
1593 if (v.type == jbvString)
1594 {
1595 /* copy string values in the aggregate context */
1596 char *buf = palloc(v.val.string.len + 1);
1597
1598 snprintf(buf, v.val.string.len + 1, "%s", v.val.string.val);
1599 v.val.string.val = buf;
1600 }
1601 else if (v.type == jbvNumeric)
1602 {
1603 /* same for numeric */
1604 v.val.numeric =
1606 NumericGetDatum(v.val.numeric)));
1607 }
1608 result->res = pushJsonbValue(&result->parseState,
1609 type, &v);
1610 break;
1611 default:
1612 elog(ERROR, "unknown jsonb iterator token type");
1613 }
1614 }
1615
1616 MemoryContextSwitchTo(oldcontext);
1617
1619}
Datum numeric_uplus(PG_FUNCTION_ARGS)
Definition: numeric.c:1462
Oid get_fn_expr_argtype(FmgrInfo *flinfo, int argnum)
Definition: fmgr.c:1910
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:641
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:268
void * palloc0(Size size)
Definition: mcxt.c:1347
static Datum NumericGetDatum(Numeric X)
Definition: numeric.h:73
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:124
static char * buf
Definition: pg_test_fsync.c:72
#define snprintf
Definition: port.h:238
FmgrInfo * flinfo
Definition: fmgr.h:87

References AggCheckCallContext(), buf, datum_to_jsonb_internal(), DatumGetNumeric(), DirectFunctionCall1, elog, ereport, errcode(), errmsg(), ERROR, FunctionCallInfoBaseData::flinfo, get_fn_expr_argtype(), InvalidOid, jbvNumeric, jbvString, json_categorize_type(), JsonbIteratorInit(), JsonbIteratorNext(), JsonbValueToJsonb(), MemoryContextSwitchTo(), numeric_uplus(), NumericGetDatum(), palloc(), palloc0(), JsonbInState::parseState, PG_ARGISNULL, PG_GETARG_DATUM, PG_GETARG_POINTER, PG_RETURN_POINTER, pushJsonbValue(), JsonbInState::res, Jsonb::root, snprintf, type, JsonbValue::type, JsonbValue::val, val, WJB_BEGIN_ARRAY, WJB_BEGIN_OBJECT, WJB_DONE, WJB_ELEM, WJB_END_ARRAY, WJB_END_OBJECT, WJB_KEY, and WJB_VALUE.

Referenced by jsonb_agg_strict_transfn(), and jsonb_agg_transfn().

◆ jsonb_bool()

Datum jsonb_bool ( PG_FUNCTION_ARGS  )

Definition at line 2038 of file jsonb.c.

2039{
2040 Jsonb *in = PG_GETARG_JSONB_P(0);
2041 JsonbValue v;
2042
2043 if (!JsonbExtractScalar(&in->root, &v) || v.type != jbvBool)
2044 cannotCastJsonbValue(v.type, "boolean");
2045
2046 PG_FREE_IF_COPY(in, 0);
2047
2048 PG_RETURN_BOOL(v.val.boolean);
2049}
#define PG_FREE_IF_COPY(ptr, n)
Definition: fmgr.h:260
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:359
static void cannotCastJsonbValue(enum jbvType type, const char *sqltype)
Definition: jsonb.c:2008
bool JsonbExtractScalar(JsonbContainer *jbc, JsonbValue *res)
Definition: jsonb.c:1968
#define PG_GETARG_JSONB_P(x)
Definition: jsonb.h:391

References cannotCastJsonbValue(), jbvBool, JsonbExtractScalar(), PG_FREE_IF_COPY, PG_GETARG_JSONB_P, PG_RETURN_BOOL, Jsonb::root, JsonbValue::type, and JsonbValue::val.

◆ jsonb_build_array()

Datum jsonb_build_array ( PG_FUNCTION_ARGS  )

Definition at line 1237 of file jsonb.c.

1238{
1239 Datum *args;
1240 bool *nulls;
1241 Oid *types;
1242
1243 /* build argument values to build the object */
1244 int nargs = extract_variadic_args(fcinfo, 0, true,
1245 &args, &types, &nulls);
1246
1247 if (nargs < 0)
1249
1250 PG_RETURN_DATUM(jsonb_build_array_worker(nargs, args, nulls, types, false));
1251}
struct typedefs * types
Definition: ecpg.c:30
#define PG_RETURN_DATUM(x)
Definition: fmgr.h:353
int extract_variadic_args(FunctionCallInfo fcinfo, int variadic_start, bool convert_unknown, Datum **args, Oid **types, bool **nulls)
Definition: funcapi.c:2005
Datum jsonb_build_array_worker(int nargs, const Datum *args, const bool *nulls, const Oid *types, bool absent_on_null)
Definition: jsonb.c:1210

References generate_unaccent_rules::args, extract_variadic_args(), jsonb_build_array_worker(), PG_RETURN_DATUM, PG_RETURN_NULL, and types.

◆ jsonb_build_array_noargs()

Datum jsonb_build_array_noargs ( PG_FUNCTION_ARGS  )

Definition at line 1258 of file jsonb.c.

1259{
1260 JsonbInState result;
1261
1262 memset(&result, 0, sizeof(JsonbInState));
1263
1264 (void) pushJsonbValue(&result.parseState, WJB_BEGIN_ARRAY, NULL);
1265 result.res = pushJsonbValue(&result.parseState, WJB_END_ARRAY, NULL);
1266
1268}

References JsonbValueToJsonb(), JsonbInState::parseState, PG_RETURN_POINTER, pushJsonbValue(), JsonbInState::res, WJB_BEGIN_ARRAY, and WJB_END_ARRAY.

◆ jsonb_build_array_worker()

Datum jsonb_build_array_worker ( int  nargs,
const Datum args,
const bool *  nulls,
const Oid types,
bool  absent_on_null 
)

Definition at line 1210 of file jsonb.c.

1212{
1213 int i;
1214 JsonbInState result;
1215
1216 memset(&result, 0, sizeof(JsonbInState));
1217
1218 result.res = pushJsonbValue(&result.parseState, WJB_BEGIN_ARRAY, NULL);
1219
1220 for (i = 0; i < nargs; i++)
1221 {
1222 if (absent_on_null && nulls[i])
1223 continue;
1224
1225 add_jsonb(args[i], nulls[i], &result, types[i], false);
1226 }
1227
1228 result.res = pushJsonbValue(&result.parseState, WJB_END_ARRAY, NULL);
1229
1230 return JsonbPGetDatum(JsonbValueToJsonb(result.res));
1231}
static void add_jsonb(Datum val, bool is_null, JsonbInState *result, Oid val_type, bool key_scalar)
Definition: jsonb.c:1016

References add_jsonb(), generate_unaccent_rules::args, i, JsonbPGetDatum(), JsonbValueToJsonb(), JsonbInState::parseState, pushJsonbValue(), JsonbInState::res, types, WJB_BEGIN_ARRAY, and WJB_END_ARRAY.

Referenced by ExecEvalJsonConstructor(), and jsonb_build_array().

◆ jsonb_build_object()

Datum jsonb_build_object ( PG_FUNCTION_ARGS  )

Definition at line 1177 of file jsonb.c.

1178{
1179 Datum *args;
1180 bool *nulls;
1181 Oid *types;
1182
1183 /* build argument values to build the object */
1184 int nargs = extract_variadic_args(fcinfo, 0, true,
1185 &args, &types, &nulls);
1186
1187 if (nargs < 0)
1189
1190 PG_RETURN_DATUM(jsonb_build_object_worker(nargs, args, nulls, types, false, false));
1191}
Datum jsonb_build_object_worker(int nargs, const Datum *args, const bool *nulls, const Oid *types, bool absent_on_null, bool unique_keys)
Definition: jsonb.c:1125

References generate_unaccent_rules::args, extract_variadic_args(), jsonb_build_object_worker(), PG_RETURN_DATUM, PG_RETURN_NULL, and types.

◆ jsonb_build_object_noargs()

Datum jsonb_build_object_noargs ( PG_FUNCTION_ARGS  )

Definition at line 1197 of file jsonb.c.

1198{
1199 JsonbInState result;
1200
1201 memset(&result, 0, sizeof(JsonbInState));
1202
1203 (void) pushJsonbValue(&result.parseState, WJB_BEGIN_OBJECT, NULL);
1204 result.res = pushJsonbValue(&result.parseState, WJB_END_OBJECT, NULL);
1205
1207}

References JsonbValueToJsonb(), JsonbInState::parseState, PG_RETURN_POINTER, pushJsonbValue(), JsonbInState::res, WJB_BEGIN_OBJECT, and WJB_END_OBJECT.

◆ jsonb_build_object_worker()

Datum jsonb_build_object_worker ( int  nargs,
const Datum args,
const bool *  nulls,
const Oid types,
bool  absent_on_null,
bool  unique_keys 
)

Definition at line 1125 of file jsonb.c.

1127{
1128 int i;
1129 JsonbInState result;
1130
1131 if (nargs % 2 != 0)
1132 ereport(ERROR,
1133 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1134 errmsg("argument list must have even number of elements"),
1135 /* translator: %s is a SQL function name */
1136 errhint("The arguments of %s must consist of alternating keys and values.",
1137 "jsonb_build_object()")));
1138
1139 memset(&result, 0, sizeof(JsonbInState));
1140
1141 result.res = pushJsonbValue(&result.parseState, WJB_BEGIN_OBJECT, NULL);
1142 result.parseState->unique_keys = unique_keys;
1143 result.parseState->skip_nulls = absent_on_null;
1144
1145 for (i = 0; i < nargs; i += 2)
1146 {
1147 /* process key */
1148 bool skip;
1149
1150 if (nulls[i])
1151 ereport(ERROR,
1152 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1153 errmsg("argument %d: key must not be null", i + 1)));
1154
1155 /* skip null values if absent_on_null */
1156 skip = absent_on_null && nulls[i + 1];
1157
1158 /* we need to save skipped keys for the key uniqueness check */
1159 if (skip && !unique_keys)
1160 continue;
1161
1162 add_jsonb(args[i], false, &result, types[i], true);
1163
1164 /* process value */
1165 add_jsonb(args[i + 1], nulls[i + 1], &result, types[i + 1], false);
1166 }
1167
1168 result.res = pushJsonbValue(&result.parseState, WJB_END_OBJECT, NULL);
1169
1170 return JsonbPGetDatum(JsonbValueToJsonb(result.res));
1171}
int errhint(const char *fmt,...)
Definition: elog.c:1317
static const struct exclude_list_item skip[]
Definition: pg_checksums.c:107

References add_jsonb(), generate_unaccent_rules::args, ereport, errcode(), errhint(), errmsg(), ERROR, i, JsonbPGetDatum(), JsonbValueToJsonb(), JsonbInState::parseState, pushJsonbValue(), JsonbInState::res, skip, JsonbParseState::skip_nulls, types, JsonbParseState::unique_keys, WJB_BEGIN_OBJECT, and WJB_END_OBJECT.

Referenced by ExecEvalJsonConstructor(), and jsonb_build_object().

◆ jsonb_float4()

Datum jsonb_float4 ( PG_FUNCTION_ARGS  )

Definition at line 2127 of file jsonb.c.

2128{
2129 Jsonb *in = PG_GETARG_JSONB_P(0);
2130 JsonbValue v;
2131 Datum retValue;
2132
2133 if (!JsonbExtractScalar(&in->root, &v) || v.type != jbvNumeric)
2134 cannotCastJsonbValue(v.type, "real");
2135
2137 NumericGetDatum(v.val.numeric));
2138
2139 PG_FREE_IF_COPY(in, 0);
2140
2141 PG_RETURN_DATUM(retValue);
2142}
Datum numeric_float4(PG_FUNCTION_ARGS)
Definition: numeric.c:4840

References cannotCastJsonbValue(), DirectFunctionCall1, jbvNumeric, JsonbExtractScalar(), numeric_float4(), NumericGetDatum(), PG_FREE_IF_COPY, PG_GETARG_JSONB_P, PG_RETURN_DATUM, Jsonb::root, JsonbValue::type, and JsonbValue::val.

◆ jsonb_float8()

Datum jsonb_float8 ( PG_FUNCTION_ARGS  )

Definition at line 2145 of file jsonb.c.

2146{
2147 Jsonb *in = PG_GETARG_JSONB_P(0);
2148 JsonbValue v;
2149 Datum retValue;
2150
2151 if (!JsonbExtractScalar(&in->root, &v) || v.type != jbvNumeric)
2152 cannotCastJsonbValue(v.type, "double precision");
2153
2155 NumericGetDatum(v.val.numeric));
2156
2157 PG_FREE_IF_COPY(in, 0);
2158
2159 PG_RETURN_DATUM(retValue);
2160}
Datum numeric_float8(PG_FUNCTION_ARGS)
Definition: numeric.c:4746

References cannotCastJsonbValue(), DirectFunctionCall1, jbvNumeric, JsonbExtractScalar(), numeric_float8(), NumericGetDatum(), PG_FREE_IF_COPY, PG_GETARG_JSONB_P, PG_RETURN_DATUM, Jsonb::root, JsonbValue::type, and JsonbValue::val.

◆ jsonb_from_cstring()

static Datum jsonb_from_cstring ( char *  json,
int  len,
bool  unique_keys,
Node escontext 
)
inlinestatic

Definition at line 248 of file jsonb.c.

249{
250 JsonLexContext lex;
253
254 memset(&state, 0, sizeof(state));
255 memset(&sem, 0, sizeof(sem));
257
258 state.unique_keys = unique_keys;
259 state.escontext = escontext;
260 sem.semstate = &state;
261
268
269 if (!pg_parse_json_or_errsave(&lex, &sem, escontext))
270 return (Datum) 0;
271
272 /* after parsing, the item member has the composed jsonb structure */
274}
JsonLexContext * makeJsonLexContextCstringLen(JsonLexContext *lex, const char *json, size_t len, int encoding, bool need_escapes)
Definition: jsonapi.c:392
bool pg_parse_json_or_errsave(JsonLexContext *lex, const JsonSemAction *sem, Node *escontext)
Definition: jsonfuncs.c:518
int GetDatabaseEncoding(void)
Definition: mbutils.c:1261

References JsonSemAction::array_end, JsonSemAction::array_start, GetDatabaseEncoding(), jsonb_in_array_end(), jsonb_in_array_start(), jsonb_in_object_end(), jsonb_in_object_field_start(), jsonb_in_object_start(), jsonb_in_scalar(), JsonbValueToJsonb(), len, makeJsonLexContextCstringLen(), JsonSemAction::object_end, JsonSemAction::object_field_start, JsonSemAction::object_start, pg_parse_json_or_errsave(), PG_RETURN_POINTER, JsonSemAction::scalar, sem, and JsonSemAction::semstate.

Referenced by jsonb_from_text(), jsonb_in(), and jsonb_recv().

◆ jsonb_from_text()

Datum jsonb_from_text ( text js,
bool  unique_keys 
)

Definition at line 147 of file jsonb.c.

148{
151 unique_keys,
152 NULL);
153}
static Datum jsonb_from_cstring(char *json, int len, bool unique_keys, Node *escontext)
Definition: jsonb.c:248
#define VARDATA_ANY(PTR)
Definition: varatt.h:324
#define VARSIZE_ANY_EXHDR(PTR)
Definition: varatt.h:317

References jsonb_from_cstring(), VARDATA_ANY, and VARSIZE_ANY_EXHDR.

Referenced by ExecEvalJsonConstructor().

◆ jsonb_in()

Datum jsonb_in ( PG_FUNCTION_ARGS  )

Definition at line 73 of file jsonb.c.

74{
75 char *json = PG_GETARG_CSTRING(0);
76
77 return jsonb_from_cstring(json, strlen(json), false, fcinfo->context);
78}
#define PG_GETARG_CSTRING(n)
Definition: fmgr.h:277

References jsonb_from_cstring(), and PG_GETARG_CSTRING.

Referenced by ExecEvalJsonCoercion(), GetJsonBehaviorConst(), jsonb_set_lax(), JsonItemFromDatum(), and transformJsonBehavior().

◆ jsonb_in_array_end()

static JsonParseErrorType jsonb_in_array_end ( void *  pstate)
static

Definition at line 321 of file jsonb.c.

322{
323 JsonbInState *_state = (JsonbInState *) pstate;
324
325 _state->res = pushJsonbValue(&_state->parseState, WJB_END_ARRAY, NULL);
326
327 return JSON_SUCCESS;
328}
@ JSON_SUCCESS
Definition: jsonapi.h:36

References JSON_SUCCESS, JsonbInState::parseState, pushJsonbValue(), JsonbInState::res, and WJB_END_ARRAY.

Referenced by datum_to_jsonb_internal(), and jsonb_from_cstring().

◆ jsonb_in_array_start()

static JsonParseErrorType jsonb_in_array_start ( void *  pstate)
static

Definition at line 311 of file jsonb.c.

312{
313 JsonbInState *_state = (JsonbInState *) pstate;
314
315 _state->res = pushJsonbValue(&_state->parseState, WJB_BEGIN_ARRAY, NULL);
316
317 return JSON_SUCCESS;
318}

References JSON_SUCCESS, JsonbInState::parseState, pushJsonbValue(), JsonbInState::res, and WJB_BEGIN_ARRAY.

Referenced by datum_to_jsonb_internal(), and jsonb_from_cstring().

◆ jsonb_in_object_end()

static JsonParseErrorType jsonb_in_object_end ( void *  pstate)
static

Definition at line 301 of file jsonb.c.

302{
303 JsonbInState *_state = (JsonbInState *) pstate;
304
305 _state->res = pushJsonbValue(&_state->parseState, WJB_END_OBJECT, NULL);
306
307 return JSON_SUCCESS;
308}

References JSON_SUCCESS, JsonbInState::parseState, pushJsonbValue(), JsonbInState::res, and WJB_END_OBJECT.

Referenced by datum_to_jsonb_internal(), and jsonb_from_cstring().

◆ jsonb_in_object_field_start()

static JsonParseErrorType jsonb_in_object_field_start ( void *  pstate,
char *  fname,
bool  isnull 
)
static

Definition at line 331 of file jsonb.c.

332{
333 JsonbInState *_state = (JsonbInState *) pstate;
334 JsonbValue v;
335
336 Assert(fname != NULL);
337 v.type = jbvString;
338 v.val.string.len = strlen(fname);
339 if (!checkStringLen(v.val.string.len, _state->escontext))
341 v.val.string.val = fname;
342
343 _state->res = pushJsonbValue(&_state->parseState, WJB_KEY, &v);
344
345 return JSON_SUCCESS;
346}
@ JSON_SEM_ACTION_FAILED
Definition: jsonapi.h:59
Node * escontext
Definition: jsonb.c:33

References Assert, checkStringLen(), JsonbInState::escontext, jbvString, JSON_SEM_ACTION_FAILED, JSON_SUCCESS, JsonbInState::parseState, pushJsonbValue(), JsonbInState::res, JsonbValue::type, JsonbValue::val, and WJB_KEY.

Referenced by datum_to_jsonb_internal(), and jsonb_from_cstring().

◆ jsonb_in_object_start()

static JsonParseErrorType jsonb_in_object_start ( void *  pstate)
static

Definition at line 290 of file jsonb.c.

291{
292 JsonbInState *_state = (JsonbInState *) pstate;
293
294 _state->res = pushJsonbValue(&_state->parseState, WJB_BEGIN_OBJECT, NULL);
295 _state->parseState->unique_keys = _state->unique_keys;
296
297 return JSON_SUCCESS;
298}
bool unique_keys
Definition: jsonb.c:32

References JSON_SUCCESS, JsonbInState::parseState, pushJsonbValue(), JsonbInState::res, JsonbInState::unique_keys, JsonbParseState::unique_keys, and WJB_BEGIN_OBJECT.

Referenced by datum_to_jsonb_internal(), and jsonb_from_cstring().

◆ jsonb_in_scalar()

static JsonParseErrorType jsonb_in_scalar ( void *  pstate,
char *  token,
JsonTokenType  tokentype 
)
static

Definition at line 379 of file jsonb.c.

380{
381 JsonbInState *_state = (JsonbInState *) pstate;
382 JsonbValue v;
383 Datum numd;
384
385 switch (tokentype)
386 {
387
389 Assert(token != NULL);
390 v.type = jbvString;
391 v.val.string.len = strlen(token);
392 if (!checkStringLen(v.val.string.len, _state->escontext))
394 v.val.string.val = token;
395 break;
397
398 /*
399 * No need to check size of numeric values, because maximum
400 * numeric size is well below the JsonbValue restriction
401 */
402 Assert(token != NULL);
403 v.type = jbvNumeric;
405 InvalidOid, -1,
406 _state->escontext,
407 &numd))
409 v.val.numeric = DatumGetNumeric(numd);
410 break;
411 case JSON_TOKEN_TRUE:
412 v.type = jbvBool;
413 v.val.boolean = true;
414 break;
415 case JSON_TOKEN_FALSE:
416 v.type = jbvBool;
417 v.val.boolean = false;
418 break;
419 case JSON_TOKEN_NULL:
420 v.type = jbvNull;
421 break;
422 default:
423 /* should not be possible */
424 elog(ERROR, "invalid json token type");
425 break;
426 }
427
428 if (_state->parseState == NULL)
429 {
430 /* single scalar */
431 JsonbValue va;
432
433 va.type = jbvArray;
434 va.val.array.rawScalar = true;
435 va.val.array.nElems = 1;
436
437 _state->res = pushJsonbValue(&_state->parseState, WJB_BEGIN_ARRAY, &va);
438 _state->res = pushJsonbValue(&_state->parseState, WJB_ELEM, &v);
439 _state->res = pushJsonbValue(&_state->parseState, WJB_END_ARRAY, NULL);
440 }
441 else
442 {
443 JsonbValue *o = &_state->parseState->contVal;
444
445 switch (o->type)
446 {
447 case jbvArray:
448 _state->res = pushJsonbValue(&_state->parseState, WJB_ELEM, &v);
449 break;
450 case jbvObject:
451 _state->res = pushJsonbValue(&_state->parseState, WJB_VALUE, &v);
452 break;
453 default:
454 elog(ERROR, "unexpected parent of nested structure");
455 }
456 }
457
458 return JSON_SUCCESS;
459}
bool DirectInputFunctionCallSafe(PGFunction func, char *str, Oid typioparam, int32 typmod, fmNodePtr escontext, Datum *result)
Definition: fmgr.c:1640
#define token
Definition: indent_globs.h:126
@ JSON_TOKEN_FALSE
Definition: jsonapi.h:29
@ JSON_TOKEN_TRUE
Definition: jsonapi.h:28
@ JSON_TOKEN_NULL
Definition: jsonapi.h:30
@ JSON_TOKEN_NUMBER
Definition: jsonapi.h:21
@ JSON_TOKEN_STRING
Definition: jsonapi.h:20

References Assert, checkStringLen(), JsonbParseState::contVal, DatumGetNumeric(), DirectInputFunctionCallSafe(), elog, ERROR, JsonbInState::escontext, InvalidOid, jbvArray, jbvBool, jbvNull, jbvNumeric, jbvObject, jbvString, JSON_SEM_ACTION_FAILED, JSON_SUCCESS, JSON_TOKEN_FALSE, JSON_TOKEN_NULL, JSON_TOKEN_NUMBER, JSON_TOKEN_STRING, JSON_TOKEN_TRUE, numeric_in(), JsonbInState::parseState, pushJsonbValue(), JsonbInState::res, token, JsonbValue::type, JsonbValue::val, WJB_BEGIN_ARRAY, WJB_ELEM, WJB_END_ARRAY, and WJB_VALUE.

Referenced by datum_to_jsonb_internal(), and jsonb_from_cstring().

◆ jsonb_int2()

Datum jsonb_int2 ( PG_FUNCTION_ARGS  )

Definition at line 2073 of file jsonb.c.

2074{
2075 Jsonb *in = PG_GETARG_JSONB_P(0);
2076 JsonbValue v;
2077 Datum retValue;
2078
2079 if (!JsonbExtractScalar(&in->root, &v) || v.type != jbvNumeric)
2080 cannotCastJsonbValue(v.type, "smallint");
2081
2083 NumericGetDatum(v.val.numeric));
2084
2085 PG_FREE_IF_COPY(in, 0);
2086
2087 PG_RETURN_DATUM(retValue);
2088}
Datum numeric_int2(PG_FUNCTION_ARGS)
Definition: numeric.c:4671

References cannotCastJsonbValue(), DirectFunctionCall1, jbvNumeric, JsonbExtractScalar(), numeric_int2(), NumericGetDatum(), PG_FREE_IF_COPY, PG_GETARG_JSONB_P, PG_RETURN_DATUM, Jsonb::root, JsonbValue::type, and JsonbValue::val.

◆ jsonb_int4()

Datum jsonb_int4 ( PG_FUNCTION_ARGS  )

Definition at line 2091 of file jsonb.c.

2092{
2093 Jsonb *in = PG_GETARG_JSONB_P(0);
2094 JsonbValue v;
2095 Datum retValue;
2096
2097 if (!JsonbExtractScalar(&in->root, &v) || v.type != jbvNumeric)
2098 cannotCastJsonbValue(v.type, "integer");
2099
2101 NumericGetDatum(v.val.numeric));
2102
2103 PG_FREE_IF_COPY(in, 0);
2104
2105 PG_RETURN_DATUM(retValue);
2106}
Datum numeric_int4(PG_FUNCTION_ARGS)
Definition: numeric.c:4565

References cannotCastJsonbValue(), DirectFunctionCall1, jbvNumeric, JsonbExtractScalar(), numeric_int4(), NumericGetDatum(), PG_FREE_IF_COPY, PG_GETARG_JSONB_P, PG_RETURN_DATUM, Jsonb::root, JsonbValue::type, and JsonbValue::val.

◆ jsonb_int8()

Datum jsonb_int8 ( PG_FUNCTION_ARGS  )

Definition at line 2109 of file jsonb.c.

2110{
2111 Jsonb *in = PG_GETARG_JSONB_P(0);
2112 JsonbValue v;
2113 Datum retValue;
2114
2115 if (!JsonbExtractScalar(&in->root, &v) || v.type != jbvNumeric)
2116 cannotCastJsonbValue(v.type, "bigint");
2117
2119 NumericGetDatum(v.val.numeric));
2120
2121 PG_FREE_IF_COPY(in, 0);
2122
2123 PG_RETURN_DATUM(retValue);
2124}
Datum numeric_int8(PG_FUNCTION_ARGS)
Definition: numeric.c:4653

References cannotCastJsonbValue(), DirectFunctionCall1, jbvNumeric, JsonbExtractScalar(), numeric_int8(), NumericGetDatum(), PG_FREE_IF_COPY, PG_GETARG_JSONB_P, PG_RETURN_DATUM, Jsonb::root, JsonbValue::type, and JsonbValue::val.

◆ jsonb_numeric()

Datum jsonb_numeric ( PG_FUNCTION_ARGS  )

Definition at line 2052 of file jsonb.c.

2053{
2054 Jsonb *in = PG_GETARG_JSONB_P(0);
2055 JsonbValue v;
2056 Numeric retValue;
2057
2058 if (!JsonbExtractScalar(&in->root, &v) || v.type != jbvNumeric)
2059 cannotCastJsonbValue(v.type, "numeric");
2060
2061 /*
2062 * v.val.numeric points into jsonb body, so we need to make a copy to
2063 * return
2064 */
2065 retValue = DatumGetNumericCopy(NumericGetDatum(v.val.numeric));
2066
2067 PG_FREE_IF_COPY(in, 0);
2068
2069 PG_RETURN_NUMERIC(retValue);
2070}
static Numeric DatumGetNumericCopy(Datum X)
Definition: numeric.h:67
#define PG_RETURN_NUMERIC(x)
Definition: numeric.h:80

References cannotCastJsonbValue(), DatumGetNumericCopy(), jbvNumeric, JsonbExtractScalar(), NumericGetDatum(), PG_FREE_IF_COPY, PG_GETARG_JSONB_P, PG_RETURN_NUMERIC, Jsonb::root, JsonbValue::type, and JsonbValue::val.

◆ jsonb_object()

Datum jsonb_object ( PG_FUNCTION_ARGS  )

Definition at line 1279 of file jsonb.c.

1280{
1281 ArrayType *in_array = PG_GETARG_ARRAYTYPE_P(0);
1282 int ndims = ARR_NDIM(in_array);
1283 Datum *in_datums;
1284 bool *in_nulls;
1285 int in_count,
1286 count,
1287 i;
1288 JsonbInState result;
1289
1290 memset(&result, 0, sizeof(JsonbInState));
1291
1292 (void) pushJsonbValue(&result.parseState, WJB_BEGIN_OBJECT, NULL);
1293
1294 switch (ndims)
1295 {
1296 case 0:
1297 goto close_object;
1298 break;
1299
1300 case 1:
1301 if ((ARR_DIMS(in_array)[0]) % 2)
1302 ereport(ERROR,
1303 (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
1304 errmsg("array must have even number of elements")));
1305 break;
1306
1307 case 2:
1308 if ((ARR_DIMS(in_array)[1]) != 2)
1309 ereport(ERROR,
1310 (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
1311 errmsg("array must have two columns")));
1312 break;
1313
1314 default:
1315 ereport(ERROR,
1316 (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
1317 errmsg("wrong number of array subscripts")));
1318 }
1319
1320 deconstruct_array_builtin(in_array, TEXTOID, &in_datums, &in_nulls, &in_count);
1321
1322 count = in_count / 2;
1323
1324 for (i = 0; i < count; ++i)
1325 {
1326 JsonbValue v;
1327 char *str;
1328 int len;
1329
1330 if (in_nulls[i * 2])
1331 ereport(ERROR,
1332 (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
1333 errmsg("null value not allowed for object key")));
1334
1335 str = TextDatumGetCString(in_datums[i * 2]);
1336 len = strlen(str);
1337
1338 v.type = jbvString;
1339
1340 v.val.string.len = len;
1341 v.val.string.val = str;
1342
1343 (void) pushJsonbValue(&result.parseState, WJB_KEY, &v);
1344
1345 if (in_nulls[i * 2 + 1])
1346 {
1347 v.type = jbvNull;
1348 }
1349 else
1350 {
1351 str = TextDatumGetCString(in_datums[i * 2 + 1]);
1352 len = strlen(str);
1353
1354 v.type = jbvString;
1355
1356 v.val.string.len = len;
1357 v.val.string.val = str;
1358 }
1359
1360 (void) pushJsonbValue(&result.parseState, WJB_VALUE, &v);
1361 }
1362
1363 pfree(in_datums);
1364 pfree(in_nulls);
1365
1366close_object:
1367 result.res = pushJsonbValue(&result.parseState, WJB_END_OBJECT, NULL);
1368
1370}
#define PG_GETARG_ARRAYTYPE_P(n)
Definition: array.h:263
void deconstruct_array_builtin(ArrayType *array, Oid elmtype, Datum **elemsp, bool **nullsp, int *nelemsp)
Definition: arrayfuncs.c:3697
#define TextDatumGetCString(d)
Definition: builtins.h:98
const char * str

References ARR_DIMS, ARR_NDIM, deconstruct_array_builtin(), ereport, errcode(), errmsg(), ERROR, i, jbvNull, jbvString, JsonbValueToJsonb(), len, JsonbInState::parseState, pfree(), PG_GETARG_ARRAYTYPE_P, PG_RETURN_POINTER, pushJsonbValue(), JsonbInState::res, str, TextDatumGetCString, JsonbValue::type, JsonbValue::val, WJB_BEGIN_OBJECT, WJB_END_OBJECT, WJB_KEY, and WJB_VALUE.

◆ jsonb_object_agg_finalfn()

Datum jsonb_object_agg_finalfn ( PG_FUNCTION_ARGS  )

Definition at line 1930 of file jsonb.c.

1931{
1933 JsonbInState result;
1934 Jsonb *out;
1935
1936 /* cannot be called directly because of internal-type argument */
1937 Assert(AggCheckCallContext(fcinfo, NULL));
1938
1939 if (PG_ARGISNULL(0))
1940 PG_RETURN_NULL(); /* returns null iff no input values */
1941
1943
1944 /*
1945 * We need to do a shallow clone of the argument's res field in case the
1946 * final function is called more than once, so we avoid changing the
1947 * aggregate state value. A shallow clone is sufficient as we aren't
1948 * going to change any of the values, just add the final object end
1949 * marker.
1950 */
1951 memset(&result, 0, sizeof(JsonbInState));
1952
1953 result.parseState = clone_parse_state(arg->res->parseState);
1954
1955 result.res = pushJsonbValue(&result.parseState,
1956 WJB_END_OBJECT, NULL);
1957
1958 out = JsonbValueToJsonb(result.res);
1959
1960 PG_RETURN_POINTER(out);
1961}

References AggCheckCallContext(), arg, Assert, clone_parse_state(), JsonbValueToJsonb(), JsonbInState::parseState, PG_ARGISNULL, PG_GETARG_POINTER, PG_RETURN_NULL, PG_RETURN_POINTER, pushJsonbValue(), JsonbInState::res, and WJB_END_OBJECT.

◆ jsonb_object_agg_strict_transfn()

Datum jsonb_object_agg_strict_transfn ( PG_FUNCTION_ARGS  )

Definition at line 1906 of file jsonb.c.

1907{
1908 return jsonb_object_agg_transfn_worker(fcinfo, true, false);
1909}
static Datum jsonb_object_agg_transfn_worker(FunctionCallInfo fcinfo, bool absent_on_null, bool unique_keys)
Definition: jsonb.c:1673

References jsonb_object_agg_transfn_worker().

◆ jsonb_object_agg_transfn()

Datum jsonb_object_agg_transfn ( PG_FUNCTION_ARGS  )

Definition at line 1896 of file jsonb.c.

1897{
1898 return jsonb_object_agg_transfn_worker(fcinfo, false, false);
1899}

References jsonb_object_agg_transfn_worker().

◆ jsonb_object_agg_transfn_worker()

static Datum jsonb_object_agg_transfn_worker ( FunctionCallInfo  fcinfo,
bool  absent_on_null,
bool  unique_keys 
)
static

Definition at line 1673 of file jsonb.c.

1675{
1676 MemoryContext oldcontext,
1677 aggcontext;
1678 JsonbInState elem;
1680 Datum val;
1681 JsonbInState *result;
1682 bool single_scalar;
1683 JsonbIterator *it;
1684 Jsonb *jbkey,
1685 *jbval;
1686 JsonbValue v;
1688 bool skip;
1689
1690 if (!AggCheckCallContext(fcinfo, &aggcontext))
1691 {
1692 /* cannot be called directly because of internal-type argument */
1693 elog(ERROR, "jsonb_object_agg_transfn called in non-aggregate context");
1694 }
1695
1696 /* set up the accumulator on the first go round */
1697
1698 if (PG_ARGISNULL(0))
1699 {
1700 Oid arg_type;
1701
1702 oldcontext = MemoryContextSwitchTo(aggcontext);
1703 state = palloc(sizeof(JsonbAggState));
1704 result = palloc0(sizeof(JsonbInState));
1705 state->res = result;
1706 result->res = pushJsonbValue(&result->parseState,
1707 WJB_BEGIN_OBJECT, NULL);
1708 result->parseState->unique_keys = unique_keys;
1709 result->parseState->skip_nulls = absent_on_null;
1710
1711 MemoryContextSwitchTo(oldcontext);
1712
1713 arg_type = get_fn_expr_argtype(fcinfo->flinfo, 1);
1714
1715 if (arg_type == InvalidOid)
1716 ereport(ERROR,
1717 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1718 errmsg("could not determine input data type")));
1719
1720 json_categorize_type(arg_type, true, &state->key_category,
1721 &state->key_output_func);
1722
1723 arg_type = get_fn_expr_argtype(fcinfo->flinfo, 2);
1724
1725 if (arg_type == InvalidOid)
1726 ereport(ERROR,
1727 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1728 errmsg("could not determine input data type")));
1729
1730 json_categorize_type(arg_type, true, &state->val_category,
1731 &state->val_output_func);
1732 }
1733 else
1734 {
1736 result = state->res;
1737 }
1738
1739 /* turn the argument into jsonb in the normal function context */
1740
1741 if (PG_ARGISNULL(1))
1742 ereport(ERROR,
1743 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1744 errmsg("field name must not be null")));
1745
1746 /*
1747 * Skip null values if absent_on_null unless key uniqueness check is
1748 * needed (because we must save keys in this case).
1749 */
1750 skip = absent_on_null && PG_ARGISNULL(2);
1751
1752 if (skip && !unique_keys)
1754
1755 val = PG_GETARG_DATUM(1);
1756
1757 memset(&elem, 0, sizeof(JsonbInState));
1758
1759 datum_to_jsonb_internal(val, false, &elem, state->key_category,
1760 state->key_output_func, true);
1761
1762 jbkey = JsonbValueToJsonb(elem.res);
1763
1764 val = PG_ARGISNULL(2) ? (Datum) 0 : PG_GETARG_DATUM(2);
1765
1766 memset(&elem, 0, sizeof(JsonbInState));
1767
1768 datum_to_jsonb_internal(val, PG_ARGISNULL(2), &elem, state->val_category,
1769 state->val_output_func, false);
1770
1771 jbval = JsonbValueToJsonb(elem.res);
1772
1773 it = JsonbIteratorInit(&jbkey->root);
1774
1775 /* switch to the aggregate context for accumulation operations */
1776
1777 oldcontext = MemoryContextSwitchTo(aggcontext);
1778
1779 /*
1780 * keys should be scalar, and we should have already checked for that
1781 * above when calling datum_to_jsonb, so we only need to look for these
1782 * things.
1783 */
1784
1785 while ((type = JsonbIteratorNext(&it, &v, false)) != WJB_DONE)
1786 {
1787 switch (type)
1788 {
1789 case WJB_BEGIN_ARRAY:
1790 if (!v.val.array.rawScalar)
1791 elog(ERROR, "unexpected structure for key");
1792 break;
1793 case WJB_ELEM:
1794 if (v.type == jbvString)
1795 {
1796 /* copy string values in the aggregate context */
1797 char *buf = palloc(v.val.string.len + 1);
1798
1799 snprintf(buf, v.val.string.len + 1, "%s", v.val.string.val);
1800 v.val.string.val = buf;
1801 }
1802 else
1803 {
1804 ereport(ERROR,
1805 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1806 errmsg("object keys must be strings")));
1807 }
1808 result->res = pushJsonbValue(&result->parseState,
1809 WJB_KEY, &v);
1810
1811 if (skip)
1812 {
1813 v.type = jbvNull;
1814 result->res = pushJsonbValue(&result->parseState,
1815 WJB_VALUE, &v);
1816 MemoryContextSwitchTo(oldcontext);
1818 }
1819
1820 break;
1821 case WJB_END_ARRAY:
1822 break;
1823 default:
1824 elog(ERROR, "unexpected structure for key");
1825 break;
1826 }
1827 }
1828
1829 it = JsonbIteratorInit(&jbval->root);
1830
1831 single_scalar = false;
1832
1833 /*
1834 * values can be anything, including structured and null, so we treat them
1835 * as in json_agg_transfn, except that single scalars are always pushed as
1836 * WJB_VALUE items.
1837 */
1838
1839 while ((type = JsonbIteratorNext(&it, &v, false)) != WJB_DONE)
1840 {
1841 switch (type)
1842 {
1843 case WJB_BEGIN_ARRAY:
1844 if (v.val.array.rawScalar)
1845 single_scalar = true;
1846 else
1847 result->res = pushJsonbValue(&result->parseState,
1848 type, NULL);
1849 break;
1850 case WJB_END_ARRAY:
1851 if (!single_scalar)
1852 result->res = pushJsonbValue(&result->parseState,
1853 type, NULL);
1854 break;
1855 case WJB_BEGIN_OBJECT:
1856 case WJB_END_OBJECT:
1857 result->res = pushJsonbValue(&result->parseState,
1858 type, NULL);
1859 break;
1860 case WJB_ELEM:
1861 case WJB_KEY:
1862 case WJB_VALUE:
1863 if (v.type == jbvString)
1864 {
1865 /* copy string values in the aggregate context */
1866 char *buf = palloc(v.val.string.len + 1);
1867
1868 snprintf(buf, v.val.string.len + 1, "%s", v.val.string.val);
1869 v.val.string.val = buf;
1870 }
1871 else if (v.type == jbvNumeric)
1872 {
1873 /* same for numeric */
1874 v.val.numeric =
1876 NumericGetDatum(v.val.numeric)));
1877 }
1878 result->res = pushJsonbValue(&result->parseState,
1879 single_scalar ? WJB_VALUE : type,
1880 &v);
1881 break;
1882 default:
1883 elog(ERROR, "unknown jsonb iterator token type");
1884 }
1885 }
1886
1887 MemoryContextSwitchTo(oldcontext);
1888
1890}

References AggCheckCallContext(), buf, datum_to_jsonb_internal(), DatumGetNumeric(), DirectFunctionCall1, elog, ereport, errcode(), errmsg(), ERROR, FunctionCallInfoBaseData::flinfo, get_fn_expr_argtype(), InvalidOid, jbvNull, jbvNumeric, jbvString, json_categorize_type(), JsonbIteratorInit(), JsonbIteratorNext(), JsonbValueToJsonb(), MemoryContextSwitchTo(), numeric_uplus(), NumericGetDatum(), palloc(), palloc0(), JsonbInState::parseState, PG_ARGISNULL, PG_GETARG_DATUM, PG_GETARG_POINTER, PG_RETURN_POINTER, pushJsonbValue(), JsonbInState::res, Jsonb::root, skip, JsonbParseState::skip_nulls, snprintf, type, JsonbValue::type, JsonbParseState::unique_keys, JsonbValue::val, val, WJB_BEGIN_ARRAY, WJB_BEGIN_OBJECT, WJB_DONE, WJB_ELEM, WJB_END_ARRAY, WJB_END_OBJECT, WJB_KEY, and WJB_VALUE.

Referenced by jsonb_object_agg_strict_transfn(), jsonb_object_agg_transfn(), jsonb_object_agg_unique_strict_transfn(), and jsonb_object_agg_unique_transfn().

◆ jsonb_object_agg_unique_strict_transfn()

Datum jsonb_object_agg_unique_strict_transfn ( PG_FUNCTION_ARGS  )

Definition at line 1924 of file jsonb.c.

1925{
1926 return jsonb_object_agg_transfn_worker(fcinfo, true, true);
1927}

References jsonb_object_agg_transfn_worker().

◆ jsonb_object_agg_unique_transfn()

Datum jsonb_object_agg_unique_transfn ( PG_FUNCTION_ARGS  )

Definition at line 1915 of file jsonb.c.

1916{
1917 return jsonb_object_agg_transfn_worker(fcinfo, false, true);
1918}

References jsonb_object_agg_transfn_worker().

◆ jsonb_object_two_arg()

Datum jsonb_object_two_arg ( PG_FUNCTION_ARGS  )

Definition at line 1379 of file jsonb.c.

1380{
1381 ArrayType *key_array = PG_GETARG_ARRAYTYPE_P(0);
1382 ArrayType *val_array = PG_GETARG_ARRAYTYPE_P(1);
1383 int nkdims = ARR_NDIM(key_array);
1384 int nvdims = ARR_NDIM(val_array);
1385 Datum *key_datums,
1386 *val_datums;
1387 bool *key_nulls,
1388 *val_nulls;
1389 int key_count,
1390 val_count,
1391 i;
1392 JsonbInState result;
1393
1394 memset(&result, 0, sizeof(JsonbInState));
1395
1396 (void) pushJsonbValue(&result.parseState, WJB_BEGIN_OBJECT, NULL);
1397
1398 if (nkdims > 1 || nkdims != nvdims)
1399 ereport(ERROR,
1400 (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
1401 errmsg("wrong number of array subscripts")));
1402
1403 if (nkdims == 0)
1404 goto close_object;
1405
1406 deconstruct_array_builtin(key_array, TEXTOID, &key_datums, &key_nulls, &key_count);
1407 deconstruct_array_builtin(val_array, TEXTOID, &val_datums, &val_nulls, &val_count);
1408
1409 if (key_count != val_count)
1410 ereport(ERROR,
1411 (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
1412 errmsg("mismatched array dimensions")));
1413
1414 for (i = 0; i < key_count; ++i)
1415 {
1416 JsonbValue v;
1417 char *str;
1418 int len;
1419
1420 if (key_nulls[i])
1421 ereport(ERROR,
1422 (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
1423 errmsg("null value not allowed for object key")));
1424
1425 str = TextDatumGetCString(key_datums[i]);
1426 len = strlen(str);
1427
1428 v.type = jbvString;
1429
1430 v.val.string.len = len;
1431 v.val.string.val = str;
1432
1433 (void) pushJsonbValue(&result.parseState, WJB_KEY, &v);
1434
1435 if (val_nulls[i])
1436 {
1437 v.type = jbvNull;
1438 }
1439 else
1440 {
1441 str = TextDatumGetCString(val_datums[i]);
1442 len = strlen(str);
1443
1444 v.type = jbvString;
1445
1446 v.val.string.len = len;
1447 v.val.string.val = str;
1448 }
1449
1450 (void) pushJsonbValue(&result.parseState, WJB_VALUE, &v);
1451 }
1452
1453 pfree(key_datums);
1454 pfree(key_nulls);
1455 pfree(val_datums);
1456 pfree(val_nulls);
1457
1458close_object:
1459 result.res = pushJsonbValue(&result.parseState, WJB_END_OBJECT, NULL);
1460
1462}

References ARR_NDIM, deconstruct_array_builtin(), ereport, errcode(), errmsg(), ERROR, i, jbvNull, jbvString, JsonbValueToJsonb(), len, JsonbInState::parseState, pfree(), PG_GETARG_ARRAYTYPE_P, PG_RETURN_POINTER, pushJsonbValue(), JsonbInState::res, str, TextDatumGetCString, JsonbValue::type, JsonbValue::val, WJB_BEGIN_OBJECT, WJB_END_OBJECT, WJB_KEY, and WJB_VALUE.

◆ jsonb_out()

Datum jsonb_out ( PG_FUNCTION_ARGS  )

Definition at line 108 of file jsonb.c.

109{
110 Jsonb *jb = PG_GETARG_JSONB_P(0);
111 char *out;
112
113 out = JsonbToCString(NULL, &jb->root, VARSIZE(jb));
114
116}
#define PG_RETURN_CSTRING(x)
Definition: fmgr.h:362
char * JsonbToCString(StringInfo out, JsonbContainer *in, int estimated_len)
Definition: jsonb.c:473
#define VARSIZE(PTR)
Definition: varatt.h:279

References JsonbToCString(), PG_GETARG_JSONB_P, PG_RETURN_CSTRING, Jsonb::root, and VARSIZE.

Referenced by ExecEvalJsonExprPath(), and ExecGetJsonValueItemString().

◆ jsonb_put_escaped_value()

static void jsonb_put_escaped_value ( StringInfo  out,
JsonbValue scalarVal 
)
static

Definition at line 349 of file jsonb.c.

350{
351 switch (scalarVal->type)
352 {
353 case jbvNull:
354 appendBinaryStringInfo(out, "null", 4);
355 break;
356 case jbvString:
357 escape_json_with_len(out, scalarVal->val.string.val, scalarVal->val.string.len);
358 break;
359 case jbvNumeric:
362 PointerGetDatum(scalarVal->val.numeric))));
363 break;
364 case jbvBool:
365 if (scalarVal->val.boolean)
366 appendBinaryStringInfo(out, "true", 4);
367 else
368 appendBinaryStringInfo(out, "false", 5);
369 break;
370 default:
371 elog(ERROR, "unknown jsonb scalar type");
372 }
373}
Datum numeric_out(PG_FUNCTION_ARGS)
Definition: numeric.c:816
void escape_json_with_len(StringInfo buf, const char *str, int len)
Definition: json.c:1631
static Datum PointerGetDatum(const void *X)
Definition: postgres.h:327
static char * DatumGetCString(Datum X)
Definition: postgres.h:340
void appendBinaryStringInfo(StringInfo str, const void *data, int datalen)
Definition: stringinfo.c:281
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:230

References appendBinaryStringInfo(), appendStringInfoString(), DatumGetCString(), DirectFunctionCall1, elog, ERROR, escape_json_with_len(), jbvBool, jbvNull, jbvNumeric, jbvString, numeric_out(), PointerGetDatum(), JsonbValue::type, and JsonbValue::val.

Referenced by JsonbToCStringWorker().

◆ jsonb_recv()

Datum jsonb_recv ( PG_FUNCTION_ARGS  )

Definition at line 89 of file jsonb.c.

90{
92 int version = pq_getmsgint(buf, 1);
93 char *str;
94 int nbytes;
95
96 if (version == 1)
97 str = pq_getmsgtext(buf, buf->len - buf->cursor, &nbytes);
98 else
99 elog(ERROR, "unsupported jsonb version number %d", version);
100
101 return jsonb_from_cstring(str, nbytes, false, NULL);
102}
unsigned int pq_getmsgint(StringInfo msg, int b)
Definition: pqformat.c:415
char * pq_getmsgtext(StringInfo msg, int rawbytes, int *nbytes)
Definition: pqformat.c:546
StringInfoData * StringInfo
Definition: stringinfo.h:54

References buf, elog, ERROR, jsonb_from_cstring(), PG_GETARG_POINTER, pq_getmsgint(), pq_getmsgtext(), and str.

◆ jsonb_send()

Datum jsonb_send ( PG_FUNCTION_ARGS  )

Definition at line 124 of file jsonb.c.

125{
126 Jsonb *jb = PG_GETARG_JSONB_P(0);
128 StringInfo jtext = makeStringInfo();
129 int version = 1;
130
131 (void) JsonbToCString(jtext, &jb->root, VARSIZE(jb));
132
134 pq_sendint8(&buf, version);
135 pq_sendtext(&buf, jtext->data, jtext->len);
136 destroyStringInfo(jtext);
137
139}
#define PG_RETURN_BYTEA_P(x)
Definition: fmgr.h:371
void pq_sendtext(StringInfo buf, const char *str, int slen)
Definition: pqformat.c:172
void pq_begintypsend(StringInfo buf)
Definition: pqformat.c:326
bytea * pq_endtypsend(StringInfo buf)
Definition: pqformat.c:346
static void pq_sendint8(StringInfo buf, uint8 i)
Definition: pqformat.h:128
void destroyStringInfo(StringInfo str)
Definition: stringinfo.c:409
StringInfo makeStringInfo(void)
Definition: stringinfo.c:72

References buf, StringInfoData::data, destroyStringInfo(), JsonbToCString(), StringInfoData::len, makeStringInfo(), PG_GETARG_JSONB_P, PG_RETURN_BYTEA_P, pq_begintypsend(), pq_endtypsend(), pq_sendint8(), pq_sendtext(), Jsonb::root, and VARSIZE.

◆ jsonb_typeof()

Datum jsonb_typeof ( PG_FUNCTION_ARGS  )

Definition at line 229 of file jsonb.c.

230{
231 Jsonb *in = PG_GETARG_JSONB_P(0);
232 const char *result = JsonbContainerTypeName(&in->root);
233
235}
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:372
static const char * JsonbContainerTypeName(JsonbContainer *jbc)
Definition: jsonb.c:159
text * cstring_to_text(const char *s)
Definition: varlena.c:184

References cstring_to_text(), JsonbContainerTypeName(), PG_GETARG_JSONB_P, PG_RETURN_TEXT_P, and Jsonb::root.

◆ JsonbContainerTypeName()

static const char * JsonbContainerTypeName ( JsonbContainer jbc)
static

Definition at line 159 of file jsonb.c.

160{
161 JsonbValue scalar;
162
163 if (JsonbExtractScalar(jbc, &scalar))
164 return JsonbTypeName(&scalar);
165 else if (JsonContainerIsArray(jbc))
166 return "array";
167 else if (JsonContainerIsObject(jbc))
168 return "object";
169 else
170 {
171 elog(ERROR, "invalid jsonb container type: 0x%08x", jbc->header);
172 return "unknown";
173 }
174}
const char * JsonbTypeName(JsonbValue *val)
Definition: jsonb.c:180
#define JsonContainerIsArray(jc)
Definition: jsonb.h:209
#define JsonContainerIsObject(jc)
Definition: jsonb.h:208
uint32 header
Definition: jsonb.h:192

References elog, ERROR, JsonbContainer::header, JsonbExtractScalar(), JsonbTypeName(), JsonContainerIsArray, and JsonContainerIsObject.

Referenced by jsonb_typeof(), and JsonbTypeName().

◆ JsonbExtractScalar()

bool JsonbExtractScalar ( JsonbContainer jbc,
JsonbValue res 
)

Definition at line 1968 of file jsonb.c.

1969{
1970 JsonbIterator *it;
1972 JsonbValue tmp;
1973
1975 {
1976 /* inform caller about actual type of container */
1977 res->type = (JsonContainerIsArray(jbc)) ? jbvArray : jbvObject;
1978 return false;
1979 }
1980
1981 /*
1982 * A root scalar is stored as an array of one element, so we get the array
1983 * and then its first (and only) member.
1984 */
1985 it = JsonbIteratorInit(jbc);
1986
1987 tok = JsonbIteratorNext(&it, &tmp, true);
1988 Assert(tok == WJB_BEGIN_ARRAY);
1989 Assert(tmp.val.array.nElems == 1 && tmp.val.array.rawScalar);
1990
1991 tok = JsonbIteratorNext(&it, res, true);
1992 Assert(tok == WJB_ELEM);
1994
1995 tok = JsonbIteratorNext(&it, &tmp, true);
1996 Assert(tok == WJB_END_ARRAY);
1997
1998 tok = JsonbIteratorNext(&it, &tmp, true);
1999 Assert(tok == WJB_DONE);
2000
2001 return true;
2002}
#define PG_USED_FOR_ASSERTS_ONLY
Definition: c.h:204
#define JsonContainerIsScalar(jc)
Definition: jsonb.h:207
#define IsAJsonbScalar(jsonbval)
Definition: jsonb.h:297

References Assert, IsAJsonbScalar, jbvArray, jbvObject, JsonbIteratorInit(), JsonbIteratorNext(), JsonContainerIsArray, JsonContainerIsScalar, PG_USED_FOR_ASSERTS_ONLY, res, JsonbValue::val, WJB_BEGIN_ARRAY, WJB_DONE, WJB_ELEM, and WJB_END_ARRAY.

Referenced by executeJsonPath(), jsonb_bool(), jsonb_float4(), jsonb_float8(), jsonb_int2(), jsonb_int4(), jsonb_int8(), jsonb_numeric(), JsonbContainerTypeName(), JsonbUnquote(), JsonItemFromDatum(), and JsonPathValue().

◆ JsonbToCString()

char * JsonbToCString ( StringInfo  out,
JsonbContainer in,
int  estimated_len 
)

Definition at line 473 of file jsonb.c.

474{
475 return JsonbToCStringWorker(out, in, estimated_len, false);
476}
static char * JsonbToCStringWorker(StringInfo out, JsonbContainer *in, int estimated_len, bool indent)
Definition: jsonb.c:491

References JsonbToCStringWorker().

Referenced by jsonb_get_element(), jsonb_out(), jsonb_send(), JsonbUnquote(), JsonbValueAsText(), and populate_scalar().

◆ JsonbToCStringIndent()

char * JsonbToCStringIndent ( StringInfo  out,
JsonbContainer in,
int  estimated_len 
)

Definition at line 482 of file jsonb.c.

483{
484 return JsonbToCStringWorker(out, in, estimated_len, true);
485}

References JsonbToCStringWorker().

Referenced by jsonb_pretty().

◆ JsonbToCStringWorker()

static char * JsonbToCStringWorker ( StringInfo  out,
JsonbContainer in,
int  estimated_len,
bool  indent 
)
static

Definition at line 491 of file jsonb.c.

492{
493 bool first = true;
494 JsonbIterator *it;
495 JsonbValue v;
497 int level = 0;
498 bool redo_switch = false;
499
500 /* If we are indenting, don't add a space after a comma */
501 int ispaces = indent ? 1 : 2;
502
503 /*
504 * Don't indent the very first item. This gets set to the indent flag at
505 * the bottom of the loop.
506 */
507 bool use_indent = false;
508 bool raw_scalar = false;
509 bool last_was_key = false;
510
511 if (out == NULL)
512 out = makeStringInfo();
513
514 enlargeStringInfo(out, (estimated_len >= 0) ? estimated_len : 64);
515
516 it = JsonbIteratorInit(in);
517
518 while (redo_switch ||
519 ((type = JsonbIteratorNext(&it, &v, false)) != WJB_DONE))
520 {
521 redo_switch = false;
522 switch (type)
523 {
524 case WJB_BEGIN_ARRAY:
525 if (!first)
526 appendBinaryStringInfo(out, ", ", ispaces);
527
528 if (!v.val.array.rawScalar)
529 {
530 add_indent(out, use_indent && !last_was_key, level);
532 }
533 else
534 raw_scalar = true;
535
536 first = true;
537 level++;
538 break;
539 case WJB_BEGIN_OBJECT:
540 if (!first)
541 appendBinaryStringInfo(out, ", ", ispaces);
542
543 add_indent(out, use_indent && !last_was_key, level);
545
546 first = true;
547 level++;
548 break;
549 case WJB_KEY:
550 if (!first)
551 appendBinaryStringInfo(out, ", ", ispaces);
552 first = true;
553
554 add_indent(out, use_indent, level);
555
556 /* json rules guarantee this is a string */
558 appendBinaryStringInfo(out, ": ", 2);
559
560 type = JsonbIteratorNext(&it, &v, false);
561 if (type == WJB_VALUE)
562 {
563 first = false;
565 }
566 else
567 {
569
570 /*
571 * We need to rerun the current switch() since we need to
572 * output the object which we just got from the iterator
573 * before calling the iterator again.
574 */
575 redo_switch = true;
576 }
577 break;
578 case WJB_ELEM:
579 if (!first)
580 appendBinaryStringInfo(out, ", ", ispaces);
581 first = false;
582
583 if (!raw_scalar)
584 add_indent(out, use_indent, level);
586 break;
587 case WJB_END_ARRAY:
588 level--;
589 if (!raw_scalar)
590 {
591 add_indent(out, use_indent, level);
593 }
594 first = false;
595 break;
596 case WJB_END_OBJECT:
597 level--;
598 add_indent(out, use_indent, level);
600 first = false;
601 break;
602 default:
603 elog(ERROR, "unknown jsonb iterator token type");
604 }
605 use_indent = indent;
606 last_was_key = redo_switch;
607 }
608
609 Assert(level == 0);
610
611 return out->data;
612}
static void jsonb_put_escaped_value(StringInfo out, JsonbValue *scalarVal)
Definition: jsonb.c:349
static void add_indent(StringInfo out, bool indent, int level)
Definition: jsonb.c:615
void enlargeStringInfo(StringInfo str, int needed)
Definition: stringinfo.c:337

References add_indent(), appendBinaryStringInfo(), appendStringInfoCharMacro, Assert, StringInfoData::data, elog, enlargeStringInfo(), ERROR, jsonb_put_escaped_value(), JsonbIteratorInit(), JsonbIteratorNext(), makeStringInfo(), type, JsonbValue::val, WJB_BEGIN_ARRAY, WJB_BEGIN_OBJECT, WJB_DONE, WJB_ELEM, WJB_END_ARRAY, WJB_END_OBJECT, WJB_KEY, and WJB_VALUE.

Referenced by JsonbToCString(), and JsonbToCStringIndent().

◆ JsonbTypeName()

const char * JsonbTypeName ( JsonbValue val)

Definition at line 180 of file jsonb.c.

181{
182 switch (val->type)
183 {
184 case jbvBinary:
185 return JsonbContainerTypeName(val->val.binary.data);
186 case jbvObject:
187 return "object";
188 case jbvArray:
189 return "array";
190 case jbvNumeric:
191 return "number";
192 case jbvString:
193 return "string";
194 case jbvBool:
195 return "boolean";
196 case jbvNull:
197 return "null";
198 case jbvDatetime:
199 switch (val->val.datetime.typid)
200 {
201 case DATEOID:
202 return "date";
203 case TIMEOID:
204 return "time without time zone";
205 case TIMETZOID:
206 return "time with time zone";
207 case TIMESTAMPOID:
208 return "timestamp without time zone";
209 case TIMESTAMPTZOID:
210 return "timestamp with time zone";
211 default:
212 elog(ERROR, "unrecognized jsonb value datetime type: %d",
213 val->val.datetime.typid);
214 }
215 return "unknown";
216 default:
217 elog(ERROR, "unrecognized jsonb value type: %d", val->type);
218 return "unknown";
219 }
220}
@ jbvDatetime
Definition: jsonb.h:244

References elog, ERROR, jbvArray, jbvBinary, jbvBool, jbvDatetime, jbvNull, jbvNumeric, jbvObject, jbvString, JsonbContainerTypeName(), and val.

Referenced by executeItemOptUnwrapTarget(), and JsonbContainerTypeName().

◆ JsonbUnquote()

char * JsonbUnquote ( Jsonb jb)

Definition at line 2166 of file jsonb.c.

2167{
2168 if (JB_ROOT_IS_SCALAR(jb))
2169 {
2170 JsonbValue v;
2171
2172 (void) JsonbExtractScalar(&jb->root, &v);
2173
2174 if (v.type == jbvString)
2175 return pnstrdup(v.val.string.val, v.val.string.len);
2176 else if (v.type == jbvBool)
2177 return pstrdup(v.val.boolean ? "true" : "false");
2178 else if (v.type == jbvNumeric)
2180 PointerGetDatum(v.val.numeric)));
2181 else if (v.type == jbvNull)
2182 return pstrdup("null");
2183 else
2184 {
2185 elog(ERROR, "unrecognized jsonb value type %d", v.type);
2186 return NULL;
2187 }
2188 }
2189 else
2190 return JsonbToCString(NULL, &jb->root, VARSIZE(jb));
2191}
char * pstrdup(const char *in)
Definition: mcxt.c:1696
char * pnstrdup(const char *in, Size len)
Definition: mcxt.c:1707

References DatumGetCString(), DirectFunctionCall1, elog, ERROR, JB_ROOT_IS_SCALAR, jbvBool, jbvNull, jbvNumeric, jbvString, JsonbExtractScalar(), JsonbToCString(), numeric_out(), pnstrdup(), PointerGetDatum(), pstrdup(), Jsonb::root, JsonbValue::type, JsonbValue::val, and VARSIZE.

Referenced by json_populate_type().

◆ to_jsonb()

Datum to_jsonb ( PG_FUNCTION_ARGS  )

Definition at line 1088 of file jsonb.c.

1089{
1091 Oid val_type = get_fn_expr_argtype(fcinfo->flinfo, 0);
1092 JsonTypeCategory tcategory;
1093 Oid outfuncoid;
1094
1095 if (val_type == InvalidOid)
1096 ereport(ERROR,
1097 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1098 errmsg("could not determine input data type")));
1099
1100 json_categorize_type(val_type, true,
1101 &tcategory, &outfuncoid);
1102
1103 PG_RETURN_DATUM(datum_to_jsonb(val, tcategory, outfuncoid));
1104}
Datum datum_to_jsonb(Datum val, JsonTypeCategory tcategory, Oid outfuncoid)
Definition: jsonb.c:1112

References datum_to_jsonb(), ereport, errcode(), errmsg(), ERROR, get_fn_expr_argtype(), InvalidOid, json_categorize_type(), PG_GETARG_DATUM, PG_RETURN_DATUM, and val.

◆ to_jsonb_is_immutable()

bool to_jsonb_is_immutable ( Oid  typoid)

Definition at line 1049 of file jsonb.c.

1050{
1051 JsonTypeCategory tcategory;
1052 Oid outfuncoid;
1053
1054 json_categorize_type(typoid, true, &tcategory, &outfuncoid);
1055
1056 switch (tcategory)
1057 {
1058 case JSONTYPE_NULL:
1059 case JSONTYPE_BOOL:
1060 case JSONTYPE_JSON:
1061 case JSONTYPE_JSONB:
1062 return true;
1063
1064 case JSONTYPE_DATE:
1065 case JSONTYPE_TIMESTAMP:
1067 return false;
1068
1069 case JSONTYPE_ARRAY:
1070 return false; /* TODO recurse into elements */
1071
1072 case JSONTYPE_COMPOSITE:
1073 return false; /* TODO recurse into fields */
1074
1075 case JSONTYPE_NUMERIC:
1076 case JSONTYPE_CAST:
1077 case JSONTYPE_OTHER:
1078 return func_volatile(outfuncoid) == PROVOLATILE_IMMUTABLE;
1079 }
1080
1081 return false; /* not reached */
1082}
@ JSONTYPE_OTHER
Definition: jsonfuncs.h:81
char func_volatile(Oid funcid)
Definition: lsyscache.c:1780

References func_volatile(), json_categorize_type(), JSONTYPE_ARRAY, JSONTYPE_BOOL, JSONTYPE_CAST, JSONTYPE_COMPOSITE, JSONTYPE_DATE, JSONTYPE_JSON, JSONTYPE_JSONB, JSONTYPE_NULL, JSONTYPE_NUMERIC, JSONTYPE_OTHER, JSONTYPE_TIMESTAMP, and JSONTYPE_TIMESTAMPTZ.

Referenced by contain_mutable_functions_walker().