PostgreSQL Source Code  git master
jsonb.c File Reference
#include "postgres.h"
#include "access/htup_details.h"
#include "access/transam.h"
#include "catalog/pg_proc.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
 

Functions

static Datum jsonb_from_cstring (char *json, int len, bool unique_keys)
 
static size_t checkStringLen (size_t len)
 
static void jsonb_in_object_start (void *pstate)
 
static void jsonb_in_object_end (void *pstate)
 
static void jsonb_in_array_start (void *pstate)
 
static void jsonb_in_array_end (void *pstate)
 
static void jsonb_in_object_field_start (void *pstate, char *fname, bool isnull)
 
static void jsonb_put_escaped_value (StringInfo out, JsonbValue *scalarVal)
 
static void 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, 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)
 
Datum jsonb_from_text (text *js, bool unique_keys)
 
static const char * JsonbContainerTypeName (JsonbContainer *jbc)
 
const char * JsonbTypeName (JsonbValue *jbv)
 
Datum jsonb_typeof (PG_FUNCTION_ARGS)
 
char * JsonbToCString (StringInfo out, JsonbContainer *in, int estimated_len)
 
char * JsonbToCStringIndent (StringInfo out, JsonbContainer *in, int estimated_len)
 
void jsonb_categorize_type (Oid typoid, JsonbTypeCategory *tcategory, Oid *outfuncoid)
 
Datum to_jsonb_worker (Datum val, JsonbTypeCategory tcategory, Oid outfuncoid)
 
bool to_jsonb_is_immutable (Oid typoid)
 
Datum to_jsonb (PG_FUNCTION_ARGS)
 
Datum jsonb_build_object_worker (int nargs, Datum *args, bool *nulls, 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, Datum *args, bool *nulls, 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)
 
JsonbJsonbMakeEmptyArray (void)
 
JsonbJsonbMakeEmptyObject (void)
 
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 592 of file jsonb.c.

593 {
594  if (indent)
595  {
596  int i;
597 
598  appendStringInfoCharMacro(out, '\n');
599  for (i = 0; i < level; i++)
600  appendBinaryStringInfo(out, " ", 4);
601  }
602 }
int i
Definition: isn.c:73
void appendBinaryStringInfo(StringInfo str, const char *data, int datalen)
Definition: stringinfo.c:227
#define appendStringInfoCharMacro(str, ch)
Definition: stringinfo.h:128

References appendBinaryStringInfo(), appendStringInfoCharMacro, and i.

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

1097 {
1098  JsonbTypeCategory tcategory;
1099  Oid outfuncoid;
1100 
1101  if (val_type == InvalidOid)
1102  ereport(ERROR,
1103  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1104  errmsg("could not determine input data type")));
1105 
1106  if (is_null)
1107  {
1108  tcategory = JSONBTYPE_NULL;
1109  outfuncoid = InvalidOid;
1110  }
1111  else
1112  jsonb_categorize_type(val_type,
1113  &tcategory, &outfuncoid);
1114 
1115  datum_to_jsonb(val, is_null, result, tcategory, outfuncoid, key_scalar);
1116 }
int errcode(int sqlerrcode)
Definition: elog.c:693
int errmsg(const char *fmt,...)
Definition: elog.c:904
#define ERROR
Definition: elog.h:33
#define ereport(elevel,...)
Definition: elog.h:143
long val
Definition: informix.c:664
void jsonb_categorize_type(Oid typoid, JsonbTypeCategory *tcategory, Oid *outfuncoid)
Definition: jsonb.c:613
static void datum_to_jsonb(Datum val, bool is_null, JsonbInState *result, JsonbTypeCategory tcategory, Oid outfuncoid, bool key_scalar)
Definition: jsonb.c:721
JsonbTypeCategory
Definition: jsonb.h:381
@ JSONBTYPE_NULL
Definition: jsonb.h:382
#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_worker(), and jsonb_build_object_worker().

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

946 {
947  int i;
948 
949  Assert(dim < ndims);
950 
951  result->res = pushJsonbValue(&result->parseState, WJB_BEGIN_ARRAY, NULL);
952 
953  for (i = 1; i <= dims[dim]; i++)
954  {
955  if (dim + 1 == ndims)
956  {
957  datum_to_jsonb(vals[*valcount], nulls[*valcount], result, tcategory,
958  outfuncoid, false);
959  (*valcount)++;
960  }
961  else
962  {
963  array_dim_to_jsonb(result, dim + 1, ndims, dims, vals, nulls,
964  valcount, tcategory, outfuncoid);
965  }
966  }
967 
968  result->res = pushJsonbValue(&result->parseState, WJB_END_ARRAY, NULL);
969 }
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:943
@ 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:568
Assert(fmt[strlen(fmt) - 1] !='\n')
JsonbParseState * parseState
Definition: jsonb.c:35
JsonbValue * res
Definition: jsonb.c:36

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

976 {
977  ArrayType *v = DatumGetArrayTypeP(array);
978  Oid element_type = ARR_ELEMTYPE(v);
979  int *dim;
980  int ndim;
981  int nitems;
982  int count = 0;
983  Datum *elements;
984  bool *nulls;
985  int16 typlen;
986  bool typbyval;
987  char typalign;
988  JsonbTypeCategory tcategory;
989  Oid outfuncoid;
990 
991  ndim = ARR_NDIM(v);
992  dim = ARR_DIMS(v);
993  nitems = ArrayGetNItems(ndim, dim);
994 
995  if (nitems <= 0)
996  {
997  result->res = pushJsonbValue(&result->parseState, WJB_BEGIN_ARRAY, NULL);
998  result->res = pushJsonbValue(&result->parseState, WJB_END_ARRAY, NULL);
999  return;
1000  }
1001 
1002  get_typlenbyvalalign(element_type,
1003  &typlen, &typbyval, &typalign);
1004 
1005  jsonb_categorize_type(element_type,
1006  &tcategory, &outfuncoid);
1007 
1008  deconstruct_array(v, element_type, typlen, typbyval,
1009  typalign, &elements, &nulls,
1010  &nitems);
1011 
1012  array_dim_to_jsonb(result, 0, ndim, dim, elements, nulls, &count, tcategory,
1013  outfuncoid);
1014 
1015  pfree(elements);
1016  pfree(nulls);
1017 }
#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:3491
int ArrayGetNItems(int ndim, const int *dims)
Definition: arrayutils.c:76
signed short int16
Definition: c.h:428
void get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval, char *typalign)
Definition: lsyscache.c:2228
void pfree(void *pointer)
Definition: mcxt.c:1175
char typalign
Definition: pg_type.h:176
uintptr_t Datum
Definition: postgres.h:411

References ARR_DIMS, ARR_ELEMTYPE, ARR_NDIM, array_dim_to_jsonb(), ArrayGetNItems(), DatumGetArrayTypeP, deconstruct_array(), get_typlenbyvalalign(), jsonb_categorize_type(), 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 2074 of file jsonb.c.

2075 {
2076  static const struct
2077  {
2078  enum jbvType type;
2079  const char *msg;
2080  }
2081  messages[] =
2082  {
2083  {jbvNull, gettext_noop("cannot cast jsonb null to type %s")},
2084  {jbvString, gettext_noop("cannot cast jsonb string to type %s")},
2085  {jbvNumeric, gettext_noop("cannot cast jsonb numeric to type %s")},
2086  {jbvBool, gettext_noop("cannot cast jsonb boolean to type %s")},
2087  {jbvArray, gettext_noop("cannot cast jsonb array to type %s")},
2088  {jbvObject, gettext_noop("cannot cast jsonb object to type %s")},
2089  {jbvBinary, gettext_noop("cannot cast jsonb array or object to type %s")}
2090  };
2091  int i;
2092 
2093  for (i = 0; i < lengthof(messages); i++)
2094  if (messages[i].type == type)
2095  ereport(ERROR,
2096  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2097  errmsg(messages[i].msg, sqltype)));
2098 
2099  /* should be unreachable */
2100  elog(ERROR, "unknown jsonb type: %d", (int) type);
2101 }
#define gettext_noop(x)
Definition: c.h:1194
#define lengthof(array)
Definition: c.h:734
#define elog(elevel,...)
Definition: elog.h:218
jbvType
Definition: jsonb.h:234
@ jbvObject
Definition: jsonb.h:242
@ jbvNumeric
Definition: jsonb.h:238
@ jbvBool
Definition: jsonb.h:239
@ jbvArray
Definition: jsonb.h:241
@ jbvBinary
Definition: jsonb.h:244
@ jbvNull
Definition: jsonb.h:236
@ jbvString
Definition: jsonb.h:237

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 size_t checkStringLen ( size_t  len)
static

Definition at line 271 of file jsonb.c.

272 {
273  if (len > JENTRY_OFFLENMASK)
274  ereport(ERROR,
275  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
276  errmsg("string too long to represent as jsonb string"),
277  errdetail("Due to an implementation restriction, jsonb strings cannot exceed %d bytes.",
279 
280  return len;
281 }
int errdetail(const char *fmt,...)
Definition: elog.c:1037
#define JENTRY_OFFLENMASK
Definition: jsonb.h:146
const void size_t len

References ereport, errcode(), errdetail(), errmsg(), ERROR, 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 1539 of file jsonb.c.

1540 {
1541  JsonbParseState *result,
1542  *icursor,
1543  *ocursor;
1544 
1545  if (state == NULL)
1546  return NULL;
1547 
1548  result = palloc(sizeof(JsonbParseState));
1549  icursor = state;
1550  ocursor = result;
1551  for (;;)
1552  {
1553  ocursor->contVal = icursor->contVal;
1554  ocursor->size = icursor->size;
1555  ocursor->unique_keys = icursor->unique_keys;
1556  ocursor->skip_nulls = icursor->skip_nulls;
1557  icursor = icursor->next;
1558  if (icursor == NULL)
1559  break;
1560  ocursor->next = palloc(sizeof(JsonbParseState));
1561  ocursor = ocursor->next;
1562  }
1563  ocursor->next = NULL;
1564 
1565  return result;
1566 }
void * palloc(Size size)
Definition: mcxt.c:1068
bool unique_keys
Definition: jsonb.h:332
struct JsonbParseState * next
Definition: jsonb.h:331
bool skip_nulls
Definition: jsonb.h:333
JsonbValue contVal
Definition: jsonb.h:329
Definition: regguts.h:318

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

1024 {
1025  HeapTupleHeader td;
1026  Oid tupType;
1027  int32 tupTypmod;
1028  TupleDesc tupdesc;
1029  HeapTupleData tmptup,
1030  *tuple;
1031  int i;
1032 
1033  td = DatumGetHeapTupleHeader(composite);
1034 
1035  /* Extract rowtype info and find a tupdesc */
1036  tupType = HeapTupleHeaderGetTypeId(td);
1037  tupTypmod = HeapTupleHeaderGetTypMod(td);
1038  tupdesc = lookup_rowtype_tupdesc(tupType, tupTypmod);
1039 
1040  /* Build a temporary HeapTuple control structure */
1041  tmptup.t_len = HeapTupleHeaderGetDatumLength(td);
1042  tmptup.t_data = td;
1043  tuple = &tmptup;
1044 
1045  result->res = pushJsonbValue(&result->parseState, WJB_BEGIN_OBJECT, NULL);
1046 
1047  for (i = 0; i < tupdesc->natts; i++)
1048  {
1049  Datum val;
1050  bool isnull;
1051  char *attname;
1052  JsonbTypeCategory tcategory;
1053  Oid outfuncoid;
1054  JsonbValue v;
1055  Form_pg_attribute att = TupleDescAttr(tupdesc, i);
1056 
1057  if (att->attisdropped)
1058  continue;
1059 
1060  attname = NameStr(att->attname);
1061 
1062  v.type = jbvString;
1063  /* don't need checkStringLen here - can't exceed maximum name length */
1064  v.val.string.len = strlen(attname);
1065  v.val.string.val = attname;
1066 
1067  result->res = pushJsonbValue(&result->parseState, WJB_KEY, &v);
1068 
1069  val = heap_getattr(tuple, i + 1, tupdesc, &isnull);
1070 
1071  if (isnull)
1072  {
1073  tcategory = JSONBTYPE_NULL;
1074  outfuncoid = InvalidOid;
1075  }
1076  else
1077  jsonb_categorize_type(att->atttypid, &tcategory, &outfuncoid);
1078 
1079  datum_to_jsonb(val, isnull, result, tcategory, outfuncoid, false);
1080  }
1081 
1082  result->res = pushJsonbValue(&result->parseState, WJB_END_OBJECT, NULL);
1083  ReleaseTupleDesc(tupdesc);
1084 }
#define NameStr(name)
Definition: c.h:681
signed int int32
Definition: c.h:429
#define DatumGetHeapTupleHeader(X)
Definition: fmgr.h:295
static Datum heap_getattr(HeapTuple tup, int attnum, TupleDesc tupleDesc, bool *isnull)
Definition: htup_details.h:788
#define HeapTupleHeaderGetTypMod(tup)
Definition: htup_details.h:462
#define HeapTupleHeaderGetTypeId(tup)
Definition: htup_details.h:452
#define HeapTupleHeaderGetDatumLength(tup)
Definition: htup_details.h:446
@ 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:263
char * val
Definition: jsonb.h:272
#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:1830

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

724 {
725  char *outputstr;
726  bool numeric_error;
727  JsonbValue jb;
728  bool scalar_jsonb = false;
729 
731 
732  /* Convert val to a JsonbValue in jb (in most cases) */
733  if (is_null)
734  {
735  Assert(!key_scalar);
736  jb.type = jbvNull;
737  }
738  else if (key_scalar &&
739  (tcategory == JSONBTYPE_ARRAY ||
740  tcategory == JSONBTYPE_COMPOSITE ||
741  tcategory == JSONBTYPE_JSON ||
742  tcategory == JSONBTYPE_JSONB ||
743  tcategory == JSONBTYPE_JSONCAST))
744  {
745  ereport(ERROR,
746  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
747  errmsg("key value must be scalar, not array, composite, or json")));
748  }
749  else
750  {
751  if (tcategory == JSONBTYPE_JSONCAST)
752  val = OidFunctionCall1(outfuncoid, val);
753 
754  switch (tcategory)
755  {
756  case JSONBTYPE_ARRAY:
757  array_to_jsonb_internal(val, result);
758  break;
759  case JSONBTYPE_COMPOSITE:
760  composite_to_jsonb(val, result);
761  break;
762  case JSONBTYPE_BOOL:
763  if (key_scalar)
764  {
765  outputstr = DatumGetBool(val) ? "true" : "false";
766  jb.type = jbvString;
767  jb.val.string.len = strlen(outputstr);
768  jb.val.string.val = outputstr;
769  }
770  else
771  {
772  jb.type = jbvBool;
773  jb.val.boolean = DatumGetBool(val);
774  }
775  break;
776  case JSONBTYPE_NUMERIC:
777  outputstr = OidOutputFunctionCall(outfuncoid, val);
778  if (key_scalar)
779  {
780  /* always quote keys */
781  jb.type = jbvString;
782  jb.val.string.len = strlen(outputstr);
783  jb.val.string.val = outputstr;
784  }
785  else
786  {
787  /*
788  * Make it numeric if it's a valid JSON number, otherwise
789  * a string. Invalid numeric output will always have an
790  * 'N' or 'n' in it (I think).
791  */
792  numeric_error = (strchr(outputstr, 'N') != NULL ||
793  strchr(outputstr, 'n') != NULL);
794  if (!numeric_error)
795  {
796  Datum numd;
797 
798  jb.type = jbvNumeric;
800  CStringGetDatum(outputstr),
802  Int32GetDatum(-1));
803  jb.val.numeric = DatumGetNumeric(numd);
804  pfree(outputstr);
805  }
806  else
807  {
808  jb.type = jbvString;
809  jb.val.string.len = strlen(outputstr);
810  jb.val.string.val = outputstr;
811  }
812  }
813  break;
814  case JSONBTYPE_DATE:
815  jb.type = jbvString;
816  jb.val.string.val = JsonEncodeDateTime(NULL, val,
817  DATEOID, NULL);
818  jb.val.string.len = strlen(jb.val.string.val);
819  break;
820  case JSONBTYPE_TIMESTAMP:
821  jb.type = jbvString;
822  jb.val.string.val = JsonEncodeDateTime(NULL, val,
823  TIMESTAMPOID, NULL);
824  jb.val.string.len = strlen(jb.val.string.val);
825  break;
827  jb.type = jbvString;
828  jb.val.string.val = JsonEncodeDateTime(NULL, val,
829  TIMESTAMPTZOID, NULL);
830  jb.val.string.len = strlen(jb.val.string.val);
831  break;
832  case JSONBTYPE_JSONCAST:
833  case JSONBTYPE_JSON:
834  {
835  /* parse the json right into the existing result object */
836  JsonLexContext *lex;
837  JsonSemAction sem;
838  text *json = DatumGetTextPP(val);
839 
840  lex = makeJsonLexContext(json, true);
841 
842  memset(&sem, 0, sizeof(sem));
843 
844  sem.semstate = (void *) result;
845 
850  sem.scalar = jsonb_in_scalar;
852 
853  pg_parse_json_or_ereport(lex, &sem);
854  }
855  break;
856  case JSONBTYPE_JSONB:
857  {
858  Jsonb *jsonb = DatumGetJsonbP(val);
859  JsonbIterator *it;
860 
861  it = JsonbIteratorInit(&jsonb->root);
862 
863  if (JB_ROOT_IS_SCALAR(jsonb))
864  {
865  (void) JsonbIteratorNext(&it, &jb, true);
866  Assert(jb.type == jbvArray);
867  (void) JsonbIteratorNext(&it, &jb, true);
868  scalar_jsonb = true;
869  }
870  else
871  {
873 
874  while ((type = JsonbIteratorNext(&it, &jb, false))
875  != WJB_DONE)
876  {
877  if (type == WJB_END_ARRAY || type == WJB_END_OBJECT ||
879  result->res = pushJsonbValue(&result->parseState,
880  type, NULL);
881  else
882  result->res = pushJsonbValue(&result->parseState,
883  type, &jb);
884  }
885  }
886  }
887  break;
888  default:
889  outputstr = OidOutputFunctionCall(outfuncoid, val);
890  jb.type = jbvString;
891  jb.val.string.len = checkStringLen(strlen(outputstr));
892  jb.val.string.val = outputstr;
893  break;
894  }
895  }
896 
897  /* Now insert jb into result, unless we did it recursively */
898  if (!is_null && !scalar_jsonb &&
899  tcategory >= JSONBTYPE_JSON && tcategory <= JSONBTYPE_JSONCAST)
900  {
901  /* work has been done recursively */
902  return;
903  }
904  else if (result->parseState == NULL)
905  {
906  /* single root scalar */
907  JsonbValue va;
908 
909  va.type = jbvArray;
910  va.val.array.rawScalar = true;
911  va.val.array.nElems = 1;
912 
913  result->res = pushJsonbValue(&result->parseState, WJB_BEGIN_ARRAY, &va);
914  result->res = pushJsonbValue(&result->parseState, WJB_ELEM, &jb);
915  result->res = pushJsonbValue(&result->parseState, WJB_END_ARRAY, NULL);
916  }
917  else
918  {
919  JsonbValue *o = &result->parseState->contVal;
920 
921  switch (o->type)
922  {
923  case jbvArray:
924  result->res = pushJsonbValue(&result->parseState, WJB_ELEM, &jb);
925  break;
926  case jbvObject:
927  result->res = pushJsonbValue(&result->parseState,
928  key_scalar ? WJB_KEY : WJB_VALUE,
929  &jb);
930  break;
931  default:
932  elog(ERROR, "unexpected parent of nested structure");
933  }
934  }
935 }
Datum numeric_in(PG_FUNCTION_ARGS)
Definition: numeric.c:617
char * OidOutputFunctionCall(Oid functionId, Datum val)
Definition: fmgr.c:1639
#define OidFunctionCall1(functionId, arg1)
Definition: fmgr.h:669
#define DatumGetTextPP(X)
Definition: fmgr.h:292
#define DirectFunctionCall3(func, arg1, arg2, arg3)
Definition: fmgr.h:635
char * JsonEncodeDateTime(char *buf, Datum value, Oid typid, const int *tzp)
Definition: json.c:375
static void jsonb_in_scalar(void *pstate, char *token, JsonTokenType tokentype)
Definition: jsonb.c:361
static void jsonb_in_object_end(void *pstate)
Definition: jsonb.c:293
static void array_to_jsonb_internal(Datum array, JsonbInState *result)
Definition: jsonb.c:975
static void jsonb_in_array_start(void *pstate)
Definition: jsonb.c:301
static void composite_to_jsonb(Datum composite, JsonbInState *result)
Definition: jsonb.c:1023
static void jsonb_in_object_start(void *pstate)
Definition: jsonb.c:284
static size_t checkStringLen(size_t len)
Definition: jsonb.c:271
static void jsonb_in_object_field_start(void *pstate, char *fname, bool isnull)
Definition: jsonb.c:317
static void jsonb_in_array_end(void *pstate)
Definition: jsonb.c:309
#define JB_ROOT_IS_SCALAR(jbp_)
Definition: jsonb.h:228
@ JSONBTYPE_TIMESTAMPTZ
Definition: jsonb.h:387
@ JSONBTYPE_JSONB
Definition: jsonb.h:389
@ JSONBTYPE_DATE
Definition: jsonb.h:385
@ JSONBTYPE_NUMERIC
Definition: jsonb.h:384
@ JSONBTYPE_ARRAY
Definition: jsonb.h:390
@ JSONBTYPE_COMPOSITE
Definition: jsonb.h:391
@ JSONBTYPE_JSON
Definition: jsonb.h:388
@ JSONBTYPE_BOOL
Definition: jsonb.h:383
@ JSONBTYPE_TIMESTAMP
Definition: jsonb.h:386
@ JSONBTYPE_JSONCAST
Definition: jsonb.h:392
#define DatumGetJsonbP(d)
Definition: jsonb.h:71
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:819
JsonbIteratorToken JsonbIteratorNext(JsonbIterator **it, JsonbValue *val, bool skipNested)
Definition: jsonb_util.c:855
void pg_parse_json_or_ereport(JsonLexContext *lex, JsonSemAction *sem)
Definition: jsonfuncs.c:501
JsonLexContext * makeJsonLexContext(text *json, bool need_escapes)
Definition: jsonfuncs.c:517
#define DatumGetNumeric(X)
Definition: numeric.h:59
void check_stack_depth(void)
Definition: postgres.c:3500
#define CStringGetDatum(X)
Definition: postgres.h:622
#define DatumGetBool(X)
Definition: postgres.h:437
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define Int32GetDatum(X)
Definition: postgres.h:523
json_struct_action array_end
Definition: jsonapi.h:110
json_struct_action object_start
Definition: jsonapi.h:107
json_ofield_action object_field_start
Definition: jsonapi.h:111
json_scalar_action scalar
Definition: jsonapi.h:115
void * semstate
Definition: jsonapi.h:106
json_struct_action array_start
Definition: jsonapi.h:109
json_struct_action object_end
Definition: jsonapi.h:108
Definition: jsonb.h:221
JsonbContainer root
Definition: jsonb.h:223
Definition: c.h:622

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_worker(), jsonb_object_agg_transfn_worker(), and to_jsonb_worker().

◆ jsonb_agg_finalfn()

Datum jsonb_agg_finalfn ( PG_FUNCTION_ARGS  )

Definition at line 1708 of file jsonb.c.

1709 {
1710  JsonbAggState *arg;
1711  JsonbInState result;
1712  Jsonb *out;
1713 
1714  /* cannot be called directly because of internal-type argument */
1715  Assert(AggCheckCallContext(fcinfo, NULL));
1716 
1717  if (PG_ARGISNULL(0))
1718  PG_RETURN_NULL(); /* returns null iff no input values */
1719 
1721 
1722  /*
1723  * We need to do a shallow clone of the argument in case the final
1724  * function is called more than once, so we avoid changing the argument. A
1725  * shallow clone is sufficient as we aren't going to change any of the
1726  * values, just add the final array end marker.
1727  */
1728 
1729  result.parseState = clone_parse_state(arg->res->parseState);
1730 
1731  result.res = pushJsonbValue(&result.parseState,
1732  WJB_END_ARRAY, NULL);
1733 
1734  out = JsonbValueToJsonb(result.res);
1735 
1736  PG_RETURN_POINTER(out);
1737 }
#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:1539
Jsonb * JsonbValueToJsonb(JsonbValue *val)
Definition: jsonb_util.c:94
int AggCheckCallContext(FunctionCallInfo fcinfo, MemoryContext *aggcontext)
Definition: nodeAgg.c:4487
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 1702 of file jsonb.c.

1703 {
1704  return jsonb_agg_transfn_worker(fcinfo, true);
1705 }
static Datum jsonb_agg_transfn_worker(FunctionCallInfo fcinfo, bool absent_on_null)
Definition: jsonb.c:1569

References jsonb_agg_transfn_worker().

◆ jsonb_agg_transfn()

Datum jsonb_agg_transfn ( PG_FUNCTION_ARGS  )

Definition at line 1693 of file jsonb.c.

1694 {
1695  return jsonb_agg_transfn_worker(fcinfo, false);
1696 }

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

1570 {
1571  MemoryContext oldcontext,
1572  aggcontext;
1574  JsonbInState elem;
1575  Datum val;
1576  JsonbInState *result;
1577  bool single_scalar = false;
1578  JsonbIterator *it;
1579  Jsonb *jbelem;
1580  JsonbValue v;
1582 
1583  if (!AggCheckCallContext(fcinfo, &aggcontext))
1584  {
1585  /* cannot be called directly because of internal-type argument */
1586  elog(ERROR, "jsonb_agg_transfn called in non-aggregate context");
1587  }
1588 
1589  /* set up the accumulator on the first go round */
1590 
1591  if (PG_ARGISNULL(0))
1592  {
1593  Oid arg_type = get_fn_expr_argtype(fcinfo->flinfo, 1);
1594 
1595  if (arg_type == InvalidOid)
1596  ereport(ERROR,
1597  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1598  errmsg("could not determine input data type")));
1599 
1600  oldcontext = MemoryContextSwitchTo(aggcontext);
1601  state = palloc(sizeof(JsonbAggState));
1602  result = palloc0(sizeof(JsonbInState));
1603  state->res = result;
1604  result->res = pushJsonbValue(&result->parseState,
1605  WJB_BEGIN_ARRAY, NULL);
1606  MemoryContextSwitchTo(oldcontext);
1607 
1608  jsonb_categorize_type(arg_type, &state->val_category,
1609  &state->val_output_func);
1610  }
1611  else
1612  {
1614  result = state->res;
1615  }
1616 
1617  if (absent_on_null && PG_ARGISNULL(1))
1619 
1620  /* turn the argument into jsonb in the normal function context */
1621 
1622  val = PG_ARGISNULL(1) ? (Datum) 0 : PG_GETARG_DATUM(1);
1623 
1624  memset(&elem, 0, sizeof(JsonbInState));
1625 
1626  datum_to_jsonb(val, PG_ARGISNULL(1), &elem, state->val_category,
1627  state->val_output_func, false);
1628 
1629  jbelem = JsonbValueToJsonb(elem.res);
1630 
1631  /* switch to the aggregate context for accumulation operations */
1632 
1633  oldcontext = MemoryContextSwitchTo(aggcontext);
1634 
1635  it = JsonbIteratorInit(&jbelem->root);
1636 
1637  while ((type = JsonbIteratorNext(&it, &v, false)) != WJB_DONE)
1638  {
1639  switch (type)
1640  {
1641  case WJB_BEGIN_ARRAY:
1642  if (v.val.array.rawScalar)
1643  single_scalar = true;
1644  else
1645  result->res = pushJsonbValue(&result->parseState,
1646  type, NULL);
1647  break;
1648  case WJB_END_ARRAY:
1649  if (!single_scalar)
1650  result->res = pushJsonbValue(&result->parseState,
1651  type, NULL);
1652  break;
1653  case WJB_BEGIN_OBJECT:
1654  case WJB_END_OBJECT:
1655  result->res = pushJsonbValue(&result->parseState,
1656  type, NULL);
1657  break;
1658  case WJB_ELEM:
1659  case WJB_KEY:
1660  case WJB_VALUE:
1661  if (v.type == jbvString)
1662  {
1663  /* copy string values in the aggregate context */
1664  char *buf = palloc(v.val.string.len + 1);
1665 
1666  snprintf(buf, v.val.string.len + 1, "%s", v.val.string.val);
1667  v.val.string.val = buf;
1668  }
1669  else if (v.type == jbvNumeric)
1670  {
1671  /* same for numeric */
1672  v.val.numeric =
1674  NumericGetDatum(v.val.numeric)));
1675  }
1676  result->res = pushJsonbValue(&result->parseState,
1677  type, &v);
1678  break;
1679  default:
1680  elog(ERROR, "unknown jsonb iterator token type");
1681  }
1682  }
1683 
1684  MemoryContextSwitchTo(oldcontext);
1685 
1687 }
Datum numeric_uplus(PG_FUNCTION_ARGS)
Definition: numeric.c:1381
Oid get_fn_expr_argtype(FmgrInfo *flinfo, int argnum)
Definition: fmgr.c:1786
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:631
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:268
void * palloc0(Size size)
Definition: mcxt.c:1099
#define NumericGetDatum(X)
Definition: numeric.h:61
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
static char * buf
Definition: pg_test_fsync.c:67
#define snprintf
Definition: port.h:225
FmgrInfo * flinfo
Definition: fmgr.h:87

References AggCheckCallContext(), buf, datum_to_jsonb(), DatumGetNumeric, DirectFunctionCall1, elog, ereport, errcode(), errmsg(), ERROR, FunctionCallInfoBaseData::flinfo, 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.

Referenced by jsonb_agg_strict_transfn(), and jsonb_agg_transfn().

◆ jsonb_bool()

Datum jsonb_bool ( PG_FUNCTION_ARGS  )

Definition at line 2104 of file jsonb.c.

2105 {
2106  Jsonb *in = PG_GETARG_JSONB_P(0);
2107  JsonbValue v;
2108 
2109  if (!JsonbExtractScalar(&in->root, &v) || v.type != jbvBool)
2110  cannotCastJsonbValue(v.type, "boolean");
2111 
2112  PG_FREE_IF_COPY(in, 0);
2113 
2114  PG_RETURN_BOOL(v.val.boolean);
2115 }
#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:2074
bool JsonbExtractScalar(JsonbContainer *jbc, JsonbValue *res)
Definition: jsonb.c:2034
#define PG_GETARG_JSONB_P(x)
Definition: jsonb.h:74

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

1299 {
1300  Datum *args;
1301  bool *nulls;
1302  Oid *types;
1303 
1304  /* build argument values to build the object */
1305  int nargs = extract_variadic_args(fcinfo, 0, true,
1306  &args, &types, &nulls);
1307 
1308  if (nargs < 0)
1309  PG_RETURN_NULL();
1310 
1311  PG_RETURN_DATUM(jsonb_build_array_worker(nargs, args, nulls, types, false));
1312 }
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:1976
Datum jsonb_build_array_worker(int nargs, Datum *args, bool *nulls, Oid *types, bool absent_on_null)
Definition: jsonb.c:1271

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

