PostgreSQL Source Code  git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
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:209
#define appendStringInfoCharMacro(str, ch)
Definition: stringinfo.h:204

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:36
unsigned int Oid
Definition: postgres_ext.h:31

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:863
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:566
JsonbParseState * parseState
Definition: jsonb.c:30
JsonbValue * res
Definition: jsonb.c:31

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

Referenced by 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
signed short int16
Definition: c.h:507
#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:64

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:1201
#define lengthof(array)
Definition: c.h:793
#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 {
279  if (len > JENTRY_OFFLENMASK)
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 {
944  HeapTupleHeader td;
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:751
signed int int32
Definition: c.h:508
#define DatumGetHeapTupleHeader(X)
Definition: fmgr.h:295
static Datum heap_getattr(HeapTuple tup, int attnum, TupleDesc tupleDesc, bool *isnull)
Definition: htup_details.h:792
#define HeapTupleHeaderGetTypMod(tup)
Definition: htup_details.h:466
#define HeapTupleHeaderGetTypeId(tup)
Definition: htup_details.h:456
#define HeapTupleHeaderGetDatumLength(tup)
Definition: htup_details.h:450
@ 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:209
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:122
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
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  {
662  ereport(ERROR,
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:
674  array_to_jsonb_internal(val, result);
675  break;
676  case JSONTYPE_COMPOSITE:
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;
737  case JSONTYPE_TIMESTAMP:
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 = (void *) 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:636
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:639
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:817
JsonbIteratorToken JsonbIteratorNext(JsonbIterator **it, JsonbValue *val, bool skipNested)
Definition: jsonb_util.c:853
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
void check_stack_depth(void)
Definition: postgres.c:3563
static bool DatumGetBool(Datum X)
Definition: postgres.h:90
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:252
static Datum CStringGetDatum(const char *X)
Definition: postgres.h:350
static Datum Int32GetDatum(int32 X)
Definition: postgres.h:212
json_struct_action array_end
Definition: jsonapi.h:148
json_struct_action object_start
Definition: jsonapi.h:145
json_ofield_action object_field_start
Definition: jsonapi.h:149
json_scalar_action scalar
Definition: jsonapi.h:153
void * semstate
Definition: jsonapi.h:144
json_struct_action array_start
Definition: jsonapi.h:147
json_struct_action object_end
Definition: jsonapi.h:146
Definition: jsonb.h:213
JsonbContainer root
Definition: jsonb.h:215
Definition: c.h:692
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 {
1642  JsonbAggState *arg;
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:4511
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:1461
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 char * buf
Definition: pg_test_fsync.c:72
#define snprintf
Definition: port.h:238
MemoryContextSwitchTo(old_ctx)
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)
1248  PG_RETURN_NULL();
1249 
1250  PG_RETURN_DATUM(jsonb_build_array_worker(nargs, args, nulls, types, false));
1251 }
struct typedefs * types
Definition: ecpg.c:29
#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)
1188  PG_RETURN_NULL();
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:4719

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:4625

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 = (void *) &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:390
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 {
149  return jsonb_from_cstring(VARDATA_ANY(js),
150  VARSIZE_ANY_EXHDR(js),
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))
340  return JSON_SEM_ACTION_FAILED;
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 
388  case JSON_TOKEN_STRING:
389  Assert(token != NULL);
390  v.type = jbvString;
391  v.val.string.len = strlen(token);
392  if (!checkStringLen(v.val.string.len, _state->escontext))
393  return JSON_SEM_ACTION_FAILED;
394  v.val.string.val = token;
395  break;
396  case JSON_TOKEN_NUMBER:
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))
408  return JSON_SEM_ACTION_FAILED;
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 
2082  retValue = DirectFunctionCall1(numeric_int2,
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:4550

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 
2100  retValue = DirectFunctionCall1(numeric_int4,
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:4444

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 
2118  retValue = DirectFunctionCall1(numeric_int8,
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:4532

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 
1366 close_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 {
1932  JsonbAggState *arg;
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 
1458 close_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 
115  PG_RETURN_CSTRING(out);
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:815
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:322
static char * DatumGetCString(Datum X)
Definition: postgres.h:335
void appendBinaryStringInfo(StringInfo str, const void *data, int datalen)
Definition: stringinfo.c:230
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:179

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:358
StringInfo makeStringInfo(void)
Definition: stringinfo.c:38

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 
1974  if (!JsonContainerIsArray(jbc) || !JsonContainerIsScalar(jbc))
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:197
#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);
531  appendStringInfoCharMacro(out, '[');
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);
544  appendStringInfoCharMacro(out, '{');
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 */
557  jsonb_put_escaped_value(out, &v);
558  appendBinaryStringInfo(out, ": ", 2);
559 
560  type = JsonbIteratorNext(&it, &v, false);
561  if (type == WJB_VALUE)
562  {
563  first = false;
564  jsonb_put_escaped_value(out, &v);
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);
585  jsonb_put_escaped_value(out, &v);
586  break;
587  case WJB_END_ARRAY:
588  level--;
589  if (!raw_scalar)
590  {
591  add_indent(out, use_indent, level);
592  appendStringInfoCharMacro(out, ']');
593  }
594  first = false;
595  break;
596  case WJB_END_OBJECT:
597  level--;
598  add_indent(out, use_indent, level);
599  appendStringInfoCharMacro(out, '}');
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:286

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 * pnstrdup(const char *in, Size len)
Definition: mcxt.c:1707
char * pstrdup(const char *in)
Definition: mcxt.c:1696

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 {
1090  Datum val = PG_GETARG_DATUM(0);
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:
1066  case JSONTYPE_TIMESTAMPTZ:
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().