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 json_populate_type (Datum json_val, Oid json_type, Oid typid, int32 typmod, void **cache, MemoryContext mcxt, bool *isnull)
 
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)
 
JsonTokenType json_get_first_token (text *json, bool throw_error)
 

Macro Definition Documentation

◆ JB_PATH_CONSISTENT_POSITION

#define JB_PATH_CONSISTENT_POSITION   0x0040

Definition at line 49 of file jsonfuncs.c.

◆ JB_PATH_CREATE

#define JB_PATH_CREATE   0x0001

Definition at line 41 of file jsonfuncs.c.

◆ 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.

◆ JB_PATH_DELETE

#define JB_PATH_DELETE   0x0002

Definition at line 42 of file jsonfuncs.c.

◆ JB_PATH_FILL_GAPS

#define JB_PATH_FILL_GAPS   0x0020

Definition at line 48 of file jsonfuncs.c.

◆ JB_PATH_INSERT_AFTER

#define JB_PATH_INSERT_AFTER   0x0010

Definition at line 45 of file jsonfuncs.c.

◆ JB_PATH_INSERT_BEFORE

#define JB_PATH_INSERT_BEFORE   0x0008

Definition at line 44 of file jsonfuncs.c.

◆ JB_PATH_REPLACE

#define JB_PATH_REPLACE   0x0004

Definition at line 43 of file jsonfuncs.c.

◆ 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.

◆ 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

Definition at line 324 of file jsonfuncs.c.

◆ 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))
@ JSON_TOKEN_NULL
Definition: jsonapi.h:32
@ jbvNull
Definition: jsonb.h:236

Definition at line 315 of file jsonfuncs.c.

◆ JsValueIsString

#define JsValueIsString (   jsv)
Value:
((jsv)->is_json ? (jsv)->val.json.type == JSON_TOKEN_STRING \
: ((jsv)->val.jsonb && (jsv)->val.jsonb->type == jbvString))
@ JSON_TOKEN_STRING
Definition: jsonapi.h:22
@ jbvString
Definition: jsonb.h:237

Definition at line 320 of file jsonfuncs.c.

Typedef Documentation

◆ AlenState

typedef struct AlenState AlenState

◆ ArrayIOData

typedef struct ArrayIOData ArrayIOData

◆ ColumnIOData

typedef struct ColumnIOData ColumnIOData

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

197 {
198  TYPECAT_SCALAR = 's',
199  TYPECAT_ARRAY = 'a',
200  TYPECAT_COMPOSITE = 'c',
202  TYPECAT_DOMAIN = 'd'
203 } TypeCat;
TypeCat
Definition: jsonfuncs.c:197
@ TYPECAT_COMPOSITE
Definition: jsonfuncs.c:200
@ TYPECAT_SCALAR
Definition: jsonfuncs.c:198
@ TYPECAT_COMPOSITE_DOMAIN
Definition: jsonfuncs.c:201
@ TYPECAT_DOMAIN
Definition: jsonfuncs.c:202
@ TYPECAT_ARRAY
Definition: jsonfuncs.c:199

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.

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
JsonLexContext * lex
Definition: jsonfuncs.c:101
int lex_level
Definition: jsonapi.h:81
Definition: regguts.h:318

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

Referenced by json_array_length().

◆ alen_object_start()

static void alen_object_start ( void *  state)
static

Definition at line 1840 of file jsonfuncs.c.

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:693
int errmsg(const char *fmt,...)
Definition: elog.c:904
#define ERROR
Definition: elog.h:33
#define ereport(elevel,...)
Definition: elog.h:143

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

Referenced by json_array_length().

◆ alen_scalar()

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

Definition at line 1852 of file jsonfuncs.c.

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 }

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

Referenced by json_array_length().

◆ allocate_record_info()

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

Definition at line 3183 of file jsonfuncs.c.

3184 {
3186  MemoryContextAlloc(mcxt,
3187  offsetof(RecordIOData, columns) +
3188  ncolumns * sizeof(ColumnIOData));
3189 
3190  data->record_type = InvalidOid;
3191  data->record_typmod = 0;
3192  data->ncolumns = ncolumns;
3193  MemSet(data->columns, 0, sizeof(ColumnIOData) * ncolumns);
3194 
3195  return data;
3196 }
#define offsetof(type, field)
Definition: c.h:727
#define MemSet(start, val, len)
Definition: c.h:1008
struct ColumnIOData ColumnIOData
Definition: jsonfuncs.c:159
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:863
const void * data
#define InvalidOid
Definition: postgres_ext.h:36

References data, InvalidOid, MemoryContextAlloc(), MemSet, and offsetof.

Referenced by populate_record().

◆ each_array_start()

static void each_array_start ( void *  state)
static

Definition at line 2098 of file jsonfuncs.c.

2099 {
2100  EachState *_state = (EachState *) state;
2101 
2102  /* json structure check */
2103  if (_state->lex->lex_level == 0)
2104  ereport(ERROR,
2105  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2106  errmsg("cannot deconstruct an array as an object")));
2107 }
JsonLexContext * lex
Definition: jsonfuncs.c:108

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

Referenced by each_worker().

◆ each_object_field_end()

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

Definition at line 2052 of file jsonfuncs.c.

2053 {
2054  EachState *_state = (EachState *) state;
2055  MemoryContext old_cxt;
2056  int len;
2057  text *val;
2058  HeapTuple tuple;
2059  Datum values[2];
2060  bool nulls[2] = {false, false};
2061 
2062  /* skip over nested objects */
2063  if (_state->lex->lex_level != 1)
2064  return;
2065 
2066  /* use the tmp context so we can clean up after each tuple is done */
2067  old_cxt = MemoryContextSwitchTo(_state->tmp_cxt);
2068 
2069  values[0] = CStringGetTextDatum(fname);
2070 
2071  if (isnull && _state->normalize_results)
2072  {
2073  nulls[1] = true;
2074  values[1] = (Datum) 0;
2075  }
2076  else if (_state->next_scalar)
2077  {
2079  _state->next_scalar = false;
2080  }
2081  else
2082  {
2083  len = _state->lex->prev_token_terminator - _state->result_start;
2085  values[1] = PointerGetDatum(val);
2086  }
2087 
2088  tuple = heap_form_tuple(_state->ret_tdesc, values, nulls);
2089 
2090  tuplestore_puttuple(_state->tuple_store, tuple);
2091 
2092  /* clean up and switch back */
2093  MemoryContextSwitchTo(old_cxt);
2094  MemoryContextReset(_state->tmp_cxt);
2095 }
static Datum values[MAXATTR]
Definition: bootstrap.c:156
#define CStringGetTextDatum(s)
Definition: builtins.h:85
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:1020
void MemoryContextReset(MemoryContext context)
Definition: mcxt.c:143
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
const void size_t len
uintptr_t Datum
Definition: postgres.h:411
#define PointerGetDatum(X)
Definition: postgres.h:600
bool normalize_results
Definition: jsonfuncs.c:113
TupleDesc ret_tdesc
Definition: jsonfuncs.c:110
char * result_start
Definition: jsonfuncs.c:112
char * normalized_scalar
Definition: jsonfuncs.c:115
Tuplestorestate * tuple_store
Definition: jsonfuncs.c:109
MemoryContext tmp_cxt
Definition: jsonfuncs.c:111
bool next_scalar
Definition: jsonfuncs.c:114
char * prev_token_terminator
Definition: jsonapi.h:79
Definition: c.h:622
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:200

References cstring_to_text_with_len(), CStringGetTextDatum, heap_form_tuple(), len, 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().

◆ each_object_field_start()

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

Definition at line 2032 of file jsonfuncs.c.

2033 {
2034  EachState *_state = (EachState *) state;
2035 
2036  /* save a pointer to where the value starts */
2037  if (_state->lex->lex_level == 1)
2038  {
2039  /*
2040  * next_scalar will be reset in the object_field_end handler, and
2041  * since we know the value is a scalar there is no danger of it being
2042  * on while recursing down the tree.
2043  */
2044  if (_state->normalize_results && _state->lex->token_type == JSON_TOKEN_STRING)
2045  _state->next_scalar = true;
2046  else
2047  _state->result_start = _state->lex->token_start;
2048  }
2049 }
char * token_start
Definition: jsonapi.h:77
JsonTokenType token_type
Definition: jsonapi.h:80

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().

◆ each_scalar()

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

Definition at line 2110 of file jsonfuncs.c.

2111 {
2112  EachState *_state = (EachState *) state;
2113 
2114  /* json structure check */
2115  if (_state->lex->lex_level == 0)
2116  ereport(ERROR,
2117  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2118  errmsg("cannot deconstruct a scalar")));
2119 
2120  /* supply de-escaped value if required */
2121  if (_state->next_scalar)
2122  _state->normalized_scalar = token;
2123 }

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

Referenced by each_worker().

◆ each_worker()

static Datum each_worker ( FunctionCallInfo  fcinfo,
bool  as_text 
)
static

Definition at line 1992 of file jsonfuncs.c.

1993 {
1994  text *json = PG_GETARG_TEXT_PP(0);
1995  JsonLexContext *lex;
1996  JsonSemAction *sem;
1997  ReturnSetInfo *rsi;
1998  EachState *state;
1999 
2000  lex = makeJsonLexContext(json, true);
2001  state = palloc0(sizeof(EachState));
2002  sem = palloc0(sizeof(JsonSemAction));
2003 
2004  rsi = (ReturnSetInfo *) fcinfo->resultinfo;
2005 
2007  state->tuple_store = rsi->setResult;
2008  state->ret_tdesc = rsi->setDesc;
2009 
2010  sem->semstate = (void *) state;
2012  sem->scalar = each_scalar;
2015 
2016  state->normalize_results = as_text;
2017  state->next_scalar = false;
2018  state->lex = lex;
2020  "json_each temporary cxt",
2022 
2023  pg_parse_json_or_ereport(lex, sem);
2024 
2025  MemoryContextDelete(state->tmp_cxt);
2026 
2027  PG_RETURN_NULL();
2028 }
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:309
#define PG_RETURN_NULL()
Definition: fmgr.h:345
void SetSingleFuncCall(FunctionCallInfo fcinfo, bits32 flags)
Definition: funcapi.c:76
#define SRF_SINGLE_BLESS
Definition: funcapi.h:292
void pg_parse_json_or_ereport(JsonLexContext *lex, JsonSemAction *sem)
Definition: jsonfuncs.c:501
static void each_array_start(void *state)
Definition: jsonfuncs.c:2098
JsonLexContext * makeJsonLexContext(text *json, bool need_escapes)
Definition: jsonfuncs.c:517
static void each_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:2110
static void each_object_field_end(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:2052
static void each_object_field_start(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:2032
void * palloc0(Size size)
Definition: mcxt.c:1099
MemoryContext CurrentMemoryContext
Definition: mcxt.c:42
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:218
#define AllocSetContextCreate
Definition: memutils.h:173
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:197
fmNodePtr resultinfo
Definition: fmgr.h:89
json_ofield_action object_field_start
Definition: jsonapi.h:111
json_scalar_action scalar
Definition: jsonapi.h:115
void * semstate
Definition: jsonapi.h:106
json_struct_action array_start
Definition: jsonapi.h:109
json_ofield_action object_field_end
Definition: jsonapi.h:112
TupleDesc setDesc
Definition: execnodes.h:317
Tuplestorestate * setResult
Definition: execnodes.h:316

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, JsonSemAction::array_start, CurrentMemoryContext, each_array_start(), each_object_field_end(), each_object_field_start(), each_scalar(), makeJsonLexContext(), MemoryContextDelete(), JsonSemAction::object_field_end, JsonSemAction::object_field_start, palloc0(), PG_GETARG_TEXT_PP, pg_parse_json_or_ereport(), PG_RETURN_NULL, FunctionCallInfoBaseData::resultinfo, JsonSemAction::scalar, JsonSemAction::semstate, ReturnSetInfo::setDesc, ReturnSetInfo::setResult, SetSingleFuncCall(), and SRF_SINGLE_BLESS.

Referenced by json_each(), and json_each_text().

◆ 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.

1909 {
1910  Jsonb *jb = PG_GETARG_JSONB_P(0);
1911  ReturnSetInfo *rsi;
1912  MemoryContext old_cxt,
1913  tmp_cxt;
1914  bool skipNested = false;
1915  JsonbIterator *it;
1916  JsonbValue v;
1918 
1919  if (!JB_ROOT_IS_OBJECT(jb))
1920  ereport(ERROR,
1921  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1922  errmsg("cannot call %s on a non-object",
1923  funcname)));
1924 
1925  rsi = (ReturnSetInfo *) fcinfo->resultinfo;
1927 
1929  "jsonb_each temporary cxt",
1931 
1932  it = JsonbIteratorInit(&jb->root);
1933 
1934  while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE)
1935  {
1936  skipNested = true;
1937 
1938  if (r == WJB_KEY)
1939  {
1940  text *key;
1941  Datum values[2];
1942  bool nulls[2] = {false, false};
1943 
1944  /* Use the tmp context so we can clean up after each tuple is done */
1945  old_cxt = MemoryContextSwitchTo(tmp_cxt);
1946 
1947  key = cstring_to_text_with_len(v.val.string.val, v.val.string.len);
1948 
1949  /*
1950  * The next thing the iterator fetches should be the value, no
1951  * matter what shape it is.
1952  */
1953  r = JsonbIteratorNext(&it, &v, skipNested);
1954  Assert(r != WJB_DONE);
1955 
1956  values[0] = PointerGetDatum(key);
1957 
1958  if (as_text)
1959  {
1960  if (v.type == jbvNull)
1961  {
1962  /* a json null is an sql null in text mode */
1963  nulls[1] = true;
1964  values[1] = (Datum) NULL;
1965  }
1966  else
1968  }
1969  else
1970  {
1971  /* Not in text mode, just return the Jsonb */
1972  Jsonb *val = JsonbValueToJsonb(&v);
1973 
1974  values[1] = PointerGetDatum(val);
1975  }
1976 
1977  tuplestore_putvalues(rsi->setResult, rsi->setDesc, values, nulls);
1978 
1979  /* clean up and switch back */
1980  MemoryContextSwitchTo(old_cxt);
1981  MemoryContextReset(tmp_cxt);
1982  }
1983  }
1984 
1985  MemoryContextDelete(tmp_cxt);
1986 
1987  PG_RETURN_NULL();
1988 }
#define JB_ROOT_IS_OBJECT(jbp_)
Definition: jsonb.h:229
#define PG_GETARG_JSONB_P(x)
Definition: jsonb.h:74
JsonbIteratorToken
Definition: jsonb.h:21
@ WJB_KEY
Definition: jsonb.h:23
@ WJB_DONE
Definition: jsonb.h:22
JsonbIterator * JsonbIteratorInit(JsonbContainer *container)
Definition: jsonb_util.c:819
Jsonb * JsonbValueToJsonb(JsonbValue *val)
Definition: jsonb_util.c:94
JsonbIteratorToken JsonbIteratorNext(JsonbIterator **it, JsonbValue *val, bool skipNested)
Definition: jsonb_util.c:855
static text * JsonbValueAsText(JsonbValue *v)
Definition: jsonfuncs.c:1743
Assert(fmt[strlen(fmt) - 1] !='\n')
enum jbvType type
Definition: jsonb.h:263
char * val
Definition: jsonb.h:272
Definition: jsonb.h:221
JsonbContainer root
Definition: jsonb.h:223
void tuplestore_putvalues(Tuplestorestate *state, TupleDesc tdesc, Datum *values, bool *isnull)
Definition: tuplestore.c:750

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, Assert(), cstring_to_text_with_len(), CurrentMemoryContext, ereport, errcode(), errmsg(), ERROR, 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, Jsonb::root, ReturnSetInfo::setDesc, ReturnSetInfo::setResult, SetSingleFuncCall(), SRF_SINGLE_BLESS, tuplestore_putvalues(), JsonbValue::type, JsonbValue::val, val, values, WJB_DONE, and WJB_KEY.

Referenced by jsonb_each(), and jsonb_each_text().

◆ elements_array_element_end()

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

Definition at line 2295 of file jsonfuncs.c.

2296 {
2297  ElementsState *_state = (ElementsState *) state;
2298  MemoryContext old_cxt;
2299  int len;
2300  text *val;
2301  HeapTuple tuple;
2302  Datum values[1];
2303  bool nulls[1] = {false};
2304 
2305  /* skip over nested objects */
2306  if (_state->lex->lex_level != 1)
2307  return;
2308 
2309  /* use the tmp context so we can clean up after each tuple is done */
2310  old_cxt = MemoryContextSwitchTo(_state->tmp_cxt);
2311 
2312  if (isnull && _state->normalize_results)
2313  {
2314  nulls[0] = true;
2315  values[0] = (Datum) NULL;
2316  }
2317  else if (_state->next_scalar)
2318  {
2320  _state->next_scalar = false;
2321  }
2322  else
2323  {
2324  len = _state->lex->prev_token_terminator - _state->result_start;
2326  values[0] = PointerGetDatum(val);
2327  }
2328 
2329  tuple = heap_form_tuple(_state->ret_tdesc, values, nulls);
2330 
2331  tuplestore_puttuple(_state->tuple_store, tuple);
2332 
2333  /* clean up and switch back */
2334  MemoryContextSwitchTo(old_cxt);
2335  MemoryContextReset(_state->tmp_cxt);
2336 }
char * result_start
Definition: jsonfuncs.c:126
bool next_scalar
Definition: jsonfuncs.c:128
TupleDesc ret_tdesc
Definition: jsonfuncs.c:124
Tuplestorestate * tuple_store
Definition: jsonfuncs.c:123
bool normalize_results
Definition: jsonfuncs.c:127
MemoryContext tmp_cxt
Definition: jsonfuncs.c:125
JsonLexContext * lex
Definition: jsonfuncs.c:121
char * normalized_scalar
Definition: jsonfuncs.c:129

References cstring_to_text_with_len(), CStringGetTextDatum, heap_form_tuple(), len, 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().

◆ elements_array_element_start()

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

Definition at line 2275 of file jsonfuncs.c.

2276 {
2277  ElementsState *_state = (ElementsState *) state;
2278 
2279  /* save a pointer to where the value starts */
2280  if (_state->lex->lex_level == 1)
2281  {
2282  /*
2283  * next_scalar will be reset in the array_element_end handler, and
2284  * since we know the value is a scalar there is no danger of it being
2285  * on while recursing down the tree.
2286  */
2287  if (_state->normalize_results && _state->lex->token_type == JSON_TOKEN_STRING)
2288  _state->next_scalar = true;
2289  else
2290  _state->result_start = _state->lex->token_start;
2291  }
2292 }

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().

◆ elements_object_start()

static void elements_object_start ( void *  state)
static

Definition at line 2339 of file jsonfuncs.c.

2340 {
2341  ElementsState *_state = (ElementsState *) state;
2342 
2343  /* json structure check */
2344  if (_state->lex->lex_level == 0)
2345  ereport(ERROR,
2346  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2347  errmsg("cannot call %s on a non-array",
2348  _state->function_name)));
2349 }
const char * function_name
Definition: jsonfuncs.c:122

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

Referenced by elements_worker().

◆ elements_scalar()

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

Definition at line 2352 of file jsonfuncs.c.

2353 {
2354  ElementsState *_state = (ElementsState *) state;
2355 
2356  /* json structure check */
2357  if (_state->lex->lex_level == 0)
2358  ereport(ERROR,
2359  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2360  errmsg("cannot call %s on a scalar",
2361  _state->function_name)));
2362 
2363  /* supply de-escaped value if required */
2364  if (_state->next_scalar)
2365  _state->normalized_scalar = token;
2366 }

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

Referenced by elements_worker().

◆ elements_worker()

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

Definition at line 2235 of file jsonfuncs.c.

2236 {
2237  text *json = PG_GETARG_TEXT_PP(0);
2238 
2239  /* elements only needs escaped strings when as_text */
2240  JsonLexContext *lex = makeJsonLexContext(json, as_text);
2241  JsonSemAction *sem;
2242  ReturnSetInfo *rsi;
2244 
2245  state = palloc0(sizeof(ElementsState));
2246  sem = palloc0(sizeof(JsonSemAction));
2247 
2249  rsi = (ReturnSetInfo *) fcinfo->resultinfo;
2250  state->tuple_store = rsi->setResult;
2251  state->ret_tdesc = rsi->setDesc;
2252 
2253  sem->semstate = (void *) state;
2255  sem->scalar = elements_scalar;
2258 
2259  state->function_name = funcname;
2260  state->normalize_results = as_text;
2261  state->next_scalar = false;
2262  state->lex = lex;
2264  "json_array_elements temporary cxt",
2266 
2267  pg_parse_json_or_ereport(lex, sem);
2268 
2269  MemoryContextDelete(state->tmp_cxt);
2270 
2271  PG_RETURN_NULL();
2272 }
#define SRF_SINGLE_USE_EXPECTED
Definition: funcapi.h:291
static void elements_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:2352
static void elements_object_start(void *state)
Definition: jsonfuncs.c:2339
static void elements_array_element_end(void *state, bool isnull)
Definition: jsonfuncs.c:2295
static void elements_array_element_start(void *state, bool isnull)
Definition: jsonfuncs.c:2275
json_struct_action object_start
Definition: jsonapi.h:107
json_aelem_action array_element_start
Definition: jsonapi.h:113
json_aelem_action array_element_end
Definition: jsonapi.h:114

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, JsonSemAction::array_element_end, JsonSemAction::array_element_start, CurrentMemoryContext, elements_array_element_end(), elements_array_element_start(), elements_object_start(), elements_scalar(), makeJsonLexContext(), MemoryContextDelete(), JsonSemAction::object_start, palloc0(), PG_GETARG_TEXT_PP, pg_parse_json_or_ereport(), PG_RETURN_NULL, FunctionCallInfoBaseData::resultinfo, JsonSemAction::scalar, JsonSemAction::semstate, ReturnSetInfo::setDesc, ReturnSetInfo::setResult, SetSingleFuncCall(), SRF_SINGLE_BLESS, and SRF_SINGLE_USE_EXPECTED.

Referenced by json_array_elements(), and json_array_elements_text().

◆ elements_worker_jsonb()

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

Definition at line 2146 of file jsonfuncs.c.

2148 {
2149  Jsonb *jb = PG_GETARG_JSONB_P(0);
2150  ReturnSetInfo *rsi;
2151  MemoryContext old_cxt,
2152  tmp_cxt;
2153  bool skipNested = false;
2154  JsonbIterator *it;
2155  JsonbValue v;
2157 
2158  if (JB_ROOT_IS_SCALAR(jb))
2159  ereport(ERROR,
2160  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2161  errmsg("cannot extract elements from a scalar")));
2162  else if (!JB_ROOT_IS_ARRAY(jb))
2163  ereport(ERROR,
2164  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2165  errmsg("cannot extract elements from an object")));
2166 
2167  rsi = (ReturnSetInfo *) fcinfo->resultinfo;
2168 
2169  SetSingleFuncCall(fcinfo,
2171 
2173  "jsonb_array_elements temporary cxt",
2175 
2176  it = JsonbIteratorInit(&jb->root);
2177 
2178  while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE)
2179  {
2180  skipNested = true;
2181 
2182  if (r == WJB_ELEM)
2183  {
2184  Datum values[1];
2185  bool nulls[1] = {false};
2186 
2187  /* use the tmp context so we can clean up after each tuple is done */
2188  old_cxt = MemoryContextSwitchTo(tmp_cxt);
2189 
2190  if (as_text)
2191  {
2192  if (v.type == jbvNull)
2193  {
2194  /* a json null is an sql null in text mode */
2195  nulls[0] = true;
2196  values[0] = (Datum) NULL;
2197  }
2198  else
2200  }
2201  else
2202  {
2203  /* Not in text mode, just return the Jsonb */
2204  Jsonb *val = JsonbValueToJsonb(&v);
2205 
2206  values[0] = PointerGetDatum(val);
2207  }
2208 
2209  tuplestore_putvalues(rsi->setResult, rsi->setDesc, values, nulls);
2210 
2211  /* clean up and switch back */
2212  MemoryContextSwitchTo(old_cxt);
2213  MemoryContextReset(tmp_cxt);
2214  }
2215  }
2216 
2217  MemoryContextDelete(tmp_cxt);
2218 
2219  PG_RETURN_NULL();
2220 }
#define JB_ROOT_IS_ARRAY(jbp_)
Definition: jsonb.h:230
#define JB_ROOT_IS_SCALAR(jbp_)
Definition: jsonb.h:228
@ WJB_ELEM
Definition: jsonb.h:25

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, CurrentMemoryContext, ereport, errcode(), errmsg(), ERROR, 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, Jsonb::root, ReturnSetInfo::setDesc, ReturnSetInfo::setResult, SetSingleFuncCall(), SRF_SINGLE_BLESS, SRF_SINGLE_USE_EXPECTED, tuplestore_putvalues(), JsonbValue::type, val, values, WJB_DONE, and WJB_ELEM.

Referenced by jsonb_array_elements(), and jsonb_array_elements_text().

◆ get_array_element_end()

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

Definition at line 1344 of file jsonfuncs.c.

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 * path_indexes
Definition: jsonfuncs.c:92
bool * pathok
Definition: jsonfuncs.c:93
char * result_start
Definition: jsonfuncs.c:87
int * array_cur_index
Definition: jsonfuncs.c:94
text * tresult
Definition: jsonfuncs.c:86
JsonLexContext * lex
Definition: jsonfuncs.c:85
bool normalize_results
Definition: jsonfuncs.c:88

References GetState::array_cur_index, cstring_to_text_with_len(), 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().

◆ get_array_element_start()

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

Definition at line 1298 of file jsonfuncs.c.

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 }
bool next_scalar
Definition: jsonfuncs.c:89

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().

◆ get_array_end()

static void get_array_end ( void *  state)
static

Definition at line 1282 of file jsonfuncs.c.

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 }
int npath
Definition: jsonfuncs.c:90

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

Referenced by get_worker().

◆ get_array_start()

static void get_array_start ( void *  state)
static

Definition at line 1244 of file jsonfuncs.c.

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 }
JsonParseErrorType json_count_array_elements(JsonLexContext *lex, int *elements)
Definition: jsonapi.c:208
JsonParseErrorType
Definition: jsonapi.h:37
@ JSON_SUCCESS
Definition: jsonapi.h:38
void json_ereport_error(JsonParseErrorType error, JsonLexContext *lex)
Definition: jsonfuncs.c:611
static void error(void)
Definition: sql-dyntest.c:147

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().

◆ get_json_object_as_hash()

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

Definition at line 3508 of file jsonfuncs.c.

3509 {
3510  HASHCTL ctl;
3511  HTAB *tab;
3512  JHashState *state;
3514  JsonSemAction *sem;
3515 
3516  ctl.keysize = NAMEDATALEN;
3517  ctl.entrysize = sizeof(JsonHashEntry);
3518  ctl.hcxt = CurrentMemoryContext;
3519  tab = hash_create("json object hashtable",
3520  100,
3521  &ctl,
3523 
3524  state = palloc0(sizeof(JHashState));
3525  sem = palloc0(sizeof(JsonSemAction));
3526 
3527  state->function_name = funcname;
3528  state->hash = tab;
3529  state->lex = lex;
3530 
3531  sem->semstate = (void *) state;
3533  sem->scalar = hash_scalar;
3536 
3537  pg_parse_json_or_ereport(lex, sem);
3538 
3539  return tab;
3540 }
HTAB * hash_create(const char *tabname, long nelem, const HASHCTL *info, int flags)
Definition: dynahash.c:349
#define HASH_STRINGS
Definition: hsearch.h:96
#define HASH_CONTEXT
Definition: hsearch.h:102
#define HASH_ELEM
Definition: hsearch.h:95
JsonLexContext * makeJsonLexContextCstringLen(char *json, int len, int encoding, bool need_escapes)
Definition: jsonapi.c:144
static void hash_object_field_start(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:3543
static void hash_object_field_end(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:3567
struct JsonHashEntry JsonHashEntry
static void hash_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:3627
static void hash_array_start(void *state)
Definition: jsonfuncs.c:3616
int GetDatabaseEncoding(void)
Definition: mbutils.c:1210
#define NAMEDATALEN
Size keysize
Definition: hsearch.h:75
Size entrysize
Definition: hsearch.h:76
MemoryContext hcxt
Definition: hsearch.h:86
Definition: dynahash.c:220

References JsonSemAction::array_start, CurrentMemoryContext, HASHCTL::entrysize, GetDatabaseEncoding(), 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, len, makeJsonLexContextCstringLen(), NAMEDATALEN, JsonSemAction::object_field_end, JsonSemAction::object_field_start, palloc0(), pg_parse_json_or_ereport(), JsonSemAction::scalar, and JsonSemAction::semstate.

Referenced by JsValueToJsObject().

◆ get_jsonb_path_all()

static Datum get_jsonb_path_all ( FunctionCallInfo  fcinfo,
bool  as_text 
)
static

Definition at line 1439 of file jsonfuncs.c.

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
1468 }
#define PG_GETARG_ARRAYTYPE_P(n)
Definition: array.h:256
bool array_contains_nulls(ArrayType *array)
Definition: arrayfuncs.c:3558
void deconstruct_array(ArrayType *array, Oid elmtype, int elmlen, bool elmbyval, char elmalign, Datum **elemsp, bool **nullsp, int *nelemsp)
Definition: arrayfuncs.c:3491
#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

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

Referenced by jsonb_extract_path(), and jsonb_extract_path_text().

◆ get_object_end()

static void get_object_end ( void *  state)
static

Definition at line 1134 of file jsonfuncs.c.

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 }

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

Referenced by get_worker().

◆ 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.

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 ** path_names
Definition: jsonfuncs.c:91

References cstring_to_text_with_len(), 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().

◆ 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.

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 }

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().

◆ get_object_start()

static void get_object_start ( void *  state)
static

Definition at line 1117 of file jsonfuncs.c.

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 }

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

Referenced by get_worker().

◆ get_path_all()

static Datum get_path_all ( FunctionCallInfo  fcinfo,
bool  as_text 
)
static

Definition at line 981 of file jsonfuncs.c.

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 TextDatumGetCString(d)
Definition: builtins.h:86
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:372
int i
Definition: isn.c:73
static text * get_worker(text *json, char **tpath, int *ipath, int npath, bool normalize_results)
Definition: jsonfuncs.c:1061
void * palloc(Size size)
Definition: mcxt.c:1068
int strtoint(const char *pg_restrict str, char **pg_restrict endptr, int base)
Definition: string.c:50

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, strtoint(), and TextDatumGetCString.

Referenced by json_extract_path(), and json_extract_path_text().

◆ get_record_type_from_argument()

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

Definition at line 3340 of file jsonfuncs.c.

3343 {
3344  cache->argtype = get_fn_expr_argtype(fcinfo->flinfo, 0);
3345  prepare_column_cache(&cache->c,
3346  cache->argtype, -1,
3347  cache->fn_mcxt, false);
3348  if (cache->c.typcat != TYPECAT_COMPOSITE &&
3349  cache->c.typcat != TYPECAT_COMPOSITE_DOMAIN)
3350  ereport(ERROR,
3351  (errcode(ERRCODE_DATATYPE_MISMATCH),
3352  /* translator: %s is a function name, eg json_to_record */
3353  errmsg("first argument of %s must be a row type",
3354  funcname)));
3355 }
Oid get_fn_expr_argtype(FmgrInfo *flinfo, int argnum)
Definition: fmgr.c:1786
static void prepare_column_cache(ColumnIOData *column, Oid typid, int32 typmod, MemoryContext mcxt, bool need_scalar)
Definition: jsonfuncs.c:2986
TypeCat typcat
Definition: jsonfuncs.c:212
FmgrInfo * flinfo
Definition: fmgr.h:87
ColumnIOData c
Definition: jsonfuncs.c:237
MemoryContext fn_mcxt
Definition: jsonfuncs.c:238

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().

◆ get_record_type_from_query()

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

Definition at line 3366 of file jsonfuncs.c.

3369 {
3370  TupleDesc tupdesc;
3371  MemoryContext old_cxt;
3372 
3373  if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
3374  ereport(ERROR,
3375  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3376  /* translator: %s is a function name, eg json_to_record */
3377  errmsg("could not determine row type for result of %s",
3378  funcname),
3379  errhint("Provide a non-null record argument, "
3380  "or call the function in the FROM clause "
3381  "using a column definition list.")));
3382 
3383  Assert(tupdesc);
3384  cache->argtype = tupdesc->tdtypeid;
3385 
3386  /* If we go through this more than once, avoid memory leak */
3387  if (cache->c.io.composite.tupdesc)
3389 
3390  /* Save identified tupdesc */
3391  old_cxt = MemoryContextSwitchTo(cache->fn_mcxt);
3392  cache->c.io.composite.tupdesc = CreateTupleDescCopy(tupdesc);
3393  cache->c.io.composite.base_typid = tupdesc->tdtypeid;
3394  cache->c.io.composite.base_typmod = tupdesc->tdtypmod;
3395  MemoryContextSwitchTo(old_cxt);
3396 }
int errhint(const char *fmt,...)
Definition: elog.c:1151
TypeFuncClass get_call_result_type(FunctionCallInfo fcinfo, Oid *resultTypeId, TupleDesc *resultTupleDesc)
Definition: funcapi.c:276
@ TYPEFUNC_COMPOSITE
Definition: funcapi.h:149
CompositeIOData composite
Definition: jsonfuncs.c:218
union ColumnIOData::@21 io
int32 base_typmod
Definition: jsonfuncs.c:181
TupleDesc tupdesc
Definition: jsonfuncs.c:178
int32 tdtypmod
Definition: tupdesc.h:83
Oid tdtypeid
Definition: tupdesc.h:82
void FreeTupleDesc(TupleDesc tupdesc)
Definition: tupdesc.c:309
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
Definition: tupdesc.c:111

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().

◆ get_scalar()

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

Definition at line 1386 of file jsonfuncs.c.

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 * input
Definition: jsonapi.h:74
text * cstring_to_text(const char *s)
Definition: varlena.c:188

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

Referenced by get_worker().

◆ 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.

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 }
static void get_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:1386
static void get_array_element_end(void *state, bool isnull)
Definition: jsonfuncs.c:1344
static void get_object_field_end(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:1195
static void get_object_end(void *state)
Definition: jsonfuncs.c:1134
static void get_array_element_start(void *state, bool isnull)
Definition: jsonfuncs.c:1298
static void get_object_start(void *state)
Definition: jsonfuncs.c:1117
static void get_array_start(void *state)
Definition: jsonfuncs.c:1244
static void get_object_field_start(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:1150
static void get_array_end(void *state)
Definition: jsonfuncs.c:1282
json_struct_action array_end
Definition: jsonapi.h:110
json_struct_action object_end
Definition: jsonapi.h:108

References 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(), makeJsonLexContext(), JsonSemAction::object_end, JsonSemAction::object_field_end, JsonSemAction::object_field_start, JsonSemAction::object_start, palloc(), palloc0(), pg_parse_json_or_ereport(), JsonSemAction::scalar, and JsonSemAction::semstate.

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

◆ hash_array_start()

static void hash_array_start ( void *  state)
static

Definition at line 3616 of file jsonfuncs.c.

3617 {
3618  JHashState *_state = (JHashState *) state;
3619 
3620  if (_state->lex->lex_level == 0)
3621  ereport(ERROR,
3622  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3623  errmsg("cannot call %s on an array", _state->function_name)));
3624 }
const char * function_name
Definition: jsonfuncs.c:136
JsonLexContext * lex
Definition: jsonfuncs.c:135

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

Referenced by get_json_object_as_hash().

◆ hash_object_field_end()

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

Definition at line 3567 of file jsonfuncs.c.

3568 {
3569  JHashState *_state = (JHashState *) state;
3570  JsonHashEntry *hashentry;
3571  bool found;
3572 
3573  /*
3574  * Ignore nested fields.
3575  */
3576  if (_state->lex->lex_level > 1)
3577  return;
3578 
3579  /*
3580  * Ignore field names >= NAMEDATALEN - they can't match a record field.
3581  * (Note: without this test, the hash code would truncate the string at
3582  * NAMEDATALEN-1, and could then match against a similarly-truncated
3583  * record field name. That would be a reasonable behavior, but this code
3584  * has previously insisted on exact equality, so we keep this behavior.)
3585  */
3586  if (strlen(fname) >= NAMEDATALEN)
3587  return;
3588 
3589  hashentry = hash_search(_state->hash, fname, HASH_ENTER, &found);
3590 
3591  /*
3592  * found being true indicates a duplicate. We don't do anything about
3593  * that, a later field with the same name overrides the earlier field.
3594  */
3595 
3596  hashentry->type = _state->saved_token_type;
3597  Assert(isnull == (hashentry->type == JSON_TOKEN_NULL));
3598 
3599  if (_state->save_json_start != NULL)
3600  {
3601  int len = _state->lex->prev_token_terminator - _state->save_json_start;
3602  char *val = palloc((len + 1) * sizeof(char));
3603 
3604  memcpy(val, _state->save_json_start, len);
3605  val[len] = '\0';
3606  hashentry->val = val;
3607  }
3608  else
3609  {
3610  /* must have had a scalar instead */
3611  hashentry->val = _state->saved_scalar;
3612  }
3613 }
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:954
@ HASH_ENTER
Definition: hsearch.h:114
char * saved_scalar
Definition: jsonfuncs.c:138
JsonTokenType saved_token_type
Definition: jsonfuncs.c:140
char * save_json_start
Definition: jsonfuncs.c:139
HTAB * hash
Definition: jsonfuncs.c:137
char * val
Definition: jsonfuncs.c:147
JsonTokenType type
Definition: jsonfuncs.c:148

References Assert(), JHashState::hash, HASH_ENTER, hash_search(), JSON_TOKEN_NULL, len, 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().

◆ hash_object_field_start()

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

Definition at line 3543 of file jsonfuncs.c.

3544 {
3545  JHashState *_state = (JHashState *) state;
3546 
3547  if (_state->lex->lex_level > 1)
3548  return;
3549 
3550  /* remember token type */
3551  _state->saved_token_type = _state->lex->token_type;
3552 
3553  if (_state->lex->token_type == JSON_TOKEN_ARRAY_START ||
3555  {
3556  /* remember start position of the whole text of the subobject */
3557  _state->save_json_start = _state->lex->token_start;
3558  }
3559  else
3560  {
3561  /* must be a scalar */
3562  _state->save_json_start = NULL;
3563  }
3564 }
@ JSON_TOKEN_OBJECT_START
Definition: jsonapi.h:24
@ JSON_TOKEN_ARRAY_START
Definition: jsonapi.h:26

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().

◆ hash_scalar()

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

Definition at line 3627 of file jsonfuncs.c.

3628 {
3629  JHashState *_state = (JHashState *) state;
3630 
3631  if (_state->lex->lex_level == 0)
3632  ereport(ERROR,
3633  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3634  errmsg("cannot call %s on a scalar", _state->function_name)));
3635 
3636  if (_state->lex->lex_level == 1)
3637  {
3638  _state->saved_scalar = token;
3639  /* saved_token_type must already be set in hash_object_field_start() */
3640  Assert(_state->saved_token_type == tokentype);
3641  }
3642 }

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().

◆ iterate_json_values()

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

Definition at line 5358 of file jsonfuncs.c.

5360 {
5361  JsonLexContext *lex = makeJsonLexContext(json, true);
5362  JsonSemAction *sem = palloc0(sizeof(JsonSemAction));
5364 
5365  state->lex = lex;
5366  state->action = action;
5367  state->action_state = action_state;
5368  state->flags = flags;
5369 
5370  sem->semstate = (void *) state;
5373 
5374  pg_parse_json_or_ereport(lex, sem);
5375 }
static void iterate_values_object_field_start(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:5408
static void iterate_values_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:5382

References generate_unaccent_rules::action, iterate_values_object_field_start(), iterate_values_scalar(), makeJsonLexContext(), JsonSemAction::object_field_start, palloc0(), pg_parse_json_or_ereport(), JsonSemAction::scalar, and JsonSemAction::semstate.

Referenced by json_to_tsvector_worker().

◆ iterate_jsonb_values()

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

Definition at line 5290 of file jsonfuncs.c.

5292 {
5293  JsonbIterator *it;
5294  JsonbValue v;
5296 
5297  it = JsonbIteratorInit(&jb->root);
5298 
5299  /*
5300  * Just recursively iterating over jsonb and call callback on all
5301  * corresponding elements
5302  */
5303  while ((type = JsonbIteratorNext(&it, &v, false)) != WJB_DONE)
5304  {
5305  if (type == WJB_KEY)
5306  {
5307  if (flags & jtiKey)
5308  action(state, v.val.string.val, v.val.string.len);
5309 
5310  continue;
5311  }
5312  else if (!(type == WJB_VALUE || type == WJB_ELEM))
5313  {
5314  /* do not call callback for composite JsonbValue */
5315  continue;
5316  }
5317 
5318  /* JsonbValue is a value of object or element of array */
5319  switch (v.type)
5320  {
5321  case jbvString:
5322  if (flags & jtiString)
5323  action(state, v.val.string.val, v.val.string.len);
5324  break;
5325  case jbvNumeric:
5326  if (flags & jtiNumeric)
5327  {
5328  char *val;
5329 
5331  NumericGetDatum(v.val.numeric)));
5332 
5333  action(state, val, strlen(val));
5334  pfree(val);
5335  }
5336  break;
5337  case jbvBool:
5338  if (flags & jtiBool)
5339  {
5340  if (v.val.boolean)
5341  action(state, "true", 4);
5342  else
5343  action(state, "false", 5);
5344  }
5345  break;
5346  default:
5347  /* do not call callback for composite JsonbValue */
5348  break;
5349  }
5350  }
5351 }
Datum numeric_out(PG_FUNCTION_ARGS)
Definition: numeric.c:735
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:631
@ jbvNumeric
Definition: jsonb.h:238
@ jbvBool
Definition: jsonb.h:239
@ WJB_VALUE
Definition: jsonb.h:24
@ jtiKey
Definition: jsonfuncs.h:26
@ jtiNumeric
Definition: jsonfuncs.h:28
@ jtiBool
Definition: jsonfuncs.h:29
@ jtiString
Definition: jsonfuncs.h:27
void pfree(void *pointer)
Definition: mcxt.c:1175
#define NumericGetDatum(X)
Definition: numeric.h:61
#define DatumGetCString(X)
Definition: postgres.h:610

References generate_unaccent_rules::action, DatumGetCString, DirectFunctionCall1, jbvBool, jbvNumeric, jbvString, JsonbIteratorInit(), JsonbIteratorNext(), jtiBool, jtiKey, jtiNumeric, jtiString, numeric_out(), NumericGetDatum, pfree(), Jsonb::root, generate_unaccent_rules::type, JsonbValue::type, JsonbValue::val, val, WJB_DONE, WJB_ELEM, WJB_KEY, and WJB_VALUE.

Referenced by jsonb_to_tsvector_worker().

◆ iterate_values_object_field_start()

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

Definition at line 5408 of file jsonfuncs.c.

5409 {
5411 
5412  if (_state->flags & jtiKey)
5413  {
5414  char *val = pstrdup(fname);
5415 
5416  _state->action(_state->action_state, val, strlen(val));
5417  }
5418 }
char * pstrdup(const char *in)
Definition: mcxt.c:1305
JsonIterateStringValuesAction action
Definition: jsonfuncs.c:65

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

Referenced by iterate_json_values().

◆ iterate_values_scalar()

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

Definition at line 5382 of file jsonfuncs.c.

5383 {
5385 
5386  switch (tokentype)
5387  {
5388  case JSON_TOKEN_STRING:
5389  if (_state->flags & jtiString)
5390  _state->action(_state->action_state, token, strlen(token));
5391  break;
5392  case JSON_TOKEN_NUMBER:
5393  if (_state->flags & jtiNumeric)
5394  _state->action(_state->action_state, token, strlen(token));
5395  break;
5396  case JSON_TOKEN_TRUE:
5397  case JSON_TOKEN_FALSE:
5398  if (_state->flags & jtiBool)
5399  _state->action(_state->action_state, token, strlen(token));
5400  break;
5401  default:
5402  /* do not call callback for any other token */
5403  break;
5404  }
5405 }
@ JSON_TOKEN_FALSE
Definition: jsonapi.h:31
@ JSON_TOKEN_TRUE
Definition: jsonapi.h:30
@ JSON_TOKEN_NUMBER
Definition: jsonapi.h:23

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().

◆ IteratorConcat()

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

Definition at line 4708 of file jsonfuncs.c.

4710 {
4711  JsonbValue v1,
4712  v2,
4713  *res = NULL;
4714  JsonbIteratorToken r1,
4715  r2,
4716  rk1,
4717  rk2;
4718 
4719  rk1 = JsonbIteratorNext(it1, &v1, false);
4720  rk2 = JsonbIteratorNext(it2, &v2, false);
4721 
4722  /*
4723  * JsonbIteratorNext reports raw scalars as if they were single-element
4724  * arrays; hence we only need consider "object" and "array" cases here.
4725  */
4726  if (rk1 == WJB_BEGIN_OBJECT && rk2 == WJB_BEGIN_OBJECT)
4727  {
4728  /*
4729  * Both inputs are objects.
4730  *
4731  * Append all the tokens from v1 to res, except last WJB_END_OBJECT
4732  * (because res will not be finished yet).
4733  */
4734  pushJsonbValue(state, rk1, NULL);
4735  while ((r1 = JsonbIteratorNext(it1, &v1, true)) != WJB_END_OBJECT)
4736  pushJsonbValue(state, r1, &v1);
4737 
4738  /*
4739  * Append all the tokens from v2 to res, including last WJB_END_OBJECT
4740  * (the concatenation will be completed). Any duplicate keys will
4741  * automatically override the value from the first object.
4742  */
4743  while ((r2 = JsonbIteratorNext(it2, &v2, true)) != WJB_DONE)
4744  res = pushJsonbValue(state, r2, r2 != WJB_END_OBJECT ? &v2 : NULL);
4745  }
4746  else if (rk1 == WJB_BEGIN_ARRAY && rk2 == WJB_BEGIN_ARRAY)
4747  {
4748  /*
4749  * Both inputs are arrays.
4750  */
4751  pushJsonbValue(state, rk1, NULL);
4752 
4753  while ((r1 = JsonbIteratorNext(it1, &v1, true)) != WJB_END_ARRAY)
4754  {
4755  Assert(r1 == WJB_ELEM);
4756  pushJsonbValue(state, r1, &v1);
4757  }
4758 
4759  while ((r2 = JsonbIteratorNext(it2, &v2, true)) != WJB_END_ARRAY)
4760  {
4761  Assert(r2 == WJB_ELEM);
4762  pushJsonbValue(state, WJB_ELEM, &v2);
4763  }
4764 
4765  res = pushJsonbValue(state, WJB_END_ARRAY, NULL /* signal to sort */ );
4766  }
4767  else if (rk1 == WJB_BEGIN_OBJECT)
4768  {
4769  /*
4770  * We have object || array.
4771  */
4772  Assert(rk2 == WJB_BEGIN_ARRAY);
4773 
4775 
4777  while ((r1 = JsonbIteratorNext(it1, &v1, true)) != WJB_DONE)
4778  pushJsonbValue(state, r1, r1 != WJB_END_OBJECT ? &v1 : NULL);
4779 
4780  while ((r2 = JsonbIteratorNext(it2, &v2, true)) != WJB_DONE)
4781  res = pushJsonbValue(state, r2, r2 != WJB_END_ARRAY ? &v2 : NULL);
4782  }
4783  else
4784  {
4785  /*
4786  * We have array || object.
4787  */
4788  Assert(rk1 == WJB_BEGIN_ARRAY);
4789  Assert(rk2 == WJB_BEGIN_OBJECT);
4790 
4792 
4793  while ((r1 = JsonbIteratorNext(it1, &v1, true)) != WJB_END_ARRAY)
4794  pushJsonbValue(state, r1, &v1);
4795 
4797  while ((r2 = JsonbIteratorNext(it2, &v2, true)) != WJB_DONE)
4798  pushJsonbValue(state, r2, r2 != WJB_END_OBJECT ? &v2 : NULL);
4799 
4801  }
4802 
4803  return res;
4804 }
@ WJB_END_ARRAY
Definition: jsonb.h:27
@ WJB_END_OBJECT
Definition: jsonb.h:29
@ WJB_BEGIN_OBJECT
Definition: jsonb.h:28
@ WJB_BEGIN_ARRAY
Definition: jsonb.h:26
JsonbValue * pushJsonbValue(JsonbParseState **pstate, JsonbIteratorToken seq, JsonbValue *jbval)
Definition: jsonb_util.c:568

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

Referenced by jsonb_concat().

◆ JsObjectGetField()

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

Definition at line 3199 of file jsonfuncs.c.

3200 {
3201  jsv->is_json = obj->is_json;
3202 
3203  if (jsv->is_json)
3204  {
3205  JsonHashEntry *hashentry = hash_search(obj->val.json_hash, field,
3206  HASH_FIND, NULL);
3207 
3208  jsv->val.json.type = hashentry ? hashentry->type : JSON_TOKEN_NULL;
3209  jsv->val.json.str = jsv->val.json.type == JSON_TOKEN_NULL ? NULL :
3210  hashentry->val;
3211  jsv->val.json.len = jsv->val.json.str ? -1 : 0; /* null-terminated */
3212 
3213  return hashentry != NULL;
3214  }
3215  else
3216  {
3217  jsv->val.jsonb = !obj->val.jsonb_cont ? NULL :
3218  getKeyJsonValueFromContainer(obj->val.jsonb_cont, field, strlen(field),
3219  NULL);
3220 
3221  return jsv->val.jsonb != NULL;
3222  }
3223 }
@ HASH_FIND
Definition: hsearch.h:113
JsonbValue * getKeyJsonValueFromContainer(JsonbContainer *container, const char *keyVal, int keyLen, JsonbValue *res)
Definition: jsonb_util.c:400
bool is_json
Definition: jsonfuncs.c:306
JsonbContainer * jsonb_cont
Definition: jsonfuncs.c:310
HTAB * json_hash
Definition: jsonfuncs.c:309
union JsObject::@24 val
struct JsValue::@22::@23 json
JsonbValue * jsonb
Definition: jsonfuncs.c:300
bool is_json
Definition: jsonfuncs.c:290
union JsValue::@22 val

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().

◆ json_array_element()

Datum json_array_element ( PG_FUNCTION_ARGS  )

Definition at line 879 of file jsonfuncs.c.

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
static chr element(struct vars *v, const chr *startp, const chr *endp)
Definition: regc_locale.c:376

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

◆ json_array_element_text()

Datum json_array_element_text ( PG_FUNCTION_ARGS  )

Definition at line 922 of file jsonfuncs.c.

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 }

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

◆ json_array_elements()

Datum json_array_elements ( PG_FUNCTION_ARGS  )

Definition at line 2223 of file jsonfuncs.c.

2224 {
2225  return elements_worker(fcinfo, "json_array_elements", false);
2226 }
static Datum elements_worker(FunctionCallInfo fcinfo, const char *funcname, bool as_text)
Definition: jsonfuncs.c:2235

References elements_worker().

◆ json_array_elements_text()

Datum json_array_elements_text ( PG_FUNCTION_ARGS  )

Definition at line 2229 of file jsonfuncs.c.

2230 {
2231  return elements_worker(fcinfo, "json_array_elements_text", true);
2232 }

References elements_worker().

◆ json_array_length()

Datum json_array_length ( PG_FUNCTION_ARGS  )

Definition at line 1790 of file jsonfuncs.c.

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 }
#define PG_RETURN_INT32(x)
Definition: fmgr.h:354
static void alen_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:1852
static void alen_object_start(void *state)
Definition: jsonfuncs.c:1840
static void alen_array_element_start(void *state, bool isnull)
Definition: jsonfuncs.c:1864

References alen_array_element_start(), alen_object_start(), alen_scalar(), JsonSemAction::array_element_start, makeJsonLexContext(), JsonSemAction::object_start, palloc0(), PG_GETARG_TEXT_PP, pg_parse_json_or_ereport(), PG_RETURN_INT32, JsonSemAction::scalar, and JsonSemAction::semstate.

◆ json_each()

Datum json_each ( PG_FUNCTION_ARGS  )

Definition at line 1884 of file jsonfuncs.c.

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

References each_worker().

◆ json_each_text()

Datum json_each_text ( PG_FUNCTION_ARGS  )

Definition at line 1896 of file jsonfuncs.c.

1897 {
1898  return each_worker(fcinfo, true);
1899 }

References each_worker().

◆ json_ereport_error()

void json_ereport_error ( JsonParseErrorType  error,
JsonLexContext lex 
)

Definition at line 611 of file jsonfuncs.c.

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 }
int errdetail(const char *fmt,...)
Definition: elog.c:1037
char * json_errdetail(JsonParseErrorType error, JsonLexContext *lex)
Definition: jsonapi.c:1067
@ JSON_UNICODE_CODE_POINT_ZERO
Definition: jsonapi.h:51
@ JSON_UNICODE_HIGH_ESCAPE
Definition: jsonapi.h:53
static int report_json_context(JsonLexContext *lex)
Definition: jsonfuncs.c:639

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

Referenced by get_array_start(), json_get_first_token(), json_validate(), and pg_parse_json_or_ereport().

◆ json_extract_path()

Datum json_extract_path ( PG_FUNCTION_ARGS  )

Definition at line 966 of file jsonfuncs.c.

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

References get_path_all().

◆ json_extract_path_text()

Datum json_extract_path_text ( PG_FUNCTION_ARGS  )

Definition at line 972 of file jsonfuncs.c.

973 {
974  return get_path_all(fcinfo, true);
975 }

References get_path_all().

◆ json_get_first_token()

JsonTokenType json_get_first_token ( text json,
bool  throw_error 
)

Definition at line 5577 of file jsonfuncs.c.

5578 {
5579  JsonLexContext *lex;
5580  JsonParseErrorType result;
5581 
5582  lex = makeJsonLexContext(json, false);
5583 
5584  /* Lex exactly one token from the input and check its type. */
5585  result = json_lex(lex);
5586 
5587  if (result == JSON_SUCCESS)
5588  return lex->token_type;
5589 
5590  if (throw_error)
5591  json_ereport_error(result, lex);
5592 
5593  return JSON_TOKEN_INVALID; /* invalid json */
5594 }
JsonParseErrorType json_lex(JsonLexContext *lex)
Definition: jsonapi.c:519
@ JSON_TOKEN_INVALID
Definition: jsonapi.h:21

References json_ereport_error(), json_lex(), JSON_SUCCESS, JSON_TOKEN_INVALID, makeJsonLexContext(), and JsonLexContext::token_type.

Referenced by ExecEvalJsonIsPredicate(), and json_typeof().

◆ json_object_field()

Datum json_object_field ( PG_FUNCTION_ARGS  )

Definition at line 803 of file jsonfuncs.c.

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 }
char * text_to_cstring(const text *t)
Definition: varlena.c:221

References get_worker(), PG_GETARG_TEXT_PP, PG_RETURN_NULL, PG_RETURN_TEXT_P, and text_to_cstring().

◆ json_object_field_text()

Datum json_object_field_text ( PG_FUNCTION_ARGS  )

Definition at line 841 of file jsonfuncs.c.

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 }

References get_worker(), PG_GETARG_TEXT_PP, PG_RETURN_NULL, PG_RETURN_TEXT_P, and text_to_cstring().

◆ json_object_keys()

Datum json_object_keys ( PG_FUNCTION_ARGS  )

Definition at line 693 of file jsonfuncs.c.

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 }
#define SRF_IS_FIRSTCALL()
Definition: funcapi.h:299
#define SRF_PERCALL_SETUP()
Definition: funcapi.h:303
#define SRF_RETURN_NEXT(_funcctx, _result)
Definition: funcapi.h:305
#define SRF_FIRSTCALL_INIT()
Definition: funcapi.h:301
#define SRF_RETURN_DONE(_funcctx)
Definition: funcapi.h:323
static void okeys_object_field_start(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:749
static void okeys_array_start(void *state)
Definition: jsonfuncs.c:770
static void okeys_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:783
void * user_fctx
Definition: funcapi.h:82
MemoryContext multi_call_memory_ctx
Definition: funcapi.h:101
StringInfo strval
Definition: jsonapi.h:84

References JsonSemAction::array_start, CStringGetTextDatum, StringInfoData::data, if(), 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(), JsonSemAction::scalar, JsonSemAction::semstate, SRF_FIRSTCALL_INIT, SRF_IS_FIRSTCALL, SRF_PERCALL_SETUP, SRF_RETURN_DONE, SRF_RETURN_NEXT, JsonLexContext::strval, and FuncCallContext::user_fctx.

◆ json_populate_record()

Datum json_populate_record ( PG_FUNCTION_ARGS  )

Definition at line 2395 of file jsonfuncs.c.

2396 {
2397  return populate_record_worker(fcinfo, "json_populate_record",
2398  true, true);
2399 }
static Datum populate_record_worker(FunctionCallInfo fcinfo, const char *funcname, bool is_json, bool have_record_arg)
Definition: jsonfuncs.c:3403

References populate_record_worker().

◆ json_populate_recordset()

Datum json_populate_recordset ( PG_FUNCTION_ARGS  )

Definition at line 3670 of file jsonfuncs.c.

3671 {
3672  return populate_recordset_worker(fcinfo, "json_populate_recordset",
3673  true, true);
3674 }
static Datum populate_recordset_worker(FunctionCallInfo fcinfo, const char *funcname, bool is_json, bool have_record_arg)
Definition: jsonfuncs.c:3721

References populate_recordset_worker().

◆ json_populate_type()

Datum json_populate_type ( Datum  json_val,
Oid  json_type,
Oid  typid,
int32  typmod,
void **  cache,
MemoryContext  mcxt,
bool isnull 
)

Definition at line 3139 of file jsonfuncs.c.

3141 {
3142  JsValue jsv = {0};
3143  JsonbValue jbv;
3144 
3145  jsv.is_json = json_type == JSONOID;
3146 
3147  if (*isnull)
3148  {
3149  if (jsv.is_json)
3150  jsv.val.json.str = NULL;
3151  else
3152  jsv.val.jsonb = NULL;
3153  }
3154  else if (jsv.is_json)
3155  {
3156  text *json = DatumGetTextPP(json_val);
3157 
3158  jsv.val.json.str = VARDATA_ANY(json);
3159  jsv.val.json.len = VARSIZE_ANY_EXHDR(json);
3160  jsv.val.json.type = JSON_TOKEN_INVALID; /* not used in
3161  * populate_composite() */
3162  }
3163  else
3164  {
3165  Jsonb *jsonb = DatumGetJsonbP(json_val);
3166 
3167  jsv.val.jsonb = &jbv;
3168 
3169  /* fill binary jsonb value pointing to jb */
3170  jbv.type = jbvBinary;
3171  jbv.val.binary.data = &jsonb->root;
3172  jbv.val.binary.len = VARSIZE(jsonb) - VARHDRSZ;
3173  }
3174 
3175  if (!*cache)
3176  *cache = MemoryContextAllocZero(mcxt, sizeof(ColumnIOData));
3177 
3178  return populate_record_field(*cache, typid, typmod, NULL, mcxt,
3179  PointerGetDatum(NULL), &jsv, isnull);
3180 }
#define VARHDRSZ
Definition: c.h:627
#define DatumGetTextPP(X)
Definition: fmgr.h:292
@ jbvBinary
Definition: jsonb.h:244
#define DatumGetJsonbP(d)
Definition: jsonb.h:71
static Datum populate_record_field(ColumnIOData *col, Oid typid, int32 typmod, const char *colname, MemoryContext mcxt, Datum defaultval, JsValue *jsv, bool *isnull)
Definition: jsonfuncs.c:3073
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition: mcxt.c:906
#define VARDATA_ANY(PTR)
Definition: postgres.h:361
#define VARSIZE(PTR)
Definition: postgres.h:316
#define VARSIZE_ANY_EXHDR(PTR)
Definition: postgres.h:354

References DatumGetJsonbP, DatumGetTextPP, JsValue::is_json, jbvBinary, JsValue::json, JSON_TOKEN_INVALID, JsValue::jsonb, MemoryContextAllocZero(), PointerGetDatum, populate_record_field(), Jsonb::root, JsonbValue::type, JsValue::val, JsonbValue::val, VARDATA_ANY, VARHDRSZ, VARSIZE, and VARSIZE_ANY_EXHDR.

Referenced by ExecEvalJsonExprCoercion().

◆ json_strip_nulls()

Datum json_strip_nulls ( PG_FUNCTION_ARGS  )

Definition at line 4144 of file jsonfuncs.c.

4145 {
4146  text *json = PG_GETARG_TEXT_PP(0);
4148  JsonLexContext *lex;
4149  JsonSemAction *sem;
4150 
4151  lex = makeJsonLexContext(json, true);
4152  state = palloc0(sizeof(StripnullState));
4153  sem = palloc0(sizeof(JsonSemAction));
4154 
4155  state->strval = makeStringInfo();
4156  state->skip_next_null = false;
4157  state->lex = lex;
4158 
4159  sem->semstate = (void *) state;
4161  sem->object_end = sn_object_end;
4162  sem->array_start = sn_array_start;
4163  sem->array_end = sn_array_end;
4164  sem->scalar = sn_scalar;
4167 
4168  pg_parse_json_or_ereport(lex, sem);
4169 
4171  state->strval->len));
4172 }
static void sn_array_end(void *state)
Definition: jsonfuncs.c:4078
static void sn_object_end(void *state)
Definition: jsonfuncs.c:4062
static void sn_array_element_start(void *state, bool isnull)
Definition: jsonfuncs.c:4114
static void sn_object_field_start(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:4086
static void sn_array_start(void *state)
Definition: jsonfuncs.c:4070
static void sn_object_start(void *state)
Definition: jsonfuncs.c:4054
static void sn_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:4123
StringInfo makeStringInfo(void)
Definition: stringinfo.c:41

References JsonSemAction::array_element_start, JsonSemAction::array_end, JsonSemAction::array_start, cstring_to_text_with_len(), 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, sn_array_element_start(), sn_array_end(), sn_array_start(), sn_object_end(), sn_object_field_start(), sn_object_start(), and sn_scalar().

◆ json_to_record()

Datum json_to_record ( PG_FUNCTION_ARGS  )

Definition at line 2402 of file jsonfuncs.c.

2403 {
2404  return populate_record_worker(fcinfo, "json_to_record",
2405  true, false);
2406 }

References populate_record_worker().

◆ json_to_recordset()

Datum json_to_recordset ( PG_FUNCTION_ARGS  )

Definition at line 3677 of file jsonfuncs.c.

3678 {
3679  return populate_recordset_worker(fcinfo, "json_to_recordset",
3680  true, false);
3681 }

References populate_recordset_worker().

◆ jsonb_array_element()

Datum jsonb_array_element ( PG_FUNCTION_ARGS  )

Definition at line 894 of file jsonfuncs.c.

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 
915  if (v != NULL)
917 
918  PG_RETURN_NULL();
919 }
unsigned int uint32
Definition: c.h:441
#define PG_RETURN_JSONB_P(x)
Definition: jsonb.h:76
#define JB_ROOT_COUNT(jbp_)
Definition: jsonb.h:227
JsonbValue * getIthJsonbValueFromContainer(JsonbContainer *container, uint32 i)
Definition: jsonb_util.c:470

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.

◆ jsonb_array_element_text()

Datum jsonb_array_element_text ( PG_FUNCTION_ARGS  )

Definition at line 937 of file jsonfuncs.c.

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 
958 
959  if (v != NULL && v->type != jbvNull)
961 
962  PG_RETURN_NULL();
963 }

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.

◆ jsonb_array_elements()

Datum jsonb_array_elements ( PG_FUNCTION_ARGS  )

Definition at line 2134 of file jsonfuncs.c.

2135 {
2136  return elements_worker_jsonb(fcinfo, "jsonb_array_elements", false);
2137 }
static Datum elements_worker_jsonb(FunctionCallInfo fcinfo, const char *funcname, bool as_text)
Definition: jsonfuncs.c:2146

References elements_worker_jsonb().

◆ jsonb_array_elements_text()

Datum jsonb_array_elements_text ( PG_FUNCTION_ARGS  )

Definition at line 2140 of file jsonfuncs.c.

2141 {
2142  return elements_worker_jsonb(fcinfo, "jsonb_array_elements_text", true);
2143 }

References elements_worker_jsonb().

◆ jsonb_array_length()

Datum jsonb_array_length ( PG_FUNCTION_ARGS  )

Definition at line 1818 of file jsonfuncs.c.

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 }

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

◆ jsonb_concat()

Datum jsonb_concat ( PG_FUNCTION_ARGS  )

Definition at line 4252 of file jsonfuncs.c.

4253 {
4254  Jsonb *jb1 = PG_GETARG_JSONB_P(0);
4255  Jsonb *jb2 = PG_GETARG_JSONB_P(1);
4256  JsonbParseState *state = NULL;
4257  JsonbValue *res;
4258  JsonbIterator *it1,
4259  *it2;
4260 
4261  /*
4262  * If one of the jsonb is empty, just return the other if it's not scalar
4263  * and both are of the same kind. If it's a scalar or they are of
4264  * different kinds we need to perform the concatenation even if one is
4265  * empty.
4266  */
4267  if (JB_ROOT_IS_OBJECT(jb1) == JB_ROOT_IS_OBJECT(jb2))
4268  {
4269  if (JB_ROOT_COUNT(jb1) == 0 && !JB_ROOT_IS_SCALAR(jb2))
4270  PG_RETURN_JSONB_P(jb2);
4271  else if (JB_ROOT_COUNT(jb2) == 0 && !JB_ROOT_IS_SCALAR(jb1))
4272  PG_RETURN_JSONB_P(jb1);
4273  }
4274 
4275  it1 = JsonbIteratorInit(&jb1->root);
4276  it2 = JsonbIteratorInit(&jb2->root);
4277 
4278  res = IteratorConcat(&it1, &it2, &state);
4279 
4280  Assert(res != NULL);
4281 
4283 }
static JsonbValue * IteratorConcat(JsonbIterator **it1, JsonbIterator **it2, JsonbParseState **state)
Definition: jsonfuncs.c:4708

References Assert(), IteratorConcat(), JB_ROOT_COUNT, JB_ROOT_IS_OBJECT, JB_ROOT_IS_SCALAR, JsonbIteratorInit(), JsonbValueToJsonb(), PG_GETARG_JSONB_P, PG_RETURN_JSONB_P, res, and Jsonb::root.

◆ jsonb_delete()

Datum jsonb_delete ( PG_FUNCTION_ARGS  )

Definition at line 4293 of file jsonfuncs.c.

4294 {
4295  Jsonb *in = PG_GETARG_JSONB_P(0);
4296  text *key = PG_GETARG_TEXT_PP(1);
4297  char *keyptr = VARDATA_ANY(key);
4298  int keylen = VARSIZE_ANY_EXHDR(key);
4299  JsonbParseState *state = NULL;
4300  JsonbIterator *it;
4301  JsonbValue v,
4302  *res = NULL;
4303  bool skipNested = false;
4305 
4306  if (JB_ROOT_IS_SCALAR(in))
4307  ereport(ERROR,
4308  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4309  errmsg("cannot delete from scalar")));
4310 
4311  if (JB_ROOT_COUNT(in) == 0)
4312  PG_RETURN_JSONB_P(in);
4313 
4314  it = JsonbIteratorInit(&in->root);
4315 
4316  while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE)
4317  {
4318  skipNested = true;
4319 
4320  if ((r == WJB_ELEM || r == WJB_KEY) &&
4321  (v.type == jbvString && keylen == v.val.string.len &&
4322  memcmp(keyptr, v.val.string.val, keylen) == 0))
4323  {
4324  /* skip corresponding value as well */
4325  if (r == WJB_KEY)
4326  (void) JsonbIteratorNext(&it, &v, true);
4327 
4328  continue;
4329  }
4330 
4331  res = pushJsonbValue(&state, r, r < WJB_BEGIN_ARRAY ? &v : NULL);
4332  }
4333 
4334  Assert(res != NULL);
4335 
4337 }

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(), res, Jsonb::root, JsonbValue::type, JsonbValue::val, VARDATA_ANY, VARSIZE_ANY_EXHDR, WJB_BEGIN_ARRAY, WJB_DONE, WJB_ELEM, and WJB_KEY.

◆ jsonb_delete_array()

Datum jsonb_delete_array ( PG_FUNCTION_ARGS  )

Definition at line 4346 of file jsonfuncs.c.

4347 {
4348  Jsonb *in = PG_GETARG_JSONB_P(0);
4349  ArrayType *keys = PG_GETARG_ARRAYTYPE_P(1);
4350  Datum *keys_elems;
4351  bool *keys_nulls;
4352  int keys_len;
4353  JsonbParseState *state = NULL;
4354  JsonbIterator *it;
4355  JsonbValue v,
4356  *res = NULL;
4357  bool skipNested = false;
4359 
4360  if (ARR_NDIM(keys) > 1)
4361  ereport(ERROR,
4362  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
4363  errmsg("wrong number of array subscripts")));
4364 
4365  if (JB_ROOT_IS_SCALAR(in))
4366  ereport(ERROR,
4367  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4368  errmsg("cannot delete from scalar")));
4369 
4370  if (JB_ROOT_COUNT(in) == 0)
4371  PG_RETURN_JSONB_P(in);
4372 
4373  deconstruct_array(keys, TEXTOID, -1, false, TYPALIGN_INT,
4374  &keys_elems, &keys_nulls, &keys_len);
4375 
4376  if (keys_len == 0)
4377  PG_RETURN_JSONB_P(in);
4378 
4379  it = JsonbIteratorInit(&in->root);
4380 
4381  while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE)
4382  {
4383  skipNested = true;
4384 
4385  if ((r == WJB_ELEM || r == WJB_KEY) && v.type == jbvString)
4386  {
4387  int i;
4388  bool found = false;
4389 
4390  for (i = 0; i < keys_len; i++)
4391  {
4392  char *keyptr;
4393  int keylen;
4394 
4395  if (keys_nulls[i])
4396  continue;
4397 
4398  keyptr = VARDATA_ANY(keys_elems[i]);
4399  keylen = VARSIZE_ANY_EXHDR(keys_elems[i]);
4400  if (keylen == v.val.string.len &&
4401  memcmp(keyptr, v.val.string.val, keylen) == 0)
4402  {
4403  found = true;
4404  break;
4405  }
4406  }
4407  if (found)
4408  {
4409  /* skip corresponding value as well */
4410  if (r == WJB_KEY)
4411  (void) JsonbIteratorNext(&it, &v, true);
4412 
4413  continue;
4414  }
4415  }
4416 
4417  res = pushJsonbValue(&state, r, r < WJB_BEGIN_ARRAY ? &v : NULL);
4418  }
4419 
4420  Assert(res != NULL);
4421 
4423 }
#define ARR_NDIM(a)
Definition: array.h:283

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(), res, Jsonb::root, JsonbValue::type, JsonbValue::val, VARDATA_ANY, VARSIZE_ANY_EXHDR, WJB_BEGIN_ARRAY, WJB_DONE, WJB_ELEM, and WJB_KEY.

◆ jsonb_delete_idx()

Datum jsonb_delete_idx ( PG_FUNCTION_ARGS  )

Definition at line 4433 of file jsonfuncs.c.

4434 {
4435  Jsonb *in = PG_GETARG_JSONB_P(0);
4436  int idx = PG_GETARG_INT32(1);
4437  JsonbParseState *state = NULL;
4438  JsonbIterator *it;
4439  uint32 i = 0,
4440  n;
4441  JsonbValue v,
4442  *res = NULL;
4444 
4445  if (JB_ROOT_IS_SCALAR(in))
4446  ereport(ERROR,
4447  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4448  errmsg("cannot delete from scalar")));
4449 
4450  if (JB_ROOT_IS_OBJECT(in))
4451  ereport(ERROR,
4452  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4453  errmsg("cannot delete from object using integer index")));
4454 
4455  if (JB_ROOT_COUNT(in) == 0)
4456  PG_RETURN_JSONB_P(in);
4457 
4458  it = JsonbIteratorInit(&in->root);
4459 
4460  r = JsonbIteratorNext(&it, &v, false);
4461  Assert(r == WJB_BEGIN_ARRAY);
4462  n = v.val.array.nElems;
4463 
4464  if (idx < 0)
4465  {
4466  if (-idx > n)
4467  idx = n;
4468  else
4469  idx = n + idx;
4470  }
4471 
4472  if (idx >= n)
4473  PG_RETURN_JSONB_P(in);
4474 
4475  pushJsonbValue(&state, r, NULL);
4476 
4477  while ((r = JsonbIteratorNext(&it, &v, true)) != WJB_DONE)
4478  {
4479  if (r == WJB_ELEM)
4480  {
4481  if (i++ == idx)
4482  continue;
4483  }
4484 
4485  res = pushJsonbValue(&state, r, r < WJB_BEGIN_ARRAY ? &v : NULL);
4486  }
4487 
4488  Assert(res != NULL);
4489 
4491 }
Datum idx(PG_FUNCTION_ARGS)
Definition: _int_op.c:259

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(), res, Jsonb::root, JsonbValue::val, WJB_BEGIN_ARRAY, WJB_DONE, and WJB_ELEM.

◆ jsonb_delete_path()

Datum jsonb_delete_path ( PG_FUNCTION_ARGS  )

Definition at line 4614 of file jsonfuncs.c.

4615 {
4616  Jsonb *in = PG_GETARG_JSONB_P(0);
4617  ArrayType *path = PG_GETARG_ARRAYTYPE_P(1);
4618  JsonbValue *res = NULL;
4619  Datum *path_elems;
4620  bool *path_nulls;
4621  int path_len;
4622  JsonbIterator *it;
4623  JsonbParseState *st = NULL;
4624 
4625  if (ARR_NDIM(path) > 1)
4626  ereport(ERROR,
4627  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
4628  errmsg("wrong number of array subscripts")));
4629 
4630  if (JB_ROOT_IS_SCALAR(in))
4631  ereport(ERROR,
4632  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4633  errmsg("cannot delete path in scalar")));
4634 
4635  if (JB_ROOT_COUNT(in) == 0)
4636  PG_RETURN_JSONB_P(in);
4637 
4638  deconstruct_array(path, TEXTOID, -1, false, TYPALIGN_INT,
4639  &path_elems, &path_nulls, &path_len);
4640 
4641  if (path_len == 0)
4642  PG_RETURN_JSONB_P(in);
4643 
4644  it = JsonbIteratorInit(&in->root);
4645 
4646  res = setPath(&it, path_elems, path_nulls, path_len, &st,
4647  0, NULL, JB_PATH_DELETE);
4648 
4649  Assert(res != NULL);
4650 
4652 }
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:4836
#define JB_PATH_DELETE
Definition: jsonfuncs.c:42

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, res, Jsonb::root, and setPath().

Referenced by jsonb_set_lax().

◆ jsonb_each()

Datum jsonb_each ( PG_FUNCTION_ARGS  )

Definition at line 1890 of file jsonfuncs.c.

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

References each_worker_jsonb().

◆ jsonb_each_text()

Datum jsonb_each_text ( PG_FUNCTION_ARGS  )

Definition at line 1902 of file jsonfuncs.c.

1903 {
1904  return each_worker_jsonb(fcinfo, "jsonb_each_text", true);
1905 }

References each_worker_jsonb().

◆ jsonb_extract_path()

Datum jsonb_extract_path ( PG_FUNCTION_ARGS  )

Definition at line 1427 of file jsonfuncs.c.

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

References get_jsonb_path_all().

◆ jsonb_extract_path_text()

Datum jsonb_extract_path_text ( PG_FUNCTION_ARGS  )

Definition at line 1433 of file jsonfuncs.c.

1434 {
1435  return get_jsonb_path_all(fcinfo, true);
1436 }

References get_jsonb_path_all().

◆ 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.

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 */
1613  }
1614 }
#define elog(elevel,...)
Definition: elog.h:218
char * JsonbToCString(StringInfo out, JsonbContainer *in, int estimated_len)
Definition: jsonb.c:450
#define JsonContainerIsScalar(jc)
Definition: jsonb.h:215
#define JsonContainerIsArray(jc)
Definition: jsonb.h:217
#define JsonContainerSize(jc)
Definition: jsonb.h:214
#define IsAJsonbScalar(jsonbval)
Definition: jsonb.h:305
#define JsonContainerIsObject(jc)
Definition: jsonb.h:216
#define VARDATA(PTR)
Definition: postgres.h:315
Definition: type.h:90

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, res, 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().

◆ jsonb_insert()

Datum jsonb_insert ( PG_FUNCTION_ARGS  )

Definition at line 4658 of file jsonfuncs.c.

4659 {
4660  Jsonb *in = PG_GETARG_JSONB_P(0);
4661  ArrayType *path = PG_GETARG_ARRAYTYPE_P(1);
4662  Jsonb *newjsonb = PG_GETARG_JSONB_P(2);
4664  bool after = PG_GETARG_BOOL(3);
4665  JsonbValue *res = NULL;
4666  Datum *path_elems;
4667  bool *path_nulls;
4668  int path_len;
4669  JsonbIterator *it;
4670  JsonbParseState *st = NULL;
4671 
4672  JsonbToJsonbValue(newjsonb, &newval);
4673 
4674  if (ARR_NDIM(path) > 1)
4675  ereport(ERROR,
4676  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
4677  errmsg("wrong number of array subscripts")));
4678 
4679  if (JB_ROOT_IS_SCALAR(in))
4680  ereport(ERROR,
4681  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4682  errmsg("cannot set path in scalar")));
4683 
4684  deconstruct_array(path, TEXTOID, -1, false, TYPALIGN_INT,
4685  &path_elems, &path_nulls, &path_len);
4686 
4687  if (path_len == 0)
4688  PG_RETURN_JSONB_P(in);
4689 
4690  it = JsonbIteratorInit(&in->root);
4691 
4692  res = setPath(&it, path_elems, path_nulls, path_len, &st, 0, &newval,
4694 
4695  Assert(res != NULL);
4696 
4698 }
#define PG_GETARG_BOOL(n)
Definition: fmgr.h:274
#define newval
void JsonbToJsonbValue(Jsonb *jsonb, JsonbValue *val)
Definition: jsonb_util.c:74
#define JB_PATH_INSERT_BEFORE
Definition: jsonfuncs.c:44
#define JB_PATH_INSERT_AFTER
Definition: jsonfuncs.c:45

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

◆ jsonb_object_field()

Datum jsonb_object_field ( PG_FUNCTION_ARGS  )

Definition at line 819 of file jsonfuncs.c.

820 {
821  Jsonb *jb = PG_GETARG_JSONB_P(0);
822  text *key = PG_GETARG_TEXT_PP(1);
823  JsonbValue *v;
824  JsonbValue vbuf;
825 
826  if (!JB_ROOT_IS_OBJECT(jb))
827  PG_RETURN_NULL();
828 
830  VARDATA_ANY(key),
832  &vbuf);
833 
834  if (v != NULL)
836 
837  PG_RETURN_NULL();
838 }

References getKeyJsonValueFromContainer(), JB_ROOT_IS_OBJECT, JsonbValueToJsonb(), sort-test::key, PG_GETARG_JSONB_P, PG_GETARG_TEXT_PP, PG_RETURN_JSONB_P, PG_RETURN_NULL, Jsonb::root, VARDATA_ANY, and VARSIZE_ANY_EXHDR.

◆ jsonb_object_field_text()

Datum jsonb_object_field_text ( PG_FUNCTION_ARGS  )

Definition at line 857 of file jsonfuncs.c.

858 {
859  Jsonb *jb = PG_GETARG_JSONB_P(0);
860  text *key = PG_GETARG_TEXT_PP(1);
861  JsonbValue *v;
862  JsonbValue vbuf;
863 
864  if (!JB_ROOT_IS_OBJECT(jb))
865  PG_RETURN_NULL();
866 
868  VARDATA_ANY(key),
870  &vbuf);
871 
872  if (v != NULL && v->type != jbvNull)
874 
875  PG_RETURN_NULL();
876 }

References getKeyJsonValueFromContainer(), JB_ROOT_IS_OBJECT, jbvNull, JsonbValueAsText(), sort-test::key, PG_GETARG_JSONB_P, PG_GETARG_TEXT_PP, PG_RETURN_NULL, PG_RETURN_TEXT_P, Jsonb::root, JsonbValue::type, VARDATA_ANY, and VARSIZE_ANY_EXHDR.

◆ jsonb_object_keys()

Datum jsonb_object_keys ( PG_FUNCTION_ARGS  )

Definition at line 538 of file jsonfuncs.c.

539 {
540  FuncCallContext *funcctx;
541  OkeysState *state;
542 
543  if (SRF_IS_FIRSTCALL())
544  {
545  MemoryContext oldcontext;
546  Jsonb *jb = PG_GETARG_JSONB_P(0);
547  bool skipNested = false;
548  JsonbIterator *it;
549  JsonbValue v;
551 
552  if (JB_ROOT_IS_SCALAR(jb))
553  ereport(ERROR,
554  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
555  errmsg("cannot call %s on a scalar",
556  "jsonb_object_keys")));
557  else if (JB_ROOT_IS_ARRAY(jb))
558  ereport(ERROR,
559  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
560  errmsg("cannot call %s on an array",
561  "jsonb_object_keys")));
562 
563  funcctx = SRF_FIRSTCALL_INIT();
564  oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
565 
566  state = palloc(sizeof(OkeysState));
567 
568  state->result_size = JB_ROOT_COUNT(jb);
569  state->result_count = 0;
570  state->sent_count = 0;
571  state->result = palloc(state->result_size * sizeof(char *));
572 
573  it = JsonbIteratorInit(&jb->root);
574 
575  while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE)
576  {
577  skipNested = true;
578 
579  if (r == WJB_KEY)
580  {
581  char *cstr;
582 
583  cstr = palloc(v.val.string.len + 1 * sizeof(char));
584  memcpy(cstr, v.val.string.val, v.val.string.len);
585  cstr[v.val.string.len] = '\0';
586  state->result[state->result_count++] = cstr;
587  }
588  }
589 
590  MemoryContextSwitchTo(oldcontext);
591  funcctx->user_fctx = (void *) state;
592  }
593 
594  funcctx = SRF_PERCALL_SETUP();
595  state = (OkeysState *) funcctx->user_fctx;
596 
597  if (state->sent_count < state->result_count)
598  {
599  char *nxt = state->result[state->sent_count++];
600 
601  SRF_RETURN_NEXT(funcctx, CStringGetTextDatum(nxt));
602  }
603 
604  SRF_RETURN_DONE(funcctx);
605 }

References CStringGetTextDatum, ereport, errcode(), errmsg(), ERROR, if(), JB_ROOT_COUNT, JB_ROOT_IS_ARRAY, JB_ROOT_IS_SCALAR, JsonbIteratorInit(), JsonbIteratorNext(), MemoryContextSwitchTo(), FuncCallContext::multi_call_memory_ctx, palloc(), PG_GETARG_JSONB_P, Jsonb::root, SRF_FIRSTCALL_INIT, SRF_IS_FIRSTCALL, SRF_PERCALL_SETUP, SRF_RETURN_DONE, SRF_RETURN_NEXT, FuncCallContext::user_fctx, JsonbValue::val, WJB_DONE, and WJB_KEY.

◆ jsonb_populate_record()

Datum jsonb_populate_record ( PG_FUNCTION_ARGS  )

Definition at line 2381 of file jsonfuncs.c.

2382 {
2383  return populate_record_worker(fcinfo, "jsonb_populate_record",
2384  false, true);
2385 }

References populate_record_worker().

◆ jsonb_populate_recordset()

Datum jsonb_populate_recordset ( PG_FUNCTION_ARGS  )

Definition at line 3656 of file jsonfuncs.c.

3657 {
3658  return populate_recordset_worker(fcinfo, "jsonb_populate_recordset",
3659  false, true);
3660 }

References populate_recordset_worker().

◆ jsonb_pretty()

Datum jsonb_pretty ( PG_FUNCTION_ARGS  )

Definition at line 4236 of file jsonfuncs.c.

4237 {
4238  Jsonb *jb = PG_GETARG_JSONB_P(0);
4240 
4241  JsonbToCStringIndent(str, &jb->root, VARSIZE(jb));
4242 
4244 }
char * JsonbToCStringIndent(StringInfo out, JsonbContainer *in, int estimated_len)
Definition: jsonb.c:459

References cstring_to_text_with_len(), JsonbToCStringIndent(), makeStringInfo(), PG_GETARG_JSONB_P, PG_RETURN_TEXT_P, Jsonb::root, generate_unaccent_rules::str, and VARSIZE.

◆ jsonb_set()

Datum jsonb_set ( PG_FUNCTION_ARGS  )

Definition at line 4497 of file jsonfuncs.c.

4498 {
4499  Jsonb *in = PG_GETARG_JSONB_P(0);
4500  ArrayType *path = PG_GETARG_ARRAYTYPE_P(1);
4501  Jsonb *newjsonb = PG_GETARG_JSONB_P(2);
4503  bool create = PG_GETARG_BOOL(3);
4504  JsonbValue *res = NULL;
4505  Datum *path_elems;
4506  bool *path_nulls;
4507  int path_len;
4508  JsonbIterator *it;
4509  JsonbParseState *st = NULL;
4510 
4511  JsonbToJsonbValue(newjsonb, &newval);
4512 
4513  if (ARR_NDIM(path) > 1)
4514  ereport(ERROR,
4515  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
4516  errmsg("wrong number of array subscripts")));
4517 
4518  if (JB_ROOT_IS_SCALAR(in))
4519  ereport(ERROR,
4520  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4521  errmsg("cannot set path in scalar")));
4522 
4523  if (JB_ROOT_COUNT(in) == 0 && !create)
4524  PG_RETURN_JSONB_P(in);
4525 
4526  deconstruct_array(path, TEXTOID, -1, false, TYPALIGN_INT,
4527  &path_elems, &path_nulls, &path_len);
4528 
4529  if (path_len == 0)
4530  PG_RETURN_JSONB_P(in);
4531 
4532  it = JsonbIteratorInit(&in->root);
4533 
4534  res = setPath(&it, path_elems, path_nulls, path_len, &st,
4535  0, &newval, create ? JB_PATH_CREATE : JB_PATH_REPLACE);
4536 
4537  Assert(res != NULL);
4538 
4540 }
#define JB_PATH_CREATE
Definition: jsonfuncs.c:41
#define JB_PATH_REPLACE
Definition: jsonfuncs.c:43

References ARR_NDIM, Assert(), deconstruct_array(), ereport, errcode(), errmsg(), ERROR, JB_PATH_CREATE, JB_PATH_REPLACE, JB_ROOT_COUNT, JB_ROOT_IS_SCALAR, JsonbIteratorInit(), JsonbToJsonbValue(), JsonbValueToJsonb(), newval, PG_GETARG_ARRAYTYPE_P, PG_GETARG_BOOL, PG_GETARG_JSONB_P, PG_RETURN_JSONB_P, res, Jsonb::root, and setPath().

Referenced by jsonb_set_lax().

◆ jsonb_set_element()

Datum jsonb_set_element ( Jsonb jb,
Datum path,
int  path_len,
JsonbValue newval 
)

Definition at line 1617 of file jsonfuncs.c.

1619 {
1620  JsonbValue *res;
1621  JsonbParseState *state = NULL;
1622  JsonbIterator *it;
1623  bool *path_nulls = palloc0(path_len * sizeof(bool));
1624 
1625  if (newval->type == jbvArray && newval->val.array.rawScalar)
1626  *newval = newval->val.array.elems[0];
1627 
1628  it = JsonbIteratorInit(&jb->root);
1629 
1630  res = setPath(&it, path, path_nulls, path_len, &state, 0, newval,
1633 
1634  pfree(path_nulls);
1635 
1637 }
@ jbvArray
Definition: jsonb.h:241
#define JB_PATH_CONSISTENT_POSITION
Definition: jsonfuncs.c:49
#define JB_PATH_FILL_GAPS
Definition: jsonfuncs.c:48

References JB_PATH_CONSISTENT_POSITION, JB_PATH_CREATE, JB_PATH_FILL_GAPS, jbvArray, JsonbIteratorInit(), JsonbValueToJsonb(), newval, palloc0(), pfree(), PG_RETURN_JSONB_P, res, Jsonb::root, and setPath().

Referenced by jsonb_subscript_assign().

◆ jsonb_set_lax()

Datum jsonb_set_lax ( PG_FUNCTION_ARGS  )

Definition at line 4547 of file jsonfuncs.c.

4548 {
4549  /* Jsonb *in = PG_GETARG_JSONB_P(0); */
4550  /* ArrayType *path = PG_GETARG_ARRAYTYPE_P(1); */
4551  /* Jsonb *newval = PG_GETARG_JSONB_P(2); */
4552  /* bool create = PG_GETARG_BOOL(3); */
4553  text *handle_null;
4554  char *handle_val;
4555 
4556  if (PG_ARGISNULL(0) || PG_ARGISNULL(1) || PG_ARGISNULL(3))
4557  PG_RETURN_NULL();
4558 
4559  /* could happen if they pass in an explicit NULL */
4560  if (PG_ARGISNULL(4))
4561  ereport(ERROR,
4562  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4563  errmsg("null_value_treatment must be \"delete_key\", \"return_target\", \"use_json_null\", or \"raise_exception\"")));
4564 
4565  /* if the new value isn't an SQL NULL just call jsonb_set */
4566  if (!PG_ARGISNULL(2))
4567  return jsonb_set(fcinfo);
4568 
4569  handle_null = PG_GETARG_TEXT_P(4);
4570  handle_val = text_to_cstring(handle_null);
4571 
4572  if (strcmp(handle_val, "raise_exception") == 0)
4573  {
4574  ereport(ERROR,
4575  (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
4576  errmsg("JSON value must not be null"),
4577  errdetail("Exception was raised because null_value_treatment is \"raise_exception\"."),
4578  errhint("To avoid, either change the null_value_treatment argument or ensure that an SQL NULL is not passed.")));
4579  return (Datum) 0; /* silence stupider compilers */
4580  }
4581  else if (strcmp(handle_val, "use_json_null") == 0)
4582  {
4583  Datum newval;
4584 
4586 
4587  fcinfo->args[2].value = newval;
4588  fcinfo->args[2].isnull = false;
4589  return jsonb_set(fcinfo);
4590  }
4591  else if (strcmp(handle_val, "delete_key") == 0)
4592  {
4593  return jsonb_delete_path(fcinfo);
4594  }
4595  else if (strcmp(handle_val, "return_target") == 0)
4596  {
4597  Jsonb *in = PG_GETARG_JSONB_P(0);
4598 
4599  PG_RETURN_JSONB_P(in);
4600  }
4601  else
4602  {
4603  ereport(ERROR,
4604  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4605  errmsg("null_value_treatment must be \"delete_key\", \"return_target\", \"use_json_null\", or \"raise_exception\"")));
4606  return (Datum) 0; /* silence stupider compilers */
4607  }
4608 }
#define PG_ARGISNULL(n)
Definition: fmgr.h:209
#define PG_GETARG_TEXT_P(n)
Definition: fmgr.h:336
Datum jsonb_in(PG_FUNCTION_ARGS)
Definition: jsonb.c:76
Datum jsonb_delete_path(PG_FUNCTION_ARGS)
Definition: jsonfuncs.c:4614
Datum jsonb_set(PG_FUNCTION_ARGS)
Definition: jsonfuncs.c:4497
#define CStringGetDatum(X)
Definition: postgres.h:622

References CStringGetDatum, DirectFunctionCall1, ereport, errcode(), errdetail(), errhint(), errmsg(), ERROR, jsonb_delete_path(), jsonb_in(), jsonb_set(), newval, PG_ARGISNULL, PG_GETARG_JSONB_P, PG_GETARG_TEXT_P, PG_RETURN_JSONB_P, PG_RETURN_NULL, and text_to_cstring().

◆ jsonb_strip_nulls()

Datum jsonb_strip_nulls ( PG_FUNCTION_ARGS  )

Definition at line 4178 of file jsonfuncs.c.

4179 {
4180  Jsonb *jb = PG_GETARG_JSONB_P(0);
4181  JsonbIterator *it;
4182  JsonbParseState *parseState = NULL;
4183  JsonbValue *res = NULL;
4184  JsonbValue v,
4185  k;
4187  bool last_was_key = false;
4188 
4189  if (JB_ROOT_IS_SCALAR(jb))
4190  PG_RETURN_POINTER(jb);
4191 
4192  it = JsonbIteratorInit(&jb->root);
4193 
4194  while ((type = JsonbIteratorNext(&it, &v, false)) != WJB_DONE)
4195  {
4196  Assert(!(type == WJB_KEY && last_was_key));
4197 
4198  if (type == WJB_KEY)
4199  {
4200  /* stash the key until we know if it has a null value */
4201  k = v;
4202  last_was_key = true;
4203  continue;
4204  }
4205 
4206  if (last_was_key)
4207  {
4208  /* if the last element was a key this one can't be */
4209  last_was_key = false;
4210 
4211  /* skip this field if value is null */
4212  if (type == WJB_VALUE && v.type == jbvNull)
4213  continue;
4214 
4215  /* otherwise, do a delayed push of the key */
4216  (void) pushJsonbValue(&parseState, WJB_KEY, &k);
4217  }
4218 
4219  if (type == WJB_VALUE || type == WJB_ELEM)
4220  res = pushJsonbValue(&parseState, type, &v);
4221  else
4222  res = pushJsonbValue(&parseState, type, NULL);
4223  }
4224 
4225  Assert(res != NULL);
4226 
4228 }
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:361

References Assert(), JB_ROOT_IS_SCALAR, jbvNull, JsonbIteratorInit(), JsonbIteratorNext(), JsonbValueToJsonb(), PG_GETARG_JSONB_P, PG_RETURN_POINTER, pushJsonbValue(), res, Jsonb::root, generate_unaccent_rules::type, JsonbValue::type, WJB_DONE, WJB_ELEM, WJB_KEY, and WJB_VALUE.

◆ jsonb_to_record()

Datum jsonb_to_record ( PG_FUNCTION_ARGS  )

Definition at line 2388 of file jsonfuncs.c.

2389 {
2390  return populate_record_worker(fcinfo, "jsonb_to_record",
2391  false, false);
2392 }

References populate_record_worker().

◆ jsonb_to_recordset()

Datum jsonb_to_recordset ( PG_FUNCTION_ARGS  )

Definition at line 3663 of file jsonfuncs.c.

3664 {
3665  return populate_recordset_worker(fcinfo, "jsonb_to_recordset",
3666  false, false);
3667 }

References populate_recordset_worker().

◆ JsonbValueAsText()

static text * JsonbValueAsText ( JsonbValue v)
static

Definition at line 1743 of file jsonfuncs.c.

1744 {
1745  switch (v->type)
1746  {
1747  case jbvNull:
1748  return NULL;
1749 
1750  case jbvBool:
1751  return v->val.boolean ?
1752  cstring_to_text_with_len("true", 4) :
1753  cstring_to_text_with_len("false", 5);
1754 
1755  case jbvString:
1756  return cstring_to_text_with_len(v->val.string.val,
1757  v->val.string.len);
1758 
1759  case jbvNumeric:
1760  {
1761  Datum cstr;
1762 
1764  PointerGetDatum(v->val.numeric));
1765 
1766  return cstring_to_text(DatumGetCString(cstr));
1767  }
1768 
1769  case jbvBinary:
1770  {
1771  StringInfoData jtext;
1772 
1773  initStringInfo(&jtext);
1774  (void) JsonbToCString(&jtext, v->val.binary.data,
1775  v->val.binary.len);
1776 
1777  return cstring_to_text_with_len(jtext.data, jtext.len);
1778  }
1779 
1780  default:
1781  elog(ERROR, "unrecognized jsonb type: %d", (int) v->type);
1782  return NULL;
1783  }
1784 }
void initStringInfo(StringInfo str)
Definition: stringinfo.c:59

References cstring_to_text(), cstring_to_text_with_len(), StringInfoData::data, DatumGetCString, DirectFunctionCall1, elog, ERROR, initStringInfo(), jbvBinary, jbvBool, jbvNull, jbvNumeric, jbvString, JsonbToCString(), StringInfoData::len, numeric_out(), PointerGetDatum, JsonbValue::type, and JsonbValue::val.

Referenced by each_worker_jsonb(), elements_worker_jsonb(), jsonb_array_element_text(), jsonb_get_element(), and jsonb_object_field_text().

◆ JsValueToJsObject()

static void JsValueToJsObject ( JsValue jsv,
JsObject jso 
)
static

Definition at line 2767 of file jsonfuncs.c.

2768 {
2769  jso->is_json = jsv->is_json;
2770 
2771  if (jsv->is_json)
2772  {
2773  /* convert plain-text json into a hash table */
2774  jso->val.json_hash =
2775  get_json_object_as_hash(jsv->val.json.str,
2776  jsv->val.json.len >= 0
2777  ? jsv->val.json.len
2778  : strlen(jsv->val.json.str),
2779  "populate_composite");
2780  }
2781  else
2782  {
2783  JsonbValue *jbv = jsv->val.jsonb;
2784 
2785  if (jbv->type == jbvBinary &&
2786  JsonContainerIsObject(jbv->val.binary.data))
2787  {
2788  jso->val.jsonb_cont = jbv->val.binary.data;
2789  }
2790  else
2791  {
2792  bool is_scalar;
2793 
2794  is_scalar = IsAJsonbScalar(jbv) ||
2795  (jbv->type == jbvBinary &&
2796  JsonContainerIsScalar(jbv->val.binary.data));
2797  ereport(ERROR,
2798  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2799  is_scalar
2800  ? errmsg("cannot call %s on a scalar",
2801  "populate_composite")
2802  : errmsg("cannot call %s on an array",
2803  "populate_composite")));
2804  }
2805  }
2806 }
static HTAB * get_json_object_as_hash(char *json, int len, const char *funcname)
Definition: jsonfuncs.c:3508

References ereport, errcode(), errmsg(), ERROR, get_json_object_as_hash(), JsValue::is_json, JsObject::is_json, IsAJsonbScalar, jbvBinary, JsValue::json, JsObject::json_hash, JsValue::jsonb, JsObject::jsonb_cont, JsonContainerIsObject, JsonContainerIsScalar, JsonbValue::type, JsValue::val, JsObject::val, and JsonbValue::val.

Referenced by populate_composite().

◆ makeJsonLexContext()

◆ okeys_array_start()

static void okeys_array_start ( void *  state)
static

Definition at line 770 of file jsonfuncs.c.

771 {
772  OkeysState *_state = (OkeysState *) state;
773 
774  /* top level must be a json object */
775  if (_state->lex->lex_level == 0)
776  ereport(ERROR,
777  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
778  errmsg("cannot call %s on an array",
779  "json_object_keys")));
780 }
JsonLexContext * lex
Definition: jsonfuncs.c:54

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

Referenced by json_object_keys().

◆ okeys_object_field_start()

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

Definition at line 749 of file jsonfuncs.c.

750 {
751  OkeysState *_state = (OkeysState *) state;
752 
753  /* only collecting keys for the top level object */
754  if (_state->lex->lex_level != 1)
755  return;
756 
757  /* enlarge result array if necessary */
758  if (_state->result_count >= _state->result_size)
759  {
760  _state->result_size *= 2;
761  _state->result = (char **)
762  repalloc(_state->result, sizeof(char *) * _state->result_size);
763  }
764 
765  /* save a copy of the field name */
766  _state->result[_state->result_count++] = pstrdup(fname);
767 }
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1188
int result_size
Definition: jsonfuncs.c:56
char ** result
Definition: jsonfuncs.c:55
int result_count
Definition: jsonfuncs.c:57

References OkeysState::lex, JsonLexContext::lex_level, pstrdup(), repalloc(), OkeysState::result, OkeysState::result_count, and OkeysState::result_size.

Referenced by json_object_keys().

◆ okeys_scalar()

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

Definition at line 783 of file jsonfuncs.c.

784 {
785  OkeysState *_state = (OkeysState *) state;
786 
787  /* top level must be a json object */
788  if (_state->lex->lex_level == 0)
789  ereport(ERROR,
790  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
791  errmsg("cannot call %s on a scalar",
792  "json_object_keys")));
793 }

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

Referenced by json_object_keys().

◆ parse_jsonb_index_flags()

uint32 parse_jsonb_index_flags ( Jsonb jb)

Definition at line 5222 of file jsonfuncs.c.

5223 {
5224  JsonbIterator *it;
5225  JsonbValue v;
5227  uint32 flags = 0;
5228 
5229  it = JsonbIteratorInit(&jb->root);
5230 
5231  type = JsonbIteratorNext(&it, &v, false);
5232 
5233  /*
5234  * We iterate over array (scalar internally is represented as array, so,
5235  * we will accept it too) to check all its elements. Flag names are
5236  * chosen the same as jsonb_typeof uses.
5237  */
5238  if (type != WJB_BEGIN_ARRAY)
5239  ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
5240  errmsg("wrong flag type, only arrays and scalars are allowed")));
5241 
5242  while ((type = JsonbIteratorNext(&it, &v, false)) == WJB_ELEM)
5243  {
5244  if (v.type != jbvString)
5245  ereport(ERROR,
5246  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
5247  errmsg("flag array element is not a string"),
5248  errhint("Possible values are: \"string\", \"numeric\", \"boolean\", \"key\", and \"all\".")));
5249 
5250  if (v.val.string.len == 3 &&
5251  pg_strncasecmp(v.val.string.val, "all", 3) == 0)
5252  flags |= jtiAll;
5253  else if (v.val.string.len == 3 &&
5254  pg_strncasecmp(v.val.string.val, "key", 3) == 0)
5255  flags |= jtiKey;
5256  else if (v.val.string.len == 6 &&
5257  pg_strncasecmp(v.val.string.val, "string", 6) == 0)
5258  flags |= jtiString;
5259  else if (v.val.string.len == 7 &&
5260  pg_strncasecmp(v.val.string.val, "numeric", 7) == 0)
5261  flags |= jtiNumeric;
5262  else if (v.val.string.len == 7 &&
5263  pg_strncasecmp(v.val.string.val, "boolean", 7) == 0)
5264  flags |= jtiBool;
5265  else
5266  ereport(ERROR,
5267  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
5268  errmsg("wrong flag in flag array: \"%s\"",
5269  pnstrdup(v.val.string.val, v.val.string.len)),
5270  errhint("Possible values are: \"string\", \"numeric\", \"boolean\", \"key\", and \"all\".")));
5271  }
5272 
5273  /* expect end of array now */
5274  if (type != WJB_END_ARRAY)
5275  elog(ERROR, "unexpected end of flag array");
5276 
5277  /* get final WJB_DONE and free iterator */
5278  type = JsonbIteratorNext(&it, &v, false);
5279  if (type != WJB_DONE)
5280  elog(ERROR, "unexpected end of flag array");
5281 
5282  return flags;
5283 }
@ jtiAll
Definition: jsonfuncs.h:30
char * pnstrdup(const char *in, Size len)
Definition: mcxt.c:1316
int pg_strncasecmp(const char *s1, const char *s2, size_t n)
Definition: pgstrcasecmp.c:69

References elog, ereport, errcode(), errhint(), errmsg(), ERROR, jbvString, JsonbIteratorInit(), JsonbIteratorNext(), jtiAll, jtiBool, jtiKey, jtiNumeric, jtiString, pg_strncasecmp(), pnstrdup(), Jsonb::root, generate_unaccent_rules::type, JsonbValue::type, JsonbValue::val, WJB_BEGIN_ARRAY, WJB_DONE, WJB_ELEM, and WJB_END_ARRAY.

Referenced by json_to_tsvector(), json_to_tsvector_byid(), jsonb_to_tsvector(), and jsonb_to_tsvector_byid().

◆ pg_parse_json_or_ereport()

void pg_parse_json_or_ereport ( JsonLexContext lex,
JsonSemAction sem 
)

Definition at line 501 of file jsonfuncs.c.

502 {
503  JsonParseErrorType result;
504 
505  result = pg_parse_json(lex, sem);
506  if (result != JSON_SUCCESS)
507  json_ereport_error(result, lex);
508 }
JsonParseErrorType pg_parse_json(JsonLexContext *lex, JsonSemAction *sem)
Definition: jsonapi.c:168

References json_ereport_error(), JSON_SUCCESS, and pg_parse_json().

Referenced by datum_to_jsonb(), each_worker(), elements_worker(), get_json_object_as_hash(), get_worker(), iterate_json_values(), json_array_length(), json_in(), json_object_keys(), json_recv(), json_strip_nulls(), jsonb_from_cstring(), populate_array_json(), populate_recordset_worker(), and transform_json_string_values().

◆ populate_array()

static Datum populate_array ( ArrayIOData aio,
const char *  colname,
MemoryContext  mcxt,
JsValue jsv 
)
static

Definition at line 2720 of file jsonfuncs.c.

2724 {
2726  Datum result;
2727  int *lbs;
2728  int i;
2729 
2730  ctx.aio = aio;
2731  ctx.mcxt = mcxt;
2732  ctx.acxt = CurrentMemoryContext;
2733  ctx.astate = initArrayResult(aio->element_type, ctx.acxt, true);
2734  ctx.colname = colname;
2735  ctx.ndims = 0; /* unknown yet */
2736  ctx.dims = NULL;
2737  ctx.sizes = NULL;
2738 
2739  if (jsv->is_json)
2740  populate_array_json(&ctx, jsv->val.json.str,
2741  jsv->val.json.len >= 0 ? jsv->val.json.len
2742  : strlen(jsv->val.json.str));
2743  else
2744  {
2745  populate_array_dim_jsonb(&ctx, jsv->val.jsonb, 1);
2746  ctx.dims[0] = ctx.sizes[0];
2747  }
2748 
2749  Assert(ctx.ndims > 0);
2750 
2751  lbs = palloc(sizeof(int) * ctx.ndims);
2752 
2753  for (i = 0; i < ctx.ndims; i++)
2754  lbs[i] = 1;
2755 
2756  result = makeMdArrayResult(ctx.astate, ctx.ndims, ctx.dims, lbs,
2757  ctx.acxt, true);
2758 
2759  pfree(ctx.dims);
2760  pfree(ctx.sizes);
2761  pfree(lbs);
2762 
2763  return result;
2764 }
ArrayBuildState * initArrayResult(Oid element_type, MemoryContext rcontext, bool subcontext)
Definition: arrayfuncs.c:5084
Datum makeMdArrayResult(ArrayBuildState *astate, int ndims, int *dims, int *lbs, MemoryContext rcontext, bool release)
Definition: arrayfuncs.c:5219
static void populate_array_json(PopulateArrayContext *ctx, char *json, int len)
Definition: jsonfuncs.c:2620
static void populate_array_dim_jsonb(PopulateArrayContext *ctx, JsonbValue *jbv, int ndim)
Definition: jsonfuncs.c:2649
Oid element_type
Definition: jsonfuncs.c:166
ArrayBuildState * astate
Definition: jsonfuncs.c:258
MemoryContext mcxt
Definition: jsonfuncs.c:261
ArrayIOData * aio
Definition: jsonfuncs.c:259
MemoryContext acxt
Definition: jsonfuncs.c:260
const char * colname
Definition: jsonfuncs.c:262

References PopulateArrayContext::acxt, PopulateArrayContext::aio, Assert(), PopulateArrayContext::astate, PopulateArrayContext::colname, CurrentMemoryContext, PopulateArrayContext::dims, ArrayIOData::element_type, i, initArrayResult(), JsValue::is_json, JsValue::json, JsValue::jsonb, makeMdArrayResult(), PopulateArrayContext::mcxt, PopulateArrayContext::ndims, palloc(), pfree(), populate_array_dim_jsonb(), populate_array_json(), PopulateArrayContext::sizes, and JsValue::val.

Referenced by populate_record_field().

◆ populate_array_array_end()

static void populate_array_array_end ( void *  _state)
static

Definition at line 2528 of file jsonfuncs.c.

2529 {
2531  PopulateArrayContext *ctx = state->ctx;
2532  int ndim = state->lex->lex_level;
2533 
2534  if (ctx->ndims <= 0)
2535  populate_array_assign_ndims(ctx, ndim + 1);
2536 
2537  if (ndim < ctx->ndims)
2538  populate_array_check_dimension(ctx, ndim);
2539 }
static void populate_array_check_dimension(PopulateArrayContext *ctx, int ndim)
Definition: jsonfuncs.c:2472
static void populate_array_assign_ndims(PopulateArrayContext *ctx, int ndims)
Definition: jsonfuncs.c:2453

References PopulateArrayContext::ndims, populate_array_assign_ndims(), and populate_array_check_dimension().

Referenced by populate_array_json().

◆ populate_array_assign_ndims()

static void populate_array_assign_ndims ( PopulateArrayContext ctx,
int  ndims 
)
static

Definition at line 2453 of file jsonfuncs.c.

2454 {
2455  int i;
2456 
2457  Assert(ctx->ndims <= 0);
2458 
2459  if (ndims <= 0)
2461 
2462  ctx->ndims = ndims;
2463  ctx->dims = palloc(sizeof(int) * ndims);
2464  ctx->sizes = palloc0(sizeof(int) * ndims);
2465 
2466  for (i = 0; i < ndims; i++)
2467  ctx->dims[i] = -1; /* dimensions are unknown yet */
2468 }
static void populate_array_report_expected_array(PopulateArrayContext *ctx, int ndim)
Definition: jsonfuncs.c:2410

References Assert(), PopulateArrayContext::dims, i, PopulateArrayContext::ndims, palloc(), palloc0(), populate_array_report_expected_array(), and PopulateArrayContext::sizes.

Referenced by populate_array_array_end(), populate_array_dim_jsonb(), populate_array_object_start(), and populate_array_scalar().

◆ populate_array_check_dimension()

static void populate_array_check_dimension ( PopulateArrayContext ctx,
int  ndim 
)
static

Definition at line 2472 of file jsonfuncs.c.

2473 {
2474  int dim = ctx->sizes[ndim]; /* current dimension counter */
2475 
2476  if (ctx->dims[ndim] == -1)
2477  ctx->dims[ndim] = dim; /* assign dimension if not yet known */
2478  else if (ctx->dims[ndim] != dim)
2479  ereport(ERROR,
2480  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2481  errmsg("malformed JSON array"),
2482  errdetail("Multidimensional arrays must have "
2483  "sub-arrays with matching dimensions.")));
2484 
2485  /* reset the current array dimension size counter */
2486  ctx->sizes[ndim] = 0;
2487 
2488  /* increment the parent dimension counter if it is a nested sub-array */
2489  if (ndim > 0)
2490  ctx->sizes[ndim - 1]++;
2491 }

References PopulateArrayContext::dims, ereport, errcode(), errdetail(), errmsg(), ERROR, and PopulateArrayContext::sizes.

Referenced by populate_array_array_end(), and populate_array_dim_jsonb().

◆ populate_array_dim_jsonb()

static void populate_array_dim_jsonb ( PopulateArrayContext ctx,
JsonbValue jbv,
int  ndim 
)
static

Definition at line 2649 of file jsonfuncs.c.

2652 {
2653  JsonbContainer *jbc = jbv->val.binary.data;
2654  JsonbIterator *it;
2655  JsonbIteratorToken tok;
2656  JsonbValue val;
2657  JsValue jsv;
2658 
2660 
2661  if (jbv->type != jbvBinary ||
2662  !JsonContainerIsArray(jbc) ||
2663  JsonContainerIsScalar(jbc))
2664  populate_array_report_expected_array(ctx, ndim - 1);
2665 
2666  it = JsonbIteratorInit(jbc);
2667 
2668  tok = JsonbIteratorNext(&it, &val, true);
2669  Assert(tok == WJB_BEGIN_ARRAY);
2670 
2671  tok = JsonbIteratorNext(&it, &val, true);
2672 
2673  /*
2674  * If the number of dimensions is not yet known and we have found end of
2675  * the array, or the first child element is not an array, then assign the
2676  * number of dimensions now.
2677  */
2678  if (ctx->ndims <= 0 &&
2679  (tok == WJB_END_ARRAY ||
2680  (tok == WJB_ELEM &&
2681  (val.type != jbvBinary ||
2682  !JsonContainerIsArray(val.val.binary.data)))))
2683  populate_array_assign_ndims(ctx, ndim);
2684 
2685  jsv.is_json = false;
2686  jsv.val.jsonb = &val;
2687 
2688  /* process all the array elements */
2689  while (tok == WJB_ELEM)
2690  {
2691  /*
2692  * Recurse only if the dimensions of dimensions is still unknown or if
2693  * it is not the innermost dimension.
2694  */
2695  if (ctx->ndims > 0 && ndim >= ctx->ndims)
2696  populate_array_element(ctx, ndim, &jsv);
2697  else
2698  {
2699  /* populate child sub-array */
2700  populate_array_dim_jsonb(ctx, &val, ndim + 1);
2701 
2702  /* number of dimensions should be already known */
2703  Assert(ctx->ndims > 0 && ctx->dims);
2704 
2705  populate_array_check_dimension(ctx, ndim);
2706  }
2707 
2708  tok = JsonbIteratorNext(&it, &val, true);
2709  }
2710 
2711  Assert(tok == WJB_END_ARRAY);
2712 
2713  /* free iterator, iterating until WJB_DONE */
2714  tok = JsonbIteratorNext(&it, &val, true);
2715  Assert(tok == WJB_DONE && !it);
2716 }
static void populate_array_element(PopulateArrayContext *ctx, int ndim, JsValue *jsv)
Definition: jsonfuncs.c:2494
void check_stack_depth(void)
Definition: postgres.c:3500

References Assert(), check_stack_depth(), PopulateArrayContext::dims, JsValue::is_json, jbvBinary, JsValue::jsonb, JsonbIteratorInit(), JsonbIteratorNext(), JsonContainerIsArray, JsonContainerIsScalar, PopulateArrayContext::ndims, populate_array_assign_ndims(), populate_array_check_dimension(), populate_array_element(), populate_array_report_expected_array(), JsonbValue::type, JsValue::val, JsonbValue::val, val, WJB_BEGIN_ARRAY, WJB_DONE, WJB_ELEM, and WJB_END_ARRAY.

Referenced by populate_array().

◆ populate_array_element()

static void populate_array_element ( PopulateArrayContext ctx,
int  ndim,
JsValue jsv 
)
static

Definition at line 2494 of file jsonfuncs.c.

2495 {
2496  Datum element;
2497  bool element_isnull;
2498 
2499  /* populate the array element */
2501  ctx->aio->element_type,
2502  ctx->aio->element_typmod,
2503  NULL, ctx->mcxt, PointerGetDatum(NULL),
2504  jsv, &element_isnull);
2505 
2506  accumArrayResult(ctx->astate, element, element_isnull,
2507  ctx->aio->element_type, ctx->acxt);
2508 
2509  Assert(ndim > 0);
2510  ctx->sizes[ndim - 1]++; /* increment current dimension counter */
2511 }
ArrayBuildState * accumArrayResult(ArrayBuildState *astate, Datum dvalue, bool disnull, Oid element_type, MemoryContext rcontext)
Definition: arrayfuncs.c:5123
int32 element_typmod
Definition: jsonfuncs.c:167
ColumnIOData * element_info
Definition: jsonfuncs.c:165

References accumArrayResult(), PopulateArrayContext::acxt, PopulateArrayContext::aio, Assert(), PopulateArrayContext::astate, element(), ArrayIOData::element_info, ArrayIOData::element_type, ArrayIOData::element_typmod, PopulateArrayContext::mcxt, PointerGetDatum, populate_record_field(), and PopulateArrayContext::sizes.

Referenced by populate_array_dim_jsonb(), and populate_array_element_end().

◆ populate_array_element_end()

static void populate_array_element_end ( void *  _state,
bool  isnull 
)
static

Definition at line 2559 of file jsonfuncs.c.

2560 {
2562  PopulateArrayContext *ctx = state->ctx;
2563  int ndim = state->lex->lex_level;
2564 
2565  Assert(ctx->ndims > 0);
2566 
2567  if (ndim == ctx->ndims)
2568  {
2569  JsValue jsv;
2570 
2571  jsv.is_json = true;
2572  jsv.val.json.type = state->element_type;
2573 
2574  if (isnull)
2575  {
2576  Assert(jsv.val.json.type == JSON_TOKEN_NULL);
2577  jsv.val.json.str = NULL;
2578  jsv.val.json.len = 0;
2579  }
2580  else if (state->element_scalar)
2581  {
2582  jsv.val.json.str = state->element_scalar;
2583  jsv.val.json.len = -1; /* null-terminated */
2584  }
2585  else
2586  {
2587  jsv.val.json.str = state->element_start;
2588  jsv.val.json.len = (state->lex->prev_token_terminator -
2589  state->element_start) * sizeof(char);
2590  }
2591 
2592  populate_array_element(ctx, ndim, &jsv);
2593  }
2594 }

References Assert(), JsValue::is_json, JsValue::json, JSON_TOKEN_NULL, PopulateArrayContext::ndims, populate_array_element(), and JsValue::val.

Referenced by populate_array_json().

◆ populate_array_element_start()

static void populate_array_element_start ( void *  _state,
bool  isnull 
)
static

Definition at line 2543 of file jsonfuncs.c.

2544 {
2546  int ndim = state->lex->lex_level;
2547 
2548  if (state->ctx->ndims <= 0 || ndim == state->ctx->ndims)
2549  {
2550  /* remember current array element start */
2551  state->element_start = state->lex->token_start;
2552  state->element_type = state->lex->token_type;
2553  state->element_scalar = NULL;
2554  }
2555 }

Referenced by populate_array_json().

◆ populate_array_json()

static void populate_array_json ( PopulateArrayContext ctx,
char *  json,
int  len 
)
static

Definition at line 2620 of file jsonfuncs.c.

2621 {
2623  JsonSemAction sem;
2624 
2626  state.ctx = ctx;
2627 
2628  memset(&sem, 0, sizeof(sem));
2629  sem.semstate = (void *) &state;
2635 
2636  pg_parse_json_or_ereport(state.lex, &sem);
2637 
2638  /* number of dimensions should be already known */
2639  Assert(ctx->ndims > 0 && ctx->dims);
2640 
2641  pfree(state.lex);
2642 }
static void populate_array_element_start(void *_state, bool isnull)
Definition: jsonfuncs.c:2543
static void populate_array_scalar(void *_state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:2598
static void populate_array_object_start(void *_state)
Definition: jsonfuncs.c:2515
static void populate_array_array_end(void *_state)
Definition: jsonfuncs.c:2528
static void populate_array_element_end(void *_state, bool isnull)
Definition: jsonfuncs.c:2559

References JsonSemAction::array_element_end, JsonSemAction::array_element_start, JsonSemAction::array_end, Assert(), PopulateArrayContext::dims, GetDatabaseEncoding(), len, makeJsonLexContextCstringLen(), PopulateArrayContext::ndims, JsonSemAction::object_start, pfree(), pg_parse_json_or_ereport(), populate_array_array_end(), populate_array_element_end(), populate_array_element_start(), populate_array_object_start(), populate_array_scalar(), JsonSemAction::scalar, and JsonSemAction::semstate.

Referenced by populate_array().

◆ populate_array_object_start()

static void populate_array_object_start ( void *  _state)
static

Definition at line 2515 of file jsonfuncs.c.

2516 {
2518  int ndim = state->lex->lex_level;
2519 
2520  if (state->ctx->ndims <= 0)
2521  populate_array_assign_ndims(state->ctx, ndim);
2522  else if (ndim < state->ctx->ndims)
2524 }

References populate_array_assign_ndims(), and populate_array_report_expected_array().

Referenced by populate_array_json().

◆ populate_array_report_expected_array()

static void populate_array_report_expected_array ( PopulateArrayContext ctx,
int  ndim 
)
static

Definition at line 2410 of file jsonfuncs.c.

2411 {
2412  if (ndim <= 0)
2413  {
2414  if (ctx->colname)
2415  ereport(ERROR,
2416  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2417  errmsg("expected JSON array"),
2418  errhint("See the value of key \"%s\".", ctx->colname)));
2419  else
2420  ereport(ERROR,
2421  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2422  errmsg("expected JSON array")));
2423  }
2424  else
2425  {
2426  StringInfoData indices;
2427  int i;
2428 
2429  initStringInfo(&indices);
2430 
2431  Assert(ctx->ndims > 0 && ndim < ctx->ndims);
2432 
2433  for (i = 0; i < ndim; i++)
2434  appendStringInfo(&indices, "[%d]", ctx->sizes[i]);
2435 
2436  if (ctx->