1320 {
1321  JsonbInState result;
1322 
1323  memset(&result, 0, sizeof(JsonbInState));
1324 
1325  (void) pushJsonbValue(&result.parseState, WJB_BEGIN_ARRAY, NULL);
1326  result.res = pushJsonbValue(&result.parseState, WJB_END_ARRAY, NULL);
1327 
1329 }

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,
Datum args,
bool nulls,
Oid types,
bool  absent_on_null 
)

Definition at line 1271 of file jsonb.c.

1273 {
1274  int i;
1275  JsonbInState result;
1276 
1277  memset(&result, 0, sizeof(JsonbInState));
1278 
1279  result.res = pushJsonbValue(&result.parseState, WJB_BEGIN_ARRAY, NULL);
1280 
1281  for (i = 0; i < nargs; i++)
1282  {
1283  if (absent_on_null && nulls[i])
1284  continue;
1285 
1286  add_jsonb(args[i], nulls[i], &result, types[i], false);
1287  }
1288 
1289  result.res = pushJsonbValue(&result.parseState, WJB_END_ARRAY, NULL);
1290 
1291  return JsonbPGetDatum(JsonbValueToJsonb(result.res));
1292 }
static void add_jsonb(Datum val, bool is_null, JsonbInState *result, Oid val_type, bool key_scalar)
Definition: jsonb.c:1095
#define JsonbPGetDatum(p)
Definition: jsonb.h:73

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

1239 {
1240  Datum *args;
1241  bool *nulls;
1242  Oid *types;
1243 
1244  /* build argument values to build the object */
1245  int nargs = extract_variadic_args(fcinfo, 0, true,
1246  &args, &types, &nulls);
1247 
1248  if (nargs < 0)
1249  PG_RETURN_NULL();
1250 
1251  PG_RETURN_DATUM(jsonb_build_object_worker(nargs, args, nulls, types, false, false));
1252 }
Datum jsonb_build_object_worker(int nargs, Datum *args, bool *nulls, Oid *types, bool absent_on_null, bool unique_keys)
Definition: jsonb.c:1186

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

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

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,
Datum args,
bool nulls,
Oid types,
bool  absent_on_null,
bool  unique_keys 
)

Definition at line 1186 of file jsonb.c.

1188 {
1189  int i;
1190  JsonbInState result;
1191 
1192  if (nargs % 2 != 0)
1193  ereport(ERROR,
1194  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1195  errmsg("argument list must have even number of elements"),
1196  /* translator: %s is a SQL function name */
1197  errhint("The arguments of %s must consist of alternating keys and values.",
1198  "jsonb_build_object()")));
1199 
1200  memset(&result, 0, sizeof(JsonbInState));
1201 
1202  result.res = pushJsonbValue(&result.parseState, WJB_BEGIN_OBJECT, NULL);
1203  result.parseState->unique_keys = unique_keys;
1204  result.parseState->skip_nulls = absent_on_null;
1205 
1206  for (i = 0; i < nargs; i += 2)
1207  {
1208  /* process key */
1209  bool skip;
1210 
1211  if (nulls[i])
1212  ereport(ERROR,
1213  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1214  errmsg("argument %d: key must not be null", i + 1)));
1215 
1216  /* skip null values if absent_on_null */
1217  skip = absent_on_null && nulls[i + 1];
1218 
1219  /* we need to save skipped keys for the key uniqueness check */
1220  if (skip && !unique_keys)
1221  continue;
1222 
1223  add_jsonb(args[i], false, &result, types[i], true);
1224 
1225  /* process value */
1226  add_jsonb(args[i + 1], nulls[i + 1], &result, types[i + 1], false);
1227  }
1228 
1229  result.res = pushJsonbValue(&result.parseState, WJB_END_OBJECT, NULL);
1230 
1231  return JsonbPGetDatum(JsonbValueToJsonb(result.res));
1232 }
int errhint(const char *fmt,...)
Definition: elog.c:1151
static const struct exclude_list_item skip[]
Definition: pg_checksums.c:116

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

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

Definition at line 613 of file jsonb.c.

616 {
617  bool typisvarlena;
618 
619  /* Look through any domain */
620  typoid = getBaseType(typoid);
621 
622  *outfuncoid = InvalidOid;
623 
624  /*
625  * We need to get the output function for everything except date and
626  * timestamp types, booleans, array and composite types, json and jsonb,
627  * and non-builtin types where there's a cast to json. In this last case
628  * we return the oid of the cast function instead.
629  */
630 
631  switch (typoid)
632  {
633  case BOOLOID:
634  *tcategory = JSONBTYPE_BOOL;
635  break;
636 
637  case INT2OID:
638  case INT4OID:
639  case INT8OID:
640  case FLOAT4OID:
641  case FLOAT8OID:
642  case NUMERICOID:
643  getTypeOutputInfo(typoid, outfuncoid, &typisvarlena);
644  *tcategory = JSONBTYPE_NUMERIC;
645  break;
646 
647  case DATEOID:
648  *tcategory = JSONBTYPE_DATE;
649  break;
650 
651  case TIMESTAMPOID:
652  *tcategory = JSONBTYPE_TIMESTAMP;
653  break;
654 
655  case TIMESTAMPTZOID:
656  *tcategory = JSONBTYPE_TIMESTAMPTZ;
657  break;
658 
659  case JSONBOID:
660  *tcategory = JSONBTYPE_JSONB;
661  break;
662 
663  case JSONOID:
664  *tcategory = JSONBTYPE_JSON;
665  break;
666 
667  default:
668  /* Check for arrays and composites */
669  if (OidIsValid(get_element_type(typoid)) || typoid == ANYARRAYOID
670  || typoid == ANYCOMPATIBLEARRAYOID || typoid == RECORDARRAYOID)
671  *tcategory = JSONBTYPE_ARRAY;
672  else if (type_is_rowtype(typoid)) /* includes RECORDOID */
673  *tcategory = JSONBTYPE_COMPOSITE;
674  else
675  {
676  /* It's probably the general case ... */
677  *tcategory = JSONBTYPE_OTHER;
678 
679  /*
680  * but first let's look for a cast to json (note: not to
681  * jsonb) if it's not built-in.
682  */
683  if (typoid >= FirstNormalObjectId)
684  {
685  Oid castfunc;
686  CoercionPathType ctype;
687 
688  ctype = find_coercion_pathway(JSONOID, typoid,
689  COERCION_EXPLICIT, &castfunc);
690  if (ctype == COERCION_PATH_FUNC && OidIsValid(castfunc))
691  {
692  *tcategory = JSONBTYPE_JSONCAST;
693  *outfuncoid = castfunc;
694  }
695  else
696  {
697  /* not a cast type, so just get the usual output func */
698  getTypeOutputInfo(typoid, outfuncoid, &typisvarlena);
699  }
700  }
701  else
702  {
703  /* any other builtin type */
704  getTypeOutputInfo(typoid, outfuncoid, &typisvarlena);
705  }
706  break;
707  }
708  }
709 }
#define OidIsValid(objectId)
Definition: c.h:710
@ JSONBTYPE_OTHER
Definition: jsonb.h:393
Oid get_element_type(Oid typid)
Definition: lsyscache.c:2716
bool type_is_rowtype(Oid typid)
Definition: lsyscache.c:2612
void getTypeOutputInfo(Oid type, Oid *typOutput, bool *typIsVarlena)
Definition: lsyscache.c:2864
Oid getBaseType(Oid typid)
Definition: lsyscache.c:2478
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:475
#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(), ExecInitExprRec(), jsonb_agg_transfn_worker(), jsonb_object_agg_transfn_worker(), to_jsonb(), and to_jsonb_is_immutable().

◆ jsonb_float4()

Datum jsonb_float4 ( PG_FUNCTION_ARGS  )

Definition at line 2193 of file jsonb.c.

2194 {
2195  Jsonb *in = PG_GETARG_JSONB_P(0);
2196  JsonbValue v;
2197  Datum retValue;
2198 
2199  if (!JsonbExtractScalar(&in->root, &v) || v.type != jbvNumeric)
2200  cannotCastJsonbValue(v.type, "real");
2201 
2203  NumericGetDatum(v.val.numeric));
2204 
2205  PG_FREE_IF_COPY(in, 0);
2206 
2207  PG_RETURN_DATUM(retValue);
2208 }
Datum numeric_float4(PG_FUNCTION_ARGS)
Definition: numeric.c:4519

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

