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_values_scalar (void *state, char *token, JsonTokenType tokentype)
 
static void iterate_values_object_field_start (void *state, char *fname, bool isnull)
 
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)
 
uint32 parse_jsonb_index_flags (Jsonb *jb)
 
void iterate_jsonb_values (Jsonb *jb, uint32 flags, void *state, JsonIterateStringValuesAction action)
 
void iterate_json_values (text *json, uint32 flags, 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 331 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:1335
long val
Definition: informix.c:689

Definition at line 325 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 316 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 321 of file jsonfuncs.c.

Referenced by populate_record_field().

Typedef Documentation

◆ AlenState

◆ ArrayIOData

◆ ColumnIOData

Definition at line 153 of file jsonfuncs.c.

◆ CompositeIOData

◆ DomainIOData

◆ EachState

◆ ElementsState

◆ GetState

◆ IterateJsonStringValuesState

◆ JHashState

◆ JsObject

◆ JsonHashEntry

◆ JsValue

◆ OkeysState

◆ PopulateArrayContext

◆ PopulateArrayState

◆ PopulateRecordCache

◆ PopulateRecordsetCache

◆ PopulateRecordsetState

◆ RecordIOData

Definition at line 154 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 190 of file jsonfuncs.c.

Function Documentation

◆ addJsonbToParseState()

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

Definition at line 4101 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().

4102 {
4103  JsonbIterator *it;
4104  JsonbValue *o = &(*jbps)->contVal;
4105  JsonbValue v;
4107 
4108  it = JsonbIteratorInit(&jb->root);
4109 
4110  Assert(o->type == jbvArray || o->type == jbvObject);
4111 
4112  if (JB_ROOT_IS_SCALAR(jb))
4113  {
4114  (void) JsonbIteratorNext(&it, &v, false); /* skip array header */
4115  Assert(v.type == jbvArray);
4116  (void) JsonbIteratorNext(&it, &v, false); /* fetch scalar value */
4117 
4118  switch (o->type)
4119  {
4120  case jbvArray:
4121  (void) pushJsonbValue(jbps, WJB_ELEM, &v);
4122  break;
4123  case jbvObject:
4124  (void) pushJsonbValue(jbps, WJB_VALUE, &v);
4125  break;
4126  default:
4127  elog(ERROR, "unexpected parent of nested structure");
4128  }
4129  }
4130  else
4131  {
4132  while ((type = JsonbIteratorNext(&it, &v, false)) != WJB_DONE)
4133  {
4134  if (type == WJB_KEY || type == WJB_VALUE || type == WJB_ELEM)
4135  (void) pushJsonbValue(jbps, type, &v);
4136  else
4137  (void) pushJsonbValue(jbps, type, NULL);
4138  }
4139  }
4140 
4141 }
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:699
JsonbIterator * JsonbIteratorInit(JsonbContainer *container)
Definition: jsonb_util.c:718
enum jbvType type
Definition: jsonb.h:250
#define elog
Definition: elog.h:219
JsonbIteratorToken JsonbIteratorNext(JsonbIterator **it, JsonbValue *val, bool skipNested)
Definition: jsonb_util.c:754
Definition: jsonb.h:25

◆ alen_array_element_start()

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

Definition at line 1629 of file jsonfuncs.c.

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

Referenced by json_array_length().

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

◆ alen_object_start()

static void alen_object_start ( void *  state)
static

Definition at line 1605 of file jsonfuncs.c.

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

Referenced by json_array_length().

1606 {
1607  AlenState *_state = (AlenState *) state;
1608 
1609  /* json structure check */
1610  if (_state->lex->lex_level == 0)
1611  ereport(ERROR,
1612  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1613  errmsg("cannot get array length of a non-array")));
1614 }
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:95
#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 1617 of file jsonfuncs.c.

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

Referenced by json_array_length().

1618 {
1619  AlenState *_state = (AlenState *) state;
1620 
1621  /* json structure check */
1622  if (_state->lex->lex_level == 0)
1623  ereport(ERROR,
1624  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1625  errmsg("cannot get array length of a scalar")));
1626 }
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:95
#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 3054 of file jsonfuncs.c.

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

Referenced by populate_record().

3055 {
3056  RecordIOData *data = (RecordIOData *)
3057  MemoryContextAlloc(mcxt,
3058  offsetof(RecordIOData, columns) +
3059  ncolumns * sizeof(ColumnIOData));
3060 
3061  data->record_type = InvalidOid;
3062  data->record_typmod = 0;
3063  data->ncolumns = ncolumns;
3064  MemSet(data->columns, 0, sizeof(ColumnIOData) * ncolumns);
3065 
3066  return data;
3067 }
Oid record_type
Definition: hstore_io.c:754
struct ColumnIOData ColumnIOData
Definition: jsonfuncs.c:153
#define MemSet(start, val, len)
Definition: c.h:908
int32 record_typmod
Definition: hstore_io.c:755
ColumnIOData columns[FLEXIBLE_ARRAY_MEMBER]
Definition: hstore_io.c:759
#define InvalidOid
Definition: postgres_ext.h:36
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:771
#define offsetof(type, field)
Definition: c.h:622

◆ each_array_start()

static void each_array_start ( void *  state)
static

Definition at line 1940 of file jsonfuncs.c.

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

Referenced by each_worker().

1941 {
1942  EachState *_state = (EachState *) state;
1943 
1944  /* json structure check */
1945  if (_state->lex->lex_level == 0)
1946  ereport(ERROR,
1947  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1948  errmsg("cannot deconstruct an array as an object")));
1949 }
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:102
#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 1894 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().

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

◆ each_object_field_start()

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

Definition at line 1874 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().

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

◆ each_scalar()

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

Definition at line 1952 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().

1953 {
1954  EachState *_state = (EachState *) state;
1955 
1956  /* json structure check */
1957  if (_state->lex->lex_level == 0)
1958  ereport(ERROR,
1959  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1960  errmsg("cannot deconstruct a scalar")));
1961 
1962  /* supply de-escaped value if required */
1963  if (_state->next_scalar)
1964  _state->normalized_scalar = token;
1965 }
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:102
#define ereport(elevel, rest)
Definition: elog.h:122
char * normalized_scalar
Definition: jsonfuncs.c:109
Definition: regguts.h:298
int errmsg(const char *fmt,...)
Definition: elog.c:797
bool next_scalar
Definition: jsonfuncs.c:108

◆ each_worker()

static Datum each_worker ( FunctionCallInfo  fcinfo,
bool  as_text 
)
static

Definition at line 1810 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().

