PostgreSQL Source Code  git master
jsonb.c File Reference
#include "postgres.h"
#include "access/htup_details.h"
#include "access/transam.h"
#include "catalog/pg_type.h"
#include "funcapi.h"
#include "libpq/pqformat.h"
#include "miscadmin.h"
#include "parser/parse_coerce.h"
#include "utils/builtins.h"
#include "utils/date.h"
#include "utils/datetime.h"
#include "utils/json.h"
#include "utils/jsonb.h"
#include "utils/jsonfuncs.h"
#include "utils/lsyscache.h"
#include "utils/syscache.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
 

Enumerations

enum  JsonbTypeCategory {
  JSONBTYPE_NULL , JSONBTYPE_BOOL , JSONBTYPE_NUMERIC , JSONBTYPE_DATE ,
  JSONBTYPE_TIMESTAMP , JSONBTYPE_TIMESTAMPTZ , JSONBTYPE_JSON , JSONBTYPE_JSONB ,
  JSONBTYPE_ARRAY , JSONBTYPE_COMPOSITE , JSONBTYPE_JSONCAST , JSONBTYPE_OTHER
}
 

Functions

static Datum jsonb_from_cstring (char *json, int len, 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 jsonb_categorize_type (Oid typoid, JsonbTypeCategory *tcategory, Oid *outfuncoid)
 
static void composite_to_jsonb (Datum composite, JsonbInState *result)
 
static void array_dim_to_jsonb (JsonbInState *result, int dim, int ndims, int *dims, Datum *vals, bool *nulls, int *valcount, JsonbTypeCategory tcategory, Oid outfuncoid)
 
static void array_to_jsonb_internal (Datum array, JsonbInState *result)
 
static void datum_to_jsonb (Datum val, bool is_null, JsonbInState *result, JsonbTypeCategory 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)
 
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)
 
Datum to_jsonb (PG_FUNCTION_ARGS)
 
Datum jsonb_build_object (PG_FUNCTION_ARGS)
 
Datum jsonb_build_object_noargs (PG_FUNCTION_ARGS)
 
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)
 
Datum jsonb_agg_transfn (PG_FUNCTION_ARGS)
 
Datum jsonb_agg_finalfn (PG_FUNCTION_ARGS)
 
Datum jsonb_object_agg_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)
 

Typedef Documentation

◆ JsonbAggState

typedef struct JsonbAggState JsonbAggState

◆ JsonbInState

typedef struct JsonbInState JsonbInState

Enumeration Type Documentation

◆ JsonbTypeCategory

Enumerator
JSONBTYPE_NULL 
JSONBTYPE_BOOL 
JSONBTYPE_NUMERIC 
JSONBTYPE_DATE 
JSONBTYPE_TIMESTAMP 
JSONBTYPE_TIMESTAMPTZ 
JSONBTYPE_JSON 
JSONBTYPE_JSONB 
JSONBTYPE_ARRAY 
JSONBTYPE_COMPOSITE 
JSONBTYPE_JSONCAST 
JSONBTYPE_OTHER 

Definition at line 40 of file jsonb.c.

41 {
42  JSONBTYPE_NULL, /* null, so we didn't bother to identify */
43  JSONBTYPE_BOOL, /* boolean (built-in types only) */
44  JSONBTYPE_NUMERIC, /* numeric (ditto) */
45  JSONBTYPE_DATE, /* we use special formatting for datetimes */
46  JSONBTYPE_TIMESTAMP, /* we use special formatting for timestamp */
47  JSONBTYPE_TIMESTAMPTZ, /* ... and timestamptz */
48  JSONBTYPE_JSON, /* JSON */
49  JSONBTYPE_JSONB, /* JSONB */
50  JSONBTYPE_ARRAY, /* array */
51  JSONBTYPE_COMPOSITE, /* composite */
52  JSONBTYPE_JSONCAST, /* something with an explicit cast to JSON */
53  JSONBTYPE_OTHER /* all else */
JsonbTypeCategory
Definition: jsonb.c:41
@ JSONBTYPE_OTHER
Definition: jsonb.c:53
@ JSONBTYPE_TIMESTAMPTZ
Definition: jsonb.c:47
@ JSONBTYPE_JSONB
Definition: jsonb.c:49
@ JSONBTYPE_DATE
Definition: jsonb.c:45
@ JSONBTYPE_NUMERIC
Definition: jsonb.c:44
@ JSONBTYPE_ARRAY
Definition: jsonb.c:50
@ JSONBTYPE_COMPOSITE
Definition: jsonb.c:51
@ JSONBTYPE_JSON
Definition: jsonb.c:48
@ JSONBTYPE_BOOL
Definition: jsonb.c:43
@ JSONBTYPE_NULL
Definition: jsonb.c:42
@ JSONBTYPE_TIMESTAMP
Definition: jsonb.c:46
@ JSONBTYPE_JSONCAST
Definition: jsonb.c:52

Function Documentation

◆ add_indent()

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

Definition at line 625 of file jsonb.c.

626 {
627  if (indent)
628  {
629  appendStringInfoCharMacro(out, '\n');
630  appendStringInfoSpaces(out, level * 4);
631  }
632 }
void appendStringInfoSpaces(StringInfo str, int count)
Definition: stringinfo.c:206
#define appendStringInfoCharMacro(str, ch)
Definition: stringinfo.h:128

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 1129 of file jsonb.c.

1131 {
1132  JsonbTypeCategory tcategory;
1133  Oid outfuncoid;
1134 
1135  if (val_type == InvalidOid)
1136  ereport(ERROR,
1137  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1138  errmsg("could not determine input data type")));
1139 
1140  if (is_null)
1141  {
1142  tcategory = JSONBTYPE_NULL;
1143  outfuncoid = InvalidOid;
1144  }
1145  else
1146  jsonb_categorize_type(val_type,
1147  &tcategory, &outfuncoid);
1148 
1149  datum_to_jsonb(val, is_null, result, tcategory, outfuncoid, key_scalar);
1150 }
int errcode(int sqlerrcode)
Definition: elog.c:858
int errmsg(const char *fmt,...)
Definition: elog.c:1069
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:149
long val
Definition: informix.c:664
static void jsonb_categorize_type(Oid typoid, JsonbTypeCategory *tcategory, Oid *outfuncoid)
Definition: jsonb.c:643
static void datum_to_jsonb(Datum val, bool is_null, JsonbInState *result, JsonbTypeCategory tcategory, Oid outfuncoid, bool key_scalar)
Definition: jsonb.c:754
#define InvalidOid
Definition: postgres_ext.h:36
unsigned int Oid
Definition: postgres_ext.h:31

References datum_to_jsonb(), ereport, errcode(), errmsg(), ERROR, InvalidOid, jsonb_categorize_type(), JSONBTYPE_NULL, and val.

Referenced by jsonb_build_array(), and jsonb_build_object().

◆ array_dim_to_jsonb()

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

Definition at line 977 of file jsonb.c.

980 {
981  int i;
982 
983  Assert(dim < ndims);
984 
985  result->res = pushJsonbValue(&result->parseState, WJB_BEGIN_ARRAY, NULL);
986 
987  for (i = 1; i <= dims[dim]; i++)
988  {
989  if (dim + 1 == ndims)
990  {
991  datum_to_jsonb(vals[*valcount], nulls[*valcount], result, tcategory,
992  outfuncoid, false);
993  (*valcount)++;
994  }
995  else
996  {
997  array_dim_to_jsonb(result, dim + 1, ndims, dims, vals, nulls,
998  valcount, tcategory, outfuncoid);
999  }
1000  }
1001 
1002  result->res = pushJsonbValue(&result->parseState, WJB_END_ARRAY, NULL);
1003 }
int i
Definition: isn.c:73
static void array_dim_to_jsonb(JsonbInState *result, int dim, int ndims, int *dims, Datum *vals, bool *nulls, int *valcount, JsonbTypeCategory tcategory, Oid outfuncoid)
Definition: jsonb.c:977
@ 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:567
Assert(fmt[strlen(fmt) - 1] !='\n')
JsonbParseState * parseState
Definition: jsonb.c:34
JsonbValue * res
Definition: jsonb.c:35

References Assert(), datum_to_jsonb(), 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 1009 of file jsonb.c.

1010 {
1011  ArrayType *v = DatumGetArrayTypeP(array);
1012  Oid element_type = ARR_ELEMTYPE(v);
1013  int *dim;
1014  int ndim;
1015  int nitems;
1016  int count = 0;
1017  Datum *elements;
1018  bool *nulls;
1019  int16 typlen;
1020  bool typbyval;
1021  char typalign;
1022  JsonbTypeCategory tcategory;
1023  Oid outfuncoid;
1024 
1025  ndim = ARR_NDIM(v);
1026  dim = ARR_DIMS(v);
1027  nitems = ArrayGetNItems(ndim, dim);
1028 
1029  if (nitems <= 0)
1030  {
1031  result->res = pushJsonbValue(&result->parseState, WJB_BEGIN_ARRAY, NULL);
1032  result->res = pushJsonbValue(&result->parseState, WJB_END_ARRAY, NULL);
1033  return;
1034  }
1035 
1036  get_typlenbyvalalign(element_type,
1037  &typlen, &typbyval, &typalign);
1038 
1039  jsonb_categorize_type(element_type,
1040  &tcategory, &outfuncoid);
1041 
1042  deconstruct_array(v, element_type, typlen, typbyval,
1043  typalign, &elements, &nulls,
1044  &nitems);
1045 
1046  array_dim_to_jsonb(result, 0, ndim, dim, elements, nulls, &count, tcategory,
1047  outfuncoid);
1048 
1049  pfree(elements);
1050  pfree(nulls);
1051 }
#define ARR_NDIM(a)
Definition: array.h:283
#define DatumGetArrayTypeP(X)
Definition: array.h:254
#define ARR_ELEMTYPE(a)
Definition: array.h:285
#define ARR_DIMS(a)
Definition: array.h:287
void deconstruct_array(ArrayType *array, Oid elmtype, int elmlen, bool elmbyval, char elmalign, Datum **elemsp, bool **nullsp, int *nelemsp)
Definition: arrayfuncs.c:3602
int ArrayGetNItems(int ndim, const int *dims)
Definition: arrayutils.c:76
signed short int16
Definition: c.h:477
#define nitems(x)
Definition: indent.h:31
void get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval, char *typalign)
Definition: lsyscache.c:2229
void pfree(void *pointer)
Definition: mcxt.c:1436
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(), jsonb_categorize_type(), nitems, JsonbInState::parseState, pfree(), pushJsonbValue(), JsonbInState::res, typalign, WJB_BEGIN_ARRAY, and WJB_END_ARRAY.

Referenced by datum_to_jsonb().

◆ cannotCastJsonbValue()

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

Definition at line 1953 of file jsonb.c.

1954 {
1955  static const struct
1956  {
1957  enum jbvType type;
1958  const char *msg;
1959  }
1960  messages[] =
1961  {
1962  {jbvNull, gettext_noop("cannot cast jsonb null to type %s")},
1963  {jbvString, gettext_noop("cannot cast jsonb string to type %s")},
1964  {jbvNumeric, gettext_noop("cannot cast jsonb numeric to type %s")},
1965  {jbvBool, gettext_noop("cannot cast jsonb boolean to type %s")},
1966  {jbvArray, gettext_noop("cannot cast jsonb array to type %s")},
1967  {jbvObject, gettext_noop("cannot cast jsonb object to type %s")},
1968  {jbvBinary, gettext_noop("cannot cast jsonb array or object to type %s")}
1969  };
1970  int i;
1971 
1972  for (i = 0; i < lengthof(messages); i++)
1973  if (messages[i].type == type)
1974  ereport(ERROR,
1975  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1976  errmsg(messages[i].msg, sqltype)));
1977 
1978  /* should be unreachable */
1979  elog(ERROR, "unknown jsonb type: %d", (int) type);
1980 }
#define gettext_noop(x)
Definition: c.h:1186
#define lengthof(array)
Definition: c.h:772
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

References elog(), ereport, errcode(), errmsg(), ERROR, gettext_noop, i, jbvArray, jbvBinary, jbvBool, jbvNull, jbvNumeric, jbvObject, jbvString, lengthof, and generate_unaccent_rules::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 288 of file jsonb.c.

