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 332 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 326 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 317 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 322 of file jsonfuncs.c.

Referenced by populate_record_field().

Typedef Documentation

◆ AlenState

◆ ArrayIOData

◆ ColumnIOData

Definition at line 154 of file jsonfuncs.c.

◆ CompositeIOData

◆ DomainIOData

◆ EachState

◆ ElementsState

◆ GetState

◆ IterateJsonStringValuesState

◆ JHashState

◆ JsObject

◆ JsonHashEntry

◆ JsValue

◆ OkeysState

◆ PopulateArrayContext

◆ PopulateArrayState

◆ PopulateRecordCache

◆ PopulateRecordsetCache

◆ PopulateRecordsetState

◆ RecordIOData

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

Function Documentation

◆ addJsonbToParseState()

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

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

4103 {
4104  JsonbIterator *it;
4105  JsonbValue *o = &(*jbps)->contVal;
4106  JsonbValue v;
4108 
4109  it = JsonbIteratorInit(&jb->root);
4110 
4111  Assert(o->type == jbvArray || o->type == jbvObject);
4112 
4113  if (JB_ROOT_IS_SCALAR(jb))
4114  {
4115  (void) JsonbIteratorNext(&it, &v, false); /* skip array header */
4116  Assert(v.type == jbvArray);
4117  (void) JsonbIteratorNext(&it, &v, false); /* fetch scalar value */
4118 
4119  switch (o->type)
4120  {
4121  case jbvArray:
4122  (void) pushJsonbValue(jbps, WJB_ELEM, &v);
4123  break;
4124  case jbvObject:
4125  (void) pushJsonbValue(jbps, WJB_VALUE, &v);
4126  break;
4127  default:
4128  elog(ERROR, "unexpected parent of nested structure");
4129  }
4130  }
4131  else
4132  {
4133  while ((type = JsonbIteratorNext(&it, &v, false)) != WJB_DONE)
4134  {
4135  if (type == WJB_KEY || type == WJB_VALUE || type == WJB_ELEM)
4136  (void) pushJsonbValue(jbps, type, &v);
4137  else
4138  (void) pushJsonbValue(jbps, type, NULL);
4139  }
4140  }
4141 
4142 }
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 1630 of file jsonfuncs.c.

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

Referenced by json_array_length().

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

◆ alen_object_start()

static void alen_object_start ( void *  state)
static

Definition at line 1606 of file jsonfuncs.c.

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

Referenced by json_array_length().

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

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

Referenced by json_array_length().

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

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

Referenced by populate_record().

3056 {
3057  RecordIOData *data = (RecordIOData *)
3058  MemoryContextAlloc(mcxt,
3059  offsetof(RecordIOData, columns) +
3060  ncolumns * sizeof(ColumnIOData));
3061 
3062  data->record_type = InvalidOid;
3063  data->record_typmod = 0;
3064  data->ncolumns = ncolumns;
3065  MemSet(data->columns, 0, sizeof(ColumnIOData) * ncolumns);
3066 
3067  return data;
3068 }
Oid record_type
Definition: hstore_io.c:754
struct ColumnIOData ColumnIOData
Definition: jsonfuncs.c:154
#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 1941 of file jsonfuncs.c.

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

Referenced by each_worker().

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

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

◆ each_object_field_start()

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

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

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

◆ each_scalar()

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

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

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

◆ each_worker()

static Datum each_worker ( FunctionCallInfo  fcinfo,
bool  as_text 
)
static

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

1812 {
1813  text *json = PG_GETARG_TEXT_PP(0);
1814  JsonLexContext *lex;
1815  JsonSemAction *sem;
1816  ReturnSetInfo *rsi;
1817  MemoryContext old_cxt;
1818  TupleDesc tupdesc;
1819  EachState *state;
1820 
1821  lex = makeJsonLexContext(json, true);
1822  state = palloc0(sizeof(EachState));
1823  sem = palloc0(sizeof(JsonSemAction));
1824 
1825  rsi = (ReturnSetInfo *) fcinfo->resultinfo;
1826 
1827  if (!rsi || !IsA(rsi, ReturnSetInfo) ||
1828  (rsi->allowedModes & SFRM_Materialize) == 0 ||
1829  rsi->expectedDesc == NULL)
1830  ereport(ERROR,
1831  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1832  errmsg("set-valued function called in context that "
1833  "cannot accept a set")));
1834 
1836 
1837  (void) get_call_result_type(fcinfo, NULL, &tupdesc);
1838 
1839  /* make these in a sufficiently long-lived memory context */
1841 
1842  state->ret_tdesc = CreateTupleDescCopy(tupdesc);
1843  BlessTupleDesc(state->ret_tdesc);
1844  state->tuple_store =
1846  false, work_mem);
1847 
1848  MemoryContextSwitchTo(old_cxt);
1849 
1850  sem->semstate = (void *) state;
1852  sem->scalar = each_scalar;
1855 
1856  state->normalize_results = as_text;
1857  state->next_scalar = false;
1858  state->lex = lex;
1860  "json_each temporary cxt",
1862 
1863  pg_parse_json(lex, sem);
1864 
1865  MemoryContextDelete(state->tmp_cxt);
1866 
1867  rsi->setResult = state->tuple_store;
1868  rsi->setDesc = state->ret_tdesc;
1869 
1870  PG_RETURN_NULL();
1871 }
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
Definition: tupdesc.c:112
#define IsA(nodeptr, _type_)
Definition: nodes.h:567
Tuplestorestate * tuple_store
Definition: jsonfuncs.c:104
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:211
static void each_object_field_start(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:1875
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:1941
TupleDesc ret_tdesc
Definition: jsonfuncs.c:105
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:278
MemoryContext tmp_cxt
Definition: jsonfuncs.c:106
static void each_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:1953
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:103
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:108
int work_mem
Definition: globals.c:120
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:1895
#define PG_RETURN_NULL()
Definition: fmgr.h:310
bool next_scalar
Definition: jsonfuncs.c:109

◆ each_worker_jsonb()

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

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

1675 {
1676  Jsonb *jb = PG_GETARG_JSONB_P(0);
1677  ReturnSetInfo *rsi;
1678  Tuplestorestate *tuple_store;
1679  TupleDesc tupdesc;
1680  TupleDesc ret_tdesc;
1681  MemoryContext old_cxt,
1682  tmp_cxt;
1683  bool skipNested = false;
1684  JsonbIterator *it;
1685  JsonbValue v;
1687 
1688  if (!JB_ROOT_IS_OBJECT(jb))
1689  ereport(ERROR,
1690  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1691  errmsg("cannot call %s on a non-object",
1692  funcname)));
1693 
1694  rsi = (ReturnSetInfo *) fcinfo->resultinfo;
1695 
1696  if (!rsi || !IsA(rsi, ReturnSetInfo) ||
1697  (rsi->allowedModes & SFRM_Materialize) == 0 ||
1698  rsi->expectedDesc == NULL)
1699  ereport(ERROR,
1700  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1701  errmsg("set-valued function called in context that "
1702  "cannot accept a set")));
1703 
1705 
1706  if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
1707  ereport(ERROR,
1708  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1709  errmsg("function returning record called in context "
1710  "that cannot accept type record")));
1711 
1713 
1714  ret_tdesc = CreateTupleDescCopy(tupdesc);
1715  BlessTupleDesc(ret_tdesc);
1716  tuple_store =
1718  false, work_mem);
1719 
1720  MemoryContextSwitchTo(old_cxt);
1721 
1723  "jsonb_each temporary cxt",
1725 
1726  it = JsonbIteratorInit(&jb->root);
1727 
1728  while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE)
1729  {
1730  skipNested = true;
1731 
1732  if (r == WJB_KEY)
1733  {
1734  text *key;
1735  HeapTuple tuple;
1736  Datum values[2];
1737  bool nulls[2] = {false, false};
1738 
1739  /* Use the tmp context so we can clean up after each tuple is done */
1740  old_cxt = MemoryContextSwitchTo(tmp_cxt);
1741 
1742  key = cstring_to_text_with_len(v.val.string.val, v.val.string.len);
1743 
1744  /*
1745  * The next thing the iterator fetches should be the value, no
1746  * matter what shape it is.
1747  */
1748  r = JsonbIteratorNext(&it, &v, skipNested);
1749  Assert(r != WJB_DONE);
1750 
1751  values[0] = PointerGetDatum(key);
1752 
1753  if (as_text)
1754  {
1755  if (v.type == jbvNull)
1756  {
1757  /* a json null is an sql null in text mode */
1758  nulls[1] = true;
1759  values[1] = (Datum) NULL;
1760  }
1761  else
1762  {
1763  text *sv;
1764 
1765  if (v.type == jbvString)
1766  {
1767  /* In text mode, scalar strings should be dequoted */
1768  sv = cstring_to_text_with_len(v.val.string.val, v.val.string.len);
1769  }
1770  else
1771  {
1772  /* Turn anything else into a json string */
1773  StringInfo jtext = makeStringInfo();
1774  Jsonb *jb = JsonbValueToJsonb(&v);
1775 
1776  (void) JsonbToCString(jtext, &jb->root, 0);
1777  sv = cstring_to_text_with_len(jtext->data, jtext->len);
1778  }
1779 
1780  values[1] = PointerGetDatum(sv);
1781  }
1782  }
1783  else
1784  {
1785  /* Not in text mode, just return the Jsonb */
1786  Jsonb *val = JsonbValueToJsonb(&v);
1787 
1788  values[1] = PointerGetDatum(val);
1789  }
1790 
1791  tuple = heap_form_tuple(ret_tdesc, values, nulls);
1792 
1793  tuplestore_puttuple(tuple_store, tuple);
1794 
1795  /* clean up and switch back */
1796  MemoryContextSwitchTo(old_cxt);
1797  MemoryContextReset(tmp_cxt);
1798  }
1799  }
1800 
1801  MemoryContextDelete(tmp_cxt);
1802 
1803  rsi->setResult = tuple_store;
1804  rsi->setDesc = ret_tdesc;
1805 
1806  PG_RETURN_NULL();
1807 }
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
Definition: tupdesc.c:112
#define IsA(nodeptr, _type_)
Definition: nodes.h:567
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:541
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:367
int work_mem
Definition: globals.c:120
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:431
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 2211 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().

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

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

◆ elements_object_start()

static void elements_object_start ( void *  state)
static

Definition at line 2255 of file jsonfuncs.c.

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

Referenced by elements_worker().

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

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

2126 {
2127  text *json = PG_GETARG_TEXT_PP(0);
2128 
2129  /* elements only needs escaped strings when as_text */
2130  JsonLexContext *lex = makeJsonLexContext(json, as_text);
2131  JsonSemAction *sem;
2132  ReturnSetInfo *rsi;
2133  MemoryContext old_cxt;
2134  TupleDesc tupdesc;
2136 
2137  state = palloc0(sizeof(ElementsState));
2138  sem = palloc0(sizeof(JsonSemAction));
2139 
2140  rsi = (ReturnSetInfo *) fcinfo->resultinfo;
2141 
2142  if (!rsi || !IsA(rsi, ReturnSetInfo) ||
2143  (rsi->allowedModes & SFRM_Materialize) == 0 ||
2144  rsi->expectedDesc == NULL)
2145  ereport(ERROR,
2146  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2147  errmsg("set-valued function called in context that "
2148  "cannot accept a set")));
2149 
2151 
2152  /* it's a simple type, so don't use get_call_result_type() */
2153  tupdesc = rsi->expectedDesc;
2154 
2155  /* make these in a sufficiently long-lived memory context */
2157 
2158  state->ret_tdesc = CreateTupleDescCopy(tupdesc);
2159  BlessTupleDesc(state->ret_tdesc);
2160  state->tuple_store =
2162  false, work_mem);
2163 
2164  MemoryContextSwitchTo(old_cxt);
2165 
2166  sem->semstate = (void *) state;
2168  sem->scalar = elements_scalar;
2171 
2172  state->function_name = funcname;
2173  state->normalize_results = as_text;
2174  state->next_scalar = false;
2175  state->lex = lex;
2177  "json_array_elements temporary cxt",
2179 
2180  pg_parse_json(lex, sem);
2181 
2182  MemoryContextDelete(state->tmp_cxt);
2183 
2184  rsi->setResult = state->tuple_store;
2185  rsi->setDesc = state->ret_tdesc;
2186 
2187  PG_RETURN_NULL();
2188 }
bool normalize_results
Definition: jsonfuncs.c:122
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
Definition: tupdesc.c:112
#define IsA(nodeptr, _type_)
Definition: nodes.h:567
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:211
const char * function_name
Definition: jsonfuncs.c:117
JsonLexContext * lex
Definition: jsonfuncs.c:116
static void elements_object_start(void *state)
Definition: jsonfuncs.c:2255
bool next_scalar
Definition: jsonfuncs.c:123
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:119
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:2191
#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:2211
void * palloc0(Size size)
Definition: mcxt.c:955
static void elements_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:2268
json_aelem_action array_element_start
Definition: jsonapi.h:91
Tuplestorestate * tuple_store
Definition: jsonfuncs.c:118
int work_mem
Definition: globals.c:120
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:120
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 1989 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().

1991 {
1992  Jsonb *jb = PG_GETARG_JSONB_P(0);
1993  ReturnSetInfo *rsi;
1994  Tuplestorestate *tuple_store;
1995  TupleDesc tupdesc;
1996  TupleDesc ret_tdesc;
1997  MemoryContext old_cxt,
1998  tmp_cxt;
1999  bool skipNested = false;
2000  JsonbIterator *it;
2001  JsonbValue v;
2003 
2004  if (JB_ROOT_IS_SCALAR(jb))
2005  ereport(ERROR,
2006  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2007  errmsg("cannot extract elements from a scalar")));
2008  else if (!JB_ROOT_IS_ARRAY(jb))
2009  ereport(ERROR,
2010  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2011  errmsg("cannot extract elements from an object")));
2012 
2013  rsi = (ReturnSetInfo *) fcinfo->resultinfo;
2014 
2015  if (!rsi || !IsA(rsi, ReturnSetInfo) ||
2016  (rsi->allowedModes & SFRM_Materialize) == 0 ||
2017  rsi->expectedDesc == NULL)
2018  ereport(ERROR,
2019  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2020  errmsg("set-valued function called in context that "
2021  "cannot accept a set")));
2022 
2024 
2025  /* it's a simple type, so don't use get_call_result_type() */
2026  tupdesc = rsi->expectedDesc;
2027 
2029 
2030  ret_tdesc = CreateTupleDescCopy(tupdesc);
2031  BlessTupleDesc(ret_tdesc);
2032  tuple_store =
2034  false, work_mem);
2035 
2036  MemoryContextSwitchTo(old_cxt);
2037 
2039  "jsonb_array_elements temporary cxt",
2041 
2042  it = JsonbIteratorInit(&jb->root);
2043 
2044  while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE)
2045  {
2046  skipNested = true;
2047 
2048  if (r == WJB_ELEM)
2049  {
2050  HeapTuple tuple;
2051  Datum values[1];
2052  bool nulls[1] = {false};
2053 
2054  /* use the tmp context so we can clean up after each tuple is done */
2055  old_cxt = MemoryContextSwitchTo(tmp_cxt);
2056 
2057  if (!as_text)
2058  {
2059  Jsonb *val = JsonbValueToJsonb(&v);
2060 
2061  values[0] = PointerGetDatum(val);
2062  }
2063  else
2064  {
2065  if (v.type == jbvNull)
2066  {
2067  /* a json null is an sql null in text mode */
2068  nulls[0] = true;
2069  values[0] = (Datum) NULL;
2070  }
2071  else
2072  {
2073  text *sv;
2074 
2075  if (v.type == jbvString)
2076  {
2077  /* in text mode scalar strings should be dequoted */
2078  sv = cstring_to_text_with_len(v.val.string.val, v.val.string.len);
2079  }
2080  else
2081  {
2082  /* turn anything else into a json string */
2083  StringInfo jtext = makeStringInfo();
2084  Jsonb *jb = JsonbValueToJsonb(&v);
2085 
2086  (void) JsonbToCString(jtext, &jb->root, 0);
2087  sv = cstring_to_text_with_len(jtext->data, jtext->len);
2088  }
2089 
2090  values[0] = PointerGetDatum(sv);
2091  }
2092  }
2093 
2094  tuple = heap_form_tuple(ret_tdesc, values, nulls);
2095 
2096  tuplestore_puttuple(tuple_store, tuple);
2097 
2098  /* clean up and switch back */
2099  MemoryContextSwitchTo(old_cxt);
2100  MemoryContextReset(tmp_cxt);
2101  }
2102  }
2103 
2104  MemoryContextDelete(tmp_cxt);
2105 
2106  rsi->setResult = tuple_store;
2107  rsi->setDesc = ret_tdesc;
2108 
2109  PG_RETURN_NULL();
2110 }
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
Definition: tupdesc.c:112
#define IsA(nodeptr, _type_)
Definition: nodes.h:567
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:541
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:367
int work_mem
Definition: globals.c:120
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:431
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 3893 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().

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

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

◆ get_array_element_start()

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

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

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

◆ get_array_end()

static void get_array_end ( void *  state)
static

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

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

◆ get_array_start()

static void get_array_start ( void *  state)
static

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

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

◆ get_json_object_as_hash()

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

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

3342 {
3343  HASHCTL ctl;
3344  HTAB *tab;
3345  JHashState *state;
3346  JsonLexContext *lex = makeJsonLexContextCstringLen(json, len, true);
3347  JsonSemAction *sem;
3348 
3349  memset(&ctl, 0, sizeof(ctl));
3350  ctl.keysize = NAMEDATALEN;
3351  ctl.entrysize = sizeof(JsonHashEntry);
3352  ctl.hcxt = CurrentMemoryContext;
3353  tab = hash_create("json object hashtable",
3354  100,
3355  &ctl,
3357 
3358  state = palloc0(sizeof(JHashState));
3359  sem = palloc0(sizeof(JsonSemAction));
3360 
3361  state->function_name = funcname;
3362  state->hash = tab;
3363  state->lex = lex;
3364 
3365  sem->semstate = (void *) state;
3367  sem->scalar = hash_scalar;
3370 
3371  pg_parse_json(lex, sem);
3372 
3373  return tab;
3374 }
#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:3401
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:132
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:3377
const char * function_name
Definition: jsonfuncs.c:131
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:130
static void hash_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:3461
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:3450

◆ get_jsonb_path_all()

static Datum get_jsonb_path_all ( FunctionCallInfo  fcinfo,
bool  as_text 
)
static

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

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

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

◆ get_object_field_end()

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

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

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

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

◆ get_object_start()

static void get_object_start ( void *  state)
static

Definition at line 1071 of file jsonfuncs.c.

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

Referenced by get_worker().

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

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

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

1020 {
1021  JsonLexContext *lex = makeJsonLexContext(json, true);
1022  JsonSemAction *sem = palloc0(sizeof(JsonSemAction));
1023  GetState *state = palloc0(sizeof(GetState));
1024 
1025  Assert(npath >= 0);
1026 
1027  state->lex = lex;
1028  /* is it "_as_text" variant? */
1029  state->normalize_results = normalize_results;
1030  state->npath = npath;
1031  state->path_names = tpath;
1032  state->path_indexes = ipath;
1033  state->pathok = palloc0(sizeof(bool) * npath);
1034  state->array_cur_index = palloc(sizeof(int) * npath);
1035 
1036  if (npath > 0)
1037  state->pathok[0] = true;
1038 
1039  sem->semstate = (void *) state;
1040 
1041  /*
1042  * Not all variants need all the semantic routines. Only set the ones that
1043  * are actually needed for maximum efficiency.
1044  */
1045  sem->scalar = get_scalar;
1046  if (npath == 0)
1047  {
1049  sem->object_end = get_object_end;
1051  sem->array_end = get_array_end;
1052  }
1053  if (tpath != NULL)
1054  {
1057  }
1058  if (ipath != NULL)
1059  {
1063  }
1064 
1065  pg_parse_json(lex, sem);
1066 
1067  return state->tresult;
1068 }
json_struct_action array_end
Definition: jsonapi.h:88
static void get_array_end(void *state)
Definition: jsonfuncs.c:1231
int * array_cur_index
Definition: jsonfuncs.c:89
static void get_array_element_start(void *state, bool isnull)
Definition: jsonfuncs.c:1247
json_struct_action object_end
Definition: jsonapi.h:86
static void get_object_start(void *state)
Definition: jsonfuncs.c:1071
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:1149
JsonLexContext * lex
Definition: jsonfuncs.c:80
static void get_object_end(void *state)
Definition: jsonfuncs.c:1088
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:81
int npath
Definition: jsonfuncs.c:85
json_ofield_action object_field_end
Definition: jsonapi.h:90
static void get_array_element_end(void *state, bool isnull)
Definition: jsonfuncs.c:1293
bool * pathok
Definition: jsonfuncs.c:88
bool normalize_results
Definition: jsonfuncs.c:83
static void get_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:1335
void * palloc0(Size size)
Definition: mcxt.c:955
static void get_array_start(void *state)
Definition: jsonfuncs.c:1198
json_aelem_action array_element_start
Definition: jsonapi.h:91
char ** path_names
Definition: jsonfuncs.c:86
#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:87
void * palloc(Size size)
Definition: mcxt.c:924
static void get_object_field_start(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:1104
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 3450 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().

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

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

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

◆ hash_scalar()

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

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

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

5090 {
5091  JsonLexContext *lex = makeJsonLexContext(json, true);
5092  JsonSemAction *sem = palloc0(sizeof(JsonSemAction));
5094 
5095  state->lex = lex;
5096  state->action = action;
5097  state->action_state = action_state;
5098  state->flags = flags;
5099 
5100  sem->semstate = (void *) state;
5103 
5104  pg_parse_json(lex, sem);
5105 }
JsonIterateStringValuesAction action
Definition: jsonfuncs.c:60
static void iterate_values_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:5112
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:5138
void * semstate
Definition: jsonapi.h:84

◆ iterate_jsonb_values()

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

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

5022 {
5023  JsonbIterator *it;
5024  JsonbValue v;
5026 
5027  it = JsonbIteratorInit(&jb->root);
5028 
5029  /*
5030  * Just recursively iterating over jsonb and call callback on all
5031  * correspoding elements
5032  */
5033  while ((type = JsonbIteratorNext(&it, &v, false)) != WJB_DONE)
5034  {
5035  if (type == WJB_KEY)
5036  {
5037  if (flags & jtiKey)
5038  action(state, v.val.string.val, v.val.string.len);
5039 
5040  continue;
5041  }
5042  else if (!(type == WJB_VALUE || type == WJB_ELEM))
5043  {
5044  /* do not call callback for composite JsonbValue */
5045  continue;
5046  }
5047 
5048  /* JsonbValue is a value of object or element of array */
5049  switch (v.type)
5050  {
5051  case jbvString:
5052  if (flags & jtiString)
5053  action(state, v.val.string.val, v.val.string.len);
5054  break;
5055  case jbvNumeric:
5056  if (flags & jtiNumeric)
5057  {
5058  char *val;
5059 
5061  NumericGetDatum(v.val.numeric)));
5062 
5063  action(state, val, strlen(val));
5064  pfree(val);
5065  }
5066  break;
5067  case jbvBool:
5068  if (flags & jtiBool)
5069  {
5070  if (v.val.boolean)
5071  action(state, "true", 4);
5072  else
5073  action(state, "false", 5);
5074  }
5075  break;
5076  default:
5077  /* do not call callback for composite JsonbValue */
5078  break;
5079  }
5080  }
5081 }
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:551
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 5138 of file jsonfuncs.c.

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

Referenced by iterate_json_values().

5139 {
5141 
5142  if (_state->flags & jtiKey)
5143  {
5144  char *val = pstrdup(fname);
5145 
5146  _state->action(_state->action_state, val, strlen(val));
5147  }
5148 }
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 5112 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().

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

◆ IteratorConcat()

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

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

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

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

◆ json_array_element()

Datum json_array_element ( PG_FUNCTION_ARGS  )

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

804 {
805  text *json = PG_GETARG_TEXT_PP(0);
806  int element = PG_GETARG_INT32(1);
807  text *result;
808 
809  result = get_worker(json, NULL, &element, 1, false);
810 
811  if (result != NULL)
812  PG_RETURN_TEXT_P(result);
813  else
814  PG_RETURN_NULL();
815 }
#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:1015
#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 846 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.

847 {
848  text *json = PG_GETARG_TEXT_PP(0);
849  int element = PG_GETARG_INT32(1);
850  text *result;
851 
852  result = get_worker(json, NULL, &element, 1, true);
853 
854  if (result != NULL)
855  PG_RETURN_TEXT_P(result);
856  else
857  PG_RETURN_NULL();
858 }
#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:1015
#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 2113 of file jsonfuncs.c.

References elements_worker().

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

◆ json_array_elements_text()

Datum json_array_elements_text ( PG_FUNCTION_ARGS  )

Definition at line 2119 of file jsonfuncs.c.

References elements_worker().

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

◆ json_array_length()

Datum json_array_length ( PG_FUNCTION_ARGS  )

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

1557 {
1558  text *json = PG_GETARG_TEXT_PP(0);
1559  AlenState *state;
1560  JsonLexContext *lex;
1561  JsonSemAction *sem;
1562 
1563  lex = makeJsonLexContext(json, false);
1564  state = palloc0(sizeof(AlenState));
1565  sem = palloc0(sizeof(JsonSemAction));
1566 
1567  /* palloc0 does this for us */
1568 #if 0
1569  state->count = 0;
1570 #endif
1571  state->lex = lex;
1572 
1573  sem->semstate = (void *) state;
1575  sem->scalar = alen_scalar;
1577 
1578  pg_parse_json(lex, sem);
1579 
1580  PG_RETURN_INT32(state->count);
1581 }
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:97
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:278
static void alen_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:1618
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:96
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:1606
Definition: c.h:516
static void alen_array_element_start(void *state, bool isnull)
Definition: jsonfuncs.c:1630
void * semstate
Definition: jsonapi.h:84

◆ json_each()

Datum json_each ( PG_FUNCTION_ARGS  )

Definition at line 1650 of file jsonfuncs.c.

References each_worker().

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

◆ json_each_text()

Datum json_each_text ( PG_FUNCTION_ARGS  )

Definition at line 1662 of file jsonfuncs.c.

References each_worker().

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

◆ json_extract_path()

Datum json_extract_path ( PG_FUNCTION_ARGS  )

Definition at line 920 of file jsonfuncs.c.

References get_path_all().

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

◆ json_extract_path_text()

Datum json_extract_path_text ( PG_FUNCTION_ARGS  )

Definition at line 926 of file jsonfuncs.c.

References get_path_all().

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

◆ json_object_field()

Datum json_object_field ( PG_FUNCTION_ARGS  )

Definition at line 700 of file jsonfuncs.c.

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

701 {
702  text *json = PG_GETARG_TEXT_PP(0);
703  text *fname = PG_GETARG_TEXT_PP(1);
704  char *fnamestr = text_to_cstring(fname);
705  text *result;
706 
707  result = get_worker(json, &fnamestr, NULL, 1, false);
708 
709  if (result != NULL)
710  PG_RETURN_TEXT_P(result);
711  else
712  PG_RETURN_NULL();
713 }
#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:1015
#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 736 of file jsonfuncs.c.

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

737 {
738  text *json = PG_GETARG_TEXT_PP(0);
739  text *fname = PG_GETARG_TEXT_PP(1);
740  char *fnamestr = text_to_cstring(fname);
741  text *result;
742 
743  result = get_worker(json, &fnamestr, NULL, 1, true);
744 
745  if (result != NULL)
746  PG_RETURN_TEXT_P(result);
747  else
748  PG_RETURN_NULL();
749 }
#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:1015
#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 583 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.

584 {
585  FuncCallContext *funcctx;
586  OkeysState *state;
587  int i;
588 
589  if (SRF_IS_FIRSTCALL())
590  {
591  text *json = PG_GETARG_TEXT_PP(0);
592  JsonLexContext *lex = makeJsonLexContext(json, true);
593  JsonSemAction *sem;
594  MemoryContext oldcontext;
595 
596  funcctx = SRF_FIRSTCALL_INIT();
597  oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
598 
599  state = palloc(sizeof(OkeysState));
600  sem = palloc0(sizeof(JsonSemAction));
601 
602  state->lex = lex;
603  state->result_size = 256;
604  state->result_count = 0;
605  state->sent_count = 0;
606  state->result = palloc(256 * sizeof(char *));
607 
608  sem->semstate = (void *) state;
610  sem->scalar = okeys_scalar;
612  /* remainder are all NULL, courtesy of palloc0 above */
613 
614  pg_parse_json(lex, sem);
615  /* keys are now in state->result */
616 
617  pfree(lex->strval->data);
618  pfree(lex->strval);
619  pfree(lex);
620  pfree(sem);
621 
622  MemoryContextSwitchTo(oldcontext);
623  funcctx->user_fctx = (void *) state;
624  }
625 
626  funcctx = SRF_PERCALL_SETUP();
627  state = (OkeysState *) funcctx->user_fctx;
628 
629  if (state->sent_count < state->result_count)
630  {
631  char *nxt = state->result[state->sent_count++];
632 
633  SRF_RETURN_NEXT(funcctx, CStringGetTextDatum(nxt));
634  }
635 
636  /* cleanup to reduce or eliminate memory leaks */
637  for (i = 0; i < state->result_count; i++)
638  pfree(state->result[i]);
639  pfree(state->result);
640  pfree(state);
641 
642  SRF_RETURN_DONE(funcctx);
643 }
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:667
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:646
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:680
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 2309 of file jsonfuncs.c.

References populate_record_worker().

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

◆ json_populate_recordset()

Datum json_populate_recordset ( PG_FUNCTION_ARGS  )

Definition at line 3502 of file jsonfuncs.c.

References populate_recordset_worker().

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

◆ json_strip_nulls()

Datum json_strip_nulls ( PG_FUNCTION_ARGS  )

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

4006 {
4007  text *json = PG_GETARG_TEXT_PP(0);
4009  JsonLexContext *lex;
4010  JsonSemAction *sem;
4011 
4012  lex = makeJsonLexContext(json, true);
4013  state = palloc0(sizeof(StripnullState));
4014  sem = palloc0(sizeof(JsonSemAction));
4015 
4016  state->strval = makeStringInfo();
4017  state->skip_next_null = false;
4018  state->lex = lex;
4019 
4020  sem->semstate = (void *) state;
4022  sem->object_end = sn_object_end;
4023  sem->array_start = sn_array_start;
4024  sem->array_end = sn_array_end;
4025  sem->scalar = sn_scalar;
4028 
4029  pg_parse_json(lex, sem);
4030 
4032  state->strval->len));
4033 
4034 }
json_struct_action array_end
Definition: jsonapi.h:88
bool skip_next_null
Definition: jsonfuncs.c:286
static void sn_object_start(void *state)
Definition: jsonfuncs.c:3915
json_struct_action object_end
Definition: jsonapi.h:86
static void sn_array_element_start(void *state, bool isnull)
Definition: jsonfuncs.c:3975
static void sn_object_field_start(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:3947
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:3931
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:284
static void sn_object_end(void *state)
Definition: jsonfuncs.c:3923
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:3984
#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:285
Definition: c.h:516
json_ofield_action object_field_start
Definition: jsonapi.h:89
static void sn_array_end(void *state)
Definition: jsonfuncs.c:3939
void * semstate
Definition: jsonapi.h:84

◆ json_to_record()

Datum json_to_record ( PG_FUNCTION_ARGS  )

Definition at line 2315 of file jsonfuncs.c.

References populate_record_worker().

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

◆ json_to_recordset()

Datum json_to_recordset ( PG_FUNCTION_ARGS  )

Definition at line 3508 of file jsonfuncs.c.

References populate_recordset_worker().

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

◆ jsonb_array_element()

Datum jsonb_array_element ( PG_FUNCTION_ARGS  )

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

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

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

References elements_worker_jsonb().

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

◆ jsonb_array_elements_text()

Datum jsonb_array_elements_text ( PG_FUNCTION_ARGS  )

Definition at line 1983 of file jsonfuncs.c.

References elements_worker_jsonb().

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

◆ jsonb_array_length()

Datum jsonb_array_length ( PG_FUNCTION_ARGS  )

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

1585 {
1586  Jsonb *jb = PG_GETARG_JSONB_P(0);
1587 
1588  if (JB_ROOT_IS_SCALAR(jb))
1589  ereport(ERROR,
1590  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1591  errmsg("cannot get array length of a scalar")));
1592  else if (!JB_ROOT_IS_ARRAY(jb))
1593  ereport(ERROR,
1594  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1595  errmsg("cannot get array length of a non-array")));
1596 
1598 }
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 4166 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.

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

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

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

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

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

References each_worker_jsonb().

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

◆ jsonb_each_text()

Datum jsonb_each_text ( PG_FUNCTION_ARGS  )

Definition at line 1668 of file jsonfuncs.c.

References each_worker_jsonb().

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

◆ jsonb_extract_path()

Datum jsonb_extract_path ( PG_FUNCTION_ARGS  )

Definition at line 1376 of file jsonfuncs.c.

References get_jsonb_path_all().

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

◆ jsonb_extract_path_text()

Datum jsonb_extract_path_text ( PG_FUNCTION_ARGS  )

Definition at line 1382 of file jsonfuncs.c.

References get_jsonb_path_all().

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

◆ jsonb_insert()

Datum jsonb_insert (