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

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

Referenced by json_array_length().

1865 {
1866  AlenState *_state = (AlenState *) state;
1867 
1868  /* just count up all the level 1 elements */
1869  if (_state->lex->lex_level == 1)
1870  _state->count++;
1871 }
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 1840 of file jsonfuncs.c.

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

Referenced by json_array_length().

1841 {
1842  AlenState *_state = (AlenState *) state;
1843 
1844  /* json structure check */
1845  if (_state->lex->lex_level == 0)
1846  ereport(ERROR,
1847  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1848  errmsg("cannot get array length of a non-array")));
1849 }
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 1852 of file jsonfuncs.c.

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

Referenced by json_array_length().

1853 {
1854  AlenState *_state = (AlenState *) state;
1855 
1856  /* json structure check */
1857  if (_state->lex->lex_level == 0)
1858  ereport(ERROR,
1859  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1860  errmsg("cannot get array length of a scalar")));
1861 }
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 3251 of file jsonfuncs.c.

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

Referenced by populate_record().

3252 {
3253  RecordIOData *data = (RecordIOData *)
3254  MemoryContextAlloc(mcxt,
3255  offsetof(RecordIOData, columns) +
3256  ncolumns * sizeof(ColumnIOData));
3257 
3258  data->record_type = InvalidOid;
3259  data->record_typmod = 0;
3260  data->ncolumns = ncolumns;
3261  MemSet(data->columns, 0, sizeof(ColumnIOData) * ncolumns);
3262 
3263  return data;
3264 }
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 2156 of file jsonfuncs.c.

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

Referenced by each_worker().

2157 {
2158  EachState *_state = (EachState *) state;
2159 
2160  /* json structure check */
2161  if (_state->lex->lex_level == 0)
2162  ereport(ERROR,
2163  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2164  errmsg("cannot deconstruct an array as an object")));
2165 }
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 2110 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().

2111 {
2112  EachState *_state = (EachState *) state;
2113  MemoryContext old_cxt;
2114  int len;
2115  text *val;
2116  HeapTuple tuple;
2117  Datum values[2];
2118  bool nulls[2] = {false, false};
2119 
2120  /* skip over nested objects */
2121  if (_state->lex->lex_level != 1)
2122  return;
2123 
2124  /* use the tmp context so we can clean up after each tuple is done */
2125  old_cxt = MemoryContextSwitchTo(_state->tmp_cxt);
2126 
2127  values[0] = CStringGetTextDatum(fname);
2128 
2129  if (isnull && _state->normalize_results)
2130  {
2131  nulls[1] = true;
2132  values[1] = (Datum) 0;
2133  }
2134  else if (_state->next_scalar)
2135  {
2136  values[1] = CStringGetTextDatum(_state->normalized_scalar);
2137  _state->next_scalar = false;
2138  }
2139  else
2140  {
2141  len = _state->lex->prev_token_terminator - _state->result_start;
2142  val = cstring_to_text_with_len(_state->result_start, len);
2143  values[1] = PointerGetDatum(val);
2144  }
2145 
2146  tuple = heap_form_tuple(_state->ret_tdesc, values, nulls);
2147 
2148  tuplestore_puttuple(_state->tuple_store, tuple);
2149 
2150  /* clean up and switch back */
2151  MemoryContextSwitchTo(old_cxt);
2152  MemoryContextReset(_state->tmp_cxt);
2153 }
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:201
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:156
#define CStringGetTextDatum(s)
Definition: builtins.h:86
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 2090 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().

2091 {
2092  EachState *_state = (EachState *) state;
2093 
2094  /* save a pointer to where the value starts */
2095  if (_state->lex->lex_level == 1)
2096  {
2097  /*
2098  * next_scalar will be reset in the object_field_end handler, and
2099  * since we know the value is a scalar there is no danger of it being
2100  * on while recursing down the tree.
2101  */
2102  if (_state->normalize_results && _state->lex->token_type == JSON_TOKEN_STRING)
2103  _state->next_scalar = true;
2104  else
2105  _state->result_start = _state->lex->token_start;
2106  }
2107 }
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 2168 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().

2169 {
2170  EachState *_state = (EachState *) state;
2171 
2172  /* json structure check */
2173  if (_state->lex->lex_level == 0)
2174  ereport(ERROR,
2175  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2176  errmsg("cannot deconstruct a scalar")));
2177 
2178  /* supply de-escaped value if required */
2179  if (_state->next_scalar)
2180  _state->normalized_scalar = token;
2181 }
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 2026 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().

2027 {
2028  text *json = PG_GETARG_TEXT_PP(0);
2029  JsonLexContext *lex;
2030  JsonSemAction *sem;
2031  ReturnSetInfo *rsi;
2032  MemoryContext old_cxt;
2033  TupleDesc tupdesc;
2034  EachState *state;
2035 
2036  lex = makeJsonLexContext(json, true);
2037  state = palloc0(sizeof(EachState));
2038  sem = palloc0(sizeof(JsonSemAction));
2039 
2040  rsi = (ReturnSetInfo *) fcinfo->resultinfo;
2041 
2042  if (!rsi || !IsA(rsi, ReturnSetInfo) ||
2043  (rsi->allowedModes & SFRM_Materialize) == 0 ||
2044  rsi->expectedDesc == NULL)
2045  ereport(ERROR,
2046  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2047  errmsg("set-valued function called in context that "
2048  "cannot accept a set")));
2049 
2051 
2052  (void) get_call_result_type(fcinfo, NULL, &tupdesc);
2053 
2054  /* make these in a sufficiently long-lived memory context */
2056 
2057  state->ret_tdesc = CreateTupleDescCopy(tupdesc);
2058  BlessTupleDesc(state->ret_tdesc);
2059  state->tuple_store =
2061  false, work_mem);
2062 
2063  MemoryContextSwitchTo(old_cxt);
2064 
2065  sem->semstate = (void *) state;
2067  sem->scalar = each_scalar;
2070 
2071  state->normalize_results = as_text;
2072  state->next_scalar = false;
2073  state->lex = lex;
2075  "json_each temporary cxt",
2077 
2078  pg_parse_json_or_ereport(lex, sem);
2079 
2080  MemoryContextDelete(state->tmp_cxt);
2081 
2082  rsi->setResult = state->tuple_store;
2083  rsi->setDesc = state->ret_tdesc;
2084 
2085  PG_RETURN_NULL();
2086 }
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
Definition: tupdesc.c:111
#define IsA(nodeptr, _type_)
Definition: nodes.h:587
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:2090
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:2156
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:2168
TupleDesc expectedDesc
Definition: execnodes.h:305
#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:306
SetFunctionReturnMode returnMode
Definition: execnodes.h:308
json_struct_action array_start
Definition: jsonapi.h:109
Definition: regguts.h:317
MemoryContext ecxt_per_query_memory
Definition: execnodes.h:234
Tuplestorestate * setResult
Definition: execnodes.h:311
ExprContext * econtext
Definition: execnodes.h:304
TupleDesc setDesc
Definition: execnodes.h:312
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:2110
#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 1908 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().

