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 textJsonbValueAsText (JsonbValue *v)
 
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 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

typedef struct AlenState AlenState

◆ ArrayIOData

typedef struct ArrayIOData ArrayIOData

◆ ColumnIOData

typedef struct ColumnIOData ColumnIOData

Definition at line 154 of file jsonfuncs.c.

◆ CompositeIOData

◆ DomainIOData

typedef struct DomainIOData DomainIOData

◆ EachState

typedef struct EachState EachState

◆ ElementsState

typedef struct ElementsState ElementsState

◆ GetState

typedef struct GetState GetState

◆ IterateJsonStringValuesState

◆ JHashState

typedef struct JHashState JHashState

◆ JsObject

typedef struct JsObject JsObject

◆ JsonHashEntry

typedef struct JsonHashEntry JsonHashEntry

◆ JsValue

typedef struct JsValue JsValue

◆ OkeysState

typedef struct OkeysState OkeysState

◆ PopulateArrayContext

◆ PopulateArrayState

◆ PopulateRecordCache

◆ PopulateRecordsetState

◆ RecordIOData

typedef struct RecordIOData RecordIOData

Definition at line 155 of file jsonfuncs.c.

◆ ScalarIOData

typedef struct ScalarIOData ScalarIOData

◆ StripnullState

◆ TransformJsonStringValuesState

◆ TypeCat

typedef enum TypeCat 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 4046 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().

4047 {
4048  JsonbIterator *it;
4049  JsonbValue *o = &(*jbps)->contVal;
4050  JsonbValue v;
4052 
4053  it = JsonbIteratorInit(&jb->root);
4054 
4055  Assert(o->type == jbvArray || o->type == jbvObject);
4056 
4057  if (JB_ROOT_IS_SCALAR(jb))
4058  {
4059  (void) JsonbIteratorNext(&it, &v, false); /* skip array header */
4060  Assert(v.type == jbvArray);
4061  (void) JsonbIteratorNext(&it, &v, false); /* fetch scalar value */
4062 
4063  switch (o->type)
4064  {
4065  case jbvArray:
4066  (void) pushJsonbValue(jbps, WJB_ELEM, &v);
4067  break;
4068  case jbvObject:
4069  (void) pushJsonbValue(jbps, WJB_VALUE, &v);
4070  break;
4071  default:
4072  elog(ERROR, "unexpected parent of nested structure");
4073  }
4074  }
4075  else
4076  {
4077  while ((type = JsonbIteratorNext(&it, &v, false)) != WJB_DONE)
4078  {
4079  if (type == WJB_KEY || type == WJB_VALUE || type == WJB_ELEM)
4080  (void) pushJsonbValue(jbps, type, &v);
4081  else
4082  (void) pushJsonbValue(jbps, type, NULL);
4083  }
4084  }
4085 
4086 }
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:558
#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:759
enum jbvType type
Definition: jsonb.h:263
#define elog(elevel,...)
Definition: elog.h:226
JsonbIteratorToken JsonbIteratorNext(JsonbIterator **it, JsonbValue *val, bool skipNested)
Definition: jsonb_util.c:795
Definition: jsonb.h:25

◆ alen_array_element_start()

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

Definition at line 1602 of file jsonfuncs.c.

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

Referenced by json_array_length().

1603 {
1604  AlenState *_state = (AlenState *) state;
1605 
1606  /* just count up all the level 1 elements */
1607  if (_state->lex->lex_level == 1)
1608  _state->count++;
1609 }
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 1578 of file jsonfuncs.c.

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

Referenced by json_array_length().

1579 {
1580  AlenState *_state = (AlenState *) state;
1581 
1582  /* json structure check */
1583  if (_state->lex->lex_level == 0)
1584  ereport(ERROR,
1585  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1586  errmsg("cannot get array length of a non-array")));
1587 }
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 1590 of file jsonfuncs.c.

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

Referenced by json_array_length().

1591 {
1592  AlenState *_state = (AlenState *) state;
1593 
1594  /* json structure check */
1595  if (_state->lex->lex_level == 0)
1596  ereport(ERROR,
1597  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1598  errmsg("cannot get array length of a scalar")));
1599 }
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 2989 of file jsonfuncs.c.

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

Referenced by populate_record().

2990 {
2991  RecordIOData *data = (RecordIOData *)
2992  MemoryContextAlloc(mcxt,
2993  offsetof(RecordIOData, columns) +
2994  ncolumns * sizeof(ColumnIOData));
2995 
2996  data->record_type = InvalidOid;
2997  data->record_typmod = 0;
2998  data->ncolumns = ncolumns;
2999  MemSet(data->columns, 0, sizeof(ColumnIOData) * ncolumns);
3000 
3001  return data;
3002 }
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:796
#define offsetof(type, field)
Definition: c.h:655

◆ each_array_start()

static void each_array_start ( void *  state)
static

Definition at line 1894 of file jsonfuncs.c.

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

Referenced by each_worker().

1895 {
1896  EachState *_state = (EachState *) state;
1897 
1898  /* json structure check */
1899  if (_state->lex->lex_level == 0)
1900  ereport(ERROR,
1901  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1902  errmsg("cannot deconstruct an array as an object")));
1903 }
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 1848 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().

1849 {
1850  EachState *_state = (EachState *) state;
1851  MemoryContext old_cxt;
1852  int len;
1853  text *val;
1854  HeapTuple tuple;
1855  Datum values[2];
1856  bool nulls[2] = {false, false};
1857 
1858  /* skip over nested objects */
1859  if (_state->lex->lex_level != 1)
1860  return;
1861 
1862  /* use the tmp context so we can clean up after each tuple is done */
1863  old_cxt = MemoryContextSwitchTo(_state->tmp_cxt);
1864 
1865  values[0] = CStringGetTextDatum(fname);
1866 
1867  if (isnull && _state->normalize_results)
1868  {
1869  nulls[1] = true;
1870  values[1] = (Datum) 0;
1871  }
1872  else if (_state->next_scalar)
1873  {
1874  values[1] = CStringGetTextDatum(_state->normalized_scalar);
1875  _state->next_scalar = false;
1876  }
1877  else
1878  {
1879  len = _state->lex->prev_token_terminator - _state->result_start;
1880  val = cstring_to_text_with_len(_state->result_start, len);
1881  values[1] = PointerGetDatum(val);
1882  }
1883 
1884  tuple = heap_form_tuple(_state->ret_tdesc, values, nulls);
1885 
1886  tuplestore_puttuple(_state->tuple_store, tuple);
1887 
1888  /* clean up and switch back */
1889  MemoryContextSwitchTo(old_cxt);
1890  MemoryContextReset(_state->tmp_cxt);
1891 }
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 1828 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().

1829 {
1830  EachState *_state = (EachState *) state;
1831 
1832  /* save a pointer to where the value starts */
1833  if (_state->lex->lex_level == 1)
1834  {
1835  /*
1836  * next_scalar will be reset in the object_field_end handler, and
1837  * since we know the value is a scalar there is no danger of it being
1838  * on while recursing down the tree.
1839  */
1840  if (_state->normalize_results && _state->lex->token_type == JSON_TOKEN_STRING)
1841  _state->next_scalar = true;
1842  else
1843  _state->result_start = _state->lex->token_start;
1844  }
1845 }
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 1906 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().

1907 {
1908  EachState *_state = (EachState *) state;
1909 
1910  /* json structure check */
1911  if (_state->lex->lex_level == 0)
1912  ereport(ERROR,
1913  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1914  errmsg("cannot deconstruct a scalar")));
1915 
1916  /* supply de-escaped value if required */
1917  if (_state->next_scalar)
1918  _state->normalized_scalar = token;
1919 }
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 1764 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().

1765 {
1766  text *json = PG_GETARG_TEXT_PP(0);
1767  JsonLexContext *lex;
1768  JsonSemAction *sem;
1769  ReturnSetInfo *rsi;
1770  MemoryContext old_cxt;
1771  TupleDesc tupdesc;
1772  EachState *state;
1773 
1774  lex = makeJsonLexContext(json, true);
1775  state = palloc0(sizeof(EachState));
1776  sem = palloc0(sizeof(JsonSemAction));
1777 
1778  rsi = (ReturnSetInfo *) fcinfo->resultinfo;
1779 
1780  if (!rsi || !IsA(rsi, ReturnSetInfo) ||
1781  (rsi->allowedModes & SFRM_Materialize) == 0 ||
1782  rsi->expectedDesc == NULL)
1783  ereport(ERROR,
1784  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1785  errmsg("set-valued function called in context that "
1786  "cannot accept a set")));
1787 
1789 
1790  (void) get_call_result_type(fcinfo, NULL, &tupdesc);
1791 
1792  /* make these in a sufficiently long-lived memory context */
1794 
1795  state->ret_tdesc = CreateTupleDescCopy(tupdesc);
1796  BlessTupleDesc(state->ret_tdesc);
1797  state->tuple_store =
1799  false, work_mem);
1800 
1801  MemoryContextSwitchTo(old_cxt);
1802 
1803  sem->semstate = (void *) state;
1805  sem->scalar = each_scalar;
1808 
1809  state->normalize_results = as_text;
1810  state->next_scalar = false;
1811  state->lex = lex;
1813  "json_each temporary cxt",
1815 
1816  pg_parse_json(lex, sem);
1817 
1818  MemoryContextDelete(state->tmp_cxt);
1819 
1820  rsi->setResult = state->tuple_store;
1821  rsi->setDesc = state->ret_tdesc;
1822 
1823  PG_RETURN_NULL();
1824 }
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
Definition: tupdesc.c:110
#define IsA(nodeptr, _type_)
Definition: nodes.h:576
Tuplestorestate * tuple_store
Definition: jsonfuncs.c:104
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:211
#define AllocSetContextCreate
Definition: memutils.h:170
static void each_object_field_start(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:1828
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:1894
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:1906
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:192
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:980
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:1848
#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 1646 of file jsonfuncs.c.

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, ReturnSetInfo::allowedModes, Assert, BlessTupleDesc(), CreateTupleDescCopy(), cstring_to_text_with_len(), CurrentMemoryContext, 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, JsonbIteratorInit(), JsonbIteratorNext(), JsonbValueAsText(), JsonbValueToJsonb(), sort-test::key, 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().

1647 {
1648  Jsonb *jb = PG_GETARG_JSONB_P(0);
1649  ReturnSetInfo *rsi;
1650  Tuplestorestate *tuple_store;
1651  TupleDesc tupdesc;
1652  TupleDesc ret_tdesc;
1653  MemoryContext old_cxt,
1654  tmp_cxt;
1655  bool skipNested = false;
1656  JsonbIterator *it;
1657  JsonbValue v;
1659 
1660  if (!JB_ROOT_IS_OBJECT(jb))
1661  ereport(ERROR,
1662  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1663  errmsg("cannot call %s on a non-object",
1664  funcname)));
1665 
1666  rsi = (ReturnSetInfo *) fcinfo->resultinfo;
1667 
1668  if (!rsi || !IsA(rsi, ReturnSetInfo) ||
1669  (rsi->allowedModes & SFRM_Materialize) == 0 ||
1670  rsi->expectedDesc == NULL)
1671  ereport(ERROR,
1672  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1673  errmsg("set-valued function called in context that "
1674  "cannot accept a set")));
1675 
1677 
1678  if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
1679  ereport(ERROR,
1680  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1681  errmsg("function returning record called in context "
1682  "that cannot accept type record")));
1683 
1685 
1686  ret_tdesc = CreateTupleDescCopy(tupdesc);
1687  BlessTupleDesc(ret_tdesc);
1688  tuple_store =
1690  false, work_mem);
1691 
1692  MemoryContextSwitchTo(old_cxt);
1693 
1695  "jsonb_each temporary cxt",
1697 
1698  it = JsonbIteratorInit(&jb->root);
1699 
1700  while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE)
1701  {
1702  skipNested = true;
1703 
1704  if (r == WJB_KEY)
1705  {
1706  text *key;
1707  HeapTuple tuple;
1708  Datum values[2];
1709  bool nulls[2] = {false, false};
1710 
1711  /* Use the tmp context so we can clean up after each tuple is done */
1712  old_cxt = MemoryContextSwitchTo(tmp_cxt);
1713 
1714  key = cstring_to_text_with_len(v.val.string.val, v.val.string.len);
1715 
1716  /*
1717  * The next thing the iterator fetches should be the value, no
1718  * matter what shape it is.
1719  */
1720  r = JsonbIteratorNext(&it, &v, skipNested);
1721  Assert(r != WJB_DONE);
1722 
1723  values[0] = PointerGetDatum(key);
1724 
1725  if (as_text)
1726  {
1727  if (v.type == jbvNull)
1728  {
1729  /* a json null is an sql null in text mode */
1730  nulls[1] = true;
1731  values[1] = (Datum) NULL;
1732  }
1733  else
1734  values[1] = PointerGetDatum(JsonbValueAsText(&v));
1735  }
1736  else
1737  {
1738  /* Not in text mode, just return the Jsonb */
1739  Jsonb *val = JsonbValueToJsonb(&v);
1740 
1741  values[1] = PointerGetDatum(val);
1742  }
1743 
1744  tuple = heap_form_tuple(ret_tdesc, values, nulls);
1745 
1746  tuplestore_puttuple(tuple_store, tuple);
1747 
1748  /* clean up and switch back */
1749  MemoryContextSwitchTo(old_cxt);
1750  MemoryContextReset(tmp_cxt);
1751  }
1752  }
1753 
1754  MemoryContextDelete(tmp_cxt);
1755 
1756  rsi->setResult = tuple_store;
1757  rsi->setDesc = ret_tdesc;
1758 
1759  PG_RETURN_NULL();
1760 }
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
Definition: tupdesc.c:110
#define IsA(nodeptr, _type_)
Definition: nodes.h:576
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:211
#define AllocSetContextCreate
Definition: memutils.h:170
#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:84
Definition: jsonb.h:220
#define PointerGetDatum(X)
Definition: postgres.h:556
char * val
Definition: jsonb.h:272
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
static text * JsonbValueAsText(JsonbValue *v)
Definition: jsonfuncs.c:1481
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:192
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:759
MemoryContext ecxt_per_query_memory
Definition: execnodes.h:231
enum jbvType type
Definition: jsonb.h:263
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:795
#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 2146 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().

2147 {
2148  ElementsState *_state = (ElementsState *) state;
2149  MemoryContext old_cxt;
2150  int len;
2151  text *val;
2152  HeapTuple tuple;
2153  Datum values[1];
2154  bool nulls[1] = {false};
2155 
2156  /* skip over nested objects */
2157  if (_state->lex->lex_level != 1)
2158  return;
2159 
2160  /* use the tmp context so we can clean up after each tuple is done */
2161  old_cxt = MemoryContextSwitchTo(_state->tmp_cxt);
2162 
2163  if (isnull && _state->normalize_results)
2164  {
2165  nulls[0] = true;
2166  values[0] = (Datum) NULL;
2167  }
2168  else if (_state->next_scalar)
2169  {
2170  values[0] = CStringGetTextDatum(_state->normalized_scalar);
2171  _state->next_scalar = false;
2172  }
2173  else
2174  {
2175  len = _state->lex->prev_token_terminator - _state->result_start;
2176  val = cstring_to_text_with_len(_state->result_start, len);
2177  values[0] = PointerGetDatum(val);
2178  }
2179 
2180  tuple = heap_form_tuple(_state->ret_tdesc, values, nulls);
2181 
2182  tuplestore_puttuple(_state->tuple_store, tuple);
2183 
2184  /* clean up and switch back */
2185  MemoryContextSwitchTo(old_cxt);
2186  MemoryContextReset(_state->tmp_cxt);
2187 }
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 2126 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().

2127 {
2128  ElementsState *_state = (ElementsState *) state;
2129 
2130  /* save a pointer to where the value starts */
2131  if (_state->lex->lex_level == 1)
2132  {
2133  /*
2134  * next_scalar will be reset in the array_element_end handler, and
2135  * since we know the value is a scalar there is no danger of it being
2136  * on while recursing down the tree.
2137  */
2138  if (_state->normalize_results && _state->lex->token_type == JSON_TOKEN_STRING)
2139  _state->next_scalar = true;
2140  else
2141  _state->result_start = _state->lex->token_start;
2142  }
2143 }
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 2190 of file jsonfuncs.c.

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

Referenced by elements_worker().

2191 {
2192  ElementsState *_state = (ElementsState *) state;
2193 
2194  /* json structure check */
2195  if (_state->lex->lex_level == 0)
2196  ereport(ERROR,
2197  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2198  errmsg("cannot call %s on a non-array",
2199  _state->function_name)));
2200 }
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 2203 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().

2204 {
2205  ElementsState *_state = (ElementsState *) state;
2206 
2207  /* json structure check */
2208  if (_state->lex->lex_level == 0)
2209  ereport(ERROR,
2210  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2211  errmsg("cannot call %s on a scalar",
2212  _state->function_name)));
2213 
2214  /* supply de-escaped value if required */
2215  if (_state->next_scalar)
2216  _state->normalized_scalar = token;
2217 }
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 2060 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().

2061 {
2062  text *json = PG_GETARG_TEXT_PP(0);
2063 
2064  /* elements only needs escaped strings when as_text */
2065  JsonLexContext *lex = makeJsonLexContext(json, as_text);
2066  JsonSemAction *sem;
2067  ReturnSetInfo *rsi;
2068  MemoryContext old_cxt;
2069  TupleDesc tupdesc;
2071 
2072  state = palloc0(sizeof(ElementsState));
2073  sem = palloc0(sizeof(JsonSemAction));
2074 
2075  rsi = (ReturnSetInfo *) fcinfo->resultinfo;
2076 
2077  if (!rsi || !IsA(rsi, ReturnSetInfo) ||
2078  (rsi->allowedModes & SFRM_Materialize) == 0 ||
2079  rsi->expectedDesc == NULL)
2080  ereport(ERROR,
2081  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2082  errmsg("set-valued function called in context that "
2083  "cannot accept a set")));
2084 
2086 
2087  /* it's a simple type, so don't use get_call_result_type() */
2088  tupdesc = rsi->expectedDesc;
2089 
2090  /* make these in a sufficiently long-lived memory context */
2092 
2093  state->ret_tdesc = CreateTupleDescCopy(tupdesc);
2094  BlessTupleDesc(state->ret_tdesc);
2095  state->tuple_store =
2097  false, work_mem);
2098 
2099  MemoryContextSwitchTo(old_cxt);
2100 
2101  sem->semstate = (void *) state;
2103  sem->scalar = elements_scalar;
2106 
2107  state->function_name = funcname;
2108  state->normalize_results = as_text;
2109  state->next_scalar = false;
2110  state->lex = lex;
2112  "json_array_elements temporary cxt",
2114 
2115  pg_parse_json(lex, sem);
2116 
2117  MemoryContextDelete(state->tmp_cxt);
2118 
2119  rsi->setResult = state->tuple_store;
2120  rsi->setDesc = state->ret_tdesc;
2121 
2122  PG_RETURN_NULL();
2123 }
bool normalize_results
Definition: jsonfuncs.c:122
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
Definition: tupdesc.c:110
#define IsA(nodeptr, _type_)
Definition: nodes.h:576
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:211
#define AllocSetContextCreate
Definition: memutils.h:170
const char * function_name
Definition: jsonfuncs.c:117
JsonLexContext * lex
Definition: jsonfuncs.c:116
static void elements_object_start(void *state)
Definition: jsonfuncs.c:2190
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:192
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:2126
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:2146
void * palloc0(Size size)
Definition: mcxt.c:980
static void elements_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:2203
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 1942 of file jsonfuncs.c.

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, ReturnSetInfo::allowedModes, BlessTupleDesc(), CreateTupleDescCopy(), CurrentMemoryContext, 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, JsonbIteratorInit(), JsonbIteratorNext(), JsonbValueAsText(), JsonbValueToJsonb(), 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, val, values, WJB_DONE, WJB_ELEM, and work_mem.

Referenced by jsonb_array_elements(), and jsonb_array_elements_text().

1944 {
1945  Jsonb *jb = PG_GETARG_JSONB_P(0);
1946  ReturnSetInfo *rsi;
1947  Tuplestorestate *tuple_store;
1948  TupleDesc tupdesc;
1949  TupleDesc ret_tdesc;
1950  MemoryContext old_cxt,
1951  tmp_cxt;
1952  bool skipNested = false;
1953  JsonbIterator *it;
1954  JsonbValue v;
1956 
1957  if (JB_ROOT_IS_SCALAR(jb))
1958  ereport(ERROR,
1959  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1960  errmsg("cannot extract elements from a scalar")));
1961  else if (!JB_ROOT_IS_ARRAY(jb))
1962  ereport(ERROR,
1963  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1964  errmsg("cannot extract elements from an object")));
1965 
1966  rsi = (ReturnSetInfo *) fcinfo->resultinfo;
1967 
1968  if (!rsi || !IsA(rsi, ReturnSetInfo) ||
1969  (rsi->allowedModes & SFRM_Materialize) == 0 ||
1970  rsi->expectedDesc == NULL)
1971  ereport(ERROR,
1972  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1973  errmsg("set-valued function called in context that "
1974  "cannot accept a set")));
1975 
1977 
1978  /* it's a simple type, so don't use get_call_result_type() */
1979  tupdesc = rsi->expectedDesc;
1980 
1982 
1983  ret_tdesc = CreateTupleDescCopy(tupdesc);
1984  BlessTupleDesc(ret_tdesc);
1985  tuple_store =
1987  false, work_mem);
1988 
1989  MemoryContextSwitchTo(old_cxt);
1990 
1992  "jsonb_array_elements temporary cxt",
1994 
1995  it = JsonbIteratorInit(&jb->root);
1996 
1997  while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE)
1998  {
1999  skipNested = true;
2000 
2001  if (r == WJB_ELEM)
2002  {
2003  HeapTuple tuple;
2004  Datum values[1];
2005  bool nulls[1] = {false};
2006 
2007  /* use the tmp context so we can clean up after each tuple is done */
2008  old_cxt = MemoryContextSwitchTo(tmp_cxt);
2009 
2010  if (as_text)
2011  {
2012  if (v.type == jbvNull)
2013  {
2014  /* a json null is an sql null in text mode */
2015  nulls[0] = true;
2016  values[0] = (Datum) NULL;
2017  }
2018  else
2019  values[0] = PointerGetDatum(JsonbValueAsText(&v));
2020  }
2021  else
2022  {
2023  /* Not in text mode, just return the Jsonb */
2024  Jsonb *val = JsonbValueToJsonb(&v);
2025 
2026  values[0] = PointerGetDatum(val);
2027  }
2028 
2029  tuple = heap_form_tuple(ret_tdesc, values, nulls);
2030 
2031  tuplestore_puttuple(tuple_store, tuple);
2032 
2033  /* clean up and switch back */
2034  MemoryContextSwitchTo(old_cxt);
2035  MemoryContextReset(tmp_cxt);
2036  }
2037  }
2038 
2039  MemoryContextDelete(tmp_cxt);
2040 
2041  rsi->setResult = tuple_store;
2042  rsi->setDesc = ret_tdesc;
2043 
2044  PG_RETURN_NULL();
2045 }
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
Definition: tupdesc.c:110
#define IsA(nodeptr, _type_)
Definition: nodes.h:576
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:211
#define AllocSetContextCreate
Definition: memutils.h:170
Jsonb * JsonbValueToJsonb(JsonbValue *val)
Definition: jsonb_util.c:84
Definition: jsonb.h:220
#define PointerGetDatum(X)
Definition: postgres.h:556
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
static text * JsonbValueAsText(JsonbValue *v)
Definition: jsonfuncs.c:1481
#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:192
void tuplestore_puttuple(Tuplestorestate *state, HeapTuple tuple)
Definition: tuplestore.c:730
TupleDesc BlessTupleDesc(TupleDesc tupdesc)
Definition: execTuples.c:2048
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:759
MemoryContext ecxt_per_query_memory
Definition: execnodes.h:231
enum jbvType type
Definition: jsonb.h:263
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
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:795
Definition: jsonb.h:25
#define PG_GETARG_JSONB_P(x)
Definition: jsonb.h:74

◆ get_array_element_end()

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

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

1231 {
1232  GetState *_state = (GetState *) state;
1233  bool get_last = false;
1234  int lex_level = _state->lex->lex_level;
1235 
1236  /* same tests as in get_array_element_start */
1237  if (lex_level <= _state->npath &&
1238  _state->pathok[lex_level - 1] &&
1239  _state->path_indexes != NULL &&
1240  _state->array_cur_index[lex_level - 1] == _state->path_indexes[lex_level - 1])
1241  {
1242  if (lex_level < _state->npath)
1243  {
1244  /* done with this element so reset pathok */
1245  _state->pathok[lex_level] = false;
1246  }
1247  else
1248  {
1249  /* end of path, so we want this value */
1250  get_last = true;
1251  }
1252  }
1253 
1254  /* same logic as for objects */
1255  if (get_last && _state->result_start != NULL)
1256  {
1257  if (isnull && _state->normalize_results)
1258  _state->tresult = (text *) NULL;
1259  else
1260  {
1261  char *start = _state->result_start;
1262  int len = _state->lex->prev_token_terminator - start;
1263 
1264  _state->tresult = cstring_to_text_with_len(start, len);
1265  }
1266 
1267  _state->result_start = NULL;
1268  }
1269 }
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 1184 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().

1185 {
1186  GetState *_state = (GetState *) state;
1187  bool get_next = false;
1188  int lex_level = _state->lex->lex_level;
1189 
1190  /* Update array element counter */
1191  if (lex_level <= _state->npath)
1192  _state->array_cur_index[lex_level - 1]++;
1193 
1194  if (lex_level <= _state->npath &&
1195  _state->pathok[lex_level - 1] &&
1196  _state->path_indexes != NULL &&
1197  _state->array_cur_index[lex_level - 1] == _state->path_indexes[lex_level - 1])
1198  {
1199  if (lex_level < _state->npath)
1200  {
1201  /* if not at end of path just mark path ok */
1202  _state->pathok[lex_level] = true;
1203  }
1204  else
1205  {
1206  /* end of path, so we want this value */
1207  get_next = true;
1208  }
1209  }
1210 
1211  /* same logic as for objects */
1212  if (get_next)
1213  {
1214  _state->tresult = NULL;
1215  _state->result_start = NULL;
1216 
1217  if (_state->normalize_results &&
1218  _state->lex->token_type == JSON_TOKEN_STRING)
1219  {
1220  _state->next_scalar = true;
1221  }
1222  else
1223  {
1224  _state->result_start = _state->lex->token_start;
1225  }
1226  }
1227 }
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 1168 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().

1169 {
1170  GetState *_state = (GetState *) state;
1171  int lex_level = _state->lex->lex_level;
1172 
1173  if (lex_level == 0 && _state->npath == 0)
1174  {
1175  /* Special case: return the entire array */
1176  char *start = _state->result_start;
1177  int len = _state->lex->prev_token_terminator - start;
1178 
1179  _state->tresult = cstring_to_text_with_len(start, len);
1180  }
1181 }
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 1135 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().

1136 {
1137  GetState *_state = (GetState *) state;
1138  int lex_level = _state->lex->lex_level;
1139 
1140  if (lex_level < _state->npath)
1141  {
1142  /* Initialize counting of elements in this array */
1143  _state->array_cur_index[lex_level] = -1;
1144 
1145  /* INT_MIN value is reserved to represent invalid subscript */
1146  if (_state->path_indexes[lex_level] < 0 &&
1147  _state->path_indexes[lex_level] != INT_MIN)
1148  {
1149  /* Negative subscript -- convert to positive-wise subscript */
1150  int nelements = json_count_array_elements(_state->lex);
1151 
1152  if (-_state->path_indexes[lex_level] <= nelements)
1153  _state->path_indexes[lex_level] += nelements;
1154  }
1155  }
1156  else if (lex_level == 0 && _state->npath == 0)
1157  {
1158  /*
1159  * Special case: we should match the entire array. We only need this
1160  * at the outermost level because at nested levels the match will have
1161  * been started by the outer field or array element callback.
1162  */
1163  _state->result_start = _state->lex->token_start;
1164  }
1165 }
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 3314 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().

3315 {
3316  HASHCTL ctl;
3317  HTAB *tab;
3318  JHashState *state;
3319  JsonLexContext *lex = makeJsonLexContextCstringLen(json, len, true);
3320  JsonSemAction *sem;
3321 
3322  memset(&ctl, 0, sizeof(ctl));
3323  ctl.keysize = NAMEDATALEN;
3324  ctl.entrysize = sizeof(JsonHashEntry);
3325  ctl.hcxt = CurrentMemoryContext;
3326  tab = hash_create("json object hashtable",
3327  100,
3328  &ctl,
3330 
3331  state = palloc0(sizeof(JHashState));
3332  sem = palloc0(sizeof(JsonSemAction));
3333 
3334  state->function_name = funcname;
3335  state->hash = tab;
3336  state->lex = lex;
3337 
3338  sem->semstate = (void *) state;
3340  sem->scalar = hash_scalar;
3343 
3344  pg_parse_json(lex, sem);
3345 
3346  return tab;
3347 }
#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:3374
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:3350
const char * function_name
Definition: jsonfuncs.c:131
void * palloc0(Size size)
Definition: mcxt.c:980
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:3434
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:3423

◆ get_jsonb_path_all()

static Datum get_jsonb_path_all ( FunctionCallInfo  fcinfo,
bool  as_text 
)
static

Definition at line 1325 of file jsonfuncs.c.

References array_contains_nulls(), Assert, cstring_to_text(), deconstruct_array(), elog, ERROR, getIthJsonbValueFromContainer(), getKeyJsonValueFromContainer(), i, IsAJsonbScalar, JB_ROOT_IS_ARRAY, JB_ROOT_IS_OBJECT, JB_ROOT_IS_SCALAR, jbvBinary, jbvNull, JsonbToCString(), JsonbValueAsText(), JsonbValueToJsonb(), JsonContainerIsArray, JsonContainerIsObject, JsonContainerIsScalar, 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, and VARSIZE.

Referenced by jsonb_extract_path(), and jsonb_extract_path_text().

1326 {
1327  Jsonb *jb = PG_GETARG_JSONB_P(0);
1328  ArrayType *path = PG_GETARG_ARRAYTYPE_P(1);
1329  Datum *pathtext;
1330  bool *pathnulls;
1331  int npath;
1332  int i;
1333  bool have_object = false,
1334  have_array = false;
1335  JsonbValue *jbvp = NULL;
1336  JsonbValue jbvbuf;
1337  JsonbContainer *container;
1338 
1339  /*
1340  * If the array contains any null elements, return NULL, on the grounds
1341  * that you'd have gotten NULL if any RHS value were NULL in a nested
1342  * series of applications of the -> operator. (Note: because we also
1343  * return NULL for error cases such as no-such-field, this is true
1344  * regardless of the contents of the rest of the array.)
1345  */
1346  if (array_contains_nulls(path))
1347  PG_RETURN_NULL();
1348 
1349  deconstruct_array(path, TEXTOID, -1, false, 'i',
1350  &pathtext, &pathnulls, &npath);
1351 
1352  /* Identify whether we have object, array, or scalar at top-level */
1353  container = &jb->root;
1354 
1355  if (JB_ROOT_IS_OBJECT(jb))
1356  have_object = true;
1357  else if (JB_ROOT_IS_ARRAY(jb) && !JB_ROOT_IS_SCALAR(jb))
1358  have_array = true;
1359  else
1360  {
1362  /* Extract the scalar value, if it is what we'll return */
1363  if (npath <= 0)
1364  jbvp = getIthJsonbValueFromContainer(container, 0);
1365  }
1366 
1367  /*
1368  * If the array is empty, return the entire LHS object, on the grounds
1369  * that we should do zero field or element extractions. For the
1370  * non-scalar case we can just hand back the object without much work. For
1371  * the scalar case, fall through and deal with the value below the loop.
1372  * (This inconsistency arises because there's no easy way to generate a
1373  * JsonbValue directly for root-level containers.)
1374  */
1375  if (npath <= 0 && jbvp == NULL)
1376  {
1377  if (as_text)
1378  {
1380  container,
1381  VARSIZE(jb))));
1382  }
1383  else
1384  {
1385  /* not text mode - just hand back the jsonb */
1386  PG_RETURN_JSONB_P(jb);
1387  }
1388  }
1389 
1390  for (i = 0; i < npath; i++)
1391  {
1392  if (have_object)
1393  {
1394  jbvp = getKeyJsonValueFromContainer(container,
1395  VARDATA(pathtext[i]),
1396  VARSIZE(pathtext[i]) - VARHDRSZ,
1397  &jbvbuf);
1398  }
1399  else if (have_array)
1400  {
1401  long lindex;
1402  uint32 index;
1403  char *indextext = TextDatumGetCString(pathtext[i]);
1404  char *endptr;
1405 
1406  errno = 0;
1407  lindex = strtol(indextext, &endptr, 10);
1408  if (endptr == indextext || *endptr != '\0' || errno != 0 ||
1409  lindex > INT_MAX || lindex < INT_MIN)
1410  PG_RETURN_NULL();
1411 
1412  if (lindex >= 0)
1413  {
1414  index = (uint32) lindex;
1415  }
1416  else
1417  {
1418  /* Handle negative subscript */
1419  uint32 nelements;
1420 
1421  /* Container must be array, but make sure */
1422  if (!JsonContainerIsArray(container))
1423  elog(ERROR, "not a jsonb array");
1424 
1425  nelements = JsonContainerSize(container);
1426 
1427  if (-lindex > nelements)
1428  PG_RETURN_NULL();
1429  else
1430  index = nelements + lindex;
1431  }
1432 
1433  jbvp = getIthJsonbValueFromContainer(container, index);
1434  }
1435  else
1436  {
1437  /* scalar, extraction yields a null */
1438  PG_RETURN_NULL();
1439  }
1440 
1441  if (jbvp == NULL)
1442  PG_RETURN_NULL();
1443  else if (i == npath - 1)
1444  break;
1445 
1446  if (jbvp->type == jbvBinary)
1447  {
1448  container = jbvp->val.binary.data;
1449  have_object = JsonContainerIsObject(container);
1450  have_array = JsonContainerIsArray(container);
1451  Assert(!JsonContainerIsScalar(container));
1452  }
1453  else
1454  {
1455  Assert(IsAJsonbScalar(jbvp));
1456  have_object = false;
1457  have_array = false;
1458  }
1459  }
1460 
1461  if (as_text)
1462  {
1463  if (jbvp->type == jbvNull)
1464  PG_RETURN_NULL();
1465 
1467  }
1468  else
1469  {
1470  Jsonb *res = JsonbValueToJsonb(jbvp);
1471 
1472  /* not text mode - just hand back the jsonb */
1473  PG_RETURN_JSONB_P(res);
1474  }
1475 }
#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:84
Definition: jsonb.h:220
#define VARSIZE(PTR)
Definition: postgres.h:303
#define VARHDRSZ
Definition: c.h:555
char * val
Definition: jsonb.h:272
#define JsonContainerIsScalar(jc)
Definition: jsonb.h:215
JsonbValue * getKeyJsonValueFromContainer(JsonbContainer *container, const char *keyVal, int keyLen, JsonbValue *res)
Definition: jsonb_util.c:390
Definition: jsonb.h:236
static text * JsonbValueAsText(JsonbValue *v)
Definition: jsonfuncs.c:1481
#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
#define JsonContainerSize(jc)
Definition: jsonb.h:214
unsigned int uint32
Definition: c.h:358
#define JsonContainerIsArray(jc)
Definition: jsonb.h:217
JsonbContainer root
Definition: jsonb.h:223
#define TextDatumGetCString(d)
Definition: builtins.h:84
uintptr_t Datum
Definition: postgres.h:367
#define JsonContainerIsObject(jc)
Definition: jsonb.h:216
#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:460
#define Assert(condition)
Definition: c.h:732
char * JsonbToCString(StringInfo out, JsonbContainer *in, int estimated_len)
Definition: jsonb.c:460
#define IsAJsonbScalar(jsonbval)
Definition: jsonb.h:305
enum jbvType type
Definition: jsonb.h:263
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
#define PG_GETARG_JSONB_P(x)
Definition: jsonb.h:74

◆ get_object_end()

static void get_object_end ( void *  state)
static

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

1026 {
1027  GetState *_state = (GetState *) state;
1028  int lex_level = _state->lex->lex_level;
1029 
1030  if (lex_level == 0 && _state->npath == 0)
1031  {
1032  /* Special case: return the entire object */
1033  char *start = _state->result_start;
1034  int len = _state->lex->prev_token_terminator - start;
1035 
1036  _state->tresult = cstring_to_text_with_len(start, len);
1037  }
1038 }
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 1086 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().

1087 {
1088  GetState *_state = (GetState *) state;
1089  bool get_last = false;
1090  int lex_level = _state->lex->lex_level;
1091 
1092  /* same tests as in get_object_field_start */
1093  if (lex_level <= _state->npath &&
1094  _state->pathok[lex_level - 1] &&
1095  _state->path_names != NULL &&
1096  _state->path_names[lex_level - 1] != NULL &&
1097  strcmp(fname, _state->path_names[lex_level - 1]) == 0)
1098  {
1099  if (lex_level < _state->npath)
1100  {
1101  /* done with this field so reset pathok */
1102  _state->pathok[lex_level] = false;
1103  }
1104  else
1105  {
1106  /* end of path, so we want this value */
1107  get_last = true;
1108  }
1109  }
1110 
1111  /* for as_text scalar case, our work is already done */
1112  if (get_last && _state->result_start != NULL)
1113  {
1114  /*
1115  * make a text object from the string from the previously noted json
1116  * start up to the end of the previous token (the lexer is by now
1117  * ahead of us on whatever came after what we're interested in).
1118  */
1119  if (isnull && _state->normalize_results)
1120  _state->tresult = (text *) NULL;
1121  else
1122  {
1123  char *start = _state->result_start;
1124  int len = _state->lex->prev_token_terminator - start;
1125 
1126  _state->tresult = cstring_to_text_with_len(start, len);
1127  }
1128 
1129  /* this should be unnecessary but let's do it for cleanliness: */
1130  _state->result_start = NULL;
1131  }
1132 }
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 1041 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().

1042 {
1043  GetState *_state = (GetState *) state;
1044  bool get_next = false;
1045  int lex_level = _state->lex->lex_level;
1046 
1047  if (lex_level <= _state->npath &&
1048  _state->pathok[lex_level - 1] &&
1049  _state->path_names != NULL &&
1050  _state->path_names[lex_level - 1] != NULL &&
1051  strcmp(fname, _state->path_names[lex_level - 1]) == 0)
1052  {
1053  if (lex_level < _state->npath)
1054  {
1055  /* if not at end of path just mark path ok */
1056  _state->pathok[lex_level] = true;
1057  }
1058  else
1059  {
1060  /* end of path, so we want this value */
1061  get_next = true;
1062  }
1063  }
1064 
1065  if (get_next)
1066  {
1067  /* this object overrides any previous matching object */
1068  _state->tresult = NULL;
1069  _state->result_start = NULL;
1070 
1071  if (_state->normalize_results &&
1072  _state->lex->token_type == JSON_TOKEN_STRING)
1073  {
1074  /* for as_text variants, tell get_scalar to set it for us */
1075  _state->next_scalar = true;
1076  }
1077  else
1078  {
1079  /* for non-as_text variants, just note the json starting point */
1080  _state->result_start = _state->lex->token_start;
1081  }
1082  }
1083 }
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 1008 of file jsonfuncs.c.

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

Referenced by get_worker().

1009 {
1010  GetState *_state = (GetState *) state;
1011  int lex_level = _state->lex->lex_level;
1012 
1013  if (lex_level == 0 && _state->npath == 0)
1014  {
1015  /*
1016  * Special case: we should match the entire object. We only need this
1017  * at outermost level because at nested levels the match will have
1018  * been started by the outer field or array element callback.
1019  */
1020  _state->result_start = _state->lex->token_start;
1021  }
1022 }
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 872 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().

873 {
874  text *json = PG_GETARG_TEXT_PP(0);
875  ArrayType *path = PG_GETARG_ARRAYTYPE_P(1);
876  text *result;
877  Datum *pathtext;
878  bool *pathnulls;
879  int npath;
880  char **tpath;
881  int *ipath;
882  int i;
883 
884  /*
885  * If the array contains any null elements, return NULL, on the grounds
886  * that you'd have gotten NULL if any RHS value were NULL in a nested
887  * series of applications of the -> operator. (Note: because we also
888  * return NULL for error cases such as no-such-field, this is true
889  * regardless of the contents of the rest of the array.)
890  */
891  if (array_contains_nulls(path))
892  PG_RETURN_NULL();
893 
894  deconstruct_array(path, TEXTOID, -1, false, 'i',
895  &pathtext, &pathnulls, &npath);
896 
897  tpath = palloc(npath * sizeof(char *));
898  ipath = palloc(npath * sizeof(int));
899 
900  for (i = 0; i < npath; i++)
901  {
902  Assert(!pathnulls[i]);
903  tpath[i] = TextDatumGetCString(pathtext[i]);
904 
905  /*
906  * we have no idea at this stage what structure the document is so
907  * just convert anything in the path that we can to an integer and set
908  * all the other integers to INT_MIN which will never match.
909  */
910  if (*tpath[i] != '\0')
911  {
912  long ind;
913  char *endptr;
914 
915  errno = 0;
916  ind = strtol(tpath[i], &endptr, 10);
917  if (*endptr == '\0' && errno == 0 && ind <= INT_MAX && ind >= INT_MIN)
918  ipath[i] = (int) ind;
919  else
920  ipath[i] = INT_MIN;
921  }
922  else
923  ipath[i] = INT_MIN;
924  }
925 
926  result = get_worker(json, tpath, ipath, npath, as_text);
927 
928  if (result != NULL)
929  PG_RETURN_TEXT_P(result);
930  else
931  PG_RETURN_NULL();
932 }
#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:952
#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:949
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 3146 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().

3149 {
3150  cache->argtype = get_fn_expr_argtype(fcinfo->flinfo, 0);
3151  prepare_column_cache(&cache->c,
3152  cache->argtype, -1,
3153  cache->fn_mcxt, false);
3154  if (cache->c.typcat != TYPECAT_COMPOSITE &&
3155  cache->c.typcat != TYPECAT_COMPOSITE_DOMAIN)
3156  ereport(ERROR,
3157  (errcode(ERRCODE_DATATYPE_MISMATCH),
3158  /* translator: %s is a function name, eg json_to_record */
3159  errmsg("first argument of %s must be a row type",
3160  funcname)));
3161 }
static void prepare_column_cache(ColumnIOData *column, Oid typid, int32 typmod, MemoryContext mcxt, bool need_scalar)
Definition: jsonfuncs.c:2837
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 3172 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().

3175 {
3176  TupleDesc tupdesc;
3177  MemoryContext old_cxt;
3178 
3179  if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
3180  ereport(ERROR,
3181  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3182  /* translator: %s is a function name, eg json_to_record */
3183  errmsg("could not determine row type for result of %s",
3184  funcname),
3185  errhint("Provide a non-null record argument, "
3186  "or call the function in the FROM clause "
3187  "using a column definition list.")));
3188 
3189  Assert(tupdesc);
3190  cache->argtype = tupdesc->tdtypeid;
3191 
3192  /* If we go through this more than once, avoid memory leak */
3193  if (cache->c.io.composite.tupdesc)
3195 
3196  /* Save identified tupdesc */
3197  old_cxt = MemoryContextSwitchTo(cache->fn_mcxt);
3198  cache->c.io.composite.tupdesc = CreateTupleDescCopy(tupdesc);
3199  cache->c.io.composite.base_typid = tupdesc->tdtypeid;
3200  cache->c.io.composite.base_typmod = tupdesc->tdtypmod;
3201  MemoryContextSwitchTo(old_cxt);
3202 }
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 1272 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().

1273 {
1274  GetState *_state = (GetState *) state;
1275  int lex_level = _state->lex->lex_level;
1276 
1277  /* Check for whole-object match */
1278  if (lex_level == 0 && _state->npath == 0)
1279  {
1280  if (_state->normalize_results && tokentype == JSON_TOKEN_STRING)
1281  {
1282  /* we want the de-escaped string */
1283  _state->next_scalar = true;
1284  }
1285  else if (_state->normalize_results && tokentype == JSON_TOKEN_NULL)
1286  {
1287  _state->tresult = (text *) NULL;
1288  }
1289  else
1290  {
1291  /*
1292  * This is a bit hokey: we will suppress whitespace after the
1293  * scalar token, but not whitespace before it. Probably not worth
1294  * doing our own space-skipping to avoid that.
1295  */
1296  char *start = _state->lex->input;
1297  int len = _state->lex->prev_token_terminator - start;
1298 
1299  _state->tresult = cstring_to_text_with_len(start, len);
1300  }
1301  }
1302 
1303  if (_state->next_scalar)
1304  {
1305  /* a de-escaped text value is wanted, so supply it */
1306  _state->tresult = cstring_to_text(token);
1307  /* make sure the next call to get_scalar doesn't overwrite it */
1308  _state->next_scalar = false;
1309  }
1310 }
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 952 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().

957 {
958  JsonLexContext *lex = makeJsonLexContext(json, true);
959  JsonSemAction *sem = palloc0(sizeof(JsonSemAction));
960  GetState *state = palloc0(sizeof(GetState));
961 
962  Assert(npath >= 0);
963 
964  state->lex = lex;
965  /* is it "_as_text" variant? */
966  state->normalize_results = normalize_results;
967  state->npath = npath;
968  state->path_names = tpath;
969  state->path_indexes = ipath;
970  state->pathok = palloc0(sizeof(bool) * npath);
971  state->array_cur_index = palloc(sizeof(int) * npath);
972 
973  if (npath > 0)
974  state->pathok[0] = true;
975 
976  sem->semstate = (void *) state;
977 
978  /*
979  * Not all variants need all the semantic routines. Only set the ones that
980  * are actually needed for maximum efficiency.
981  */
982  sem->scalar = get_scalar;
983  if (npath == 0)
984  {
986  sem->object_end = get_object_end;
988  sem->array_end = get_array_end;
989  }
990  if (tpath != NULL)
991  {
994  }
995  if (ipath != NULL)
996  {
1000  }
1001 
1002  pg_parse_json(lex, sem);
1003 
1004  return state->tresult;
1005 }
json_struct_action array_end
Definition: jsonapi.h:88
static void get_array_end(void *state)
Definition: jsonfuncs.c:1168
int * array_cur_index
Definition: jsonfuncs.c:89
static void get_array_element_start(void *state, bool isnull)
Definition: jsonfuncs.c:1184
json_struct_action object_end
Definition: jsonapi.h:86
static void get_object_start(void *state)
Definition: jsonfuncs.c:1008
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:1086
JsonLexContext * lex
Definition: jsonfuncs.c:80
static void get_object_end(void *state)
Definition: jsonfuncs.c:1025
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:1230
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:1272
void * palloc0(Size size)
Definition: mcxt.c:980
static void get_array_start(void *state)
Definition: jsonfuncs.c:1135
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:949
static void get_object_field_start(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:1041
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 3423 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().

3424 {
3425  JHashState *_state = (JHashState *) state;
3426 
3427  if (_state->lex->lex_level == 0)
3428  ereport(ERROR,
3429  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3430  errmsg("cannot call %s on an array", _state->function_name)));
3431 }
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 3374 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().

3375 {
3376  JHashState *_state = (JHashState *) state;
3377  JsonHashEntry *hashentry;
3378  bool found;
3379 
3380  /*
3381  * Ignore nested fields.
3382  */
3383  if (_state->lex->lex_level > 1)
3384  return;
3385 
3386  /*
3387  * Ignore field names >= NAMEDATALEN - they can't match a record field.
3388  * (Note: without this test, the hash code would truncate the string at
3389  * NAMEDATALEN-1, and could then match against a similarly-truncated
3390  * record field name. That would be a reasonable behavior, but this code
3391  * has previously insisted on exact equality, so we keep this behavior.)
3392  */
3393  if (strlen(fname) >= NAMEDATALEN)
3394  return;
3395 
3396  hashentry = hash_search(_state->hash, fname, HASH_ENTER, &found);
3397 
3398  /*
3399  * found being true indicates a duplicate. We don't do anything about
3400  * that, a later field with the same name overrides the earlier field.
3401  */
3402 
3403  hashentry->type = _state->saved_token_type;
3404  Assert(isnull == (hashentry->type == JSON_TOKEN_NULL));
3405 
3406  if (_state->save_json_start != NULL)
3407  {
3408  int len = _state->lex->prev_token_terminator - _state->save_json_start;
3409  char *val = palloc((len + 1) * sizeof(char));
3410 
3411  memcpy(val, _state->save_json_start, len);
3412  val[len] = '\0';
3413  hashentry->val = val;
3414  }
3415  else
3416  {
3417  /* must have had a scalar instead */
3418  hashentry->val = _state->saved_scalar;
3419  }
3420 }
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:949
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 3350 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().

3351 {
3352  JHashState *_state = (JHashState *) state;
3353 
3354  if (_state->lex->lex_level > 1)
3355  return;
3356 
3357  /* remember token type */
3358  _state->saved_token_type = _state->lex->token_type;
3359 
3360  if (_state->lex->token_type == JSON_TOKEN_ARRAY_START ||
3362  {
3363  /* remember start position of the whole text of the subobject */
3364  _state->save_json_start = _state->lex->token_start;
3365  }
3366  else
3367  {
3368  /* must be a scalar */
3369  _state->save_json_start = NULL;
3370  }
3371 }
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 3434 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().

3435 {
3436  JHashState *_state = (JHashState *) state;
3437 
3438  if (_state->lex->lex_level == 0)
3439  ereport(ERROR,
3440  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3441  errmsg("cannot call %s on a scalar", _state->function_name)));
3442 
3443  if (_state->lex->lex_level == 1)
3444  {
3445  _state->saved_scalar = token;
3446  /* saved_token_type must already be set in hash_object_field_start() */
3447  Assert(_state->saved_token_type == tokentype);
3448  }
3449 }
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 5030 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().

5032 {
5033  JsonLexContext *lex = makeJsonLexContext(json, true);
5034  JsonSemAction *sem = palloc0(sizeof(JsonSemAction));
5036 
5037  state->lex = lex;
5038  state->action = action;
5039  state->action_state = action_state;
5040  state->flags = flags;
5041 
5042  sem->semstate = (void *) state;
5045 
5046  pg_parse_json(lex, sem);
5047 }
JsonIterateStringValuesAction action
Definition: jsonfuncs.c:60
static void iterate_values_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:5054
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:980
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:5080
void * semstate
Definition: jsonapi.h:84

◆ iterate_jsonb_values()

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

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

4964 {
4965  JsonbIterator *it;
4966  JsonbValue v;
4968 
4969  it = JsonbIteratorInit(&jb->root);
4970 
4971  /*
4972  * Just recursively iterating over jsonb and call callback on all
4973  * corresponding elements
4974  */
4975  while ((type = JsonbIteratorNext(&it, &v, false)) != WJB_DONE)
4976  {
4977  if (type == WJB_KEY)
4978  {
4979  if (flags & jtiKey)
4980  action(state, v.val.string.val, v.val.string.len);
4981 
4982  continue;
4983  }
4984  else if (!(type == WJB_VALUE || type == WJB_ELEM))
4985  {
4986  /* do not call callback for composite JsonbValue */
4987  continue;
4988  }
4989 
4990  /* JsonbValue is a value of object or element of array */
4991  switch (v.type)
4992  {
4993  case jbvString:
4994  if (flags & jtiString)
4995  action(state, v.val.string.val, v.val.string.len);
4996  break;
4997  case jbvNumeric:
4998  if (flags & jtiNumeric)
4999  {
5000  char *val;
5001 
5003  NumericGetDatum(v.val.numeric)));
5004 
5005  action(state, val, strlen(val));
5006  pfree(val);
5007  }
5008  break;
5009  case jbvBool:
5010  if (flags & jtiBool)
5011  {
5012  if (v.val.boolean)
5013  action(state, "true", 4);
5014  else
5015  action(state, "false", 5);
5016  }
5017  break;
5018  default:
5019  /* do not call callback for composite JsonbValue */
5020  break;
5021  }
5022  }
5023 }
char * val
Definition: jsonb.h:272
#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:617
void pfree(void *pointer)
Definition: mcxt.c:1056
#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:759
Definition: regguts.h:298
enum jbvType type
Definition: jsonb.h:263
long val
Definition: informix.c:684
JsonbIteratorToken JsonbIteratorNext(JsonbIterator **it, JsonbValue *val, bool skipNested)
Definition: jsonb_util.c:795
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 5080 of file jsonfuncs.c.

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

Referenced by iterate_json_values().

5081 {
5083 
5084  if (_state->flags & jtiKey)
5085  {
5086  char *val = pstrdup(fname);
5087 
5088  _state->action(_state->action_state, val, strlen(val));
5089  }
5090 }
JsonIterateStringValuesAction action
Definition: jsonfuncs.c:60
char * pstrdup(const char *in)
Definition: mcxt.c:1186
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 5054 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().

5055 {
5057 
5058  switch (tokentype)
5059  {
5060  case JSON_TOKEN_STRING:
5061  if (_state->flags & jtiString)
5062  _state->action(_state->action_state, token, strlen(token));
5063  break;
5064  case JSON_TOKEN_NUMBER:
5065  if (_state->flags & jtiNumeric)
5066  _state->action(_state->action_state, token, strlen(token));
5067  break;
5068  case JSON_TOKEN_TRUE:
5069  case JSON_TOKEN_FALSE:
5070  if (_state->flags & jtiBool)
5071  _state->action(_state->action_state, token, strlen(token));
5072  break;
5073  default:
5074  /* do not call callback for any other token */
5075  break;
5076  }
5077 }
JsonIterateStringValuesAction action
Definition: jsonfuncs.c:60
Definition: regguts.h:298

◆ IteratorConcat()

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

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

4495 {
4496  JsonbValue v1,
4497  v2,
4498  *res = NULL;
4499  JsonbIteratorToken r1,
4500  r2,
4501  rk1,
4502  rk2;
4503 
4504  r1 = rk1 = JsonbIteratorNext(it1, &v1, false);
4505  r2 = rk2 = JsonbIteratorNext(it2, &v2, false);
4506 
4507  /*
4508  * Both elements are objects.
4509  */
4510  if (rk1 == WJB_BEGIN_OBJECT && rk2 == WJB_BEGIN_OBJECT)
4511  {
4512  /*
4513  * Append the all tokens from v1 to res, except last WJB_END_OBJECT
4514  * (because res will not be finished yet).
4515  */
4516  pushJsonbValue(state, r1, NULL);
4517  while ((r1 = JsonbIteratorNext(it1, &v1, true)) != WJB_END_OBJECT)
4518  pushJsonbValue(state, r1, &v1);
4519 
4520  /*
4521  * Append the all tokens from v2 to res, include last WJB_END_OBJECT
4522  * (the concatenation will be completed).
4523  */
4524  while ((r2 = JsonbIteratorNext(it2, &v2, true)) != WJB_DONE)
4525  res = pushJsonbValue(state, r2, r2 != WJB_END_OBJECT ? &v2 : NULL);
4526  }
4527 
4528  /*
4529  * Both elements are arrays (either can be scalar).
4530  */
4531  else if (rk1 == WJB_BEGIN_ARRAY && rk2 == WJB_BEGIN_ARRAY)
4532  {
4533  pushJsonbValue(state, r1, NULL);
4534 
4535  while ((r1 = JsonbIteratorNext(it1, &v1, true)) != WJB_END_ARRAY)
4536  {
4537  Assert(r1 == WJB_ELEM);
4538  pushJsonbValue(state, r1, &v1);
4539  }
4540 
4541  while ((r2 = JsonbIteratorNext(it2, &v2, true)) != WJB_END_ARRAY)
4542  {
4543  Assert(r2 == WJB_ELEM);
4544  pushJsonbValue(state, WJB_ELEM, &v2);
4545  }
4546 
4547  res = pushJsonbValue(state, WJB_END_ARRAY, NULL /* signal to sort */ );
4548  }
4549  /* have we got array || object or object || array? */
4550  else if (((rk1 == WJB_BEGIN_ARRAY && !(*it1)->isScalar) && rk2 == WJB_BEGIN_OBJECT) ||
4551  (rk1 == WJB_BEGIN_OBJECT && (rk2 == WJB_BEGIN_ARRAY && !(*it2)->isScalar)))
4552  {
4553 
4554  JsonbIterator **it_array = rk1 == WJB_BEGIN_ARRAY ? it1 : it2;
4555  JsonbIterator **it_object = rk1 == WJB_BEGIN_OBJECT ? it1 : it2;
4556 
4557  bool prepend = (rk1 == WJB_BEGIN_OBJECT);
4558 
4559  pushJsonbValue(state, WJB_BEGIN_ARRAY, NULL);
4560 
4561  if (prepend)
4562  {
4563  pushJsonbValue(state, WJB_BEGIN_OBJECT, NULL);
4564  while ((r1 = JsonbIteratorNext(it_object, &v1, true)) != WJB_DONE)
4565  pushJsonbValue(state, r1, r1 != WJB_END_OBJECT ? &v1 : NULL);
4566 
4567  while ((r2 = JsonbIteratorNext(it_array, &v2, true)) != WJB_DONE)
4568  res = pushJsonbValue(state, r2, r2 != WJB_END_ARRAY ? &v2 : NULL);
4569  }
4570  else
4571  {
4572  while ((r1 = JsonbIteratorNext(it_array, &v1, true)) != WJB_END_ARRAY)
4573  pushJsonbValue(state, r1, &v1);
4574 
4575  pushJsonbValue(state, WJB_BEGIN_OBJECT, NULL);
4576  while ((r2 = JsonbIteratorNext(it_object, &v2, true)) != WJB_DONE)
4577  pushJsonbValue(state, r2, r2 != WJB_END_OBJECT ? &v2 : NULL);
4578 
4579  res = pushJsonbValue(state, WJB_END_ARRAY, NULL);
4580  }
4581  }
4582  else
4583  {
4584  /*
4585  * This must be scalar || object or object || scalar, as that's all
4586  * that's left. Both of these make no sense, so error out.
4587  */
4588  ereport(ERROR,
4589  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4590  errmsg("invalid concatenation of jsonb objects")));
4591  }
4592 
4593  return res;
4594 }
Definition: jsonb.h:22
int errcode(int sqlerrcode)
Definition: elog.c:570
JsonbValue * pushJsonbValue(JsonbParseState **pstate, JsonbIteratorToken seq, JsonbValue *jbval)
Definition: jsonb_util.c:558
#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:795
Definition: jsonb.h:25

◆ JsObjectGetField()

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

Definition at line 3005 of file jsonfuncs.c.

References getKeyJsonValueFromContainer(), HASH_FIND, hash_search(), JsValue::is_json, JsObject::is_json, 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().

3006 {
3007  jsv->is_json = obj->is_json;
3008 
3009  if (jsv->is_json)
3010  {
3011  JsonHashEntry *hashentry = hash_search(obj->val.json_hash, field,
3012  HASH_FIND, NULL);
3013 
3014  jsv->val.json.type = hashentry ? hashentry->type : JSON_TOKEN_NULL;
3015  jsv->val.json.str = jsv->val.json.type == JSON_TOKEN_NULL ? NULL :
3016  hashentry->val;
3017  jsv->val.json.len = jsv->val.json.str ? -1 : 0; /* null-terminated */
3018 
3019  return hashentry != NULL;
3020  }
3021  else
3022  {
3023  jsv->val.jsonb = !obj->val.jsonb_cont ? NULL :
3024  getKeyJsonValueFromContainer(obj->val.jsonb_cont, field, strlen(field),
3025  NULL);
3026 
3027  return jsv->val.jsonb != NULL;
3028  }
3029 }
bool is_json
Definition: jsonfuncs.c:301
JsonbValue * getKeyJsonValueFromContainer(JsonbContainer *container, const char *keyVal, int keyLen, JsonbValue *res)
Definition: jsonb_util.c:390
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
struct JsValue::@30::@31 json
JsonbValue * jsonb
Definition: jsonfuncs.c:295

◆ json_array_element()

Datum json_array_element ( PG_FUNCTION_ARGS  )

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

771 {
772  text *json = PG_GETARG_TEXT_PP(0);
773  int element = PG_GETARG_INT32(1);
774  text *result;
775 
776  result = get_worker(json, NULL, &element, 1, false);
777 
778  if (result != NULL)
779  PG_RETURN_TEXT_P(result);
780  else
781  PG_RETURN_NULL();
782 }
#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:952
#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 813 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.

814 {
815  text *json = PG_GETARG_TEXT_PP(0);
816  int element = PG_GETARG_INT32(1);
817  text *result;
818 
819  result = get_worker(json, NULL, &element, 1, true);
820 
821  if (result != NULL)
822  PG_RETURN_TEXT_P(result);
823  else
824  PG_RETURN_NULL();
825 }
#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:952
#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 2048 of file jsonfuncs.c.

References elements_worker().

2049 {
2050  return elements_worker(fcinfo, "json_array_elements", false);
2051 }
static Datum elements_worker(FunctionCallInfo fcinfo, const char *funcname, bool as_text)
Definition: jsonfuncs.c:2060

◆ json_array_elements_text()

Datum json_array_elements_text ( PG_FUNCTION_ARGS  )

Definition at line 2054 of file jsonfuncs.c.

References elements_worker().

2055 {
2056  return elements_worker(fcinfo, "json_array_elements_text", true);
2057 }
static Datum elements_worker(FunctionCallInfo fcinfo, const char *funcname, bool as_text)
Definition: jsonfuncs.c:2060

◆ json_array_length()

Datum json_array_length ( PG_FUNCTION_ARGS  )

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

1529 {
1530  text *json = PG_GETARG_TEXT_PP(0);
1531  AlenState *state;
1532  JsonLexContext *lex;
1533  JsonSemAction *sem;
1534 
1535  lex = makeJsonLexContext(json, false);
1536  state = palloc0(sizeof(AlenState));
1537  sem = palloc0(sizeof(JsonSemAction));
1538 
1539  /* palloc0 does this for us */
1540 #if 0
1541  state->count = 0;
1542 #endif
1543  state->lex = lex;
1544 
1545  sem->semstate = (void *) state;
1547  sem->scalar = alen_scalar;
1549 
1550  pg_parse_json(lex, sem);
1551 
1552  PG_RETURN_INT32(state->count);
1553 }
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:1590
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:980
json_aelem_action array_element_start
Definition: jsonapi.h:91
Definition: regguts.h:298
static void alen_object_start(void *state)
Definition: jsonfuncs.c:1578
Definition: c.h:549
static void alen_array_element_start(void *state, bool isnull)
Definition: jsonfuncs.c:1602
void * semstate
Definition: jsonapi.h:84

◆ json_each()

Datum json_each ( PG_FUNCTION_ARGS  )

Definition at line 1622 of file jsonfuncs.c.

References each_worker().

1623 {
1624  return each_worker(fcinfo, false);
1625 }
static Datum each_worker(FunctionCallInfo fcinfo, bool as_text)
Definition: jsonfuncs.c:1764

◆ json_each_text()

Datum json_each_text ( PG_FUNCTION_ARGS  )

Definition at line 1634 of file jsonfuncs.c.

References each_worker().

1635 {
1636  return each_worker(fcinfo, true);
1637 }
static Datum each_worker(FunctionCallInfo fcinfo, bool as_text)
Definition: jsonfuncs.c:1764

◆ json_extract_path()

Datum json_extract_path ( PG_FUNCTION_ARGS  )

Definition at line 857 of file jsonfuncs.c.

References get_path_all().

858 {
859  return get_path_all(fcinfo, false);
860 }
static Datum get_path_all(FunctionCallInfo fcinfo, bool as_text)
Definition: jsonfuncs.c:872

◆ json_extract_path_text()

Datum json_extract_path_text ( PG_FUNCTION_ARGS  )

Definition at line 863 of file jsonfuncs.c.

References get_path_all().

864 {
865  return get_path_all(fcinfo, true);
866 }
static Datum get_path_all(FunctionCallInfo fcinfo, bool as_text)
Definition: jsonfuncs.c:872

◆ json_object_field()

Datum json_object_field ( PG_FUNCTION_ARGS  )

Definition at line 694 of file jsonfuncs.c.

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

695 {
696  text *json = PG_GETARG_TEXT_PP(0);
697  text *fname = PG_GETARG_TEXT_PP(1);
698  char *fnamestr = text_to_cstring(fname);
699  text *result;
700 
701  result = get_worker(json, &fnamestr, NULL, 1, false);
702 
703  if (result != NULL)
704  PG_RETURN_TEXT_P(result);
705  else
706  PG_RETURN_NULL();
707 }
#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:952
#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 732 of file jsonfuncs.c.

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

733 {
734  text *json = PG_GETARG_TEXT_PP(0);
735  text *fname = PG_GETARG_TEXT_PP(1);
736  char *fnamestr = text_to_cstring(fname);
737  text *result;
738 
739  result = get_worker(json, &fnamestr, NULL, 1, true);
740 
741  if (result != NULL)
742  PG_RETURN_TEXT_P(result);
743  else
744  PG_RETURN_NULL();
745 }
#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:952
#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 577 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.

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

References populate_record_worker().

2247 {
2248  return populate_record_worker(fcinfo, "json_populate_record",
2249  true, true);
2250 }
static Datum populate_record_worker(FunctionCallInfo fcinfo, const char *funcname, bool is_json, bool have_record_arg)
Definition: jsonfuncs.c:3209

◆ json_populate_recordset()

Datum json_populate_recordset ( PG_FUNCTION_ARGS  )

Definition at line 3477 of file jsonfuncs.c.

References populate_recordset_worker().

3478 {
3479  return populate_recordset_worker(fcinfo, "json_populate_recordset",
3480  true, true);
3481 }
static Datum populate_recordset_worker(FunctionCallInfo fcinfo, const char *funcname, bool is_json, bool have_record_arg)
Definition: jsonfuncs.c:3528

◆ json_strip_nulls()

Datum json_strip_nulls ( PG_FUNCTION_ARGS  )

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

3950 {
3951  text *json = PG_GETARG_TEXT_PP(0);
3953  JsonLexContext *lex;
3954  JsonSemAction *sem;
3955 
3956  lex = makeJsonLexContext(json, true);
3957  state = palloc0(sizeof(StripnullState));
3958  sem = palloc0(sizeof(JsonSemAction));
3959 
3960  state->strval = makeStringInfo();
3961  state->skip_next_null = false;
3962  state->lex = lex;
3963 
3964  sem->semstate = (void *) state;
3966  sem->object_end = sn_object_end;
3967  sem->array_start = sn_array_start;
3968  sem->array_end = sn_array_end;
3969  sem->scalar = sn_scalar;
3972 
3973  pg_parse_json(lex, sem);
3974 
3976  state->strval->len));
3977 
3978 }
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:3859
json_struct_action object_end
Definition: jsonapi.h:86
static void sn_array_element_start(void *state, bool isnull)
Definition: jsonfuncs.c:3919
static void sn_object_field_start(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:3891
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:3875
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:3867
void * palloc0(Size size)
Definition: mcxt.c:980
json_aelem_action array_element_start
Definition: jsonapi.h:91
static void sn_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:3928
#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:3883
void * semstate
Definition: jsonapi.h:84

◆ json_to_record()

Datum json_to_record ( PG_FUNCTION_ARGS  )

Definition at line 2253 of file jsonfuncs.c.

References populate_record_worker().

2254 {
2255  return populate_record_worker(fcinfo, "json_to_record",
2256  true, false);
2257 }
static Datum populate_record_worker(FunctionCallInfo fcinfo, const char *funcname, bool is_json, bool have_record_arg)
Definition: jsonfuncs.c:3209

◆ json_to_recordset()

Datum json_to_recordset ( PG_FUNCTION_ARGS  )

Definition at line 3484 of file jsonfuncs.c.

References populate_recordset_worker().

3485 {
3486  return populate_recordset_worker(fcinfo, "json_to_recordset",
3487  true, false);
3488 }
static Datum populate_recordset_worker(FunctionCallInfo fcinfo, const char *funcname, bool is_json, bool have_record_arg)
Definition: jsonfuncs.c:3528

◆ jsonb_array_element()

Datum jsonb_array_element ( PG_FUNCTION_ARGS  )

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

786 {
787  Jsonb *jb = PG_GETARG_JSONB_P(0);
788  int element = PG_GETARG_INT32(1);
789  JsonbValue *v;
790 
791  if (!JB_ROOT_IS_ARRAY(jb))
792  PG_RETURN_NULL();
793 
794  /* Handle negative subscript */
795  if (element < 0)
796  {
797  uint32 nelements = JB_ROOT_COUNT(jb);
798 
799  if (-element > nelements)
800  PG_RETURN_NULL();
801  else
802  element += nelements;
803  }
804 
805  v = getIthJsonbValueFromContainer(&jb->root, element);
806  if (v != NULL)
808 
809  PG_RETURN_NULL();
810 }
#define PG_GETARG_INT32(n)
Definition: fmgr.h:264
Jsonb * JsonbValueToJsonb(JsonbValue *val)
Definition: jsonb_util.c:84
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:460
#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 828 of file jsonfuncs.c.

References element(), getIthJsonbValueFromContainer(), JB_ROOT_COUNT, JB_ROOT_IS_ARRAY, jbvNull, JsonbValueAsText(), PG_GETARG_INT32, PG_GETARG_JSONB_P, PG_RETURN_NULL, PG_RETURN_TEXT_P, Jsonb::root, and JsonbValue::type.

829 {
830  Jsonb *jb = PG_GETARG_JSONB_P(0);
831  int element = PG_GETARG_INT32(1);
832  JsonbValue *v;
833 
834  if (!JB_ROOT_IS_ARRAY(jb))
835  PG_RETURN_NULL();
836 
837  /* Handle negative subscript */
838  if (element < 0)
839  {
840  uint32 nelements = JB_ROOT_COUNT(jb);
841 
842  if (-element > nelements)
843  PG_RETURN_NULL();
844  else
845  element += nelements;
846  }
847 
848  v = getIthJsonbValueFromContainer(&jb->root, element);
849 
850  if (v != NULL && v->type != jbvNull)
852 
853  PG_RETURN_NULL();
854 }
#define PG_GETARG_INT32(n)
Definition: fmgr.h:264
Definition: jsonb.h:220
#define JB_ROOT_COUNT(jbp_)
Definition: jsonb.h:227
Definition: jsonb.h:236
static text * JsonbValueAsText(JsonbValue *v)
Definition: jsonfuncs.c:1481
#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
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:361
JsonbValue * getIthJsonbValueFromContainer(JsonbContainer *container, uint32 i)
Definition: jsonb_util.c:460
enum jbvType type
Definition: jsonb.h:263
#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 1930 of file jsonfuncs.c.

References elements_worker_jsonb().

1931 {
1932  return elements_worker_jsonb(fcinfo, "jsonb_array_elements", false);
1933 }
static Datum elements_worker_jsonb(FunctionCallInfo fcinfo, const char *funcname, bool as_text)
Definition: jsonfuncs.c:1942

◆ jsonb_array_elements_text()

Datum jsonb_array_elements_text ( PG_FUNCTION_ARGS  )

Definition at line 1936 of file jsonfuncs.c.

References elements_worker_jsonb().

1937 {
1938  return elements_worker_jsonb(fcinfo, "jsonb_array_elements_text", true);
1939 }
static Datum elements_worker_jsonb(FunctionCallInfo fcinfo, const char *funcname, bool as_text)
Definition: jsonfuncs.c:1942

◆ jsonb_array_length()

Datum jsonb_array_length ( PG_FUNCTION_ARGS  )

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

1557 {
1558  Jsonb *jb = PG_GETARG_JSONB_P(0);
1559 
1560  if (JB_ROOT_IS_SCALAR(jb))
1561  ereport(ERROR,
1562  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1563  errmsg("cannot get array length of a scalar")));
1564  else if (!JB_ROOT_IS_ARRAY(jb))
1565  ereport(ERROR,
1566  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1567  errmsg("cannot get array length of a non-array")));
1568 
1570 }
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 4110 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.

4111 {
4112  Jsonb *jb1 = PG_GETARG_JSONB_P(0);
4113  Jsonb *jb2 = PG_GETARG_JSONB_P(1);
4114  JsonbParseState *state = NULL;
4115  JsonbValue *res;
4116  JsonbIterator *it1,
4117  *it2;
4118 
4119  /*
4120  * If one of the jsonb is empty, just return the other if it's not scalar
4121  * and both are of the same kind. If it's a scalar or they are of
4122  * different kinds we need to perform the concatenation even if one is
4123  * empty.
4124  */
4125  if (JB_ROOT_IS_OBJECT(jb1) == JB_ROOT_IS_OBJECT(jb2))
4126  {
4127  if (JB_ROOT_COUNT(jb1) == 0 && !JB_ROOT_IS_SCALAR(jb2))
4128  PG_RETURN_JSONB_P(jb2);
4129  else if (JB_ROOT_COUNT(jb2) == 0 && !JB_ROOT_IS_SCALAR(jb1))
4130  PG_RETURN_JSONB_P(jb1);
4131  }
4132 
4133  it1 = JsonbIteratorInit(&jb1->root);
4134  it2 = JsonbIteratorInit(&jb2->root);
4135 
4136  res = IteratorConcat(&it1, &it2, &state);
4137 
4138  Assert(res != NULL);
4139 
4141 }
#define JB_ROOT_IS_OBJECT(jbp_)
Definition: jsonb.h:229
Jsonb * JsonbValueToJsonb(JsonbValue *val)
Definition: jsonb_util.c:84
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:759
Definition: regguts.h:298
static JsonbValue * IteratorConcat(JsonbIterator **it1, JsonbIterator **it2, JsonbParseState **state)
Definition: jsonfuncs.c:4493
#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 4151 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.

4152 {
4153  Jsonb *in = PG_GETARG_JSONB_P(0);
4154  text *key = PG_GETARG_TEXT_PP(1);
4155  char *keyptr = VARDATA_ANY(key);
4156  int keylen = VARSIZE_ANY_EXHDR(key);
4157  JsonbParseState *state = NULL;
4158  JsonbIterator *it;
4159  JsonbValue v,
4160  *res = NULL;
4161  bool skipNested = false;
4163 
4164  if (JB_ROOT_IS_SCALAR(in))
4165  ereport(ERROR,
4166  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4167  errmsg("cannot delete from scalar")));
4168 
4169  if (JB_ROOT_COUNT(in) == 0)
4170  PG_RETURN_JSONB_P(in);
4171 
4172  it = JsonbIteratorInit(&in->root);
4173 
4174  while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE)
4175  {
4176  skipNested = true;
4177 
4178  if ((r == WJB_ELEM || r == WJB_KEY) &&
4179  (v.type == jbvString && keylen == v.val.string.len &&
4180  memcmp(keyptr, v.val.string.val, keylen) == 0))
4181  {
4182  /* skip corresponding value as well */
4183  if (r == WJB_KEY)
4184  (void) JsonbIteratorNext(&it, &v, true);
4185 
4186  continue;
4187  }
4188 
4189  res = pushJsonbValue(&state, r, r < WJB_BEGIN_ARRAY ? &v : NULL);
4190  }
4191 
4192  Assert(res != NULL);
4193 
4195 }
#define VARDATA_ANY(PTR)
Definition: postgres.h:348
Jsonb * JsonbValueToJsonb(JsonbValue *val)
Definition: jsonb_util.c:84
Definition: jsonb.h:220
char * val
Definition: jsonb.h:272
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:558
#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:759
Definition: regguts.h:298
enum jbvType type
Definition: jsonb.h:263
#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:795
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 4204 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.

4205 {
4206  Jsonb *in = PG_GETARG_JSONB_P(0);
4207  ArrayType *keys = PG_GETARG_ARRAYTYPE_P(1);
4208  Datum *keys_elems;
4209  bool *keys_nulls;
4210  int keys_len;
4211  JsonbParseState *state = NULL;
4212  JsonbIterator *it;
4213  JsonbValue v,
4214  *res = NULL;
4215  bool skipNested = false;
4217 
4218  if (ARR_NDIM(keys) > 1)
4219  ereport(ERROR,
4220  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
4221  errmsg("wrong number of array subscripts")));
4222 
4223  if (JB_ROOT_IS_SCALAR(in))
4224  ereport(ERROR,
4225  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4226  errmsg("cannot delete from scalar")));
4227 
4228  if (JB_ROOT_COUNT(in) == 0)
4229  PG_RETURN_JSONB_P(in);
4230 
4231  deconstruct_array(keys, TEXTOID, -1, false, 'i',
4232  &keys_elems, &keys_nulls, &keys_len);
4233 
4234  if (keys_len == 0)
4235  PG_RETURN_JSONB_P(in);
4236 
4237  it = JsonbIteratorInit(&in->root);
4238 
4239  while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE)
4240  {
4241  skipNested = true;
4242 
4243  if ((r == WJB_ELEM || r == WJB_KEY) && v.type == jbvString)
4244  {
4245  int i;
4246  bool found = false;
4247 
4248  for (i = 0; i < keys_len; i++)
4249  {
4250  char *keyptr;
4251  int keylen;
4252 
4253  if (keys_nulls[i])
4254  continue;
4255 
4256  keyptr = VARDATA_ANY(keys_elems[i]);
4257  keylen = VARSIZE_ANY_EXHDR(keys_elems[i]);
4258  if (keylen == v.val.string.len &&
4259  memcmp(keyptr, v.val.string.val, keylen) == 0)
4260  {
4261  found = true;
4262  break;
4263  }
4264  }
4265  if (found)
4266  {
4267  /* skip corresponding value as well */
4268  if (r == WJB_KEY)
4269  (void) JsonbIteratorNext(&it, &v, true);
4270 
4271  continue;
4272  }
4273  }
4274 
4275  res = pushJsonbValue(&state, r, r < WJB_BEGIN_ARRAY ? &v : NULL);
4276  }
4277 
4278  Assert(res != NULL);
4279 
4281 }
#define VARDATA_ANY(PTR)
Definition: postgres.h:348
Jsonb * JsonbValueToJsonb(JsonbValue *val)
Definition: jsonb_util.c:84
Definition: jsonb.h:220
char * val
Definition: jsonb.h:272
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:558
#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:759
Definition: regguts.h:298
#define ARR_NDIM(a)
Definition: array.h:278
enum jbvType type
Definition: jsonb.h:263
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:795
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 4291 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.

4292 {
4293  Jsonb *in = PG_GETARG_JSONB_P(0);
4294  int idx = PG_GETARG_INT32(1);
4295  JsonbParseState *state = NULL;
4296  JsonbIterator *it;
4297  uint32 i = 0,
4298  n;
4299  JsonbValue v,
4300  *res = NULL;
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_IS_OBJECT(in))
4309  ereport(ERROR,
4310  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4311  errmsg("cannot delete from object using integer index")));
4312 
4313  if (JB_ROOT_COUNT(in) == 0)
4314  PG_RETURN_JSONB_P(in);
4315 
4316  it = JsonbIteratorInit(&in->root);
4317 
4318  r = JsonbIteratorNext(&it, &v, false);
4319  Assert(r == WJB_BEGIN_ARRAY);
4320  n = v.val.array.nElems;
4321 
4322  if (idx < 0)
4323  {
4324  if (-idx > n)
4325  idx = n;
4326  else
4327  idx = n + idx;
4328  }
4329 
4330  if (idx >= n)
4331  PG_RETURN_JSONB_P(in);
4332 
4333  pushJsonbValue(&state, r, NULL);
4334 
4335  while ((r = JsonbIteratorNext(&it, &v, true)) != WJB_DONE)
4336  {
4337  if (r == WJB_ELEM)
4338  {
4339  if (i++ == idx)
4340  continue;
4341  }
4342 
4343  res = pushJsonbValue(&state, r, r < WJB_BEGIN_ARRAY ? &v : NULL);
4344  }
4345 
4346  Assert(res != NULL);
4347 
4349 }
#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:84
Definition: jsonb.h:220
char * val
Definition: jsonb.h:272
Definition: jsonb.h:22
#define JB_ROOT_COUNT(jbp_)
Definition: jsonb.h:227
int errcode(int sqlerrcode)
Definition: elog.c:570
Datum idx(PG_FUNCTION_ARGS)
Definition: _int_op.c:264
#define JB_ROOT_IS_SCALAR(jbp_)
Definition: jsonb.h:228
JsonbValue * pushJsonbValue(JsonbParseState **pstate, JsonbIteratorToken seq, JsonbValue *jbval)
Definition: jsonb_util.c:558
#define ERROR
Definition: elog.h:43
unsigned int uint32
Definition: c.h:358
#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:759
Definition: regguts.h:298
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:795
Definition: jsonb.h:25
#define PG_GETARG_JSONB_P(x)
Definition: jsonb.h:74

◆ jsonb_delete_path()

Datum jsonb_delete_path ( PG_FUNCTION_ARGS  )

Definition at line 4402 of file jsonfuncs.c.

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

4403 {
4404  Jsonb *in = PG_GETARG_JSONB_P(0);
4405  ArrayType *path = PG_GETARG_ARRAYTYPE_P(1);
4406  JsonbValue *res = NULL;
4407  Datum *path_elems;
4408  bool *path_nulls;
4409  int path_len;
4410  JsonbIterator *it;
4411  JsonbParseState *st = NULL;
4412 
4413  if (ARR_NDIM(path) > 1)
4414  ereport(ERROR,
4415  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
4416  errmsg("wrong number of array subscripts")));
4417 
4418  if (JB_ROOT_IS_SCALAR(in))
4419  ereport(ERROR,
4420  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4421  errmsg("cannot delete path in scalar")));
4422 
4423  if (JB_ROOT_COUNT(in) == 0)
4424  PG_RETURN_JSONB_P(in);
4425 
4426  deconstruct_array(path, TEXTOID, -1, false, 'i',
4427  &path_elems, &path_nulls, &path_len);
4428 
4429  if (path_len == 0)
4430  PG_RETURN_JSONB_P(in);
4431 
4432  it = JsonbIteratorInit(&in->root);
4433 
4434  res = setPath(&it, path_elems, path_nulls, path_len, &st,
4435  0, NULL, JB_PATH_DELETE);
4436 
4437  Assert(res != NULL);
4438 
4440 }
Jsonb * JsonbValueToJsonb(JsonbValue *val)
Definition: jsonb_util.c:84
Definition: jsonb.h:220
static JsonbValue * setPath(JsonbIterator **it, Datum *path_elems, bool *path_nulls, int path_len, JsonbParseState **st, int level, Jsonb *newval, int op_type)
Definition: jsonfuncs.c:4611
#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_ARRAYTYPE_P(n)
Definition: array.h:251
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:141
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:759
#define ARR_NDIM(a)
Definition: array.h:278
void deconstruct_array(ArrayType *array, Oid elmtype, int elmlen, bool elmbyval, char elmalign, Datum **elemsp, bool **nullsp, int *nelemsp)
Definition: arrayfuncs.c:3461
int errmsg(const char *fmt,...)
Definition: elog.c:784
#define PG_RETURN_JSONB_P(x)
Definition: jsonb.h:76
#define JB_PATH_DELETE
Definition: jsonfuncs.c:39
#define PG_GETARG_JSONB_P(x)
Definition: jsonb.h:74

◆ jsonb_each()

Datum jsonb_each ( PG_FUNCTION_ARGS  )

Definition at line 1628 of file jsonfuncs.c.

References each_worker_jsonb().

1629 {
1630  return each_worker_jsonb(fcinfo, "jsonb_each", false);
1631 }
static Datum each_worker_jsonb(FunctionCallInfo fcinfo, const char *funcname, bool as_text)
Definition: jsonfuncs.c:1646

◆ jsonb_each_text()

Datum jsonb_each_text ( PG_FUNCTION_ARGS  )

Definition at line 1640 of file jsonfuncs.c.

References each_worker_jsonb().

1641 {
1642  return each_worker_jsonb(fcinfo, "jsonb_each_text", true);
1643 }
static Datum each_worker_jsonb(FunctionCallInfo fcinfo, const char *funcname, bool as_text)
Definition: jsonfuncs.c:1646

◆ jsonb_extract_path()

Datum jsonb_extract_path ( PG_FUNCTION_ARGS  )

Definition at line 1313 of file jsonfuncs.c.

References get_jsonb_path_all().

1314 {
1315  return get_jsonb_path_all(fcinfo, false);
1316 }
static Datum get_jsonb_path_all(FunctionCallInfo fcinfo, bool as_text)
Definition: jsonfuncs.c:1325

◆ jsonb_extract_path_text()

Datum jsonb_extract_path_text ( PG_FUNCTION_ARGS  )

Definition at line 1319 of file jsonfuncs.c.

References get_jsonb_path_all().

1320 {
1321  return get_jsonb_path_all(fcinfo, true);
1322 }
static Datum get_jsonb_path_all(FunctionCallInfo fcinfo, bool as_text)
Definition: jsonfuncs.c:1325

◆ jsonb_insert()

Datum jsonb_insert ( PG_FUNCTION_ARGS  )

Definition at line 4446 of file jsonfuncs.c.

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

4447 {
4448  Jsonb *in = PG_GETARG_JSONB_P(0);
4449  ArrayType *path = PG_GETARG_ARRAYTYPE_P(1);
4451  bool after = PG_GETARG_BOOL(3);
4452  JsonbValue *res = NULL;
4453  Datum *path_elems;
4454  bool *path_nulls;
4455  int path_len;
4456  JsonbIterator *it;
4457  JsonbParseState *st = NULL;
4458 
4459  if (ARR_NDIM(path) > 1)
4460  ereport(ERROR,
4461  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
4462  errmsg("wrong number of array subscripts")));
4463 
4464  if (JB_ROOT_IS_SCALAR(in))
4465  ereport(ERROR,
4466  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4467  errmsg("cannot set path in scalar")));
4468 
4469  deconstruct_array(path, TEXTOID, -1, false, 'i',
4470  &path_elems, &path_nulls, &path_len);
4471 
4472  if (path_len == 0)
4473  PG_RETURN_JSONB_P(in);
4474 
4475  it = JsonbIteratorInit(&in->root);
4476 
4477  res = setPath(&it, path_elems, path_nulls, path_len, &st, 0, newval,
4479 
4480  Assert(res != NULL);
4481 
4483 }
Jsonb * JsonbValueToJsonb(JsonbValue *val)
Definition: jsonb_util.c:84
Definition: jsonb.h:220
static JsonbValue * setPath(JsonbIterator **it, Datum *path_elems, bool *path_nulls, int path_len, JsonbParseState **st, int level, Jsonb *newval, int op_type)
Definition: jsonfuncs.c:4611
int errcode(int sqlerrcode)
Definition: