PostgreSQL Source Code  git master
jsonfuncs.c File Reference
#include "postgres.h"
#include <limits.h>
#include "access/htup_details.h"
#include "catalog/pg_type.h"
#include "fmgr.h"
#include "funcapi.h"
#include "lib/stringinfo.h"
#include "mb/pg_wchar.h"
#include "miscadmin.h"
#include "utils/array.h"
#include "utils/builtins.h"
#include "utils/hsearch.h"
#include "utils/json.h"
#include "utils/jsonapi.h"
#include "utils/jsonb.h"
#include "utils/lsyscache.h"
#include "utils/memutils.h"
#include "utils/syscache.h"
#include "utils/typcache.h"
Include dependency graph for jsonfuncs.c:

Go to the source code of this file.

Data Structures

struct  OkeysState
 
struct  IterateJsonStringValuesState
 
struct  TransformJsonStringValuesState
 
struct  GetState
 
struct  AlenState
 
struct  EachState
 
struct  ElementsState
 
struct  JHashState
 
struct  JsonHashEntry
 
struct  ScalarIOData
 
struct  ArrayIOData
 
struct  CompositeIOData
 
struct  DomainIOData
 
struct  ColumnIOData
 
struct  RecordIOData
 
struct  PopulateRecordsetCache
 
struct  PopulateRecordsetState
 
struct  PopulateRecordCache
 
struct  PopulateArrayContext
 
struct  PopulateArrayState
 
struct  StripnullState
 
struct  JsValue
 
struct  JsObject
 

Macros

#define JB_PATH_CREATE   0x0001
 
#define JB_PATH_DELETE   0x0002
 
#define JB_PATH_REPLACE   0x0004
 
#define JB_PATH_INSERT_BEFORE   0x0008
 
#define JB_PATH_INSERT_AFTER   0x0010
 
#define JB_PATH_CREATE_OR_INSERT   (JB_PATH_INSERT_BEFORE | JB_PATH_INSERT_AFTER | JB_PATH_CREATE)
 
#define JsValueIsNull(jsv)
 
#define JsValueIsString(jsv)
 
#define JsObjectIsEmpty(jso)
 
#define JsObjectFree(jso)
 

Typedefs

typedef struct OkeysState OkeysState
 
typedef struct IterateJsonStringValuesState IterateJsonStringValuesState
 
typedef struct TransformJsonStringValuesState TransformJsonStringValuesState
 
typedef struct GetState GetState
 
typedef struct AlenState AlenState
 
typedef struct EachState EachState
 
typedef struct ElementsState ElementsState
 
typedef struct JHashState JHashState
 
typedef struct JsonHashEntry JsonHashEntry
 
typedef struct ScalarIOData ScalarIOData
 
typedef struct ColumnIOData ColumnIOData
 
typedef struct RecordIOData RecordIOData
 
typedef struct ArrayIOData ArrayIOData
 
typedef struct CompositeIOData CompositeIOData
 
typedef struct DomainIOData DomainIOData
 
typedef enum TypeCat TypeCat
 
typedef struct PopulateRecordsetCache PopulateRecordsetCache
 
typedef struct PopulateRecordsetState PopulateRecordsetState
 
typedef struct PopulateRecordCache PopulateRecordCache
 
typedef struct PopulateArrayContext PopulateArrayContext
 
typedef struct PopulateArrayState PopulateArrayState
 
typedef struct StripnullState StripnullState
 
typedef struct JsValue JsValue
 
typedef struct JsObject JsObject
 

Enumerations

enum  TypeCat {
  TYPECAT_SCALAR = 's', TYPECAT_ARRAY = 'a', TYPECAT_COMPOSITE = 'c', TYPECAT_COMPOSITE_DOMAIN = 'C',
  TYPECAT_DOMAIN = 'd'
}
 

Functions

static void okeys_object_field_start (void *state, char *fname, bool isnull)
 
static void okeys_array_start (void *state)
 
static void okeys_scalar (void *state, char *token, JsonTokenType tokentype)
 
static void get_object_start (void *state)
 
static void get_object_end (void *state)
 
static void get_object_field_start (void *state, char *fname, bool isnull)
 
static void get_object_field_end (void *state, char *fname, bool isnull)
 
static void get_array_start (void *state)
 
static void get_array_end (void *state)
 
static void get_array_element_start (void *state, bool isnull)
 
static void get_array_element_end (void *state, bool isnull)
 
static void get_scalar (void *state, char *token, JsonTokenType tokentype)
 
static Datum get_path_all (FunctionCallInfo fcinfo, bool as_text)
 
static textget_worker (text *json, char **tpath, int *ipath, int npath, bool normalize_results)
 
static Datum get_jsonb_path_all (FunctionCallInfo fcinfo, bool as_text)
 
static void alen_object_start (void *state)
 
static void alen_scalar (void *state, char *token, JsonTokenType tokentype)
 
static void alen_array_element_start (void *state, bool isnull)
 
static Datum each_worker (FunctionCallInfo fcinfo, bool as_text)
 
static Datum each_worker_jsonb (FunctionCallInfo fcinfo, const char *funcname, bool as_text)
 
static void each_object_field_start (void *state, char *fname, bool isnull)
 
static void each_object_field_end (void *state, char *fname, bool isnull)
 
static void each_array_start (void *state)
 
static void each_scalar (void *state, char *token, JsonTokenType tokentype)
 
static Datum elements_worker (FunctionCallInfo fcinfo, const char *funcname, bool as_text)
 
static Datum elements_worker_jsonb (FunctionCallInfo fcinfo, const char *funcname, bool as_text)
 
static void elements_object_start (void *state)
 
static void elements_array_element_start (void *state, bool isnull)
 
static void elements_array_element_end (void *state, bool isnull)
 
static void elements_scalar (void *state, char *token, JsonTokenType tokentype)
 
static HTABget_json_object_as_hash (char *json, int len, const char *funcname)
 
static void populate_array_object_start (void *_state)
 
static void populate_array_array_end (void *_state)
 
static void populate_array_element_start (void *_state, bool isnull)
 
static void populate_array_element_end (void *_state, bool isnull)
 
static void populate_array_scalar (void *_state, char *token, JsonTokenType tokentype)
 
static void hash_object_field_start (void *state, char *fname, bool isnull)
 
static void hash_object_field_end (void *state, char *fname, bool isnull)
 
static void hash_array_start (void *state)
 
static void hash_scalar (void *state, char *token, JsonTokenType tokentype)
 
static void populate_recordset_object_field_start (void *state, char *fname, bool isnull)
 
static void populate_recordset_object_field_end (void *state, char *fname, bool isnull)
 
static void populate_recordset_scalar (void *state, char *token, JsonTokenType tokentype)
 
static void populate_recordset_object_start (void *state)
 
static void populate_recordset_object_end (void *state)
 
static void populate_recordset_array_start (void *state)
 
static void populate_recordset_array_element_start (void *state, bool isnull)
 
static void sn_object_start (void *state)
 
static void sn_object_end (void *state)
 
static void sn_array_start (void *state)
 
static void sn_array_end (void *state)
 
static void sn_object_field_start (void *state, char *fname, bool isnull)
 
static void sn_array_element_start (void *state, bool isnull)
 
static void sn_scalar (void *state, char *token, JsonTokenType tokentype)
 
static Datum populate_recordset_worker (FunctionCallInfo fcinfo, const char *funcname, bool have_record_arg)
 
static Datum populate_record_worker (FunctionCallInfo fcinfo, const char *funcname, bool have_record_arg)
 
static HeapTupleHeader populate_record (TupleDesc tupdesc, RecordIOData **record_p, HeapTupleHeader defaultval, MemoryContext mcxt, JsObject *obj)
 
static void JsValueToJsObject (JsValue *jsv, JsObject *jso)
 
static Datum populate_composite (CompositeIOData *io, Oid typid, const char *colname, MemoryContext mcxt, HeapTupleHeader defaultval, JsValue *jsv, bool isnull)
 
static Datum populate_scalar (ScalarIOData *io, Oid typid, int32 typmod, JsValue *jsv)
 
static void prepare_column_cache (ColumnIOData *column, Oid typid, int32 typmod, MemoryContext mcxt, bool need_scalar)
 
static Datum populate_record_field (ColumnIOData *col, Oid typid, int32 typmod, const char *colname, MemoryContext mcxt, Datum defaultval, JsValue *jsv, bool *isnull)
 
static RecordIODataallocate_record_info (MemoryContext mcxt, int ncolumns)
 
static bool JsObjectGetField (JsObject *obj, char *field, JsValue *jsv)
 
static void populate_recordset_record (PopulateRecordsetState *state, JsObject *obj)
 
static void populate_array_json (PopulateArrayContext *ctx, char *json, int len)
 
static void populate_array_dim_jsonb (PopulateArrayContext *ctx, JsonbValue *jbv, int ndim)
 
static void populate_array_report_expected_array (PopulateArrayContext *ctx, int ndim)
 
static void populate_array_assign_ndims (PopulateArrayContext *ctx, int ndims)
 
static void populate_array_check_dimension (PopulateArrayContext *ctx, int ndim)
 
static void populate_array_element (PopulateArrayContext *ctx, int ndim, JsValue *jsv)
 
static Datum populate_array (ArrayIOData *aio, const char *colname, MemoryContext mcxt, JsValue *jsv)
 
static Datum populate_domain (DomainIOData *io, Oid typid, const char *colname, MemoryContext mcxt, JsValue *jsv, bool isnull)
 
static JsonbValuefindJsonbValueFromContainerLen (JsonbContainer *container, uint32 flags, char *key, uint32 keylen)
 
static JsonbValueIteratorConcat (JsonbIterator **it1, JsonbIterator **it2, JsonbParseState **state)
 
static JsonbValuesetPath (JsonbIterator **it, Datum *path_elems, bool *path_nulls, int path_len, JsonbParseState **st, int level, Jsonb *newval, int op_type)
 
static void setPathObject (JsonbIterator **it, Datum *path_elems, bool *path_nulls, int path_len, JsonbParseState **st, int level, Jsonb *newval, uint32 npairs, int op_type)
 
static void setPathArray (JsonbIterator **it, Datum *path_elems, bool *path_nulls, int path_len, JsonbParseState **st, int level, Jsonb *newval, uint32 nelems, int op_type)
 
static void addJsonbToParseState (JsonbParseState **jbps, Jsonb *jb)
 
static void iterate_string_values_scalar (void *state, char *token, JsonTokenType tokentype)
 
static void transform_string_values_object_start (void *state)
 
static void transform_string_values_object_end (void *state)
 
static void transform_string_values_array_start (void *state)
 
static void transform_string_values_array_end (void *state)
 
static void transform_string_values_object_field_start (void *state, char *fname, bool isnull)
 
static void transform_string_values_array_element_start (void *state, bool isnull)
 
static void transform_string_values_scalar (void *state, char *token, JsonTokenType tokentype)
 
Datum jsonb_object_keys (PG_FUNCTION_ARGS)
 
Datum json_object_keys (PG_FUNCTION_ARGS)
 
Datum json_object_field (PG_FUNCTION_ARGS)
 
Datum jsonb_object_field (PG_FUNCTION_ARGS)
 
Datum json_object_field_text (PG_FUNCTION_ARGS)
 
Datum jsonb_object_field_text (PG_FUNCTION_ARGS)
 
Datum json_array_element (PG_FUNCTION_ARGS)
 
Datum jsonb_array_element (PG_FUNCTION_ARGS)
 
Datum json_array_element_text (PG_FUNCTION_ARGS)
 
Datum jsonb_array_element_text (PG_FUNCTION_ARGS)
 
Datum json_extract_path (PG_FUNCTION_ARGS)
 
Datum json_extract_path_text (PG_FUNCTION_ARGS)
 
Datum jsonb_extract_path (PG_FUNCTION_ARGS)
 
Datum jsonb_extract_path_text (PG_FUNCTION_ARGS)
 
Datum json_array_length (PG_FUNCTION_ARGS)
 
Datum jsonb_array_length (PG_FUNCTION_ARGS)
 
Datum json_each (PG_FUNCTION_ARGS)
 
Datum jsonb_each (PG_FUNCTION_ARGS)
 
Datum json_each_text (PG_FUNCTION_ARGS)
 
Datum jsonb_each_text (PG_FUNCTION_ARGS)
 
Datum jsonb_array_elements (PG_FUNCTION_ARGS)
 
Datum jsonb_array_elements_text (PG_FUNCTION_ARGS)
 
Datum json_array_elements (PG_FUNCTION_ARGS)
 
Datum json_array_elements_text (PG_FUNCTION_ARGS)
 
Datum jsonb_populate_record (PG_FUNCTION_ARGS)
 
Datum jsonb_to_record (PG_FUNCTION_ARGS)
 
Datum json_populate_record (PG_FUNCTION_ARGS)
 
Datum json_to_record (PG_FUNCTION_ARGS)
 
static void update_cached_tupdesc (CompositeIOData *io, MemoryContext mcxt)
 
Datum jsonb_populate_recordset (PG_FUNCTION_ARGS)
 
Datum jsonb_to_recordset (PG_FUNCTION_ARGS)
 
Datum json_populate_recordset (PG_FUNCTION_ARGS)
 
Datum json_to_recordset (PG_FUNCTION_ARGS)
 
Datum json_strip_nulls (PG_FUNCTION_ARGS)
 
Datum jsonb_strip_nulls (PG_FUNCTION_ARGS)
 
Datum jsonb_pretty (PG_FUNCTION_ARGS)
 
Datum jsonb_concat (PG_FUNCTION_ARGS)
 
Datum jsonb_delete (PG_FUNCTION_ARGS)
 
Datum jsonb_delete_array (PG_FUNCTION_ARGS)
 
Datum jsonb_delete_idx (PG_FUNCTION_ARGS)
 
Datum jsonb_set (PG_FUNCTION_ARGS)
 
Datum jsonb_delete_path (PG_FUNCTION_ARGS)
 
Datum jsonb_insert (PG_FUNCTION_ARGS)
 
void iterate_jsonb_string_values (Jsonb *jb, void *state, JsonIterateStringValuesAction action)
 
void iterate_json_string_values (text *json, void *action_state, JsonIterateStringValuesAction action)
 
Jsonbtransform_jsonb_string_values (Jsonb *jsonb, void *action_state, JsonTransformStringValuesAction transform_action)
 
texttransform_json_string_values (text *json, void *action_state, JsonTransformStringValuesAction transform_action)
 

Macro Definition Documentation

◆ JB_PATH_CREATE

#define JB_PATH_CREATE   0x0001

Definition at line 38 of file jsonfuncs.c.

Referenced by jsonb_set(), and setPathArray().

◆ JB_PATH_CREATE_OR_INSERT

#define JB_PATH_CREATE_OR_INSERT   (JB_PATH_INSERT_BEFORE | JB_PATH_INSERT_AFTER | JB_PATH_CREATE)

Definition at line 43 of file jsonfuncs.c.

Referenced by setPathArray(), and setPathObject().

◆ JB_PATH_DELETE

#define JB_PATH_DELETE   0x0002

Definition at line 39 of file jsonfuncs.c.

Referenced by jsonb_delete_path(), and setPathObject().

◆ JB_PATH_INSERT_AFTER

#define JB_PATH_INSERT_AFTER   0x0010

Definition at line 42 of file jsonfuncs.c.

Referenced by jsonb_insert(), setPathArray(), and setPathObject().

◆ JB_PATH_INSERT_BEFORE

#define JB_PATH_INSERT_BEFORE   0x0008

Definition at line 41 of file jsonfuncs.c.

Referenced by jsonb_insert(), setPathArray(), and setPathObject().

◆ JB_PATH_REPLACE

#define JB_PATH_REPLACE   0x0004

Definition at line 40 of file jsonfuncs.c.

Referenced by jsonb_set(), and setPathArray().

◆ JsObjectFree

#define JsObjectFree (   jso)
Value:
do { \
if ((jso)->is_json) \
hash_destroy((jso)->val.json_hash); \
} while (0)
long val
Definition: informix.c:689

Definition at line 330 of file jsonfuncs.c.

Referenced by populate_composite().

◆ JsObjectIsEmpty

#define JsObjectIsEmpty (   jso)
Value:
((jso)->is_json \
? hash_get_num_entries((jso)->val.json_hash) == 0 \
: ((jso)->val.jsonb_cont == NULL || \
JsonContainerSize((jso)->val.jsonb_cont) == 0))
long hash_get_num_entries(HTAB *hashp)
Definition: dynahash.c:1331
long val
Definition: informix.c:689

Definition at line 324 of file jsonfuncs.c.

Referenced by populate_record().

◆ JsValueIsNull

#define JsValueIsNull (   jsv)
Value:
((jsv)->is_json ? \
(!(jsv)->val.json.str || (jsv)->val.json.type == JSON_TOKEN_NULL) : \
(!(jsv)->val.jsonb || (jsv)->val.jsonb->type == jbvNull))
Definition: jsonb.h:231
long val
Definition: informix.c:689

Definition at line 315 of file jsonfuncs.c.

Referenced by populate_record_field().

◆ JsValueIsString

#define JsValueIsString (   jsv)
Value:
((jsv)->is_json ? (jsv)->val.json.type == JSON_TOKEN_STRING \
: ((jsv)->val.jsonb && (jsv)->val.jsonb->type == jbvString))
long val
Definition: informix.c:689

Definition at line 320 of file jsonfuncs.c.

Referenced by populate_record_field().

Typedef Documentation

◆ AlenState

◆ ArrayIOData

◆ ColumnIOData

Definition at line 152 of file jsonfuncs.c.

◆ CompositeIOData

◆ DomainIOData

◆ EachState

◆ ElementsState

◆ GetState

◆ IterateJsonStringValuesState

◆ JHashState

◆ JsObject

◆ JsonHashEntry

◆ JsValue

◆ OkeysState

◆ PopulateArrayContext

◆ PopulateArrayState

◆ PopulateRecordCache

◆ PopulateRecordsetCache

◆ PopulateRecordsetState

◆ RecordIOData

Definition at line 153 of file jsonfuncs.c.

◆ ScalarIOData

◆ StripnullState

◆ TransformJsonStringValuesState

◆ TypeCat

Enumeration Type Documentation

◆ TypeCat

enum TypeCat
Enumerator
TYPECAT_SCALAR 
TYPECAT_ARRAY 
TYPECAT_COMPOSITE 
TYPECAT_COMPOSITE_DOMAIN 
TYPECAT_DOMAIN 

Definition at line 189 of file jsonfuncs.c.

Function Documentation

◆ addJsonbToParseState()

static void addJsonbToParseState ( JsonbParseState **  jbps,
Jsonb jb 
)
static

Definition at line 4098 of file jsonfuncs.c.

References Assert, elog, ERROR, JB_ROOT_IS_SCALAR, jbvArray, jbvObject, JsonbIteratorInit(), JsonbIteratorNext(), pushJsonbValue(), Jsonb::root, generate_unaccent_rules::type, JsonbValue::type, WJB_DONE, WJB_ELEM, WJB_KEY, and WJB_VALUE.

Referenced by setPathArray(), and setPathObject().

4099 {
4100  JsonbIterator *it;
4101  JsonbValue *o = &(*jbps)->contVal;
4102  JsonbValue v;
4104 
4105  it = JsonbIteratorInit(&jb->root);
4106 
4107  Assert(o->type == jbvArray || o->type == jbvObject);
4108 
4109  if (JB_ROOT_IS_SCALAR(jb))
4110  {
4111  (void) JsonbIteratorNext(&it, &v, false); /* skip array header */
4112  (void) JsonbIteratorNext(&it, &v, false); /* fetch scalar value */
4113 
4114  switch (o->type)
4115  {
4116  case jbvArray:
4117  (void) pushJsonbValue(jbps, WJB_ELEM, &v);
4118  break;
4119  case jbvObject:
4120  (void) pushJsonbValue(jbps, WJB_VALUE, &v);
4121  break;
4122  default:
4123  elog(ERROR, "unexpected parent of nested structure");
4124  }
4125  }
4126  else
4127  {
4128  while ((type = JsonbIteratorNext(&it, &v, false)) != WJB_DONE)
4129  {
4130  if (type == WJB_KEY || type == WJB_VALUE || type == WJB_ELEM)
4131  (void) pushJsonbValue(jbps, type, &v);
4132  else
4133  (void) pushJsonbValue(jbps, type, NULL);
4134  }
4135  }
4136 
4137 }
Definition: jsonb.h:22
#define JB_ROOT_IS_SCALAR(jbp_)
Definition: jsonb.h:223
JsonbValue * pushJsonbValue(JsonbParseState **pstate, JsonbIteratorToken seq, JsonbValue *jbval)
Definition: jsonb_util.c:517
#define ERROR
Definition: elog.h:43
Definition: jsonb.h:23
JsonbIteratorToken
Definition: jsonb.h:20
JsonbContainer root
Definition: jsonb.h:218
#define Assert(condition)
Definition: c.h:670
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
Definition: jsonb.h:25

◆ alen_array_element_start()

static void alen_array_element_start ( void *  state,
bool  isnull 
)
static

Definition at line 1627 of file jsonfuncs.c.

References AlenState::count, AlenState::lex, and JsonLexContext::lex_level.

Referenced by json_array_length().

1628 {
1629  AlenState *_state = (AlenState *) state;
1630 
1631  /* just count up all the level 1 elements */
1632  if (_state->lex->lex_level == 1)
1633  _state->count++;
1634 }
int count
Definition: jsonfuncs.c:95
int lex_level
Definition: jsonapi.h:59
JsonLexContext * lex
Definition: jsonfuncs.c:94
Definition: regguts.h:298

◆ alen_object_start()

static void alen_object_start ( void *  state)
static

Definition at line 1603 of file jsonfuncs.c.

References ereport, errcode(), errmsg(), ERROR, AlenState::lex, and JsonLexContext::lex_level.

Referenced by json_array_length().

1604 {
1605  AlenState *_state = (AlenState *) state;
1606 
1607  /* json structure check */
1608  if (_state->lex->lex_level == 0)
1609  ereport(ERROR,
1610  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1611  errmsg("cannot get array length of a non-array")));
1612 }
int errcode(int sqlerrcode)
Definition: elog.c:575
int lex_level
Definition: jsonapi.h:59
#define ERROR
Definition: elog.h:43
JsonLexContext * lex
Definition: jsonfuncs.c:94
#define ereport(elevel, rest)
Definition: elog.h:122
Definition: regguts.h:298
int errmsg(const char *fmt,...)
Definition: elog.c:797

◆ alen_scalar()

static void alen_scalar ( void *  state,
char *  token,
JsonTokenType  tokentype 
)
static

Definition at line 1615 of file jsonfuncs.c.

References ereport, errcode(), errmsg(), ERROR, AlenState::lex, and JsonLexContext::lex_level.

Referenced by json_array_length().

1616 {
1617  AlenState *_state = (AlenState *) state;
1618 
1619  /* json structure check */
1620  if (_state->lex->lex_level == 0)
1621  ereport(ERROR,
1622  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1623  errmsg("cannot get array length of a scalar")));
1624 }
int errcode(int sqlerrcode)
Definition: elog.c:575
int lex_level
Definition: jsonapi.h:59
#define ERROR
Definition: elog.h:43
JsonLexContext * lex
Definition: jsonfuncs.c:94
#define ereport(elevel, rest)
Definition: elog.h:122
Definition: regguts.h:298
int errmsg(const char *fmt,...)
Definition: elog.c:797

◆ allocate_record_info()

static RecordIOData * allocate_record_info ( MemoryContext  mcxt,
int  ncolumns 
)
static

Definition at line 3051 of file jsonfuncs.c.

References RecordIOData::columns, InvalidOid, MemoryContextAlloc(), MemSet, RecordIOData::ncolumns, offsetof, RecordIOData::record_type, and RecordIOData::record_typmod.

Referenced by populate_record().

3052 {
3053  RecordIOData *data = (RecordIOData *)
3054  MemoryContextAlloc(mcxt,
3055  offsetof(RecordIOData, columns) +
3056  ncolumns * sizeof(ColumnIOData));
3057 
3058  data->record_type = InvalidOid;
3059  data->record_typmod = 0;
3060  data->ncolumns = ncolumns;
3061  MemSet(data->columns, 0, sizeof(ColumnIOData) * ncolumns);
3062 
3063  return data;
3064 }
Oid record_type
Definition: hstore_io.c:753
struct ColumnIOData ColumnIOData
Definition: jsonfuncs.c:152
#define MemSet(start, val, len)
Definition: c.h:853
int32 record_typmod
Definition: hstore_io.c:754
ColumnIOData columns[FLEXIBLE_ARRAY_MEMBER]
Definition: hstore_io.c:758
#define InvalidOid
Definition: postgres_ext.h:36
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:706
#define offsetof(type, field)
Definition: c.h:593

◆ each_array_start()

static void each_array_start ( void *  state)
static

Definition at line 1937 of file jsonfuncs.c.

References ereport, errcode(), errmsg(), ERROR, EachState::lex, and JsonLexContext::lex_level.

Referenced by each_worker().

1938 {
1939  EachState *_state = (EachState *) state;
1940 
1941  /* json structure check */
1942  if (_state->lex->lex_level == 0)
1943  ereport(ERROR,
1944  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1945  errmsg("cannot deconstruct an array as an object")));
1946 }
int errcode(int sqlerrcode)
Definition: elog.c:575
int lex_level
Definition: jsonapi.h:59
#define ERROR
Definition: elog.h:43
JsonLexContext * lex
Definition: jsonfuncs.c:101
#define ereport(elevel, rest)
Definition: elog.h:122
Definition: regguts.h:298
int errmsg(const char *fmt,...)
Definition: elog.c:797

◆ each_object_field_end()

static void each_object_field_end ( void *  state,
char *  fname,
bool  isnull 
)
static

Definition at line 1891 of file jsonfuncs.c.

References cstring_to_text_with_len(), CStringGetTextDatum, heap_form_tuple(), EachState::lex, JsonLexContext::lex_level, MemoryContextReset(), MemoryContextSwitchTo(), EachState::next_scalar, EachState::normalize_results, EachState::normalized_scalar, PointerGetDatum, JsonLexContext::prev_token_terminator, EachState::result_start, EachState::ret_tdesc, EachState::tmp_cxt, EachState::tuple_store, tuplestore_puttuple(), val, and values.

Referenced by each_worker().

1892 {
1893  EachState *_state = (EachState *) state;
1894  MemoryContext old_cxt;
1895  int len;
1896  text *val;
1897  HeapTuple tuple;
1898  Datum values[2];
1899  bool nulls[2] = {false, false};
1900 
1901  /* skip over nested objects */
1902  if (_state->lex->lex_level != 1)
1903  return;
1904 
1905  /* use the tmp context so we can clean up after each tuple is done */
1906  old_cxt = MemoryContextSwitchTo(_state->tmp_cxt);
1907 
1908  values[0] = CStringGetTextDatum(fname);
1909 
1910  if (isnull && _state->normalize_results)
1911  {
1912  nulls[1] = true;
1913  values[1] = (Datum) 0;
1914  }
1915  else if (_state->next_scalar)
1916  {
1917  values[1] = CStringGetTextDatum(_state->normalized_scalar);
1918  _state->next_scalar = false;
1919  }
1920  else
1921  {
1922  len = _state->lex->prev_token_terminator - _state->result_start;
1923  val = cstring_to_text_with_len(_state->result_start, len);
1924  values[1] = PointerGetDatum(val);
1925  }
1926 
1927  tuple = heap_form_tuple(_state->ret_tdesc, values, nulls);
1928 
1929  tuplestore_puttuple(_state->tuple_store, tuple);
1930 
1931  /* clean up and switch back */
1932  MemoryContextSwitchTo(old_cxt);
1933  MemoryContextReset(_state->tmp_cxt);
1934 }
Tuplestorestate * tuple_store
Definition: jsonfuncs.c:102
#define PointerGetDatum(X)
Definition: postgres.h:562
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
char * prev_token_terminator
Definition: jsonapi.h:57
void MemoryContextReset(MemoryContext context)
Definition: mcxt.c:135
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:695
TupleDesc ret_tdesc
Definition: jsonfuncs.c:103
int lex_level
Definition: jsonapi.h:59
MemoryContext tmp_cxt
Definition: jsonfuncs.c:104
char * result_start
Definition: jsonfuncs.c:105
JsonLexContext * lex
Definition: jsonfuncs.c:101
void tuplestore_puttuple(Tuplestorestate *state, HeapTuple tuple)
Definition: tuplestore.c:730
text * cstring_to_text_with_len(const char *s, int len)
Definition: varlena.c:161
uintptr_t Datum
Definition: postgres.h:372
bool normalize_results
Definition: jsonfuncs.c:106
char * normalized_scalar
Definition: jsonfuncs.c:108
Definition: regguts.h:298
static Datum values[MAXATTR]
Definition: bootstrap.c:164
#define CStringGetTextDatum(s)
Definition: builtins.h:91
Definition: c.h:487
long val
Definition: informix.c:689
bool next_scalar
Definition: jsonfuncs.c:107

◆ each_object_field_start()

static void each_object_field_start ( void *  state,
char *  fname,
bool  isnull 
)
static

Definition at line 1871 of file jsonfuncs.c.

References JSON_TOKEN_STRING, EachState::lex, JsonLexContext::lex_level, EachState::next_scalar, EachState::normalize_results, EachState::result_start, JsonLexContext::token_start, and JsonLexContext::token_type.

Referenced by each_worker().

1872 {
1873  EachState *_state = (EachState *) state;
1874 
1875  /* save a pointer to where the value starts */
1876  if (_state->lex->lex_level == 1)
1877  {
1878  /*
1879  * next_scalar will be reset in the object_field_end handler, and
1880  * since we know the value is a scalar there is no danger of it being
1881  * on while recursing down the tree.
1882  */
1883  if (_state->normalize_results && _state->lex->token_type == JSON_TOKEN_STRING)
1884  _state->next_scalar = true;
1885  else
1886  _state->result_start = _state->lex->token_start;
1887  }
1888 }
JsonTokenType token_type
Definition: jsonapi.h:58
int lex_level
Definition: jsonapi.h:59
char * result_start
Definition: jsonfuncs.c:105
JsonLexContext * lex
Definition: jsonfuncs.c:101
char * token_start
Definition: jsonapi.h:55
bool normalize_results
Definition: jsonfuncs.c:106
Definition: regguts.h:298
bool next_scalar
Definition: jsonfuncs.c:107

◆ each_scalar()

static void each_scalar ( void *  state,
char *  token,
JsonTokenType  tokentype 
)
static

Definition at line 1949 of file jsonfuncs.c.

References ereport, errcode(), errmsg(), ERROR, EachState::lex, JsonLexContext::lex_level, EachState::next_scalar, and EachState::normalized_scalar.

Referenced by each_worker().

1950 {
1951  EachState *_state = (EachState *) state;
1952 
1953  /* json structure check */
1954  if (_state->lex->lex_level == 0)
1955  ereport(ERROR,
1956  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1957  errmsg("cannot deconstruct a scalar")));
1958 
1959  /* supply de-escaped value if required */
1960  if (_state->next_scalar)
1961  _state->normalized_scalar = token;
1962 }
int errcode(int sqlerrcode)
Definition: elog.c:575
int lex_level
Definition: jsonapi.h:59
#define ERROR
Definition: elog.h:43
JsonLexContext * lex
Definition: jsonfuncs.c:101
#define ereport(elevel, rest)
Definition: elog.h:122
char * normalized_scalar
Definition: jsonfuncs.c:108
Definition: regguts.h:298
int errmsg(const char *fmt,...)
Definition: elog.c:797
bool next_scalar
Definition: jsonfuncs.c:107

◆ each_worker()

static Datum each_worker ( FunctionCallInfo  fcinfo,
bool  as_text 
)
static

Definition at line 1807 of file jsonfuncs.c.

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate(), ReturnSetInfo::allowedModes, JsonSemAction::array_start, BlessTupleDesc(), CreateTupleDescCopy(), CurrentMemoryContext, each_array_start(), each_object_field_end(), each_object_field_start(), each_scalar(), ReturnSetInfo::econtext, ExprContext::ecxt_per_query_memory, ereport, errcode(), errmsg(), ERROR, ReturnSetInfo::expectedDesc, get_call_result_type(), IsA, OkeysState::lex, EachState::lex, makeJsonLexContext(), MemoryContextDelete(), MemoryContextSwitchTo(), EachState::next_scalar, EachState::normalize_results, JsonSemAction::object_field_end, JsonSemAction::object_field_start, palloc0(), PG_GETARG_TEXT_PP, pg_parse_json(), PG_RETURN_NULL, FunctionCallInfoData::resultinfo, EachState::ret_tdesc, ReturnSetInfo::returnMode, JsonSemAction::scalar, JsonSemAction::semstate, ReturnSetInfo::setDesc, ReturnSetInfo::setResult, SFRM_Materialize, SFRM_Materialize_Random, EachState::tmp_cxt, EachState::tuple_store, tuplestore_begin_heap(), and work_mem.

Referenced by json_each(), and json_each_text().

1808 {
1809  text *json = PG_GETARG_TEXT_PP(0);
1810  JsonLexContext *lex;
1811  JsonSemAction *sem;
1812  ReturnSetInfo *rsi;
1813  MemoryContext old_cxt;
1814  TupleDesc tupdesc;
1815  EachState *state;
1816 
1817  lex = makeJsonLexContext(json, true);
1818  state = palloc0(sizeof(EachState));
1819  sem = palloc0(sizeof(JsonSemAction));
1820 
1821  rsi = (ReturnSetInfo *) fcinfo->resultinfo;
1822 
1823  if (!rsi || !IsA(rsi, ReturnSetInfo) ||
1824  (rsi->allowedModes & SFRM_Materialize) == 0 ||
1825  rsi->expectedDesc == NULL)
1826  ereport(ERROR,
1827  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1828  errmsg("set-valued function called in context that "
1829  "cannot accept a set")));
1830 
1832 
1833  (void) get_call_result_type(fcinfo, NULL, &tupdesc);
1834 
1835  /* make these in a sufficiently long-lived memory context */
1837 
1838  state->ret_tdesc = CreateTupleDescCopy(tupdesc);
1839  BlessTupleDesc(state->ret_tdesc);
1840  state->tuple_store =
1842  false, work_mem);
1843 
1844  MemoryContextSwitchTo(old_cxt);
1845 
1846  sem->semstate = (void *) state;
1848  sem->scalar = each_scalar;
1851 
1852  state->normalize_results = as_text;
1853  state->next_scalar = false;
1854  state->lex = lex;
1856  "json_each temporary cxt",
1858 
1859  pg_parse_json(lex, sem);
1860 
1861  MemoryContextDelete(state->tmp_cxt);
1862 
1863  rsi->setResult = state->tuple_store;
1864  rsi->setDesc = state->ret_tdesc;
1865 
1866  PG_RETURN_NULL();
1867 }
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
Definition: tupdesc.c:102
#define IsA(nodeptr, _type_)
Definition: nodes.h:561
Tuplestorestate * tuple_store
Definition: jsonfuncs.c:102
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:200
static void each_object_field_start(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:1871
TypeFuncClass get_call_result_type(FunctionCallInfo fcinfo, Oid *resultTypeId, TupleDesc *resultTupleDesc)
Definition: funcapi.c:211
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
int errcode(int sqlerrcode)
Definition: elog.c:575
json_scalar_action scalar
Definition: jsonapi.h:93
static void each_array_start(void *state)
Definition: jsonfuncs.c:1937
TupleDesc ret_tdesc
Definition: jsonfuncs.c:103
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:273
MemoryContext tmp_cxt
Definition: jsonfuncs.c:104
static void each_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:1949
TupleDesc expectedDesc
Definition: execnodes.h:267
JsonLexContext * makeJsonLexContext(text *json, bool need_escapes)
Definition: json.c:301
#define ERROR
Definition: elog.h:43
void pg_parse_json(JsonLexContext *lex, JsonSemAction *sem)
Definition: json.c:332
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:165
JsonLexContext * lex
Definition: jsonfuncs.c:101
TupleDesc BlessTupleDesc(TupleDesc tupdesc)
Definition: execTuples.c:1032
fmNodePtr resultinfo
Definition: fmgr.h:81
MemoryContext CurrentMemoryContext
Definition: mcxt.c:37
#define ereport(elevel, rest)
Definition: elog.h:122
json_ofield_action object_field_end
Definition: jsonapi.h:90
Tuplestorestate * tuplestore_begin_heap(bool randomAccess, bool interXact, int maxKBytes)
Definition: tuplestore.c:318
MemoryContext AllocSetContextCreate(MemoryContext parent, const char *name, Size minContextSize, Size initBlockSize, Size maxBlockSize)
Definition: aset.c:322
void * palloc0(Size size)
Definition: mcxt.c:877
bool normalize_results
Definition: jsonfuncs.c:106
int work_mem
Definition: globals.c:113
int allowedModes
Definition: execnodes.h:268
SetFunctionReturnMode returnMode
Definition: execnodes.h:270
json_struct_action array_start
Definition: jsonapi.h:87
Definition: regguts.h:298
MemoryContext ecxt_per_query_memory
Definition: execnodes.h:202
Tuplestorestate * setResult
Definition: execnodes.h:273
ExprContext * econtext
Definition: execnodes.h:266
TupleDesc setDesc
Definition: execnodes.h:274
int errmsg(const char *fmt,...)
Definition: elog.c:797
Definition: c.h:487
json_ofield_action object_field_start
Definition: jsonapi.h:89
void * semstate
Definition: jsonapi.h:84
static void each_object_field_end(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:1891
#define PG_RETURN_NULL()
Definition: fmgr.h:305
bool next_scalar
Definition: jsonfuncs.c:107

◆ each_worker_jsonb()

static Datum each_worker_jsonb ( FunctionCallInfo  fcinfo,
const char *  funcname,
bool  as_text 
)
static

Definition at line 1671 of file jsonfuncs.c.

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate(), ReturnSetInfo::allowedModes, BlessTupleDesc(), CreateTupleDescCopy(), cstring_to_text_with_len(), CurrentMemoryContext, StringInfoData::data, ReturnSetInfo::econtext, ExprContext::ecxt_per_query_memory, ereport, errcode(), errmsg(), ERROR, ReturnSetInfo::expectedDesc, get_call_result_type(), heap_form_tuple(), IsA, JB_ROOT_IS_OBJECT, jbvNull, jbvString, JsonbIteratorInit(), JsonbIteratorNext(), JsonbToCString(), JsonbValueToJsonb(), StringInfoData::len, makeStringInfo(), MemoryContextDelete(), MemoryContextReset(), MemoryContextSwitchTo(), PG_GETARG_JSONB_P, PG_RETURN_NULL, PointerGetDatum, FunctionCallInfoData::resultinfo, ReturnSetInfo::returnMode, Jsonb::root, ReturnSetInfo::setDesc, ReturnSetInfo::setResult, SFRM_Materialize, SFRM_Materialize_Random, tuplestore_begin_heap(), tuplestore_puttuple(), JsonbValue::type, TYPEFUNC_COMPOSITE, JsonbValue::val, val, values, WJB_DONE, WJB_KEY, and work_mem.

Referenced by jsonb_each(), and jsonb_each_text().

1672 {
1673  Jsonb *jb = PG_GETARG_JSONB_P(0);
1674  ReturnSetInfo *rsi;
1675  Tuplestorestate *tuple_store;
1676  TupleDesc tupdesc;
1677  TupleDesc ret_tdesc;
1678  MemoryContext old_cxt,
1679  tmp_cxt;
1680  bool skipNested = false;
1681  JsonbIterator *it;
1682  JsonbValue v;
1684 
1685  if (!JB_ROOT_IS_OBJECT(jb))
1686  ereport(ERROR,
1687  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1688  errmsg("cannot call %s on a non-object",
1689  funcname)));
1690 
1691  rsi = (ReturnSetInfo *) fcinfo->resultinfo;
1692 
1693  if (!rsi || !IsA(rsi, ReturnSetInfo) ||
1694  (rsi->allowedModes & SFRM_Materialize) == 0 ||
1695  rsi->expectedDesc == NULL)
1696  ereport(ERROR,
1697  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1698  errmsg("set-valued function called in context that "
1699  "cannot accept a set")));
1700 
1702 
1703  if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
1704  ereport(ERROR,
1705  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1706  errmsg("function returning record called in context "
1707  "that cannot accept type record")));
1708 
1710 
1711  ret_tdesc = CreateTupleDescCopy(tupdesc);
1712  BlessTupleDesc(ret_tdesc);
1713  tuple_store =
1715  false, work_mem);
1716 
1717  MemoryContextSwitchTo(old_cxt);
1718 
1720  "jsonb_each temporary cxt",
1722 
1723  it = JsonbIteratorInit(&jb->root);
1724 
1725  while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE)
1726  {
1727  skipNested = true;
1728 
1729  if (r == WJB_KEY)
1730  {
1731  text *key;
1732  HeapTuple tuple;
1733  Datum values[2];
1734  bool nulls[2] = {false, false};
1735 
1736  /* Use the tmp context so we can clean up after each tuple is done */
1737  old_cxt = MemoryContextSwitchTo(tmp_cxt);
1738 
1739  key = cstring_to_text_with_len(v.val.string.val, v.val.string.len);
1740 
1741  /*
1742  * The next thing the iterator fetches should be the value, no
1743  * matter what shape it is.
1744  */
1745  r = JsonbIteratorNext(&it, &v, skipNested);
1746 
1747  values[0] = PointerGetDatum(key);
1748 
1749  if (as_text)
1750  {
1751  if (v.type == jbvNull)
1752  {
1753  /* a json null is an sql null in text mode */
1754  nulls[1] = true;
1755  values[1] = (Datum) NULL;
1756  }
1757  else
1758  {
1759  text *sv;
1760 
1761  if (v.type == jbvString)
1762  {
1763  /* In text mode, scalar strings should be dequoted */
1764  sv = cstring_to_text_with_len(v.val.string.val, v.val.string.len);
1765  }
1766  else
1767  {
1768  /* Turn anything else into a json string */
1769  StringInfo jtext = makeStringInfo();
1770  Jsonb *jb = JsonbValueToJsonb(&v);
1771 
1772  (void) JsonbToCString(jtext, &jb->root, 0);
1773  sv = cstring_to_text_with_len(jtext->data, jtext->len);
1774  }
1775 
1776  values[1] = PointerGetDatum(sv);
1777  }
1778  }
1779  else
1780  {
1781  /* Not in text mode, just return the Jsonb */
1782  Jsonb *val = JsonbValueToJsonb(&v);
1783 
1784  values[1] = PointerGetDatum(val);
1785  }
1786 
1787  tuple = heap_form_tuple(ret_tdesc, values, nulls);
1788 
1789  tuplestore_puttuple(tuple_store, tuple);
1790 
1791  /* clean up and switch back */
1792  MemoryContextSwitchTo(old_cxt);
1793  MemoryContextReset(tmp_cxt);
1794  }
1795  }
1796 
1797  MemoryContextDelete(tmp_cxt);
1798 
1799  rsi->setResult = tuple_store;
1800  rsi->setDesc = ret_tdesc;
1801 
1802  PG_RETURN_NULL();
1803 }
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
Definition: tupdesc.c:102
#define IsA(nodeptr, _type_)
Definition: nodes.h:561
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:200
#define JB_ROOT_IS_OBJECT(jbp_)
Definition: jsonb.h:224
TypeFuncClass get_call_result_type(FunctionCallInfo fcinfo, Oid *resultTypeId, TupleDesc *resultTupleDesc)
Definition: funcapi.c:211
Jsonb * JsonbValueToJsonb(JsonbValue *val)
Definition: jsonb_util.c:79
Definition: jsonb.h:215
#define PointerGetDatum(X)
Definition: postgres.h:562
char * val
Definition: jsonb.h:259
StringInfo makeStringInfo(void)
Definition: stringinfo.c:28
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
Definition: jsonb.h:22
int errcode(int sqlerrcode)
Definition: elog.c:575
void MemoryContextReset(MemoryContext context)
Definition: mcxt.c:135
Definition: jsonb.h:231
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:695
TupleDesc expectedDesc
Definition: execnodes.h:267
#define ERROR
Definition: elog.h:43
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:165
void tuplestore_puttuple(Tuplestorestate *state, HeapTuple tuple)
Definition: tuplestore.c:730
TupleDesc BlessTupleDesc(TupleDesc tupdesc)
Definition: execTuples.c:1032
text * cstring_to_text_with_len(const char *s, int len)
Definition: varlena.c:161
fmNodePtr resultinfo
Definition: fmgr.h:81
Definition: jsonb.h:23
MemoryContext CurrentMemoryContext
Definition: mcxt.c:37
#define ereport(elevel, rest)
Definition: elog.h:122
JsonbIteratorToken
Definition: jsonb.h:20
JsonbContainer root
Definition: jsonb.h:218
Tuplestorestate * tuplestore_begin_heap(bool randomAccess, bool interXact, int maxKBytes)
Definition: tuplestore.c:318
MemoryContext AllocSetContextCreate(MemoryContext parent, const char *name, Size minContextSize, Size initBlockSize, Size maxBlockSize)
Definition: aset.c:322
uintptr_t Datum
Definition: postgres.h:372
int work_mem
Definition: globals.c:113
int allowedModes
Definition: execnodes.h:268
SetFunctionReturnMode returnMode
Definition: execnodes.h:270
JsonbIterator * JsonbIteratorInit(JsonbContainer *container)
Definition: jsonb_util.c:718
char * JsonbToCString(StringInfo out, JsonbContainer *in, int estimated_len)
Definition: jsonb.c:429
MemoryContext ecxt_per_query_memory
Definition: execnodes.h:202
enum jbvType type
Definition: jsonb.h:250
Tuplestorestate * setResult
Definition: execnodes.h:273
static Datum values[MAXATTR]
Definition: bootstrap.c:164
ExprContext * econtext
Definition: execnodes.h:266
TupleDesc setDesc
Definition: execnodes.h:274
int errmsg(const char *fmt,...)
Definition: elog.c:797
Definition: c.h:487
long val
Definition: informix.c:689
#define PG_RETURN_NULL()
Definition: fmgr.h:305
JsonbIteratorToken JsonbIteratorNext(JsonbIterator **it, JsonbValue *val, bool skipNested)
Definition: jsonb_util.c:754
#define PG_GETARG_JSONB_P(x)
Definition: jsonb.h:70

◆ elements_array_element_end()

static void elements_array_element_end ( void *  state,
bool  isnull 
)
static

Definition at line 2207 of file jsonfuncs.c.

References cstring_to_text_with_len(), CStringGetTextDatum, heap_form_tuple(), ElementsState::lex, JsonLexContext::lex_level, MemoryContextReset(), MemoryContextSwitchTo(), ElementsState::next_scalar, ElementsState::normalize_results, ElementsState::normalized_scalar, PointerGetDatum, JsonLexContext::prev_token_terminator, ElementsState::result_start, ElementsState::ret_tdesc, ElementsState::tmp_cxt, ElementsState::tuple_store, tuplestore_puttuple(), val, and values.

Referenced by elements_worker().

2208 {
2209  ElementsState *_state = (ElementsState *) state;
2210  MemoryContext old_cxt;
2211  int len;
2212  text *val;
2213  HeapTuple tuple;
2214  Datum values[1];
2215  bool nulls[1] = {false};
2216 
2217  /* skip over nested objects */
2218  if (_state->lex->lex_level != 1)
2219  return;
2220 
2221  /* use the tmp context so we can clean up after each tuple is done */
2222  old_cxt = MemoryContextSwitchTo(_state->tmp_cxt);
2223 
2224  if (isnull && _state->normalize_results)
2225  {
2226  nulls[0] = true;
2227  values[0] = (Datum) NULL;
2228  }
2229  else if (_state->next_scalar)
2230  {
2231  values[0] = CStringGetTextDatum(_state->normalized_scalar);
2232  _state->next_scalar = false;
2233  }
2234  else
2235  {
2236  len = _state->lex->prev_token_terminator - _state->result_start;
2237  val = cstring_to_text_with_len(_state->result_start, len);
2238  values[0] = PointerGetDatum(val);
2239  }
2240 
2241  tuple = heap_form_tuple(_state->ret_tdesc, values, nulls);
2242 
2243  tuplestore_puttuple(_state->tuple_store, tuple);
2244 
2245  /* clean up and switch back */
2246  MemoryContextSwitchTo(old_cxt);
2247  MemoryContextReset(_state->tmp_cxt);
2248 }
bool normalize_results
Definition: jsonfuncs.c:120
JsonLexContext * lex
Definition: jsonfuncs.c:114
bool next_scalar
Definition: jsonfuncs.c:121
#define PointerGetDatum(X)
Definition: postgres.h:562
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
char * prev_token_terminator
Definition: jsonapi.h:57
void MemoryContextReset(MemoryContext context)
Definition: mcxt.c:135
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:695
int lex_level
Definition: jsonapi.h:59
TupleDesc ret_tdesc
Definition: jsonfuncs.c:117
void tuplestore_puttuple(Tuplestorestate *state, HeapTuple tuple)
Definition: tuplestore.c:730
text * cstring_to_text_with_len(const char *s, int len)
Definition: varlena.c:161
uintptr_t Datum
Definition: postgres.h:372
Tuplestorestate * tuple_store
Definition: jsonfuncs.c:116
char * result_start
Definition: jsonfuncs.c:119
Definition: regguts.h:298
static Datum values[MAXATTR]
Definition: bootstrap.c:164
char * normalized_scalar
Definition: jsonfuncs.c:122
#define CStringGetTextDatum(s)
Definition: builtins.h:91
MemoryContext tmp_cxt
Definition: jsonfuncs.c:118
Definition: c.h:487
long val
Definition: informix.c:689

◆ elements_array_element_start()

static void elements_array_element_start ( void *  state,
bool  isnull 
)
static

Definition at line 2187 of file jsonfuncs.c.

References JSON_TOKEN_STRING, ElementsState::lex, JsonLexContext::lex_level, ElementsState::next_scalar, ElementsState::normalize_results, ElementsState::result_start, JsonLexContext::token_start, and JsonLexContext::token_type.

Referenced by elements_worker().

2188 {
2189  ElementsState *_state = (ElementsState *) state;
2190 
2191  /* save a pointer to where the value starts */
2192  if (_state->lex->lex_level == 1)
2193  {
2194  /*
2195  * next_scalar will be reset in the array_element_end handler, and
2196  * since we know the value is a scalar there is no danger of it being
2197  * on while recursing down the tree.
2198  */
2199  if (_state->normalize_results && _state->lex->token_type == JSON_TOKEN_STRING)
2200  _state->next_scalar = true;
2201  else
2202  _state->result_start = _state->lex->token_start;
2203  }
2204 }
bool normalize_results
Definition: jsonfuncs.c:120
JsonLexContext * lex
Definition: jsonfuncs.c:114
bool next_scalar
Definition: jsonfuncs.c:121
JsonTokenType token_type
Definition: jsonapi.h:58
int lex_level
Definition: jsonapi.h:59
char * token_start
Definition: jsonapi.h:55
char * result_start
Definition: jsonfuncs.c:119
Definition: regguts.h:298

◆ elements_object_start()

static void elements_object_start ( void *  state)
static

Definition at line 2251 of file jsonfuncs.c.

References ereport, errcode(), errmsg(), ERROR, ElementsState::function_name, ElementsState::lex, and JsonLexContext::lex_level.

Referenced by elements_worker().

2252 {
2253  ElementsState *_state = (ElementsState *) state;
2254 
2255  /* json structure check */
2256  if (_state->lex->lex_level == 0)
2257  ereport(ERROR,
2258  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2259  errmsg("cannot call %s on a non-array",
2260  _state->function_name)));
2261 }
const char * function_name
Definition: jsonfuncs.c:115
JsonLexContext * lex
Definition: jsonfuncs.c:114
int errcode(int sqlerrcode)
Definition: elog.c:575
int lex_level
Definition: jsonapi.h:59
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:122
Definition: regguts.h:298
int errmsg(const char *fmt,...)
Definition: elog.c:797

◆ elements_scalar()

static void elements_scalar ( void *  state,
char *  token,
JsonTokenType  tokentype 
)
static

Definition at line 2264 of file jsonfuncs.c.

References ereport, errcode(), errmsg(), ERROR, ElementsState::function_name, ElementsState::lex, JsonLexContext::lex_level, ElementsState::next_scalar, and ElementsState::normalized_scalar.

Referenced by elements_worker().

2265 {
2266  ElementsState *_state = (ElementsState *) state;
2267 
2268  /* json structure check */
2269  if (_state->lex->lex_level == 0)
2270  ereport(ERROR,
2271  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2272  errmsg("cannot call %s on a scalar",
2273  _state->function_name)));
2274 
2275  /* supply de-escaped value if required */
2276  if (_state->next_scalar)
2277  _state->normalized_scalar = token;
2278 }
const char * function_name
Definition: jsonfuncs.c:115
JsonLexContext * lex
Definition: jsonfuncs.c:114
bool next_scalar
Definition: jsonfuncs.c:121
int errcode(int sqlerrcode)
Definition: elog.c:575
int lex_level
Definition: jsonapi.h:59
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:122
Definition: regguts.h:298
char * normalized_scalar
Definition: jsonfuncs.c:122
int errmsg(const char *fmt,...)
Definition: elog.c:797

◆ elements_worker()

static Datum elements_worker ( FunctionCallInfo  fcinfo,
const char *  funcname,
bool  as_text 
)
static

Definition at line 2121 of file jsonfuncs.c.

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate(), ReturnSetInfo::allowedModes, JsonSemAction::array_element_end, JsonSemAction::array_element_start, BlessTupleDesc(), CreateTupleDescCopy(), CurrentMemoryContext, ReturnSetInfo::econtext, ExprContext::ecxt_per_query_memory, elements_array_element_end(), elements_array_element_start(), elements_object_start(), elements_scalar(), ereport, errcode(), errmsg(), ERROR, ReturnSetInfo::expectedDesc, ElementsState::function_name, IsA, OkeysState::lex, ElementsState::lex, makeJsonLexContext(), MemoryContextDelete(), MemoryContextSwitchTo(), ElementsState::next_scalar, ElementsState::normalize_results, JsonSemAction::object_start, palloc0(), PG_GETARG_TEXT_PP, pg_parse_json(), PG_RETURN_NULL, FunctionCallInfoData::resultinfo, ElementsState::ret_tdesc, ReturnSetInfo::returnMode, JsonSemAction::scalar, JsonSemAction::semstate, ReturnSetInfo::setDesc, ReturnSetInfo::setResult, SFRM_Materialize, SFRM_Materialize_Random, ElementsState::tmp_cxt, ElementsState::tuple_store, tuplestore_begin_heap(), and work_mem.

Referenced by json_array_elements(), and json_array_elements_text().

2122 {
2123  text *json = PG_GETARG_TEXT_PP(0);
2124 
2125  /* elements only needs escaped strings when as_text */
2126  JsonLexContext *lex = makeJsonLexContext(json, as_text);
2127  JsonSemAction *sem;
2128  ReturnSetInfo *rsi;
2129  MemoryContext old_cxt;
2130  TupleDesc tupdesc;
2132 
2133  state = palloc0(sizeof(ElementsState));
2134  sem = palloc0(sizeof(JsonSemAction));
2135 
2136  rsi = (ReturnSetInfo *) fcinfo->resultinfo;
2137 
2138  if (!rsi || !IsA(rsi, ReturnSetInfo) ||
2139  (rsi->allowedModes & SFRM_Materialize) == 0 ||
2140  rsi->expectedDesc == NULL)
2141  ereport(ERROR,
2142  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2143  errmsg("set-valued function called in context that "
2144  "cannot accept a set")));
2145 
2147 
2148  /* it's a simple type, so don't use get_call_result_type() */
2149  tupdesc = rsi->expectedDesc;
2150 
2151  /* make these in a sufficiently long-lived memory context */
2153 
2154  state->ret_tdesc = CreateTupleDescCopy(tupdesc);
2155  BlessTupleDesc(state->ret_tdesc);
2156  state->tuple_store =
2158  false, work_mem);
2159 
2160  MemoryContextSwitchTo(old_cxt);
2161 
2162  sem->semstate = (void *) state;
2164  sem->scalar = elements_scalar;
2167 
2168  state->function_name = funcname;
2169  state->normalize_results = as_text;
2170  state->next_scalar = false;
2171  state->lex = lex;
2173  "json_array_elements temporary cxt",
2175 
2176  pg_parse_json(lex, sem);
2177 
2178  MemoryContextDelete(state->tmp_cxt);
2179 
2180  rsi->setResult = state->tuple_store;
2181  rsi->setDesc = state->ret_tdesc;
2182 
2183  PG_RETURN_NULL();
2184 }
bool normalize_results
Definition: jsonfuncs.c:120
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
Definition: tupdesc.c:102
#define IsA(nodeptr, _type_)
Definition: nodes.h:561
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:200
const char * function_name
Definition: jsonfuncs.c:115
JsonLexContext * lex
Definition: jsonfuncs.c:114
static void elements_object_start(void *state)
Definition: jsonfuncs.c:2251
bool next_scalar
Definition: jsonfuncs.c:121
json_struct_action object_start
Definition: jsonapi.h:85
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
int errcode(int sqlerrcode)
Definition: elog.c:575
json_scalar_action scalar
Definition: jsonapi.h:93
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:273
TupleDesc expectedDesc
Definition: execnodes.h:267
TupleDesc ret_tdesc
Definition: jsonfuncs.c:117
JsonLexContext * makeJsonLexContext(text *json, bool need_escapes)
Definition: json.c:301
#define ERROR
Definition: elog.h:43
void pg_parse_json(JsonLexContext *lex, JsonSemAction *sem)
Definition: json.c:332
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:165
TupleDesc BlessTupleDesc(TupleDesc tupdesc)
Definition: execTuples.c:1032
fmNodePtr resultinfo
Definition: fmgr.h:81
MemoryContext CurrentMemoryContext
Definition: mcxt.c:37
#define ereport(elevel, rest)
Definition: elog.h:122
static void elements_array_element_start(void *state, bool isnull)
Definition: jsonfuncs.c:2187
Tuplestorestate * tuplestore_begin_heap(bool randomAccess, bool interXact, int maxKBytes)
Definition: tuplestore.c:318
MemoryContext AllocSetContextCreate(MemoryContext parent, const char *name, Size minContextSize, Size initBlockSize, Size maxBlockSize)
Definition: aset.c:322
static void elements_array_element_end(void *state, bool isnull)
Definition: jsonfuncs.c:2207
void * palloc0(Size size)
Definition: mcxt.c:877
static void elements_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:2264
json_aelem_action array_element_start
Definition: jsonapi.h:91
Tuplestorestate * tuple_store
Definition: jsonfuncs.c:116
int work_mem
Definition: globals.c:113
int allowedModes
Definition: execnodes.h:268
SetFunctionReturnMode returnMode
Definition: execnodes.h:270
Definition: regguts.h:298
MemoryContext ecxt_per_query_memory
Definition: execnodes.h:202
Tuplestorestate * setResult
Definition: execnodes.h:273
ExprContext * econtext
Definition: execnodes.h:266
TupleDesc setDesc
Definition: execnodes.h:274
int errmsg(const char *fmt,...)
Definition: elog.c:797
MemoryContext tmp_cxt
Definition: jsonfuncs.c:118
Definition: c.h:487
void * semstate
Definition: jsonapi.h:84
#define PG_RETURN_NULL()
Definition: fmgr.h:305
json_aelem_action array_element_end
Definition: jsonapi.h:92

◆ elements_worker_jsonb()

static Datum elements_worker_jsonb ( FunctionCallInfo  fcinfo,
const char *  funcname,
bool  as_text 
)
static

Definition at line 1985 of file jsonfuncs.c.

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate(), ReturnSetInfo::allowedModes, BlessTupleDesc(), CreateTupleDescCopy(), cstring_to_text_with_len(), CurrentMemoryContext, StringInfoData::data, ReturnSetInfo::econtext, ExprContext::ecxt_per_query_memory, ereport, errcode(), errmsg(), ERROR, ReturnSetInfo::expectedDesc, heap_form_tuple(), IsA, JB_ROOT_IS_ARRAY, JB_ROOT_IS_SCALAR, jbvNull, jbvString, JsonbIteratorInit(), JsonbIteratorNext(), JsonbToCString(), JsonbValueToJsonb(), StringInfoData::len, makeStringInfo(), MemoryContextDelete(), MemoryContextReset(), MemoryContextSwitchTo(), PG_GETARG_JSONB_P, PG_RETURN_NULL, PointerGetDatum, FunctionCallInfoData::resultinfo, ReturnSetInfo::returnMode, Jsonb::root, ReturnSetInfo::setDesc, ReturnSetInfo::setResult, SFRM_Materialize, SFRM_Materialize_Random, tuplestore_begin_heap(), tuplestore_puttuple(), JsonbValue::type, JsonbValue::val, val, values, WJB_DONE, WJB_ELEM, and work_mem.

Referenced by jsonb_array_elements(), and jsonb_array_elements_text().

1987 {
1988  Jsonb *jb = PG_GETARG_JSONB_P(0);
1989  ReturnSetInfo *rsi;
1990  Tuplestorestate *tuple_store;
1991  TupleDesc tupdesc;
1992  TupleDesc ret_tdesc;
1993  MemoryContext old_cxt,
1994  tmp_cxt;
1995  bool skipNested = false;
1996  JsonbIterator *it;
1997  JsonbValue v;
1999 
2000  if (JB_ROOT_IS_SCALAR(jb))
2001  ereport(ERROR,
2002  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2003  errmsg("cannot extract elements from a scalar")));
2004  else if (!JB_ROOT_IS_ARRAY(jb))
2005  ereport(ERROR,
2006  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2007  errmsg("cannot extract elements from an object")));
2008 
2009  rsi = (ReturnSetInfo *) fcinfo->resultinfo;
2010 
2011  if (!rsi || !IsA(rsi, ReturnSetInfo) ||
2012  (rsi->allowedModes & SFRM_Materialize) == 0 ||
2013  rsi->expectedDesc == NULL)
2014  ereport(ERROR,
2015  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2016  errmsg("set-valued function called in context that "
2017  "cannot accept a set")));
2018 
2020 
2021  /* it's a simple type, so don't use get_call_result_type() */
2022  tupdesc = rsi->expectedDesc;
2023 
2025 
2026  ret_tdesc = CreateTupleDescCopy(tupdesc);
2027  BlessTupleDesc(ret_tdesc);
2028  tuple_store =
2030  false, work_mem);
2031 
2032  MemoryContextSwitchTo(old_cxt);
2033 
2035  "jsonb_array_elements temporary cxt",
2037 
2038  it = JsonbIteratorInit(&jb->root);
2039 
2040  while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE)
2041  {
2042  skipNested = true;
2043 
2044  if (r == WJB_ELEM)
2045  {
2046  HeapTuple tuple;
2047  Datum values[1];
2048  bool nulls[1] = {false};
2049 
2050  /* use the tmp context so we can clean up after each tuple is done */
2051  old_cxt = MemoryContextSwitchTo(tmp_cxt);
2052 
2053  if (!as_text)
2054  {
2055  Jsonb *val = JsonbValueToJsonb(&v);
2056 
2057  values[0] = PointerGetDatum(val);
2058  }
2059  else
2060  {
2061  if (v.type == jbvNull)
2062  {
2063  /* a json null is an sql null in text mode */
2064  nulls[0] = true;
2065  values[0] = (Datum) NULL;
2066  }
2067  else
2068  {
2069  text *sv;
2070 
2071  if (v.type == jbvString)
2072  {
2073  /* in text mode scalar strings should be dequoted */
2074  sv = cstring_to_text_with_len(v.val.string.val, v.val.string.len);
2075  }
2076  else
2077  {
2078  /* turn anything else into a json string */
2079  StringInfo jtext = makeStringInfo();
2080  Jsonb *jb = JsonbValueToJsonb(&v);
2081 
2082  (void) JsonbToCString(jtext, &jb->root, 0);
2083  sv = cstring_to_text_with_len(jtext->data, jtext->len);
2084  }
2085 
2086  values[0] = PointerGetDatum(sv);
2087  }
2088  }
2089 
2090  tuple = heap_form_tuple(ret_tdesc, values, nulls);
2091 
2092  tuplestore_puttuple(tuple_store, tuple);
2093 
2094  /* clean up and switch back */
2095  MemoryContextSwitchTo(old_cxt);
2096  MemoryContextReset(tmp_cxt);
2097  }
2098  }
2099 
2100  MemoryContextDelete(tmp_cxt);
2101 
2102  rsi->setResult = tuple_store;
2103  rsi->setDesc = ret_tdesc;
2104 
2105  PG_RETURN_NULL();
2106 }
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
Definition: tupdesc.c:102
#define IsA(nodeptr, _type_)
Definition: nodes.h:561
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:200
Jsonb * JsonbValueToJsonb(JsonbValue *val)
Definition: jsonb_util.c:79
Definition: jsonb.h:215
#define PointerGetDatum(X)
Definition: postgres.h:562
char * val
Definition: jsonb.h:259
StringInfo makeStringInfo(void)
Definition: stringinfo.c:28
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
Definition: jsonb.h:22
int errcode(int sqlerrcode)
Definition: elog.c:575
void MemoryContextReset(MemoryContext context)
Definition: mcxt.c:135
Definition: jsonb.h:231
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:695
#define JB_ROOT_IS_SCALAR(jbp_)
Definition: jsonb.h:223
TupleDesc expectedDesc
Definition: execnodes.h:267
#define ERROR
Definition: elog.h:43
#define JB_ROOT_IS_ARRAY(jbp_)
Definition: jsonb.h:225
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:165
void tuplestore_puttuple(Tuplestorestate *state, HeapTuple tuple)
Definition: tuplestore.c:730
TupleDesc BlessTupleDesc(TupleDesc tupdesc)
Definition: execTuples.c:1032
text * cstring_to_text_with_len(const char *s, int len)
Definition: varlena.c:161
fmNodePtr resultinfo
Definition: fmgr.h:81
MemoryContext CurrentMemoryContext
Definition: mcxt.c:37
#define ereport(elevel, rest)
Definition: elog.h:122
JsonbIteratorToken
Definition: jsonb.h:20
JsonbContainer root
Definition: jsonb.h:218
Tuplestorestate * tuplestore_begin_heap(bool randomAccess, bool interXact, int maxKBytes)
Definition: tuplestore.c:318
MemoryContext AllocSetContextCreate(MemoryContext parent, const char *name, Size minContextSize, Size initBlockSize, Size maxBlockSize)
Definition: aset.c:322
uintptr_t Datum
Definition: postgres.h:372
int work_mem
Definition: globals.c:113
int allowedModes
Definition: execnodes.h:268
SetFunctionReturnMode returnMode
Definition: execnodes.h:270
JsonbIterator * JsonbIteratorInit(JsonbContainer *container)
Definition: jsonb_util.c:718
char * JsonbToCString(StringInfo out, JsonbContainer *in, int estimated_len)
Definition: jsonb.c:429
MemoryContext ecxt_per_query_memory
Definition: execnodes.h:202
enum jbvType type
Definition: jsonb.h:250
Tuplestorestate * setResult
Definition: execnodes.h:273
static Datum values[MAXATTR]
Definition: bootstrap.c:164
ExprContext * econtext
Definition: execnodes.h:266
TupleDesc setDesc
Definition: execnodes.h:274
int errmsg(const char *fmt,...)
Definition: elog.c:797
Definition: c.h:487
long val
Definition: informix.c:689
#define PG_RETURN_NULL()
Definition: fmgr.h:305
JsonbIteratorToken JsonbIteratorNext(JsonbIterator **it, JsonbValue *val, bool skipNested)
Definition: jsonb_util.c:754
Definition: jsonb.h:25
#define PG_GETARG_JSONB_P(x)
Definition: jsonb.h:70

◆ findJsonbValueFromContainerLen()

static JsonbValue * findJsonbValueFromContainerLen ( JsonbContainer container,
uint32  flags,
char *  key,
uint32  keylen 
)
static

Definition at line 3889 of file jsonfuncs.c.

References findJsonbValueFromContainer(), jbvString, JsonbValue::type, and JsonbValue::val.

Referenced by get_jsonb_path_all(), JsObjectGetField(), jsonb_object_field(), and jsonb_object_field_text().

3891 {
3892  JsonbValue k;
3893 
3894  k.type = jbvString;
3895  k.val.string.val = key;
3896  k.val.string.len = keylen;
3897 
3898  return findJsonbValueFromContainer(container, flags, &k);
3899 }
char * val
Definition: jsonb.h:259
enum jbvType type
Definition: jsonb.h:250
JsonbValue * findJsonbValueFromContainer(JsonbContainer *container, uint32 flags, JsonbValue *key)
Definition: jsonb_util.c:327

◆ get_array_element_end()

static void get_array_element_end ( void *  state,
bool  isnull 
)
static

Definition at line 1290 of file jsonfuncs.c.

References GetState::array_cur_index, cstring_to_text_with_len(), GetState::lex, JsonLexContext::lex_level, GetState::normalize_results, GetState::path_indexes, GetState::pathok, JsonLexContext::prev_token_terminator, GetState::result_start, and GetState::tresult.

Referenced by get_worker().

1291 {
1292  GetState *_state = (GetState *) state;
1293  bool get_last = false;
1294  int lex_level = _state->lex->lex_level;
1295 
1296  /* same tests as in get_array_element_start */
1297  if (lex_level <= _state->npath &&
1298  _state->pathok[lex_level - 1] &&
1299  _state->path_indexes != NULL &&
1300  _state->array_cur_index[lex_level - 1] == _state->path_indexes[lex_level - 1])
1301  {
1302  if (lex_level < _state->npath)
1303  {
1304  /* done with this element so reset pathok */
1305  _state->pathok[lex_level] = false;
1306  }
1307  else
1308  {
1309  /* end of path, so we want this value */
1310  get_last = true;
1311  }
1312  }
1313 
1314  /* same logic as for objects */
1315  if (get_last && _state->result_start != NULL)
1316  {
1317  if (isnull && _state->normalize_results)
1318  _state->tresult = (text *) NULL;
1319  else
1320  {
1321  char *start = _state->result_start;
1322  int len = _state->lex->prev_token_terminator - start;
1323 
1324  _state->tresult = cstring_to_text_with_len(start, len);
1325  }
1326 
1327  _state->result_start = NULL;
1328  }
1329 }
int * array_cur_index
Definition: jsonfuncs.c:87
char * prev_token_terminator
Definition: jsonapi.h:57
int lex_level
Definition: jsonapi.h:59
JsonLexContext * lex
Definition: jsonfuncs.c:78
char * result_start
Definition: jsonfuncs.c:80
text * tresult
Definition: jsonfuncs.c:79
text * cstring_to_text_with_len(const char *s, int len)
Definition: varlena.c:161
bool * pathok
Definition: jsonfuncs.c:86
bool normalize_results
Definition: jsonfuncs.c:81
Definition: regguts.h:298
int * path_indexes
Definition: jsonfuncs.c:85
Definition: c.h:487

◆ get_array_element_start()

static void get_array_element_start ( void *  state,
bool  isnull 
)
static

Definition at line 1244 of file jsonfuncs.c.

References GetState::array_cur_index, JSON_TOKEN_STRING, GetState::lex, JsonLexContext::lex_level, GetState::next_scalar, GetState::normalize_results, GetState::path_indexes, GetState::pathok, GetState::result_start, JsonLexContext::token_start, JsonLexContext::token_type, and GetState::tresult.

Referenced by get_worker().

1245 {
1246  GetState *_state = (GetState *) state;
1247  bool get_next = false;
1248  int lex_level = _state->lex->lex_level;
1249 
1250  /* Update array element counter */
1251  if (lex_level <= _state->npath)
1252  _state->array_cur_index[lex_level - 1]++;
1253 
1254  if (lex_level <= _state->npath &&
1255  _state->pathok[lex_level - 1] &&
1256  _state->path_indexes != NULL &&
1257  _state->array_cur_index[lex_level - 1] == _state->path_indexes[lex_level - 1])
1258  {
1259  if (lex_level < _state->npath)
1260  {
1261  /* if not at end of path just mark path ok */
1262  _state->pathok[lex_level] = true;
1263  }
1264  else
1265  {
1266  /* end of path, so we want this value */
1267  get_next = true;
1268  }
1269  }
1270 
1271  /* same logic as for objects */
1272  if (get_next)
1273  {
1274  _state->tresult = NULL;
1275  _state->result_start = NULL;
1276 
1277  if (_state->normalize_results &&
1278  _state->lex->token_type == JSON_TOKEN_STRING)
1279  {
1280  _state->next_scalar = true;
1281  }
1282  else
1283  {
1284  _state->result_start = _state->lex->token_start;
1285  }
1286  }
1287 }
int * array_cur_index
Definition: jsonfuncs.c:87
JsonTokenType token_type
Definition: jsonapi.h:58
int lex_level
Definition: jsonapi.h:59
JsonLexContext * lex
Definition: jsonfuncs.c:78
char * result_start
Definition: jsonfuncs.c:80
text * tresult
Definition: jsonfuncs.c:79
char * token_start
Definition: jsonapi.h:55
bool * pathok
Definition: jsonfuncs.c:86
bool normalize_results
Definition: jsonfuncs.c:81
bool next_scalar
Definition: jsonfuncs.c:82
Definition: regguts.h:298
int * path_indexes
Definition: jsonfuncs.c:85

◆ get_array_end()

static void get_array_end ( void *  state)
static

Definition at line 1228 of file jsonfuncs.c.

References cstring_to_text_with_len(), GetState::lex, JsonLexContext::lex_level, GetState::npath, JsonLexContext::prev_token_terminator, GetState::result_start, and GetState::tresult.

Referenced by get_worker().

1229 {
1230  GetState *_state = (GetState *) state;
1231  int lex_level = _state->lex->lex_level;
1232 
1233  if (lex_level == 0 && _state->npath == 0)
1234  {
1235  /* Special case: return the entire array */
1236  char *start = _state->result_start;
1237  int len = _state->lex->prev_token_terminator - start;
1238 
1239  _state->tresult = cstring_to_text_with_len(start, len);
1240  }
1241 }
char * prev_token_terminator
Definition: jsonapi.h:57
int lex_level
Definition: jsonapi.h:59
JsonLexContext * lex
Definition: jsonfuncs.c:78
char * result_start
Definition: jsonfuncs.c:80
text * tresult
Definition: jsonfuncs.c:79
text * cstring_to_text_with_len(const char *s, int len)
Definition: varlena.c:161
int npath
Definition: jsonfuncs.c:83
Definition: regguts.h:298

◆ get_array_start()

static void get_array_start ( void *  state)
static

Definition at line 1195 of file jsonfuncs.c.

References GetState::array_cur_index, json_count_array_elements(), GetState::lex, JsonLexContext::lex_level, GetState::npath, GetState::path_indexes, GetState::result_start, and JsonLexContext::token_start.

Referenced by get_worker().

1196 {
1197  GetState *_state = (GetState *) state;
1198  int lex_level = _state->lex->lex_level;
1199 
1200  if (lex_level < _state->npath)
1201  {
1202  /* Initialize counting of elements in this array */
1203  _state->array_cur_index[lex_level] = -1;
1204 
1205  /* INT_MIN value is reserved to represent invalid subscript */
1206  if (_state->path_indexes[lex_level] < 0 &&
1207  _state->path_indexes[lex_level] != INT_MIN)
1208  {
1209  /* Negative subscript -- convert to positive-wise subscript */
1210  int nelements = json_count_array_elements(_state->lex);
1211 
1212  if (-_state->path_indexes[lex_level] <= nelements)
1213  _state->path_indexes[lex_level] += nelements;
1214  }
1215  }
1216  else if (lex_level == 0 && _state->npath == 0)
1217  {
1218  /*
1219  * Special case: we should match the entire array. We only need this
1220  * at the outermost level because at nested levels the match will have
1221  * been started by the outer field or array element callback.
1222  */
1223  _state->result_start = _state->lex->token_start;
1224  }
1225 }
int * array_cur_index
Definition: jsonfuncs.c:87
int lex_level
Definition: jsonapi.h:59
JsonLexContext * lex
Definition: jsonfuncs.c:78
char * result_start
Definition: jsonfuncs.c:80
int npath
Definition: jsonfuncs.c:83
int json_count_array_elements(JsonLexContext *lex)
Definition: json.c:367
char * token_start
Definition: jsonapi.h:55
Definition: regguts.h:298
int * path_indexes
Definition: jsonfuncs.c:85

◆ get_json_object_as_hash()

static HTAB * get_json_object_as_hash ( char *  json,
int  len,
const char *  funcname 
)
static

Definition at line 3337 of file jsonfuncs.c.

References JsonSemAction::array_start, CurrentMemoryContext, HASHCTL::entrysize, JHashState::function_name, JHashState::hash, hash_array_start(), HASH_CONTEXT, hash_create(), HASH_ELEM, hash_object_field_end(), hash_object_field_start(), hash_scalar(), HASHCTL::hcxt, HASHCTL::keysize, OkeysState::lex, JHashState::lex, makeJsonLexContextCstringLen(), NAMEDATALEN, JsonSemAction::object_field_end, JsonSemAction::object_field_start, palloc0(), pg_parse_json(), JsonSemAction::scalar, and JsonSemAction::semstate.

Referenced by JsValueToJsObject().

3338 {
3339  HASHCTL ctl;
3340  HTAB *tab;
3341  JHashState *state;
3342  JsonLexContext *lex = makeJsonLexContextCstringLen(json, len, true);
3343  JsonSemAction *sem;
3344 
3345  memset(&ctl, 0, sizeof(ctl));
3346  ctl.keysize = NAMEDATALEN;
3347  ctl.entrysize = sizeof(JsonHashEntry);
3348  ctl.hcxt = CurrentMemoryContext;
3349  tab = hash_create("json object hashtable",
3350  100,
3351  &ctl,
3353 
3354  state = palloc0(sizeof(JHashState));
3355  sem = palloc0(sizeof(JsonSemAction));
3356 
3357  state->function_name = funcname;
3358  state->hash = tab;
3359  state->lex = lex;
3360 
3361  sem->semstate = (void *) state;
3363  sem->scalar = hash_scalar;
3366 
3367  pg_parse_json(lex, sem);
3368 
3369  return tab;
3370 }
#define HASH_CONTEXT
Definition: hsearch.h:93
#define HASH_ELEM
Definition: hsearch.h:87
MemoryContext hcxt
Definition: hsearch.h:78
Size entrysize
Definition: hsearch.h:73
static void hash_object_field_end(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:3397
json_scalar_action scalar
Definition: jsonapi.h:93
#define NAMEDATALEN
Definition: dynahash.c:208
void pg_parse_json(JsonLexContext *lex, JsonSemAction *sem)
Definition: json.c:332
HTAB * hash
Definition: jsonfuncs.c:130
MemoryContext CurrentMemoryContext
Definition: mcxt.c:37
json_ofield_action object_field_end
Definition: jsonapi.h:90
static void hash_object_field_start(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:3373
const char * function_name
Definition: jsonfuncs.c:129
void * palloc0(Size size)
Definition: mcxt.c:877
HTAB * hash_create(const char *tabname, long nelem, HASHCTL *info, int flags)
Definition: dynahash.c:316
Size keysize
Definition: hsearch.h:72
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
struct JsonHashEntry JsonHashEntry
JsonLexContext * lex
Definition: jsonfuncs.c:128
static void hash_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:3457
json_ofield_action object_field_start
Definition: jsonapi.h:89
void * semstate
Definition: jsonapi.h:84
static void hash_array_start(void *state)
Definition: jsonfuncs.c:3446

◆ get_jsonb_path_all()

static Datum get_jsonb_path_all ( FunctionCallInfo  fcinfo,
bool  as_text 
)
static

Definition at line 1385 of file jsonfuncs.c.

References array_contains_nulls(), Assert, cstring_to_text(), cstring_to_text_with_len(), deconstruct_array(), elog, ERROR, findJsonbValueFromContainerLen(), getIthJsonbValueFromContainer(), i, JB_FOBJECT, JB_ROOT_IS_ARRAY, JB_ROOT_IS_OBJECT, JB_ROOT_IS_SCALAR, jbvArray, jbvBinary, jbvNull, jbvObject, jbvString, JsonbIteratorInit(), JsonbIteratorNext(), JsonbToCString(), JsonbValueToJsonb(), JsonContainerIsArray, JsonContainerSize, PG_GETARG_ARRAYTYPE_P, PG_GETARG_JSONB_P, PG_RETURN_JSONB_P, PG_RETURN_NULL, PG_RETURN_TEXT_P, Jsonb::root, TextDatumGetCString, TEXTOID, JsonbValue::type, JsonbValue::val, VARDATA, VARHDRSZ, VARSIZE, WJB_BEGIN_ARRAY, and WJB_BEGIN_OBJECT.

Referenced by jsonb_extract_path(), and jsonb_extract_path_text().

1386 {
1387  Jsonb *jb = PG_GETARG_JSONB_P(0);
1388  ArrayType *path = PG_GETARG_ARRAYTYPE_P(1);
1389  Jsonb *res;
1390  Datum *pathtext;
1391  bool *pathnulls;
1392  int npath;
1393  int i;
1394  bool have_object = false,
1395  have_array = false;
1396  JsonbValue *jbvp = NULL;
1397  JsonbValue tv;
1398  JsonbContainer *container;
1399 
1400  /*
1401  * If the array contains any null elements, return NULL, on the grounds
1402  * that you'd have gotten NULL if any RHS value were NULL in a nested
1403  * series of applications of the -> operator. (Note: because we also
1404  * return NULL for error cases such as no-such-field, this is true
1405  * regardless of the contents of the rest of the array.)
1406  */
1407  if (array_contains_nulls(path))
1408  PG_RETURN_NULL();
1409 
1410  deconstruct_array(path, TEXTOID, -1, false, 'i',
1411  &pathtext, &pathnulls, &npath);
1412 
1413  /* Identify whether we have object, array, or scalar at top-level */
1414  container = &jb->root;
1415 
1416  if (JB_ROOT_IS_OBJECT(jb))
1417  have_object = true;
1418  else if (JB_ROOT_IS_ARRAY(jb) && !JB_ROOT_IS_SCALAR(jb))
1419  have_array = true;
1420  else
1421  {
1423  /* Extract the scalar value, if it is what we'll return */
1424  if (npath <= 0)
1425  jbvp = getIthJsonbValueFromContainer(container, 0);
1426  }
1427 
1428  /*
1429  * If the array is empty, return the entire LHS object, on the grounds
1430  * that we should do zero field or element extractions. For the
1431  * non-scalar case we can just hand back the object without much work. For
1432  * the scalar case, fall through and deal with the value below the loop.
1433  * (This inconsistency arises because there's no easy way to generate a
1434  * JsonbValue directly for root-level containers.)
1435  */
1436  if (npath <= 0 && jbvp == NULL)
1437  {
1438  if (as_text)
1439  {
1441  container,
1442  VARSIZE(jb))));
1443  }
1444  else
1445  {
1446  /* not text mode - just hand back the jsonb */
1447  PG_RETURN_JSONB_P(jb);
1448  }
1449  }
1450 
1451  for (i = 0; i < npath; i++)
1452  {
1453  if (have_object)
1454  {
1455  jbvp = findJsonbValueFromContainerLen(container,
1456  JB_FOBJECT,
1457  VARDATA(pathtext[i]),
1458  VARSIZE(pathtext[i]) - VARHDRSZ);
1459  }
1460  else if (have_array)
1461  {
1462  long lindex;
1463  uint32 index;
1464  char *indextext = TextDatumGetCString(pathtext[i]);
1465  char *endptr;
1466 
1467  errno = 0;
1468  lindex = strtol(indextext, &endptr, 10);
1469  if (endptr == indextext || *endptr != '\0' || errno != 0 ||
1470  lindex > INT_MAX || lindex < INT_MIN)
1471  PG_RETURN_NULL();
1472 
1473  if (lindex >= 0)
1474  {
1475  index = (uint32) lindex;
1476  }
1477  else
1478  {
1479  /* Handle negative subscript */
1480  uint32 nelements;
1481 
1482  /* Container must be array, but make sure */
1483  if (!JsonContainerIsArray(container))
1484  elog(ERROR, "not a jsonb array");
1485 
1486  nelements = JsonContainerSize(container);
1487 
1488  if (-lindex > nelements)
1489  PG_RETURN_NULL();
1490  else
1491  index = nelements + lindex;
1492  }
1493 
1494  jbvp = getIthJsonbValueFromContainer(container, index);
1495  }
1496  else
1497  {
1498  /* scalar, extraction yields a null */
1499  PG_RETURN_NULL();
1500  }
1501 
1502  if (jbvp == NULL)
1503  PG_RETURN_NULL();
1504  else if (i == npath - 1)
1505  break;
1506 
1507  if (jbvp->type == jbvBinary)
1508  {
1509  JsonbIterator *it = JsonbIteratorInit((JsonbContainer *) jbvp->val.binary.data);
1511 
1512  r = JsonbIteratorNext(&it, &tv, true);
1513  container = (JsonbContainer *) jbvp->val.binary.data;
1514  have_object = r == WJB_BEGIN_OBJECT;
1515  have_array = r == WJB_BEGIN_ARRAY;
1516  }
1517  else
1518  {
1519  have_object = jbvp->type == jbvObject;
1520  have_array = jbvp->type == jbvArray;
1521  }
1522  }
1523 
1524  if (as_text)
1525  {
1526  /* special-case outputs for string and null values */
1527  if (jbvp->type == jbvString)
1529  jbvp->val.string.len));
1530  if (jbvp->type == jbvNull)
1531  PG_RETURN_NULL();
1532  }
1533 
1534  res = JsonbValueToJsonb(jbvp);
1535 
1536  if (as_text)
1537  {
1539  &res->root,
1540  VARSIZE(res))));
1541  }
1542  else
1543  {
1544  /* not text mode - just hand back the jsonb */
1545  PG_RETURN_JSONB_P(res);
1546  }
1547 }
#define JB_ROOT_IS_OBJECT(jbp_)
Definition: jsonb.h:224
#define VARDATA(PTR)
Definition: postgres.h:303
Jsonb * JsonbValueToJsonb(JsonbValue *val)
Definition: jsonb_util.c:79
Definition: jsonb.h:215
#define TEXTOID
Definition: pg_type.h:324
#define VARSIZE(PTR)
Definition: postgres.h:304
#define VARHDRSZ
Definition: c.h:493
char * val
Definition: jsonb.h:259
static JsonbValue * findJsonbValueFromContainerLen(JsonbContainer *container, uint32 flags, char *key, uint32 keylen)
Definition: jsonfuncs.c:3889
Definition: jsonb.h:231
#define JB_ROOT_IS_SCALAR(jbp_)
Definition: jsonb.h:223
Definition: type.h:89
#define PG_GETARG_ARRAYTYPE_P(n)
Definition: array.h:248
#define ERROR
Definition: elog.h:43
#define JB_ROOT_IS_ARRAY(jbp_)
Definition: jsonb.h:225
text * cstring_to_text_with_len(const char *s, int len)
Definition: varlena.c:161
#define JsonContainerSize(jc)
Definition: jsonb.h:209
unsigned int uint32
Definition: c.h:296
#define JsonContainerIsArray(jc)
Definition: jsonb.h:212
JsonbIteratorToken
Definition: jsonb.h:20
JsonbContainer root
Definition: jsonb.h:218
#define TextDatumGetCString(d)
Definition: builtins.h:92
uintptr_t Datum
Definition: postgres.h:372
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:331
text * cstring_to_text(const char *s)
Definition: varlena.c:149
JsonbValue * getIthJsonbValueFromContainer(JsonbContainer *container, uint32 i)
Definition: jsonb_util.c:419
#define Assert(condition)
Definition: c.h:670
JsonbIterator * JsonbIteratorInit(JsonbContainer *container)
Definition: jsonb_util.c:718
#define JB_FOBJECT
Definition: jsonb.h:205
char * JsonbToCString(StringInfo out, JsonbContainer *in, int estimated_len)
Definition: jsonb.c:429
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 i
#define elog
Definition: elog.h:219
#define PG_RETURN_JSONB_P(x)
Definition: jsonb.h:71
bool array_contains_nulls(ArrayType *array)
Definition: arrayfuncs.c:3516
#define PG_RETURN_NULL()
Definition: fmgr.h:305
JsonbIteratorToken JsonbIteratorNext(JsonbIterator **it, JsonbValue *val, bool skipNested)
Definition: jsonb_util.c:754
#define PG_GETARG_JSONB_P(x)
Definition: jsonb.h:70

◆ get_object_end()

static void get_object_end ( void *  state)
static

Definition at line 1085 of file jsonfuncs.c.

References cstring_to_text_with_len(), GetState::lex, JsonLexContext::lex_level, GetState::npath, JsonLexContext::prev_token_terminator, GetState::result_start, and GetState::tresult.

Referenced by get_worker().

1086 {
1087  GetState *_state = (GetState *) state;
1088  int lex_level = _state->lex->lex_level;
1089 
1090  if (lex_level == 0 && _state->npath == 0)
1091  {
1092  /* Special case: return the entire object */
1093  char *start = _state->result_start;
1094  int len = _state->lex->prev_token_terminator - start;
1095 
1096  _state->tresult = cstring_to_text_with_len(start, len);
1097  }
1098 }
char * prev_token_terminator
Definition: jsonapi.h:57
int lex_level
Definition: jsonapi.h:59
JsonLexContext * lex
Definition: jsonfuncs.c:78
char * result_start
Definition: jsonfuncs.c:80
text * tresult
Definition: jsonfuncs.c:79
text * cstring_to_text_with_len(const char *s, int len)
Definition: varlena.c:161
int npath
Definition: jsonfuncs.c:83
Definition: regguts.h:298

◆ get_object_field_end()

static void get_object_field_end ( void *  state,
char *  fname,
bool  isnull 
)
static

Definition at line 1146 of file jsonfuncs.c.

References cstring_to_text_with_len(), GetState::lex, JsonLexContext::lex_level, GetState::normalize_results, GetState::path_names, GetState::pathok, JsonLexContext::prev_token_terminator, GetState::result_start, and GetState::tresult.

Referenced by get_worker().

1147 {
1148  GetState *_state = (GetState *) state;
1149  bool get_last = false;
1150  int lex_level = _state->lex->lex_level;
1151 
1152  /* same tests as in get_object_field_start */
1153  if (lex_level <= _state->npath &&
1154  _state->pathok[lex_level - 1] &&
1155  _state->path_names != NULL &&
1156  _state->path_names[lex_level - 1] != NULL &&
1157  strcmp(fname, _state->path_names[lex_level - 1]) == 0)
1158  {
1159  if (lex_level < _state->npath)
1160  {
1161  /* done with this field so reset pathok */
1162  _state->pathok[lex_level] = false;
1163  }
1164  else
1165  {
1166  /* end of path, so we want this value */
1167  get_last = true;
1168  }
1169  }
1170 
1171  /* for as_text scalar case, our work is already done */
1172  if (get_last && _state->result_start != NULL)
1173  {
1174  /*
1175  * make a text object from the string from the prevously noted json
1176  * start up to the end of the previous token (the lexer is by now
1177  * ahead of us on whatever came after what we're interested in).
1178  */
1179  if (isnull && _state->normalize_results)
1180  _state->tresult = (text *) NULL;
1181  else
1182  {
1183  char *start = _state->result_start;
1184  int len = _state->lex->prev_token_terminator - start;
1185 
1186  _state->tresult = cstring_to_text_with_len(start, len);
1187  }
1188 
1189  /* this should be unnecessary but let's do it for cleanliness: */
1190  _state->result_start = NULL;
1191  }
1192 }
char * prev_token_terminator
Definition: jsonapi.h:57
int lex_level
Definition: jsonapi.h:59
JsonLexContext * lex
Definition: jsonfuncs.c:78
char * result_start
Definition: jsonfuncs.c:80
text * tresult
Definition: jsonfuncs.c:79
text * cstring_to_text_with_len(const char *s, int len)
Definition: varlena.c:161
bool * pathok
Definition: jsonfuncs.c:86
bool normalize_results
Definition: jsonfuncs.c:81
char ** path_names
Definition: jsonfuncs.c:84
Definition: regguts.h:298
Definition: c.h:487

◆ get_object_field_start()

static void get_object_field_start ( void *  state,
char *  fname,
bool  isnull 
)
static

Definition at line 1101 of file jsonfuncs.c.

References JSON_TOKEN_STRING, GetState::lex, JsonLexContext::lex_level, GetState::next_scalar, GetState::normalize_results, GetState::path_names, GetState::pathok, GetState::result_start, JsonLexContext::token_start, JsonLexContext::token_type, and GetState::tresult.

Referenced by get_worker().

1102 {
1103  GetState *_state = (GetState *) state;
1104  bool get_next = false;
1105  int lex_level = _state->lex->lex_level;
1106 
1107  if (lex_level <= _state->npath &&
1108  _state->pathok[lex_level - 1] &&
1109  _state->path_names != NULL &&
1110  _state->path_names[lex_level - 1] != NULL &&
1111  strcmp(fname, _state->path_names[lex_level - 1]) == 0)
1112  {
1113  if (lex_level < _state->npath)
1114  {
1115  /* if not at end of path just mark path ok */
1116  _state->pathok[lex_level] = true;
1117  }
1118  else
1119  {
1120  /* end of path, so we want this value */
1121  get_next = true;
1122  }
1123  }
1124 
1125  if (get_next)
1126  {
1127  /* this object overrides any previous matching object */
1128  _state->tresult = NULL;
1129  _state->result_start = NULL;
1130 
1131  if (_state->normalize_results &&
1132  _state->lex->token_type == JSON_TOKEN_STRING)
1133  {
1134  /* for as_text variants, tell get_scalar to set it for us */
1135  _state->next_scalar = true;
1136  }
1137  else
1138  {
1139  /* for non-as_text variants, just note the json starting point */
1140  _state->result_start = _state->lex->token_start;
1141  }
1142  }
1143 }
JsonTokenType token_type
Definition: jsonapi.h:58
int lex_level
Definition: jsonapi.h:59
JsonLexContext * lex
Definition: jsonfuncs.c:78
char * result_start
Definition: jsonfuncs.c:80
text * tresult
Definition: jsonfuncs.c:79
char * token_start
Definition: jsonapi.h:55
bool * pathok
Definition: jsonfuncs.c:86
bool normalize_results
Definition: jsonfuncs.c:81
bool next_scalar
Definition: jsonfuncs.c:82
char ** path_names
Definition: jsonfuncs.c:84
Definition: regguts.h:298

◆ get_object_start()

static void get_object_start ( void *  state)
static

Definition at line 1068 of file jsonfuncs.c.

References GetState::lex, JsonLexContext::lex_level, GetState::npath, GetState::result_start, and JsonLexContext::token_start.

Referenced by get_worker().

1069 {
1070  GetState *_state = (GetState *) state;
1071  int lex_level = _state->lex->lex_level;
1072 
1073  if (lex_level == 0 && _state->npath == 0)
1074  {
1075  /*
1076  * Special case: we should match the entire object. We only need this
1077  * at outermost level because at nested levels the match will have
1078  * been started by the outer field or array element callback.
1079  */
1080  _state->result_start = _state->lex->token_start;
1081  }
1082 }
int lex_level
Definition: jsonapi.h:59
JsonLexContext * lex
Definition: jsonfuncs.c:78
char * result_start
Definition: jsonfuncs.c:80
int npath
Definition: jsonfuncs.c:83
char * token_start
Definition: jsonapi.h:55
Definition: regguts.h:298

◆ get_path_all()

static Datum get_path_all ( FunctionCallInfo  fcinfo,
bool  as_text 
)
static

Definition at line 932 of file jsonfuncs.c.

References array_contains_nulls(), Assert, deconstruct_array(), get_worker(), i, palloc(), PG_GETARG_ARRAYTYPE_P, PG_GETARG_TEXT_PP, PG_RETURN_NULL, PG_RETURN_TEXT_P, OkeysState::result, TextDatumGetCString, and TEXTOID.

Referenced by json_extract_path(), and json_extract_path_text().

933 {
934  text *json = PG_GETARG_TEXT_PP(0);
935  ArrayType *path = PG_GETARG_ARRAYTYPE_P(1);
936  text *result;
937  Datum *pathtext;
938  bool *pathnulls;
939  int npath;
940  char **tpath;
941  int *ipath;
942  int i;
943 
944  /*
945  * If the array contains any null elements, return NULL, on the grounds
946  * that you'd have gotten NULL if any RHS value were NULL in a nested
947  * series of applications of the -> operator. (Note: because we also
948  * return NULL for error cases such as no-such-field, this is true
949  * regardless of the contents of the rest of the array.)
950  */
951  if (array_contains_nulls(path))
952  PG_RETURN_NULL();
953 
954  deconstruct_array(path, TEXTOID, -1, false, 'i',
955  &pathtext, &pathnulls, &npath);
956 
957  tpath = palloc(npath * sizeof(char *));
958  ipath = palloc(npath * sizeof(int));
959 
960  for (i = 0; i < npath; i++)
961  {
962  Assert(!pathnulls[i]);
963  tpath[i] = TextDatumGetCString(pathtext[i]);
964 
965  /*
966  * we have no idea at this stage what structure the document is so
967  * just convert anything in the path that we can to an integer and set
968  * all the other integers to INT_MIN which will never match.
969  */
970  if (*tpath[i] != '\0')
971  {
972  long ind;
973  char *endptr;
974 
975  errno = 0;
976  ind = strtol(tpath[i], &endptr, 10);
977  if (*endptr == '\0' && errno == 0 && ind <= INT_MAX && ind >= INT_MIN)
978  ipath[i] = (int) ind;
979  else
980  ipath[i] = INT_MIN;
981  }
982  else
983  ipath[i] = INT_MIN;
984  }
985 
986  result = get_worker(json, tpath, ipath, npath, as_text);
987 
988  if (result != NULL)
989  PG_RETURN_TEXT_P(result);
990  else
991  PG_RETURN_NULL();
992 }
#define TEXTOID
Definition: pg_type.h:324
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:273
#define PG_GETARG_ARRAYTYPE_P(n)
Definition: array.h:248
#define TextDatumGetCString(d)
Definition: builtins.h:92
uintptr_t Datum
Definition: postgres.h:372
static text * get_worker(text *json, char **tpath, int *ipath, int npath, bool normalize_results)
Definition: jsonfuncs.c:1012
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:331
#define Assert(condition)
Definition: c.h:670
void deconstruct_array(ArrayType *array, Oid elmtype, int elmlen, bool elmbyval, char elmalign, Datum **elemsp, bool **nullsp, int *nelemsp)
Definition: arrayfuncs.c:3449
void * palloc(Size size)
Definition: mcxt.c:848
int i
Definition: c.h:487
bool array_contains_nulls(ArrayType *array)
Definition: arrayfuncs.c:3516
#define PG_RETURN_NULL()
Definition: fmgr.h:305

◆ get_scalar()

static void get_scalar ( void *  state,
char *  token,
JsonTokenType  tokentype 
)
static

Definition at line 1332 of file jsonfuncs.c.

References cstring_to_text(), cstring_to_text_with_len(), JsonLexContext::input, JSON_TOKEN_NULL, JSON_TOKEN_STRING, GetState::lex, JsonLexContext::lex_level, GetState::next_scalar, GetState::normalize_results, GetState::npath, JsonLexContext::prev_token_terminator, and GetState::tresult.

Referenced by get_worker().

1333 {
1334  GetState *_state = (GetState *) state;
1335  int lex_level = _state->lex->lex_level;
1336 
1337  /* Check for whole-object match */
1338  if (lex_level == 0 && _state->npath == 0)
1339  {
1340  if (_state->normalize_results && tokentype == JSON_TOKEN_STRING)
1341  {
1342  /* we want the de-escaped string */
1343  _state->next_scalar = true;
1344  }
1345  else if (_state->normalize_results && tokentype == JSON_TOKEN_NULL)
1346  {
1347  _state->tresult = (text *) NULL;
1348  }
1349  else
1350  {
1351  /*
1352  * This is a bit hokey: we will suppress whitespace after the
1353  * scalar token, but not whitespace before it. Probably not worth
1354  * doing our own space-skipping to avoid that.
1355  */
1356  char *start = _state->lex->input;
1357  int len = _state->lex->prev_token_terminator - start;
1358 
1359  _state->tresult = cstring_to_text_with_len(start, len);
1360  }
1361  }
1362 
1363  if (_state->next_scalar)
1364  {
1365  /* a de-escaped text value is wanted, so supply it */
1366  _state->tresult = cstring_to_text(token);
1367  /* make sure the next call to get_scalar doesn't overwrite it */
1368  _state->next_scalar = false;
1369  }
1370 }
char * prev_token_terminator
Definition: jsonapi.h:57
int lex_level
Definition: jsonapi.h:59
JsonLexContext * lex
Definition: jsonfuncs.c:78
text * tresult
Definition: jsonfuncs.c:79
text * cstring_to_text_with_len(const char *s, int len)
Definition: varlena.c:161
int npath
Definition: jsonfuncs.c:83
bool normalize_results
Definition: jsonfuncs.c:81
bool next_scalar
Definition: jsonfuncs.c:82
text * cstring_to_text(const char *s)
Definition: varlena.c:149
char * input
Definition: jsonapi.h:53
Definition: regguts.h:298
Definition: c.h:487

◆ get_worker()

static text * get_worker ( text json,
char **  tpath,
int *  ipath,
int  npath,
bool  normalize_results 
)
static

Definition at line 1012 of file jsonfuncs.c.

References GetState::array_cur_index, JsonSemAction::array_element_end, JsonSemAction::array_element_start, JsonSemAction::array_end, JsonSemAction::array_start, Assert, get_array_element_end(), get_array_element_start(), get_array_end(), get_array_start(), get_object_end(), get_object_field_end(), get_object_field_start(), get_object_start(), get_scalar(), OkeysState::lex, GetState::lex, makeJsonLexContext(), GetState::normalize_results, GetState::npath, JsonSemAction::object_end, JsonSemAction::object_field_end, JsonSemAction::object_field_start, JsonSemAction::object_start, palloc(), palloc0(), GetState::path_indexes, GetState::path_names, GetState::pathok, pg_parse_json(), JsonSemAction::scalar, JsonSemAction::semstate, and GetState::tresult.

Referenced by get_path_all(), json_array_element(), json_array_element_text(), json_object_field(), and json_object_field_text().

