PostgreSQL Source Code  git master
jsonfuncs.c File Reference
#include "postgres.h"
#include <limits.h>
#include "access/htup_details.h"
#include "catalog/pg_type.h"
#include "common/jsonapi.h"
#include "common/string.h"
#include "fmgr.h"
#include "funcapi.h"
#include "lib/stringinfo.h"
#include "mb/pg_wchar.h"
#include "miscadmin.h"
#include "utils/array.h"
#include "utils/builtins.h"
#include "utils/fmgroids.h"
#include "utils/hsearch.h"
#include "utils/json.h"
#include "utils/jsonb.h"
#include "utils/jsonfuncs.h"
#include "utils/lsyscache.h"
#include "utils/memutils.h"
#include "utils/syscache.h"
#include "utils/typcache.h"
Include dependency graph for jsonfuncs.c:

Go to the source code of this file.

Data Structures

struct  OkeysState
 
struct  IterateJsonStringValuesState
 
struct  TransformJsonStringValuesState
 
struct  GetState
 
struct  AlenState
 
struct  EachState
 
struct  ElementsState
 
struct  JHashState
 
struct  JsonHashEntry
 
struct  ScalarIOData
 
struct  ArrayIOData
 
struct  CompositeIOData
 
struct  DomainIOData
 
struct  ColumnIOData
 
struct  RecordIOData
 
struct  PopulateRecordCache
 
struct  PopulateRecordsetState
 
struct  PopulateArrayContext
 
struct  PopulateArrayState
 
struct  StripnullState
 
struct  JsValue
 
struct  JsObject
 

Macros

#define JB_PATH_CREATE   0x0001
 
#define JB_PATH_DELETE   0x0002
 
#define JB_PATH_REPLACE   0x0004
 
#define JB_PATH_INSERT_BEFORE   0x0008
 
#define JB_PATH_INSERT_AFTER   0x0010
 
#define JB_PATH_CREATE_OR_INSERT    (JB_PATH_INSERT_BEFORE | JB_PATH_INSERT_AFTER | JB_PATH_CREATE)
 
#define JB_PATH_FILL_GAPS   0x0020
 
#define JB_PATH_CONSISTENT_POSITION   0x0040
 
#define JsValueIsNull(jsv)
 
#define JsValueIsString(jsv)
 
#define JsObjectIsEmpty(jso)
 
#define JsObjectFree(jso)
 

Typedefs

typedef struct OkeysState OkeysState
 
typedef struct IterateJsonStringValuesState IterateJsonStringValuesState
 
typedef struct TransformJsonStringValuesState TransformJsonStringValuesState
 
typedef struct GetState GetState
 
typedef struct AlenState AlenState
 
typedef struct EachState EachState
 
typedef struct ElementsState ElementsState
 
typedef struct JHashState JHashState
 
typedef struct JsonHashEntry JsonHashEntry
 
typedef struct ScalarIOData ScalarIOData
 
typedef struct ColumnIOData ColumnIOData
 
typedef struct RecordIOData RecordIOData
 
typedef struct ArrayIOData ArrayIOData
 
typedef struct CompositeIOData CompositeIOData
 
typedef struct DomainIOData DomainIOData
 
typedef enum TypeCat TypeCat
 
typedef struct PopulateRecordCache PopulateRecordCache
 
typedef struct PopulateRecordsetState PopulateRecordsetState
 
typedef struct PopulateArrayContext PopulateArrayContext
 
typedef struct PopulateArrayState PopulateArrayState
 
typedef struct StripnullState StripnullState
 
typedef struct JsValue JsValue
 
typedef struct JsObject JsObject
 

Enumerations

enum  TypeCat {
  TYPECAT_SCALAR = 's' , TYPECAT_ARRAY = 'a' , TYPECAT_COMPOSITE = 'c' , TYPECAT_COMPOSITE_DOMAIN = 'C' ,
  TYPECAT_DOMAIN = 'd'
}
 

Functions

static int report_json_context (JsonLexContext *lex)
 
static void okeys_object_field_start (void *state, char *fname, bool isnull)
 
static void okeys_array_start (void *state)
 
static void okeys_scalar (void *state, char *token, JsonTokenType tokentype)
 
static void get_object_start (void *state)
 
static void get_object_end (void *state)
 
static void get_object_field_start (void *state, char *fname, bool isnull)
 
static void get_object_field_end (void *state, char *fname, bool isnull)
 
static void get_array_start (void *state)
 
static void get_array_end (void *state)
 
static void get_array_element_start (void *state, bool isnull)
 
static void get_array_element_end (void *state, bool isnull)
 
static void get_scalar (void *state, char *token, JsonTokenType tokentype)
 
static Datum get_path_all (FunctionCallInfo fcinfo, bool as_text)
 
static textget_worker (text *json, char **tpath, int *ipath, int npath, bool normalize_results)
 
static Datum get_jsonb_path_all (FunctionCallInfo fcinfo, bool as_text)
 
static textJsonbValueAsText (JsonbValue *v)
 
static void alen_object_start (void *state)
 
static void alen_scalar (void *state, char *token, JsonTokenType tokentype)
 
static void alen_array_element_start (void *state, bool isnull)
 
static Datum each_worker (FunctionCallInfo fcinfo, bool as_text)
 
static Datum each_worker_jsonb (FunctionCallInfo fcinfo, const char *funcname, bool as_text)
 
static void each_object_field_start (void *state, char *fname, bool isnull)
 
static void each_object_field_end (void *state, char *fname, bool isnull)
 
static void each_array_start (void *state)
 
static void each_scalar (void *state, char *token, JsonTokenType tokentype)
 
static Datum elements_worker (FunctionCallInfo fcinfo, const char *funcname, bool as_text)
 
static Datum elements_worker_jsonb (FunctionCallInfo fcinfo, const char *funcname, bool as_text)
 
static void elements_object_start (void *state)
 
static void elements_array_element_start (void *state, bool isnull)
 
static void elements_array_element_end (void *state, bool isnull)
 
static void elements_scalar (void *state, char *token, JsonTokenType tokentype)
 
static HTABget_json_object_as_hash (char *json, int len, const char *funcname)
 
static void populate_array_object_start (void *_state)
 
static void populate_array_array_end (void *_state)
 
static void populate_array_element_start (void *_state, bool isnull)
 
static void populate_array_element_end (void *_state, bool isnull)
 
static void populate_array_scalar (void *_state, char *token, JsonTokenType tokentype)
 
static void hash_object_field_start (void *state, char *fname, bool isnull)
 
static void hash_object_field_end (void *state, char *fname, bool isnull)
 
static void hash_array_start (void *state)
 
static void hash_scalar (void *state, char *token, JsonTokenType tokentype)
 
static void populate_recordset_object_field_start (void *state, char *fname, bool isnull)
 
static void populate_recordset_object_field_end (void *state, char *fname, bool isnull)
 
static void populate_recordset_scalar (void *state, char *token, JsonTokenType tokentype)
 
static void populate_recordset_object_start (void *state)
 
static void populate_recordset_object_end (void *state)
 
static void populate_recordset_array_start (void *state)
 
static void populate_recordset_array_element_start (void *state, bool isnull)
 
static void sn_object_start (void *state)
 
static void sn_object_end (void *state)
 
static void sn_array_start (void *state)
 
static void sn_array_end (void *state)
 
static void sn_object_field_start (void *state, char *fname, bool isnull)
 
static void sn_array_element_start (void *state, bool isnull)
 
static void sn_scalar (void *state, char *token, JsonTokenType tokentype)
 
static Datum populate_recordset_worker (FunctionCallInfo fcinfo, const char *funcname, bool is_json, bool have_record_arg)
 
static Datum populate_record_worker (FunctionCallInfo fcinfo, const char *funcname, bool is_json, bool have_record_arg)
 
static HeapTupleHeader populate_record (TupleDesc tupdesc, RecordIOData **record_p, HeapTupleHeader defaultval, MemoryContext mcxt, JsObject *obj)
 
static void get_record_type_from_argument (FunctionCallInfo fcinfo, const char *funcname, PopulateRecordCache *cache)
 
static void get_record_type_from_query (FunctionCallInfo fcinfo, const char *funcname, PopulateRecordCache *cache)
 
static void JsValueToJsObject (JsValue *jsv, JsObject *jso)
 
static Datum populate_composite (CompositeIOData *io, Oid typid, const char *colname, MemoryContext mcxt, HeapTupleHeader defaultval, JsValue *jsv, bool isnull)
 
static Datum populate_scalar (ScalarIOData *io, Oid typid, int32 typmod, JsValue *jsv)
 
static void prepare_column_cache (ColumnIOData *column, Oid typid, int32 typmod, MemoryContext mcxt, bool need_scalar)
 
static Datum populate_record_field (ColumnIOData *col, Oid typid, int32 typmod, const char *colname, MemoryContext mcxt, Datum defaultval, JsValue *jsv, bool *isnull)
 
static RecordIODataallocate_record_info (MemoryContext mcxt, int ncolumns)
 
static bool JsObjectGetField (JsObject *obj, char *field, JsValue *jsv)
 
static void populate_recordset_record (PopulateRecordsetState *state, JsObject *obj)
 
static void populate_array_json (PopulateArrayContext *ctx, char *json, int len)
 
static void populate_array_dim_jsonb (PopulateArrayContext *ctx, JsonbValue *jbv, int ndim)
 
static void populate_array_report_expected_array (PopulateArrayContext *ctx, int ndim)
 
static void populate_array_assign_ndims (PopulateArrayContext *ctx, int ndims)
 
static void populate_array_check_dimension (PopulateArrayContext *ctx, int ndim)
 
static void populate_array_element (PopulateArrayContext *ctx, int ndim, JsValue *jsv)
 
static Datum populate_array (ArrayIOData *aio, const char *colname, MemoryContext mcxt, JsValue *jsv)
 
static Datum populate_domain (DomainIOData *io, Oid typid, const char *colname, MemoryContext mcxt, JsValue *jsv, bool isnull)
 
static JsonbValueIteratorConcat (JsonbIterator **it1, JsonbIterator **it2, JsonbParseState **state)
 
static JsonbValuesetPath (JsonbIterator **it, Datum *path_elems, bool *path_nulls, int path_len, JsonbParseState **st, int level, JsonbValue *newval, int op_type)
 
static void setPathObject (JsonbIterator **it, Datum *path_elems, bool *path_nulls, int path_len, JsonbParseState **st, int level, JsonbValue *newval, uint32 npairs, int op_type)
 
static void setPathArray (JsonbIterator **it, Datum *path_elems, bool *path_nulls, int path_len, JsonbParseState **st, int level, JsonbValue *newval, uint32 nelems, int op_type)
 
static void iterate_values_scalar (void *state, char *token, JsonTokenType tokentype)
 
static void iterate_values_object_field_start (void *state, char *fname, bool isnull)
 
static void transform_string_values_object_start (void *state)
 
static void transform_string_values_object_end (void *state)
 
static void transform_string_values_array_start (void *state)
 
static void transform_string_values_array_end (void *state)
 
static void transform_string_values_object_field_start (void *state, char *fname, bool isnull)
 
static void transform_string_values_array_element_start (void *state, bool isnull)
 
static void transform_string_values_scalar (void *state, char *token, JsonTokenType tokentype)
 
void pg_parse_json_or_ereport (JsonLexContext *lex, JsonSemAction *sem)
 
JsonLexContextmakeJsonLexContext (text *json, bool need_escapes)
 
Datum jsonb_object_keys (PG_FUNCTION_ARGS)
 
void json_ereport_error (JsonParseErrorType error, JsonLexContext *lex)
 
Datum json_object_keys (PG_FUNCTION_ARGS)
 
Datum json_object_field (PG_FUNCTION_ARGS)
 
Datum jsonb_object_field (PG_FUNCTION_ARGS)
 
Datum json_object_field_text (PG_FUNCTION_ARGS)
 
Datum jsonb_object_field_text (PG_FUNCTION_ARGS)
 
Datum json_array_element (PG_FUNCTION_ARGS)
 
Datum jsonb_array_element (PG_FUNCTION_ARGS)
 
Datum json_array_element_text (PG_FUNCTION_ARGS)
 
Datum jsonb_array_element_text (PG_FUNCTION_ARGS)
 
Datum json_extract_path (PG_FUNCTION_ARGS)
 
Datum json_extract_path_text (PG_FUNCTION_ARGS)
 
Datum jsonb_extract_path (PG_FUNCTION_ARGS)
 
Datum jsonb_extract_path_text (PG_FUNCTION_ARGS)
 
Datum jsonb_get_element (Jsonb *jb, Datum *path, int npath, bool *isnull, bool as_text)
 
Datum jsonb_set_element (Jsonb *jb, Datum *path, int path_len, JsonbValue *newval)
 
static void push_null_elements (JsonbParseState **ps, int num)
 
static void push_path (JsonbParseState **st, int level, Datum *path_elems, bool *path_nulls, int path_len, JsonbValue *newval)
 
Datum json_array_length (PG_FUNCTION_ARGS)
 
Datum jsonb_array_length (PG_FUNCTION_ARGS)
 
Datum json_each (PG_FUNCTION_ARGS)
 
Datum jsonb_each (PG_FUNCTION_ARGS)
 
Datum json_each_text (PG_FUNCTION_ARGS)
 
Datum jsonb_each_text (PG_FUNCTION_ARGS)
 
Datum jsonb_array_elements (PG_FUNCTION_ARGS)
 
Datum jsonb_array_elements_text (PG_FUNCTION_ARGS)
 
Datum json_array_elements (PG_FUNCTION_ARGS)
 
Datum json_array_elements_text (PG_FUNCTION_ARGS)
 
Datum jsonb_populate_record (PG_FUNCTION_ARGS)
 
Datum jsonb_to_record (PG_FUNCTION_ARGS)
 
Datum json_populate_record (PG_FUNCTION_ARGS)
 
Datum json_to_record (PG_FUNCTION_ARGS)
 
static void update_cached_tupdesc (CompositeIOData *io, MemoryContext mcxt)
 
Datum jsonb_populate_recordset (PG_FUNCTION_ARGS)
 
Datum jsonb_to_recordset (PG_FUNCTION_ARGS)
 
Datum json_populate_recordset (PG_FUNCTION_ARGS)
 
Datum json_to_recordset (PG_FUNCTION_ARGS)
 
Datum json_strip_nulls (PG_FUNCTION_ARGS)
 
Datum jsonb_strip_nulls (PG_FUNCTION_ARGS)
 
Datum jsonb_pretty (PG_FUNCTION_ARGS)
 
Datum jsonb_concat (PG_FUNCTION_ARGS)
 
Datum jsonb_delete (PG_FUNCTION_ARGS)
 
Datum jsonb_delete_array (PG_FUNCTION_ARGS)
 
Datum jsonb_delete_idx (PG_FUNCTION_ARGS)
 
Datum jsonb_set (PG_FUNCTION_ARGS)
 
Datum jsonb_set_lax (PG_FUNCTION_ARGS)
 
Datum jsonb_delete_path (PG_FUNCTION_ARGS)
 
Datum jsonb_insert (PG_FUNCTION_ARGS)
 
uint32 parse_jsonb_index_flags (Jsonb *jb)
 
void iterate_jsonb_values (Jsonb *jb, uint32 flags, void *state, JsonIterateStringValuesAction action)
 
void iterate_json_values (text *json, uint32 flags, void *action_state, JsonIterateStringValuesAction action)
 
Jsonbtransform_jsonb_string_values (Jsonb *jsonb, void *action_state, JsonTransformStringValuesAction transform_action)
 
texttransform_json_string_values (text *json, void *action_state, JsonTransformStringValuesAction transform_action)
 

Macro Definition Documentation

◆ JB_PATH_CONSISTENT_POSITION

#define JB_PATH_CONSISTENT_POSITION   0x0040

Definition at line 49 of file jsonfuncs.c.

◆ 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:1377

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:228

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:229

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

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

1839 {
1840  AlenState *_state = (AlenState *) state;
1841 
1842  /* json structure check */
1843  if (_state->lex->lex_level == 0)
1844  ereport(ERROR,
1845  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1846  errmsg("cannot get array length of a non-array")));
1847 }
int errcode(int sqlerrcode)
Definition: elog.c:695
int errmsg(const char *fmt,...)
Definition: elog.c:906
#define ERROR
Definition: elog.h:35
#define ereport(elevel,...)
Definition: elog.h:145

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

1851 {
1852  AlenState *_state = (AlenState *) state;
1853 
1854  /* json structure check */
1855  if (_state->lex->lex_level == 0)
1856  ereport(ERROR,
1857  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1858  errmsg("cannot get array length of a scalar")));
1859 }

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

3136 {
3138  MemoryContextAlloc(mcxt,
3139  offsetof(RecordIOData, columns) +
3140  ncolumns * sizeof(ColumnIOData));
3141 
3142  data->record_type = InvalidOid;
3143  data->record_typmod = 0;
3144  data->ncolumns = ncolumns;
3145  MemSet(data->columns, 0, sizeof(ColumnIOData) * ncolumns);
3146 
3147  return data;
3148 }
#define MemSet(start, val, len)
Definition: c.h:953
struct ColumnIOData ColumnIOData
Definition: jsonfuncs.c:159
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:994
const void * data
#define InvalidOid
Definition: postgres_ext.h:36

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

Referenced by populate_record().

◆ each_array_start()

static void each_array_start ( void *  state)
static

Definition at line 2096 of file jsonfuncs.c.

2097 {
2098  EachState *_state = (EachState *) state;
2099 
2100  /* json structure check */
2101  if (_state->lex->lex_level == 0)
2102  ereport(ERROR,
2103  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2104  errmsg("cannot deconstruct an array as an object")));
2105 }
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 2050 of file jsonfuncs.c.

2051 {
2052  EachState *_state = (EachState *) state;
2053  MemoryContext old_cxt;
2054  int len;
2055  text *val;
2056  HeapTuple tuple;
2057  Datum values[2];
2058  bool nulls[2] = {false, false};
2059 
2060  /* skip over nested objects */
2061  if (_state->lex->lex_level != 1)
2062  return;
2063 
2064  /* use the tmp context so we can clean up after each tuple is done */
2065  old_cxt = MemoryContextSwitchTo(_state->tmp_cxt);
2066 
2067  values[0] = CStringGetTextDatum(fname);
2068 
2069  if (isnull && _state->normalize_results)
2070  {
2071  nulls[1] = true;
2072  values[1] = (Datum) 0;
2073  }
2074  else if (_state->next_scalar)
2075  {
2077  _state->next_scalar = false;
2078  }
2079  else
2080  {
2081  len = _state->lex->prev_token_terminator - _state->result_start;
2083  values[1] = PointerGetDatum(val);
2084  }
2085 
2086  tuple = heap_form_tuple(_state->ret_tdesc, values, nulls);
2087 
2088  tuplestore_puttuple(_state->tuple_store, tuple);
2089 
2090  /* clean up and switch back */
2091  MemoryContextSwitchTo(old_cxt);
2092  MemoryContextReset(_state->tmp_cxt);
2093 }
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:303
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:135
const void size_t len
static Datum PointerGetDatum(const void *X)
Definition: postgres.h:670
uintptr_t Datum
Definition: postgres.h:412
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:623
void tuplestore_puttuple(Tuplestorestate *state, HeapTuple tuple)
Definition: tuplestore.c:730
text * cstring_to_text_with_len(const char *s, int len)
Definition: varlena.c:201

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

2031 {
2032  EachState *_state = (EachState *) state;
2033 
2034  /* save a pointer to where the value starts */
2035  if (_state->lex->lex_level == 1)
2036  {
2037  /*
2038  * next_scalar will be reset in the object_field_end handler, and
2039  * since we know the value is a scalar there is no danger of it being
2040  * on while recursing down the tree.
2041  */
2042  if (_state->normalize_results && _state->lex->token_type == JSON_TOKEN_STRING)
2043  _state->next_scalar = true;
2044  else
2045  _state->result_start = _state->lex->token_start;
2046  }
2047 }
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 2108 of file jsonfuncs.c.

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

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

