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/int.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, const 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 52 of file jsonfuncs.c.

◆ JB_PATH_CREATE

#define JB_PATH_CREATE   0x0001

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

◆ JB_PATH_DELETE

#define JB_PATH_DELETE   0x0002

Definition at line 45 of file jsonfuncs.c.

◆ JB_PATH_FILL_GAPS

#define JB_PATH_FILL_GAPS   0x0020

Definition at line 51 of file jsonfuncs.c.

◆ JB_PATH_INSERT_AFTER

#define JB_PATH_INSERT_AFTER   0x0010

Definition at line 48 of file jsonfuncs.c.

◆ JB_PATH_INSERT_BEFORE

#define JB_PATH_INSERT_BEFORE   0x0008

Definition at line 47 of file jsonfuncs.c.

◆ JB_PATH_REPLACE

#define JB_PATH_REPLACE   0x0004

Definition at line 46 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:689

Definition at line 334 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 328 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:30
@ jbvNull
Definition: jsonb.h:228

Definition at line 319 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:20
@ jbvString
Definition: jsonb.h:229

Definition at line 324 of file jsonfuncs.c.

Typedef Documentation

◆ AlenState

typedef struct AlenState AlenState

◆ ArrayIOData

typedef struct ArrayIOData ArrayIOData

◆ ColumnIOData

typedef struct ColumnIOData ColumnIOData

Definition at line 162 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 163 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 199 of file jsonfuncs.c.

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

Function Documentation

◆ alen_array_element_start()

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

Definition at line 1927 of file jsonfuncs.c.

1928{
1929 AlenState *_state = (AlenState *) state;
1930
1931 /* just count up all the level 1 elements */
1932 if (_state->lex->lex_level == 1)
1933 _state->count++;
1934
1935 return JSON_SUCCESS;
1936}
@ JSON_SUCCESS
Definition: jsonapi.h:36
int count
Definition: jsonfuncs.c:105
JsonLexContext * lex
Definition: jsonfuncs.c:104
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 1899 of file jsonfuncs.c.

1900{
1901 AlenState *_state = (AlenState *) state;
1902
1903 /* json structure check */
1904 if (_state->lex->lex_level == 0)
1905 ereport(ERROR,
1906 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1907 errmsg("cannot get array length of a non-array")));
1908
1909 return JSON_SUCCESS;
1910}
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 1913 of file jsonfuncs.c.

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

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

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

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

Referenced by populate_record().

◆ each_array_start()

static JsonParseErrorType each_array_start ( void *  state)
static

Definition at line 2167 of file jsonfuncs.c.

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

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

2120{
2121 EachState *_state = (EachState *) state;
2122 MemoryContext old_cxt;
2123 int len;
2124 text *val;
2125 HeapTuple tuple;
2126 Datum values[2];
2127 bool nulls[2] = {false, false};
2128
2129 /* skip over nested objects */
2130 if (_state->lex->lex_level != 1)
2131 return JSON_SUCCESS;
2132
2133 /* use the tmp context so we can clean up after each tuple is done */
2134 old_cxt = MemoryContextSwitchTo(_state->tmp_cxt);
2135
2136 values[0] = CStringGetTextDatum(fname);
2137
2138 if (isnull && _state->normalize_results)
2139 {
2140 nulls[1] = true;
2141 values[1] = (Datum) 0;
2142 }
2143 else if (_state->next_scalar)
2144 {
2146 _state->next_scalar = false;
2147 }
2148 else
2149 {
2150 len = _state->lex->prev_token_terminator - _state->result_start;
2153 }
2154
2155 tuple = heap_form_tuple(_state->ret_tdesc, values, nulls);
2156
2157 tuplestore_puttuple(_state->tuple_store, tuple);
2158
2159 /* clean up and switch back */
2160 MemoryContextSwitchTo(old_cxt);
2161 MemoryContextReset(_state->tmp_cxt);
2162
2163 return JSON_SUCCESS;
2164}
static Datum values[MAXATTR]
Definition: bootstrap.c:151
#define CStringGetTextDatum(s)
Definition: builtins.h:97
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, const Datum *values, const bool *isnull)
Definition: heaptuple.c:1117
void MemoryContextReset(MemoryContext context)
Definition: mcxt.c:383
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:124
const void size_t len
static Datum PointerGetDatum(const void *X)
Definition: postgres.h:327
uintptr_t Datum
Definition: postgres.h:69
bool normalize_results
Definition: jsonfuncs.c:116
TupleDesc ret_tdesc
Definition: jsonfuncs.c:113
char * normalized_scalar
Definition: jsonfuncs.c:118
const char * result_start
Definition: jsonfuncs.c:115
Tuplestorestate * tuple_store
Definition: jsonfuncs.c:112
MemoryContext tmp_cxt
Definition: jsonfuncs.c:114
bool next_scalar
Definition: jsonfuncs.c:117
const char * prev_token_terminator
Definition: jsonapi.h:107
Definition: c.h:644
void tuplestore_puttuple(Tuplestorestate *state, HeapTuple tuple)
Definition: tuplestore.c:764
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 2097 of file jsonfuncs.c.

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

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