289 {
290  if (len > JENTRY_OFFLENMASK)
291  ereturn(escontext, false,
292  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
293  errmsg("string too long to represent as jsonb string"),
294  errdetail("Due to an implementation restriction, jsonb strings cannot exceed %d bytes.",
296 
297  return true;
298 }
int errdetail(const char *fmt,...)
Definition: elog.c:1202
#define ereturn(context, dummy_value,...)
Definition: elog.h:276
#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(), jsonb_in_object_field_start(), and jsonb_in_scalar().

◆ clone_parse_state()

static JsonbParseState * clone_parse_state ( JsonbParseState state)
static

Definition at line 1493 of file jsonb.c.

1494 {
1495  JsonbParseState *result,
1496  *icursor,
1497  *ocursor;
1498 
1499  if (state == NULL)
1500  return NULL;
1501 
1502  result = palloc(sizeof(JsonbParseState));
1503  icursor = state;
1504  ocursor = result;
1505  for (;;)
1506  {
1507  ocursor->contVal = icursor->contVal;
1508  ocursor->size = icursor->size;
1509  icursor = icursor->next;
1510  if (icursor == NULL)
1511  break;
1512  ocursor->next = palloc(sizeof(JsonbParseState));
1513  ocursor = ocursor->next;
1514  }
1515  ocursor->next = NULL;
1516 
1517  return result;
1518 }
void * palloc(Size size)
Definition: mcxt.c:1210
struct JsonbParseState * next
Definition: jsonb.h:323
JsonbValue contVal
Definition: jsonb.h:321
Definition: regguts.h:318

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

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 1057 of file jsonb.c.

1058 {
1059  HeapTupleHeader td;
1060  Oid tupType;
1061  int32 tupTypmod;
1062  TupleDesc tupdesc;
1063  HeapTupleData tmptup,
1064  *tuple;
1065  int i;
1066 
1067  td = DatumGetHeapTupleHeader(composite);
1068 
1069  /* Extract rowtype info and find a tupdesc */
1070  tupType = HeapTupleHeaderGetTypeId(td);
1071  tupTypmod = HeapTupleHeaderGetTypMod(td);
1072  tupdesc = lookup_rowtype_tupdesc(tupType, tupTypmod);
1073 
1074  /* Build a temporary HeapTuple control structure */
1075  tmptup.t_len = HeapTupleHeaderGetDatumLength(td);
1076  tmptup.t_data = td;
1077  tuple = &tmptup;
1078 
1079  result->res = pushJsonbValue(&result->parseState, WJB_BEGIN_OBJECT, NULL);
1080 
1081  for (i = 0; i < tupdesc->natts; i++)
1082  {
1083  Datum val;
1084  bool isnull;
1085  char *attname;
1086  JsonbTypeCategory tcategory;
1087  Oid outfuncoid;
1088  JsonbValue v;
1089  Form_pg_attribute att = TupleDescAttr(tupdesc, i);
1090 
1091  if (att->attisdropped)
1092  continue;
1093 
1094  attname = NameStr(att->attname);
1095 
1096  v.type = jbvString;
1097  /* don't need checkStringLen here - can't exceed maximum name length */
1098  v.val.string.len = strlen(attname);
1099  v.val.string.val = attname;
1100 
1101  result->res = pushJsonbValue(&result->parseState, WJB_KEY, &v);
1102 
1103  val = heap_getattr(tuple, i + 1, tupdesc, &isnull);
1104 
1105  if (isnull)
1106  {
1107  tcategory = JSONBTYPE_NULL;
1108  outfuncoid = InvalidOid;
1109  }
1110  else
1111  jsonb_categorize_type(att->atttypid, &tcategory, &outfuncoid);
1112 
1113  datum_to_jsonb(val, isnull, result, tcategory, outfuncoid, false);
1114  }
1115 
1116  result->res = pushJsonbValue(&result->parseState, WJB_END_OBJECT, NULL);
1117  ReleaseTupleDesc(tupdesc);
1118 }
#define NameStr(name)
Definition: c.h:730
signed int int32
Definition: c.h:478
#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:207
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:1824

References attname, datum_to_jsonb(), DatumGetHeapTupleHeader, heap_getattr(), HeapTupleHeaderGetDatumLength, HeapTupleHeaderGetTypeId, HeapTupleHeaderGetTypMod, i, InvalidOid, jbvString, jsonb_categorize_type(), JSONBTYPE_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().

◆ datum_to_jsonb()

static void datum_to_jsonb ( Datum  val,
bool  is_null,
JsonbInState result,
JsonbTypeCategory  tcategory,
Oid  outfuncoid,
bool  key_scalar 
)
static

Definition at line 754 of file jsonb.c.

757 {
758  char *outputstr;
759  bool numeric_error;
760  JsonbValue jb;
761  bool scalar_jsonb = false;
762 
764 
765  /* Convert val to a JsonbValue in jb (in most cases) */
766  if (is_null)
767  {
768  Assert(!key_scalar);
769  jb.type = jbvNull;
770  }
771  else if (key_scalar &&
772  (tcategory == JSONBTYPE_ARRAY ||
773  tcategory == JSONBTYPE_COMPOSITE ||
774  tcategory == JSONBTYPE_JSON ||
775  tcategory == JSONBTYPE_JSONB ||
776  tcategory == JSONBTYPE_JSONCAST))
777  {
778  ereport(ERROR,
779  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
780  errmsg("key value must be scalar, not array, composite, or json")));
781  }
782  else
783  {
784  if (tcategory == JSONBTYPE_JSONCAST)
785  val = OidFunctionCall1(outfuncoid, val);
786 
787  switch (tcategory)
788  {
789  case JSONBTYPE_ARRAY:
790  array_to_jsonb_internal(val, result);
791  break;
792  case JSONBTYPE_COMPOSITE:
793  composite_to_jsonb(val, result);
794  break;
795  case JSONBTYPE_BOOL:
796  if (key_scalar)
797  {
798  outputstr = DatumGetBool(val) ? "true" : "false";
799  jb.type = jbvString;
800  jb.val.string.len = strlen(outputstr);
801  jb.val.string.val = outputstr;
802  }
803  else
804  {
805  jb.type = jbvBool;
806  jb.val.boolean = DatumGetBool(val);
807  }
808  break;
809  case JSONBTYPE_NUMERIC:
810  outputstr = OidOutputFunctionCall(outfuncoid, val);
811  if (key_scalar)
812  {
813  /* always quote keys */
814  jb.type = jbvString;
815  jb.val.string.len = strlen(outputstr);
816  jb.val.string.val = outputstr;
817  }
818  else
819  {
820  /*
821  * Make it numeric if it's a valid JSON number, otherwise
822  * a string. Invalid numeric output will always have an
823  * 'N' or 'n' in it (I think).
824  */
825  numeric_error = (strchr(outputstr, 'N') != NULL ||
826  strchr(outputstr, 'n') != NULL);
827  if (!numeric_error)
828  {
829  Datum numd;
830 
831  jb.type = jbvNumeric;
833  CStringGetDatum(outputstr),
835  Int32GetDatum(-1));
836  jb.val.numeric = DatumGetNumeric(numd);
837  pfree(outputstr);
838  }
839  else
840  {
841  jb.type = jbvString;
842  jb.val.string.len = strlen(outputstr);
843  jb.val.string.val = outputstr;
844  }
845  }
846  break;
847  case JSONBTYPE_DATE:
848  jb.type = jbvString;
849  jb.val.string.val = JsonEncodeDateTime(NULL, val,
850  DATEOID, NULL);
851  jb.val.string.len = strlen(jb.val.string.val);
852  break;
853  case JSONBTYPE_TIMESTAMP:
854  jb.type = jbvString;
855  jb.val.string.val = JsonEncodeDateTime(NULL, val,
856  TIMESTAMPOID, NULL);
857  jb.val.string.len = strlen(jb.val.string.val);
858  break;
860  jb.type = jbvString;
861  jb.val.string.val = JsonEncodeDateTime(NULL, val,
862  TIMESTAMPTZOID, NULL);
863  jb.val.string.len = strlen(jb.val.string.val);
864  break;
865  case JSONBTYPE_JSONCAST:
866  case JSONBTYPE_JSON:
867  {
868  /* parse the json right into the existing result object */
869  JsonLexContext *lex;
870  JsonSemAction sem;
871  text *json = DatumGetTextPP(val);
872 
873  lex = makeJsonLexContext(json, true);
874 
875  memset(&sem, 0, sizeof(sem));
876 
877  sem.semstate = (void *) result;
878 
883  sem.scalar = jsonb_in_scalar;
885 
886  pg_parse_json_or_ereport(lex, &sem);
887  }
888  break;
889  case JSONBTYPE_JSONB:
890  {
891  Jsonb *jsonb = DatumGetJsonbP(val);
892  JsonbIterator *it;
893 
894  it = JsonbIteratorInit(&jsonb->root);
895 
896  if (JB_ROOT_IS_SCALAR(jsonb))
897  {
898  (void) JsonbIteratorNext(&it, &jb, true);
899  Assert(jb.type == jbvArray);
900  (void) JsonbIteratorNext(&it, &jb, true);
901  scalar_jsonb = true;
902  }
903  else
904  {
906 
907  while ((type = JsonbIteratorNext(&it, &jb, false))
908  != WJB_DONE)
909  {
910  if (type == WJB_END_ARRAY || type == WJB_END_OBJECT ||
912  result->res = pushJsonbValue(&result->parseState,
913  type, NULL);
914  else
915  result->res = pushJsonbValue(&result->parseState,
916  type, &jb);
917  }
918  }
919  }
920  break;
921  default:
922  outputstr = OidOutputFunctionCall(outfuncoid, val);
923  jb.type = jbvString;
924  jb.val.string.len = strlen(outputstr);
925  (void) checkStringLen(jb.val.string.len, NULL);
926  jb.val.string.val = outputstr;
927  break;
928  }
929  }
930 
931  /* Now insert jb into result, unless we did it recursively */
932  if (!is_null && !scalar_jsonb &&
933  tcategory >= JSONBTYPE_JSON && tcategory <= JSONBTYPE_JSONCAST)
934  {
935  /* work has been done recursively */
936  return;
937  }
938  else if (result->parseState == NULL)
939  {
940  /* single root scalar */
941  JsonbValue va;
942 
943  va.type = jbvArray;
944  va.val.array.rawScalar = true;
945  va.val.array.nElems = 1;
946 
947  result->res = pushJsonbValue(&result->parseState, WJB_BEGIN_ARRAY, &va);
948  result->res = pushJsonbValue(&result->parseState, WJB_ELEM, &jb);
949  result->res = pushJsonbValue(&result->parseState, WJB_END_ARRAY, NULL);
950  }
951  else
952  {
953  JsonbValue *o = &result->parseState->contVal;
954 
955  switch (o->type)
956  {
957  case jbvArray:
958  result->res = pushJsonbValue(&result->parseState, WJB_ELEM, &jb);
959  break;
960  case jbvObject:
961  result->res = pushJsonbValue(&result->parseState,
962  key_scalar ? WJB_KEY : WJB_VALUE,
963  &jb);
964  break;
965  default:
966  elog(ERROR, "unexpected parent of nested structure");
967  }
968  }
969 }
Datum numeric_in(PG_FUNCTION_ARGS)
Definition: numeric.c:627
char * OidOutputFunctionCall(Oid functionId, Datum val)
Definition: fmgr.c:1750
#define OidFunctionCall1(functionId, arg1)
Definition: fmgr.h:680
#define DatumGetTextPP(X)
Definition: fmgr.h:292
#define DirectFunctionCall3(func, arg1, arg2, arg3)
Definition: fmgr.h:646
char * JsonEncodeDateTime(char *buf, Datum value, Oid typid, const int *tzp)
Definition: json.c:354
static JsonParseErrorType jsonb_in_object_start(void *pstate)
Definition: jsonb.c:301
static JsonParseErrorType jsonb_in_array_end(void *pstate)
Definition: jsonb.c:331
static JsonParseErrorType jsonb_in_object_field_start(void *pstate, char *fname, bool isnull)
Definition: jsonb.c:341
static void array_to_jsonb_internal(Datum array, JsonbInState *result)
Definition: jsonb.c:1009
static void composite_to_jsonb(Datum composite, JsonbInState *result)
Definition: jsonb.c:1057
static JsonParseErrorType jsonb_in_array_start(void *pstate)
Definition: jsonb.c:321
static JsonParseErrorType jsonb_in_object_end(void *pstate)
Definition: jsonb.c:311
static JsonParseErrorType jsonb_in_scalar(void *pstate, char *token, JsonTokenType tokentype)
Definition: jsonb.c:389
static bool checkStringLen(size_t len, Node *escontext)
Definition: jsonb.c:288
static Jsonb * DatumGetJsonbP(Datum d)
Definition: jsonb.h:372
#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:813
JsonbIteratorToken JsonbIteratorNext(JsonbIterator **it, JsonbValue *val, bool skipNested)
Definition: jsonb_util.c:849
JsonLexContext * makeJsonLexContext(text *json, bool need_escapes)
Definition: jsonfuncs.c:528
#define pg_parse_json_or_ereport(lex, sem)
Definition: jsonfuncs.h:46
static Numeric DatumGetNumeric(Datum X)
Definition: numeric.h:60
void check_stack_depth(void)
Definition: postgres.c:3461
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:118
json_struct_action object_start
Definition: jsonapi.h:115
json_ofield_action object_field_start
Definition: jsonapi.h:119
json_scalar_action scalar
Definition: jsonapi.h:123
void * semstate
Definition: jsonapi.h:114
json_struct_action array_start
Definition: jsonapi.h:117
json_struct_action object_end
Definition: jsonapi.h:116
Definition: jsonb.h:213
JsonbContainer root
Definition: jsonb.h:215
Definition: c.h:671

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, 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(), JSONBTYPE_ARRAY, JSONBTYPE_BOOL, JSONBTYPE_COMPOSITE, JSONBTYPE_DATE, JSONBTYPE_JSON, JSONBTYPE_JSONB, JSONBTYPE_JSONCAST, JSONBTYPE_NUMERIC, JSONBTYPE_TIMESTAMP, JSONBTYPE_TIMESTAMPTZ, JsonEncodeDateTime(), 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, JsonSemAction::semstate, generate_unaccent_rules::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(), jsonb_agg_transfn(), jsonb_object_agg_transfn(), and to_jsonb().

◆ jsonb_agg_finalfn()

Datum jsonb_agg_finalfn ( PG_FUNCTION_ARGS  )

Definition at line 1643 of file jsonb.c.

1644 {
1645  JsonbAggState *arg;
1646  JsonbInState result;
1647  Jsonb *out;
1648 
1649  /* cannot be called directly because of internal-type argument */
1650  Assert(AggCheckCallContext(fcinfo, NULL));
1651 
1652  if (PG_ARGISNULL(0))
1653  PG_RETURN_NULL(); /* returns null iff no input values */
1654 
1656 
1657  /*
1658  * We need to do a shallow clone of the argument in case the final
1659  * function is called more than once, so we avoid changing the argument. A
1660  * shallow clone is sufficient as we aren't going to change any of the
1661  * values, just add the final array end marker.
1662  */
1663  memset(&result, 0, sizeof(JsonbInState));
1664 
1665  result.parseState = clone_parse_state(arg->res->parseState);
1666 
1667  result.res = pushJsonbValue(&result.parseState,
1668  WJB_END_ARRAY, NULL);
1669 
1670  out = JsonbValueToJsonb(result.res);
1671 
1672  PG_RETURN_POINTER(out);
1673 }
#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:1493
Jsonb * JsonbValueToJsonb(JsonbValue *val)
Definition: jsonb_util.c:93
int AggCheckCallContext(FunctionCallInfo fcinfo, MemoryContext *aggcontext)
Definition: nodeAgg.c:4514
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_transfn()

Datum jsonb_agg_transfn ( PG_FUNCTION_ARGS  )

Definition at line 1525 of file jsonb.c.

1526 {
1527  MemoryContext oldcontext,
1528  aggcontext;
1530  JsonbInState elem;
1531  Datum val;
1532  JsonbInState *result;
1533  bool single_scalar = false;
1534  JsonbIterator *it;
1535  Jsonb *jbelem;
1536  JsonbValue v;
1538 
1539  if (!AggCheckCallContext(fcinfo, &aggcontext))
1540  {
1541  /* cannot be called directly because of internal-type argument */
1542  elog(ERROR, "jsonb_agg_transfn called in non-aggregate context");
1543  }
1544 
1545  /* set up the accumulator on the first go round */
1546 
1547  if (PG_ARGISNULL(0))
1548  {
1549  Oid arg_type = get_fn_expr_argtype(fcinfo->flinfo, 1);
1550 
1551  if (arg_type == InvalidOid)
1552  ereport(ERROR,
1553  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1554  errmsg("could not determine input data type")));
1555 
1556  oldcontext = MemoryContextSwitchTo(aggcontext);
1557  state = palloc(sizeof(JsonbAggState));
1558  result = palloc0(sizeof(JsonbInState));
1559  state->res = result;
1560  result->res = pushJsonbValue(&result->parseState,
1561  WJB_BEGIN_ARRAY, NULL);
1562  MemoryContextSwitchTo(oldcontext);
1563 
1564  jsonb_categorize_type(arg_type, &state->val_category,
1565  &state->val_output_func);
1566  }
1567  else
1568  {
1570  result = state->res;
1571  }
1572 
1573  /* turn the argument into jsonb in the normal function context */
1574 
1575  val = PG_ARGISNULL(1) ? (Datum) 0 : PG_GETARG_DATUM(1);
1576 
1577  memset(&elem, 0, sizeof(JsonbInState));
1578 
1579  datum_to_jsonb(val, PG_ARGISNULL(1), &elem, state->val_category,
1580  state->val_output_func, false);
1581 
1582  jbelem = JsonbValueToJsonb(elem.res);
1583 
1584  /* switch to the aggregate context for accumulation operations */
1585 
1586  oldcontext = MemoryContextSwitchTo(aggcontext);
1587 
1588  it = JsonbIteratorInit(&jbelem->root);
1589 
1590  while ((type = JsonbIteratorNext(&it, &v, false)) != WJB_DONE)
1591  {
1592  switch (type)
1593  {
1594  case WJB_BEGIN_ARRAY:
1595  if (v.val.array.rawScalar)
1596  single_scalar = true;
1597  else
1598  result->res = pushJsonbValue(&result->parseState,
1599  type, NULL);
1600  break;
1601  case WJB_END_ARRAY:
1602  if (!single_scalar)
1603  result->res = pushJsonbValue(&result->parseState,
1604  type, NULL);
1605  break;
1606  case WJB_BEGIN_OBJECT:
1607  case WJB_END_OBJECT:
1608  result->res = pushJsonbValue(&result->parseState,
1609  type, NULL);
1610  break;
1611  case WJB_ELEM:
1612  case WJB_KEY:
1613  case WJB_VALUE:
1614  if (v.type == jbvString)
1615  {
1616  /* copy string values in the aggregate context */
1617  char *buf = palloc(v.val.string.len + 1);
1618 
1619  snprintf(buf, v.val.string.len + 1, "%s", v.val.string.val);
1620  v.val.string.val = buf;
1621  }
1622  else if (v.type == jbvNumeric)
1623  {
1624  /* same for numeric */
1625  v.val.numeric =
1627  NumericGetDatum(v.val.numeric)));
1628  }
1629  result->res = pushJsonbValue(&result->parseState,
1630  type, &v);
1631  break;
1632  default:
1633  elog(ERROR, "unknown jsonb iterator token type");
1634  }
1635  }
1636 
1637  MemoryContextSwitchTo(oldcontext);
1638 
1640 }
Datum numeric_uplus(PG_FUNCTION_ARGS)
Definition: numeric.c:1452
Oid get_fn_expr_argtype(FmgrInfo *flinfo, int argnum)
Definition: fmgr.c:1897
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:642
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:268
void * palloc0(Size size)
Definition: mcxt.c:1241
static Datum NumericGetDatum(Numeric X)
Definition: numeric.h:72
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:138
static char * buf
Definition: pg_test_fsync.c:67
#define snprintf
Definition: port.h:238

