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  PopulateRecordCache
 
struct  PopulateRecordsetState
 
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 PopulateRecordCache PopulateRecordCache
 
typedef struct PopulateRecordsetState PopulateRecordsetState
 
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 is_json, bool have_record_arg)
 
static Datum populate_record_worker (FunctionCallInfo fcinfo, const char *funcname, bool is_json, bool have_record_arg)
 
static HeapTupleHeader populate_record (TupleDesc tupdesc, RecordIOData **record_p, HeapTupleHeader defaultval, MemoryContext mcxt, JsObject *obj)
 
static void get_record_type_from_argument (FunctionCallInfo fcinfo, const char *funcname, PopulateRecordCache *cache)
 
static void get_record_type_from_query (FunctionCallInfo fcinfo, const char *funcname, PopulateRecordCache *cache)
 
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:684

Definition at line 325 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:684

Definition at line 319 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:236
long val
Definition: informix.c:684

Definition at line 310 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:684

Definition at line 315 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

◆ 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 4126 of file jsonfuncs.c.

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

Referenced by setPathArray(), and setPathObject().

4127 {
4128  JsonbIterator *it;
4129  JsonbValue *o = &(*jbps)->contVal;
4130  JsonbValue v;
4132 
4133  it = JsonbIteratorInit(&jb->root);
4134 
4135  Assert(o->type == jbvArray || o->type == jbvObject);
4136 
4137  if (JB_ROOT_IS_SCALAR(jb))
4138  {
4139  (void) JsonbIteratorNext(&it, &v, false); /* skip array header */
4140  Assert(v.type == jbvArray);
4141  (void) JsonbIteratorNext(&it, &v, false); /* fetch scalar value */
4142 
4143  switch (o->type)
4144  {
4145  case jbvArray:
4146  (void) pushJsonbValue(jbps, WJB_ELEM, &v);
4147  break;
4148  case jbvObject:
4149  (void) pushJsonbValue(jbps, WJB_VALUE, &v);
4150  break;
4151  default:
4152  elog(ERROR, "unexpected parent of nested structure");
4153  }
4154  }
4155  else
4156  {
4157  while ((type = JsonbIteratorNext(&it, &v, false)) != WJB_DONE)
4158  {
4159  if (type == WJB_KEY || type == WJB_VALUE || type == WJB_ELEM)
4160  (void) pushJsonbValue(jbps, type, &v);
4161  else
4162  (void) pushJsonbValue(jbps, type, NULL);
4163  }
4164  }
4165 
4166 }
Definition: jsonb.h:22
#define JB_ROOT_IS_SCALAR(jbp_)
Definition: jsonb.h:228
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:223
#define Assert(condition)
Definition: c.h:732
JsonbIterator * JsonbIteratorInit(JsonbContainer *container)
Definition: jsonb_util.c:718
enum jbvType type
Definition: jsonb.h:255
#define elog(elevel,...)
Definition: elog.h:226
JsonbIteratorToken JsonbIteratorNext(JsonbIterator **it, JsonbValue *val, bool skipNested)
Definition: jsonb_util.c:754
Definition: jsonb.h:25

◆ alen_array_element_start()

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

Definition at line 1629 of file jsonfuncs.c.

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

Referenced by json_array_length().

1630 {
1631  AlenState *_state = (AlenState *) state;
1632 
1633  /* just count up all the level 1 elements */
1634  if (_state->lex->lex_level == 1)
1635  _state->count++;
1636 }
int count
Definition: jsonfuncs.c: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 1605 of file jsonfuncs.c.

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

Referenced by json_array_length().

1606 {
1607  AlenState *_state = (AlenState *) state;
1608 
1609  /* json structure check */
1610  if (_state->lex->lex_level == 0)
1611  ereport(ERROR,
1612  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1613  errmsg("cannot get array length of a non-array")));
1614 }
int errcode(int sqlerrcode)
Definition: elog.c:570
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:141
Definition: regguts.h:298
int errmsg(const char *fmt,...)
Definition: elog.c:784

◆ alen_scalar()

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

Definition at line 1617 of file jsonfuncs.c.

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

Referenced by json_array_length().

1618 {
1619  AlenState *_state = (AlenState *) state;
1620 
1621  /* json structure check */
1622  if (_state->lex->lex_level == 0)
1623  ereport(ERROR,
1624  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1625  errmsg("cannot get array length of a scalar")));
1626 }
int errcode(int sqlerrcode)
Definition: elog.c:570
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:141
Definition: regguts.h:298
int errmsg(const char *fmt,...)
Definition: elog.c:784

◆ allocate_record_info()

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

Definition at line 3053 of file jsonfuncs.c.

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

Referenced by populate_record().

3054 {
3055  RecordIOData *data = (RecordIOData *)
3056  MemoryContextAlloc(mcxt,
3057  offsetof(RecordIOData, columns) +
3058  ncolumns * sizeof(ColumnIOData));
3059 
3060  data->record_type = InvalidOid;
3061  data->record_typmod = 0;
3062  data->ncolumns = ncolumns;
3063  MemSet(data->columns, 0, sizeof(ColumnIOData) * ncolumns);
3064 
3065  return data;
3066 }
Oid record_type
Definition: hstore_io.c:754
struct ColumnIOData ColumnIOData
Definition: jsonfuncs.c:154
#define MemSet(start, val, len)
Definition: c.h:955
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:655

◆ each_array_start()

static void each_array_start ( void *  state)
static

Definition at line 1940 of file jsonfuncs.c.

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

Referenced by each_worker().

1941 {
1942  EachState *_state = (EachState *) state;
1943 
1944  /* json structure check */
1945  if (_state->lex->lex_level == 0)
1946  ereport(ERROR,
1947  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1948  errmsg("cannot deconstruct an array as an object")));
1949 }
int errcode(int sqlerrcode)
Definition: elog.c:570
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:141
Definition: regguts.h:298
int errmsg(const char *fmt,...)
Definition: elog.c:784

◆ each_object_field_end()

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

Definition at line 1894 of file jsonfuncs.c.

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

Referenced by each_worker().

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

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

Referenced by each_worker().

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

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

Referenced by each_worker().

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

◆ each_worker()

static Datum each_worker ( FunctionCallInfo  fcinfo,
bool  as_text 
)
static

Definition at line 1810 of file jsonfuncs.c.

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

Referenced by json_each(), and json_each_text().

1811 {
1812  text *json = PG_GETARG_TEXT_PP(0);
1813  JsonLexContext *lex;
1814  JsonSemAction *sem;
1815  ReturnSetInfo *rsi;
1816  MemoryContext old_cxt;
1817  TupleDesc tupdesc;
1818  EachState *state;
1819 
1820  lex = makeJsonLexContext(json, true);
1821  state = palloc0(sizeof(EachState));
1822  sem = palloc0(sizeof(JsonSemAction));
1823 
1824  rsi = (ReturnSetInfo *) fcinfo->resultinfo;
1825 
1826  if (!rsi || !IsA(rsi, ReturnSetInfo) ||
1827  (rsi->allowedModes & SFRM_Materialize) == 0 ||
1828  rsi->expectedDesc == NULL)
1829  ereport(ERROR,
1830  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1831  errmsg("set-valued function called in context that "
1832  "cannot accept a set")));
1833 
1835 
1836  (void) get_call_result_type(fcinfo, NULL, &tupdesc);
1837 
1838  /* make these in a sufficiently long-lived memory context */
1840 
1841  state->ret_tdesc = CreateTupleDescCopy(tupdesc);
1842  BlessTupleDesc(state->ret_tdesc);
1843  state->tuple_store =
1845  false, work_mem);
1846 
1847  MemoryContextSwitchTo(old_cxt);
1848 
1849  sem->semstate = (void *) state;
1851  sem->scalar = each_scalar;
1854 
1855  state->normalize_results = as_text;
1856  state->next_scalar = false;
1857  state->lex = lex;
1859  "json_each temporary cxt",
1861 
1862  pg_parse_json(lex, sem);
1863 
1864  MemoryContextDelete(state->tmp_cxt);
1865 
1866  rsi->setResult = state->tuple_store;
1867  rsi->setDesc = state->ret_tdesc;
1868 
1869  PG_RETURN_NULL();
1870 }
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
Definition: tupdesc.c:110
#define IsA(nodeptr, _type_)
Definition: nodes.h:575
Tuplestorestate * tuple_store
Definition: jsonfuncs.c:104
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:211
#define AllocSetContextCreate
Definition: memutils.h:169
static void each_object_field_start(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:1874
TypeFuncClass get_call_result_type(FunctionCallInfo fcinfo, Oid *resultTypeId, TupleDesc *resultTupleDesc)
Definition: funcapi.c:196
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
int errcode(int sqlerrcode)
Definition: elog.c:570
json_scalar_action scalar
Definition: jsonapi.h:93
static void each_array_start(void *state)
Definition: jsonfuncs.c:1940
TupleDesc ret_tdesc
Definition: jsonfuncs.c:105
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:303
MemoryContext tmp_cxt
Definition: jsonfuncs.c:106
static void each_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:1952
TupleDesc expectedDesc
Definition: execnodes.h:302
JsonLexContext * makeJsonLexContext(text *json, bool need_escapes)
Definition: json.c:301
#define ERROR
Definition: elog.h:43
fmNodePtr resultinfo
Definition: fmgr.h:89
void pg_parse_json(JsonLexContext *lex, JsonSemAction *sem)
Definition: json.c:332
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:191
JsonLexContext * lex
Definition: jsonfuncs.c:103
TupleDesc BlessTupleDesc(TupleDesc tupdesc)
Definition: execTuples.c:2048
MemoryContext CurrentMemoryContext
Definition: mcxt.c:38
#define ereport(elevel, rest)
Definition: elog.h:141
json_ofield_action object_field_end
Definition: jsonapi.h:90
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:121
int allowedModes
Definition: execnodes.h:303
SetFunctionReturnMode returnMode
Definition: execnodes.h:305
json_struct_action array_start
Definition: jsonapi.h:87
Definition: regguts.h:298
MemoryContext ecxt_per_query_memory
Definition: execnodes.h:231
Tuplestorestate * setResult
Definition: execnodes.h:308
ExprContext * econtext
Definition: execnodes.h:301
TupleDesc setDesc
Definition: execnodes.h:309
int errmsg(const char *fmt,...)
Definition: elog.c:784
Definition: c.h:549
json_ofield_action object_field_start
Definition: jsonapi.h:89
void * semstate
Definition: jsonapi.h:84
static void each_object_field_end(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:1894
#define PG_RETURN_NULL()
Definition: fmgr.h:335
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 1673 of file jsonfuncs.c.

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

Referenced by jsonb_each(), and jsonb_each_text().

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

◆ elements_array_element_end()

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

Definition at line 2210 of file jsonfuncs.c.

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

Referenced by elements_worker().

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

◆ elements_array_element_start()

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

Definition at line 2190 of file jsonfuncs.c.

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

Referenced by elements_worker().

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

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

Referenced by elements_worker().

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

◆ elements_scalar()

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

Definition at line 2267 of file jsonfuncs.c.

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

Referenced by elements_worker().

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

◆ elements_worker()

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

Definition at line 2124 of file jsonfuncs.c.

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

Referenced by json_array_elements(), and json_array_elements_text().

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

◆ elements_worker_jsonb()

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

Definition at line 1988 of file jsonfuncs.c.

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

Referenced by jsonb_array_elements(), and jsonb_array_elements_text().

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

◆ findJsonbValueFromContainerLen()

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

Definition at line 3917 of file jsonfuncs.c.

References findJsonbValueFromContainer(), jbvString, sort-test::key, JsonbValue::type, and JsonbValue::val.

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

3919 {
3920  JsonbValue k;
3921 
3922  k.type = jbvString;
3923  k.val.string.val = key;
3924  k.val.string.len = keylen;
3925 
3926  return findJsonbValueFromContainer(container, flags, &k);
3927 }
char * val
Definition: jsonb.h:264
enum jbvType type
Definition: jsonb.h:255
JsonbValue * findJsonbValueFromContainer(JsonbContainer *container, uint32 flags, JsonbValue *key)
Definition: jsonb_util.c:327

◆ get_array_element_end()

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

Definition at line 1292 of file jsonfuncs.c.

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

Referenced by get_worker().

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

◆ get_array_element_start()

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

Definition at line 1246 of file jsonfuncs.c.

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

Referenced by get_worker().

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

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

Referenced by get_worker().

1231 {
1232  GetState *_state = (GetState *) state;
1233  int lex_level = _state->lex->lex_level;
1234 
1235  if (lex_level == 0 && _state->npath == 0)
1236  {
1237  /* Special case: return the entire array */
1238  char *start = _state->result_start;
1239  int len = _state->lex->prev_token_terminator - start;
1240 
1241  _state->tresult = cstring_to_text_with_len(start, len);
1242  }
1243 }
char * prev_token_terminator
Definition: jsonapi.h:57
int lex_level
Definition: jsonapi.h:59
JsonLexContext * lex
Definition: jsonfuncs.c: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:183
int npath
Definition: jsonfuncs.c:85
Definition: regguts.h:298

◆ get_array_start()

static void get_array_start ( void *  state)
static

Definition at line 1197 of file jsonfuncs.c.

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

Referenced by get_worker().

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

3379 {
3380  HASHCTL ctl;
3381  HTAB *tab;
3382  JHashState *state;
3383  JsonLexContext *lex = makeJsonLexContextCstringLen(json, len, true);
3384  JsonSemAction *sem;
3385 
3386  memset(&ctl, 0, sizeof(ctl));
3387  ctl.keysize = NAMEDATALEN;
3388  ctl.entrysize = sizeof(JsonHashEntry);
3389  ctl.hcxt = CurrentMemoryContext;
3390  tab = hash_create("json object hashtable",
3391  100,
3392  &ctl,
3394 
3395  state = palloc0(sizeof(JHashState));
3396  sem = palloc0(sizeof(JsonSemAction));
3397 
3398  state->function_name = funcname;
3399  state->hash = tab;
3400  state->lex = lex;
3401 
3402  sem->semstate = (void *) state;
3404  sem->scalar = hash_scalar;
3407 
3408  pg_parse_json(lex, sem);
3409 
3410  return tab;
3411 }
#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:3438
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:3414
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:3498
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:3487

◆ get_jsonb_path_all()

static Datum get_jsonb_path_all ( FunctionCallInfo  fcinfo,
bool  as_text 
)
static

Definition at line 1387 of file jsonfuncs.c.

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

Referenced by jsonb_extract_path(), and jsonb_extract_path_text().

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

◆ get_object_end()

static void get_object_end ( void *  state)
static

Definition at line 1087 of file jsonfuncs.c.

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

Referenced by get_worker().

1088 {
1089  GetState *_state = (GetState *) state;
1090  int lex_level = _state->lex->lex_level;
1091 
1092  if (lex_level == 0 && _state->npath == 0)
1093  {
1094  /* Special case: return the entire object */
1095  char *start = _state->result_start;
1096  int len = _state->lex->prev_token_terminator - start;
1097 
1098  _state->tresult = cstring_to_text_with_len(start, len);
1099  }
1100 }
char * prev_token_terminator
Definition: jsonapi.h:57
int lex_level
Definition: jsonapi.h:59
JsonLexContext * lex
Definition: jsonfuncs.c: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:183
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 1148 of file jsonfuncs.c.

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

Referenced by get_worker().

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

◆ get_object_field_start()

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

Definition at line 1103 of file jsonfuncs.c.

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

Referenced by get_worker().

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

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

Referenced by get_worker().

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

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

Referenced by json_extract_path(), and json_extract_path_text().

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

◆ get_record_type_from_argument()

static void get_record_type_from_argument ( FunctionCallInfo  fcinfo,
const char *  funcname,
PopulateRecordCache cache 
)
static

Definition at line 3210 of file jsonfuncs.c.

References PopulateRecordCache::argtype, PopulateRecordCache::c, ereport, errcode(), errmsg(), ERROR, FunctionCallInfoBaseData::flinfo, PopulateRecordCache::fn_mcxt, get_fn_expr_argtype(), prepare_column_cache(), ColumnIOData::typcat, TYPECAT_COMPOSITE, and TYPECAT_COMPOSITE_DOMAIN.

Referenced by populate_record_worker(), and populate_recordset_worker().

3213 {
3214  cache->argtype = get_fn_expr_argtype(fcinfo->flinfo, 0);
3215  prepare_column_cache(&cache->c,
3216  cache->argtype, -1,
3217  cache->fn_mcxt, false);
3218  if (cache->c.typcat != TYPECAT_COMPOSITE &&
3219  cache->c.typcat != TYPECAT_COMPOSITE_DOMAIN)
3220  ereport(ERROR,
3221  (errcode(ERRCODE_DATATYPE_MISMATCH),
3222  /* translator: %s is a function name, eg json_to_record */
3223  errmsg("first argument of %s must be a row type",
3224  funcname)));
3225 }
static void prepare_column_cache(ColumnIOData *column, Oid typid, int32 typmod, MemoryContext mcxt, bool need_scalar)
Definition: jsonfuncs.c:2901
int errcode(int sqlerrcode)
Definition: elog.c:570
#define ERROR
Definition: elog.h:43
Oid get_fn_expr_argtype(FmgrInfo *flinfo, int argnum)
Definition: fmgr.c:1817
ColumnIOData c
Definition: jsonfuncs.c:232
#define ereport(elevel, rest)
Definition: elog.h:141
FmgrInfo * flinfo
Definition: fmgr.h:87
MemoryContext fn_mcxt
Definition: jsonfuncs.c:233
int errmsg(const char *fmt,...)
Definition: elog.c:784
TypeCat typcat
Definition: jsonfuncs.c:207

◆ get_record_type_from_query()

static void get_record_type_from_query ( FunctionCallInfo  fcinfo,
const char *  funcname,
PopulateRecordCache cache 
)
static

Definition at line 3236 of file jsonfuncs.c.

References PopulateRecordCache::argtype, Assert, CompositeIOData::base_typid, CompositeIOData::base_typmod, PopulateRecordCache::c, ColumnIOData::composite, CreateTupleDescCopy(), ereport, errcode(), errhint(), errmsg(), ERROR, PopulateRecordCache::fn_mcxt, FreeTupleDesc(), get_call_result_type(), ColumnIOData::io, MemoryContextSwitchTo(), TupleDescData::tdtypeid, TupleDescData::tdtypmod, CompositeIOData::tupdesc, and TYPEFUNC_COMPOSITE.

Referenced by populate_record_worker(), and populate_recordset_worker().

3239 {
3240  TupleDesc tupdesc;
3241  MemoryContext old_cxt;
3242 
3243  if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
3244  ereport(ERROR,
3245  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3246  /* translator: %s is a function name, eg json_to_record */
3247  errmsg("could not determine row type for result of %s",
3248  funcname),
3249  errhint("Provide a non-null record argument, "
3250  "or call the function in the FROM clause "
3251  "using a column definition list.")));
3252 
3253  Assert(tupdesc);
3254  cache->argtype = tupdesc->tdtypeid;
3255 
3256  /* If we go through this more than once, avoid memory leak */
3257  if (cache->c.io.composite.tupdesc)
3259 
3260  /* Save identified tupdesc */
3261  old_cxt = MemoryContextSwitchTo(cache->fn_mcxt);
3262  cache->c.io.composite.tupdesc = CreateTupleDescCopy(tupdesc);
3263  cache->c.io.composite.base_typid = tupdesc->tdtypeid;
3264  cache->c.io.composite.base_typmod = tupdesc->tdtypmod;
3265  MemoryContextSwitchTo(old_cxt);
3266 }
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
Definition: tupdesc.c:110
TypeFuncClass get_call_result_type(FunctionCallInfo fcinfo, Oid *resultTypeId, TupleDesc *resultTupleDesc)
Definition: funcapi.c:196
int errhint(const char *fmt,...)
Definition: elog.c:974
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
int errcode(int sqlerrcode)
Definition: elog.c:570
int32 base_typmod
Definition: jsonfuncs.c:176
#define ERROR
Definition: elog.h:43
int32 tdtypmod
Definition: tupdesc.h:83
ColumnIOData c
Definition: jsonfuncs.c:232
#define ereport(elevel, rest)
Definition: elog.h:141
#define Assert(condition)
Definition: c.h:732
MemoryContext fn_mcxt
Definition: jsonfuncs.c:233
union ColumnIOData::@29 io
void FreeTupleDesc(TupleDesc tupdesc)
Definition: tupdesc.c:313
Oid tdtypeid
Definition: tupdesc.h:82
int errmsg(const char *fmt,...)
Definition: elog.c:784
TupleDesc tupdesc
Definition: jsonfuncs.c:173
CompositeIOData composite
Definition: jsonfuncs.c:213

◆ get_scalar()

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

Definition at line 1334 of file jsonfuncs.c.

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

Referenced by get_worker().

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

◆ get_worker()

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

Definition at line 1014 of file jsonfuncs.c.

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

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

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

◆ hash_array_start()

static void hash_array_start ( void *  state)
static

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

3488 {
3489  JHashState *_state = (JHashState *) state;
3490 
3491  if (_state->lex->lex_level == 0)
3492  ereport(ERROR,
3493  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3494  errmsg("cannot call %s on an array", _state->function_name)));
3495 }
int errcode(int sqlerrcode)
Definition: elog.c:570
int lex_level
Definition: jsonapi.h:59
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:141
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:784

◆ hash_object_field_end()

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

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

3439 {
3440  JHashState *_state = (JHashState *) state;
3441  JsonHashEntry *hashentry;
3442  bool found;
3443 
3444  /*
3445  * Ignore nested fields.
3446  */
3447  if (_state->lex->lex_level > 1)
3448  return;
3449 
3450  /*
3451  * Ignore field names >= NAMEDATALEN - they can't match a record field.
3452  * (Note: without this test, the hash code would truncate the string at
3453  * NAMEDATALEN-1, and could then match against a similarly-truncated
3454  * record field name. That would be a reasonable behavior, but this code
3455  * has previously insisted on exact equality, so we keep this behavior.)
3456  */
3457  if (strlen(fname) >= NAMEDATALEN)
3458  return;
3459 
3460  hashentry = hash_search(_state->hash, fname, HASH_ENTER, &found);
3461 
3462  /*
3463  * found being true indicates a duplicate. We don't do anything about
3464  * that, a later field with the same name overrides the earlier field.
3465  */
3466 
3467  hashentry->type = _state->saved_token_type;
3468  Assert(isnull == (hashentry->type == JSON_TOKEN_NULL));
3469 
3470  if (_state->save_json_start != NULL)
3471  {
3472  int len = _state->lex->prev_token_terminator - _state->save_json_start;
3473  char *val = palloc((len + 1) * sizeof(char));
3474 
3475  memcpy(val, _state->save_json_start, len);
3476  val[len] = '\0';
3477  hashentry->val = val;
3478  }
3479  else
3480  {
3481  /* must have had a scalar instead */
3482  hashentry->val = _state->saved_scalar;
3483  }
3484 }
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:732
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:684

◆ hash_object_field_start()

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

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

3415 {
3416  JHashState *_state = (JHashState *) state;
3417 
3418  if (_state->lex->lex_level > 1)
3419  return;
3420 
3421  /* remember token type */
3422  _state->saved_token_type = _state->lex->token_type;
3423 
3424  if (_state->lex->token_type == JSON_TOKEN_ARRAY_START ||
3426  {
3427  /* remember start position of the whole text of the subobject */
3428  _state->save_json_start = _state->lex->token_start;
3429  }
3430  else
3431  {
3432  /* must be a scalar */
3433  _state->save_json_start = NULL;
3434  }
3435 }
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 3498 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().

3499 {
3500  JHashState *_state = (JHashState *) state;
3501 
3502  if (_state->lex->lex_level == 0)
3503  ereport(ERROR,
3504  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3505  errmsg("cannot call %s on a scalar", _state->function_name)));
3506 
3507  if (_state->lex->lex_level == 1)
3508  {
3509  _state->saved_scalar = token;
3510  /* saved_token_type must already be set in hash_object_field_start() */
3511  Assert(_state->saved_token_type == tokentype);
3512  }
3513 }
int errcode(int sqlerrcode)
Definition: elog.c:570
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:141
const char * function_name
Definition: jsonfuncs.c:131
#define Assert(condition)
Definition: c.h:732
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:784

◆ iterate_json_values()

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

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

5114 {
5115  JsonLexContext *lex = makeJsonLexContext(json, true);
5116  JsonSemAction *sem = palloc0(sizeof(JsonSemAction));
5118 
5119  state->lex = lex;
5120  state->action = action;
5121  state->action_state = action_state;
5122  state->flags = flags;
5123 
5124  sem->semstate = (void *) state;
5127 
5128  pg_parse_json(lex, sem);
5129 }
JsonIterateStringValuesAction action
Definition: jsonfuncs.c:60
static void iterate_values_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:5136
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:5162
void * semstate
Definition: jsonapi.h:84

◆ iterate_jsonb_values()

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

Definition at line 5044 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, JsonbValue::type, generate_unaccent_rules::type, JsonbValue::val, val, WJB_DONE, WJB_ELEM, WJB_KEY, and WJB_VALUE.

Referenced by jsonb_to_tsvector_worker().

5046 {
5047  JsonbIterator *it;
5048  JsonbValue v;
5050 
5051  it = JsonbIteratorInit(&jb->root);
5052 
5053  /*
5054  * Just recursively iterating over jsonb and call callback on all
5055  * corresponding elements
5056  */
5057  while ((type = JsonbIteratorNext(&it, &v, false)) != WJB_DONE)
5058  {
5059  if (type == WJB_KEY)
5060  {
5061  if (flags & jtiKey)
5062  action(state, v.val.string.val, v.val.string.len);
5063 
5064  continue;
5065  }
5066  else if (!(type == WJB_VALUE || type == WJB_ELEM))
5067  {
5068  /* do not call callback for composite JsonbValue */
5069  continue;
5070  }
5071 
5072  /* JsonbValue is a value of object or element of array */
5073  switch (v.type)
5074  {
5075  case jbvString:
5076  if (flags & jtiString)
5077  action(state, v.val.string.val, v.val.string.len);
5078  break;
5079  case jbvNumeric:
5080  if (flags & jtiNumeric)
5081  {
5082  char *val;
5083 
5085  NumericGetDatum(v.val.numeric)));
5086 
5087  action(state, val, strlen(val));
5088  pfree(val);
5089  }
5090  break;
5091  case jbvBool:
5092  if (flags & jtiBool)
5093  {
5094  if (v.val.boolean)
5095  action(state, "true", 4);
5096  else
5097  action(state, "false", 5);
5098  }
5099  break;
5100  default:
5101  /* do not call callback for composite JsonbValue */
5102  break;
5103  }
5104  }
5105 }
char * val
Definition: jsonb.h:264
#define NumericGetDatum(X)
Definition: numeric.h:51
Definition: jsonb.h:239
Datum numeric_out(PG_FUNCTION_ARGS)
Definition: numeric.c:655
Definition: jsonb.h:22
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:616
void pfree(void *pointer)
Definition: mcxt.c:1031
#define DatumGetCString(X)
Definition: postgres.h:566
Definition: jsonb.h:23
JsonbIteratorToken
Definition: jsonb.h:20
JsonbContainer root
Definition: jsonb.h:223
JsonbIterator * JsonbIteratorInit(JsonbContainer *container)
Definition: jsonb_util.c:718
Definition: regguts.h:298
enum jbvType type
Definition: jsonb.h:255
long val
Definition: informix.c:684
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 5162 of file jsonfuncs.c.

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

