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 "common/jsonapi.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/jsonb.h"
#include "utils/jsonfuncs.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 int report_json_context (JsonLexContext *lex)
 
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)
 
void pg_parse_json_or_ereport (JsonLexContext *lex, JsonSemAction *sem)
 
JsonLexContextmakeJsonLexContext (text *json, bool need_escapes)
 
Datum jsonb_object_keys (PG_FUNCTION_ARGS)
 
void json_ereport_error (JsonParseErrorType error, JsonLexContext *lex)
 
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_set_lax (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 39 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 44 of file jsonfuncs.c.

Referenced by setPathArray(), and setPathObject().

◆ JB_PATH_DELETE

#define JB_PATH_DELETE   0x0002

Definition at line 40 of file jsonfuncs.c.

Referenced by jsonb_delete_path(), and setPathObject().

◆ JB_PATH_INSERT_AFTER

#define JB_PATH_INSERT_AFTER   0x0010

Definition at line 43 of file jsonfuncs.c.

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

◆ JB_PATH_INSERT_BEFORE

#define JB_PATH_INSERT_BEFORE   0x0008

Definition at line 42 of file jsonfuncs.c.

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

◆ JB_PATH_REPLACE

#define JB_PATH_REPLACE   0x0004

Definition at line 41 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:664

Definition at line 326 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:1337
long val
Definition: informix.c:664

Definition at line 320 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:664

Definition at line 311 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:664

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

Function Documentation

◆ addJsonbToParseState()

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

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

4166 {
4167  JsonbIterator *it;
4168  JsonbValue *o = &(*jbps)->contVal;
4169  JsonbValue v;
4171 
4172  it = JsonbIteratorInit(&jb->root);
4173 
4174  Assert(o->type == jbvArray || o->type == jbvObject);
4175 
4176  if (JB_ROOT_IS_SCALAR(jb))
4177  {
4178  (void) JsonbIteratorNext(&it, &v, false); /* skip array header */
4179  Assert(v.type == jbvArray);
4180  (void) JsonbIteratorNext(&it, &v, false); /* fetch scalar value */
4181 
4182  switch (o->type)
4183  {
4184  case jbvArray:
4185  (void) pushJsonbValue(jbps, WJB_ELEM, &v);
4186  break;
4187  case jbvObject:
4188  (void) pushJsonbValue(jbps, WJB_VALUE, &v);
4189  break;
4190  default:
4191  elog(ERROR, "unexpected parent of nested structure");
4192  }
4193  }
4194  else
4195  {
4196  while ((type = JsonbIteratorNext(&it, &v, false)) != WJB_DONE)
4197  {
4198  if (type == WJB_KEY || type == WJB_VALUE || type == WJB_ELEM)
4199  (void) pushJsonbValue(jbps, type, &v);
4200  else
4201  (void) pushJsonbValue(jbps, type, NULL);
4202  }
4203  }
4204 
4205 }
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:559
#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:738
JsonbIterator * JsonbIteratorInit(JsonbContainer *container)
Definition: jsonb_util.c:760
enum jbvType type
Definition: jsonb.h:263
#define elog(elevel,...)
Definition: elog.h:214
JsonbIteratorToken JsonbIteratorNext(JsonbIterator **it, JsonbValue *val, bool skipNested)
Definition: jsonb_util.c:796
Definition: jsonb.h:25

◆ alen_array_element_start()

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

Definition at line 1721 of file jsonfuncs.c.

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

Referenced by json_array_length().

1722 {
1723  AlenState *_state = (AlenState *) state;
1724 
1725  /* just count up all the level 1 elements */
1726  if (_state->lex->lex_level == 1)
1727  _state->count++;
1728 }
int count
Definition: jsonfuncs.c:98
int lex_level
Definition: jsonapi.h:81
JsonLexContext * lex
Definition: jsonfuncs.c:97
Definition: regguts.h:298

◆ alen_object_start()

static void alen_object_start ( void *  state)
static

Definition at line 1697 of file jsonfuncs.c.

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

Referenced by json_array_length().

1698 {
1699  AlenState *_state = (AlenState *) state;
1700 
1701  /* json structure check */
1702  if (_state->lex->lex_level == 0)
1703  ereport(ERROR,
1704  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1705  errmsg("cannot get array length of a non-array")));
1706 }
int errcode(int sqlerrcode)
Definition: elog.c:610
int lex_level
Definition: jsonapi.h:81
#define ERROR
Definition: elog.h:43
JsonLexContext * lex
Definition: jsonfuncs.c:97
#define ereport(elevel,...)
Definition: elog.h:144
Definition: regguts.h:298
int errmsg(const char *fmt,...)
Definition: elog.c:824

◆ alen_scalar()

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

Definition at line 1709 of file jsonfuncs.c.

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

Referenced by json_array_length().

1710 {
1711  AlenState *_state = (AlenState *) state;
1712 
1713  /* json structure check */
1714  if (_state->lex->lex_level == 0)
1715  ereport(ERROR,
1716  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1717  errmsg("cannot get array length of a scalar")));
1718 }
int errcode(int sqlerrcode)
Definition: elog.c:610
int lex_level
Definition: jsonapi.h:81
#define ERROR
Definition: elog.h:43
JsonLexContext * lex
Definition: jsonfuncs.c:97
#define ereport(elevel,...)
Definition: elog.h:144
Definition: regguts.h:298
int errmsg(const char *fmt,...)
Definition: elog.c:824

◆ allocate_record_info()

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

Definition at line 3108 of file jsonfuncs.c.

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

Referenced by populate_record().

3109 {
3110  RecordIOData *data = (RecordIOData *)
3111  MemoryContextAlloc(mcxt,
3112  offsetof(RecordIOData, columns) +
3113  ncolumns * sizeof(ColumnIOData));
3114 
3115  data->record_type = InvalidOid;
3116  data->record_typmod = 0;
3117  data->ncolumns = ncolumns;
3118  MemSet(data->columns, 0, sizeof(ColumnIOData) * ncolumns);
3119 
3120  return data;
3121 }
Oid record_type
Definition: hstore_io.c:758
struct ColumnIOData ColumnIOData
Definition: jsonfuncs.c:155
#define MemSet(start, val, len)
Definition: c.h:971
int32 record_typmod
Definition: hstore_io.c:759
ColumnIOData columns[FLEXIBLE_ARRAY_MEMBER]
Definition: hstore_io.c:763
#define InvalidOid
Definition: postgres_ext.h:36
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:796
#define offsetof(type, field)
Definition: c.h:661

◆ each_array_start()

static void each_array_start ( void *  state)
static

Definition at line 2013 of file jsonfuncs.c.

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

Referenced by each_worker().

2014 {
2015  EachState *_state = (EachState *) state;
2016 
2017  /* json structure check */
2018  if (_state->lex->lex_level == 0)
2019  ereport(ERROR,
2020  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2021  errmsg("cannot deconstruct an array as an object")));
2022 }
int errcode(int sqlerrcode)
Definition: elog.c:610
int lex_level
Definition: jsonapi.h:81
#define ERROR
Definition: elog.h:43
JsonLexContext * lex
Definition: jsonfuncs.c:104
#define ereport(elevel,...)
Definition: elog.h:144
Definition: regguts.h:298
int errmsg(const char *fmt,...)
Definition: elog.c:824

◆ each_object_field_end()

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

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

1968 {
1969  EachState *_state = (EachState *) state;
1970  MemoryContext old_cxt;
1971  int len;
1972  text *val;
1973  HeapTuple tuple;
1974  Datum values[2];
1975  bool nulls[2] = {false, false};
1976 
1977  /* skip over nested objects */
1978  if (_state->lex->lex_level != 1)
1979  return;
1980 
1981  /* use the tmp context so we can clean up after each tuple is done */
1982  old_cxt = MemoryContextSwitchTo(_state->tmp_cxt);
1983 
1984  values[0] = CStringGetTextDatum(fname);
1985 
1986  if (isnull && _state->normalize_results)
1987  {
1988  nulls[1] = true;
1989  values[1] = (Datum) 0;
1990  }
1991  else if (_state->next_scalar)
1992  {
1993  values[1] = CStringGetTextDatum(_state->normalized_scalar);
1994  _state->next_scalar = false;
1995  }
1996  else
1997  {
1998  len = _state->lex->prev_token_terminator - _state->result_start;
1999  val = cstring_to_text_with_len(_state->result_start, len);
2000  values[1] = PointerGetDatum(val);
2001  }
2002 
2003  tuple = heap_form_tuple(_state->ret_tdesc, values, nulls);
2004 
2005  tuplestore_puttuple(_state->tuple_store, tuple);
2006 
2007  /* clean up and switch back */
2008  MemoryContextSwitchTo(old_cxt);
2009  MemoryContextReset(_state->tmp_cxt);
2010 }
Tuplestorestate * tuple_store
Definition: jsonfuncs.c:105
#define PointerGetDatum(X)
Definition: postgres.h:556
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
char * prev_token_terminator
Definition: jsonapi.h:79
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:106
int lex_level
Definition: jsonapi.h:81
MemoryContext tmp_cxt
Definition: jsonfuncs.c:107
char * result_start
Definition: jsonfuncs.c:108
JsonLexContext * lex
Definition: jsonfuncs.c:104
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:184
uintptr_t Datum
Definition: postgres.h:367
bool normalize_results
Definition: jsonfuncs.c:109
char * normalized_scalar
Definition: jsonfuncs.c:111
Definition: regguts.h:298
static Datum values[MAXATTR]
Definition: bootstrap.c:167
#define CStringGetTextDatum(s)
Definition: builtins.h:87
Definition: c.h:555
long val
Definition: informix.c:664
bool next_scalar
Definition: jsonfuncs.c:110

◆ each_object_field_start()

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

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

1948 {
1949  EachState *_state = (EachState *) state;
1950 
1951  /* save a pointer to where the value starts */
1952  if (_state->lex->lex_level == 1)
1953  {
1954  /*
1955  * next_scalar will be reset in the object_field_end handler, and
1956  * since we know the value is a scalar there is no danger of it being
1957  * on while recursing down the tree.
1958  */
1959  if (_state->normalize_results && _state->lex->token_type == JSON_TOKEN_STRING)
1960  _state->next_scalar = true;
1961  else
1962  _state->result_start = _state->lex->token_start;
1963  }
1964 }
JsonTokenType token_type
Definition: jsonapi.h:80
int lex_level
Definition: jsonapi.h:81
char * result_start
Definition: jsonfuncs.c:108
JsonLexContext * lex
Definition: jsonfuncs.c:104
char * token_start
Definition: jsonapi.h:77
bool normalize_results
Definition: jsonfuncs.c:109
Definition: regguts.h:298
bool next_scalar
Definition: jsonfuncs.c:110

◆ each_scalar()

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

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

2026 {
2027  EachState *_state = (EachState *) state;
2028 
2029  /* json structure check */
2030  if (_state->lex->lex_level == 0)
2031  ereport(ERROR,
2032  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2033  errmsg("cannot deconstruct a scalar")));
2034 
2035  /* supply de-escaped value if required */
2036  if (_state->next_scalar)
2037  _state->normalized_scalar = token;
2038 }
int errcode(int sqlerrcode)
Definition: elog.c:610
int lex_level
Definition: jsonapi.h:81
#define ERROR
Definition: elog.h:43
JsonLexContext * lex
Definition: jsonfuncs.c:104
#define ereport(elevel,...)
Definition: elog.h:144
char * normalized_scalar
Definition: jsonfuncs.c:111
Definition: regguts.h:298
int errmsg(const char *fmt,...)
Definition: elog.c:824
bool next_scalar
Definition: jsonfuncs.c:110

◆ each_worker()

static Datum each_worker ( FunctionCallInfo  fcinfo,
bool  as_text 
)
static

Definition at line 1883 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_or_ereport(), 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().

1884 {
1885  text *json = PG_GETARG_TEXT_PP(0);
1886  JsonLexContext *lex;
1887  JsonSemAction *sem;
1888  ReturnSetInfo *rsi;
1889  MemoryContext old_cxt;
1890  TupleDesc tupdesc;
1891  EachState *state;
1892 
1893  lex = makeJsonLexContext(json, true);
1894  state = palloc0(sizeof(EachState));
1895  sem = palloc0(sizeof(JsonSemAction));
1896 
1897  rsi = (ReturnSetInfo *) fcinfo->resultinfo;
1898 
1899  if (!rsi || !IsA(rsi, ReturnSetInfo) ||
1900  (rsi->allowedModes & SFRM_Materialize) == 0 ||
1901  rsi->expectedDesc == NULL)
1902  ereport(ERROR,
1903  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1904  errmsg("set-valued function called in context that "
1905  "cannot accept a set")));
1906 
1908 
1909  (void) get_call_result_type(fcinfo, NULL, &tupdesc);
1910 
1911  /* make these in a sufficiently long-lived memory context */
1913 
1914  state->ret_tdesc = CreateTupleDescCopy(tupdesc);
1915  BlessTupleDesc(state->ret_tdesc);
1916  state->tuple_store =
1918  false, work_mem);
1919 
1920  MemoryContextSwitchTo(old_cxt);
1921 
1922  sem->semstate = (void *) state;
1924  sem->scalar = each_scalar;
1927 
1928  state->normalize_results = as_text;
1929  state->next_scalar = false;
1930  state->lex = lex;
1932  "json_each temporary cxt",
1934 
1935  pg_parse_json_or_ereport(lex, sem);
1936 
1937  MemoryContextDelete(state->tmp_cxt);
1938 
1939  rsi->setResult = state->tuple_store;
1940  rsi->setDesc = state->ret_tdesc;
1941 
1942  PG_RETURN_NULL();
1943 }
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
Definition: tupdesc.c:110
#define IsA(nodeptr, _type_)
Definition: nodes.h:580
Tuplestorestate * tuple_store
Definition: jsonfuncs.c:105
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:1947
TypeFuncClass get_call_result_type(FunctionCallInfo fcinfo, Oid *resultTypeId, TupleDesc *resultTupleDesc)
Definition: funcapi.c:205
JsonLexContext * makeJsonLexContext(text *json, bool need_escapes)
Definition: jsonfuncs.c:513
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
int errcode(int sqlerrcode)
Definition: elog.c:610
json_scalar_action scalar
Definition: jsonapi.h:115
static void each_array_start(void *state)
Definition: jsonfuncs.c:2013
TupleDesc ret_tdesc
Definition: jsonfuncs.c:106
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:308
MemoryContext tmp_cxt
Definition: jsonfuncs.c:107
static void each_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:2025
TupleDesc expectedDesc
Definition: execnodes.h:304
#define ERROR
Definition: elog.h:43
fmNodePtr resultinfo
Definition: fmgr.h:89
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:192
JsonLexContext * lex
Definition: jsonfuncs.c:104
TupleDesc BlessTupleDesc(TupleDesc tupdesc)
Definition: execTuples.c:2052
MemoryContext CurrentMemoryContext
Definition: mcxt.c:38
json_ofield_action object_field_end
Definition: jsonapi.h:112
void pg_parse_json_or_ereport(JsonLexContext *lex, JsonSemAction *sem)
Definition: jsonfuncs.c:497
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:109
int work_mem
Definition: globals.c:121
#define ereport(elevel,...)
Definition: elog.h:144
int allowedModes
Definition: execnodes.h:305
SetFunctionReturnMode returnMode
Definition: execnodes.h:307
json_struct_action array_start
Definition: jsonapi.h:109
Definition: regguts.h:298
MemoryContext ecxt_per_query_memory
Definition: execnodes.h:233
Tuplestorestate * setResult
Definition: execnodes.h:310
ExprContext * econtext
Definition: execnodes.h:303
TupleDesc setDesc
Definition: execnodes.h:311
int errmsg(const char *fmt,...)
Definition: elog.c:824
Definition: c.h:555
json_ofield_action object_field_start
Definition: jsonapi.h:111
void * semstate
Definition: jsonapi.h:106
static void each_object_field_end(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:1967
#define PG_RETURN_NULL()
Definition: fmgr.h:344
bool next_scalar
Definition: jsonfuncs.c:110

◆ each_worker_jsonb()

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

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

1766 {
1767  Jsonb *jb = PG_GETARG_JSONB_P(0);
1768  ReturnSetInfo *rsi;
1769  Tuplestorestate *tuple_store;
1770  TupleDesc tupdesc;
1771  TupleDesc ret_tdesc;
1772  MemoryContext old_cxt,
1773  tmp_cxt;
1774  bool skipNested = false;
1775  JsonbIterator *it;
1776  JsonbValue v;
1778 
1779  if (!JB_ROOT_IS_OBJECT(jb))
1780  ereport(ERROR,
1781  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1782  errmsg("cannot call %s on a non-object",
1783  funcname)));
1784 
1785  rsi = (ReturnSetInfo *) fcinfo->resultinfo;
1786 
1787  if (!rsi || !IsA(rsi, ReturnSetInfo) ||
1788  (rsi->allowedModes & SFRM_Materialize) == 0 ||
1789  rsi->expectedDesc == NULL)
1790  ereport(ERROR,
1791  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1792  errmsg("set-valued function called in context that "
1793  "cannot accept a set")));
1794 
1796 
1797  if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
1798  ereport(ERROR,
1799  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1800  errmsg("function returning record called in context "
1801  "that cannot accept type record")));
1802 
1804 
1805  ret_tdesc = CreateTupleDescCopy(tupdesc);
1806  BlessTupleDesc(ret_tdesc);
1807  tuple_store =
1809  false, work_mem);
1810 
1811  MemoryContextSwitchTo(old_cxt);
1812 
1814  "jsonb_each temporary cxt",
1816 
1817  it = JsonbIteratorInit(&jb->root);
1818 
1819  while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE)
1820  {
1821  skipNested = true;
1822 
1823  if (r == WJB_KEY)
1824  {
1825  text *key;
1826  HeapTuple tuple;
1827  Datum values[2];
1828  bool nulls[2] = {false, false};
1829 
1830  /* Use the tmp context so we can clean up after each tuple is done */
1831  old_cxt = MemoryContextSwitchTo(tmp_cxt);
1832 
1833  key = cstring_to_text_with_len(v.val.string.val, v.val.string.len);
1834 
1835  /*
1836  * The next thing the iterator fetches should be the value, no
1837  * matter what shape it is.
1838  */
1839  r = JsonbIteratorNext(&it, &v, skipNested);
1840  Assert(r != WJB_DONE);
1841 
1842  values[0] = PointerGetDatum(key);
1843 
1844  if (as_text)
1845  {
1846  if (v.type == jbvNull)
1847  {
1848  /* a json null is an sql null in text mode */
1849  nulls[1] = true;
1850  values[1] = (Datum) NULL;
1851  }
1852  else
1853  values[1] = PointerGetDatum(JsonbValueAsText(&v));
1854  }
1855  else
1856  {
1857  /* Not in text mode, just return the Jsonb */
1858  Jsonb *val = JsonbValueToJsonb(&v);
1859 
1860  values[1] = PointerGetDatum(val);
1861  }
1862 
1863  tuple = heap_form_tuple(ret_tdesc, values, nulls);
1864 
1865  tuplestore_puttuple(tuple_store, tuple);
1866 
1867  /* clean up and switch back */
1868  MemoryContextSwitchTo(old_cxt);
1869  MemoryContextReset(tmp_cxt);
1870  }
1871  }
1872 
1873  MemoryContextDelete(tmp_cxt);
1874 
1875  rsi->setResult = tuple_store;
1876  rsi->setDesc = ret_tdesc;
1877 
1878  PG_RETURN_NULL();
1879 }
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
Definition: tupdesc.c:110
#define IsA(nodeptr, _type_)
Definition: nodes.h:580
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:205
Jsonb * JsonbValueToJsonb(JsonbValue *val)
Definition: jsonb_util.c:85
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:610
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:1600
TupleDesc expectedDesc
Definition: execnodes.h:304
#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:2052
text * cstring_to_text_with_len(const char *s, int len)
Definition: varlena.c:184
Definition: jsonb.h:23
MemoryContext CurrentMemoryContext
Definition: mcxt.c:38
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
#define ereport(elevel,...)
Definition: elog.h:144
int allowedModes
Definition: execnodes.h:305
SetFunctionReturnMode returnMode
Definition: execnodes.h:307
#define Assert(condition)
Definition: c.h:738
JsonbIterator * JsonbIteratorInit(JsonbContainer *container)
Definition: jsonb_util.c:760
MemoryContext ecxt_per_query_memory
Definition: execnodes.h:233
enum jbvType type
Definition: jsonb.h:263
Tuplestorestate * setResult
Definition: execnodes.h:310
static Datum values[MAXATTR]
Definition: bootstrap.c:167
ExprContext * econtext
Definition: execnodes.h:303
TupleDesc setDesc
Definition: execnodes.h:311
int errmsg(const char *fmt,...)
Definition: elog.c:824
Definition: c.h:555
long val
Definition: informix.c:664
#define PG_RETURN_NULL()
Definition: fmgr.h:344
JsonbIteratorToken JsonbIteratorNext(JsonbIterator **it, JsonbValue *val, bool skipNested)
Definition: jsonb_util.c:796
#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 2265 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().

2266 {
2267  ElementsState *_state = (ElementsState *) state;
2268  MemoryContext old_cxt;
2269  int len;
2270  text *val;
2271  HeapTuple tuple;
2272  Datum values[1];
2273  bool nulls[1] = {false};
2274 
2275  /* skip over nested objects */
2276  if (_state->lex->lex_level != 1)
2277  return;
2278 
2279  /* use the tmp context so we can clean up after each tuple is done */
2280  old_cxt = MemoryContextSwitchTo(_state->tmp_cxt);
2281 
2282  if (isnull && _state->normalize_results)
2283  {
2284  nulls[0] = true;
2285  values[0] = (Datum) NULL;
2286  }
2287  else if (_state->next_scalar)
2288  {
2289  values[0] = CStringGetTextDatum(_state->normalized_scalar);
2290  _state->next_scalar = false;
2291  }
2292  else
2293  {
2294  len = _state->lex->prev_token_terminator - _state->result_start;
2295  val = cstring_to_text_with_len(_state->result_start, len);
2296  values[0] = PointerGetDatum(val);
2297  }
2298 
2299  tuple = heap_form_tuple(_state->ret_tdesc, values, nulls);
2300 
2301  tuplestore_puttuple(_state->tuple_store, tuple);
2302 
2303  /* clean up and switch back */
2304  MemoryContextSwitchTo(old_cxt);
2305  MemoryContextReset(_state->tmp_cxt);
2306 }
bool normalize_results
Definition: jsonfuncs.c:123
JsonLexContext * lex
Definition: jsonfuncs.c:117
bool next_scalar
Definition: jsonfuncs.c:124
#define PointerGetDatum(X)
Definition: postgres.h:556
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
char * prev_token_terminator
Definition: jsonapi.h:79
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:81
TupleDesc ret_tdesc
Definition: jsonfuncs.c:120
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:184
uintptr_t Datum
Definition: postgres.h:367
Tuplestorestate * tuple_store
Definition: jsonfuncs.c:119
char * result_start
Definition: jsonfuncs.c:122
Definition: regguts.h:298
static Datum values[MAXATTR]
Definition: bootstrap.c:167
char * normalized_scalar
Definition: jsonfuncs.c:125
#define CStringGetTextDatum(s)
Definition: builtins.h:87
MemoryContext tmp_cxt
Definition: jsonfuncs.c:121
Definition: c.h:555
long val
Definition: informix.c:664

◆ elements_array_element_start()

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

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

2246 {
2247  ElementsState *_state = (ElementsState *) state;
2248 
2249  /* save a pointer to where the value starts */
2250  if (_state->lex->lex_level == 1)
2251  {
2252  /*
2253  * next_scalar will be reset in the array_element_end handler, and
2254  * since we know the value is a scalar there is no danger of it being
2255  * on while recursing down the tree.
2256  */
2257  if (_state->normalize_results && _state->lex->token_type == JSON_TOKEN_STRING)
2258  _state->next_scalar = true;
2259  else
2260  _state->result_start = _state->lex->token_start;
2261  }
2262 }
bool normalize_results
Definition: jsonfuncs.c:123
JsonLexContext * lex
Definition: jsonfuncs.c:117
bool next_scalar
Definition: jsonfuncs.c:124
JsonTokenType token_type
Definition: jsonapi.h:80
int lex_level
Definition: jsonapi.h:81
char * token_start
Definition: jsonapi.h:77
char * result_start
Definition: jsonfuncs.c:122
Definition: regguts.h:298

◆ elements_object_start()

static void elements_object_start ( void *  state)
static

Definition at line 2309 of file jsonfuncs.c.

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

Referenced by elements_worker().

2310 {
2311  ElementsState *_state = (ElementsState *) state;
2312 
2313  /* json structure check */
2314  if (_state->lex->lex_level == 0)
2315  ereport(ERROR,
2316  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2317  errmsg("cannot call %s on a non-array",
2318  _state->function_name)));
2319 }
const char * function_name
Definition: jsonfuncs.c:118
JsonLexContext * lex
Definition: jsonfuncs.c:117
int errcode(int sqlerrcode)
Definition: elog.c:610
int lex_level
Definition: jsonapi.h:81
#define ERROR
Definition: elog.h:43
#define ereport(elevel,...)
Definition: elog.h:144
Definition: regguts.h:298
int errmsg(const char *fmt,...)
Definition: elog.c:824

◆ elements_scalar()

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

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

2323 {
2324  ElementsState *_state = (ElementsState *) state;
2325 
2326  /* json structure check */
2327  if (_state->lex->lex_level == 0)
2328  ereport(ERROR,
2329  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2330  errmsg("cannot call %s on a scalar",
2331  _state->function_name)));
2332 
2333  /* supply de-escaped value if required */
2334  if (_state->next_scalar)
2335  _state->normalized_scalar = token;
2336 }
const char * function_name
Definition: jsonfuncs.c:118
JsonLexContext * lex
Definition: jsonfuncs.c:117
bool next_scalar
Definition: jsonfuncs.c:124
int errcode(int sqlerrcode)
Definition: elog.c:610
int lex_level
Definition: jsonapi.h:81
#define ERROR
Definition: elog.h:43
#define ereport(elevel,...)
Definition: elog.h:144
Definition: regguts.h:298
char * normalized_scalar
Definition: jsonfuncs.c:125
int errmsg(const char *fmt,...)
Definition: elog.c:824

◆ elements_worker()

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

Definition at line 2179 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_or_ereport(), 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().

2180 {
2181  text *json = PG_GETARG_TEXT_PP(0);
2182 
2183  /* elements only needs escaped strings when as_text */
2184  JsonLexContext *lex = makeJsonLexContext(json, as_text);
2185  JsonSemAction *sem;
2186  ReturnSetInfo *rsi;
2187  MemoryContext old_cxt;
2188  TupleDesc tupdesc;
2190 
2191  state = palloc0(sizeof(ElementsState));
2192  sem = palloc0(sizeof(JsonSemAction));
2193 
2194  rsi = (ReturnSetInfo *) fcinfo->resultinfo;
2195 
2196  if (!rsi || !IsA(rsi, ReturnSetInfo) ||
2197  (rsi->allowedModes & SFRM_Materialize) == 0 ||
2198  rsi->expectedDesc == NULL)
2199  ereport(ERROR,
2200  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2201  errmsg("set-valued function called in context that "
2202  "cannot accept a set")));
2203 
2205 
2206  /* it's a simple type, so don't use get_call_result_type() */
2207  tupdesc = rsi->expectedDesc;
2208 
2209  /* make these in a sufficiently long-lived memory context */
2211 
2212  state->ret_tdesc = CreateTupleDescCopy(tupdesc);
2213  BlessTupleDesc(state->ret_tdesc);
2214  state->tuple_store =
2216  false, work_mem);
2217 
2218  MemoryContextSwitchTo(old_cxt);
2219 
2220  sem->semstate = (void *) state;
2222  sem->scalar = elements_scalar;
2225 
2226  state->function_name = funcname;
2227  state->normalize_results = as_text;
2228  state->next_scalar = false;
2229  state->lex = lex;
2231  "json_array_elements temporary cxt",
2233 
2234  pg_parse_json_or_ereport(lex, sem);
2235 
2236  MemoryContextDelete(state->tmp_cxt);
2237 
2238  rsi->setResult = state->tuple_store;
2239  rsi->setDesc = state->ret_tdesc;
2240 
2241  PG_RETURN_NULL();
2242 }
bool normalize_results
Definition: jsonfuncs.c:123
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
Definition: tupdesc.c:110
#define IsA(nodeptr, _type_)
Definition: nodes.h:580
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:211
#define AllocSetContextCreate
Definition: memutils.h:170
const char * function_name
Definition: jsonfuncs.c:118
JsonLexContext * lex
Definition: jsonfuncs.c:117
static void elements_object_start(void *state)
Definition: jsonfuncs.c:2309
bool next_scalar
Definition: jsonfuncs.c:124
json_struct_action object_start
Definition: jsonapi.h:107
JsonLexContext * makeJsonLexContext(text *json, bool need_escapes)
Definition: jsonfuncs.c:513
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
int errcode(int sqlerrcode)
Definition: elog.c:610
json_scalar_action scalar
Definition: jsonapi.h:115
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:308
TupleDesc expectedDesc
Definition: execnodes.h:304
TupleDesc ret_tdesc
Definition: jsonfuncs.c:120
#define ERROR
Definition: elog.h:43
fmNodePtr resultinfo
Definition: fmgr.h:89
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:192
TupleDesc BlessTupleDesc(TupleDesc tupdesc)
Definition: execTuples.c:2052
MemoryContext CurrentMemoryContext
Definition: mcxt.c:38
static void elements_array_element_start(void *state, bool isnull)
Definition: jsonfuncs.c:2245
void pg_parse_json_or_ereport(JsonLexContext *lex, JsonSemAction *sem)
Definition: jsonfuncs.c:497
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:2265
void * palloc0(Size size)
Definition: mcxt.c:980
static void elements_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:2322
json_aelem_action array_element_start
Definition: jsonapi.h:113
Tuplestorestate * tuple_store
Definition: jsonfuncs.c:119
int work_mem
Definition: globals.c:121
#define ereport(elevel,...)
Definition: elog.h:144
int allowedModes
Definition: execnodes.h:305
SetFunctionReturnMode returnMode
Definition: execnodes.h:307
Definition: regguts.h:298
MemoryContext ecxt_per_query_memory
Definition: execnodes.h:233
Tuplestorestate * setResult
Definition: execnodes.h:310
ExprContext * econtext
Definition: execnodes.h:303
TupleDesc setDesc
Definition: execnodes.h:311
int errmsg(const char *fmt,...)
Definition: elog.c:824
MemoryContext tmp_cxt
Definition: jsonfuncs.c:121
Definition: c.h:555
void * semstate
Definition: jsonapi.h:106
#define PG_RETURN_NULL()
Definition: fmgr.h:344
json_aelem_action array_element_end
Definition: jsonapi.h:114

◆ elements_worker_jsonb()

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

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

2063 {
2064  Jsonb *jb = PG_GETARG_JSONB_P(0);
2065  ReturnSetInfo *rsi;
2066  Tuplestorestate *tuple_store;
2067  TupleDesc tupdesc;
2068  TupleDesc ret_tdesc;
2069  MemoryContext old_cxt,
2070  tmp_cxt;
2071  bool skipNested = false;
2072  JsonbIterator *it;
2073  JsonbValue v;
2075 
2076  if (JB_ROOT_IS_SCALAR(jb))
2077  ereport(ERROR,
2078  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2079  errmsg("cannot extract elements from a scalar")));
2080  else if (!JB_ROOT_IS_ARRAY(jb))
2081  ereport(ERROR,
2082  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2083  errmsg("cannot extract elements from an object")));
2084 
2085  rsi = (ReturnSetInfo *) fcinfo->resultinfo;
2086 
2087  if (!rsi || !IsA(rsi, ReturnSetInfo) ||
2088  (rsi->allowedModes & SFRM_Materialize) == 0 ||
2089  rsi->expectedDesc == NULL)
2090  ereport(ERROR,
2091  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2092  errmsg("set-valued function called in context that "
2093  "cannot accept a set")));
2094 
2096 
2097  /* it's a simple type, so don't use get_call_result_type() */
2098  tupdesc = rsi->expectedDesc;
2099 
2101 
2102  ret_tdesc = CreateTupleDescCopy(tupdesc);
2103  BlessTupleDesc(ret_tdesc);
2104  tuple_store =
2106  false, work_mem);
2107 
2108  MemoryContextSwitchTo(old_cxt);
2109 
2111  "jsonb_array_elements temporary cxt",
2113 
2114  it = JsonbIteratorInit(&jb->root);
2115 
2116  while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE)
2117  {
2118  skipNested = true;
2119 
2120  if (r == WJB_ELEM)
2121  {
2122  HeapTuple tuple;
2123  Datum values[1];
2124  bool nulls[1] = {false};
2125 
2126  /* use the tmp context so we can clean up after each tuple is done */
2127  old_cxt = MemoryContextSwitchTo(tmp_cxt);
2128 
2129  if (as_text)
2130  {
2131  if (v.type == jbvNull)
2132  {
2133  /* a json null is an sql null in text mode */
2134  nulls[0] = true;
2135  values[0] = (Datum) NULL;
2136  }
2137  else
2138  values[0] = PointerGetDatum(JsonbValueAsText(&v));
2139  }
2140  else
2141  {
2142  /* Not in text mode, just return the Jsonb */
2143  Jsonb *val = JsonbValueToJsonb(&v);
2144 
2145  values[0] = PointerGetDatum(val);
2146  }
2147 
2148  tuple = heap_form_tuple(ret_tdesc, values, nulls);
2149 
2150  tuplestore_puttuple(tuple_store, tuple);
2151 
2152  /* clean up and switch back */
2153  MemoryContextSwitchTo(old_cxt);
2154  MemoryContextReset(tmp_cxt);
2155  }
2156  }
2157 
2158  MemoryContextDelete(tmp_cxt);
2159 
2160  rsi->setResult = tuple_store;
2161  rsi->setDesc = ret_tdesc;
2162 
2163  PG_RETURN_NULL();
2164 }
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
Definition: tupdesc.c:110
#define IsA(nodeptr, _type_)
Definition: nodes.h:580
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:211
#define AllocSetContextCreate
Definition: memutils.h:170
Jsonb * JsonbValueToJsonb(JsonbValue *val)
Definition: jsonb_util.c:85
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:610
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:1600
#define JB_ROOT_IS_SCALAR(jbp_)
Definition: jsonb.h:228
TupleDesc expectedDesc
Definition: execnodes.h:304
#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:2052
MemoryContext CurrentMemoryContext
Definition: mcxt.c:38
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
#define ereport(elevel,...)
Definition: elog.h:144
int allowedModes
Definition: execnodes.h:305
SetFunctionReturnMode returnMode
Definition: execnodes.h:307
JsonbIterator * JsonbIteratorInit(JsonbContainer *container)
Definition: jsonb_util.c:760
MemoryContext ecxt_per_query_memory
Definition: execnodes.h:233
enum jbvType type
Definition: jsonb.h:263
Tuplestorestate * setResult
Definition: execnodes.h:310
static Datum values[MAXATTR]
Definition: bootstrap.c:167
ExprContext * econtext
Definition: execnodes.h:303
TupleDesc setDesc
Definition: execnodes.h:311
int errmsg(const char *fmt,...)
Definition: elog.c:824
long val
Definition: informix.c:664
#define PG_RETURN_NULL()
Definition: fmgr.h:344
JsonbIteratorToken JsonbIteratorNext(JsonbIterator **it, JsonbValue *val, bool skipNested)
Definition: jsonb_util.c:796
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 1349 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().

1350 {
1351  GetState *_state = (GetState *) state;
1352  bool get_last = false;
1353  int lex_level = _state->lex->lex_level;
1354 
1355  /* same tests as in get_array_element_start */
1356  if (lex_level <= _state->npath &&
1357  _state->pathok[lex_level - 1] &&
1358  _state->path_indexes != NULL &&
1359  _state->array_cur_index[lex_level - 1] == _state->path_indexes[lex_level - 1])
1360  {
1361  if (lex_level < _state->npath)
1362  {
1363  /* done with this element so reset pathok */
1364  _state->pathok[lex_level] = false;
1365  }
1366  else
1367  {
1368  /* end of path, so we want this value */
1369  get_last = true;
1370  }
1371  }
1372 
1373  /* same logic as for objects */
1374  if (get_last && _state->result_start != NULL)
1375  {
1376  if (isnull && _state->normalize_results)
1377  _state->tresult = (text *) NULL;
1378  else
1379  {
1380  char *start = _state->result_start;
1381  int len = _state->lex->prev_token_terminator - start;
1382 
1383  _state->tresult = cstring_to_text_with_len(start, len);
1384  }
1385 
1386  _state->result_start = NULL;
1387  }
1388 }
int * array_cur_index
Definition: jsonfuncs.c:90
char * prev_token_terminator
Definition: jsonapi.h:79
int lex_level
Definition: jsonapi.h:81
JsonLexContext * lex
Definition: jsonfuncs.c:81
char * result_start
Definition: jsonfuncs.c:83
text * tresult
Definition: jsonfuncs.c:82
text * cstring_to_text_with_len(const char *s, int len)
Definition: varlena.c:184
bool * pathok
Definition: jsonfuncs.c:89
bool normalize_results
Definition: jsonfuncs.c:84
Definition: regguts.h:298
int * path_indexes
Definition: jsonfuncs.c:88
Definition: c.h:555

◆ get_array_element_start()

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

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

1304 {
1305  GetState *_state = (GetState *) state;
1306  bool get_next = false;
1307  int lex_level = _state->lex->lex_level;
1308 
1309  /* Update array element counter */
1310  if (lex_level <= _state->npath)
1311  _state->array_cur_index[lex_level - 1]++;
1312 
1313  if (lex_level <= _state->npath &&
1314  _state->pathok[lex_level - 1] &&
1315  _state->path_indexes != NULL &&
1316  _state->array_cur_index[lex_level - 1] == _state->path_indexes[lex_level - 1])
1317  {
1318  if (lex_level < _state->npath)
1319  {
1320  /* if not at end of path just mark path ok */
1321  _state->pathok[lex_level] = true;
1322  }
1323  else
1324  {
1325  /* end of path, so we want this value */
1326  get_next = true;
1327  }
1328  }
1329 
1330  /* same logic as for objects */
1331  if (get_next)
1332  {
1333  _state->tresult = NULL;
1334  _state->result_start = NULL;
1335 
1336  if (_state->normalize_results &&
1337  _state->lex->token_type == JSON_TOKEN_STRING)
1338  {
1339  _state->next_scalar = true;
1340  }
1341  else
1342  {
1343  _state->result_start = _state->lex->token_start;
1344  }
1345  }
1346 }
int * array_cur_index
Definition: jsonfuncs.c:90
JsonTokenType token_type
Definition: jsonapi.h:80
int lex_level
Definition: jsonapi.h:81
JsonLexContext * lex
Definition: jsonfuncs.c:81
char * result_start
Definition: jsonfuncs.c:83
text * tresult
Definition: jsonfuncs.c:82
char * token_start
Definition: jsonapi.h:77
bool * pathok
Definition: jsonfuncs.c:89
bool normalize_results
Definition: jsonfuncs.c:84
bool next_scalar
Definition: jsonfuncs.c:85
Definition: regguts.h:298
int * path_indexes
Definition: jsonfuncs.c:88

◆ get_array_end()

static void get_array_end ( void *  state)
static

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

1288 {
1289  GetState *_state = (GetState *) state;
1290  int lex_level = _state->lex->lex_level;
1291 
1292  if (lex_level == 0 && _state->npath == 0)
1293  {
1294  /* Special case: return the entire array */
1295  char *start = _state->result_start;
1296  int len = _state->lex->prev_token_terminator - start;
1297 
1298  _state->tresult = cstring_to_text_with_len(start, len);
1299  }
1300 }
char * prev_token_terminator
Definition: jsonapi.h:79
int lex_level
Definition: jsonapi.h:81
JsonLexContext * lex
Definition: jsonfuncs.c:81
char * result_start
Definition: jsonfuncs.c:83
text * tresult
Definition: jsonfuncs.c:82
text * cstring_to_text_with_len(const char *s, int len)
Definition: varlena.c:184
int npath
Definition: jsonfuncs.c:86
Definition: regguts.h:298

◆ get_array_start()

static void get_array_start ( void *  state)
static

Definition at line 1249 of file jsonfuncs.c.

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

Referenced by get_worker().

1250 {
1251  GetState *_state = (GetState *) state;
1252  int lex_level = _state->lex->lex_level;
1253 
1254  if (lex_level < _state->npath)
1255  {
1256  /* Initialize counting of elements in this array */
1257  _state->array_cur_index[lex_level] = -1;
1258 
1259  /* INT_MIN value is reserved to represent invalid subscript */
1260  if (_state->path_indexes[lex_level] < 0 &&
1261  _state->path_indexes[lex_level] != INT_MIN)
1262  {
1263  /* Negative subscript -- convert to positive-wise subscript */
1265  int nelements;
1266 
1267  error = json_count_array_elements(_state->lex, &nelements);
1268  if (error != JSON_SUCCESS)
1269  json_ereport_error(error, _state->lex);
1270 
1271  if (-_state->path_indexes[lex_level] <= nelements)
1272  _state->path_indexes[lex_level] += nelements;
1273  }
1274  }
1275  else if (lex_level == 0 && _state->npath == 0)
1276  {
1277  /*
1278  * Special case: we should match the entire array. We only need this
1279  * at the outermost level because at nested levels the match will have
1280  * been started by the outer field or array element callback.
1281  */
1282  _state->result_start = _state->lex->token_start;
1283  }
1284 }
int * array_cur_index
Definition: jsonfuncs.c:90
static void error(void)
Definition: sql-dyntest.c:147
int lex_level
Definition: jsonapi.h:81
JsonLexContext * lex
Definition: jsonfuncs.c:81
char * result_start
Definition: jsonfuncs.c:83
int npath
Definition: jsonfuncs.c:86
char * token_start
Definition: jsonapi.h:77
JsonParseErrorType
Definition: jsonapi.h:36
Definition: regguts.h:298
JsonParseErrorType json_count_array_elements(JsonLexContext *lex, int *elements)
Definition: jsonapi.c:219
void json_ereport_error(JsonParseErrorType error, JsonLexContext *lex)
Definition: jsonfuncs.c:607
int * path_indexes
Definition: jsonfuncs.c:88

◆ get_json_object_as_hash()

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

Definition at line 3433 of file jsonfuncs.c.

References JsonSemAction::array_start, CurrentMemoryContext, HASHCTL::entrysize, JHashState::function_name, GetDatabaseEncoding(), 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_or_ereport(), JsonSemAction::scalar, and JsonSemAction::semstate.

Referenced by JsValueToJsObject().

3434 {
3435  HASHCTL ctl;
3436  HTAB *tab;
3437  JHashState *state;
3439  JsonSemAction *sem;
3440 
3441  memset(&ctl, 0, sizeof(ctl));
3442  ctl.keysize = NAMEDATALEN;
3443  ctl.entrysize = sizeof(JsonHashEntry);
3444  ctl.hcxt = CurrentMemoryContext;
3445  tab = hash_create("json object hashtable",
3446  100,
3447  &ctl,
3449 
3450  state = palloc0(sizeof(JHashState));
3451  sem = palloc0(sizeof(JsonSemAction));
3452 
3453  state->function_name = funcname;
3454  state->hash = tab;
3455  state->lex = lex;
3456 
3457  sem->semstate = (void *) state;
3459  sem->scalar = hash_scalar;
3462 
3463  pg_parse_json_or_ereport(lex, sem);
3464 
3465  return tab;
3466 }
#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:3493
json_scalar_action scalar
Definition: jsonapi.h:115
#define NAMEDATALEN
Definition: dynahash.c:210
JsonLexContext * makeJsonLexContextCstringLen(char *json, int len, int encoding, bool need_escapes)
Definition: jsonapi.c:155
HTAB * hash
Definition: jsonfuncs.c:133
MemoryContext CurrentMemoryContext
Definition: mcxt.c:38
json_ofield_action object_field_end
Definition: jsonapi.h:112
static void hash_object_field_start(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:3469
const char * function_name
Definition: jsonfuncs.c:132
void pg_parse_json_or_ereport(JsonLexContext *lex, JsonSemAction *sem)
Definition: jsonfuncs.c:497
void * palloc0(Size size)
Definition: mcxt.c:980
HTAB * hash_create(const char *tabname, long nelem, HASHCTL *info, int flags)
Definition: dynahash.c:318
int GetDatabaseEncoding(void)
Definition: mbutils.c:1151
Size keysize
Definition: hsearch.h:72
json_struct_action array_start
Definition: jsonapi.h:109
Definition: regguts.h:298
struct JsonHashEntry JsonHashEntry
JsonLexContext * lex
Definition: jsonfuncs.c:131
static void hash_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:3553
json_ofield_action object_field_start
Definition: jsonapi.h:111
void * semstate
Definition: jsonapi.h:106
static void hash_array_start(void *state)
Definition: jsonfuncs.c:3542

◆ get_jsonb_path_all()

static Datum get_jsonb_path_all ( FunctionCallInfo  fcinfo,
bool  as_text 
)
static

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

1445 {
1446  Jsonb *jb = PG_GETARG_JSONB_P(0);
1447  ArrayType *path = PG_GETARG_ARRAYTYPE_P(1);
1448  Datum *pathtext;
1449  bool *pathnulls;
1450  int npath;
1451  int i;
1452  bool have_object = false,
1453  have_array = false;
1454  JsonbValue *jbvp = NULL;
1455  JsonbValue jbvbuf;
1456  JsonbContainer *container;
1457 
1458  /*
1459  * If the array contains any null elements, return NULL, on the grounds
1460  * that you'd have gotten NULL if any RHS value were NULL in a nested
1461  * series of applications of the -> operator. (Note: because we also
1462  * return NULL for error cases such as no-such-field, this is true
1463  * regardless of the contents of the rest of the array.)
1464  */
1465  if (array_contains_nulls(path))
1466  PG_RETURN_NULL();
1467 
1468  deconstruct_array(path, TEXTOID, -1, false, TYPALIGN_INT,
1469  &pathtext, &pathnulls, &npath);
1470 
1471  /* Identify whether we have object, array, or scalar at top-level */
1472  container = &jb->root;
1473 
1474  if (JB_ROOT_IS_OBJECT(jb))
1475  have_object = true;
1476  else if (JB_ROOT_IS_ARRAY(jb) && !JB_ROOT_IS_SCALAR(jb))
1477  have_array = true;
1478  else
1479  {
1481  /* Extract the scalar value, if it is what we'll return */
1482  if (npath <= 0)
1483  jbvp = getIthJsonbValueFromContainer(container, 0);
1484  }
1485 
1486  /*
1487  * If the array is empty, return the entire LHS object, on the grounds
1488  * that we should do zero field or element extractions. For the
1489  * non-scalar case we can just hand back the object without much work. For
1490  * the scalar case, fall through and deal with the value below the loop.
1491  * (This inconsistency arises because there's no easy way to generate a
1492  * JsonbValue directly for root-level containers.)
1493  */
1494  if (npath <= 0 && jbvp == NULL)
1495  {
1496  if (as_text)
1497  {
1499  container,
1500  VARSIZE(jb))));
1501  }
1502  else
1503  {
1504  /* not text mode - just hand back the jsonb */
1505  PG_RETURN_JSONB_P(jb);
1506  }
1507  }
1508 
1509  for (i = 0; i < npath; i++)
1510  {
1511  if (have_object)
1512  {
1513  jbvp = getKeyJsonValueFromContainer(container,
1514  VARDATA(pathtext[i]),
1515  VARSIZE(pathtext[i]) - VARHDRSZ,
1516  &jbvbuf);
1517  }
1518  else if (have_array)
1519  {
1520  long lindex;
1521  uint32 index;
1522  char *indextext = TextDatumGetCString(pathtext[i]);
1523  char *endptr;
1524 
1525  errno = 0;
1526  lindex = strtol(indextext, &endptr, 10);
1527  if (endptr == indextext || *endptr != '\0' || errno != 0 ||
1528  lindex > INT_MAX || lindex < INT_MIN)
1529  PG_RETURN_NULL();
1530 
1531  if (lindex >= 0)
1532  {
1533  index = (uint32) lindex;
1534  }
1535  else
1536  {
1537  /* Handle negative subscript */
1538  uint32 nelements;
1539 
1540  /* Container must be array, but make sure */
1541  if (!JsonContainerIsArray(container))
1542  elog(ERROR, "not a jsonb array");
1543 
1544  nelements = JsonContainerSize(container);
1545 
1546  if (-lindex > nelements)
1547  PG_RETURN_NULL();
1548  else
1549  index = nelements + lindex;
1550  }
1551 
1552  jbvp = getIthJsonbValueFromContainer(container, index);
1553  }
1554  else
1555  {
1556  /* scalar, extraction yields a null */
1557  PG_RETURN_NULL();
1558  }
1559 
1560  if (jbvp == NULL)
1561  PG_RETURN_NULL();
1562  else if (i == npath - 1)
1563  break;
1564 
1565  if (jbvp->type == jbvBinary)
1566  {
1567  container = jbvp->val.binary.data;
1568  have_object = JsonContainerIsObject(container);
1569  have_array = JsonContainerIsArray(container);
1570  Assert(!JsonContainerIsScalar(container));
1571  }
1572  else
1573  {
1574  Assert(IsAJsonbScalar(jbvp));
1575  have_object = false;
1576  have_array = false;
1577  }
1578  }
1579 
1580  if (as_text)
1581  {
1582  if (jbvp->type == jbvNull)
1583  PG_RETURN_NULL();
1584 
1586  }
1587  else
1588  {
1589  Jsonb *res = JsonbValueToJsonb(jbvp);
1590 
1591  /* not text mode - just hand back the jsonb */
1592  PG_RETURN_JSONB_P(res);
1593  }
1594 }
#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:85
Definition: jsonb.h:220
#define VARSIZE(PTR)
Definition: postgres.h:303
#define VARHDRSZ
Definition: c.h:561
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:391
Definition: jsonb.h:236
static text * JsonbValueAsText(JsonbValue *v)
Definition: jsonfuncs.c:1600
#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:367
#define JsonContainerIsArray(jc)
Definition: jsonb.h:217
JsonbContainer root
Definition: jsonb.h:223
#define TextDatumGetCString(d)
Definition: builtins.h:88
uintptr_t Datum
Definition: postgres.h:367
#define JsonContainerIsObject(jc)
Definition: jsonb.h:216
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:370
text * cstring_to_text(const char *s)
Definition: varlena.c:172
JsonbValue * getIthJsonbValueFromContainer(JsonbContainer *container, uint32 i)
Definition: jsonb_util.c:461
#define Assert(condition)
Definition: c.h:738
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:3462
#define elog(elevel,...)
Definition: elog.h:214
int i
#define PG_RETURN_JSONB_P(x)
Definition: jsonb.h:76
bool array_contains_nulls(ArrayType *array)
Definition: arrayfuncs.c:3529
#define PG_RETURN_NULL()
Definition: fmgr.h:344
#define PG_GETARG_JSONB_P(x)
Definition: jsonb.h:74

◆ get_object_end()

static void get_object_end ( void *  state)
static

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

1140 {
1141  GetState *_state = (GetState *) state;
1142  int lex_level = _state->lex->lex_level;
1143 
1144  if (lex_level == 0 && _state->npath == 0)
1145  {
1146  /* Special case: return the entire object */
1147  char *start = _state->result_start;
1148  int len = _state->lex->prev_token_terminator - start;
1149 
1150  _state->tresult = cstring_to_text_with_len(start, len);
1151  }
1152 }
char * prev_token_terminator
Definition: jsonapi.h:79
int lex_level
Definition: jsonapi.h:81
JsonLexContext * lex
Definition: jsonfuncs.c:81
char * result_start
Definition: jsonfuncs.c:83
text * tresult
Definition: jsonfuncs.c:82
text * cstring_to_text_with_len(const char *s, int len)
Definition: varlena.c:184
int npath
Definition: jsonfuncs.c:86
Definition: regguts.h:298

◆ get_object_field_end()

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

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

1201 {
1202  GetState *_state = (GetState *) state;
1203  bool get_last = false;
1204  int lex_level = _state->lex->lex_level;
1205 
1206  /* same tests as in get_object_field_start */
1207  if (lex_level <= _state->npath &&
1208  _state->pathok[lex_level - 1] &&
1209  _state->path_names != NULL &&
1210  _state->path_names[lex_level - 1] != NULL &&
1211  strcmp(fname, _state->path_names[lex_level - 1]) == 0)
1212  {
1213  if (lex_level < _state->npath)
1214  {
1215  /* done with this field so reset pathok */
1216  _state->pathok[lex_level] = false;
1217  }
1218  else
1219  {
1220  /* end of path, so we want this value */
1221  get_last = true;
1222  }
1223  }
1224 
1225  /* for as_text scalar case, our work is already done */
1226  if (get_last && _state->result_start != NULL)
1227  {
1228  /*
1229  * make a text object from the string from the previously noted json
1230  * start up to the end of the previous token (the lexer is by now
1231  * ahead of us on whatever came after what we're interested in).
1232  */
1233  if (isnull && _state->normalize_results)
1234  _state->tresult = (text *) NULL;
1235  else
1236  {
1237  char *start = _state->result_start;
1238  int len = _state->lex->prev_token_terminator - start;
1239 
1240  _state->tresult = cstring_to_text_with_len(start, len);
1241  }
1242 
1243  /* this should be unnecessary but let's do it for cleanliness: */
1244  _state->result_start = NULL;
1245  }
1246 }
char * prev_token_terminator
Definition: jsonapi.h:79
int lex_level
Definition: jsonapi.h:81
JsonLexContext * lex
Definition: jsonfuncs.c:81
char * result_start
Definition: jsonfuncs.c:83
text * tresult
Definition: jsonfuncs.c:82
text * cstring_to_text_with_len(const char *s, int len)
Definition: varlena.c:184
bool * pathok
Definition: jsonfuncs.c:89
bool normalize_results
Definition: jsonfuncs.c:84
char ** path_names
Definition: jsonfuncs.c:87
Definition: regguts.h:298
Definition: c.h:555

◆ get_object_field_start()

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

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

1156 {
1157  GetState *_state = (GetState *) state;
1158  bool get_next = false;
1159  int lex_level = _state->lex->lex_level;
1160 
1161  if (lex_level <= _state->npath &&
1162  _state->pathok[lex_level - 1] &&
1163  _state->path_names != NULL &&
1164  _state->path_names[lex_level - 1] != NULL &&
1165  strcmp(fname, _state->path_names[lex_level - 1]) == 0)
1166  {
1167  if (lex_level < _state->npath)
1168  {
1169  /* if not at end of path just mark path ok */
1170  _state->pathok[lex_level] = true;
1171  }
1172  else
1173  {
1174  /* end of path, so we want this value */
1175  get_next = true;
1176  }
1177  }
1178 
1179  if (get_next)
1180  {
1181  /* this object overrides any previous matching object */
1182  _state->tresult = NULL;
1183  _state->result_start = NULL;
1184 
1185  if (_state->normalize_results &&
1186  _state->lex->token_type == JSON_TOKEN_STRING)
1187  {
1188  /* for as_text variants, tell get_scalar to set it for us */
1189  _state->next_scalar = true;
1190  }
1191  else
1192  {
1193  /* for non-as_text variants, just note the json starting point */
1194  _state->result_start = _state->lex->token_start;
1195  }
1196  }
1197 }
JsonTokenType token_type
Definition: jsonapi.h:80
int lex_level
Definition: jsonapi.h:81
JsonLexContext * lex
Definition: jsonfuncs.c:81
char * result_start
Definition: jsonfuncs.c:83
text * tresult
Definition: jsonfuncs.c:82
char * token_start
Definition: jsonapi.h:77
bool * pathok
Definition: jsonfuncs.c:89
bool normalize_results
Definition: jsonfuncs.c:84
bool next_scalar
Definition: jsonfuncs.c:85
char ** path_names
Definition: jsonfuncs.c:87
Definition: regguts.h:298

◆ get_object_start()

static void get_object_start ( void *  state)
static

Definition at line 1122 of file jsonfuncs.c.

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

Referenced by get_worker().

1123 {
1124  GetState *_state = (GetState *) state;
1125  int lex_level = _state->lex->lex_level;
1126 
1127  if (lex_level == 0 && _state->npath == 0)
1128  {
1129  /*
1130  * Special case: we should match the entire object. We only need this
1131  * at outermost level because at nested levels the match will have
1132  * been started by the outer field or array element callback.
1133  */
1134  _state->result_start = _state->lex->token_start;
1135  }
1136 }
int lex_level
Definition: jsonapi.h:81
JsonLexContext * lex
Definition: jsonfuncs.c:81
char * result_start
Definition: jsonfuncs.c:83
int npath
Definition: jsonfuncs.c:86
char * token_start
Definition: jsonapi.h:77
Definition: regguts.h:298

◆ get_path_all()

static Datum get_path_all ( FunctionCallInfo  fcinfo,
bool  as_text 
)
static

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

987 {
988  text *json = PG_GETARG_TEXT_PP(0);
989  ArrayType *path = PG_GETARG_ARRAYTYPE_P(1);
990  text *result;
991  Datum *pathtext;
992  bool *pathnulls;
993  int npath;
994  char **tpath;
995  int *ipath;
996  int i;
997 
998  /*
999  * If the array contains any null elements, return NULL, on the grounds
1000  * that you'd have gotten NULL if any RHS value were NULL in a nested
1001  * series of applications of the -> operator. (Note: because we also
1002  * return NULL for error cases such as no-such-field, this is true
1003  * regardless of the contents of the rest of the array.)
1004  */
1005  if (array_contains_nulls(path))
1006  PG_RETURN_NULL();
1007 
1008  deconstruct_array(path, TEXTOID, -1, false, TYPALIGN_INT,
1009  &pathtext, &pathnulls, &npath);
1010 
1011  tpath = palloc(npath * sizeof(char *));
1012  ipath = palloc(npath * sizeof(int));
1013 
1014  for (i = 0; i < npath; i++)
1015  {
1016  Assert(!pathnulls[i]);
1017  tpath[i] = TextDatumGetCString(pathtext[i]);
1018 
1019  /*
1020  * we have no idea at this stage what structure the document is so
1021  * just convert anything in the path that we can to an integer and set
1022  * all the other integers to INT_MIN which will never match.
1023  */
1024  if (*tpath[i] != '\0')
1025  {
1026  long ind;
1027  char *endptr;
1028 
1029  errno = 0;
1030  ind = strtol(tpath[i], &endptr, 10);
1031  if (*endptr == '\0' && errno == 0 && ind <= INT_MAX && ind >= INT_MIN)
1032  ipath[i] = (int) ind;
1033  else
1034  ipath[i] = INT_MIN;
1035  }
1036  else
1037  ipath[i] = INT_MIN;
1038  }
1039 
1040  result = get_worker(json, tpath, ipath, npath, as_text);
1041 
1042  if (result != NULL)
1043  PG_RETURN_TEXT_P(result);
1044  else
1045  PG_RETURN_NULL();
1046 }
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:308
#define PG_GETARG_ARRAYTYPE_P(n)
Definition: array.h:251
#define TextDatumGetCString(d)
Definition: builtins.h:88
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:1066
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:370
#define Assert(condition)
Definition: c.h:738
void deconstruct_array(ArrayType *array, Oid elmtype, int elmlen, bool elmbyval, char elmalign, Datum **elemsp, bool **nullsp, int *nelemsp)
Definition: arrayfuncs.c:3462
void * palloc(Size size)
Definition: mcxt.c:949
int i
Definition: c.h:555
bool array_contains_nulls(ArrayType *array)
Definition: arrayfuncs.c:3529
#define PG_RETURN_NULL()
Definition: fmgr.h:344

◆ get_record_type_from_argument()

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

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

3268 {
3269  cache->argtype = get_fn_expr_argtype(fcinfo->flinfo, 0);
3270  prepare_column_cache(&cache->c,
3271  cache->argtype, -1,
3272  cache->fn_mcxt, false);
3273  if (cache->c.typcat != TYPECAT_COMPOSITE &&
3274  cache->c.typcat != TYPECAT_COMPOSITE_DOMAIN)
3275  ereport(ERROR,
3276  (errcode(ERRCODE_DATATYPE_MISMATCH),
3277  /* translator: %s is a function name, eg json_to_record */
3278  errmsg("first argument of %s must be a row type",
3279  funcname)));
3280 }
static void prepare_column_cache(ColumnIOData *column, Oid typid, int32 typmod, MemoryContext mcxt, bool need_scalar)
Definition: jsonfuncs.c:2956
int errcode(int sqlerrcode)
Definition: elog.c:610
#define ERROR
Definition: elog.h:43
Oid get_fn_expr_argtype(FmgrInfo *flinfo, int argnum)
Definition: fmgr.c:1804
ColumnIOData c
Definition: jsonfuncs.c:233
FmgrInfo * flinfo
Definition: fmgr.h:87
#define ereport(elevel,...)
Definition: elog.h:144
MemoryContext fn_mcxt
Definition: jsonfuncs.c:234
int errmsg(const char *fmt,...)
Definition: elog.c:824
TypeCat typcat
Definition: jsonfuncs.c:208

◆ get_record_type_from_query()

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

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

3294 {
3295  TupleDesc tupdesc;
3296  MemoryContext old_cxt;
3297 
3298  if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
3299  ereport(ERROR,
3300  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3301  /* translator: %s is a function name, eg json_to_record */
3302  errmsg("could not determine row type for result of %s",
3303  funcname),
3304  errhint("Provide a non-null record argument, "
3305  "or call the function in the FROM clause "
3306  "using a column definition list.")));
3307 
3308  Assert(tupdesc);
3309  cache->argtype = tupdesc->tdtypeid;
3310 
3311  /* If we go through this more than once, avoid memory leak */
3312  if (cache->c.io.composite.tupdesc)
3314 
3315  /* Save identified tupdesc */
3316  old_cxt = MemoryContextSwitchTo(cache->fn_mcxt);
3317  cache->c.io.composite.tupdesc = CreateTupleDescCopy(tupdesc);
3318  cache->c.io.composite.base_typid = tupdesc->tdtypeid;
3319  cache->c.io.composite.base_typmod = tupdesc->tdtypmod;
3320  MemoryContextSwitchTo(old_cxt);
3321 }
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
Definition: tupdesc.c:110
TypeFuncClass get_call_result_type(FunctionCallInfo fcinfo, Oid *resultTypeId, TupleDesc *resultTupleDesc)
Definition: funcapi.c:205
int errhint(const char *fmt,...)
Definition: elog.c:1071
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
int errcode(int sqlerrcode)
Definition: elog.c:610
int32 base_typmod
Definition: jsonfuncs.c:177
union ColumnIOData::@28 io
#define ERROR
Definition: elog.h:43
int32 tdtypmod
Definition: tupdesc.h:83
ColumnIOData c
Definition: jsonfuncs.c:233
#define ereport(elevel,...)
Definition: elog.h:144
#define Assert(condition)
Definition: c.h:738
MemoryContext fn_mcxt
Definition: jsonfuncs.c:234
void FreeTupleDesc(TupleDesc tupdesc)
Definition: tupdesc.c:313
Oid tdtypeid
Definition: tupdesc.h:82
int errmsg(const char *fmt,...)
Definition: elog.c:824
TupleDesc tupdesc
Definition: jsonfuncs.c:174
CompositeIOData composite
Definition: jsonfuncs.c:214

◆ get_scalar()

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

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

1392 {
1393  GetState *_state = (GetState *) state;
1394  int lex_level = _state->lex->lex_level;
1395 
1396  /* Check for whole-object match */
1397  if (lex_level == 0 && _state->npath == 0)
1398  {
1399  if (_state->normalize_results && tokentype == JSON_TOKEN_STRING)
1400  {
1401  /* we want the de-escaped string */
1402  _state->next_scalar = true;
1403  }
1404  else if (_state->normalize_results && tokentype == JSON_TOKEN_NULL)
1405  {
1406  _state->tresult = (text *) NULL;
1407  }
1408  else
1409  {
1410  /*
1411  * This is a bit hokey: we will suppress whitespace after the
1412  * scalar token, but not whitespace before it. Probably not worth
1413  * doing our own space-skipping to avoid that.
1414  */
1415  char *start = _state->lex->input;
1416  int len = _state->lex->prev_token_terminator - start;
1417 
1418  _state->tresult = cstring_to_text_with_len(start, len);
1419  }
1420  }
1421 
1422  if (_state->next_scalar)
1423  {
1424  /* a de-escaped text value is wanted, so supply it */
1425  _state->tresult = cstring_to_text(token);
1426  /* make sure the next call to get_scalar doesn't overwrite it */
1427  _state->next_scalar = false;
1428  }
1429 }
char * prev_token_terminator
Definition: jsonapi.h:79
int lex_level
Definition: jsonapi.h:81
JsonLexContext * lex
Definition: jsonfuncs.c:81
text * tresult
Definition: jsonfuncs.c:82
text * cstring_to_text_with_len(const char *s, int len)
Definition: varlena.c:184
int npath
Definition: jsonfuncs.c:86
bool normalize_results
Definition: jsonfuncs.c:84
bool next_scalar
Definition: jsonfuncs.c:85
text * cstring_to_text(const char *s)
Definition: varlena.c:172
char * input
Definition: jsonapi.h:74
Definition: regguts.h:298
Definition: c.h:555

◆ get_worker()

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

Definition at line 1066 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_or_ereport(), 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().

1071 {
1072  JsonLexContext *lex = makeJsonLexContext(json, true);
1073  JsonSemAction *sem = palloc0(sizeof(JsonSemAction));
1074  GetState *state = palloc0(sizeof(GetState));
1075 
1076  Assert(npath >= 0);
1077 
1078  state->lex = lex;
1079  /* is it "_as_text" variant? */
1080  state->normalize_results = normalize_results;
1081  state->npath = npath;
1082  state->path_names = tpath;
1083  state->path_indexes = ipath;
1084  state->pathok = palloc0(sizeof(bool) * npath);
1085  state->array_cur_index = palloc(sizeof(int) * npath);
1086 
1087  if (npath > 0)
1088  state->pathok[0] = true;
1089 
1090  sem->semstate = (void *) state;
1091 
1092  /*
1093  * Not all variants need all the semantic routines. Only set the ones that
1094  * are actually needed for maximum efficiency.
1095  */
1096  sem->scalar = get_scalar;
1097  if (npath == 0)
1098  {
1100  sem->object_end = get_object_end;
1102  sem->array_end = get_array_end;
1103  }
1104  if (tpath != NULL)
1105  {
1108  }
1109  if (ipath != NULL)
1110  {
1114  }
1115 
1116  pg_parse_json_or_ereport(lex, sem);
1117 
1118  return state->tresult;
1119 }
json_struct_action array_end
Definition: jsonapi.h:110
static void get_array_end(void *state)
Definition: jsonfuncs.c:1287
int * array_cur_index
Definition: jsonfuncs.c:90
static void get_array_element_start(void *state, bool isnull)
Definition: jsonfuncs.c:1303
json_struct_action object_end
Definition: jsonapi.h:108
static void get_object_start(void *state)
Definition: jsonfuncs.c:1122
json_struct_action object_start
Definition: jsonapi.h:107
JsonLexContext * makeJsonLexContext(text *json, bool need_escapes)
Definition: jsonfuncs.c:513
json_scalar_action scalar
Definition: jsonapi.h:115
static void get_object_field_end(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:1200
JsonLexContext * lex
Definition: jsonfuncs.c:81
static void get_object_end(void *state)
Definition: jsonfuncs.c:1139
text * tresult
Definition: jsonfuncs.c:82
int npath
Definition: jsonfuncs.c:86
json_ofield_action object_field_end
Definition: jsonapi.h:112
static void get_array_element_end(void *state, bool isnull)
Definition: jsonfuncs.c:1349
bool * pathok
Definition: jsonfuncs.c:89
bool normalize_results
Definition: jsonfuncs.c:84
void pg_parse_json_or_ereport(JsonLexContext *lex, JsonSemAction *sem)
Definition: jsonfuncs.c:497
static void get_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:1391
void * palloc0(Size size)
Definition: mcxt.c:980
static void get_array_start(void *state)
Definition: jsonfuncs.c:1249
json_aelem_action array_element_start
Definition: jsonapi.h:113
char ** path_names
Definition: jsonfuncs.c:87
#define Assert(condition)
Definition: c.h:738
json_struct_action array_start
Definition: jsonapi.h:109
Definition: regguts.h:298
int * path_indexes
Definition: jsonfuncs.c:88
void * palloc(Size size)
Definition: mcxt.c:949
static void get_object_field_start(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:1155
json_ofield_action object_field_start
Definition: jsonapi.h:111
void * semstate
Definition: jsonapi.h:106
json_aelem_action array_element_end
Definition: jsonapi.h:114

◆ hash_array_start()

static void hash_array_start ( void *  state)
static

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

3543 {
3544  JHashState *_state = (JHashState *) state;
3545 
3546  if (_state->lex->lex_level == 0)
3547  ereport(ERROR,
3548  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3549  errmsg("cannot call %s on an array", _state->function_name)));
3550 }
int errcode(int sqlerrcode)
Definition: elog.c:610
int lex_level
Definition: jsonapi.h:81
#define ERROR
Definition: elog.h:43
const char * function_name
Definition: jsonfuncs.c:132
#define ereport(elevel,...)
Definition: elog.h:144
Definition: regguts.h:298
JsonLexContext * lex
Definition: jsonfuncs.c:131
int errmsg(const char *fmt,...)
Definition: elog.c:824

◆ hash_object_field_end()

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

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

3494 {
3495  JHashState *_state = (JHashState *) state;
3496  JsonHashEntry *hashentry;
3497  bool found;
3498 
3499  /*
3500  * Ignore nested fields.
3501  */
3502  if (_state->lex->lex_level > 1)
3503  return;
3504 
3505  /*
3506  * Ignore field names >= NAMEDATALEN - they can't match a record field.
3507  * (Note: without this test, the hash code would truncate the string at
3508  * NAMEDATALEN-1, and could then match against a similarly-truncated
3509  * record field name. That would be a reasonable behavior, but this code
3510  * has previously insisted on exact equality, so we keep this behavior.)
3511  */
3512  if (strlen(fname) >= NAMEDATALEN)
3513  return;
3514 
3515  hashentry = hash_search(_state->hash, fname, HASH_ENTER, &found);
3516 
3517  /*
3518  * found being true indicates a duplicate. We don't do anything about
3519  * that, a later field with the same name overrides the earlier field.
3520  */
3521 
3522  hashentry->type = _state->saved_token_type;
3523  Assert(isnull == (hashentry->type == JSON_TOKEN_NULL));
3524 
3525  if (_state->save_json_start != NULL)
3526  {
3527  int len = _state->lex->prev_token_terminator - _state->save_json_start;
3528  char *val = palloc((len + 1) * sizeof(char));
3529 
3530  memcpy(val, _state->save_json_start, len);
3531  val[len] = '\0';
3532  hashentry->val = val;
3533  }
3534  else
3535  {
3536  /* must have had a scalar instead */
3537  hashentry->val = _state->saved_scalar;
3538  }
3539 }
char * prev_token_terminator
Definition: jsonapi.h:79
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:908
JsonTokenType type
Definition: jsonfuncs.c:144
int lex_level
Definition: jsonapi.h:81
char * save_json_start
Definition: jsonfuncs.c:135
#define NAMEDATALEN
JsonTokenType saved_token_type
Definition: jsonfuncs.c:136
char * val
Definition: jsonfuncs.c:143
HTAB * hash
Definition: jsonfuncs.c:133
#define Assert(condition)
Definition: c.h:738
Definition: regguts.h:298
JsonLexContext * lex
Definition: jsonfuncs.c:131
char * saved_scalar
Definition: jsonfuncs.c:134
void * palloc(Size size)
Definition: mcxt.c:949
long val
Definition: informix.c:664

◆ hash_object_field_start()

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

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

3470 {
3471  JHashState *_state = (JHashState *) state;
3472 
3473  if (_state->lex->lex_level > 1)
3474  return;
3475 
3476  /* remember token type */
3477  _state->saved_token_type = _state->lex->token_type;
3478 
3479  if (_state->lex->token_type == JSON_TOKEN_ARRAY_START ||
3481  {
3482  /* remember start position of the whole text of the subobject */
3483  _state->save_json_start = _state->lex->token_start;
3484  }
3485  else
3486  {
3487  /* must be a scalar */
3488  _state->save_json_start = NULL;
3489  }
3490 }
JsonTokenType token_type
Definition: jsonapi.h:80
int lex_level
Definition: jsonapi.h:81
char * save_json_start
Definition: jsonfuncs.c:135
JsonTokenType saved_token_type
Definition: jsonfuncs.c:136
char * token_start
Definition: jsonapi.h:77
Definition: regguts.h:298
JsonLexContext * lex
Definition: jsonfuncs.c:131

◆ hash_scalar()

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

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

3554 {
3555  JHashState *_state = (JHashState *) state;
3556 
3557  if (_state->lex->lex_level == 0)
3558  ereport(ERROR,
3559  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3560  errmsg("cannot call %s on a scalar", _state->function_name)));
3561 
3562  if (_state->lex->lex_level == 1)
3563  {
3564  _state->saved_scalar = token;
3565  /* saved_token_type must already be set in hash_object_field_start() */
3566  Assert(_state->saved_token_type == tokentype);
3567  }
3568 }
int errcode(int sqlerrcode)
Definition: elog.c:610
int lex_level
Definition: jsonapi.h:81
#define ERROR
Definition: elog.h:43
JsonTokenType saved_token_type
Definition: jsonfuncs.c:136
const char * function_name
Definition: jsonfuncs.c:132
#define ereport(elevel,...)
Definition: elog.h:144
#define Assert(condition)
Definition: c.h:738
Definition: regguts.h:298
JsonLexContext * lex
Definition: jsonfuncs.c:131
char * saved_scalar
Definition: jsonfuncs.c:134
int errmsg(const char *fmt,...)
Definition: elog.c:824

◆ iterate_json_values()

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

Definition at line 5216 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_or_ereport(), JsonSemAction::scalar, and JsonSemAction::semstate.

Referenced by json_to_tsvector_worker().

5218 {
5219  JsonLexContext *lex = makeJsonLexContext(json, true);
5220  JsonSemAction *sem = palloc0(sizeof(JsonSemAction));
5222 
5223  state->lex = lex;
5224  state->action = action;
5225  state->action_state = action_state;
5226  state->flags = flags;
5227 
5228  sem->semstate = (void *) state;
5231 
5232  pg_parse_json_or_ereport(lex, sem);
5233 }
JsonIterateStringValuesAction action
Definition: jsonfuncs.c:61
static void iterate_values_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:5240
JsonLexContext * makeJsonLexContext(text *json, bool need_escapes)
Definition: jsonfuncs.c:513
json_scalar_action scalar
Definition: jsonapi.h:115
void pg_parse_json_or_ereport(JsonLexContext *lex, JsonSemAction *sem)
Definition: jsonfuncs.c:497
void * palloc0(Size size)
Definition: mcxt.c:980
Definition: regguts.h:298
JsonLexContext * lex
Definition: jsonfuncs.c:60
json_ofield_action object_field_start
Definition: jsonapi.h:111
static void iterate_values_object_field_start(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:5266
void * semstate
Definition: jsonapi.h:106

◆ iterate_jsonb_values()

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

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

5150 {
5151  JsonbIterator *it;
5152  JsonbValue v;
5154 
5155  it = JsonbIteratorInit(&jb->root);
5156 
5157  /*
5158  * Just recursively iterating over jsonb and call callback on all
5159  * corresponding elements
5160  */
5161  while ((type = JsonbIteratorNext(&it, &v, false)) != WJB_DONE)
5162  {
5163  if (type == WJB_KEY)
5164  {
5165  if (flags & jtiKey)
5166  action(state, v.val.string.val, v.val.string.len);
5167 
5168  continue;
5169  }
5170  else if (!(type == WJB_VALUE || type == WJB_ELEM))
5171  {
5172  /* do not call callback for composite JsonbValue */
5173  continue;
5174  }
5175 
5176  /* JsonbValue is a value of object or element of array */
5177  switch (v.type)
5178  {
5179  case jbvString:
5180  if (flags & jtiString)
5181  action(state, v.val.string.val, v.val.string.len);
5182  break;
5183  case jbvNumeric:
5184  if (flags & jtiNumeric)
5185  {
5186  char *val;
5187 
5189  NumericGetDatum(v.val.numeric)));
5190 
5191  action(state, val, strlen(val));
5192  pfree(val);
5193  }
5194  break;
5195  case jbvBool:
5196  if (flags & jtiBool)
5197  {
5198  if (v.val.boolean)
5199  action(state, "true", 4);
5200  else
5201  action(state, "false", 5);
5202  }
5203  break;
5204  default:
5205  /* do not call callback for composite JsonbValue */
5206  break;
5207  }
5208  }
5209 }
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:649
Definition: jsonb.h:22
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:624
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:760
Definition: regguts.h:298
enum jbvType type
Definition: jsonb.h:263
long val
Definition: informix.c:664
JsonbIteratorToken JsonbIteratorNext(JsonbIterator **it, JsonbValue *val, bool skipNested)
Definition: jsonb_util.c:796
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 5266 of file jsonfuncs.c.

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

Referenced by iterate_json_values().

5267 {
5269 
5270  if (_state->flags & jtiKey)
5271  {
5272  char *val = pstrdup(fname);
5273 
5274  _state->action(_state->action_state, val, strlen(val));
5275  }
5276 }
JsonIterateStringValuesAction action
Definition: jsonfuncs.c:61
char * pstrdup(const char *in)
Definition: mcxt.c:1186
Definition: regguts.h:298
long val
Definition: informix.c:664

◆ iterate_values_scalar()

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

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

5241 {
5243 
5244  switch (tokentype)
5245  {
5246  case JSON_TOKEN_STRING:
5247  if (_state->flags & jtiString)
5248  _state->action(_state->action_state, token, strlen(token));
5249  break;
5250  case JSON_TOKEN_NUMBER:
5251  if (_state->flags & jtiNumeric)
5252  _state->action(_state->action_state, token, strlen(token));
5253  break;
5254  case JSON_TOKEN_TRUE:
5255  case JSON_TOKEN_FALSE:
5256  if (_state->flags & jtiBool)
5257  _state->action(_state->action_state, token, strlen(token));
5258  break;
5259  default:
5260  /* do not call callback for any other token */
5261  break;
5262  }
5263 }
JsonIterateStringValuesAction action
Definition: jsonfuncs.c:61
Definition: regguts.h:298

◆ IteratorConcat()

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

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

4681 {
4682  JsonbValue v1,
4683  v2,
4684  *res = NULL;
4685  JsonbIteratorToken r1,
4686  r2,
4687  rk1,
4688  rk2;
4689 
4690  r1 = rk1 = JsonbIteratorNext(it1, &v1, false);
4691  r2 = rk2 = JsonbIteratorNext(it2, &v2, false);
4692 
4693  /*
4694  * Both elements are objects.
4695  */
4696  if (rk1 == WJB_BEGIN_OBJECT && rk2 == WJB_BEGIN_OBJECT)
4697  {
4698  /*
4699  * Append the all tokens from v1 to res, except last WJB_END_OBJECT
4700  * (because res will not be finished yet).
4701  */
4702  pushJsonbValue(state, r1, NULL);
4703  while ((r1 = JsonbIteratorNext(it1, &v1, true)) != WJB_END_OBJECT)
4704  pushJsonbValue(state, r1, &v1);
4705 
4706  /*
4707  * Append the all tokens from v2 to res, include last WJB_END_OBJECT
4708  * (the concatenation will be completed).
4709  */
4710  while ((r2 = JsonbIteratorNext(it2, &v2, true)) != WJB_DONE)
4711  res = pushJsonbValue(state, r2, r2 != WJB_END_OBJECT ? &v2 : NULL);
4712  }
4713 
4714  /*
4715  * Both elements are arrays (either can be scalar).
4716  */
4717  else if (rk1 == WJB_BEGIN_ARRAY && rk2 == WJB_BEGIN_ARRAY)
4718  {
4719  pushJsonbValue(state, r1, NULL);
4720 
4721  while ((r1 = JsonbIteratorNext(it1, &v1, true)) != WJB_END_ARRAY)
4722  {
4723  Assert(r1 == WJB_ELEM);
4724  pushJsonbValue(state, r1, &v1);
4725  }
4726 
4727  while ((r2 = JsonbIteratorNext(it2, &v2, true)) != WJB_END_ARRAY)
4728  {
4729  Assert(r2 == WJB_ELEM);
4730  pushJsonbValue(state, WJB_ELEM, &v2);
4731  }
4732 
4733  res = pushJsonbValue(state, WJB_END_ARRAY, NULL /* signal to sort */ );
4734  }
4735  /* have we got array || object or object || array? */
4736  else if (((rk1 == WJB_BEGIN_ARRAY && !(*it1)->isScalar) && rk2 == WJB_BEGIN_OBJECT) ||
4737  (rk1 == WJB_BEGIN_OBJECT && (rk2 == WJB_BEGIN_ARRAY && !(*it2)->isScalar)))
4738  {
4739 
4740  JsonbIterator **it_array = rk1 == WJB_BEGIN_ARRAY ? it1 : it2;
4741  JsonbIterator **it_object = rk1 == WJB_BEGIN_OBJECT ? it1 : it2;
4742 
4743  bool prepend = (rk1 == WJB_BEGIN_OBJECT);
4744 
4745  pushJsonbValue(state, WJB_BEGIN_ARRAY, NULL);
4746 
4747  if (prepend)
4748  {
4749  pushJsonbValue(state, WJB_BEGIN_OBJECT, NULL);
4750  while ((r1 = JsonbIteratorNext(it_object, &v1, true)) != WJB_DONE)
4751  pushJsonbValue(state, r1, r1 != WJB_END_OBJECT ? &v1 : NULL);
4752 
4753  while ((r2 = JsonbIteratorNext(it_array, &v2, true)) != WJB_DONE)
4754  res = pushJsonbValue(state, r2, r2 != WJB_END_ARRAY ? &v2 : NULL);
4755  }
4756  else
4757  {
4758  while ((r1 = JsonbIteratorNext(it_array, &v1, true)) != WJB_END_ARRAY)
4759  pushJsonbValue(state, r1, &v1);
4760 
4761  pushJsonbValue(state, WJB_BEGIN_OBJECT, NULL);
4762  while ((r2 = JsonbIteratorNext(it_object, &v2, true)) != WJB_DONE)
4763  pushJsonbValue(state, r2, r2 != WJB_END_OBJECT ? &v2 : NULL);
4764 
4765  res = pushJsonbValue(state, WJB_END_ARRAY, NULL);
4766  }
4767  }
4768  else
4769  {
4770  /*
4771  * This must be scalar || object or object || scalar, as that's all
4772  * that's left. Both of these make no sense, so error out.
4773  */
4774  ereport(ERROR,
4775  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4776  errmsg("invalid concatenation of jsonb objects")));
4777  }
4778 
4779  return res;
4780 }
Definition: jsonb.h:22
int errcode(int sqlerrcode)
Definition: elog.c:610
JsonbValue * pushJsonbValue(JsonbParseState **pstate, JsonbIteratorToken seq, JsonbValue *jbval)
Definition: jsonb_util.c:559
#define ERROR
Definition: elog.h:43
JsonbIteratorToken
Definition: jsonb.h:20
#define ereport(elevel,...)
Definition: elog.h:144
#define Assert(condition)
Definition: c.h:738
int errmsg(const char *fmt,...)
Definition: elog.c:824
JsonbIteratorToken JsonbIteratorNext(JsonbIterator **it, JsonbValue *val, bool skipNested)
Definition: jsonb_util.c:796
Definition: jsonb.h:25

◆ JsObjectGetField()

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

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

3125 {
3126  jsv->is_json = obj->is_json;
3127 
3128  if (jsv->is_json)
3129  {
3130  JsonHashEntry *hashentry = hash_search(obj->val.json_hash, field,
3131  HASH_FIND, NULL);
3132 
3133  jsv->val.json.type = hashentry ? hashentry->type : JSON_TOKEN_NULL;
3134  jsv->val.json.str = jsv->val.json.type == JSON_TOKEN_NULL ? NULL :
3135  hashentry->val;
3136  jsv->val.json.len = jsv->val.json.str ? -1 : 0; /* null-terminated */
3137 
3138  return hashentry != NULL;
3139  }
3140  else
3141  {
3142  jsv->val.jsonb = !obj->val.jsonb_cont ? NULL :
3143  getKeyJsonValueFromContainer(obj->val.jsonb_cont, field, strlen(field),
3144  NULL);
3145 
3146  return jsv->val.jsonb != NULL;
3147  }
3148 }
bool is_json
Definition: jsonfuncs.c:302
JsonbValue * getKeyJsonValueFromContainer(JsonbContainer *container, const char *keyVal, int keyLen, JsonbValue *res)
Definition: jsonb_util.c:391
union JsObject::@31 val
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:908
JsonTokenType type
Definition: jsonfuncs.c:144
struct JsValue::@29::@30 json
JsonbContainer * jsonb_cont
Definition: jsonfuncs.c:306
char * val
Definition: jsonfuncs.c:143
bool is_json
Definition: jsonfuncs.c:286
HTAB * json_hash
Definition: jsonfuncs.c:305
union JsValue::@29 val
JsonbValue * jsonb
Definition: jsonfuncs.c:296

◆ json_array_element()

Datum json_array_element ( PG_FUNCTION_ARGS  )

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

885 {
886  text *json = PG_GETARG_TEXT_PP(0);
887  int element = PG_GETARG_INT32(1);
888  text *result;
889 
890  result = get_worker(json, NULL, &element, 1, false);
891 
892  if (result != NULL)
893  PG_RETURN_TEXT_P(result);
894  else
895  PG_RETURN_NULL();
896 }
#define PG_GETARG_INT32(n)
Definition: fmgr.h:269
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:308
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:1066
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:370
Definition: c.h:555
#define PG_RETURN_NULL()
Definition: fmgr.h:344

◆ json_array_element_text()

Datum json_array_element_text ( PG_FUNCTION_ARGS  )

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

928 {
929  text *json = PG_GETARG_TEXT_PP(0);
930  int element = PG_GETARG_INT32(1);
931  text *result;
932 
933  result = get_worker(json, NULL, &element, 1, true);
934 
935  if (result != NULL)
936  PG_RETURN_TEXT_P(result);
937  else
938  PG_RETURN_NULL();
939 }
#define PG_GETARG_INT32(n)
Definition: fmgr.h:269
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:308
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:1066
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:370
Definition: c.h:555
#define PG_RETURN_NULL()
Definition: fmgr.h:344

◆ json_array_elements()

Datum json_array_elements ( PG_FUNCTION_ARGS  )

Definition at line 2167 of file jsonfuncs.c.

References elements_worker().

2168 {
2169  return elements_worker(fcinfo, "json_array_elements", false);
2170 }
static Datum elements_worker(FunctionCallInfo fcinfo, const char *funcname, bool as_text)
Definition: jsonfuncs.c:2179

◆ json_array_elements_text()

Datum json_array_elements_text ( PG_FUNCTION_ARGS  )

Definition at line 2173 of file jsonfuncs.c.

References elements_worker().

2174 {
2175  return elements_worker(fcinfo, "json_array_elements_text", true);
2176 }
static Datum elements_worker(FunctionCallInfo fcinfo, const char *funcname, bool as_text)
Definition: jsonfuncs.c:2179

◆ json_array_length()

Datum json_array_length ( PG_FUNCTION_ARGS  )

Definition at line 1647 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_or_ereport(), PG_RETURN_INT32, JsonSemAction::scalar, and JsonSemAction::semstate.

1648 {
1649  text *json = PG_GETARG_TEXT_PP(0);
1650  AlenState *state;
1651  JsonLexContext *lex;
1652  JsonSemAction *sem;
1653 
1654  lex = makeJsonLexContext(json, false);
1655  state = palloc0(sizeof(AlenState));
1656  sem = palloc0(sizeof(JsonSemAction));
1657 
1658  /* palloc0 does this for us */
1659 #if 0
1660  state->count = 0;
1661 #endif
1662  state->lex = lex;
1663 
1664  sem->semstate = (void *) state;
1666  sem->scalar = alen_scalar;
1668 
1669  pg_parse_json_or_ereport(lex, sem);
1670 
1671  PG_RETURN_INT32(state->count);
1672 }
json_struct_action object_start
Definition: jsonapi.h:107
JsonLexContext * makeJsonLexContext(text *json, bool need_escapes)
Definition: jsonfuncs.c:513
#define PG_RETURN_INT32(x)
Definition: fmgr.h:353
json_scalar_action scalar
Definition: jsonapi.h:115
int count
Definition: jsonfuncs.c:98
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:308
static void alen_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:1709
JsonLexContext * lex
Definition: jsonfuncs.c:97
void pg_parse_json_or_ereport(JsonLexContext *lex, JsonSemAction *sem)
Definition: jsonfuncs.c:497
void * palloc0(Size size)
Definition: mcxt.c:980
json_aelem_action array_element_start
Definition: jsonapi.h:113
Definition: regguts.h:298
static void alen_object_start(void *state)
Definition: jsonfuncs.c:1697
Definition: c.h:555
static void alen_array_element_start(void *state, bool isnull)
Definition: jsonfuncs.c:1721
void * semstate
Definition: jsonapi.h:106

◆ json_each()

Datum json_each ( PG_FUNCTION_ARGS  )

Definition at line 1741 of file jsonfuncs.c.

References each_worker().

1742 {
1743  return each_worker(fcinfo, false);
1744 }
static Datum each_worker(FunctionCallInfo fcinfo, bool as_text)
Definition: jsonfuncs.c:1883

◆ json_each_text()

Datum json_each_text ( PG_FUNCTION_ARGS  )

Definition at line 1753 of file jsonfuncs.c.

References each_worker().

1754 {
1755  return each_worker(fcinfo, true);
1756 }
static Datum each_worker(FunctionCallInfo fcinfo, bool as_text)
Definition: jsonfuncs.c:1883

◆ json_ereport_error()

void json_ereport_error ( JsonParseErrorType  error,
JsonLexContext lex 
)

Definition at line 607 of file jsonfuncs.c.

References ereport, errcode(), errdetail(), errmsg(), ERROR, json_errdetail(), JSON_UNICODE_CODE_POINT_ZERO, JSON_UNICODE_HIGH_ESCAPE, and report_json_context().

Referenced by get_array_start(), json_typeof(), and pg_parse_json_or_ereport().

608 {
611  ereport(ERROR,
612  (errcode(ERRCODE_UNTRANSLATABLE_CHARACTER),
613  errmsg("unsupported Unicode escape sequence"),
614  errdetail("%s", json_errdetail(error, lex)),
615  report_json_context(lex)));
616  else
617  ereport(ERROR,
618  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
619  errmsg("invalid input syntax for type %s", "json"),
620  errdetail("%s", json_errdetail(error, lex)),
621  report_json_context(lex)));
622 }
static void error(void)
Definition: sql-dyntest.c:147
char * json_errdetail(JsonParseErrorType error, JsonLexContext *lex)
Definition: jsonapi.c:1056
int errcode(int sqlerrcode)
Definition: elog.c:610
#define ERROR
Definition: elog.h:43
int errdetail(const char *fmt,...)
Definition: elog.c:957
static int report_json_context(JsonLexContext *lex)
Definition: jsonfuncs.c:635
#define ereport(elevel,...)
Definition: elog.h:144
int errmsg(const char *fmt,...)
Definition: elog.c:824

◆ json_extract_path()

Datum json_extract_path ( PG_FUNCTION_ARGS  )

Definition at line 971 of file jsonfuncs.c.

References get_path_all().

972 {
973  return get_path_all(fcinfo, false);
974 }
static Datum get_path_all(FunctionCallInfo fcinfo, bool as_text)
Definition: jsonfuncs.c:986

◆ json_extract_path_text()

Datum json_extract_path_text ( PG_FUNCTION_ARGS  )

Definition at line 977 of file jsonfuncs.c.

References get_path_all().

978 {
979  return get_path_all(fcinfo, true);
980 }
static Datum get_path_all(FunctionCallInfo fcinfo, bool as_text)
Definition: jsonfuncs.c:986

◆ json_object_field()

Datum json_object_field ( PG_FUNCTION_ARGS  )

Definition at line 808 of file jsonfuncs.c.

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

809 {
810  text *json = PG_GETARG_TEXT_PP(0);
811  text *fname = PG_GETARG_TEXT_PP(1);
812  char *fnamestr = text_to_cstring(fname);
813  text *result;
814 
815  result = get_worker(json, &fnamestr, NULL, 1, false);
816 
817  if (result != NULL)
818  PG_RETURN_TEXT_P(result);
819  else
820  PG_RETURN_NULL();
821 }
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:308
static text * get_worker(text *json, char **tpath, int *ipath, int npath, bool normalize_results)
Definition: jsonfuncs.c:1066
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:370
char * text_to_cstring(const text *t)
Definition: varlena.c:205
Definition: c.h:555
#define PG_RETURN_NULL()
Definition: fmgr.h:344

◆ json_object_field_text()

Datum json_object_field_text ( PG_FUNCTION_ARGS  )

Definition at line 846 of file jsonfuncs.c.

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

847 {
848  text *json = PG_GETARG_TEXT_PP(0);
849  text *fname = PG_GETARG_TEXT_PP(1);
850  char *fnamestr = text_to_cstring(fname);
851  text *result;
852 
853  result = get_worker(json, &fnamestr, NULL, 1, true);
854 
855  if (result != NULL)
856  PG_RETURN_TEXT_P(result);
857  else
858  PG_RETURN_NULL();
859 }
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:308
static text * get_worker(text *json, char **tpath, int *ipath, int npath, bool normalize_results)
Definition: jsonfuncs.c:1066
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:370
char * text_to_cstring(const text *t)
Definition: varlena.c:205
Definition: c.h:555
#define PG_RETURN_NULL()
Definition: fmgr.h:344

◆ json_object_keys()

Datum json_object_keys ( PG_FUNCTION_ARGS  )

Definition at line 698 of file jsonfuncs.c.

References JsonSemAction::array_start, CStringGetTextDatum, StringInfoData::data, 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_or_ereport(), 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.

699 {
700  FuncCallContext *funcctx;
701  OkeysState *state;
702 
703  if (SRF_IS_FIRSTCALL())
704  {
705  text *json = PG_GETARG_TEXT_PP(0);
706  JsonLexContext *lex = makeJsonLexContext(json, true);
707  JsonSemAction *sem;
708  MemoryContext oldcontext;
709 
710  funcctx = SRF_FIRSTCALL_INIT();
711  oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
712 
713  state = palloc(sizeof(OkeysState));
714  sem = palloc0(sizeof(JsonSemAction));
715 
716  state->lex = lex;
717  state->result_size = 256;
718  state->result_count = 0;
719  state->sent_count = 0;
720  state->result = palloc(256 * sizeof(char *));
721 
722  sem->semstate = (void *) state;
724  sem->scalar = okeys_scalar;
726  /* remainder are all NULL, courtesy of palloc0 above */
727 
728  pg_parse_json_or_ereport(lex, sem);
729  /* keys are now in state->result */
730 
731  pfree(lex->strval->data);
732  pfree(lex->strval);
733  pfree(lex);
734  pfree(sem);
735 
736  MemoryContextSwitchTo(oldcontext);
737  funcctx->user_fctx = (void *) state;
738  }
739 
740  funcctx = SRF_PERCALL_SETUP();
741  state = (OkeysState *) funcctx->user_fctx;
742 
743  if (state->sent_count < state->result_count)
744  {
745  char *nxt = state->result[state->sent_count++];
746 
747  SRF_RETURN_NEXT(funcctx, CStringGetTextDatum(nxt));
748  }
749 
750  SRF_RETURN_DONE(funcctx);
751 }
int result_count
Definition: jsonfuncs.c:53
#define SRF_IS_FIRSTCALL()
Definition: funcapi.h:293
JsonLexContext * makeJsonLexContext(text *json, bool need_escapes)
Definition: jsonfuncs.c:513
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
static void okeys_array_start(void *state)
Definition: jsonfuncs.c:775
json_scalar_action scalar
Definition: jsonapi.h:115
int sent_count
Definition: jsonfuncs.c:54
#define SRF_PERCALL_SETUP()
Definition: funcapi.h:297
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:308
#define SRF_RETURN_NEXT(_funcctx, _result)
Definition: funcapi.h:299
void pfree(void *pointer)
Definition: mcxt.c:1056
StringInfo strval
Definition: jsonapi.h:84
static void okeys_object_field_start(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:754
void pg_parse_json_or_ereport(JsonLexContext *lex, JsonSemAction *sem)
Definition: jsonfuncs.c:497
char ** result
Definition: jsonfuncs.c:51
void * palloc0(Size size)
Definition: mcxt.c:980
JsonLexContext * lex
Definition: jsonfuncs.c:50
json_struct_action array_start
Definition: jsonapi.h:109
Definition: regguts.h:298
MemoryContext multi_call_memory_ctx
Definition: funcapi.h:101
static void okeys_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:788
int result_size
Definition: jsonfuncs.c:52
void * user_fctx
Definition: funcapi.h:82
void * palloc(Size size)
Definition: mcxt.c:949
#define CStringGetTextDatum(s)
Definition: builtins.h:87
Definition: c.h:555
json_ofield_action object_field_start
Definition: jsonapi.h:111
void * semstate
Definition: jsonapi.h:106
#define SRF_RETURN_DONE(_funcctx)
Definition: funcapi.h:317
#define SRF_FIRSTCALL_INIT()
Definition: funcapi.h:295

◆ json_populate_record()

Datum json_populate_record ( PG_FUNCTION_ARGS  )

Definition at line 2365 of file jsonfuncs.c.

References populate_record_worker().

2366 {
2367  return populate_record_worker(fcinfo, "json_populate_record",
2368  true, true);
2369 }
static Datum populate_record_worker(FunctionCallInfo fcinfo, const char *funcname, bool is_json, bool have_record_arg)
Definition: jsonfuncs.c:3328

◆ json_populate_recordset()

Datum json_populate_recordset ( PG_FUNCTION_ARGS  )

Definition at line 3596 of file jsonfuncs.c.

References populate_recordset_worker().

3597 {
3598  return populate_recordset_worker(fcinfo, "json_populate_recordset",
3599  true, true);
3600 }
static Datum populate_recordset_worker(FunctionCallInfo fcinfo, const char *funcname, bool is_json, bool have_record_arg)
Definition: jsonfuncs.c:3647

◆ json_strip_nulls()

Datum json_strip_nulls ( PG_FUNCTION_ARGS  )

Definition at line 4068 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_or_ereport(), 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.

4069 {
4070  text *json = PG_GETARG_TEXT_PP(0);
4072  JsonLexContext *lex;
4073  JsonSemAction *sem;
4074 
4075  lex = makeJsonLexContext(json, true);
4076  state = palloc0(sizeof(StripnullState));
4077  sem = palloc0(sizeof(JsonSemAction));
4078 
4079  state->strval = makeStringInfo();
4080  state->skip_next_null = false;
4081  state->lex = lex;
4082 
4083  sem->semstate = (void *) state;
4085  sem->object_end = sn_object_end;
4086  sem->array_start = sn_array_start;
4087  sem->array_end = sn_array_end;
4088  sem->scalar = sn_scalar;
4091 
4092  pg_parse_json_or_ereport(lex, sem);
4093 
4095  state->strval->len));
4096 
4097 }
json_struct_action array_end
Definition: jsonapi.h:110
bool skip_next_null
Definition: jsonfuncs.c:280
static void sn_object_start(void *state)
Definition: jsonfuncs.c:3978
json_struct_action object_end
Definition: jsonapi.h:108
static void sn_array_element_start(void *state, bool isnull)
Definition: jsonfuncs.c:4038
static void sn_object_field_start(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:4010
StringInfo makeStringInfo(void)
Definition: stringinfo.c:41
json_struct_action object_start
Definition: jsonapi.h:107
JsonLexContext * makeJsonLexContext(text *json, bool need_escapes)
Definition: jsonfuncs.c:513
json_scalar_action scalar
Definition: jsonapi.h:115
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:308
static void sn_array_start(void *state)
Definition: jsonfuncs.c:3994
text * cstring_to_text_with_len(const char *s, int len)
Definition: varlena.c:184
JsonLexContext * lex
Definition: jsonfuncs.c:278
static void sn_object_end(void *state)
Definition: jsonfuncs.c:3986
void pg_parse_json_or_ereport(JsonLexContext *lex, JsonSemAction *sem)
Definition: jsonfuncs.c:497
void * palloc0(Size size)
Definition: mcxt.c:980
json_aelem_action array_element_start
Definition: jsonapi.h:113
static void sn_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:4047
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:370
json_struct_action array_start
Definition: jsonapi.h:109
Definition: regguts.h:298
StringInfo strval
Definition: jsonfuncs.c:279
Definition: c.h:555
json_ofield_action object_field_start
Definition: jsonapi.h:111
static void sn_array_end(void *state)
Definition: jsonfuncs.c:4002
void * semstate
Definition: jsonapi.h:106

◆ json_to_record()

Datum json_to_record ( PG_FUNCTION_ARGS  )

Definition at line 2372 of file jsonfuncs.c.

References populate_record_worker().

2373 {
2374  return populate_record_worker(fcinfo, "json_to_record",
2375  true, false);
2376 }
static Datum populate_record_worker(FunctionCallInfo fcinfo, const char *funcname, bool is_json, bool have_record_arg)
Definition: jsonfuncs.c:3328

◆ json_to_recordset()

Datum json_to_recordset ( PG_FUNCTION_ARGS  )

Definition at line 3603 of file jsonfuncs.c.

References populate_recordset_worker().

3604 {
3605  return populate_recordset_worker(fcinfo, "json_to_recordset",
3606  true, false);
3607 }
static Datum populate_recordset_worker(FunctionCallInfo fcinfo, const char *funcname, bool is_json, bool have_record_arg)
Definition: jsonfuncs.c:3647

◆ jsonb_array_element()

Datum jsonb_array_element ( PG_FUNCTION_ARGS  )

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

900 {
901  Jsonb *jb = PG_GETARG_JSONB_P(0);
902  int element = PG_GETARG_INT32(1);
903  JsonbValue *v;
904 
905  if (!JB_ROOT_IS_ARRAY(jb))
906  PG_RETURN_NULL();
907 
908  /* Handle negative subscript */
909  if (element < 0)
910  {
911  uint32 nelements = JB_ROOT_COUNT(jb);
912 
913  if (-element > nelements)
914  PG_RETURN_NULL();
915  else
916  element += nelements;
917  }
918 
919  v = getIthJsonbValueFromContainer(&jb->root, element);
920  if (v != NULL)
922 
923  PG_RETURN_NULL();
924 }
#define PG_GETARG_INT32(n)
Definition: fmgr.h:269
Jsonb * JsonbValueToJsonb(JsonbValue *val)
Definition: jsonb_util.c:85
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:367
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:461
#define PG_RETURN_JSONB_P(x)
Definition: jsonb.h:76
#define PG_RETURN_NULL()
Definition: fmgr.h:344
#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 942 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.

943 {
944  Jsonb *jb = PG_GETARG_JSONB_P(0);
945  int element = PG_GETARG_INT32(1);
946  JsonbValue *v;
947 
948  if (!JB_ROOT_IS_ARRAY(jb))
949  PG_RETURN_NULL();
950 
951  /* Handle negative subscript */
952  if (element < 0)
953  {
954  uint32 nelements = JB_ROOT_COUNT(jb);
955 
956  if (-element > nelements)
957  PG_RETURN_NULL();
958  else
959  element += nelements;
960  }
961 
962  v = getIthJsonbValueFromContainer(&jb->root, element);
963 
964  if (v != NULL && v->type != jbvNull)
966 
967  PG_RETURN_NULL();
968 }
#define PG_GETARG_INT32(n)
Definition: fmgr.h:269
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:1600
#define JB_ROOT_IS_ARRAY(jbp_)
Definition: jsonb.h:230
unsigned int uint32
Definition: c.h:367
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:370
JsonbValue * getIthJsonbValueFromContainer(JsonbContainer *container, uint32 i)
Definition: jsonb_util.c:461
enum jbvType type
Definition: jsonb.h:263
#define PG_RETURN_NULL()
Definition: fmgr.h:344
#define PG_GETARG_JSONB_P(x)
Definition: jsonb.h:74

◆ jsonb_array_elements()

Datum jsonb_array_elements ( PG_FUNCTION_ARGS  )

Definition at line 2049 of file jsonfuncs.c.

References elements_worker_jsonb().

2050 {
2051  return elements_worker_jsonb(fcinfo, "jsonb_array_elements", false);
2052 }
static Datum elements_worker_jsonb(FunctionCallInfo fcinfo, const char *funcname, bool as_text)
Definition: jsonfuncs.c:2061

◆ jsonb_array_elements_text()

Datum jsonb_array_elements_text ( PG_FUNCTION_ARGS  )

Definition at line 2055 of file jsonfuncs.c.

References elements_worker_jsonb().

2056 {
2057  return elements_worker_jsonb(fcinfo, "jsonb_array_elements_text", true);
2058 }
static Datum elements_worker_jsonb(FunctionCallInfo fcinfo, const char *funcname, bool as_text)
Definition: jsonfuncs.c:2061

◆ jsonb_array_length()

Datum jsonb_array_length ( PG_FUNCTION_ARGS  )

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

1676 {
1677  Jsonb *jb = PG_GETARG_JSONB_P(0);
1678 
1679  if (JB_ROOT_IS_SCALAR(jb))
1680  ereport(ERROR,
1681  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1682  errmsg("cannot get array length of a scalar")));
1683  else if (!JB_ROOT_IS_ARRAY(jb))
1684  ereport(ERROR,
1685  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1686  errmsg("cannot get array length of a non-array")));
1687 
1689 }
Definition: jsonb.h:220
#define PG_RETURN_INT32(x)
Definition: fmgr.h:353
#define JB_ROOT_COUNT(jbp_)
Definition: jsonb.h:227
int errcode(int sqlerrcode)
Definition: elog.c:610
#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,...)
Definition: elog.h:144
int errmsg(const char *fmt,...)
Definition: elog.c:824
#define PG_GETARG_JSONB_P(x)
Definition: jsonb.h:74

◆ jsonb_concat()

Datum jsonb_concat ( PG_FUNCTION_ARGS  )

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

4230 {
4231  Jsonb *jb1 = PG_GETARG_JSONB_P(0);
4232  Jsonb *jb2 = PG_GETARG_JSONB_P(1);
4233  JsonbParseState *state = NULL;
4234  JsonbValue *res;
4235  JsonbIterator *it1,
4236  *it2;
4237 
4238  /*
4239  * If one of the jsonb is empty, just return the other if it's not scalar
4240  * and both are of the same kind. If it's a scalar or they are of
4241  * different kinds we need to perform the concatenation even if one is
4242  * empty.
4243  */
4244  if (JB_ROOT_IS_OBJECT(jb1) == JB_ROOT_IS_OBJECT(jb2))
4245  {
4246  if (JB_ROOT_COUNT(jb1) == 0 && !JB_ROOT_IS_SCALAR(jb2))
4247  PG_RETURN_JSONB_P(jb2);
4248  else if (JB_ROOT_COUNT(jb2) == 0 && !JB_ROOT_IS_SCALAR(jb1))
4249  PG_RETURN_JSONB_P(jb1);
4250  }
4251 
4252  it1 = JsonbIteratorInit(&jb1->root);
4253  it2 = JsonbIteratorInit(&jb2->root);
4254 
4255  res = IteratorConcat(&it1, &it2, &state);
4256 
4257  Assert(res != NULL);
4258 
4260 }
#define JB_ROOT_IS_OBJECT(jbp_)
Definition: jsonb.h:229
Jsonb * JsonbValueToJsonb(JsonbValue *val)
Definition: jsonb_util.c:85
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:738
JsonbIterator * JsonbIteratorInit(JsonbContainer *container)
Definition: jsonb_util.c:760
Definition: regguts.h:298
static JsonbValue * IteratorConcat(JsonbIterator **it1, JsonbIterator **it2, JsonbParseState **state)
Definition: jsonfuncs.c:4679
#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 4270 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.

4271 {
4272  Jsonb *in = PG_GETARG_JSONB_P(0);
4273  text *key = PG_GETARG_TEXT_PP(1);
4274  char *keyptr = VARDATA_ANY(key);
4275  int keylen = VARSIZE_ANY_EXHDR(key);
4276  JsonbParseState *state = NULL;
4277  JsonbIterator *it;
4278  JsonbValue v,
4279  *res = NULL;
4280  bool skipNested = false;
4282 
4283  if (JB_ROOT_IS_SCALAR(in))
4284  ereport(ERROR,
4285  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4286  errmsg("cannot delete from scalar")));
4287 
4288  if (JB_ROOT_COUNT(in) == 0)
4289  PG_RETURN_JSONB_P(in);
4290 
4291  it = JsonbIteratorInit(&in->root);
4292 
4293  while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE)
4294  {
4295  skipNested = true;
4296 
4297  if ((r == WJB_ELEM || r == WJB_KEY) &&
4298  (v.type == jbvString && keylen == v.val.string.len &&
4299  memcmp(keyptr, v.val.string.val, keylen) == 0))
4300  {
4301  /* skip corresponding value as well */
4302  if (r == WJB_KEY)
4303  (void) JsonbIteratorNext(&it, &v, true);
4304 
4305  continue;
4306  }
4307 
4308  res = pushJsonbValue(&state, r, r < WJB_BEGIN_ARRAY ? &v : NULL);
4309  }
4310 
4311  Assert(res != NULL);
4312 
4314 }
#define VARDATA_ANY(PTR)
Definition: postgres.h:348
Jsonb * JsonbValueToJsonb(JsonbValue *val)
Definition: jsonb_util.c:85
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:610
#define JB_ROOT_IS_SCALAR(jbp_)
Definition: jsonb.h:228
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:308
JsonbValue * pushJsonbValue(JsonbParseState **pstate, JsonbIteratorToken seq, JsonbValue *jbval)
Definition: jsonb_util.c:559
#define ERROR
Definition: elog.h:43
Definition: jsonb.h:23
JsonbIteratorToken
Definition: jsonb.h:20
JsonbContainer root
Definition: jsonb.h:223
#define ereport(elevel,...)
Definition: elog.h:144
#define Assert(condition)
Definition: c.h:738
JsonbIterator * JsonbIteratorInit(JsonbContainer *container)
Definition: jsonb_util.c:760
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:824
Definition: c.h:555
#define PG_RETURN_JSONB_P(x)
Definition: jsonb.h:76
JsonbIteratorToken JsonbIteratorNext(JsonbIterator **it, JsonbValue *val, bool skipNested)
Definition: jsonb_util.c:796
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 4323 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.

4324 {
4325  Jsonb *in = PG_GETARG_JSONB_P(0);
4326  ArrayType *keys = PG_GETARG_ARRAYTYPE_P(1);
4327  Datum *keys_elems;
4328  bool *keys_nulls;
4329  int keys_len;
4330  JsonbParseState *state = NULL;
4331  JsonbIterator *it;
4332  JsonbValue v,
4333  *res = NULL;
4334  bool skipNested = false;
4336 
4337  if (ARR_NDIM(keys) > 1)
4338  ereport(ERROR,
4339  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
4340  errmsg("wrong number of array subscripts")));
4341 
4342  if (JB_ROOT_IS_SCALAR(in))
4343  ereport(ERROR,
4344  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4345  errmsg("cannot delete from scalar")));
4346 
4347  if (JB_ROOT_COUNT(in) == 0)
4348  PG_RETURN_JSONB_P(in);
4349 
4350  deconstruct_array(keys, TEXTOID, -1, false, TYPALIGN_INT,
4351  &keys_elems, &keys_nulls, &keys_len);
4352 
4353  if (keys_len == 0)
4354  PG_RETURN_JSONB_P(in);
4355 
4356  it = JsonbIteratorInit(&in->root);
4357 
4358  while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE)
4359  {
4360  skipNested = true;
4361 
4362  if ((r == WJB_ELEM || r == WJB_KEY) && v.type == jbvString)
4363  {
4364  int i;
4365  bool found = false;
4366 
4367  for (i = 0; i < keys_len; i++)
4368  {
4369  char *keyptr;
4370  int keylen;
4371 
4372  if (keys_nulls[i])
4373  continue;
4374 
4375  keyptr = VARDATA_ANY(keys_elems[i]);
4376  keylen = VARSIZE_ANY_EXHDR(keys_elems[i]);
4377  if (keylen == v.val.string.len &&
4378  memcmp(keyptr, v.val.string.val, keylen) == 0)
4379  {
4380  found = true;
4381  break;
4382  }
4383  }
4384  if (found)
4385  {
4386  /* skip corresponding value as well */
4387  if (r == WJB_KEY)
4388  (void) JsonbIteratorNext(&it, &v, true);
4389 
4390  continue;
4391  }
4392  }
4393 
4394  res = pushJsonbValue(&state, r, r < WJB_BEGIN_ARRAY ? &v : NULL);
4395  }
4396 
4397  Assert(res != NULL);
4398 
4400 }
#define VARDATA_ANY(PTR)
Definition: postgres.h:348
Jsonb * JsonbValueToJsonb(JsonbValue *val)
Definition: jsonb_util.c:85
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:610
#define JB_ROOT_IS_SCALAR(jbp_)
Definition: jsonb.h:228
JsonbValue * pushJsonbValue(JsonbParseState **pstate, JsonbIteratorToken seq, JsonbValue *jbval)
Definition: jsonb_util.c:559
#define PG_GETARG_ARRAYTYPE_P(n)
Definition: array.h:251
#define ERROR
Definition: elog.h:43
Definition: jsonb.h:23
JsonbIteratorToken
Definition: jsonb.h:20
JsonbContainer root
Definition: jsonb.h:223
uintptr_t Datum
Definition: postgres.h:367
#define ereport(elevel,...)
Definition: elog.h:144
#define Assert(condition)
Definition: c.h:738
JsonbIterator * JsonbIteratorInit(JsonbContainer *container)
Definition: jsonb_util.c:760
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:3462
#define VARSIZE_ANY_EXHDR(PTR)
Definition: postgres.h:341
int errmsg(const char *fmt,...)
Definition: elog.c:824
int i
#define PG_RETURN_JSONB_P(x)
Definition: jsonb.h:76
JsonbIteratorToken JsonbIteratorNext(JsonbIterator **it, JsonbValue *val, bool skipNested)
Definition: jsonb_util.c:796
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 4410 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.

4411 {
4412  Jsonb *in = PG_GETARG_JSONB_P(0);
4413  int idx = PG_GETARG_INT32(1);
4414  JsonbParseState *state = NULL;
4415  JsonbIterator *it;
4416  uint32 i = 0,
4417  n;
4418  JsonbValue v,
4419  *res = NULL;
4421 
4422  if (JB_ROOT_IS_SCALAR(in))
4423  ereport(ERROR,
4424  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4425  errmsg("cannot delete from scalar")));
4426 
4427  if (JB_ROOT_IS_OBJECT(in))
4428  ereport(ERROR,
4429  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4430  errmsg("cannot delete from object using integer index")));
4431 
4432  if (JB_ROOT_COUNT(in) == 0)
4433  PG_RETURN_JSONB_P(in);
4434 
4435  it = JsonbIteratorInit(&in->root);
4436 
4437  r = JsonbIteratorNext(&it, &v, false);
4438  Assert(r == WJB_BEGIN_ARRAY);
4439  n = v.val.array.nElems;
4440 
4441  if (idx < 0)
4442  {
4443  if (-idx > n)
4444  idx = n;
4445  else
4446  idx = n + idx;
4447  }
4448 
4449  if (idx >= n)
4450  PG_RETURN_JSONB_P(in);
4451 
4452  pushJsonbValue(&state, r, NULL);
4453 
4454  while ((r = JsonbIteratorNext(&it, &v, true)) != WJB_DONE)
4455  {
4456  if (r == WJB_ELEM)
4457  {
4458  if (i++ == idx)
4459  continue;
4460  }
4461 
4462  res = pushJsonbValue(&state, r, r < WJB_BEGIN_ARRAY ? &v : NULL);
4463  }
4464 
4465  Assert(res != NULL);
4466 
4468 }
#define PG_GETARG_INT32(n)
Definition: fmgr.h:269
#define JB_ROOT_IS_OBJECT(jbp_)
Definition: jsonb.h:229
Jsonb * JsonbValueToJsonb(JsonbValue *val)
Definition: jsonb_util.c:85
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:610
Datum idx(PG_FUNCTION_ARGS)
Definition: _int_op.c:259
#define JB_ROOT_IS_SCALAR(jbp_)
Definition: jsonb.h:228
JsonbValue * pushJsonbValue(JsonbParseState **pstate, JsonbIteratorToken seq, JsonbValue *jbval)
Definition: jsonb_util.c:559
#define ERROR
Definition: elog.h:43
unsigned int uint32
Definition: c.h:367
JsonbIteratorToken
Definition: jsonb.h:20
JsonbContainer root
Definition: jsonb.h:223
#define ereport(elevel,...)
Definition: elog.h:144
#define Assert(condition)
Definition: c.h:738
JsonbIterator * JsonbIteratorInit(JsonbContainer *container)
Definition: jsonb_util.c:760
Definition: regguts.h:298
int errmsg(const char *fmt,...)
Definition: elog.c:824
int i
#define PG_RETURN_JSONB_P(x)
Definition: jsonb.h:76
JsonbIteratorToken JsonbIteratorNext(JsonbIterator **it, JsonbValue *val, bool skipNested)
Definition: jsonb_util.c:796
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 4588 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().

Referenced by jsonb_set_lax().

4589 {
4590  Jsonb *in = PG_GETARG_JSONB_P(0);
4591  ArrayType *path = PG_GETARG_ARRAYTYPE_P(1);
4592  JsonbValue *res = NULL;
4593  Datum *path_elems;
4594  bool *path_nulls;
4595  int path_len;
4596  JsonbIterator *it;
4597  JsonbParseState *st = NULL;
4598 
4599  if (ARR_NDIM(path) > 1)
4600  ereport(ERROR,
4601  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
4602  errmsg("wrong number of array subscripts")));
4603 
4604  if (JB_ROOT_IS_SCALAR(in))
4605  ereport(ERROR,
4606  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4607  errmsg("cannot delete path in scalar")));
4608 
4609  if (JB_ROOT_COUNT(in) == 0)
4610  PG_RETURN_JSONB_P(in);
4611 
4612  deconstruct_array(path, TEXTOID, -1, false, TYPALIGN_INT,
4613  &path_elems, &path_nulls, &path_len);
4614 
4615  if (path_len == 0)
4616  PG_RETURN_JSONB_P(in);
4617 
4618  it = JsonbIteratorInit(&in->root);
4619 
4620  res = setPath(&it, path_elems, path_nulls, path_len, &st,
4621  0, NULL, JB_PATH_DELETE);
4622 
4623  Assert(res != NULL);
4624 
4626 }
Jsonb * JsonbValueToJsonb(JsonbValue *val)
Definition: jsonb_util.c:85
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:4797
#define JB_ROOT_COUNT(jbp_)
Definition: jsonb.h:227
int errcode(int sqlerrcode)
Definition: elog.c:610
#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
JsonbContainer root
Definition: jsonb.h:223
uintptr_t Datum
Definition: postgres.h:367
#define ereport(elevel,...)
Definition: elog.h:144
#define Assert(condition)
Definition: c.h:738
JsonbIterator * JsonbIteratorInit(JsonbContainer *container)
Definition: jsonb_util.c:760
#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:3462
int errmsg(const char *fmt,...)
Definition: elog.c:824
#define PG_RETURN_JSONB_P(x)
Definition: jsonb.h:76
#define JB_PATH_DELETE
Definition: jsonfuncs.c:40
#define PG_GETARG_JSONB_P(x)
Definition: jsonb.h:74

◆ jsonb_each()

Datum jsonb_each ( PG_FUNCTION_ARGS  )

Definition at line 1747 of file jsonfuncs.c.

References each_worker_jsonb().

1748 {
1749  return each_worker_jsonb(fcinfo, "jsonb_each", false);
1750 }
static Datum each_worker_jsonb(FunctionCallInfo fcinfo, const char *funcname, bool as_text)
Definition: jsonfuncs.c:1765

◆ jsonb_each_text()

Datum jsonb_each_text ( PG_FUNCTION_ARGS  )

Definition at line 1759 of file jsonfuncs.c.

References each_worker_jsonb().

1760 {
1761  return each_worker_jsonb(fcinfo, "jsonb_each_text", true);
1762 }