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

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

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

Function Documentation

◆ add_indent()

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

Definition at line 573 of file jsonb.c.

References appendBinaryStringInfo(), appendStringInfoCharMacro, and i.

Referenced by JsonbToCStringWorker().

574 {
575  if (indent)
576  {
577  int i;
578 
579  appendStringInfoCharMacro(out, '\n');
580  for (i = 0; i < level; i++)
581  appendBinaryStringInfo(out, " ", 4);
582  }
583 }
#define appendStringInfoCharMacro(str, ch)
Definition: stringinfo.h:127
int i
void appendBinaryStringInfo(StringInfo str, const char *data, int datalen)
Definition: stringinfo.c:208

◆ add_jsonb()

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

Definition at line 1074 of file jsonb.c.

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

Referenced by jsonb_build_array(), and jsonb_build_object().

1076 {
1077  JsonbTypeCategory tcategory;
1078  Oid outfuncoid;
1079 
1080  if (val_type == InvalidOid)
1081  ereport(ERROR,
1082  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1083  errmsg("could not determine input data type")));
1084 
1085  if (is_null)
1086  {
1087  tcategory = JSONBTYPE_NULL;
1088  outfuncoid = InvalidOid;
1089  }
1090  else
1091  jsonb_categorize_type(val_type,
1092  &tcategory, &outfuncoid);
1093 
1094  datum_to_jsonb(val, is_null, result, tcategory, outfuncoid, key_scalar);
1095 }
int errcode(int sqlerrcode)
Definition: elog.c:575
unsigned int Oid
Definition: postgres_ext.h:31
static void datum_to_jsonb(Datum val, bool is_null, JsonbInState *result, JsonbTypeCategory tcategory, Oid outfuncoid, bool key_scalar)
Definition: jsonb.c:702
#define ERROR
Definition: elog.h:43
static void jsonb_categorize_type(Oid typoid, JsonbTypeCategory *tcategory, Oid *outfuncoid)
Definition: jsonb.c:594
#define ereport(elevel, rest)
Definition: elog.h:122
JsonbTypeCategory
Definition: jsonb.c:39
#define InvalidOid
Definition: postgres_ext.h:36
int errmsg(const char *fmt,...)
Definition: elog.c:797
long val
Definition: informix.c:689

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

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

Referenced by array_to_jsonb_internal().

925 {
926  int i;
927 
928  Assert(dim < ndims);
929 
930  result->res = pushJsonbValue(&result->parseState, WJB_BEGIN_ARRAY, NULL);
931 
932  for (i = 1; i <= dims[dim]; i++)
933  {
934  if (dim + 1 == ndims)
935  {
936  datum_to_jsonb(vals[*valcount], nulls[*valcount], result, tcategory,
937  outfuncoid, false);
938  (*valcount)++;
939  }
940  else
941  {
942  array_dim_to_jsonb(result, dim + 1, ndims, dims, vals, nulls,
943  valcount, tcategory, outfuncoid);
944  }
945  }
946 
947  result->res = pushJsonbValue(&result->parseState, WJB_END_ARRAY, NULL);
948 }
JsonbParseState * parseState
Definition: jsonb.c:34
JsonbValue * res
Definition: jsonb.c:35
static void datum_to_jsonb(Datum val, bool is_null, JsonbInState *result, JsonbTypeCategory tcategory, Oid outfuncoid, bool key_scalar)
Definition: jsonb.c:702
JsonbValue * pushJsonbValue(JsonbParseState **pstate, JsonbIteratorToken seq, JsonbValue *jbval)
Definition: jsonb_util.c:517
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:922
#define Assert(condition)
Definition: c.h:699
int i

◆ array_to_jsonb_internal()

static void array_to_jsonb_internal ( Datum  array,
JsonbInState result 
)
static

Definition at line 954 of file jsonb.c.

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, typbyval, typlen, WJB_BEGIN_ARRAY, and WJB_END_ARRAY.

Referenced by datum_to_jsonb().

955 {
956  ArrayType *v = DatumGetArrayTypeP(array);
957  Oid element_type = ARR_ELEMTYPE(v);
958  int *dim;
959  int ndim;
960  int nitems;
961  int count = 0;
962  Datum *elements;
963  bool *nulls;
964  int16 typlen;
965  bool typbyval;
966  char typalign;
967  JsonbTypeCategory tcategory;
968  Oid outfuncoid;
969 
970  ndim = ARR_NDIM(v);
971  dim = ARR_DIMS(v);
972  nitems = ArrayGetNItems(ndim, dim);
973 
974  if (nitems <= 0)
975  {
976  result->res = pushJsonbValue(&result->parseState, WJB_BEGIN_ARRAY, NULL);
977  result->res = pushJsonbValue(&result->parseState, WJB_END_ARRAY, NULL);
978  return;
979  }
980 
981  get_typlenbyvalalign(element_type,
982  &typlen, &typbyval, &typalign);
983 
984  jsonb_categorize_type(element_type,
985  &tcategory, &outfuncoid);
986 
987  deconstruct_array(v, element_type, typlen, typbyval,
988  typalign, &elements, &nulls,
989  &nitems);
990 
991  array_dim_to_jsonb(result, 0, ndim, dim, elements, nulls, &count, tcategory,
992  outfuncoid);
993 
994  pfree(elements);
995  pfree(nulls);
996 }
signed short int16
Definition: c.h:312
JsonbParseState * parseState
Definition: jsonb.c:34
JsonbValue * res
Definition: jsonb.c:35
int16 typlen
Definition: pg_type.h:55
void get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval, char *typalign)
Definition: lsyscache.c:2025
int ArrayGetNItems(int ndim, const int *dims)
Definition: arrayutils.c:75
unsigned int Oid
Definition: postgres_ext.h:31
JsonbValue * pushJsonbValue(JsonbParseState **pstate, JsonbIteratorToken seq, JsonbValue *jbval)
Definition: jsonb_util.c:517
void pfree(void *pointer)
Definition: mcxt.c:1031
char typalign
Definition: pg_type.h:168
#define ARR_DIMS(a)
Definition: array.h:279
static void jsonb_categorize_type(Oid typoid, JsonbTypeCategory *tcategory, Oid *outfuncoid)
Definition: jsonb.c:594
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:922
uintptr_t Datum
Definition: postgres.h:367
JsonbTypeCategory
Definition: jsonb.c:39
#define ARR_NDIM(a)
Definition: array.h:275
void deconstruct_array(ArrayType *array, Oid elmtype, int elmlen, bool elmbyval, char elmalign, Datum **elemsp, bool **nullsp, int *nelemsp)
Definition: arrayfuncs.c:3449
#define ARR_ELEMTYPE(a)
Definition: array.h:277
#define DatumGetArrayTypeP(X)
Definition: array.h:246
bool typbyval
Definition: pg_type.h:65

◆ cannotCastJsonbValue()

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

Definition at line 1901 of file jsonb.c.

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

1902 {
1903  static const struct
1904  {
1905  enum jbvType type;
1906  const char *msg;
1907  }
1908  messages[] =
1909  {
1910  { jbvNull, gettext_noop("cannot cast jsonb null to type %s") },
1911  { jbvString, gettext_noop("cannot cast jsonb string to type %s") },
1912  { jbvNumeric, gettext_noop("cannot cast jsonb numeric to type %s") },
1913  { jbvBool, gettext_noop("cannot cast jsonb boolean to type %s") },
1914  { jbvArray, gettext_noop("cannot cast jsonb array to type %s") },
1915  { jbvObject, gettext_noop("cannot cast jsonb object to type %s") },
1916  { jbvBinary, gettext_noop("cannot cast jsonb array or object to type %s") }
1917  };
1918  int i;
1919 
1920  for(i=0; i<lengthof(messages); i++)
1921  if (messages[i].type == type)
1922  ereport(ERROR,
1923  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1924  errmsg(messages[i].msg, sqltype)));
1925 
1926  /* should be unreachable */
1927  elog(ERROR, "unknown jsonb type: %d", (int)type);
1928 }
jbvType
Definition: jsonb.h:228
Definition: jsonb.h:234
#define gettext_noop(x)
Definition: c.h:1036
int errcode(int sqlerrcode)
Definition: elog.c:575
Definition: jsonb.h:231
#define lengthof(array)
Definition: c.h:629
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:122
int errmsg(const char *fmt,...)
Definition: elog.c:797
int i
#define elog
Definition: elog.h:219

◆ checkStringLen()

static size_t checkStringLen ( size_t  len)
static

Definition at line 253 of file jsonb.c.

References ereport, errcode(), errdetail(), errmsg(), ERROR, and JENTRY_OFFLENMASK.

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