References AggCheckCallContext(), buf, datum_to_jsonb(), DatumGetNumeric(), DirectFunctionCall1, elog(), ereport, errcode(), errmsg(), ERROR, get_fn_expr_argtype(), InvalidOid, jbvNumeric, jbvString, jsonb_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, generate_unaccent_rules::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.

◆ jsonb_bool()

Datum jsonb_bool ( PG_FUNCTION_ARGS  )

Definition at line 1983 of file jsonb.c.

1984 {
1985  Jsonb *in = PG_GETARG_JSONB_P(0);
1986  JsonbValue v;
1987 
1988  if (!JsonbExtractScalar(&in->root, &v) || v.type != jbvBool)
1989  cannotCastJsonbValue(v.type, "boolean");
1990 
1991  PG_FREE_IF_COPY(in, 0);
1992 
1993  PG_RETURN_BOOL(v.val.boolean);
1994 }
#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:1953
bool JsonbExtractScalar(JsonbContainer *jbc, JsonbValue *res)
Definition: jsonb.c:1913
#define PG_GETARG_JSONB_P(x)
Definition: jsonb.h:389

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 1249 of file jsonb.c.

1250 {
1251  int nargs;
1252  int i;
1253  JsonbInState result;
1254  Datum *args;
1255  bool *nulls;
1256  Oid *types;
1257 
1258  /* build argument values to build the array */
1259  nargs = extract_variadic_args(fcinfo, 0, true, &args, &types, &nulls);
1260 
1261  if (nargs < 0)
1262  PG_RETURN_NULL();
1263 
1264  memset(&result, 0, sizeof(JsonbInState));
1265 
1266  result.res = pushJsonbValue(&result.parseState, WJB_BEGIN_ARRAY, NULL);
1267 
1268  for (i = 0; i < nargs; i++)
1269  add_jsonb(args[i], nulls[i], &result, types[i], false);
1270 
1271  result.res = pushJsonbValue(&result.parseState, WJB_END_ARRAY, NULL);
1272 
1274 }
struct typedefs * types
Definition: ecpg.c:29
int extract_variadic_args(FunctionCallInfo fcinfo, int variadic_start, bool convert_unknown, Datum **args, Oid **types, bool **nulls)
Definition: funcapi.c:2006
static void add_jsonb(Datum val, bool is_null, JsonbInState *result, Oid val_type, bool key_scalar)
Definition: jsonb.c:1129

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

◆ jsonb_build_array_noargs()

Datum jsonb_build_array_noargs ( PG_FUNCTION_ARGS  )

Definition at line 1280 of file jsonb.c.

1281 {
1282  JsonbInState result;
1283 
1284  memset(&result, 0, sizeof(JsonbInState));
1285 
1286  (void) pushJsonbValue(&result.parseState, WJB_BEGIN_ARRAY, NULL);
1287  result.res = pushJsonbValue(&result.parseState, WJB_END_ARRAY, NULL);
1288 
1290 }

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

◆ jsonb_build_object()

Datum jsonb_build_object ( PG_FUNCTION_ARGS  )

Definition at line 1183 of file jsonb.c.

1184 {
1185  int nargs;
1186  int i;
1187  JsonbInState result;
1188  Datum *args;
1189  bool *nulls;
1190  Oid *types;
1191 
1192  /* build argument values to build the object */
1193  nargs = extract_variadic_args(fcinfo, 0, true, &args, &types, &nulls);
1194 
1195  if (nargs < 0)
1196  PG_RETURN_NULL();
1197 
1198  if (nargs % 2 != 0)
1199  ereport(ERROR,
1200  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1201  errmsg("argument list must have even number of elements"),
1202  /* translator: %s is a SQL function name */
1203  errhint("The arguments of %s must consist of alternating keys and values.",
1204  "jsonb_build_object()")));
1205 
1206  memset(&result, 0, sizeof(JsonbInState));
1207 
1208  result.res = pushJsonbValue(&result.parseState, WJB_BEGIN_OBJECT, NULL);
1209 
1210  for (i = 0; i < nargs; i += 2)
1211  {
1212  /* process key */
1213  if (nulls[i])
1214  ereport(ERROR,
1215  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1216  errmsg("argument %d: key must not be null", i + 1)));
1217 
1218  add_jsonb(args[i], false, &result, types[i], true);
1219 
1220  /* process value */
1221  add_jsonb(args[i + 1], nulls[i + 1], &result, types[i + 1], false);
1222  }
1223 
1224  result.res = pushJsonbValue(&result.parseState, WJB_END_OBJECT, NULL);
1225 
1227 }
int errhint(const char *fmt,...)
Definition: elog.c:1316

References add_jsonb(), generate_unaccent_rules::args, ereport, errcode(), errhint(), errmsg(), ERROR, extract_variadic_args(), i, JsonbValueToJsonb(), JsonbInState::parseState, PG_RETURN_NULL, PG_RETURN_POINTER, pushJsonbValue(), JsonbInState::res, types, WJB_BEGIN_OBJECT, and WJB_END_OBJECT.

◆ jsonb_build_object_noargs()

Datum jsonb_build_object_noargs ( PG_FUNCTION_ARGS  )

Definition at line 1233 of file jsonb.c.

1234 {
1235  JsonbInState result;
1236 
1237  memset(&result, 0, sizeof(JsonbInState));
1238 
1239  (void) pushJsonbValue(&result.parseState, WJB_BEGIN_OBJECT, NULL);
1240  result.res = pushJsonbValue(&result.parseState, WJB_END_OBJECT, NULL);
1241 
1243 }

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

◆ jsonb_categorize_type()

static void jsonb_categorize_type ( Oid  typoid,
JsonbTypeCategory tcategory,
Oid outfuncoid 
)
static

Definition at line 643 of file jsonb.c.

646 {
647  bool typisvarlena;
648 
649  /* Look through any domain */
650  typoid = getBaseType(typoid);
651 
652  *outfuncoid = InvalidOid;
653 
654  /*
655  * We need to get the output function for everything except date and
656  * timestamp types, booleans, array and composite types, json and jsonb,
657  * and non-builtin types where there's a cast to json. In this last case
658  * we return the oid of the cast function instead.
659  */
660 
661  switch (typoid)
662  {
663  case BOOLOID:
664  *tcategory = JSONBTYPE_BOOL;
665  break;
666 
667  case INT2OID:
668  case INT4OID:
669  case INT8OID:
670  case FLOAT4OID:
671  case FLOAT8OID:
672  case NUMERICOID:
673  getTypeOutputInfo(typoid, outfuncoid, &typisvarlena);
674  *tcategory = JSONBTYPE_NUMERIC;
675  break;
676 
677  case DATEOID:
678  *tcategory = JSONBTYPE_DATE;
679  break;
680 
681  case TIMESTAMPOID:
682  *tcategory = JSONBTYPE_TIMESTAMP;
683  break;
684 
685  case TIMESTAMPTZOID:
686  *tcategory = JSONBTYPE_TIMESTAMPTZ;
687  break;
688 
689  case JSONBOID:
690  *tcategory = JSONBTYPE_JSONB;
691  break;
692 
693  case JSONOID:
694  *tcategory = JSONBTYPE_JSON;
695  break;
696 
697  default:
698  /* Check for arrays and composites */
699  if (OidIsValid(get_element_type(typoid)) || typoid == ANYARRAYOID
700  || typoid == ANYCOMPATIBLEARRAYOID || typoid == RECORDARRAYOID)
701  *tcategory = JSONBTYPE_ARRAY;
702  else if (type_is_rowtype(typoid)) /* includes RECORDOID */
703  *tcategory = JSONBTYPE_COMPOSITE;
704  else
705  {
706  /* It's probably the general case ... */
707  *tcategory = JSONBTYPE_OTHER;
708 
709  /*
710  * but first let's look for a cast to json (note: not to
711  * jsonb) if it's not built-in.
712  */
713  if (typoid >= FirstNormalObjectId)
714  {
715  Oid castfunc;
716  CoercionPathType ctype;
717 
718  ctype = find_coercion_pathway(JSONOID, typoid,
719  COERCION_EXPLICIT, &castfunc);
720  if (ctype == COERCION_PATH_FUNC && OidIsValid(castfunc))
721  {
722  *tcategory = JSONBTYPE_JSONCAST;
723  *outfuncoid = castfunc;
724  }
725  else
726  {
727  /* not a cast type, so just get the usual output func */
728  getTypeOutputInfo(typoid, outfuncoid, &typisvarlena);
729  }
730  }
731  else
732  {
733  /* any other builtin type */
734  getTypeOutputInfo(typoid, outfuncoid, &typisvarlena);
735  }
736  break;
737  }
738  }
739 }
#define OidIsValid(objectId)
Definition: c.h:759
Oid get_element_type(Oid typid)
Definition: lsyscache.c:2717
bool type_is_rowtype(Oid typid)
Definition: lsyscache.c:2613
void getTypeOutputInfo(Oid type, Oid *typOutput, bool *typIsVarlena)
Definition: lsyscache.c:2865
Oid getBaseType(Oid typid)
Definition: lsyscache.c:2479
CoercionPathType find_coercion_pathway(Oid targetTypeId, Oid sourceTypeId, CoercionContext ccontext, Oid *funcid)
CoercionPathType
Definition: parse_coerce.h:25
@ COERCION_PATH_FUNC
Definition: parse_coerce.h:27
@ COERCION_EXPLICIT
Definition: primnodes.h:644
#define FirstNormalObjectId
Definition: transam.h:197