Referenced by iterate_json_values().

5163 {
5165 
5166  if (_state->flags & jtiKey)
5167  {
5168  char *val = pstrdup(fname);
5169 
5170  _state->action(_state->action_state, val, strlen(val));
5171  }
5172 }
JsonIterateStringValuesAction action
Definition: jsonfuncs.c:60
char * pstrdup(const char *in)
Definition: mcxt.c:1161
Definition: regguts.h:298
long val
Definition: informix.c:684

◆ iterate_values_scalar()

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

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

5137 {
5139 
5140  switch (tokentype)
5141  {
5142  case JSON_TOKEN_STRING:
5143  if (_state->flags & jtiString)
5144  _state->action(_state->action_state, token, strlen(token));
5145  break;
5146  case JSON_TOKEN_NUMBER:
5147  if (_state->flags & jtiNumeric)
5148  _state->action(_state->action_state, token, strlen(token));
5149  break;
5150  case JSON_TOKEN_TRUE:
5151  case JSON_TOKEN_FALSE:
5152  if (_state->flags & jtiBool)
5153  _state->action(_state->action_state, token, strlen(token));
5154  break;
5155  default:
5156  /* do not call callback for any other token */
5157  break;
5158  }
5159 }
JsonIterateStringValuesAction action
Definition: jsonfuncs.c:60
Definition: regguts.h:298

◆ IteratorConcat()

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

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

4577 {
4578  JsonbValue v1,
4579  v2,
4580  *res = NULL;
4581  JsonbIteratorToken r1,
4582  r2,
4583  rk1,
4584  rk2;
4585 
4586  r1 = rk1 = JsonbIteratorNext(it1, &v1, false);
4587  r2 = rk2 = JsonbIteratorNext(it2, &v2, false);
4588 
4589  /*
4590  * Both elements are objects.
4591  */
4592  if (rk1 == WJB_BEGIN_OBJECT && rk2 == WJB_BEGIN_OBJECT)
4593  {
4594  /*
4595  * Append the all tokens from v1 to res, except last WJB_END_OBJECT
4596  * (because res will not be finished yet).
4597  */
4598  pushJsonbValue(state, r1, NULL);
4599  while ((r1 = JsonbIteratorNext(it1, &v1, true)) != WJB_END_OBJECT)
4600  pushJsonbValue(state, r1, &v1);
4601 
4602  /*
4603  * Append the all tokens from v2 to res, include last WJB_END_OBJECT
4604  * (the concatenation will be completed).
4605  */
4606  while ((r2 = JsonbIteratorNext(it2, &v2, true)) != WJB_DONE)
4607  res = pushJsonbValue(state, r2, r2 != WJB_END_OBJECT ? &v2 : NULL);
4608  }
4609 
4610  /*
4611  * Both elements are arrays (either can be scalar).
4612  */
4613  else if (rk1 == WJB_BEGIN_ARRAY && rk2 == WJB_BEGIN_ARRAY)
4614  {
4615  pushJsonbValue(state, r1, NULL);
4616 
4617  while ((r1 = JsonbIteratorNext(it1, &v1, true)) != WJB_END_ARRAY)
4618  {
4619  Assert(r1 == WJB_ELEM);
4620  pushJsonbValue(state, r1, &v1);
4621  }
4622 
4623  while ((r2 = JsonbIteratorNext(it2, &v2, true)) != WJB_END_ARRAY)
4624  {
4625  Assert(r2 == WJB_ELEM);
4626  pushJsonbValue(state, WJB_ELEM, &v2);
4627  }
4628 
4629  res = pushJsonbValue(state, WJB_END_ARRAY, NULL /* signal to sort */ );
4630  }
4631  /* have we got array || object or object || array? */
4632  else if (((rk1 == WJB_BEGIN_ARRAY && !(*it1)->isScalar) && rk2 == WJB_BEGIN_OBJECT) ||
4633  (rk1 == WJB_BEGIN_OBJECT && (rk2 == WJB_BEGIN_ARRAY && !(*it2)->isScalar)))
4634  {
4635 
4636  JsonbIterator **it_array = rk1 == WJB_BEGIN_ARRAY ? it1 : it2;
4637  JsonbIterator **it_object = rk1 == WJB_BEGIN_OBJECT ? it1 : it2;
4638 
4639  bool prepend = (rk1 == WJB_BEGIN_OBJECT);
4640 
4641  pushJsonbValue(state, WJB_BEGIN_ARRAY, NULL);
4642 
4643  if (prepend)
4644  {
4645  pushJsonbValue(state, WJB_BEGIN_OBJECT, NULL);
4646  while ((r1 = JsonbIteratorNext(it_object, &v1, true)) != WJB_DONE)
4647  pushJsonbValue(state, r1, r1 != WJB_END_OBJECT ? &v1 : NULL);
4648 
4649  while ((r2 = JsonbIteratorNext(it_array, &v2, true)) != WJB_DONE)
4650  res = pushJsonbValue(state, r2, r2 != WJB_END_ARRAY ? &v2 : NULL);
4651  }
4652  else
4653  {
4654  while ((r1 = JsonbIteratorNext(it_array, &v1, true)) != WJB_END_ARRAY)
4655  pushJsonbValue(state, r1, &v1);
4656 
4657  pushJsonbValue(state, WJB_BEGIN_OBJECT, NULL);
4658  while ((r2 = JsonbIteratorNext(it_object, &v2, true)) != WJB_DONE)
4659  pushJsonbValue(state, r2, r2 != WJB_END_OBJECT ? &v2 : NULL);
4660 
4661  res = pushJsonbValue(state, WJB_END_ARRAY, NULL);
4662  }
4663  }
4664  else
4665  {
4666  /*
4667  * This must be scalar || object or object || scalar, as that's all
4668  * that's left. Both of these make no sense, so error out.
4669  */
4670  ereport(ERROR,
4671  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4672  errmsg("invalid concatenation of jsonb objects")));
4673  }
4674 
4675  return res;
4676 }
Definition: jsonb.h:22
int errcode(int sqlerrcode)
Definition: elog.c:570
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:141
JsonbIteratorToken
Definition: jsonb.h:20
#define Assert(condition)
Definition: c.h:732
int errmsg(const char *fmt,...)
Definition: elog.c:784
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 3069 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().

3070 {
3071  jsv->is_json = obj->is_json;
3072 
3073  if (jsv->is_json)
3074  {
3075  JsonHashEntry *hashentry = hash_search(obj->val.json_hash, field,
3076  HASH_FIND, NULL);
3077 
3078  jsv->val.json.type = hashentry ? hashentry->type : JSON_TOKEN_NULL;
3079  jsv->val.json.str = jsv->val.json.type == JSON_TOKEN_NULL ? NULL :
3080  hashentry->val;
3081  jsv->val.json.len = jsv->val.json.str ? -1 : 0; /* null-terminated */
3082 
3083  return hashentry != NULL;
3084  }
3085  else
3086  {
3087  jsv->val.jsonb = !obj->val.jsonb_cont ? NULL :
3089  field, strlen(field));
3090 
3091  return jsv->val.jsonb != NULL;
3092  }
3093 }
bool is_json
Definition: jsonfuncs.c:301
static JsonbValue * findJsonbValueFromContainerLen(JsonbContainer *container, uint32 flags, char *key, uint32 keylen)
Definition: jsonfuncs.c:3917
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:305
char * val
Definition: jsonfuncs.c:142
union JsValue::@30 val
union JsObject::@32 val
bool is_json
Definition: jsonfuncs.c:285
HTAB * json_hash
Definition: jsonfuncs.c:304
#define JB_FOBJECT
Definition: jsonb.h:210
struct JsValue::@30::@31 json
JsonbValue * jsonb
Definition: jsonfuncs.c:295

◆ json_array_element()

Datum json_array_element ( PG_FUNCTION_ARGS  )

Definition at line 802 of file jsonfuncs.c.

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

803 {
804  text *json = PG_GETARG_TEXT_PP(0);
805  int element = PG_GETARG_INT32(1);
806  text *result;
807 
808  result = get_worker(json, NULL, &element, 1, false);
809 
810  if (result != NULL)
811  PG_RETURN_TEXT_P(result);
812  else
813  PG_RETURN_NULL();
814 }
#define PG_GETARG_INT32(n)
Definition: fmgr.h:264
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:303
static chr element(struct vars *v, const chr *startp, const chr *endp)
Definition: regc_locale.c:380
static text * get_worker(text *json, char **tpath, int *ipath, int npath, bool normalize_results)
Definition: jsonfuncs.c:1014
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:361
Definition: c.h:549
#define PG_RETURN_NULL()
Definition: fmgr.h:335

◆ json_array_element_text()

Datum json_array_element_text ( PG_FUNCTION_ARGS  )

Definition at line 845 of file jsonfuncs.c.

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

846 {
847  text *json = PG_GETARG_TEXT_PP(0);
848  int element = PG_GETARG_INT32(1);
849  text *result;
850 
851  result = get_worker(json, NULL, &element, 1, true);
852 
853  if (result != NULL)
854  PG_RETURN_TEXT_P(result);
855  else
856  PG_RETURN_NULL();
857 }
#define PG_GETARG_INT32(n)
Definition: fmgr.h:264
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:303
static chr element(struct vars *v, const chr *startp, const chr *endp)
Definition: regc_locale.c:380
static text * get_worker(text *json, char **tpath, int *ipath, int npath, bool normalize_results)
Definition: jsonfuncs.c:1014
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:361
Definition: c.h:549
#define PG_RETURN_NULL()
Definition: fmgr.h:335

◆ json_array_elements()

Datum json_array_elements ( PG_FUNCTION_ARGS  )

Definition at line 2112 of file jsonfuncs.c.

References elements_worker().

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

◆ json_array_elements_text()

Datum json_array_elements_text ( PG_FUNCTION_ARGS  )

Definition at line 2118 of file jsonfuncs.c.

References elements_worker().

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

◆ json_array_length()

Datum json_array_length ( PG_FUNCTION_ARGS  )

Definition at line 1555 of file jsonfuncs.c.

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

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

◆ json_each()

Datum json_each ( PG_FUNCTION_ARGS  )

Definition at line 1649 of file jsonfuncs.c.

References each_worker().

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

◆ json_each_text()

Datum json_each_text ( PG_FUNCTION_ARGS  )

Definition at line 1661 of file jsonfuncs.c.

References each_worker().

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

◆ json_extract_path()

Datum json_extract_path ( PG_FUNCTION_ARGS  )

Definition at line 919 of file jsonfuncs.c.

References get_path_all().

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

◆ json_extract_path_text()

Datum json_extract_path_text ( PG_FUNCTION_ARGS  )

Definition at line 925 of file jsonfuncs.c.

References get_path_all().

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

◆ json_object_field()

Datum json_object_field ( PG_FUNCTION_ARGS  )

Definition at line 699 of file jsonfuncs.c.

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

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

◆ json_object_field_text()

Datum json_object_field_text ( PG_FUNCTION_ARGS  )

Definition at line 735 of file jsonfuncs.c.

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

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

◆ json_object_keys()

Datum json_object_keys ( PG_FUNCTION_ARGS  )

Definition at line 582 of file jsonfuncs.c.

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

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

◆ json_populate_record()

Datum json_populate_record ( PG_FUNCTION_ARGS  )

Definition at line 2310 of file jsonfuncs.c.

References populate_record_worker().

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

◆ json_populate_recordset()

Datum json_populate_recordset ( PG_FUNCTION_ARGS  )

Definition at line 3541 of file jsonfuncs.c.

References populate_recordset_worker().

3542 {
3543  return populate_recordset_worker(fcinfo, "json_populate_recordset",
3544  true, true);
3545 }
static Datum populate_recordset_worker(FunctionCallInfo fcinfo, const char *funcname, bool is_json, bool have_record_arg)
Definition: jsonfuncs.c:3592

◆ json_strip_nulls()

Datum json_strip_nulls ( PG_FUNCTION_ARGS  )

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

4030 {
4031  text *json = PG_GETARG_TEXT_PP(0);
4033  JsonLexContext *lex;
4034  JsonSemAction *sem;
4035 
4036  lex = makeJsonLexContext(json, true);
4037  state = palloc0(sizeof(StripnullState));
4038  sem = palloc0(sizeof(JsonSemAction));
4039 
4040  state->strval = makeStringInfo();
4041  state->skip_next_null = false;
4042  state->lex = lex;
4043 
4044  sem->semstate = (void *) state;
4046  sem->object_end = sn_object_end;
4047  sem->array_start = sn_array_start;
4048  sem->array_end = sn_array_end;
4049  sem->scalar = sn_scalar;
4052 
4053  pg_parse_json(lex, sem);
4054 
4056  state->strval->len));
4057 
4058 }
json_struct_action array_end
Definition: jsonapi.h:88
bool skip_next_null
Definition: jsonfuncs.c:279
static void sn_object_start(void *state)
Definition: jsonfuncs.c:3939
json_struct_action object_end
Definition: jsonapi.h:86
static void sn_array_element_start(void *state, bool isnull)
Definition: jsonfuncs.c:3999
static void sn_object_field_start(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:3971
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:303
JsonLexContext * makeJsonLexContext(text *json, bool need_escapes)
Definition: json.c:301
static void sn_array_start(void *state)
Definition: jsonfuncs.c:3955
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:183
JsonLexContext * lex
Definition: jsonfuncs.c:277
static void sn_object_end(void *state)
Definition: jsonfuncs.c:3947
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:4008
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:361
json_struct_action array_start
Definition: jsonapi.h:87
Definition: regguts.h:298
StringInfo strval
Definition: jsonfuncs.c:278
Definition: c.h:549
json_ofield_action object_field_start
Definition: jsonapi.h:89
static void sn_array_end(void *state)
Definition: jsonfuncs.c:3963
void * semstate
Definition: jsonapi.h:84

◆ json_to_record()

Datum json_to_record ( PG_FUNCTION_ARGS  )

Definition at line 2317 of file jsonfuncs.c.

References populate_record_worker().

2318 {
2319  return populate_record_worker(fcinfo, "json_to_record",
2320  true, false);
2321 }
static Datum populate_record_worker(FunctionCallInfo fcinfo, const char *funcname, bool is_json, bool have_record_arg)
Definition: jsonfuncs.c:3273

◆ json_to_recordset()

Datum json_to_recordset ( PG_FUNCTION_ARGS  )

Definition at line 3548 of file jsonfuncs.c.

References populate_recordset_worker().

3549 {
3550  return populate_recordset_worker(fcinfo, "json_to_recordset",
3551  true, false);
3552 }
static Datum populate_recordset_worker(FunctionCallInfo fcinfo, const char *funcname, bool is_json, bool have_record_arg)
Definition: jsonfuncs.c:3592

◆ jsonb_array_element()

Datum jsonb_array_element ( PG_FUNCTION_ARGS  )

Definition at line 817 of file jsonfuncs.c.

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

818 {
819  Jsonb *jb = PG_GETARG_JSONB_P(0);
820  int element = PG_GETARG_INT32(1);
821  JsonbValue *v;
822 
823  if (!JB_ROOT_IS_ARRAY(jb))
824  PG_RETURN_NULL();
825 
826  /* Handle negative subscript */
827  if (element < 0)
828  {
829  uint32 nelements = JB_ROOT_COUNT(jb);
830 
831  if (-element > nelements)
832  PG_RETURN_NULL();
833  else
834  element += nelements;
835  }
836 
837  v = getIthJsonbValueFromContainer(&jb->root, element);
838  if (v != NULL)
840 
841  PG_RETURN_NULL();
842 }
#define PG_GETARG_INT32(n)
Definition: fmgr.h:264
Jsonb * JsonbValueToJsonb(JsonbValue *val)
Definition: jsonb_util.c:79
Definition: jsonb.h:220
#define JB_ROOT_COUNT(jbp_)
Definition: jsonb.h:227
#define JB_ROOT_IS_ARRAY(jbp_)
Definition: jsonb.h:230
unsigned int uint32
Definition: c.h:358
static chr element(struct vars *v, const chr *startp, const chr *endp)
Definition: regc_locale.c:380
JsonbContainer root
Definition: jsonb.h:223
JsonbValue * getIthJsonbValueFromContainer(JsonbContainer *container, uint32 i)
Definition: jsonb_util.c:419
#define PG_RETURN_JSONB_P(x)
Definition: jsonb.h:76
#define PG_RETURN_NULL()
Definition: fmgr.h:335
#define PG_GETARG_JSONB_P(x)
Definition: jsonb.h:74

◆ jsonb_array_element_text()

Datum jsonb_array_element_text ( PG_FUNCTION_ARGS  )

Definition at line 860 of file jsonfuncs.c.

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

861 {
862  Jsonb *jb = PG_GETARG_JSONB_P(0);
863  int element = PG_GETARG_INT32(1);
864  JsonbValue *v;
865 
866  if (!JB_ROOT_IS_ARRAY(jb))
867  PG_RETURN_NULL();
868 
869  /* Handle negative subscript */
870  if (element < 0)
871  {
872  uint32 nelements = JB_ROOT_COUNT(jb);
873 
874  if (-element > nelements)
875  PG_RETURN_NULL();
876  else
877  element += nelements;
878  }
879 
880  v = getIthJsonbValueFromContainer(&jb->root, element);
881  if (v != NULL)
882  {
883  text *result = NULL;
884 
885  switch (v->type)
886  {
887  case jbvNull:
888  break;
889  case jbvBool:
890  result = cstring_to_text(v->val.boolean ? "true" : "false");
891  break;
892  case jbvString:
893  result = cstring_to_text_with_len(v->val.string.val, v->val.string.len);
894  break;
895  case jbvNumeric:
897  PointerGetDatum(v->val.numeric))));
898  break;
899  case jbvBinary:
900  {
901  StringInfo jtext = makeStringInfo();
902 
903  (void) JsonbToCString(jtext, v->val.binary.data, -1);
904  result = cstring_to_text_with_len(jtext->data, jtext->len);
905  }
906  break;
907  default:
908  elog(ERROR, "unrecognized jsonb type: %d", (int) v->type);
909  }
910 
911  if (result)
912  PG_RETURN_TEXT_P(result);
913  }
914 
915  PG_RETURN_NULL();
916 }
#define PG_GETARG_INT32(n)
Definition: fmgr.h:264
Definition: jsonb.h:220
#define PointerGetDatum(X)
Definition: postgres.h:556
char * val
Definition: jsonb.h:264
Definition: jsonb.h:239
StringInfo makeStringInfo(void)
Definition: stringinfo.c:28
Datum numeric_out(PG_FUNCTION_ARGS)
Definition: numeric.c:655
#define JB_ROOT_COUNT(jbp_)
Definition: jsonb.h:227
Definition: jsonb.h:236
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:616
#define ERROR
Definition: elog.h:43
#define DatumGetCString(X)
Definition: postgres.h:566
#define JB_ROOT_IS_ARRAY(jbp_)
Definition: jsonb.h:230
text * cstring_to_text_with_len(const char *s, int len)
Definition: varlena.c:183
unsigned int uint32
Definition: c.h:358
static chr element(struct vars *v, const chr *startp, const chr *endp)
Definition: regc_locale.c:380
JsonbContainer root
Definition: jsonb.h:223
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:361
text * cstring_to_text(const char *s)
Definition: varlena.c:171
JsonbValue * getIthJsonbValueFromContainer(JsonbContainer *container, uint32 i)
Definition: jsonb_util.c:419
char * JsonbToCString(StringInfo out, JsonbContainer *in, int estimated_len)
Definition: jsonb.c:442
enum jbvType type
Definition: jsonb.h:255
#define elog(elevel,...)
Definition: elog.h:226
Definition: c.h:549
#define PG_RETURN_NULL()
Definition: fmgr.h:335
#define PG_GETARG_JSONB_P(x)
Definition: jsonb.h:74

◆ jsonb_array_elements()

Datum jsonb_array_elements ( PG_FUNCTION_ARGS  )

Definition at line 1976 of file jsonfuncs.c.

References elements_worker_jsonb().

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

◆ jsonb_array_elements_text()

Datum jsonb_array_elements_text ( PG_FUNCTION_ARGS  )

Definition at line 1982 of file jsonfuncs.c.

References elements_worker_jsonb().

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

◆ jsonb_array_length()

Datum jsonb_array_length ( PG_FUNCTION_ARGS  )

Definition at line 1583 of file jsonfuncs.c.

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

1584 {
1585  Jsonb *jb = PG_GETARG_JSONB_P(0);
1586 
1587  if (JB_ROOT_IS_SCALAR(jb))
1588  ereport(ERROR,
1589  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1590  errmsg("cannot get array length of a scalar")));
1591  else if (!JB_ROOT_IS_ARRAY(jb))
1592  ereport(ERROR,
1593  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1594  errmsg("cannot get array length of a non-array")));
1595 
1597 }
Definition: jsonb.h:220
#define PG_RETURN_INT32(x)
Definition: fmgr.h:344
#define JB_ROOT_COUNT(jbp_)
Definition: jsonb.h:227
int errcode(int sqlerrcode)
Definition: elog.c:570
#define JB_ROOT_IS_SCALAR(jbp_)
Definition: jsonb.h:228
#define ERROR
Definition: elog.h:43
#define JB_ROOT_IS_ARRAY(jbp_)
Definition: jsonb.h:230
#define ereport(elevel, rest)
Definition: elog.h:141
int errmsg(const char *fmt,...)
Definition: elog.c:784
#define PG_GETARG_JSONB_P(x)
Definition: jsonb.h:74

◆ jsonb_concat()

Datum jsonb_concat ( PG_FUNCTION_ARGS  )

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

4191 {
4192  Jsonb *jb1 = PG_GETARG_JSONB_P(0);
4193  Jsonb *jb2 = PG_GETARG_JSONB_P(1);
4194  JsonbParseState *state = NULL;
4195  JsonbValue *res;
4196  JsonbIterator *it1,
4197  *it2;
4198 
4199  /*
4200  * If one of the jsonb is empty, just return the other if it's not scalar
4201  * and both are of the same kind. If it's a scalar or they are of
4202  * different kinds we need to perform the concatenation even if one is
4203  * empty.
4204  */
4205  if (JB_ROOT_IS_OBJECT(jb1) == JB_ROOT_IS_OBJECT(jb2))
4206  {
4207  if (JB_ROOT_COUNT(jb1) == 0 && !JB_ROOT_IS_SCALAR(jb2))
4208  PG_RETURN_JSONB_P(jb2);
4209  else if (JB_ROOT_COUNT(jb2) == 0 && !JB_ROOT_IS_SCALAR(jb1))
4210  PG_RETURN_JSONB_P(jb1);
4211  }
4212 
4213  it1 = JsonbIteratorInit(&jb1->root);
4214  it2 = JsonbIteratorInit(&jb2->root);
4215 
4216  res = IteratorConcat(&it1, &it2, &state);
4217 
4218  Assert(res != NULL);
4219 
4221 }
#define JB_ROOT_IS_OBJECT(jbp_)
Definition: jsonb.h:229
Jsonb * JsonbValueToJsonb(JsonbValue *val)
Definition: jsonb_util.c:79
Definition: jsonb.h:220
#define JB_ROOT_COUNT(jbp_)
Definition: jsonb.h:227
#define JB_ROOT_IS_SCALAR(jbp_)
Definition: jsonb.h:228
JsonbContainer root
Definition: jsonb.h:223
#define Assert(condition)
Definition: c.h:732
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:4575
#define PG_RETURN_JSONB_P(x)
Definition: jsonb.h:76
#define PG_GETARG_JSONB_P(x)
Definition: jsonb.h:74

◆ jsonb_delete()

Datum jsonb_delete ( PG_FUNCTION_ARGS  )

Definition at line 4231 of file jsonfuncs.c.

References Assert, ereport, errcode(), errmsg(), ERROR, JB_ROOT_COUNT, JB_ROOT_IS_SCALAR, jbvString, JsonbIteratorInit(), JsonbIteratorNext(), JsonbValueToJsonb(), sort-test::key, 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.

4232 {
4233  Jsonb *in = PG_GETARG_JSONB_P(0);
4234  text *key = PG_GETARG_TEXT_PP(1);
4235  char *keyptr = VARDATA_ANY(key);
4236  int keylen = VARSIZE_ANY_EXHDR(key);
4237  JsonbParseState *state = NULL;
4238  JsonbIterator *it;
4239  JsonbValue v,
4240  *res = NULL;
4241  bool skipNested = false;
4243 
4244  if (JB_ROOT_IS_SCALAR(in))
4245  ereport(ERROR,
4246  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4247  errmsg("cannot delete from scalar")));
4248 
4249  if (JB_ROOT_COUNT(in) == 0)
4250  PG_RETURN_JSONB_P(in);
4251 
4252  it = JsonbIteratorInit(&in->root);
4253 
4254  while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE)
4255  {
4256  skipNested = true;
4257 
4258  if ((r == WJB_ELEM || r == WJB_KEY) &&
4259  (v.type == jbvString && keylen == v.val.string.len &&
4260  memcmp(keyptr, v.val.string.val, keylen) == 0))
4261  {
4262  /* skip corresponding value as well */
4263  if (r == WJB_KEY)
4264  (void) JsonbIteratorNext(&it, &v, true);
4265 
4266  continue;
4267  }
4268 
4269  res = pushJsonbValue(&state, r, r < WJB_BEGIN_ARRAY ? &v : NULL);
4270  }
4271 
4272  Assert(res != NULL);
4273 
4275 }
#define VARDATA_ANY(PTR)
Definition: postgres.h:348
Jsonb * JsonbValueToJsonb(JsonbValue *val)
Definition: jsonb_util.c:79
Definition: jsonb.h:220
char * val
Definition: jsonb.h:264
Definition: jsonb.h:22
#define JB_ROOT_COUNT(jbp_)
Definition: jsonb.h:227
int errcode(int sqlerrcode)
Definition: elog.c:570
#define JB_ROOT_IS_SCALAR(jbp_)
Definition: jsonb.h:228
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:303
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:141
JsonbIteratorToken
Definition: jsonb.h:20
JsonbContainer root
Definition: jsonb.h:223
#define Assert(condition)
Definition: c.h:732
JsonbIterator * JsonbIteratorInit(JsonbContainer *container)
Definition: jsonb_util.c:718
Definition: regguts.h:298
enum jbvType type
Definition: jsonb.h:255
#define VARSIZE_ANY_EXHDR(PTR)
Definition: postgres.h:341
int errmsg(const char *fmt,...)
Definition: elog.c:784
Definition: c.h:549
#define PG_RETURN_JSONB_P(x)
Definition: jsonb.h:76
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:74

◆ jsonb_delete_array()

Datum jsonb_delete_array ( PG_FUNCTION_ARGS  )

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

4285 {
4286  Jsonb *in = PG_GETARG_JSONB_P(0);
4287  ArrayType *keys = PG_GETARG_ARRAYTYPE_P(1);
4288  Datum *keys_elems;
4289  bool *keys_nulls;
4290  int keys_len;
4291  JsonbParseState *state = NULL;
4292  JsonbIterator *it;
4293  JsonbValue v,
4294  *res = NULL;
4295  bool skipNested = false;
4297 
4298  if (ARR_NDIM(keys) > 1)
4299  ereport(ERROR,
4300  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
4301  errmsg("wrong number of array subscripts")));
4302 
4303  if (JB_ROOT_IS_SCALAR(in))
4304  ereport(ERROR,
4305  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4306  errmsg("cannot delete from scalar")));
4307 
4308  if (JB_ROOT_COUNT(in) == 0)
4309  PG_RETURN_JSONB_P(in);
4310 
4311  deconstruct_array(keys, TEXTOID, -1, false, 'i',
4312  &keys_elems, &keys_nulls, &keys_len);
4313 
4314  if (keys_len == 0)
4315  PG_RETURN_JSONB_P(in);
4316 
4317  it = JsonbIteratorInit(&in->root);
4318 
4319  while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE)
4320  {
4321  skipNested = true;
4322 
4323  if ((r == WJB_ELEM || r == WJB_KEY) && v.type == jbvString)
4324  {
4325  int i;
4326  bool found = false;
4327 
4328  for (i = 0; i < keys_len; i++)
4329  {
4330  char *keyptr;
4331  int keylen;
4332 
4333  if (keys_nulls[i])
4334  continue;
4335 
4336  keyptr = VARDATA_ANY(keys_elems[i]);
4337  keylen = VARSIZE_ANY_EXHDR(keys_elems[i]);
4338  if (keylen == v.val.string.len &&
4339  memcmp(keyptr, v.val.string.val, keylen) == 0)
4340  {
4341  found = true;
4342  break;
4343  }
4344  }
4345  if (found)
4346  {
4347  /* skip corresponding value as well */
4348  if (r == WJB_KEY)
4349  (void) JsonbIteratorNext(&it, &v, true);
4350 
4351  continue;
4352  }
4353  }
4354 
4355  res = pushJsonbValue(&state, r, r < WJB_BEGIN_ARRAY ? &v : NULL);
4356  }
4357 
4358  Assert(res != NULL);
4359 
4361 }
#define VARDATA_ANY(PTR)
Definition: postgres.h:348
Jsonb * JsonbValueToJsonb(JsonbValue *val)
Definition: jsonb_util.c:79
Definition: jsonb.h:220
char * val
Definition: jsonb.h:264
Definition: jsonb.h:22
#define JB_ROOT_COUNT(jbp_)
Definition: jsonb.h:227
int errcode(int sqlerrcode)
Definition: elog.c:570
#define JB_ROOT_IS_SCALAR(jbp_)
Definition: jsonb.h:228
JsonbValue * pushJsonbValue(JsonbParseState **pstate, JsonbIteratorToken seq, JsonbValue *jbval)
Definition: jsonb_util.c:517
#define PG_GETARG_ARRAYTYPE_P(n)
Definition: array.h:251
#define ERROR
Definition: elog.h:43
Definition: jsonb.h:23
#define ereport(elevel, rest)
Definition: elog.h:141
JsonbIteratorToken
Definition: jsonb.h:20
JsonbContainer root
Definition: jsonb.h:223
uintptr_t Datum
Definition: postgres.h:367
#define Assert(condition)
Definition: c.h:732
JsonbIterator * JsonbIteratorInit(JsonbContainer *container)
Definition: jsonb_util.c:718
Definition: regguts.h:298
#define ARR_NDIM(a)
Definition: array.h:278
enum jbvType type
Definition: jsonb.h:255
void deconstruct_array(ArrayType *array, Oid elmtype, int elmlen, bool elmbyval, char elmalign, Datum **elemsp, bool **nullsp, int *nelemsp)
Definition: arrayfuncs.c:3461
#define VARSIZE_ANY_EXHDR(PTR)
Definition: postgres.h:341
int errmsg(const char *fmt,...)
Definition: elog.c:784
int i
#define PG_RETURN_JSONB_P(x)
Definition: jsonb.h:76
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:74

◆ jsonb_delete_idx()

Datum jsonb_delete_idx ( PG_FUNCTION_ARGS  )

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

4372 {
4373  Jsonb *in = PG_GETARG_JSONB_P(0);
4374  int idx = PG_GETARG_INT32(1);
4375  JsonbParseState *state = NULL;
4376  JsonbIterator *it;
4377  uint32 i = 0,
4378  n;
4379  JsonbValue v,
4380  *res = NULL;
4382 
4383  if (JB_ROOT_IS_SCALAR(in))
4384  ereport(ERROR,
4385  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4386  errmsg("cannot delete from scalar")));
4387 
4388  if (JB_ROOT_IS_OBJECT(in))
4389  ereport(ERROR,
4390  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4391  errmsg("cannot delete from object using integer index")));
4392 
4393  if (JB_ROOT_COUNT(in) == 0)
4394  PG_RETURN_JSONB_P(in);
4395 
4396  it = JsonbIteratorInit(&in->root);
4397 
4398  r = JsonbIteratorNext(&it, &v, false);
4399  Assert(r == WJB_BEGIN_ARRAY);
4400  n = v.val.array.nElems;
4401 
4402  if (idx < 0)
4403  {
4404  if (-idx > n)
4405  idx = n;
4406  else
4407  idx = n + idx;
4408  }
4409 
4410  if (idx >= n)
4411  PG_RETURN_JSONB_P(in);
4412 
4413  pushJsonbValue(&state, r, NULL);
4414 
4415  while ((r = JsonbIteratorNext(&it, &v, true)) != WJB_DONE)
4416  {
4417  if (r == WJB_ELEM)
4418  {
4419  if (i++ == idx)
4420  continue;
4421  }
4422 
4423  res = pushJsonbValue(&state, r, r < WJB_BEGIN_ARRAY ? &v : NULL);
4424  }
4425 
4426  Assert(res != NULL);
4427 
4429 }
#define PG_GETARG_INT32(n)
Definition: fmgr.h:264
#define JB_ROOT_IS_OBJECT(jbp_)
Definition: jsonb.h:229
Jsonb * JsonbValueToJsonb(JsonbValue *val)
Definition: jsonb_util.c:79
Definition: jsonb.h:220
char * val
Definition: jsonb.h:264
Definition: jsonb.h:22