1017 {
1018  JsonLexContext *lex = makeJsonLexContext(json, true);
1019  JsonSemAction *sem = palloc0(sizeof(JsonSemAction));
1020  GetState *state = palloc0(sizeof(GetState));
1021 
1022  Assert(npath >= 0);
1023 
1024  state->lex = lex;
1025  /* is it "_as_text" variant? */
1026  state->normalize_results = normalize_results;
1027  state->npath = npath;
1028  state->path_names = tpath;
1029  state->path_indexes = ipath;
1030  state->pathok = palloc0(sizeof(bool) * npath);
1031  state->array_cur_index = palloc(sizeof(int) * npath);
1032 
1033  if (npath > 0)
1034  state->pathok[0] = true;
1035 
1036  sem->semstate = (void *) state;
1037 
1038  /*
1039  * Not all variants need all the semantic routines. Only set the ones that
1040  * are actually needed for maximum efficiency.
1041  */
1042  sem->scalar = get_scalar;
1043  if (npath == 0)
1044  {
1046  sem->object_end = get_object_end;
1048  sem->array_end = get_array_end;
1049  }
1050  if (tpath != NULL)
1051  {
1054  }
1055  if (ipath != NULL)
1056  {
1060  }
1061 
1062  pg_parse_json(lex, sem);
1063 
1064  return state->tresult;
1065 }
json_struct_action array_end
Definition: jsonapi.h:88
static void get_array_end(void *state)
Definition: jsonfuncs.c:1228
int * array_cur_index
Definition: jsonfuncs.c:87
static void get_array_element_start(void *state, bool isnull)
Definition: jsonfuncs.c:1244
json_struct_action object_end
Definition: jsonapi.h:86
static void get_object_start(void *state)
Definition: jsonfuncs.c:1068
json_struct_action object_start
Definition: jsonapi.h:85
json_scalar_action scalar
Definition: jsonapi.h:93
static void get_object_field_end(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:1146
JsonLexContext * lex
Definition: jsonfuncs.c:78
static void get_object_end(void *state)
Definition: jsonfuncs.c:1085
JsonLexContext * makeJsonLexContext(text *json, bool need_escapes)
Definition: json.c:301
void pg_parse_json(JsonLexContext *lex, JsonSemAction *sem)
Definition: json.c:332
text * tresult
Definition: jsonfuncs.c:79
int npath
Definition: jsonfuncs.c:83
json_ofield_action object_field_end
Definition: jsonapi.h:90
static void get_array_element_end(void *state, bool isnull)
Definition: jsonfuncs.c:1290
bool * pathok
Definition: jsonfuncs.c:86
bool normalize_results
Definition: jsonfuncs.c:81
static void get_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:1332
void * palloc0(Size size)
Definition: mcxt.c:877
static void get_array_start(void *state)
Definition: jsonfuncs.c:1195
json_aelem_action array_element_start
Definition: jsonapi.h:91
char ** path_names
Definition: jsonfuncs.c:84
#define Assert(condition)
Definition: c.h:670
json_struct_action array_start
Definition: jsonapi.h:87
Definition: regguts.h:298
int * path_indexes
Definition: jsonfuncs.c:85
void * palloc(Size size)
Definition: mcxt.c:848
static void get_object_field_start(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:1101
json_ofield_action object_field_start
Definition: jsonapi.h:89
void * semstate
Definition: jsonapi.h:84
json_aelem_action array_element_end
Definition: jsonapi.h:92

◆ hash_array_start()

static void hash_array_start ( void *  state)
static

Definition at line 3446 of file jsonfuncs.c.

References ereport, errcode(), errmsg(), ERROR, JHashState::function_name, JHashState::lex, and JsonLexContext::lex_level.

Referenced by get_json_object_as_hash().

3447 {
3448  JHashState *_state = (JHashState *) state;
3449 
3450  if (_state->lex->lex_level == 0)
3451  ereport(ERROR,
3452  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3453  errmsg("cannot call %s on an array", _state->function_name)));
3454 }
int errcode(int sqlerrcode)
Definition: elog.c:575
int lex_level
Definition: jsonapi.h:59
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:122
const char * function_name
Definition: jsonfuncs.c:129
Definition: regguts.h:298
JsonLexContext * lex
Definition: jsonfuncs.c:128
int errmsg(const char *fmt,...)
Definition: elog.c:797

◆ hash_object_field_end()

static void hash_object_field_end ( void *  state,
char *  fname,
bool  isnull 
)
static

Definition at line 3397 of file jsonfuncs.c.

References Assert, JHashState::hash, HASH_ENTER, hash_search(), JSON_TOKEN_NULL, JHashState::lex, JsonLexContext::lex_level, NAMEDATALEN, palloc(), JsonLexContext::prev_token_terminator, JHashState::save_json_start, JHashState::saved_scalar, JHashState::saved_token_type, JsonHashEntry::type, JsonHashEntry::val, and val.

Referenced by get_json_object_as_hash().

3398 {
3399  JHashState *_state = (JHashState *) state;
3400  JsonHashEntry *hashentry;
3401  bool found;
3402 
3403  /*
3404  * Ignore nested fields.
3405  */
3406  if (_state->lex->lex_level > 1)
3407  return;
3408 
3409  /*
3410  * Ignore field names >= NAMEDATALEN - they can't match a record field.
3411  * (Note: without this test, the hash code would truncate the string at
3412  * NAMEDATALEN-1, and could then match against a similarly-truncated
3413  * record field name. That would be a reasonable behavior, but this code
3414  * has previously insisted on exact equality, so we keep this behavior.)
3415  */
3416  if (strlen(fname) >= NAMEDATALEN)
3417  return;
3418 
3419  hashentry = hash_search(_state->hash, fname, HASH_ENTER, &found);
3420 
3421  /*
3422  * found being true indicates a duplicate. We don't do anything about
3423  * that, a later field with the same name overrides the earlier field.
3424  */
3425 
3426  hashentry->type = _state->saved_token_type;
3427  Assert(isnull == (hashentry->type == JSON_TOKEN_NULL));
3428 
3429  if (_state->save_json_start != NULL)
3430  {
3431  int len = _state->lex->prev_token_terminator - _state->save_json_start;
3432  char *val = palloc((len + 1) * sizeof(char));
3433 
3434  memcpy(val, _state->save_json_start, len);
3435  val[len] = '\0';
3436  hashentry->val = val;
3437  }
3438  else
3439  {
3440  /* must have had a scalar instead */
3441  hashentry->val = _state->saved_scalar;
3442  }
3443 }
char * prev_token_terminator
Definition: jsonapi.h:57
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:902
JsonTokenType type
Definition: jsonfuncs.c:141
int lex_level
Definition: jsonapi.h:59
char * save_json_start
Definition: jsonfuncs.c:132
#define NAMEDATALEN
JsonTokenType saved_token_type
Definition: jsonfuncs.c:133
char * val
Definition: jsonfuncs.c:140
HTAB * hash
Definition: jsonfuncs.c:130
#define Assert(condition)
Definition: c.h:670
Definition: regguts.h:298
JsonLexContext * lex
Definition: jsonfuncs.c:128
char * saved_scalar
Definition: jsonfuncs.c:131
void * palloc(Size size)
Definition: mcxt.c:848
long val
Definition: informix.c:689

◆ hash_object_field_start()

static void hash_object_field_start ( void *  state,
char *  fname,
bool  isnull 
)
static

Definition at line 3373 of file jsonfuncs.c.

References JSON_TOKEN_ARRAY_START, JSON_TOKEN_OBJECT_START, JHashState::lex, JsonLexContext::lex_level, JHashState::save_json_start, JHashState::saved_token_type, JsonLexContext::token_start, and JsonLexContext::token_type.

Referenced by get_json_object_as_hash().

3374 {
3375  JHashState *_state = (JHashState *) state;
3376 
3377  if (_state->lex->lex_level > 1)
3378  return;
3379 
3380  /* remember token type */
3381  _state->saved_token_type = _state->lex->token_type;
3382 
3383  if (_state->lex->token_type == JSON_TOKEN_ARRAY_START ||
3385  {
3386  /* remember start position of the whole text of the subobject */
3387  _state->save_json_start = _state->lex->token_start;
3388  }
3389  else
3390  {
3391  /* must be a scalar */
3392  _state->save_json_start = NULL;
3393  }
3394 }
JsonTokenType token_type
Definition: jsonapi.h:58
int lex_level
Definition: jsonapi.h:59
char * save_json_start
Definition: jsonfuncs.c:132
JsonTokenType saved_token_type
Definition: jsonfuncs.c:133
char * token_start
Definition: jsonapi.h:55
Definition: regguts.h:298
JsonLexContext * lex
Definition: jsonfuncs.c:128

◆ hash_scalar()

static void hash_scalar ( void *  state,
char *  token,
JsonTokenType  tokentype 
)
static

Definition at line 3457 of file jsonfuncs.c.

References Assert, ereport, errcode(), errmsg(), ERROR, JHashState::function_name, JHashState::lex, JsonLexContext::lex_level, JHashState::saved_scalar, and JHashState::saved_token_type.

Referenced by get_json_object_as_hash().

3458 {
3459  JHashState *_state = (JHashState *) state;
3460 
3461  if (_state->lex->lex_level == 0)
3462  ereport(ERROR,
3463  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3464  errmsg("cannot call %s on a scalar", _state->function_name)));
3465 
3466  if (_state->lex->lex_level == 1)
3467  {
3468  _state->saved_scalar = token;
3469  /* saved_token_type must already be set in hash_object_field_start() */
3470  Assert(_state->saved_token_type == tokentype);
3471  }
3472 }
int errcode(int sqlerrcode)
Definition: elog.c:575
int lex_level
Definition: jsonapi.h:59
#define ERROR
Definition: elog.h:43
JsonTokenType saved_token_type
Definition: jsonfuncs.c:133
#define ereport(elevel, rest)
Definition: elog.h:122
const char * function_name
Definition: jsonfuncs.c:129
#define Assert(condition)
Definition: c.h:670
Definition: regguts.h:298
JsonLexContext * lex
Definition: jsonfuncs.c:128
char * saved_scalar
Definition: jsonfuncs.c:131
int errmsg(const char *fmt,...)
Definition: elog.c:797

◆ iterate_json_string_values()

void iterate_json_string_values ( text json,
void *  action_state,
JsonIterateStringValuesAction  action 
)

Definition at line 4968 of file jsonfuncs.c.

References IterateJsonStringValuesState::action, generate_unaccent_rules::action, IterateJsonStringValuesState::action_state, iterate_string_values_scalar(), OkeysState::lex, IterateJsonStringValuesState::lex, makeJsonLexContext(), palloc0(), pg_parse_json(), JsonSemAction::scalar, and JsonSemAction::semstate.

Referenced by json_to_tsvector_byid().

4969 {
4970  JsonLexContext *lex = makeJsonLexContext(json, true);
4971  JsonSemAction *sem = palloc0(sizeof(JsonSemAction));
4973 
4974  state->lex = lex;
4975  state->action = action;
4976  state->action_state = action_state;
4977 
4978  sem->semstate = (void *) state;
4980 
4981  pg_parse_json(lex, sem);
4982 }
JsonIterateStringValuesAction action
Definition: jsonfuncs.c:60
json_scalar_action scalar
Definition: jsonapi.h:93
JsonLexContext * makeJsonLexContext(text *json, bool need_escapes)
Definition: json.c:301
void pg_parse_json(JsonLexContext *lex, JsonSemAction *sem)
Definition: json.c:332
void * palloc0(Size size)
Definition: mcxt.c:877
Definition: regguts.h:298
static void iterate_string_values_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:4989
JsonLexContext * lex
Definition: jsonfuncs.c:59
void * semstate
Definition: jsonapi.h:84

◆ iterate_jsonb_string_values()

void iterate_jsonb_string_values ( Jsonb jb,
void *  state,
JsonIterateStringValuesAction  action 
)

Definition at line 4946 of file jsonfuncs.c.

References generate_unaccent_rules::action, jbvString, JsonbIteratorInit(), JsonbIteratorNext(), Jsonb::root, generate_unaccent_rules::type, JsonbValue::type, JsonbValue::val, WJB_DONE, WJB_ELEM, and WJB_VALUE.

Referenced by jsonb_to_tsvector_byid().

4947 {
4948  JsonbIterator *it;
4949  JsonbValue v;
4951 
4952  it = JsonbIteratorInit(&jb->root);
4953 
4954  while ((type = JsonbIteratorNext(&it, &v, false)) != WJB_DONE)
4955  {
4956  if ((type == WJB_VALUE || type == WJB_ELEM) && v.type == jbvString)
4957  {
4958  action(state, v.val.string.val, v.val.string.len);
4959  }
4960  }
4961 }
char * val
Definition: jsonb.h:259
Definition: jsonb.h:22
JsonbIteratorToken
Definition: jsonb.h:20
JsonbContainer root
Definition: jsonb.h:218
JsonbIterator * JsonbIteratorInit(JsonbContainer *container)
Definition: jsonb_util.c:718
Definition: regguts.h:298
enum jbvType type
Definition: jsonb.h:250
JsonbIteratorToken JsonbIteratorNext(JsonbIterator **it, JsonbValue *val, bool skipNested)
Definition: jsonb_util.c:754
Definition: jsonb.h:25

◆ iterate_string_values_scalar()

static void iterate_string_values_scalar ( void *  state,
char *  token,
JsonTokenType  tokentype 
)
static

Definition at line 4989 of file jsonfuncs.c.

References IterateJsonStringValuesState::action, IterateJsonStringValuesState::action_state, and JSON_TOKEN_STRING.

Referenced by iterate_json_string_values().

4990 {
4992 
4993  if (tokentype == JSON_TOKEN_STRING)
4994  _state->action(_state->action_state, token, strlen(token));
4995 }
JsonIterateStringValuesAction action
Definition: jsonfuncs.c:60
Definition: regguts.h:298

◆ IteratorConcat()

static JsonbValue * IteratorConcat ( JsonbIterator **  it1,
JsonbIterator **  it2,
JsonbParseState **  state 
)
static

Definition at line 4546 of file jsonfuncs.c.

References Assert, ereport, errcode(), errmsg(), ERROR, JsonbIteratorNext(), pushJsonbValue(), WJB_BEGIN_ARRAY, WJB_BEGIN_OBJECT, WJB_ELEM, WJB_END_ARRAY, and WJB_END_OBJECT.

Referenced by jsonb_concat().

4548 {
4549  JsonbValue v1,
4550  v2,
4551  *res = NULL;
4552  JsonbIteratorToken r1,
4553  r2,
4554  rk1,
4555  rk2;
4556 
4557  r1 = rk1 = JsonbIteratorNext(it1, &v1, false);
4558  r2 = rk2 = JsonbIteratorNext(it2, &v2, false);
4559 
4560  /*
4561  * Both elements are objects.
4562  */
4563  if (rk1 == WJB_BEGIN_OBJECT && rk2 == WJB_BEGIN_OBJECT)
4564  {
4565  /*
4566  * Append the all tokens from v1 to res, except last WJB_END_OBJECT
4567  * (because res will not be finished yet).
4568  */
4569  pushJsonbValue(state, r1, NULL);
4570  while ((r1 = JsonbIteratorNext(it1, &v1, true)) != WJB_END_OBJECT)
4571  pushJsonbValue(state, r1, &v1);
4572 
4573  /*
4574  * Append the all tokens from v2 to res, include last WJB_END_OBJECT
4575  * (the concatenation will be completed).
4576  */
4577  while ((r2 = JsonbIteratorNext(it2, &v2, true)) != 0)
4578  res = pushJsonbValue(state, r2, r2 != WJB_END_OBJECT ? &v2 : NULL);
4579  }
4580 
4581  /*
4582  * Both elements are arrays (either can be scalar).
4583  */
4584  else if (rk1 == WJB_BEGIN_ARRAY && rk2 == WJB_BEGIN_ARRAY)
4585  {
4586  pushJsonbValue(state, r1, NULL);
4587 
4588  while ((r1 = JsonbIteratorNext(it1, &v1, true)) != WJB_END_ARRAY)
4589  {
4590  Assert(r1 == WJB_ELEM);
4591  pushJsonbValue(state, r1, &v1);
4592  }
4593 
4594  while ((r2 = JsonbIteratorNext(it2, &v2, true)) != WJB_END_ARRAY)
4595  {
4596  Assert(r2 == WJB_ELEM);
4597  pushJsonbValue(state, WJB_ELEM, &v2);
4598  }
4599 
4600  res = pushJsonbValue(state, WJB_END_ARRAY, NULL /* signal to sort */ );
4601  }
4602  /* have we got array || object or object || array? */
4603  else if (((rk1 == WJB_BEGIN_ARRAY && !(*it1)->isScalar) && rk2 == WJB_BEGIN_OBJECT) ||
4604  (rk1 == WJB_BEGIN_OBJECT && (rk2 == WJB_BEGIN_ARRAY && !(*it2)->isScalar)))
4605  {
4606 
4607  JsonbIterator **it_array = rk1 == WJB_BEGIN_ARRAY ? it1 : it2;
4608  JsonbIterator **it_object = rk1 == WJB_BEGIN_OBJECT ? it1 : it2;
4609 
4610  bool prepend = (rk1 == WJB_BEGIN_OBJECT);
4611 
4612  pushJsonbValue(state, WJB_BEGIN_ARRAY, NULL);
4613 
4614  if (prepend)
4615  {
4616  pushJsonbValue(state, WJB_BEGIN_OBJECT, NULL);
4617  while ((r1 = JsonbIteratorNext(it_object, &v1, true)) != 0)
4618  pushJsonbValue(state, r1, r1 != WJB_END_OBJECT ? &v1 : NULL);
4619 
4620  while ((r2 = JsonbIteratorNext(it_array, &v2, true)) != 0)
4621  res = pushJsonbValue(state, r2, r2 != WJB_END_ARRAY ? &v2 : NULL);
4622  }
4623  else
4624  {
4625  while ((r1 = JsonbIteratorNext(it_array, &v1, true)) != WJB_END_ARRAY)
4626  pushJsonbValue(state, r1, &v1);
4627 
4628  pushJsonbValue(state, WJB_BEGIN_OBJECT, NULL);
4629  while ((r2 = JsonbIteratorNext(it_object, &v2, true)) != 0)
4630  pushJsonbValue(state, r2, r2 != WJB_END_OBJECT ? &v2 : NULL);
4631 
4632  res = pushJsonbValue(state, WJB_END_ARRAY, NULL);
4633  }
4634  }
4635  else
4636  {
4637  /*
4638  * This must be scalar || object or object || scalar, as that's all
4639  * that's left. Both of these make no sense, so error out.
4640  */
4641  ereport(ERROR,
4642  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4643  errmsg("invalid concatenation of jsonb objects")));
4644  }
4645 
4646  return res;
4647 }
int errcode(int sqlerrcode)
Definition: elog.c:575
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
JsonbIteratorToken
Definition: jsonb.h:20
#define Assert(condition)
Definition: c.h:670
int errmsg(const char *fmt,...)
Definition: elog.c:797
JsonbIteratorToken JsonbIteratorNext(JsonbIterator **it, JsonbValue *val, bool skipNested)
Definition: jsonb_util.c:754
Definition: jsonb.h:25

◆ JsObjectGetField()

static bool JsObjectGetField ( JsObject obj,
char *  field,
JsValue jsv 
)
static

Definition at line 3067 of file jsonfuncs.c.

References findJsonbValueFromContainerLen(), HASH_FIND, hash_search(), JsValue::is_json, JsObject::is_json, JB_FOBJECT, JsValue::json, JsObject::json_hash, JSON_TOKEN_NULL, JsValue::jsonb, JsObject::jsonb_cont, JsonHashEntry::type, JsonHashEntry::val, JsValue::val, and JsObject::val.

Referenced by populate_record().

3068 {
3069  jsv->is_json = obj->is_json;
3070 
3071  if (jsv->is_json)
3072  {
3073  JsonHashEntry *hashentry = hash_search(obj->val.json_hash, field,
3074  HASH_FIND, NULL);
3075 
3076  jsv->val.json.type = hashentry ? hashentry->type : JSON_TOKEN_NULL;
3077  jsv->val.json.str = jsv->val.json.type == JSON_TOKEN_NULL ? NULL :
3078  hashentry->val;
3079  jsv->val.json.len = jsv->val.json.str ? -1 : 0; /* null-terminated */
3080 
3081  return hashentry != NULL;
3082  }
3083  else
3084  {
3085  jsv->val.jsonb = !obj->val.jsonb_cont ? NULL :
3087  field, strlen(field));
3088 
3089  return jsv->val.jsonb != NULL;
3090  }
3091 }
bool is_json
Definition: jsonfuncs.c:306
static JsonbValue * findJsonbValueFromContainerLen(JsonbContainer *container, uint32 flags, char *key, uint32 keylen)
Definition: jsonfuncs.c:3889
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:902
JsonTokenType type
Definition: jsonfuncs.c:141
JsonbContainer * jsonb_cont
Definition: jsonfuncs.c:310
char * val
Definition: jsonfuncs.c:140
union JsValue::@30 val
union JsObject::@32 val
bool is_json
Definition: jsonfuncs.c:290
HTAB * json_hash
Definition: jsonfuncs.c:309
#define JB_FOBJECT
Definition: jsonb.h:205
struct JsValue::@30::@31 json
JsonbValue * jsonb
Definition: jsonfuncs.c:300

◆ json_array_element()

Datum json_array_element ( PG_FUNCTION_ARGS  )

Definition at line 800 of file jsonfuncs.c.

References element(), get_worker(), PG_GETARG_INT32, PG_GETARG_TEXT_PP, PG_RETURN_NULL, PG_RETURN_TEXT_P, and OkeysState::result.

801 {
802  text *json = PG_GETARG_TEXT_PP(0);
803  int element = PG_GETARG_INT32(1);
804  text *result;
805 
806  result = get_worker(json, NULL, &element, 1, false);
807 
808  if (result != NULL)
809  PG_RETURN_TEXT_P(result);
810  else
811  PG_RETURN_NULL();
812 }
#define PG_GETARG_INT32(n)
Definition: fmgr.h:234
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:273
static chr element(struct vars *v, const chr *startp, const chr *endp)
Definition: regc_locale.c:380
static text * get_worker(text *json, char **tpath, int *ipath, int npath, bool normalize_results)
Definition: jsonfuncs.c:1012
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:331
Definition: c.h:487
#define PG_RETURN_NULL()
Definition: fmgr.h:305

◆ json_array_element_text()

Datum json_array_element_text ( PG_FUNCTION_ARGS  )

Definition at line 843 of file jsonfuncs.c.

References element(), get_worker(), PG_GETARG_INT32, PG_GETARG_TEXT_PP, PG_RETURN_NULL, PG_RETURN_TEXT_P, and OkeysState::result.

844 {
845  text *json = PG_GETARG_TEXT_PP(0);
846  int element = PG_GETARG_INT32(1);
847  text *result;
848 
849  result = get_worker(json, NULL, &element, 1, true);
850 
851  if (result != NULL)
852  PG_RETURN_TEXT_P(result);
853  else
854  PG_RETURN_NULL();
855 }
#define PG_GETARG_INT32(n)
Definition: fmgr.h:234
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:273
static chr element(struct vars *v, const chr *startp, const chr *endp)
Definition: regc_locale.c:380
static text * get_worker(text *json, char **tpath, int *ipath, int npath, bool normalize_results)
Definition: jsonfuncs.c:1012
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:331
Definition: c.h:487
#define PG_RETURN_NULL()
Definition: fmgr.h:305

◆ json_array_elements()

Datum json_array_elements ( PG_FUNCTION_ARGS  )

Definition at line 2109 of file jsonfuncs.c.

References elements_worker().

2110 {
2111  return elements_worker(fcinfo, "json_array_elements", false);
2112 }
static Datum elements_worker(FunctionCallInfo fcinfo, const char *funcname, bool as_text)
Definition: jsonfuncs.c:2121

◆ json_array_elements_text()

Datum json_array_elements_text ( PG_FUNCTION_ARGS  )

Definition at line 2115 of file jsonfuncs.c.

References elements_worker().

2116 {
2117  return elements_worker(fcinfo, "json_array_elements_text", true);
2118 }
static Datum elements_worker(FunctionCallInfo fcinfo, const char *funcname, bool as_text)
Definition: jsonfuncs.c:2121

◆ json_array_length()

Datum json_array_length ( PG_FUNCTION_ARGS  )

Definition at line 1553 of file jsonfuncs.c.

References alen_array_element_start(), alen_object_start(), alen_scalar(), JsonSemAction::array_element_start, AlenState::count, OkeysState::lex, AlenState::lex, makeJsonLexContext(), JsonSemAction::object_start, palloc0(), PG_GETARG_TEXT_PP, pg_parse_json(), PG_RETURN_INT32, JsonSemAction::scalar, and JsonSemAction::semstate.

1554 {
1555  text *json = PG_GETARG_TEXT_PP(0);
1556  AlenState *state;
1557  JsonLexContext *lex;
1558  JsonSemAction *sem;
1559 
1560  lex = makeJsonLexContext(json, false);
1561  state = palloc0(sizeof(AlenState));
1562  sem = palloc0(sizeof(JsonSemAction));
1563 
1564  /* palloc0 does this for us */
1565 #if 0
1566  state->count = 0;
1567 #endif
1568  state->lex = lex;
1569 
1570  sem->semstate = (void *) state;
1572  sem->scalar = alen_scalar;
1574 
1575  pg_parse_json(lex, sem);
1576 
1577  PG_RETURN_INT32(state->count);
1578 }
json_struct_action object_start
Definition: jsonapi.h:85
#define PG_RETURN_INT32(x)
Definition: fmgr.h:314
json_scalar_action scalar
Definition: jsonapi.h:93
int count
Definition: jsonfuncs.c:95
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:273
static void alen_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:1615
JsonLexContext * makeJsonLexContext(text *json, bool need_escapes)
Definition: json.c:301
void pg_parse_json(JsonLexContext *lex, JsonSemAction *sem)
Definition: json.c:332
JsonLexContext * lex
Definition: jsonfuncs.c:94
void * palloc0(Size size)
Definition: mcxt.c:877
json_aelem_action array_element_start
Definition: jsonapi.h:91
Definition: regguts.h:298
static void alen_object_start(void *state)
Definition: jsonfuncs.c:1603
Definition: c.h:487
static void alen_array_element_start(void *state, bool isnull)
Definition: jsonfuncs.c:1627
void * semstate
Definition: jsonapi.h:84

◆ json_each()

Datum json_each ( PG_FUNCTION_ARGS  )

Definition at line 1647 of file jsonfuncs.c.

References each_worker().

1648 {
1649  return each_worker(fcinfo, false);
1650 }
static Datum each_worker(FunctionCallInfo fcinfo, bool as_text)
Definition: jsonfuncs.c:1807

◆ json_each_text()

Datum json_each_text ( PG_FUNCTION_ARGS  )

Definition at line 1659 of file jsonfuncs.c.

References each_worker().

1660 {
1661  return each_worker(fcinfo, true);
1662 }
static Datum each_worker(FunctionCallInfo fcinfo, bool as_text)
Definition: jsonfuncs.c:1807

◆ json_extract_path()

Datum json_extract_path ( PG_FUNCTION_ARGS  )

Definition at line 917 of file jsonfuncs.c.

References get_path_all().

918 {
919  return get_path_all(fcinfo, false);
920 }
static Datum get_path_all(FunctionCallInfo fcinfo, bool as_text)
Definition: jsonfuncs.c:932

◆ json_extract_path_text()

Datum json_extract_path_text ( PG_FUNCTION_ARGS  )

Definition at line 923 of file jsonfuncs.c.

References get_path_all().

924 {
925  return get_path_all(fcinfo, true);
926 }
static Datum get_path_all(FunctionCallInfo fcinfo, bool as_text)
Definition: jsonfuncs.c:932

◆ json_object_field()

Datum json_object_field ( PG_FUNCTION_ARGS  )

Definition at line 697 of file jsonfuncs.c.

References get_worker(), PG_GETARG_TEXT_PP, PG_RETURN_NULL, PG_RETURN_TEXT_P, OkeysState::result, and text_to_cstring().

698 {
699  text *json = PG_GETARG_TEXT_PP(0);
700  text *fname = PG_GETARG_TEXT_PP(1);
701  char *fnamestr = text_to_cstring(fname);
702  text *result;
703 
704  result = get_worker(json, &fnamestr, NULL, 1, false);
705 
706  if (result != NULL)
707  PG_RETURN_TEXT_P(result);
708  else
709  PG_RETURN_NULL();
710 }
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:273
static text * get_worker(text *json, char **tpath, int *ipath, int npath, bool normalize_results)
Definition: jsonfuncs.c:1012
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:331
char * text_to_cstring(const text *t)
Definition: varlena.c:182
Definition: c.h:487
#define PG_RETURN_NULL()
Definition: fmgr.h:305

◆ json_object_field_text()

Datum json_object_field_text ( PG_FUNCTION_ARGS  )

Definition at line 733 of file jsonfuncs.c.

References get_worker(), PG_GETARG_TEXT_PP, PG_RETURN_NULL, PG_RETURN_TEXT_P, OkeysState::result, and text_to_cstring().