References COERCION_EXPLICIT, COERCION_PATH_FUNC, find_coercion_pathway(), FirstNormalObjectId, get_element_type(), getBaseType(), getTypeOutputInfo(), InvalidOid, JSONBTYPE_ARRAY, JSONBTYPE_BOOL, JSONBTYPE_COMPOSITE, JSONBTYPE_DATE, JSONBTYPE_JSON, JSONBTYPE_JSONB, JSONBTYPE_JSONCAST, JSONBTYPE_NUMERIC, JSONBTYPE_OTHER, JSONBTYPE_TIMESTAMP, JSONBTYPE_TIMESTAMPTZ, OidIsValid, and type_is_rowtype().

Referenced by add_jsonb(), array_to_jsonb_internal(), composite_to_jsonb(), jsonb_agg_transfn(), jsonb_object_agg_transfn(), and to_jsonb().

◆ jsonb_float4()

Datum jsonb_float4 ( PG_FUNCTION_ARGS  )

Definition at line 2072 of file jsonb.c.

2073 {
2074  Jsonb *in = PG_GETARG_JSONB_P(0);
2075  JsonbValue v;
2076  Datum retValue;
2077 
2078  if (!JsonbExtractScalar(&in->root, &v) || v.type != jbvNumeric)
2079  cannotCastJsonbValue(v.type, "real");
2080 
2082  NumericGetDatum(v.val.numeric));
2083 
2084  PG_FREE_IF_COPY(in, 0);
2085 
2086  PG_RETURN_DATUM(retValue);
2087 }
Datum numeric_float4(PG_FUNCTION_ARGS)
Definition: numeric.c:4633
#define PG_RETURN_DATUM(x)
Definition: fmgr.h:353

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 2090 of file jsonb.c.

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

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,
Node escontext 
)
inlinestatic

Definition at line 260 of file jsonb.c.

261 {
262  JsonLexContext *lex;
264  JsonSemAction sem;
265 
266  memset(&state, 0, sizeof(state));
267  memset(&sem, 0, sizeof(sem));
269 
270  state.escontext = escontext;
271  sem.semstate = (void *) &state;
272 
277  sem.scalar = jsonb_in_scalar;
279 
280  if (!pg_parse_json_or_errsave(lex, &sem, escontext))
281  return (Datum) 0;
282 
283  /* after parsing, the item member has the composed jsonb structure */
285 }
JsonLexContext * makeJsonLexContextCstringLen(char *json, int len, int encoding, bool need_escapes)
Definition: jsonapi.c:145
bool pg_parse_json_or_errsave(JsonLexContext *lex, JsonSemAction *sem, Node *escontext)
Definition: jsonfuncs.c:507
int GetDatabaseEncoding(void)
Definition: mbutils.c:1268

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, and JsonSemAction::semstate.

Referenced by jsonb_in(), and jsonb_recv().

◆ jsonb_in()

Datum jsonb_in ( PG_FUNCTION_ARGS  )

Definition at line 98 of file jsonb.c.

99 {
100  char *json = PG_GETARG_CSTRING(0);
101 
102  return jsonb_from_cstring(json, strlen(json), fcinfo->context);
103 }
#define PG_GETARG_CSTRING(n)
Definition: fmgr.h:277
static Datum jsonb_from_cstring(char *json, int len, Node *escontext)
Definition: jsonb.c:260

References jsonb_from_cstring(), and PG_GETARG_CSTRING.

Referenced by jsonb_set_lax().

◆ jsonb_in_array_end()

static JsonParseErrorType jsonb_in_array_end ( void *  pstate)
static

Definition at line 331 of file jsonb.c.

332 {
333  JsonbInState *_state = (JsonbInState *) pstate;
334 
335  _state->res = pushJsonbValue(&_state->parseState, WJB_END_ARRAY, NULL);
336 
337  return JSON_SUCCESS;
338 }
@ JSON_SUCCESS
Definition: jsonapi.h:38

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

Referenced by datum_to_jsonb(), and jsonb_from_cstring().

◆ jsonb_in_array_start()

static JsonParseErrorType jsonb_in_array_start ( 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_BEGIN_ARRAY, NULL);
326 
327  return JSON_SUCCESS;
328 }

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

Referenced by datum_to_jsonb(), and jsonb_from_cstring().

◆ jsonb_in_object_end()

static JsonParseErrorType jsonb_in_object_end ( 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_END_OBJECT, NULL);
316 
317  return JSON_SUCCESS;
318 }

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

Referenced by datum_to_jsonb(), 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 341 of file jsonb.c.

342 {
343  JsonbInState *_state = (JsonbInState *) pstate;
344  JsonbValue v;
345 
346  Assert(fname != NULL);
347  v.type = jbvString;
348  v.val.string.len = strlen(fname);
349  if (!checkStringLen(v.val.string.len, _state->escontext))
350  return JSON_SEM_ACTION_FAILED;
351  v.val.string.val = fname;
352 
353  _state->res = pushJsonbValue(&_state->parseState, WJB_KEY, &v);
354 
355  return JSON_SUCCESS;
356 }
@ JSON_SEM_ACTION_FAILED
Definition: jsonapi.h:57
Node * escontext
Definition: jsonb.c:36

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(), and jsonb_from_cstring().

◆ jsonb_in_object_start()

static JsonParseErrorType jsonb_in_object_start ( 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_BEGIN_OBJECT, NULL);
306 
307  return JSON_SUCCESS;
308 }

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

Referenced by datum_to_jsonb(), and jsonb_from_cstring().

◆ jsonb_in_scalar()

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

Definition at line 389 of file jsonb.c.

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

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(), and jsonb_from_cstring().

◆ jsonb_int2()

Datum jsonb_int2 ( PG_FUNCTION_ARGS  )

Definition at line 2018 of file jsonb.c.

2019 {
2020  Jsonb *in = PG_GETARG_JSONB_P(0);
2021  JsonbValue v;
2022  Datum retValue;
2023 
2024  if (!JsonbExtractScalar(&in->root, &v) || v.type != jbvNumeric)
2025  cannotCastJsonbValue(v.type, "smallint");
2026 
2027  retValue = DirectFunctionCall1(numeric_int2,
2028  NumericGetDatum(v.val.numeric));
2029 
2030  PG_FREE_IF_COPY(in, 0);
2031 
2032  PG_RETURN_DATUM(retValue);
2033 }
Datum numeric_int2(PG_FUNCTION_ARGS)
Definition: numeric.c:4464

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 2036 of file jsonb.c.

2037 {
2038  Jsonb *in = PG_GETARG_JSONB_P(0);
2039  JsonbValue v;
2040  Datum retValue;
2041 
2042  if (!JsonbExtractScalar(&in->root, &v) || v.type != jbvNumeric)
2043  cannotCastJsonbValue(v.type, "integer");
2044 
2045  retValue = DirectFunctionCall1(numeric_int4,
2046  NumericGetDatum(v.val.numeric));
2047 
2048  PG_FREE_IF_COPY(in, 0);
2049 
2050  PG_RETURN_DATUM(retValue);
2051 }
Datum numeric_int4(PG_FUNCTION_ARGS)
Definition: numeric.c:4385

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 2054 of file jsonb.c.

2055 {
2056  Jsonb *in = PG_GETARG_JSONB_P(0);
2057  JsonbValue v;
2058  Datum retValue;
2059 
2060  if (!JsonbExtractScalar(&in->root, &v) || v.type != jbvNumeric)
2061  cannotCastJsonbValue(v.type, "bigint");
2062 
2063  retValue = DirectFunctionCall1(numeric_int8,
2064  NumericGetDatum(v.val.numeric));
2065 
2066  PG_FREE_IF_COPY(in, 0);
2067 
2068  PG_RETURN_DATUM(retValue);
2069 }
Datum numeric_int8(PG_FUNCTION_ARGS)
Definition: numeric.c:4424

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 1997 of file jsonb.c.

1998 {
1999  Jsonb *in = PG_GETARG_JSONB_P(0);
2000  JsonbValue v;
2001  Numeric retValue;
2002 
2003  if (!JsonbExtractScalar(&in->root, &v) || v.type != jbvNumeric)
2004  cannotCastJsonbValue(v.type, "numeric");
2005 
2006  /*
2007  * v.val.numeric points into jsonb body, so we need to make a copy to
2008  * return
2009  */
2010  retValue = DatumGetNumericCopy(NumericGetDatum(v.val.numeric));
2011 
2012  PG_FREE_IF_COPY(in, 0);
2013 
2014  PG_RETURN_NUMERIC(retValue);
2015 }
static Numeric DatumGetNumericCopy(Datum X)
Definition: numeric.h:66
#define PG_RETURN_NUMERIC(x)
Definition: numeric.h:79

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 1301 of file jsonb.c.

1302 {
1303  ArrayType *in_array = PG_GETARG_ARRAYTYPE_P(0);
1304  int ndims = ARR_NDIM(in_array);
1305  Datum *in_datums;
1306  bool *in_nulls;
1307  int in_count,
1308  count,
1309  i;
1310  JsonbInState result;
1311 
1312  memset(&result, 0, sizeof(JsonbInState));
1313 
1314  (void) pushJsonbValue(&result.parseState, WJB_BEGIN_OBJECT, NULL);
1315 
1316  switch (ndims)
1317  {
1318  case 0:
1319  goto close_object;
1320  break;
1321 
1322  case 1:
1323  if ((ARR_DIMS(in_array)[0]) % 2)
1324  ereport(ERROR,
1325  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
1326  errmsg("array must have even number of elements")));
1327  break;
1328 
1329  case 2:
1330  if ((ARR_DIMS(in_array)[1]) != 2)
1331  ereport(ERROR,
1332  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
1333  errmsg("array must have two columns")));
1334  break;
1335 
1336  default:
1337  ereport(ERROR,
1338  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
1339  errmsg("wrong number of array subscripts")));
1340  }
1341 
1342  deconstruct_array_builtin(in_array, TEXTOID, &in_datums, &in_nulls, &in_count);
1343 
1344  count = in_count / 2;
1345 
1346  for (i = 0; i < count; ++i)
1347  {
1348  JsonbValue v;
1349  char *str;
1350  int len;
1351 
1352  if (in_nulls[i * 2])
1353  ereport(ERROR,
1354  (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
1355  errmsg("null value not allowed for object key")));
1356 
1357  str = TextDatumGetCString(in_datums[i * 2]);
1358  len = strlen(str);
1359 
1360  v.type = jbvString;
1361 
1362  v.val.string.len = len;
1363  v.val.string.val = str;
1364 
1365  (void) pushJsonbValue(&result.parseState, WJB_KEY, &v);
1366 
1367  if (in_nulls[i * 2 + 1])
1368  {
1369  v.type = jbvNull;
1370  }
1371  else
1372  {
1373  str = TextDatumGetCString(in_datums[i * 2 + 1]);
1374  len = strlen(str);
1375 
1376  v.type = jbvString;
1377 
1378  v.val.string.len = len;
1379  v.val.string.val = str;
1380  }
1381 
1382  (void) pushJsonbValue(&result.parseState, WJB_VALUE, &v);
1383  }
1384 
1385  pfree(in_datums);
1386  pfree(in_nulls);
1387 
1388 close_object:
1389  result.res = pushJsonbValue(&result.parseState, WJB_END_OBJECT, NULL);
1390 
1392 }
#define PG_GETARG_ARRAYTYPE_P(n)
Definition: array.h:256
void deconstruct_array_builtin(ArrayType *array, Oid elmtype, Datum **elemsp, bool **nullsp, int *nelemsp)
Definition: arrayfuncs.c:3668
#define TextDatumGetCString(d)
Definition: builtins.h:95

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, generate_unaccent_rules::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 1875 of file jsonb.c.

1876 {
1877  JsonbAggState *arg;
1878  JsonbInState result;
1879  Jsonb *out;
1880 
1881  /* cannot be called directly because of internal-type argument */
1882  Assert(AggCheckCallContext(fcinfo, NULL));
1883 
1884  if (PG_ARGISNULL(0))
1885  PG_RETURN_NULL(); /* returns null iff no input values */
1886 
1888 
1889  /*
1890  * We need to do a shallow clone of the argument's res field in case the
1891  * final function is called more than once, so we avoid changing the
1892  * aggregate state value. A shallow clone is sufficient as we aren't
1893  * going to change any of the values, just add the final object end
1894  * marker.
1895  */
1896  memset(&result, 0, sizeof(JsonbInState));
1897 
1898  result.parseState = clone_parse_state(arg->res->parseState);
1899 
1900  result.res = pushJsonbValue(&result.parseState,
1901  WJB_END_OBJECT, NULL);
1902 
1903  out = JsonbValueToJsonb(result.res);
1904 
1905  PG_RETURN_POINTER(out);
1906 }

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_transfn()

Datum jsonb_object_agg_transfn ( PG_FUNCTION_ARGS  )

Definition at line 1679 of file jsonb.c.

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

References AggCheckCallContext(), buf, datum_to_jsonb(), DatumGetNumeric(), DirectFunctionCall1, elog(), ereport, errcode(), errmsg(), ERROR, get_fn_expr_argtype(), InvalidOid, jbvNumeric, jbvString, jsonb_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, generate_unaccent_rules::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.

◆ jsonb_object_two_arg()

Datum jsonb_object_two_arg ( PG_FUNCTION_ARGS  )

Definition at line 1401 of file jsonb.c.

1402 {
1403  ArrayType *key_array = PG_GETARG_ARRAYTYPE_P(0);
1404  ArrayType *val_array = PG_GETARG_ARRAYTYPE_P(1);
1405  int nkdims = ARR_NDIM(key_array);
1406  int nvdims = ARR_NDIM(val_array);
1407  Datum *key_datums,
1408  *val_datums;
1409  bool *key_nulls,
1410  *val_nulls;
1411  int key_count,
1412  val_count,
1413  i;
1414  JsonbInState result;
1415 
1416  memset(&result, 0, sizeof(JsonbInState));
1417 
1418  (void) pushJsonbValue(&result.parseState, WJB_BEGIN_OBJECT, NULL);
1419 
1420  if (nkdims > 1 || nkdims != nvdims)
1421  ereport(ERROR,
1422  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
1423  errmsg("wrong number of array subscripts")));
1424 
1425  if (nkdims == 0)
1426  goto close_object;
1427 
1428  deconstruct_array_builtin(key_array, TEXTOID, &key_datums, &key_nulls, &key_count);
1429  deconstruct_array_builtin(val_array, TEXTOID, &val_datums, &val_nulls, &val_count);
1430 
1431  if (key_count != val_count)
1432  ereport(ERROR,
1433  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
1434  errmsg("mismatched array dimensions")));
1435 
1436  for (i = 0; i < key_count; ++i)
1437  {
1438  JsonbValue v;
1439  char *str;
1440  int len;
1441 
1442  if (key_nulls[i])
1443  ereport(ERROR,
1444  (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
1445  errmsg("null value not allowed for object key")));
1446 
1447  str = TextDatumGetCString(key_datums[i]);
1448  len = strlen(str);
1449 
1450  v.type = jbvString;
1451 
1452  v.val.string.len = len;
1453  v.val.string.val = str;
1454 
1455  (void) pushJsonbValue(&result.parseState, WJB_KEY, &v);
1456 
1457  if (val_nulls[i])
1458  {
1459  v.type = jbvNull;
1460  }
1461  else
1462  {
1463  str = TextDatumGetCString(val_datums[i]);
1464  len = strlen(str);
1465 
1466  v.type = jbvString;
1467 
1468  v.val.string.len = len;
1469  v.val.string.val = str;
1470  }
1471 
1472  (void) pushJsonbValue(&result.parseState, WJB_VALUE, &v);
1473  }
1474 
1475  pfree(key_datums);
1476  pfree(key_nulls);
1477  pfree(val_datums);
1478  pfree(val_nulls);
1479 
1480 close_object:
1481  result.res = pushJsonbValue(&result.parseState, WJB_END_OBJECT, NULL);
1482 
1484 }

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, generate_unaccent_rules::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 133 of file jsonb.c.

134 {
135  Jsonb *jb = PG_GETARG_JSONB_P(0);
136  char *out;
137 
138  out = JsonbToCString(NULL, &jb->root, VARSIZE(jb));
139 
140  PG_RETURN_CSTRING(out);
141 }
#define PG_RETURN_CSTRING(x)
Definition: fmgr.h:362
char * JsonbToCString(StringInfo out, JsonbContainer *in, int estimated_len)
Definition: jsonb.c:483
#define VARSIZE(PTR)
Definition: varatt.h:279

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

◆ jsonb_put_escaped_value()

static void jsonb_put_escaped_value ( StringInfo  out,
JsonbValue scalarVal 
)
static

Definition at line 359 of file jsonb.c.

360 {
361  switch (scalarVal->type)
362  {
363  case jbvNull:
364  appendBinaryStringInfo(out, "null", 4);
365  break;
366  case jbvString:
367  escape_json(out, pnstrdup(scalarVal->val.string.val, scalarVal->val.string.len));
368  break;
369  case jbvNumeric:
372  PointerGetDatum(scalarVal->val.numeric))));
373  break;
374  case jbvBool:
375  if (scalarVal->val.boolean)
376  appendBinaryStringInfo(out, "true", 4);
377  else
378  appendBinaryStringInfo(out, "false", 5);
379  break;
380  default:
381  elog(ERROR, "unknown jsonb scalar type");
382  }
383 }
Datum numeric_out(PG_FUNCTION_ARGS)
Definition: numeric.c:806
void escape_json(StringInfo buf, const char *str)
Definition: json.c:1272
char * pnstrdup(const char *in, Size len)
Definition: mcxt.c:1635
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:227
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:176

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

Referenced by JsonbToCStringWorker().

◆ jsonb_recv()

Datum jsonb_recv ( PG_FUNCTION_ARGS  )

Definition at line 114 of file jsonb.c.

115 {
117  int version = pq_getmsgint(buf, 1);
118  char *str;
119  int nbytes;
120 
121  if (version == 1)
122  str = pq_getmsgtext(buf, buf->len - buf->cursor, &nbytes);
123  else
124  elog(ERROR, "unsupported jsonb version number %d", version);
125 
126  return jsonb_from_cstring(str, nbytes, NULL);
127 }
unsigned int pq_getmsgint(StringInfo msg, int b)
Definition: pqformat.c:418
char * pq_getmsgtext(StringInfo msg, int rawbytes, int *nbytes)
Definition: pqformat.c:549
StringInfoData * StringInfo
Definition: stringinfo.h:44

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

◆ jsonb_send()

Datum jsonb_send ( PG_FUNCTION_ARGS  )

Definition at line 149 of file jsonb.c.

150 {
151  Jsonb *jb = PG_GETARG_JSONB_P(0);
153  StringInfo jtext = makeStringInfo();
154  int version = 1;
155 
156  (void) JsonbToCString(jtext, &jb->root, VARSIZE(jb));
157 
159  pq_sendint8(&buf, version);
160  pq_sendtext(&buf, jtext->data, jtext->len);
161  pfree(jtext->data);
162  pfree(jtext);
163 
165 }
#define PG_RETURN_BYTEA_P(x)
Definition: fmgr.h:371
void pq_sendtext(StringInfo buf, const char *str, int slen)
Definition: pqformat.c:175
void pq_begintypsend(StringInfo buf)
Definition: pqformat.c:329
bytea * pq_endtypsend(StringInfo buf)
Definition: pqformat.c:349
static void pq_sendint8(StringInfo buf, uint8 i)
Definition: pqformat.h:129
StringInfo makeStringInfo(void)
Definition: stringinfo.c:41

References buf, StringInfoData::data, JsonbToCString(), StringInfoData::len, makeStringInfo(), pfree(), 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 241 of file jsonb.c.

242 {
243  Jsonb *in = PG_GETARG_JSONB_P(0);
244  const char *result = JsonbContainerTypeName(&in->root);
245 
247 }
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:372
static const char * JsonbContainerTypeName(JsonbContainer *jbc)
Definition: jsonb.c:171
text * cstring_to_text(const char *s)
Definition: varlena.c:182

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 171 of file jsonb.c.

172 {
173  JsonbValue scalar;
174 
175  if (JsonbExtractScalar(jbc, &scalar))
176  return JsonbTypeName(&scalar);
177  else if (JsonContainerIsArray(jbc))
178  return "array";
179  else if (JsonContainerIsObject(jbc))
180  return "object";
181  else
182  {
183  elog(ERROR, "invalid jsonb container type: 0x%08x", jbc->header);
184  return "unknown";
185  }
186 }
const char * JsonbTypeName(JsonbValue *val)
Definition: jsonb.c:192
#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 1913 of file jsonb.c.

1914 {
1915  JsonbIterator *it;
1917  JsonbValue tmp;
1918 
1919  if (!JsonContainerIsArray(jbc) || !JsonContainerIsScalar(jbc))
1920  {
1921  /* inform caller about actual type of container */
1922  res->type = (JsonContainerIsArray(jbc)) ? jbvArray : jbvObject;
1923  return false;
1924  }
1925 
1926  /*
1927  * A root scalar is stored as an array of one element, so we get the array
1928  * and then its first (and only) member.
1929  */
1930  it = JsonbIteratorInit(jbc);
1931 
1932  tok = JsonbIteratorNext(&it, &tmp, true);
1933  Assert(tok == WJB_BEGIN_ARRAY);
1934  Assert(tmp.val.array.nElems == 1 && tmp.val.array.rawScalar);
1935 
1936  tok = JsonbIteratorNext(&it, res, true);
1937  Assert(tok == WJB_ELEM);
1939 
1940  tok = JsonbIteratorNext(&it, &tmp, true);
1941  Assert(tok == WJB_END_ARRAY);
1942 
1943  tok = JsonbIteratorNext(&it, &tmp, true);
1944  Assert(tok == WJB_DONE);
1945 
1946  return true;
1947 }
#define PG_USED_FOR_ASSERTS_ONLY
Definition: c.h:166
#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(), and JsonbContainerTypeName().

◆ JsonbToCString()

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

Definition at line 483 of file jsonb.c.

484 {
485  return JsonbToCStringWorker(out, in, estimated_len, false);
486 }
static char * JsonbToCStringWorker(StringInfo out, JsonbContainer *in, int estimated_len, bool indent)
Definition: jsonb.c:501

References JsonbToCStringWorker().

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

◆ JsonbToCStringIndent()

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

Definition at line 492 of file jsonb.c.

493 {
494  return JsonbToCStringWorker(out, in, estimated_len, true);
495 }

References JsonbToCStringWorker().

Referenced by jsonb_pretty().

◆ JsonbToCStringWorker()

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

Definition at line 501 of file jsonb.c.

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

References add_indent(), appendBinaryStringInfo(), appendStringInfoCharMacro, Assert(), StringInfoData::data, elog(), enlargeStringInfo(), ERROR, jsonb_put_escaped_value(), JsonbIteratorInit(), JsonbIteratorNext(), makeStringInfo(), generate_unaccent_rules::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 192 of file jsonb.c.

193 {
194  switch (val->type)
195  {
196  case jbvBinary:
197  return JsonbContainerTypeName(val->val.binary.data);
198  case jbvObject:
199  return "object";
200  case jbvArray:
201  return "array";
202  case jbvNumeric:
203  return "number";
204  case jbvString:
205  return "string";
206  case jbvBool:
207  return "boolean";
208  case jbvNull:
209  return "null";
210  case jbvDatetime:
211  switch (val->val.datetime.typid)
212  {
213  case DATEOID:
214  return "date";
215  case TIMEOID:
216  return "time without time zone";
217  case TIMETZOID:
218  return "time with time zone";
219  case TIMESTAMPOID:
220  return "timestamp without time zone";
221  case TIMESTAMPTZOID:
222  return "timestamp with time zone";
223  default:
224  elog(ERROR, "unrecognized jsonb value datetime type: %d",
225  val->val.datetime.typid);
226  }
227  return "unknown";
228  default:
229  elog(ERROR, "unrecognized jsonb value type: %d", val->type);
230  return "unknown";
231  }
232 }
@ jbvDatetime
Definition: jsonb.h:244

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

Referenced by executeItemOptUnwrapTarget(), and JsonbContainerTypeName().

◆ to_jsonb()

Datum to_jsonb ( PG_FUNCTION_ARGS  )

Definition at line 1156 of file jsonb.c.

1157 {
1158  Datum val = PG_GETARG_DATUM(0);
1159  Oid val_type = get_fn_expr_argtype(fcinfo->flinfo, 0);
1160  JsonbInState result;
1161  JsonbTypeCategory tcategory;
1162  Oid outfuncoid;
1163 
1164  if (val_type == InvalidOid)
1165  ereport(ERROR,
1166  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1167  errmsg("could not determine input data type")));
1168 
1169  jsonb_categorize_type(val_type,
1170  &tcategory, &outfuncoid);
1171 
1172  memset(&result, 0, sizeof(JsonbInState));
1173 
1174  datum_to_jsonb(val, false, &result, tcategory, outfuncoid, false);
1175 
1177 }

References datum_to_jsonb(), ereport, errcode(), errmsg(), ERROR, get_fn_expr_argtype(), InvalidOid, jsonb_categorize_type(), JsonbValueToJsonb(), PG_GETARG_DATUM, PG_RETURN_POINTER, JsonbInState::res, and val.