254 {
255  if (len > JENTRY_OFFLENMASK)
256  ereport(ERROR,
257  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
258  errmsg("string too long to represent as jsonb string"),
259  errdetail("Due to an implementation restriction, jsonb strings cannot exceed %d bytes.",
261 
262  return len;
263 }
int errcode(int sqlerrcode)
Definition: elog.c:575
#define JENTRY_OFFLENMASK
Definition: jsonb.h:141
#define ERROR
Definition: elog.h:43
int errdetail(const char *fmt,...)
Definition: elog.c:873
#define ereport(elevel, rest)
Definition: elog.h:122
int errmsg(const char *fmt,...)
Definition: elog.c:797

◆ clone_parse_state()

static JsonbParseState * clone_parse_state ( JsonbParseState state)
static

Definition at line 1443 of file jsonb.c.

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

Referenced by jsonb_agg_finalfn(), and jsonb_object_agg_finalfn().

1444 {
1445  JsonbParseState *result,
1446  *icursor,
1447  *ocursor;
1448 
1449  if (state == NULL)
1450  return NULL;
1451 
1452  result = palloc(sizeof(JsonbParseState));
1453  icursor = state;
1454  ocursor = result;
1455  for (;;)
1456  {
1457  ocursor->contVal = icursor->contVal;
1458  ocursor->size = icursor->size;
1459  icursor = icursor->next;
1460  if (icursor == NULL)
1461  break;
1462  ocursor->next = palloc(sizeof(JsonbParseState));
1463  ocursor = ocursor->next;
1464  }
1465  ocursor->next = NULL;
1466 
1467  return result;
1468 }
struct JsonbParseState * next
Definition: jsonb.h:308
JsonbValue contVal
Definition: jsonb.h:306
void * palloc(Size size)
Definition: mcxt.c:924

◆ composite_to_jsonb()

static void composite_to_jsonb ( Datum  composite,
JsonbInState result 
)
static

Definition at line 1002 of file jsonb.c.

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

1003 {
1004  HeapTupleHeader td;
1005  Oid tupType;
1006  int32 tupTypmod;
1007  TupleDesc tupdesc;
1008  HeapTupleData tmptup,
1009  *tuple;
1010  int i;
1011 
1012  td = DatumGetHeapTupleHeader(composite);
1013 
1014  /* Extract rowtype info and find a tupdesc */
1015  tupType = HeapTupleHeaderGetTypeId(td);
1016  tupTypmod = HeapTupleHeaderGetTypMod(td);
1017  tupdesc = lookup_rowtype_tupdesc(tupType, tupTypmod);
1018 
1019  /* Build a temporary HeapTuple control structure */
1020  tmptup.t_len = HeapTupleHeaderGetDatumLength(td);
1021  tmptup.t_data = td;
1022  tuple = &tmptup;
1023 
1024  result->res = pushJsonbValue(&result->parseState, WJB_BEGIN_OBJECT, NULL);
1025 
1026  for (i = 0; i < tupdesc->natts; i++)
1027  {
1028  Datum val;
1029  bool isnull;
1030  char *attname;
1031  JsonbTypeCategory tcategory;
1032  Oid outfuncoid;
1033  JsonbValue v;
1034  Form_pg_attribute att = TupleDescAttr(tupdesc, i);
1035 
1036  if (att->attisdropped)
1037  continue;
1038 
1039  attname = NameStr(att->attname);
1040 
1041  v.type = jbvString;
1042  /* don't need checkStringLen here - can't exceed maximum name length */
1043  v.val.string.len = strlen(attname);
1044  v.val.string.val = attname;
1045 
1046  result->res = pushJsonbValue(&result->parseState, WJB_KEY, &v);
1047 
1048  val = heap_getattr(tuple, i + 1, tupdesc, &isnull);
1049 
1050  if (isnull)
1051  {
1052  tcategory = JSONBTYPE_NULL;
1053  outfuncoid = InvalidOid;
1054  }
1055  else
1056  jsonb_categorize_type(att->atttypid, &tcategory, &outfuncoid);
1057 
1058  datum_to_jsonb(val, isnull, result, tcategory, outfuncoid, false);
1059  }
1060 
1061  result->res = pushJsonbValue(&result->parseState, WJB_END_OBJECT, NULL);
1062  ReleaseTupleDesc(tupdesc);
1063 }
JsonbParseState * parseState
Definition: jsonb.c:34
JsonbValue * res
Definition: jsonb.c:35
TupleDesc lookup_rowtype_tupdesc(Oid type_id, int32 typmod)
Definition: typcache.c:1641
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:93
char * val
Definition: jsonb.h:259
unsigned int Oid
Definition: postgres_ext.h:31
#define DatumGetHeapTupleHeader(X)
Definition: fmgr.h:264
int natts
Definition: tupdesc.h:82
signed int int32
Definition: c.h:313
HeapTupleHeader t_data
Definition: htup.h:68
#define HeapTupleHeaderGetTypMod(tup)
Definition: htup_details.h:467
static void datum_to_jsonb(Datum val, bool is_null, JsonbInState *result, JsonbTypeCategory tcategory, Oid outfuncoid, bool key_scalar)
Definition: jsonb.c:702
JsonbValue * pushJsonbValue(JsonbParseState **pstate, JsonbIteratorToken seq, JsonbValue *jbval)
Definition: jsonb_util.c:517
NameData attname
Definition: pg_attribute.h:40
uint32 t_len
Definition: htup.h:64
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:197
static void jsonb_categorize_type(Oid typoid, JsonbTypeCategory *tcategory, Oid *outfuncoid)
Definition: jsonb.c:594
Definition: jsonb.h:23
#define heap_getattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:781
uintptr_t Datum
Definition: postgres.h:367
#define HeapTupleHeaderGetTypeId(tup)
Definition: htup_details.h:457
JsonbTypeCategory
Definition: jsonb.c:39
#define InvalidOid
Definition: postgres_ext.h:36
enum jbvType type
Definition: jsonb.h:250
int i
#define NameStr(name)
Definition: c.h:576
#define ReleaseTupleDesc(tupdesc)
Definition: tupdesc.h:124
long val
Definition: informix.c:689
#define HeapTupleHeaderGetDatumLength(tup)
Definition: htup_details.h:451

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

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(), pushJsonbValue(), JsonbInState::res, Jsonb::root, JsonSemAction::scalar, JsonSemAction::semstate, generate_unaccent_rules::type, JsonbValue::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 add_jsonb(), array_dim_to_jsonb(), composite_to_jsonb(), jsonb_agg_transfn(), jsonb_object_agg_transfn(), and to_jsonb().

705 {
706  char *outputstr;
707  bool numeric_error;
708  JsonbValue jb;
709  bool scalar_jsonb = false;
710 
712 
713  /* Convert val to a JsonbValue in jb (in most cases) */
714  if (is_null)
715  {
716  Assert(!key_scalar);
717  jb.type = jbvNull;
718  }
719  else if (key_scalar &&
720  (tcategory == JSONBTYPE_ARRAY ||
721  tcategory == JSONBTYPE_COMPOSITE ||
722  tcategory == JSONBTYPE_JSON ||
723  tcategory == JSONBTYPE_JSONB ||
724  tcategory == JSONBTYPE_JSONCAST))
725  {
726  ereport(ERROR,
727  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
728  errmsg("key value must be scalar, not array, composite, or json")));
729  }
730  else
731  {
732  if (tcategory == JSONBTYPE_JSONCAST)
733  val = OidFunctionCall1(outfuncoid, val);
734 
735  switch (tcategory)
736  {
737  case JSONBTYPE_ARRAY:
738  array_to_jsonb_internal(val, result);
739  break;
740  case JSONBTYPE_COMPOSITE:
741  composite_to_jsonb(val, result);
742  break;
743  case JSONBTYPE_BOOL:
744  if (key_scalar)
745  {
746  outputstr = DatumGetBool(val) ? "true" : "false";
747  jb.type = jbvString;
748  jb.val.string.len = strlen(outputstr);
749  jb.val.string.val = outputstr;
750  }
751  else
752  {
753  jb.type = jbvBool;
754  jb.val.boolean = DatumGetBool(val);
755  }
756  break;
757  case JSONBTYPE_NUMERIC:
758  outputstr = OidOutputFunctionCall(outfuncoid, val);
759  if (key_scalar)
760  {
761  /* always quote keys */
762  jb.type = jbvString;
763  jb.val.string.len = strlen(outputstr);
764  jb.val.string.val = outputstr;
765  }
766  else
767  {
768  /*
769  * Make it numeric if it's a valid JSON number, otherwise
770  * a string. Invalid numeric output will always have an
771  * 'N' or 'n' in it (I think).
772  */
773  numeric_error = (strchr(outputstr, 'N') != NULL ||
774  strchr(outputstr, 'n') != NULL);
775  if (!numeric_error)
776  {
777  Datum numd;
778 
779  jb.type = jbvNumeric;
781  CStringGetDatum(outputstr),
783  Int32GetDatum(-1));
784  jb.val.numeric = DatumGetNumeric(numd);
785  pfree(outputstr);
786  }
787  else
788  {
789  jb.type = jbvString;
790  jb.val.string.len = strlen(outputstr);
791  jb.val.string.val = outputstr;
792  }
793  }
794  break;
795  case JSONBTYPE_DATE:
796  jb.type = jbvString;
797  jb.val.string.val = JsonEncodeDateTime(NULL, val, DATEOID);
798  jb.val.string.len = strlen(jb.val.string.val);
799  break;
800  case JSONBTYPE_TIMESTAMP:
801  jb.type = jbvString;
802  jb.val.string.val = JsonEncodeDateTime(NULL, val, TIMESTAMPOID);
803  jb.val.string.len = strlen(jb.val.string.val);
804  break;
806  jb.type = jbvString;
807  jb.val.string.val = JsonEncodeDateTime(NULL, val, TIMESTAMPTZOID);
808  jb.val.string.len = strlen(jb.val.string.val);
809  break;
810  case JSONBTYPE_JSONCAST:
811  case JSONBTYPE_JSON:
812  {
813  /* parse the json right into the existing result object */
814  JsonLexContext *lex;
815  JsonSemAction sem;
816  text *json = DatumGetTextPP(val);
817 
818  lex = makeJsonLexContext(json, true);
819 
820  memset(&sem, 0, sizeof(sem));
821 
822  sem.semstate = (void *) result;
823 
828  sem.scalar = jsonb_in_scalar;
830 
831  pg_parse_json(lex, &sem);
832 
833  }
834  break;
835  case JSONBTYPE_JSONB:
836  {
837  Jsonb *jsonb = DatumGetJsonbP(val);
838  JsonbIterator *it;
839 
840  it = JsonbIteratorInit(&jsonb->root);
841 
842  if (JB_ROOT_IS_SCALAR(jsonb))
843  {
844  (void) JsonbIteratorNext(&it, &jb, true);
845  Assert(jb.type == jbvArray);
846  (void) JsonbIteratorNext(&it, &jb, true);
847  scalar_jsonb = true;
848  }
849  else
850  {
852 
853  while ((type = JsonbIteratorNext(&it, &jb, false))
854  != WJB_DONE)
855  {
856  if (type == WJB_END_ARRAY || type == WJB_END_OBJECT ||
857  type == WJB_BEGIN_ARRAY || type == WJB_BEGIN_OBJECT)
858  result->res = pushJsonbValue(&result->parseState,
859  type, NULL);
860  else
861  result->res = pushJsonbValue(&result->parseState,
862  type, &jb);
863  }
864  }
865  }
866  break;
867  default:
868  outputstr = OidOutputFunctionCall(outfuncoid, val);
869  jb.type = jbvString;
870  jb.val.string.len = checkStringLen(strlen(outputstr));
871  jb.val.string.val = outputstr;
872  break;
873  }
874  }
875 
876  /* Now insert jb into result, unless we did it recursively */
877  if (!is_null && !scalar_jsonb &&
878  tcategory >= JSONBTYPE_JSON && tcategory <= JSONBTYPE_JSONCAST)
879  {
880  /* work has been done recursively */
881  return;
882  }
883  else if (result->parseState == NULL)
884  {
885  /* single root scalar */
886  JsonbValue va;
887 
888  va.type = jbvArray;
889  va.val.array.rawScalar = true;
890  va.val.array.nElems = 1;
891 
892  result->res = pushJsonbValue(&result->parseState, WJB_BEGIN_ARRAY, &va);
893  result->res = pushJsonbValue(&result->parseState, WJB_ELEM, &jb);
894  result->res = pushJsonbValue(&result->parseState, WJB_END_ARRAY, NULL);
895  }
896  else
897  {
898  JsonbValue *o = &result->parseState->contVal;
899 
900  switch (o->type)
901  {
902  case jbvArray:
903  result->res = pushJsonbValue(&result->parseState, WJB_ELEM, &jb);
904  break;
905  case jbvObject:
906  result->res = pushJsonbValue(&result->parseState,
907  key_scalar ? WJB_KEY : WJB_VALUE,
908  &jb);
909  break;
910  default:
911  elog(ERROR, "unexpected parent of nested structure");
912  }
913  }
914 }
json_struct_action array_end
Definition: jsonapi.h:88
static void array_to_jsonb_internal(Datum array, JsonbInState *result)
Definition: jsonb.c:954
JsonbParseState * parseState
Definition: jsonb.c:34
JsonbValue * res
Definition: jsonb.c:35
static void jsonb_in_object_end(void *pstate)
Definition: jsonb.c:274
Definition: jsonb.h:215
json_struct_action object_end
Definition: jsonapi.h:86
static void jsonb_in_array_start(void *pstate)
Definition: jsonb.c:282
#define DatumGetJsonbP(d)
Definition: jsonb.h:68
char * val
Definition: jsonb.h:259
#define DatumGetTextPP(X)
Definition: fmgr.h:261
Definition: jsonb.h:234
json_struct_action object_start
Definition: jsonapi.h:85
Definition: jsonb.h:22
int errcode(int sqlerrcode)
Definition: elog.c:575
json_scalar_action scalar
Definition: jsonapi.h:93
static void jsonb_in_scalar(void *pstate, char *token, JsonTokenType tokentype)
Definition: jsonb.c:342
Definition: jsonb.h:231
#define JB_ROOT_IS_SCALAR(jbp_)
Definition: jsonb.h:223
static void jsonb_in_array_end(void *pstate)
Definition: jsonb.c:290
JsonbValue * pushJsonbValue(JsonbParseState **pstate, JsonbIteratorToken seq, JsonbValue *jbval)
Definition: jsonb_util.c:517
JsonLexContext * makeJsonLexContext(text *json, bool need_escapes)
Definition: json.c:301
void pfree(void *pointer)
Definition: mcxt.c:1031
#define ObjectIdGetDatum(X)
Definition: postgres.h:492
#define ERROR
Definition: elog.h:43
void pg_parse_json(JsonLexContext *lex, JsonSemAction *sem)
Definition: json.c:332
#define OidFunctionCall1(functionId, arg1)
Definition: fmgr.h:628
static size_t checkStringLen(size_t len)
Definition: jsonb.c:253
void check_stack_depth(void)
Definition: postgres.c:3159
#define CStringGetDatum(X)
Definition: postgres.h:563
#define DatumGetBool(X)
Definition: postgres.h:378
Datum numeric_in(PG_FUNCTION_ARGS)
Definition: numeric.c:570
Definition: jsonb.h:23
#define ereport(elevel, rest)
Definition: elog.h:122
JsonbIteratorToken
Definition: jsonb.h:20
#define DirectFunctionCall3(func, arg1, arg2, arg3)
Definition: fmgr.h:594
JsonbContainer root
Definition: jsonb.h:218
static void composite_to_jsonb(Datum composite, JsonbInState *result)
Definition: jsonb.c:1002
uintptr_t Datum
Definition: postgres.h:367
JsonbValue contVal
Definition: jsonb.h:306
#define InvalidOid
Definition: postgres_ext.h:36
#define DatumGetNumeric(X)
Definition: numeric.h:49
#define Assert(condition)
Definition: c.h:699
JsonbIterator * JsonbIteratorInit(JsonbContainer *container)
Definition: jsonb_util.c:718
json_struct_action array_start
Definition: jsonapi.h:87
enum jbvType type
Definition: jsonb.h:250
static void jsonb_in_object_start(void *pstate)
Definition: jsonb.c:266
#define Int32GetDatum(X)
Definition: postgres.h:464
char * OidOutputFunctionCall(Oid functionId, Datum val)
Definition: fmgr.c:1833
int errmsg(const char *fmt,...)
Definition: elog.c:797
char * JsonEncodeDateTime(char *buf, Datum value, Oid typid)
Definition: json.c:1556
Definition: c.h:516
json_ofield_action object_field_start
Definition: jsonapi.h:89
#define elog
Definition: elog.h:219
static void jsonb_in_object_field_start(void *pstate, char *fname, bool isnull)
Definition: jsonb.c:298
void * semstate
Definition: jsonapi.h:84
long val
Definition: informix.c:689
JsonbIteratorToken JsonbIteratorNext(JsonbIterator **it, JsonbValue *val, bool skipNested)
Definition: jsonb_util.c:754
Definition: jsonb.h:25

◆ jsonb_agg_finalfn()

Datum jsonb_agg_finalfn ( PG_FUNCTION_ARGS  )

Definition at line 1593 of file jsonb.c.

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

1594 {
1595  JsonbAggState *arg;
1596  JsonbInState result;
1597  Jsonb *out;
1598 
1599  /* cannot be called directly because of internal-type argument */
1600  Assert(AggCheckCallContext(fcinfo, NULL));
1601 
1602  if (PG_ARGISNULL(0))
1603  PG_RETURN_NULL(); /* returns null iff no input values */
1604 
1605  arg = (JsonbAggState *) PG_GETARG_POINTER(0);
1606 
1607  /*
1608  * We need to do a shallow clone of the argument in case the final
1609  * function is called more than once, so we avoid changing the argument. A
1610  * shallow clone is sufficient as we aren't going to change any of the
1611  * values, just add the final array end marker.
1612  */
1613 
1614  result.parseState = clone_parse_state(arg->res->parseState);
1615 
1616  result.res = pushJsonbValue(&result.parseState,
1617  WJB_END_ARRAY, NULL);
1618 
1619  out = JsonbValueToJsonb(result.res);
1620 
1621  PG_RETURN_POINTER(out);
1622 }
JsonbParseState * parseState
Definition: jsonb.c:34
JsonbValue * res
Definition: jsonb.c:35
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:326
Jsonb * JsonbValueToJsonb(JsonbValue *val)
Definition: jsonb_util.c:79
Definition: jsonb.h:215
static JsonbParseState * clone_parse_state(JsonbParseState *state)
Definition: jsonb.c:1443
JsonbInState * res
Definition: jsonb.c:57
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:246
JsonbValue * pushJsonbValue(JsonbParseState **pstate, JsonbIteratorToken seq, JsonbValue *jbval)
Definition: jsonb_util.c:517
#define PG_ARGISNULL(n)
Definition: fmgr.h:179
#define Assert(condition)
Definition: c.h:699
int AggCheckCallContext(FunctionCallInfo fcinfo, MemoryContext *aggcontext)
Definition: nodeAgg.c:3492
void * arg
#define PG_RETURN_NULL()
Definition: fmgr.h:310

◆ jsonb_agg_transfn()

Datum jsonb_agg_transfn ( PG_FUNCTION_ARGS  )

Definition at line 1475 of file jsonb.c.

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, JsonbAggState::res, Jsonb::root, snprintf(), generate_unaccent_rules::type, JsonbValue::type, JsonbValue::val, val, JsonbAggState::val_category, JsonbAggState::val_output_func, WJB_BEGIN_ARRAY, WJB_BEGIN_OBJECT, WJB_DONE, WJB_ELEM, WJB_END_ARRAY, WJB_END_OBJECT, WJB_KEY, and WJB_VALUE.

1476 {
1477  MemoryContext oldcontext,
1478  aggcontext;
1480  JsonbInState elem;
1481  Datum val;
1482  JsonbInState *result;
1483  bool single_scalar = false;
1484  JsonbIterator *it;
1485  Jsonb *jbelem;
1486  JsonbValue v;
1488 
1489  if (!AggCheckCallContext(fcinfo, &aggcontext))
1490  {
1491  /* cannot be called directly because of internal-type argument */
1492  elog(ERROR, "jsonb_agg_transfn called in non-aggregate context");
1493  }
1494 
1495  /* set up the accumulator on the first go round */
1496 
1497  if (PG_ARGISNULL(0))
1498  {
1499  Oid arg_type = get_fn_expr_argtype(fcinfo->flinfo, 1);
1500 
1501  if (arg_type == InvalidOid)
1502  ereport(ERROR,
1503  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1504  errmsg("could not determine input data type")));
1505 
1506  oldcontext = MemoryContextSwitchTo(aggcontext);
1507  state = palloc(sizeof(JsonbAggState));
1508  result = palloc0(sizeof(JsonbInState));
1509  state->res = result;
1510  result->res = pushJsonbValue(&result->parseState,
1511  WJB_BEGIN_ARRAY, NULL);
1512  MemoryContextSwitchTo(oldcontext);
1513 
1514  jsonb_categorize_type(arg_type, &state->val_category,
1515  &state->val_output_func);
1516  }
1517  else
1518  {
1519  state = (JsonbAggState *) PG_GETARG_POINTER(0);
1520  result = state->res;
1521  }
1522 
1523  /* turn the argument into jsonb in the normal function context */
1524 
1525  val = PG_ARGISNULL(1) ? (Datum) 0 : PG_GETARG_DATUM(1);
1526 
1527  memset(&elem, 0, sizeof(JsonbInState));
1528 
1529  datum_to_jsonb(val, PG_ARGISNULL(1), &elem, state->val_category,
1530  state->val_output_func, false);
1531 
1532  jbelem = JsonbValueToJsonb(elem.res);
1533 
1534  /* switch to the aggregate context for accumulation operations */
1535 
1536  oldcontext = MemoryContextSwitchTo(aggcontext);
1537 
1538  it = JsonbIteratorInit(&jbelem->root);
1539 
1540  while ((type = JsonbIteratorNext(&it, &v, false)) != WJB_DONE)
1541  {
1542  switch (type)
1543  {
1544  case WJB_BEGIN_ARRAY:
1545  if (v.val.array.rawScalar)
1546  single_scalar = true;
1547  else
1548  result->res = pushJsonbValue(&result->parseState,
1549  type, NULL);
1550  break;
1551  case WJB_END_ARRAY:
1552  if (!single_scalar)
1553  result->res = pushJsonbValue(&result->parseState,
1554  type, NULL);
1555  break;
1556  case WJB_BEGIN_OBJECT:
1557  case WJB_END_OBJECT:
1558  result->res = pushJsonbValue(&result->parseState,
1559  type, NULL);
1560  break;
1561  case WJB_ELEM:
1562  case WJB_KEY:
1563  case WJB_VALUE:
1564  if (v.type == jbvString)
1565  {
1566  /* copy string values in the aggregate context */
1567  char *buf = palloc(v.val.string.len + 1);
1568 
1569  snprintf(buf, v.val.string.len + 1, "%s", v.val.string.val);
1570  v.val.string.val = buf;
1571  }
1572  else if (v.type == jbvNumeric)
1573  {
1574  /* same for numeric */
1575  v.val.numeric =
1577  NumericGetDatum(v.val.numeric)));
1578  }
1579  result->res = pushJsonbValue(&result->parseState,
1580  type, &v);
1581  break;
1582  default:
1583  elog(ERROR, "unknown jsonb iterator token type");
1584  }
1585  }
1586 
1587  MemoryContextSwitchTo(oldcontext);
1588 
1589  PG_RETURN_POINTER(state);
1590 }
JsonbParseState * parseState
Definition: jsonb.c:34
JsonbValue * res
Definition: jsonb.c:35
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:326
Jsonb * JsonbValueToJsonb(JsonbValue *val)
Definition: jsonb_util.c:79
Definition: jsonb.h:215
Datum numeric_uplus(PG_FUNCTION_ARGS)
Definition: numeric.c:1159
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:238
char * val
Definition: jsonb.h:259
#define NumericGetDatum(X)
Definition: numeric.h:51
JsonbInState * res
Definition: jsonb.c:57
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
Definition: jsonb.h:22
int errcode(int sqlerrcode)
Definition: elog.c:575
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:246
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:590
unsigned int Oid
Definition: postgres_ext.h:31
JsonbTypeCategory val_category
Definition: jsonb.c:60
static void datum_to_jsonb(Datum val, bool is_null, JsonbInState *result, JsonbTypeCategory tcategory, Oid outfuncoid, bool key_scalar)
Definition: jsonb.c:702
JsonbValue * pushJsonbValue(JsonbParseState **pstate, JsonbIteratorToken seq, JsonbValue *jbval)
Definition: jsonb_util.c:517
#define ERROR
Definition: elog.h:43
Oid get_fn_expr_argtype(FmgrInfo *flinfo, int argnum)
Definition: fmgr.c:1995
static char * buf
Definition: pg_test_fsync.c:67
static void jsonb_categorize_type(Oid typoid, JsonbTypeCategory *tcategory, Oid *outfuncoid)
Definition: jsonb.c:594
Definition: jsonb.h:23
#define ereport(elevel, rest)
Definition: elog.h:122
JsonbIteratorToken
Definition: jsonb.h:20
JsonbContainer root
Definition: jsonb.h:218
void * palloc0(Size size)
Definition: mcxt.c:955
uintptr_t Datum
Definition: postgres.h:367
#define InvalidOid
Definition: postgres_ext.h:36
#define PG_ARGISNULL(n)
Definition: fmgr.h:179
#define DatumGetNumeric(X)
Definition: numeric.h:49
JsonbIterator * JsonbIteratorInit(JsonbContainer *container)
Definition: jsonb_util.c:718
Definition: regguts.h:298
int AggCheckCallContext(FunctionCallInfo fcinfo, MemoryContext *aggcontext)
Definition: nodeAgg.c:3492
enum jbvType type
Definition: jsonb.h:250
void * palloc(Size size)
Definition: mcxt.c:924
int errmsg(const char *fmt,...)
Definition: elog.c:797
Oid val_output_func
Definition: jsonb.c:61
#define elog
Definition: elog.h:219
long val
Definition: informix.c:689
JsonbIteratorToken JsonbIteratorNext(JsonbIterator **it, JsonbValue *val, bool skipNested)
Definition: jsonb_util.c:754
Definition: jsonb.h:25

◆ jsonb_bool()

Datum jsonb_bool ( PG_FUNCTION_ARGS  )

Definition at line 1931 of file jsonb.c.

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

1932 {
1933  Jsonb *in = PG_GETARG_JSONB_P(0);
1934  JsonbValue v;
1935 
1936  if (!JsonbExtractScalar(&in->root, &v) || v.type != jbvBool)
1937  cannotCastJsonbValue(v.type, "boolean");
1938 
1939  PG_FREE_IF_COPY(in, 0);
1940 
1941  PG_RETURN_BOOL(v.val.boolean);
1942 }
Definition: jsonb.h:215
char * val
Definition: jsonb.h:259
Definition: jsonb.h:234
static void cannotCastJsonbValue(enum jbvType type, const char *sqltype)
Definition: jsonb.c:1901
static bool JsonbExtractScalar(JsonbContainer *jbc, JsonbValue *res)
Definition: jsonb.c:1861
JsonbContainer root
Definition: jsonb.h:218
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:324
#define PG_FREE_IF_COPY(ptr, n)
Definition: fmgr.h:230
enum jbvType type
Definition: jsonb.h:250
#define PG_GETARG_JSONB_P(x)
Definition: jsonb.h:70

◆ jsonb_build_array()

Datum jsonb_build_array ( PG_FUNCTION_ARGS  )

Definition at line 1192 of file jsonb.c.

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.

1193 {
1194  int nargs;
1195  int i;
1196  JsonbInState result;
1197  Datum *args;
1198  bool *nulls;
1199  Oid *types;
1200 
1201  /* build argument values to build the array */
1202  nargs = extract_variadic_args(fcinfo, 0, true, &args, &types, &nulls);
1203 
1204  if (nargs < 0)
1205  PG_RETURN_NULL();
1206 
1207  memset(&result, 0, sizeof(JsonbInState));
1208 
1209  result.res = pushJsonbValue(&result.parseState, WJB_BEGIN_ARRAY, NULL);
1210 
1211  for (i = 0; i < nargs; i++)
1212  add_jsonb(args[i], nulls[i], &result, types[i], false);
1213 
1214  result.res = pushJsonbValue(&result.parseState, WJB_END_ARRAY, NULL);
1215 
1217 }
JsonbParseState * parseState
Definition: jsonb.c:34
JsonbValue * res
Definition: jsonb.c:35
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:326
Jsonb * JsonbValueToJsonb(JsonbValue *val)
Definition: jsonb_util.c:79
int extract_variadic_args(FunctionCallInfo fcinfo, int variadic_start, bool convert_unknown, Datum **args, Oid **types, bool **nulls)
Definition: funcapi.c:1479
struct typedefs * types
Definition: ecpg.c:29
static void add_jsonb(Datum val, bool is_null, JsonbInState *result, Oid val_type, bool key_scalar)
Definition: jsonb.c:1074
unsigned int Oid
Definition: postgres_ext.h:31
JsonbValue * pushJsonbValue(JsonbParseState **pstate, JsonbIteratorToken seq, JsonbValue *jbval)
Definition: jsonb_util.c:517
uintptr_t Datum
Definition: postgres.h:367
int i
#define PG_RETURN_NULL()
Definition: fmgr.h:310

◆ jsonb_build_array_noargs()

Datum jsonb_build_array_noargs ( PG_FUNCTION_ARGS  )

Definition at line 1223 of file jsonb.c.

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

1224 {
1225  JsonbInState result;
1226 
1227  memset(&result, 0, sizeof(JsonbInState));
1228 
1229  (void) pushJsonbValue(&result.parseState, WJB_BEGIN_ARRAY, NULL);
1230  result.res = pushJsonbValue(&result.parseState, WJB_END_ARRAY, NULL);
1231 
1233 }
JsonbParseState * parseState
Definition: jsonb.c:34
JsonbValue * res
Definition: jsonb.c:35
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:326
Jsonb * JsonbValueToJsonb(JsonbValue *val)
Definition: jsonb_util.c:79
JsonbValue * pushJsonbValue(JsonbParseState **pstate, JsonbIteratorToken seq, JsonbValue *jbval)
Definition: jsonb_util.c:517

◆ jsonb_build_object()

Datum jsonb_build_object ( PG_FUNCTION_ARGS  )

Definition at line 1128 of file jsonb.c.

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.