1909 {
1910  Jsonb *jb = PG_GETARG_JSONB_P(0);
1911  ReturnSetInfo *rsi;
1912  Tuplestorestate *tuple_store;
1913  TupleDesc tupdesc;
1914  TupleDesc ret_tdesc;
1915  MemoryContext old_cxt,
1916  tmp_cxt;
1917  bool skipNested = false;
1918  JsonbIterator *it;
1919  JsonbValue v;
1921 
1922  if (!JB_ROOT_IS_OBJECT(jb))
1923  ereport(ERROR,
1924  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1925  errmsg("cannot call %s on a non-object",
1926  funcname)));
1927 
1928  rsi = (ReturnSetInfo *) fcinfo->resultinfo;
1929 
1930  if (!rsi || !IsA(rsi, ReturnSetInfo) ||
1931  (rsi->allowedModes & SFRM_Materialize) == 0 ||
1932  rsi->expectedDesc == NULL)
1933  ereport(ERROR,
1934  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1935  errmsg("set-valued function called in context that "
1936  "cannot accept a set")));
1937 
1939 
1940  if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
1941  ereport(ERROR,
1942  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1943  errmsg("function returning record called in context "
1944  "that cannot accept type record")));
1945 
1947 
1948  ret_tdesc = CreateTupleDescCopy(tupdesc);
1949  BlessTupleDesc(ret_tdesc);
1950  tuple_store =
1952  false, work_mem);
1953 
1954  MemoryContextSwitchTo(old_cxt);
1955 
1957  "jsonb_each temporary cxt",
1959 
1960  it = JsonbIteratorInit(&jb->root);
1961 
1962  while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE)
1963  {
1964  skipNested = true;
1965 
1966  if (r == WJB_KEY)
1967  {
1968  text *key;
1969  HeapTuple tuple;
1970  Datum values[2];
1971  bool nulls[2] = {false, false};
1972 
1973  /* Use the tmp context so we can clean up after each tuple is done */
1974  old_cxt = MemoryContextSwitchTo(tmp_cxt);
1975 
1976  key = cstring_to_text_with_len(v.val.string.val, v.val.string.len);
1977 
1978  /*
1979  * The next thing the iterator fetches should be the value, no
1980  * matter what shape it is.
1981  */
1982  r = JsonbIteratorNext(&it, &v, skipNested);
1983  Assert(r != WJB_DONE);
1984 
1985  values[0] = PointerGetDatum(key);
1986 
1987  if (as_text)
1988  {
1989  if (v.type == jbvNull)
1990  {
1991  /* a json null is an sql null in text mode */
1992  nulls[1] = true;
1993  values[1] = (Datum) NULL;
1994  }
1995  else
1996  values[1] = PointerGetDatum(JsonbValueAsText(&v));
1997  }
1998  else
1999  {
2000  /* Not in text mode, just return the Jsonb */
2001  Jsonb *val = JsonbValueToJsonb(&v);
2002 
2003  values[1] = PointerGetDatum(val);
2004  }
2005 
2006  tuple = heap_form_tuple(ret_tdesc, values, nulls);
2007 
2008  tuplestore_puttuple(tuple_store, tuple);
2009 
2010  /* clean up and switch back */
2011  MemoryContextSwitchTo(old_cxt);
2012  MemoryContextReset(tmp_cxt);
2013  }
2014  }
2015 
2016  MemoryContextDelete(tmp_cxt);
2017 
2018  rsi->setResult = tuple_store;
2019  rsi->setDesc = ret_tdesc;
2020 
2021  PG_RETURN_NULL();
2022 }
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
Definition: tupdesc.c:111
#define IsA(nodeptr, _type_)
Definition: nodes.h:587
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:1743
TupleDesc expectedDesc
Definition: execnodes.h:305
#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:201
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:306
SetFunctionReturnMode returnMode
Definition: execnodes.h:308
#define Assert(condition)
Definition: c.h:804
JsonbIterator * JsonbIteratorInit(JsonbContainer *container)
Definition: jsonb_util.c:812
MemoryContext ecxt_per_query_memory
Definition: execnodes.h:234
enum jbvType type
Definition: jsonb.h:263
Tuplestorestate * setResult
Definition: execnodes.h:311
static Datum values[MAXATTR]
Definition: bootstrap.c:156
ExprContext * econtext
Definition: execnodes.h:304
TupleDesc setDesc
Definition: execnodes.h:312
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 2408 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().

2409 {
2410  ElementsState *_state = (ElementsState *) state;
2411  MemoryContext old_cxt;
2412  int len;
2413  text *val;
2414  HeapTuple tuple;
2415  Datum values[1];
2416  bool nulls[1] = {false};
2417 
2418  /* skip over nested objects */
2419  if (_state->lex->lex_level != 1)
2420  return;
2421 
2422  /* use the tmp context so we can clean up after each tuple is done */
2423  old_cxt = MemoryContextSwitchTo(_state->tmp_cxt);
2424 
2425  if (isnull && _state->normalize_results)
2426  {
2427  nulls[0] = true;
2428  values[0] = (Datum) NULL;
2429  }
2430  else if (_state->next_scalar)
2431  {
2432  values[0] = CStringGetTextDatum(_state->normalized_scalar);
2433  _state->next_scalar = false;
2434  }
2435  else
2436  {
2437  len = _state->lex->prev_token_terminator - _state->result_start;
2438  val = cstring_to_text_with_len(_state->result_start, len);
2439  values[0] = PointerGetDatum(val);
2440  }
2441 
2442  tuple = heap_form_tuple(_state->ret_tdesc, values, nulls);
2443 
2444  tuplestore_puttuple(_state->tuple_store, tuple);
2445 
2446  /* clean up and switch back */
2447  MemoryContextSwitchTo(old_cxt);
2448  MemoryContextReset(_state->tmp_cxt);
2449 }
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:201
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:156
char * normalized_scalar
Definition: jsonfuncs.c:129
#define CStringGetTextDatum(s)
Definition: builtins.h:86
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 2388 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().

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

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

Referenced by elements_worker().

2453 {
2454  ElementsState *_state = (ElementsState *) state;
2455 
2456  /* json structure check */
2457  if (_state->lex->lex_level == 0)
2458  ereport(ERROR,
2459  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2460  errmsg("cannot call %s on a non-array",
2461  _state->function_name)));
2462 }
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 2465 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().

2466 {
2467  ElementsState *_state = (ElementsState *) state;
2468 
2469  /* json structure check */
2470  if (_state->lex->lex_level == 0)
2471  ereport(ERROR,
2472  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2473  errmsg("cannot call %s on a scalar",
2474  _state->function_name)));
2475 
2476  /* supply de-escaped value if required */
2477  if (_state->next_scalar)
2478  _state->normalized_scalar = token;
2479 }
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 2322 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().

2323 {
2324  text *json = PG_GETARG_TEXT_PP(0);
2325 
2326  /* elements only needs escaped strings when as_text */
2327  JsonLexContext *lex = makeJsonLexContext(json, as_text);
2328  JsonSemAction *sem;
2329  ReturnSetInfo *rsi;
2330  MemoryContext old_cxt;
2331  TupleDesc tupdesc;
2333 
2334  state = palloc0(sizeof(ElementsState));
2335  sem = palloc0(sizeof(JsonSemAction));
2336 
2337  rsi = (ReturnSetInfo *) fcinfo->resultinfo;
2338 
2339  if (!rsi || !IsA(rsi, ReturnSetInfo) ||
2340  (rsi->allowedModes & SFRM_Materialize) == 0 ||
2341  rsi->expectedDesc == NULL)
2342  ereport(ERROR,
2343  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2344  errmsg("set-valued function called in context that "
2345  "cannot accept a set")));
2346 
2348 
2349  /* it's a simple type, so don't use get_call_result_type() */
2350  tupdesc = rsi->expectedDesc;
2351 
2352  /* make these in a sufficiently long-lived memory context */
2354 
2355  state->ret_tdesc = CreateTupleDescCopy(tupdesc);
2356  BlessTupleDesc(state->ret_tdesc);
2357  state->tuple_store =
2359  false, work_mem);
2360 
2361  MemoryContextSwitchTo(old_cxt);
2362 
2363  sem->semstate = (void *) state;
2365  sem->scalar = elements_scalar;
2368 
2369  state->function_name = funcname;
2370  state->normalize_results = as_text;
2371  state->next_scalar = false;
2372  state->lex = lex;
2374  "json_array_elements temporary cxt",
2376 
2377  pg_parse_json_or_ereport(lex, sem);
2378 
2379  MemoryContextDelete(state->tmp_cxt);
2380 
2381  rsi->setResult = state->tuple_store;
2382  rsi->setDesc = state->ret_tdesc;
2383 
2384  PG_RETURN_NULL();
2385 }
bool normalize_results
Definition: jsonfuncs.c:127
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
Definition: tupdesc.c:111
#define IsA(nodeptr, _type_)
Definition: nodes.h:587
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:2452
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:305
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:2388
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:2408
void * palloc0(Size size)
Definition: mcxt.c:1093
static void elements_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:2465
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:306
SetFunctionReturnMode returnMode
Definition: execnodes.h:308
Definition: regguts.h:317
MemoryContext ecxt_per_query_memory
Definition: execnodes.h:234
Tuplestorestate * setResult
Definition: execnodes.h:311
ExprContext * econtext
Definition: execnodes.h:304
TupleDesc setDesc
Definition: execnodes.h:312
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 2204 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().

2206 {
2207  Jsonb *jb = PG_GETARG_JSONB_P(0);
2208  ReturnSetInfo *rsi;
2209  Tuplestorestate *tuple_store;
2210  TupleDesc tupdesc;
2211  TupleDesc ret_tdesc;
2212  MemoryContext old_cxt,
2213  tmp_cxt;
2214  bool skipNested = false;
2215  JsonbIterator *it;
2216  JsonbValue v;
2218 
2219  if (JB_ROOT_IS_SCALAR(jb))
2220  ereport(ERROR,
2221  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2222  errmsg("cannot extract elements from a scalar")));
2223  else if (!JB_ROOT_IS_ARRAY(jb))
2224  ereport(ERROR,
2225  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2226  errmsg("cannot extract elements from an object")));
2227 
2228  rsi = (ReturnSetInfo *) fcinfo->resultinfo;
2229 
2230  if (!rsi || !IsA(rsi, ReturnSetInfo) ||
2231  (rsi->allowedModes & SFRM_Materialize) == 0 ||
2232  rsi->expectedDesc == NULL)
2233  ereport(ERROR,
2234  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2235  errmsg("set-valued function called in context that "
2236  "cannot accept a set")));
2237 
2239 
2240  /* it's a simple type, so don't use get_call_result_type() */
2241  tupdesc = rsi->expectedDesc;
2242 
2244 
2245  ret_tdesc = CreateTupleDescCopy(tupdesc);
2246  BlessTupleDesc(ret_tdesc);
2247  tuple_store =
2249  false, work_mem);
2250 
2251  MemoryContextSwitchTo(old_cxt);
2252 
2254  "jsonb_array_elements temporary cxt",
2256 
2257  it = JsonbIteratorInit(&jb->root);
2258 
2259  while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE)
2260  {
2261  skipNested = true;
2262 
2263  if (r == WJB_ELEM)
2264  {
2265  HeapTuple tuple;
2266  Datum values[1];
2267  bool nulls[1] = {false};
2268 
2269  /* use the tmp context so we can clean up after each tuple is done */
2270  old_cxt = MemoryContextSwitchTo(tmp_cxt);
2271 
2272  if (as_text)
2273  {
2274  if (v.type == jbvNull)
2275  {
2276  /* a json null is an sql null in text mode */
2277  nulls[0] = true;
2278  values[0] = (Datum) NULL;
2279  }
2280  else
2281  values[0] = PointerGetDatum(JsonbValueAsText(&v));
2282  }
2283  else
2284  {
2285  /* Not in text mode, just return the Jsonb */
2286  Jsonb *val = JsonbValueToJsonb(&v);
2287 
2288  values[0] = PointerGetDatum(val);
2289  }
2290 
2291  tuple = heap_form_tuple(ret_tdesc, values, nulls);
2292 
2293  tuplestore_puttuple(tuple_store, tuple);
2294 
2295  /* clean up and switch back */
2296  MemoryContextSwitchTo(old_cxt);
2297  MemoryContextReset(tmp_cxt);
2298  }
2299  }
2300 
2301  MemoryContextDelete(tmp_cxt);
2302 
2303  rsi->setResult = tuple_store;
2304  rsi->setDesc = ret_tdesc;
2305 
2306  PG_RETURN_NULL();
2307 }
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
Definition: tupdesc.c:111
#define IsA(nodeptr, _type_)
Definition: nodes.h:587
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:1743
#define JB_ROOT_IS_SCALAR(jbp_)
Definition: jsonb.h:228
TupleDesc expectedDesc
Definition: execnodes.h:305
#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:306
SetFunctionReturnMode returnMode
Definition: execnodes.h:308
JsonbIterator * JsonbIteratorInit(JsonbContainer *container)
Definition: jsonb_util.c:812
MemoryContext ecxt_per_query_memory
Definition: execnodes.h:234
enum jbvType type
Definition: jsonb.h:263
Tuplestorestate * setResult
Definition: execnodes.h:311
static Datum values[MAXATTR]
Definition: bootstrap.c:156
ExprContext * econtext
Definition: execnodes.h:304
TupleDesc setDesc
Definition: execnodes.h:312
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 1344 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().

1345 {
1346  GetState *_state = (GetState *) state;
1347  bool get_last = false;
1348  int lex_level = _state->lex->lex_level;
1349 
1350  /* same tests as in get_array_element_start */
1351  if (lex_level <= _state->npath &&
1352  _state->pathok[lex_level - 1] &&
1353  _state->path_indexes != NULL &&
1354  _state->array_cur_index[lex_level - 1] == _state->path_indexes[lex_level - 1])
1355  {
1356  if (lex_level < _state->npath)
1357  {
1358  /* done with this element so reset pathok */
1359  _state->pathok[lex_level] = false;
1360  }
1361  else
1362  {
1363  /* end of path, so we want this value */
1364  get_last = true;
1365  }
1366  }
1367 
1368  /* same logic as for objects */
1369  if (get_last && _state->result_start != NULL)
1370  {
1371  if (isnull && _state->normalize_results)
1372  _state->tresult = (text *) NULL;
1373  else
1374  {
1375  char *start = _state->result_start;
1376  int len = _state->lex->prev_token_terminator - start;
1377 
1378  _state->tresult = cstring_to_text_with_len(start, len);
1379  }
1380 
1381  _state->result_start = NULL;
1382  }
1383 }
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:201
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 1298 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().

1299 {
1300  GetState *_state = (GetState *) state;
1301  bool get_next = false;
1302  int lex_level = _state->lex->lex_level;
1303 
1304  /* Update array element counter */
1305  if (lex_level <= _state->npath)
1306  _state->array_cur_index[lex_level - 1]++;
1307 
1308  if (lex_level <= _state->npath &&
1309  _state->pathok[lex_level - 1] &&
1310  _state->path_indexes != NULL &&
1311  _state->array_cur_index[lex_level - 1] == _state->path_indexes[lex_level - 1])
1312  {
1313  if (lex_level < _state->npath)
1314  {
1315  /* if not at end of path just mark path ok */
1316  _state->pathok[lex_level] = true;
1317  }
1318  else
1319  {
1320  /* end of path, so we want this value */
1321  get_next = true;
1322  }
1323  }
1324 
1325  /* same logic as for objects */
1326  if (get_next)
1327  {
1328  _state->tresult = NULL;
1329  _state->result_start = NULL;
1330 
1331  if (_state->normalize_results &&
1332  _state->lex->token_type == JSON_TOKEN_STRING)
1333  {
1334  _state->next_scalar = true;
1335  }
1336  else
1337  {
1338  _state->result_start = _state->lex->token_start;
1339  }
1340  }
1341 }
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 1282 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().

1283 {
1284  GetState *_state = (GetState *) state;
1285  int lex_level = _state->lex->lex_level;
1286 
1287  if (lex_level == 0 && _state->npath == 0)
1288  {
1289  /* Special case: return the entire array */
1290  char *start = _state->result_start;
1291  int len = _state->lex->prev_token_terminator - start;
1292 
1293  _state->tresult = cstring_to_text_with_len(start, len);
1294  }
1295 }
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:201
int npath
Definition: jsonfuncs.c:90
Definition: regguts.h:317

◆ get_array_start()

static void get_array_start ( void *  state)
static

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

1245 {
1246  GetState *_state = (GetState *) state;
1247  int lex_level = _state->lex->lex_level;
1248 
1249  if (lex_level < _state->npath)
1250  {
1251  /* Initialize counting of elements in this array */
1252  _state->array_cur_index[lex_level] = -1;
1253 
1254  /* INT_MIN value is reserved to represent invalid subscript */
1255  if (_state->path_indexes[lex_level] < 0 &&
1256  _state->path_indexes[lex_level] != INT_MIN)
1257  {
1258  /* Negative subscript -- convert to positive-wise subscript */
1260  int nelements;
1261 
1262  error = json_count_array_elements(_state->lex, &nelements);
1263  if (error != JSON_SUCCESS)
1264  json_ereport_error(error, _state->lex);
1265 
1266  if (-_state->path_indexes[lex_level] <= nelements)
1267  _state->path_indexes[lex_level] += nelements;
1268  }
1269  }
1270  else if (lex_level == 0 && _state->npath == 0)
1271  {
1272  /*
1273  * Special case: we should match the entire array. We only need this
1274  * at the outermost level because at nested levels the match will have
1275  * been started by the outer field or array element callback.
1276  */
1277  _state->result_start = _state->lex->token_start;
1278  }
1279 }
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 3576 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().

3577 {
3578  HASHCTL ctl;
3579  HTAB *tab;
3580  JHashState *state;
3582  JsonSemAction *sem;
3583 
3584  ctl.keysize = NAMEDATALEN;
3585  ctl.entrysize = sizeof(JsonHashEntry);
3586  ctl.hcxt = CurrentMemoryContext;
3587  tab = hash_create("json object hashtable",
3588  100,
3589  &ctl,
3591 
3592  state = palloc0(sizeof(JHashState));
3593  sem = palloc0(sizeof(JsonSemAction));
3594 
3595  state->function_name = funcname;
3596  state->hash = tab;
3597  state->lex = lex;
3598 
3599  sem->semstate = (void *) state;
3601  sem->scalar = hash_scalar;
3604 
3605  pg_parse_json_or_ereport(lex, sem);
3606 
3607  return tab;
3608 }
#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:3635
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:3611
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:3695
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:3684

◆ get_jsonb_path_all()

static Datum get_jsonb_path_all ( FunctionCallInfo  fcinfo,
bool  as_text 
)
static

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

1440 {
1441  Jsonb *jb = PG_GETARG_JSONB_P(0);
1442  ArrayType *path = PG_GETARG_ARRAYTYPE_P(1);
1443  Datum *pathtext;
1444  bool *pathnulls;
1445  bool isnull;
1446  int npath;
1447  Datum res;
1448 
1449  /*
1450  * If the array contains any null elements, return NULL, on the grounds
1451  * that you'd have gotten NULL if any RHS value were NULL in a nested
1452  * series of applications of the -> operator. (Note: because we also
1453  * return NULL for error cases such as no-such-field, this is true
1454  * regardless of the contents of the rest of the array.)
1455  */
1456  if (array_contains_nulls(path))
1457  PG_RETURN_NULL();
1458 
1459  deconstruct_array(path, TEXTOID, -1, false, TYPALIGN_INT,
1460  &pathtext, &pathnulls, &npath);
1461 
1462  res = jsonb_get_element(jb, pathtext, npath, &isnull, as_text);
1463 
1464  if (isnull)
1465  PG_RETURN_NULL();
1466  else
1467  PG_RETURN_DATUM(res);
1468 }
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:1471
void deconstruct_array(ArrayType *array, Oid elmtype, int elmlen, bool elmbyval, char elmalign, Datum **elemsp, bool **nullsp, int *nelemsp)
Definition: arrayfuncs.c:3491
bool array_contains_nulls(ArrayType *array)
Definition: arrayfuncs.c:3558
#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 1134 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().

1135 {
1136  GetState *_state = (GetState *) state;
1137  int lex_level = _state->lex->lex_level;
1138 
1139  if (lex_level == 0 && _state->npath == 0)
1140  {
1141  /* Special case: return the entire object */
1142  char *start = _state->result_start;
1143  int len = _state->lex->prev_token_terminator - start;
1144 
1145  _state->tresult = cstring_to_text_with_len(start, len);
1146  }
1147 }
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:201
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 1195 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().

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

1151 {
1152  GetState *_state = (GetState *) state;
1153  bool get_next = false;
1154  int lex_level = _state->lex->lex_level;
1155 
1156  if (lex_level <= _state->npath &&
1157  _state->pathok[lex_level - 1] &&
1158  _state->path_names != NULL &&
1159  _state->path_names[lex_level - 1] != NULL &&
1160  strcmp(fname, _state->path_names[lex_level - 1]) == 0)
1161  {
1162  if (lex_level < _state->npath)
1163  {
1164  /* if not at end of path just mark path ok */
1165  _state->pathok[lex_level] = true;
1166  }
1167  else
1168  {
1169  /* end of path, so we want this value */
1170  get_next = true;
1171  }
1172  }
1173 
1174  if (get_next)
1175  {
1176  /* this object overrides any previous matching object */
1177  _state->tresult = NULL;
1178  _state->result_start = NULL;
1179 
1180  if (_state->normalize_results &&
1181  _state->lex->token_type == JSON_TOKEN_STRING)
1182  {
1183  /* for as_text variants, tell get_scalar to set it for us */
1184  _state->next_scalar = true;
1185  }
1186  else
1187  {
1188  /* for non-as_text variants, just note the json starting point */
1189  _state->result_start = _state->lex->token_start;
1190  }
1191  }
1192 }
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 1117 of file jsonfuncs.c.

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

Referenced by get_worker().

1118 {
1119  GetState *_state = (GetState *) state;
1120  int lex_level = _state->lex->lex_level;
1121 
1122  if (lex_level == 0 && _state->npath == 0)
1123  {
1124  /*
1125  * Special case: we should match the entire object. We only need this
1126  * at outermost level because at nested levels the match will have
1127  * been started by the outer field or array element callback.
1128  */
1129  _state->result_start = _state->lex->token_start;
1130  }
1131 }
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 981 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().

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

3411 {
3412  cache->argtype = get_fn_expr_argtype(fcinfo->flinfo, 0);
3413  prepare_column_cache(&cache->c,
3414  cache->argtype, -1,
3415  cache->fn_mcxt, false);
3416  if (cache->c.typcat != TYPECAT_COMPOSITE &&
3417  cache->c.typcat != TYPECAT_COMPOSITE_DOMAIN)
3418  ereport(ERROR,
3419  (errcode(ERRCODE_DATATYPE_MISMATCH),
3420  /* translator: %s is a function name, eg json_to_record */
3421  errmsg("first argument of %s must be a row type",
3422  funcname)));
3423 }
static void prepare_column_cache(ColumnIOData *column, Oid typid, int32 typmod, MemoryContext mcxt, bool need_scalar)
Definition: jsonfuncs.c:3099
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 3434 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().

3437 {
3438  TupleDesc tupdesc;
3439  MemoryContext old_cxt;
3440 
3441  if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
3442  ereport(ERROR,
3443  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3444  /* translator: %s is a function name, eg json_to_record */
3445  errmsg("could not determine row type for result of %s",
3446  funcname),
3447  errhint("Provide a non-null record argument, "
3448  "or call the function in the FROM clause "
3449  "using a column definition list.")));
3450 
3451  Assert(tupdesc);
3452  cache->argtype = tupdesc->tdtypeid;
3453 
3454  /* If we go through this more than once, avoid memory leak */
3455  if (cache->c.io.composite.tupdesc)
3457 
3458  /* Save identified tupdesc */
3459  old_cxt = MemoryContextSwitchTo(cache->fn_mcxt);
3460  cache->c.io.composite.tupdesc = CreateTupleDescCopy(tupdesc);
3461  cache->c.io.composite.base_typid = tupdesc->tdtypeid;
3462  cache->c.io.composite.base_typmod = tupdesc->tdtypmod;
3463  MemoryContextSwitchTo(old_cxt);
3464 }
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 1386 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().

1387 {
1388  GetState *_state = (GetState *) state;
1389  int lex_level = _state->lex->lex_level;
1390 
1391  /* Check for whole-object match */
1392  if (lex_level == 0 && _state->npath == 0)
1393  {
1394  if (_state->normalize_results && tokentype == JSON_TOKEN_STRING)
1395  {
1396  /* we want the de-escaped string */
1397  _state->next_scalar = true;
1398  }
1399  else if (_state->normalize_results && tokentype == JSON_TOKEN_NULL)
1400  {
1401  _state->tresult = (text *) NULL;
1402  }
1403  else
1404  {
1405  /*
1406  * This is a bit hokey: we will suppress whitespace after the
1407  * scalar token, but not whitespace before it. Probably not worth
1408  * doing our own space-skipping to avoid that.
1409  */
1410  char *start = _state->lex->input;
1411  int len = _state->lex->prev_token_terminator - start;
1412 
1413  _state->tresult = cstring_to_text_with_len(start, len);
1414  }
1415  }
1416 
1417  if (_state->next_scalar)
1418  {
1419  /* a de-escaped text value is wanted, so supply it */
1420  _state->tresult = cstring_to_text(token);
1421  /* make sure the next call to get_scalar doesn't overwrite it */
1422  _state->next_scalar = false;
1423  }
1424 }
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:201
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:189
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 1061 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().

1066 {
1067  JsonLexContext *lex = makeJsonLexContext(json, true);
1068  JsonSemAction *sem = palloc0(sizeof(JsonSemAction));
1069  GetState *state = palloc0(sizeof(GetState));
1070 
1071  Assert(npath >= 0);
1072 
1073  state->lex = lex;
1074  /* is it "_as_text" variant? */
1075  state->normalize_results = normalize_results;
1076  state->npath = npath;
1077  state->path_names = tpath;
1078  state->path_indexes = ipath;
1079  state->pathok = palloc0(sizeof(bool) * npath);
1080  state->array_cur_index = palloc(sizeof(int) * npath);
1081 
1082  if (npath > 0)
1083  state->pathok[0] = true;
1084 
1085  sem->semstate = (void *) state;
1086 
1087  /*
1088  * Not all variants need all the semantic routines. Only set the ones that
1089  * are actually needed for maximum efficiency.
1090  */
1091  sem->scalar = get_scalar;
1092  if (npath == 0)
1093  {
1095  sem->object_end = get_object_end;
1097  sem->array_end = get_array_end;
1098  }
1099  if (tpath != NULL)
1100  {
1103  }
1104  if (ipath != NULL)
1105  {
1109  }
1110 
1111  pg_parse_json_or_ereport(lex, sem);
1112 
1113  return state->tresult;
1114 }
json_struct_action array_end
Definition: jsonapi.h:110
static void get_array_end(void *state)
Definition: jsonfuncs.c:1282
int * array_cur_index
Definition: jsonfuncs.c:94
static void get_array_element_start(void *state, bool isnull)
Definition: jsonfuncs.c:1298
json_struct_action object_end
Definition: jsonapi.h:108
static void get_object_start(void *state)
Definition: jsonfuncs.c:1117
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:1195
JsonLexContext * lex
Definition: jsonfuncs.c:85
static void get_object_end(void *state)
Definition: jsonfuncs.c:1134
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:1344
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:1386
void * palloc0(Size size)
Definition: mcxt.c:1093
static void get_array_start(void *state)
Definition: jsonfuncs.c:1244
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:1150
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 3684 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().

3685 {
3686  JHashState *_state = (JHashState *) state;
3687 
3688  if (_state->lex->lex_level == 0)
3689  ereport(ERROR,
3690  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3691  errmsg("cannot call %s on an array", _state->function_name)));
3692 }
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 3635 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().

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

3612 {
3613  JHashState *_state = (JHashState *) state;
3614 
3615  if (_state->lex->lex_level > 1)
3616  return;
3617 
3618  /* remember token type */
3619  _state->saved_token_type = _state->lex->token_type;
3620 
3621  if (_state->lex->token_type == JSON_TOKEN_ARRAY_START ||
3623  {
3624  /* remember start position of the whole text of the subobject */
3625  _state->save_json_start = _state->lex->token_start;
3626  }
3627  else
3628  {
3629  /* must be a scalar */
3630  _state->save_json_start = NULL;
3631  }
3632 }
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 3695 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().

3696 {
3697  JHashState *_state = (JHashState *) state;
3698 
3699  if (_state->lex->lex_level == 0)
3700  ereport(ERROR,
3701  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3702  errmsg("cannot call %s on a scalar", _state->function_name)));
3703 
3704  if (_state->lex->lex_level == 1)
3705  {
3706  _state->saved_scalar = token;
3707  /* saved_token_type must already be set in hash_object_field_start() */
3708  Assert(_state->saved_token_type == tokentype);
3709  }
3710 }
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 5424 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().

5426 {
5427  JsonLexContext *lex = makeJsonLexContext(json, true);
5428  JsonSemAction *sem = palloc0(sizeof(JsonSemAction));
5430 
5431  state->lex = lex;
5432  state->action = action;
5433  state->action_state = action_state;
5434  state->flags = flags;
5435 
5436  sem->semstate = (void *) state;
5439 
5440  pg_parse_json_or_ereport(lex, sem);
5441 }
JsonIterateStringValuesAction action
Definition: jsonfuncs.c:65
static void iterate_values_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:5448
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:5474
void * semstate
Definition: jsonapi.h:106

◆ iterate_jsonb_values()

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

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

5358 {
5359  JsonbIterator *it;
5360  JsonbValue v;
5362 
5363  it = JsonbIteratorInit(&jb->root);
5364 
5365  /*
5366  * Just recursively iterating over jsonb and call callback on all
5367  * corresponding elements
5368  */
5369  while ((type = JsonbIteratorNext(&it, &v, false)) != WJB_DONE)
5370  {
5371  if (type == WJB_KEY)
5372  {
5373  if (flags & jtiKey)
5374  action(state, v.val.string.val, v.val.string.len);
5375 
5376  continue;
5377  }
5378  else if (!(type == WJB_VALUE || type == WJB_ELEM))
5379  {
5380  /* do not call callback for composite JsonbValue */
5381  continue;
5382  }
5383 
5384  /* JsonbValue is a value of object or element of array */
5385  switch (v.type)
5386  {
5387  case jbvString:
5388  if (flags & jtiString)
5389  action(state, v.val.string.val, v.val.string.len);
5390  break;
5391  case jbvNumeric:
5392  if (flags & jtiNumeric)
5393  {
5394  char *val;
5395 
5397  NumericGetDatum(v.val.numeric)));
5398 
5399  action(state, val, strlen(val));
5400  pfree(val);
5401  }
5402  break;
5403  case jbvBool:
5404  if (flags & jtiBool)
5405  {
5406  if (v.val.boolean)
5407  action(state, "true", 4);
5408  else
5409  action(state, "false", 5);
5410  }
5411  break;
5412  default:
5413  /* do not call callback for composite JsonbValue */
5414  break;
5415  }
5416  }
5417 }
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:734
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 5474 of file jsonfuncs.c.

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

Referenced by iterate_json_values().

5475 {
5477 
5478  if (_state->flags & jtiKey)
5479  {
5480  char *val = pstrdup(fname);
5481 
5482  _state->action(_state->action_state, val, strlen(val));
5483  }
5484 }
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 5448 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().

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

◆ IteratorConcat()

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

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

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

3268 {
3269  jsv->is_json = obj->is_json;
3270 
3271  if (jsv->is_json)
3272  {
3273  JsonHashEntry *hashentry = hash_search(obj->val.json_hash, field,
3274  HASH_FIND, NULL);
3275 
3276  jsv->val.json.type = hashentry ? hashentry->type : JSON_TOKEN_NULL;
3277  jsv->val.json.str = jsv->val.json.type == JSON_TOKEN_NULL ? NULL :
3278  hashentry->val;
3279  jsv->val.json.len = jsv->val.json.str ? -1 : 0; /* null-terminated */
3280 
3281  return hashentry != NULL;
3282  }
3283  else
3284  {
3285  jsv->val.jsonb = !obj->val.jsonb_cont ? NULL :
3286  getKeyJsonValueFromContainer(obj->val.jsonb_cont, field, strlen(field),
3287  NULL);
3288 
3289  return jsv->val.jsonb != NULL;
3290  }
3291 }
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 879 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.

880 {
881  text *json = PG_GETARG_TEXT_PP(0);
882  int element = PG_GETARG_INT32(1);
883  text *result;
884 
885  result = get_worker(json, NULL, &element, 1, false);
886 
887  if (result != NULL)
888  PG_RETURN_TEXT_P(result);
889  else
890  PG_RETURN_NULL();
891 }
#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:1061
#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 922 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.

923 {
924  text *json = PG_GETARG_TEXT_PP(0);
925  int element = PG_GETARG_INT32(1);
926  text *result;
927 
928  result = get_worker(json, NULL, &element, 1, true);
929 
930  if (result != NULL)
931  PG_RETURN_TEXT_P(result);
932  else
933  PG_RETURN_NULL();
934 }
#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:1061
#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 2310 of file jsonfuncs.c.

References elements_worker().

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

◆ json_array_elements_text()

Datum json_array_elements_text ( PG_FUNCTION_ARGS  )

Definition at line 2316 of file jsonfuncs.c.

References elements_worker().

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

◆ json_array_length()

Datum json_array_length ( PG_FUNCTION_ARGS  )

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

1791 {
1792  text *json = PG_GETARG_TEXT_PP(0);
1793  AlenState *state;
1794  JsonLexContext *lex;
1795  JsonSemAction *sem;
1796 
1797  lex = makeJsonLexContext(json, false);
1798  state = palloc0(sizeof(AlenState));
1799  sem = palloc0(sizeof(JsonSemAction));
1800 
1801  /* palloc0 does this for us */
1802 #if 0
1803  state->count = 0;
1804 #endif
1805  state->lex = lex;
1806 
1807  sem->semstate = (void *) state;
1809  sem->scalar = alen_scalar;
1811 
1812  pg_parse_json_or_ereport(lex, sem);
1813 
1814  PG_RETURN_INT32(state->count);
1815 }
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:1852
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:1840
Definition: c.h:621
static void alen_array_element_start(void *state, bool isnull)
Definition: jsonfuncs.c:1864
void * semstate
Definition: jsonapi.h:106

◆ json_each()

Datum json_each ( PG_FUNCTION_ARGS  )

Definition at line 1884 of file jsonfuncs.c.

References each_worker().

1885 {
1886  return each_worker(fcinfo, false);
1887 }
static Datum each_worker(FunctionCallInfo fcinfo, bool as_text)
Definition: jsonfuncs.c:2026

◆ json_each_text()

Datum json_each_text ( PG_FUNCTION_ARGS  )

Definition at line 1896 of file jsonfuncs.c.

References each_worker().

1897 {
1898  return each_worker(fcinfo, true);
1899 }
static Datum each_worker(FunctionCallInfo fcinfo, bool as_text)
Definition: jsonfuncs.c:2026

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

References get_path_all().

967 {
968  return get_path_all(fcinfo, false);
969 }
static Datum get_path_all(FunctionCallInfo fcinfo, bool as_text)
Definition: jsonfuncs.c:981

◆ json_extract_path_text()

Datum json_extract_path_text ( PG_FUNCTION_ARGS  )

Definition at line 972 of file jsonfuncs.c.

References get_path_all().

973 {
974  return get_path_all(fcinfo, true);
975 }
static Datum get_path_all(FunctionCallInfo fcinfo, bool as_text)
Definition: jsonfuncs.c:981

◆ json_object_field()

Datum json_object_field ( PG_FUNCTION_ARGS  )

Definition at line 803 of file jsonfuncs.c.

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

804 {
805  text *json = PG_GETARG_TEXT_PP(0);
806  text *fname = PG_GETARG_TEXT_PP(1);
807  char *fnamestr = text_to_cstring(fname);
808  text *result;
809 
810  result = get_worker(json, &fnamestr, NULL, 1, false);
811 
812  if (result != NULL)
813  PG_RETURN_TEXT_P(result);
814  else
815  PG_RETURN_NULL();
816 }
#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:1061
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:372
char * text_to_cstring(const text *t)
Definition: varlena.c:222
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 841 of file jsonfuncs.c.

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

842 {
843  text *json = PG_GETARG_TEXT_PP(0);
844  text *fname = PG_GETARG_TEXT_PP(1);
845  char *fnamestr = text_to_cstring(fname);
846  text *result;
847 
848  result = get_worker(json, &fnamestr, NULL, 1, true);
849 
850  if (result != NULL)
851  PG_RETURN_TEXT_P(result);
852  else
853  PG_RETURN_NULL();
854 }
#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:1061
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:372
char * text_to_cstring(const text *t)
Definition: varlena.c:222
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 693 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.

694 {
695  FuncCallContext *funcctx;
696  OkeysState *state;
697 
698  if (SRF_IS_FIRSTCALL())
699  {
700  text *json = PG_GETARG_TEXT_PP(0);
701  JsonLexContext *lex = makeJsonLexContext(json, true);
702  JsonSemAction *sem;
703  MemoryContext oldcontext;
704 
705  funcctx = SRF_FIRSTCALL_INIT();
706  oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
707 
708  state = palloc(sizeof(OkeysState));
709  sem = palloc0(sizeof(JsonSemAction));
710 
711  state->lex = lex;
712  state->result_size = 256;
713  state->result_count = 0;
714  state->sent_count = 0;
715  state->result = palloc(256 * sizeof(char *));
716 
717  sem->semstate = (void *) state;
719  sem->scalar = okeys_scalar;
721  /* remainder are all NULL, courtesy of palloc0 above */
722 
723  pg_parse_json_or_ereport(lex, sem);
724  /* keys are now in state->result */
725 
726  pfree(lex->strval->data);
727  pfree(lex->strval);
728  pfree(lex);
729  pfree(sem);
730 
731  MemoryContextSwitchTo(oldcontext);
732  funcctx->user_fctx = (void *) state;
733  }
734 
735  funcctx = SRF_PERCALL_SETUP();
736  state = (OkeysState *) funcctx->user_fctx;
737 
738  if (state->sent_count < state->result_count)
739  {
740  char *nxt = state->result[state->sent_count++];
741 
742  SRF_RETURN_NEXT(funcctx, CStringGetTextDatum(nxt));
743  }
744 
745  SRF_RETURN_DONE(funcctx);
746 }
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:770
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:749
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:783
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:86
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 2508 of file jsonfuncs.c.

References populate_record_worker().

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

◆ json_populate_recordset()

Datum json_populate_recordset ( PG_FUNCTION_ARGS  )

Definition at line 3738 of file jsonfuncs.c.

References populate_recordset_worker().

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

◆ json_strip_nulls()

Datum json_strip_nulls ( PG_FUNCTION_ARGS  )

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

4210 {
4211  text *json = PG_GETARG_TEXT_PP(0);
4213  JsonLexContext *lex;
4214  JsonSemAction *sem;
4215 
4216  lex = makeJsonLexContext(json, true);
4217  state = palloc0(sizeof(StripnullState));
4218  sem = palloc0(sizeof(JsonSemAction));
4219 
4220  state->strval = makeStringInfo();
4221  state->skip_next_null = false;
4222  state->lex = lex;
4223 
4224  sem->semstate = (void *) state;
4226  sem->object_end = sn_object_end;
4227  sem->array_start = sn_array_start;
4228  sem->array_end = sn_array_end;
4229  sem->scalar = sn_scalar;
4232 
4233  pg_parse_json_or_ereport(lex, sem);
4234 
4236  state->strval->len));
4237 
4238 }
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:4119
json_struct_action object_end
Definition: jsonapi.h:108
static void sn_array_element_start(void *state, bool isnull)
Definition: jsonfuncs.c:4179
static void sn_object_field_start(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:4151
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:4135
text * cstring_to_text_with_len(const char *s, int len)
Definition: varlena.c:201
JsonLexContext * lex
Definition: jsonfuncs.c:282
static void sn_object_end(void *state)
Definition: jsonfuncs.c:4127
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:4188
#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:4143
void * semstate
Definition: jsonapi.h:106

◆ json_to_record()

Datum json_to_record ( PG_FUNCTION_ARGS  )

Definition at line 2515 of file jsonfuncs.c.

References populate_record_worker().

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

◆ json_to_recordset()

Datum json_to_recordset ( PG_FUNCTION_ARGS  )

Definition at line 3745 of file jsonfuncs.c.

References populate_recordset_worker().

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

◆ jsonb_array_element()

Datum jsonb_array_element ( PG_FUNCTION_ARGS  )

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

895 {
896  Jsonb *jb = PG_GETARG_JSONB_P(0);
897  int element = PG_GETARG_INT32(1);
898  JsonbValue *v;
899 
900  if (!JB_ROOT_IS_ARRAY(jb))
901  PG_RETURN_NULL();
902 
903  /* Handle negative subscript */
904  if (element < 0)
905  {
906  uint32 nelements = JB_ROOT_COUNT(jb);
907 
908  if (-element > nelements)
909  PG_RETURN_NULL();
910  else
911  element += nelements;
912  }
913 
914  v = getIthJsonbValueFromContainer(&jb->root, element);
915  if (v != NULL)
917 
918  PG_RETURN_NULL();
919 }
#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 937 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.

938 {
939  Jsonb *jb = PG_GETARG_JSONB_P(0);
940  int element = PG_GETARG_INT32(1);
941  JsonbValue *v;
942 
943  if (!JB_ROOT_IS_ARRAY(jb))
944  PG_RETURN_NULL();
945 
946  /* Handle negative subscript */
947  if (element < 0)
948  {
949  uint32 nelements = JB_ROOT_COUNT(jb);
950 
951  if (-element > nelements)
952  PG_RETURN_NULL();
953  else
954  element += nelements;
955  }
956 
957  v = getIthJsonbValueFromContainer(&jb->root, element);
958 
959  if (v != NULL && v->type != jbvNull)
961 
962  PG_RETURN_NULL();
963 }
#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:1743
#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 2192 of file jsonfuncs.c.

References elements_worker_jsonb().

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

◆ jsonb_array_elements_text()

Datum jsonb_array_elements_text ( PG_FUNCTION_ARGS  )

Definition at line 2198 of file jsonfuncs.c.

References elements_worker_jsonb().

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

◆ jsonb_array_length()

Datum jsonb_array_length ( PG_FUNCTION_ARGS  )

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

1819 {
1820  Jsonb *jb = PG_GETARG_JSONB_P(0);
1821 
1822  if (JB_ROOT_IS_SCALAR(jb))
1823  ereport(ERROR,
1824  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1825  errmsg("cannot get array length of a scalar")));
1826  else if (!JB_ROOT_IS_ARRAY(jb))
1827  ereport(ERROR,
1828  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1829  errmsg("cannot get array length of a non-array")));
1830 
1832 }
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 4318 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.

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

4360 {
4361  Jsonb *in = PG_GETARG_JSONB_P(0);
4362  text *key = PG_GETARG_TEXT_PP(1);
4363  char *keyptr = VARDATA_ANY(key);
4364  int keylen = VARSIZE_ANY_EXHDR(key);
4365  JsonbParseState *state = NULL;
4366  JsonbIterator *it;
4367  JsonbValue v,
4368  *res = NULL;
4369  bool skipNested = false;
4371 
4372  if (JB_ROOT_IS_SCALAR(in))
4373  ereport(ERROR,
4374  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4375  errmsg("cannot delete from scalar")));
4376 
4377  if (JB_ROOT_COUNT(in) == 0)
4378  PG_RETURN_JSONB_P(in);
4379 
4380  it = JsonbIteratorInit(&in->root);
4381 
4382  while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE)
4383  {
4384  skipNested = true;
4385 
4386  if ((r == WJB_ELEM || r == WJB_KEY) &&
4387  (v.type == jbvString && keylen == v.val.string.len &&
4388  memcmp(keyptr, v.val.string.val, keylen) == 0))
4389  {
4390  /* skip corresponding value as well */
4391  if (r == WJB_KEY)
4392  (void) JsonbIteratorNext(&it, &v, true);
4393 
4394  continue;
4395  }
4396 
4397  res = pushJsonbValue(&state, r, r < WJB_BEGIN_ARRAY ? &v : NULL);
4398  }
4399 
4400  Assert(res != NULL);
4401 
4403 }
#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 4412 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.

4413 {
4414  Jsonb *in = PG_GETARG_JSONB_P(0);
4415  ArrayType *keys = PG_GETARG_ARRAYTYPE_P(1);
4416  Datum *keys_elems;
4417  bool *keys_nulls;
4418  int keys_len;
4419  JsonbParseState *state = NULL;
4420  JsonbIterator *it;
4421  JsonbValue v,
4422  *res = NULL;
4423  bool skipNested = false;
4425 
4426  if (ARR_NDIM(keys) > 1)
4427  ereport(ERROR,
4428  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
4429  errmsg("wrong number of array subscripts")));
4430 
4431  if (JB_ROOT_IS_SCALAR(in))
4432  ereport(ERROR,
4433  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4434  errmsg("cannot delete from scalar")));
4435 
4436  if (JB_ROOT_COUNT(in) == 0)
4437  PG_RETURN_JSONB_P(in);
4438 
4439  deconstruct_array(keys, TEXTOID, -1, false, TYPALIGN_INT,
4440  &keys_elems, &keys_nulls, &keys_len);
4441 
4442  if (keys_len == 0)
4443  PG_RETURN_JSONB_P(in);
4444 
4445  it = JsonbIteratorInit(&in->root);
4446 
4447  while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE)
4448  {
4449  skipNested = true;
4450 
4451  if ((r == WJB_ELEM || r == WJB_KEY) && v.type == jbvString)
4452  {
4453  int i;
4454  bool found = false;
4455 
4456  for (i = 0; i < keys_len; i++)
4457  {
4458  char *keyptr;
4459  int keylen;
4460 
4461  if (keys_nulls[i])
4462  continue;
4463 
4464  keyptr = VARDATA_ANY(keys_elems[i]);
4465  keylen = VARSIZE_ANY_EXHDR(keys_elems[i]);
4466  if (keylen == v.val.string.len &&
4467  memcmp(keyptr, v.val.string.val, keylen) == 0)
4468  {
4469  found = true;
4470  break;
4471  }
4472  }
4473  if (found)
4474  {
4475  /* skip corresponding value as well */
4476  if (r == WJB_KEY)
4477  (void) JsonbIteratorNext(&it, &v, true);
4478 
4479  continue;
4480  }
4481  }
4482 
4483  res = pushJsonbValue(&state, r, r < WJB_BEGIN_ARRAY ? &v : NULL);
4484  }
4485 
4486  Assert(res != NULL);
4487 
4489 }
#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:3491
#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 4499 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.

4500 {
4501  Jsonb *in = PG_GETARG_JSONB_P(0);
4502  int idx = PG_GETARG_INT32(1);
4503  JsonbParseState *state = NULL;
4504  JsonbIterator *it;
4505  uint32 i = 0,
4506  n;
4507  JsonbValue v,
4508  *res = NULL;
4510 
4511  if (JB_ROOT_IS_SCALAR(in))
4512  ereport(ERROR,
4513  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4514  errmsg("cannot delete from scalar")));
4515 
4516  if (JB_ROOT_IS_OBJECT(in))
4517  ereport(ERROR,
4518  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4519  errmsg("cannot delete from object using integer index")));
4520 
4521  if (JB_ROOT_COUNT(in) == 0)
4522  PG_RETURN_JSONB_P(in);
4523 
4524  it = JsonbIteratorInit(&in->root);
4525 
4526  r = JsonbIteratorNext(&it, &v, false);
4527  Assert(r == WJB_BEGIN_ARRAY);
4528  n = v.val.array.nElems;
4529 
4530  if (idx < 0)
4531  {
4532  if (-idx > n)
4533  idx = n;
4534  else
4535  idx = n + idx;
4536  }
4537 
4538  if (idx >= n)
4539  PG_RETURN_JSONB_P(in);
4540 
4541  pushJsonbValue(&state, r, NULL);
4542 
4543  while ((r = JsonbIteratorNext(&it, &v, true)) != WJB_DONE)
4544  {
4545  if (r == WJB_ELEM)
4546  {
4547  if (i++ == idx)
4548  continue;
4549  }
4550 
4551  res = pushJsonbValue(&state, r, r < WJB_BEGIN_ARRAY ? &v : NULL);
4552  }
4553 
4554  Assert(res != NULL);
4555 
4557 }
#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 4680 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().

4681 {
4682  Jsonb *in = PG_GETARG_JSONB_P(0);
4683  ArrayType *path = PG_GETARG_ARRAYTYPE_P(1);
4684  JsonbValue *res = NULL;
4685  Datum *path_elems;
4686  bool *path_nulls;
4687  int path_len;
4688  JsonbIterator *it;
4689  JsonbParseState *st = NULL;
4690 
4691  if (ARR_NDIM(path) > 1)
4692  ereport(ERROR,
4693  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
4694  errmsg("wrong number of array subscripts")));
4695 
4696  if (JB_ROOT_IS_SCALAR(in))
4697  ereport(ERROR,
4698  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4699  errmsg("cannot delete path in scalar")));
4700 
4701  if (JB_ROOT_COUNT(in) == 0)
4702  PG_RETURN_JSONB_P(in);
4703 
4704  deconstruct_array(path, TEXTOID, -1, false, TYPALIGN_INT,
4705  &path_elems, &path_nulls, &path_len);
4706 
4707  if (path_len == 0)
4708  PG_RETURN_JSONB_P(in);
4709 
4710  it = JsonbIteratorInit(&in->root);
4711 
4712  res = setPath(&it, path_elems, path_nulls, path_len, &st,
4713  0, NULL, JB_PATH_DELETE);
4714 
4715  Assert(res != NULL);
4716 
4718 }
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:4902
void deconstruct_array(ArrayType *array, Oid elmtype, int elmlen, bool elmbyval, char elmalign, Datum **elemsp, bool **nullsp, int *nelemsp)
Definition: arrayfuncs.c:3491
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 1890 of file jsonfuncs.c.

References each_worker_jsonb().

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

◆ jsonb_each_text()

Datum jsonb_each_text ( PG_FUNCTION_ARGS  )

Definition at line 1902 of file jsonfuncs.c.

References each_worker_jsonb().

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

◆ jsonb_extract_path()

Datum jsonb_extract_path ( PG_FUNCTION_ARGS  )

Definition at line 1427 of file jsonfuncs.c.

References get_jsonb_path_all().

1428 {
1429  return get_jsonb_path_all(fcinfo, false);
1430 }
static Datum get_jsonb_path_all(FunctionCallInfo fcinfo, bool as_text)
Definition: jsonfuncs.c:1439

◆ jsonb_extract_path_text()

Datum jsonb_extract_path_text ( PG_FUNCTION_ARGS  )

Definition at line 1433 of file jsonfuncs.c.

References get_jsonb_path_all().

1434 {
1435  return get_jsonb_path_all(fcinfo, true);
1436 }
static Datum get_jsonb_path_all(FunctionCallInfo fcinfo, bool as_text)
Definition: jsonfuncs.c:1439

◆ jsonb_get_element()

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

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

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