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 "nodes/miscnodes.h"
#include "parser/parse_coerce.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 JsonParseErrorType okeys_object_field_start (void *state, char *fname, bool isnull)
 
static JsonParseErrorType okeys_array_start (void *state)
 
static JsonParseErrorType okeys_scalar (void *state, char *token, JsonTokenType tokentype)
 
static JsonParseErrorType get_object_start (void *state)
 
static JsonParseErrorType get_object_end (void *state)
 
static JsonParseErrorType get_object_field_start (void *state, char *fname, bool isnull)
 
static JsonParseErrorType get_object_field_end (void *state, char *fname, bool isnull)
 
static JsonParseErrorType get_array_start (void *state)
 
static JsonParseErrorType get_array_end (void *state)
 
static JsonParseErrorType get_array_element_start (void *state, bool isnull)
 
static JsonParseErrorType get_array_element_end (void *state, bool isnull)
 
static JsonParseErrorType 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 JsonParseErrorType alen_object_start (void *state)
 
static JsonParseErrorType alen_scalar (void *state, char *token, JsonTokenType tokentype)
 
static JsonParseErrorType 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 JsonParseErrorType each_object_field_start (void *state, char *fname, bool isnull)
 
static JsonParseErrorType each_object_field_end (void *state, char *fname, bool isnull)
 
static JsonParseErrorType each_array_start (void *state)
 
static JsonParseErrorType 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 JsonParseErrorType elements_object_start (void *state)
 
static JsonParseErrorType elements_array_element_start (void *state, bool isnull)
 
static JsonParseErrorType elements_array_element_end (void *state, bool isnull)
 
static JsonParseErrorType elements_scalar (void *state, char *token, JsonTokenType tokentype)
 
static HTABget_json_object_as_hash (const char *json, int len, const char *funcname, Node *escontext)
 
static JsonParseErrorType populate_array_object_start (void *_state)
 
static JsonParseErrorType populate_array_array_end (void *_state)
 
static JsonParseErrorType populate_array_element_start (void *_state, bool isnull)
 
static JsonParseErrorType populate_array_element_end (void *_state, bool isnull)
 
static JsonParseErrorType populate_array_scalar (void *_state, char *token, JsonTokenType tokentype)
 
static JsonParseErrorType hash_object_field_start (void *state, char *fname, bool isnull)
 
static JsonParseErrorType hash_object_field_end (void *state, char *fname, bool isnull)
 
static JsonParseErrorType hash_array_start (void *state)
 
static JsonParseErrorType hash_scalar (void *state, char *token, JsonTokenType tokentype)
 
static JsonParseErrorType populate_recordset_object_field_start (void *state, char *fname, bool isnull)
 
static JsonParseErrorType populate_recordset_object_field_end (void *state, char *fname, bool isnull)
 
static JsonParseErrorType populate_recordset_scalar (void *state, char *token, JsonTokenType tokentype)
 
static JsonParseErrorType populate_recordset_object_start (void *state)
 
static JsonParseErrorType populate_recordset_object_end (void *state)
 
static JsonParseErrorType populate_recordset_array_start (void *state)
 
static JsonParseErrorType populate_recordset_array_element_start (void *state, bool isnull)
 
static JsonParseErrorType sn_object_start (void *state)
 
static JsonParseErrorType sn_object_end (void *state)
 
static JsonParseErrorType sn_array_start (void *state)
 
static JsonParseErrorType sn_array_end (void *state)
 
static JsonParseErrorType sn_object_field_start (void *state, char *fname, bool isnull)
 
static JsonParseErrorType sn_array_element_start (void *state, bool isnull)
 
static JsonParseErrorType 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, Node *escontext)
 
static HeapTupleHeader populate_record (TupleDesc tupdesc, RecordIOData **record_p, HeapTupleHeader defaultval, MemoryContext mcxt, JsObject *obj, Node *escontext)
 
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 bool JsValueToJsObject (JsValue *jsv, JsObject *jso, Node *escontext)
 
static Datum populate_composite (CompositeIOData *io, Oid typid, const char *colname, MemoryContext mcxt, HeapTupleHeader defaultval, JsValue *jsv, bool *isnull, Node *escontext)
 
static Datum populate_scalar (ScalarIOData *io, Oid typid, int32 typmod, JsValue *jsv, bool *isnull, Node *escontext, bool omit_quotes)
 
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, Node *escontext, bool omit_scalar_quotes)
 
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 bool populate_array_json (PopulateArrayContext *ctx, const char *json, int len)
 
static bool populate_array_dim_jsonb (PopulateArrayContext *ctx, JsonbValue *jbv, int ndim)
 
static void populate_array_report_expected_array (PopulateArrayContext *ctx, int ndim)
 
static bool populate_array_assign_ndims (PopulateArrayContext *ctx, int ndims)
 
static bool populate_array_check_dimension (PopulateArrayContext *ctx, int ndim)
 
static bool populate_array_element (PopulateArrayContext *ctx, int ndim, JsValue *jsv)
 
static Datum populate_array (ArrayIOData *aio, const char *colname, MemoryContext mcxt, JsValue *jsv, bool *isnull, Node *escontext)
 
static Datum populate_domain (DomainIOData *io, Oid typid, const char *colname, MemoryContext mcxt, JsValue *jsv, bool *isnull, Node *escontext, bool omit_quotes)
 
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 JsonParseErrorType iterate_values_scalar (void *state, char *token, JsonTokenType tokentype)
 
static JsonParseErrorType iterate_values_object_field_start (void *state, char *fname, bool isnull)
 
static JsonParseErrorType transform_string_values_object_start (void *state)
 
static JsonParseErrorType transform_string_values_object_end (void *state)
 
static JsonParseErrorType transform_string_values_array_start (void *state)
 
static JsonParseErrorType transform_string_values_array_end (void *state)
 
static JsonParseErrorType transform_string_values_object_field_start (void *state, char *fname, bool isnull)
 
static JsonParseErrorType transform_string_values_array_element_start (void *state, bool isnull)
 
static JsonParseErrorType transform_string_values_scalar (void *state, char *token, JsonTokenType tokentype)
 
bool pg_parse_json_or_errsave (JsonLexContext *lex, JsonSemAction *sem, Node *escontext)
 
JsonLexContextmakeJsonLexContext (JsonLexContext *lex, text *json, bool need_escapes)
 
Datum jsonb_object_keys (PG_FUNCTION_ARGS)
 
void json_errsave_error (JsonParseErrorType error, JsonLexContext *lex, Node *escontext)
 
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_populate_record_valid (PG_FUNCTION_ARGS)
 
Datum jsonb_to_record (PG_FUNCTION_ARGS)
 
Datum json_populate_record (PG_FUNCTION_ARGS)
 
Datum json_to_record (PG_FUNCTION_ARGS)
 
static void update_cached_tupdesc (CompositeIOData *io, MemoryContext mcxt)
 
Datum json_populate_type (Datum json_val, Oid json_type, Oid typid, int32 typmod, void **cache, MemoryContext mcxt, bool *isnull, bool omit_quotes, Node *escontext)
 
Datum jsonb_populate_recordset (PG_FUNCTION_ARGS)
 
Datum jsonb_to_recordset (PG_FUNCTION_ARGS)
 
Datum json_populate_recordset (PG_FUNCTION_ARGS)
 
Datum json_to_recordset (PG_FUNCTION_ARGS)
 
Datum json_strip_nulls (PG_FUNCTION_ARGS)
 
Datum jsonb_strip_nulls (PG_FUNCTION_ARGS)
 
Datum jsonb_pretty (PG_FUNCTION_ARGS)
 
Datum jsonb_concat (PG_FUNCTION_ARGS)
 
Datum jsonb_delete (PG_FUNCTION_ARGS)
 
Datum jsonb_delete_array (PG_FUNCTION_ARGS)
 
Datum jsonb_delete_idx (PG_FUNCTION_ARGS)
 
Datum jsonb_set (PG_FUNCTION_ARGS)
 
Datum jsonb_set_lax (PG_FUNCTION_ARGS)
 
Datum jsonb_delete_path (PG_FUNCTION_ARGS)
 
Datum jsonb_insert (PG_FUNCTION_ARGS)
 
uint32 parse_jsonb_index_flags (Jsonb *jb)
 
void iterate_jsonb_values (Jsonb *jb, uint32 flags, void *state, JsonIterateStringValuesAction action)
 
void iterate_json_values (text *json, uint32 flags, void *action_state, JsonIterateStringValuesAction action)
 
Jsonbtransform_jsonb_string_values (Jsonb *jsonb, void *action_state, JsonTransformStringValuesAction transform_action)
 
texttransform_json_string_values (text *json, void *action_state, JsonTransformStringValuesAction transform_action)
 
JsonTokenType json_get_first_token (text *json, bool throw_error)
 
void json_categorize_type (Oid typoid, bool is_jsonb, JsonTypeCategory *tcategory, Oid *outfuncoid)
 

Macro Definition Documentation

◆ JB_PATH_CONSISTENT_POSITION

#define JB_PATH_CONSISTENT_POSITION   0x0040

Definition at line 51 of file jsonfuncs.c.

◆ JB_PATH_CREATE

#define JB_PATH_CREATE   0x0001

Definition at line 43 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 48 of file jsonfuncs.c.

◆ JB_PATH_DELETE

#define JB_PATH_DELETE   0x0002

Definition at line 44 of file jsonfuncs.c.

◆ JB_PATH_FILL_GAPS

#define JB_PATH_FILL_GAPS   0x0020

Definition at line 50 of file jsonfuncs.c.

◆ JB_PATH_INSERT_AFTER

#define JB_PATH_INSERT_AFTER   0x0010

Definition at line 47 of file jsonfuncs.c.

◆ JB_PATH_INSERT_BEFORE

#define JB_PATH_INSERT_BEFORE   0x0008

Definition at line 46 of file jsonfuncs.c.

◆ JB_PATH_REPLACE

#define JB_PATH_REPLACE   0x0004

Definition at line 45 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:670

Definition at line 333 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:1341

Definition at line 327 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 318 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 323 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 198 of file jsonfuncs.c.

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

Function Documentation

◆ alen_array_element_start()

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

Definition at line 1926 of file jsonfuncs.c.

1927 {
1928  AlenState *_state = (AlenState *) state;
1929 
1930  /* just count up all the level 1 elements */
1931  if (_state->lex->lex_level == 1)
1932  _state->count++;
1933 
1934  return JSON_SUCCESS;
1935 }
@ JSON_SUCCESS
Definition: jsonapi.h:38
int count
Definition: jsonfuncs.c:104
JsonLexContext * lex
Definition: jsonfuncs.c:103
int lex_level
Definition: jsonapi.h:99
Definition: regguts.h:323

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

Referenced by json_array_length().

◆ alen_object_start()

static JsonParseErrorType alen_object_start ( void *  state)
static

Definition at line 1898 of file jsonfuncs.c.

1899 {
1900  AlenState *_state = (AlenState *) state;
1901 
1902  /* json structure check */
1903  if (_state->lex->lex_level == 0)
1904  ereport(ERROR,
1905  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1906  errmsg("cannot get array length of a non-array")));
1907 
1908  return JSON_SUCCESS;
1909 }
int errcode(int sqlerrcode)
Definition: elog.c:853
int errmsg(const char *fmt,...)
Definition: elog.c:1070
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:149

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

Referenced by json_array_length().

◆ alen_scalar()

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

Definition at line 1912 of file jsonfuncs.c.

1913 {
1914  AlenState *_state = (AlenState *) state;
1915 
1916  /* json structure check */
1917  if (_state->lex->lex_level == 0)
1918  ereport(ERROR,
1919  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1920  errmsg("cannot get array length of a scalar")));
1921 
1922  return JSON_SUCCESS;
1923 }

References ereport, errcode(), errmsg(), ERROR, JSON_SUCCESS, 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 3474 of file jsonfuncs.c.

3475 {
3477  MemoryContextAlloc(mcxt,
3478  offsetof(RecordIOData, columns) +
3479  ncolumns * sizeof(ColumnIOData));
3480 
3481  data->record_type = InvalidOid;
3482  data->record_typmod = 0;
3483  data->ncolumns = ncolumns;
3484  MemSet(data->columns, 0, sizeof(ColumnIOData) * ncolumns);
3485 
3486  return data;
3487 }
#define MemSet(start, val, len)
Definition: c.h:1020
struct ColumnIOData ColumnIOData
Definition: jsonfuncs.c:161
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:1181
const void * data
#define InvalidOid
Definition: postgres_ext.h:36

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

Referenced by populate_record().

◆ each_array_start()

static JsonParseErrorType each_array_start ( void *  state)
static

Definition at line 2166 of file jsonfuncs.c.

2167 {
2168  EachState *_state = (EachState *) state;
2169 
2170  /* json structure check */
2171  if (_state->lex->lex_level == 0)
2172  ereport(ERROR,
2173  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2174  errmsg("cannot deconstruct an array as an object")));
2175 
2176  return JSON_SUCCESS;
2177 }
JsonLexContext * lex
Definition: jsonfuncs.c:110

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

Referenced by each_worker().

◆ each_object_field_end()

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

Definition at line 2118 of file jsonfuncs.c.

2119 {
2120  EachState *_state = (EachState *) state;
2121  MemoryContext old_cxt;
2122  int len;
2123  text *val;
2124  HeapTuple tuple;
2125  Datum values[2];
2126  bool nulls[2] = {false, false};
2127 
2128  /* skip over nested objects */
2129  if (_state->lex->lex_level != 1)
2130  return JSON_SUCCESS;
2131 
2132  /* use the tmp context so we can clean up after each tuple is done */
2133  old_cxt = MemoryContextSwitchTo(_state->tmp_cxt);
2134 
2135  values[0] = CStringGetTextDatum(fname);
2136 
2137  if (isnull && _state->normalize_results)
2138  {
2139  nulls[1] = true;
2140  values[1] = (Datum) 0;
2141  }
2142  else if (_state->next_scalar)
2143  {
2145  _state->next_scalar = false;
2146  }
2147  else
2148  {
2149  len = _state->lex->prev_token_terminator - _state->result_start;
2151  values[1] = PointerGetDatum(val);
2152  }
2153 
2154  tuple = heap_form_tuple(_state->ret_tdesc, values, nulls);
2155 
2156  tuplestore_puttuple(_state->tuple_store, tuple);
2157 
2158  /* clean up and switch back */
2159  MemoryContextSwitchTo(old_cxt);
2160  MemoryContextReset(_state->tmp_cxt);
2161 
2162  return JSON_SUCCESS;
2163 }
static Datum values[MAXATTR]
Definition: bootstrap.c:150
#define CStringGetTextDatum(s)
Definition: builtins.h:97
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, const Datum *values, const bool *isnull)
Definition: heaptuple.c:1116
void MemoryContextReset(MemoryContext context)
Definition: mcxt.c:383
const void size_t len
static Datum PointerGetDatum(const void *X)
Definition: postgres.h:322
uintptr_t Datum
Definition: postgres.h:64
MemoryContextSwitchTo(old_ctx)
bool normalize_results
Definition: jsonfuncs.c:115
TupleDesc ret_tdesc
Definition: jsonfuncs.c:112
char * normalized_scalar
Definition: jsonfuncs.c:117
const char * result_start
Definition: jsonfuncs.c:114
Tuplestorestate * tuple_store
Definition: jsonfuncs.c:111
MemoryContext tmp_cxt
Definition: jsonfuncs.c:113
bool next_scalar
Definition: jsonfuncs.c:116
const char * prev_token_terminator
Definition: jsonapi.h:96
Definition: c.h:687
void tuplestore_puttuple(Tuplestorestate *state, HeapTuple tuple)
Definition: tuplestore.c:762
text * cstring_to_text_with_len(const char *s, int len)
Definition: varlena.c:196

References cstring_to_text_with_len(), CStringGetTextDatum, heap_form_tuple(), JSON_SUCCESS, 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 JsonParseErrorType each_object_field_start ( void *  state,
char *  fname,
bool  isnull 
)
static

Definition at line 2096 of file jsonfuncs.c.

2097 {
2098  EachState *_state = (EachState *) state;
2099 
2100  /* save a pointer to where the value starts */
2101  if (_state->lex->lex_level == 1)
2102  {
2103  /*
2104  * next_scalar will be reset in the object_field_end handler, and
2105  * since we know the value is a scalar there is no danger of it being
2106  * on while recursing down the tree.
2107  */
2108  if (_state->normalize_results && _state->lex->token_type == JSON_TOKEN_STRING)
2109  _state->next_scalar = true;
2110  else
2111  _state->result_start = _state->lex->token_start;
2112  }
2113 
2114  return JSON_SUCCESS;
2115 }
const char * token_start
Definition: jsonapi.h:94
JsonTokenType token_type
Definition: jsonapi.h:98

References JSON_SUCCESS, 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 JsonParseErrorType each_scalar ( void *  state,
char *  token,
JsonTokenType  tokentype 
)
static

Definition at line 2180 of file jsonfuncs.c.

2181 {
2182  EachState *_state = (EachState *) state;
2183 
2184  /* json structure check */
2185  if (_state->lex->lex_level == 0)
2186  ereport(ERROR,
2187  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2188  errmsg("cannot deconstruct a scalar")));
2189 
2190  /* supply de-escaped value if required */
2191  if (_state->next_scalar)
2192  _state->normalized_scalar = token;
2193 
2194  return JSON_SUCCESS;
2195 }
#define token
Definition: indent_globs.h:126

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

Referenced by each_worker().

◆ each_worker()

static Datum each_worker ( FunctionCallInfo  fcinfo,
bool  as_text 
)
static

Definition at line 2056 of file jsonfuncs.c.

2057 {
2058  text *json = PG_GETARG_TEXT_PP(0);
2059  JsonLexContext lex;
2060  JsonSemAction *sem;
2061  ReturnSetInfo *rsi;
2062  EachState *state;
2063 
2064  state = palloc0(sizeof(EachState));
2065  sem = palloc0(sizeof(JsonSemAction));
2066 
2067  rsi = (ReturnSetInfo *) fcinfo->resultinfo;
2068 
2070  state->tuple_store = rsi->setResult;
2071  state->ret_tdesc = rsi->setDesc;
2072 
2073  sem->semstate = (void *) state;
2075  sem->scalar = each_scalar;
2078 
2079  state->normalize_results = as_text;
2080  state->next_scalar = false;
2081  state->lex = makeJsonLexContext(&lex, json, true);
2083  "json_each temporary cxt",
2085 
2087 
2088  MemoryContextDelete(state->tmp_cxt);
2089  freeJsonLexContext(&lex);
2090 
2091  PG_RETURN_NULL();
2092 }
#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:297
void freeJsonLexContext(JsonLexContext *lex)
Definition: jsonapi.c:482
JsonLexContext * makeJsonLexContext(JsonLexContext *lex, text *json, bool need_escapes)
Definition: jsonfuncs.c:538
static JsonParseErrorType each_object_field_end(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:2118
static JsonParseErrorType each_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:2180
static JsonParseErrorType each_object_field_start(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:2096
static JsonParseErrorType each_array_start(void *state)
Definition: jsonfuncs.c:2166
#define pg_parse_json_or_ereport(lex, sem)
Definition: jsonfuncs.h:47
void * palloc0(Size size)
Definition: mcxt.c:1347
MemoryContext CurrentMemoryContext
Definition: mcxt.c:143
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:454
#define AllocSetContextCreate
Definition: memutils.h:129
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:160
fmNodePtr resultinfo
Definition: fmgr.h:89
json_ofield_action object_field_start
Definition: jsonapi.h:139
json_scalar_action scalar
Definition: jsonapi.h:143
void * semstate
Definition: jsonapi.h:134
json_struct_action array_start
Definition: jsonapi.h:137
json_ofield_action object_field_end
Definition: jsonapi.h:140
TupleDesc setDesc
Definition: execnodes.h:340
Tuplestorestate * setResult
Definition: execnodes.h:339
static JsonSemAction sem

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, JsonSemAction::array_start, CurrentMemoryContext, each_array_start(), each_object_field_end(), each_object_field_start(), each_scalar(), freeJsonLexContext(), 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, sem, 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 1972 of file jsonfuncs.c.

1973 {
1974  Jsonb *jb = PG_GETARG_JSONB_P(0);
1975  ReturnSetInfo *rsi;
1976  MemoryContext old_cxt,
1977  tmp_cxt;
1978  bool skipNested = false;
1979  JsonbIterator *it;
1980  JsonbValue v;
1982 
1983  if (!JB_ROOT_IS_OBJECT(jb))
1984  ereport(ERROR,
1985  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1986  errmsg("cannot call %s on a non-object",
1987  funcname)));
1988 
1989  rsi = (ReturnSetInfo *) fcinfo->resultinfo;
1991 
1993  "jsonb_each temporary cxt",
1995 
1996  it = JsonbIteratorInit(&jb->root);
1997 
1998  while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE)
1999  {
2000  skipNested = true;
2001 
2002  if (r == WJB_KEY)
2003  {
2004  text *key;
2005  Datum values[2];
2006  bool nulls[2] = {false, false};
2007 
2008  /* Use the tmp context so we can clean up after each tuple is done */
2009  old_cxt = MemoryContextSwitchTo(tmp_cxt);
2010 
2011  key = cstring_to_text_with_len(v.val.string.val, v.val.string.len);
2012 
2013  /*
2014  * The next thing the iterator fetches should be the value, no
2015  * matter what shape it is.
2016  */
2017  r = JsonbIteratorNext(&it, &v, skipNested);
2018  Assert(r != WJB_DONE);
2019 
2020  values[0] = PointerGetDatum(key);
2021 
2022  if (as_text)
2023  {
2024  if (v.type == jbvNull)
2025  {
2026  /* a json null is an sql null in text mode */
2027  nulls[1] = true;
2028  values[1] = (Datum) NULL;
2029  }
2030  else
2032  }
2033  else
2034  {
2035  /* Not in text mode, just return the Jsonb */
2036  Jsonb *val = JsonbValueToJsonb(&v);
2037 
2038  values[1] = PointerGetDatum(val);
2039  }
2040 
2041  tuplestore_putvalues(rsi->setResult, rsi->setDesc, values, nulls);
2042 
2043  /* clean up and switch back */
2044  MemoryContextSwitchTo(old_cxt);
2045  MemoryContextReset(tmp_cxt);
2046  }
2047  }
2048 
2049  MemoryContextDelete(tmp_cxt);
2050 
2051  PG_RETURN_NULL();
2052 }
#define Assert(condition)
Definition: c.h:858
#define funcname
Definition: indent_codes.h:69
#define JB_ROOT_IS_OBJECT(jbp_)
Definition: jsonb.h:221
#define PG_GETARG_JSONB_P(x)
Definition: jsonb.h:391
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:817
Jsonb * JsonbValueToJsonb(JsonbValue *val)
Definition: jsonb_util.c:92
JsonbIteratorToken JsonbIteratorNext(JsonbIterator **it, JsonbValue *val, bool skipNested)
Definition: jsonb_util.c:853
static text * JsonbValueAsText(JsonbValue *v)
Definition: jsonfuncs.c:1803
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, const Datum *values, const bool *isnull)
Definition: tuplestore.c:782

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, Assert, cstring_to_text_with_len(), CurrentMemoryContext, ereport, errcode(), errmsg(), ERROR, funcname, 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 JsonParseErrorType elements_array_element_end ( void *  state,
bool  isnull 
)
static

Definition at line 2370 of file jsonfuncs.c.

2371 {
2372  ElementsState *_state = (ElementsState *) state;
2373  MemoryContext old_cxt;
2374  int len;
2375  text *val;
2376  HeapTuple tuple;
2377  Datum values[1];
2378  bool nulls[1] = {false};
2379 
2380  /* skip over nested objects */
2381  if (_state->lex->lex_level != 1)
2382  return JSON_SUCCESS;
2383 
2384  /* use the tmp context so we can clean up after each tuple is done */
2385  old_cxt = MemoryContextSwitchTo(_state->tmp_cxt);
2386 
2387  if (isnull && _state->normalize_results)
2388  {
2389  nulls[0] = true;
2390  values[0] = (Datum) NULL;
2391  }
2392  else if (_state->next_scalar)
2393  {
2395  _state->next_scalar = false;
2396  }
2397  else
2398  {
2399  len = _state->lex->prev_token_terminator - _state->result_start;
2401  values[0] = PointerGetDatum(val);
2402  }
2403 
2404  tuple = heap_form_tuple(_state->ret_tdesc, values, nulls);
2405 
2406  tuplestore_puttuple(_state->tuple_store, tuple);
2407 
2408  /* clean up and switch back */
2409  MemoryContextSwitchTo(old_cxt);
2410  MemoryContextReset(_state->tmp_cxt);
2411 
2412  return JSON_SUCCESS;
2413 }
bool next_scalar
Definition: jsonfuncs.c:130
TupleDesc ret_tdesc
Definition: jsonfuncs.c:126
Tuplestorestate * tuple_store
Definition: jsonfuncs.c:125
bool normalize_results
Definition: jsonfuncs.c:129
MemoryContext tmp_cxt
Definition: jsonfuncs.c:127
JsonLexContext * lex
Definition: jsonfuncs.c:123
const char * result_start
Definition: jsonfuncs.c:128
char * normalized_scalar
Definition: jsonfuncs.c:131

References cstring_to_text_with_len(), CStringGetTextDatum, heap_form_tuple(), JSON_SUCCESS, 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 JsonParseErrorType elements_array_element_start ( void *  state,
bool  isnull 
)
static

Definition at line 2348 of file jsonfuncs.c.

2349 {
2350  ElementsState *_state = (ElementsState *) state;
2351 
2352  /* save a pointer to where the value starts */
2353  if (_state->lex->lex_level == 1)
2354  {
2355  /*
2356  * next_scalar will be reset in the array_element_end handler, and
2357  * since we know the value is a scalar there is no danger of it being
2358  * on while recursing down the tree.
2359  */
2360  if (_state->normalize_results && _state->lex->token_type == JSON_TOKEN_STRING)
2361  _state->next_scalar = true;
2362  else
2363  _state->result_start = _state->lex->token_start;
2364  }
2365 
2366  return JSON_SUCCESS;
2367 }

References JSON_SUCCESS, 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 JsonParseErrorType elements_object_start ( void *  state)
static

Definition at line 2416 of file jsonfuncs.c.

2417 {
2418  ElementsState *_state = (ElementsState *) state;
2419 
2420  /* json structure check */
2421  if (_state->lex->lex_level == 0)
2422  ereport(ERROR,
2423  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2424  errmsg("cannot call %s on a non-array",
2425  _state->function_name)));
2426 
2427  return JSON_SUCCESS;
2428 }
const char * function_name
Definition: jsonfuncs.c:124

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

Referenced by elements_worker().

◆ elements_scalar()

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

Definition at line 2431 of file jsonfuncs.c.

2432 {
2433  ElementsState *_state = (ElementsState *) state;
2434 
2435  /* json structure check */
2436  if (_state->lex->lex_level == 0)
2437  ereport(ERROR,
2438  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2439  errmsg("cannot call %s on a scalar",
2440  _state->function_name)));
2441 
2442  /* supply de-escaped value if required */
2443  if (_state->next_scalar)
2444  _state->normalized_scalar = token;
2445 
2446  return JSON_SUCCESS;
2447 }

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

Referenced by elements_worker().

◆ elements_worker()

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

Definition at line 2306 of file jsonfuncs.c.

2307 {
2308  text *json = PG_GETARG_TEXT_PP(0);
2309  JsonLexContext lex;
2310  JsonSemAction *sem;
2311  ReturnSetInfo *rsi;
2313 
2314  /* elements only needs escaped strings when as_text */
2315  makeJsonLexContext(&lex, json, as_text);
2316 
2317  state = palloc0(sizeof(ElementsState));
2318  sem = palloc0(sizeof(JsonSemAction));
2319 
2321  rsi = (ReturnSetInfo *) fcinfo->resultinfo;
2322  state->tuple_store = rsi->setResult;
2323  state->ret_tdesc = rsi->setDesc;
2324 
2325  sem->semstate = (void *) state;
2330 
2331  state->function_name = funcname;
2332  state->normalize_results = as_text;
2333  state->next_scalar = false;
2334  state->lex = &lex;
2336  "json_array_elements temporary cxt",
2338 
2340 
2341  MemoryContextDelete(state->tmp_cxt);
2342  freeJsonLexContext(&lex);
2343 
2344  PG_RETURN_NULL();
2345 }
#define MAT_SRF_USE_EXPECTED_DESC
Definition: funcapi.h:296
static JsonParseErrorType elements_object_start(void *state)
Definition: jsonfuncs.c:2416
static JsonParseErrorType elements_array_element_end(void *state, bool isnull)
Definition: jsonfuncs.c:2370
static JsonParseErrorType elements_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:2431
static JsonParseErrorType elements_array_element_start(void *state, bool isnull)
Definition: jsonfuncs.c:2348
json_struct_action object_start
Definition: jsonapi.h:135
json_aelem_action array_element_start
Definition: jsonapi.h:141
json_aelem_action array_element_end
Definition: jsonapi.h:142

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(), freeJsonLexContext(), funcname, 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, sem, 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 2218 of file jsonfuncs.c.

2220 {
2221  Jsonb *jb = PG_GETARG_JSONB_P(0);
2222  ReturnSetInfo *rsi;
2223  MemoryContext old_cxt,
2224  tmp_cxt;
2225  bool skipNested = false;
2226  JsonbIterator *it;
2227  JsonbValue v;
2229 
2230  if (JB_ROOT_IS_SCALAR(jb))
2231  ereport(ERROR,
2232  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2233  errmsg("cannot extract elements from a scalar")));
2234  else if (!JB_ROOT_IS_ARRAY(jb))
2235  ereport(ERROR,
2236  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2237  errmsg("cannot extract elements from an object")));
2238 
2239  rsi = (ReturnSetInfo *) fcinfo->resultinfo;
2240 
2242 
2244  "jsonb_array_elements temporary cxt",
2246 
2247  it = JsonbIteratorInit(&jb->root);
2248 
2249  while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE)
2250  {
2251  skipNested = true;
2252 
2253  if (r == WJB_ELEM)
2254  {
2255  Datum values[1];
2256  bool nulls[1] = {false};
2257 
2258  /* use the tmp context so we can clean up after each tuple is done */
2259  old_cxt = MemoryContextSwitchTo(tmp_cxt);
2260 
2261  if (as_text)
2262  {
2263  if (v.type == jbvNull)
2264  {
2265  /* a json null is an sql null in text mode */
2266  nulls[0] = true;
2267  values[0] = (Datum) NULL;
2268  }
2269  else
2271  }
2272  else
2273  {
2274  /* Not in text mode, just return the Jsonb */
2275  Jsonb *val = JsonbValueToJsonb(&v);
2276 
2277  values[0] = PointerGetDatum(val);
2278  }
2279 
2280  tuplestore_putvalues(rsi->setResult, rsi->setDesc, values, nulls);
2281 
2282  /* clean up and switch back */
2283  MemoryContextSwitchTo(old_cxt);
2284  MemoryContextReset(tmp_cxt);
2285  }
2286  }
2287 
2288  MemoryContextDelete(tmp_cxt);
2289 
2290  PG_RETURN_NULL();
2291 }
#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 JsonParseErrorType get_array_element_end ( void *  state,
bool  isnull 
)
static

Definition at line 1399 of file jsonfuncs.c.

1400 {
1401  GetState *_state = (GetState *) state;
1402  bool get_last = false;
1403  int lex_level = _state->lex->lex_level;
1404 
1405  /* same tests as in get_array_element_start */
1406  if (lex_level <= _state->npath &&
1407  _state->pathok[lex_level - 1] &&
1408  _state->path_indexes != NULL &&
1409  _state->array_cur_index[lex_level - 1] == _state->path_indexes[lex_level - 1])
1410  {
1411  if (lex_level < _state->npath)
1412  {
1413  /* done with this element so reset pathok */
1414  _state->pathok[lex_level] = false;
1415  }
1416  else
1417  {
1418  /* end of path, so we want this value */
1419  get_last = true;
1420  }
1421  }
1422 
1423  /* same logic as for objects */
1424  if (get_last && _state->result_start != NULL)
1425  {
1426  if (isnull && _state->normalize_results)
1427  _state->tresult = (text *) NULL;
1428  else
1429  {
1430  const char *start = _state->result_start;
1431  int len = _state->lex->prev_token_terminator - start;
1432 
1434  }
1435 
1436  _state->result_start = NULL;
1437  }
1438 
1439  return JSON_SUCCESS;
1440 }
return str start
int * path_indexes
Definition: jsonfuncs.c:94
bool * pathok
Definition: jsonfuncs.c:95
const char * result_start
Definition: jsonfuncs.c:89
int * array_cur_index
Definition: jsonfuncs.c:96
text * tresult
Definition: jsonfuncs.c:88
JsonLexContext * lex
Definition: jsonfuncs.c:87
bool normalize_results
Definition: jsonfuncs.c:90

References GetState::array_cur_index, cstring_to_text_with_len(), JSON_SUCCESS, len, GetState::lex, JsonLexContext::lex_level, GetState::normalize_results, GetState::path_indexes, GetState::pathok, JsonLexContext::prev_token_terminator, GetState::result_start, start, and GetState::tresult.

Referenced by get_worker().

◆ get_array_element_start()

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

Definition at line 1351 of file jsonfuncs.c.

1352 {
1353  GetState *_state = (GetState *) state;
1354  bool get_next = false;
1355  int lex_level = _state->lex->lex_level;
1356 
1357  /* Update array element counter */
1358  if (lex_level <= _state->npath)
1359  _state->array_cur_index[lex_level - 1]++;
1360 
1361  if (lex_level <= _state->npath &&
1362  _state->pathok[lex_level - 1] &&
1363  _state->path_indexes != NULL &&
1364  _state->array_cur_index[lex_level - 1] == _state->path_indexes[lex_level - 1])
1365  {
1366  if (lex_level < _state->npath)
1367  {
1368  /* if not at end of path just mark path ok */
1369  _state->pathok[lex_level] = true;
1370  }
1371  else
1372  {
1373  /* end of path, so we want this value */
1374  get_next = true;
1375  }
1376  }
1377 
1378  /* same logic as for objects */
1379  if (get_next)
1380  {
1381  _state->tresult = NULL;
1382  _state->result_start = NULL;
1383 
1384  if (_state->normalize_results &&
1385  _state->lex->token_type == JSON_TOKEN_STRING)
1386  {
1387  _state->next_scalar = true;
1388  }
1389  else
1390  {
1391  _state->result_start = _state->lex->token_start;
1392  }
1393  }
1394 
1395  return JSON_SUCCESS;
1396 }
bool next_scalar
Definition: jsonfuncs.c:91

References GetState::array_cur_index, JSON_SUCCESS, 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 JsonParseErrorType get_array_end ( void *  state)
static

Definition at line 1333 of file jsonfuncs.c.

1334 {
1335  GetState *_state = (GetState *) state;
1336  int lex_level = _state->lex->lex_level;
1337 
1338  if (lex_level == 0 && _state->npath == 0)
1339  {
1340  /* Special case: return the entire array */
1341  const char *start = _state->result_start;
1342  int len = _state->lex->prev_token_terminator - start;
1343 
1345  }
1346 
1347  return JSON_SUCCESS;
1348 }
int npath
Definition: jsonfuncs.c:92

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

Referenced by get_worker().

◆ get_array_start()

static JsonParseErrorType get_array_start ( void *  state)
static

Definition at line 1293 of file jsonfuncs.c.

1294 {
1295  GetState *_state = (GetState *) state;
1296  int lex_level = _state->lex->lex_level;
1297 
1298  if (lex_level < _state->npath)
1299  {
1300  /* Initialize counting of elements in this array */
1301  _state->array_cur_index[lex_level] = -1;
1302 
1303  /* INT_MIN value is reserved to represent invalid subscript */
1304  if (_state->path_indexes[lex_level] < 0 &&
1305  _state->path_indexes[lex_level] != INT_MIN)
1306  {
1307  /* Negative subscript -- convert to positive-wise subscript */
1309  int nelements;
1310 
1311  error = json_count_array_elements(_state->lex, &nelements);
1312  if (error != JSON_SUCCESS)
1313  json_errsave_error(error, _state->lex, NULL);
1314 
1315  if (-_state->path_indexes[lex_level] <= nelements)
1316  _state->path_indexes[lex_level] += nelements;
1317  }
1318  }
1319  else if (lex_level == 0 && _state->npath == 0)
1320  {
1321  /*
1322  * Special case: we should match the entire array. We only need this
1323  * at the outermost level because at nested levels the match will have
1324  * been started by the outer field or array element callback.
1325  */
1326  _state->result_start = _state->lex->token_start;
1327  }
1328 
1329  return JSON_SUCCESS;
1330 }
JsonParseErrorType json_count_array_elements(JsonLexContext *lex, int *elements)
Definition: jsonapi.c:587
JsonParseErrorType
Definition: jsonapi.h:37
void json_errsave_error(JsonParseErrorType error, JsonLexContext *lex, Node *escontext)
Definition: jsonfuncs.c:639
static void error(void)
Definition: sql-dyntest.c:147

References GetState::array_cur_index, error(), json_count_array_elements(), json_errsave_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 ( const char *  json,
int  len,
const char *  funcname,
Node escontext 
)
static

Definition at line 3809 of file jsonfuncs.c.

3811 {
3812  HASHCTL ctl;
3813  HTAB *tab;
3814  JHashState *state;
3815  JsonSemAction *sem;
3816 
3817  ctl.keysize = NAMEDATALEN;
3818  ctl.entrysize = sizeof(JsonHashEntry);
3819  ctl.hcxt = CurrentMemoryContext;
3820  tab = hash_create("json object hashtable",
3821  100,
3822  &ctl,
3824 
3825  state = palloc0(sizeof(JHashState));
3826  sem = palloc0(sizeof(JsonSemAction));
3827 
3828  state->function_name = funcname;
3829  state->hash = tab;
3830  state->lex = makeJsonLexContextCstringLen(NULL, json, len,
3831  GetDatabaseEncoding(), true);
3832 
3833  sem->semstate = (void *) state;
3835  sem->scalar = hash_scalar;
3838 
3839  if (!pg_parse_json_or_errsave(state->lex, sem, escontext))
3840  {
3841  hash_destroy(state->hash);
3842  tab = NULL;
3843  }
3844 
3845  freeJsonLexContext(state->lex);
3846 
3847  return tab;
3848 }
void hash_destroy(HTAB *hashp)
Definition: dynahash.c:865
HTAB * hash_create(const char *tabname, long nelem, const HASHCTL *info, int flags)
Definition: dynahash.c:352
#define HASH_STRINGS
Definition: hsearch.h:96
#define HASH_CONTEXT
Definition: hsearch.h:102
#define HASH_ELEM
Definition: hsearch.h:95
JsonLexContext * makeJsonLexContextCstringLen(JsonLexContext *lex, const char *json, size_t len, int encoding, bool need_escapes)
Definition: jsonapi.c:326
static JsonParseErrorType hash_array_start(void *state)
Definition: jsonfuncs.c:3928
static JsonParseErrorType hash_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:3941
struct JsonHashEntry JsonHashEntry
bool pg_parse_json_or_errsave(JsonLexContext *lex, JsonSemAction *sem, Node *escontext)
Definition: jsonfuncs.c:517
static JsonParseErrorType hash_object_field_end(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:3877
static JsonParseErrorType hash_object_field_start(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:3851
int GetDatabaseEncoding(void)
Definition: mbutils.c:1261
#define NAMEDATALEN
tree ctl
Definition: radixtree.h:1853
Definition: dynahash.c:220

References JsonSemAction::array_start, ctl, CurrentMemoryContext, freeJsonLexContext(), funcname, GetDatabaseEncoding(), hash_array_start(), HASH_CONTEXT, hash_create(), hash_destroy(), HASH_ELEM, hash_object_field_end(), hash_object_field_start(), hash_scalar(), HASH_STRINGS, len, makeJsonLexContextCstringLen(), NAMEDATALEN, JsonSemAction::object_field_end, JsonSemAction::object_field_start, palloc0(), pg_parse_json_or_errsave(), JsonSemAction::scalar, sem, 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 1498 of file jsonfuncs.c.

1499 {
1500  Jsonb *jb = PG_GETARG_JSONB_P(0);
1501  ArrayType *path = PG_GETARG_ARRAYTYPE_P(1);
1502  Datum *pathtext;
1503  bool *pathnulls;
1504  bool isnull;
1505  int npath;
1506  Datum res;
1507 
1508  /*
1509  * If the array contains any null elements, return NULL, on the grounds
1510  * that you'd have gotten NULL if any RHS value were NULL in a nested
1511  * series of applications of the -> operator. (Note: because we also
1512  * return NULL for error cases such as no-such-field, this is true
1513  * regardless of the contents of the rest of the array.)
1514  */
1515  if (array_contains_nulls(path))
1516  PG_RETURN_NULL();
1517 
1518  deconstruct_array_builtin(path, TEXTOID, &pathtext, &pathnulls, &npath);
1519 
1520  res = jsonb_get_element(jb, pathtext, npath, &isnull, as_text);
1521 
1522  if (isnull)
1523  PG_RETURN_NULL();
1524  else
1526 }
#define PG_GETARG_ARRAYTYPE_P(n)
Definition: array.h:263
bool array_contains_nulls(ArrayType *array)
Definition: arrayfuncs.c:3755
void deconstruct_array_builtin(ArrayType *array, Oid elmtype, Datum **elemsp, bool **nullsp, int *nelemsp)
Definition: arrayfuncs.c:3685
#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:1529

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 JsonParseErrorType get_object_end ( void *  state)
static

Definition at line 1177 of file jsonfuncs.c.

1178 {
1179  GetState *_state = (GetState *) state;
1180  int lex_level = _state->lex->lex_level;
1181 
1182  if (lex_level == 0 && _state->npath == 0)
1183  {
1184  /* Special case: return the entire object */
1185  const char *start = _state->result_start;
1186  int len = _state->lex->prev_token_terminator - start;
1187 
1189  }
1190 
1191  return JSON_SUCCESS;
1192 }

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

Referenced by get_worker().

◆ get_object_field_end()

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

Definition at line 1242 of file jsonfuncs.c.

1243 {
1244  GetState *_state = (GetState *) state;
1245  bool get_last = false;
1246  int lex_level = _state->lex->lex_level;
1247 
1248  /* same tests as in get_object_field_start */
1249  if (lex_level <= _state->npath &&
1250  _state->pathok[lex_level - 1] &&
1251  _state->path_names != NULL &&
1252  _state->path_names[lex_level - 1] != NULL &&
1253  strcmp(fname, _state->path_names[lex_level - 1]) == 0)
1254  {
1255  if (lex_level < _state->npath)
1256  {
1257  /* done with this field so reset pathok */
1258  _state->pathok[lex_level] = false;
1259  }
1260  else
1261  {
1262  /* end of path, so we want this value */
1263  get_last = true;
1264  }
1265  }
1266 
1267  /* for as_text scalar case, our work is already done */
1268  if (get_last && _state->result_start != NULL)
1269  {
1270  /*
1271  * make a text object from the string from the previously noted json
1272  * start up to the end of the previous token (the lexer is by now
1273  * ahead of us on whatever came after what we're interested in).
1274  */
1275  if (isnull && _state->normalize_results)
1276  _state->tresult = (text *) NULL;
1277  else
1278  {
1279  const char *start = _state->result_start;
1280  int len = _state->lex->prev_token_terminator - start;
1281 
1283  }
1284 
1285  /* this should be unnecessary but let's do it for cleanliness: */
1286  _state->result_start = NULL;
1287  }
1288 
1289  return JSON_SUCCESS;
1290 }
char ** path_names
Definition: jsonfuncs.c:93

References cstring_to_text_with_len(), JSON_SUCCESS, len, GetState::lex, JsonLexContext::lex_level, GetState::normalize_results, GetState::path_names, GetState::pathok, JsonLexContext::prev_token_terminator, GetState::result_start, start, and GetState::tresult.

Referenced by get_worker().

◆ get_object_field_start()

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

Definition at line 1195 of file jsonfuncs.c.

1196 {
1197  GetState *_state = (GetState *) state;
1198  bool get_next = false;
1199  int lex_level = _state->lex->lex_level;
1200 
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  /* if not at end of path just mark path ok */
1210  _state->pathok[lex_level] = true;
1211  }
1212  else
1213  {
1214  /* end of path, so we want this value */
1215  get_next = true;
1216  }
1217  }
1218 
1219  if (get_next)
1220  {
1221  /* this object overrides any previous matching object */
1222  _state->tresult = NULL;
1223  _state->result_start = NULL;
1224 
1225  if (_state->normalize_results &&
1226  _state->lex->token_type == JSON_TOKEN_STRING)
1227  {
1228  /* for as_text variants, tell get_scalar to set it for us */
1229  _state->next_scalar = true;
1230  }
1231  else
1232  {
1233  /* for non-as_text variants, just note the json starting point */
1234  _state->result_start = _state->lex->token_start;
1235  }
1236  }
1237 
1238  return JSON_SUCCESS;
1239 }

References JSON_SUCCESS, 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 JsonParseErrorType get_object_start ( void *  state)
static

Definition at line 1158 of file jsonfuncs.c.

1159 {
1160  GetState *_state = (GetState *) state;
1161  int lex_level = _state->lex->lex_level;
1162 
1163  if (lex_level == 0 && _state->npath == 0)
1164  {
1165  /*
1166  * Special case: we should match the entire object. We only need this
1167  * at outermost level because at nested levels the match will have
1168  * been started by the outer field or array element callback.
1169  */
1170  _state->result_start = _state->lex->token_start;
1171  }
1172 
1173  return JSON_SUCCESS;
1174 }

References JSON_SUCCESS, 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 1022 of file jsonfuncs.c.

1023 {
1024  text *json = PG_GETARG_TEXT_PP(0);
1025  ArrayType *path = PG_GETARG_ARRAYTYPE_P(1);
1026  text *result;
1027  Datum *pathtext;
1028  bool *pathnulls;
1029  int npath;
1030  char **tpath;
1031  int *ipath;
1032  int i;
1033 
1034  /*
1035  * If the array contains any null elements, return NULL, on the grounds
1036  * that you'd have gotten NULL if any RHS value were NULL in a nested
1037  * series of applications of the -> operator. (Note: because we also
1038  * return NULL for error cases such as no-such-field, this is true
1039  * regardless of the contents of the rest of the array.)
1040  */
1041  if (array_contains_nulls(path))
1042  PG_RETURN_NULL();
1043 
1044  deconstruct_array_builtin(path, TEXTOID, &pathtext, &pathnulls, &npath);
1045 
1046  tpath = palloc(npath * sizeof(char *));
1047  ipath = palloc(npath * sizeof(int));
1048 
1049  for (i = 0; i < npath; i++)
1050  {
1051  Assert(!pathnulls[i]);
1052  tpath[i] = TextDatumGetCString(pathtext[i]);
1053 
1054  /*
1055  * we have no idea at this stage what structure the document is so
1056  * just convert anything in the path that we can to an integer and set
1057  * all the other integers to INT_MIN which will never match.
1058  */
1059  if (*tpath[i] != '\0')
1060  {
1061  int ind;
1062  char *endptr;
1063 
1064  errno = 0;
1065  ind = strtoint(tpath[i], &endptr, 10);
1066  if (endptr == tpath[i] || *endptr != '\0' || errno != 0)
1067  ipath[i] = INT_MIN;
1068  else
1069  ipath[i] = ind;
1070  }
1071  else
1072  ipath[i] = INT_MIN;
1073  }
1074 
1075  result = get_worker(json, tpath, ipath, npath, as_text);
1076 
1077  if (result != NULL)
1078  PG_RETURN_TEXT_P(result);
1079  else
1080  PG_RETURN_NULL();
1081 }
#define TextDatumGetCString(d)
Definition: builtins.h:98
#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:1101
void * palloc(Size size)
Definition: mcxt.c:1317
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 3634 of file jsonfuncs.c.

3637 {
3638  cache->argtype = get_fn_expr_argtype(fcinfo->flinfo, 0);
3639  prepare_column_cache(&cache->c,
3640  cache->argtype, -1,
3641  cache->fn_mcxt, false);
3642  if (cache->c.typcat != TYPECAT_COMPOSITE &&
3643  cache->c.typcat != TYPECAT_COMPOSITE_DOMAIN)
3644  ereport(ERROR,
3645  (errcode(ERRCODE_DATATYPE_MISMATCH),
3646  /* translator: %s is a function name, eg json_to_record */
3647  errmsg("first argument of %s must be a row type",
3648  funcname)));
3649 }
Oid get_fn_expr_argtype(FmgrInfo *flinfo, int argnum)
Definition: fmgr.c:1910
static void prepare_column_cache(ColumnIOData *column, Oid typid, int32 typmod, MemoryContext mcxt, bool need_scalar)
Definition: jsonfuncs.c:3249
TypeCat typcat
Definition: jsonfuncs.c:214
FmgrInfo * flinfo
Definition: fmgr.h:87
ColumnIOData c
Definition: jsonfuncs.c:239
MemoryContext fn_mcxt
Definition: jsonfuncs.c:240

References PopulateRecordCache::argtype, PopulateRecordCache::c, ereport, errcode(), errmsg(), ERROR, FunctionCallInfoBaseData::flinfo, PopulateRecordCache::fn_mcxt, funcname, 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 3660 of file jsonfuncs.c.

3663 {
3664  TupleDesc tupdesc;
3665  MemoryContext old_cxt;
3666 
3667  if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
3668  ereport(ERROR,
3669  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3670  /* translator: %s is a function name, eg json_to_record */
3671  errmsg("could not determine row type for result of %s",
3672  funcname),
3673  errhint("Provide a non-null record argument, "
3674  "or call the function in the FROM clause "
3675  "using a column definition list.")));
3676 
3677  Assert(tupdesc);
3678  cache->argtype = tupdesc->tdtypeid;
3679 
3680  /* If we go through this more than once, avoid memory leak */
3681  if (cache->c.io.composite.tupdesc)
3683 
3684  /* Save identified tupdesc */
3685  old_cxt = MemoryContextSwitchTo(cache->fn_mcxt);
3686  cache->c.io.composite.tupdesc = CreateTupleDescCopy(tupdesc);
3687  cache->c.io.composite.base_typid = tupdesc->tdtypeid;
3688  cache->c.io.composite.base_typmod = tupdesc->tdtypmod;
3689  MemoryContextSwitchTo(old_cxt);
3690 }
int errhint(const char *fmt,...)
Definition: elog.c:1317
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:220
union ColumnIOData::@26 io
int32 base_typmod
Definition: jsonfuncs.c:183
TupleDesc tupdesc
Definition: jsonfuncs.c:180
int32 tdtypmod
Definition: tupdesc.h:83
Oid tdtypeid
Definition: tupdesc.h:82
void FreeTupleDesc(TupleDesc tupdesc)
Definition: tupdesc.c:331
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
Definition: tupdesc.c:133

References PopulateRecordCache::argtype, Assert, CompositeIOData::base_typid, CompositeIOData::base_typmod, PopulateRecordCache::c, ColumnIOData::composite, CreateTupleDescCopy(), ereport, errcode(), errhint(), errmsg(), ERROR, PopulateRecordCache::fn_mcxt, FreeTupleDesc(), funcname, 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 JsonParseErrorType get_scalar ( void *  state,
char *  token,
JsonTokenType  tokentype 
)
static

Definition at line 1443 of file jsonfuncs.c.

1444 {
1445  GetState *_state = (GetState *) state;
1446  int lex_level = _state->lex->lex_level;
1447 
1448  /* Check for whole-object match */
1449  if (lex_level == 0 && _state->npath == 0)
1450  {
1451  if (_state->normalize_results && tokentype == JSON_TOKEN_STRING)
1452  {
1453  /* we want the de-escaped string */
1454  _state->next_scalar = true;
1455  }
1456  else if (_state->normalize_results && tokentype == JSON_TOKEN_NULL)
1457  {
1458  _state->tresult = (text *) NULL;
1459  }
1460  else
1461  {
1462  /*
1463  * This is a bit hokey: we will suppress whitespace after the
1464  * scalar token, but not whitespace before it. Probably not worth
1465  * doing our own space-skipping to avoid that.
1466  */
1467  const char *start = _state->lex->input;
1468  int len = _state->lex->prev_token_terminator - start;
1469 
1471  }
1472  }
1473 
1474  if (_state->next_scalar)
1475  {
1476  /* a de-escaped text value is wanted, so supply it */
1477  _state->tresult = cstring_to_text(token);
1478  /* make sure the next call to get_scalar doesn't overwrite it */
1479  _state->next_scalar = false;
1480  }
1481 
1482  return JSON_SUCCESS;
1483 }
const char * input
Definition: jsonapi.h:91
text * cstring_to_text(const char *s)
Definition: varlena.c:184

References cstring_to_text(), cstring_to_text_with_len(), JsonLexContext::input, JSON_SUCCESS, JSON_TOKEN_NULL, JSON_TOKEN_STRING, len, GetState::lex, JsonLexContext::lex_level, GetState::next_scalar, GetState::normalize_results, GetState::npath, JsonLexContext::prev_token_terminator, start, token, 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 1101 of file jsonfuncs.c.

1106 {
1107  JsonSemAction *sem = palloc0(sizeof(JsonSemAction));
1108  GetState *state = palloc0(sizeof(GetState));
1109 
1110  Assert(npath >= 0);
1111 
1112  state->lex = makeJsonLexContext(NULL, json, true);
1113 
1114  /* is it "_as_text" variant? */
1115  state->normalize_results = normalize_results;
1116  state->npath = npath;
1117  state->path_names = tpath;
1118  state->path_indexes = ipath;
1119  state->pathok = palloc0(sizeof(bool) * npath);
1120  state->array_cur_index = palloc(sizeof(int) * npath);
1121 
1122  if (npath > 0)
1123  state->pathok[0] = true;
1124 
1125  sem->semstate = (void *) state;
1126 
1127  /*
1128  * Not all variants need all the semantic routines. Only set the ones that
1129  * are actually needed for maximum efficiency.
1130  */
1131  sem->scalar = get_scalar;
1132  if (npath == 0)
1133  {
1138  }
1139  if (tpath != NULL)
1140  {
1143  }
1144  if (ipath != NULL)
1145  {
1149  }
1150 
1152  freeJsonLexContext(state->lex);
1153 
1154  return state->tresult;
1155 }
static JsonParseErrorType get_array_element_end(void *state, bool isnull)
Definition: jsonfuncs.c:1399
static JsonParseErrorType get_object_field_start(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:1195
static JsonParseErrorType get_object_start(void *state)
Definition: jsonfuncs.c:1158
static JsonParseErrorType get_array_start(void *state)
Definition: jsonfuncs.c:1293
static JsonParseErrorType get_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:1443
static JsonParseErrorType get_object_end(void *state)
Definition: jsonfuncs.c:1177
static JsonParseErrorType get_object_field_end(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:1242
static JsonParseErrorType get_array_end(void *state)
Definition: jsonfuncs.c:1333
static JsonParseErrorType get_array_element_start(void *state, bool isnull)
Definition: jsonfuncs.c:1351
json_struct_action array_end
Definition: jsonapi.h:138
json_struct_action object_end
Definition: jsonapi.h:136

References JsonSemAction::array_element_end, JsonSemAction::array_element_start, JsonSemAction::array_end, JsonSemAction::array_start, Assert, freeJsonLexContext(), 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, sem, 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 JsonParseErrorType hash_array_start ( void *  state)
static

Definition at line 3928 of file jsonfuncs.c.

3929 {
3930  JHashState *_state = (JHashState *) state;
3931 
3932  if (_state->lex->lex_level == 0)
3933  ereport(ERROR,
3934  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3935  errmsg("cannot call %s on an array", _state->function_name)));
3936 
3937  return JSON_SUCCESS;
3938 }
const char * function_name
Definition: jsonfuncs.c:138
JsonLexContext * lex
Definition: jsonfuncs.c:137

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

Referenced by get_json_object_as_hash().

◆ hash_object_field_end()

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

Definition at line 3877 of file jsonfuncs.c.

3878 {
3879  JHashState *_state = (JHashState *) state;
3880  JsonHashEntry *hashentry;
3881  bool found;
3882 
3883  /*
3884  * Ignore nested fields.
3885  */
3886  if (_state->lex->lex_level > 1)
3887  return JSON_SUCCESS;
3888 
3889  /*
3890  * Ignore field names >= NAMEDATALEN - they can't match a record field.
3891  * (Note: without this test, the hash code would truncate the string at
3892  * NAMEDATALEN-1, and could then match against a similarly-truncated
3893  * record field name. That would be a reasonable behavior, but this code
3894  * has previously insisted on exact equality, so we keep this behavior.)
3895  */
3896  if (strlen(fname) >= NAMEDATALEN)
3897  return JSON_SUCCESS;
3898 
3899  hashentry = hash_search(_state->hash, fname, HASH_ENTER, &found);
3900 
3901  /*
3902  * found being true indicates a duplicate. We don't do anything about
3903  * that, a later field with the same name overrides the earlier field.
3904  */
3905 
3906  hashentry->type = _state->saved_token_type;
3907  Assert(isnull == (hashentry->type == JSON_TOKEN_NULL));
3908 
3909  if (_state->save_json_start != NULL)
3910  {
3911  int len = _state->lex->prev_token_terminator - _state->save_json_start;
3912  char *val = palloc((len + 1) * sizeof(char));
3913 
3914  memcpy(val, _state->save_json_start, len);
3915  val[len] = '\0';
3916  hashentry->val = val;
3917  }
3918  else
3919  {
3920  /* must have had a scalar instead */
3921  hashentry->val = _state->saved_scalar;
3922  }
3923 
3924  return JSON_SUCCESS;
3925 }
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:955
@ HASH_ENTER
Definition: hsearch.h:114
char * saved_scalar
Definition: jsonfuncs.c:140
const char * save_json_start
Definition: jsonfuncs.c:141
JsonTokenType saved_token_type
Definition: jsonfuncs.c:142
HTAB * hash
Definition: jsonfuncs.c:139
char * val
Definition: jsonfuncs.c:149
JsonTokenType type
Definition: jsonfuncs.c:150

References Assert, JHashState::hash, HASH_ENTER, hash_search(), JSON_SUCCESS, 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 JsonParseErrorType hash_object_field_start ( void *  state,
char *  fname,
bool  isnull 
)
static

Definition at line 3851 of file jsonfuncs.c.

3852 {
3853  JHashState *_state = (JHashState *) state;
3854 
3855  if (_state->lex->lex_level > 1)
3856  return JSON_SUCCESS;
3857 
3858  /* remember token type */
3859  _state->saved_token_type = _state->lex->token_type;
3860 
3861  if (_state->lex->token_type == JSON_TOKEN_ARRAY_START ||
3863  {
3864  /* remember start position of the whole text of the subobject */
3865  _state->save_json_start = _state->lex->token_start;
3866  }
3867  else
3868  {
3869  /* must be a scalar */
3870  _state->save_json_start = NULL;
3871  }
3872 
3873  return JSON_SUCCESS;
3874 }
@ JSON_TOKEN_OBJECT_START
Definition: jsonapi.h:24
@ JSON_TOKEN_ARRAY_START
Definition: jsonapi.h:26

References JSON_SUCCESS, 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 JsonParseErrorType hash_scalar ( void *  state,
char *  token,
JsonTokenType  tokentype 
)
static

Definition at line 3941 of file jsonfuncs.c.

3942 {
3943  JHashState *_state = (JHashState *) state;
3944 
3945  if (_state->lex->lex_level == 0)
3946  ereport(ERROR,
3947  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3948  errmsg("cannot call %s on a scalar", _state->function_name)));
3949 
3950  if (_state->lex->lex_level == 1)
3951  {
3952  _state->saved_scalar = token;
3953  /* saved_token_type must already be set in hash_object_field_start() */
3954  Assert(_state->saved_token_type == tokentype);
3955  }
3956 
3957  return JSON_SUCCESS;
3958 }

References Assert, ereport, errcode(), errmsg(), ERROR, JHashState::function_name, JSON_SUCCESS, JHashState::lex, JsonLexContext::lex_level, JHashState::saved_scalar, JHashState::saved_token_type, and token.

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

5710 {
5711  JsonLexContext lex;
5712  JsonSemAction *sem = palloc0(sizeof(JsonSemAction));
5714 
5715  state->lex = makeJsonLexContext(&lex, json, true);
5716  state->action = action;
5717  state->action_state = action_state;
5718  state->flags = flags;
5719 
5720  sem->semstate = (void *) state;
5723 
5725  freeJsonLexContext(&lex);
5726 }
static JsonParseErrorType iterate_values_object_field_start(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:5761
static JsonParseErrorType iterate_values_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:5733

References generate_unaccent_rules::action, freeJsonLexContext(), iterate_values_object_field_start(), iterate_values_scalar(), makeJsonLexContext(), JsonSemAction::object_field_start, palloc0(), pg_parse_json_or_ereport, JsonSemAction::scalar, sem, 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 5640 of file jsonfuncs.c.

5642 {
5643  JsonbIterator *it;
5644  JsonbValue v;
5646 
5647  it = JsonbIteratorInit(&jb->root);
5648 
5649  /*
5650  * Just recursively iterating over jsonb and call callback on all
5651  * corresponding elements
5652  */
5653  while ((type = JsonbIteratorNext(&it, &v, false)) != WJB_DONE)
5654  {
5655  if (type == WJB_KEY)
5656  {
5657  if (flags & jtiKey)
5658  action(state, v.val.string.val, v.val.string.len);
5659 
5660  continue;
5661  }
5662  else if (!(type == WJB_VALUE || type == WJB_ELEM))
5663  {
5664  /* do not call callback for composite JsonbValue */
5665  continue;
5666  }
5667 
5668  /* JsonbValue is a value of object or element of array */
5669  switch (v.type)
5670  {
5671  case jbvString:
5672  if (flags & jtiString)
5673  action(state, v.val.string.val, v.val.string.len);
5674  break;
5675  case jbvNumeric:
5676  if (flags & jtiNumeric)
5677  {
5678  char *val;
5679 
5681  NumericGetDatum(v.val.numeric)));
5682 
5683  action(state, val, strlen(val));
5684  pfree(val);
5685  }
5686  break;
5687  case jbvBool:
5688  if (flags & jtiBool)
5689  {
5690  if (v.val.boolean)
5691  action(state, "true", 4);
5692  else
5693  action(state, "false", 5);
5694  }
5695  break;
5696  default:
5697  /* do not call callback for composite JsonbValue */
5698  break;
5699  }
5700  }
5701 }
Datum numeric_out(PG_FUNCTION_ARGS)
Definition: numeric.c:816
#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:27
@ jtiNumeric
Definition: jsonfuncs.h:29
@ jtiBool
Definition: jsonfuncs.h:30
@ jtiString
Definition: jsonfuncs.h:28
void pfree(void *pointer)
Definition: mcxt.c:1521
static Datum NumericGetDatum(Numeric X)
Definition: numeric.h:73
static char * DatumGetCString(Datum X)
Definition: postgres.h:335
const char * type

References generate_unaccent_rules::action, DatumGetCString(), DirectFunctionCall1, jbvBool, jbvNumeric, jbvString, JsonbIteratorInit(), JsonbIteratorNext(), jtiBool, jtiKey, jtiNumeric, jtiString, numeric_out(), NumericGetDatum(), pfree(), Jsonb::root, 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 JsonParseErrorType iterate_values_object_field_start ( void *  state,
char *  fname,
bool  isnull 
)
static

Definition at line 5761 of file jsonfuncs.c.

5762 {
5764 
5765  if (_state->flags & jtiKey)
5766  {
5767  char *val = pstrdup(fname);
5768 
5769  _state->action(_state->action_state, val, strlen(val));
5770  }
5771 
5772  return JSON_SUCCESS;
5773 }
char * pstrdup(const char *in)
Definition: mcxt.c:1696
JsonIterateStringValuesAction action
Definition: jsonfuncs.c:67

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

Referenced by iterate_json_values().

◆ iterate_values_scalar()

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

Definition at line 5733 of file jsonfuncs.c.

5734 {
5736 
5737  switch (tokentype)
5738  {
5739  case JSON_TOKEN_STRING:
5740  if (_state->flags & jtiString)
5741  _state->action(_state->action_state, token, strlen(token));
5742  break;
5743  case JSON_TOKEN_NUMBER:
5744  if (_state->flags & jtiNumeric)
5745  _state->action(_state->action_state, token, strlen(token));
5746  break;
5747  case JSON_TOKEN_TRUE:
5748  case JSON_TOKEN_FALSE:
5749  if (_state->flags & jtiBool)
5750  _state->action(_state->action_state, token, strlen(token));
5751  break;
5752  default:
5753  /* do not call callback for any other token */
5754  break;
5755  }
5756 
5757  return JSON_SUCCESS;
5758 }
@ 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_SUCCESS, JSON_TOKEN_FALSE, JSON_TOKEN_NUMBER, JSON_TOKEN_STRING, JSON_TOKEN_TRUE, jtiBool, jtiNumeric, jtiString, and token.

Referenced by iterate_json_values().

◆ IteratorConcat()

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

Definition at line 5052 of file jsonfuncs.c.

5054 {
5055  JsonbValue v1,
5056  v2,
5057  *res = NULL;
5058  JsonbIteratorToken r1,
5059  r2,
5060  rk1,
5061  rk2;
5062 
5063  rk1 = JsonbIteratorNext(it1, &v1, false);
5064  rk2 = JsonbIteratorNext(it2, &v2, false);
5065 
5066  /*
5067  * JsonbIteratorNext reports raw scalars as if they were single-element
5068  * arrays; hence we only need consider "object" and "array" cases here.
5069  */
5070  if (rk1 == WJB_BEGIN_OBJECT && rk2 == WJB_BEGIN_OBJECT)
5071  {
5072  /*
5073  * Both inputs are objects.
5074  *
5075  * Append all the tokens from v1 to res, except last WJB_END_OBJECT
5076  * (because res will not be finished yet).
5077  */
5078  pushJsonbValue(state, rk1, NULL);
5079  while ((r1 = JsonbIteratorNext(it1, &v1, true)) != WJB_END_OBJECT)
5080  pushJsonbValue(state, r1, &v1);
5081 
5082  /*
5083  * Append all the tokens from v2 to res, including last WJB_END_OBJECT
5084  * (the concatenation will be completed). Any duplicate keys will
5085  * automatically override the value from the first object.
5086  */
5087  while ((r2 = JsonbIteratorNext(it2, &v2, true)) != WJB_DONE)
5088  res = pushJsonbValue(state, r2, r2 != WJB_END_OBJECT ? &v2 : NULL);
5089  }
5090  else if (rk1 == WJB_BEGIN_ARRAY && rk2 == WJB_BEGIN_ARRAY)
5091  {
5092  /*
5093  * Both inputs are arrays.
5094  */
5095  pushJsonbValue(state, rk1, NULL);
5096 
5097  while ((r1 = JsonbIteratorNext(it1, &v1, true)) != WJB_END_ARRAY)
5098  {
5099  Assert(r1 == WJB_ELEM);
5100  pushJsonbValue(state, r1, &v1);
5101  }
5102 
5103  while ((r2 = JsonbIteratorNext(it2, &v2, true)) != WJB_END_ARRAY)
5104  {
5105  Assert(r2 == WJB_ELEM);
5106  pushJsonbValue(state, WJB_ELEM, &v2);
5107  }
5108 
5109  res = pushJsonbValue(state, WJB_END_ARRAY, NULL /* signal to sort */ );
5110  }
5111  else if (rk1 == WJB_BEGIN_OBJECT)
5112  {
5113  /*
5114  * We have object || array.
5115  */
5116  Assert(rk2 == WJB_BEGIN_ARRAY);
5117 
5119 
5121  while ((r1 = JsonbIteratorNext(it1, &v1, true)) != WJB_DONE)
5122  pushJsonbValue(state, r1, r1 != WJB_END_OBJECT ? &v1 : NULL);
5123 
5124  while ((r2 = JsonbIteratorNext(it2, &v2, true)) != WJB_DONE)
5125  res = pushJsonbValue(state, r2, r2 != WJB_END_ARRAY ? &v2 : NULL);
5126  }
5127  else
5128  {
5129  /*
5130  * We have array || object.
5131  */
5132  Assert(rk1 == WJB_BEGIN_ARRAY);
5133  Assert(rk2 == WJB_BEGIN_OBJECT);
5134 
5136 
5137  while ((r1 = JsonbIteratorNext(it1, &v1, true)) != WJB_END_ARRAY)
5138  pushJsonbValue(state, r1, &v1);
5139 
5141  while ((r2 = JsonbIteratorNext(it2, &v2, true)) != WJB_DONE)
5142  pushJsonbValue(state, r2, r2 != WJB_END_OBJECT ? &v2 : NULL);
5143 
5145  }
5146 
5147  return res;
5148 }
@ 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:566

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

3491 {
3492  jsv->is_json = obj->is_json;
3493 
3494  if (jsv->is_json)
3495  {
3496  JsonHashEntry *hashentry = hash_search(obj->val.json_hash, field,
3497  HASH_FIND, NULL);
3498 
3499  jsv->val.json.type = hashentry ? hashentry->type : JSON_TOKEN_NULL;
3500  jsv->val.json.str = jsv->val.json.type == JSON_TOKEN_NULL ? NULL :
3501  hashentry->val;
3502  jsv->val.json.len = jsv->val.json.str ? -1 : 0; /* null-terminated */
3503 
3504  return hashentry != NULL;
3505  }
3506  else
3507  {
3508  jsv->val.jsonb = !obj->val.jsonb_cont ? NULL :
3509  getKeyJsonValueFromContainer(obj->val.jsonb_cont, field, strlen(field),
3510  NULL);
3511 
3512  return jsv->val.jsonb != NULL;
3513  }
3514 }
@ HASH_FIND
Definition: hsearch.h:113
JsonbValue * getKeyJsonValueFromContainer(JsonbContainer *container, const char *keyVal, int keyLen, JsonbValue *res)
Definition: jsonb_util.c:398
bool is_json
Definition: jsonfuncs.c:309
JsonbContainer * jsonb_cont
Definition: jsonfuncs.c:313
HTAB * json_hash
Definition: jsonfuncs.c:312
union JsObject::@29 val
union JsValue::@27 val
JsonbValue * jsonb
Definition: jsonfuncs.c:303
struct JsValue::@27::@28 json
bool is_json
Definition: jsonfuncs.c:293

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

921 {
922  text *json = PG_GETARG_TEXT_PP(0);
923  int element = PG_GETARG_INT32(1);
924  text *result;
925 
926  result = get_worker(json, NULL, &element, 1, false);
927 
928  if (result != NULL)
929  PG_RETURN_TEXT_P(result);
930  else
931  PG_RETURN_NULL();
932 }
#define PG_GETARG_INT32(n)
Definition: fmgr.h:269
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 963 of file jsonfuncs.c.

964 {
965  text *json = PG_GETARG_TEXT_PP(0);
966  int element = PG_GETARG_INT32(1);
967  text *result;
968 
969  result = get_worker(json, NULL, &element, 1, true);
970 
971  if (result != NULL)
972  PG_RETURN_TEXT_P(result);
973  else
974  PG_RETURN_NULL();
975 }

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

2295 {
2296  return elements_worker(fcinfo, "json_array_elements", false);
2297 }
static Datum elements_worker(FunctionCallInfo fcinfo, const char *funcname, bool as_text)
Definition: jsonfuncs.c:2306

References elements_worker().

◆ json_array_elements_text()

Datum json_array_elements_text ( PG_FUNCTION_ARGS  )

Definition at line 2300 of file jsonfuncs.c.

2301 {
2302  return elements_worker(fcinfo, "json_array_elements_text", true);
2303 }

References elements_worker().

◆ json_array_length()

Datum json_array_length ( PG_FUNCTION_ARGS  )

Definition at line 1850 of file jsonfuncs.c.

1851 {
1852  text *json = PG_GETARG_TEXT_PP(0);
1853  AlenState *state;
1854  JsonLexContext lex;
1855  JsonSemAction *sem;
1856 
1857  state = palloc0(sizeof(AlenState));
1858  state->lex = makeJsonLexContext(&lex, json, false);
1859  /* palloc0 does this for us */
1860 #if 0
1861  state->count = 0;
1862 #endif
1863 
1864  sem = palloc0(sizeof(JsonSemAction));
1865  sem->semstate = (void *) state;
1867  sem->scalar = alen_scalar;
1869 
1871 
1872  PG_RETURN_INT32(state->count);
1873 }
#define PG_RETURN_INT32(x)
Definition: fmgr.h:354
static JsonParseErrorType alen_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:1912
static JsonParseErrorType alen_object_start(void *state)
Definition: jsonfuncs.c:1898
static JsonParseErrorType alen_array_element_start(void *state, bool isnull)
Definition: jsonfuncs.c:1926

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, sem, and JsonSemAction::semstate.

◆ json_categorize_type()

void json_categorize_type ( Oid  typoid,
bool  is_jsonb,
JsonTypeCategory tcategory,
Oid outfuncoid 
)

Definition at line 5975 of file jsonfuncs.c.

5977 {
5978  bool typisvarlena;
5979 
5980  /* Look through any domain */
5981  typoid = getBaseType(typoid);
5982 
5983  *outfuncoid = InvalidOid;
5984 
5985  switch (typoid)
5986  {
5987  case BOOLOID:
5988  *outfuncoid = F_BOOLOUT;
5989  *tcategory = JSONTYPE_BOOL;
5990  break;
5991 
5992  case INT2OID:
5993  case INT4OID:
5994  case INT8OID:
5995  case FLOAT4OID:
5996  case FLOAT8OID:
5997  case NUMERICOID:
5998  getTypeOutputInfo(typoid, outfuncoid, &typisvarlena);
5999  *tcategory = JSONTYPE_NUMERIC;
6000  break;
6001 
6002  case DATEOID:
6003  *outfuncoid = F_DATE_OUT;
6004  *tcategory = JSONTYPE_DATE;
6005  break;
6006 
6007  case TIMESTAMPOID:
6008  *outfuncoid = F_TIMESTAMP_OUT;
6009  *tcategory = JSONTYPE_TIMESTAMP;
6010  break;
6011 
6012  case TIMESTAMPTZOID:
6013  *outfuncoid = F_TIMESTAMPTZ_OUT;
6014  *tcategory = JSONTYPE_TIMESTAMPTZ;
6015  break;
6016 
6017  case JSONOID:
6018  getTypeOutputInfo(typoid, outfuncoid, &typisvarlena);
6019  *tcategory = JSONTYPE_JSON;
6020  break;
6021 
6022  case JSONBOID:
6023  getTypeOutputInfo(typoid, outfuncoid, &typisvarlena);
6024  *tcategory = is_jsonb ? JSONTYPE_JSONB : JSONTYPE_JSON;
6025  break;
6026 
6027  default:
6028  /* Check for arrays and composites */
6029  if (OidIsValid(get_element_type(typoid)) || typoid == ANYARRAYOID
6030  || typoid == ANYCOMPATIBLEARRAYOID || typoid == RECORDARRAYOID)
6031  {
6032  *outfuncoid = F_ARRAY_OUT;
6033  *tcategory = JSONTYPE_ARRAY;
6034  }
6035  else if (type_is_rowtype(typoid)) /* includes RECORDOID */
6036  {
6037  *outfuncoid = F_RECORD_OUT;
6038  *tcategory = JSONTYPE_COMPOSITE;
6039  }
6040  else
6041  {
6042  /*
6043  * It's probably the general case. But let's look for a cast
6044  * to json (note: not to jsonb even if is_jsonb is true), if
6045  * it's not built-in.
6046  */
6047  *tcategory = JSONTYPE_OTHER;
6048  if (typoid >= FirstNormalObjectId)
6049  {
6050  Oid castfunc;
6051  CoercionPathType ctype;
6052 
6053  ctype = find_coercion_pathway(JSONOID, typoid,
6055  &castfunc);
6056  if (ctype == COERCION_PATH_FUNC && OidIsValid(castfunc))
6057  {
6058  *outfuncoid = castfunc;
6059  *tcategory = JSONTYPE_CAST;
6060  }
6061  else
6062  {
6063  /* non builtin type with no cast */
6064  getTypeOutputInfo(typoid, outfuncoid, &typisvarlena);
6065  }
6066  }
6067  else
6068  {
6069  /* any other builtin type */
6070  getTypeOutputInfo(typoid, outfuncoid, &typisvarlena);
6071  }
6072  }
6073  break;
6074  }
6075 }
#define OidIsValid(objectId)
Definition: c.h:775
@ JSONTYPE_JSON
Definition: jsonfuncs.h:76
@ JSONTYPE_TIMESTAMP
Definition: jsonfuncs.h:74
@ JSONTYPE_NUMERIC
Definition: jsonfuncs.h:72
@ JSONTYPE_DATE
Definition: jsonfuncs.h:73
@ JSONTYPE_BOOL
Definition: jsonfuncs.h:71
@ JSONTYPE_OTHER
Definition: jsonfuncs.h:81
@ JSONTYPE_CAST
Definition: jsonfuncs.h:80
@ JSONTYPE_COMPOSITE
Definition: jsonfuncs.h:79
@ JSONTYPE_ARRAY
Definition: jsonfuncs.h:78
@ JSONTYPE_TIMESTAMPTZ
Definition: jsonfuncs.h:75
@ JSONTYPE_JSONB
Definition: jsonfuncs.h:77
Oid get_element_type(Oid typid)
Definition: lsyscache.c:2759
bool type_is_rowtype(Oid typid)
Definition: lsyscache.c:2655
void getTypeOutputInfo(Oid type, Oid *typOutput, bool *typIsVarlena)
Definition: lsyscache.c:2907
Oid getBaseType(Oid typid)
Definition: lsyscache.c:2521
CoercionPathType find_coercion_pathway(Oid targetTypeId, Oid sourceTypeId, CoercionContext ccontext, Oid *funcid)
CoercionPathType
Definition: parse_coerce.h:25
@ COERCION_PATH_FUNC
Definition: parse_coerce.h:27
unsigned int Oid
Definition: postgres_ext.h:31
@ COERCION_EXPLICIT
Definition: primnodes.h:717
#define FirstNormalObjectId
Definition: transam.h:197

References COERCION_EXPLICIT, COERCION_PATH_FUNC, find_coercion_pathway(), FirstNormalObjectId, get_element_type(), getBaseType(), getTypeOutputInfo(), InvalidOid, JSONTYPE_ARRAY, JSONTYPE_BOOL, JSONTYPE_CAST, JSONTYPE_COMPOSITE, JSONTYPE_DATE, JSONTYPE_JSON, JSONTYPE_JSONB, JSONTYPE_NUMERIC, JSONTYPE_OTHER, JSONTYPE_TIMESTAMP, JSONTYPE_TIMESTAMPTZ, OidIsValid, and type_is_rowtype().

Referenced by add_json(), add_jsonb(), array_to_json_internal(), array_to_jsonb_internal(), composite_to_json(), composite_to_jsonb(), ExecInitExprRec(), json_agg_transfn_worker(), json_object_agg_transfn_worker(), jsonb_agg_transfn_worker(), jsonb_object_agg_transfn_worker(), to_json(), to_json_is_immutable(), to_jsonb(), and to_jsonb_is_immutable().

◆ json_each()

Datum json_each ( PG_FUNCTION_ARGS  )

Definition at line 1948 of file jsonfuncs.c.

1949 {
1950  return each_worker(fcinfo, false);
1951 }
static Datum each_worker(FunctionCallInfo fcinfo, bool as_text)
Definition: jsonfuncs.c:2056

References each_worker().

◆ json_each_text()

Datum json_each_text ( PG_FUNCTION_ARGS  )

Definition at line 1960 of file jsonfuncs.c.

1961 {
1962  return each_worker(fcinfo, true);
1963 }

References each_worker().

◆ json_errsave_error()

void json_errsave_error ( JsonParseErrorType  error,
JsonLexContext lex,
Node escontext 
)

Definition at line 639 of file jsonfuncs.c.

641 {
645  errsave(escontext,
646  (errcode(ERRCODE_UNTRANSLATABLE_CHARACTER),
647  errmsg("unsupported Unicode escape sequence"),
649  report_json_context(lex)));
650  else if (error == JSON_SEM_ACTION_FAILED)
651  {
652  /* semantic action function had better have reported something */
653  if (!SOFT_ERROR_OCCURRED(escontext))
654  elog(ERROR, "JSON semantic action function did not provide error information");
655  }
656  else
657  errsave(escontext,
658  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
659  errmsg("invalid input syntax for type %s", "json"),
661  report_json_context(lex)));
662 }
int errdetail_internal(const char *fmt,...)
Definition: elog.c:1230
#define errsave(context,...)
Definition: elog.h:260
#define elog(elevel,...)
Definition: elog.h:224
char * json_errdetail(JsonParseErrorType error, JsonLexContext *lex)
Definition: jsonapi.c:2096
@ JSON_SEM_ACTION_FAILED
Definition: jsonapi.h:60
@ JSON_UNICODE_CODE_POINT_ZERO
Definition: jsonapi.h:54
@ JSON_UNICODE_UNTRANSLATABLE
Definition: jsonapi.h:57
@ JSON_UNICODE_HIGH_ESCAPE
Definition: jsonapi.h:56
static int report_json_context(JsonLexContext *lex)
Definition: jsonfuncs.c:675
#define SOFT_ERROR_OCCURRED(escontext)
Definition: miscnodes.h:52

References elog, errcode(), errdetail_internal(), errmsg(), ERROR, error(), errsave, json_errdetail(), JSON_SEM_ACTION_FAILED, JSON_UNICODE_CODE_POINT_ZERO, JSON_UNICODE_HIGH_ESCAPE, JSON_UNICODE_UNTRANSLATABLE, report_json_context(), and SOFT_ERROR_OCCURRED.

Referenced by get_array_start(), json_get_first_token(), json_typeof(), json_validate(), and pg_parse_json_or_errsave().

◆ json_extract_path()

Datum json_extract_path ( PG_FUNCTION_ARGS  )

Definition at line 1007 of file jsonfuncs.c.

1008 {
1009  return get_path_all(fcinfo, false);
1010 }
static Datum get_path_all(FunctionCallInfo fcinfo, bool as_text)
Definition: jsonfuncs.c:1022

References get_path_all().

◆ json_extract_path_text()

Datum json_extract_path_text ( PG_FUNCTION_ARGS  )

Definition at line 1013 of file jsonfuncs.c.

1014 {
1015  return get_path_all(fcinfo, true);
1016 }

References get_path_all().

◆ json_get_first_token()

JsonTokenType json_get_first_token ( text json,
bool  throw_error 
)

Definition at line 5948 of file jsonfuncs.c.

5949 {
5950  JsonLexContext lex;
5951  JsonParseErrorType result;
5952 
5953  makeJsonLexContext(&lex, json, false);
5954 
5955  /* Lex exactly one token from the input and check its type. */
5956  result = json_lex(&lex);
5957 
5958  if (result == JSON_SUCCESS)
5959  return lex.token_type;
5960 
5961  if (throw_error)
5962  json_errsave_error(result, &lex, NULL);
5963 
5964  return JSON_TOKEN_INVALID; /* invalid json */
5965 }
JsonParseErrorType json_lex(JsonLexContext *lex)
Definition: jsonapi.c:1308
@ JSON_TOKEN_INVALID
Definition: jsonapi.h:21

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

Referenced by ExecEvalJsonIsPredicate().

◆ json_object_field()

Datum json_object_field ( PG_FUNCTION_ARGS  )

Definition at line 844 of file jsonfuncs.c.

845 {
846  text *json = PG_GETARG_TEXT_PP(0);
847  text *fname = PG_GETARG_TEXT_PP(1);
848  char *fnamestr = text_to_cstring(fname);
849  text *result;
850 
851  result = get_worker(json, &fnamestr, NULL, 1, false);
852 
853  if (result != NULL)
854  PG_RETURN_TEXT_P(result);
855  else
856  PG_RETURN_NULL();
857 }
char * text_to_cstring(const text *t)
Definition: varlena.c:217

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

883 {
884  text *json = PG_GETARG_TEXT_PP(0);
885  text *fname = PG_GETARG_TEXT_PP(1);
886  char *fnamestr = text_to_cstring(fname);
887  text *result;
888 
889  result = get_worker(json, &fnamestr, NULL, 1, true);
890 
891  if (result != NULL)
892  PG_RETURN_TEXT_P(result);
893  else
894  PG_RETURN_NULL();
895 }

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

731 {
732  FuncCallContext *funcctx;
733  OkeysState *state;
734 
735  if (SRF_IS_FIRSTCALL())
736  {
737  text *json = PG_GETARG_TEXT_PP(0);
738  JsonLexContext lex;
740  MemoryContext oldcontext;
741 
742  funcctx = SRF_FIRSTCALL_INIT();
743  oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
744 
745  state = palloc(sizeof(OkeysState));
746  sem = palloc0(sizeof(JsonSemAction));
747 
748  state->lex = makeJsonLexContext(&lex, json, true);
749  state->result_size = 256;
750  state->result_count = 0;
751  state->sent_count = 0;
752  state->result = palloc(256 * sizeof(char *));
753 
754  sem->semstate = (void *) state;
758  /* remainder are all NULL, courtesy of palloc0 above */
759 
761  /* keys are now in state->result */
762 
763  freeJsonLexContext(&lex);
764  pfree(sem);
765 
766  MemoryContextSwitchTo(oldcontext);
767  funcctx->user_fctx = (void *) state;
768  }
769 
770  funcctx = SRF_PERCALL_SETUP();
771  state = (OkeysState *) funcctx->user_fctx;
772 
773  if (state->sent_count < state->result_count)
774  {
775  char *nxt = state->result[state->sent_count++];
776 
777  SRF_RETURN_NEXT(funcctx, CStringGetTextDatum(nxt));
778  }
779 
780  SRF_RETURN_DONE(funcctx);
781 }
#define SRF_IS_FIRSTCALL()
Definition: funcapi.h:304
#define SRF_PERCALL_SETUP()
Definition: funcapi.h:308
#define SRF_RETURN_NEXT(_funcctx, _result)
Definition: funcapi.h:310
#define SRF_FIRSTCALL_INIT()
Definition: funcapi.h:306
#define SRF_RETURN_DONE(_funcctx)
Definition: funcapi.h:328
if(TABLE==NULL||TABLE_index==NULL)
Definition: isn.c:77
static JsonParseErrorType okeys_array_start(void *state)
Definition: jsonfuncs.c:807
static JsonParseErrorType okeys_object_field_start(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:784
static JsonParseErrorType okeys_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:822
void * user_fctx
Definition: funcapi.h:82
MemoryContext multi_call_memory_ctx
Definition: funcapi.h:101

References JsonSemAction::array_start, CStringGetTextDatum, freeJsonLexContext(), 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, sem, JsonSemAction::semstate, SRF_FIRSTCALL_INIT, SRF_IS_FIRSTCALL, SRF_PERCALL_SETUP, SRF_RETURN_DONE, SRF_RETURN_NEXT, and FuncCallContext::user_fctx.

◆ json_populate_record()

Datum json_populate_record ( PG_FUNCTION_ARGS  )

Definition at line 2493 of file jsonfuncs.c.

2494 {
2495  return populate_record_worker(fcinfo, "json_populate_record",
2496  true, true, NULL);
2497 }
static Datum populate_record_worker(FunctionCallInfo fcinfo, const char *funcname, bool is_json, bool have_record_arg, Node *escontext)
Definition: jsonfuncs.c:3697

References populate_record_worker().

◆ json_populate_recordset()

Datum json_populate_recordset ( PG_FUNCTION_ARGS  )

Definition at line 3986 of file jsonfuncs.c.

3987 {
3988  return populate_recordset_worker(fcinfo, "json_populate_recordset",
3989  true, true);
3990 }
static Datum populate_recordset_worker(FunctionCallInfo fcinfo, const char *funcname, bool is_json, bool have_record_arg)
Definition: jsonfuncs.c:4039

References populate_recordset_worker().

◆ json_populate_type()

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

Definition at line 3343 of file jsonfuncs.c.

3348 {
3349  JsValue jsv = {0};
3350  JsonbValue jbv;
3351 
3352  jsv.is_json = json_type == JSONOID;
3353 
3354  if (*isnull)
3355  {
3356  if (jsv.is_json)
3357  jsv.val.json.str = NULL;
3358  else
3359  jsv.val.jsonb = NULL;
3360  }
3361  else if (jsv.is_json)
3362  {
3363  text *json = DatumGetTextPP(json_val);
3364 
3365  jsv.val.json.str = VARDATA_ANY(json);
3366  jsv.val.json.len = VARSIZE_ANY_EXHDR(json);
3367  jsv.val.json.type = JSON_TOKEN_INVALID; /* not used in
3368  * populate_composite() */
3369  }
3370  else
3371  {
3372  Jsonb *jsonb = DatumGetJsonbP(json_val);
3373 
3374  jsv.val.jsonb = &jbv;
3375 
3376  if (omit_quotes)
3377  {
3378  char *str = JsonbUnquote(DatumGetJsonbP(json_val));
3379 
3380  /* fill the quote-stripped string */
3381  jbv.type = jbvString;
3382  jbv.val.string.len = strlen(str);
3383  jbv.val.string.val = str;
3384  }
3385  else
3386  {
3387  /* fill binary jsonb value pointing to jb */
3388  jbv.type = jbvBinary;
3389  jbv.val.binary.data = &jsonb->root;
3390  jbv.val.binary.len = VARSIZE(jsonb) - VARHDRSZ;
3391  }
3392  }
3393 
3394  if (*cache == NULL)
3395  *cache = MemoryContextAllocZero(mcxt, sizeof(ColumnIOData));
3396 
3397  return populate_record_field(*cache, typid, typmod, NULL, mcxt,
3398  PointerGetDatum(NULL), &jsv, isnull,
3399  escontext, omit_quotes);
3400 }
#define VARHDRSZ
Definition: c.h:692
#define DatumGetTextPP(X)
Definition: fmgr.h:292
const char * str
char * JsonbUnquote(Jsonb *jb)
Definition: jsonb.c:2166
@ jbvBinary
Definition: jsonb.h:236
static Jsonb * DatumGetJsonbP(Datum d)
Definition: jsonb.h:374
static Datum populate_record_field(ColumnIOData *col, Oid typid, int32 typmod, const char *colname, MemoryContext mcxt, Datum defaultval, JsValue *jsv, bool *isnull, Node *escontext, bool omit_scalar_quotes)
Definition: jsonfuncs.c:3404
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition: mcxt.c:1215
#define VARDATA_ANY(PTR)
Definition: varatt.h:324
#define VARSIZE(PTR)
Definition: varatt.h:279
#define VARSIZE_ANY_EXHDR(PTR)
Definition: varatt.h:317

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

Referenced by ExecEvalJsonCoercion().

◆ json_strip_nulls()

Datum json_strip_nulls ( PG_FUNCTION_ARGS  )

Definition at line 4492 of file jsonfuncs.c.

4493 {
4494  text *json = PG_GETARG_TEXT_PP(0);
4496  JsonLexContext lex;
4497  JsonSemAction *sem;
4498 
4499  state = palloc0(sizeof(StripnullState));
4500  sem = palloc0(sizeof(JsonSemAction));
4501 
4502  state->lex = makeJsonLexContext(&lex, json, true);
4503  state->strval = makeStringInfo();
4504  state->skip_next_null = false;
4505 
4506  sem->semstate = (void *) state;
4511  sem->scalar = sn_scalar;
4514 
4516 
4518  state->strval->len));
4519 }
static JsonParseErrorType sn_object_end(void *state)
Definition: jsonfuncs.c:4398
static JsonParseErrorType sn_array_element_start(void *state, bool isnull)
Definition: jsonfuncs.c:4458
static JsonParseErrorType sn_object_start(void *state)
Definition: jsonfuncs.c:4388
static JsonParseErrorType sn_array_start(void *state)
Definition: jsonfuncs.c:4408
static JsonParseErrorType sn_array_end(void *state)
Definition: jsonfuncs.c:4418
static JsonParseErrorType sn_object_field_start(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:4428
static JsonParseErrorType sn_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:4469
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, sem, 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 2500 of file jsonfuncs.c.

2501 {
2502  return populate_record_worker(fcinfo, "json_to_record",
2503  true, false, NULL);
2504 }

References populate_record_worker().

◆ json_to_recordset()

Datum json_to_recordset ( PG_FUNCTION_ARGS  )

Definition at line 3993 of file jsonfuncs.c.

3994 {
3995  return populate_recordset_worker(fcinfo, "json_to_recordset",
3996  true, false);
3997 }

References populate_recordset_worker().

◆ jsonb_array_element()

Datum jsonb_array_element ( PG_FUNCTION_ARGS  )

Definition at line 935 of file jsonfuncs.c.

936 {
937  Jsonb *jb = PG_GETARG_JSONB_P(0);
938  int element = PG_GETARG_INT32(1);
939  JsonbValue *v;
940 
941  if (!JB_ROOT_IS_ARRAY(jb))
942  PG_RETURN_NULL();
943 
944  /* Handle negative subscript */
945  if (element < 0)
946  {
947  uint32 nelements = JB_ROOT_COUNT(jb);
948 
949  if (-element > nelements)
950  PG_RETURN_NULL();
951  else
952  element += nelements;
953  }
954 
956  if (v != NULL)
958 
959  PG_RETURN_NULL();
960 }
unsigned int uint32
Definition: c.h:506
#define PG_RETURN_JSONB_P(x)
Definition: jsonb.h:393
#define JB_ROOT_COUNT(jbp_)
Definition: jsonb.h:219
JsonbValue * getIthJsonbValueFromContainer(JsonbContainer *container, uint32 i)
Definition: jsonb_util.c:468

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

979 {
980  Jsonb *jb = PG_GETARG_JSONB_P(0);
981  int element = PG_GETARG_INT32(1);
982  JsonbValue *v;
983 
984  if (!JB_ROOT_IS_ARRAY(jb))
985  PG_RETURN_NULL();
986 
987  /* Handle negative subscript */
988  if (element < 0)
989  {
990  uint32 nelements = JB_ROOT_COUNT(jb);
991 
992  if (-element > nelements)
993  PG_RETURN_NULL();
994  else
995  element += nelements;
996  }
997 
999 
1000  if (v != NULL && v->type != jbvNull)
1002 
1003  PG_RETURN_NULL();
1004 }

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

2207 {
2208  return elements_worker_jsonb(fcinfo, "jsonb_array_elements", false);
2209 }
static Datum elements_worker_jsonb(FunctionCallInfo fcinfo, const char *funcname, bool as_text)
Definition: jsonfuncs.c:2218

References elements_worker_jsonb().

◆ jsonb_array_elements_text()

Datum jsonb_array_elements_text ( PG_FUNCTION_ARGS  )

Definition at line 2212 of file jsonfuncs.c.

2213 {
2214  return elements_worker_jsonb(fcinfo, "jsonb_array_elements_text", true);
2215 }

References elements_worker_jsonb().

◆ jsonb_array_length()

Datum jsonb_array_length ( PG_FUNCTION_ARGS  )

Definition at line 1876 of file jsonfuncs.c.

1877 {
1878  Jsonb *jb = PG_GETARG_JSONB_P(0);
1879 
1880  if (JB_ROOT_IS_SCALAR(jb))
1881  ereport(ERROR,
1882  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1883  errmsg("cannot get array length of a scalar")));
1884  else if (!JB_ROOT_IS_ARRAY(jb))
1885  ereport(ERROR,
1886  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1887  errmsg("cannot get array length of a non-array")));
1888 
1890 }

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

4600 {
4601  Jsonb *jb1 = PG_GETARG_JSONB_P(0);
4602  Jsonb *jb2 = PG_GETARG_JSONB_P(1);
4603  JsonbParseState *state = NULL;
4604  JsonbValue *res;
4605  JsonbIterator *it1,
4606  *it2;
4607 
4608  /*
4609  * If one of the jsonb is empty, just return the other if it's not scalar
4610  * and both are of the same kind. If it's a scalar or they are of
4611  * different kinds we need to perform the concatenation even if one is
4612  * empty.
4613  */
4614  if (JB_ROOT_IS_OBJECT(jb1) == JB_ROOT_IS_OBJECT(jb2))
4615  {
4616  if (JB_ROOT_COUNT(jb1) == 0 && !JB_ROOT_IS_SCALAR(jb2))
4617  PG_RETURN_JSONB_P(jb2);
4618  else if (JB_ROOT_COUNT(jb2) == 0 && !JB_ROOT_IS_SCALAR(jb1))
4619  PG_RETURN_JSONB_P(jb1);
4620  }
4621 
4622  it1 = JsonbIteratorInit(&jb1->root);
4623  it2 = JsonbIteratorInit(&jb2->root);
4624 
4625  res = IteratorConcat(&it1, &it2, &state);
4626 
4627  Assert(res != NULL);
4628 
4630 }
static JsonbValue * IteratorConcat(JsonbIterator **it1, JsonbIterator **it2, JsonbParseState **state)
Definition: jsonfuncs.c:5052

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

4641 {
4642  Jsonb *in = PG_GETARG_JSONB_P(0);
4643  text *key = PG_GETARG_TEXT_PP(1);
4644  char *keyptr = VARDATA_ANY(key);
4645  int keylen = VARSIZE_ANY_EXHDR(key);
4646  JsonbParseState *state = NULL;
4647  JsonbIterator *it;
4648  JsonbValue v,
4649  *res = NULL;
4650  bool skipNested = false;
4652 
4653  if (JB_ROOT_IS_SCALAR(in))
4654  ereport(ERROR,
4655  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4656  errmsg("cannot delete from scalar")));
4657 
4658  if (JB_ROOT_COUNT(in) == 0)
4659  PG_RETURN_JSONB_P(in);
4660 
4661  it = JsonbIteratorInit(&in->root);
4662 
4663  while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE)
4664  {
4665  skipNested = true;
4666 
4667  if ((r == WJB_ELEM || r == WJB_KEY) &&
4668  (v.type == jbvString && keylen == v.val.string.len &&
4669  memcmp(keyptr, v.val.string.val, keylen) == 0))
4670  {
4671  /* skip corresponding value as well */
4672  if (r == WJB_KEY)
4673  (void) JsonbIteratorNext(&it, &v, true);
4674 
4675  continue;
4676  }
4677 
4678  res = pushJsonbValue(&state, r, r < WJB_BEGIN_ARRAY ? &v : NULL);
4679  }
4680 
4681  Assert(res != NULL);
4682 
4684 }

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

4694 {
4695  Jsonb *in = PG_GETARG_JSONB_P(0);
4696  ArrayType *keys = PG_GETARG_ARRAYTYPE_P(1);
4697  Datum *keys_elems;
4698  bool *keys_nulls;
4699  int keys_len;
4700  JsonbParseState *state = NULL;
4701  JsonbIterator *it;
4702  JsonbValue v,
4703  *res = NULL;
4704  bool skipNested = false;
4706 
4707  if (ARR_NDIM(keys) > 1)
4708  ereport(ERROR,
4709  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
4710  errmsg("wrong number of array subscripts")));
4711 
4712  if (JB_ROOT_IS_SCALAR(in))
4713  ereport(ERROR,
4714  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4715  errmsg("cannot delete from scalar")));
4716 
4717  if (JB_ROOT_COUNT(in) == 0)
4718  PG_RETURN_JSONB_P(in);
4719 
4720  deconstruct_array_builtin(keys, TEXTOID, &keys_elems, &keys_nulls, &keys_len);
4721 
4722  if (keys_len == 0)
4723  PG_RETURN_JSONB_P(in);
4724 
4725  it = JsonbIteratorInit(&in->root);
4726 
4727  while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE)
4728  {
4729  skipNested = true;
4730 
4731  if ((r == WJB_ELEM || r == WJB_KEY) && v.type == jbvString)
4732  {
4733  int i;
4734  bool found = false;
4735 
4736  for (i = 0; i < keys_len; i++)
4737  {
4738  char *keyptr;
4739  int keylen;
4740 
4741  if (keys_nulls[i])
4742  continue;
4743 
4744  /* We rely on the array elements not being toasted */
4745  keyptr = VARDATA_ANY(keys_elems[i]);
4746  keylen = VARSIZE_ANY_EXHDR(keys_elems[i]);
4747  if (keylen == v.val.string.len &&
4748  memcmp(keyptr, v.val.string.val, keylen) == 0)
4749  {
4750  found = true;
4751  break;
4752  }
4753  }
4754  if (found)
4755  {
4756  /* skip corresponding value as well */
4757  if (r == WJB_KEY)
4758  (void) JsonbIteratorNext(&it, &v, true);
4759 
4760  continue;
4761  }
4762  }
4763 
4764  res = pushJsonbValue(&state, r, r < WJB_BEGIN_ARRAY ? &v : NULL);
4765  }
4766 
4767  Assert(res != NULL);
4768 
4770 }
#define ARR_NDIM(a)
Definition: array.h:290

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

4781 {
4782  Jsonb *in = PG_GETARG_JSONB_P(0);
4783  int idx = PG_GETARG_INT32(1);
4784  JsonbParseState *state = NULL;
4785  JsonbIterator *it;
4786  uint32 i = 0,
4787  n;
4788  JsonbValue v,
4789  *res = NULL;
4791 
4792  if (JB_ROOT_IS_SCALAR(in))
4793  ereport(ERROR,
4794  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4795  errmsg("cannot delete from scalar")));
4796 
4797  if (JB_ROOT_IS_OBJECT(in))
4798  ereport(ERROR,
4799  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4800  errmsg("cannot delete from object using integer index")));
4801 
4802  if (JB_ROOT_COUNT(in) == 0)
4803  PG_RETURN_JSONB_P(in);
4804 
4805  it = JsonbIteratorInit(&in->root);
4806 
4807  r = JsonbIteratorNext(&it, &v, false);
4808  Assert(r == WJB_BEGIN_ARRAY);
4809  n = v.val.array.nElems;
4810 
4811  if (idx < 0)
4812  {
4813  if (-idx > n)
4814  idx = n;
4815  else
4816  idx = n + idx;
4817  }
4818 
4819  if (idx >= n)
4820  PG_RETURN_JSONB_P(in);
4821 
4822  pushJsonbValue(&state, r, NULL);
4823 
4824  while ((r = JsonbIteratorNext(&it, &v, true)) != WJB_DONE)
4825  {
4826  if (r == WJB_ELEM)
4827  {
4828  if (i++ == idx)
4829  continue;
4830  }
4831 
4832  res = pushJsonbValue(&state, r, r < WJB_BEGIN_ARRAY ? &v : NULL);
4833  }
4834 
4835  Assert(res != NULL);
4836 
4838 }
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 4960 of file jsonfuncs.c.

4961 {
4962  Jsonb *in = PG_GETARG_JSONB_P(0);
4963  ArrayType *path = PG_GETARG_ARRAYTYPE_P(1);
4964  JsonbValue *res = NULL;
4965  Datum *path_elems;
4966  bool *path_nulls;
4967  int path_len;
4968  JsonbIterator *it;
4969  JsonbParseState *st = NULL;
4970 
4971  if (ARR_NDIM(path) > 1)
4972  ereport(ERROR,
4973  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
4974  errmsg("wrong number of array subscripts")));
4975 
4976  if (JB_ROOT_IS_SCALAR(in))
4977  ereport(ERROR,
4978  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4979  errmsg("cannot delete path in scalar")));
4980 
4981  if (JB_ROOT_COUNT(in) == 0)
4982  PG_RETURN_JSONB_P(in);
4983 
4984  deconstruct_array_builtin(path, TEXTOID, &path_elems, &path_nulls, &path_len);
4985 
4986  if (path_len == 0)
4987  PG_RETURN_JSONB_P(in);
4988 
4989  it = JsonbIteratorInit(&in->root);
4990 
4991  res = setPath(&it, path_elems, path_nulls, path_len, &st,
4992  0, NULL, JB_PATH_DELETE);
4993 
4994  Assert(res != NULL);
4995 
4997 }
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:5180
#define JB_PATH_DELETE
Definition: jsonfuncs.c:44

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

1955 {
1956  return each_worker_jsonb(fcinfo, "jsonb_each", false);
1957 }
static Datum each_worker_jsonb(FunctionCallInfo fcinfo, const char *funcname, bool as_text)
Definition: jsonfuncs.c:1972

References each_worker_jsonb().

◆ jsonb_each_text()

Datum jsonb_each_text ( PG_FUNCTION_ARGS  )

Definition at line 1966 of file jsonfuncs.c.

1967 {
1968  return each_worker_jsonb(fcinfo, "jsonb_each_text", true);
1969 }

References each_worker_jsonb().

◆ jsonb_extract_path()

Datum jsonb_extract_path ( PG_FUNCTION_ARGS  )

Definition at line 1486 of file jsonfuncs.c.

1487 {
1488  return get_jsonb_path_all(fcinfo, false);
1489 }
static Datum get_jsonb_path_all(FunctionCallInfo fcinfo, bool as_text)
Definition: jsonfuncs.c:1498

References get_jsonb_path_all().

◆ jsonb_extract_path_text()

Datum jsonb_extract_path_text ( PG_FUNCTION_ARGS  )

Definition at line 1492 of file jsonfuncs.c.

1493 {
1494  return get_jsonb_path_all(fcinfo, true);
1495 }

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

1530 {
1531  JsonbContainer *container = &jb->root;
1532  JsonbValue *jbvp = NULL;
1533  int i;
1534  bool have_object = false,
1535  have_array = false;
1536 
1537  *isnull = false;
1538 
1539  /* Identify whether we have object, array, or scalar at top-level */
1540  if (JB_ROOT_IS_OBJECT(jb))
1541  have_object = true;
1542  else if (JB_ROOT_IS_ARRAY(jb) && !JB_ROOT_IS_SCALAR(jb))
1543  have_array = true;
1544  else
1545  {
1547  /* Extract the scalar value, if it is what we'll return */
1548  if (npath <= 0)
1549  jbvp = getIthJsonbValueFromContainer(container, 0);
1550  }
1551 
1552  /*
1553  * If the array is empty, return the entire LHS object, on the grounds
1554  * that we should do zero field or element extractions. For the
1555  * non-scalar case we can just hand back the object without much work. For
1556  * the scalar case, fall through and deal with the value below the loop.
1557  * (This inconsistency arises because there's no easy way to generate a
1558  * JsonbValue directly for root-level containers.)
1559  */
1560  if (npath <= 0 && jbvp == NULL)
1561  {
1562  if (as_text)
1563  {
1565  container,
1566  VARSIZE(jb))));
1567  }
1568  else
1569  {
1570  /* not text mode - just hand back the jsonb */
1571  PG_RETURN_JSONB_P(jb);
1572  }
1573  }
1574 
1575  for (i = 0; i < npath; i++)
1576  {
1577  if (have_object)
1578  {
1579  text *subscr = DatumGetTextPP(path[i]);
1580 
1581  jbvp = getKeyJsonValueFromContainer(container,
1582  VARDATA_ANY(subscr),
1583  VARSIZE_ANY_EXHDR(subscr),
1584  NULL);
1585  }
1586  else if (have_array)
1587  {
1588  int lindex;
1589  uint32 index;
1590  char *indextext = TextDatumGetCString(path[i]);
1591  char *endptr;
1592 
1593  errno = 0;
1594  lindex = strtoint(indextext, &endptr, 10);
1595  if (endptr == indextext || *endptr != '\0' || errno != 0)
1596  {
1597  *isnull = true;
1598  return PointerGetDatum(NULL);
1599  }
1600 
1601  if (lindex >= 0)
1602  {
1603  index = (uint32) lindex;
1604  }
1605  else
1606  {
1607  /* Handle negative subscript */
1608  uint32 nelements;
1609 
1610  /* Container must be array, but make sure */
1611  if (!JsonContainerIsArray(container))
1612  elog(ERROR, "not a jsonb array");
1613 
1614  nelements = JsonContainerSize(container);
1615 
1616  if (lindex == INT_MIN || -lindex > nelements)
1617  {
1618  *isnull = true;
1619  return PointerGetDatum(NULL);
1620  }
1621  else
1622  index = nelements + lindex;
1623  }
1624 
1625  jbvp = getIthJsonbValueFromContainer(container, index);
1626  }
1627  else
1628  {
1629  /* scalar, extraction yields a null */
1630  *isnull = true;
1631  return PointerGetDatum(NULL);
1632  }
1633 
1634  if (jbvp == NULL)
1635  {
1636  *isnull = true;
1637  return PointerGetDatum(NULL);
1638  }
1639  else if (i == npath - 1)
1640  break;
1641 
1642  if (jbvp->type == jbvBinary)
1643  {
1644  container = jbvp->val.binary.data;
1645  have_object = JsonContainerIsObject(container);
1646  have_array = JsonContainerIsArray(container);
1647  Assert(!JsonContainerIsScalar(container));
1648  }
1649  else
1650  {
1651  Assert(IsAJsonbScalar(jbvp));
1652  have_object = false;
1653  have_array = false;
1654  }
1655  }
1656 
1657  if (as_text)
1658  {
1659  if (jbvp->type == jbvNull)
1660  {
1661  *isnull = true;
1662  return PointerGetDatum(NULL);
1663  }
1664 
1665  return PointerGetDatum(JsonbValueAsText(jbvp));
1666  }
1667  else
1668  {
1669  Jsonb *res = JsonbValueToJsonb(jbvp);
1670 
1671  /* not text mode - just hand back the jsonb */
1673  }
1674 }
char * JsonbToCString(StringInfo out, JsonbContainer *in, int estimated_len)
Definition: jsonb.c:473
#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
Definition: type.h:95

References Assert, cstring_to_text(), DatumGetTextPP, 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_ANY, VARSIZE, and VARSIZE_ANY_EXHDR.

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

5004 {
5005  Jsonb *in = PG_GETARG_JSONB_P(0);
5006  ArrayType *path = PG_GETARG_ARRAYTYPE_P(1);
5007  Jsonb *newjsonb = PG_GETARG_JSONB_P(2);
5009  bool after = PG_GETARG_BOOL(3);
5010  JsonbValue *res = NULL;
5011  Datum *path_elems;
5012  bool *path_nulls;
5013  int path_len;
5014  JsonbIterator *it;
5015  JsonbParseState *st = NULL;
5016 
5017  JsonbToJsonbValue(newjsonb, &newval);
5018 
5019  if (ARR_NDIM(path) > 1)
5020  ereport(ERROR,
5021  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
5022  errmsg("wrong number of array subscripts")));
5023 
5024  if (JB_ROOT_IS_SCALAR(in))
5025  ereport(ERROR,
5026  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
5027  errmsg("cannot set path in scalar")));
5028 
5029  deconstruct_array_builtin(path, TEXTOID, &path_elems, &path_nulls, &path_len);
5030 
5031  if (path_len == 0)
5032  PG_RETURN_JSONB_P(in);
5033 
5034  it = JsonbIteratorInit(&in->root);
5035 
5036  res = setPath(&it, path_elems, path_nulls, path_len, &st, 0, &newval,
5038 
5039  Assert(res != NULL);
5040 
5042 }
#define PG_GETARG_BOOL(n)
Definition: fmgr.h:274
#define newval
void JsonbToJsonbValue(Jsonb *jsonb, JsonbValue *val)
Definition: jsonb_util.c:72
#define JB_PATH_INSERT_BEFORE
Definition: jsonfuncs.c:46
#define JB_PATH_INSERT_AFTER
Definition: jsonfuncs.c:47

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

861 {
862  Jsonb *jb = PG_GETARG_JSONB_P(0);
863  text *key = PG_GETARG_TEXT_PP(1);
864  JsonbValue *v;
865  JsonbValue vbuf;
866 
867  if (!JB_ROOT_IS_OBJECT(jb))
868  PG_RETURN_NULL();
869 
871  VARDATA_ANY(key),
873  &vbuf);
874 
875  if (v != NULL)
877 
878  PG_RETURN_NULL();
879 }

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

899 {
900  Jsonb *jb = PG_GETARG_JSONB_P(0);
901  text *key = PG_GETARG_TEXT_PP(1);
902  JsonbValue *v;
903  JsonbValue vbuf;
904 
905  if (!JB_ROOT_IS_OBJECT(jb))
906  PG_RETURN_NULL();
907 
909  VARDATA_ANY(key),
911  &vbuf);
912 
913  if (v != NULL && v->type != jbvNull)
915 
916  PG_RETURN_NULL();
917 }

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

567 {
568  FuncCallContext *funcctx;
569  OkeysState *state;
570 
571  if (SRF_IS_FIRSTCALL())
572  {
573  MemoryContext oldcontext;
574  Jsonb *jb = PG_GETARG_JSONB_P(0);
575  bool skipNested = false;
576  JsonbIterator *it;
577  JsonbValue v;
579 
580  if (JB_ROOT_IS_SCALAR(jb))
581  ereport(ERROR,
582  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
583  errmsg("cannot call %s on a scalar",
584  "jsonb_object_keys")));
585  else if (JB_ROOT_IS_ARRAY(jb))
586  ereport(ERROR,
587  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
588  errmsg("cannot call %s on an array",
589  "jsonb_object_keys")));
590 
591  funcctx = SRF_FIRSTCALL_INIT();
592  oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
593 
594  state = palloc(sizeof(OkeysState));
595 
596  state->result_size = JB_ROOT_COUNT(jb);
597  state->result_count = 0;
598  state->sent_count = 0;
599  state->result = palloc(state->result_size * sizeof(char *));
600 
601  it = JsonbIteratorInit(&jb->root);
602 
603  while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE)
604  {
605  skipNested = true;
606 
607  if (r == WJB_KEY)
608  {
609  char *cstr;
610 
611  cstr = palloc(v.val.string.len + 1 * sizeof(char));
612  memcpy(cstr, v.val.string.val, v.val.string.len);
613  cstr[v.val.string.len] = '\0';
614  state->result[state->result_count++] = cstr;
615  }
616  }
617 
618  MemoryContextSwitchTo(oldcontext);
619  funcctx->user_fctx = (void *) state;
620  }
621 
622  funcctx = SRF_PERCALL_SETUP();
623  state = (OkeysState *) funcctx->user_fctx;
624 
625  if (state->sent_count < state->result_count)
626  {
627  char *nxt = state->result[state->sent_count++];
628 
629  SRF_RETURN_NEXT(funcctx, CStringGetTextDatum(nxt));
630  }
631 
632  SRF_RETURN_DONE(funcctx);
633 }

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

2463 {
2464  return populate_record_worker(fcinfo, "jsonb_populate_record",
2465  false, true, NULL);
2466 }

References populate_record_worker().

◆ jsonb_populate_record_valid()

Datum jsonb_populate_record_valid ( PG_FUNCTION_ARGS  )

Definition at line 2475 of file jsonfuncs.c.

2476 {
2477  ErrorSaveContext escontext = {T_ErrorSaveContext};
2478 
2479  (void) populate_record_worker(fcinfo, "jsonb_populate_record",
2480  false, true, (Node *) &escontext);
2481 
2482  return BoolGetDatum(!escontext.error_occurred);
2483 }
static Datum BoolGetDatum(bool X)
Definition: postgres.h:102
bool error_occurred
Definition: miscnodes.h:46
Definition: nodes.h:129

References BoolGetDatum(), ErrorSaveContext::error_occurred, and populate_record_worker().

◆ jsonb_populate_recordset()

Datum jsonb_populate_recordset ( PG_FUNCTION_ARGS  )

Definition at line 3972 of file jsonfuncs.c.

3973 {
3974  return populate_recordset_worker(fcinfo, "jsonb_populate_recordset",
3975  false, true);
3976 }

References populate_recordset_worker().

◆ jsonb_pretty()

Datum jsonb_pretty ( PG_FUNCTION_ARGS  )

Definition at line 4583 of file jsonfuncs.c.

4584 {
4585  Jsonb *jb = PG_GETARG_JSONB_P(0);
4587 
4588  JsonbToCStringIndent(str, &jb->root, VARSIZE(jb));
4589 
4591 }
char * JsonbToCStringIndent(StringInfo out, JsonbContainer *in, int estimated_len)
Definition: jsonb.c:482

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

◆ jsonb_set()

Datum jsonb_set ( PG_FUNCTION_ARGS  )

Definition at line 4844 of file jsonfuncs.c.

4845 {
4846  Jsonb *in = PG_GETARG_JSONB_P(0);
4847  ArrayType *path = PG_GETARG_ARRAYTYPE_P(1);
4848  Jsonb *newjsonb = PG_GETARG_JSONB_P(2);
4850  bool create = PG_GETARG_BOOL(3);
4851  JsonbValue *res = NULL;
4852  Datum *path_elems;
4853  bool *path_nulls;
4854  int path_len;
4855  JsonbIterator *it;
4856  JsonbParseState *st = NULL;
4857 
4858  JsonbToJsonbValue(newjsonb, &newval);
4859 
4860  if (ARR_NDIM(path) > 1)
4861  ereport(ERROR,
4862  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
4863  errmsg("wrong number of array subscripts")));
4864 
4865  if (JB_ROOT_IS_SCALAR(in))
4866  ereport(ERROR,
4867  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4868  errmsg("cannot set path in scalar")));
4869 
4870  if (JB_ROOT_COUNT(in) == 0 && !create)
4871  PG_RETURN_JSONB_P(in);
4872 
4873  deconstruct_array_builtin(path, TEXTOID, &path_elems, &path_nulls, &path_len);
4874 
4875  if (path_len == 0)
4876  PG_RETURN_JSONB_P(in);
4877 
4878  it = JsonbIteratorInit(&in->root);
4879 
4880  res = setPath(&it, path_elems, path_nulls, path_len, &st,
4881  0, &newval, create ? JB_PATH_CREATE : JB_PATH_REPLACE);
4882 
4883  Assert(res != NULL);
4884 
4886 }
#define JB_PATH_CREATE
Definition: jsonfuncs.c:43
#define JB_PATH_REPLACE
Definition: jsonfuncs.c:45

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

1679 {
1680  JsonbValue *res;
1681  JsonbParseState *state = NULL;
1682  JsonbIterator *it;
1683  bool *path_nulls = palloc0(path_len * sizeof(bool));
1684 
1685  if (newval->type == jbvArray && newval->val.array.rawScalar)
1686  *newval = newval->val.array.elems[0];
1687 
1688  it = JsonbIteratorInit(&jb->root);
1689 
1690  res = setPath(&it, path, path_nulls, path_len, &state, 0, newval,
1693 
1694  pfree(path_nulls);
1695 
1697 }
@ jbvArray
Definition: jsonb.h:233
#define JB_PATH_CONSISTENT_POSITION
Definition: jsonfuncs.c:51
#define JB_PATH_FILL_GAPS
Definition: jsonfuncs.c:50

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

4894 {
4895  /* Jsonb *in = PG_GETARG_JSONB_P(0); */
4896  /* ArrayType *path = PG_GETARG_ARRAYTYPE_P(1); */
4897  /* Jsonb *newval = PG_GETARG_JSONB_P(2); */
4898  /* bool create = PG_GETARG_BOOL(3); */
4899  text *handle_null;
4900  char *handle_val;
4901 
4902  if (PG_ARGISNULL(0) || PG_ARGISNULL(1) || PG_ARGISNULL(3))
4903  PG_RETURN_NULL();
4904 
4905  /* could happen if they pass in an explicit NULL */
4906  if (PG_ARGISNULL(4))
4907  ereport(ERROR,
4908  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4909  errmsg("null_value_treatment must be \"delete_key\", \"return_target\", \"use_json_null\", or \"raise_exception\"")));
4910 
4911  /* if the new value isn't an SQL NULL just call jsonb_set */
4912  if (!PG_ARGISNULL(2))
4913  return jsonb_set(fcinfo);
4914 
4915  handle_null = PG_GETARG_TEXT_P(4);
4916  handle_val = text_to_cstring(handle_null);
4917 
4918  if (strcmp(handle_val, "raise_exception") == 0)
4919  {
4920  ereport(ERROR,
4921  (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
4922  errmsg("JSON value must not be null"),
4923  errdetail("Exception was raised because null_value_treatment is \"raise_exception\"."),
4924  errhint("To avoid, either change the null_value_treatment argument or ensure that an SQL NULL is not passed.")));
4925  return (Datum) 0; /* silence stupider compilers */
4926  }
4927  else if (strcmp(handle_val, "use_json_null") == 0)
4928  {
4929  Datum newval;
4930 
4932 
4933  fcinfo->args[2].value = newval;
4934  fcinfo->args[2].isnull = false;
4935  return jsonb_set(fcinfo);
4936  }
4937  else if (strcmp(handle_val, "delete_key") == 0)
4938  {
4939  return jsonb_delete_path(fcinfo);
4940  }
4941  else if (strcmp(handle_val, "return_target") == 0)
4942  {
4943  Jsonb *in = PG_GETARG_JSONB_P(0);
4944 
4945  PG_RETURN_JSONB_P(in);
4946  }
4947  else
4948  {
4949  ereport(ERROR,
4950  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4951  errmsg("null_value_treatment must be \"delete_key\", \"return_target\", \"use_json_null\", or \"raise_exception\"")));
4952  return (Datum) 0; /* silence stupider compilers */
4953  }
4954 }
int errdetail(const char *fmt,...)
Definition: elog.c:1203
#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:73
Datum jsonb_delete_path(PG_FUNCTION_ARGS)
Definition: jsonfuncs.c:4960
Datum jsonb_set(PG_FUNCTION_ARGS)
Definition: jsonfuncs.c:4844
static Datum CStringGetDatum(const char *X)
Definition: postgres.h:350

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

4526 {
4527  Jsonb *jb = PG_GETARG_JSONB_P(0);
4528  JsonbIterator *it;
4529  JsonbParseState *parseState = NULL;
4530  JsonbValue *res = NULL;
4531  JsonbValue v,
4532  k;
4534  bool last_was_key = false;
4535 
4536  if (JB_ROOT_IS_SCALAR(jb))
4537  PG_RETURN_POINTER(jb);
4538 
4539  it = JsonbIteratorInit(&jb->root);
4540 
4541  while ((type = JsonbIteratorNext(&it, &v, false)) != WJB_DONE)
4542  {
4543  Assert(!(type == WJB_KEY && last_was_key));
4544 
4545  if (type == WJB_KEY)
4546  {
4547  /* stash the key until we know if it has a null value */
4548  k = v;
4549  last_was_key = true;
4550  continue;
4551  }
4552 
4553  if (last_was_key)
4554  {
4555  /* if the last element was a key this one can't be */
4556  last_was_key = false;
4557 
4558  /* skip this field if value is null */
4559  if (type == WJB_VALUE && v.type == jbvNull)
4560  continue;
4561 
4562  /* otherwise, do a delayed push of the key */
4563  (void) pushJsonbValue(&parseState, WJB_KEY, &k);
4564  }
4565 
4566  if (type == WJB_VALUE || type == WJB_ELEM)
4567  res = pushJsonbValue(&parseState, type, &v);
4568  else
4569  res = pushJsonbValue(&parseState, type, NULL);
4570  }
4571 
4572  Assert(res != NULL);
4573 
4575 }
#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, 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 2486 of file jsonfuncs.c.

2487 {
2488  return populate_record_worker(fcinfo, "jsonb_to_record",
2489  false, false, NULL);
2490 }

References populate_record_worker().

◆ jsonb_to_recordset()

Datum jsonb_to_recordset ( PG_FUNCTION_ARGS  )

Definition at line 3979 of file jsonfuncs.c.

3980 {
3981  return populate_recordset_worker(fcinfo, "jsonb_to_recordset",
3982  false, false);
3983 }

References populate_recordset_worker().

◆ JsonbValueAsText()

static text * JsonbValueAsText ( JsonbValue v)
static

Definition at line 1803 of file jsonfuncs.c.

1804 {
1805  switch (v->type)
1806  {
1807  case jbvNull:
1808  return NULL;
1809 
1810  case jbvBool:
1811  return v->val.boolean ?
1812  cstring_to_text_with_len("true", 4) :
1813  cstring_to_text_with_len("false", 5);
1814 
1815  case jbvString:
1816  return cstring_to_text_with_len(v->val.string.val,
1817  v->val.string.len);
1818 
1819  case jbvNumeric:
1820  {
1821  Datum cstr;
1822 
1824  PointerGetDatum(v->val.numeric));
1825 
1826  return cstring_to_text(DatumGetCString(cstr));
1827  }
1828 
1829  case jbvBinary:
1830  {
1831  StringInfoData jtext;
1832 
1833  initStringInfo(&jtext);
1834  (void) JsonbToCString(&jtext, v->val.binary.data,
1835  v->val.binary.len);
1836 
1837  return cstring_to_text_with_len(jtext.data, jtext.len);
1838  }
1839 
1840  default:
1841  elog(ERROR, "unrecognized jsonb type: %d", (int) v->type);
1842  return NULL;
1843  }
1844 }
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 bool JsValueToJsObject ( JsValue jsv,
JsObject jso,
Node escontext 
)
static

Definition at line 2980 of file jsonfuncs.c.

2981 {
2982  jso->is_json = jsv->is_json;
2983 
2984  if (jsv->is_json)
2985  {
2986  /* convert plain-text json into a hash table */
2987  jso->val.json_hash =
2988  get_json_object_as_hash(jsv->val.json.str,
2989  jsv->val.json.len >= 0
2990  ? jsv->val.json.len
2991  : strlen(jsv->val.json.str),
2992  "populate_composite",
2993  escontext);
2994  Assert(jso->val.json_hash != NULL || SOFT_ERROR_OCCURRED(escontext));
2995  }
2996  else
2997  {
2998  JsonbValue *jbv = jsv->val.jsonb;
2999 
3000  if (jbv->type == jbvBinary &&
3001  JsonContainerIsObject(jbv->val.binary.data))
3002  {
3003  jso->val.jsonb_cont = jbv->val.binary.data;
3004  }
3005  else
3006  {
3007  bool is_scalar;
3008 
3009  is_scalar = IsAJsonbScalar(jbv) ||
3010  (jbv->type == jbvBinary &&
3011  JsonContainerIsScalar(jbv->val.binary.data));
3012  errsave(escontext,
3013  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3014  is_scalar
3015  ? errmsg("cannot call %s on a scalar",
3016  "populate_composite")
3017  : errmsg("cannot call %s on an array",
3018  "populate_composite")));
3019  }
3020  }
3021 
3022  return !SOFT_ERROR_OCCURRED(escontext);
3023 }
static HTAB * get_json_object_as_hash(const char *json, int len, const char *funcname, Node *escontext)
Definition: jsonfuncs.c:3809

References Assert, errcode(), errmsg(), errsave, 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, SOFT_ERROR_OCCURRED, JsonbValue::type, JsValue::val, JsObject::val, and JsonbValue::val.

Referenced by populate_composite().

◆ makeJsonLexContext()

JsonLexContext* makeJsonLexContext ( JsonLexContext lex,
text json,
bool  need_escapes 
)

Definition at line 538 of file jsonfuncs.c.

539 {
540  /*
541  * Most callers pass a detoasted datum, but it's not clear that they all
542  * do. pg_detoast_datum_packed() is cheap insurance.
543  */
544  json = pg_detoast_datum_packed(json);
545 
546  return makeJsonLexContextCstringLen(lex,
547  VARDATA_ANY(json),
548  VARSIZE_ANY_EXHDR(json),
550  need_escapes);
551 }
struct varlena * pg_detoast_datum_packed(struct varlena *datum)
Definition: fmgr.c:1864

References GetDatabaseEncoding(), makeJsonLexContextCstringLen(), pg_detoast_datum_packed(), VARDATA_ANY, and VARSIZE_ANY_EXHDR.

Referenced by datum_to_jsonb_internal(), each_worker(), elements_worker(), get_worker(), iterate_json_values(), json_array_length(), json_get_first_token(), json_in(), json_object_keys(), json_strip_nulls(), json_typeof(), json_validate(), populate_recordset_worker(), and transform_json_string_values().

◆ okeys_array_start()

static JsonParseErrorType okeys_array_start ( void *  state)
static

Definition at line 807 of file jsonfuncs.c.

808 {
809  OkeysState *_state = (OkeysState *) state;
810 
811  /* top level must be a json object */
812  if (_state->lex->lex_level == 0)
813  ereport(ERROR,
814  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
815  errmsg("cannot call %s on an array",
816  "json_object_keys")));
817 
818  return JSON_SUCCESS;
819 }
JsonLexContext * lex
Definition: jsonfuncs.c:56

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

Referenced by json_object_keys().

◆ okeys_object_field_start()

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

Definition at line 784 of file jsonfuncs.c.

785 {
786  OkeysState *_state = (OkeysState *) state;
787 
788  /* only collecting keys for the top level object */
789  if (_state->lex->lex_level != 1)
790  return JSON_SUCCESS;
791 
792  /* enlarge result array if necessary */
793  if (_state->result_count >= _state->result_size)
794  {
795  _state->result_size *= 2;
796  _state->result = (char **)
797  repalloc(_state->result, sizeof(char *) * _state->result_size);
798  }
799 
800  /* save a copy of the field name */
801  _state->result[_state->result_count++] = pstrdup(fname);
802 
803  return JSON_SUCCESS;
804 }
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1541
int result_size
Definition: jsonfuncs.c:58
char ** result
Definition: jsonfuncs.c:57
int result_count
Definition: jsonfuncs.c:59

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

Referenced by json_object_keys().

◆ okeys_scalar()

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

Definition at line 822 of file jsonfuncs.c.

823 {
824  OkeysState *_state = (OkeysState *) state;
825 
826  /* top level must be a json object */
827  if (_state->lex->lex_level == 0)
828  ereport(ERROR,
829  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
830  errmsg("cannot call %s on a scalar",
831  "json_object_keys")));
832 
833  return JSON_SUCCESS;
834 }

References ereport, errcode(), errmsg(), ERROR, JSON_SUCCESS, 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 5572 of file jsonfuncs.c.

5573 {
5574  JsonbIterator *it;
5575  JsonbValue v;
5577  uint32 flags = 0;
5578 
5579  it = JsonbIteratorInit(&jb->root);
5580 
5581  type = JsonbIteratorNext(&it, &v, false);
5582 
5583  /*
5584  * We iterate over array (scalar internally is represented as array, so,
5585  * we will accept it too) to check all its elements. Flag names are
5586  * chosen the same as jsonb_typeof uses.
5587  */
5588  if (type != WJB_BEGIN_ARRAY)
5589  ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
5590  errmsg("wrong flag type, only arrays and scalars are allowed")));
5591 
5592  while ((type = JsonbIteratorNext(&it, &v, false)) == WJB_ELEM)
5593  {
5594  if (v.type != jbvString)
5595  ereport(ERROR,
5596  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
5597  errmsg("flag array element is not a string"),
5598  errhint("Possible values are: \"string\", \"numeric\", \"boolean\", \"key\", and \"all\".")));
5599 
5600  if (v.val.string.len == 3 &&
5601  pg_strncasecmp(v.val.string.val, "all", 3) == 0)
5602  flags |= jtiAll;
5603  else if (v.val.string.len == 3 &&
5604  pg_strncasecmp(v.val.string.val, "key", 3) == 0)
5605  flags |= jtiKey;
5606  else if (v.val.string.len == 6 &&
5607  pg_strncasecmp(v.val.string.val, "string", 6) == 0)
5608  flags |= jtiString;
5609  else if (v.val.string.len == 7 &&
5610  pg_strncasecmp(v.val.string.val, "numeric", 7) == 0)
5611  flags |= jtiNumeric;
5612  else if (v.val.string.len == 7 &&
5613  pg_strncasecmp(v.val.string.val, "boolean", 7) == 0)
5614  flags |= jtiBool;
5615  else
5616  ereport(ERROR,
5617  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
5618  errmsg("wrong flag in flag array: \"%s\"",
5619  pnstrdup(v.val.string.val, v.val.string.len)),
5620  errhint("Possible values are: \"string\", \"numeric\", \"boolean\", \"key\", and \"all\".")));
5621  }
5622 
5623  /* expect end of array now */
5624  if (type != WJB_END_ARRAY)
5625  elog(ERROR, "unexpected end of flag array");
5626 
5627  /* get final WJB_DONE and free iterator */
5628  type = JsonbIteratorNext(&it, &v, false);
5629  if (type != WJB_DONE)
5630  elog(ERROR, "unexpected end of flag array");
5631 
5632  return flags;
5633 }
@ jtiAll
Definition: jsonfuncs.h:31
char * pnstrdup(const char *in, Size len)
Definition: mcxt.c:1707
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, 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_errsave()

bool pg_parse_json_or_errsave ( JsonLexContext lex,
JsonSemAction sem,
Node escontext 
)

Definition at line 517 of file jsonfuncs.c.

519 {
520  JsonParseErrorType result;
521 
522  result = pg_parse_json(lex, sem);
523  if (result != JSON_SUCCESS)
524  {
525  json_errsave_error(result, lex, escontext);
526  return false;
527  }
528  return true;
529 }
JsonParseErrorType pg_parse_json(JsonLexContext *lex, JsonSemAction *sem)
Definition: jsonapi.c:521

References json_errsave_error(), JSON_SUCCESS, pg_parse_json(), and sem.

Referenced by get_json_object_as_hash(), json_in(), jsonb_from_cstring(), and populate_array_json().

◆ populate_array()

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

Definition at line 2913 of file jsonfuncs.c.

2919 {
2921  Datum result;
2922  int *lbs;
2923  int i;
2924 
2925  ctx.aio = aio;
2926  ctx.mcxt = mcxt;
2927  ctx.acxt = CurrentMemoryContext;
2928  ctx.astate = initArrayResult(aio->element_type, ctx.acxt, true);
2929  ctx.colname = colname;
2930  ctx.ndims = 0; /* unknown yet */
2931  ctx.dims = NULL;
2932  ctx.sizes = NULL;
2933  ctx.escontext = escontext;
2934 
2935  if (jsv->is_json)
2936  {
2937  /* Return null if an error was found. */
2938  if (!populate_array_json(&ctx, jsv->val.json.str,
2939  jsv->val.json.len >= 0 ? jsv->val.json.len
2940  : strlen(jsv->val.json.str)))
2941  {
2942  *isnull = true;
2943  return (Datum) 0;
2944  }
2945  }
2946  else
2947  {
2948  /* Return null if an error was found. */
2949  if (!populate_array_dim_jsonb(&ctx, jsv->val.jsonb, 1))
2950  {
2951  *isnull = true;
2952  return (Datum) 0;
2953  }
2954  ctx.dims[0] = ctx.sizes[0];
2955  }
2956 
2957  Assert(ctx.ndims > 0);
2958 
2959  lbs = palloc(sizeof(int) * ctx.ndims);
2960 
2961  for (i = 0; i < ctx.ndims; i++)
2962  lbs[i] = 1;
2963 
2964  result = makeMdArrayResult(ctx.astate, ctx.ndims, ctx.dims, lbs,
2965  ctx.acxt, true);
2966 
2967  pfree(ctx.dims);
2968  pfree(ctx.sizes);
2969  pfree(lbs);
2970 
2971  *isnull = false;
2972  return result;
2973 }
ArrayBuildState * initArrayResult(Oid element_type, MemoryContext rcontext, bool subcontext)
Definition: arrayfuncs.c:5281
Datum makeMdArrayResult(ArrayBuildState *astate, int ndims, int *dims, int *lbs, MemoryContext rcontext, bool release)
Definition: arrayfuncs.c:5440
static bool populate_array_json(PopulateArrayContext *ctx, const char *json, int len)
Definition: jsonfuncs.c:2787
static bool populate_array_dim_jsonb(PopulateArrayContext *ctx, JsonbValue *jbv, int ndim)
Definition: jsonfuncs.c:2823
Oid element_type
Definition: jsonfuncs.c:168
ArrayBuildState * astate
Definition: jsonfuncs.c:260
MemoryContext mcxt
Definition: jsonfuncs.c:263
ArrayIOData * aio
Definition: jsonfuncs.c:261
MemoryContext acxt
Definition: jsonfuncs.c:262
const char * colname
Definition: jsonfuncs.c:264

References PopulateArrayContext::acxt, PopulateArrayContext::aio, Assert, PopulateArrayContext::astate, PopulateArrayContext::colname, CurrentMemoryContext, PopulateArrayContext::dims, ArrayIOData::element_type, PopulateArrayContext::escontext, 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 JsonParseErrorType populate_array_array_end ( void *  _state)
static

Definition at line 2666 of file jsonfuncs.c.

2667 {
2669  PopulateArrayContext *ctx = state->ctx;
2670  int ndim = state->lex->lex_level;
2671 
2672  if (ctx->ndims <= 0)
2673  {
2674  if (!populate_array_assign_ndims(ctx, ndim + 1))
2675  return JSON_SEM_ACTION_FAILED;
2676  }
2677 
2678  if (ndim < ctx->ndims)
2679  {
2680  /* Report if an error occurred. */
2681  if (!populate_array_check_dimension(ctx, ndim))
2682  return JSON_SEM_ACTION_FAILED;
2683  }
2684 
2685  return JSON_SUCCESS;
2686 }
static bool populate_array_check_dimension(PopulateArrayContext *ctx, int ndim)
Definition: jsonfuncs.c:2588
static bool populate_array_assign_ndims(PopulateArrayContext *ctx, int ndims)
Definition: jsonfuncs.c:2558

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

Referenced by populate_array_json().

◆ populate_array_assign_ndims()

static bool populate_array_assign_ndims ( PopulateArrayContext ctx,
int  ndims 
)
static

Definition at line 2558 of file jsonfuncs.c.

2559 {
2560  int i;
2561 
2562  Assert(ctx->ndims <= 0);
2563 
2564  if (ndims <= 0)
2565  {
2567  /* Getting here means the error was reported softly. */
2569  return false;
2570  }
2571 
2572  ctx->ndims = ndims;
2573  ctx->dims = palloc(sizeof(int) * ndims);
2574  ctx->sizes = palloc0(sizeof(int) * ndims);
2575 
2576  for (i = 0; i < ndims; i++)
2577  ctx->dims[i] = -1; /* dimensions are unknown yet */
2578 
2579  return true;
2580 }
static void populate_array_report_expected_array(PopulateArrayContext *ctx, int ndim)
Definition: jsonfuncs.c:2508

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

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

◆ populate_array_check_dimension()

static bool populate_array_check_dimension ( PopulateArrayContext ctx,
int  ndim 
)
static

Definition at line 2588 of file jsonfuncs.c.

2589 {
2590  int dim = ctx->sizes[ndim]; /* current dimension counter */
2591 
2592  if (ctx->dims[ndim] == -1)
2593  ctx->dims[ndim] = dim; /* assign dimension if not yet known */
2594  else if (ctx->dims[ndim] != dim)
2595  ereturn(ctx->escontext, false,
2596  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2597  errmsg("malformed JSON array"),
2598  errdetail("Multidimensional arrays must have "
2599  "sub-arrays with matching dimensions.")));
2600 
2601  /* reset the current array dimension size counter */
2602  ctx->sizes[ndim] = 0;
2603 
2604  /* increment the parent dimension counter if it is a nested sub-array */
2605  if (ndim > 0)
2606  ctx->sizes[ndim - 1]++;
2607 
2608  return true;
2609 }
#define ereturn(context, dummy_value,...)
Definition: elog.h:276

References PopulateArrayContext::dims, ereturn, errcode(), errdetail(), errmsg(), PopulateArrayContext::escontext, and PopulateArrayContext::sizes.

Referenced by populate_array_array_end(), and populate_array_dim_jsonb().

◆ populate_array_dim_jsonb()

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

Definition at line 2823 of file jsonfuncs.c.

2826 {
2827  JsonbContainer *jbc = jbv->val.binary.data;
2828  JsonbIterator *it;
2829  JsonbIteratorToken tok;
2830  JsonbValue val;
2831  JsValue jsv;
2832 
2834 
2835  /* Even scalars can end up here thanks to ExecEvalJsonCoercion(). */
2836  if (jbv->type != jbvBinary || !JsonContainerIsArray(jbc) ||
2837  JsonContainerIsScalar(jbc))
2838  {
2839  populate_array_report_expected_array(ctx, ndim - 1);
2840  /* Getting here means the error was reported softly. */
2842  return false;
2843  }
2844 
2845  it = JsonbIteratorInit(jbc);
2846 
2847  tok = JsonbIteratorNext(&it, &val, true);
2848  Assert(tok == WJB_BEGIN_ARRAY);
2849 
2850  tok = JsonbIteratorNext(&it, &val, true);
2851 
2852  /*
2853  * If the number of dimensions is not yet known and we have found end of
2854  * the array, or the first child element is not an array, then assign the
2855  * number of dimensions now.
2856  */
2857  if (ctx->ndims <= 0 &&
2858  (tok == WJB_END_ARRAY ||
2859  (tok == WJB_ELEM &&
2860  (val.type != jbvBinary ||
2861  !JsonContainerIsArray(val.val.binary.data)))))
2862  {
2863  if (!populate_array_assign_ndims(ctx, ndim))
2864  return false;
2865  }
2866 
2867  jsv.is_json = false;
2868  jsv.val.jsonb = &val;
2869 
2870  /* process all the array elements */
2871  while (tok == WJB_ELEM)
2872  {
2873  /*
2874  * Recurse only if the dimensions of dimensions is still unknown or if
2875  * it is not the innermost dimension.
2876  */
2877  if (ctx->ndims > 0 && ndim >= ctx->ndims)
2878  {
2879  if (!populate_array_element(ctx, ndim, &jsv))
2880  return false;
2881  }
2882  else
2883  {
2884  /* populate child sub-array */
2885  if (!populate_array_dim_jsonb(ctx, &val, ndim + 1))
2886  return false;
2887 
2888  /* number of dimensions should be already known */
2889  Assert(ctx->ndims > 0 && ctx->dims);
2890 
2891  if (!populate_array_check_dimension(ctx, ndim))
2892  return false;
2893  }
2894 
2895  tok = JsonbIteratorNext(&it, &val, true);
2896  }
2897 
2898  Assert(tok == WJB_END_ARRAY);
2899 
2900  /* free iterator, iterating until WJB_DONE */
2901  tok = JsonbIteratorNext(&it, &val, true);
2902  Assert(tok == WJB_DONE && !it);
2903 
2904  return true;
2905 }
static bool populate_array_element(PopulateArrayContext *ctx, int ndim, JsValue *jsv)
Definition: jsonfuncs.c:2616
void check_stack_depth(void)
Definition: postgres.c:3530

References Assert, check_stack_depth(), PopulateArrayContext::dims, PopulateArrayContext::escontext, 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(), SOFT_ERROR_OCCURRED, 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 bool populate_array_element ( PopulateArrayContext ctx,
int  ndim,
JsValue jsv 
)
static

Definition at line 2616 of file jsonfuncs.c.

2617 {
2618  Datum element;
2619  bool element_isnull;
2620 
2621  /* populate the array element */
2623  ctx->aio->element_type,
2624  ctx->aio->element_typmod,
2625  NULL, ctx->mcxt, PointerGetDatum(NULL),
2626  jsv, &element_isnull, ctx->escontext,
2627  false);
2628  /* Nothing to do on an error. */
2629  if (SOFT_ERROR_OCCURRED(ctx->escontext))
2630  return false;
2631 
2632  accumArrayResult(ctx->astate, element, element_isnull,
2633  ctx->aio->element_type, ctx->acxt);
2634 
2635  Assert(ndim > 0);
2636  ctx->sizes[ndim - 1]++; /* increment current dimension counter */
2637 
2638  return true;
2639 }
ArrayBuildState * accumArrayResult(ArrayBuildState *astate, Datum dvalue, bool disnull, Oid element_type, MemoryContext rcontext)
Definition: arrayfuncs.c:5338
int32 element_typmod
Definition: jsonfuncs.c:169
ColumnIOData * element_info
Definition: jsonfuncs.c:167

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

Referenced by populate_array_dim_jsonb(), and populate_array_element_end().

◆ populate_array_element_end()

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

Definition at line 2708 of file jsonfuncs.c.

2709 {
2711  PopulateArrayContext *ctx = state->ctx;
2712  int ndim = state->lex->lex_level;
2713 
2714  Assert(ctx->ndims > 0);
2715 
2716  if (ndim == ctx->ndims)
2717  {
2718  JsValue jsv;
2719 
2720  jsv.is_json = true;
2721  jsv.val.json.type = state->element_type;
2722 
2723  if (isnull)
2724  {
2725  Assert(jsv.val.json.type == JSON_TOKEN_NULL);
2726  jsv.val.json.str = NULL;
2727  jsv.val.json.len = 0;
2728  }
2729  else if (state->element_scalar)
2730  {
2731  jsv.val.json.str = state->element_scalar;
2732  jsv.val.json.len = -1; /* null-terminated */
2733  }
2734  else
2735  {
2736  jsv.val.json.str = state->element_start;
2737  jsv.val.json.len = (state->lex->prev_token_terminator -
2738  state->element_start) * sizeof(char);
2739  }
2740 
2741  /* Report if an error occurred. */
2742  if (!populate_array_element(ctx, ndim, &jsv))
2743  return JSON_SEM_ACTION_FAILED;
2744  }
2745 
2746  return JSON_SUCCESS;
2747 }

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

Referenced by populate_array_json().

◆ populate_array_element_start()

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

Definition at line 2690 of file jsonfuncs.c.

2691 {
2693  int ndim = state->lex->lex_level;
2694 
2695  if (state->ctx->ndims <= 0 || ndim == state->ctx->ndims)
2696  {
2697  /* remember current array element start */
2698  state->element_start = state->lex->token_start;
2699  state->element_type = state->lex->token_type;
2700  state->element_scalar = NULL;
2701  }
2702 
2703  return JSON_SUCCESS;
2704 }

References JSON_SUCCESS.

Referenced by populate_array_json().

◆ populate_array_json()

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

Definition at line 2787 of file jsonfuncs.c.

2788 {
2791 
2792  state.lex = makeJsonLexContextCstringLen(NULL, json, len,
2793  GetDatabaseEncoding(), true);
2794  state.ctx = ctx;
2795 
2796  memset(&sem, 0, sizeof(sem));
2797  sem.semstate = (void *) &state;
2803 
2804  if (pg_parse_json_or_errsave(state.lex, &sem, ctx->escontext))
2805  {
2806  /* number of dimensions should be already known */
2807  Assert(ctx->ndims > 0 && ctx->dims);
2808  }
2809 
2811 
2812  return !SOFT_ERROR_OCCURRED(ctx->escontext);
2813 }
static JsonParseErrorType populate_array_scalar(void *_state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:2751
static JsonParseErrorType populate_array_object_start(void *_state)
Definition: jsonfuncs.c:2643
static JsonParseErrorType populate_array_element_end(void *_state, bool isnull)
Definition: jsonfuncs.c:2708
static JsonParseErrorType populate_array_element_start(void *_state, bool isnull)
Definition: jsonfuncs.c:2690
static JsonParseErrorType populate_array_array_end(void *_state)
Definition: jsonfuncs.c:2666

References JsonSemAction::array_element_end, JsonSemAction::array_element_start, JsonSemAction::array_end, Assert, PopulateArrayContext::dims, PopulateArrayContext::escontext, freeJsonLexContext(), GetDatabaseEncoding(), len, makeJsonLexContextCstringLen(), PopulateArrayContext::ndims, JsonSemAction::object_start, pg_parse_json_or_errsave(), populate_array_array_end(), populate_array_element_end(), populate_array_element_start(), populate_array_object_start(), populate_array_scalar(), JsonSemAction::scalar, sem, JsonSemAction::semstate, and SOFT_ERROR_OCCURRED.

Referenced by populate_array().

◆ populate_array_object_start()

static JsonParseErrorType populate_array_object_start ( void *  _state)
static

Definition at line 2643 of file jsonfuncs.c.

2644 {
2646  int ndim = state->lex->lex_level;
2647 
2648  if (state->ctx->ndims <= 0)
2649  {
2650  if (!populate_array_assign_ndims(state->ctx, ndim))
2651  return JSON_SEM_ACTION_FAILED;
2652  }
2653  else if (ndim < state->ctx->ndims)
2654  {
2656  /* Getting here means the error was reported softly. */
2657  Assert(SOFT_ERROR_OCCURRED(state->ctx->escontext));
2658  return JSON_SEM_ACTION_FAILED;
2659  }
2660 
2661  return JSON_SUCCESS;
2662 }

References Assert, JSON_SEM_ACTION_FAILED, JSON_SUCCESS, populate_array_assign_ndims(), populate_array_report_expected_array(), and SOFT_ERROR_OCCURRED.

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

2509 {
2510  if (ndim <= 0)
2511  {
2512  if (ctx->colname)
2513  errsave(ctx->escontext,
2514  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2515  errmsg("expected JSON array"),
2516  errhint("See the value of key \"%s\".", ctx->colname)));
2517  else
2518  errsave(ctx->escontext,
2519  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2520  errmsg("expected JSON array")));
2521  return;
2522  }
2523  else
2524  {
2525  StringInfoData indices;
2526  int i;
2527 
2528  initStringInfo(&indices);
2529 
2530  Assert(ctx->ndims > 0 && ndim < ctx->ndims);
2531 
2532  for (i = 0; i < ndim; i++)
2533  appendStringInfo(&indices, "[%d]", ctx->sizes[i]);
2534 
2535  if (ctx->colname)
2536  errsave(ctx->escontext,
2537  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2538  errmsg("expected JSON array"),
2539  errhint("See the array element %s of key \"%s\".",
2540  indices.data, ctx->colname)));
2541  else
2542  errsave(ctx->escontext,
2543  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2544  errmsg("expected JSON array"),
2545  errhint("See the array element %s.",
2546  indices.data)));
2547  return;
2548  }
2549 }
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:97

References appendStringInfo(), Assert, PopulateArrayContext::colname, StringInfoData::data, errcode(), errhint(), errmsg(), errsave, PopulateArrayContext::escontext, 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 JsonParseErrorType populate_array_scalar ( void *  _state,
char *  token,
JsonTokenType  tokentype 
)
static

Definition at line 2751 of file jsonfuncs.c.

2752 {
2754  PopulateArrayContext *ctx = state->ctx;
2755  int ndim = state->lex->lex_level;
2756 
2757  if (ctx->ndims <= 0)
2758  {
2759  if (!populate_array_assign_ndims(ctx, ndim))
2760  return JSON_SEM_ACTION_FAILED;
2761  }
2762  else if (ndim < ctx->ndims)
2763  {
2765  /* Getting here means the error was reported softly. */
2767  return JSON_SEM_ACTION_FAILED;
2768  }
2769 
2770  if (ndim == ctx->ndims)
2771  {
2772  /* remember the scalar element token */
2773  state->element_scalar = token;
2774  /* element_type must already be set in populate_array_element_start() */
2775  Assert(state->element_type == tokentype);
2776  }
2777 
2778  return JSON_SUCCESS;
2779 }

References Assert, PopulateArrayContext::escontext, JSON_SEM_ACTION_FAILED, JSON_SUCCESS, PopulateArrayContext::ndims, populate_array_assign_ndims(), populate_array_report_expected_array(), SOFT_ERROR_OCCURRED, and token.

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,
Node escontext 
)
static

Definition at line 3056 of file jsonfuncs.c.

3064 {
3065  Datum result;
3066 
3067  /* acquire/update cached tuple descriptor */
3068  update_cached_tupdesc(io, mcxt);
3069 
3070  if (*isnull)
3071  result = (Datum) 0;
3072  else
3073  {
3074  HeapTupleHeader tuple;
3075  JsObject jso;
3076 
3077  /* prepare input value */
3078  if (!JsValueToJsObject(jsv, &jso, escontext))
3079  {
3080  *isnull = true;
3081  return (Datum) 0;
3082  }
3083 
3084  /* populate resulting record tuple */
3085  tuple = populate_record(io->tupdesc, &io->record_io,
3086  defaultval, mcxt, &jso, escontext);
3087 
3088  if (SOFT_ERROR_OCCURRED(escontext))
3089  {
3090  *isnull = true;
3091  return (Datum) 0;
3092  }
3093  result = HeapTupleHeaderGetDatum(tuple);
3094 
3095  JsObjectFree(&jso);
3096  }
3097 
3098  /*
3099  * If it's domain over composite, check domain constraints. (This should
3100  * probably get refactored so that we can see the TYPECAT value, but for
3101  * now, we can tell by comparing typid to base_typid.)
3102  */
3103  if (typid != io->base_typid && typid != RECORDOID)
3104  {
3105  if (!domain_check_safe(result, *isnull, typid, &io->domain_info, mcxt,
3106  escontext))
3107  {
3108  *isnull = true;
3109  return (Datum) 0;
3110  }
3111  }
3112 
3113  return result;
3114 }
bool domain_check_safe(Datum value, bool isnull, Oid domainType, void **extra, MemoryContext mcxt, Node *escontext)
Definition: domains.c:355
Datum HeapTupleHeaderGetDatum(HeapTupleHeader tuple)
Definition: execTuples.c:2311
static void update_cached_tupdesc(CompositeIOData *io, MemoryContext mcxt)
Definition: jsonfuncs.c:3027
static bool JsValueToJsObject(JsValue *jsv, JsObject *jso, Node *escontext)
Definition: jsonfuncs.c:2980
static HeapTupleHeader populate_record(TupleDesc tupdesc, RecordIOData **record_p, HeapTupleHeader defaultval, MemoryContext mcxt, JsObject *obj, Node *escontext)
Definition: jsonfuncs.c:3518
#define JsObjectFree(jso)
Definition: jsonfuncs.c:333
RecordIOData * record_io
Definition: jsonfuncs.c:179
void * domain_info
Definition: jsonfuncs.c:185

References CompositeIOData::base_typid, domain_check_safe(), CompositeIOData::domain_info, HeapTupleHeaderGetDatum(), JsObjectFree, JsValueToJsObject(), populate_record(), CompositeIOData::record_io, SOFT_ERROR_OCCURRED, CompositeIOData::tupdesc, and update_cached_tupdesc().

Referenced by populate_record_field(), and populate_record_worker().

◆ populate_domain()

static Datum populate_domain ( DomainIOData io,
Oid  typid,
const char *  colname,
MemoryContext  mcxt,
JsValue jsv,
bool isnull,
Node escontext,
bool  omit_quotes 
)
static

Definition at line 3215 of file jsonfuncs.c.

3223 {
3224  Datum res;
3225 
3226  if (*isnull)
3227  res = (Datum) 0;
3228  else
3229  {
3231  io->base_typid, io->base_typmod,
3232  colname, mcxt, PointerGetDatum(NULL),
3233  jsv, isnull, escontext, omit_quotes);
3234  Assert(!*isnull || SOFT_ERROR_OCCURRED(escontext));
3235  }
3236 
3237  if (!domain_check_safe(res, *isnull, typid, &io->domain_info, mcxt,
3238  escontext))
3239  {
3240  *isnull = true;
3241  return (Datum) 0;
3242  }
3243 
3244  return res;
3245 }
void * domain_info
Definition: jsonfuncs.c:194
int32 base_typmod
Definition: jsonfuncs.c:193
Oid base_typid
Definition: jsonfuncs.c:192
ColumnIOData * base_io
Definition: jsonfuncs.c:191

References Assert, DomainIOData::base_io, DomainIOData::base_typid, DomainIOData::base_typmod, domain_check_safe(), DomainIOData::domain_info, PointerGetDatum(), populate_record_field(), res, and SOFT_ERROR_OCCURRED.

Referenced by populate_record_field().

◆ populate_record()

static HeapTupleHeader populate_record ( TupleDesc  tupdesc,
RecordIOData **  record_p,
HeapTupleHeader  defaultval,
MemoryContext  mcxt,
JsObject obj,
Node escontext 
)
static

Definition at line 3518 of file jsonfuncs.c.

3524 {
3525  RecordIOData *record = *record_p;
3526  Datum *values;
3527  bool *nulls;
3528  HeapTuple res;
3529  int ncolumns = tupdesc->natts;
3530  int i;
3531 
3532  /*
3533  * if the input json is empty, we can only skip the rest if we were passed
3534  * in a non-null record, since otherwise there may be issues with domain
3535  * nulls.
3536  */
3537  if (defaultval && JsObjectIsEmpty(obj))
3538  return defaultval;
3539 
3540  /* (re)allocate metadata cache */
3541  if (record == NULL ||
3542  record->ncolumns != ncolumns)
3543  *record_p = record = allocate_record_info(mcxt, ncolumns);
3544 
3545  /* invalidate metadata cache if the record type has changed */
3546  if (record->record_type != tupdesc->tdtypeid ||
3547  record->record_typmod != tupdesc->tdtypmod)
3548  {
3549  MemSet(record, 0, offsetof(RecordIOData, columns) +
3550  ncolumns * sizeof(ColumnIOData));
3551  record->record_type = tupdesc->tdtypeid;
3552  record->record_typmod = tupdesc->tdtypmod;
3553  record->ncolumns = ncolumns;
3554  }
3555 
3556  values = (Datum *) palloc(ncolumns * sizeof(Datum));
3557  nulls = (bool *) palloc(ncolumns * sizeof(bool));
3558 
3559  if (defaultval)
3560  {
3561  HeapTupleData tuple;
3562 
3563  /* Build a temporary HeapTuple control structure */
3564  tuple.t_len = HeapTupleHeaderGetDatumLength(defaultval);
3565  ItemPointerSetInvalid(&(tuple.t_self));
3566  tuple.t_tableOid = InvalidOid;
3567  tuple.t_data = defaultval;
3568 
3569  /* Break down the tuple into fields */
3570  heap_deform_tuple(&tuple, tupdesc, values, nulls);
3571  }
3572  else
3573  {
3574  for (i = 0; i < ncolumns; ++i)
3575  {
3576  values[i] = (Datum) 0;
3577  nulls[i] = true;
3578  }
3579  }
3580 
3581  for (i = 0; i < ncolumns; ++i)
3582  {
3583  Form_pg_attribute att = TupleDescAttr(tupdesc, i);
3584  char *colname = NameStr(att->attname);
3585  JsValue field = {0};
3586  bool found;
3587 
3588  /* Ignore dropped columns in datatype */
3589  if (att->attisdropped)
3590  {
3591  nulls[i] = true;
3592  continue;
3593  }
3594 
3595  found = JsObjectGetField(obj, colname, &field);
3596 
3597  /*
3598  * we can't just skip here if the key wasn't found since we might have
3599  * a domain to deal with. If we were passed in a non-null record
3600  * datum, we assume that the existing values are valid (if they're
3601  * not, then it's not our fault), but if we were passed in a null,
3602  * then every field which we don't populate needs to be run through
3603  * the input function just in case it's a domain type.
3604  */
3605  if (defaultval && !found)
3606  continue;
3607 
3608  values[i] = populate_record_field(&record->columns[i],
3609  att->atttypid,
3610  att->atttypmod,
3611  colname,
3612  mcxt,
3613  nulls[i] ? (Datum) 0 : values[i],
3614  &field,
3615  &nulls[i],
3616  escontext,
3617  false);
3618  }
3619 
3620  res = heap_form_tuple(tupdesc, values, nulls);
3621 
3622  pfree(values);
3623  pfree(nulls);
3624 
3625  return res->t_data;
3626 }
#define NameStr(name)
Definition: c.h:746
void heap_deform_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *values, bool *isnull)
Definition: heaptuple.c:1345
#define HeapTupleHeaderGetDatumLength(tup)
Definition: htup_details.h:450
static void ItemPointerSetInvalid(ItemPointerData *pointer)
Definition: itemptr.h:184
static RecordIOData * allocate_record_info(MemoryContext mcxt, int ncolumns)
Definition: jsonfuncs.c:3474
#define JsObjectIsEmpty(jso)
Definition: jsonfuncs.c:327
static bool JsObjectGetField(JsObject *obj, char *field, JsValue *jsv)
Definition: jsonfuncs.c:3490
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:209
ItemPointerData t_self
Definition: htup.h:65
uint32 t_len
Definition: htup.h:64
HeapTupleHeader t_data
Definition: htup.h:68
Oid t_tableOid
Definition: htup.h:66
ColumnIOData columns[FLEXIBLE_ARRAY_MEMBER]
Definition: hstore_io.c:826
Oid record_type
Definition: hstore_io.c:821
int32 record_typmod
Definition: hstore_io.c:822
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92

References allocate_record_info(), RecordIOData::columns, heap_deform_tuple(), heap_form_tuple(), HeapTupleHeaderGetDatumLength, i, InvalidOid, ItemPointerSetInvalid(), JsObjectGetField(), JsObjectIsEmpty, MemSet, NameStr, TupleDescData::natts, RecordIOData::ncolumns, palloc(), pfree(), populate_record_field(), RecordIOData::record_type, RecordIOData::record_typmod, res, HeapTupleData::t_data, HeapTupleData::t_len, HeapTupleData::t_self, HeapTupleData::t_tableOid, TupleDescData::tdtypeid, TupleDescData::tdtypmod, TupleDescAttr, and values.

Referenced by populate_composite(), and populate_recordset_record().

◆ populate_record_field()

static Datum populate_record_field ( ColumnIOData col,
Oid  typid,
int32  typmod,
const char *  colname,
MemoryContext  mcxt,
Datum  defaultval,
JsValue jsv,
bool isnull,
Node escontext,
bool  omit_scalar_quotes 
)
static

Definition at line 3404 of file jsonfuncs.c.

3414 {
3415  TypeCat typcat;
3416 
3418 
3419  /*
3420  * Prepare column metadata cache for the given type. Force lookup of the
3421  * scalar_io data so that the json string hack below will work.
3422  */
3423  if (col->typid != typid || col->typmod != typmod)
3424  prepare_column_cache(col, typid, typmod, mcxt, true);
3425 
3426  *isnull = JsValueIsNull(jsv);
3427 
3428  typcat = col->typcat;
3429 
3430  /* try to convert json string to a non-scalar type through input function */
3431  if (JsValueIsString(jsv) &&
3432  (typcat == TYPECAT_ARRAY ||
3433  typcat == TYPECAT_COMPOSITE ||
3434  typcat == TYPECAT_COMPOSITE_DOMAIN))
3435  typcat = TYPECAT_SCALAR;
3436 
3437  /* we must perform domain checks for NULLs, otherwise exit immediately */
3438  if (*isnull &&
3439  typcat != TYPECAT_DOMAIN &&
3440  typcat != TYPECAT_COMPOSITE_DOMAIN)
3441  return (Datum) 0;
3442 
3443  switch (typcat)
3444  {
3445  case TYPECAT_SCALAR:
3446  return populate_scalar(&col->scalar_io, typid, typmod, jsv,
3447  isnull, escontext, omit_scalar_quotes);
3448 
3449  case TYPECAT_ARRAY:
3450  return populate_array(&col->io.array, colname, mcxt, jsv,
3451  isnull, escontext);
3452 
3453  case TYPECAT_COMPOSITE:
3455  return populate_composite(&col->io.composite, typid,
3456  colname, mcxt,
3457  DatumGetPointer(defaultval)
3458  ? DatumGetHeapTupleHeader(defaultval)
3459  : NULL,
3460  jsv, isnull,
3461  escontext);
3462 
3463  case TYPECAT_DOMAIN:
3464  return populate_domain(&col->io.domain, typid, colname, mcxt,
3465  jsv, isnull, escontext, omit_scalar_quotes);
3466 
3467  default:
3468  elog(ERROR, "unrecognized type category '%c'", typcat);
3469  return (Datum) 0;
3470  }
3471 }
#define DatumGetHeapTupleHeader(X)
Definition: fmgr.h:295
#define JsValueIsString(jsv)
Definition: jsonfuncs.c:323
#define JsValueIsNull(jsv)
Definition: jsonfuncs.c:318
static Datum populate_array(ArrayIOData *aio, const char *colname, MemoryContext mcxt, JsValue *jsv, bool *isnull, Node *escontext)
Definition: jsonfuncs.c:2913
static Datum populate_composite(CompositeIOData *io, Oid typid, const char *colname, MemoryContext mcxt, HeapTupleHeader defaultval, JsValue *jsv, bool *isnull, Node *escontext)
Definition: jsonfuncs.c:3056
static Datum populate_scalar(ScalarIOData *io, Oid typid, int32 typmod, JsValue *jsv, bool *isnull, Node *escontext, bool omit_quotes)
Definition: jsonfuncs.c:3123
static Datum populate_domain(DomainIOData *io, Oid typid, const char *colname, MemoryContext mcxt, JsValue *jsv, bool *isnull, Node *escontext, bool omit_quotes)
Definition: jsonfuncs.c:3215
static Pointer DatumGetPointer(Datum X)
Definition: postgres.h:312
int32 typmod
Definition: jsonfuncs.c:213
ScalarIOData scalar_io
Definition: jsonfuncs.c:215
ArrayIOData array
Definition: jsonfuncs.c:219
DomainIOData domain
Definition: jsonfuncs.c:221

References ColumnIOData::array, check_stack_depth(), ColumnIOData::composite, DatumGetHeapTupleHeader, DatumGetPointer(), ColumnIOData::domain, elog, ERROR, ColumnIOData::io, JsValueIsNull, JsValueIsString, populate_array(), populate_composite(), populate_domain(), populate_scalar(), prepare_column_cache(), ColumnIOData::scalar_io, ColumnIOData::typcat, TYPECAT_ARRAY, TYPECAT_COMPOSITE, TYPECAT_COMPOSITE_DOMAIN, TYPECAT_DOMAIN, TYPECAT_SCALAR, ColumnIOData::typid, and ColumnIOData::typmod.

Referenced by json_populate_type(), populate_array_element(), populate_domain(), and populate_record().

◆ populate_record_worker()

static Datum populate_record_worker ( FunctionCallInfo  fcinfo,
const char *  funcname,
bool  is_json,
bool  have_record_arg,
Node escontext 
)
static

Definition at line 3697 of file jsonfuncs.c.

3700 {
3701  int json_arg_num = have_record_arg ? 1 : 0;
3702  JsValue jsv = {0};
3703  HeapTupleHeader rec;
3704  Datum rettuple;
3705  bool isnull;
3706  JsonbValue jbv;
3707  MemoryContext fnmcxt = fcinfo->flinfo->fn_mcxt;
3708  PopulateRecordCache *cache = fcinfo->flinfo->fn_extra;
3709 
3710  /*
3711  * If first time through, identify input/result record type. Note that
3712  * this stanza looks only at fcinfo context, which can't change during the
3713  * query; so we may not be able to fully resolve a RECORD input type yet.
3714  */
3715  if (!cache)
3716  {
3717  fcinfo->flinfo->fn_extra = cache =
3718  MemoryContextAllocZero(fnmcxt, sizeof(*cache));
3719  cache->fn_mcxt = fnmcxt;
3720 
3721  if (have_record_arg)
3722  get_record_type_from_argument(fcinfo, funcname, cache);
3723  else
3724  get_record_type_from_query(fcinfo, funcname, cache);
3725  }
3726 
3727  /* Collect record arg if we have one */
3728  if (!have_record_arg)
3729  rec = NULL; /* it's json{b}_to_record() */
3730  else if (!PG_ARGISNULL(0))
3731  {
3732  rec = PG_GETARG_HEAPTUPLEHEADER(0);
3733 
3734  /*
3735  * When declared arg type is RECORD, identify actual record type from
3736  * the tuple itself.
3737  */
3738  if (cache->argtype == RECORDOID)
3739  {
3742  }
3743  }
3744  else
3745  {
3746  rec = NULL;
3747 
3748  /*
3749  * When declared arg type is RECORD, identify actual record type from
3750  * calling query, or fail if we can't.
3751  */
3752  if (cache->argtype == RECORDOID)
3753  {
3754  get_record_type_from_query(fcinfo, funcname, cache);
3755  /* This can't change argtype, which is important for next time */
3756  Assert(cache->argtype == RECORDOID);
3757  }
3758  }
3759 
3760  /* If no JSON argument, just return the record (if any) unchanged */
3761  if (PG_ARGISNULL(json_arg_num))
3762  {
3763  if (rec)
3764  PG_RETURN_POINTER(rec);
3765  else
3766  PG_RETURN_NULL();
3767  }
3768 
3769  jsv.is_json = is_json;
3770 
3771  if (is_json)
3772  {
3773  text *json = PG_GETARG_TEXT_PP(json_arg_num);
3774 
3775  jsv.val.json.str = VARDATA_ANY(json);
3776  jsv.val.json.len = VARSIZE_ANY_EXHDR(json);
3777  jsv.val.json.type = JSON_TOKEN_INVALID; /* not used in
3778  * populate_composite() */
3779  }
3780  else
3781  {
3782  Jsonb *jb = PG_GETARG_JSONB_P(json_arg_num);
3783 
3784  jsv.val.jsonb = &jbv;
3785 
3786  /* fill binary jsonb value pointing to jb */
3787  jbv.type = jbvBinary;
3788  jbv.val.binary.data = &jb->root;
3789  jbv.val.binary.len = VARSIZE(jb) - VARHDRSZ;
3790  }
3791 
3792  isnull = false;
3793  rettuple = populate_composite(&cache->c.io.composite, cache->argtype,
3794  NULL, fnmcxt, rec, &jsv, &isnull,
3795  escontext);
3796  Assert(!isnull || SOFT_ERROR_OCCURRED(escontext));
3797 
3798  PG_RETURN_DATUM(rettuple);
3799 }
#define PG_GETARG_HEAPTUPLEHEADER(n)
Definition: fmgr.h:312
#define HeapTupleHeaderGetTypMod(tup)
Definition: htup_details.h:466
#define HeapTupleHeaderGetTypeId(tup)
Definition: htup_details.h:456
static void get_record_type_from_argument(FunctionCallInfo fcinfo, const char *funcname, PopulateRecordCache *cache)
Definition: jsonfuncs.c:3634
static void get_record_type_from_query(FunctionCallInfo fcinfo, const char *funcname, PopulateRecordCache *cache)
Definition: jsonfuncs.c:3660
void * fn_extra
Definition: fmgr.h:64
MemoryContext fn_mcxt
Definition: fmgr.h:65

References PopulateRecordCache::argtype, Assert, CompositeIOData::base_typid, CompositeIOData::base_typmod, PopulateRecordCache::c, ColumnIOData::composite, FunctionCallInfoBaseData::flinfo, FmgrInfo::fn_extra, PopulateRecordCache::fn_mcxt, FmgrInfo::fn_mcxt, funcname, get_record_type_from_argument(), get_record_type_from_query(), HeapTupleHeaderGetTypeId, HeapTupleHeaderGetTypMod, ColumnIOData::io, JsValue::is_json, jbvBinary, JsValue::json, JSON_TOKEN_INVALID, JsValue::jsonb, MemoryContextAllocZero(), PG_ARGISNULL, PG_GETARG_HEAPTUPLEHEADER, PG_GETARG_JSONB_P, PG_GETARG_TEXT_PP, PG_RETURN_DATUM, PG_RETURN_NULL, PG_RETURN_POINTER, populate_composite(), Jsonb::root, SOFT_ERROR_OCCURRED, JsonbValue::type, JsValue::val, JsonbValue::val, VARDATA_ANY, VARHDRSZ, VARSIZE, and VARSIZE_ANY_EXHDR.

Referenced by json_populate_record(), json_to_record(), jsonb_populate_record(), jsonb_populate_record_valid(), and jsonb_to_record().

◆ populate_recordset_array_element_start()

static JsonParseErrorType populate_recordset_array_element_start ( void *  state,
bool  isnull 
)
static

Definition at line 4266 of file jsonfuncs.c.

4267 {
4269 
4270  if (_state->lex->lex_level == 1 &&
4272  ereport(ERROR,
4273  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4274  errmsg("argument of %s must be an array of objects",
4275  _state->function_name)));
4276 
4277  return JSON_SUCCESS;
4278 }
JsonLexContext * lex
Definition: jsonfuncs.c:246
const char * function_name
Definition: jsonfuncs.c:247

References ereport, errcode(), errmsg(), ERROR, PopulateRecordsetState::function_name, JSON_SUCCESS, JSON_TOKEN_OBJECT_START, PopulateRecordsetState::lex, JsonLexContext::lex_level, and JsonLexContext::token_type.

Referenced by populate_recordset_worker().

◆ populate_recordset_array_start()

static JsonParseErrorType populate_recordset_array_start ( void *  state)
static

Definition at line 4281 of file jsonfuncs.c.

4282 {
4283  /* nothing to do */
4284  return JSON_SUCCESS;
4285 }

References JSON_SUCCESS.

Referenced by populate_recordset_worker().

◆ populate_recordset_object_end()

static JsonParseErrorType populate_recordset_object_end ( void *  state)
static

Definition at line 4243 of file jsonfuncs.c.

4244 {
4246  JsObject obj;
4247 
4248  /* Nested objects require no special processing */
4249  if (_state->lex->lex_level > 1)
4250  return JSON_SUCCESS;
4251 
4252  obj.is_json = true;
4253  obj.val.json_hash = _state->json_hash;
4254 
4255  /* Otherwise, construct and return a tuple based on this level-1 object */
4256  populate_recordset_record(_state, &obj);
4257 
4258  /* Done with hash for this object */
4259  hash_destroy(_state->json_hash);
4260  _state->json_hash = NULL;
4261 
4262  return JSON_SUCCESS;
4263 }
static void populate_recordset_record(PopulateRecordsetState *state, JsObject *obj)
Definition: jsonfuncs.c:4000

References hash_destroy(), JsObject::is_json, PopulateRecordsetState::json_hash, JsObject::json_hash, JSON_SUCCESS, PopulateRecordsetState::lex, JsonLexContext::lex_level, populate_recordset_record(), and JsObject::val.

Referenced by populate_recordset_worker().

◆ populate_recordset_object_field_end()

static JsonParseErrorType populate_recordset_object_field_end ( void *  state,
char *  fname,
bool  isnull 
)
static

Definition at line 4328 of file jsonfuncs.c.

4329 {
4331  JsonHashEntry *hashentry;
4332  bool found;
4333 
4334  /*
4335  * Ignore nested fields.
4336  */
4337  if (_state->lex->lex_level > 2)
4338  return JSON_SUCCESS;
4339 
4340  /*
4341  * Ignore field names >= NAMEDATALEN - they can't match a record field.
4342  * (Note: without this test, the hash code would truncate the string at
4343  * NAMEDATALEN-1, and could then match against a similarly-truncated
4344  * record field name. That would be a reasonable behavior, but this code
4345  * has previously insisted on exact equality, so we keep this behavior.)
4346  */
4347  if (strlen(fname) >= NAMEDATALEN)
4348  return JSON_SUCCESS;
4349 
4350  hashentry = hash_search(_state->json_hash, fname, HASH_ENTER, &found);
4351 
4352  /*
4353  * found being true indicates a duplicate. We don't do anything about
4354  * that, a later field with the same name overrides the earlier field.
4355  */
4356 
4357  hashentry->type = _state->saved_token_type;
4358  Assert(isnull == (hashentry->type == JSON_TOKEN_NULL));
4359 
4360  if (_state->save_json_start != NULL)
4361  {
4362  int len = _state->lex->prev_token_terminator - _state->save_json_start;
4363  char *val = palloc((len + 1) * sizeof(char));
4364 
4365  memcpy(val, _state->save_json_start, len);
4366  val[len] = '\0';
4367  hashentry->val = val;
4368  }
4369  else
4370  {
4371  /* must have had a scalar instead */
4372  hashentry->val = _state->saved_scalar;
4373  }
4374 
4375  return JSON_SUCCESS;
4376 }
const char * save_json_start
Definition: jsonfuncs.c:250
JsonTokenType saved_token_type
Definition: jsonfuncs.c:251

References Assert, HASH_ENTER, hash_search(), PopulateRecordsetState::json_hash, JSON_SUCCESS, JSON_TOKEN_NULL, len, PopulateRecordsetState::lex, JsonLexContext::lex_level, NAMEDATALEN, palloc(), JsonLexContext::prev_token_terminator, PopulateRecordsetState::save_json_start, PopulateRecordsetState::saved_scalar, PopulateRecordsetState::saved_token_type, JsonHashEntry::type, JsonHashEntry::val, and val.

Referenced by populate_recordset_worker().

◆ populate_recordset_object_field_start()

static JsonParseErrorType populate_recordset_object_field_start ( void *  state,
char *  fname,
bool  isnull 
)
static

Definition at line 4305 of file jsonfuncs.c.

4306 {
4308 
4309  if (_state->lex->lex_level > 2)
4310  return JSON_SUCCESS;
4311 
4312  _state->saved_token_type = _state->lex->token_type;
4313 
4314  if (_state->lex->token_type == JSON_TOKEN_ARRAY_START ||
4316  {
4317  _state->save_json_start = _state->lex->token_start;
4318  }
4319  else
4320  {
4321  _state->save_json_start = NULL;
4322  }
4323 
4324  return JSON_SUCCESS;
4325 }

References JSON_SUCCESS, JSON_TOKEN_ARRAY_START, JSON_TOKEN_OBJECT_START, PopulateRecordsetState::lex, JsonLexContext::lex_level, PopulateRecordsetState::save_json_start, PopulateRecordsetState::saved_token_type, JsonLexContext::token_start, and JsonLexContext::token_type.

Referenced by populate_recordset_worker().

◆ populate_recordset_object_start()

static JsonParseErrorType populate_recordset_object_start ( void *  state)
static

Definition at line 4213 of file jsonfuncs.c.

4214 {
4216  int lex_level = _state->lex->lex_level;
4217  HASHCTL ctl;
4218 
4219  /* Reject object at top level: we must have an array at level 0 */
4220  if (lex_level == 0)
4221  ereport(ERROR,
4222  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4223  errmsg("cannot call %s on an object",
4224  _state->function_name)));
4225 
4226  /* Nested objects require no special processing */
4227  if (lex_level > 1)
4228  return JSON_SUCCESS;
4229 
4230  /* Object at level 1: set up a new hash table for this object */
4231  ctl.keysize = NAMEDATALEN;
4232  ctl.entrysize = sizeof(JsonHashEntry);
4233  ctl.hcxt = CurrentMemoryContext;
4234  _state->json_hash = hash_create("json object hashtable",
4235  100,
4236  &ctl,
4238 
4239  return JSON_SUCCESS;
4240 }

References ctl, CurrentMemoryContext, ereport, errcode(), errmsg(), ERROR, PopulateRecordsetState::function_name, HASH_CONTEXT, hash_create(), HASH_ELEM, HASH_STRINGS, PopulateRecordsetState::json_hash, JSON_SUCCESS, PopulateRecordsetState::lex, JsonLexContext::lex_level, and NAMEDATALEN.

Referenced by populate_recordset_worker().

◆ populate_recordset_record()

static void populate_recordset_record ( PopulateRecordsetState state,
JsObject obj 
)
static

Definition at line 4000 of file jsonfuncs.c.

4001 {
4002  PopulateRecordCache *cache = state->cache;
4003  HeapTupleHeader tuphead;
4004  HeapTupleData tuple;
4005 
4006  /* acquire/update cached tuple descriptor */
4007  update_cached_tupdesc(&cache->c.io.composite, cache->fn_mcxt);
4008 
4009  /* replace record fields from json */
4010  tuphead = populate_record(cache->c.io.composite.tupdesc,
4011  &cache->c.io.composite.record_io,
4012  state->rec,
4013  cache->fn_mcxt,
4014  obj,
4015  NULL);
4016 
4017  /* if it's domain over composite, check domain constraints */
4018  if (cache->c.typcat == TYPECAT_COMPOSITE_DOMAIN)
4019  (void) domain_check_safe(HeapTupleHeaderGetDatum(tuphead), false,
4020  cache->argtype,
4021  &cache->c.io.composite.domain_info,
4022  cache->fn_mcxt,
4023  NULL);
4024 
4025  /* ok, save into tuplestore */
4026  tuple.t_len = HeapTupleHeaderGetDatumLength(tuphead);
4027  ItemPointerSetInvalid(&(tuple.t_self));
4028  tuple.t_tableOid = InvalidOid;
4029  tuple.t_data = tuphead;
4030 
4031  tuplestore_puttuple(state->tuple_store, &tuple);
4032 }

References PopulateRecordCache::argtype, PopulateRecordCache::c, ColumnIOData::composite, domain_check_safe(), CompositeIOData::domain_info, PopulateRecordCache::fn_mcxt, HeapTupleHeaderGetDatum(), HeapTupleHeaderGetDatumLength, InvalidOid, ColumnIOData::io, ItemPointerSetInvalid(), populate_record(), CompositeIOData::record_io, HeapTupleData::t_data, HeapTupleData::t_len, HeapTupleData::t_self, HeapTupleData::t_tableOid, CompositeIOData::tupdesc, tuplestore_puttuple(), ColumnIOData::typcat, TYPECAT_COMPOSITE_DOMAIN, and update_cached_tupdesc().

Referenced by populate_recordset_object_end(), and populate_recordset_worker().

◆ populate_recordset_scalar()

static JsonParseErrorType populate_recordset_scalar ( void *  state,
char *  token,
JsonTokenType  tokentype 
)
static

Definition at line 4288 of file jsonfuncs.c.

4289 {
4291 
4292  if (_state->lex->lex_level == 0)
4293  ereport(ERROR,
4294  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4295  errmsg("cannot call %s on a scalar",
4296  _state->function_name)));
4297 
4298  if (_state->lex->lex_level == 2)
4299  _state->saved_scalar = token;
4300 
4301  return JSON_SUCCESS;
4302 }

References ereport, errcode(), errmsg(), ERROR, PopulateRecordsetState::function_name, JSON_SUCCESS, PopulateRecordsetState::lex, JsonLexContext::lex_level, PopulateRecordsetState::saved_scalar, and token.

Referenced by populate_recordset_worker().

◆ populate_recordset_worker()

static Datum populate_recordset_worker ( FunctionCallInfo  fcinfo,
const char *  funcname,
bool  is_json,
bool  have_record_arg 
)
static

Definition at line 4039 of file jsonfuncs.c.

4041 {
4042  int json_arg_num = have_record_arg ? 1 : 0;
4043  ReturnSetInfo *rsi;
4044  MemoryContext old_cxt;
4045  HeapTupleHeader rec;
4046  PopulateRecordCache *cache = fcinfo->flinfo->fn_extra;
4048 
4049  rsi = (ReturnSetInfo *) fcinfo->resultinfo;
4050 
4051  if (!rsi || !IsA(rsi, ReturnSetInfo))
4052  ereport(ERROR,
4053  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4054  errmsg("set-valued function called in context that cannot accept a set")));
4055 
4056  if (!(rsi->allowedModes & SFRM_Materialize))
4057  ereport(ERROR,
4058  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4059  errmsg("materialize mode required, but it is not allowed in this context")));
4060 
4062 
4063  /*
4064  * If first time through, identify input/result record type. Note that
4065  * this stanza looks only at fcinfo context, which can't change during the
4066  * query; so we may not be able to fully resolve a RECORD input type yet.
4067  */
4068  if (!cache)
4069  {
4070  fcinfo->flinfo->fn_extra = cache =
4071  MemoryContextAllocZero(fcinfo->flinfo->fn_mcxt, sizeof(*cache));
4072  cache->fn_mcxt = fcinfo->flinfo->fn_mcxt;
4073 
4074  if (have_record_arg)
4075  get_record_type_from_argument(fcinfo, funcname, cache);
4076  else
4077  get_record_type_from_query(fcinfo, funcname, cache);
4078  }
4079 
4080  /* Collect record arg if we have one */
4081  if (!have_record_arg)
4082  rec = NULL; /* it's json{b}_to_recordset() */
4083  else if (!PG_ARGISNULL(0))
4084  {
4085  rec = PG_GETARG_HEAPTUPLEHEADER(0);
4086 
4087  /*
4088  * When declared arg type is RECORD, identify actual record type from
4089  * the tuple itself.
4090  */
4091  if (cache->argtype == RECORDOID)
4092  {
4095  }
4096  }
4097  else
4098  {
4099  rec = NULL;
4100 
4101  /*
4102  * When declared arg type is RECORD, identify actual record type from
4103  * calling query, or fail if we can't.
4104  */
4105  if (cache->argtype == RECORDOID)
4106  {
4107  get_record_type_from_query(fcinfo, funcname, cache);
4108  /* This can't change argtype, which is important for next time */
4109  Assert(cache->argtype == RECORDOID);
4110  }
4111  }
4112 
4113  /* if the json is null send back an empty set */
4114  if (PG_ARGISNULL(json_arg_num))
4115  PG_RETURN_NULL();
4116 
4117  /*
4118  * Forcibly update the cached tupdesc, to ensure we have the right tupdesc
4119  * to return even if the JSON contains no rows.
4120  */
4121  update_cached_tupdesc(&cache->c.io.composite, cache->fn_mcxt);
4122 
4124 
4125  /* make tuplestore in a sufficiently long-lived memory context */
4127  state->tuple_store = tuplestore_begin_heap(rsi->allowedModes &
4129  false, work_mem);
4130  MemoryContextSwitchTo(old_cxt);
4131 
4132  state->function_name = funcname;
4133  state->cache = cache;
4134  state->rec = rec;
4135 
4136  if (is_json)
4137  {
4138  text *json = PG_GETARG_TEXT_PP(json_arg_num);
4139  JsonLexContext lex;
4140  JsonSemAction *sem;
4141 
4142  sem = palloc0(sizeof(JsonSemAction));
4143 
4144  makeJsonLexContext(&lex, json, true);
4145 
4146  sem->semstate = (void *) state;
4154 
4155  state->lex = &lex;
4156 
4158 
4159  freeJsonLexContext(&lex);
4160  state->lex = NULL;
4161  }
4162  else
4163  {
4164  Jsonb *jb = PG_GETARG_JSONB_P(json_arg_num);
4165  JsonbIterator *it;
4166  JsonbValue v;
4167  bool skipNested = false;
4169 
4170  if (JB_ROOT_IS_SCALAR(jb) || !JB_ROOT_IS_ARRAY(jb))
4171  ereport(ERROR,
4172  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4173  errmsg("cannot call %s on a non-array",
4174  funcname)));
4175 
4176  it = JsonbIteratorInit(&jb->root);
4177 
4178  while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE)
4179  {
4180  skipNested = true;
4181 
4182  if (r == WJB_ELEM)
4183  {
4184  JsObject obj;
4185 
4186  if (v.type != jbvBinary ||
4187  !JsonContainerIsObject(v.val.binary.data))
4188  ereport(ERROR,
4189  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4190  errmsg("argument of %s must be an array of objects",
4191  funcname)));
4192 
4193  obj.is_json = false;
4194  obj.val.jsonb_cont = v.val.binary.data;
4195 
4197  }
4198  }
4199  }
4200 
4201  /*
4202  * Note: we must copy the cached tupdesc because the executor will free
4203  * the passed-back setDesc, but we want to hang onto the cache in case
4204  * we're called again in the same query.
4205  */
4206  rsi->setResult = state->tuple_store;
4208 
4209  PG_RETURN_NULL();
4210 }
@ SFRM_Materialize_Random
Definition: execnodes.h:318
@ SFRM_Materialize
Definition: execnodes.h:317
int work_mem
Definition: globals.c:129
static JsonParseErrorType populate_recordset_array_start(void *state)
Definition: jsonfuncs.c:4281
static JsonParseErrorType populate_recordset_object_start(void *state)
Definition: jsonfuncs.c:4213
static JsonParseErrorType populate_recordset_object_field_start(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:4305
static JsonParseErrorType populate_recordset_object_field_end(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:4328
static JsonParseErrorType populate_recordset_object_end(void *state)
Definition: jsonfuncs.c:4243
static JsonParseErrorType populate_recordset_array_element_start(void *state, bool isnull)
Definition: jsonfuncs.c:4266
static JsonParseErrorType populate_recordset_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:4288
#define IsA(nodeptr, _type_)
Definition: nodes.h:158
MemoryContext ecxt_per_query_memory
Definition: execnodes.h:262
SetFunctionReturnMode returnMode
Definition: execnodes.h:336
ExprContext * econtext
Definition: execnodes.h:332
int allowedModes
Definition: execnodes.h:334
Tuplestorestate * tuplestore_begin_heap(bool randomAccess, bool interXact, int maxKBytes)
Definition: tuplestore.c:328

References ReturnSetInfo::allowedModes, PopulateRecordCache::argtype, JsonSemAction::array_element_start, JsonSemAction::array_start, Assert, CompositeIOData::base_typid, CompositeIOData::base_typmod, PopulateRecordCache::c, ColumnIOData::composite, CreateTupleDescCopy(), ReturnSetInfo::econtext, ExprContext::ecxt_per_query_memory, ereport, errcode(), errmsg(), ERROR, FunctionCallInfoBaseData::flinfo, FmgrInfo::fn_extra, PopulateRecordCache::fn_mcxt, FmgrInfo::fn_mcxt, freeJsonLexContext(), funcname, get_record_type_from_argument(), get_record_type_from_query(), HeapTupleHeaderGetTypeId, HeapTupleHeaderGetTypMod, if(), ColumnIOData::io, JsObject::is_json, IsA, JB_ROOT_IS_ARRAY, JB_ROOT_IS_SCALAR, jbvBinary, JsObject::jsonb_cont, JsonbIteratorInit(), JsonbIteratorNext(), JsonContainerIsObject, makeJsonLexContext(), MemoryContextAllocZero(), MemoryContextSwitchTo(), JsonSemAction::object_end, JsonSemAction::object_field_end, JsonSemAction::object_field_start, JsonSemAction::object_start, palloc0(), PG_ARGISNULL, PG_GETARG_HEAPTUPLEHEADER, PG_GETARG_JSONB_P, PG_GETARG_TEXT_PP, pg_parse_json_or_ereport, PG_RETURN_NULL, populate_recordset_array_element_start(), populate_recordset_array_start(), populate_recordset_object_end(), populate_recordset_object_field_end(), populate_recordset_object_field_start(), populate_recordset_object_start(), populate_recordset_record(), populate_recordset_scalar(), FunctionCallInfoBaseData::resultinfo, ReturnSetInfo::returnMode, Jsonb::root, JsonSemAction::scalar, sem, JsonSemAction::semstate, ReturnSetInfo::setDesc, ReturnSetInfo::setResult, SFRM_Materialize, SFRM_Materialize_Random, CompositeIOData::tupdesc, tuplestore_begin_heap(), JsonbValue::type, update_cached_tupdesc(), JsObject::val, JsonbValue::val, WJB_DONE, WJB_ELEM, and work_mem.

Referenced by json_populate_recordset(), json_to_recordset(), jsonb_populate_recordset(), and jsonb_to_recordset().

◆ populate_scalar()

static Datum populate_scalar ( ScalarIOData io,
Oid  typid,
int32  typmod,
JsValue jsv,
bool isnull,
Node escontext,
bool  omit_quotes 
)
static

Definition at line 3123 of file jsonfuncs.c.

3125 {
3126  Datum res;
3127  char *str = NULL;
3128  const char *json = NULL;
3129 
3130  if (jsv->is_json)
3131  {
3132  int len = jsv->val.json.len;
3133 
3134  json = jsv->val.json.str;
3135  Assert(json);
3136  if (len >= 0)
3137  {
3138  /* Need to copy non-null-terminated string */
3139  str = palloc(len + 1 * sizeof(char));
3140  memcpy(str, json, len);
3141  str[len] = '\0';
3142  }
3143  else
3144  {
3145  /* string is already null-terminated */
3146  str = unconstify(char *, json);
3147  }
3148 
3149  /* If converting to json/jsonb, make string into valid JSON literal */
3150  if ((typid == JSONOID || typid == JSONBOID) &&
3151  jsv->val.json.type == JSON_TOKEN_STRING)
3152  {
3154 
3155  initStringInfo(&buf);
3156  escape_json(&buf, str);
3157  /* free temporary buffer */
3158  if (str != json)
3159  pfree(str);
3160  str = buf.data;
3161  }
3162  }
3163  else
3164  {
3165  JsonbValue *jbv = jsv->val.jsonb;
3166 
3167  if (jbv->type == jbvString && omit_quotes)
3168  str = pnstrdup(jbv->val.string.val, jbv->val.string.len);
3169  else if (typid == JSONBOID)
3170  {
3171  Jsonb *jsonb = JsonbValueToJsonb(jbv); /* directly use jsonb */
3172 
3173  return JsonbPGetDatum(jsonb);
3174  }
3175  /* convert jsonb to string for typio call */
3176  else if (typid == JSONOID && jbv->type != jbvBinary)
3177  {
3178  /*
3179  * Convert scalar jsonb (non-scalars are passed here as jbvBinary)
3180  * to json string, preserving quotes around top-level strings.
3181  */
3182  Jsonb *jsonb = JsonbValueToJsonb(jbv);
3183 
3184  str = JsonbToCString(NULL, &jsonb->root, VARSIZE(jsonb));
3185  }
3186  else if (jbv->type == jbvString) /* quotes are stripped */
3187  str = pnstrdup(jbv->val.string.val, jbv->val.string.len);
3188  else if (jbv->type == jbvBool)
3189  str = pstrdup(jbv->val.boolean ? "true" : "false");
3190  else if (jbv->type == jbvNumeric)
3192  PointerGetDatum(jbv->val.numeric)));
3193  else if (jbv->type == jbvBinary)
3194  str = JsonbToCString(NULL, jbv->val.binary.data,
3195  jbv->val.binary.len);
3196  else
3197  elog(ERROR, "unrecognized jsonb type: %d", (int) jbv->type);
3198  }
3199 
3200  if (!InputFunctionCallSafe(&io->typiofunc, str, io->typioparam, typmod,
3201  escontext, &res))
3202  {
3203  res = (Datum) 0;
3204  *isnull = true;
3205  }
3206 
3207  /* free temporary buffer */
3208  if (str != json)
3209  pfree(str);
3210 
3211  return res;
3212 }
#define unconstify(underlying_type, expr)
Definition: c.h:1245
bool InputFunctionCallSafe(FmgrInfo *flinfo, char *str, Oid typioparam, int32 typmod, fmNodePtr escontext, Datum *result)
Definition: fmgr.c:1585
void escape_json(StringInfo buf, const char *str)
Definition: json.c:1549
static Datum JsonbPGetDatum(const Jsonb *p)
Definition: jsonb.h:386
static char * buf
Definition: pg_test_fsync.c:73
Oid typioparam
Definition: jsonfuncs.c:156
FmgrInfo typiofunc
Definition: jsonfuncs.c:157

References Assert, buf, DatumGetCString(), DirectFunctionCall1, elog, ERROR, escape_json(), initStringInfo(), InputFunctionCallSafe(), JsValue::is_json, jbvBinary, jbvBool, jbvNumeric, jbvString, JsValue::json, JSON_TOKEN_STRING, JsValue::jsonb, JsonbPGetDatum(), JsonbToCString(), JsonbValueToJsonb(), len, numeric_out(), palloc(), pfree(), pnstrdup(), PointerGetDatum(), pstrdup(), res, Jsonb::root, str, JsonbValue::type, ScalarIOData::typiofunc, ScalarIOData::typioparam, unconstify, JsValue::val, JsonbValue::val, and VARSIZE.

Referenced by populate_record_field().

◆ prepare_column_cache()

static void prepare_column_cache ( ColumnIOData column,
Oid  typid,
int32  typmod,
MemoryContext  mcxt,
bool  need_scalar 
)
static

Definition at line 3249 of file jsonfuncs.c.

3254 {
3255  HeapTuple tup;
3257 
3258  column->typid = typid;
3259  column->typmod = typmod;
3260 
3261  tup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
3262  if (!HeapTupleIsValid(tup))
3263  elog(ERROR, "cache lookup failed for type %u", typid);
3264 
3265  type = (Form_pg_type) GETSTRUCT(tup);
3266 
3267  if (type->typtype == TYPTYPE_DOMAIN)
3268  {
3269  /*
3270  * We can move directly to the bottom base type; domain_check() will
3271  * take care of checking all constraints for a stack of domains.
3272  */
3273  Oid base_typid;
3274  int32 base_typmod = typmod;
3275 
3276  base_typid = getBaseTypeAndTypmod(typid, &base_typmod);
3277  if (get_typtype(base_typid) == TYPTYPE_COMPOSITE)
3278  {
3279  /* domain over composite has its own code path */
3280  column->typcat = TYPECAT_COMPOSITE_DOMAIN;
3281  column->io.composite.record_io = NULL;
3282  column->io.composite.tupdesc = NULL;
3283  column->io.composite.base_typid = base_typid;
3284  column->io.composite.base_typmod = base_typmod;
3285  column->io.composite.domain_info = NULL;
3286  }
3287  else
3288  {
3289  /* domain over anything else */
3290  column->typcat = TYPECAT_DOMAIN;
3291  column->io.domain.base_typid = base_typid;
3292  column->io.domain.base_typmod = base_typmod;
3293  column->io.domain.base_io =
3294  MemoryContextAllocZero(mcxt, sizeof(ColumnIOData));
3295  column->io.domain.domain_info = NULL;
3296  }
3297  }
3298  else if (type->typtype == TYPTYPE_COMPOSITE || typid == RECORDOID)
3299  {
3300  column->typcat = TYPECAT_COMPOSITE;
3301  column->io.composite.record_io = NULL;
3302  column->io.composite.tupdesc = NULL;
3303  column->io.composite.base_typid = typid;
3304  column->io.composite.base_typmod = typmod;
3305  column->io.composite.domain_info = NULL;
3306  }
3307  else if (IsTrueArrayType(type))
3308  {
3309  column->typcat = TYPECAT_ARRAY;
3311  sizeof(ColumnIOData));
3312  column->io.array.element_type = type->typelem;
3313  /* array element typemod stored in attribute's typmod */
3314  column->io.array.element_typmod = typmod;
3315  }
3316  else
3317  {
3318  column->typcat = TYPECAT_SCALAR;
3319  need_scalar = true;
3320  }
3321 
3322  /* caller can force us to look up scalar_io info even for non-scalars */
3323  if (need_scalar)
3324  {
3325  Oid typioproc;
3326 
3327  getTypeInputInfo(typid, &typioproc, &column->scalar_io.typioparam);
3328  fmgr_info_cxt(typioproc, &column->scalar_io.typiofunc, mcxt);
3329  }
3330 
3331  ReleaseSysCache(tup);
3332 }
signed int int32
Definition: c.h:494
void fmgr_info_cxt(Oid functionId, FmgrInfo *finfo, MemoryContext mcxt)
Definition: fmgr.c:137
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define GETSTRUCT(TUP)
Definition: htup_details.h:653
void getTypeInputInfo(Oid type, Oid *typInput, Oid *typIOParam)
Definition: lsyscache.c:2874
char get_typtype(Oid typid)
Definition: lsyscache.c:2629
Oid getBaseTypeAndTypmod(Oid typid, int32 *typmod)
Definition: lsyscache.c:2538
FormData_pg_type * Form_pg_type
Definition: pg_type.h:261
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:252
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:266
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:218

References ColumnIOData::array, DomainIOData::base_io, CompositeIOData::base_typid, DomainIOData::base_typid, CompositeIOData::base_typmod, DomainIOData::base_typmod, ColumnIOData::composite, ColumnIOData::domain, CompositeIOData::domain_info, DomainIOData::domain_info, ArrayIOData::element_info, ArrayIOData::element_type, ArrayIOData::element_typmod, elog, ERROR, fmgr_info_cxt(), get_typtype(), getBaseTypeAndTypmod(), GETSTRUCT, getTypeInputInfo(), HeapTupleIsValid, ColumnIOData::io, MemoryContextAllocZero(), ObjectIdGetDatum(), CompositeIOData::record_io, ReleaseSysCache(), ColumnIOData::scalar_io, SearchSysCache1(), CompositeIOData::tupdesc, ColumnIOData::typcat, type, TYPECAT_ARRAY, TYPECAT_COMPOSITE, TYPECAT_COMPOSITE_DOMAIN, TYPECAT_DOMAIN, TYPECAT_SCALAR, ColumnIOData::typid, ScalarIOData::typiofunc, ScalarIOData::typioparam, and ColumnIOData::typmod.

Referenced by get_record_type_from_argument(), and populate_record_field().

◆ push_null_elements()

static void push_null_elements ( JsonbParseState **  ps,
int  num 
)
static

Definition at line 1700 of file jsonfuncs.c.

1701 {
1702  JsonbValue null;
1703 
1704  null.type = jbvNull;
1705 
1706  while (num-- > 0)
1707  pushJsonbValue(ps, WJB_ELEM, &null);
1708 }
struct parser_state ps

References jbvNull, ps, pushJsonbValue(), JsonbValue::type, and WJB_ELEM.

Referenced by push_path(), and setPathArray().

◆ push_path()

static void push_path ( JsonbParseState **  st,
int  level,
Datum path_elems,
bool path_nulls,
int  path_len,
JsonbValue newval 
)
static

Definition at line 1719 of file jsonfuncs.c.

1721 {
1722  /*
1723  * tpath contains expected type of an empty jsonb created at each level
1724  * higher or equal than the current one, either jbvObject or jbvArray.
1725  * Since it contains only information about path slice from level to the
1726  * end, the access index must be normalized by level.
1727  */
1728  enum jbvType *tpath = palloc0((path_len - level) * sizeof(enum jbvType));
1729  JsonbValue newkey;
1730 
1731  /*
1732  * Create first part of the chain with beginning tokens. For the current
1733  * level WJB_BEGIN_OBJECT/WJB_BEGIN_ARRAY was already created, so start
1734  * with the next one.
1735  */
1736  for (int i = level + 1; i < path_len; i++)
1737  {
1738  char *c,
1739  *badp;
1740  int lindex;
1741 
1742  if (path_nulls[i])
1743  break;
1744 
1745  /*
1746  * Try to convert to an integer to find out the expected type, object
1747  * or array.
1748  */
1749  c = TextDatumGetCString(path_elems[i]);
1750  errno = 0;
1751  lindex = strtoint(c, &badp, 10);
1752  if (badp == c || *badp != '\0' || errno != 0)
1753  {
1754  /* text, an object is expected */
1755  newkey.type = jbvString;
1756  newkey.val.string.val = c;
1757  newkey.val.string.len = strlen(c);
1758 
1759  (void) pushJsonbValue(st, WJB_BEGIN_OBJECT, NULL);
1760  (void) pushJsonbValue(st, WJB_KEY, &newkey);
1761 
1762  tpath[i - level] = jbvObject;
1763  }
1764  else
1765  {
1766  /* integer, an array is expected */
1767  (void) pushJsonbValue(st, WJB_BEGIN_ARRAY, NULL);
1768 
1769  push_null_elements(st, lindex);
1770 
1771  tpath[i - level] = jbvArray;
1772  }
1773  }
1774 
1775  /* Insert an actual value for either an object or array */
1776  if (tpath[(path_len - level) - 1] == jbvArray)
1777  {
1778  (void) pushJsonbValue(st, WJB_ELEM, newval);
1779  }
1780  else
1781  (void) pushJsonbValue(st, WJB_VALUE, newval);
1782 
1783  /*
1784  * Close everything up to the last but one level. The last one will be
1785  * closed outside of this function.
1786  */
1787  for (int i = path_len - 1; i > level; i--)
1788  {
1789  if (path_nulls[i])
1790  break;
1791 
1792  if (tpath[i - level] == jbvObject)
1793  (void) pushJsonbValue(st, WJB_END_OBJECT, NULL);
1794  else
1795  (void) pushJsonbValue(st, WJB_END_ARRAY, NULL);
1796  }
1797 }
jbvType
Definition: jsonb.h:226
@ jbvObject
Definition: jsonb.h:234
static void push_null_elements(JsonbParseState **ps, int num)
Definition: jsonfuncs.c:1700
char * c

References i, jbvArray, jbvObject, jbvString, newval, palloc0(), push_null_elements(), pushJsonbValue(), strtoint(), TextDatumGetCString, JsonbValue::type, JsonbValue::val, WJB_BEGIN_ARRAY, WJB_BEGIN_OBJECT, WJB_ELEM, WJB_END_ARRAY, WJB_END_OBJECT, WJB_KEY, and WJB_VALUE.

Referenced by setPathArray(), and setPathObject().

◆ report_json_context()

static int report_json_context ( JsonLexContext lex)
static

Definition at line 675 of file jsonfuncs.c.

676 {
677  const char *context_start;
678  const char *context_end;
679  const char *line_start;
680  char *ctxt;
681  int ctxtlen;
682  const char *prefix;
683  const char *suffix;
684 
685  /* Choose boundaries for the part of the input we will display */
686  line_start = lex->line_start;
687  context_start = line_start;
688  context_end = lex->token_terminator;
689  Assert(context_end >= context_start);
690 
691  /* Advance until we are close enough to context_end */
692  while (context_end - context_start >= 50)
693  {
694  /* Advance to next multibyte character */
695  if (IS_HIGHBIT_SET(*context_start))
696  context_start += pg_mblen(context_start);
697  else
698  context_start++;
699  }
700 
701  /*
702  * We add "..." to indicate that the excerpt doesn't start at the
703  * beginning of the line ... but if we're within 3 characters of the
704  * beginning of the line, we might as well just show the whole line.
705  */
706  if (context_start - line_start <= 3)
707  context_start = line_start;
708 
709  /* Get a null-terminated copy of the data to present */
710  ctxtlen = context_end - context_start;
711  ctxt = palloc(ctxtlen + 1);
712  memcpy(ctxt, context_start, ctxtlen);
713  ctxt[ctxtlen] = '\0';
714 
715  /*
716  * Show the context, prefixing "..." if not starting at start of line, and
717  * suffixing "..." if not ending at end of line.
718  */
719  prefix = (context_start > line_start) ? "..." : "";
720  suffix = (lex->token_type != JSON_TOKEN_END &&
721  context_end - lex->input < lex->input_length &&
722  *context_end != '\n' && *context_end != '\r') ? "..." : "";
723 
724  return errcontext("JSON data, line %d: %s%s%s",
725  lex->line_number, prefix, ctxt, suffix);
726 }
#define IS_HIGHBIT_SET(ch)
Definition: c.h:1155
#define errcontext
Definition: elog.h:196
@ JSON_TOKEN_END
Definition: jsonapi.h:33
int pg_mblen(const char *mbstr)
Definition: mbutils.c:1023
size_t input_length
Definition: jsonapi.h:92
const char * line_start
Definition: jsonapi.h:102
int line_number
Definition: jsonapi.h:101
const char * token_terminator
Definition: jsonapi.h:95

References Assert, errcontext, JsonLexContext::input, JsonLexContext::input_length, IS_HIGHBIT_SET, JSON_TOKEN_END, JsonLexContext::line_number, JsonLexContext::line_start, palloc(), pg_mblen(), JsonLexContext::token_terminator, and JsonLexContext::token_type.

Referenced by json_errsave_error().

◆ setPath()

static JsonbValue * setPath ( JsonbIterator **  it,
Datum path_elems,
bool path_nulls,
int  path_len,
JsonbParseState **  st,
int  level,
JsonbValue newval,
int  op_type 
)
static

Definition at line 5180 of file jsonfuncs.c.

5183 {
5184  JsonbValue v;
5186  JsonbValue *res;
5187 
5189 
5190  if (path_nulls[level])
5191  ereport(ERROR,
5192  (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
5193  errmsg("path element at position %d is null",
5194  level + 1)));
5195 
5196  r = JsonbIteratorNext(it, &v, false);
5197 
5198  switch (r)
5199  {
5200  case WJB_BEGIN_ARRAY:
5201 
5202  /*
5203  * If instructed complain about attempts to replace within a raw
5204  * scalar value. This happens even when current level is equal to
5205  * path_len, because the last path key should also correspond to
5206  * an object or an array, not raw scalar.
5207  */
5208  if ((op_type & JB_PATH_FILL_GAPS) && (level <= path_len - 1) &&
5209  v.val.array.rawScalar)
5210  ereport(ERROR,
5211  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
5212  errmsg("cannot replace existing key"),
5213  errdetail("The path assumes key is a composite object, "
5214  "but it is a scalar value.")));
5215 
5216  (void) pushJsonbValue(st, r, NULL);
5217  setPathArray(it, path_elems, path_nulls, path_len, st, level,
5218  newval, v.val.array.nElems, op_type);
5219  r = JsonbIteratorNext(it, &v, false);
5220  Assert(r == WJB_END_ARRAY);
5221  res = pushJsonbValue(st, r, NULL);
5222  break;
5223  case WJB_BEGIN_OBJECT:
5224  (void) pushJsonbValue(st, r, NULL);
5225  setPathObject(it, path_elems, path_nulls, path_len, st, level,
5226  newval, v.val.object.nPairs, op_type);
5227  r = JsonbIteratorNext(it, &v, true);
5228  Assert(r == WJB_END_OBJECT);
5229  res = pushJsonbValue(st, r, NULL);
5230  break;
5231  case WJB_ELEM:
5232  case WJB_VALUE:
5233 
5234  /*
5235  * If instructed complain about attempts to replace within a
5236  * scalar value. This happens even when current level is equal to
5237  * path_len, because the last path key should also correspond to
5238  * an object or an array, not an element or value.
5239  */
5240  if ((op_type & JB_PATH_FILL_GAPS) && (level <= path_len - 1))
5241  ereport(ERROR,
5242  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
5243  errmsg("cannot replace existing key"),
5244  errdetail("The path assumes key is a composite object, "
5245  "but it is a scalar value.")));
5246 
5247  res = pushJsonbValue(st, r, &v);
5248  break;
5249  default:
5250  elog(ERROR, "unrecognized iterator result: %d", (int) r);
5251  res = NULL; /* keep compiler quiet */
5252  break;
5253  }
5254 
5255  return res;
5256 }
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)
Definition: jsonfuncs.c:5401
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)
Definition: jsonfuncs.c:5262

References Assert, check_stack_depth(), elog, ereport, errcode(), errdetail(), errmsg(), ERROR, JB_PATH_FILL_GAPS, JsonbIteratorNext(), newval, pushJsonbValue(), res, setPathArray(), setPathObject(), JsonbValue::val, WJB_BEGIN_ARRAY, WJB_BEGIN_OBJECT, WJB_ELEM, WJB_END_ARRAY, WJB_END_OBJECT, and WJB_VALUE.

Referenced by jsonb_delete_path(), jsonb_insert(), jsonb_set(), jsonb_set_element(), setPathArray(), and setPathObject().

◆ setPathArray()

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

Definition at line 5401 of file jsonfuncs.c.

5404 {
5405  JsonbValue v;
5406  int idx,
5407  i;
5408  bool done = false;
5409 
5410  /* pick correct index */
5411  if (level < path_len && !path_nulls[level])
5412  {
5413  char *c = TextDatumGetCString(path_elems[level]);
5414  char *badp;
5415 
5416  errno = 0;
5417  idx = strtoint(c, &badp, 10);
5418  if (badp == c || *badp != '\0' || errno != 0)
5419  ereport(ERROR,
5420  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
5421  errmsg("path element at position %d is not an integer: \"%s\"",
5422  level + 1, c)));
5423  }
5424  else
5425  idx = nelems;
5426 
5427  if (idx < 0)
5428  {
5429  if (-idx > nelems)
5430  {
5431  /*
5432  * If asked to keep elements position consistent, it's not allowed
5433  * to prepend the array.
5434  */
5435  if (op_type & JB_PATH_CONSISTENT_POSITION)
5436  ereport(ERROR,
5437  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
5438  errmsg("path element at position %d is out of range: %d",
5439  level + 1, idx)));
5440  else
5441  idx = INT_MIN;
5442  }
5443  else
5444  idx = nelems + idx;
5445  }
5446 
5447  /*
5448  * Filling the gaps means there are no limits on the positive index are
5449  * imposed, we can set any element. Otherwise limit the index by nelems.
5450  */
5451  if (!(op_type & JB_PATH_FILL_GAPS))
5452  {
5453  if (idx > 0 && idx > nelems)
5454  idx = nelems;
5455  }
5456 
5457  /*
5458  * if we're creating, and idx == INT_MIN, we prepend the new value to the
5459  * array also if the array is empty - in which case we don't really care
5460  * what the idx value is
5461  */
5462  if ((idx == INT_MIN || nelems == 0) && (level == path_len - 1) &&
5463  (op_type & JB_PATH_CREATE_OR_INSERT))
5464  {
5465  Assert(newval != NULL);
5466 
5467  if (op_type & JB_PATH_FILL_GAPS && nelems == 0 && idx > 0)
5468  push_null_elements(st, idx);
5469 
5470  (void) pushJsonbValue(st, WJB_ELEM, newval);
5471 
5472  done = true;
5473  }
5474 
5475  /* iterate over the array elements */
5476  for (i = 0; i < nelems; i++)
5477  {
5479 
5480  if (i == idx && level < path_len)
5481  {
5482  done = true;
5483 
5484  if (level == path_len - 1)
5485  {
5486  r = JsonbIteratorNext(it, &v, true); /* skip */
5487 
5488  if (op_type & (JB_PATH_INSERT_BEFORE | JB_PATH_CREATE))
5489  (void) pushJsonbValue(st, WJB_ELEM, newval);
5490 
5491  /*
5492  * We should keep current value only in case of
5493  * JB_PATH_INSERT_BEFORE or JB_PATH_INSERT_AFTER because
5494  * otherwise it should be deleted or replaced
5495  */
5496  if (op_type & (JB_PATH_INSERT_AFTER | JB_PATH_INSERT_BEFORE))
5497  (void) pushJsonbValue(st, r, &v);
5498 
5499  if (op_type & (JB_PATH_INSERT_AFTER | JB_PATH_REPLACE))
5500  (void) pushJsonbValue(st, WJB_ELEM, newval);
5501  }
5502  else
5503  (void) setPath(it, path_elems, path_nulls, path_len,
5504  st, level + 1, newval, op_type);
5505  }
5506  else
5507  {
5508  r = JsonbIteratorNext(it, &v, false);
5509 
5510  (void) pushJsonbValue(st, r, r < WJB_BEGIN_ARRAY ? &v : NULL);
5511 
5512  if (r == WJB_BEGIN_ARRAY || r == WJB_BEGIN_OBJECT)
5513  {
5514  int walking_level = 1;
5515 
5516  while (walking_level != 0)
5517  {
5518  r = JsonbIteratorNext(it, &v, false);
5519 
5520  if (r == WJB_BEGIN_ARRAY || r == WJB_BEGIN_OBJECT)
5521  ++walking_level;
5522  if (r == WJB_END_ARRAY || r == WJB_END_OBJECT)
5523  --walking_level;
5524 
5525  (void) pushJsonbValue(st, r, r < WJB_BEGIN_ARRAY ? &v : NULL);
5526  }
5527  }
5528  }
5529  }
5530 
5531  if ((op_type & JB_PATH_CREATE_OR_INSERT) && !done && level == path_len - 1)
5532  {
5533  /*
5534  * If asked to fill the gaps, idx could be bigger than nelems, so
5535  * prepend the new element with nulls if that's the case.
5536  */
5537  if (op_type & JB_PATH_FILL_GAPS && idx > nelems)
5538  push_null_elements(st, idx - nelems);
5539 
5540  (void) pushJsonbValue(st, WJB_ELEM, newval);
5541  done = true;
5542  }
5543 
5544  /*--
5545  * If we got here there are only few possibilities:
5546  * - no target path was found, and an open array with some keys/values was
5547  * pushed into the state
5548  * - an array is empty, only WJB_BEGIN_ARRAY is pushed
5549  *
5550  * In both cases if instructed to create the path when not present,
5551  * generate the whole chain of empty objects and insert the new value
5552  * there.
5553  */
5554  if (!done && (op_type & JB_PATH_FILL_GAPS) && (level < path_len - 1))
5555  {
5556  if (idx > 0)
5557  push_null_elements(st, idx - nelems);
5558 
5559  (void) push_path(st, level, path_elems, path_nulls,
5560  path_len, newval);
5561 
5562  /* Result is closed with WJB_END_OBJECT outside of this function */
5563  }
5564 }
#define JB_PATH_CREATE_OR_INSERT
Definition: jsonfuncs.c:48
static void push_path(JsonbParseState **st, int level, Datum *path_elems, bool *path_nulls, int path_len, JsonbValue *newval)
Definition: jsonfuncs.c:1719

References Assert, ereport, errcode(), errmsg(), ERROR, i, idx(), JB_PATH_CONSISTENT_POSITION, JB_PATH_CREATE, JB_PATH_CREATE_OR_INSERT, JB_PATH_FILL_GAPS, JB_PATH_INSERT_AFTER, JB_PATH_INSERT_BEFORE, JB_PATH_REPLACE, JsonbIteratorNext(), newval, push_null_elements(), push_path(), pushJsonbValue(), setPath(), strtoint(), TextDatumGetCString, WJB_BEGIN_ARRAY, WJB_BEGIN_OBJECT, WJB_ELEM, WJB_END_ARRAY, and WJB_END_OBJECT.

Referenced by setPath().

◆ setPathObject()

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

Definition at line 5262 of file jsonfuncs.c.

5265 {
5266  text *pathelem = NULL;
5267  int i;
5268  JsonbValue k,
5269  v;
5270  bool done = false;
5271 
5272  if (level >= path_len || path_nulls[level])
5273  done = true;
5274  else
5275  {
5276  /* The path Datum could be toasted, in which case we must detoast it */
5277  pathelem = DatumGetTextPP(path_elems[level]);
5278  }
5279 
5280  /* empty object is a special case for create */
5281  if ((npairs == 0) && (op_type & JB_PATH_CREATE_OR_INSERT) &&
5282  (level == path_len - 1))
5283  {
5284  JsonbValue newkey;
5285 
5286  newkey.type = jbvString;
5287  newkey.val.string.val = VARDATA_ANY(pathelem);
5288  newkey.val.string.len = VARSIZE_ANY_EXHDR(pathelem);
5289 
5290  (void) pushJsonbValue(st, WJB_KEY, &newkey);
5291  (void) pushJsonbValue(st, WJB_VALUE, newval);
5292  }
5293 
5294  for (i = 0; i < npairs; i++)
5295  {
5296  JsonbIteratorToken r = JsonbIteratorNext(it, &k, true);
5297 
5298  Assert(r == WJB_KEY);
5299 
5300  if (!done &&
5301  k.val.string.len == VARSIZE_ANY_EXHDR(pathelem) &&
5302  memcmp(k.val.string.val, VARDATA_ANY(pathelem),
5303  k.val.string.len) == 0)
5304  {
5305  done = true;
5306 
5307  if (level == path_len - 1)
5308  {
5309  /*
5310  * called from jsonb_insert(), it forbids redefining an
5311  * existing value
5312  */
5313  if (op_type & (JB_PATH_INSERT_BEFORE | JB_PATH_INSERT_AFTER))
5314  ereport(ERROR,
5315  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
5316  errmsg("cannot replace existing key"),
5317  errhint("Try using the function jsonb_set "
5318  "to replace key value.")));
5319 
5320  r = JsonbIteratorNext(it, &v, true); /* skip value */
5321  if (!(op_type & JB_PATH_DELETE))
5322  {
5323  (void) pushJsonbValue(st, WJB_KEY, &k);
5324  (void) pushJsonbValue(st, WJB_VALUE, newval);
5325  }
5326  }
5327  else
5328  {
5329  (void) pushJsonbValue(st, r, &k);
5330  setPath(it, path_elems, path_nulls, path_len,
5331  st, level + 1, newval, op_type);
5332  }
5333  }
5334  else
5335  {
5336  if ((op_type & JB_PATH_CREATE_OR_INSERT) && !done &&
5337  level == path_len - 1 && i == npairs - 1)
5338  {
5339  JsonbValue newkey;
5340 
5341  newkey.type = jbvString;
5342  newkey.val.string.val = VARDATA_ANY(pathelem);
5343  newkey.val.string.len = VARSIZE_ANY_EXHDR(pathelem);
5344 
5345  (void) pushJsonbValue(st, WJB_KEY, &newkey);
5346  (void) pushJsonbValue(st, WJB_VALUE, newval);
5347  }
5348 
5349  (void) pushJsonbValue(st, r, &k);
5350  r = JsonbIteratorNext(it, &v, false);
5351  (void) pushJsonbValue(st, r, r < WJB_BEGIN_ARRAY ? &v : NULL);
5352  if (r == WJB_BEGIN_ARRAY || r == WJB_BEGIN_OBJECT)
5353  {
5354  int walking_level = 1;
5355 
5356  while (walking_level != 0)
5357  {
5358  r = JsonbIteratorNext(it, &v, false);
5359 
5360  if (r == WJB_BEGIN_ARRAY || r == WJB_BEGIN_OBJECT)
5361  ++walking_level;
5362  if (r == WJB_END_ARRAY || r == WJB_END_OBJECT)
5363  --walking_level;
5364 
5365  (void) pushJsonbValue(st, r, r < WJB_BEGIN_ARRAY ? &v : NULL);
5366  }
5367  }
5368  }
5369  }
5370 
5371  /*--
5372  * If we got here there are only few possibilities:
5373  * - no target path was found, and an open object with some keys/values was
5374  * pushed into the state
5375  * - an object is empty, only WJB_BEGIN_OBJECT is pushed
5376  *
5377  * In both cases if instructed to create the path when not present,
5378  * generate the whole chain of empty objects and insert the new value
5379  * there.
5380  */
5381  if (!done && (op_type & JB_PATH_FILL_GAPS) && (level < path_len - 1))
5382  {
5383  JsonbValue newkey;
5384 
5385  newkey.type = jbvString;
5386  newkey.val.string.val = VARDATA_ANY(pathelem);
5387  newkey.val.string.len = VARSIZE_ANY_EXHDR(pathelem);
5388 
5389  (void) pushJsonbValue(st, WJB_KEY, &newkey);
5390  (void) push_path(st, level, path_elems, path_nulls,
5391  path_len, newval);
5392 
5393  /* Result is closed with WJB_END_OBJECT outside of this function */
5394  }
5395 }

References Assert, DatumGetTextPP, ereport, errcode(), errhint(), errmsg(), ERROR, i, JB_PATH_CREATE_OR_INSERT, JB_PATH_DELETE, JB_PATH_FILL_GAPS, JB_PATH_INSERT_AFTER, JB_PATH_INSERT_BEFORE, jbvString, JsonbIteratorNext(), newval, push_path(), pushJsonbValue(), setPath(), JsonbValue::type, JsonbValue::val, VARDATA_ANY, VARSIZE_ANY_EXHDR, WJB_BEGIN_ARRAY, WJB_BEGIN_OBJECT, WJB_END_ARRAY, WJB_END_OBJECT, WJB_KEY, and WJB_VALUE.

Referenced by setPath().

◆ sn_array_element_start()

static JsonParseErrorType sn_array_element_start ( void *  state,
bool  isnull 
)
static

Definition at line 4458 of file jsonfuncs.c.

4459 {
4460  StripnullState *_state = (StripnullState *) state;
4461 
4462  if (_state->strval->data[_state->strval->len - 1] != '[')
4463  appendStringInfoCharMacro(_state->strval, ',');
4464 
4465  return JSON_SUCCESS;
4466 }
#define appendStringInfoCharMacro(str, ch)
Definition: stringinfo.h:204
StringInfo strval
Definition: jsonfuncs.c:286

References appendStringInfoCharMacro, StringInfoData::data, JSON_SUCCESS, StringInfoData::len, and StripnullState::strval.

Referenced by json_strip_nulls().

◆ sn_array_end()

static JsonParseErrorType sn_array_end ( void *  state)
static

Definition at line 4418 of file jsonfuncs.c.

4419 {
4420  StripnullState *_state = (StripnullState *) state;
4421 
4422  appendStringInfoCharMacro(_state->strval, ']');
4423 
4424  return JSON_SUCCESS;
4425 }

References appendStringInfoCharMacro, JSON_SUCCESS, and StripnullState::strval.

Referenced by json_strip_nulls().

◆ sn_array_start()

static JsonParseErrorType sn_array_start ( void *  state)
static

Definition at line 4408 of file jsonfuncs.c.

4409 {
4410  StripnullState *_state = (StripnullState *) state;
4411 
4412  appendStringInfoCharMacro(_state->strval, '[');
4413 
4414  return JSON_SUCCESS;
4415 }

References appendStringInfoCharMacro, JSON_SUCCESS, and StripnullState::strval.

Referenced by json_strip_nulls().

◆ sn_object_end()

static JsonParseErrorType sn_object_end ( void *  state)
static

Definition at line 4398 of file jsonfuncs.c.

4399 {
4400  StripnullState *_state = (StripnullState *) state;
4401 
4402  appendStringInfoCharMacro(_state->strval, '}');
4403 
4404  return JSON_SUCCESS;
4405 }

References appendStringInfoCharMacro, JSON_SUCCESS, and StripnullState::strval.

Referenced by json_strip_nulls().

◆ sn_object_field_start()

static JsonParseErrorType sn_object_field_start ( void *  state,
char *  fname,
bool  isnull 
)
static

Definition at line 4428 of file jsonfuncs.c.

4429 {
4430  StripnullState *_state = (StripnullState *) state;
4431 
4432  if (isnull)
4433  {
4434  /*
4435  * The next thing must be a scalar or isnull couldn't be true, so
4436  * there is no danger of this state being carried down into a nested
4437  * object or array. The flag will be reset in the scalar action.
4438  */
4439  _state->skip_next_null = true;
4440  return JSON_SUCCESS;
4441  }
4442 
4443  if (_state->strval->data[_state->strval->len - 1] != '{')
4444  appendStringInfoCharMacro(_state->strval, ',');
4445 
4446  /*
4447  * Unfortunately we don't have the quoted and escaped string any more, so
4448  * we have to re-escape it.
4449  */
4450  escape_json(_state->strval, fname);
4451 
4452  appendStringInfoCharMacro(_state->strval, ':');
4453 
4454  return JSON_SUCCESS;
4455 }
bool skip_next_null
Definition: jsonfuncs.c:287

References appendStringInfoCharMacro, StringInfoData::data, escape_json(), JSON_SUCCESS, StringInfoData::len, StripnullState::skip_next_null, and StripnullState::strval.

Referenced by json_strip_nulls().

◆ sn_object_start()

static JsonParseErrorType sn_object_start ( void *  state)
static

Definition at line 4388 of file jsonfuncs.c.

4389 {
4390  StripnullState *_state = (StripnullState *) state;
4391 
4392  appendStringInfoCharMacro(_state->strval, '{');
4393 
4394  return JSON_SUCCESS;
4395 }

References appendStringInfoCharMacro, JSON_SUCCESS, and StripnullState::strval.

Referenced by json_strip_nulls().

◆ sn_scalar()

static JsonParseErrorType sn_scalar ( void *  state,
char *  token,
JsonTokenType  tokentype 
)
static

Definition at line 4469 of file jsonfuncs.c.

4470 {
4471  StripnullState *_state = (StripnullState *) state;
4472 
4473  if (_state->skip_next_null)
4474  {
4475  Assert(tokentype == JSON_TOKEN_NULL);
4476  _state->skip_next_null = false;
4477  return JSON_SUCCESS;
4478  }
4479 
4480  if (tokentype == JSON_TOKEN_STRING)
4481  escape_json(_state->strval, token);
4482  else
4484 
4485  return JSON_SUCCESS;
4486 }
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:182

References appendStringInfoString(), Assert, escape_json(), JSON_SUCCESS, JSON_TOKEN_NULL, JSON_TOKEN_STRING, StripnullState::skip_next_null, StripnullState::strval, and token.

Referenced by json_strip_nulls().

◆ transform_json_string_values()

text* transform_json_string_values ( text json,
void *  action_state,
JsonTransformStringValuesAction  transform_action 
)

Definition at line 5829 of file jsonfuncs.c.

5831 {
5832  JsonLexContext lex;
5833  JsonSemAction *sem = palloc0(sizeof(JsonSemAction));
5835 
5836  state->lex = makeJsonLexContext(&lex, json, true);
5837  state->strval = makeStringInfo();
5838  state->action = transform_action;
5839  state->action_state = action_state;
5840 
5841  sem->semstate = (void *) state;
5849 
5851  freeJsonLexContext(&lex);
5852 
5853  return cstring_to_text_with_len(state->strval->data, state->strval->len);
5854 }
static JsonParseErrorType transform_string_values_array_start(void *state)
Definition: jsonfuncs.c:5882
static JsonParseErrorType transform_string_values_object_field_start(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:5902
static JsonParseErrorType transform_string_values_array_end(void *state)
Definition: jsonfuncs.c:5892
static JsonParseErrorType transform_string_values_object_end(void *state)
Definition: jsonfuncs.c:5872
static JsonParseErrorType transform_string_values_object_start(void *state)
Definition: jsonfuncs.c:5862
static JsonParseErrorType transform_string_values_array_element_start(void *state, bool isnull)
Definition: jsonfuncs.c:5920
static JsonParseErrorType transform_string_values_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:5931

References JsonSemAction::array_element_start, JsonSemAction::array_end, JsonSemAction::array_start, cstring_to_text_with_len(), freeJsonLexContext(), makeJsonLexContext(), makeStringInfo(), JsonSemAction::object_end, JsonSemAction::object_field_start, JsonSemAction::object_start, palloc0(), pg_parse_json_or_ereport, JsonSemAction::scalar, sem, JsonSemAction::semstate, transform_string_values_array_element_start(), transform_string_values_array_end(), transform_string_values_array_start(), transform_string_values_object_end(), transform_string_values_object_field_start(), transform_string_values_object_start(), and transform_string_values_scalar().

Referenced by ts_headline_json_byid_opt().

◆ transform_jsonb_string_values()

Jsonb* transform_jsonb_string_values ( Jsonb jsonb,
void *  action_state,
JsonTransformStringValuesAction  transform_action 
)

Definition at line 5782 of file jsonfuncs.c.

5784 {
5785  JsonbIterator *it;
5786  JsonbValue v,
5787  *res = NULL;
5789  JsonbParseState *st = NULL;
5790  text *out;
5791  bool is_scalar = false;
5792 
5793  it = JsonbIteratorInit(&jsonb->root);
5794  is_scalar = it->isScalar;
5795 
5796  while ((type = JsonbIteratorNext(&it, &v, false)) != WJB_DONE)
5797  {
5798  if ((type == WJB_VALUE || type == WJB_ELEM) && v.type == jbvString)
5799  {
5800  out = transform_action(action_state, v.val.string.val, v.val.string.len);
5801  /* out is probably not toasted, but let's be sure */
5802  out = pg_detoast_datum_packed(out);
5803  v.val.string.val = VARDATA_ANY(out);
5804  v.val.string.len = VARSIZE_ANY_EXHDR(out);
5805  res = pushJsonbValue(&st, type, type < WJB_BEGIN_ARRAY ? &v : NULL);
5806  }
5807  else
5808  {
5809  res = pushJsonbValue(&st, type, (type == WJB_KEY ||
5810  type == WJB_VALUE ||
5811  type == WJB_ELEM) ? &v : NULL);
5812  }
5813  }
5814 
5815  if (res->type == jbvArray)
5816  res->val.array.rawScalar = is_scalar;
5817 
5818  return JsonbValueToJsonb(res);
5819 }
bool isScalar
Definition: jsonb.h:347

References JsonbIterator::isScalar, jbvArray, jbvString, JsonbIteratorInit(), JsonbIteratorNext(), JsonbValueToJsonb(), pg_detoast_datum_packed(), pushJsonbValue(), res, Jsonb::root, type, JsonbValue::type, JsonbValue::val, VARDATA_ANY, VARSIZE_ANY_EXHDR, WJB_BEGIN_ARRAY, WJB_DONE, WJB_ELEM, WJB_KEY, and WJB_VALUE.

Referenced by ts_headline_jsonb_byid_opt().

◆ transform_string_values_array_element_start()

static JsonParseErrorType transform_string_values_array_element_start ( void *  state,
bool  isnull 
)
static

Definition at line 5920 of file jsonfuncs.c.

5921 {
5923 
5924  if (_state->strval->data[_state->strval->len - 1] != '[')
5925  appendStringInfoCharMacro(_state->strval, ',');
5926 
5927  return JSON_SUCCESS;
5928 }

References appendStringInfoCharMacro, StringInfoData::data, JSON_SUCCESS, StringInfoData::len, and TransformJsonStringValuesState::strval.

Referenced by transform_json_string_values().

◆ transform_string_values_array_end()

static JsonParseErrorType transform_string_values_array_end ( void *  state)
static

Definition at line 5892 of file jsonfuncs.c.

5893 {
5895 
5896  appendStringInfoCharMacro(_state->strval, ']');
5897 
5898  return JSON_SUCCESS;
5899 }

References appendStringInfoCharMacro, JSON_SUCCESS, and TransformJsonStringValuesState::strval.

Referenced by transform_json_string_values().

◆ transform_string_values_array_start()

static JsonParseErrorType transform_string_values_array_start ( void *  state)
static

Definition at line 5882 of file jsonfuncs.c.

5883 {
5885 
5886  appendStringInfoCharMacro(_state->strval, '[');
5887 
5888  return JSON_SUCCESS;
5889 }

References appendStringInfoCharMacro, JSON_SUCCESS, and TransformJsonStringValuesState::strval.

Referenced by transform_json_string_values().

◆ transform_string_values_object_end()

static JsonParseErrorType transform_string_values_object_end ( void *  state)
static

Definition at line 5872 of file jsonfuncs.c.

5873 {
5875 
5876  appendStringInfoCharMacro(_state->strval, '}');
5877 
5878  return JSON_SUCCESS;
5879 }

References appendStringInfoCharMacro, JSON_SUCCESS, and TransformJsonStringValuesState::strval.

Referenced by transform_json_string_values().

◆ transform_string_values_object_field_start()

static JsonParseErrorType transform_string_values_object_field_start ( void *  state,
char *  fname,
bool  isnull 
)
static

Definition at line 5902 of file jsonfuncs.c.

5903 {
5905 
5906  if (_state->strval->data[_state->strval->len - 1] != '{')
5907  appendStringInfoCharMacro(_state->strval, ',');
5908 
5909  /*
5910  * Unfortunately we don't have the quoted and escaped string any more, so
5911  * we have to re-escape it.
5912  */
5913  escape_json(_state->strval, fname);
5914  appendStringInfoCharMacro(_state->strval, ':');
5915 
5916  return JSON_SUCCESS;
5917 }

References appendStringInfoCharMacro, StringInfoData::data, escape_json(), JSON_SUCCESS, StringInfoData::len, and TransformJsonStringValuesState::strval.

Referenced by transform_json_string_values().

◆ transform_string_values_object_start()

static JsonParseErrorType transform_string_values_object_start ( void *  state)
static

Definition at line 5862 of file jsonfuncs.c.

5863 {
5865 
5866  appendStringInfoCharMacro(_state->strval, '{');
5867 
5868  return JSON_SUCCESS;
5869 }

References appendStringInfoCharMacro, JSON_SUCCESS, and TransformJsonStringValuesState::strval.

Referenced by transform_json_string_values().

◆ transform_string_values_scalar()

static JsonParseErrorType transform_string_values_scalar ( void *  state,
char *  token,
JsonTokenType  tokentype 
)
static

Definition at line 5931 of file jsonfuncs.c.

5932 {
5934 
5935  if (tokentype == JSON_TOKEN_STRING)
5936  {
5937  text *out = _state->action(_state->action_state, token, strlen(token));
5938 
5939  escape_json(_state->strval, text_to_cstring(out));
5940  }
5941  else
5943 
5944  return JSON_SUCCESS;
5945 }
JsonTransformStringValuesAction action
Definition: jsonfuncs.c:79

References TransformJsonStringValuesState::action, TransformJsonStringValuesState::action_state, appendStringInfoString(), escape_json(), JSON_SUCCESS, JSON_TOKEN_STRING, TransformJsonStringValuesState::strval, text_to_cstring(), and token.

Referenced by transform_json_string_values().

◆ update_cached_tupdesc()

static void update_cached_tupdesc ( CompositeIOData io,
MemoryContext  mcxt 
)
static

Definition at line 3027 of file jsonfuncs.c.

3028 {
3029  if (!io->tupdesc ||
3030  io->tupdesc->tdtypeid != io->base_typid ||
3031  io->tupdesc->tdtypmod != io->base_typmod)
3032  {
3034  io->base_typmod);
3035  MemoryContext oldcxt;
3036 
3037  if (io->tupdesc)
3038  FreeTupleDesc(io->tupdesc);
3039 
3040  /* copy tuple desc without constraints into cache memory context */
3041  oldcxt = MemoryContextSwitchTo(mcxt);
3042  io->tupdesc = CreateTupleDescCopy(tupdesc);
3043  MemoryContextSwitchTo(oldcxt);
3044 
3045  ReleaseTupleDesc(tupdesc);
3046  }
3047 }
#define ReleaseTupleDesc(tupdesc)
Definition: tupdesc.h:122
TupleDesc lookup_rowtype_tupdesc(Oid type_id, int32 typmod)
Definition: typcache.c:1833

References CompositeIOData::base_typid, CompositeIOData::base_typmod, CreateTupleDescCopy(), FreeTupleDesc(), lookup_rowtype_tupdesc(), MemoryContextSwitchTo(), ReleaseTupleDesc, TupleDescData::tdtypeid, TupleDescData::tdtypmod, and CompositeIOData::tupdesc.

Referenced by populate_composite(), populate_recordset_record(), and populate_recordset_worker().