1129 {
1130  int nargs;
1131  int i;
1132  JsonbInState result;
1133  Datum *args;
1134  bool *nulls;
1135  Oid *types;
1136 
1137  /* build argument values to build the object */
1138  nargs = extract_variadic_args(fcinfo, 0, true, &args, &types, &nulls);
1139 
1140  if (nargs < 0)
1141  PG_RETURN_NULL();
1142 
1143  if (nargs % 2 != 0)
1144  ereport(ERROR,
1145  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1146  errmsg("argument list must have even number of elements"),
1147  errhint("The arguments of jsonb_build_object() must consist of alternating keys and values.")));
1148 
1149  memset(&result, 0, sizeof(JsonbInState));
1150 
1151  result.res = pushJsonbValue(&result.parseState, WJB_BEGIN_OBJECT, NULL);
1152 
1153  for (i = 0; i < nargs; i += 2)
1154  {
1155  /* process key */
1156  if (nulls[i])
1157  ereport(ERROR,
1158  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1159  errmsg("argument %d: key must not be null", i + 1)));
1160 
1161  add_jsonb(args[i], false, &result, types[i], true);
1162 
1163  /* process value */
1164  add_jsonb(args[i + 1], nulls[i + 1], &result, types[i + 1], false);
1165  }
1166 
1167  result.res = pushJsonbValue(&result.parseState, WJB_END_OBJECT, NULL);
1168 
1170 }
JsonbParseState * parseState
Definition: jsonb.c:34
JsonbValue * res
Definition: jsonb.c:35
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:326
int errhint(const char *fmt,...)
Definition: elog.c:987
Jsonb * JsonbValueToJsonb(JsonbValue *val)
Definition: jsonb_util.c:79
int extract_variadic_args(FunctionCallInfo fcinfo, int variadic_start, bool convert_unknown, Datum **args, Oid **types, bool **nulls)
Definition: funcapi.c:1479
struct typedefs * types
Definition: ecpg.c:29
static void add_jsonb(Datum val, bool is_null, JsonbInState *result, Oid val_type, bool key_scalar)
Definition: jsonb.c:1074
int errcode(int sqlerrcode)
Definition: elog.c:575
unsigned int Oid
Definition: postgres_ext.h:31
JsonbValue * pushJsonbValue(JsonbParseState **pstate, JsonbIteratorToken seq, JsonbValue *jbval)
Definition: jsonb_util.c:517
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:122
uintptr_t Datum
Definition: postgres.h:367
int errmsg(const char *fmt,...)
Definition: elog.c:797
int i
#define PG_RETURN_NULL()
Definition: fmgr.h:310

◆ jsonb_build_object_noargs()

Datum jsonb_build_object_noargs ( PG_FUNCTION_ARGS  )

Definition at line 1176 of file jsonb.c.

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

1177 {
1178  JsonbInState result;
1179 
1180  memset(&result, 0, sizeof(JsonbInState));
1181 
1182  (void) pushJsonbValue(&result.parseState, WJB_BEGIN_OBJECT, NULL);
1183  result.res = pushJsonbValue(&result.parseState, WJB_END_OBJECT, NULL);
1184 
1186 }
JsonbParseState * parseState
Definition: jsonb.c:34
JsonbValue * res
Definition: jsonb.c:35
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:326
Jsonb * JsonbValueToJsonb(JsonbValue *val)
Definition: jsonb_util.c:79
JsonbValue * pushJsonbValue(JsonbParseState **pstate, JsonbIteratorToken seq, JsonbValue *jbval)
Definition: jsonb_util.c:517

◆ jsonb_categorize_type()

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

Definition at line 594 of file jsonb.c.

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

597 {
598  bool typisvarlena;
599 
600  /* Look through any domain */
601  typoid = getBaseType(typoid);
602 
603  *outfuncoid = InvalidOid;
604 
605  /*
606  * We need to get the output function for everything except date and
607  * timestamp types, booleans, array and composite types, json and jsonb,
608  * and non-builtin types where there's a cast to json. In this last case
609  * we return the oid of the cast function instead.
610  */
611 
612  switch (typoid)
613  {
614  case BOOLOID:
615  *tcategory = JSONBTYPE_BOOL;
616  break;
617 
618  case INT2OID:
619  case INT4OID:
620  case INT8OID:
621  case FLOAT4OID:
622  case FLOAT8OID:
623  case NUMERICOID:
624  getTypeOutputInfo(typoid, outfuncoid, &typisvarlena);
625  *tcategory = JSONBTYPE_NUMERIC;
626  break;
627 
628  case DATEOID:
629  *tcategory = JSONBTYPE_DATE;
630  break;
631 
632  case TIMESTAMPOID:
633  *tcategory = JSONBTYPE_TIMESTAMP;
634  break;
635 
636  case TIMESTAMPTZOID:
637  *tcategory = JSONBTYPE_TIMESTAMPTZ;
638  break;
639 
640  case JSONBOID:
641  *tcategory = JSONBTYPE_JSONB;
642  break;
643 
644  case JSONOID:
645  *tcategory = JSONBTYPE_JSON;
646  break;
647 
648  default:
649  /* Check for arrays and composites */
650  if (OidIsValid(get_element_type(typoid)) || typoid == ANYARRAYOID
651  || typoid == RECORDARRAYOID)
652  *tcategory = JSONBTYPE_ARRAY;
653  else if (type_is_rowtype(typoid)) /* includes RECORDOID */
654  *tcategory = JSONBTYPE_COMPOSITE;
655  else
656  {
657  /* It's probably the general case ... */
658  *tcategory = JSONBTYPE_OTHER;
659 
660  /*
661  * but first let's look for a cast to json (note: not to
662  * jsonb) if it's not built-in.
663  */
664  if (typoid >= FirstNormalObjectId)
665  {
666  Oid castfunc;
667  CoercionPathType ctype;
668 
669  ctype = find_coercion_pathway(JSONOID, typoid,
670  COERCION_EXPLICIT, &castfunc);
671  if (ctype == COERCION_PATH_FUNC && OidIsValid(castfunc))
672  {
673  *tcategory = JSONBTYPE_JSONCAST;
674  *outfuncoid = castfunc;
675  }
676  else
677  {
678  /* not a cast type, so just get the usual output func */
679  getTypeOutputInfo(typoid, outfuncoid, &typisvarlena);
680  }
681  }
682  else
683  {
684  /* any other builtin type */
685  getTypeOutputInfo(typoid, outfuncoid, &typisvarlena);
686  }
687  break;
688  }
689  }
690 }
void getTypeOutputInfo(Oid type, Oid *typOutput, bool *typIsVarlena)
Definition: lsyscache.c:2650
Oid get_element_type(Oid typid)
Definition: lsyscache.c:2502
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:605
CoercionPathType
Definition: parse_coerce.h:24
#define FirstNormalObjectId
Definition: transam.h:94
bool type_is_rowtype(Oid typid)
Definition: lsyscache.c:2409
#define InvalidOid
Definition: postgres_ext.h:36
CoercionPathType find_coercion_pathway(Oid targetTypeId, Oid sourceTypeId, CoercionContext ccontext, Oid *funcid)
Oid getBaseType(Oid typid)
Definition: lsyscache.c:2275

◆ jsonb_float4()

Datum jsonb_float4 ( PG_FUNCTION_ARGS  )

Definition at line 2020 of file jsonb.c.

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.

2021 {
2022  Jsonb *in = PG_GETARG_JSONB_P(0);
2023  JsonbValue v;
2024  Datum retValue;
2025 
2026  if (!JsonbExtractScalar(&in->root, &v) || v.type != jbvNumeric)
2027  cannotCastJsonbValue(v.type, "real");
2028 
2030  NumericGetDatum(v.val.numeric));
2031 
2032  PG_FREE_IF_COPY(in, 0);
2033 
2034  PG_RETURN_DATUM(retValue);
2035 }
Definition: jsonb.h:215
char * val
Definition: jsonb.h:259
#define NumericGetDatum(X)
Definition: numeric.h:51
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:590
static void cannotCastJsonbValue(enum jbvType type, const char *sqltype)
Definition: jsonb.c:1901
static bool JsonbExtractScalar(JsonbContainer *jbc, JsonbValue *res)
Definition: jsonb.c:1861
Datum numeric_float4(PG_FUNCTION_ARGS)
Definition: numeric.c:3332
JsonbContainer root
Definition: jsonb.h:218
uintptr_t Datum
Definition: postgres.h:367
#define PG_RETURN_DATUM(x)
Definition: fmgr.h:318
#define PG_FREE_IF_COPY(ptr, n)
Definition: fmgr.h:230
enum jbvType type
Definition: jsonb.h:250
#define PG_GETARG_JSONB_P(x)
Definition: jsonb.h:70

◆ jsonb_float8()

Datum jsonb_float8 ( PG_FUNCTION_ARGS  )

Definition at line 2038 of file jsonb.c.

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.

2039 {
2040  Jsonb *in = PG_GETARG_JSONB_P(0);
2041  JsonbValue v;
2042  Datum retValue;
2043 
2044  if (!JsonbExtractScalar(&in->root, &v) || v.type != jbvNumeric)
2045  cannotCastJsonbValue(v.type, "double precision");
2046 
2048  NumericGetDatum(v.val.numeric));
2049 
2050  PG_FREE_IF_COPY(in, 0);
2051 
2052  PG_RETURN_DATUM(retValue);
2053 }
Definition: jsonb.h:215
char * val
Definition: jsonb.h:259
#define NumericGetDatum(X)
Definition: numeric.h:51
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:590
static void cannotCastJsonbValue(enum jbvType type, const char *sqltype)
Definition: jsonb.c:1901
static bool JsonbExtractScalar(JsonbContainer *jbc, JsonbValue *res)
Definition: jsonb.c:1861
Datum numeric_float8(PG_FUNCTION_ARGS)
Definition: numeric.c:3261
JsonbContainer root
Definition: jsonb.h:218
uintptr_t Datum
Definition: postgres.h:367
#define PG_RETURN_DATUM(x)
Definition: fmgr.h:318
#define PG_FREE_IF_COPY(ptr, n)
Definition: fmgr.h:230
enum jbvType type
Definition: jsonb.h:250
#define PG_GETARG_JSONB_P(x)
Definition: jsonb.h:70

◆ jsonb_from_cstring()

static Datum jsonb_from_cstring ( char *  json,
int  len 
)
inlinestatic

Definition at line 227 of file jsonb.c.

References JsonSemAction::array_end, JsonSemAction::array_start, 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(), makeJsonLexContextCstringLen(), JsonSemAction::object_end, JsonSemAction::object_field_start, JsonSemAction::object_start, pg_parse_json(), PG_RETURN_POINTER, JsonbInState::res, JsonSemAction::scalar, and JsonSemAction::semstate.

Referenced by jsonb_in(), and jsonb_recv().

228 {
229  JsonLexContext *lex;
231  JsonSemAction sem;
232 
233  memset(&state, 0, sizeof(state));
234  memset(&sem, 0, sizeof(sem));
235  lex = makeJsonLexContextCstringLen(json, len, true);
236 
237  sem.semstate = (void *) &state;
238 
243  sem.scalar = jsonb_in_scalar;
245 
246  pg_parse_json(lex, &sem);
247 
248  /* after parsing, the item member has the composed jsonb structure */
250 }
json_struct_action array_end
Definition: jsonapi.h:88
JsonbValue * res
Definition: jsonb.c:35
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:326
static void jsonb_in_object_end(void *pstate)
Definition: jsonb.c:274
Jsonb * JsonbValueToJsonb(JsonbValue *val)
Definition: jsonb_util.c:79
json_struct_action object_end
Definition: jsonapi.h:86
static void jsonb_in_array_start(void *pstate)
Definition: jsonb.c:282
json_struct_action object_start
Definition: jsonapi.h:85
json_scalar_action scalar
Definition: jsonapi.h:93
static void jsonb_in_scalar(void *pstate, char *token, JsonTokenType tokentype)
Definition: jsonb.c:342
static void jsonb_in_array_end(void *pstate)
Definition: jsonb.c:290
void pg_parse_json(JsonLexContext *lex, JsonSemAction *sem)
Definition: json.c:332
json_struct_action array_start
Definition: jsonapi.h:87
Definition: regguts.h:298
JsonLexContext * makeJsonLexContextCstringLen(char *json, int len, bool need_escapes)
Definition: json.c:309
static void jsonb_in_object_start(void *pstate)
Definition: jsonb.c:266
json_ofield_action object_field_start
Definition: jsonapi.h:89
static void jsonb_in_object_field_start(void *pstate, char *fname, bool isnull)
Definition: jsonb.c:298
void * semstate
Definition: jsonapi.h:84

◆ jsonb_in()

Datum jsonb_in ( PG_FUNCTION_ARGS  )

Definition at line 97 of file jsonb.c.

References jsonb_from_cstring(), and PG_GETARG_CSTRING.

98 {
99  char *json = PG_GETARG_CSTRING(0);
100 
101  return jsonb_from_cstring(json, strlen(json));
102 }
static Datum jsonb_from_cstring(char *json, int len)
Definition: jsonb.c:227
#define PG_GETARG_CSTRING(n)
Definition: fmgr.h:247

◆ jsonb_in_array_end()

static void jsonb_in_array_end ( void *  pstate)
static

Definition at line 290 of file jsonb.c.

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

Referenced by datum_to_jsonb(), and jsonb_from_cstring().

291 {
292  JsonbInState *_state = (JsonbInState *) pstate;
293 
294  _state->res = pushJsonbValue(&_state->parseState, WJB_END_ARRAY, NULL);
295 }
JsonbParseState * parseState
Definition: jsonb.c:34
JsonbValue * res
Definition: jsonb.c:35
JsonbValue * pushJsonbValue(JsonbParseState **pstate, JsonbIteratorToken seq, JsonbValue *jbval)
Definition: jsonb_util.c:517

◆ jsonb_in_array_start()

static void jsonb_in_array_start ( void *  pstate)
static

Definition at line 282 of file jsonb.c.

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

Referenced by datum_to_jsonb(), and jsonb_from_cstring().

283 {
284  JsonbInState *_state = (JsonbInState *) pstate;
285 
286  _state->res = pushJsonbValue(&_state->parseState, WJB_BEGIN_ARRAY, NULL);
287 }
JsonbParseState * parseState
Definition: jsonb.c:34
JsonbValue * res
Definition: jsonb.c:35
JsonbValue * pushJsonbValue(JsonbParseState **pstate, JsonbIteratorToken seq, JsonbValue *jbval)
Definition: jsonb_util.c:517

◆ jsonb_in_object_end()

static void jsonb_in_object_end ( void *  pstate)
static

Definition at line 274 of file jsonb.c.

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

Referenced by datum_to_jsonb(), and jsonb_from_cstring().

275 {
276  JsonbInState *_state = (JsonbInState *) pstate;
277 
278  _state->res = pushJsonbValue(&_state->parseState, WJB_END_OBJECT, NULL);
279 }
JsonbParseState * parseState
Definition: jsonb.c:34
JsonbValue * res
Definition: jsonb.c:35
JsonbValue * pushJsonbValue(JsonbParseState **pstate, JsonbIteratorToken seq, JsonbValue *jbval)
Definition: jsonb_util.c:517

◆ jsonb_in_object_field_start()

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

Definition at line 298 of file jsonb.c.

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

299 {
300  JsonbInState *_state = (JsonbInState *) pstate;
301  JsonbValue v;
302 
303  Assert(fname != NULL);
304  v.type = jbvString;
305  v.val.string.len = checkStringLen(strlen(fname));
306  v.val.string.val = fname;
307 
308  _state->res = pushJsonbValue(&_state->parseState, WJB_KEY, &v);
309 }
JsonbParseState * parseState
Definition: jsonb.c:34
JsonbValue * res
Definition: jsonb.c:35
char * val
Definition: jsonb.h:259
JsonbValue * pushJsonbValue(JsonbParseState **pstate, JsonbIteratorToken seq, JsonbValue *jbval)
Definition: jsonb_util.c:517
static size_t checkStringLen(size_t len)
Definition: jsonb.c:253
Definition: jsonb.h:23
#define Assert(condition)
Definition: c.h:699
enum jbvType type
Definition: jsonb.h:250

◆ jsonb_in_object_start()

static void jsonb_in_object_start ( void *  pstate)
static

Definition at line 266 of file jsonb.c.

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

Referenced by datum_to_jsonb(), and jsonb_from_cstring().

267 {
268  JsonbInState *_state = (JsonbInState *) pstate;
269 
270  _state->res = pushJsonbValue(&_state->parseState, WJB_BEGIN_OBJECT, NULL);
271 }
JsonbParseState * parseState
Definition: jsonb.c:34
JsonbValue * res
Definition: jsonb.c:35
JsonbValue * pushJsonbValue(JsonbParseState **pstate, JsonbIteratorToken seq, JsonbValue *jbval)
Definition: jsonb_util.c:517

◆ jsonb_in_scalar()

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

Definition at line 342 of file jsonb.c.

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

343 {
344  JsonbInState *_state = (JsonbInState *) pstate;
345  JsonbValue v;
346  Datum numd;
347 
348  switch (tokentype)
349  {
350 
351  case JSON_TOKEN_STRING:
352  Assert(token != NULL);
353  v.type = jbvString;
354  v.val.string.len = checkStringLen(strlen(token));
355  v.val.string.val = token;
356  break;
357  case JSON_TOKEN_NUMBER:
358 
359  /*
360  * No need to check size of numeric values, because maximum
361  * numeric size is well below the JsonbValue restriction
362  */
363  Assert(token != NULL);
364  v.type = jbvNumeric;
366  CStringGetDatum(token),
368  Int32GetDatum(-1));
369  v.val.numeric = DatumGetNumeric(numd);
370  break;
371  case JSON_TOKEN_TRUE:
372  v.type = jbvBool;
373  v.val.boolean = true;
374  break;
375  case JSON_TOKEN_FALSE:
376  v.type = jbvBool;
377  v.val.boolean = false;
378  break;
379  case JSON_TOKEN_NULL:
380  v.type = jbvNull;
381  break;
382  default:
383  /* should not be possible */
384  elog(ERROR, "invalid json token type");
385  break;
386  }
387 
388  if (_state->parseState == NULL)
389  {
390  /* single scalar */
391  JsonbValue va;
392 
393  va.type = jbvArray;
394  va.val.array.rawScalar = true;
395  va.val.array.nElems = 1;
396 
397  _state->res = pushJsonbValue(&_state->parseState, WJB_BEGIN_ARRAY, &va);
398  _state->res = pushJsonbValue(&_state->parseState, WJB_ELEM, &v);
399  _state->res = pushJsonbValue(&_state->parseState, WJB_END_ARRAY, NULL);
400  }
401  else
402  {
403  JsonbValue *o = &_state->parseState->contVal;
404 
405  switch (o->type)
406  {
407  case jbvArray:
408  _state->res = pushJsonbValue(&_state->parseState, WJB_ELEM, &v);
409  break;
410  case jbvObject:
411  _state->res = pushJsonbValue(&_state->parseState, WJB_VALUE, &v);
412  break;
413  default:
414  elog(ERROR, "unexpected parent of nested structure");
415  }
416  }
417 }
JsonbParseState * parseState
Definition: jsonb.c:34
JsonbValue * res
Definition: jsonb.c:35
char * val
Definition: jsonb.h:259
Definition: jsonb.h:234
Definition: jsonb.h:231
JsonbValue * pushJsonbValue(JsonbParseState **pstate, JsonbIteratorToken seq, JsonbValue *jbval)
Definition: jsonb_util.c:517
#define ObjectIdGetDatum(X)
Definition: postgres.h:492
#define ERROR
Definition: elog.h:43
static size_t checkStringLen(size_t len)
Definition: jsonb.c:253
#define CStringGetDatum(X)
Definition: postgres.h:563
Datum numeric_in(PG_FUNCTION_ARGS)
Definition: numeric.c:570
#define DirectFunctionCall3(func, arg1, arg2, arg3)
Definition: fmgr.h:594
uintptr_t Datum
Definition: postgres.h:367
JsonbValue contVal
Definition: jsonb.h:306
#define InvalidOid
Definition: postgres_ext.h:36
#define DatumGetNumeric(X)
Definition: numeric.h:49
#define Assert(condition)
Definition: c.h:699
enum jbvType type
Definition: jsonb.h:250
#define Int32GetDatum(X)
Definition: postgres.h:464
#define elog
Definition: elog.h:219
Definition: jsonb.h:25

◆ jsonb_int2()

Datum jsonb_int2 ( PG_FUNCTION_ARGS  )

Definition at line 1966 of file jsonb.c.

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.

1967 {
1968  Jsonb *in = PG_GETARG_JSONB_P(0);
1969  JsonbValue v;
1970  Datum retValue;
1971 
1972  if (!JsonbExtractScalar(&in->root, &v) || v.type != jbvNumeric)
1973  cannotCastJsonbValue(v.type, "smallint");
1974 
1975  retValue = DirectFunctionCall1(numeric_int2,
1976  NumericGetDatum(v.val.numeric));
1977 
1978  PG_FREE_IF_COPY(in, 0);
1979 
1980  PG_RETURN_DATUM(retValue);
1981 }
Definition: jsonb.h:215
char * val
Definition: jsonb.h:259
#define NumericGetDatum(X)
Definition: numeric.h:51
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:590
static void cannotCastJsonbValue(enum jbvType type, const char *sqltype)
Definition: jsonb.c:1901
static bool JsonbExtractScalar(JsonbContainer *jbc, JsonbValue *res)
Definition: jsonb.c:1861
Datum numeric_int2(PG_FUNCTION_ARGS)
Definition: numeric.c:3195
JsonbContainer root
Definition: jsonb.h:218
uintptr_t Datum
Definition: postgres.h:367
#define PG_RETURN_DATUM(x)
Definition: fmgr.h:318
#define PG_FREE_IF_COPY(ptr, n)
Definition: fmgr.h:230
enum jbvType type
Definition: jsonb.h:250
#define PG_GETARG_JSONB_P(x)
Definition: jsonb.h:70

◆ jsonb_int4()

Datum jsonb_int4 ( PG_FUNCTION_ARGS  )

Definition at line 1984 of file jsonb.c.

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.

1985 {
1986  Jsonb *in = PG_GETARG_JSONB_P(0);
1987  JsonbValue v;
1988  Datum retValue;
1989 
1990  if (!JsonbExtractScalar(&in->root, &v) || v.type != jbvNumeric)
1991  cannotCastJsonbValue(v.type, "integer");
1992 
1993  retValue = DirectFunctionCall1(numeric_int4,
1994  NumericGetDatum(v.val.numeric));
1995 
1996  PG_FREE_IF_COPY(in, 0);
1997 
1998  PG_RETURN_DATUM(retValue);
1999 }
Definition: jsonb.h:215
char * val
Definition: jsonb.h:259
#define NumericGetDatum(X)
Definition: numeric.h:51
Datum numeric_int4(PG_FUNCTION_ARGS)
Definition: numeric.c:3085
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:590
static void cannotCastJsonbValue(enum jbvType type, const char *sqltype)
Definition: jsonb.c:1901
static bool JsonbExtractScalar(JsonbContainer *jbc, JsonbValue *res)
Definition: jsonb.c:1861
JsonbContainer root
Definition: jsonb.h:218
uintptr_t Datum
Definition: postgres.h:367
#define PG_RETURN_DATUM(x)
Definition: fmgr.h:318
#define PG_FREE_IF_COPY(ptr, n)
Definition: fmgr.h:230
enum jbvType type
Definition: jsonb.h:250
#define PG_GETARG_JSONB_P(x)
Definition: jsonb.h:70

◆ jsonb_int8()

Datum jsonb_int8 ( PG_FUNCTION_ARGS  )

Definition at line 2002 of file jsonb.c.

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.

2003 {
2004  Jsonb *in = PG_GETARG_JSONB_P(0);
2005  JsonbValue v;
2006  Datum retValue;
2007 
2008  if (!JsonbExtractScalar(&in->root, &v) || v.type != jbvNumeric)
2009  cannotCastJsonbValue(v.type, "bigint");
2010 
2011  retValue = DirectFunctionCall1(numeric_int8,
2012  NumericGetDatum(v.val.numeric));
2013 
2014  PG_FREE_IF_COPY(in, 0);
2015 
2016  PG_RETURN_DATUM(retValue);
2017 }
Definition: jsonb.h:215
char * val
Definition: jsonb.h:259
#define NumericGetDatum(X)
Definition: numeric.h:51
Datum numeric_int8(PG_FUNCTION_ARGS)
Definition: numeric.c:3151
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:590
static void cannotCastJsonbValue(enum jbvType type, const char *sqltype)
Definition: jsonb.c:1901
static bool JsonbExtractScalar(JsonbContainer *jbc, JsonbValue *res)
Definition: jsonb.c:1861
JsonbContainer root
Definition: jsonb.h:218
uintptr_t Datum
Definition: postgres.h:367
#define PG_RETURN_DATUM(x)
Definition: fmgr.h:318
#define PG_FREE_IF_COPY(ptr, n)
Definition: fmgr.h:230
enum jbvType type
Definition: jsonb.h:250
#define PG_GETARG_JSONB_P(x)
Definition: jsonb.h:70

◆ jsonb_numeric()

Datum jsonb_numeric ( PG_FUNCTION_ARGS  )

Definition at line 1945 of file jsonb.c.

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

1946 {
1947  Jsonb *in = PG_GETARG_JSONB_P(0);
1948  JsonbValue v;
1949  Numeric retValue;
1950 
1951  if (!JsonbExtractScalar(&in->root, &v) || v.type != jbvNumeric)
1952  cannotCastJsonbValue(v.type, "numeric");
1953 
1954  /*
1955  * v.val.numeric points into jsonb body, so we need to make a copy to
1956  * return
1957  */
1958  retValue = DatumGetNumericCopy(NumericGetDatum(v.val.numeric));
1959 
1960  PG_FREE_IF_COPY(in, 0);
1961 
1962  PG_RETURN_NUMERIC(retValue);
1963 }
#define PG_RETURN_NUMERIC(x)
Definition: numeric.h:54
Definition: jsonb.h:215
char * val
Definition: jsonb.h:259
#define NumericGetDatum(X)
Definition: numeric.h:51
#define DatumGetNumericCopy(X)
Definition: numeric.h:50
static void cannotCastJsonbValue(enum jbvType type, const char *sqltype)
Definition: jsonb.c:1901
static bool JsonbExtractScalar(JsonbContainer *jbc, JsonbValue *res)
Definition: jsonb.c:1861
JsonbContainer root
Definition: jsonb.h:218
#define PG_FREE_IF_COPY(ptr, n)
Definition: fmgr.h:230
enum jbvType type
Definition: jsonb.h:250
#define PG_GETARG_JSONB_P(x)
Definition: jsonb.h:70

◆ jsonb_object()

Datum jsonb_object ( PG_FUNCTION_ARGS  )

Definition at line 1244 of file jsonb.c.

References ARR_DIMS, ARR_NDIM, deconstruct_array(), ereport, errcode(), errmsg(), ERROR, i, jbvNull, jbvString, JsonbValueToJsonb(), 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.

1245 {
1246  ArrayType *in_array = PG_GETARG_ARRAYTYPE_P(0);
1247  int ndims = ARR_NDIM(in_array);
1248  Datum *in_datums;
1249  bool *in_nulls;
1250  int in_count,
1251  count,
1252  i;
1253  JsonbInState result;
1254 
1255  memset(&result, 0, sizeof(JsonbInState));
1256 
1257  (void) pushJsonbValue(&result.parseState, WJB_BEGIN_OBJECT, NULL);
1258 
1259  switch (ndims)
1260  {
1261  case 0:
1262  goto close_object;
1263  break;
1264 
1265  case 1:
1266  if ((ARR_DIMS(in_array)[0]) % 2)
1267  ereport(ERROR,
1268  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
1269  errmsg("array must have even number of elements")));
1270  break;
1271 
1272  case 2:
1273  if ((ARR_DIMS(in_array)[1]) != 2)
1274  ereport(ERROR,
1275  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
1276  errmsg("array must have two columns")));
1277  break;
1278 
1279  default:
1280  ereport(ERROR,
1281  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
1282  errmsg("wrong number of array subscripts")));
1283  }
1284 
1285  deconstruct_array(in_array,
1286  TEXTOID, -1, false, 'i',
1287  &in_datums, &in_nulls, &in_count);
1288 
1289  count = in_count / 2;
1290 
1291  for (i = 0; i < count; ++i)
1292  {
1293  JsonbValue v;
1294  char *str;
1295  int len;
1296 
1297  if (in_nulls[i * 2])
1298  ereport(ERROR,
1299  (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
1300  errmsg("null value not allowed for object key")));
1301 
1302  str = TextDatumGetCString(in_datums[i * 2]);
1303  len = strlen(str);
1304 
1305  v.type = jbvString;
1306 
1307  v.val.string.len = len;
1308  v.val.string.val = str;
1309 
1310  (void) pushJsonbValue(&result.parseState, WJB_KEY, &v);
1311 
1312  if (in_nulls[i * 2 + 1])
1313  {
1314  v.type = jbvNull;
1315  }
1316  else
1317  {
1318  str = TextDatumGetCString(in_datums[i * 2 + 1]);
1319  len = strlen(str);
1320 
1321  v.type = jbvString;
1322 
1323  v.val.string.len = len;
1324  v.val.string.val = str;
1325  }
1326 
1327  (void) pushJsonbValue(&result.parseState, WJB_VALUE, &v);
1328  }
1329 
1330  pfree(in_datums);
1331  pfree(in_nulls);
1332 
1333 close_object:
1334  result.res = pushJsonbValue(&result.parseState, WJB_END_OBJECT, NULL);
1335 
1337 }
JsonbParseState * parseState
Definition: jsonb.c:34
JsonbValue * res
Definition: jsonb.c:35
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:326
Jsonb * JsonbValueToJsonb(JsonbValue *val)
Definition: jsonb_util.c:79
char * val
Definition: jsonb.h:259
int errcode(int sqlerrcode)
Definition: elog.c:575
Definition: jsonb.h:231
JsonbValue * pushJsonbValue(JsonbParseState **pstate, JsonbIteratorToken seq, JsonbValue *jbval)
Definition: jsonb_util.c:517
#define PG_GETARG_ARRAYTYPE_P(n)
Definition: array.h:248
void pfree(void *pointer)
Definition: mcxt.c:1031
#define ERROR
Definition: elog.h:43
#define ARR_DIMS(a)
Definition: array.h:279
Definition: jsonb.h:23
#define ereport(elevel, rest)
Definition: elog.h:122
#define TextDatumGetCString(d)
Definition: builtins.h:96
uintptr_t Datum
Definition: postgres.h:367
#define ARR_NDIM(a)
Definition: array.h:275
enum jbvType type
Definition: jsonb.h:250
void deconstruct_array(ArrayType *array, Oid elmtype, int elmlen, bool elmbyval, char elmalign, Datum **elemsp, bool **nullsp, int *nelemsp)
Definition: arrayfuncs.c:3449
int errmsg(const char *fmt,...)
Definition: elog.c:797
int i

◆ jsonb_object_agg_finalfn()

Datum jsonb_object_agg_finalfn ( PG_FUNCTION_ARGS  )

Definition at line 1824 of file jsonb.c.

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

1825 {
1826  JsonbAggState *arg;
1827  JsonbInState result;
1828  Jsonb *out;
1829 
1830  /* cannot be called directly because of internal-type argument */
1831  Assert(AggCheckCallContext(fcinfo, NULL));
1832 
1833  if (PG_ARGISNULL(0))
1834  PG_RETURN_NULL(); /* returns null iff no input values */
1835 
1836  arg = (JsonbAggState *) PG_GETARG_POINTER(0);
1837 
1838  /*
1839  * We need to do a shallow clone of the argument's res field in case the
1840  * final function is called more than once, so we avoid changing the
1841  * aggregate state value. A shallow clone is sufficient as we aren't
1842  * going to change any of the values, just add the final object end
1843  * marker.
1844  */
1845 
1846  result.parseState = clone_parse_state(arg->res->parseState);
1847 
1848  result.res = pushJsonbValue(&result.parseState,
1849  WJB_END_OBJECT, NULL);
1850 
1851  out = JsonbValueToJsonb(result.res);
1852 
1853  PG_RETURN_POINTER(out);
1854 }
JsonbParseState * parseState
Definition: jsonb.c:34
JsonbValue * res
Definition: jsonb.c:35
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:326
Jsonb * JsonbValueToJsonb(JsonbValue *val)
Definition: jsonb_util.c:79
Definition: jsonb.h:215
static JsonbParseState * clone_parse_state(JsonbParseState *state)
Definition: jsonb.c:1443
JsonbInState * res
Definition: jsonb.c:57
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:246
JsonbValue * pushJsonbValue(JsonbParseState **pstate, JsonbIteratorToken seq, JsonbValue *jbval)
Definition: jsonb_util.c:517
#define PG_ARGISNULL(n)
Definition: fmgr.h:179
#define Assert(condition)
Definition: c.h:699
int AggCheckCallContext(FunctionCallInfo fcinfo, MemoryContext *aggcontext)
Definition: nodeAgg.c:3492
void * arg
#define PG_RETURN_NULL()
Definition: fmgr.h:310

◆ jsonb_object_agg_transfn()

Datum jsonb_object_agg_transfn ( PG_FUNCTION_ARGS  )

Definition at line 1628 of file jsonb.c.

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(), JsonbAggState::key_category, JsonbAggState::key_output_func, MemoryContextSwitchTo(), numeric_uplus(), NumericGetDatum, palloc(), palloc0(), JsonbInState::parseState, PG_ARGISNULL, PG_GETARG_DATUM, PG_GETARG_POINTER, PG_RETURN_POINTER, pushJsonbValue(), JsonbInState::res, JsonbAggState::res, Jsonb::root, snprintf(), generate_unaccent_rules::type, JsonbValue::type, JsonbValue::val, val, JsonbAggState::val_category, JsonbAggState::val_output_func, WJB_BEGIN_ARRAY, WJB_BEGIN_OBJECT, WJB_DONE, WJB_ELEM, WJB_END_ARRAY, WJB_END_OBJECT, WJB_KEY, and WJB_VALUE.

1629 {
1630  MemoryContext oldcontext,
1631  aggcontext;
1632  JsonbInState elem;
1634  Datum val;
1635  JsonbInState *result;
1636  bool single_scalar;
1637  JsonbIterator *it;
1638  Jsonb *jbkey,
1639  *jbval;
1640  JsonbValue v;
1642 
1643  if (!AggCheckCallContext(fcinfo, &aggcontext))
1644  {
1645  /* cannot be called directly because of internal-type argument */
1646  elog(ERROR, "jsonb_object_agg_transfn called in non-aggregate context");
1647  }
1648 
1649  /* set up the accumulator on the first go round */
1650 
1651  if (PG_ARGISNULL(0))
1652  {
1653  Oid arg_type;
1654 
1655  oldcontext = MemoryContextSwitchTo(aggcontext);
1656  state = palloc(sizeof(JsonbAggState));
1657  result = palloc0(sizeof(JsonbInState));
1658  state->res = result;
1659  result->res = pushJsonbValue(&result->parseState,
1660  WJB_BEGIN_OBJECT, NULL);
1661  MemoryContextSwitchTo(oldcontext);
1662 
1663  arg_type = get_fn_expr_argtype(fcinfo->flinfo, 1);
1664 
1665  if (arg_type == InvalidOid)
1666  ereport(ERROR,
1667  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1668  errmsg("could not determine input data type")));
1669 
1670  jsonb_categorize_type(arg_type, &state->key_category,
1671  &state->key_output_func);
1672 
1673  arg_type = get_fn_expr_argtype(fcinfo->flinfo, 2);
1674 
1675  if (arg_type == InvalidOid)
1676  ereport(ERROR,
1677  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1678  errmsg("could not determine input data type")));
1679 
1680  jsonb_categorize_type(arg_type, &state->val_category,
1681  &state->val_output_func);
1682  }
1683  else
1684  {
1685  state = (JsonbAggState *) PG_GETARG_POINTER(0);
1686  result = state->res;
1687  }
1688 
1689  /* turn the argument into jsonb in the normal function context */
1690 
1691  if (PG_ARGISNULL(1))
1692  ereport(ERROR,
1693  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1694  errmsg("field name must not be null")));
1695 
1696  val = PG_GETARG_DATUM(1);
1697 
1698  memset(&elem, 0, sizeof(JsonbInState));
1699 
1700  datum_to_jsonb(val, false, &elem, state->key_category,
1701  state->key_output_func, true);
1702 
1703  jbkey = JsonbValueToJsonb(elem.res);
1704 
1705  val = PG_ARGISNULL(2) ? (Datum) 0 : PG_GETARG_DATUM(2);
1706 
1707  memset(&elem, 0, sizeof(JsonbInState));
1708 
1709  datum_to_jsonb(val, PG_ARGISNULL(2), &elem, state->val_category,
1710  state->val_output_func, false);
1711 
1712  jbval = JsonbValueToJsonb(elem.res);
1713 
1714  it = JsonbIteratorInit(&jbkey->root);
1715 
1716  /* switch to the aggregate context for accumulation operations */
1717 
1718  oldcontext = MemoryContextSwitchTo(aggcontext);
1719 
1720  /*
1721  * keys should be scalar, and we should have already checked for that
1722  * above when calling datum_to_jsonb, so we only need to look for these
1723  * things.
1724  */
1725 
1726  while ((type = JsonbIteratorNext(&it, &v, false)) != WJB_DONE)
1727  {
1728  switch (type)
1729  {
1730  case WJB_BEGIN_ARRAY:
1731  if (!v.val.array.rawScalar)
1732  elog(ERROR, "unexpected structure for key");
1733  break;
1734  case WJB_ELEM:
1735  if (v.type == jbvString)
1736  {
1737  /* copy string values in the aggregate context */
1738  char *buf = palloc(v.val.string.len + 1);
1739 
1740  snprintf(buf, v.val.string.len + 1, "%s", v.val.string.val);
1741  v.val.string.val = buf;
1742  }
1743  else
1744  {
1745  ereport(ERROR,
1746  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1747  errmsg("object keys must be strings")));
1748  }
1749  result->res = pushJsonbValue(&result->parseState,
1750  WJB_KEY, &v);
1751  break;
1752  case WJB_END_ARRAY:
1753  break;
1754  default:
1755  elog(ERROR, "unexpected structure for key");
1756  break;
1757  }
1758  }
1759 
1760  it = JsonbIteratorInit(&jbval->root);
1761 
1762  single_scalar = false;
1763 
1764  /*
1765  * values can be anything, including structured and null, so we treat them
1766  * as in json_agg_transfn, except that single scalars are always pushed as
1767  * WJB_VALUE items.
1768  */
1769 
1770  while ((type = JsonbIteratorNext(&it, &v, false)) != WJB_DONE)
1771  {
1772  switch (type)
1773  {
1774  case WJB_BEGIN_ARRAY:
1775  if (v.val.array.rawScalar)
1776  single_scalar = true;
1777  else
1778  result->res = pushJsonbValue(&result->parseState,
1779  type, NULL);
1780  break;
1781  case WJB_END_ARRAY:
1782  if (!single_scalar)
1783  result->res = pushJsonbValue(&result->parseState,
1784  type, NULL);
1785  break;
1786  case WJB_BEGIN_OBJECT:
1787  case WJB_END_OBJECT:
1788  result->res = pushJsonbValue(&result->parseState,
1789  type, NULL);
1790  break;
1791  case WJB_ELEM:
1792  case WJB_KEY:
1793  case WJB_VALUE:
1794  if (v.type == jbvString)
1795  {
1796  /* copy string values in the aggregate context */
1797  char *buf = palloc(v.val.string.len + 1);
1798 
1799  snprintf(buf, v.val.string.len + 1, "%s", v.val.string.val);
1800  v.val.string.val = buf;
1801  }
1802  else if (v.type == jbvNumeric)
1803  {
1804  /* same for numeric */
1805  v.val.numeric =
1807  NumericGetDatum(v.val.numeric)));
1808  }
1809  result->res = pushJsonbValue(&result->parseState,
1810  single_scalar ? WJB_VALUE : type,
1811  &v);
1812  break;
1813  default:
1814  elog(ERROR, "unknown jsonb iterator token type");
1815  }
1816  }
1817 
1818  MemoryContextSwitchTo(oldcontext);
1819 
1820  PG_RETURN_POINTER(state);
1821 }
JsonbParseState * parseState
Definition: jsonb.c:34
JsonbValue * res
Definition: jsonb.c:35
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:326
Jsonb * JsonbValueToJsonb(JsonbValue *val)
Definition: jsonb_util.c:79
Definition: jsonb.h:215
Datum numeric_uplus(PG_FUNCTION_ARGS)
Definition: numeric.c:1159
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:238
char * val
Definition: jsonb.h:259
#define NumericGetDatum(X)
Definition: numeric.h:51
JsonbInState * res
Definition: jsonb.c:57
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
Definition: jsonb.h:22
int errcode(int sqlerrcode)
Definition: elog.c:575
Oid key_output_func
Definition: jsonb.c:59
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:246
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:590
unsigned int Oid
Definition: postgres_ext.h:31
JsonbTypeCategory val_category
Definition: jsonb.c:60
static void datum_to_jsonb(Datum val, bool is_null, JsonbInState *result, JsonbTypeCategory tcategory, Oid outfuncoid, bool key_scalar)
Definition: jsonb.c:702
JsonbValue * pushJsonbValue(JsonbParseState **pstate, JsonbIteratorToken seq, JsonbValue *jbval)
Definition: jsonb_util.c:517
#define ERROR
Definition: elog.h:43
Oid get_fn_expr_argtype(FmgrInfo *flinfo, int argnum)
Definition: fmgr.c:1995
static char * buf
Definition: pg_test_fsync.c:67
static void jsonb_categorize_type(Oid typoid, JsonbTypeCategory *tcategory, Oid *outfuncoid)
Definition: jsonb.c:594
Definition: jsonb.h:23
#define ereport(elevel, rest)
Definition: elog.h:122
JsonbIteratorToken
Definition: jsonb.h:20
JsonbContainer root
Definition: jsonb.h:218
void * palloc0(Size size)
Definition: mcxt.c:955
uintptr_t Datum
Definition: postgres.h:367
#define InvalidOid
Definition: postgres_ext.h:36
#define PG_ARGISNULL(n)
Definition: fmgr.h:179
#define DatumGetNumeric(X)
Definition: numeric.h:49
JsonbIterator * JsonbIteratorInit(JsonbContainer *container)
Definition: jsonb_util.c:718
Definition: regguts.h:298
int AggCheckCallContext(FunctionCallInfo fcinfo, MemoryContext *aggcontext)
Definition: nodeAgg.c:3492
JsonbTypeCategory key_category
Definition: jsonb.c:58
enum jbvType type
Definition: jsonb.h:250
void * palloc(Size size)
Definition: mcxt.c:924
int errmsg(const char *fmt,...)
Definition: elog.c:797
Oid val_output_func
Definition: jsonb.c:61
#define elog
Definition: elog.h:219
long val
Definition: informix.c:689
JsonbIteratorToken JsonbIteratorNext(JsonbIterator **it, JsonbValue *val, bool skipNested)
Definition: jsonb_util.c:754
Definition: jsonb.h:25