1811 {
1812  text *json = PG_GETARG_TEXT_PP(0);
1813  JsonLexContext *lex;
1814  JsonSemAction *sem;
1815  ReturnSetInfo *rsi;
1816  MemoryContext old_cxt;
1817  TupleDesc tupdesc;
1818  EachState *state;
1819 
1820  lex = makeJsonLexContext(json, true);
1821  state = palloc0(sizeof(EachState));
1822  sem = palloc0(sizeof(JsonSemAction));
1823 
1824  rsi = (ReturnSetInfo *) fcinfo->resultinfo;
1825 
1826  if (!rsi || !IsA(rsi, ReturnSetInfo) ||
1827  (rsi->allowedModes & SFRM_Materialize) == 0 ||
1828  rsi->expectedDesc == NULL)
1829  ereport(ERROR,
1830  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1831  errmsg("set-valued function called in context that "
1832  "cannot accept a set")));
1833 
1835 
1836  (void) get_call_result_type(fcinfo, NULL, &tupdesc);
1837 
1838  /* make these in a sufficiently long-lived memory context */
1840 
1841  state->ret_tdesc = CreateTupleDescCopy(tupdesc);
1842  BlessTupleDesc(state->ret_tdesc);
1843  state->tuple_store =
1845  false, work_mem);
1846 
1847  MemoryContextSwitchTo(old_cxt);
1848 
1849  sem->semstate = (void *) state;
1851  sem->scalar = each_scalar;
1854 
1855  state->normalize_results = as_text;
1856  state->next_scalar = false;
1857  state->lex = lex;
1859  "json_each temporary cxt",
1861 
1862  pg_parse_json(lex, sem);
1863 
1864  MemoryContextDelete(state->tmp_cxt);
1865 
1866  rsi->setResult = state->tuple_store;
1867  rsi->setDesc = state->ret_tdesc;
1868 
1869  PG_RETURN_NULL();
1870 }
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
Definition: tupdesc.c:112
#define IsA(nodeptr, _type_)
Definition: nodes.h:568
Tuplestorestate * tuple_store
Definition: jsonfuncs.c:103
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:211
static void each_object_field_start(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:1874
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:1940
TupleDesc ret_tdesc
Definition: jsonfuncs.c:104
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:278
MemoryContext tmp_cxt
Definition: jsonfuncs.c:105
static void each_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:1952
TupleDesc expectedDesc
Definition: execnodes.h:296
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:192
JsonLexContext * lex
Definition: jsonfuncs.c:102
TupleDesc BlessTupleDesc(TupleDesc tupdesc)
Definition: execTuples.c:1109
fmNodePtr resultinfo
Definition: fmgr.h:81
MemoryContext CurrentMemoryContext
Definition: mcxt.c:38
#define ereport(elevel, rest)
Definition: elog.h:122
json_ofield_action object_field_end
Definition: jsonapi.h:90
#define AllocSetContextCreate(parent, name, allocparams)
Definition: memutils.h:170
Tuplestorestate * tuplestore_begin_heap(bool randomAccess, bool interXact, int maxKBytes)
Definition: tuplestore.c:318
void * palloc0(Size size)
Definition: mcxt.c:955
bool normalize_results
Definition: jsonfuncs.c:107
int work_mem
Definition: globals.c:122
int allowedModes
Definition: execnodes.h:297
SetFunctionReturnMode returnMode
Definition: execnodes.h:299
json_struct_action array_start
Definition: jsonapi.h:87
Definition: regguts.h:298
MemoryContext ecxt_per_query_memory
Definition: execnodes.h:225
Tuplestorestate * setResult
Definition: execnodes.h:302
ExprContext * econtext
Definition: execnodes.h:295
TupleDesc setDesc
Definition: execnodes.h:303
int errmsg(const char *fmt,...)
Definition: elog.c:797
Definition: c.h:516
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:1894
#define PG_RETURN_NULL()
Definition: fmgr.h:310
bool next_scalar
Definition: jsonfuncs.c:108

◆ each_worker_jsonb()

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

Definition at line 1673 of file jsonfuncs.c.

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, ReturnSetInfo::allowedModes, Assert, 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().

1674 {
1675  Jsonb *jb = PG_GETARG_JSONB_P(0);
1676  ReturnSetInfo *rsi;
1677  Tuplestorestate *tuple_store;
1678  TupleDesc tupdesc;
1679  TupleDesc ret_tdesc;
1680  MemoryContext old_cxt,
1681  tmp_cxt;
1682  bool skipNested = false;
1683  JsonbIterator *it;
1684  JsonbValue v;
1686 
1687  if (!JB_ROOT_IS_OBJECT(jb))
1688  ereport(ERROR,
1689  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1690  errmsg("cannot call %s on a non-object",
1691  funcname)));
1692 
1693  rsi = (ReturnSetInfo *) fcinfo->resultinfo;
1694 
1695  if (!rsi || !IsA(rsi, ReturnSetInfo) ||
1696  (rsi->allowedModes & SFRM_Materialize) == 0 ||
1697  rsi->expectedDesc == NULL)
1698  ereport(ERROR,
1699  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1700  errmsg("set-valued function called in context that "
1701  "cannot accept a set")));
1702 
1704 
1705  if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
1706  ereport(ERROR,
1707  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1708  errmsg("function returning record called in context "
1709  "that cannot accept type record")));
1710 
1712 
1713  ret_tdesc = CreateTupleDescCopy(tupdesc);
1714  BlessTupleDesc(ret_tdesc);
1715  tuple_store =
1717  false, work_mem);
1718 
1719  MemoryContextSwitchTo(old_cxt);
1720 
1722  "jsonb_each temporary cxt",
1724 
1725  it = JsonbIteratorInit(&jb->root);
1726 
1727  while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE)
1728  {
1729  skipNested = true;
1730 
1731  if (r == WJB_KEY)
1732  {
1733  text *key;
1734  HeapTuple tuple;
1735  Datum values[2];
1736  bool nulls[2] = {false, false};
1737 
1738  /* Use the tmp context so we can clean up after each tuple is done */
1739  old_cxt = MemoryContextSwitchTo(tmp_cxt);
1740 
1741  key = cstring_to_text_with_len(v.val.string.val, v.val.string.len);
1742 
1743  /*
1744  * The next thing the iterator fetches should be the value, no
1745  * matter what shape it is.
1746  */
1747  r = JsonbIteratorNext(&it, &v, skipNested);
1748  Assert(r != WJB_DONE);
1749 
1750  values[0] = PointerGetDatum(key);
1751 
1752  if (as_text)
1753  {
1754  if (v.type == jbvNull)
1755  {
1756  /* a json null is an sql null in text mode */
1757  nulls[1] = true;
1758  values[1] = (Datum) NULL;
1759  }
1760  else
1761  {
1762  text *sv;
1763 
1764  if (v.type == jbvString)
1765  {
1766  /* In text mode, scalar strings should be dequoted */
1767  sv = cstring_to_text_with_len(v.val.string.val, v.val.string.len);
1768  }
1769  else
1770  {
1771  /* Turn anything else into a json string */
1772  StringInfo jtext = makeStringInfo();
1773  Jsonb *jb = JsonbValueToJsonb(&v);
1774 
1775  (void) JsonbToCString(jtext, &jb->root, 0);
1776  sv = cstring_to_text_with_len(jtext->data, jtext->len);
1777  }
1778 
1779  values[1] = PointerGetDatum(sv);
1780  }
1781  }
1782  else
1783  {
1784  /* Not in text mode, just return the Jsonb */
1785  Jsonb *val = JsonbValueToJsonb(&v);
1786 
1787  values[1] = PointerGetDatum(val);
1788  }
1789 
1790  tuple = heap_form_tuple(ret_tdesc, values, nulls);
1791 
1792  tuplestore_puttuple(tuple_store, tuple);
1793 
1794  /* clean up and switch back */
1795  MemoryContextSwitchTo(old_cxt);
1796  MemoryContextReset(tmp_cxt);
1797  }
1798  }
1799 
1800  MemoryContextDelete(tmp_cxt);
1801 
1802  rsi->setResult = tuple_store;
1803  rsi->setDesc = ret_tdesc;
1804 
1805  PG_RETURN_NULL();
1806 }
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
Definition: tupdesc.c:112
#define IsA(nodeptr, _type_)
Definition: nodes.h:568
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:211
#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:539
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:136
Definition: jsonb.h:231
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:1074
TupleDesc expectedDesc
Definition: execnodes.h:296
#define ERROR
Definition: elog.h:43
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:192
void tuplestore_puttuple(Tuplestorestate *state, HeapTuple tuple)
Definition: tuplestore.c:730
TupleDesc BlessTupleDesc(TupleDesc tupdesc)
Definition: execTuples.c:1109
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:38
#define ereport(elevel, rest)
Definition: elog.h:122
JsonbIteratorToken
Definition: jsonb.h:20
JsonbContainer root
Definition: jsonb.h:218
#define AllocSetContextCreate(parent, name, allocparams)
Definition: memutils.h:170
Tuplestorestate * tuplestore_begin_heap(bool randomAccess, bool interXact, int maxKBytes)
Definition: tuplestore.c:318
uintptr_t Datum
Definition: postgres.h:365
int work_mem
Definition: globals.c:122
int allowedModes
Definition: execnodes.h:297
SetFunctionReturnMode returnMode
Definition: execnodes.h:299
#define Assert(condition)
Definition: c.h:699
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:225
enum jbvType type
Definition: jsonb.h:250
Tuplestorestate * setResult
Definition: execnodes.h:302
static Datum values[MAXATTR]
Definition: bootstrap.c:164
ExprContext * econtext
Definition: execnodes.h:295
TupleDesc setDesc
Definition: execnodes.h:303
int errmsg(const char *fmt,...)
Definition: elog.c:797
Definition: c.h:516
long val
Definition: informix.c:689
#define PG_RETURN_NULL()
Definition: fmgr.h:310
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 2210 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().

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

◆ elements_array_element_start()

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

Definition at line 2190 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().

2191 {
2192  ElementsState *_state = (ElementsState *) state;
2193 
2194  /* save a pointer to where the value starts */
2195  if (_state->lex->lex_level == 1)
2196  {
2197  /*
2198  * next_scalar will be reset in the array_element_end handler, and
2199  * since we know the value is a scalar there is no danger of it being
2200  * on while recursing down the tree.
2201  */
2202  if (_state->normalize_results && _state->lex->token_type == JSON_TOKEN_STRING)
2203  _state->next_scalar = true;
2204  else
2205  _state->result_start = _state->lex->token_start;
2206  }
2207 }
bool normalize_results
Definition: jsonfuncs.c:121
JsonLexContext * lex
Definition: jsonfuncs.c:115
bool next_scalar
Definition: jsonfuncs.c:122
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:120
Definition: regguts.h:298

◆ elements_object_start()

static void elements_object_start ( void *  state)
static

Definition at line 2254 of file jsonfuncs.c.

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

Referenced by elements_worker().

2255 {
2256  ElementsState *_state = (ElementsState *) state;
2257 
2258  /* json structure check */
2259  if (_state->lex->lex_level == 0)
2260  ereport(ERROR,
2261  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2262  errmsg("cannot call %s on a non-array",
2263  _state->function_name)));
2264 }
const char * function_name
Definition: jsonfuncs.c:116
JsonLexContext * lex
Definition: jsonfuncs.c:115
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 2267 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().

2268 {
2269  ElementsState *_state = (ElementsState *) state;
2270 
2271  /* json structure check */
2272  if (_state->lex->lex_level == 0)
2273  ereport(ERROR,
2274  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2275  errmsg("cannot call %s on a scalar",
2276  _state->function_name)));
2277 
2278  /* supply de-escaped value if required */
2279  if (_state->next_scalar)
2280  _state->normalized_scalar = token;
2281 }
const char * function_name
Definition: jsonfuncs.c:116
JsonLexContext * lex
Definition: jsonfuncs.c:115
bool next_scalar
Definition: jsonfuncs.c:122
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:123
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 2124 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().

2125 {
2126  text *json = PG_GETARG_TEXT_PP(0);
2127 
2128  /* elements only needs escaped strings when as_text */
2129  JsonLexContext *lex = makeJsonLexContext(json, as_text);
2130  JsonSemAction *sem;
2131  ReturnSetInfo *rsi;
2132  MemoryContext old_cxt;
2133  TupleDesc tupdesc;
2135 
2136  state = palloc0(sizeof(ElementsState));
2137  sem = palloc0(sizeof(JsonSemAction));
2138 
2139  rsi = (ReturnSetInfo *) fcinfo->resultinfo;
2140 
2141  if (!rsi || !IsA(rsi, ReturnSetInfo) ||
2142  (rsi->allowedModes & SFRM_Materialize) == 0 ||
2143  rsi->expectedDesc == NULL)
2144  ereport(ERROR,
2145  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2146  errmsg("set-valued function called in context that "
2147  "cannot accept a set")));
2148 
2150 
2151  /* it's a simple type, so don't use get_call_result_type() */
2152  tupdesc = rsi->expectedDesc;
2153 
2154  /* make these in a sufficiently long-lived memory context */
2156 
2157  state->ret_tdesc = CreateTupleDescCopy(tupdesc);
2158  BlessTupleDesc(state->ret_tdesc);
2159  state->tuple_store =
2161  false, work_mem);
2162 
2163  MemoryContextSwitchTo(old_cxt);
2164 
2165  sem->semstate = (void *) state;
2167  sem->scalar = elements_scalar;
2170 
2171  state->function_name = funcname;
2172  state->normalize_results = as_text;
2173  state->next_scalar = false;
2174  state->lex = lex;
2176  "json_array_elements temporary cxt",
2178 
2179  pg_parse_json(lex, sem);
2180 
2181  MemoryContextDelete(state->tmp_cxt);
2182 
2183  rsi->setResult = state->tuple_store;
2184  rsi->setDesc = state->ret_tdesc;
2185 
2186  PG_RETURN_NULL();
2187 }
bool normalize_results
Definition: jsonfuncs.c:121
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
Definition: tupdesc.c:112
#define IsA(nodeptr, _type_)
Definition: nodes.h:568
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:211
const char * function_name
Definition: jsonfuncs.c:116
JsonLexContext * lex
Definition: jsonfuncs.c:115
static void elements_object_start(void *state)
Definition: jsonfuncs.c:2254
bool next_scalar
Definition: jsonfuncs.c:122
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:278
TupleDesc expectedDesc
Definition: execnodes.h:296
TupleDesc ret_tdesc
Definition: jsonfuncs.c:118
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:192
TupleDesc BlessTupleDesc(TupleDesc tupdesc)
Definition: execTuples.c:1109
fmNodePtr resultinfo
Definition: fmgr.h:81
MemoryContext CurrentMemoryContext
Definition: mcxt.c:38
#define ereport(elevel, rest)
Definition: elog.h:122
static void elements_array_element_start(void *state, bool isnull)
Definition: jsonfuncs.c:2190
#define AllocSetContextCreate(parent, name, allocparams)
Definition: memutils.h:170
Tuplestorestate * tuplestore_begin_heap(bool randomAccess, bool interXact, int maxKBytes)
Definition: tuplestore.c:318
static void elements_array_element_end(void *state, bool isnull)
Definition: jsonfuncs.c:2210
void * palloc0(Size size)
Definition: mcxt.c:955
static void elements_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:2267
json_aelem_action array_element_start
Definition: jsonapi.h:91
Tuplestorestate * tuple_store
Definition: jsonfuncs.c:117
int work_mem
Definition: globals.c:122
int allowedModes
Definition: execnodes.h:297
SetFunctionReturnMode returnMode
Definition: execnodes.h:299
Definition: regguts.h:298
MemoryContext ecxt_per_query_memory
Definition: execnodes.h:225
Tuplestorestate * setResult
Definition: execnodes.h:302
ExprContext * econtext
Definition: execnodes.h:295
TupleDesc setDesc
Definition: execnodes.h:303
int errmsg(const char *fmt,...)
Definition: elog.c:797
MemoryContext tmp_cxt
Definition: jsonfuncs.c:119
Definition: c.h:516
void * semstate
Definition: jsonapi.h:84
#define PG_RETURN_NULL()
Definition: fmgr.h:310
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 1988 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().

1990 {
1991  Jsonb *jb = PG_GETARG_JSONB_P(0);
1992  ReturnSetInfo *rsi;
1993  Tuplestorestate *tuple_store;
1994  TupleDesc tupdesc;
1995  TupleDesc ret_tdesc;
1996  MemoryContext old_cxt,
1997  tmp_cxt;
1998  bool skipNested = false;
1999  JsonbIterator *it;
2000  JsonbValue v;
2002 
2003  if (JB_ROOT_IS_SCALAR(jb))
2004  ereport(ERROR,
2005  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2006  errmsg("cannot extract elements from a scalar")));
2007  else if (!JB_ROOT_IS_ARRAY(jb))
2008  ereport(ERROR,
2009  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2010  errmsg("cannot extract elements from an object")));
2011 
2012  rsi = (ReturnSetInfo *) fcinfo->resultinfo;
2013 
2014  if (!rsi || !IsA(rsi, ReturnSetInfo) ||
2015  (rsi->allowedModes & SFRM_Materialize) == 0 ||
2016  rsi->expectedDesc == NULL)
2017  ereport(ERROR,
2018  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2019  errmsg("set-valued function called in context that "
2020  "cannot accept a set")));
2021 
2023 
2024  /* it's a simple type, so don't use get_call_result_type() */
2025  tupdesc = rsi->expectedDesc;
2026 
2028 
2029  ret_tdesc = CreateTupleDescCopy(tupdesc);
2030  BlessTupleDesc(ret_tdesc);
2031  tuple_store =
2033  false, work_mem);
2034 
2035  MemoryContextSwitchTo(old_cxt);
2036 
2038  "jsonb_array_elements temporary cxt",
2040 
2041  it = JsonbIteratorInit(&jb->root);
2042 
2043  while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE)
2044  {
2045  skipNested = true;
2046 
2047  if (r == WJB_ELEM)
2048  {
2049  HeapTuple tuple;
2050  Datum values[1];
2051  bool nulls[1] = {false};
2052 
2053  /* use the tmp context so we can clean up after each tuple is done */
2054  old_cxt = MemoryContextSwitchTo(tmp_cxt);
2055 
2056  if (!as_text)
2057  {
2058  Jsonb *val = JsonbValueToJsonb(&v);
2059 
2060  values[0] = PointerGetDatum(val);
2061  }
2062  else
2063  {
2064  if (v.type == jbvNull)
2065  {
2066  /* a json null is an sql null in text mode */
2067  nulls[0] = true;
2068  values[0] = (Datum) NULL;
2069  }
2070  else
2071  {
2072  text *sv;
2073 
2074  if (v.type == jbvString)
2075  {
2076  /* in text mode scalar strings should be dequoted */
2077  sv = cstring_to_text_with_len(v.val.string.val, v.val.string.len);
2078  }
2079  else
2080  {
2081  /* turn anything else into a json string */
2082  StringInfo jtext = makeStringInfo();
2083  Jsonb *jb = JsonbValueToJsonb(&v);
2084 
2085  (void) JsonbToCString(jtext, &jb->root, 0);
2086  sv = cstring_to_text_with_len(jtext->data, jtext->len);
2087  }
2088 
2089  values[0] = PointerGetDatum(sv);
2090  }
2091  }
2092 
2093  tuple = heap_form_tuple(ret_tdesc, values, nulls);
2094 
2095  tuplestore_puttuple(tuple_store, tuple);
2096 
2097  /* clean up and switch back */
2098  MemoryContextSwitchTo(old_cxt);
2099  MemoryContextReset(tmp_cxt);
2100  }
2101  }
2102 
2103  MemoryContextDelete(tmp_cxt);
2104 
2105  rsi->setResult = tuple_store;
2106  rsi->setDesc = ret_tdesc;
2107 
2108  PG_RETURN_NULL();
2109 }
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
Definition: tupdesc.c:112
#define IsA(nodeptr, _type_)
Definition: nodes.h:568
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:211
Jsonb * JsonbValueToJsonb(JsonbValue *val)
Definition: jsonb_util.c:79
Definition: jsonb.h:215
#define PointerGetDatum(X)
Definition: postgres.h:539
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:136
Definition: jsonb.h:231
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:1074
#define JB_ROOT_IS_SCALAR(jbp_)
Definition: jsonb.h:223
TupleDesc expectedDesc
Definition: execnodes.h:296
#define ERROR
Definition: elog.h:43
#define JB_ROOT_IS_ARRAY(jbp_)
Definition: jsonb.h:225
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:192
void tuplestore_puttuple(Tuplestorestate *state, HeapTuple tuple)
Definition: tuplestore.c:730
TupleDesc BlessTupleDesc(TupleDesc tupdesc)
Definition: execTuples.c:1109
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:38
#define ereport(elevel, rest)
Definition: elog.h:122
JsonbIteratorToken
Definition: jsonb.h:20
JsonbContainer root
Definition: jsonb.h:218
#define AllocSetContextCreate(parent, name, allocparams)
Definition: memutils.h:170
Tuplestorestate * tuplestore_begin_heap(bool randomAccess, bool interXact, int maxKBytes)
Definition: tuplestore.c:318
uintptr_t Datum
Definition: postgres.h:365
int work_mem
Definition: globals.c:122
int allowedModes
Definition: execnodes.h:297
SetFunctionReturnMode returnMode
Definition: execnodes.h:299
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:225
enum jbvType type
Definition: jsonb.h:250
Tuplestorestate * setResult
Definition: execnodes.h:302
static Datum values[MAXATTR]
Definition: bootstrap.c:164
ExprContext * econtext
Definition: execnodes.h:295
TupleDesc setDesc
Definition: execnodes.h:303
int errmsg(const char *fmt,...)
Definition: elog.c:797
Definition: c.h:516
long val
Definition: informix.c:689
#define PG_RETURN_NULL()
Definition: fmgr.h:310
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 3892 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().

3894 {
3895  JsonbValue k;
3896 
3897  k.type = jbvString;
3898  k.val.string.val = key;
3899  k.val.string.len = keylen;
3900 
3901  return findJsonbValueFromContainer(container, flags, &k);
3902 }
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 1292 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().

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

◆ get_array_element_start()

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

Definition at line 1246 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().

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

◆ get_array_end()

static void get_array_end ( void *  state)
static

Definition at line 1230 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().

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

◆ get_array_start()

static void get_array_start ( void *  state)
static

Definition at line 1197 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().

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

◆ get_json_object_as_hash()

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

Definition at line 3340 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().

3341 {
3342  HASHCTL ctl;
3343  HTAB *tab;
3344  JHashState *state;
3345  JsonLexContext *lex = makeJsonLexContextCstringLen(json, len, true);
3346  JsonSemAction *sem;
3347 
3348  memset(&ctl, 0, sizeof(ctl));
3349  ctl.keysize = NAMEDATALEN;
3350  ctl.entrysize = sizeof(JsonHashEntry);
3351  ctl.hcxt = CurrentMemoryContext;
3352  tab = hash_create("json object hashtable",
3353  100,
3354  &ctl,
3356 
3357  state = palloc0(sizeof(JHashState));
3358  sem = palloc0(sizeof(JsonSemAction));
3359 
3360  state->function_name = funcname;
3361  state->hash = tab;
3362  state->lex = lex;
3363 
3364  sem->semstate = (void *) state;
3366  sem->scalar = hash_scalar;
3369 
3370  pg_parse_json(lex, sem);
3371 
3372  return tab;
3373 }
#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:3400
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:131
MemoryContext CurrentMemoryContext
Definition: mcxt.c:38
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:3376
const char * function_name
Definition: jsonfuncs.c:130
void * palloc0(Size size)
Definition: mcxt.c:955
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:129
static void hash_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:3460
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:3449

◆ get_jsonb_path_all()

static Datum get_jsonb_path_all ( FunctionCallInfo  fcinfo,
bool  as_text 
)
static

Definition at line 1387 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, JsonbValue::type, JsonbValue::val, VARDATA, VARHDRSZ, VARSIZE, WJB_BEGIN_ARRAY, and WJB_BEGIN_OBJECT.

Referenced by jsonb_extract_path(), and jsonb_extract_path_text().

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

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

◆ get_object_field_end()

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

Definition at line 1148 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().

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

◆ get_object_field_start()

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

Definition at line 1103 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().

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

◆ get_object_start()

static void get_object_start ( void *  state)
static

Definition at line 1070 of file jsonfuncs.c.

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

Referenced by get_worker().

1071 {
1072  GetState *_state = (GetState *) state;
1073  int lex_level = _state->lex->lex_level;
1074 
1075  if (lex_level == 0 && _state->npath == 0)
1076  {
1077  /*
1078  * Special case: we should match the entire object. We only need this
1079  * at outermost level because at nested levels the match will have
1080  * been started by the outer field or array element callback.
1081  */
1082  _state->result_start = _state->lex->token_start;
1083  }
1084 }
int lex_level
Definition: jsonapi.h:59
JsonLexContext * lex
Definition: jsonfuncs.c:79
char * result_start
Definition: jsonfuncs.c:81
int npath
Definition: jsonfuncs.c:84
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 934 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, and TextDatumGetCString.

Referenced by json_extract_path(), and json_extract_path_text().

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

◆ get_scalar()

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

Definition at line 1334 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().

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

◆ get_worker()

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

Definition at line 1014 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().

1019 {
1020  JsonLexContext *lex = makeJsonLexContext(json, true);
1021  JsonSemAction *sem = palloc0(sizeof(JsonSemAction));
1022  GetState *state = palloc0(sizeof(GetState));
1023 
1024  Assert(npath >= 0);
1025 
1026  state->lex = lex;
1027  /* is it "_as_text" variant? */
1028  state->normalize_results = normalize_results;
1029  state->npath = npath;
1030  state->path_names = tpath;
1031  state->path_indexes = ipath;
1032  state->pathok = palloc0(sizeof(bool) * npath);
1033  state->array_cur_index = palloc(sizeof(int) * npath);
1034 
1035  if (npath > 0)
1036  state->pathok[0] = true;
1037 
1038  sem->semstate = (void *) state;
1039 
1040  /*
1041  * Not all variants need all the semantic routines. Only set the ones that
1042  * are actually needed for maximum efficiency.
1043  */
1044  sem->scalar = get_scalar;
1045  if (npath == 0)
1046  {
1048  sem->object_end = get_object_end;
1050  sem->array_end = get_array_end;
1051  }
1052  if (tpath != NULL)
1053  {
1056  }
1057  if (ipath != NULL)
1058  {
1062  }
1063 
1064  pg_parse_json(lex, sem);
1065 
1066  return state->tresult;
1067 }
json_struct_action array_end
Definition: jsonapi.h:88
static void get_array_end(void *state)
Definition: jsonfuncs.c:1230
int * array_cur_index
Definition: jsonfuncs.c:88
static void get_array_element_start(void *state, bool isnull)
Definition: jsonfuncs.c:1246
json_struct_action object_end
Definition: jsonapi.h:86
static void get_object_start(void *state)
Definition: jsonfuncs.c:1070
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:1148
JsonLexContext * lex
Definition: jsonfuncs.c:79
static void get_object_end(void *state)
Definition: jsonfuncs.c:1087
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:80
int npath
Definition: jsonfuncs.c:84
json_ofield_action object_field_end
Definition: jsonapi.h:90
static void get_array_element_end(void *state, bool isnull)
Definition: jsonfuncs.c:1292
bool * pathok
Definition: jsonfuncs.c:87
bool normalize_results
Definition: jsonfuncs.c:82
static void get_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:1334
void * palloc0(Size size)
Definition: mcxt.c:955
static void get_array_start(void *state)
Definition: jsonfuncs.c:1197
json_aelem_action array_element_start
Definition: jsonapi.h:91
char ** path_names
Definition: jsonfuncs.c:85
#define Assert(condition)
Definition: c.h:699
json_struct_action array_start
Definition: jsonapi.h:87
Definition: regguts.h:298
int * path_indexes
Definition: jsonfuncs.c:86
void * palloc(Size size)
Definition: mcxt.c:924
static void get_object_field_start(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:1103
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 3449 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().

3450 {
3451  JHashState *_state = (JHashState *) state;
3452 
3453  if (_state->lex->lex_level == 0)
3454  ereport(ERROR,
3455  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3456  errmsg("cannot call %s on an array", _state->function_name)));
3457 }
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:130
Definition: regguts.h:298
JsonLexContext * lex
Definition: jsonfuncs.c:129
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 3400 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().

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

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

◆ hash_scalar()

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

Definition at line 3460 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().

3461 {
3462  JHashState *_state = (JHashState *) state;
3463 
3464  if (_state->lex->lex_level == 0)
3465  ereport(ERROR,
3466  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3467  errmsg("cannot call %s on a scalar", _state->function_name)));
3468 
3469  if (_state->lex->lex_level == 1)
3470  {
3471  _state->saved_scalar = token;
3472  /* saved_token_type must already be set in hash_object_field_start() */
3473  Assert(_state->saved_token_type == tokentype);
3474  }
3475 }
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:134
#define ereport(elevel, rest)
Definition: elog.h:122
const char * function_name
Definition: jsonfuncs.c:130
#define Assert(condition)
Definition: c.h:699
Definition: regguts.h:298
JsonLexContext * lex
Definition: jsonfuncs.c:129
char * saved_scalar
Definition: jsonfuncs.c:132
int errmsg(const char *fmt,...)
Definition: elog.c:797

◆ iterate_json_values()

void iterate_json_values ( text json,
uint32  flags,
void *  action_state,
JsonIterateStringValuesAction  action 
)

Definition at line 5087 of file jsonfuncs.c.

References IterateJsonStringValuesState::action, generate_unaccent_rules::action, IterateJsonStringValuesState::action_state, IterateJsonStringValuesState::flags, iterate_values_object_field_start(), iterate_values_scalar(), OkeysState::lex, IterateJsonStringValuesState::lex, makeJsonLexContext(), JsonSemAction::object_field_start, palloc0(), pg_parse_json(), JsonSemAction::scalar, and JsonSemAction::semstate.

Referenced by json_to_tsvector_worker().

5089 {
5090  JsonLexContext *lex = makeJsonLexContext(json, true);
5091  JsonSemAction *sem = palloc0(sizeof(JsonSemAction));
5093 
5094  state->lex = lex;
5095  state->action = action;
5096  state->action_state = action_state;
5097  state->flags = flags;
5098 
5099  sem->semstate = (void *) state;
5102 
5103  pg_parse_json(lex, sem);
5104 }
JsonIterateStringValuesAction action
Definition: jsonfuncs.c:60
static void iterate_values_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:5111
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:955
Definition: regguts.h:298
JsonLexContext * lex
Definition: jsonfuncs.c:59
json_ofield_action object_field_start
Definition: jsonapi.h:89
static void iterate_values_object_field_start(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:5137
void * semstate
Definition: jsonapi.h:84

◆ iterate_jsonb_values()

void iterate_jsonb_values ( Jsonb jb,
uint32  flags,
void *  state,
JsonIterateStringValuesAction  action 
)

Definition at line 5019 of file jsonfuncs.c.

References generate_unaccent_rules::action, DatumGetCString, DirectFunctionCall1, jbvBool, jbvNumeric, jbvString, JsonbIteratorInit(), JsonbIteratorNext(), jtiBool, jtiKey, jtiNumeric, jtiString, numeric_out(), NumericGetDatum, pfree(), Jsonb::root, generate_unaccent_rules::type, JsonbValue::type, JsonbValue::val, val, WJB_DONE, WJB_ELEM, WJB_KEY, and WJB_VALUE.

Referenced by jsonb_to_tsvector_worker().

5021 {
5022  JsonbIterator *it;
5023  JsonbValue v;
5025 
5026  it = JsonbIteratorInit(&jb->root);
5027 
5028  /*
5029  * Just recursively iterating over jsonb and call callback on all
5030  * correspoding elements
5031  */
5032  while ((type = JsonbIteratorNext(&it, &v, false)) != WJB_DONE)
5033  {
5034  if (type == WJB_KEY)
5035  {
5036  if (flags & jtiKey)
5037  action(state, v.val.string.val, v.val.string.len);
5038 
5039  continue;
5040  }
5041  else if (!(type == WJB_VALUE || type == WJB_ELEM))
5042  {
5043  /* do not call callback for composite JsonbValue */
5044  continue;
5045  }
5046 
5047  /* JsonbValue is a value of object or element of array */
5048  switch(v.type)
5049  {
5050  case jbvString:
5051  if (flags & jtiString)
5052  action(state, v.val.string.val, v.val.string.len);
5053  break;
5054  case jbvNumeric:
5055  if (flags & jtiNumeric)
5056  {
5057  char *val;
5058 
5060  NumericGetDatum(v.val.numeric)));
5061 
5062  action(state, val, strlen(val));
5063  pfree(val);
5064  }
5065  break;
5066  case jbvBool:
5067  if (flags & jtiBool)
5068  {
5069  if (v.val.boolean)
5070  action(state, "true", 4);
5071  else
5072  action(state, "false", 5);
5073  }
5074  break;
5075  default:
5076  /* do not call callback for composite JsonbValue */
5077  break;
5078  }
5079  }
5080 }
char * val
Definition: jsonb.h:259
#define NumericGetDatum(X)
Definition: numeric.h:51
Definition: jsonb.h:234
Datum numeric_out(PG_FUNCTION_ARGS)
Definition: numeric.c:652
Definition: jsonb.h:22
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:590
void pfree(void *pointer)
Definition: mcxt.c:1031
#define DatumGetCString(X)
Definition: postgres.h:549
Definition: jsonb.h:23
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
long val
Definition: informix.c:689
JsonbIteratorToken JsonbIteratorNext(JsonbIterator **it, JsonbValue *val, bool skipNested)
Definition: jsonb_util.c:754
Definition: jsonb.h:25

◆ iterate_values_object_field_start()

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

Definition at line 5137 of file jsonfuncs.c.

References IterateJsonStringValuesState::action, IterateJsonStringValuesState::action_state, IterateJsonStringValuesState::flags, jtiKey, pstrdup(), and val.

Referenced by iterate_json_values().

5138 {
5140 
5141  if (_state->flags & jtiKey)
5142  {
5143  char *val = pstrdup(fname);
5144  _state->action(_state->action_state, val, strlen(val));
5145  }
5146 }
JsonIterateStringValuesAction action
Definition: jsonfuncs.c:60
char * pstrdup(const char *in)
Definition: mcxt.c:1161
Definition: regguts.h:298
long val
Definition: informix.c:689

◆ iterate_values_scalar()

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

Definition at line 5111 of file jsonfuncs.c.

References IterateJsonStringValuesState::action, IterateJsonStringValuesState::action_state, IterateJsonStringValuesState::flags, JSON_TOKEN_FALSE, JSON_TOKEN_NUMBER, JSON_TOKEN_STRING, JSON_TOKEN_TRUE, jtiBool, jtiNumeric, and jtiString.

Referenced by iterate_json_values().

5112 {
5114 
5115  switch(tokentype)
5116  {
5117  case JSON_TOKEN_STRING:
5118  if (_state->flags & jtiString)
5119  _state->action(_state->action_state, token, strlen(token));
5120  break;
5121  case JSON_TOKEN_NUMBER:
5122  if (_state->flags & jtiNumeric)
5123  _state->action(_state->action_state, token, strlen(token));
5124  break;
5125  case JSON_TOKEN_TRUE:
5126  case JSON_TOKEN_FALSE:
5127  if (_state->flags & jtiBool)
5128  _state->action(_state->action_state, token, strlen(token));
5129  break;
5130  default:
5131  /* do not call callback for any other token */
5132  break;
5133  }
5134 }
JsonIterateStringValuesAction action
Definition: jsonfuncs.c:60
Definition: regguts.h:298

◆ IteratorConcat()

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

Definition at line 4550 of file jsonfuncs.c.

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

Referenced by jsonb_concat().

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

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

◆ json_array_element()

Datum json_array_element ( PG_FUNCTION_ARGS  )

Definition at line 802 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.

803 {
804  text *json = PG_GETARG_TEXT_PP(0);
805  int element = PG_GETARG_INT32(1);
806  text *result;
807 
808  result = get_worker(json, NULL, &element, 1, false);
809 
810  if (result != NULL)
811  PG_RETURN_TEXT_P(result);
812  else
813  PG_RETURN_NULL();
814 }
#define PG_GETARG_INT32(n)
Definition: fmgr.h:239
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:278
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:1014
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:336
Definition: c.h:516
#define PG_RETURN_NULL()
Definition: fmgr.h:310

◆ json_array_element_text()

Datum json_array_element_text ( PG_FUNCTION_ARGS  )

Definition at line 845 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.

846 {
847  text *json = PG_GETARG_TEXT_PP(0);
848  int element = PG_GETARG_INT32(1);
849  text *result;
850 
851  result = get_worker(json, NULL, &element, 1, true);
852 
853  if (result != NULL)
854  PG_RETURN_TEXT_P(result);
855  else
856  PG_RETURN_NULL();
857 }
#define PG_GETARG_INT32(n)
Definition: fmgr.h:239
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:278
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:1014
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:336
Definition: c.h:516
#define PG_RETURN_NULL()
Definition: fmgr.h:310

◆ json_array_elements()

Datum json_array_elements ( PG_FUNCTION_ARGS  )

Definition at line 2112 of file jsonfuncs.c.

References elements_worker().

2113 {
2114  return elements_worker(fcinfo, "json_array_elements", false);
2115 }
static Datum elements_worker(FunctionCallInfo fcinfo, const char *funcname, bool as_text)
Definition: jsonfuncs.c:2124

◆ json_array_elements_text()

Datum json_array_elements_text ( PG_FUNCTION_ARGS  )

Definition at line 2118 of file jsonfuncs.c.

References elements_worker().

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

◆ json_array_length()

Datum json_array_length ( PG_FUNCTION_ARGS  )

Definition at line 1555 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.

1556 {
1557  text *json = PG_GETARG_TEXT_PP(0);
1558  AlenState *state;
1559  JsonLexContext *lex;
1560  JsonSemAction *sem;
1561 
1562  lex = makeJsonLexContext(json, false);
1563  state = palloc0(sizeof(AlenState));
1564  sem = palloc0(sizeof(JsonSemAction));
1565 
1566  /* palloc0 does this for us */
1567 #if 0
1568  state->count = 0;
1569 #endif
1570  state->lex = lex;
1571 
1572  sem->semstate = (void *) state;
1574  sem->scalar = alen_scalar;
1576 
1577  pg_parse_json(lex, sem);
1578 
1579  PG_RETURN_INT32(state->count);
1580 }
json_struct_action object_start
Definition: jsonapi.h:85
#define PG_RETURN_INT32(x)
Definition: fmgr.h:319
json_scalar_action scalar
Definition: jsonapi.h:93
int count
Definition: jsonfuncs.c:96
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:278
static void alen_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:1617
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:95
void * palloc0(Size size)
Definition: mcxt.c:955
json_aelem_action array_element_start
Definition: jsonapi.h:91
Definition: regguts.h:298
static void alen_object_start(void *state)
Definition: jsonfuncs.c:1605
Definition: c.h:516
static void alen_array_element_start(void *state, bool isnull)
Definition: jsonfuncs.c:1629
void * semstate
Definition: jsonapi.h:84

◆ json_each()

Datum json_each ( PG_FUNCTION_ARGS  )

Definition at line 1649 of file jsonfuncs.c.

References each_worker().

1650 {
1651  return each_worker(fcinfo, false);
1652 }
static Datum each_worker(FunctionCallInfo fcinfo, bool as_text)
Definition: jsonfuncs.c:1810

◆ json_each_text()

Datum json_each_text ( PG_FUNCTION_ARGS  )

Definition at line 1661 of file jsonfuncs.c.

References each_worker().

1662 {
1663  return each_worker(fcinfo, true);
1664 }
static Datum each_worker(FunctionCallInfo fcinfo, bool as_text)
Definition: jsonfuncs.c:1810

◆ json_extract_path()

Datum json_extract_path ( PG_FUNCTION_ARGS  )

Definition at line 919 of file jsonfuncs.c.

References get_path_all().

920 {
921  return get_path_all(fcinfo, false);
922 }
static Datum get_path_all(FunctionCallInfo fcinfo, bool as_text)
Definition: jsonfuncs.c:934

◆ json_extract_path_text()

Datum json_extract_path_text ( PG_FUNCTION_ARGS  )

Definition at line 925 of file jsonfuncs.c.

References get_path_all().

926 {
927  return get_path_all(fcinfo, true);
928 }
static Datum get_path_all(FunctionCallInfo fcinfo, bool as_text)
Definition: jsonfuncs.c:934

◆ json_object_field()

Datum json_object_field ( PG_FUNCTION_ARGS  )

Definition at line 699 of file jsonfuncs.c.

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

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

◆ json_object_field_text()

Datum json_object_field_text ( PG_FUNCTION_ARGS  )

Definition at line 735 of file jsonfuncs.c.

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

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

◆ json_object_keys()

Datum json_object_keys ( PG_FUNCTION_ARGS  )

Definition at line 582 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.

583 {
584  FuncCallContext *funcctx;
585  OkeysState *state;
586  int i;
587 
588  if (SRF_IS_FIRSTCALL())
589  {
590  text *json = PG_GETARG_TEXT_PP(0);
591  JsonLexContext *lex = makeJsonLexContext(json, true);
592  JsonSemAction *sem;
593  MemoryContext oldcontext;
594 
595  funcctx = SRF_FIRSTCALL_INIT();
596  oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
597 
598  state = palloc(sizeof(OkeysState));
599  sem = palloc0(sizeof(JsonSemAction));
600 
601  state->lex = lex;
602  state->result_size = 256;
603  state->result_count = 0;
604  state->sent_count = 0;
605  state->result = palloc(256 * sizeof(char *));
606 
607  sem->semstate = (void *) state;
609  sem->scalar = okeys_scalar;
611  /* remainder are all NULL, courtesy of palloc0 above */
612 
613  pg_parse_json(lex, sem);
614  /* keys are now in state->result */
615 
616  pfree(lex->strval->data);
617  pfree(lex->strval);
618  pfree(lex);
619  pfree(sem);
620 
621  MemoryContextSwitchTo(oldcontext);
622  funcctx->user_fctx = (void *) state;
623  }
624 
625  funcctx = SRF_PERCALL_SETUP();
626  state = (OkeysState *) funcctx->user_fctx;
627 
628  if (state->sent_count < state->result_count)
629  {
630  char *nxt = state->result[state->sent_count++];
631 
632  SRF_RETURN_NEXT(funcctx, CStringGetTextDatum(nxt));
633  }
634 
635  /* cleanup to reduce or eliminate memory leaks */
636  for (i = 0; i < state->result_count; i++)
637  pfree(state->result[i]);
638  pfree(state->result);
639  pfree(state);
640 
641  SRF_RETURN_DONE(funcctx);
642 }
int result_count
Definition: jsonfuncs.c:52
#define SRF_IS_FIRSTCALL()
Definition: funcapi.h:294
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
static void okeys_array_start(void *state)
Definition: jsonfuncs.c:666
json_scalar_action scalar
Definition: jsonapi.h:93
int sent_count
Definition: jsonfuncs.c:53
#define SRF_PERCALL_SETUP()
Definition: funcapi.h:298
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:278
#define SRF_RETURN_NEXT(_funcctx, _result)
Definition: funcapi.h:300
JsonLexContext * makeJsonLexContext(text *json, bool need_escapes)
Definition: json.c:301
void pfree(void *pointer)
Definition: mcxt.c:1031
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:645
char ** result
Definition: jsonfuncs.c:50
void * palloc0(Size size)
Definition: mcxt.c:955
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:679
int result_size
Definition: jsonfuncs.c:51
void * user_fctx
Definition: funcapi.h:91
void * palloc(Size size)
Definition: mcxt.c:924
int i
#define CStringGetTextDatum(s)
Definition: builtins.h:95
Definition: c.h:516
json_ofield_action object_field_start
Definition: jsonapi.h:89
void * semstate
Definition: jsonapi.h:84
#define SRF_RETURN_DONE(_funcctx)
Definition: funcapi.h:318
#define SRF_FIRSTCALL_INIT()
Definition: funcapi.h:296

◆ json_populate_record()

Datum json_populate_record ( PG_FUNCTION_ARGS  )

Definition at line 2308 of file jsonfuncs.c.

References populate_record_worker().

2309 {
2310  return populate_record_worker(fcinfo, "json_populate_record", true);
2311 }
static Datum populate_record_worker(FunctionCallInfo fcinfo, const char *funcname, bool have_record_arg)
Definition: jsonfuncs.c:3206

◆ json_populate_recordset()

Datum json_populate_recordset ( PG_FUNCTION_ARGS  )

Definition at line 3501 of file jsonfuncs.c.

References populate_recordset_worker().

3502 {
3503  return populate_recordset_worker(fcinfo, "json_populate_recordset", true);
3504 }
static Datum populate_recordset_worker(FunctionCallInfo fcinfo, const char *funcname, bool have_record_arg)
Definition: jsonfuncs.c:3549

◆ json_strip_nulls()

Datum json_strip_nulls ( PG_FUNCTION_ARGS  )

Definition at line 4004 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.

4005 {
4006  text *json = PG_GETARG_TEXT_PP(0);
4008  JsonLexContext *lex;
4009  JsonSemAction *sem;
4010 
4011  lex = makeJsonLexContext(json, true);
4012  state = palloc0(sizeof(StripnullState));
4013  sem = palloc0(sizeof(JsonSemAction));
4014 
4015  state->strval = makeStringInfo();
4016  state->skip_next_null = false;
4017  state->lex = lex;
4018 
4019  sem->semstate = (void *) state;
4021  sem->object_end = sn_object_end;
4022  sem->array_start = sn_array_start;
4023  sem->array_end = sn_array_end;
4024  sem->scalar = sn_scalar;
4027 
4028  pg_parse_json(lex, sem);
4029 
4031  state->strval->len));
4032 
4033 }
json_struct_action array_end
Definition: jsonapi.h:88
bool skip_next_null
Definition: jsonfuncs.c:285
static void sn_object_start(void *state)
Definition: jsonfuncs.c:3914
json_struct_action object_end
Definition: jsonapi.h:86
static void sn_array_element_start(void *state, bool isnull)
Definition: jsonfuncs.c:3974
static void sn_object_field_start(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:3946
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:278
JsonLexContext * makeJsonLexContext(text *json, bool need_escapes)
Definition: json.c:301
static void sn_array_start(void *state)
Definition: jsonfuncs.c:3930
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:283
static void sn_object_end(void *state)
Definition: jsonfuncs.c:3922
void * palloc0(Size size)
Definition: mcxt.c:955
json_aelem_action array_element_start
Definition: jsonapi.h:91
static void sn_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:3983
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:336
json_struct_action array_start
Definition: jsonapi.h:87
Definition: regguts.h:298
StringInfo strval
Definition: jsonfuncs.c:284
Definition: c.h:516
json_ofield_action object_field_start
Definition: jsonapi.h:89
static void sn_array_end(void *state)
Definition: jsonfuncs.c:3938
void * semstate
Definition: jsonapi.h:84

◆ json_to_record()

Datum json_to_record ( PG_FUNCTION_ARGS  )

Definition at line 2314 of file jsonfuncs.c.

References populate_record_worker().

2315 {
2316  return populate_record_worker(fcinfo, "json_to_record", false);
2317 }
static Datum populate_record_worker(FunctionCallInfo fcinfo, const char *funcname, bool have_record_arg)
Definition: jsonfuncs.c:3206

◆ json_to_recordset()

Datum json_to_recordset ( PG_FUNCTION_ARGS  )

Definition at line 3507 of file jsonfuncs.c.

References populate_recordset_worker().

3508 {
3509  return populate_recordset_worker(fcinfo, "json_to_recordset", false);
3510 }
static Datum populate_recordset_worker(FunctionCallInfo fcinfo, const char *funcname, bool have_record_arg)
Definition: jsonfuncs.c:3549

◆ jsonb_array_element()

Datum jsonb_array_element ( PG_FUNCTION_ARGS  )

Definition at line 817 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.

818 {
819  Jsonb *jb = PG_GETARG_JSONB_P(0);
820  int element = PG_GETARG_INT32(1);
821  JsonbValue *v;
822 
823  if (!JB_ROOT_IS_ARRAY(jb))
824  PG_RETURN_NULL();
825 
826  /* Handle negative subscript */
827  if (element < 0)
828  {
829  uint32 nelements = JB_ROOT_COUNT(jb);
830 
831  if (-element > nelements)
832  PG_RETURN_NULL();
833  else
834  element += nelements;
835  }
836 
837  v = getIthJsonbValueFromContainer(&jb->root, element);
838  if (v != NULL)
840 
841  PG_RETURN_NULL();
842 }
#define PG_GETARG_INT32(n)
Definition: fmgr.h:239
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:325
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:310
#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 860 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.

861 {
862  Jsonb *jb = PG_GETARG_JSONB_P(0);
863  int element = PG_GETARG_INT32(1);
864  JsonbValue *v;
865 
866  if (!JB_ROOT_IS_ARRAY(jb))
867  PG_RETURN_NULL();
868 
869  /* Handle negative subscript */
870  if (element < 0)
871  {
872  uint32 nelements = JB_ROOT_COUNT(jb);
873 
874  if (-element > nelements)
875  PG_RETURN_NULL();
876  else
877  element += nelements;
878  }
879 
880  v = getIthJsonbValueFromContainer(&jb->root, element);
881  if (v != NULL)
882  {
883  text *result = NULL;
884 
885  switch (v->type)
886  {
887  case jbvNull:
888  break;
889  case jbvBool:
890  result = cstring_to_text(v->val.boolean ? "true" : "false");
891  break;
892  case jbvString:
893  result = cstring_to_text_with_len(v->val.string.val, v->val.string.len);
894  break;
895  case jbvNumeric:
897  PointerGetDatum(v->val.numeric))));
898  break;
899  case jbvBinary:
900  {
901  StringInfo jtext = makeStringInfo();
902 
903  (void) JsonbToCString(jtext, v->val.binary.data, -1);
904  result = cstring_to_text_with_len(jtext->data, jtext->len);
905  }
906  break;
907  default:
908  elog(ERROR, "unrecognized jsonb type: %d", (int) v->type);
909  }
910 
911  if (result)
912  PG_RETURN_TEXT_P(result);
913  }
914 
915  PG_RETURN_NULL();
916 }
#define PG_GETARG_INT32(n)
Definition: fmgr.h:239
Definition: jsonb.h:215
#define PointerGetDatum(X)
Definition: postgres.h:539
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:652
#define JB_ROOT_COUNT(jbp_)
Definition: jsonb.h:222
Definition: jsonb.h:231
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:590
#define ERROR
Definition: elog.h:43
#define DatumGetCString(X)
Definition: postgres.h:549
#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:325
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:336
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:516
#define elog
Definition: elog.h:219
#define PG_RETURN_NULL()
Definition: fmgr.h:310
#define PG_GETARG_JSONB_P(x)
Definition: jsonb.h:70

◆ jsonb_array_elements()

Datum jsonb_array_elements ( PG_FUNCTION_ARGS  )

Definition at line 1976 of file jsonfuncs.c.

References elements_worker_jsonb().

1977 {
1978  return elements_worker_jsonb(fcinfo, "jsonb_array_elements", false);
1979 }
static Datum elements_worker_jsonb(FunctionCallInfo fcinfo, const char *funcname, bool as_text)
Definition: jsonfuncs.c:1988

◆ jsonb_array_elements_text()

Datum jsonb_array_elements_text ( PG_FUNCTION_ARGS  )

Definition at line 1982 of file jsonfuncs.c.

References elements_worker_jsonb().

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

◆ jsonb_array_length()

Datum jsonb_array_length ( PG_FUNCTION_ARGS  )

Definition at line 1583 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.

1584 {
1585  Jsonb *jb = PG_GETARG_JSONB_P(0);
1586 
1587  if (JB_ROOT_IS_SCALAR(jb))
1588  ereport(ERROR,
1589  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1590  errmsg("cannot get array length of a scalar")));
1591  else if (!JB_ROOT_IS_ARRAY(jb))
1592  ereport(ERROR,
1593  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1594  errmsg("cannot get array length of a non-array")));
1595 
1597 }
Definition: jsonb.h:215
#define PG_RETURN_INT32(x)
Definition: fmgr.h:319
#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 4165 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.

4166 {
4167  Jsonb *jb1 = PG_GETARG_JSONB_P(0);
4168  Jsonb *jb2 = PG_GETARG_JSONB_P(1);
4169  JsonbParseState *state = NULL;
4170  JsonbValue *res;
4171  JsonbIterator *it1,
4172  *it2;
4173 
4174  /*
4175  * If one of the jsonb is empty, just return the other if it's not scalar
4176  * and both are of the same kind. If it's a scalar or they are of
4177  * different kinds we need to perform the concatenation even if one is
4178  * empty.
4179  */
4180  if (JB_ROOT_IS_OBJECT(jb1) == JB_ROOT_IS_OBJECT(jb2))
4181  {
4182  if (JB_ROOT_COUNT(jb1) == 0 && !JB_ROOT_IS_SCALAR(jb2))
4183  PG_RETURN_JSONB_P(jb2);
4184  else if (JB_ROOT_COUNT(jb2) == 0 && !JB_ROOT_IS_SCALAR(jb1))
4185  PG_RETURN_JSONB_P(jb1);
4186  }
4187 
4188  it1 = JsonbIteratorInit(&jb1->root);
4189  it2 = JsonbIteratorInit(&jb2->root);
4190 
4191  res = IteratorConcat(&it1, &it2, &state);
4192 
4193  Assert(res != NULL);
4194 
4196 }
#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:699
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:4550
#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 4206 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_DONE, WJB_ELEM, and WJB_KEY.

4207 {
4208  Jsonb *in = PG_GETARG_JSONB_P(0);
4209  text *key = PG_GETARG_TEXT_PP(1);
4210  char *keyptr = VARDATA_ANY(key);
4211  int keylen = VARSIZE_ANY_EXHDR(key);
4212  JsonbParseState *state = NULL;
4213  JsonbIterator *it;
4214  JsonbValue v,
4215  *res = NULL;
4216  bool skipNested = false;
4218 
4219  if (JB_ROOT_IS_SCALAR(in))
4220  ereport(ERROR,
4221  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4222  errmsg("cannot delete from scalar")));
4223 
4224  if (JB_ROOT_COUNT(in) == 0)
4225  PG_RETURN_JSONB_P(in);
4226 
4227  it = JsonbIteratorInit(&in->root);
4228 
4229  while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE)
4230  {
4231  skipNested = true;
4232 
4233  if ((r == WJB_ELEM || r == WJB_KEY) &&
4234  (v.type == jbvString && keylen == v.val.string.len &&
4235  memcmp(keyptr, v.val.string.val, keylen) == 0))
4236  {
4237  /* skip corresponding value as well */
4238  if (r == WJB_KEY)
4239  (void) JsonbIteratorNext(&it, &v, true);
4240 
4241  continue;
4242  }
4243 
4244  res = pushJsonbValue(&state, r, r < WJB_BEGIN_ARRAY ? &v : NULL);
4245  }
4246 
4247  Assert(res != NULL);
4248 
4250 }
#define VARDATA_ANY(PTR)
Definition: postgres.h:346
Jsonb * JsonbValueToJsonb(JsonbValue *val)
Definition: jsonb_util.c:79
Definition: jsonb.h:215
char * val
Definition: jsonb.h:259
Definition: jsonb.h:22
#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:278
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:699
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:339
int errmsg(const char *fmt,...)
Definition: elog.c:797
Definition: c.h:516
#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 4259 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, JsonbValue::type, JsonbValue::val, VARDATA_ANY, VARSIZE_ANY_EXHDR, WJB_BEGIN_ARRAY, WJB_DONE, WJB_ELEM, and WJB_KEY.

4260 {
4261  Jsonb *in = PG_GETARG_JSONB_P(0);
4262  ArrayType *keys = PG_GETARG_ARRAYTYPE_P(1);
4263  Datum *keys_elems;
4264  bool *keys_nulls;
4265  int keys_len;
4266  JsonbParseState *state = NULL;
4267  JsonbIterator *it;
4268  JsonbValue v,
4269  *res = NULL;
4270  bool skipNested = false;
4272 
4273  if (ARR_NDIM(keys) > 1)
4274  ereport(ERROR,
4275  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
4276  errmsg("wrong number of array subscripts")));
4277 
4278  if (JB_ROOT_IS_SCALAR(in))
4279  ereport(ERROR,
4280  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4281  errmsg("cannot delete from scalar")));
4282 
4283  if (JB_ROOT_COUNT(in) == 0)
4284  PG_RETURN_JSONB_P(in);
4285 
4286  deconstruct_array(keys, TEXTOID, -1, false, 'i',
4287  &keys_elems, &keys_nulls, &keys_len);
4288 
4289  if (keys_len == 0)
4290  PG_RETURN_JSONB_P(in);
4291 
4292  it = JsonbIteratorInit(&in->root);
4293 
4294  while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE)
4295  {
4296  skipNested = true;
4297 
4298  if ((r == WJB_ELEM || r == WJB_KEY) && v.type == jbvString)
4299  {
4300  int i;
4301  bool found = false;
4302 
4303  for (i = 0; i < keys_len; i++)
4304  {
4305  char *keyptr;
4306  int keylen;
4307 
4308  if (keys_nulls[i])
4309  continue;
4310 
4311  keyptr = VARDATA_ANY(keys_elems[i]);
4312  keylen = VARSIZE_ANY_EXHDR(keys_elems[i]);
4313  if (keylen == v.val.string.len &&
4314  memcmp(keyptr, v.val.string.val, keylen) == 0)
4315  {
4316  found = true;
4317  break;
4318  }
4319  }
4320  if (found)
4321  {
4322  /* skip corresponding value as well */
4323  if (r == WJB_KEY)
4324  (void) JsonbIteratorNext(&it, &v, true);
4325 
4326  continue;
4327  }
4328  }
4329 
4330  res = pushJsonbValue(&state, r, r < WJB_BEGIN_ARRAY ? &v : NULL);
4331  }
4332 
4333  Assert(res != NULL);
4334 
4336 }
#define VARDATA_ANY(PTR)
Definition: postgres.h:346
Jsonb * JsonbValueToJsonb(JsonbValue *val)
Definition: jsonb_util.c:79
Definition: jsonb.h:215
char * val
Definition: jsonb.h:259
Definition: jsonb.h:22
#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:365
#define Assert(condition)
Definition: c.h:699
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:339
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 4346 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, WJB_DONE, and WJB_ELEM.

4347 {
4348  Jsonb *in = PG_GETARG_JSONB_P(0);
4349  int idx = PG_GETARG_INT32(1);
4350  JsonbParseState *state = NULL;
4351  JsonbIterator *it;
4352  uint32 i = 0,
4353  n;
4354  JsonbValue v,
4355  *res = NULL;
4357 
4358  if (JB_ROOT_IS_SCALAR(in))
4359  ereport(ERROR,
4360  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4361  errmsg("cannot delete from scalar")));
4362 
4363  if (JB_ROOT_IS_OBJECT(in))
4364  ereport(ERROR,
4365  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4366  errmsg("cannot delete from object using integer index")));
4367 
4368  if (JB_ROOT_COUNT(in) == 0)
4369  PG_RETURN_JSONB_P(in);
4370 
4371  it = JsonbIteratorInit(&in->root);
4372 
4373  r = JsonbIteratorNext(&it, &v, false);
4374  Assert(r == WJB_BEGIN_ARRAY);
4375  n = v.val.array.nElems;
4376 
4377  if (idx < 0)
4378  {
4379  if (-idx > n)
4380  idx = n;
4381  else
4382  idx = n + idx;
4383  }
4384 
4385  if (idx >= n)
4386  PG_RETURN_JSONB_P(in);
4387 
4388  pushJsonbValue(&state, r, NULL);
4389 
4390  while ((r = JsonbIteratorNext(&it, &v, true)) != WJB_DONE)
4391  {
4392  if (r == WJB_ELEM)
4393  {
4394  if (i++ == idx)
4395  continue;
4396  }
4397 
4398  res = pushJsonbValue(&state, r, r < WJB_BEGIN_ARRAY ? &v : NULL);
4399  }
4400 
4401  Assert(res != NULL);
4402 
4404 }
#define PG_GETARG_INT32(n)
Definition: fmgr.h:239
#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
Definition: jsonb.h:22
#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:325
#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:699
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 4458 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, and setPath().

4459 {
4460  Jsonb *in = PG_GETARG_JSONB_P(0);
4461  ArrayType *path = PG_GETARG_ARRAYTYPE_P(1);
4462  JsonbValue *res = NULL;
4463  Datum *path_elems;
4464  bool *path_nulls;
4465  int path_len;
4466  JsonbIterator *it;
4467  JsonbParseState *st = NULL;
4468 
4469  if (ARR_NDIM(path) > 1)
4470  ereport(ERROR,
4471  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
4472  errmsg("wrong number of array subscripts")));
4473 
4474  if (JB_ROOT_IS_SCALAR(in))
4475  ereport(ERROR,
4476  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4477  errmsg("cannot delete path in scalar")));
4478 
4479  if (JB_ROOT_COUNT(in) == 0)
4480  PG_RETURN_JSONB_P(in);
4481 
4482  deconstruct_array(path, TEXTOID, -1, false, 'i',
4483  &path_elems, &path_nulls, &path_len);
4484 
4485  if (path_len == 0)
4486  PG_RETURN_JSONB_P(in);
4487 
4488  it = JsonbIteratorInit(&in->root);
4489 
4490  res = setPath(&it, path_elems, path_nulls, path_len, &st,
4491  0, NULL, JB_PATH_DELETE);
4492 
4493  Assert(res != NULL);
4494 
4496 }
Jsonb * JsonbValueToJsonb(JsonbValue *val)
Definition: jsonb_util.c:79
Definition: jsonb.h:215
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:4668
#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:365
#define Assert(condition)
Definition: c.h:699
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 1655 of file jsonfuncs.c.

References each_worker_jsonb().

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

◆ jsonb_each_text()

Datum jsonb_each_text ( PG_FUNCTION_ARGS  )

Definition at line 1667 of file jsonfuncs.c.

References each_worker_jsonb().

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

◆ jsonb_extract_path()

Datum jsonb_extract_path ( PG_FUNCTION_ARGS  )

Definition at line 1375 of file jsonfuncs.c.

References get_jsonb_path_all().

1376 {
1377  return get_jsonb_path_all(fcinfo, false);
1378 }
static Datum get_jsonb_path_all(FunctionCallInfo fcinfo, bool as_text)
Definition: jsonfuncs.c:1387

◆ jsonb_extract_path_text()

Datum jsonb_extract_path_text ( PG_FUNCTION_ARGS  )

Definition at line 1381 of file jsonfuncs.c.

References get_jsonb_path_all().

1382 {
1383  return get_jsonb_path_all(fcinfo, true);
1384 }
static Datum get_jsonb_path_all(FunctionCallInfo fcinfo, bool as_text)
Definition: jsonfuncs.c:1387

◆ jsonb_insert()

Datum jsonb_insert ( PG_FUNCTION_ARGS  )