734 {
735  text *json = PG_GETARG_TEXT_PP(0);
736  text *fname = PG_GETARG_TEXT_PP(1);
737  char *fnamestr = text_to_cstring(fname);
738  text *result;
739 
740  result = get_worker(json, &fnamestr, NULL, 1, true);
741 
742  if (result != NULL)
743  PG_RETURN_TEXT_P(result);
744  else
745  PG_RETURN_NULL();
746 }
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:273
static text * get_worker(text *json, char **tpath, int *ipath, int npath, bool normalize_results)
Definition: jsonfuncs.c:1012
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:331
char * text_to_cstring(const text *t)
Definition: varlena.c:182
Definition: c.h:487
#define PG_RETURN_NULL()
Definition: fmgr.h:305

◆ json_object_keys()

Datum json_object_keys ( PG_FUNCTION_ARGS  )

Definition at line 580 of file jsonfuncs.c.

References JsonSemAction::array_start, CStringGetTextDatum, StringInfoData::data, i, OkeysState::lex, makeJsonLexContext(), MemoryContextSwitchTo(), FuncCallContext::multi_call_memory_ctx, JsonSemAction::object_field_start, okeys_array_start(), okeys_object_field_start(), okeys_scalar(), palloc(), palloc0(), pfree(), PG_GETARG_TEXT_PP, pg_parse_json(), OkeysState::result, OkeysState::result_count, OkeysState::result_size, JsonSemAction::scalar, JsonSemAction::semstate, OkeysState::sent_count, SRF_FIRSTCALL_INIT, SRF_IS_FIRSTCALL, SRF_PERCALL_SETUP, SRF_RETURN_DONE, SRF_RETURN_NEXT, JsonLexContext::strval, and FuncCallContext::user_fctx.

581 {
582  FuncCallContext *funcctx;
583  OkeysState *state;
584  int i;
585 
586  if (SRF_IS_FIRSTCALL())
587  {
588  text *json = PG_GETARG_TEXT_PP(0);
589  JsonLexContext *lex = makeJsonLexContext(json, true);
590  JsonSemAction *sem;
591  MemoryContext oldcontext;
592 
593  funcctx = SRF_FIRSTCALL_INIT();
594  oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
595 
596  state = palloc(sizeof(OkeysState));
597  sem = palloc0(sizeof(JsonSemAction));
598 
599  state->lex = lex;
600  state->result_size = 256;
601  state->result_count = 0;
602  state->sent_count = 0;
603  state->result = palloc(256 * sizeof(char *));
604 
605  sem->semstate = (void *) state;
607  sem->scalar = okeys_scalar;
609  /* remainder are all NULL, courtesy of palloc0 above */
610 
611  pg_parse_json(lex, sem);
612  /* keys are now in state->result */
613 
614  pfree(lex->strval->data);
615  pfree(lex->strval);
616  pfree(lex);
617  pfree(sem);
618 
619  MemoryContextSwitchTo(oldcontext);
620  funcctx->user_fctx = (void *) state;
621  }
622 
623  funcctx = SRF_PERCALL_SETUP();
624  state = (OkeysState *) funcctx->user_fctx;
625 
626  if (state->sent_count < state->result_count)
627  {
628  char *nxt = state->result[state->sent_count++];
629 
630  SRF_RETURN_NEXT(funcctx, CStringGetTextDatum(nxt));
631  }
632 
633  /* cleanup to reduce or eliminate memory leaks */
634  for (i = 0; i < state->result_count; i++)
635  pfree(state->result[i]);
636  pfree(state->result);
637  pfree(state);
638 
639  SRF_RETURN_DONE(funcctx);
640 }
int result_count
Definition: jsonfuncs.c:52
#define SRF_IS_FIRSTCALL()
Definition: funcapi.h:293
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
static void okeys_array_start(void *state)
Definition: jsonfuncs.c:664
json_scalar_action scalar
Definition: jsonapi.h:93
int sent_count
Definition: jsonfuncs.c:53
#define SRF_PERCALL_SETUP()
Definition: funcapi.h:297
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:273
#define SRF_RETURN_NEXT(_funcctx, _result)
Definition: funcapi.h:299
JsonLexContext * makeJsonLexContext(text *json, bool need_escapes)
Definition: json.c:301
void pfree(void *pointer)
Definition: mcxt.c:949
void pg_parse_json(JsonLexContext *lex, JsonSemAction *sem)
Definition: json.c:332
StringInfo strval
Definition: jsonapi.h:62
static void okeys_object_field_start(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:643
char ** result
Definition: jsonfuncs.c:50
void * palloc0(Size size)
Definition: mcxt.c:877
JsonLexContext * lex
Definition: jsonfuncs.c:49
json_struct_action array_start
Definition: jsonapi.h:87
Definition: regguts.h:298
MemoryContext multi_call_memory_ctx
Definition: funcapi.h:110
static void okeys_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:677
int result_size
Definition: jsonfuncs.c:51
void * user_fctx
Definition: funcapi.h:91
void * palloc(Size size)
Definition: mcxt.c:848
int i
#define CStringGetTextDatum(s)
Definition: builtins.h:91
Definition: c.h:487
json_ofield_action object_field_start
Definition: jsonapi.h:89
void * semstate
Definition: jsonapi.h:84
#define SRF_RETURN_DONE(_funcctx)
Definition: funcapi.h:317
#define SRF_FIRSTCALL_INIT()
Definition: funcapi.h:295

◆ json_populate_record()

Datum json_populate_record ( PG_FUNCTION_ARGS  )

Definition at line 2305 of file jsonfuncs.c.

References populate_record_worker().

2306 {
2307  return populate_record_worker(fcinfo, "json_populate_record", true);
2308 }
static Datum populate_record_worker(FunctionCallInfo fcinfo, const char *funcname, bool have_record_arg)
Definition: jsonfuncs.c:3203

◆ json_populate_recordset()

Datum json_populate_recordset ( PG_FUNCTION_ARGS  )

Definition at line 3498 of file jsonfuncs.c.

References populate_recordset_worker().

3499 {
3500  return populate_recordset_worker(fcinfo, "json_populate_recordset", true);
3501 }
static Datum populate_recordset_worker(FunctionCallInfo fcinfo, const char *funcname, bool have_record_arg)
Definition: jsonfuncs.c:3546

◆ json_strip_nulls()

Datum json_strip_nulls ( PG_FUNCTION_ARGS  )

Definition at line 4001 of file jsonfuncs.c.

References JsonSemAction::array_element_start, JsonSemAction::array_end, JsonSemAction::array_start, cstring_to_text_with_len(), StringInfoData::data, StringInfoData::len, OkeysState::lex, StripnullState::lex, makeJsonLexContext(), makeStringInfo(), JsonSemAction::object_end, JsonSemAction::object_field_start, JsonSemAction::object_start, palloc0(), PG_GETARG_TEXT_PP, pg_parse_json(), PG_RETURN_TEXT_P, JsonSemAction::scalar, JsonSemAction::semstate, StripnullState::skip_next_null, sn_array_element_start(), sn_array_end(), sn_array_start(), sn_object_end(), sn_object_field_start(), sn_object_start(), sn_scalar(), and StripnullState::strval.

4002 {
4003  text *json = PG_GETARG_TEXT_PP(0);
4005  JsonLexContext *lex;
4006  JsonSemAction *sem;
4007 
4008  lex = makeJsonLexContext(json, true);
4009  state = palloc0(sizeof(StripnullState));
4010  sem = palloc0(sizeof(JsonSemAction));
4011 
4012  state->strval = makeStringInfo();
4013  state->skip_next_null = false;
4014  state->lex = lex;
4015 
4016  sem->semstate = (void *) state;
4018  sem->object_end = sn_object_end;
4019  sem->array_start = sn_array_start;
4020  sem->array_end = sn_array_end;
4021  sem->scalar = sn_scalar;
4024 
4025  pg_parse_json(lex, sem);
4026 
4028  state->strval->len));
4029 
4030 }
json_struct_action array_end
Definition: jsonapi.h:88
bool skip_next_null
Definition: jsonfuncs.c:284
static void sn_object_start(void *state)
Definition: jsonfuncs.c:3911
json_struct_action object_end
Definition: jsonapi.h:86
static void sn_array_element_start(void *state, bool isnull)
Definition: jsonfuncs.c:3971
static void sn_object_field_start(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:3943
StringInfo makeStringInfo(void)
Definition: stringinfo.c:28
json_struct_action object_start
Definition: jsonapi.h:85
json_scalar_action scalar
Definition: jsonapi.h:93
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:273
JsonLexContext * makeJsonLexContext(text *json, bool need_escapes)
Definition: json.c:301
static void sn_array_start(void *state)
Definition: jsonfuncs.c:3927
void pg_parse_json(JsonLexContext *lex, JsonSemAction *sem)
Definition: json.c:332
text * cstring_to_text_with_len(const char *s, int len)
Definition: varlena.c:161
JsonLexContext * lex
Definition: jsonfuncs.c:282
static void sn_object_end(void *state)
Definition: jsonfuncs.c:3919
void * palloc0(Size size)
Definition: mcxt.c:877
json_aelem_action array_element_start
Definition: jsonapi.h:91
static void sn_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:3980
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:331
json_struct_action array_start
Definition: jsonapi.h:87
Definition: regguts.h:298
StringInfo strval
Definition: jsonfuncs.c:283
Definition: c.h:487
json_ofield_action object_field_start
Definition: jsonapi.h:89
static void sn_array_end(void *state)
Definition: jsonfuncs.c:3935
void * semstate
Definition: jsonapi.h:84

◆ json_to_record()

Datum json_to_record ( PG_FUNCTION_ARGS  )

Definition at line 2311 of file jsonfuncs.c.

References populate_record_worker().

2312 {
2313  return populate_record_worker(fcinfo, "json_to_record", false);
2314 }
static Datum populate_record_worker(FunctionCallInfo fcinfo, const char *funcname, bool have_record_arg)
Definition: jsonfuncs.c:3203

◆ json_to_recordset()

Datum json_to_recordset ( PG_FUNCTION_ARGS  )

Definition at line 3504 of file jsonfuncs.c.

References populate_recordset_worker().

3505 {
3506  return populate_recordset_worker(fcinfo, "json_to_recordset", false);
3507 }
static Datum populate_recordset_worker(FunctionCallInfo fcinfo, const char *funcname, bool have_record_arg)
Definition: jsonfuncs.c:3546

◆ jsonb_array_element()

Datum jsonb_array_element ( PG_FUNCTION_ARGS  )

Definition at line 815 of file jsonfuncs.c.

References element(), getIthJsonbValueFromContainer(), JB_ROOT_COUNT, JB_ROOT_IS_ARRAY, JsonbValueToJsonb(), PG_GETARG_INT32, PG_GETARG_JSONB_P, PG_RETURN_JSONB_P, PG_RETURN_NULL, and Jsonb::root.

816 {
817  Jsonb *jb = PG_GETARG_JSONB_P(0);
818  int element = PG_GETARG_INT32(1);
819  JsonbValue *v;
820 
821  if (!JB_ROOT_IS_ARRAY(jb))
822  PG_RETURN_NULL();
823 
824  /* Handle negative subscript */
825  if (element < 0)
826  {
827  uint32 nelements = JB_ROOT_COUNT(jb);
828 
829  if (-element > nelements)
830  PG_RETURN_NULL();
831  else
832  element += nelements;
833  }
834 
835  v = getIthJsonbValueFromContainer(&jb->root, element);
836  if (v != NULL)
838 
839  PG_RETURN_NULL();
840 }
#define PG_GETARG_INT32(n)
Definition: fmgr.h:234
Jsonb * JsonbValueToJsonb(JsonbValue *val)
Definition: jsonb_util.c:79
Definition: jsonb.h:215
#define JB_ROOT_COUNT(jbp_)
Definition: jsonb.h:222
#define JB_ROOT_IS_ARRAY(jbp_)
Definition: jsonb.h:225
unsigned int uint32
Definition: c.h:296
static chr element(struct vars *v, const chr *startp, const chr *endp)
Definition: regc_locale.c:380
JsonbContainer root
Definition: jsonb.h:218
JsonbValue * getIthJsonbValueFromContainer(JsonbContainer *container, uint32 i)
Definition: jsonb_util.c:419
#define PG_RETURN_JSONB_P(x)
Definition: jsonb.h:71
#define PG_RETURN_NULL()
Definition: fmgr.h:305
#define PG_GETARG_JSONB_P(x)
Definition: jsonb.h:70

◆ jsonb_array_element_text()

Datum jsonb_array_element_text ( PG_FUNCTION_ARGS  )

Definition at line 858 of file jsonfuncs.c.

References cstring_to_text(), cstring_to_text_with_len(), StringInfoData::data, DatumGetCString, DirectFunctionCall1, element(), elog, ERROR, getIthJsonbValueFromContainer(), JB_ROOT_COUNT, JB_ROOT_IS_ARRAY, jbvBinary, jbvBool, jbvNull, jbvNumeric, jbvString, JsonbToCString(), StringInfoData::len, makeStringInfo(), numeric_out(), PG_GETARG_INT32, PG_GETARG_JSONB_P, PG_RETURN_NULL, PG_RETURN_TEXT_P, PointerGetDatum, OkeysState::result, Jsonb::root, JsonbValue::type, and JsonbValue::val.

859 {
860  Jsonb *jb = PG_GETARG_JSONB_P(0);
861  int element = PG_GETARG_INT32(1);
862  JsonbValue *v;
863 
864  if (!JB_ROOT_IS_ARRAY(jb))
865  PG_RETURN_NULL();
866 
867  /* Handle negative subscript */
868  if (element < 0)
869  {
870  uint32 nelements = JB_ROOT_COUNT(jb);
871 
872  if (-element > nelements)
873  PG_RETURN_NULL();
874  else
875  element += nelements;
876  }
877 
878  v = getIthJsonbValueFromContainer(&jb->root, element);
879  if (v != NULL)
880  {
881  text *result = NULL;
882 
883  switch (v->type)
884  {
885  case jbvNull:
886  break;
887  case jbvBool:
888  result = cstring_to_text(v->val.boolean ? "true" : "false");
889  break;
890  case jbvString:
891  result = cstring_to_text_with_len(v->val.string.val, v->val.string.len);
892  break;
893  case jbvNumeric:
895  PointerGetDatum(v->val.numeric))));
896  break;
897  case jbvBinary:
898  {
899  StringInfo jtext = makeStringInfo();
900 
901  (void) JsonbToCString(jtext, v->val.binary.data, -1);
902  result = cstring_to_text_with_len(jtext->data, jtext->len);
903  }
904  break;
905  default:
906  elog(ERROR, "unrecognized jsonb type: %d", (int) v->type);
907  }
908 
909  if (result)
910  PG_RETURN_TEXT_P(result);
911  }
912 
913  PG_RETURN_NULL();
914 }
#define PG_GETARG_INT32(n)
Definition: fmgr.h:234
Definition: jsonb.h:215
#define PointerGetDatum(X)
Definition: postgres.h:562
char * val
Definition: jsonb.h:259
Definition: jsonb.h:234
StringInfo makeStringInfo(void)
Definition: stringinfo.c:28
Datum numeric_out(PG_FUNCTION_ARGS)
Definition: numeric.c:651
#define JB_ROOT_COUNT(jbp_)
Definition: jsonb.h:222
Definition: jsonb.h:231
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:585
#define ERROR
Definition: elog.h:43
#define DatumGetCString(X)
Definition: postgres.h:572
#define JB_ROOT_IS_ARRAY(jbp_)
Definition: jsonb.h:225
text * cstring_to_text_with_len(const char *s, int len)
Definition: varlena.c:161
unsigned int uint32
Definition: c.h:296
static chr element(struct vars *v, const chr *startp, const chr *endp)
Definition: regc_locale.c:380
JsonbContainer root
Definition: jsonb.h:218
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:331
text * cstring_to_text(const char *s)
Definition: varlena.c:149
JsonbValue * getIthJsonbValueFromContainer(JsonbContainer *container, uint32 i)
Definition: jsonb_util.c:419
char * JsonbToCString(StringInfo out, JsonbContainer *in, int estimated_len)
Definition: jsonb.c:429
enum jbvType type
Definition: jsonb.h:250
Definition: c.h:487
#define elog
Definition: elog.h:219
#define PG_RETURN_NULL()
Definition: fmgr.h:305
#define PG_GETARG_JSONB_P(x)
Definition: jsonb.h:70

◆ jsonb_array_elements()

Datum jsonb_array_elements ( PG_FUNCTION_ARGS  )

Definition at line 1973 of file jsonfuncs.c.

References elements_worker_jsonb().

1974 {
1975  return elements_worker_jsonb(fcinfo, "jsonb_array_elements", false);
1976 }
static Datum elements_worker_jsonb(FunctionCallInfo fcinfo, const char *funcname, bool as_text)
Definition: jsonfuncs.c:1985

◆ jsonb_array_elements_text()

Datum jsonb_array_elements_text ( PG_FUNCTION_ARGS  )

Definition at line 1979 of file jsonfuncs.c.

References elements_worker_jsonb().

1980 {
1981  return elements_worker_jsonb(fcinfo, "jsonb_array_elements_text", true);
1982 }
static Datum elements_worker_jsonb(FunctionCallInfo fcinfo, const char *funcname, bool as_text)
Definition: jsonfuncs.c:1985

◆ jsonb_array_length()

Datum jsonb_array_length ( PG_FUNCTION_ARGS  )

Definition at line 1581 of file jsonfuncs.c.

References ereport, errcode(), errmsg(), ERROR, JB_ROOT_COUNT, JB_ROOT_IS_ARRAY, JB_ROOT_IS_SCALAR, PG_GETARG_JSONB_P, and PG_RETURN_INT32.

1582 {
1583  Jsonb *jb = PG_GETARG_JSONB_P(0);
1584 
1585  if (JB_ROOT_IS_SCALAR(jb))
1586  ereport(ERROR,
1587  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1588  errmsg("cannot get array length of a scalar")));
1589  else if (!JB_ROOT_IS_ARRAY(jb))
1590  ereport(ERROR,
1591  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1592  errmsg("cannot get array length of a non-array")));
1593 
1595 }
Definition: jsonb.h:215
#define PG_RETURN_INT32(x)
Definition: fmgr.h:314
#define JB_ROOT_COUNT(jbp_)
Definition: jsonb.h:222
int errcode(int sqlerrcode)
Definition: elog.c:575
#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
#define ereport(elevel, rest)
Definition: elog.h:122
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define PG_GETARG_JSONB_P(x)
Definition: jsonb.h:70

◆ jsonb_concat()

Datum jsonb_concat ( PG_FUNCTION_ARGS  )

Definition at line 4161 of file jsonfuncs.c.

References Assert, IteratorConcat(), JB_ROOT_COUNT, JB_ROOT_IS_OBJECT, JB_ROOT_IS_SCALAR, JsonbIteratorInit(), JsonbValueToJsonb(), PG_GETARG_JSONB_P, PG_RETURN_JSONB_P, and Jsonb::root.

4162 {
4163  Jsonb *jb1 = PG_GETARG_JSONB_P(0);
4164  Jsonb *jb2 = PG_GETARG_JSONB_P(1);
4165  JsonbParseState *state = NULL;
4166  JsonbValue *res;
4167  JsonbIterator *it1,
4168  *it2;
4169 
4170  /*
4171  * If one of the jsonb is empty, just return the other if it's not scalar
4172  * and both are of the same kind. If it's a scalar or they are of
4173  * different kinds we need to perform the concatenation even if one is
4174  * empty.
4175  */
4176  if (JB_ROOT_IS_OBJECT(jb1) == JB_ROOT_IS_OBJECT(jb2))
4177  {
4178  if (JB_ROOT_COUNT(jb1) == 0 && !JB_ROOT_IS_SCALAR(jb2))
4179  PG_RETURN_JSONB_P(jb2);
4180  else if (JB_ROOT_COUNT(jb2) == 0 && !JB_ROOT_IS_SCALAR(jb1))
4181  PG_RETURN_JSONB_P(jb1);
4182  }
4183 
4184  it1 = JsonbIteratorInit(&jb1->root);
4185  it2 = JsonbIteratorInit(&jb2->root);
4186 
4187  res = IteratorConcat(&it1, &it2, &state);
4188 
4189  Assert(res != NULL);
4190 
4192 }
#define JB_ROOT_IS_OBJECT(jbp_)
Definition: jsonb.h:224
Jsonb * JsonbValueToJsonb(JsonbValue *val)
Definition: jsonb_util.c:79
Definition: jsonb.h:215
#define JB_ROOT_COUNT(jbp_)
Definition: jsonb.h:222
#define JB_ROOT_IS_SCALAR(jbp_)
Definition: jsonb.h:223
JsonbContainer root
Definition: jsonb.h:218
#define Assert(condition)
Definition: c.h:670
JsonbIterator * JsonbIteratorInit(JsonbContainer *container)
Definition: jsonb_util.c:718
Definition: regguts.h:298
static JsonbValue * IteratorConcat(JsonbIterator **it1, JsonbIterator **it2, JsonbParseState **state)
Definition: jsonfuncs.c:4546
#define PG_RETURN_JSONB_P(x)
Definition: jsonb.h:71
#define PG_GETARG_JSONB_P(x)
Definition: jsonb.h:70

◆ jsonb_delete()

Datum jsonb_delete ( PG_FUNCTION_ARGS  )

Definition at line 4202 of file jsonfuncs.c.

References Assert, ereport, errcode(), errmsg(), ERROR, JB_ROOT_COUNT, JB_ROOT_IS_SCALAR, jbvString, JsonbIteratorInit(), JsonbIteratorNext(), JsonbValueToJsonb(), PG_GETARG_JSONB_P, PG_GETARG_TEXT_PP, PG_RETURN_JSONB_P, pushJsonbValue(), Jsonb::root, JsonbValue::type, JsonbValue::val, VARDATA_ANY, VARSIZE_ANY_EXHDR, WJB_BEGIN_ARRAY, WJB_ELEM, and WJB_KEY.

4203 {
4204  Jsonb *in = PG_GETARG_JSONB_P(0);
4205  text *key = PG_GETARG_TEXT_PP(1);
4206  char *keyptr = VARDATA_ANY(key);
4207  int keylen = VARSIZE_ANY_EXHDR(key);
4208  JsonbParseState *state = NULL;
4209  JsonbIterator *it;
4210  JsonbValue v,
4211  *res = NULL;
4212  bool skipNested = false;
4214 
4215  if (JB_ROOT_IS_SCALAR(in))
4216  ereport(ERROR,
4217  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4218  errmsg("cannot delete from scalar")));
4219 
4220  if (JB_ROOT_COUNT(in) == 0)
4221  PG_RETURN_JSONB_P(in);
4222 
4223  it = JsonbIteratorInit(&in->root);
4224 
4225  while ((r = JsonbIteratorNext(&it, &v, skipNested)) != 0)
4226  {
4227  skipNested = true;
4228 
4229  if ((r == WJB_ELEM || r == WJB_KEY) &&
4230  (v.type == jbvString && keylen == v.val.string.len &&
4231  memcmp(keyptr, v.val.string.val, keylen) == 0))
4232  {
4233  /* skip corresponding value as well */
4234  if (r == WJB_KEY)
4235  JsonbIteratorNext(&it, &v, true);
4236 
4237  continue;
4238  }
4239 
4240  res = pushJsonbValue(&state, r, r < WJB_BEGIN_ARRAY ? &v : NULL);
4241  }
4242 
4243  Assert(res != NULL);
4244 
4246 }
#define VARDATA_ANY(PTR)
Definition: postgres.h:347
Jsonb * JsonbValueToJsonb(JsonbValue *val)
Definition: jsonb_util.c:79
Definition: jsonb.h:215
char * val
Definition: jsonb.h:259
#define JB_ROOT_COUNT(jbp_)
Definition: jsonb.h:222
int errcode(int sqlerrcode)
Definition: elog.c:575
#define JB_ROOT_IS_SCALAR(jbp_)
Definition: jsonb.h:223
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:273
JsonbValue * pushJsonbValue(JsonbParseState **pstate, JsonbIteratorToken seq, JsonbValue *jbval)
Definition: jsonb_util.c:517
#define ERROR
Definition: elog.h:43
Definition: jsonb.h:23
#define ereport(elevel, rest)
Definition: elog.h:122
JsonbIteratorToken
Definition: jsonb.h:20
JsonbContainer root
Definition: jsonb.h:218
#define Assert(condition)
Definition: c.h:670
JsonbIterator * JsonbIteratorInit(JsonbContainer *container)
Definition: jsonb_util.c:718
Definition: regguts.h:298
enum jbvType type
Definition: jsonb.h:250
#define VARSIZE_ANY_EXHDR(PTR)
Definition: postgres.h:340
int errmsg(const char *fmt,...)
Definition: elog.c:797
Definition: c.h:487
#define PG_RETURN_JSONB_P(x)
Definition: jsonb.h:71
JsonbIteratorToken JsonbIteratorNext(JsonbIterator **it, JsonbValue *val, bool skipNested)
Definition: jsonb_util.c:754
Definition: jsonb.h:25
#define PG_GETARG_JSONB_P(x)
Definition: jsonb.h:70

◆ jsonb_delete_array()

Datum jsonb_delete_array ( PG_FUNCTION_ARGS  )

Definition at line 4255 of file jsonfuncs.c.

References ARR_NDIM, Assert, deconstruct_array(), ereport, errcode(), errmsg(), ERROR, i, JB_ROOT_COUNT, JB_ROOT_IS_SCALAR, jbvString, JsonbIteratorInit(), JsonbIteratorNext(), JsonbValueToJsonb(), PG_GETARG_ARRAYTYPE_P, PG_GETARG_JSONB_P, PG_RETURN_JSONB_P, pushJsonbValue(), Jsonb::root, TEXTOID, JsonbValue::type, JsonbValue::val, VARDATA_ANY, VARSIZE_ANY_EXHDR, WJB_BEGIN_ARRAY, WJB_ELEM, and WJB_KEY.

4256 {
4257  Jsonb *in = PG_GETARG_JSONB_P(0);
4258  ArrayType *keys = PG_GETARG_ARRAYTYPE_P(1);
4259  Datum *keys_elems;
4260  bool *keys_nulls;
4261  int keys_len;
4262  JsonbParseState *state = NULL;
4263  JsonbIterator *it;
4264  JsonbValue v,
4265  *res = NULL;
4266  bool skipNested = false;
4268 
4269  if (ARR_NDIM(keys) > 1)
4270  ereport(ERROR,
4271  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
4272  errmsg("wrong number of array subscripts")));
4273 
4274  if (JB_ROOT_IS_SCALAR(in))
4275  ereport(ERROR,
4276  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4277  errmsg("cannot delete from scalar")));
4278 
4279  if (JB_ROOT_COUNT(in) == 0)
4280  PG_RETURN_JSONB_P(in);
4281 
4282  deconstruct_array(keys, TEXTOID, -1, false, 'i',
4283  &keys_elems, &keys_nulls, &keys_len);
4284 
4285  if (keys_len == 0)
4286  PG_RETURN_JSONB_P(in);
4287 
4288  it = JsonbIteratorInit(&in->root);
4289 
4290  while ((r = JsonbIteratorNext(&it, &v, skipNested)) != 0)
4291  {
4292  skipNested = true;
4293 
4294  if ((r == WJB_ELEM || r == WJB_KEY) && v.type == jbvString)
4295  {
4296  int i;
4297  bool found = false;
4298 
4299  for (i = 0; i < keys_len; i++)
4300  {
4301  char *keyptr;
4302  int keylen;
4303 
4304  if (keys_nulls[i])
4305  continue;
4306 
4307  keyptr = VARDATA_ANY(keys_elems[i]);
4308  keylen = VARSIZE_ANY_EXHDR(keys_elems[i]);
4309  if (keylen == v.val.string.len &&
4310  memcmp(keyptr, v.val.string.val, keylen) == 0)
4311  {
4312  found = true;
4313  break;
4314  }
4315  }
4316  if (found)
4317  {
4318  /* skip corresponding value as well */
4319  if (r == WJB_KEY)
4320  JsonbIteratorNext(&it, &v, true);
4321 
4322  continue;
4323  }
4324  }
4325 
4326  res = pushJsonbValue(&state, r, r < WJB_BEGIN_ARRAY ? &v : NULL);
4327  }
4328 
4329  Assert(res != NULL);
4330 
4332 }
#define VARDATA_ANY(PTR)
Definition: postgres.h:347
Jsonb * JsonbValueToJsonb(JsonbValue *val)
Definition: jsonb_util.c:79
Definition: jsonb.h:215
#define TEXTOID
Definition: pg_type.h:324
char * val
Definition: jsonb.h:259
#define JB_ROOT_COUNT(jbp_)
Definition: jsonb.h:222
int errcode(int sqlerrcode)
Definition: elog.c:575
#define JB_ROOT_IS_SCALAR(jbp_)
Definition: jsonb.h:223
JsonbValue * pushJsonbValue(JsonbParseState **pstate, JsonbIteratorToken seq, JsonbValue *jbval)
Definition: jsonb_util.c:517
#define PG_GETARG_ARRAYTYPE_P(n)
Definition: array.h:248
#define ERROR
Definition: elog.h:43
Definition: jsonb.h:23
#define ereport(elevel, rest)
Definition: elog.h:122
JsonbIteratorToken
Definition: jsonb.h:20
JsonbContainer root
Definition: jsonb.h:218
uintptr_t Datum
Definition: postgres.h:372
#define Assert(condition)
Definition: c.h:670
JsonbIterator * JsonbIteratorInit(JsonbContainer *container)
Definition: jsonb_util.c:718
Definition: regguts.h:298
#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
#define VARSIZE_ANY_EXHDR(PTR)
Definition: postgres.h:340
int errmsg(const char *fmt,...)
Definition: elog.c:797
int i
#define PG_RETURN_JSONB_P(x)
Definition: jsonb.h:71
JsonbIteratorToken JsonbIteratorNext(JsonbIterator **it, JsonbValue *val, bool skipNested)
Definition: jsonb_util.c:754
Definition: jsonb.h:25
#define PG_GETARG_JSONB_P(x)
Definition: jsonb.h:70

◆ jsonb_delete_idx()

Datum jsonb_delete_idx ( PG_FUNCTION_ARGS  )

Definition at line 4342 of file jsonfuncs.c.

References Assert, ereport, errcode(), errmsg(), ERROR, i, idx(), JB_ROOT_COUNT, JB_ROOT_IS_OBJECT, JB_ROOT_IS_SCALAR, JsonbIteratorInit(), JsonbIteratorNext(), JsonbValueToJsonb(), PG_GETARG_INT32, PG_GETARG_JSONB_P, PG_RETURN_JSONB_P, pushJsonbValue(), Jsonb::root, JsonbValue::val, WJB_BEGIN_ARRAY, and WJB_ELEM.

4343 {
4344  Jsonb *in = PG_GETARG_JSONB_P(0);
4345  int idx = PG_GETARG_INT32(1);
4346  JsonbParseState *state = NULL;
4347  JsonbIterator *it;
4348  uint32 i = 0,
4349  n;
4350  JsonbValue v,
4351  *res = NULL;
4353 
4354  if (JB_ROOT_IS_SCALAR(in))
4355  ereport(ERROR,
4356  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4357  errmsg("cannot delete from scalar")));
4358 
4359  if (JB_ROOT_IS_OBJECT(in))
4360  ereport(ERROR,
4361  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4362  errmsg("cannot delete from object using integer index")));
4363 
4364  if (JB_ROOT_COUNT(in) == 0)
4365  PG_RETURN_JSONB_P(in);
4366 
4367  it = JsonbIteratorInit(&in->root);
4368 
4369  r = JsonbIteratorNext(&it, &v, false);
4370  Assert(r == WJB_BEGIN_ARRAY);
4371  n = v.val.array.nElems;
4372 
4373  if (idx < 0)
4374  {
4375  if (-idx > n)
4376  idx = n;
4377  else
4378  idx = n + idx;
4379  }
4380 
4381  if (idx >= n)
4382  PG_RETURN_JSONB_P(in);
4383 
4384  pushJsonbValue(&state, r, NULL);
4385 
4386  while ((r = JsonbIteratorNext(&it, &v, true)) != 0)
4387  {
4388  if (r == WJB_ELEM)
4389  {
4390  if (i++ == idx)
4391  continue;
4392  }
4393 
4394  res = pushJsonbValue(&state, r, r < WJB_BEGIN_ARRAY ? &v : NULL);
4395  }
4396 
4397  Assert(res != NULL);
4398 
4400 }
#define PG_GETARG_INT32(n)
Definition: fmgr.h:234
#define JB_ROOT_IS_OBJECT(jbp_)
Definition: jsonb.h:224
Jsonb * JsonbValueToJsonb(JsonbValue *val)
Definition: jsonb_util.c:79
Definition: jsonb.h:215
char * val
Definition: jsonb.h:259
#define JB_ROOT_COUNT(jbp_)
Definition: jsonb.h:222
int errcode(int sqlerrcode)
Definition: elog.c:575
Datum idx(PG_FUNCTION_ARGS)
Definition: _int_op.c:264
#define JB_ROOT_IS_SCALAR(jbp_)
Definition: jsonb.h:223
JsonbValue * pushJsonbValue(JsonbParseState **pstate, JsonbIteratorToken seq, JsonbValue *jbval)
Definition: jsonb_util.c:517
#define ERROR
Definition: elog.h:43
unsigned int uint32
Definition: c.h:296
#define ereport(elevel, rest)
Definition: elog.h:122
JsonbIteratorToken
Definition: jsonb.h:20
JsonbContainer root
Definition: jsonb.h:218
#define Assert(condition)
Definition: c.h:670
JsonbIterator * JsonbIteratorInit(JsonbContainer *container)
Definition: jsonb_util.c:718
Definition: regguts.h:298
int errmsg(const char *fmt,...)
Definition: elog.c:797
int i
#define PG_RETURN_JSONB_P(x)
Definition: jsonb.h:71
JsonbIteratorToken JsonbIteratorNext(JsonbIterator **it, JsonbValue *val, bool skipNested)
Definition: jsonb_util.c:754
Definition: jsonb.h:25
#define PG_GETARG_JSONB_P(x)
Definition: jsonb.h:70

◆ jsonb_delete_path()

Datum jsonb_delete_path ( PG_FUNCTION_ARGS  )

Definition at line 4454 of file jsonfuncs.c.

References ARR_NDIM, Assert, deconstruct_array(), ereport, errcode(), errmsg(), ERROR, JB_PATH_DELETE, JB_ROOT_COUNT, JB_ROOT_IS_SCALAR, JsonbIteratorInit(), JsonbValueToJsonb(), PG_GETARG_ARRAYTYPE_P, PG_GETARG_JSONB_P, PG_RETURN_JSONB_P, Jsonb::root, setPath(), and TEXTOID.

4455 {
4456  Jsonb *in = PG_GETARG_JSONB_P(0);
4457  ArrayType *path = PG_GETARG_ARRAYTYPE_P(1);
4458  JsonbValue *res = NULL;
4459  Datum *path_elems;
4460  bool *path_nulls;
4461  int path_len;
4462  JsonbIterator *it;
4463  JsonbParseState *st = NULL;
4464 
4465  if (ARR_NDIM(path) > 1)
4466  ereport(ERROR,
4467  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
4468  errmsg("wrong number of array subscripts")));
4469 
4470  if (JB_ROOT_IS_SCALAR(in))
4471  ereport(ERROR,
4472  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4473  errmsg("cannot delete path in scalar")));
4474 
4475  if (JB_ROOT_COUNT(in) == 0)
4476  PG_RETURN_JSONB_P(in);
4477 
4478  deconstruct_array(path, TEXTOID, -1, false, 'i',
4479  &path_elems, &path_nulls, &path_len);
4480 
4481  if (path_len == 0)
4482  PG_RETURN_JSONB_P(in);
4483 
4484  it = JsonbIteratorInit(&in->root);
4485 
4486  res = setPath(&it, path_elems, path_nulls, path_len, &st,
4487  0, NULL, JB_PATH_DELETE);
4488 
4489  Assert(res != NULL);
4490 
4492 }
Jsonb * JsonbValueToJsonb(JsonbValue *val)
Definition: jsonb_util.c:79
Definition: jsonb.h:215
#define TEXTOID
Definition: pg_type.h:324
static JsonbValue * setPath(JsonbIterator **it, Datum *path_elems, bool *path_nulls, int path_len, JsonbParseState **st, int level, Jsonb *newval, int op_type)
Definition: jsonfuncs.c:4664
#define JB_ROOT_COUNT(jbp_)
Definition: jsonb.h:222
int errcode(int sqlerrcode)
Definition: elog.c:575
#define JB_ROOT_IS_SCALAR(jbp_)
Definition: jsonb.h:223
#define PG_GETARG_ARRAYTYPE_P(n)
Definition: array.h:248
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:122
JsonbContainer root
Definition: jsonb.h:218
uintptr_t Datum
Definition: postgres.h:372
#define Assert(condition)
Definition: c.h:670
JsonbIterator * JsonbIteratorInit(JsonbContainer *container)
Definition: jsonb_util.c:718
#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
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define PG_RETURN_JSONB_P(x)
Definition: jsonb.h:71
#define JB_PATH_DELETE
Definition: jsonfuncs.c:39
#define PG_GETARG_JSONB_P(x)
Definition: jsonb.h:70

◆ jsonb_each()

Datum jsonb_each ( PG_FUNCTION_ARGS  )

Definition at line 1653 of file jsonfuncs.c.

References each_worker_jsonb().

1654 {
1655  return each_worker_jsonb(fcinfo, "jsonb_each", false);
1656 }
static Datum each_worker_jsonb(FunctionCallInfo fcinfo, const char *funcname, bool as_text)
Definition: jsonfuncs.c:1671

◆ jsonb_each_text()

Datum jsonb_each_text ( PG_FUNCTION_ARGS  )

Definition at line 1665 of file jsonfuncs.c.

References each_worker_jsonb().

1666 {
1667  return each_worker_jsonb(fcinfo, "jsonb_each_text", true);
1668 }
static Datum each_worker_jsonb(FunctionCallInfo fcinfo, const char *funcname, bool as_text)
Definition: jsonfuncs.c:1671

◆ jsonb_extract_path()

Datum jsonb_extract_path ( PG_FUNCTION_ARGS  )

Definition at line 1373 of file jsonfuncs.c.

References get_jsonb_path_all().

1374 {
1375  return get_jsonb_path_all(fcinfo, false);
1376 }
static Datum get_jsonb_path_all(FunctionCallInfo fcinfo, bool as_text)
Definition: jsonfuncs.c:1385

◆ jsonb_extract_path_text()

Datum jsonb_extract_path_text ( PG_FUNCTION_ARGS  )

Definition at line 1379 of file jsonfuncs.c.

References get_jsonb_path_all().

1380 {
1381  return get_jsonb_path_all(fcinfo, true);
1382 }
static Datum get_jsonb_path_all(FunctionCallInfo fcinfo, bool as_text)
Definition: jsonfuncs.c:1385

◆ jsonb_insert()

Datum jsonb_insert ( PG_FUNCTION_ARGS  )

Definition at line 4499 of file jsonfuncs.c.

References ARR_NDIM, Assert, deconstruct_array(), ereport, errcode(), errmsg(), ERROR, JB_PATH_INSERT_AFTER, JB_PATH_INSERT_BEFORE, JB_ROOT_IS_SCALAR, JsonbIteratorInit(), JsonbValueToJsonb(), newval, PG_GETARG_ARRAYTYPE_P, PG_GETARG_BOOL, PG_GETARG_JSONB_P, PG_RETURN_JSONB_P, Jsonb::root, setPath(), and TEXTOID.

4500 {
4501  Jsonb *in = PG_GETARG_JSONB_P(0);
4502  ArrayType *path = PG_GETARG_ARRAYTYPE_P(1);
4504  bool after = PG_GETARG_BOOL(3);
4505  JsonbValue *res = NULL;
4506  Datum *path_elems;
4507  bool *path_nulls;
4508  int path_len;
4509  JsonbIterator *it;
4510  JsonbParseState *st = NULL;
4511 
4512  if (ARR_NDIM(path) > 1)
4513  ereport(ERROR,
4514  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
4515  errmsg("wrong number of array subscripts")));
4516 
4517  if (JB_ROOT_IS_SCALAR(in))
4518  ereport(ERROR,
4519  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4520  errmsg("cannot set path in scalar")));
4521 
4522  deconstruct_array(path, TEXTOID, -1, false, 'i',
4523  &path_elems, &path_nulls, &path_len);
4524 
4525  if (path_len == 0)
4526  PG_RETURN_JSONB_P(in);
4527 
4528  it = JsonbIteratorInit(&in->root);
4529 
4530  res = setPath(&it, path_elems, path_nulls, path_len, &st, 0, newval,
4532 
4533  Assert(res != NULL);
4534 
4536 }
Jsonb * JsonbValueToJsonb(JsonbValue *val)
Definition: jsonb_util.c:79
Definition: jsonb.h:215
#define TEXTOID
Definition: pg_type.h:324
static JsonbValue * setPath(JsonbIterator **it, Datum *path_elems, bool *path_nulls, int path_len, JsonbParseState **st, int level, Jsonb *newval, int op_type)
Definition: jsonfuncs.c:4664
int errcode(int sqlerrcode)
Definition: elog.c:575
#define PG_GETARG_BOOL(n)
Definition: fmgr.h:239
#define JB_PATH_INSERT_BEFORE
Definition: jsonfuncs.c:41
#define JB_ROOT_IS_SCALAR(jbp_)
Definition: jsonb.h:223
#define JB_PATH_INSERT_AFTER
Definition: jsonfuncs.c:42
#define PG_GETARG_ARRAYTYPE_P(n)
Definition: array.h:248
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:122
JsonbContainer root
Definition: jsonb.h:218
uintptr_t Datum
Definition: postgres.h:372
#define Assert(condition)
Definition: c.h:670
JsonbIterator * JsonbIteratorInit(JsonbContainer *container)
Definition: jsonb_util.c:718
#define newval
#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
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define PG_RETURN_JSONB_P(x)
Definition: jsonb.h:71
#define PG_GETARG_JSONB_P(x)
Definition: jsonb.h:70

◆ jsonb_object_field()

Datum jsonb_object_field ( PG_FUNCTION_ARGS  )

Definition at line 713 of file jsonfuncs.c.

References findJsonbValueFromContainerLen(), JB_FOBJECT, JB_ROOT_IS_OBJECT, JsonbValueToJsonb(), PG_GETARG_JSONB_P, PG_GETARG_TEXT_PP, PG_RETURN_JSONB_P, PG_RETURN_NULL, Jsonb::root, VARDATA_ANY, and VARSIZE_ANY_EXHDR.

714 {
715  Jsonb *jb = PG_GETARG_JSONB_P(0);
716  text *key = PG_GETARG_TEXT_PP(1);
717  JsonbValue *v;
718 
719  if (!JB_ROOT_IS_OBJECT(jb))
720  PG_RETURN_NULL();
721 
723  VARDATA_ANY(key),
724  VARSIZE_ANY_EXHDR(key));
725 
726  if (v != NULL)
728 
729  PG_RETURN_NULL();
730 }
#define JB_ROOT_IS_OBJECT(jbp_)
Definition: jsonb.h:224
#define VARDATA_ANY(PTR)
Definition: postgres.h:347
Jsonb * JsonbValueToJsonb(JsonbValue *val)
Definition: jsonb_util.c:79
Definition: jsonb.h:215
static JsonbValue * findJsonbValueFromContainerLen(JsonbContainer *container, uint32 flags, char *key, uint32 keylen)
Definition: jsonfuncs.c:3889
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:273
JsonbContainer root
Definition: jsonb.h:218
#define JB_FOBJECT
Definition: jsonb.h:205
#define VARSIZE_ANY_EXHDR(PTR)
Definition: postgres.h:340
Definition: c.h:487
#define PG_RETURN_JSONB_P(x)
Definition: jsonb.h:71
#define PG_RETURN_NULL()
Definition: fmgr.h:305
#define PG_GETARG_JSONB_P(x)
Definition: jsonb.h:70

◆ jsonb_object_field_text()