◆ jsonb_object_two_arg()

Datum jsonb_object_two_arg ( PG_FUNCTION_ARGS  )

Definition at line 1346 of file jsonb.c.

References ARR_NDIM, deconstruct_array(), ereport, errcode(), errmsg(), ERROR, i, jbvNull, jbvString, JsonbValueToJsonb(), 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.

1347 {
1348  ArrayType *key_array = PG_GETARG_ARRAYTYPE_P(0);
1349  ArrayType *val_array = PG_GETARG_ARRAYTYPE_P(1);
1350  int nkdims = ARR_NDIM(key_array);
1351  int nvdims = ARR_NDIM(val_array);
1352  Datum *key_datums,
1353  *val_datums;
1354  bool *key_nulls,
1355  *val_nulls;
1356  int key_count,
1357  val_count,
1358  i;
1359  JsonbInState result;
1360 
1361  memset(&result, 0, sizeof(JsonbInState));
1362 
1363  (void) pushJsonbValue(&result.parseState, WJB_BEGIN_OBJECT, NULL);
1364 
1365  if (nkdims > 1 || nkdims != nvdims)
1366  ereport(ERROR,
1367  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
1368  errmsg("wrong number of array subscripts")));
1369 
1370  if (nkdims == 0)
1371  goto close_object;
1372 
1373  deconstruct_array(key_array,
1374  TEXTOID, -1, false, 'i',
1375  &key_datums, &key_nulls, &key_count);
1376 
1377  deconstruct_array(val_array,
1378  TEXTOID, -1, false, 'i',
1379  &val_datums, &val_nulls, &val_count);
1380 
1381  if (key_count != val_count)
1382  ereport(ERROR,
1383  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
1384  errmsg("mismatched array dimensions")));
1385 
1386  for (i = 0; i < key_count; ++i)
1387  {
1388  JsonbValue v;
1389  char *str;
1390  int len;
1391 
1392  if (key_nulls[i])
1393  ereport(ERROR,
1394  (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
1395  errmsg("null value not allowed for object key")));
1396 
1397  str = TextDatumGetCString(key_datums[i]);
1398  len = strlen(str);
1399 
1400  v.type = jbvString;
1401 
1402  v.val.string.len = len;
1403  v.val.string.val = str;
1404 
1405  (void) pushJsonbValue(&result.parseState, WJB_KEY, &v);
1406 
1407  if (val_nulls[i])
1408  {
1409  v.type = jbvNull;
1410  }
1411  else
1412  {
1413  str = TextDatumGetCString(val_datums[i]);
1414  len = strlen(str);
1415 
1416  v.type = jbvString;
1417 
1418  v.val.string.len = len;
1419  v.val.string.val = str;
1420  }
1421 
1422  (void) pushJsonbValue(&result.parseState, WJB_VALUE, &v);
1423  }
1424 
1425  pfree(key_datums);
1426  pfree(key_nulls);
1427  pfree(val_datums);
1428  pfree(val_nulls);
1429 
1430 close_object:
1431  result.res = pushJsonbValue(&result.parseState, WJB_END_OBJECT, NULL);
1432 
1434 }
JsonbParseState * parseState
Definition: jsonb.c:34
JsonbValue * res
Definition: jsonb.c:35
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:326
Jsonb * JsonbValueToJsonb(JsonbValue *val)
Definition: jsonb_util.c:79
char * val
Definition: jsonb.h:259
int errcode(int sqlerrcode)
Definition: elog.c:575
Definition: jsonb.h:231
JsonbValue * pushJsonbValue(JsonbParseState **pstate, JsonbIteratorToken seq, JsonbValue *jbval)
Definition: jsonb_util.c:517
#define PG_GETARG_ARRAYTYPE_P(n)
Definition: array.h:248
void pfree(void *pointer)
Definition: mcxt.c:1031
#define ERROR
Definition: elog.h:43
Definition: jsonb.h:23
#define ereport(elevel, rest)
Definition: elog.h:122
#define TextDatumGetCString(d)
Definition: builtins.h:96
uintptr_t Datum
Definition: postgres.h:367
#define ARR_NDIM(a)
Definition: array.h:275
enum jbvType type
Definition: jsonb.h:250
void deconstruct_array(ArrayType *array, Oid elmtype, int elmlen, bool elmbyval, char elmalign, Datum **elemsp, bool **nullsp, int *nelemsp)
Definition: arrayfuncs.c:3449
int errmsg(const char *fmt,...)
Definition: elog.c:797
int i

◆ jsonb_out()

Datum jsonb_out ( PG_FUNCTION_ARGS  )

Definition at line 132 of file jsonb.c.

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

133 {
134  Jsonb *jb = PG_GETARG_JSONB_P(0);
135  char *out;
136 
137  out = JsonbToCString(NULL, &jb->root, VARSIZE(jb));
138 
139  PG_RETURN_CSTRING(out);
140 }
Definition: jsonb.h:215
#define VARSIZE(PTR)
Definition: postgres.h:303
JsonbContainer root
Definition: jsonb.h:218
#define PG_RETURN_CSTRING(x)
Definition: fmgr.h:327
char * JsonbToCString(StringInfo out, JsonbContainer *in, int estimated_len)
Definition: jsonb.c:431
#define PG_GETARG_JSONB_P(x)
Definition: jsonb.h:70

◆ jsonb_put_escaped_value()

static void jsonb_put_escaped_value ( StringInfo  out,
JsonbValue scalarVal 
)
static

Definition at line 312 of file jsonb.c.

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

313 {
314  switch (scalarVal->type)
315  {
316  case jbvNull:
317  appendBinaryStringInfo(out, "null", 4);
318  break;
319  case jbvString:
320  escape_json(out, pnstrdup(scalarVal->val.string.val, scalarVal->val.string.len));
321  break;
322  case jbvNumeric:
325  PointerGetDatum(scalarVal->val.numeric))));
326  break;
327  case jbvBool:
328  if (scalarVal->val.boolean)
329  appendBinaryStringInfo(out, "true", 4);
330  else
331  appendBinaryStringInfo(out, "false", 5);
332  break;
333  default:
334  elog(ERROR, "unknown jsonb scalar type");
335  }
336 }
char * pnstrdup(const char *in, Size len)
Definition: mcxt.c:1172
void escape_json(StringInfo buf, const char *str)
Definition: json.c:2461
#define PointerGetDatum(X)
Definition: postgres.h:541
char * val
Definition: jsonb.h:259
Definition: jsonb.h:234
Datum numeric_out(PG_FUNCTION_ARGS)
Definition: numeric.c:652
Definition: jsonb.h:231
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:590
#define ERROR
Definition: elog.h:43
#define DatumGetCString(X)
Definition: postgres.h:551
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:157
enum jbvType type
Definition: jsonb.h:250
#define elog
Definition: elog.h:219
void appendBinaryStringInfo(StringInfo str, const char *data, int datalen)
Definition: stringinfo.c:208

◆ jsonb_recv()

Datum jsonb_recv ( PG_FUNCTION_ARGS  )

Definition at line 113 of file jsonb.c.

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

114 {
116  int version = pq_getmsgint(buf, 1);
117  char *str;
118  int nbytes;
119 
120  if (version == 1)
121  str = pq_getmsgtext(buf, buf->len - buf->cursor, &nbytes);
122  else
123  elog(ERROR, "unsupported jsonb version number %d", version);
124 
125  return jsonb_from_cstring(str, nbytes);
126 }
static Datum jsonb_from_cstring(char *json, int len)
Definition: jsonb.c:227
StringInfoData * StringInfo
Definition: stringinfo.h:43
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:246
#define ERROR
Definition: elog.h:43
static char * buf
Definition: pg_test_fsync.c:67
char * pq_getmsgtext(StringInfo msg, int rawbytes, int *nbytes)
Definition: pqformat.c:548
unsigned int pq_getmsgint(StringInfo msg, int b)
Definition: pqformat.c:417
#define elog
Definition: elog.h:219

◆ jsonb_send()

Datum jsonb_send ( PG_FUNCTION_ARGS  )

Definition at line 148 of file jsonb.c.

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.

149 {
150  Jsonb *jb = PG_GETARG_JSONB_P(0);
152  StringInfo jtext = makeStringInfo();
153  int version = 1;
154 
155  (void) JsonbToCString(jtext, &jb->root, VARSIZE(jb));
156 
157  pq_begintypsend(&buf);
158  pq_sendint8(&buf, version);
159  pq_sendtext(&buf, jtext->data, jtext->len);
160  pfree(jtext->data);
161  pfree(jtext);
162 
164 }
Definition: jsonb.h:215
#define VARSIZE(PTR)
Definition: postgres.h:303
void pq_begintypsend(StringInfo buf)
Definition: pqformat.c:328
StringInfo makeStringInfo(void)
Definition: stringinfo.c:28
void pq_sendtext(StringInfo buf, const char *str, int slen)
Definition: pqformat.c:174
#define PG_RETURN_BYTEA_P(x)
Definition: fmgr.h:335
bytea * pq_endtypsend(StringInfo buf)
Definition: pqformat.c:348
static void pq_sendint8(StringInfo buf, int8 i)
Definition: pqformat.h:132
void pfree(void *pointer)
Definition: mcxt.c:1031
static char * buf
Definition: pg_test_fsync.c:67
JsonbContainer root
Definition: jsonb.h:218
char * JsonbToCString(StringInfo out, JsonbContainer *in, int estimated_len)
Definition: jsonb.c:431
#define PG_GETARG_JSONB_P(x)
Definition: jsonb.h:70

◆ jsonb_typeof()

Datum jsonb_typeof ( PG_FUNCTION_ARGS  )

Definition at line 173 of file jsonb.c.

References Assert, cstring_to_text(), elog, ERROR, JB_ROOT_IS_ARRAY, JB_ROOT_IS_OBJECT, JB_ROOT_IS_SCALAR, jbvArray, jbvBool, jbvNull, jbvNumeric, jbvString, JsonbIteratorInit(), JsonbIteratorNext(), PG_GETARG_JSONB_P, PG_RETURN_TEXT_P, Jsonb::root, and JsonbValue::type.

174 {
175  Jsonb *in = PG_GETARG_JSONB_P(0);
176  JsonbIterator *it;
177  JsonbValue v;
178  char *result;
179 
180  if (JB_ROOT_IS_OBJECT(in))
181  result = "object";
182  else if (JB_ROOT_IS_ARRAY(in) && !JB_ROOT_IS_SCALAR(in))
183  result = "array";
184  else
185  {
187 
188  it = JsonbIteratorInit(&in->root);
189 
190  /*
191  * A root scalar is stored as an array of one element, so we get the
192  * array and then its first (and only) member.
193  */
194  (void) JsonbIteratorNext(&it, &v, true);
195  Assert(v.type == jbvArray);
196  (void) JsonbIteratorNext(&it, &v, true);
197  switch (v.type)
198  {
199  case jbvNull:
200  result = "null";
201  break;
202  case jbvString:
203  result = "string";
204  break;
205  case jbvNumeric:
206  result = "number";
207  break;
208  case jbvBool:
209  result = "boolean";
210  break;
211  default:
212  elog(ERROR, "unknown jsonb scalar type");
213  }
214  }
215 
217 }
#define JB_ROOT_IS_OBJECT(jbp_)
Definition: jsonb.h:224
Definition: jsonb.h:215
Definition: jsonb.h:234
Definition: jsonb.h:231
#define JB_ROOT_IS_SCALAR(jbp_)
Definition: jsonb.h:223
#define ERROR
Definition: elog.h:43
#define JB_ROOT_IS_ARRAY(jbp_)
Definition: jsonb.h:225
JsonbContainer root
Definition: jsonb.h:218
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:336
text * cstring_to_text(const char *s)
Definition: varlena.c:149
#define Assert(condition)
Definition: c.h:699
JsonbIterator * JsonbIteratorInit(JsonbContainer *container)
Definition: jsonb_util.c:718
enum jbvType type
Definition: jsonb.h:250
#define elog
Definition: elog.h:219
JsonbIteratorToken JsonbIteratorNext(JsonbIterator **it, JsonbValue *val, bool skipNested)
Definition: jsonb_util.c:754
#define PG_GETARG_JSONB_P(x)
Definition: jsonb.h:70

◆ JsonbExtractScalar()

static bool JsonbExtractScalar ( JsonbContainer jbc,
JsonbValue res 
)
static

Definition at line 1861 of file jsonb.c.

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

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

1862 {
1863  JsonbIterator *it;
1865  JsonbValue tmp;
1866 
1867  if (!JsonContainerIsArray(jbc) || !JsonContainerIsScalar(jbc))
1868  {
1869  /* inform caller about actual type of container */
1870  res->type = (JsonContainerIsArray(jbc)) ? jbvArray : jbvObject;
1871  return false;
1872  }
1873 
1874  /*
1875  * A root scalar is stored as an array of one element, so we get the array
1876  * and then its first (and only) member.
1877  */
1878  it = JsonbIteratorInit(jbc);
1879 
1880  tok = JsonbIteratorNext(&it, &tmp, true);
1881  Assert(tok == WJB_BEGIN_ARRAY);
1882  Assert(tmp.val.array.nElems == 1 && tmp.val.array.rawScalar);
1883 
1884  tok = JsonbIteratorNext(&it, res, true);
1885  Assert(tok == WJB_ELEM);
1886  Assert(IsAJsonbScalar(res));
1887 
1888  tok = JsonbIteratorNext(&it, &tmp, true);
1889  Assert(tok == WJB_END_ARRAY);
1890 
1891  tok = JsonbIteratorNext(&it, &tmp, true);
1892  Assert(tok == WJB_DONE);
1893 
1894  return true;
1895 }
char * val
Definition: jsonb.h:259
#define JsonContainerIsScalar(jc)
Definition: jsonb.h:210
Definition: jsonb.h:22
#define JsonContainerIsArray(jc)
Definition: jsonb.h:212
JsonbIteratorToken
Definition: jsonb.h:20
#define Assert(condition)
Definition: c.h:699
JsonbIterator * JsonbIteratorInit(JsonbContainer *container)
Definition: jsonb_util.c:718
#define IsAJsonbScalar(jsonbval)
Definition: jsonb.h:283
enum jbvType type
Definition: jsonb.h:250
#define PG_USED_FOR_ASSERTS_ONLY
Definition: c.h:123
JsonbIteratorToken JsonbIteratorNext(JsonbIterator **it, JsonbValue *val, bool skipNested)
Definition: jsonb_util.c:754
Definition: jsonb.h:25

◆ JsonbToCString()

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

Definition at line 431 of file jsonb.c.

References JsonbToCStringWorker().

Referenced by each_worker_jsonb(), elements_worker_jsonb(), get_jsonb_path_all(), jsonb_array_element_text(), jsonb_object_field_text(), jsonb_out(), jsonb_send(), and populate_scalar().

432 {
433  return JsonbToCStringWorker(out, in, estimated_len, false);
434 }
static char * JsonbToCStringWorker(StringInfo out, JsonbContainer *in, int estimated_len, bool indent)
Definition: jsonb.c:449

◆ JsonbToCStringIndent()

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

Definition at line 440 of file jsonb.c.

References JsonbToCStringWorker().

Referenced by jsonb_pretty().

441 {
442  return JsonbToCStringWorker(out, in, estimated_len, true);
443 }
static char * JsonbToCStringWorker(StringInfo out, JsonbContainer *in, int estimated_len, bool indent)
Definition: jsonb.c:449

◆ JsonbToCStringWorker()

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

Definition at line 449 of file jsonb.c.

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

450 {
451  bool first = true;
452  JsonbIterator *it;
453  JsonbValue v;
455  int level = 0;
456  bool redo_switch = false;
457 
458  /* If we are indenting, don't add a space after a comma */
459  int ispaces = indent ? 1 : 2;
460 
461  /*
462  * Don't indent the very first item. This gets set to the indent flag at
463  * the bottom of the loop.
464  */
465  bool use_indent = false;
466  bool raw_scalar = false;
467  bool last_was_key = false;
468 
469  if (out == NULL)
470  out = makeStringInfo();
471 
472  enlargeStringInfo(out, (estimated_len >= 0) ? estimated_len : 64);
473 
474  it = JsonbIteratorInit(in);
475 
476  while (redo_switch ||
477  ((type = JsonbIteratorNext(&it, &v, false)) != WJB_DONE))
478  {
479  redo_switch = false;
480  switch (type)
481  {
482  case WJB_BEGIN_ARRAY:
483  if (!first)
484  appendBinaryStringInfo(out, ", ", ispaces);
485 
486  if (!v.val.array.rawScalar)
487  {
488  add_indent(out, use_indent && !last_was_key, level);
489  appendStringInfoCharMacro(out, '[');
490  }
491  else
492  raw_scalar = true;
493 
494  first = true;
495  level++;
496  break;
497  case WJB_BEGIN_OBJECT:
498  if (!first)
499  appendBinaryStringInfo(out, ", ", ispaces);
500 
501  add_indent(out, use_indent && !last_was_key, level);
502  appendStringInfoCharMacro(out, '{');
503 
504  first = true;
505  level++;
506  break;
507  case WJB_KEY:
508  if (!first)
509  appendBinaryStringInfo(out, ", ", ispaces);
510  first = true;
511 
512  add_indent(out, use_indent, level);
513 
514  /* json rules guarantee this is a string */
515  jsonb_put_escaped_value(out, &v);
516  appendBinaryStringInfo(out, ": ", 2);
517 
518  type = JsonbIteratorNext(&it, &v, false);
519  if (type == WJB_VALUE)
520  {
521  first = false;
522  jsonb_put_escaped_value(out, &v);
523  }
524  else
525  {
526  Assert(type == WJB_BEGIN_OBJECT || type == WJB_BEGIN_ARRAY);
527 
528  /*
529  * We need to rerun the current switch() since we need to
530  * output the object which we just got from the iterator
531  * before calling the iterator again.
532  */
533  redo_switch = true;
534  }
535  break;
536  case WJB_ELEM:
537  if (!first)
538  appendBinaryStringInfo(out, ", ", ispaces);
539  first = false;
540 
541  if (!raw_scalar)
542  add_indent(out, use_indent, level);
543  jsonb_put_escaped_value(out, &v);
544  break;
545  case WJB_END_ARRAY:
546  level--;
547  if (!raw_scalar)
548  {
549  add_indent(out, use_indent, level);
550  appendStringInfoCharMacro(out, ']');
551  }
552  first = false;
553  break;
554  case WJB_END_OBJECT:
555  level--;
556  add_indent(out, use_indent, level);
557  appendStringInfoCharMacro(out, '}');
558  first = false;
559  break;
560  default:
561  elog(ERROR, "unknown jsonb iterator token type");
562  }
563  use_indent = indent;
564  last_was_key = redo_switch;
565  }
566 
567  Assert(level == 0);
568 
569  return out->data;
570 }
char * val
Definition: jsonb.h:259
StringInfo makeStringInfo(void)
Definition: stringinfo.c:28
Definition: jsonb.h:22
#define appendStringInfoCharMacro(str, ch)
Definition: stringinfo.h:127
#define ERROR
Definition: elog.h:43
void enlargeStringInfo(StringInfo str, int needed)
Definition: stringinfo.c:264
Definition: jsonb.h:23
JsonbIteratorToken
Definition: jsonb.h:20
static void jsonb_put_escaped_value(StringInfo out, JsonbValue *scalarVal)
Definition: jsonb.c:312
static void add_indent(StringInfo out, bool indent, int level)
Definition: jsonb.c:573
#define Assert(condition)
Definition: c.h:699
JsonbIterator * JsonbIteratorInit(JsonbContainer *container)
Definition: jsonb_util.c:718
#define elog
Definition: elog.h:219
void appendBinaryStringInfo(StringInfo str, const char *data, int datalen)
Definition: stringinfo.c:208
JsonbIteratorToken JsonbIteratorNext(JsonbIterator **it, JsonbValue *val, bool skipNested)
Definition: jsonb_util.c:754
Definition: jsonb.h:25

◆ to_jsonb()

Datum to_jsonb ( PG_FUNCTION_ARGS  )

Definition at line 1101 of file jsonb.c.

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.

1102 {
1103  Datum val = PG_GETARG_DATUM(0);
1104  Oid val_type = get_fn_expr_argtype(fcinfo->flinfo, 0);
1105  JsonbInState result;
1106  JsonbTypeCategory tcategory;
1107  Oid outfuncoid;
1108 
1109  if (val_type == InvalidOid)
1110  ereport(ERROR,
1111  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1112  errmsg("could not determine input data type")));
1113 
1114  jsonb_categorize_type(val_type,
1115  &tcategory, &outfuncoid);
1116 
1117  memset(&result, 0, sizeof(JsonbInState));
1118 
1119  datum_to_jsonb(val, false, &result, tcategory, outfuncoid, false);
1120 
1122 }
JsonbValue * res
Definition: jsonb.c:35
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:326
Jsonb * JsonbValueToJsonb(JsonbValue *val)
Definition: jsonb_util.c:79
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:238
int errcode(int sqlerrcode)
Definition: elog.c:575
unsigned int Oid
Definition: postgres_ext.h:31
static void datum_to_jsonb(Datum val, bool is_null, JsonbInState *result, JsonbTypeCategory tcategory, Oid outfuncoid, bool key_scalar)
Definition: jsonb.c:702
#define ERROR
Definition: elog.h:43
Oid get_fn_expr_argtype(FmgrInfo *flinfo, int argnum)
Definition: fmgr.c:1995
static void jsonb_categorize_type(Oid typoid, JsonbTypeCategory *tcategory, Oid *outfuncoid)
Definition: jsonb.c:594
#define ereport(elevel, rest)
Definition: elog.h:122
uintptr_t Datum
Definition: postgres.h:367
JsonbTypeCategory
Definition: jsonb.c:39
#define InvalidOid
Definition: postgres_ext.h:36
int errmsg(const char *fmt,...)
Definition: elog.c:797
long val
Definition: informix.c:689