1991 {
1992  text *json = PG_GETARG_TEXT_PP(0);
1993  JsonLexContext *lex;
1994  JsonSemAction *sem;
1995  ReturnSetInfo *rsi;
1996  EachState *state;
1997 
1998  lex = makeJsonLexContext(json, true);
1999  state = palloc0(sizeof(EachState));
2000  sem = palloc0(sizeof(JsonSemAction));
2001 
2002  rsi = (ReturnSetInfo *) fcinfo->resultinfo;
2003 
2005  state->tuple_store = rsi->setResult;
2006  state->ret_tdesc = rsi->setDesc;
2007 
2008  sem->semstate = (void *) state;
2010  sem->scalar = each_scalar;
2013 
2014  state->normalize_results = as_text;
2015  state->next_scalar = false;
2016  state->lex = lex;
2018  "json_each temporary cxt",
2020 
2021  pg_parse_json_or_ereport(lex, sem);
2022 
2023  MemoryContextDelete(state->tmp_cxt);
2024 
2025  PG_RETURN_NULL();
2026 }
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:309
#define PG_RETURN_NULL()
Definition: fmgr.h:345
void InitMaterializedSRF(FunctionCallInfo fcinfo, bits32 flags)
Definition: funcapi.c:76
#define MAT_SRF_BLESS
Definition: funcapi.h:296
void pg_parse_json_or_ereport(JsonLexContext *lex, JsonSemAction *sem)
Definition: jsonfuncs.c:501
static void each_array_start(void *state)
Definition: jsonfuncs.c:2096
JsonLexContext * makeJsonLexContext(text *json, bool need_escapes)
Definition: jsonfuncs.c:517
static void each_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:2108
static void each_object_field_end(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:2050
static void each_object_field_start(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:2030
void * palloc0(Size size)
Definition: mcxt.c:1230
MemoryContext CurrentMemoryContext
Definition: mcxt.c:124
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:376
#define AllocSetContextCreate
Definition: memutils.h:129
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:153
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:332
Tuplestorestate * setResult
Definition: execnodes.h:331

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, JsonSemAction::array_start, CurrentMemoryContext, each_array_start(), each_object_field_end(), each_object_field_start(), each_scalar(), InitMaterializedSRF(), makeJsonLexContext(), MAT_SRF_BLESS, 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, and ReturnSetInfo::setResult.

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

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

2293 {
2294  ElementsState *_state = (ElementsState *) state;
2295  MemoryContext old_cxt;
2296  int len;
2297  text *val;
2298  HeapTuple tuple;
2299  Datum values[1];
2300  bool nulls[1] = {false};
2301 
2302  /* skip over nested objects */
2303  if (_state->lex->lex_level != 1)
2304  return;
2305 
2306  /* use the tmp context so we can clean up after each tuple is done */
2307  old_cxt = MemoryContextSwitchTo(_state->tmp_cxt);
2308 
2309  if (isnull && _state->normalize_results)
2310  {
2311  nulls[0] = true;
2312  values[0] = (Datum) NULL;
2313  }
2314  else if (_state->next_scalar)
2315  {
2317  _state->next_scalar = false;
2318  }
2319  else
2320  {
2321  len = _state->lex->prev_token_terminator - _state->result_start;
2323  values[0] = PointerGetDatum(val);
2324  }
2325 
2326  tuple = heap_form_tuple(_state->ret_tdesc, values, nulls);
2327 
2328  tuplestore_puttuple(_state->tuple_store, tuple);
2329 
2330  /* clean up and switch back */
2331  MemoryContextSwitchTo(old_cxt);
2332  MemoryContextReset(_state->tmp_cxt);
2333 }
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 2272 of file jsonfuncs.c.

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

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

2337 {
2338  ElementsState *_state = (ElementsState *) state;
2339 
2340  /* json structure check */
2341  if (_state->lex->lex_level == 0)
2342  ereport(ERROR,
2343  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2344  errmsg("cannot call %s on a non-array",
2345  _state->function_name)));
2346 }
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 2349 of file jsonfuncs.c.

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

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

2233 {
2234  text *json = PG_GETARG_TEXT_PP(0);
2235 
2236  /* elements only needs escaped strings when as_text */
2237  JsonLexContext *lex = makeJsonLexContext(json, as_text);
2238  JsonSemAction *sem;
2239  ReturnSetInfo *rsi;
2241 
2242  state = palloc0(sizeof(ElementsState));
2243  sem = palloc0(sizeof(JsonSemAction));
2244 
2246  rsi = (ReturnSetInfo *) fcinfo->resultinfo;
2247  state->tuple_store = rsi->setResult;
2248  state->ret_tdesc = rsi->setDesc;
2249 
2250  sem->semstate = (void *) state;
2252  sem->scalar = elements_scalar;
2255 
2256  state->function_name = funcname;
2257  state->normalize_results = as_text;
2258  state->next_scalar = false;
2259  state->lex = lex;
2261  "json_array_elements temporary cxt",
2263 
2264  pg_parse_json_or_ereport(lex, sem);
2265 
2266  MemoryContextDelete(state->tmp_cxt);
2267 
2268  PG_RETURN_NULL();
2269 }
#define MAT_SRF_USE_EXPECTED_DESC
Definition: funcapi.h:295
static void elements_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:2349
static void elements_object_start(void *state)
Definition: jsonfuncs.c:2336
static void elements_array_element_end(void *state, bool isnull)
Definition: jsonfuncs.c:2292
static void elements_array_element_start(void *state, bool isnull)
Definition: jsonfuncs.c:2272
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(), InitMaterializedSRF(), makeJsonLexContext(), MAT_SRF_BLESS, MAT_SRF_USE_EXPECTED_DESC, 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, and ReturnSetInfo::setResult.

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

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

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, CurrentMemoryContext, ereport, errcode(), errmsg(), ERROR, InitMaterializedSRF(), JB_ROOT_IS_ARRAY, JB_ROOT_IS_SCALAR, jbvNull, JsonbIteratorInit(), JsonbIteratorNext(), JsonbValueAsText(), JsonbValueToJsonb(), MAT_SRF_BLESS, MAT_SRF_USE_EXPECTED_DESC, MemoryContextDelete(), MemoryContextReset(), MemoryContextSwitchTo(), PG_GETARG_JSONB_P, PG_RETURN_NULL, PointerGetDatum(), FunctionCallInfoBaseData::resultinfo, Jsonb::root, ReturnSetInfo::setDesc, ReturnSetInfo::setResult, 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 1343 of file jsonfuncs.c.

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

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

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

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

3461 {
3462  HASHCTL ctl;
3463  HTAB *tab;
3464  JHashState *state;
3466  JsonSemAction *sem;
3467 
3468  ctl.keysize = NAMEDATALEN;
3469  ctl.entrysize = sizeof(JsonHashEntry);
3470  ctl.hcxt = CurrentMemoryContext;
3471  tab = hash_create("json object hashtable",
3472  100,
3473  &ctl,
3475 
3476  state = palloc0(sizeof(JHashState));
3477  sem = palloc0(sizeof(JsonSemAction));
3478 
3479  state->function_name = funcname;
3480  state->hash = tab;
3481  state->lex = lex;
3482 
3483  sem->semstate = (void *) state;
3485  sem->scalar = hash_scalar;
3488 
3489  pg_parse_json_or_ereport(lex, sem);
3490 
3491  return tab;
3492 }
HTAB * hash_create(const char *tabname, long nelem, const HASHCTL *info, int flags)
Definition: dynahash.c:350
#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:145
static void hash_object_field_start(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:3495
static void hash_object_field_end(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:3519
struct JsonHashEntry JsonHashEntry
static void hash_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:3579
static void hash_array_start(void *state)
Definition: jsonfuncs.c:3568
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 1438 of file jsonfuncs.c.

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

References array_contains_nulls(), deconstruct_array_builtin(), 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 1133 of file jsonfuncs.c.

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

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

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

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

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

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

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_builtin(path, TEXTOID, &pathtext, &pathnulls, &npath);
1004 
1005  tpath = palloc(npath * sizeof(char *));
1006  ipath = palloc(npath * sizeof(int));
1007 
1008  for (i = 0; i < npath; i++)
1009  {
1010  Assert(!pathnulls[i]);
1011  tpath[i] = TextDatumGetCString(pathtext[i]);
1012 
1013  /*
1014  * we have no idea at this stage what structure the document is so
1015  * just convert anything in the path that we can to an integer and set
1016  * all the other integers to INT_MIN which will never match.
1017  */
1018  if (*tpath[i] != '\0')
1019  {
1020  int ind;
1021  char *endptr;
1022 
1023  errno = 0;
1024  ind = strtoint(tpath[i], &endptr, 10);
1025  if (endptr == tpath[i] || *endptr != '\0' || errno != 0)
1026  ipath[i] = INT_MIN;
1027  else
1028  ipath[i] = ind;
1029  }
1030  else
1031  ipath[i] = INT_MIN;
1032  }
1033 
1034  result = get_worker(json, tpath, ipath, npath, as_text);
1035 
1036  if (result != NULL)
1037  PG_RETURN_TEXT_P(result);
1038  else
1039  PG_RETURN_NULL();
1040 }
#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:1060
void * palloc(Size size)
Definition: mcxt.c:1199
int strtoint(const char *pg_restrict str, char **pg_restrict endptr, int base)
Definition: string.c:51

References array_contains_nulls(), Assert(), deconstruct_array_builtin(), 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 3292 of file jsonfuncs.c.

3295 {
3296  cache->argtype = get_fn_expr_argtype(fcinfo->flinfo, 0);
3297  prepare_column_cache(&cache->c,
3298  cache->argtype, -1,
3299  cache->fn_mcxt, false);
3300  if (cache->c.typcat != TYPECAT_COMPOSITE &&
3301  cache->c.typcat != TYPECAT_COMPOSITE_DOMAIN)
3302  ereport(ERROR,
3303  (errcode(ERRCODE_DATATYPE_MISMATCH),
3304  /* translator: %s is a function name, eg json_to_record */
3305  errmsg("first argument of %s must be a row type",
3306  funcname)));
3307 }
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:2983
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 3318 of file jsonfuncs.c.

3321 {
3322  TupleDesc tupdesc;
3323  MemoryContext old_cxt;
3324 
3325  if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
3326  ereport(ERROR,
3327  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3328  /* translator: %s is a function name, eg json_to_record */
3329  errmsg("could not determine row type for result of %s",
3330  funcname),
3331  errhint("Provide a non-null record argument, "
3332  "or call the function in the FROM clause "
3333  "using a column definition list.")));
3334 
3335  Assert(tupdesc);
3336  cache->argtype = tupdesc->tdtypeid;
3337 
3338  /* If we go through this more than once, avoid memory leak */
3339  if (cache->c.io.composite.tupdesc)
3341 
3342  /* Save identified tupdesc */
3343  old_cxt = MemoryContextSwitchTo(cache->fn_mcxt);
3344  cache->c.io.composite.tupdesc = CreateTupleDescCopy(tupdesc);
3345  cache->c.io.composite.base_typid = tupdesc->tdtypeid;
3346  cache->c.io.composite.base_typmod = tupdesc->tdtypmod;
3347  MemoryContextSwitchTo(old_cxt);
3348 }
int errhint(const char *fmt,...)
Definition: elog.c:1153
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::@22 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 1385 of file jsonfuncs.c.

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

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

1065 {
1066  JsonLexContext *lex = makeJsonLexContext(json, true);
1067  JsonSemAction *sem = palloc0(sizeof(JsonSemAction));
1068  GetState *state = palloc0(sizeof(GetState));
1069 
1070  Assert(npath >= 0);
1071 
1072  state->lex = lex;
1073  /* is it "_as_text" variant? */
1074  state->normalize_results = normalize_results;
1075  state->npath = npath;
1076  state->path_names = tpath;
1077  state->path_indexes = ipath;
1078  state->pathok = palloc0(sizeof(bool) * npath);
1079  state->array_cur_index = palloc(sizeof(int) * npath);
1080 
1081  if (npath > 0)
1082  state->pathok[0] = true;
1083 
1084  sem->semstate = (void *) state;
1085 
1086  /*
1087  * Not all variants need all the semantic routines. Only set the ones that
1088  * are actually needed for maximum efficiency.
1089  */
1090  sem->scalar = get_scalar;
1091  if (npath == 0)
1092  {
1094  sem->object_end = get_object_end;
1096  sem->array_end = get_array_end;
1097  }
1098  if (tpath != NULL)
1099  {
1102  }
1103  if (ipath != NULL)
1104  {
1108  }
1109 
1110  pg_parse_json_or_ereport(lex, sem);
1111 
1112  return state->tresult;
1113 }
static void get_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:1385
static void get_array_element_end(void *state, bool isnull)
Definition: jsonfuncs.c:1343
static void get_object_field_end(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:1194
static void get_object_end(void *state)
Definition: jsonfuncs.c:1133
static void get_array_element_start(void *state, bool isnull)
Definition: jsonfuncs.c:1297
static void get_object_start(void *state)
Definition: jsonfuncs.c:1116
static void get_array_start(void *state)
Definition: jsonfuncs.c:1243
static void get_object_field_start(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:1149
static void get_array_end(void *state)
Definition: jsonfuncs.c:1281
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 3568 of file jsonfuncs.c.

3569 {
3570  JHashState *_state = (JHashState *) state;
3571 
3572  if (_state->lex->lex_level == 0)
3573  ereport(ERROR,
3574  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3575  errmsg("cannot call %s on an array", _state->function_name)));
3576 }
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 3519 of file jsonfuncs.c.

3520 {
3521  JHashState *_state = (JHashState *) state;
3522  JsonHashEntry *hashentry;
3523  bool found;
3524 
3525  /*
3526  * Ignore nested fields.
3527  */
3528  if (_state->lex->lex_level > 1)
3529  return;
3530 
3531  /*
3532  * Ignore field names >= NAMEDATALEN - they can't match a record field.
3533  * (Note: without this test, the hash code would truncate the string at
3534  * NAMEDATALEN-1, and could then match against a similarly-truncated
3535  * record field name. That would be a reasonable behavior, but this code
3536  * has previously insisted on exact equality, so we keep this behavior.)
3537  */
3538  if (strlen(fname) >= NAMEDATALEN)
3539  return;
3540 
3541  hashentry = hash_search(_state->hash, fname, HASH_ENTER, &found);
3542 
3543  /*
3544  * found being true indicates a duplicate. We don't do anything about
3545  * that, a later field with the same name overrides the earlier field.
3546  */
3547 
3548  hashentry->type = _state->saved_token_type;
3549  Assert(isnull == (hashentry->type == JSON_TOKEN_NULL));
3550 
3551  if (_state->save_json_start != NULL)
3552  {
3553  int len = _state->lex->prev_token_terminator - _state->save_json_start;
3554  char *val = palloc((len + 1) * sizeof(char));
3555 
3556  memcpy(val, _state->save_json_start, len);
3557  val[len] = '\0';
3558  hashentry->val = val;
3559  }
3560  else
3561  {
3562  /* must have had a scalar instead */
3563  hashentry->val = _state->saved_scalar;
3564  }
3565 }
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:953
@ 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 3495 of file jsonfuncs.c.

3496 {
3497  JHashState *_state = (JHashState *) state;
3498 
3499  if (_state->lex->lex_level > 1)
3500  return;
3501 
3502  /* remember token type */
3503  _state->saved_token_type = _state->lex->token_type;
3504 
3505  if (_state->lex->token_type == JSON_TOKEN_ARRAY_START ||
3507  {
3508  /* remember start position of the whole text of the subobject */
3509  _state->save_json_start = _state->lex->token_start;
3510  }
3511  else
3512  {
3513  /* must be a scalar */
3514  _state->save_json_start = NULL;
3515  }
3516 }
@ 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 3579 of file jsonfuncs.c.

3580 {
3581  JHashState *_state = (JHashState *) state;
3582 
3583  if (_state->lex->lex_level == 0)
3584  ereport(ERROR,
3585  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3586  errmsg("cannot call %s on a scalar", _state->function_name)));
3587 
3588  if (_state->lex->lex_level == 1)
3589  {
3590  _state->saved_scalar = token;
3591  /* saved_token_type must already be set in hash_object_field_start() */
3592  Assert(_state->saved_token_type == tokentype);
3593  }
3594 }

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

5308 {
5309  JsonLexContext *lex = makeJsonLexContext(json, true);
5310  JsonSemAction *sem = palloc0(sizeof(JsonSemAction));
5312 
5313  state->lex = lex;
5314  state->action = action;
5315  state->action_state = action_state;
5316  state->flags = flags;
5317 
5318  sem->semstate = (void *) state;
5321 
5322  pg_parse_json_or_ereport(lex, sem);
5323 }
static void iterate_values_object_field_start(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:5356
static void iterate_values_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:5330

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

5240 {
5241  JsonbIterator *it;
5242  JsonbValue v;
5244 
5245  it = JsonbIteratorInit(&jb->root);
5246 
5247  /*
5248  * Just recursively iterating over jsonb and call callback on all
5249  * corresponding elements
5250  */
5251  while ((type = JsonbIteratorNext(&it, &v, false)) != WJB_DONE)
5252  {
5253  if (type == WJB_KEY)
5254  {
5255  if (flags & jtiKey)
5256  action(state, v.val.string.val, v.val.string.len);
5257 
5258  continue;
5259  }
5260  else if (!(type == WJB_VALUE || type == WJB_ELEM))
5261  {
5262  /* do not call callback for composite JsonbValue */
5263  continue;
5264  }
5265 
5266  /* JsonbValue is a value of object or element of array */
5267  switch (v.type)
5268  {
5269  case jbvString:
5270  if (flags & jtiString)
5271  action(state, v.val.string.val, v.val.string.len);
5272  break;
5273  case jbvNumeric:
5274  if (flags & jtiNumeric)
5275  {
5276  char *val;
5277 
5279  NumericGetDatum(v.val.numeric)));
5280 
5281  action(state, val, strlen(val));
5282  pfree(val);
5283  }
5284  break;
5285  case jbvBool:
5286  if (flags & jtiBool)
5287  {
5288  if (v.val.boolean)
5289  action(state, "true", 4);
5290  else
5291  action(state, "false", 5);
5292  }
5293  break;
5294  default:
5295  /* do not call callback for composite JsonbValue */
5296  break;
5297  }
5298  }
5299 }
Datum numeric_out(PG_FUNCTION_ARGS)
Definition: numeric.c:735
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:642
@ jbvNumeric
Definition: jsonb.h:230
@ jbvBool
Definition: jsonb.h:231
@ 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:1306
static Datum NumericGetDatum(Numeric X)
Definition: numeric.h:72
static char * DatumGetCString(Datum X)
Definition: postgres.h:683

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

5357 {
5359 
5360  if (_state->flags & jtiKey)
5361  {
5362  char *val = pstrdup(fname);
5363 
5364  _state->action(_state->action_state, val, strlen(val));
5365  }
5366 }
char * pstrdup(const char *in)
Definition: mcxt.c:1483
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 5330 of file jsonfuncs.c.

5331 {
5333 
5334  switch (tokentype)
5335  {
5336  case JSON_TOKEN_STRING:
5337  if (_state->flags & jtiString)
5338  _state->action(_state->action_state, token, strlen(token));
5339  break;
5340  case JSON_TOKEN_NUMBER:
5341  if (_state->flags & jtiNumeric)
5342  _state->action(_state->action_state, token, strlen(token));
5343  break;
5344  case JSON_TOKEN_TRUE:
5345  case JSON_TOKEN_FALSE:
5346  if (_state->flags & jtiBool)
5347  _state->action(_state->action_state, token, strlen(token));
5348  break;
5349  default:
5350  /* do not call callback for any other token */
5351  break;
5352  }
5353 }
@ 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 4656 of file jsonfuncs.c.

4658 {
4659  JsonbValue v1,
4660  v2,
4661  *res = NULL;
4662  JsonbIteratorToken r1,
4663  r2,
4664  rk1,
4665  rk2;
4666 
4667  rk1 = JsonbIteratorNext(it1, &v1, false);
4668  rk2 = JsonbIteratorNext(it2, &v2, false);
4669 
4670  /*
4671  * JsonbIteratorNext reports raw scalars as if they were single-element
4672  * arrays; hence we only need consider "object" and "array" cases here.
4673  */
4674  if (rk1 == WJB_BEGIN_OBJECT && rk2 == WJB_BEGIN_OBJECT)
4675  {
4676  /*
4677  * Both inputs are objects.
4678  *
4679  * Append all the tokens from v1 to res, except last WJB_END_OBJECT
4680  * (because res will not be finished yet).
4681  */
4682  pushJsonbValue(state, rk1, NULL);
4683  while ((r1 = JsonbIteratorNext(it1, &v1, true)) != WJB_END_OBJECT)
4684  pushJsonbValue(state, r1, &v1);
4685 
4686  /*
4687  * Append all the tokens from v2 to res, including last WJB_END_OBJECT
4688  * (the concatenation will be completed). Any duplicate keys will
4689  * automatically override the value from the first object.
4690  */
4691  while ((r2 = JsonbIteratorNext(it2, &v2, true)) != WJB_DONE)
4692  res = pushJsonbValue(state, r2, r2 != WJB_END_OBJECT ? &v2 : NULL);
4693  }
4694  else if (rk1 == WJB_BEGIN_ARRAY && rk2 == WJB_BEGIN_ARRAY)
4695  {
4696  /*
4697  * Both inputs are arrays.
4698  */
4699  pushJsonbValue(state, rk1, NULL);
4700 
4701  while ((r1 = JsonbIteratorNext(it1, &v1, true)) != WJB_END_ARRAY)
4702  {
4703  Assert(r1 == WJB_ELEM);
4704  pushJsonbValue(state, r1, &v1);
4705  }
4706 
4707  while ((r2 = JsonbIteratorNext(it2, &v2, true)) != WJB_END_ARRAY)
4708  {
4709  Assert(r2 == WJB_ELEM);
4710  pushJsonbValue(state, WJB_ELEM, &v2);
4711  }
4712 
4713  res = pushJsonbValue(state, WJB_END_ARRAY, NULL /* signal to sort */ );
4714  }
4715  else if (rk1 == WJB_BEGIN_OBJECT)
4716  {
4717  /*
4718  * We have object || array.
4719  */
4720  Assert(rk2 == WJB_BEGIN_ARRAY);
4721 
4723 
4725  while ((r1 = JsonbIteratorNext(it1, &v1, true)) != WJB_DONE)
4726  pushJsonbValue(state, r1, r1 != WJB_END_OBJECT ? &v1 : NULL);
4727 
4728  while ((r2 = JsonbIteratorNext(it2, &v2, true)) != WJB_DONE)
4729  res = pushJsonbValue(state, r2, r2 != WJB_END_ARRAY ? &v2 : NULL);
4730  }
4731  else
4732  {
4733  /*
4734  * We have array || object.
4735  */
4736  Assert(rk1 == WJB_BEGIN_ARRAY);
4737  Assert(rk2 == WJB_BEGIN_OBJECT);
4738 
4740 
4741  while ((r1 = JsonbIteratorNext(it1, &v1, true)) != WJB_END_ARRAY)
4742  pushJsonbValue(state, r1, &v1);
4743 
4745  while ((r2 = JsonbIteratorNext(it2, &v2, true)) != WJB_DONE)
4746  pushJsonbValue(state, r2, r2 != WJB_END_OBJECT ? &v2 : NULL);
4747 
4749  }
4750 
4751  return res;
4752 }
@ 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:567

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

3152 {
3153  jsv->is_json = obj->is_json;
3154 
3155  if (jsv->is_json)
3156  {
3157  JsonHashEntry *hashentry = hash_search(obj->val.json_hash, field,
3158  HASH_FIND, NULL);
3159 
3160  jsv->val.json.type = hashentry ? hashentry->type : JSON_TOKEN_NULL;
3161  jsv->val.json.str = jsv->val.json.type == JSON_TOKEN_NULL ? NULL :
3162  hashentry->val;
3163  jsv->val.json.len = jsv->val.json.str ? -1 : 0; /* null-terminated */
3164 
3165  return hashentry != NULL;
3166  }
3167  else
3168  {
3169  jsv->val.jsonb = !obj->val.jsonb_cont ? NULL :
3170  getKeyJsonValueFromContainer(obj->val.jsonb_cont, field, strlen(field),
3171  NULL);
3172 
3173  return jsv->val.jsonb != NULL;
3174  }
3175 }
@ HASH_FIND
Definition: hsearch.h:113
JsonbValue * getKeyJsonValueFromContainer(JsonbContainer *container, const char *keyVal, int keyLen, JsonbValue *res)
Definition: jsonb_util.c:399
bool is_json
Definition: jsonfuncs.c:306
JsonbContainer * jsonb_cont
Definition: jsonfuncs.c:310
HTAB * json_hash
Definition: jsonfuncs.c:309
union JsObject::@25 val
JsonbValue * jsonb
Definition: jsonfuncs.c:300
bool is_json
Definition: jsonfuncs.c:290
struct JsValue::@23::@24 json
union JsValue::@23 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 2220 of file jsonfuncs.c.

2221 {
2222  return elements_worker(fcinfo, "json_array_elements", false);
2223 }
static Datum elements_worker(FunctionCallInfo fcinfo, const char *funcname, bool as_text)
Definition: jsonfuncs.c:2232

References elements_worker().

◆ json_array_elements_text()

Datum json_array_elements_text ( PG_FUNCTION_ARGS  )

Definition at line 2226 of file jsonfuncs.c.

2227 {
2228  return elements_worker(fcinfo, "json_array_elements_text", true);
2229 }

References elements_worker().

◆ json_array_length()

Datum json_array_length ( PG_FUNCTION_ARGS  )

Definition at line 1788 of file jsonfuncs.c.

1789 {
1790  text *json = PG_GETARG_TEXT_PP(0);
1791  AlenState *state;
1792  JsonLexContext *lex;
1793  JsonSemAction *sem;
1794 
1795  lex = makeJsonLexContext(json, false);
1796  state = palloc0(sizeof(AlenState));
1797  sem = palloc0(sizeof(JsonSemAction));
1798 
1799  /* palloc0 does this for us */
1800 #if 0
1801  state->count = 0;
1802 #endif
1803  state->lex = lex;
1804 
1805  sem->semstate = (void *) state;
1807  sem->scalar = alen_scalar;
1809 
1810  pg_parse_json_or_ereport(lex, sem);
1811 
1812  PG_RETURN_INT32(state->count);
1813 }
#define PG_RETURN_INT32(x)
Definition: fmgr.h:354
static void alen_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:1850
static void alen_object_start(void *state)
Definition: jsonfuncs.c:1838
static void alen_array_element_start(void *state, bool isnull)
Definition: jsonfuncs.c:1862

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

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

References each_worker().

◆ json_each_text()

Datum json_each_text ( PG_FUNCTION_ARGS  )

Definition at line 1894 of file jsonfuncs.c.

1895 {
1896  return each_worker(fcinfo, true);
1897 }

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"),
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"),
625  report_json_context(lex)));
626 }
int errdetail_internal(const char *fmt,...)
Definition: elog.c:1066
char * json_errdetail(JsonParseErrorType error, JsonLexContext *lex)
Definition: jsonapi.c:1089
@ 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_internal(), errmsg(), ERROR, error(), json_errdetail(), JSON_UNICODE_CODE_POINT_ZERO, JSON_UNICODE_HIGH_ESCAPE, and report_json_context().

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

◆ 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_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:222

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:303
#define SRF_PERCALL_SETUP()
Definition: funcapi.h:307
#define SRF_RETURN_NEXT(_funcctx, _result)
Definition: funcapi.h:309
#define SRF_FIRSTCALL_INIT()
Definition: funcapi.h:305
#define SRF_RETURN_DONE(_funcctx)
Definition: funcapi.h:327
if(TABLE==NULL||TABLE_index==NULL)
Definition: isn.c:77
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 2392 of file jsonfuncs.c.

2393 {
2394  return populate_record_worker(fcinfo, "json_populate_record",
2395  true, true);
2396 }
static Datum populate_record_worker(FunctionCallInfo fcinfo, const char *funcname, bool is_json, bool have_record_arg)
Definition: jsonfuncs.c:3355

References populate_record_worker().

◆ json_populate_recordset()

Datum json_populate_recordset ( PG_FUNCTION_ARGS  )

Definition at line 3622 of file jsonfuncs.c.

3623 {
3624  return populate_recordset_worker(fcinfo, "json_populate_recordset",
3625  true, true);
3626 }
static Datum populate_recordset_worker(FunctionCallInfo fcinfo, const char *funcname, bool is_json, bool have_record_arg)
Definition: jsonfuncs.c:3673

References populate_recordset_worker().