2212 {
2213  Jsonb *in = PG_GETARG_JSONB_P(0);
2214  JsonbValue v;
2215  Datum retValue;
2216 
2217  if (!JsonbExtractScalar(&in->root, &v) || v.type != jbvNumeric)
2218  cannotCastJsonbValue(v.type, "double precision");
2219 
2221  NumericGetDatum(v.val.numeric));
2222 
2223  PG_FREE_IF_COPY(in, 0);
2224 
2225  PG_RETURN_DATUM(retValue);
2226 }
Datum numeric_float8(PG_FUNCTION_ARGS)
Definition: numeric.c:4426

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 
)
inlinestatic

Definition at line 243 of file jsonb.c.

244 {
245  JsonLexContext *lex;
247  JsonSemAction sem;
248 
249  memset(&state, 0, sizeof(state));
250  memset(&sem, 0, sizeof(sem));
252 
253  state.unique_keys = unique_keys;
254 
255  sem.semstate = (void *) &state;
256 
261  sem.scalar = jsonb_in_scalar;
263 
264  pg_parse_json_or_ereport(lex, &sem);
265 
266  /* after parsing, the item member has the composed jsonb structure */
268 }
JsonLexContext * makeJsonLexContextCstringLen(char *json, int len, int encoding, bool need_escapes)
Definition: jsonapi.c:144
int GetDatabaseEncoding(void)
Definition: mbutils.c:1210

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_ereport(), PG_RETURN_POINTER, JsonSemAction::scalar, 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 146 of file jsonb.c.

147 {
148  return jsonb_from_cstring(VARDATA_ANY(js),
149  VARSIZE_ANY_EXHDR(js),
150  unique_keys);
151 }
static Datum jsonb_from_cstring(char *json, int len, bool unique_keys)
Definition: jsonb.c:243
#define VARDATA_ANY(PTR)
Definition: postgres.h:361
#define VARSIZE_ANY_EXHDR(PTR)
Definition: postgres.h:354

References jsonb_from_cstring(), VARDATA_ANY, and VARSIZE_ANY_EXHDR.

Referenced by ExecEvalJsonConstructor().

◆ jsonb_in()

Datum jsonb_in ( PG_FUNCTION_ARGS  )

Definition at line 76 of file jsonb.c.

77 {
78  char *json = PG_GETARG_CSTRING(0);
79 
80  return jsonb_from_cstring(json, strlen(json), false);
81 }
#define PG_GETARG_CSTRING(n)
Definition: fmgr.h:277

References jsonb_from_cstring(), and PG_GETARG_CSTRING.

Referenced by jsonb_set_lax(), and JsonItemFromDatum().

◆ jsonb_in_array_end()

static void jsonb_in_array_end ( void *  pstate)
static

Definition at line 309 of file jsonb.c.

310 {
311  JsonbInState *_state = (JsonbInState *) pstate;
312 
313  _state->res = pushJsonbValue(&_state->parseState, WJB_END_ARRAY, NULL);
314 }

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

Referenced by datum_to_jsonb(), and jsonb_from_cstring().

◆ jsonb_in_array_start()

static void jsonb_in_array_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_ARRAY, NULL);
306 }

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

Referenced by datum_to_jsonb(), and jsonb_from_cstring().

◆ jsonb_in_object_end()

static void jsonb_in_object_end ( void *  pstate)
static

Definition at line 293 of file jsonb.c.

294 {
295  JsonbInState *_state = (JsonbInState *) pstate;
296 
297  _state->res = pushJsonbValue(&_state->parseState, WJB_END_OBJECT, NULL);
298 }

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

Referenced by datum_to_jsonb(), and jsonb_from_cstring().

◆ jsonb_in_object_field_start()

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

Definition at line 317 of file jsonb.c.

318 {
319  JsonbInState *_state = (JsonbInState *) pstate;
320  JsonbValue v;
321 
322  Assert(fname != NULL);
323  v.type = jbvString;
324  v.val.string.len = checkStringLen(strlen(fname));
325  v.val.string.val = fname;
326 
327  _state->res = pushJsonbValue(&_state->parseState, WJB_KEY, &v);
328 }

References Assert(), checkStringLen(), jbvString, 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 void jsonb_in_object_start ( void *  pstate)
static

Definition at line 284 of file jsonb.c.

285 {
286  JsonbInState *_state = (JsonbInState *) pstate;
287 
288  _state->res = pushJsonbValue(&_state->parseState, WJB_BEGIN_OBJECT, NULL);
289  _state->parseState->unique_keys = _state->unique_keys;
290 }
bool unique_keys
Definition: jsonb.c:37

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

Referenced by datum_to_jsonb(), and jsonb_from_cstring().

◆ jsonb_in_scalar()

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

Definition at line 361 of file jsonb.c.

362 {
363  JsonbInState *_state = (JsonbInState *) pstate;
364  JsonbValue v;
365  Datum numd;
366 
367  switch (tokentype)
368  {
369 
370  case JSON_TOKEN_STRING:
371  Assert(token != NULL);
372  v.type = jbvString;
373  v.val.string.len = checkStringLen(strlen(token));
374  v.val.string.val = token;
375  break;
376  case JSON_TOKEN_NUMBER:
377 
378  /*
379  * No need to check size of numeric values, because maximum
380  * numeric size is well below the JsonbValue restriction
381  */
382  Assert(token != NULL);
383  v.type = jbvNumeric;
385  CStringGetDatum(token),
387  Int32GetDatum(-1));
388  v.val.numeric = DatumGetNumeric(numd);
389  break;
390  case JSON_TOKEN_TRUE:
391  v.type = jbvBool;
392  v.val.boolean = true;
393  break;
394  case JSON_TOKEN_FALSE:
395  v.type = jbvBool;
396  v.val.boolean = false;
397  break;
398  case JSON_TOKEN_NULL:
399  v.type = jbvNull;
400  break;
401  default:
402  /* should not be possible */
403  elog(ERROR, "invalid json token type");
404  break;
405  }
406 
407  if (_state->parseState == NULL)
408  {
409  /* single scalar */
410  JsonbValue va;
411 
412  va.type = jbvArray;
413  va.val.array.rawScalar = true;
414  va.val.array.nElems = 1;
415 
416  _state->res = pushJsonbValue(&_state->parseState, WJB_BEGIN_ARRAY, &va);
417  _state->res = pushJsonbValue(&_state->parseState, WJB_ELEM, &v);
418  _state->res = pushJsonbValue(&_state->parseState, WJB_END_ARRAY, NULL);
419  }
420  else
421  {
422  JsonbValue *o = &_state->parseState->contVal;
423 
424  switch (o->type)
425  {
426  case jbvArray:
427  _state->res = pushJsonbValue(&_state->parseState, WJB_ELEM, &v);
428  break;
429  case jbvObject:
430  _state->res = pushJsonbValue(&_state->parseState, WJB_VALUE, &v);
431  break;
432  default:
433  elog(ERROR, "unexpected parent of nested structure");
434  }
435  }
436 }
@ 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, CStringGetDatum, DatumGetNumeric, DirectFunctionCall3, elog, ERROR, Int32GetDatum, InvalidOid, jbvArray, jbvBool, jbvNull, jbvNumeric, jbvObject, jbvString, JSON_TOKEN_FALSE, JSON_TOKEN_NULL, JSON_TOKEN_NUMBER, JSON_TOKEN_STRING, JSON_TOKEN_TRUE, numeric_in(), ObjectIdGetDatum, JsonbInState::parseState, pushJsonbValue(), JsonbInState::res, 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 2139 of file jsonb.c.

2140 {
2141  Jsonb *in = PG_GETARG_JSONB_P(0);
2142  JsonbValue v;
2143  Datum retValue;
2144 
2145  if (!JsonbExtractScalar(&in->root, &v) || v.type != jbvNumeric)
2146  cannotCastJsonbValue(v.type, "smallint");
2147 
2148  retValue = DirectFunctionCall1(numeric_int2,
2149  NumericGetDatum(v.val.numeric));
2150 
2151  PG_FREE_IF_COPY(in, 0);
2152 
2153  PG_RETURN_DATUM(retValue);
2154 }
Datum numeric_int2(PG_FUNCTION_ARGS)
Definition: numeric.c:4352

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

2158 {
2159  Jsonb *in = PG_GETARG_JSONB_P(0);
2160  JsonbValue v;
2161  Datum retValue;
2162 
2163  if (!JsonbExtractScalar(&in->root, &v) || v.type != jbvNumeric)
2164  cannotCastJsonbValue(v.type, "integer");
2165 
2166  retValue = DirectFunctionCall1(numeric_int4,
2167  NumericGetDatum(v.val.numeric));
2168 
2169  PG_FREE_IF_COPY(in, 0);
2170 
2171  PG_RETURN_DATUM(retValue);
2172 }
Datum numeric_int4(PG_FUNCTION_ARGS)
Definition: numeric.c:4273

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

2176 {
2177  Jsonb *in = PG_GETARG_JSONB_P(0);
2178  JsonbValue v;
2179  Datum retValue;
2180 
2181  if (!JsonbExtractScalar(&in->root, &v) || v.type != jbvNumeric)
2182  cannotCastJsonbValue(v.type, "bigint");
2183 
2184  retValue = DirectFunctionCall1(numeric_int8,
2185  NumericGetDatum(v.val.numeric));
2186 
2187  PG_FREE_IF_COPY(in, 0);
2188 
2189  PG_RETURN_DATUM(retValue);
2190 }
Datum numeric_int8(PG_FUNCTION_ARGS)
Definition: numeric.c:4312

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

2119 {
2120  Jsonb *in = PG_GETARG_JSONB_P(0);
2121  JsonbValue v;
2122  Numeric retValue;
2123 
2124  if (!JsonbExtractScalar(&in->root, &v) || v.type != jbvNumeric)
2125  cannotCastJsonbValue(v.type, "numeric");
2126 
2127  /*
2128  * v.val.numeric points into jsonb body, so we need to make a copy to
2129  * return
2130  */
2131  retValue = DatumGetNumericCopy(NumericGetDatum(v.val.numeric));
2132 
2133  PG_FREE_IF_COPY(in, 0);
2134 
2135  PG_RETURN_NUMERIC(retValue);
2136 }
#define PG_RETURN_NUMERIC(x)
Definition: numeric.h:64
#define DatumGetNumericCopy(X)
Definition: numeric.h:60

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

1341 {
1342  ArrayType *in_array = PG_GETARG_ARRAYTYPE_P(0);
1343  int ndims = ARR_NDIM(in_array);
1344  Datum *in_datums;
1345  bool *in_nulls;
1346  int in_count,
1347  count,
1348  i;
1349  JsonbInState result;
1350 
1351  memset(&result, 0, sizeof(JsonbInState));
1352 
1353  (void) pushJsonbValue(&result.parseState, WJB_BEGIN_OBJECT, NULL);
1354 
1355  switch (ndims)
1356  {
1357  case 0:
1358  goto close_object;
1359  break;
1360 
1361  case 1:
1362  if ((ARR_DIMS(in_array)[0]) % 2)
1363  ereport(ERROR,
1364  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
1365  errmsg("array must have even number of elements")));
1366  break;
1367 
1368  case 2:
1369  if ((ARR_DIMS(in_array)[1]) != 2)
1370  ereport(ERROR,
1371  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
1372  errmsg("array must have two columns")));
1373  break;
1374 
1375  default:
1376  ereport(ERROR,
1377  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
1378  errmsg("wrong number of array subscripts")));
1379  }
1380 
1381  deconstruct_array(in_array,
1382  TEXTOID, -1, false, TYPALIGN_INT,
1383  &in_datums, &in_nulls, &in_count);
1384 
1385  count = in_count / 2;
1386 
1387  for (i = 0; i < count; ++i)
1388  {
1389  JsonbValue v;
1390  char *str;
1391  int len;
1392 
1393  if (in_nulls[i * 2])
1394  ereport(ERROR,
1395  (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
1396  errmsg("null value not allowed for object key")));
1397 
1398  str = TextDatumGetCString(in_datums[i * 2]);
1399  len = strlen(str);
1400 
1401  v.type = jbvString;
1402 
1403  v.val.string.len = len;
1404  v.val.string.val = str;
1405 
1406  (void) pushJsonbValue(&result.parseState, WJB_KEY, &v);
1407 
1408  if (in_nulls[i * 2 + 1])
1409  {
1410  v.type = jbvNull;
1411  }
1412  else
1413  {
1414  str = TextDatumGetCString(in_datums[i * 2 + 1]);
1415  len = strlen(str);
1416 
1417  v.type = jbvString;
1418 
1419  v.val.string.len = len;
1420  v.val.string.val = str;
1421  }
1422 
1423  (void) pushJsonbValue(&result.parseState, WJB_VALUE, &v);
1424  }
1425 
1426  pfree(in_datums);
1427  pfree(in_nulls);
1428 
1429 close_object:
1430  result.res = pushJsonbValue(&result.parseState, WJB_END_OBJECT, NULL);
1431 
1433 }
#define PG_GETARG_ARRAYTYPE_P(n)
Definition: array.h:256
#define TextDatumGetCString(d)
Definition: builtins.h:86

References ARR_DIMS, ARR_NDIM, deconstruct_array(), 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 1997 of file jsonb.c.

1998 {
1999  JsonbAggState *arg;
2000  JsonbInState result;
2001  Jsonb *out;
2002 
2003  /* cannot be called directly because of internal-type argument */
2004  Assert(AggCheckCallContext(fcinfo, NULL));
2005 
2006  if (PG_ARGISNULL(0))
2007  PG_RETURN_NULL(); /* returns null iff no input values */
2008 
2010 
2011  /*
2012  * We need to do a shallow clone of the argument's res field in case the
2013  * final function is called more than once, so we avoid changing the
2014  * aggregate state value. A shallow clone is sufficient as we aren't
2015  * going to change any of the values, just add the final object end
2016  * marker.
2017  */
2018 
2019  result.parseState = clone_parse_state(arg->res->parseState);
2020 
2021  result.res = pushJsonbValue(&result.parseState,
2022  WJB_END_OBJECT, NULL);
2023 
2024  out = JsonbValueToJsonb(result.res);
2025 
2026  PG_RETURN_POINTER(out);
2027 }

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

1974 {
1975  return jsonb_object_agg_transfn_worker(fcinfo, true, false);
1976 }
static Datum jsonb_object_agg_transfn_worker(FunctionCallInfo fcinfo, bool absent_on_null, bool unique_keys)
Definition: jsonb.c:1740

References jsonb_object_agg_transfn_worker().

◆ jsonb_object_agg_transfn()

Datum jsonb_object_agg_transfn ( PG_FUNCTION_ARGS  )

Definition at line 1963 of file jsonb.c.

1964 {
1965  return jsonb_object_agg_transfn_worker(fcinfo, false, false);
1966 }

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

1742 {
1743  MemoryContext oldcontext,
1744  aggcontext;
1745  JsonbInState elem;
1747  Datum val;
1748  JsonbInState *result;
1749  bool single_scalar;
1750  JsonbIterator *it;
1751  Jsonb *jbkey,
1752  *jbval;
1753  JsonbValue v;
1755  bool skip;
1756 
1757  if (!AggCheckCallContext(fcinfo, &aggcontext))
1758  {
1759  /* cannot be called directly because of internal-type argument */
1760  elog(ERROR, "jsonb_object_agg_transfn called in non-aggregate context");
1761  }
1762 
1763  /* set up the accumulator on the first go round */
1764 
1765  if (PG_ARGISNULL(0))
1766  {
1767  Oid arg_type;
1768 
1769  oldcontext = MemoryContextSwitchTo(aggcontext);
1770  state = palloc(sizeof(JsonbAggState));
1771  result = palloc0(sizeof(JsonbInState));
1772  state->res = result;
1773  result->res = pushJsonbValue(&result->parseState,
1774  WJB_BEGIN_OBJECT, NULL);
1775  result->parseState->unique_keys = unique_keys;
1776  result->parseState->skip_nulls = absent_on_null;
1777 
1778  MemoryContextSwitchTo(oldcontext);
1779 
1780  arg_type = get_fn_expr_argtype(fcinfo->flinfo, 1);
1781 
1782  if (arg_type == InvalidOid)
1783  ereport(ERROR,
1784  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1785  errmsg("could not determine input data type")));
1786 
1787  jsonb_categorize_type(arg_type, &state->key_category,
1788  &state->key_output_func);
1789 
1790  arg_type = get_fn_expr_argtype(fcinfo->flinfo, 2);
1791 
1792  if (arg_type == InvalidOid)
1793  ereport(ERROR,
1794  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1795  errmsg("could not determine input data type")));
1796 
1797  jsonb_categorize_type(arg_type, &state->val_category,
1798  &state->val_output_func);
1799  }
1800  else
1801  {
1803  result = state->res;
1804  }
1805 
1806  /* turn the argument into jsonb in the normal function context */
1807 
1808  if (PG_ARGISNULL(1))
1809  ereport(ERROR,
1810  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1811  errmsg("field name must not be null")));
1812 
1813  /*
1814  * Skip null values if absent_on_null unless key uniqueness check is
1815  * needed (because we must save keys in this case).
1816  */
1817  skip = absent_on_null && PG_ARGISNULL(2);
1818 
1819  if (skip && !unique_keys)
1821 
1822  val = PG_GETARG_DATUM(1);
1823 
1824  memset(&elem, 0, sizeof(JsonbInState));
1825 
1826  datum_to_jsonb(val, false, &elem, state->key_category,
1827  state->key_output_func, true);
1828 
1829  jbkey = JsonbValueToJsonb(elem.res);
1830 
1831  val = PG_ARGISNULL(2) ? (Datum) 0 : PG_GETARG_DATUM(2);
1832 
1833  memset(&elem, 0, sizeof(JsonbInState));
1834 
1835  datum_to_jsonb(val, PG_ARGISNULL(2), &elem, state->val_category,
1836  state->val_output_func, false);
1837 
1838  jbval = JsonbValueToJsonb(elem.res);
1839 
1840  it = JsonbIteratorInit(&jbkey->root);
1841 
1842  /* switch to the aggregate context for accumulation operations */
1843 
1844  oldcontext = MemoryContextSwitchTo(aggcontext);
1845 
1846  /*
1847  * keys should be scalar, and we should have already checked for that
1848  * above when calling datum_to_jsonb, so we only need to look for these
1849  * things.
1850  */
1851 
1852  while ((type = JsonbIteratorNext(&it, &v, false)) != WJB_DONE)
1853  {
1854  switch (type)
1855  {
1856  case WJB_BEGIN_ARRAY:
1857  if (!v.val.array.rawScalar)
1858  elog(ERROR, "unexpected structure for key");
1859  break;
1860  case WJB_ELEM:
1861  if (v.type == jbvString)
1862  {
1863  /* copy string values in the aggregate context */
1864  char *buf = palloc(v.val.string.len + 1);
1865 
1866  snprintf(buf, v.val.string.len + 1, "%s", v.val.string.val);
1867  v.val.string.val = buf;
1868  }
1869  else
1870  {
1871  ereport(ERROR,
1872  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1873  errmsg("object keys must be strings")));
1874  }
1875  result->res = pushJsonbValue(&result->parseState,
1876  WJB_KEY, &v);
1877 
1878  if (skip)
1879  {
1880  v.type = jbvNull;
1881  result->res = pushJsonbValue(&result->parseState,
1882  WJB_VALUE, &v);
1883  MemoryContextSwitchTo(oldcontext);
1885  }
1886 
1887  break;
1888  case WJB_END_ARRAY:
1889  break;
1890  default:
1891  elog(ERROR, "unexpected structure for key");
1892  break;
1893  }
1894  }
1895 
1896  it = JsonbIteratorInit(&jbval->root);
1897 
1898  single_scalar = false;
1899 
1900  /*
1901  * values can be anything, including structured and null, so we treat them
1902  * as in json_agg_transfn, except that single scalars are always pushed as
1903  * WJB_VALUE items.
1904  */
1905 
1906  while ((type = JsonbIteratorNext(&it, &v, false)) != WJB_DONE)
1907  {
1908  switch (type)
1909  {
1910  case WJB_BEGIN_ARRAY:
1911  if (v.val.array.rawScalar)
1912  single_scalar = true;
1913  else
1914  result->res = pushJsonbValue(&result->parseState,
1915  type, NULL);
1916  break;
1917  case WJB_END_ARRAY:
1918  if (!single_scalar)
1919  result->res = pushJsonbValue(&result->parseState,
1920  type, NULL);
1921  break;
1922  case WJB_BEGIN_OBJECT:
1923  case WJB_END_OBJECT:
1924  result->res = pushJsonbValue(&result->parseState,
1925  type, NULL);
1926  break;
1927  case WJB_ELEM:
1928  case WJB_KEY:
1929  case WJB_VALUE:
1930  if (v.type == jbvString)
1931  {
1932  /* copy string values in the aggregate context */
1933  char *buf = palloc(v.val.string.len + 1);
1934 
1935  snprintf(buf, v.val.string.len + 1, "%s", v.val.string.val);
1936  v.val.string.val = buf;
1937  }
1938  else if (v.type == jbvNumeric)
1939  {
1940  /* same for numeric */
1941  v.val.numeric =
1943  NumericGetDatum(v.val.numeric)));
1944  }
1945  result->res = pushJsonbValue(&result->parseState,
1946  single_scalar ? WJB_VALUE : type,
1947  &v);
1948  break;
1949  default:
1950  elog(ERROR, "unknown jsonb iterator token type");
1951  }
1952  }
1953 
1954  MemoryContextSwitchTo(oldcontext);
1955 
1957 }

References AggCheckCallContext(), buf, datum_to_jsonb(), DatumGetNumeric, DirectFunctionCall1, elog, ereport, errcode(), errmsg(), ERROR, FunctionCallInfoBaseData::flinfo, get_fn_expr_argtype(), InvalidOid, jbvNull, 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, skip, JsonbParseState::skip_nulls, snprintf, generate_unaccent_rules::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 1991 of file jsonb.c.

1992 {
1993  return jsonb_object_agg_transfn_worker(fcinfo, true, true);
1994 }

References jsonb_object_agg_transfn_worker().

◆ jsonb_object_agg_unique_transfn()

Datum jsonb_object_agg_unique_transfn ( PG_FUNCTION_ARGS  )

Definition at line 1982 of file jsonb.c.

1983 {
1984  return jsonb_object_agg_transfn_worker(fcinfo, false, true);
1985 }

References jsonb_object_agg_transfn_worker().

◆ jsonb_object_two_arg()

Datum jsonb_object_two_arg ( PG_FUNCTION_ARGS  )

Definition at line 1442 of file jsonb.c.

1443 {
1444  ArrayType *key_array = PG_GETARG_ARRAYTYPE_P(0);
1445  ArrayType *val_array = PG_GETARG_ARRAYTYPE_P(1);
1446  int nkdims = ARR_NDIM(key_array);
1447  int nvdims = ARR_NDIM(val_array);
1448  Datum *key_datums,
1449  *val_datums;
1450  bool *key_nulls,
1451  *val_nulls;
1452  int key_count,
1453  val_count,
1454  i;
1455  JsonbInState result;
1456 
1457  memset(&result, 0, sizeof(JsonbInState));
1458 
1459  (void) pushJsonbValue(&result.parseState, WJB_BEGIN_OBJECT, NULL);
1460 
1461  if (nkdims > 1 || nkdims != nvdims)
1462  ereport(ERROR,
1463  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
1464  errmsg("wrong number of array subscripts")));
1465 
1466  if (nkdims == 0)
1467  goto close_object;
1468 
1469  deconstruct_array(key_array,
1470  TEXTOID, -1, false, TYPALIGN_INT,
1471  &key_datums, &key_nulls, &key_count);
1472 
1473  deconstruct_array(val_array,
1474  TEXTOID, -1, false, TYPALIGN_INT,
1475  &val_datums, &val_nulls, &val_count);
1476 
1477  if (key_count != val_count)
1478  ereport(ERROR,
1479  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
1480  errmsg("mismatched array dimensions")));
1481 
1482  for (i = 0; i < key_count; ++i)
1483  {
1484  JsonbValue v;
1485  char *str;
1486  int len;
1487 
1488  if (key_nulls[i])
1489  ereport(ERROR,
1490  (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
1491  errmsg("null value not allowed for object key")));
1492 
1493  str = TextDatumGetCString(key_datums[i]);
1494  len = strlen(str);
1495 
1496  v.type = jbvString;
1497 
1498  v.val.string.len = len;
1499  v.val.string.val = str;
1500 
1501  (void) pushJsonbValue(&result.parseState, WJB_KEY, &v);
1502 
1503  if (val_nulls[i])
1504  {
1505  v.type = jbvNull;
1506  }
1507  else
1508  {
1509  str = TextDatumGetCString(val_datums[i]);
1510  len = strlen(str);
1511 
1512  v.type = jbvString;
1513 
1514  v.val.string.len = len;
1515  v.val.string.val = str;
1516  }
1517 
1518  (void) pushJsonbValue(&result.parseState, WJB_VALUE, &v);
1519  }
1520 
1521  pfree(key_datums);
1522  pfree(key_nulls);
1523  pfree(val_datums);
1524  pfree(val_nulls);
1525 
1526 close_object:
1527  result.res = pushJsonbValue(&result.parseState, WJB_END_OBJECT, NULL);
1528 
1530 }

References ARR_NDIM, deconstruct_array(), 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 111 of file jsonb.c.

112 {
113  Jsonb *jb = PG_GETARG_JSONB_P(0);
114  char *out;
115 
116  out = JsonbToCString(NULL, &jb->root, VARSIZE(jb));
117 
118  PG_RETURN_CSTRING(out);
119 }
#define PG_RETURN_CSTRING(x)
Definition: fmgr.h:362
char * JsonbToCString(StringInfo out, JsonbContainer *in, int estimated_len)
Definition: jsonb.c:450
#define VARSIZE(PTR)
Definition: postgres.h:316

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

332 {
333  switch (scalarVal->type)
334  {
335  case jbvNull:
336  appendBinaryStringInfo(out, "null", 4);
337  break;
338  case jbvString:
339  escape_json(out, pnstrdup(scalarVal->val.string.val, scalarVal->val.string.len));
340  break;
341  case jbvNumeric:
344  PointerGetDatum(scalarVal->val.numeric))));
345  break;
346  case jbvBool:
347  if (scalarVal->val.boolean)
348  appendBinaryStringInfo(out, "true", 4);
349  else
350  appendBinaryStringInfo(out, "false", 5);
351  break;
352  default:
353  elog(ERROR, "unknown jsonb scalar type");
354  }
355 }
Datum numeric_out(PG_FUNCTION_ARGS)
Definition: numeric.c:735
void escape_json(StringInfo buf, const char *str)
Definition: json.c:1587
char * pnstrdup(const char *in, Size len)
Definition: mcxt.c:1316
#define DatumGetCString(X)
Definition: postgres.h:610
#define PointerGetDatum(X)
Definition: postgres.h:600
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 92 of file jsonb.c.

93 {
95  int version = pq_getmsgint(buf, 1);
96  char *str;
97  int nbytes;
98 
99  if (version == 1)
100  str = pq_getmsgtext(buf, buf->len - buf->cursor, &nbytes);
101  else
102  elog(ERROR, "unsupported jsonb version number %d", version);
103 
104  return jsonb_from_cstring(str, nbytes, false);
105 }
unsigned int pq_getmsgint(StringInfo msg, int b)
Definition: pqformat.c:417
char * pq_getmsgtext(StringInfo msg, int rawbytes, int *nbytes)
Definition: pqformat.c:548
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 127 of file jsonb.c.

128 {
129  Jsonb *jb = PG_GETARG_JSONB_P(0);
131  StringInfo jtext = makeStringInfo();
132  int version = 1;
133 
134  (void) JsonbToCString(jtext, &jb->root, VARSIZE(jb));
135 
137  pq_sendint8(&buf, version);
138  pq_sendtext(&buf, jtext->data, jtext->len);
139  pfree(jtext->data);
140  pfree(jtext);
141 
143 }
#define PG_RETURN_BYTEA_P(x)
Definition: fmgr.h:371
void pq_sendtext(StringInfo buf, const char *str, int slen)
Definition: pqformat.c:174
void pq_begintypsend(StringInfo buf)
Definition: pqformat.c:328
bytea * pq_endtypsend(StringInfo buf)
Definition: pqformat.c:348
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 227 of file jsonb.c.

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

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

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

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

2035 {
2036  JsonbIterator *it;
2038  JsonbValue tmp;
2039 
2040  if (!JsonContainerIsArray(jbc) || !JsonContainerIsScalar(jbc))
2041  {
2042  /* inform caller about actual type of container */
2043  res->type = (JsonContainerIsArray(jbc)) ? jbvArray : jbvObject;
2044  return false;
2045  }
2046 
2047  /*
2048  * A root scalar is stored as an array of one element, so we get the array
2049  * and then its first (and only) member.
2050  */
2051  it = JsonbIteratorInit(jbc);
2052 
2053  tok = JsonbIteratorNext(&it, &tmp, true);
2054  Assert(tok == WJB_BEGIN_ARRAY);
2055  Assert(tmp.val.array.nElems == 1 && tmp.val.array.rawScalar);
2056 
2057  tok = JsonbIteratorNext(&it, res, true);
2058  Assert(tok == WJB_ELEM);
2060 
2061  tok = JsonbIteratorNext(&it, &tmp, true);
2062  Assert(tok == WJB_END_ARRAY);
2063 
2064  tok = JsonbIteratorNext(&it, &tmp, true);
2065  Assert(tok == WJB_DONE);
2066 
2067  return true;
2068 }
#define PG_USED_FOR_ASSERTS_ONLY
Definition: c.h:155
#define JsonContainerIsScalar(jc)
Definition: jsonb.h:215
#define IsAJsonbScalar(jsonbval)
Definition: jsonb.h:305

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 ExecPrepareJsonItemCoercion(), executeJsonPath(), jsonb_bool(), jsonb_float4(), jsonb_float8(), jsonb_int2(), jsonb_int4(), jsonb_int8(), jsonb_numeric(), JsonbContainerTypeName(), JsonbUnquote(), JsonItemFromDatum(), and JsonPathValue().

◆ JsonbMakeEmptyArray()

Jsonb* JsonbMakeEmptyArray ( void  )

Definition at line 2232 of file jsonb.c.

2233 {
2234  JsonbValue jbv;
2235 
2236  jbv.type = jbvArray;
2237  jbv.val.array.elems = NULL;
2238  jbv.val.array.nElems = 0;
2239  jbv.val.array.rawScalar = false;
2240 
2241  return JsonbValueToJsonb(&jbv);
2242 }

References jbvArray, JsonbValueToJsonb(), JsonbValue::type, and JsonbValue::val.

Referenced by ExecEvalJsonBehavior().

◆ JsonbMakeEmptyObject()

Jsonb* JsonbMakeEmptyObject ( void  )

Definition at line 2248 of file jsonb.c.

2249 {
2250  JsonbValue jbv;
2251 
2252  jbv.type = jbvObject;
2253  jbv.val.object.pairs = NULL;
2254  jbv.val.object.nPairs = 0;
2255 
2256  return JsonbValueToJsonb(&jbv);
2257 }

References jbvObject, JsonbValueToJsonb(), JsonbValue::type, and JsonbValue::val.

Referenced by ExecEvalJsonBehavior().

◆ JsonbToCString()

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

Definition at line 450 of file jsonb.c.

451 {
452  return JsonbToCStringWorker(out, in, estimated_len, false);
453 }
static char * JsonbToCStringWorker(StringInfo out, JsonbContainer *in, int estimated_len, bool indent)
Definition: jsonb.c:468

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

460 {
461  return JsonbToCStringWorker(out, in, estimated_len, true);
462 }

References JsonbToCStringWorker().

Referenced by jsonb_pretty().

◆ JsonbToCStringWorker()

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

Definition at line 468 of file jsonb.c.

469 {
470  bool first = true;
471  JsonbIterator *it;
472  JsonbValue v;
474  int level = 0;
475  bool redo_switch = false;
476 
477  /* If we are indenting, don't add a space after a comma */
478  int ispaces = indent ? 1 : 2;
479 
480  /*
481  * Don't indent the very first item. This gets set to the indent flag at
482  * the bottom of the loop.
483  */
484  bool use_indent = false;
485  bool raw_scalar = false;
486  bool last_was_key = false;
487 
488  if (out == NULL)
489  out = makeStringInfo();
490 
491  enlargeStringInfo(out, (estimated_len >= 0) ? estimated_len : 64);
492 
493  it = JsonbIteratorInit(in);
494 
495  while (redo_switch ||
496  ((type = JsonbIteratorNext(&it, &v, false)) != WJB_DONE))
497  {
498  redo_switch = false;
499  switch (type)
500  {
501  case WJB_BEGIN_ARRAY:
502  if (!first)
503  appendBinaryStringInfo(out, ", ", ispaces);
504 
505  if (!v.val.array.rawScalar)
506  {
507  add_indent(out, use_indent && !last_was_key, level);
508  appendStringInfoCharMacro(out, '[');
509  }
510  else
511  raw_scalar = true;
512 
513  first = true;
514  level++;
515  break;
516  case WJB_BEGIN_OBJECT:
517  if (!first)
518  appendBinaryStringInfo(out, ", ", ispaces);
519 
520  add_indent(out, use_indent && !last_was_key, level);
521  appendStringInfoCharMacro(out, '{');
522 
523  first = true;
524  level++;
525  break;
526  case WJB_KEY:
527  if (!first)
528  appendBinaryStringInfo(out, ", ", ispaces);
529  first = true;
530 
531  add_indent(out, use_indent, level);
532 
533  /* json rules guarantee this is a string */
534  jsonb_put_escaped_value(out, &v);
535  appendBinaryStringInfo(out, ": ", 2);
536 
537  type = JsonbIteratorNext(&it, &v, false);
538  if (type == WJB_VALUE)
539  {
540  first = false;
541  jsonb_put_escaped_value(out, &v);
542  }
543  else
544  {
546 
547  /*
548  * We need to rerun the current switch() since we need to
549  * output the object which we just got from the iterator
550  * before calling the iterator again.
551  */
552  redo_switch = true;
553  }
554  break;
555  case WJB_ELEM:
556  if (!first)
557  appendBinaryStringInfo(out, ", ", ispaces);
558  first = false;
559 
560  if (!raw_scalar)
561  add_indent(out, use_indent, level);
562  jsonb_put_escaped_value(out, &v);
563  break;
564  case WJB_END_ARRAY:
565  level--;
566  if (!raw_scalar)
567  {
568  add_indent(out, use_indent, level);
569  appendStringInfoCharMacro(out, ']');
570  }
571  first = false;
572  break;
573  case WJB_END_OBJECT:
574  level--;
575  add_indent(out, use_indent, level);
576  appendStringInfoCharMacro(out, '}');
577  first = false;
578  break;
579  default:
580  elog(ERROR, "unknown jsonb iterator token type");
581  }
582  use_indent = indent;
583  last_was_key = redo_switch;
584  }
585 
586  Assert(level == 0);
587 
588  return out->data;
589 }
static void jsonb_put_escaped_value(StringInfo out, JsonbValue *scalarVal)
Definition: jsonb.c:331
static void add_indent(StringInfo out, bool indent, int level)
Definition: jsonb.c:592
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 jbv)

Definition at line 178 of file jsonb.c.

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

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

Referenced by executeItemOptUnwrapTarget(), and JsonbContainerTypeName().

◆ JsonbUnquote()

char* JsonbUnquote ( Jsonb jb)

Definition at line 2263 of file jsonb.c.

2264 {
2265  if (JB_ROOT_IS_SCALAR(jb))
2266  {
2267  JsonbValue v;
2268 
2269  (void) JsonbExtractScalar(&jb->root, &v);
2270 
2271  if (v.type == jbvString)
2272  return pnstrdup(v.val.string.val, v.val.string.len);
2273  else if (v.type == jbvBool)
2274  return pstrdup(v.val.boolean ? "true" : "false");
2275  else if (v.type == jbvNumeric)
2277  PointerGetDatum(v.val.numeric)));
2278  else if (v.type == jbvNull)
2279  return pstrdup("null");
2280  else
2281  {
2282  elog(ERROR, "unrecognized jsonb value type %d", v.type);
2283  return NULL;
2284  }
2285  }
2286  else
2287  return JsonbToCString(NULL, &jb->root, VARSIZE(jb));
2288 }
char * pstrdup(const char *in)
Definition: mcxt.c:1305

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 ExecEvalJsonExprCoercion().

◆ to_jsonb()

Datum to_jsonb ( PG_FUNCTION_ARGS  )

Definition at line 1167 of file jsonb.c.

1168 {
1169  Datum val = PG_GETARG_DATUM(0);
1170  Oid val_type = get_fn_expr_argtype(fcinfo->flinfo, 0);
1171  JsonbTypeCategory tcategory;
1172  Oid outfuncoid;
1173 
1174  if (val_type == InvalidOid)
1175  ereport(ERROR,
1176  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1177  errmsg("could not determine input data type")));
1178 
1179  jsonb_categorize_type(val_type,
1180  &tcategory, &outfuncoid);
1181 
1182  PG_RETURN_DATUM(to_jsonb_worker(val, tcategory, outfuncoid));
1183 }
Datum to_jsonb_worker(Datum val, JsonbTypeCategory tcategory, Oid outfuncoid)
Definition: jsonb.c:1119

References ereport, errcode(), errmsg(), ERROR, get_fn_expr_argtype(), InvalidOid, jsonb_categorize_type(), PG_GETARG_DATUM, PG_RETURN_DATUM, to_jsonb_worker(), and val.

◆ to_jsonb_is_immutable()

bool to_jsonb_is_immutable ( Oid  typoid)

Definition at line 1131 of file jsonb.c.

1132 {
1133  JsonbTypeCategory tcategory;
1134  Oid outfuncoid;
1135 
1136  jsonb_categorize_type(typoid, &tcategory, &outfuncoid);
1137 
1138  switch (tcategory)
1139  {
1140  case JSONBTYPE_BOOL:
1141  case JSONBTYPE_JSON:
1142  case JSONBTYPE_JSONB:
1143  return true;
1144 
1145  case JSONBTYPE_DATE:
1146  case JSONBTYPE_TIMESTAMP:
1147  case JSONBTYPE_TIMESTAMPTZ:
1148  return false;
1149 
1150  case JSONBTYPE_ARRAY:
1151  return false; /* TODO recurse into elements */
1152 
1153  case JSONBTYPE_COMPOSITE:
1154  return false; /* TODO recurse into fields */
1155 
1156  case JSONBTYPE_NUMERIC:
1157  case JSONBTYPE_JSONCAST:
1158  default:
1159  return func_volatile(outfuncoid) == PROVOLATILE_IMMUTABLE;
1160  }
1161 }
char func_volatile(Oid funcid)
Definition: lsyscache.c:1761

References func_volatile(), jsonb_categorize_type(), JSONBTYPE_ARRAY, JSONBTYPE_BOOL, JSONBTYPE_COMPOSITE, JSONBTYPE_DATE, JSONBTYPE_JSON, JSONBTYPE_JSONB, JSONBTYPE_JSONCAST, JSONBTYPE_NUMERIC, JSONBTYPE_TIMESTAMP, and JSONBTYPE_TIMESTAMPTZ.

Referenced by contain_mutable_functions_walker().

◆ to_jsonb_worker()

Datum to_jsonb_worker ( Datum  val,
JsonbTypeCategory  tcategory,
Oid  outfuncoid 
)

Definition at line 1119 of file jsonb.c.

1120 {
1121  JsonbInState result;
1122 
1123  memset(&result, 0, sizeof(JsonbInState));
1124 
1125  datum_to_jsonb(val, false, &result, tcategory, outfuncoid, false);
1126 
1127  return JsonbPGetDatum(JsonbValueToJsonb(result.res));
1128 }

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

Referenced by ExecEvalJsonConstructor(), and to_jsonb().