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 "common/string.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/fmgroids.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 JB_PATH_FILL_GAPS   0x0020
 
#define JB_PATH_CONSISTENT_POSITION   0x0040
 
#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, JsonbValue *newval, int op_type)
 
static void setPathObject (JsonbIterator **it, Datum *path_elems, bool *path_nulls, int path_len, JsonbParseState **st, int level, JsonbValue *newval, uint32 npairs, int op_type)
 
static void setPathArray (JsonbIterator **it, Datum *path_elems, bool *path_nulls, int path_len, JsonbParseState **st, int level, JsonbValue *newval, uint32 nelems, int op_type)
 
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 jsonb_get_element (Jsonb *jb, Datum *path, int npath, bool *isnull, bool as_text)
 
Datum jsonb_set_element (Jsonb *jb, Datum *path, int path_len, JsonbValue *newval)
 
static void push_null_elements (JsonbParseState **ps, int num)
 
static void push_path (JsonbParseState **st, int level, Datum *path_elems, bool *path_nulls, int path_len, JsonbValue *newval)
 
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_CONSISTENT_POSITION

#define JB_PATH_CONSISTENT_POSITION   0x0040

Definition at line 49 of file jsonfuncs.c.

Referenced by jsonb_set_element(), and setPathArray().

◆ JB_PATH_CREATE

#define JB_PATH_CREATE   0x0001

Definition at line 41 of file jsonfuncs.c.

Referenced by jsonb_set(), jsonb_set_element(), 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 46 of file jsonfuncs.c.

Referenced by setPathArray(), and setPathObject().

◆ JB_PATH_DELETE

#define JB_PATH_DELETE   0x0002

Definition at line 42 of file jsonfuncs.c.

Referenced by jsonb_delete_path(), and setPathObject().

◆ JB_PATH_FILL_GAPS

#define JB_PATH_FILL_GAPS   0x0020

Definition at line 48 of file jsonfuncs.c.

Referenced by jsonb_set_element(), setPath(), setPathArray(), and setPathObject().

◆ JB_PATH_INSERT_AFTER

#define JB_PATH_INSERT_AFTER   0x0010

Definition at line 45 of file jsonfuncs.c.

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

◆ JB_PATH_INSERT_BEFORE

#define JB_PATH_INSERT_BEFORE   0x0008

Definition at line 44 of file jsonfuncs.c.

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

◆ JB_PATH_REPLACE

#define JB_PATH_REPLACE   0x0004

Definition at line 43 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 330 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:1382
long val
Definition: informix.c:664

Definition at line 324 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 315 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 320 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 159 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 160 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 196 of file jsonfuncs.c.

Function Documentation

◆ alen_array_element_start()

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

Definition at line 1862 of file jsonfuncs.c.

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

Referenced by json_array_length().

1863 {
1864  AlenState *_state = (AlenState *) state;
1865 
1866  /* just count up all the level 1 elements */
1867  if (_state->lex->lex_level == 1)
1868  _state->count++;
1869 }
int count
Definition: jsonfuncs.c:102
int lex_level
Definition: jsonapi.h:81
JsonLexContext * lex
Definition: jsonfuncs.c:101
Definition: regguts.h:317

◆ alen_object_start()

static void alen_object_start ( void *  state)
static

Definition at line 1838 of file jsonfuncs.c.

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

Referenced by json_array_length().

1839 {
1840  AlenState *_state = (AlenState *) state;
1841 
1842  /* json structure check */
1843  if (_state->lex->lex_level == 0)
1844  ereport(ERROR,
1845  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1846  errmsg("cannot get array length of a non-array")));
1847 }
int errcode(int sqlerrcode)
Definition: elog.c:698
int lex_level
Definition: jsonapi.h:81
#define ERROR
Definition: elog.h:46
JsonLexContext * lex
Definition: jsonfuncs.c:101
#define ereport(elevel,...)
Definition: elog.h:157
Definition: regguts.h:317
int errmsg(const char *fmt,...)
Definition: elog.c:909

◆ alen_scalar()

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

Definition at line 1850 of file jsonfuncs.c.

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

Referenced by json_array_length().

1851 {
1852  AlenState *_state = (AlenState *) state;
1853 
1854  /* json structure check */
1855  if (_state->lex->lex_level == 0)
1856  ereport(ERROR,
1857  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1858  errmsg("cannot get array length of a scalar")));
1859 }
int errcode(int sqlerrcode)
Definition: elog.c:698
int lex_level
Definition: jsonapi.h:81
#define ERROR
Definition: elog.h:46
JsonLexContext * lex
Definition: jsonfuncs.c:101
#define ereport(elevel,...)
Definition: elog.h:157
Definition: regguts.h:317
int errmsg(const char *fmt,...)
Definition: elog.c:909

◆ allocate_record_info()

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

Definition at line 3249 of file jsonfuncs.c.

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

Referenced by populate_record().

3250 {
3251  RecordIOData *data = (RecordIOData *)
3252  MemoryContextAlloc(mcxt,
3253  offsetof(RecordIOData, columns) +
3254  ncolumns * sizeof(ColumnIOData));
3255 
3256  data->record_type = InvalidOid;
3257  data->record_typmod = 0;
3258  data->ncolumns = ncolumns;
3259  MemSet(data->columns, 0, sizeof(ColumnIOData) * ncolumns);
3260 
3261  return data;
3262 }
Oid record_type
Definition: hstore_io.c:766
struct ColumnIOData ColumnIOData
Definition: jsonfuncs.c:159
#define MemSet(start, val, len)
Definition: c.h:1008
int32 record_typmod
Definition: hstore_io.c:767
ColumnIOData columns[FLEXIBLE_ARRAY_MEMBER]
Definition: hstore_io.c:771
#define InvalidOid
Definition: postgres_ext.h:36
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:863
#define offsetof(type, field)
Definition: c.h:727

◆ each_array_start()

static void each_array_start ( void *  state)
static

Definition at line 2154 of file jsonfuncs.c.

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

Referenced by each_worker().

2155 {
2156  EachState *_state = (EachState *) state;
2157 
2158  /* json structure check */
2159  if (_state->lex->lex_level == 0)
2160  ereport(ERROR,
2161  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2162  errmsg("cannot deconstruct an array as an object")));
2163 }
int errcode(int sqlerrcode)
Definition: elog.c:698
int lex_level
Definition: jsonapi.h:81
#define ERROR
Definition: elog.h:46
JsonLexContext * lex
Definition: jsonfuncs.c:108
#define ereport(elevel,...)
Definition: elog.h:157
Definition: regguts.h:317
int errmsg(const char *fmt,...)
Definition: elog.c:909

◆ each_object_field_end()

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

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

2109 {
2110  EachState *_state = (EachState *) state;
2111  MemoryContext old_cxt;
2112  int len;
2113  text *val;
2114  HeapTuple tuple;
2115  Datum values[2];
2116  bool nulls[2] = {false, false};
2117 
2118  /* skip over nested objects */
2119  if (_state->lex->lex_level != 1)
2120  return;
2121 
2122  /* use the tmp context so we can clean up after each tuple is done */
2123  old_cxt = MemoryContextSwitchTo(_state->tmp_cxt);
2124 
2125  values[0] = CStringGetTextDatum(fname);
2126 
2127  if (isnull && _state->normalize_results)
2128  {
2129  nulls[1] = true;
2130  values[1] = (Datum) 0;
2131  }
2132  else if (_state->next_scalar)
2133  {
2134  values[1] = CStringGetTextDatum(_state->normalized_scalar);
2135  _state->next_scalar = false;
2136  }
2137  else
2138  {
2139  len = _state->lex->prev_token_terminator - _state->result_start;
2140  val = cstring_to_text_with_len(_state->result_start, len);
2141  values[1] = PointerGetDatum(val);
2142  }
2143 
2144  tuple = heap_form_tuple(_state->ret_tdesc, values, nulls);
2145 
2146  tuplestore_puttuple(_state->tuple_store, tuple);
2147 
2148  /* clean up and switch back */
2149  MemoryContextSwitchTo(old_cxt);
2150  MemoryContextReset(_state->tmp_cxt);
2151 }
Tuplestorestate * tuple_store
Definition: jsonfuncs.c:109
#define PointerGetDatum(X)
Definition: postgres.h:600
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
char * prev_token_terminator
Definition: jsonapi.h:79
void MemoryContextReset(MemoryContext context)
Definition: mcxt.c:143
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:1020
TupleDesc ret_tdesc
Definition: jsonfuncs.c:110
int lex_level
Definition: jsonapi.h:81
MemoryContext tmp_cxt
Definition: jsonfuncs.c:111
char * result_start
Definition: jsonfuncs.c:112
JsonLexContext * lex
Definition: jsonfuncs.c:108
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:202
uintptr_t Datum
Definition: postgres.h:411
bool normalize_results
Definition: jsonfuncs.c:113
char * normalized_scalar
Definition: jsonfuncs.c:115
Definition: regguts.h:317
static Datum values[MAXATTR]
Definition: bootstrap.c:166
#define CStringGetTextDatum(s)
Definition: builtins.h:82
Definition: c.h:621
long val
Definition: informix.c:664
bool next_scalar
Definition: jsonfuncs.c:114

◆ each_object_field_start()

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

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

2089 {
2090  EachState *_state = (EachState *) state;
2091 
2092  /* save a pointer to where the value starts */
2093  if (_state->lex->lex_level == 1)
2094  {
2095  /*
2096  * next_scalar will be reset in the object_field_end handler, and
2097  * since we know the value is a scalar there is no danger of it being
2098  * on while recursing down the tree.
2099  */
2100  if (_state->normalize_results && _state->lex->token_type == JSON_TOKEN_STRING)
2101  _state->next_scalar = true;
2102  else
2103  _state->result_start = _state->lex->token_start;
2104  }
2105 }
JsonTokenType token_type
Definition: jsonapi.h:80
int lex_level
Definition: jsonapi.h:81
char * result_start
Definition: jsonfuncs.c:112
JsonLexContext * lex
Definition: jsonfuncs.c:108
char * token_start
Definition: jsonapi.h:77
bool normalize_results
Definition: jsonfuncs.c:113
Definition: regguts.h:317
bool next_scalar
Definition: jsonfuncs.c:114

◆ each_scalar()

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

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

2167 {
2168  EachState *_state = (EachState *) state;
2169 
2170  /* json structure check */
2171  if (_state->lex->lex_level == 0)
2172  ereport(ERROR,
2173  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2174  errmsg("cannot deconstruct a scalar")));
2175 
2176  /* supply de-escaped value if required */
2177  if (_state->next_scalar)
2178  _state->normalized_scalar = token;
2179 }
int errcode(int sqlerrcode)
Definition: elog.c:698
int lex_level
Definition: jsonapi.h:81
#define ERROR
Definition: elog.h:46
JsonLexContext * lex
Definition: jsonfuncs.c:108
#define ereport(elevel,...)
Definition: elog.h:157
char * normalized_scalar
Definition: jsonfuncs.c:115
Definition: regguts.h:317
int errmsg(const char *fmt,...)
Definition: elog.c:909
bool next_scalar
Definition: jsonfuncs.c:114

◆ each_worker()

static Datum each_worker ( FunctionCallInfo  fcinfo,
bool  as_text 
)
static

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

2025 {
2026  text *json = PG_GETARG_TEXT_PP(0);
2027  JsonLexContext *lex;
2028  JsonSemAction *sem;
2029  ReturnSetInfo *rsi;
2030  MemoryContext old_cxt;
2031  TupleDesc tupdesc;
2032  EachState *state;
2033 
2034  lex = makeJsonLexContext(json, true);
2035  state = palloc0(sizeof(EachState));
2036  sem = palloc0(sizeof(JsonSemAction));
2037 
2038  rsi = (ReturnSetInfo *) fcinfo->resultinfo;
2039 
2040  if (!rsi || !IsA(rsi, ReturnSetInfo) ||
2041  (rsi->allowedModes & SFRM_Materialize) == 0 ||
2042  rsi->expectedDesc == NULL)
2043  ereport(ERROR,
2044  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2045  errmsg("set-valued function called in context that "
2046  "cannot accept a set")));
2047 
2049 
2050  (void) get_call_result_type(fcinfo, NULL, &tupdesc);
2051 
2052  /* make these in a sufficiently long-lived memory context */
2054 
2055  state->ret_tdesc = CreateTupleDescCopy(tupdesc);
2056  BlessTupleDesc(state->ret_tdesc);
2057  state->tuple_store =
2059  false, work_mem);
2060 
2061  MemoryContextSwitchTo(old_cxt);
2062 
2063  sem->semstate = (void *) state;
2065  sem->scalar = each_scalar;
2068 
2069  state->normalize_results = as_text;
2070  state->next_scalar = false;
2071  state->lex = lex;
2073  "json_each temporary cxt",
2075 
2076  pg_parse_json_or_ereport(lex, sem);
2077 
2078  MemoryContextDelete(state->tmp_cxt);
2079 
2080  rsi->setResult = state->tuple_store;
2081  rsi->setDesc = state->ret_tdesc;
2082 
2083  PG_RETURN_NULL();
2084 }
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
Definition: tupdesc.c:111
#define IsA(nodeptr, _type_)
Definition: nodes.h:590
Tuplestorestate * tuple_store
Definition: jsonfuncs.c:109
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:218
#define AllocSetContextCreate
Definition: memutils.h:173
static void each_object_field_start(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:2088
TypeFuncClass get_call_result_type(FunctionCallInfo fcinfo, Oid *resultTypeId, TupleDesc *resultTupleDesc)
Definition: funcapi.c:207
JsonLexContext * makeJsonLexContext(text *json, bool need_escapes)
Definition: jsonfuncs.c:517
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
int errcode(int sqlerrcode)
Definition: elog.c:698
json_scalar_action scalar
Definition: jsonapi.h:115
static void each_array_start(void *state)
Definition: jsonfuncs.c:2154
TupleDesc ret_tdesc
Definition: jsonfuncs.c:110
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:309
MemoryContext tmp_cxt
Definition: jsonfuncs.c:111
static void each_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:2166
TupleDesc expectedDesc
Definition: execnodes.h:304
#define ERROR
Definition: elog.h:46
fmNodePtr resultinfo
Definition: fmgr.h:89
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:195
JsonLexContext * lex
Definition: jsonfuncs.c:108
TupleDesc BlessTupleDesc(TupleDesc tupdesc)
Definition: execTuples.c:2082
MemoryContext CurrentMemoryContext
Definition: mcxt.c:42
json_ofield_action object_field_end
Definition: jsonapi.h:112
void pg_parse_json_or_ereport(JsonLexContext *lex, JsonSemAction *sem)
Definition: jsonfuncs.c:501
Tuplestorestate * tuplestore_begin_heap(bool randomAccess, bool interXact, int maxKBytes)
Definition: tuplestore.c:318
void * palloc0(Size size)
Definition: mcxt.c:1093
bool normalize_results
Definition: jsonfuncs.c:113
int work_mem
Definition: globals.c:124
#define ereport(elevel,...)
Definition: elog.h:157
int allowedModes
Definition: execnodes.h:305
SetFunctionReturnMode returnMode
Definition: execnodes.h:307
json_struct_action array_start
Definition: jsonapi.h:109
Definition: regguts.h:317
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:909
Definition: c.h:621
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:2108
#define PG_RETURN_NULL()
Definition: fmgr.h:345
bool next_scalar
Definition: jsonfuncs.c:114

◆ each_worker_jsonb()

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

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

1907 {
1908  Jsonb *jb = PG_GETARG_JSONB_P(0);
1909  ReturnSetInfo *rsi;
1910  Tuplestorestate *tuple_store;
1911  TupleDesc tupdesc;
1912  TupleDesc ret_tdesc;
1913  MemoryContext old_cxt,
1914  tmp_cxt;
1915  bool skipNested = false;
1916  JsonbIterator *it;
1917  JsonbValue v;
1919 
1920  if (!JB_ROOT_IS_OBJECT(jb))
1921  ereport(ERROR,
1922  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1923  errmsg("cannot call %s on a non-object",
1924  funcname)));
1925 
1926  rsi = (ReturnSetInfo *) fcinfo->resultinfo;
1927 
1928  if (!rsi || !IsA(rsi, ReturnSetInfo) ||
1929  (rsi->allowedModes & SFRM_Materialize) == 0 ||
1930  rsi->expectedDesc == NULL)
1931  ereport(ERROR,
1932  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1933  errmsg("set-valued function called in context that "
1934  "cannot accept a set")));
1935 
1937 
1938  if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
1939  ereport(ERROR,
1940  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1941  errmsg("function returning record called in context "
1942  "that cannot accept type record")));
1943 
1945 
1946  ret_tdesc = CreateTupleDescCopy(tupdesc);
1947  BlessTupleDesc(ret_tdesc);
1948  tuple_store =
1950  false, work_mem);
1951 
1952  MemoryContextSwitchTo(old_cxt);
1953 
1955  "jsonb_each temporary cxt",
1957 
1958  it = JsonbIteratorInit(&jb->root);
1959 
1960  while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE)
1961  {
1962  skipNested = true;
1963 
1964  if (r == WJB_KEY)
1965  {
1966  text *key;
1967  HeapTuple tuple;
1968  Datum values[2];
1969  bool nulls[2] = {false, false};
1970 
1971  /* Use the tmp context so we can clean up after each tuple is done */
1972  old_cxt = MemoryContextSwitchTo(tmp_cxt);
1973 
1974  key = cstring_to_text_with_len(v.val.string.val, v.val.string.len);
1975 
1976  /*
1977  * The next thing the iterator fetches should be the value, no
1978  * matter what shape it is.
1979  */
1980  r = JsonbIteratorNext(&it, &v, skipNested);
1981  Assert(r != WJB_DONE);
1982 
1983  values[0] = PointerGetDatum(key);
1984 
1985  if (as_text)
1986  {
1987  if (v.type == jbvNull)
1988  {
1989  /* a json null is an sql null in text mode */
1990  nulls[1] = true;
1991  values[1] = (Datum) NULL;
1992  }
1993  else
1994  values[1] = PointerGetDatum(JsonbValueAsText(&v));
1995  }
1996  else
1997  {
1998  /* Not in text mode, just return the Jsonb */
1999  Jsonb *val = JsonbValueToJsonb(&v);
2000 
2001  values[1] = PointerGetDatum(val);
2002  }
2003 
2004  tuple = heap_form_tuple(ret_tdesc, values, nulls);
2005 
2006  tuplestore_puttuple(tuple_store, tuple);
2007 
2008  /* clean up and switch back */
2009  MemoryContextSwitchTo(old_cxt);
2010  MemoryContextReset(tmp_cxt);
2011  }
2012  }
2013 
2014  MemoryContextDelete(tmp_cxt);
2015 
2016  rsi->setResult = tuple_store;
2017  rsi->setDesc = ret_tdesc;
2018 
2019  PG_RETURN_NULL();
2020 }
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
Definition: tupdesc.c:111
#define IsA(nodeptr, _type_)
Definition: nodes.h:590
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:218
#define AllocSetContextCreate
Definition: memutils.h:173
#define JB_ROOT_IS_OBJECT(jbp_)
Definition: jsonb.h:229
TypeFuncClass get_call_result_type(FunctionCallInfo fcinfo, Oid *resultTypeId, TupleDesc *resultTupleDesc)
Definition: funcapi.c:207
Jsonb * JsonbValueToJsonb(JsonbValue *val)
Definition: jsonb_util.c:92
Definition: jsonb.h:220
#define PointerGetDatum(X)
Definition: postgres.h:600
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:698
void MemoryContextReset(MemoryContext context)
Definition: mcxt.c:143
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:1741
TupleDesc expectedDesc
Definition: execnodes.h:304
#define ERROR
Definition: elog.h:46
fmNodePtr resultinfo
Definition: fmgr.h:89
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:195
void tuplestore_puttuple(Tuplestorestate *state, HeapTuple tuple)
Definition: tuplestore.c:730
TupleDesc BlessTupleDesc(TupleDesc tupdesc)
Definition: execTuples.c:2082
text * cstring_to_text_with_len(const char *s, int len)
Definition: varlena.c:202
Definition: jsonb.h:23
MemoryContext CurrentMemoryContext
Definition: mcxt.c:42
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:411
int work_mem
Definition: globals.c:124
#define ereport(elevel,...)
Definition: elog.h:157
int allowedModes
Definition: execnodes.h:305
SetFunctionReturnMode returnMode
Definition: execnodes.h:307
#define Assert(condition)
Definition: c.h:804
JsonbIterator * JsonbIteratorInit(JsonbContainer *container)
Definition: jsonb_util.c:812
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:166
ExprContext * econtext
Definition: execnodes.h:303
TupleDesc setDesc
Definition: execnodes.h:311
int errmsg(const char *fmt,...)
Definition: elog.c:909
Definition: c.h:621
long val
Definition: informix.c:664
#define PG_RETURN_NULL()
Definition: fmgr.h:345
JsonbIteratorToken JsonbIteratorNext(JsonbIterator **it, JsonbValue *val, bool skipNested)
Definition: jsonb_util.c:848
#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 2406 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().

2407 {
2408  ElementsState *_state = (ElementsState *) state;
2409  MemoryContext old_cxt;
2410  int len;
2411  text *val;
2412  HeapTuple tuple;
2413  Datum values[1];
2414  bool nulls[1] = {false};
2415 
2416  /* skip over nested objects */
2417  if (_state->lex->lex_level != 1)
2418  return;
2419 
2420  /* use the tmp context so we can clean up after each tuple is done */
2421  old_cxt = MemoryContextSwitchTo(_state->tmp_cxt);
2422 
2423  if (isnull && _state->normalize_results)
2424  {
2425  nulls[0] = true;
2426  values[0] = (Datum) NULL;
2427  }
2428  else if (_state->next_scalar)
2429  {
2430  values[0] = CStringGetTextDatum(_state->normalized_scalar);
2431  _state->next_scalar = false;
2432  }
2433  else
2434  {
2435  len = _state->lex->prev_token_terminator - _state->result_start;
2436  val = cstring_to_text_with_len(_state->result_start, len);
2437  values[0] = PointerGetDatum(val);
2438  }
2439 
2440  tuple = heap_form_tuple(_state->ret_tdesc, values, nulls);
2441 
2442  tuplestore_puttuple(_state->tuple_store, tuple);
2443 
2444  /* clean up and switch back */
2445  MemoryContextSwitchTo(old_cxt);
2446  MemoryContextReset(_state->tmp_cxt);
2447 }
bool normalize_results
Definition: jsonfuncs.c:127
JsonLexContext * lex
Definition: jsonfuncs.c:121
bool next_scalar
Definition: jsonfuncs.c:128
#define PointerGetDatum(X)
Definition: postgres.h:600
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
char * prev_token_terminator
Definition: jsonapi.h:79
void MemoryContextReset(MemoryContext context)
Definition: mcxt.c:143
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:124
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:202
uintptr_t Datum
Definition: postgres.h:411
Tuplestorestate * tuple_store
Definition: jsonfuncs.c:123
char * result_start
Definition: jsonfuncs.c:126
Definition: regguts.h:317
static Datum values[MAXATTR]
Definition: bootstrap.c:166
char * normalized_scalar
Definition: jsonfuncs.c:129
#define CStringGetTextDatum(s)
Definition: builtins.h:82
MemoryContext tmp_cxt
Definition: jsonfuncs.c:125
Definition: c.h:621
long val
Definition: informix.c:664

◆ elements_array_element_start()

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

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

2387 {
2388  ElementsState *_state = (ElementsState *) state;
2389 
2390  /* save a pointer to where the value starts */
2391  if (_state->lex->lex_level == 1)
2392  {
2393  /*
2394  * next_scalar will be reset in the array_element_end handler, and
2395  * since we know the value is a scalar there is no danger of it being
2396  * on while recursing down the tree.
2397  */
2398  if (_state->normalize_results && _state->lex->token_type == JSON_TOKEN_STRING)
2399  _state->next_scalar = true;
2400  else
2401  _state->result_start = _state->lex->token_start;
2402  }
2403 }
bool normalize_results
Definition: jsonfuncs.c:127
JsonLexContext * lex
Definition: jsonfuncs.c:121
bool next_scalar
Definition: jsonfuncs.c:128
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:126
Definition: regguts.h:317

◆ elements_object_start()

static void elements_object_start ( void *  state)
static

Definition at line 2450 of file jsonfuncs.c.

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

Referenced by elements_worker().

2451 {
2452  ElementsState *_state = (ElementsState *) state;
2453 
2454  /* json structure check */
2455  if (_state->lex->lex_level == 0)
2456  ereport(ERROR,
2457  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2458  errmsg("cannot call %s on a non-array",
2459  _state->function_name)));
2460 }
const char * function_name
Definition: jsonfuncs.c:122
JsonLexContext * lex
Definition: jsonfuncs.c:121
int errcode(int sqlerrcode)
Definition: elog.c:698
int lex_level
Definition: jsonapi.h:81
#define ERROR
Definition: elog.h:46
#define ereport(elevel,...)
Definition: elog.h:157
Definition: regguts.h:317
int errmsg(const char *fmt,...)
Definition: elog.c:909

◆ elements_scalar()

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

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

2464 {
2465  ElementsState *_state = (ElementsState *) state;
2466 
2467  /* json structure check */
2468  if (_state->lex->lex_level == 0)
2469  ereport(ERROR,
2470  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2471  errmsg("cannot call %s on a scalar",
2472  _state->function_name)));
2473 
2474  /* supply de-escaped value if required */
2475  if (_state->next_scalar)
2476  _state->normalized_scalar = token;
2477 }
const char * function_name
Definition: jsonfuncs.c:122
JsonLexContext * lex
Definition: jsonfuncs.c:121
bool next_scalar
Definition: jsonfuncs.c:128
int errcode(int sqlerrcode)
Definition: elog.c:698
int lex_level
Definition: jsonapi.h:81
#define ERROR
Definition: elog.h:46
#define ereport(elevel,...)
Definition: elog.h:157
Definition: regguts.h:317
char * normalized_scalar
Definition: jsonfuncs.c:129
int errmsg(const char *fmt,...)
Definition: elog.c:909

◆ elements_worker()

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

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

2321 {
2322  text *json = PG_GETARG_TEXT_PP(0);
2323 
2324  /* elements only needs escaped strings when as_text */
2325  JsonLexContext *lex = makeJsonLexContext(json, as_text);
2326  JsonSemAction *sem;
2327  ReturnSetInfo *rsi;
2328  MemoryContext old_cxt;
2329  TupleDesc tupdesc;
2331 
2332  state = palloc0(sizeof(ElementsState));
2333  sem = palloc0(sizeof(JsonSemAction));
2334 
2335  rsi = (ReturnSetInfo *) fcinfo->resultinfo;
2336 
2337  if (!rsi || !IsA(rsi, ReturnSetInfo) ||
2338  (rsi->allowedModes & SFRM_Materialize) == 0 ||
2339  rsi->expectedDesc == NULL)
2340  ereport(ERROR,
2341  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2342  errmsg("set-valued function called in context that "
2343  "cannot accept a set")));
2344 
2346 
2347  /* it's a simple type, so don't use get_call_result_type() */
2348  tupdesc = rsi->expectedDesc;
2349 
2350  /* make these in a sufficiently long-lived memory context */
2352 
2353  state->ret_tdesc = CreateTupleDescCopy(tupdesc);
2354  BlessTupleDesc(state->ret_tdesc);
2355  state->tuple_store =
2357  false, work_mem);
2358 
2359  MemoryContextSwitchTo(old_cxt);
2360 
2361  sem->semstate = (void *) state;
2363  sem->scalar = elements_scalar;
2366 
2367  state->function_name = funcname;
2368  state->normalize_results = as_text;
2369  state->next_scalar = false;
2370  state->lex = lex;
2372  "json_array_elements temporary cxt",
2374 
2375  pg_parse_json_or_ereport(lex, sem);
2376 
2377  MemoryContextDelete(state->tmp_cxt);
2378 
2379  rsi->setResult = state->tuple_store;
2380  rsi->setDesc = state->ret_tdesc;
2381 
2382  PG_RETURN_NULL();
2383 }
bool normalize_results
Definition: jsonfuncs.c:127
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
Definition: tupdesc.c:111
#define IsA(nodeptr, _type_)
Definition: nodes.h:590
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:218
#define AllocSetContextCreate
Definition: memutils.h:173
const char * function_name
Definition: jsonfuncs.c:122
JsonLexContext * lex
Definition: jsonfuncs.c:121
static void elements_object_start(void *state)
Definition: jsonfuncs.c:2450
bool next_scalar
Definition: jsonfuncs.c:128
json_struct_action object_start
Definition: jsonapi.h:107
JsonLexContext * makeJsonLexContext(text *json, bool need_escapes)
Definition: jsonfuncs.c:517
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
int errcode(int sqlerrcode)
Definition: elog.c:698
json_scalar_action scalar
Definition: jsonapi.h:115
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:309
TupleDesc expectedDesc
Definition: execnodes.h:304
TupleDesc ret_tdesc
Definition: jsonfuncs.c:124
#define ERROR
Definition: elog.h:46
fmNodePtr resultinfo
Definition: fmgr.h:89
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:195
TupleDesc BlessTupleDesc(TupleDesc tupdesc)
Definition: execTuples.c:2082
MemoryContext CurrentMemoryContext
Definition: mcxt.c:42
static void elements_array_element_start(void *state, bool isnull)
Definition: jsonfuncs.c:2386
void pg_parse_json_or_ereport(JsonLexContext *lex, JsonSemAction *sem)
Definition: jsonfuncs.c:501
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:2406
void * palloc0(Size size)
Definition: mcxt.c:1093
static void elements_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:2463
json_aelem_action array_element_start
Definition: jsonapi.h:113
Tuplestorestate * tuple_store
Definition: jsonfuncs.c:123
int work_mem
Definition: globals.c:124
#define ereport(elevel,...)
Definition: elog.h:157
int allowedModes
Definition: execnodes.h:305
SetFunctionReturnMode returnMode
Definition: execnodes.h:307
Definition: regguts.h:317
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:909
MemoryContext tmp_cxt
Definition: jsonfuncs.c:125
Definition: c.h:621
void * semstate
Definition: jsonapi.h:106
#define PG_RETURN_NULL()
Definition: fmgr.h:345
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 2202 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().

2204 {
2205  Jsonb *jb = PG_GETARG_JSONB_P(0);
2206  ReturnSetInfo *rsi;
2207  Tuplestorestate *tuple_store;
2208  TupleDesc tupdesc;
2209  TupleDesc ret_tdesc;
2210  MemoryContext old_cxt,
2211  tmp_cxt;
2212  bool skipNested = false;
2213  JsonbIterator *it;
2214  JsonbValue v;
2216 
2217  if (JB_ROOT_IS_SCALAR(jb))
2218  ereport(ERROR,
2219  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2220  errmsg("cannot extract elements from a scalar")));
2221  else if (!JB_ROOT_IS_ARRAY(jb))
2222  ereport(ERROR,
2223  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2224  errmsg("cannot extract elements from an object")));
2225 
2226  rsi = (ReturnSetInfo *) fcinfo->resultinfo;
2227 
2228  if (!rsi || !IsA(rsi, ReturnSetInfo) ||
2229  (rsi->allowedModes & SFRM_Materialize) == 0 ||
2230  rsi->expectedDesc == NULL)
2231  ereport(ERROR,
2232  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2233  errmsg("set-valued function called in context that "
2234  "cannot accept a set")));
2235 
2237 
2238  /* it's a simple type, so don't use get_call_result_type() */
2239  tupdesc = rsi->expectedDesc;
2240 
2242 
2243  ret_tdesc = CreateTupleDescCopy(tupdesc);
2244  BlessTupleDesc(ret_tdesc);
2245  tuple_store =
2247  false, work_mem);
2248 
2249  MemoryContextSwitchTo(old_cxt);
2250 
2252  "jsonb_array_elements temporary cxt",
2254 
2255  it = JsonbIteratorInit(&jb->root);
2256 
2257  while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE)
2258  {
2259  skipNested = true;
2260 
2261  if (r == WJB_ELEM)
2262  {
2263  HeapTuple tuple;
2264  Datum values[1];
2265  bool nulls[1] = {false};
2266 
2267  /* use the tmp context so we can clean up after each tuple is done */
2268  old_cxt = MemoryContextSwitchTo(tmp_cxt);
2269 
2270  if (as_text)
2271  {
2272  if (v.type == jbvNull)
2273  {
2274  /* a json null is an sql null in text mode */
2275  nulls[0] = true;
2276  values[0] = (Datum) NULL;
2277  }
2278  else
2279  values[0] = PointerGetDatum(JsonbValueAsText(&v));
2280  }
2281  else
2282  {
2283  /* Not in text mode, just return the Jsonb */
2284  Jsonb *val = JsonbValueToJsonb(&v);
2285 
2286  values[0] = PointerGetDatum(val);
2287  }
2288 
2289  tuple = heap_form_tuple(ret_tdesc, values, nulls);
2290 
2291  tuplestore_puttuple(tuple_store, tuple);
2292 
2293  /* clean up and switch back */
2294  MemoryContextSwitchTo(old_cxt);
2295  MemoryContextReset(tmp_cxt);
2296  }
2297  }
2298 
2299  MemoryContextDelete(tmp_cxt);
2300 
2301  rsi->setResult = tuple_store;
2302  rsi->setDesc = ret_tdesc;
2303 
2304  PG_RETURN_NULL();
2305 }
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
Definition: tupdesc.c:111
#define IsA(nodeptr, _type_)
Definition: nodes.h:590
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:218
#define AllocSetContextCreate
Definition: memutils.h:173
Jsonb * JsonbValueToJsonb(JsonbValue *val)
Definition: jsonb_util.c:92
Definition: jsonb.h:220
#define PointerGetDatum(X)
Definition: postgres.h:600
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
Definition: jsonb.h:22
int errcode(int sqlerrcode)
Definition: elog.c:698
void MemoryContextReset(MemoryContext context)
Definition: mcxt.c:143
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:1741
#define JB_ROOT_IS_SCALAR(jbp_)
Definition: jsonb.h:228
TupleDesc expectedDesc
Definition: execnodes.h:304
#define ERROR
Definition: elog.h:46
fmNodePtr resultinfo
Definition: fmgr.h:89
#define JB_ROOT_IS_ARRAY(jbp_)
Definition: jsonb.h:230
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:195
void tuplestore_puttuple(Tuplestorestate *state, HeapTuple tuple)
Definition: tuplestore.c:730
TupleDesc BlessTupleDesc(TupleDesc tupdesc)
Definition: execTuples.c:2082
MemoryContext CurrentMemoryContext
Definition: mcxt.c:42
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:411
int work_mem
Definition: globals.c:124
#define ereport(elevel,...)
Definition: elog.h:157
int allowedModes
Definition: execnodes.h:305
SetFunctionReturnMode returnMode
Definition: execnodes.h:307
JsonbIterator * JsonbIteratorInit(JsonbContainer *container)
Definition: jsonb_util.c:812
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:166
ExprContext * econtext
Definition: execnodes.h:303
TupleDesc setDesc
Definition: execnodes.h:311
int errmsg(const char *fmt,...)
Definition: elog.c:909
long val
Definition: informix.c:664
#define PG_RETURN_NULL()
Definition: fmgr.h:345
JsonbIteratorToken JsonbIteratorNext(JsonbIterator **it, JsonbValue *val, bool skipNested)
Definition: jsonb_util.c:848
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 1342 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().

1343 {
1344  GetState *_state = (GetState *) state;
1345  bool get_last = false;
1346  int lex_level = _state->lex->lex_level;
1347 
1348  /* same tests as in get_array_element_start */
1349  if (lex_level <= _state->npath &&
1350  _state->pathok[lex_level - 1] &&
1351  _state->path_indexes != NULL &&
1352  _state->array_cur_index[lex_level - 1] == _state->path_indexes[lex_level - 1])
1353  {
1354  if (lex_level < _state->npath)
1355  {
1356  /* done with this element so reset pathok */
1357  _state->pathok[lex_level] = false;
1358  }
1359  else
1360  {
1361  /* end of path, so we want this value */
1362  get_last = true;
1363  }
1364  }
1365 
1366  /* same logic as for objects */
1367  if (get_last && _state->result_start != NULL)
1368  {
1369  if (isnull && _state->normalize_results)
1370  _state->tresult = (text *) NULL;
1371  else
1372  {
1373  char *start = _state->result_start;
1374  int len = _state->lex->prev_token_terminator - start;
1375 
1376  _state->tresult = cstring_to_text_with_len(start, len);
1377  }
1378 
1379  _state->result_start = NULL;
1380  }
1381 }
int * array_cur_index
Definition: jsonfuncs.c:94
char * prev_token_terminator
Definition: jsonapi.h:79
int lex_level
Definition: jsonapi.h:81
JsonLexContext * lex
Definition: jsonfuncs.c:85
char * result_start
Definition: jsonfuncs.c:87
text * tresult
Definition: jsonfuncs.c:86
text * cstring_to_text_with_len(const char *s, int len)
Definition: varlena.c:202
bool * pathok
Definition: jsonfuncs.c:93
bool normalize_results
Definition: jsonfuncs.c:88
Definition: regguts.h:317
int * path_indexes
Definition: jsonfuncs.c:92
Definition: c.h:621

◆ get_array_element_start()

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

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

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

◆ get_array_end()

static void get_array_end ( void *  state)
static

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

1281 {
1282  GetState *_state = (GetState *) state;
1283  int lex_level = _state->lex->lex_level;
1284 
1285  if (lex_level == 0 && _state->npath == 0)
1286  {
1287  /* Special case: return the entire array */
1288  char *start = _state->result_start;
1289  int len = _state->lex->prev_token_terminator - start;
1290 
1291  _state->tresult = cstring_to_text_with_len(start, len);
1292  }
1293 }
char * prev_token_terminator
Definition: jsonapi.h:79
int lex_level
Definition: jsonapi.h:81
JsonLexContext * lex
Definition: jsonfuncs.c:85
char * result_start
Definition: jsonfuncs.c:87
text * tresult
Definition: jsonfuncs.c:86
text * cstring_to_text_with_len(const char *s, int len)
Definition: varlena.c:202
int npath
Definition: jsonfuncs.c:90
Definition: regguts.h:317

◆ get_array_start()

static void get_array_start ( void *  state)
static

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

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

◆ get_json_object_as_hash()

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

Definition at line 3574 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(), HASH_STRINGS, 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().

3575 {
3576  HASHCTL ctl;
3577  HTAB *tab;
3578  JHashState *state;
3580  JsonSemAction *sem;
3581 
3582  ctl.keysize = NAMEDATALEN;
3583  ctl.entrysize = sizeof(JsonHashEntry);
3584  ctl.hcxt = CurrentMemoryContext;
3585  tab = hash_create("json object hashtable",
3586  100,
3587  &ctl,
3589 
3590  state = palloc0(sizeof(JHashState));
3591  sem = palloc0(sizeof(JsonSemAction));
3592 
3593  state->function_name = funcname;
3594  state->hash = tab;
3595  state->lex = lex;
3596 
3597  sem->semstate = (void *) state;
3599  sem->scalar = hash_scalar;
3602 
3603  pg_parse_json_or_ereport(lex, sem);
3604 
3605  return tab;
3606 }
#define HASH_CONTEXT
Definition: hsearch.h:102
#define HASH_ELEM
Definition: hsearch.h:95
MemoryContext hcxt
Definition: hsearch.h:86
Size entrysize
Definition: hsearch.h:76
static void hash_object_field_end(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:3633
json_scalar_action scalar
Definition: jsonapi.h:115
#define NAMEDATALEN
Definition: dynahash.c:219
JsonLexContext * makeJsonLexContextCstringLen(char *json, int len, int encoding, bool need_escapes)
Definition: jsonapi.c:144
HTAB * hash_create(const char *tabname, long nelem, const HASHCTL *info, int flags)
Definition: dynahash.c:349
HTAB * hash
Definition: jsonfuncs.c:137
MemoryContext CurrentMemoryContext
Definition: mcxt.c:42
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:3609
const char * function_name
Definition: jsonfuncs.c:136
void pg_parse_json_or_ereport(JsonLexContext *lex, JsonSemAction *sem)
Definition: jsonfuncs.c:501
void * palloc0(Size size)
Definition: mcxt.c:1093
int GetDatabaseEncoding(void)
Definition: mbutils.c:1210
Size keysize
Definition: hsearch.h:75
json_struct_action array_start
Definition: jsonapi.h:109
Definition: regguts.h:317
struct JsonHashEntry JsonHashEntry
JsonLexContext * lex
Definition: jsonfuncs.c:135
static void hash_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:3693
json_ofield_action object_field_start
Definition: jsonapi.h:111
#define HASH_STRINGS
Definition: hsearch.h:96
void * semstate
Definition: jsonapi.h:106
static void hash_array_start(void *state)
Definition: jsonfuncs.c:3682

◆ get_jsonb_path_all()

static Datum get_jsonb_path_all ( FunctionCallInfo  fcinfo,
bool  as_text 
)
static

Definition at line 1437 of file jsonfuncs.c.

References array_contains_nulls(), deconstruct_array(), jsonb_get_element(), PG_GETARG_ARRAYTYPE_P, PG_GETARG_JSONB_P, PG_RETURN_DATUM, and PG_RETURN_NULL.

Referenced by jsonb_extract_path(), and jsonb_extract_path_text().

1438 {
1439  Jsonb *jb = PG_GETARG_JSONB_P(0);
1440  ArrayType *path = PG_GETARG_ARRAYTYPE_P(1);
1441  Datum *pathtext;
1442  bool *pathnulls;
1443  bool isnull;
1444  int npath;
1445  Datum res;
1446 
1447  /*
1448  * If the array contains any null elements, return NULL, on the grounds
1449  * that you'd have gotten NULL if any RHS value were NULL in a nested
1450  * series of applications of the -> operator. (Note: because we also
1451  * return NULL for error cases such as no-such-field, this is true
1452  * regardless of the contents of the rest of the array.)
1453  */
1454  if (array_contains_nulls(path))
1455  PG_RETURN_NULL();
1456 
1457  deconstruct_array(path, TEXTOID, -1, false, TYPALIGN_INT,
1458  &pathtext, &pathnulls, &npath);
1459 
1460  res = jsonb_get_element(jb, pathtext, npath, &isnull, as_text);
1461 
1462  if (isnull)
1463  PG_RETURN_NULL();
1464  else
1465  PG_RETURN_DATUM(res);
1466 }
Definition: jsonb.h:220
#define PG_GETARG_ARRAYTYPE_P(n)
Definition: array.h:256
uintptr_t Datum
Definition: postgres.h:411
#define PG_RETURN_DATUM(x)
Definition: fmgr.h:353
Datum jsonb_get_element(Jsonb *jb, Datum *path, int npath, bool *isnull, bool as_text)
Definition: jsonfuncs.c:1469
void deconstruct_array(ArrayType *array, Oid elmtype, int elmlen, bool elmbyval, char elmalign, Datum **elemsp, bool **nullsp, int *nelemsp)
Definition: arrayfuncs.c:3490
bool array_contains_nulls(ArrayType *array)
Definition: arrayfuncs.c:3557
#define PG_RETURN_NULL()
Definition: fmgr.h:345
#define PG_GETARG_JSONB_P(x)
Definition: jsonb.h:74

◆ get_object_end()

static void get_object_end ( void *  state)
static

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

1133 {
1134  GetState *_state = (GetState *) state;
1135  int lex_level = _state->lex->lex_level;
1136 
1137  if (lex_level == 0 && _state->npath == 0)
1138  {
1139  /* Special case: return the entire object */
1140  char *start = _state->result_start;
1141  int len = _state->lex->prev_token_terminator - start;
1142 
1143  _state->tresult = cstring_to_text_with_len(start, len);
1144  }
1145 }
char * prev_token_terminator
Definition: jsonapi.h:79
int lex_level
Definition: jsonapi.h:81
JsonLexContext * lex
Definition: jsonfuncs.c:85
char * result_start
Definition: jsonfuncs.c:87
text * tresult
Definition: jsonfuncs.c:86
text * cstring_to_text_with_len(const char *s, int len)
Definition: varlena.c:202
int npath
Definition: jsonfuncs.c:90
Definition: regguts.h:317

◆ get_object_field_end()

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

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

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

◆ get_object_field_start()

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

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

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

◆ get_object_start()

static void get_object_start ( void *  state)
static

Definition at line 1115 of file jsonfuncs.c.

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

Referenced by get_worker().

1116 {
1117  GetState *_state = (GetState *) state;
1118  int lex_level = _state->lex->lex_level;
1119 
1120  if (lex_level == 0 && _state->npath == 0)
1121  {
1122  /*
1123  * Special case: we should match the entire object. We only need this
1124  * at outermost level because at nested levels the match will have
1125  * been started by the outer field or array element callback.
1126  */
1127  _state->result_start = _state->lex->token_start;
1128  }
1129 }
int lex_level
Definition: jsonapi.h:81
JsonLexContext * lex
Definition: jsonfuncs.c:85
char * result_start
Definition: jsonfuncs.c:87
int npath
Definition: jsonfuncs.c:90
char * token_start
Definition: jsonapi.h:77
Definition: regguts.h:317

◆ get_path_all()

static Datum get_path_all ( FunctionCallInfo  fcinfo,
bool  as_text 
)
static

Definition at line 979 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, strtoint(), and TextDatumGetCString.

Referenced by json_extract_path(), and json_extract_path_text().

980 {
981  text *json = PG_GETARG_TEXT_PP(0);
982  ArrayType *path = PG_GETARG_ARRAYTYPE_P(1);
983  text *result;
984  Datum *pathtext;
985  bool *pathnulls;
986  int npath;
987  char **tpath;
988  int *ipath;
989  int i;
990 
991  /*
992  * If the array contains any null elements, return NULL, on the grounds
993  * that you'd have gotten NULL if any RHS value were NULL in a nested
994  * series of applications of the -> operator. (Note: because we also
995  * return NULL for error cases such as no-such-field, this is true
996  * regardless of the contents of the rest of the array.)
997  */
998  if (array_contains_nulls(path))
999  PG_RETURN_NULL();
1000 
1001  deconstruct_array(path, TEXTOID, -1, false, TYPALIGN_INT,
1002  &pathtext, &pathnulls, &npath);
1003 
1004  tpath = palloc(npath * sizeof(char *));
1005  ipath = palloc(npath * sizeof(int));
1006 
1007  for (i = 0; i < npath; i++)
1008  {
1009  Assert(!pathnulls[i]);
1010  tpath[i] = TextDatumGetCString(pathtext[i]);
1011 
1012  /*
1013  * we have no idea at this stage what structure the document is so
1014  * just convert anything in the path that we can to an integer and set
1015  * all the other integers to INT_MIN which will never match.
1016  */
1017  if (*tpath[i] != '\0')
1018  {
1019  int ind;
1020  char *endptr;
1021 
1022  errno = 0;
1023  ind = strtoint(tpath[i], &endptr, 10);
1024  if (endptr == tpath[i] || *endptr != '\0' || errno != 0)
1025  ipath[i] = INT_MIN;
1026  else
1027  ipath[i] = ind;
1028  }
1029  else
1030  ipath[i] = INT_MIN;
1031  }
1032 
1033  result = get_worker(json, tpath, ipath, npath, as_text);
1034 
1035  if (result != NULL)
1036  PG_RETURN_TEXT_P(result);
1037  else
1038  PG_RETURN_NULL();
1039 }
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:309
#define PG_GETARG_ARRAYTYPE_P(n)
Definition: array.h:256
int strtoint(const char *pg_restrict str, char **pg_restrict endptr, int base)
Definition: string.c:50
#define TextDatumGetCString(d)
Definition: builtins.h:83
uintptr_t Datum
Definition: postgres.h:411
static text * get_worker(text *json, char **tpath, int *ipath, int npath, bool normalize_results)
Definition: jsonfuncs.c:1059
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:372
#define Assert(condition)
Definition: c.h:804
void deconstruct_array(ArrayType *array, Oid elmtype, int elmlen, bool elmbyval, char elmalign, Datum **elemsp, bool **nullsp, int *nelemsp)
Definition: arrayfuncs.c:3490
void * palloc(Size size)
Definition: mcxt.c:1062
int i
Definition: c.h:621
bool array_contains_nulls(ArrayType *array)
Definition: arrayfuncs.c:3557
#define PG_RETURN_NULL()
Definition: fmgr.h:345

◆ get_record_type_from_argument()

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

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

3409 {
3410  cache->argtype = get_fn_expr_argtype(fcinfo->flinfo, 0);
3411  prepare_column_cache(&cache->c,
3412  cache->argtype, -1,
3413  cache->fn_mcxt, false);
3414  if (cache->c.typcat != TYPECAT_COMPOSITE &&
3415  cache->c.typcat != TYPECAT_COMPOSITE_DOMAIN)
3416  ereport(ERROR,
3417  (errcode(ERRCODE_DATATYPE_MISMATCH),
3418  /* translator: %s is a function name, eg json_to_record */
3419  errmsg("first argument of %s must be a row type",
3420  funcname)));
3421 }
static void prepare_column_cache(ColumnIOData *column, Oid typid, int32 typmod, MemoryContext mcxt, bool need_scalar)
Definition: jsonfuncs.c:3097
int errcode(int sqlerrcode)
Definition: elog.c:698
#define ERROR
Definition: elog.h:46
Oid get_fn_expr_argtype(FmgrInfo *flinfo, int argnum)
Definition: fmgr.c:1800
ColumnIOData c
Definition: jsonfuncs.c:237
FmgrInfo * flinfo
Definition: fmgr.h:87
#define ereport(elevel,...)
Definition: elog.h:157
MemoryContext fn_mcxt
Definition: jsonfuncs.c:238
int errmsg(const char *fmt,...)
Definition: elog.c:909
TypeCat typcat
Definition: jsonfuncs.c:212

◆ get_record_type_from_query()

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

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

3435 {
3436  TupleDesc tupdesc;
3437  MemoryContext old_cxt;
3438 
3439  if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
3440  ereport(ERROR,
3441  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3442  /* translator: %s is a function name, eg json_to_record */
3443  errmsg("could not determine row type for result of %s",
3444  funcname),
3445  errhint("Provide a non-null record argument, "
3446  "or call the function in the FROM clause "
3447  "using a column definition list.")));
3448 
3449  Assert(tupdesc);
3450  cache->argtype = tupdesc->tdtypeid;
3451 
3452  /* If we go through this more than once, avoid memory leak */
3453  if (cache->c.io.composite.tupdesc)
3455 
3456  /* Save identified tupdesc */
3457  old_cxt = MemoryContextSwitchTo(cache->fn_mcxt);
3458  cache->c.io.composite.tupdesc = CreateTupleDescCopy(tupdesc);
3459  cache->c.io.composite.base_typid = tupdesc->tdtypeid;
3460  cache->c.io.composite.base_typmod = tupdesc->tdtypmod;
3461  MemoryContextSwitchTo(old_cxt);
3462 }
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
Definition: tupdesc.c:111
TypeFuncClass get_call_result_type(FunctionCallInfo fcinfo, Oid *resultTypeId, TupleDesc *resultTupleDesc)
Definition: funcapi.c:207
int errhint(const char *fmt,...)
Definition: elog.c:1156
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
int errcode(int sqlerrcode)
Definition: elog.c:698
int32 base_typmod
Definition: jsonfuncs.c:181
#define ERROR
Definition: elog.h:46
int32 tdtypmod
Definition: tupdesc.h:83
ColumnIOData c
Definition: jsonfuncs.c:237
#define ereport(elevel,...)
Definition: elog.h:157
#define Assert(condition)
Definition: c.h:804
MemoryContext fn_mcxt
Definition: jsonfuncs.c:238
void FreeTupleDesc(TupleDesc tupdesc)
Definition: tupdesc.c:309
Oid tdtypeid
Definition: tupdesc.h:82
int errmsg(const char *fmt,...)
Definition: elog.c:909
TupleDesc tupdesc
Definition: jsonfuncs.c:178
CompositeIOData composite
Definition: jsonfuncs.c:218
union ColumnIOData::@21 io

◆ get_scalar()

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

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

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

◆ get_worker()

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

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

1064 {
1065  JsonLexContext *lex = makeJsonLexContext(json, true);
1066  JsonSemAction *sem = palloc0(sizeof(JsonSemAction));
1067  GetState *state = palloc0(sizeof(GetState));
1068 
1069  Assert(npath >= 0);
1070 
1071  state->lex = lex;
1072  /* is it "_as_text" variant? */
1073  state->normalize_results = normalize_results;
1074  state->npath = npath;
1075  state->path_names = tpath;
1076  state->path_indexes = ipath;
1077  state->pathok = palloc0(sizeof(bool) * npath);
1078  state->array_cur_index = palloc(sizeof(int) * npath);
1079 
1080  if (npath > 0)
1081  state->pathok[0] = true;
1082 
1083  sem->semstate = (void *) state;
1084 
1085  /*
1086  * Not all variants need all the semantic routines. Only set the ones that
1087  * are actually needed for maximum efficiency.
1088  */
1089  sem->scalar = get_scalar;
1090  if (npath == 0)
1091  {
1093  sem->object_end = get_object_end;
1095  sem->array_end = get_array_end;
1096  }
1097  if (tpath != NULL)
1098  {
1101  }
1102  if (ipath != NULL)
1103  {
1107  }
1108 
1109  pg_parse_json_or_ereport(lex, sem);
1110 
1111  return state->tresult;
1112 }
json_struct_action array_end
Definition: jsonapi.h:110
static void get_array_end(void *state)
Definition: jsonfuncs.c:1280
int * array_cur_index
Definition: jsonfuncs.c:94
static void get_array_element_start(void *state, bool isnull)
Definition: jsonfuncs.c:1296
json_struct_action object_end
Definition: jsonapi.h:108
static void get_object_start(void *state)
Definition: jsonfuncs.c:1115
json_struct_action object_start
Definition: jsonapi.h:107
JsonLexContext * makeJsonLexContext(text *json, bool need_escapes)
Definition: jsonfuncs.c:517
json_scalar_action scalar
Definition: jsonapi.h:115
static void get_object_field_end(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:1193
JsonLexContext * lex
Definition: jsonfuncs.c:85
static void get_object_end(void *state)
Definition: jsonfuncs.c:1132
text * tresult
Definition: jsonfuncs.c:86
int npath
Definition: jsonfuncs.c:90
json_ofield_action object_field_end
Definition: jsonapi.h:112
static void get_array_element_end(void *state, bool isnull)
Definition: jsonfuncs.c:1342
bool * pathok
Definition: jsonfuncs.c:93
bool normalize_results
Definition: jsonfuncs.c:88
void pg_parse_json_or_ereport(JsonLexContext *lex, JsonSemAction *sem)
Definition: jsonfuncs.c:501
static void get_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:1384
void * palloc0(Size size)
Definition: mcxt.c:1093
static void get_array_start(void *state)
Definition: jsonfuncs.c:1242
json_aelem_action array_element_start
Definition: jsonapi.h:113
char ** path_names
Definition: jsonfuncs.c:91
#define Assert(condition)
Definition: c.h:804
json_struct_action array_start
Definition: jsonapi.h:109
Definition: regguts.h:317
int * path_indexes
Definition: jsonfuncs.c:92
void * palloc(Size size)
Definition: mcxt.c:1062
static void get_object_field_start(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:1148
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 3682 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().

3683 {
3684  JHashState *_state = (JHashState *) state;
3685 
3686  if (_state->lex->lex_level == 0)
3687  ereport(ERROR,
3688  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3689  errmsg("cannot call %s on an array", _state->function_name)));
3690 }
int errcode(int sqlerrcode)
Definition: elog.c:698
int lex_level
Definition: jsonapi.h:81
#define ERROR
Definition: elog.h:46
const char * function_name
Definition: jsonfuncs.c:136
#define ereport(elevel,...)
Definition: elog.h:157
Definition: regguts.h:317
JsonLexContext * lex
Definition: jsonfuncs.c:135
int errmsg(const char *fmt,...)
Definition: elog.c:909

◆ hash_object_field_end()

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

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

3634 {
3635  JHashState *_state = (JHashState *) state;
3636  JsonHashEntry *hashentry;
3637  bool found;
3638 
3639  /*
3640  * Ignore nested fields.
3641  */
3642  if (_state->lex->lex_level > 1)
3643  return;
3644 
3645  /*
3646  * Ignore field names >= NAMEDATALEN - they can't match a record field.
3647  * (Note: without this test, the hash code would truncate the string at
3648  * NAMEDATALEN-1, and could then match against a similarly-truncated
3649  * record field name. That would be a reasonable behavior, but this code
3650  * has previously insisted on exact equality, so we keep this behavior.)
3651  */
3652  if (strlen(fname) >= NAMEDATALEN)
3653  return;
3654 
3655  hashentry = hash_search(_state->hash, fname, HASH_ENTER, &found);
3656 
3657  /*
3658  * found being true indicates a duplicate. We don't do anything about
3659  * that, a later field with the same name overrides the earlier field.
3660  */
3661 
3662  hashentry->type = _state->saved_token_type;
3663  Assert(isnull == (hashentry->type == JSON_TOKEN_NULL));
3664 
3665  if (_state->save_json_start != NULL)
3666  {
3667  int len = _state->lex->prev_token_terminator - _state->save_json_start;
3668  char *val = palloc((len + 1) * sizeof(char));
3669 
3670  memcpy(val, _state->save_json_start, len);
3671  val[len] = '\0';
3672  hashentry->val = val;
3673  }
3674  else
3675  {
3676  /* must have had a scalar instead */
3677  hashentry->val = _state->saved_scalar;
3678  }
3679 }
char * prev_token_terminator
Definition: jsonapi.h:79
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:954
JsonTokenType type
Definition: jsonfuncs.c:148
int lex_level
Definition: jsonapi.h:81
char * save_json_start
Definition: jsonfuncs.c:139
#define NAMEDATALEN
JsonTokenType saved_token_type
Definition: jsonfuncs.c:140
char * val
Definition: jsonfuncs.c:147
HTAB * hash
Definition: jsonfuncs.c:137
#define Assert(condition)
Definition: c.h:804
Definition: regguts.h:317
JsonLexContext * lex
Definition: jsonfuncs.c:135
char * saved_scalar
Definition: jsonfuncs.c:138
void * palloc(Size size)
Definition: mcxt.c:1062
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 3609 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().

3610 {
3611  JHashState *_state = (JHashState *) state;
3612 
3613  if (_state->lex->lex_level > 1)
3614  return;
3615 
3616  /* remember token type */
3617  _state->saved_token_type = _state->lex->token_type;
3618 
3619  if (_state->lex->token_type == JSON_TOKEN_ARRAY_START ||
3621  {
3622  /* remember start position of the whole text of the subobject */
3623  _state->save_json_start = _state->lex->token_start;
3624  }
3625  else
3626  {
3627  /* must be a scalar */
3628  _state->save_json_start = NULL;
3629  }
3630 }
JsonTokenType token_type
Definition: jsonapi.h:80
int lex_level
Definition: jsonapi.h:81
char * save_json_start
Definition: jsonfuncs.c:139
JsonTokenType saved_token_type
Definition: jsonfuncs.c:140
char * token_start
Definition: jsonapi.h:77
Definition: regguts.h:317
JsonLexContext * lex
Definition: jsonfuncs.c:135

◆ hash_scalar()

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

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

3694 {
3695  JHashState *_state = (JHashState *) state;
3696 
3697  if (_state->lex->lex_level == 0)
3698  ereport(ERROR,
3699  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3700  errmsg("cannot call %s on a scalar", _state->function_name)));
3701 
3702  if (_state->lex->lex_level == 1)
3703  {
3704  _state->saved_scalar = token;
3705  /* saved_token_type must already be set in hash_object_field_start() */
3706  Assert(_state->saved_token_type == tokentype);
3707  }
3708 }
int errcode(int sqlerrcode)
Definition: elog.c:698
int lex_level
Definition: jsonapi.h:81
#define ERROR
Definition: elog.h:46
JsonTokenType saved_token_type
Definition: jsonfuncs.c:140
const char * function_name
Definition: jsonfuncs.c:136
#define ereport(elevel,...)
Definition: elog.h:157
#define Assert(condition)
Definition: c.h:804
Definition: regguts.h:317
JsonLexContext * lex
Definition: jsonfuncs.c:135
char * saved_scalar
Definition: jsonfuncs.c:138
int errmsg(const char *fmt,...)
Definition: elog.c:909

◆ iterate_json_values()

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

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

5424 {
5425  JsonLexContext *lex = makeJsonLexContext(json, true);
5426  JsonSemAction *sem = palloc0(sizeof(JsonSemAction));
5428 
5429  state->lex = lex;
5430  state->action = action;
5431  state->action_state = action_state;
5432  state->flags = flags;
5433 
5434  sem->semstate = (void *) state;
5437 
5438  pg_parse_json_or_ereport(lex, sem);
5439 }
JsonIterateStringValuesAction action
Definition: jsonfuncs.c:65
static void iterate_values_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:5446
JsonLexContext * makeJsonLexContext(text *json, bool need_escapes)
Definition: jsonfuncs.c:517
json_scalar_action scalar
Definition: jsonapi.h:115
void pg_parse_json_or_ereport(JsonLexContext *lex, JsonSemAction *sem)
Definition: jsonfuncs.c:501
void * palloc0(Size size)
Definition: mcxt.c:1093
Definition: regguts.h:317
JsonLexContext * lex
Definition: jsonfuncs.c:64
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:5472
void * semstate
Definition: jsonapi.h:106

◆ iterate_jsonb_values()

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

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

5356 {
5357  JsonbIterator *it;
5358  JsonbValue v;
5360 
5361  it = JsonbIteratorInit(&jb->root);
5362 
5363  /*
5364  * Just recursively iterating over jsonb and call callback on all
5365  * corresponding elements
5366  */
5367  while ((type = JsonbIteratorNext(&it, &v, false)) != WJB_DONE)
5368  {
5369  if (type == WJB_KEY)
5370  {
5371  if (flags & jtiKey)
5372  action(state, v.val.string.val, v.val.string.len);
5373 
5374  continue;
5375  }
5376  else if (!(type == WJB_VALUE || type == WJB_ELEM))
5377  {
5378  /* do not call callback for composite JsonbValue */
5379  continue;
5380  }
5381 
5382  /* JsonbValue is a value of object or element of array */
5383  switch (v.type)
5384  {
5385  case jbvString:
5386  if (flags & jtiString)
5387  action(state, v.val.string.val, v.val.string.len);
5388  break;
5389  case jbvNumeric:
5390  if (flags & jtiNumeric)
5391  {
5392  char *val;
5393 
5395  NumericGetDatum(v.val.numeric)));
5396 
5397  action(state, val, strlen(val));
5398  pfree(val);
5399  }
5400  break;
5401  case jbvBool:
5402  if (flags & jtiBool)
5403  {
5404  if (v.val.boolean)
5405  action(state, "true", 4);
5406  else
5407  action(state, "false", 5);
5408  }
5409  break;
5410  default:
5411  /* do not call callback for composite JsonbValue */
5412  break;
5413  }
5414  }
5415 }
char * val
Definition: jsonb.h:272
#define NumericGetDatum(X)
Definition: numeric.h:61
Definition: jsonb.h:239
Datum numeric_out(PG_FUNCTION_ARGS)
Definition: numeric.c:743
Definition: jsonb.h:22
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:626
void pfree(void *pointer)
Definition: mcxt.c:1169
#define DatumGetCString(X)
Definition: postgres.h:610
Definition: jsonb.h:23
JsonbIteratorToken
Definition: jsonb.h:20
JsonbContainer root
Definition: jsonb.h:223
JsonbIterator * JsonbIteratorInit(JsonbContainer *container)
Definition: jsonb_util.c:812
Definition: regguts.h:317
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:848
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 5472 of file jsonfuncs.c.

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

Referenced by iterate_json_values().

5473 {
5475 
5476  if (_state->flags & jtiKey)
5477  {
5478  char *val = pstrdup(fname);
5479 
5480  _state->action(_state->action_state, val, strlen(val));
5481  }
5482 }
JsonIterateStringValuesAction action
Definition: jsonfuncs.c:65
char * pstrdup(const char *in)
Definition: mcxt.c:1299
Definition: regguts.h:317
long val
Definition: informix.c:664

◆ iterate_values_scalar()

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

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

5447 {
5449 
5450  switch (tokentype)
5451  {
5452  case JSON_TOKEN_STRING:
5453  if (_state->flags & jtiString)
5454  _state->action(_state->action_state, token, strlen(token));
5455  break;
5456  case JSON_TOKEN_NUMBER:
5457  if (_state->flags & jtiNumeric)
5458  _state->action(_state->action_state, token, strlen(token));
5459  break;
5460  case JSON_TOKEN_TRUE:
5461  case JSON_TOKEN_FALSE:
5462  if (_state->flags & jtiBool)
5463  _state->action(_state->action_state, token, strlen(token));
5464  break;
5465  default:
5466  /* do not call callback for any other token */
5467  break;
5468  }
5469 }
JsonIterateStringValuesAction action
Definition: jsonfuncs.c:65
Definition: regguts.h:317

◆ IteratorConcat()

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

Definition at line 4772 of file jsonfuncs.c.

References Assert, JsonbIteratorNext(), pushJsonbValue(), WJB_BEGIN_ARRAY, WJB_BEGIN_OBJECT, WJB_DONE, WJB_ELEM, WJB_END_ARRAY, and WJB_END_OBJECT.

Referenced by jsonb_concat().

4774 {
4775  JsonbValue v1,
4776  v2,
4777  *res = NULL;
4778  JsonbIteratorToken r1,
4779  r2,
4780  rk1,
4781  rk2;
4782 
4783  rk1 = JsonbIteratorNext(it1, &v1, false);
4784  rk2 = JsonbIteratorNext(it2, &v2, false);
4785 
4786  /*
4787  * JsonbIteratorNext reports raw scalars as if they were single-element
4788  * arrays; hence we only need consider "object" and "array" cases here.
4789  */
4790  if (rk1 == WJB_BEGIN_OBJECT && rk2 == WJB_BEGIN_OBJECT)
4791  {
4792  /*
4793  * Both inputs are objects.
4794  *
4795  * Append all the tokens from v1 to res, except last WJB_END_OBJECT
4796  * (because res will not be finished yet).
4797  */
4798  pushJsonbValue(state, rk1, NULL);
4799  while ((r1 = JsonbIteratorNext(it1, &v1, true)) != WJB_END_OBJECT)
4800  pushJsonbValue(state, r1, &v1);
4801 
4802  /*
4803  * Append all the tokens from v2 to res, including last WJB_END_OBJECT
4804  * (the concatenation will be completed). Any duplicate keys will
4805  * automatically override the value from the first object.
4806  */
4807  while ((r2 = JsonbIteratorNext(it2, &v2, true)) != WJB_DONE)
4808  res = pushJsonbValue(state, r2, r2 != WJB_END_OBJECT ? &v2 : NULL);
4809  }
4810  else if (rk1 == WJB_BEGIN_ARRAY && rk2 == WJB_BEGIN_ARRAY)
4811  {
4812  /*
4813  * Both inputs are arrays.
4814  */
4815  pushJsonbValue(state, rk1, NULL);
4816 
4817  while ((r1 = JsonbIteratorNext(it1, &v1, true)) != WJB_END_ARRAY)
4818  {
4819  Assert(r1 == WJB_ELEM);
4820  pushJsonbValue(state, r1, &v1);
4821  }
4822 
4823  while ((r2 = JsonbIteratorNext(it2, &v2, true)) != WJB_END_ARRAY)
4824  {
4825  Assert(r2 == WJB_ELEM);
4826  pushJsonbValue(state, WJB_ELEM, &v2);
4827  }
4828 
4829  res = pushJsonbValue(state, WJB_END_ARRAY, NULL /* signal to sort */ );
4830  }
4831  else if (rk1 == WJB_BEGIN_OBJECT)
4832  {
4833  /*
4834  * We have object || array.
4835  */
4836  Assert(rk2 == WJB_BEGIN_ARRAY);
4837 
4838  pushJsonbValue(state, WJB_BEGIN_ARRAY, NULL);
4839 
4840  pushJsonbValue(state, WJB_BEGIN_OBJECT, NULL);
4841  while ((r1 = JsonbIteratorNext(it1, &v1, true)) != WJB_DONE)
4842  pushJsonbValue(state, r1, r1 != WJB_END_OBJECT ? &v1 : NULL);
4843 
4844  while ((r2 = JsonbIteratorNext(it2, &v2, true)) != WJB_DONE)
4845  res = pushJsonbValue(state, r2, r2 != WJB_END_ARRAY ? &v2 : NULL);
4846  }
4847  else
4848  {
4849  /*
4850  * We have array || object.
4851  */
4852  Assert(rk1 == WJB_BEGIN_ARRAY);
4853  Assert(rk2 == WJB_BEGIN_OBJECT);
4854 
4855  pushJsonbValue(state, WJB_BEGIN_ARRAY, NULL);
4856 
4857  while ((r1 = JsonbIteratorNext(it1, &v1, true)) != WJB_END_ARRAY)
4858  pushJsonbValue(state, r1, &v1);
4859 
4860  pushJsonbValue(state, WJB_BEGIN_OBJECT, NULL);
4861  while ((r2 = JsonbIteratorNext(it2, &v2, true)) != WJB_DONE)
4862  pushJsonbValue(state, r2, r2 != WJB_END_OBJECT ? &v2 : NULL);
4863 
4864  res = pushJsonbValue(state, WJB_END_ARRAY, NULL);
4865  }
4866 
4867  return res;
4868 }
Definition: jsonb.h:22
JsonbValue * pushJsonbValue(JsonbParseState **pstate, JsonbIteratorToken seq, JsonbValue *jbval)
Definition: jsonb_util.c:566
JsonbIteratorToken
Definition: jsonb.h:20
#define Assert(condition)
Definition: c.h:804
JsonbIteratorToken JsonbIteratorNext(JsonbIterator **it, JsonbValue *val, bool skipNested)
Definition: jsonb_util.c:848
Definition: jsonb.h:25

◆ JsObjectGetField()

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

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

3266 {
3267  jsv->is_json = obj->is_json;
3268 
3269  if (jsv->is_json)
3270  {
3271  JsonHashEntry *hashentry = hash_search(obj->val.json_hash, field,
3272  HASH_FIND, NULL);
3273 
3274  jsv->val.json.type = hashentry ? hashentry->type : JSON_TOKEN_NULL;
3275  jsv->val.json.str = jsv->val.json.type == JSON_TOKEN_NULL ? NULL :
3276  hashentry->val;
3277  jsv->val.json.len = jsv->val.json.str ? -1 : 0; /* null-terminated */
3278 
3279  return hashentry != NULL;
3280  }
3281  else
3282  {
3283  jsv->val.jsonb = !obj->val.jsonb_cont ? NULL :
3284  getKeyJsonValueFromContainer(obj->val.jsonb_cont, field, strlen(field),
3285  NULL);
3286 
3287  return jsv->val.jsonb != NULL;
3288  }
3289 }
bool is_json
Definition: jsonfuncs.c:306
JsonbValue * getKeyJsonValueFromContainer(JsonbContainer *container, const char *keyVal, int keyLen, JsonbValue *res)
Definition: jsonb_util.c:398
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:954
JsonTokenType type
Definition: jsonfuncs.c:148
JsonbContainer * jsonb_cont
Definition: jsonfuncs.c:310
char * val
Definition: jsonfuncs.c:147
struct JsValue::@22::@23 json
bool is_json
Definition: jsonfuncs.c:290
union JsValue::@22 val
HTAB * json_hash
Definition: jsonfuncs.c:309
union JsObject::@24 val
JsonbValue * jsonb
Definition: jsonfuncs.c:300

◆ json_array_element()

Datum json_array_element ( PG_FUNCTION_ARGS  )

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

878 {
879  text *json = PG_GETARG_TEXT_PP(0);
880  int element = PG_GETARG_INT32(1);
881  text *result;
882 
883  result = get_worker(json, NULL, &element, 1, false);
884 
885  if (result != NULL)
886  PG_RETURN_TEXT_P(result);
887  else
888  PG_RETURN_NULL();
889 }
#define PG_GETARG_INT32(n)
Definition: fmgr.h:269
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:309
static chr element(struct vars *v, const chr *startp, const chr *endp)
Definition: regc_locale.c:376
static text * get_worker(text *json, char **tpath, int *ipath, int npath, bool normalize_results)
Definition: jsonfuncs.c:1059
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:372
Definition: c.h:621
#define PG_RETURN_NULL()
Definition: fmgr.h:345

◆ json_array_element_text()

Datum json_array_element_text ( PG_FUNCTION_ARGS  )

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

921 {
922  text *json = PG_GETARG_TEXT_PP(0);
923  int element = PG_GETARG_INT32(1);
924  text *result;
925 
926  result = get_worker(json, NULL, &element, 1, true);
927 
928  if (result != NULL)
929  PG_RETURN_TEXT_P(result);
930  else
931  PG_RETURN_NULL();
932 }
#define PG_GETARG_INT32(n)
Definition: fmgr.h:269
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:309
static chr element(struct vars *v, const chr *startp, const chr *endp)
Definition: regc_locale.c:376
static text * get_worker(text *json, char **tpath, int *ipath, int npath, bool normalize_results)
Definition: jsonfuncs.c:1059
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:372
Definition: c.h:621
#define PG_RETURN_NULL()
Definition: fmgr.h:345

◆ json_array_elements()

Datum json_array_elements ( PG_FUNCTION_ARGS  )

Definition at line 2308 of file jsonfuncs.c.

References elements_worker().

2309 {
2310  return elements_worker(fcinfo, "json_array_elements", false);
2311 }
static Datum elements_worker(FunctionCallInfo fcinfo, const char *funcname, bool as_text)
Definition: jsonfuncs.c:2320

◆ json_array_elements_text()

Datum json_array_elements_text ( PG_FUNCTION_ARGS  )

Definition at line 2314 of file jsonfuncs.c.

References elements_worker().

2315 {
2316  return elements_worker(fcinfo, "json_array_elements_text", true);
2317 }
static Datum elements_worker(FunctionCallInfo fcinfo, const char *funcname, bool as_text)
Definition: jsonfuncs.c:2320

◆ json_array_length()

Datum json_array_length ( PG_FUNCTION_ARGS  )

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

1789 {
1790  text *json = PG_GETARG_TEXT_PP(0);
1791  AlenState *state;
1792  JsonLexContext *lex;
1793  JsonSemAction *sem;
1794 
1795  lex = makeJsonLexContext(json, false);
1796  state = palloc0(sizeof(AlenState));
1797  sem = palloc0(sizeof(JsonSemAction));
1798 
1799  /* palloc0 does this for us */
1800 #if 0
1801  state->count = 0;
1802 #endif
1803  state->lex = lex;
1804 
1805  sem->semstate = (void *) state;
1807  sem->scalar = alen_scalar;
1809 
1810  pg_parse_json_or_ereport(lex, sem);
1811 
1812  PG_RETURN_INT32(state->count);
1813 }
json_struct_action object_start
Definition: jsonapi.h:107
JsonLexContext * makeJsonLexContext(text *json, bool need_escapes)
Definition: jsonfuncs.c:517
#define PG_RETURN_INT32(x)
Definition: fmgr.h:354
json_scalar_action scalar
Definition: jsonapi.h:115
int count
Definition: jsonfuncs.c:102
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:309
static void alen_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:1850
JsonLexContext * lex
Definition: jsonfuncs.c:101
void pg_parse_json_or_ereport(JsonLexContext *lex, JsonSemAction *sem)
Definition: jsonfuncs.c:501
void * palloc0(Size size)
Definition: mcxt.c:1093
json_aelem_action array_element_start
Definition: jsonapi.h:113
Definition: regguts.h:317
static void alen_object_start(void *state)
Definition: jsonfuncs.c:1838
Definition: c.h:621
static void alen_array_element_start(void *state, bool isnull)
Definition: jsonfuncs.c:1862
void * semstate
Definition: jsonapi.h:106

◆ json_each()

Datum json_each ( PG_FUNCTION_ARGS  )

Definition at line 1882 of file jsonfuncs.c.

References each_worker().

1883 {
1884  return each_worker(fcinfo, false);
1885 }
static Datum each_worker(FunctionCallInfo fcinfo, bool as_text)
Definition: jsonfuncs.c:2024

◆ json_each_text()

Datum json_each_text ( PG_FUNCTION_ARGS  )

Definition at line 1894 of file jsonfuncs.c.

References each_worker().

1895 {
1896  return each_worker(fcinfo, true);
1897 }
static Datum each_worker(FunctionCallInfo fcinfo, bool as_text)
Definition: jsonfuncs.c:2024

◆ json_ereport_error()

void json_ereport_error ( JsonParseErrorType  error,
JsonLexContext lex 
)

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

612 {
615  ereport(ERROR,
616  (errcode(ERRCODE_UNTRANSLATABLE_CHARACTER),
617  errmsg("unsupported Unicode escape sequence"),
618  errdetail("%s", json_errdetail(error, lex)),
619  report_json_context(lex)));
620  else
621  ereport(ERROR,
622  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
623  errmsg("invalid input syntax for type %s", "json"),
624  errdetail("%s", json_errdetail(error, lex)),
625  report_json_context(lex)));
626 }
static void error(void)
Definition: sql-dyntest.c:147
char * json_errdetail(JsonParseErrorType error, JsonLexContext *lex)
Definition: jsonapi.c:1070
int errcode(int sqlerrcode)
Definition: elog.c:698
#define ERROR
Definition: elog.h:46
int errdetail(const char *fmt,...)
Definition: elog.c:1042
static int report_json_context(JsonLexContext *lex)
Definition: jsonfuncs.c:639
#define ereport(elevel,...)
Definition: elog.h:157
int errmsg(const char *fmt,...)
Definition: elog.c:909

◆ json_extract_path()

Datum json_extract_path ( PG_FUNCTION_ARGS  )

Definition at line 964 of file jsonfuncs.c.

References get_path_all().

965 {
966  return get_path_all(fcinfo, false);
967 }
static Datum get_path_all(FunctionCallInfo fcinfo, bool as_text)
Definition: jsonfuncs.c:979

◆ json_extract_path_text()

Datum json_extract_path_text ( PG_FUNCTION_ARGS  )

Definition at line 970 of file jsonfuncs.c.

References get_path_all().

971 {
972  return get_path_all(fcinfo, true);
973 }
static Datum get_path_all(FunctionCallInfo fcinfo, bool as_text)
Definition: jsonfuncs.c:979

◆ json_object_field()

Datum json_object_field ( PG_FUNCTION_ARGS  )

Definition at line 801 of file jsonfuncs.c.

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

802 {
803  text *json = PG_GETARG_TEXT_PP(0);
804  text *fname = PG_GETARG_TEXT_PP(1);
805  char *fnamestr = text_to_cstring(fname);
806  text *result;
807 
808  result = get_worker(json, &fnamestr, NULL, 1, false);
809 
810  if (result != NULL)
811  PG_RETURN_TEXT_P(result);
812  else
813  PG_RETURN_NULL();
814 }
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:309
static text * get_worker(text *json, char **tpath, int *ipath, int npath, bool normalize_results)
Definition: jsonfuncs.c:1059
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:372
char * text_to_cstring(const text *t)
Definition: varlena.c:223
Definition: c.h:621
#define PG_RETURN_NULL()
Definition: fmgr.h:345

◆ json_object_field_text()

Datum json_object_field_text ( PG_FUNCTION_ARGS  )

Definition at line 839 of file jsonfuncs.c.

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

840 {
841  text *json = PG_GETARG_TEXT_PP(0);
842  text *fname = PG_GETARG_TEXT_PP(1);
843  char *fnamestr = text_to_cstring(fname);
844  text *result;
845 
846  result = get_worker(json, &fnamestr, NULL, 1, true);
847 
848  if (result != NULL)
849  PG_RETURN_TEXT_P(result);
850  else
851  PG_RETURN_NULL();
852 }
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:309
static text * get_worker(text *json, char **tpath, int *ipath, int npath, bool normalize_results)
Definition: jsonfuncs.c:1059
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:372
char * text_to_cstring(const text *t)
Definition: varlena.c:223
Definition: c.h:621
#define PG_RETURN_NULL()
Definition: fmgr.h:345

◆ json_object_keys()

Datum json_object_keys ( PG_FUNCTION_ARGS  )

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

692 {
693  FuncCallContext *funcctx;
694  OkeysState *state;
695 
696  if (SRF_IS_FIRSTCALL())
697  {
698  text *json = PG_GETARG_TEXT_PP(0);
699  JsonLexContext *lex = makeJsonLexContext(json, true);
700  JsonSemAction *sem;
701  MemoryContext oldcontext;
702 
703  funcctx = SRF_FIRSTCALL_INIT();
704  oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
705 
706  state = palloc(sizeof(OkeysState));
707  sem = palloc0(sizeof(JsonSemAction));
708 
709  state->lex = lex;
710  state->result_size = 256;
711  state->result_count = 0;
712  state->sent_count = 0;
713  state->result = palloc(256 * sizeof(char *));
714 
715  sem->semstate = (void *) state;
717  sem->scalar = okeys_scalar;
719  /* remainder are all NULL, courtesy of palloc0 above */
720 
721  pg_parse_json_or_ereport(lex, sem);
722  /* keys are now in state->result */
723 
724  pfree(lex->strval->data);
725  pfree(lex->strval);
726  pfree(lex);
727  pfree(sem);
728 
729  MemoryContextSwitchTo(oldcontext);
730  funcctx->user_fctx = (void *) state;
731  }
732 
733  funcctx = SRF_PERCALL_SETUP();
734  state = (OkeysState *) funcctx->user_fctx;
735 
736  if (state->sent_count < state->result_count)
737  {
738  char *nxt = state->result[state->sent_count++];
739 
740  SRF_RETURN_NEXT(funcctx, CStringGetTextDatum(nxt));
741  }
742 
743  SRF_RETURN_DONE(funcctx);
744 }
int result_count
Definition: jsonfuncs.c:57
#define SRF_IS_FIRSTCALL()
Definition: funcapi.h:293
JsonLexContext * makeJsonLexContext(text *json, bool need_escapes)
Definition: jsonfuncs.c:517
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
static void okeys_array_start(void *state)
Definition: jsonfuncs.c:768
json_scalar_action scalar
Definition: jsonapi.h:115
int sent_count
Definition: jsonfuncs.c:58
#define SRF_PERCALL_SETUP()
Definition: funcapi.h:297
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:309
#define SRF_RETURN_NEXT(_funcctx, _result)
Definition: funcapi.h:299
void pfree(void *pointer)
Definition: mcxt.c:1169
StringInfo strval
Definition: jsonapi.h:84
static void okeys_object_field_start(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:747
void pg_parse_json_or_ereport(JsonLexContext *lex, JsonSemAction *sem)
Definition: jsonfuncs.c:501
char ** result
Definition: jsonfuncs.c:55
void * palloc0(Size size)
Definition: mcxt.c:1093
JsonLexContext * lex
Definition: jsonfuncs.c:54
json_struct_action array_start
Definition: jsonapi.h:109
Definition: regguts.h:317
MemoryContext multi_call_memory_ctx
Definition: funcapi.h:101
static void okeys_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:781
int result_size
Definition: jsonfuncs.c:56
void * user_fctx
Definition: funcapi.h:82
void * palloc(Size size)
Definition: mcxt.c:1062
#define CStringGetTextDatum(s)
Definition: builtins.h:82
Definition: c.h:621
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 2506 of file jsonfuncs.c.

References populate_record_worker().

2507 {
2508  return populate_record_worker(fcinfo, "json_populate_record",
2509  true, true);
2510 }
static Datum populate_record_worker(FunctionCallInfo fcinfo, const char *funcname, bool is_json, bool have_record_arg)
Definition: jsonfuncs.c:3469

◆ json_populate_recordset()

Datum json_populate_recordset ( PG_FUNCTION_ARGS  )

Definition at line 3736 of file jsonfuncs.c.

References populate_recordset_worker().

3737 {
3738  return populate_recordset_worker(fcinfo, "json_populate_recordset",
3739  true, true);
3740 }
static Datum populate_recordset_worker(FunctionCallInfo fcinfo, const char *funcname, bool is_json, bool have_record_arg)
Definition: jsonfuncs.c:3787

◆ json_strip_nulls()

Datum json_strip_nulls ( PG_FUNCTION_ARGS  )

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

4208 {
4209  text *json = PG_GETARG_TEXT_PP(0);
4211  JsonLexContext *lex;
4212  JsonSemAction *sem;
4213 
4214  lex = makeJsonLexContext(json, true);
4215  state = palloc0(sizeof(StripnullState));
4216  sem = palloc0(sizeof(JsonSemAction));
4217 
4218  state->strval = makeStringInfo();
4219  state->skip_next_null = false;
4220  state->lex = lex;
4221 
4222  sem->semstate = (void *) state;
4224  sem->object_end = sn_object_end;
4225  sem->array_start = sn_array_start;
4226  sem->array_end = sn_array_end;
4227  sem->scalar = sn_scalar;
4230 
4231  pg_parse_json_or_ereport(lex, sem);
4232 
4234  state->strval->len));
4235 
4236 }
json_struct_action array_end
Definition: jsonapi.h:110
bool skip_next_null
Definition: jsonfuncs.c:284
static void sn_object_start(void *state)
Definition: jsonfuncs.c:4117
json_struct_action object_end
Definition: jsonapi.h:108
static void sn_array_element_start(void *state, bool isnull)
Definition: jsonfuncs.c:4177
static void sn_object_field_start(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:4149
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:517
json_scalar_action scalar
Definition: jsonapi.h:115
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:309
static void sn_array_start(void *state)
Definition: jsonfuncs.c:4133
text * cstring_to_text_with_len(const char *s, int len)
Definition: varlena.c:202
JsonLexContext * lex
Definition: jsonfuncs.c:282
static void sn_object_end(void *state)
Definition: jsonfuncs.c:4125
void pg_parse_json_or_ereport(JsonLexContext *lex, JsonSemAction *sem)
Definition: jsonfuncs.c:501
void * palloc0(Size size)
Definition: mcxt.c:1093
json_aelem_action array_element_start
Definition: jsonapi.h:113
static void sn_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:4186
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:372
json_struct_action array_start
Definition: jsonapi.h:109
Definition: regguts.h:317
StringInfo strval
Definition: jsonfuncs.c:283
Definition: c.h:621
json_ofield_action object_field_start
Definition: jsonapi.h:111
static void sn_array_end(void *state)
Definition: jsonfuncs.c:4141
void * semstate
Definition: jsonapi.h:106

◆ json_to_record()

Datum json_to_record ( PG_FUNCTION_ARGS  )

Definition at line 2513 of file jsonfuncs.c.

References populate_record_worker().

2514 {
2515  return populate_record_worker(fcinfo, "json_to_record",
2516  true, false);
2517 }
static Datum populate_record_worker(FunctionCallInfo fcinfo, const char *funcname, bool is_json, bool have_record_arg)
Definition: jsonfuncs.c:3469

◆ json_to_recordset()

Datum json_to_recordset ( PG_FUNCTION_ARGS  )

Definition at line 3743 of file jsonfuncs.c.

References populate_recordset_worker().

3744 {
3745  return populate_recordset_worker(fcinfo, "json_to_recordset",
3746  true, false);
3747 }
static Datum populate_recordset_worker(FunctionCallInfo fcinfo, const char *funcname, bool is_json, bool have_record_arg)
Definition: jsonfuncs.c:3787

◆ jsonb_array_element()

Datum jsonb_array_element ( PG_FUNCTION_ARGS  )

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

893 {
894  Jsonb *jb = PG_GETARG_JSONB_P(0);
895  int element = PG_GETARG_INT32(1);
896  JsonbValue *v;
897 
898  if (!JB_ROOT_IS_ARRAY(jb))
899  PG_RETURN_NULL();
900 
901  /* Handle negative subscript */
902  if (element < 0)
903  {
904  uint32 nelements = JB_ROOT_COUNT(jb);
905 
906  if (-element > nelements)
907  PG_RETURN_NULL();
908  else
909  element += nelements;
910  }
911 
912  v = getIthJsonbValueFromContainer(&jb->root, element);
913  if (v != NULL)
915 
916  PG_RETURN_NULL();
917 }
#define PG_GETARG_INT32(n)
Definition: fmgr.h:269
Jsonb * JsonbValueToJsonb(JsonbValue *val)
Definition: jsonb_util.c:92
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:441
static chr element(struct vars *v, const chr *startp, const chr *endp)
Definition: regc_locale.c:376
JsonbContainer root
Definition: jsonb.h:223
JsonbValue * getIthJsonbValueFromContainer(JsonbContainer *container, uint32 i)
Definition: jsonb_util.c:468
#define PG_RETURN_JSONB_P(x)
Definition: jsonb.h:76
#define PG_RETURN_NULL()
Definition: fmgr.h:345
#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 935 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.

936 {
937  Jsonb *jb = PG_GETARG_JSONB_P(0);
938  int element = PG_GETARG_INT32(1);
939  JsonbValue *v;
940 
941  if (!JB_ROOT_IS_ARRAY(jb))
942  PG_RETURN_NULL();
943 
944  /* Handle negative subscript */
945  if (element < 0)
946  {
947  uint32 nelements = JB_ROOT_COUNT(jb);
948 
949  if (-element > nelements)
950  PG_RETURN_NULL();
951  else
952  element += nelements;
953  }
954 
955  v = getIthJsonbValueFromContainer(&jb->root, element);
956 
957  if (v != NULL && v->type != jbvNull)
959 
960  PG_RETURN_NULL();
961 }
#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:1741
#define JB_ROOT_IS_ARRAY(jbp_)
Definition: jsonb.h:230
unsigned int uint32
Definition: c.h:441
static chr element(struct vars *v, const chr *startp, const chr *endp)
Definition: regc_locale.c:376
JsonbContainer root
Definition: jsonb.h:223
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:372
JsonbValue * getIthJsonbValueFromContainer(JsonbContainer *container, uint32 i)
Definition: jsonb_util.c:468
enum jbvType type
Definition: jsonb.h:263
#define PG_RETURN_NULL()
Definition: fmgr.h:345
#define PG_GETARG_JSONB_P(x)
Definition: jsonb.h:74

◆ jsonb_array_elements()

Datum jsonb_array_elements ( PG_FUNCTION_ARGS  )

Definition at line 2190 of file jsonfuncs.c.

References elements_worker_jsonb().

2191 {
2192  return elements_worker_jsonb(fcinfo, "jsonb_array_elements", false);
2193 }
static Datum elements_worker_jsonb(FunctionCallInfo fcinfo, const char *funcname, bool as_text)
Definition: jsonfuncs.c:2202

◆ jsonb_array_elements_text()

Datum jsonb_array_elements_text ( PG_FUNCTION_ARGS  )

Definition at line 2196 of file jsonfuncs.c.

References elements_worker_jsonb().

2197 {
2198  return elements_worker_jsonb(fcinfo, "jsonb_array_elements_text", true);
2199 }
static Datum elements_worker_jsonb(FunctionCallInfo fcinfo, const char *funcname, bool as_text)
Definition: jsonfuncs.c:2202

◆ jsonb_array_length()

Datum jsonb_array_length ( PG_FUNCTION_ARGS  )

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

1817 {
1818  Jsonb *jb = PG_GETARG_JSONB_P(0);
1819 
1820  if (JB_ROOT_IS_SCALAR(jb))
1821  ereport(ERROR,
1822  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1823  errmsg("cannot get array length of a scalar")));
1824  else if (!JB_ROOT_IS_ARRAY(jb))
1825  ereport(ERROR,
1826  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1827  errmsg("cannot get array length of a non-array")));
1828 
1830 }
Definition: jsonb.h:220
#define PG_RETURN_INT32(x)
Definition: fmgr.h:354
#define JB_ROOT_COUNT(jbp_)
Definition: jsonb.h:227
int errcode(int sqlerrcode)
Definition: elog.c:698
#define JB_ROOT_IS_SCALAR(jbp_)
Definition: jsonb.h:228
#define ERROR
Definition: elog.h:46
#define JB_ROOT_IS_ARRAY(jbp_)
Definition: jsonb.h:230
#define ereport(elevel,...)
Definition: elog.h:157
int errmsg(const char *fmt,...)
Definition: elog.c:909
#define PG_GETARG_JSONB_P(x)
Definition: jsonb.h:74

◆ jsonb_concat()

Datum jsonb_concat ( PG_FUNCTION_ARGS  )

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

4317 {
4318  Jsonb *jb1 = PG_GETARG_JSONB_P(0);
4319  Jsonb *jb2 = PG_GETARG_JSONB_P(1);
4320  JsonbParseState *state = NULL;
4321  JsonbValue *res;
4322  JsonbIterator *it1,
4323  *it2;
4324 
4325  /*
4326  * If one of the jsonb is empty, just return the other if it's not scalar
4327  * and both are of the same kind. If it's a scalar or they are of
4328  * different kinds we need to perform the concatenation even if one is
4329  * empty.
4330  */
4331  if (JB_ROOT_IS_OBJECT(jb1) == JB_ROOT_IS_OBJECT(jb2))
4332  {
4333  if (JB_ROOT_COUNT(jb1) == 0 && !JB_ROOT_IS_SCALAR(jb2))
4334  PG_RETURN_JSONB_P(jb2);
4335  else if (JB_ROOT_COUNT(jb2) == 0 && !JB_ROOT_IS_SCALAR(jb1))
4336  PG_RETURN_JSONB_P(jb1);
4337  }
4338 
4339  it1 = JsonbIteratorInit(&jb1->root);
4340  it2 = JsonbIteratorInit(&jb2->root);
4341 
4342  res = IteratorConcat(&it1, &it2, &state);
4343 
4344  Assert(res != NULL);
4345 
4347 }
#define JB_ROOT_IS_OBJECT(jbp_)
Definition: jsonb.h:229
Jsonb * JsonbValueToJsonb(JsonbValue *val)
Definition: jsonb_util.c:92
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:804
JsonbIterator * JsonbIteratorInit(JsonbContainer *container)
Definition: jsonb_util.c:812
Definition: regguts.h:317
static JsonbValue * IteratorConcat(JsonbIterator **it1, JsonbIterator **it2, JsonbParseState **state)
Definition: jsonfuncs.c:4772
#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 4357 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.

4358 {
4359  Jsonb *in = PG_GETARG_JSONB_P(0);
4360  text *key = PG_GETARG_TEXT_PP(1);
4361  char *keyptr = VARDATA_ANY(key);
4362  int keylen = VARSIZE_ANY_EXHDR(key);
4363  JsonbParseState *state = NULL;
4364  JsonbIterator *it;
4365  JsonbValue v,
4366  *res = NULL;
4367  bool skipNested = false;
4369 
4370  if (JB_ROOT_IS_SCALAR(in))
4371  ereport(ERROR,
4372  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4373  errmsg("cannot delete from scalar")));
4374 
4375  if (JB_ROOT_COUNT(in) == 0)
4376  PG_RETURN_JSONB_P(in);
4377 
4378  it = JsonbIteratorInit(&in->root);
4379 
4380  while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE)
4381  {
4382  skipNested = true;
4383 
4384  if ((r == WJB_ELEM || r == WJB_KEY) &&
4385  (v.type == jbvString && keylen == v.val.string.len &&
4386  memcmp(keyptr, v.val.string.val, keylen) == 0))
4387  {
4388  /* skip corresponding value as well */
4389  if (r == WJB_KEY)
4390  (void) JsonbIteratorNext(&it, &v, true);
4391 
4392  continue;
4393  }
4394 
4395  res = pushJsonbValue(&state, r, r < WJB_BEGIN_ARRAY ? &v : NULL);
4396  }
4397 
4398  Assert(res != NULL);
4399 
4401 }
#define VARDATA_ANY(PTR)
Definition: postgres.h:361
Jsonb * JsonbValueToJsonb(JsonbValue *val)
Definition: jsonb_util.c:92
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:698
#define JB_ROOT_IS_SCALAR(jbp_)
Definition: jsonb.h:228
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:309
JsonbValue * pushJsonbValue(JsonbParseState **pstate, JsonbIteratorToken seq, JsonbValue *jbval)
Definition: jsonb_util.c:566
#define ERROR
Definition: elog.h:46
Definition: jsonb.h:23
JsonbIteratorToken
Definition: jsonb.h:20
JsonbContainer root
Definition: jsonb.h:223
#define ereport(elevel,...)
Definition: elog.h:157
#define Assert(condition)
Definition: c.h:804
JsonbIterator * JsonbIteratorInit(JsonbContainer *container)
Definition: jsonb_util.c:812
Definition: regguts.h:317
enum jbvType type
Definition: jsonb.h:263
#define VARSIZE_ANY_EXHDR(PTR)
Definition: postgres.h:354
int errmsg(const char *fmt,...)
Definition: elog.c:909
Definition: c.h:621
#define PG_RETURN_JSONB_P(x)
Definition: jsonb.h:76
JsonbIteratorToken JsonbIteratorNext(JsonbIterator **it, JsonbValue *val, bool skipNested)
Definition: jsonb_util.c:848
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 4410 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.

4411 {
4412  Jsonb *in = PG_GETARG_JSONB_P(0);
4413  ArrayType *keys = PG_GETARG_ARRAYTYPE_P(1);
4414  Datum *keys_elems;
4415  bool *keys_nulls;
4416  int keys_len;
4417  JsonbParseState *state = NULL;
4418  JsonbIterator *it;
4419  JsonbValue v,
4420  *res = NULL;
4421  bool skipNested = false;
4423 
4424  if (ARR_NDIM(keys) > 1)
4425  ereport(ERROR,
4426  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
4427  errmsg("wrong number of array subscripts")));
4428 
4429  if (JB_ROOT_IS_SCALAR(in))
4430  ereport(ERROR,
4431  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4432  errmsg("cannot delete from scalar")));
4433 
4434  if (JB_ROOT_COUNT(in) == 0)
4435  PG_RETURN_JSONB_P(in);
4436 
4437  deconstruct_array(keys, TEXTOID, -1, false, TYPALIGN_INT,
4438  &keys_elems, &keys_nulls, &keys_len);
4439 
4440  if (keys_len == 0)
4441  PG_RETURN_JSONB_P(in);
4442 
4443  it = JsonbIteratorInit(&in->root);
4444 
4445  while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE)
4446  {
4447  skipNested = true;
4448 
4449  if ((r == WJB_ELEM || r == WJB_KEY) && v.type == jbvString)
4450  {
4451  int i;
4452  bool found = false;
4453 
4454  for (i = 0; i < keys_len; i++)
4455  {
4456  char *keyptr;
4457  int keylen;
4458 
4459  if (keys_nulls[i])
4460  continue;
4461 
4462  keyptr = VARDATA_ANY(keys_elems[i]);
4463  keylen = VARSIZE_ANY_EXHDR(keys_elems[i]);
4464  if (keylen == v.val.string.len &&
4465  memcmp(keyptr, v.val.string.val, keylen) == 0)
4466  {
4467  found = true;
4468  break;
4469  }
4470  }
4471  if (found)
4472  {
4473  /* skip corresponding value as well */
4474  if (r == WJB_KEY)
4475  (void) JsonbIteratorNext(&it, &v, true);
4476 
4477  continue;
4478  }
4479  }
4480 
4481  res = pushJsonbValue(&state, r, r < WJB_BEGIN_ARRAY ? &v : NULL);
4482  }
4483 
4484  Assert(res != NULL);
4485 
4487 }
#define VARDATA_ANY(PTR)
Definition: postgres.h:361
Jsonb * JsonbValueToJsonb(JsonbValue *val)
Definition: jsonb_util.c:92
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:698
#define JB_ROOT_IS_SCALAR(jbp_)
Definition: jsonb.h:228
JsonbValue * pushJsonbValue(JsonbParseState **pstate, JsonbIteratorToken seq, JsonbValue *jbval)
Definition: jsonb_util.c:566
#define PG_GETARG_ARRAYTYPE_P(n)
Definition: array.h:256
#define ERROR
Definition: elog.h:46
Definition: jsonb.h:23
JsonbIteratorToken
Definition: jsonb.h:20
JsonbContainer root
Definition: jsonb.h:223
uintptr_t Datum
Definition: postgres.h:411
#define ereport(elevel,...)
Definition: elog.h:157
#define Assert(condition)
Definition: c.h:804
JsonbIterator * JsonbIteratorInit(JsonbContainer *container)
Definition: jsonb_util.c:812
Definition: regguts.h:317
#define ARR_NDIM(a)
Definition: array.h:283
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:3490
#define VARSIZE_ANY_EXHDR(PTR)
Definition: postgres.h:354
int errmsg(const char *fmt,...)
Definition: elog.c:909
int i
#define PG_RETURN_JSONB_P(x)
Definition: jsonb.h:76
JsonbIteratorToken JsonbIteratorNext(JsonbIterator **it, JsonbValue *val, bool skipNested)
Definition: jsonb_util.c:848
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 4497 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.

4498 {
4499  Jsonb *in = PG_GETARG_JSONB_P(0);
4500  int idx = PG_GETARG_INT32(1);
4501  JsonbParseState *state = NULL;
4502  JsonbIterator *it;
4503  uint32 i = 0,
4504  n;
4505  JsonbValue v,
4506  *res = NULL;
4508 
4509  if (JB_ROOT_IS_SCALAR(in))
4510  ereport(ERROR,
4511  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4512  errmsg("cannot delete from scalar")));
4513 
4514  if (JB_ROOT_IS_OBJECT(in))
4515  ereport(ERROR,
4516  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4517  errmsg("cannot delete from object using integer index")));
4518 
4519  if (JB_ROOT_COUNT(in) == 0)
4520  PG_RETURN_JSONB_P(in);
4521 
4522  it = JsonbIteratorInit(&in->root);
4523 
4524  r = JsonbIteratorNext(&it, &v, false);
4525  Assert(r == WJB_BEGIN_ARRAY);
4526  n = v.val.array.nElems;
4527 
4528  if (idx < 0)
4529  {
4530  if (-idx > n)
4531  idx = n;
4532  else
4533  idx = n + idx;
4534  }
4535 
4536  if (idx >= n)
4537  PG_RETURN_JSONB_P(in);
4538 
4539  pushJsonbValue(&state, r, NULL);
4540 
4541  while ((r = JsonbIteratorNext(&it, &v, true)) != WJB_DONE)
4542  {
4543  if (r == WJB_ELEM)
4544  {
4545  if (i++ == idx)
4546  continue;
4547  }
4548 
4549  res = pushJsonbValue(&state, r, r < WJB_BEGIN_ARRAY ? &v : NULL);
4550  }
4551 
4552  Assert(res != NULL);
4553 
4555 }
#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:92
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:698
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:566
#define ERROR
Definition: elog.h:46
unsigned int uint32
Definition: c.h:441
JsonbIteratorToken
Definition: jsonb.h:20
JsonbContainer root
Definition: jsonb.h:223
#define ereport(elevel,...)
Definition: elog.h:157
#define Assert(condition)
Definition: c.h:804
JsonbIterator * JsonbIteratorInit(JsonbContainer *container)
Definition: jsonb_util.c:812
Definition: regguts.h:317
int errmsg(const char *fmt,...)
Definition: elog.c:909
int i
#define PG_RETURN_JSONB_P(x)
Definition: jsonb.h:76
JsonbIteratorToken JsonbIteratorNext(JsonbIterator **it, JsonbValue *val, bool skipNested)
Definition: jsonb_util.c:848
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 4678 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().

4679 {
4680  Jsonb *in = PG_GETARG_JSONB_P(0);
4681  ArrayType *path = PG_GETARG_ARRAYTYPE_P(1);
4682  JsonbValue *res = NULL;
4683  Datum *path_elems;
4684  bool *path_nulls;
4685  int path_len;
4686  JsonbIterator *it;
4687  JsonbParseState *st = NULL;
4688 
4689  if (ARR_NDIM(path) > 1)
4690  ereport(ERROR,
4691  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
4692  errmsg("wrong number of array subscripts")));
4693 
4694  if (JB_ROOT_IS_SCALAR(in))
4695  ereport(ERROR,
4696  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4697  errmsg("cannot delete path in scalar")));
4698 
4699  if (JB_ROOT_COUNT(in) == 0)
4700  PG_RETURN_JSONB_P(in);
4701 
4702  deconstruct_array(path, TEXTOID, -1, false, TYPALIGN_INT,
4703  &path_elems, &path_nulls, &path_len);
4704 
4705  if (path_len == 0)
4706  PG_RETURN_JSONB_P(in);
4707 
4708  it = JsonbIteratorInit(&in->root);
4709 
4710  res = setPath(&it, path_elems, path_nulls, path_len, &st,
4711  0, NULL, JB_PATH_DELETE);
4712 
4713  Assert(res != NULL);
4714 
4716 }
Jsonb * JsonbValueToJsonb(JsonbValue *val)
Definition: jsonb_util.c:92
Definition: jsonb.h:220
#define JB_ROOT_COUNT(jbp_)
Definition: jsonb.h:227
int errcode(int sqlerrcode)
Definition: elog.c:698
#define JB_ROOT_IS_SCALAR(jbp_)
Definition: jsonb.h:228
#define PG_GETARG_ARRAYTYPE_P(n)
Definition: array.h:256
#define ERROR
Definition: elog.h:46
JsonbContainer root
Definition: jsonb.h:223
uintptr_t Datum
Definition: postgres.h:411
#define ereport(elevel,...)
Definition: elog.h:157
#define Assert(condition)
Definition: c.h:804
JsonbIterator * JsonbIteratorInit(JsonbContainer *container)
Definition: jsonb_util.c:812
#define ARR_NDIM(a)
Definition: array.h:283
static JsonbValue * setPath(JsonbIterator **it, Datum *path_elems, bool *path_nulls, int path_len, JsonbParseState **st, int level, JsonbValue *newval, int op_type)
Definition: jsonfuncs.c:4900
void deconstruct_array(ArrayType *array, Oid elmtype, int elmlen, bool elmbyval, char elmalign, Datum **elemsp, bool **nullsp, int *nelemsp)
Definition: arrayfuncs.c:3490
int errmsg(const char *fmt,...)
Definition: elog.c:909
#define PG_RETURN_JSONB_P(x)
Definition: jsonb.h:76
#define JB_PATH_DELETE
Definition: jsonfuncs.c:42
#define PG_GETARG_JSONB_P(x)
Definition: jsonb.h:74

◆ jsonb_each()

Datum jsonb_each ( PG_FUNCTION_ARGS  )

Definition at line 1888 of file jsonfuncs.c.

References each_worker_jsonb().

1889 {
1890  return each_worker_jsonb(fcinfo, "jsonb_each", false);
1891 }
static Datum each_worker_jsonb(FunctionCallInfo fcinfo, const char *funcname, bool as_text)
Definition: jsonfuncs.c:1906

◆ jsonb_each_text()

Datum jsonb_each_text ( PG_FUNCTION_ARGS  )

Definition at line 1900 of file jsonfuncs.c.

References each_worker_jsonb().

1901 {
1902  return each_worker_jsonb(fcinfo, "jsonb_each_text", true);
1903 }
static Datum each_worker_jsonb(FunctionCallInfo fcinfo, const char *funcname, bool as_text)
Definition: jsonfuncs.c:1906

◆ jsonb_extract_path()

Datum jsonb_extract_path ( PG_FUNCTION_ARGS  )

Definition at line 1425 of file jsonfuncs.c.

References get_jsonb_path_all().

1426 {
1427  return get_jsonb_path_all(fcinfo, false);
1428 }
static Datum get_jsonb_path_all(FunctionCallInfo fcinfo, bool as_text)
Definition: jsonfuncs.c:1437

◆ jsonb_extract_path_text()

Datum jsonb_extract_path_text ( PG_FUNCTION_ARGS  )

Definition at line 1431 of file jsonfuncs.c.

References get_jsonb_path_all().

1432 {
1433  return get_jsonb_path_all(fcinfo, true);
1434 }
static Datum get_jsonb_path_all(FunctionCallInfo fcinfo, bool as_text)
Definition: jsonfuncs.c:1437

◆ jsonb_get_element()

Datum jsonb_get_element ( Jsonb jb,
Datum path,
int  npath,
bool isnull,
bool  as_text 
)

Definition at line 1469 of file jsonfuncs.c.

References Assert, cstring_to_text(), 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_RETURN_JSONB_P, PointerGetDatum, Jsonb::root, strtoint(), TextDatumGetCString, JsonbValue::type, JsonbValue::val, VARDATA, VARHDRSZ, and VARSIZE.

Referenced by get_jsonb_path_all(), jsonb_subscript_fetch(), and jsonb_subscript_fetch_old().

1470 {
1471  JsonbContainer *container = &jb->root;
1472  JsonbValue *jbvp = NULL;
1473  int i;
1474  bool have_object = false,
1475  have_array = false;
1476 
1477  *isnull = false;
1478 
1479  /* Identify whether we have object, array, or scalar at top-level */
1480  if (JB_ROOT_IS_OBJECT(jb))
1481  have_object = true;
1482  else if (JB_ROOT_IS_ARRAY(jb) && !JB_ROOT_IS_SCALAR(jb))
1483  have_array = true;
1484  else
1485  {
1487  /* Extract the scalar value, if it is what we'll return */
1488  if (npath <= 0)
1489  jbvp = getIthJsonbValueFromContainer(container, 0);
1490  }
1491 
1492  /*
1493  * If the array is empty, return the entire LHS object, on the grounds
1494  * that we should do zero field or element extractions. For the
1495  * non-scalar case we can just hand back the object without much work. For
1496  * the scalar case, fall through and deal with the value below the loop.
1497  * (This inconsistency arises because there's no easy way to generate a
1498  * JsonbValue directly for root-level containers.)
1499  */
1500  if (npath <= 0 && jbvp == NULL)
1501  {
1502  if (as_text)
1503  {
1505  container,
1506  VARSIZE(jb))));
1507  }
1508  else
1509  {
1510  /* not text mode - just hand back the jsonb */
1511  PG_RETURN_JSONB_P(jb);
1512  }
1513  }
1514 
1515  for (i = 0; i < npath; i++)
1516  {
1517  if (have_object)
1518  {
1519  jbvp = getKeyJsonValueFromContainer(container,
1520  VARDATA(path[i]),
1521  VARSIZE(path[i]) - VARHDRSZ,
1522  NULL);
1523  }
1524  else if (have_array)
1525  {
1526  int lindex;
1527  uint32 index;
1528  char *indextext = TextDatumGetCString(path[i]);
1529  char *endptr;
1530 
1531  errno = 0;
1532  lindex = strtoint(indextext, &endptr, 10);
1533  if (endptr == indextext || *endptr != '\0' || errno != 0)
1534  {
1535  *isnull = true;
1536  return PointerGetDatum(NULL);
1537  }
1538 
1539  if (lindex >= 0)
1540  {
1541  index = (uint32) lindex;
1542  }
1543  else
1544  {
1545  /* Handle negative subscript */
1546  uint32 nelements;
1547 
1548  /* Container must be array, but make sure */
1549  if (!JsonContainerIsArray(container))
1550  elog(ERROR, "not a jsonb array");
1551 
1552  nelements = JsonContainerSize(container);
1553 
1554  if (lindex == INT_MIN || -lindex > nelements)
1555  {
1556  *isnull = true;
1557  return PointerGetDatum(NULL);
1558  }
1559  else
1560  index = nelements + lindex;
1561  }
1562 
1563  jbvp = getIthJsonbValueFromContainer(container, index);
1564  }
1565  else
1566  {
1567  /* scalar, extraction yields a null */
1568  *isnull = true;
1569  return PointerGetDatum(NULL);
1570  }
1571 
1572  if (jbvp == NULL)
1573  {
1574  *isnull = true;
1575  return PointerGetDatum(NULL);
1576  }
1577  else if (i == npath - 1)
1578  break;
1579 
1580  if (jbvp->type == jbvBinary)
1581  {
1582  container = jbvp->val.binary.data;
1583  have_object = JsonContainerIsObject(container);
1584  have_array = JsonContainerIsArray(container);
1585  Assert(!JsonContainerIsScalar(container));
1586  }
1587  else
1588  {
1589  Assert(IsAJsonbScalar(jbvp));
1590  have_object = false;
1591  have_array = false;
1592  }
1593  }
1594 
1595  if (as_text)
1596  {
1597  if (jbvp->type == jbvNull)
1598  {
1599  *isnull = true;
1600  return PointerGetDatum(NULL);
1601  }
1602 
1603  return PointerGetDatum(JsonbValueAsText(jbvp));
1604  }
1605  else
1606  {
1607  Jsonb *res = JsonbValueToJsonb(jbvp);
1608 
1609  /* not text mode - just hand back the jsonb */
1610  PG_RETURN_JSONB_P(res);
1611  }
1612 }
#define JB_ROOT_IS_OBJECT(jbp_)
Definition: jsonb.h:229
#define VARDATA(PTR)
Definition: postgres.h:315
Jsonb * JsonbValueToJsonb(JsonbValue *val)
Definition: jsonb_util.c:92
Definition: jsonb.h:220
#define VARSIZE(PTR)
Definition: postgres.h:316
#define PointerGetDatum(X)
Definition: postgres.h:600
#define VARHDRSZ
Definition: c.h:627
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:398
Definition: jsonb.h:236
static text * JsonbValueAsText(JsonbValue *v)
Definition: jsonfuncs.c:1741
#define JB_ROOT_IS_SCALAR(jbp_)
Definition: jsonb.h:228
Definition: type.h:89
#define ERROR
Definition: elog.h:46
#define JB_ROOT_IS_ARRAY(jbp_)
Definition: jsonb.h:230
#define JsonContainerSize(jc)
Definition: jsonb.h:214
unsigned int uint32
Definition: c.h:441
int strtoint(const char *pg_restrict str, char **pg_restrict endptr, int base)
Definition: string.c:50
#define JsonContainerIsArray(jc)
Definition: jsonb.h:217
JsonbContainer root
Definition: jsonb.h:223
#define TextDatumGetCString(d)
Definition: builtins.h:83
#define JsonContainerIsObject(jc)
Definition: jsonb.h:216
text * cstring_to_text(const char *s)
Definition: varlena.c:190
JsonbValue * getIthJsonbValueFromContainer(JsonbContainer *container, uint32 i)
Definition: jsonb_util.c:468
#define Assert(condition)
Definition: c.h:804
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
#define elog(elevel,...)
Definition: elog.h:232
int i
#define PG_RETURN_JSONB_P(x)
Definition: jsonb.h:76

◆ jsonb_insert()