2182{
2183 EachState *_state = (EachState *) state;
2184
2185 /* json structure check */
2186 if (_state->lex->lex_level == 0)
2187 ereport(ERROR,
2188 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2189 errmsg("cannot deconstruct a scalar")));
2190
2191 /* supply de-escaped value if required */
2192 if (_state->next_scalar)
2193 _state->normalized_scalar = token;
2194
2195 return JSON_SUCCESS;
2196}
#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 2057 of file jsonfuncs.c.

2058{
2059 text *json = PG_GETARG_TEXT_PP(0);
2060 JsonLexContext lex;
2062 ReturnSetInfo *rsi;
2064
2065 state = palloc0(sizeof(EachState));
2066 sem = palloc0(sizeof(JsonSemAction));
2067
2068 rsi = (ReturnSetInfo *) fcinfo->resultinfo;
2069
2071 state->tuple_store = rsi->setResult;
2072 state->ret_tdesc = rsi->setDesc;
2073
2074 sem->semstate = state;
2079
2080 state->normalize_results = as_text;
2081 state->next_scalar = false;
2082 state->lex = makeJsonLexContext(&lex, json, true);
2084 "json_each temporary cxt",
2086
2088
2089 MemoryContextDelete(state->tmp_cxt);
2090 freeJsonLexContext(&lex);
2091
2093}
#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:687
JsonLexContext * makeJsonLexContext(JsonLexContext *lex, text *json, bool need_escapes)
Definition: jsonfuncs.c:539
static JsonParseErrorType each_object_field_end(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:2119
static JsonParseErrorType each_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:2181
static JsonParseErrorType each_object_field_start(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:2097
static JsonParseErrorType each_array_start(void *state)
Definition: jsonfuncs.c:2167
#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:158
json_scalar_action scalar
Definition: jsonapi.h:162
void * semstate
Definition: jsonapi.h:153
json_struct_action array_start
Definition: jsonapi.h:156
json_ofield_action object_field_end
Definition: jsonapi.h:159
TupleDesc setDesc
Definition: execnodes.h:358
Tuplestorestate * setResult
Definition: execnodes.h:357
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 1973 of file jsonfuncs.c.

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

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

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

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

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

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

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

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

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

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

2308{
2309 text *json = PG_GETARG_TEXT_PP(0);
2310 JsonLexContext lex;
2312 ReturnSetInfo *rsi;
2314
2315 /* elements only needs escaped strings when as_text */
2316 makeJsonLexContext(&lex, json, as_text);
2317
2318 state = palloc0(sizeof(ElementsState));
2319 sem = palloc0(sizeof(JsonSemAction));
2320
2322 rsi = (ReturnSetInfo *) fcinfo->resultinfo;
2323 state->tuple_store = rsi->setResult;
2324 state->ret_tdesc = rsi->setDesc;
2325
2326 sem->semstate = state;
2331
2332 state->function_name = funcname;
2333 state->normalize_results = as_text;
2334 state->next_scalar = false;
2335 state->lex = &lex;
2337 "json_array_elements temporary cxt",
2339
2341
2342 MemoryContextDelete(state->tmp_cxt);
2343 freeJsonLexContext(&lex);
2344
2346}
#define MAT_SRF_USE_EXPECTED_DESC
Definition: funcapi.h:296
static JsonParseErrorType elements_object_start(void *state)
Definition: jsonfuncs.c:2417
static JsonParseErrorType elements_array_element_end(void *state, bool isnull)
Definition: jsonfuncs.c:2371
static JsonParseErrorType elements_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:2432
static JsonParseErrorType elements_array_element_start(void *state, bool isnull)
Definition: jsonfuncs.c:2349
json_struct_action object_start
Definition: jsonapi.h:154
json_aelem_action array_element_start
Definition: jsonapi.h:160
json_aelem_action array_element_end
Definition: jsonapi.h:161

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

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

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

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

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

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

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

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

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

3812{
3813 HASHCTL ctl;
3814 HTAB *tab;
3817
3818 ctl.keysize = NAMEDATALEN;
3819 ctl.entrysize = sizeof(JsonHashEntry);
3821 tab = hash_create("json object hashtable",
3822 100,
3823 &ctl,
3825
3826 state = palloc0(sizeof(JHashState));
3827 sem = palloc0(sizeof(JsonSemAction));
3828
3829 state->function_name = funcname;
3830 state->hash = tab;
3831 state->lex = makeJsonLexContextCstringLen(NULL, json, len,
3832 GetDatabaseEncoding(), true);
3833
3834 sem->semstate = state;
3839
3840 if (!pg_parse_json_or_errsave(state->lex, sem, escontext))
3841 {
3842 hash_destroy(state->hash);
3843 tab = NULL;
3844 }
3845
3847
3848 return tab;
3849}
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:392
static JsonParseErrorType hash_array_start(void *state)
Definition: jsonfuncs.c:3929
static JsonParseErrorType hash_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:3942
struct JsonHashEntry JsonHashEntry
bool pg_parse_json_or_errsave(JsonLexContext *lex, const JsonSemAction *sem, Node *escontext)
Definition: jsonfuncs.c:518
static JsonParseErrorType hash_object_field_end(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:3878
static JsonParseErrorType hash_object_field_start(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:3852
int GetDatabaseEncoding(void)
Definition: mbutils.c:1261
#define NAMEDATALEN
tree ctl
Definition: radixtree.h:1838
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 1499 of file jsonfuncs.c.

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

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

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

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

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

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

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

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

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

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

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

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

3638{
3639 cache->argtype = get_fn_expr_argtype(fcinfo->flinfo, 0);
3640 prepare_column_cache(&cache->c,
3641 cache->argtype, -1,
3642 cache->fn_mcxt, false);
3643 if (cache->c.typcat != TYPECAT_COMPOSITE &&
3645 ereport(ERROR,
3646 (errcode(ERRCODE_DATATYPE_MISMATCH),
3647 /* translator: %s is a function name, eg json_to_record */
3648 errmsg("first argument of %s must be a row type",
3649 funcname)));
3650}
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:3250
TypeCat typcat
Definition: jsonfuncs.c:215
FmgrInfo * flinfo
Definition: fmgr.h:87
ColumnIOData c
Definition: jsonfuncs.c:240
MemoryContext fn_mcxt
Definition: jsonfuncs.c:241

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

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

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

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

1107{
1109 GetState *state = palloc0(sizeof(GetState));
1110
1111 Assert(npath >= 0);
1112
1113 state->lex = makeJsonLexContext(NULL, json, true);
1114
1115 /* is it "_as_text" variant? */
1116 state->normalize_results = normalize_results;
1117 state->npath = npath;
1118 state->path_names = tpath;
1119 state->path_indexes = ipath;
1120 state->pathok = palloc0(sizeof(bool) * npath);
1121 state->array_cur_index = palloc(sizeof(int) * npath);
1122
1123 if (npath > 0)
1124 state->pathok[0] = true;
1125
1126 sem->semstate = state;
1127
1128 /*
1129 * Not all variants need all the semantic routines. Only set the ones that
1130 * are actually needed for maximum efficiency.
1131 */
1133 if (npath == 0)
1134 {
1139 }
1140 if (tpath != NULL)
1141 {
1144 }
1145 if (ipath != NULL)
1146 {
1150 }
1151
1154
1155 return state->tresult;
1156}
static JsonParseErrorType get_array_element_end(void *state, bool isnull)
Definition: jsonfuncs.c:1400
static JsonParseErrorType get_object_field_start(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:1196
static JsonParseErrorType get_object_start(void *state)
Definition: jsonfuncs.c:1159
static JsonParseErrorType get_array_start(void *state)
Definition: jsonfuncs.c:1294
static JsonParseErrorType get_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:1444
static JsonParseErrorType get_object_end(void *state)
Definition: jsonfuncs.c:1178
static JsonParseErrorType get_object_field_end(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:1243
static JsonParseErrorType get_array_end(void *state)
Definition: jsonfuncs.c:1334
static JsonParseErrorType get_array_element_start(void *state, bool isnull)
Definition: jsonfuncs.c:1352
json_struct_action array_end
Definition: jsonapi.h:157
json_struct_action object_end
Definition: jsonapi.h:155

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

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

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

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

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

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

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

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

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

5711{
5712 JsonLexContext lex;
5715
5716 state->lex = makeJsonLexContext(&lex, json, true);
5717 state->action = action;
5718 state->action_state = action_state;
5719 state->flags = flags;
5720
5721 sem->semstate = state;
5724
5726 freeJsonLexContext(&lex);
5727}
static JsonParseErrorType iterate_values_object_field_start(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:5762
static JsonParseErrorType iterate_values_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:5734

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

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

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

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

5735{
5737
5738 switch (tokentype)
5739 {
5740 case JSON_TOKEN_STRING:
5741 if (_state->flags & jtiString)
5742 _state->action(_state->action_state, token, strlen(token));
5743 break;
5744 case JSON_TOKEN_NUMBER:
5745 if (_state->flags & jtiNumeric)
5746 _state->action(_state->action_state, token, strlen(token));
5747 break;
5748 case JSON_TOKEN_TRUE:
5749 case JSON_TOKEN_FALSE:
5750 if (_state->flags & jtiBool)
5751 _state->action(_state->action_state, token, strlen(token));
5752 break;
5753 default:
5754 /* do not call callback for any other token */
5755 break;
5756 }
5757
5758 return JSON_SUCCESS;
5759}
@ JSON_TOKEN_FALSE
Definition: jsonapi.h:29
@ JSON_TOKEN_TRUE
Definition: jsonapi.h:28
@ JSON_TOKEN_NUMBER
Definition: jsonapi.h:21

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

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

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

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

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, JsValue::len, JsValue::str, JsonHashEntry::type, JsValue::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 921 of file jsonfuncs.c.

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

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

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

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

References elements_worker().

◆ json_array_elements_text()

Datum json_array_elements_text ( PG_FUNCTION_ARGS  )

Definition at line 2301 of file jsonfuncs.c.

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

References elements_worker().

◆ json_array_length()

Datum json_array_length ( PG_FUNCTION_ARGS  )

Definition at line 1851 of file jsonfuncs.c.

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

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

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

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

References each_worker().

◆ json_each_text()

Datum json_each_text ( PG_FUNCTION_ARGS  )

Definition at line 1961 of file jsonfuncs.c.

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

References each_worker().

◆ json_errsave_error()

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

Definition at line 640 of file jsonfuncs.c.

642{
646 errsave(escontext,
647 (errcode(ERRCODE_UNTRANSLATABLE_CHARACTER),
648 errmsg("unsupported Unicode escape sequence"),
650 report_json_context(lex)));
651 else if (error == JSON_SEM_ACTION_FAILED)
652 {
653 /* semantic action function had better have reported something */
654 if (!SOFT_ERROR_OCCURRED(escontext))
655 elog(ERROR, "JSON semantic action function did not provide error information");
656 }
657 else
658 errsave(escontext,
659 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
660 errmsg("invalid input syntax for type %s", "json"),
662 report_json_context(lex)));
663}
int errdetail_internal(const char *fmt,...)
Definition: elog.c:1230
#define errsave(context,...)
Definition: elog.h:261
#define elog(elevel,...)
Definition: elog.h:225
char * json_errdetail(JsonParseErrorType error, JsonLexContext *lex)
Definition: jsonapi.c:2401
@ JSON_SEM_ACTION_FAILED
Definition: jsonapi.h:59
@ JSON_UNICODE_CODE_POINT_ZERO
Definition: jsonapi.h:53
@ JSON_UNICODE_UNTRANSLATABLE
Definition: jsonapi.h:56
@ JSON_UNICODE_HIGH_ESCAPE
Definition: jsonapi.h:55
static int report_json_context(JsonLexContext *lex)
Definition: jsonfuncs.c:676
#define SOFT_ERROR_OCCURRED(escontext)
Definition: miscnodes.h:53

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

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

References get_path_all().

◆ json_extract_path_text()

Datum json_extract_path_text ( PG_FUNCTION_ARGS  )

Definition at line 1014 of file jsonfuncs.c.

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

References get_path_all().

◆ json_get_first_token()

JsonTokenType json_get_first_token ( text json,
bool  throw_error 
)

Definition at line 5949 of file jsonfuncs.c.

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

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

846{
847 text *json = PG_GETARG_TEXT_PP(0);
848 text *fname = PG_GETARG_TEXT_PP(1);
849 char *fnamestr = text_to_cstring(fname);
850 text *result;
851
852 result = get_worker(json, &fnamestr, NULL, 1, false);
853
854 if (result != NULL)
855 PG_RETURN_TEXT_P(result);
856 else
858}
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 883 of file jsonfuncs.c.

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

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

732{
733 FuncCallContext *funcctx;
735
736 if (SRF_IS_FIRSTCALL())
737 {
738 text *json = PG_GETARG_TEXT_PP(0);
739 JsonLexContext lex;
741 MemoryContext oldcontext;
742
743 funcctx = SRF_FIRSTCALL_INIT();
744 oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
745
746 state = palloc(sizeof(OkeysState));
747 sem = palloc0(sizeof(JsonSemAction));
748
749 state->lex = makeJsonLexContext(&lex, json, true);
750 state->result_size = 256;
751 state->result_count = 0;
752 state->sent_count = 0;
753 state->result = palloc(256 * sizeof(char *));
754
755 sem->semstate = state;
759 /* remainder are all NULL, courtesy of palloc0 above */
760
762 /* keys are now in state->result */
763
764 freeJsonLexContext(&lex);
765 pfree(sem);
766
767 MemoryContextSwitchTo(oldcontext);
768 funcctx->user_fctx = state;
769 }
770
771 funcctx = SRF_PERCALL_SETUP();
772 state = (OkeysState *) funcctx->user_fctx;
773
774 if (state->sent_count < state->result_count)
775 {
776 char *nxt = state->result[state->sent_count++];
777
779 }
780
781 SRF_RETURN_DONE(funcctx);
782}
#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:76
static JsonParseErrorType okeys_array_start(void *state)
Definition: jsonfuncs.c:808
static JsonParseErrorType okeys_object_field_start(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:785
static JsonParseErrorType okeys_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:823
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 2494 of file jsonfuncs.c.

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

References populate_record_worker().

◆ json_populate_recordset()

Datum json_populate_recordset ( PG_FUNCTION_ARGS  )

Definition at line 3987 of file jsonfuncs.c.

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

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

3349{
3350 JsValue jsv = {0};
3351 JsonbValue jbv;
3352
3353 jsv.is_json = json_type == JSONOID;
3354
3355 if (*isnull)
3356 {
3357 if (jsv.is_json)
3358 jsv.val.json.str = NULL;
3359 else
3360 jsv.val.jsonb = NULL;
3361 }
3362 else if (jsv.is_json)
3363 {
3364 text *json = DatumGetTextPP(json_val);
3365
3366 jsv.val.json.str = VARDATA_ANY(json);
3367 jsv.val.json.len = VARSIZE_ANY_EXHDR(json);
3368 jsv.val.json.type = JSON_TOKEN_INVALID; /* not used in
3369 * populate_composite() */
3370 }
3371 else
3372 {
3373 Jsonb *jsonb = DatumGetJsonbP(json_val);
3374
3375 jsv.val.jsonb = &jbv;
3376
3377 if (omit_quotes)
3378 {
3379 char *str = JsonbUnquote(DatumGetJsonbP(json_val));
3380
3381 /* fill the quote-stripped string */
3382 jbv.type = jbvString;
3383 jbv.val.string.len = strlen(str);
3384 jbv.val.string.val = str;
3385 }
3386 else
3387 {
3388 /* fill binary jsonb value pointing to jb */
3389 jbv.type = jbvBinary;
3390 jbv.val.binary.data = &jsonb->root;
3391 jbv.val.binary.len = VARSIZE(jsonb) - VARHDRSZ;
3392 }
3393 }
3394
3395 if (*cache == NULL)
3396 *cache = MemoryContextAllocZero(mcxt, sizeof(ColumnIOData));
3397
3398 return populate_record_field(*cache, typid, typmod, NULL, mcxt,
3399 PointerGetDatum(NULL), &jsv, isnull,
3400 escontext, omit_quotes);
3401}
#define VARHDRSZ
Definition: c.h:649
#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:3405
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(), JsValue::len, MemoryContextAllocZero(), PointerGetDatum(), populate_record_field(), Jsonb::root, JsValue::str, str, JsValue::type, 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 4493 of file jsonfuncs.c.

4494{
4495 text *json = PG_GETARG_TEXT_PP(0);
4497 JsonLexContext lex;
4499
4500 state = palloc0(sizeof(StripnullState));
4501 sem = palloc0(sizeof(JsonSemAction));
4502
4503 state->lex = makeJsonLexContext(&lex, json, true);
4504 state->strval = makeStringInfo();
4505 state->skip_next_null = false;
4506
4507 sem->semstate = state;
4512 sem->scalar = sn_scalar;
4515
4517
4519 state->strval->len));
4520}
static JsonParseErrorType sn_object_end(void *state)
Definition: jsonfuncs.c:4399
static JsonParseErrorType sn_array_element_start(void *state, bool isnull)
Definition: jsonfuncs.c:4459
static JsonParseErrorType sn_object_start(void *state)
Definition: jsonfuncs.c:4389
static JsonParseErrorType sn_array_start(void *state)
Definition: jsonfuncs.c:4409
static JsonParseErrorType sn_array_end(void *state)
Definition: jsonfuncs.c:4419
static JsonParseErrorType sn_object_field_start(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:4429
static JsonParseErrorType sn_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:4470
StringInfo makeStringInfo(void)
Definition: stringinfo.c:72

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

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

References populate_record_worker().

◆ json_to_recordset()

Datum json_to_recordset ( PG_FUNCTION_ARGS  )

Definition at line 3994 of file jsonfuncs.c.

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

References populate_recordset_worker().

◆ jsonb_array_element()

Datum jsonb_array_element ( PG_FUNCTION_ARGS  )

Definition at line 936 of file jsonfuncs.c.

937{
938 Jsonb *jb = PG_GETARG_JSONB_P(0);
939 int element = PG_GETARG_INT32(1);
940 JsonbValue *v;
941
942 if (!JB_ROOT_IS_ARRAY(jb))
944
945 /* Handle negative subscript */
946 if (element < 0)
947 {
948 uint32 nelements = JB_ROOT_COUNT(jb);
949
950 if (pg_abs_s32(element) > nelements)
952 else
953 element += nelements;
954 }
955
957 if (v != NULL)
959
961}
uint32_t uint32
Definition: c.h:488
static uint32 pg_abs_s32(int32 a)
Definition: int.h:221
#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:475

References element(), getIthJsonbValueFromContainer(), JB_ROOT_COUNT, JB_ROOT_IS_ARRAY, JsonbValueToJsonb(), pg_abs_s32(), 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 979 of file jsonfuncs.c.

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

References element(), getIthJsonbValueFromContainer(), JB_ROOT_COUNT, JB_ROOT_IS_ARRAY, jbvNull, JsonbValueAsText(), pg_abs_s32(), 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 2207 of file jsonfuncs.c.

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

References elements_worker_jsonb().

◆ jsonb_array_elements_text()

Datum jsonb_array_elements_text ( PG_FUNCTION_ARGS  )

Definition at line 2213 of file jsonfuncs.c.

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

References elements_worker_jsonb().

◆ jsonb_array_length()

Datum jsonb_array_length ( PG_FUNCTION_ARGS  )

Definition at line 1877 of file jsonfuncs.c.

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

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

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

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

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

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

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

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

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

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

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

References each_worker_jsonb().

◆ jsonb_each_text()

Datum jsonb_each_text ( PG_FUNCTION_ARGS  )

Definition at line 1967 of file jsonfuncs.c.

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

References each_worker_jsonb().

◆ jsonb_extract_path()

Datum jsonb_extract_path ( PG_FUNCTION_ARGS  )

Definition at line 1487 of file jsonfuncs.c.

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

References get_jsonb_path_all().

◆ jsonb_extract_path_text()

Datum jsonb_extract_path_text ( PG_FUNCTION_ARGS  )

Definition at line 1493 of file jsonfuncs.c.

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

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

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

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

5005{
5006 Jsonb *in = PG_GETARG_JSONB_P(0);
5008 Jsonb *newjsonb = PG_GETARG_JSONB_P(2);
5010 bool after = PG_GETARG_BOOL(3);
5011 JsonbValue *res = NULL;
5012 Datum *path_elems;
5013 bool *path_nulls;
5014 int path_len;
5015 JsonbIterator *it;
5016 JsonbParseState *st = NULL;
5017
5018 JsonbToJsonbValue(newjsonb, &newval);
5019
5020 if (ARR_NDIM(path) > 1)
5021 ereport(ERROR,
5022 (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
5023 errmsg("wrong number of array subscripts")));
5024
5025 if (JB_ROOT_IS_SCALAR(in))
5026 ereport(ERROR,
5027 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
5028 errmsg("cannot set path in scalar")));
5029
5030 deconstruct_array_builtin(path, TEXTOID, &path_elems, &path_nulls, &path_len);
5031
5032 if (path_len == 0)
5034
5035 it = JsonbIteratorInit(&in->root);
5036
5037 res = setPath(&it, path_elems, path_nulls, path_len, &st, 0, &newval,
5039
5040 Assert(res != NULL);
5041
5043}
#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:47
#define JB_PATH_INSERT_AFTER
Definition: jsonfuncs.c:48

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

◆ jsonb_object_field_text()

◆ jsonb_object_keys()

Datum jsonb_object_keys ( PG_FUNCTION_ARGS  )

Definition at line 567 of file jsonfuncs.c.

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

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

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

References populate_record_worker().

◆ jsonb_populate_record_valid()

Datum jsonb_populate_record_valid ( PG_FUNCTION_ARGS  )

Definition at line 2476 of file jsonfuncs.c.

2477{
2478 ErrorSaveContext escontext = {T_ErrorSaveContext};
2479
2480 (void) populate_record_worker(fcinfo, "jsonb_populate_record",
2481 false, true, (Node *) &escontext);
2482
2483 return BoolGetDatum(!escontext.error_occurred);
2484}
static Datum BoolGetDatum(bool X)
Definition: postgres.h:107
bool error_occurred
Definition: miscnodes.h:47
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 3973 of file jsonfuncs.c.

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

References populate_recordset_worker().

◆ jsonb_pretty()

Datum jsonb_pretty ( PG_FUNCTION_ARGS  )

Definition at line 4584 of file jsonfuncs.c.

4585{
4586 Jsonb *jb = PG_GETARG_JSONB_P(0);
4588
4590
4592}
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 4845 of file jsonfuncs.c.

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

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

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

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

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

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

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

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

References populate_record_worker().

◆ jsonb_to_recordset()

Datum jsonb_to_recordset ( PG_FUNCTION_ARGS  )

Definition at line 3980 of file jsonfuncs.c.

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

References populate_recordset_worker().

◆ JsonbValueAsText()

static text * JsonbValueAsText ( JsonbValue v)
static

Definition at line 1804 of file jsonfuncs.c.

1805{
1806 switch (v->type)
1807 {
1808 case jbvNull:
1809 return NULL;
1810
1811 case jbvBool:
1812 return v->val.boolean ?
1813 cstring_to_text_with_len("true", 4) :
1814 cstring_to_text_with_len("false", 5);
1815
1816 case jbvString:
1817 return cstring_to_text_with_len(v->val.string.val,
1818 v->val.string.len);
1819
1820 case jbvNumeric:
1821 {
1822 Datum cstr;
1823
1825 PointerGetDatum(v->val.numeric));
1826
1827 return cstring_to_text(DatumGetCString(cstr));
1828 }
1829
1830 case jbvBinary:
1831 {
1832 StringInfoData jtext;
1833
1834 initStringInfo(&jtext);
1835 (void) JsonbToCString(&jtext, v->val.binary.data,
1836 v->val.binary.len);
1837
1838 return cstring_to_text_with_len(jtext.data, jtext.len);
1839 }
1840
1841 default:
1842 elog(ERROR, "unrecognized jsonb type: %d", (int) v->type);
1843 return NULL;
1844 }
1845}
void initStringInfo(StringInfo str)
Definition: stringinfo.c:97

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

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

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, JsValue::len, SOFT_ERROR_OCCURRED, JsValue::str, 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 539 of file jsonfuncs.c.

540{
541 /*
542 * Most callers pass a detoasted datum, but it's not clear that they all
543 * do. pg_detoast_datum_packed() is cheap insurance.
544 */
545 json = pg_detoast_datum_packed(json);
546
548 VARDATA_ANY(json),
549 VARSIZE_ANY_EXHDR(json),
551 need_escapes);
552}
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 808 of file jsonfuncs.c.

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

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

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

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

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

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

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

Definition at line 518 of file jsonfuncs.c.

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

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

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

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, JsValue::len, makeMdArrayResult(), PopulateArrayContext::mcxt, PopulateArrayContext::ndims, palloc(), pfree(), populate_array_dim_jsonb(), populate_array_json(), PopulateArrayContext::sizes, JsValue::str, and JsValue::val.

Referenced by populate_record_field().

◆ populate_array_array_end()

static JsonParseErrorType populate_array_array_end ( void *  _state)
static

Definition at line 2667 of file jsonfuncs.c.

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

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

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

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

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

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

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