◆ json_strip_nulls()

Datum json_strip_nulls ( PG_FUNCTION_ARGS  )

Definition at line 4096 of file jsonfuncs.c.

4097 {
4098  text *json = PG_GETARG_TEXT_PP(0);
4100  JsonLexContext *lex;
4101  JsonSemAction *sem;
4102 
4103  lex = makeJsonLexContext(json, true);
4104  state = palloc0(sizeof(StripnullState));
4105  sem = palloc0(sizeof(JsonSemAction));
4106 
4107  state->strval = makeStringInfo();
4108  state->skip_next_null = false;
4109  state->lex = lex;
4110 
4111  sem->semstate = (void *) state;
4113  sem->object_end = sn_object_end;
4114  sem->array_start = sn_array_start;
4115  sem->array_end = sn_array_end;
4116  sem->scalar = sn_scalar;
4119 
4120  pg_parse_json_or_ereport(lex, sem);
4121 
4123  state->strval->len));
4124 }
static void sn_array_end(void *state)
Definition: jsonfuncs.c:4030
static void sn_object_end(void *state)
Definition: jsonfuncs.c:4014
static void sn_array_element_start(void *state, bool isnull)
Definition: jsonfuncs.c:4066
static void sn_object_field_start(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:4038
static void sn_array_start(void *state)
Definition: jsonfuncs.c:4022
static void sn_object_start(void *state)
Definition: jsonfuncs.c:4006
static void sn_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:4075
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 2399 of file jsonfuncs.c.

2400 {
2401  return populate_record_worker(fcinfo, "json_to_record",
2402  true, false);
2403 }

References populate_record_worker().

◆ json_to_recordset()

Datum json_to_recordset ( PG_FUNCTION_ARGS  )

Definition at line 3629 of file jsonfuncs.c.

3630 {
3631  return populate_recordset_worker(fcinfo, "json_to_recordset",
3632  true, false);
3633 }

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:442
#define PG_RETURN_JSONB_P(x)
Definition: jsonb.h:391
#define JB_ROOT_COUNT(jbp_)
Definition: jsonb.h:219
JsonbValue * getIthJsonbValueFromContainer(JsonbContainer *container, uint32 i)
Definition: jsonb_util.c:469

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

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

References elements_worker_jsonb().

◆ jsonb_array_elements_text()

Datum jsonb_array_elements_text ( PG_FUNCTION_ARGS  )

Definition at line 2138 of file jsonfuncs.c.

2139 {
2140  return elements_worker_jsonb(fcinfo, "jsonb_array_elements_text", true);
2141 }

References elements_worker_jsonb().

◆ jsonb_array_length()

Datum jsonb_array_length ( PG_FUNCTION_ARGS  )

Definition at line 1816 of file jsonfuncs.c.

1817 {
1818  Jsonb *jb = PG_GETARG_JSONB_P(0);
1819 
1820  if (JB_ROOT_IS_SCALAR(jb))
1821  ereport(ERROR,
1822  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1823  errmsg("cannot get array length of a scalar")));
1824  else if (!JB_ROOT_IS_ARRAY(jb))
1825  ereport(ERROR,
1826  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1827  errmsg("cannot get array length of a non-array")));
1828 
1830 }

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

4205 {
4206  Jsonb *jb1 = PG_GETARG_JSONB_P(0);
4207  Jsonb *jb2 = PG_GETARG_JSONB_P(1);
4208  JsonbParseState *state = NULL;
4209  JsonbValue *res;
4210  JsonbIterator *it1,
4211  *it2;
4212 
4213  /*
4214  * If one of the jsonb is empty, just return the other if it's not scalar
4215  * and both are of the same kind. If it's a scalar or they are of
4216  * different kinds we need to perform the concatenation even if one is
4217  * empty.
4218  */
4219  if (JB_ROOT_IS_OBJECT(jb1) == JB_ROOT_IS_OBJECT(jb2))
4220  {
4221  if (JB_ROOT_COUNT(jb1) == 0 && !JB_ROOT_IS_SCALAR(jb2))
4222  PG_RETURN_JSONB_P(jb2);
4223  else if (JB_ROOT_COUNT(jb2) == 0 && !JB_ROOT_IS_SCALAR(jb1))
4224  PG_RETURN_JSONB_P(jb1);
4225  }
4226 
4227  it1 = JsonbIteratorInit(&jb1->root);
4228  it2 = JsonbIteratorInit(&jb2->root);
4229 
4230  res = IteratorConcat(&it1, &it2, &state);
4231 
4232  Assert(res != NULL);
4233 
4235 }
static JsonbValue * IteratorConcat(JsonbIterator **it1, JsonbIterator **it2, JsonbParseState **state)
Definition: jsonfuncs.c:4656

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

4246 {
4247  Jsonb *in = PG_GETARG_JSONB_P(0);
4248  text *key = PG_GETARG_TEXT_PP(1);
4249  char *keyptr = VARDATA_ANY(key);
4250  int keylen = VARSIZE_ANY_EXHDR(key);
4251  JsonbParseState *state = NULL;
4252  JsonbIterator *it;
4253  JsonbValue v,
4254  *res = NULL;
4255  bool skipNested = false;
4257 
4258  if (JB_ROOT_IS_SCALAR(in))
4259  ereport(ERROR,
4260  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4261  errmsg("cannot delete from scalar")));
4262 
4263  if (JB_ROOT_COUNT(in) == 0)
4264  PG_RETURN_JSONB_P(in);
4265 
4266  it = JsonbIteratorInit(&in->root);
4267 
4268  while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE)
4269  {
4270  skipNested = true;
4271 
4272  if ((r == WJB_ELEM || r == WJB_KEY) &&
4273  (v.type == jbvString && keylen == v.val.string.len &&
4274  memcmp(keyptr, v.val.string.val, keylen) == 0))
4275  {
4276  /* skip corresponding value as well */
4277  if (r == WJB_KEY)
4278  (void) JsonbIteratorNext(&it, &v, true);
4279 
4280  continue;
4281  }
4282 
4283  res = pushJsonbValue(&state, r, r < WJB_BEGIN_ARRAY ? &v : NULL);
4284  }
4285 
4286  Assert(res != NULL);
4287 
4289 }
#define VARDATA_ANY(PTR)
Definition: postgres.h:362
#define VARSIZE_ANY_EXHDR(PTR)
Definition: postgres.h:355

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

4299 {
4300  Jsonb *in = PG_GETARG_JSONB_P(0);
4301  ArrayType *keys = PG_GETARG_ARRAYTYPE_P(1);
4302  Datum *keys_elems;
4303  bool *keys_nulls;
4304  int keys_len;
4305  JsonbParseState *state = NULL;
4306  JsonbIterator *it;
4307  JsonbValue v,
4308  *res = NULL;
4309  bool skipNested = false;
4311 
4312  if (ARR_NDIM(keys) > 1)
4313  ereport(ERROR,
4314  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
4315  errmsg("wrong number of array subscripts")));
4316 
4317  if (JB_ROOT_IS_SCALAR(in))
4318  ereport(ERROR,
4319  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4320  errmsg("cannot delete from scalar")));
4321 
4322  if (JB_ROOT_COUNT(in) == 0)
4323  PG_RETURN_JSONB_P(in);
4324 
4325  deconstruct_array_builtin(keys, TEXTOID, &keys_elems, &keys_nulls, &keys_len);
4326 
4327  if (keys_len == 0)
4328  PG_RETURN_JSONB_P(in);
4329 
4330  it = JsonbIteratorInit(&in->root);
4331 
4332  while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE)
4333  {
4334  skipNested = true;
4335 
4336  if ((r == WJB_ELEM || r == WJB_KEY) && v.type == jbvString)
4337  {
4338  int i;
4339  bool found = false;
4340 
4341  for (i = 0; i < keys_len; i++)
4342  {
4343  char *keyptr;
4344  int keylen;
4345 
4346  if (keys_nulls[i])
4347  continue;
4348 
4349  keyptr = VARDATA_ANY(keys_elems[i]);
4350  keylen = VARSIZE_ANY_EXHDR(keys_elems[i]);
4351  if (keylen == v.val.string.len &&
4352  memcmp(keyptr, v.val.string.val, keylen) == 0)
4353  {
4354  found = true;
4355  break;
4356  }
4357  }
4358  if (found)
4359  {
4360  /* skip corresponding value as well */
4361  if (r == WJB_KEY)
4362  (void) JsonbIteratorNext(&it, &v, true);
4363 
4364  continue;
4365  }
4366  }
4367 
4368  res = pushJsonbValue(&state, r, r < WJB_BEGIN_ARRAY ? &v : NULL);
4369  }
4370 
4371  Assert(res != NULL);
4372 
4374 }
#define ARR_NDIM(a)
Definition: array.h:283

References ARR_NDIM, Assert(), deconstruct_array_builtin(), 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 4384 of file jsonfuncs.c.

4385 {
4386  Jsonb *in = PG_GETARG_JSONB_P(0);
4387  int idx = PG_GETARG_INT32(1);
4388  JsonbParseState *state = NULL;
4389  JsonbIterator *it;
4390  uint32 i = 0,
4391  n;
4392  JsonbValue v,
4393  *res = NULL;
4395 
4396  if (JB_ROOT_IS_SCALAR(in))
4397  ereport(ERROR,
4398  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4399  errmsg("cannot delete from scalar")));
4400 
4401  if (JB_ROOT_IS_OBJECT(in))
4402  ereport(ERROR,
4403  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4404  errmsg("cannot delete from object using integer index")));
4405 
4406  if (JB_ROOT_COUNT(in) == 0)
4407  PG_RETURN_JSONB_P(in);
4408 
4409  it = JsonbIteratorInit(&in->root);
4410 
4411  r = JsonbIteratorNext(&it, &v, false);
4412  Assert(r == WJB_BEGIN_ARRAY);
4413  n = v.val.array.nElems;
4414 
4415  if (idx < 0)
4416  {
4417  if (-idx > n)
4418  idx = n;
4419  else
4420  idx = n + idx;
4421  }
4422 
4423  if (idx >= n)
4424  PG_RETURN_JSONB_P(in);
4425 
4426  pushJsonbValue(&state, r, NULL);
4427 
4428  while ((r = JsonbIteratorNext(&it, &v, true)) != WJB_DONE)
4429  {
4430  if (r == WJB_ELEM)
4431  {
4432  if (i++ == idx)
4433  continue;
4434  }
4435 
4436  res = pushJsonbValue(&state, r, r < WJB_BEGIN_ARRAY ? &v : NULL);
4437  }
4438 
4439  Assert(res != NULL);
4440 
4442 }
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 4564 of file jsonfuncs.c.

4565 {
4566  Jsonb *in = PG_GETARG_JSONB_P(0);
4567  ArrayType *path = PG_GETARG_ARRAYTYPE_P(1);
4568  JsonbValue *res = NULL;
4569  Datum *path_elems;
4570  bool *path_nulls;
4571  int path_len;
4572  JsonbIterator *it;
4573  JsonbParseState *st = NULL;
4574 
4575  if (ARR_NDIM(path) > 1)
4576  ereport(ERROR,
4577  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
4578  errmsg("wrong number of array subscripts")));
4579 
4580  if (JB_ROOT_IS_SCALAR(in))
4581  ereport(ERROR,
4582  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4583  errmsg("cannot delete path in scalar")));
4584 
4585  if (JB_ROOT_COUNT(in) == 0)
4586  PG_RETURN_JSONB_P(in);
4587 
4588  deconstruct_array_builtin(path, TEXTOID, &path_elems, &path_nulls, &path_len);
4589 
4590  if (path_len == 0)
4591  PG_RETURN_JSONB_P(in);
4592 
4593  it = JsonbIteratorInit(&in->root);
4594 
4595  res = setPath(&it, path_elems, path_nulls, path_len, &st,
4596  0, NULL, JB_PATH_DELETE);
4597 
4598  Assert(res != NULL);
4599 
4601 }
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:4784
#define JB_PATH_DELETE
Definition: jsonfuncs.c:42

References ARR_NDIM, Assert(), deconstruct_array_builtin(), 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 1888 of file jsonfuncs.c.

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

References each_worker_jsonb().

◆ jsonb_each_text()

Datum jsonb_each_text ( PG_FUNCTION_ARGS  )

Definition at line 1900 of file jsonfuncs.c.

1901 {
1902  return each_worker_jsonb(fcinfo, "jsonb_each_text", true);
1903 }

References each_worker_jsonb().

◆ jsonb_extract_path()

Datum jsonb_extract_path ( PG_FUNCTION_ARGS  )

Definition at line 1426 of file jsonfuncs.c.

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

References get_jsonb_path_all().

◆ jsonb_extract_path_text()

Datum jsonb_extract_path_text ( PG_FUNCTION_ARGS  )

Definition at line 1432 of file jsonfuncs.c.

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

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

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

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

4608 {
4609  Jsonb *in = PG_GETARG_JSONB_P(0);
4610  ArrayType *path = PG_GETARG_ARRAYTYPE_P(1);
4611  Jsonb *newjsonb = PG_GETARG_JSONB_P(2);
4613  bool after = PG_GETARG_BOOL(3);
4614  JsonbValue *res = NULL;
4615  Datum *path_elems;
4616  bool *path_nulls;
4617  int path_len;
4618  JsonbIterator *it;
4619  JsonbParseState *st = NULL;
4620 
4621  JsonbToJsonbValue(newjsonb, &newval);
4622 
4623  if (ARR_NDIM(path) > 1)
4624  ereport(ERROR,
4625  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
4626  errmsg("wrong number of array subscripts")));
4627 
4628  if (JB_ROOT_IS_SCALAR(in))
4629  ereport(ERROR,
4630  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4631  errmsg("cannot set path in scalar")));
4632 
4633  deconstruct_array_builtin(path, TEXTOID, &path_elems, &path_nulls, &path_len);
4634 
4635  if (path_len == 0)
4636  PG_RETURN_JSONB_P(in);
4637 
4638  it = JsonbIteratorInit(&in->root);
4639 
4640  res = setPath(&it, path_elems, path_nulls, path_len, &st, 0, &newval,
4642 
4643  Assert(res != NULL);
4644 
4646 }
#define PG_GETARG_BOOL(n)
Definition: fmgr.h:274
#define newval
void JsonbToJsonbValue(Jsonb *jsonb, JsonbValue *val)
Definition: jsonb_util.c:73
#define JB_PATH_INSERT_BEFORE
Definition: jsonfuncs.c:44
#define JB_PATH_INSERT_AFTER
Definition: jsonfuncs.c:45

References ARR_NDIM, Assert(), deconstruct_array_builtin(), 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 2378 of file jsonfuncs.c.

2379 {
2380  return populate_record_worker(fcinfo, "jsonb_populate_record",
2381  false, true);
2382 }

References populate_record_worker().

◆ jsonb_populate_recordset()

Datum jsonb_populate_recordset ( PG_FUNCTION_ARGS  )

Definition at line 3608 of file jsonfuncs.c.

3609 {
3610  return populate_recordset_worker(fcinfo, "jsonb_populate_recordset",
3611  false, true);
3612 }

References populate_recordset_worker().

◆ jsonb_pretty()

Datum jsonb_pretty ( PG_FUNCTION_ARGS  )

Definition at line 4188 of file jsonfuncs.c.

4189 {
4190  Jsonb *jb = PG_GETARG_JSONB_P(0);
4192 
4193  JsonbToCStringIndent(str, &jb->root, VARSIZE(jb));
4194 
4196 }
char * JsonbToCStringIndent(StringInfo out, JsonbContainer *in, int estimated_len)
Definition: jsonb.c:469

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

4449 {
4450  Jsonb *in = PG_GETARG_JSONB_P(0);
4451  ArrayType *path = PG_GETARG_ARRAYTYPE_P(1);
4452  Jsonb *newjsonb = PG_GETARG_JSONB_P(2);
4454  bool create = PG_GETARG_BOOL(3);
4455  JsonbValue *res = NULL;
4456  Datum *path_elems;
4457  bool *path_nulls;
4458  int path_len;
4459  JsonbIterator *it;
4460  JsonbParseState *st = NULL;
4461 
4462  JsonbToJsonbValue(newjsonb, &newval);
4463 
4464  if (ARR_NDIM(path) > 1)
4465  ereport(ERROR,
4466  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
4467  errmsg("wrong number of array subscripts")));
4468 
4469  if (JB_ROOT_IS_SCALAR(in))
4470  ereport(ERROR,
4471  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4472  errmsg("cannot set path in scalar")));
4473 
4474  if (JB_ROOT_COUNT(in) == 0 && !create)
4475  PG_RETURN_JSONB_P(in);
4476 
4477  deconstruct_array_builtin(path, TEXTOID, &path_elems, &path_nulls, &path_len);
4478 
4479  if (path_len == 0)
4480  PG_RETURN_JSONB_P(in);
4481 
4482  it = JsonbIteratorInit(&in->root);
4483 
4484  res = setPath(&it, path_elems, path_nulls, path_len, &st,
4485  0, &newval, create ? JB_PATH_CREATE : JB_PATH_REPLACE);
4486 
4487  Assert(res != NULL);
4488 
4490 }
#define JB_PATH_CREATE
Definition: jsonfuncs.c:41
#define JB_PATH_REPLACE
Definition: jsonfuncs.c:43

References ARR_NDIM, Assert(), deconstruct_array_builtin(), 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 1615 of file jsonfuncs.c.

1617 {
1618  JsonbValue *res;
1619  JsonbParseState *state = NULL;
1620  JsonbIterator *it;
1621  bool *path_nulls = palloc0(path_len * sizeof(bool));
1622 
1623  if (newval->type == jbvArray && newval->val.array.rawScalar)
1624  *newval = newval->val.array.elems[0];
1625 
1626  it = JsonbIteratorInit(&jb->root);
1627 
1628  res = setPath(&it, path, path_nulls, path_len, &state, 0, newval,
1631 
1632  pfree(path_nulls);
1633 
1635 }
@ jbvArray
Definition: jsonb.h:233
#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 4497 of file jsonfuncs.c.

4498 {
4499  /* Jsonb *in = PG_GETARG_JSONB_P(0); */
4500  /* ArrayType *path = PG_GETARG_ARRAYTYPE_P(1); */
4501  /* Jsonb *newval = PG_GETARG_JSONB_P(2); */
4502  /* bool create = PG_GETARG_BOOL(3); */
4503  text *handle_null;
4504  char *handle_val;
4505 
4506  if (PG_ARGISNULL(0) || PG_ARGISNULL(1) || PG_ARGISNULL(3))
4507  PG_RETURN_NULL();
4508 
4509  /* could happen if they pass in an explicit NULL */
4510  if (PG_ARGISNULL(4))
4511  ereport(ERROR,
4512  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4513  errmsg("null_value_treatment must be \"delete_key\", \"return_target\", \"use_json_null\", or \"raise_exception\"")));
4514 
4515  /* if the new value isn't an SQL NULL just call jsonb_set */
4516  if (!PG_ARGISNULL(2))
4517  return jsonb_set(fcinfo);
4518 
4519  handle_null = PG_GETARG_TEXT_P(4);
4520  handle_val = text_to_cstring(handle_null);
4521 
4522  if (strcmp(handle_val, "raise_exception") == 0)
4523  {
4524  ereport(ERROR,
4525  (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
4526  errmsg("JSON value must not be null"),
4527  errdetail("Exception was raised because null_value_treatment is \"raise_exception\"."),
4528  errhint("To avoid, either change the null_value_treatment argument or ensure that an SQL NULL is not passed.")));
4529  return (Datum) 0; /* silence stupider compilers */
4530  }
4531  else if (strcmp(handle_val, "use_json_null") == 0)
4532  {
4533  Datum newval;
4534 
4536 
4537  fcinfo->args[2].value = newval;
4538  fcinfo->args[2].isnull = false;
4539  return jsonb_set(fcinfo);
4540  }
4541  else if (strcmp(handle_val, "delete_key") == 0)
4542  {
4543  return jsonb_delete_path(fcinfo);
4544  }
4545  else if (strcmp(handle_val, "return_target") == 0)
4546  {
4547  Jsonb *in = PG_GETARG_JSONB_P(0);
4548 
4549  PG_RETURN_JSONB_P(in);
4550  }
4551  else
4552  {
4553  ereport(ERROR,
4554  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4555  errmsg("null_value_treatment must be \"delete_key\", \"return_target\", \"use_json_null\", or \"raise_exception\"")));
4556  return (Datum) 0; /* silence stupider compilers */
4557  }
4558 }
int errdetail(const char *fmt,...)
Definition: elog.c:1039
#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:97
Datum jsonb_delete_path(PG_FUNCTION_ARGS)
Definition: jsonfuncs.c:4564
Datum jsonb_set(PG_FUNCTION_ARGS)
Definition: jsonfuncs.c:4448
static Datum CStringGetDatum(const char *X)
Definition: postgres.h:698

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

4131 {
4132  Jsonb *jb = PG_GETARG_JSONB_P(0);
4133  JsonbIterator *it;
4134  JsonbParseState *parseState = NULL;
4135  JsonbValue *res = NULL;
4136  JsonbValue v,
4137  k;
4139  bool last_was_key = false;
4140 
4141  if (JB_ROOT_IS_SCALAR(jb))
4142  PG_RETURN_POINTER(jb);
4143 
4144  it = JsonbIteratorInit(&jb->root);
4145 
4146  while ((type = JsonbIteratorNext(&it, &v, false)) != WJB_DONE)
4147  {
4148  Assert(!(type == WJB_KEY && last_was_key));
4149 
4150  if (type == WJB_KEY)
4151  {
4152  /* stash the key until we know if it has a null value */
4153  k = v;
4154  last_was_key = true;
4155  continue;
4156  }
4157 
4158  if (last_was_key)
4159  {
4160  /* if the last element was a key this one can't be */
4161  last_was_key = false;
4162 
4163  /* skip this field if value is null */
4164  if (type == WJB_VALUE && v.type == jbvNull)
4165  continue;
4166 
4167  /* otherwise, do a delayed push of the key */
4168  (void) pushJsonbValue(&parseState, WJB_KEY, &k);
4169  }
4170 
4171  if (type == WJB_VALUE || type == WJB_ELEM)
4172  res = pushJsonbValue(&parseState, type, &v);
4173  else
4174  res = pushJsonbValue(&parseState, type, NULL);
4175  }
4176 
4177  Assert(res != NULL);
4178 
4180 }
#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 2385 of file jsonfuncs.c.

2386 {
2387  return populate_record_worker(fcinfo, "jsonb_to_record",
2388  false, false);
2389 }

References populate_record_worker().

◆ jsonb_to_recordset()

Datum jsonb_to_recordset ( PG_FUNCTION_ARGS  )

Definition at line 3615 of file jsonfuncs.c.

3616 {
3617  return populate_recordset_worker(fcinfo, "jsonb_to_recordset",
3618  false, false);
3619 }

References populate_recordset_worker().

◆ JsonbValueAsText()

static text * JsonbValueAsText ( JsonbValue v)
static

Definition at line 1741 of file jsonfuncs.c.

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

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

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:1321
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 5170 of file jsonfuncs.c.

5171 {
5172  JsonbIterator *it;
5173  JsonbValue v;
5175  uint32 flags = 0;
5176 
5177  it = JsonbIteratorInit(&jb->root);
5178 
5179  type = JsonbIteratorNext(&it, &v, false);
5180 
5181  /*
5182  * We iterate over array (scalar internally is represented as array, so,
5183  * we will accept it too) to check all its elements. Flag names are
5184  * chosen the same as jsonb_typeof uses.
5185  */
5186  if (type != WJB_BEGIN_ARRAY)
5187  ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
5188  errmsg("wrong flag type, only arrays and scalars are allowed")));
5189 
5190  while ((type = JsonbIteratorNext(&it, &v, false)) == WJB_ELEM)
5191  {
5192  if (v.type != jbvString)
5193  ereport(ERROR,
5194  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
5195  errmsg("flag array element is not a string"),
5196  errhint("Possible values are: \"string\", \"numeric\", \"boolean\", \"key\", and \"all\".")));
5197 
5198  if (v.val.string.len == 3 &&
5199  pg_strncasecmp(v.val.string.val, "all", 3) == 0)
5200  flags |= jtiAll;
5201  else if (v.val.string.len == 3 &&
5202  pg_strncasecmp(v.val.string.val, "key", 3) == 0)
5203  flags |= jtiKey;
5204  else if (v.val.string.len == 6 &&
5205  pg_strncasecmp(v.val.string.val, "string", 6) == 0)
5206  flags |= jtiString;
5207  else if (v.val.string.len == 7 &&
5208  pg_strncasecmp(v.val.string.val, "numeric", 7) == 0)
5209  flags |= jtiNumeric;
5210  else if (v.val.string.len == 7 &&
5211  pg_strncasecmp(v.val.string.val, "boolean", 7) == 0)
5212  flags |= jtiBool;
5213  else
5214  ereport(ERROR,
5215  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
5216  errmsg("wrong flag in flag array: \"%s\"",
5217  pnstrdup(v.val.string.val, v.val.string.len)),
5218  errhint("Possible values are: \"string\", \"numeric\", \"boolean\", \"key\", and \"all\".")));
5219  }
5220 
5221  /* expect end of array now */
5222  if (type != WJB_END_ARRAY)
5223  elog(ERROR, "unexpected end of flag array");
5224 
5225  /* get final WJB_DONE and free iterator */
5226  type = JsonbIteratorNext(&it, &v, false);
5227  if (type != WJB_DONE)
5228  elog(ERROR, "unexpected end of flag array");
5229 
5230  return flags;
5231 }
@ jtiAll
Definition: jsonfuncs.h:30
char * pnstrdup(const char *in, Size len)
Definition: mcxt.c:1494
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:169

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

2721 {
2723  Datum result;
2724  int *lbs;
2725  int i;
2726 
2727  ctx.aio = aio;
2728  ctx.mcxt = mcxt;
2729  ctx.acxt = CurrentMemoryContext;
2730  ctx.astate = initArrayResult(aio->element_type, ctx.acxt, true);
2731  ctx.colname = colname;
2732  ctx.ndims = 0; /* unknown yet */
2733  ctx.dims = NULL;
2734  ctx.sizes = NULL;
2735 
2736  if (jsv->is_json)
2737  populate_array_json(&ctx, jsv->val.json.str,
2738  jsv->val.json.len >= 0 ? jsv->val.json.len
2739  : strlen(jsv->val.json.str));
2740  else
2741  {
2742  populate_array_dim_jsonb(&ctx, jsv->val.jsonb, 1);
2743  ctx.dims[0] = ctx.sizes[0];
2744  }
2745 
2746  Assert(ctx.ndims > 0);
2747 
2748  lbs = palloc(sizeof(int) * ctx.ndims);
2749 
2750  for (i = 0; i < ctx.ndims; i++)
2751  lbs[i] = 1;
2752 
2753  result = makeMdArrayResult(ctx.astate, ctx.ndims, ctx.dims, lbs,
2754  ctx.acxt, true);
2755 
2756  pfree(ctx.dims);
2757  pfree(ctx.sizes);
2758  pfree(lbs);
2759 
2760  return result;
2761 }
ArrayBuildState * initArrayResult(Oid element_type, MemoryContext rcontext, bool subcontext)
Definition: arrayfuncs.c:5238
Datum makeMdArrayResult(ArrayBuildState *astate, int ndims, int *dims, int *lbs, MemoryContext rcontext, bool release)
Definition: arrayfuncs.c:5373
static void populate_array_json(PopulateArrayContext *ctx, char *json, int len)
Definition: jsonfuncs.c:2617
static void populate_array_dim_jsonb(PopulateArrayContext *ctx, JsonbValue *jbv, int ndim)
Definition: jsonfuncs.c:2646
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 2525 of file jsonfuncs.c.

2526 {
2528  PopulateArrayContext *ctx = state->ctx;
2529  int ndim = state->lex->lex_level;
2530 
2531  if (ctx->ndims <= 0)
2532  populate_array_assign_ndims(ctx, ndim + 1);
2533 
2534  if (ndim < ctx->ndims)
2535  populate_array_check_dimension(ctx, ndim);
2536 }
static void populate_array_check_dimension(PopulateArrayContext *ctx, int ndim)
Definition: jsonfuncs.c:2469
static void populate_array_assign_ndims(PopulateArrayContext *ctx, int ndims)
Definition: jsonfuncs.c:2450

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

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

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

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

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

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

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

2492 {
2493  Datum element;
2494  bool element_isnull;
2495 
2496  /* populate the array element */
2498  ctx->aio->element_type,
2499  ctx->aio->element_typmod,
2500  NULL, ctx->mcxt, PointerGetDatum(NULL),
2501  jsv, &element_isnull);
2502 
2503  accumArrayResult(ctx->astate, element, element_isnull,
2504  ctx->aio->element_type, ctx->acxt);
2505 
2506  Assert(ndim > 0);
2507  ctx->sizes[ndim - 1]++; /* increment current dimension counter */
2508 }
ArrayBuildState * accumArrayResult(ArrayBuildState *astate, Datum dvalue, bool disnull, Oid element_type, MemoryContext rcontext)
Definition: arrayfuncs.c:5277
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:3070
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 2556 of file jsonfuncs.c.

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

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

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

Referenced by populate_array_json().

◆ populate_array_json()

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

Definition at line 2617 of file jsonfuncs.c.

2618 {
2620  JsonSemAction sem;
2621 
2623  state.ctx = ctx;
2624 
2625  memset(&sem, 0, sizeof(sem));
2626  sem.semstate = (void *) &state;
2632 
2633  pg_parse_json_or_ereport(state.lex, &sem);
2634 
2635  /* number of dimensions should be already known */
2636  Assert(ctx->ndims > 0 && ctx->dims);
2637 
2638  pfree(state.lex);
2639 }
static void populate_array_element_start(void *_state, bool isnull)
Definition: jsonfuncs.c:2540
static void populate_array_scalar(void *_state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:2595
static void populate_array_object_start(void *_state)
Definition: jsonfuncs.c:2512
static void populate_array_array_end(void *_state)
Definition: jsonfuncs.c:2525
static void populate_array_element_end(void *_state, bool isnull)
Definition: jsonfuncs.c:2556

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

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

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

2408 {
2409  if (ndim <= 0)
2410  {
2411  if (ctx->colname)
2412  ereport(ERROR,
2413  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2414  errmsg("expected JSON array"),
2415  errhint("See the value of key \"%s\".", ctx->colname)));
2416  else
2417  ereport(ERROR,
2418  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2419  errmsg("expected JSON array")));
2420  }
2421  else
2422  {
2423  StringInfoData indices;
2424  int i;
2425 
2426  initStringInfo(&indices);
2427 
2428  Assert(ctx->ndims > 0 && ndim < ctx->ndims);
2429 
2430  for (i = 0; i < ndim; i++)
2431  appendStringInfo(&indices, "[%d]", ctx->sizes[i]);
2432 
2433  if (ctx->colname)
2434  ereport(ERROR,
2435  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2436  errmsg("expected JSON array"),
2437  errhint("See the array element %s of key \"%s\".",
2438  indices.data, ctx->colname)));
2439  else
2440  ereport(ERROR,
2441  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2442  errmsg("expected JSON array"),
2443  errhint("See the array element %s.",
2444  indices.data)));
2445  }
2446 }
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:91

References appendStringInfo(), Assert(), PopulateArrayContext::colname, StringInfoData::data, ereport, errcode(), errhint(), errmsg(), ERROR, i, initStringInfo(), PopulateArrayContext::ndims, and PopulateArrayContext::sizes.

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

◆ populate_array_scalar()

static void populate_array_scalar ( void *  _state,
char *  token,
JsonTokenType  tokentype 
)
static

Definition at line 2595 of file jsonfuncs.c.

2596 {
2598  PopulateArrayContext *ctx = state->ctx;
2599  int ndim = state->lex->lex_level;
2600 
2601  if (ctx->ndims <= 0)
2602  populate_array_assign_ndims(ctx, ndim);
2603  else if (ndim < ctx->ndims)
2605 
2606  if (ndim == ctx->ndims)
2607  {
2608  /* remember the scalar element token */
2609  state->element_scalar = token;
2610  /* element_type must already be set in populate_array_element_start() */
2611  Assert(state->element_type == tokentype);
2612  }
2613 }

References Assert(), PopulateArrayContext::ndims, populate_array_assign_ndims(), and populate_array_report_expected_array().

Referenced by populate_array_json().

◆ populate_composite()

static Datum populate_composite ( CompositeIOData io,
Oid  typid,
const char *  colname,
MemoryContext  mcxt,
HeapTupleHeader  defaultval,
JsValue jsv,
bool  isnull 
)
static

Definition at line 2831 of file jsonfuncs.c.

2838 {
2839  Datum result;
2840 
2841  /* acquire/update cached tuple descriptor */
2842  update_cached_tupdesc(io, mcxt);
2843 
2844  if (isnull)
2845  result = (Datum) 0;
2846  else
2847  {
2848  HeapTupleHeader tuple;
2849  JsObject jso;
2850 
2851  /* prepare input value */
2852  JsValueToJsObject(jsv, &jso);
2853 
2854  /* populate resulting record tuple */
2855  tuple = populate_record(io->tupdesc, &io->record_io,
2856  defaultval, mcxt, &jso);
2857  result = HeapTupleHeaderGetDatum(tuple);
2858 
2859  JsObjectFree(&jso);
2860  }
2861 
2862  /*
2863  * If it's domain over composite, check domain constraints. (This should
2864  * probably get refactored so that we can see the TYPECAT value, but for
2865  * now, we can tell by comparing typid to base_typid.)
2866  */
2867  if (typid != io->base_typid && typid != RECORDOID)
2868  domain_check(result, isnull, typid, &io->domain_info, mcxt);
2869 
2870  return result;
2871 }
void domain_check(Datum value, bool isnull, Oid domainType, void **extra, MemoryContext mcxt)
Definition: domains.c:327
Datum HeapTupleHeaderGetDatum(HeapTupleHeader tuple)
Definition: execTuples.c:2224
static void update_cached_tupdesc(CompositeIOData *io, MemoryContext mcxt)
Definition: jsonfuncs.c:2807
#define JsObjectFree(jso)
Definition: jsonfuncs.c:330
static HeapTupleHeader populate_record(TupleDesc tupdesc, RecordIOData **record_p, HeapTupleHeader defaultval, MemoryContext mcxt, JsObject *obj)
Definition: jsonfuncs.c:3179
static void JsValueToJsObject(JsValue *jsv, JsObject *jso)
Definition: jsonfuncs.c:2764
RecordIOData * record_io
Definition: