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

Go to the source code of this file.

Data Structures

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

Macros

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

Typedefs

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

Enumerations

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

Functions

static int report_json_context (JsonLexContext *lex)
 
static JsonParseErrorType okeys_object_field_start (void *state, char *fname, bool isnull)
 
static JsonParseErrorType okeys_array_start (void *state)
 
static JsonParseErrorType okeys_scalar (void *state, char *token, JsonTokenType tokentype)
 
static JsonParseErrorType get_object_start (void *state)
 
static JsonParseErrorType get_object_end (void *state)
 
static JsonParseErrorType get_object_field_start (void *state, char *fname, bool isnull)
 
static JsonParseErrorType get_object_field_end (void *state, char *fname, bool isnull)
 
static JsonParseErrorType get_array_start (void *state)
 
static JsonParseErrorType get_array_end (void *state)
 
static JsonParseErrorType get_array_element_start (void *state, bool isnull)
 
static JsonParseErrorType get_array_element_end (void *state, bool isnull)
 
static JsonParseErrorType get_scalar (void *state, char *token, JsonTokenType tokentype)
 
static Datum get_path_all (FunctionCallInfo fcinfo, bool as_text)
 
static textget_worker (text *json, char **tpath, int *ipath, int npath, bool normalize_results)
 
static Datum get_jsonb_path_all (FunctionCallInfo fcinfo, bool as_text)
 
static textJsonbValueAsText (JsonbValue *v)
 
static JsonParseErrorType alen_object_start (void *state)
 
static JsonParseErrorType alen_scalar (void *state, char *token, JsonTokenType tokentype)
 
static JsonParseErrorType alen_array_element_start (void *state, bool isnull)
 
static Datum each_worker (FunctionCallInfo fcinfo, bool as_text)
 
static Datum each_worker_jsonb (FunctionCallInfo fcinfo, const char *funcname, bool as_text)
 
static JsonParseErrorType each_object_field_start (void *state, char *fname, bool isnull)
 
static JsonParseErrorType each_object_field_end (void *state, char *fname, bool isnull)
 
static JsonParseErrorType each_array_start (void *state)
 
static JsonParseErrorType each_scalar (void *state, char *token, JsonTokenType tokentype)
 
static Datum elements_worker (FunctionCallInfo fcinfo, const char *funcname, bool as_text)
 
static Datum elements_worker_jsonb (FunctionCallInfo fcinfo, const char *funcname, bool as_text)
 
static JsonParseErrorType elements_object_start (void *state)
 
static JsonParseErrorType elements_array_element_start (void *state, bool isnull)
 
static JsonParseErrorType elements_array_element_end (void *state, bool isnull)
 
static JsonParseErrorType elements_scalar (void *state, char *token, JsonTokenType tokentype)
 
static HTABget_json_object_as_hash (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)
 
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)
 
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, 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)
 
static JsonbValueIteratorConcat (JsonbIterator **it1, JsonbIterator **it2, JsonbParseState **state)
 
static JsonbValuesetPath (JsonbIterator **it, Datum *path_elems, bool *path_nulls, int path_len, JsonbParseState **st, int level, JsonbValue *newval, int op_type)
 
static void setPathObject (JsonbIterator **it, Datum *path_elems, bool *path_nulls, int path_len, JsonbParseState **st, int level, JsonbValue *newval, uint32 npairs, int op_type)
 
static void setPathArray (JsonbIterator **it, Datum *path_elems, bool *path_nulls, int path_len, JsonbParseState **st, int level, JsonbValue *newval, uint32 nelems, int op_type)
 
static JsonParseErrorType iterate_values_scalar (void *state, char *token, JsonTokenType tokentype)
 
static JsonParseErrorType iterate_values_object_field_start (void *state, char *fname, bool isnull)
 
static JsonParseErrorType transform_string_values_object_start (void *state)
 
static JsonParseErrorType transform_string_values_object_end (void *state)
 
static JsonParseErrorType transform_string_values_array_start (void *state)
 
static JsonParseErrorType transform_string_values_array_end (void *state)
 
static JsonParseErrorType transform_string_values_object_field_start (void *state, char *fname, bool isnull)
 
static JsonParseErrorType transform_string_values_array_element_start (void *state, bool isnull)
 
static JsonParseErrorType transform_string_values_scalar (void *state, char *token, JsonTokenType tokentype)
 
bool pg_parse_json_or_errsave (JsonLexContext *lex, JsonSemAction *sem, Node *escontext)
 
JsonLexContextmakeJsonLexContext (JsonLexContext *lex, text *json, bool need_escapes)
 
Datum jsonb_object_keys (PG_FUNCTION_ARGS)
 
void json_errsave_error (JsonParseErrorType error, JsonLexContext *lex, Node *escontext)
 
Datum json_object_keys (PG_FUNCTION_ARGS)
 
Datum json_object_field (PG_FUNCTION_ARGS)
 
Datum jsonb_object_field (PG_FUNCTION_ARGS)
 
Datum json_object_field_text (PG_FUNCTION_ARGS)
 
Datum jsonb_object_field_text (PG_FUNCTION_ARGS)
 
Datum json_array_element (PG_FUNCTION_ARGS)
 
Datum jsonb_array_element (PG_FUNCTION_ARGS)
 
Datum json_array_element_text (PG_FUNCTION_ARGS)
 
Datum jsonb_array_element_text (PG_FUNCTION_ARGS)
 
Datum json_extract_path (PG_FUNCTION_ARGS)
 
Datum json_extract_path_text (PG_FUNCTION_ARGS)
 
Datum jsonb_extract_path (PG_FUNCTION_ARGS)
 
Datum jsonb_extract_path_text (PG_FUNCTION_ARGS)
 
Datum jsonb_get_element (Jsonb *jb, Datum *path, int npath, bool *isnull, bool as_text)
 
Datum jsonb_set_element (Jsonb *jb, Datum *path, int path_len, JsonbValue *newval)
 
static void push_null_elements (JsonbParseState **ps, int num)
 
static void push_path (JsonbParseState **st, int level, Datum *path_elems, bool *path_nulls, int path_len, JsonbValue *newval)
 
Datum json_array_length (PG_FUNCTION_ARGS)
 
Datum jsonb_array_length (PG_FUNCTION_ARGS)
 
Datum json_each (PG_FUNCTION_ARGS)
 
Datum jsonb_each (PG_FUNCTION_ARGS)
 
Datum json_each_text (PG_FUNCTION_ARGS)
 
Datum jsonb_each_text (PG_FUNCTION_ARGS)
 
Datum jsonb_array_elements (PG_FUNCTION_ARGS)
 
Datum jsonb_array_elements_text (PG_FUNCTION_ARGS)
 
Datum json_array_elements (PG_FUNCTION_ARGS)
 
Datum json_array_elements_text (PG_FUNCTION_ARGS)
 
Datum jsonb_populate_record (PG_FUNCTION_ARGS)
 
Datum jsonb_populate_record_valid (PG_FUNCTION_ARGS)
 
Datum jsonb_to_record (PG_FUNCTION_ARGS)
 
Datum json_populate_record (PG_FUNCTION_ARGS)
 
Datum json_to_record (PG_FUNCTION_ARGS)
 
static void update_cached_tupdesc (CompositeIOData *io, MemoryContext mcxt)
 
Datum json_populate_type (Datum json_val, Oid json_type, Oid typid, int32 typmod, void **cache, MemoryContext mcxt, bool *isnull, Node *escontext)
 
Datum jsonb_populate_recordset (PG_FUNCTION_ARGS)
 
Datum jsonb_to_recordset (PG_FUNCTION_ARGS)
 
Datum json_populate_recordset (PG_FUNCTION_ARGS)
 
Datum json_to_recordset (PG_FUNCTION_ARGS)
 
Datum json_strip_nulls (PG_FUNCTION_ARGS)
 
Datum jsonb_strip_nulls (PG_FUNCTION_ARGS)
 
Datum jsonb_pretty (PG_FUNCTION_ARGS)
 
Datum jsonb_concat (PG_FUNCTION_ARGS)
 
Datum jsonb_delete (PG_FUNCTION_ARGS)
 
Datum jsonb_delete_array (PG_FUNCTION_ARGS)
 
Datum jsonb_delete_idx (PG_FUNCTION_ARGS)
 
Datum jsonb_set (PG_FUNCTION_ARGS)
 
Datum jsonb_set_lax (PG_FUNCTION_ARGS)
 
Datum jsonb_delete_path (PG_FUNCTION_ARGS)
 
Datum jsonb_insert (PG_FUNCTION_ARGS)
 
uint32 parse_jsonb_index_flags (Jsonb *jb)
 
void iterate_jsonb_values (Jsonb *jb, uint32 flags, void *state, JsonIterateStringValuesAction action)
 
void iterate_json_values (text *json, uint32 flags, void *action_state, JsonIterateStringValuesAction action)
 
Jsonbtransform_jsonb_string_values (Jsonb *jsonb, void *action_state, JsonTransformStringValuesAction transform_action)
 
texttransform_json_string_values (text *json, void *action_state, JsonTransformStringValuesAction transform_action)
 
JsonTokenType json_get_first_token (text *json, bool throw_error)
 
void json_categorize_type (Oid typoid, bool is_jsonb, JsonTypeCategory *tcategory, Oid *outfuncoid)
 

Macro Definition Documentation

◆ JB_PATH_CONSISTENT_POSITION

#define JB_PATH_CONSISTENT_POSITION   0x0040

Definition at line 51 of file jsonfuncs.c.

◆ JB_PATH_CREATE

#define JB_PATH_CREATE   0x0001

Definition at line 43 of file jsonfuncs.c.

◆ JB_PATH_CREATE_OR_INSERT

#define JB_PATH_CREATE_OR_INSERT    (JB_PATH_INSERT_BEFORE | JB_PATH_INSERT_AFTER | JB_PATH_CREATE)

Definition at line 48 of file jsonfuncs.c.

◆ JB_PATH_DELETE

#define JB_PATH_DELETE   0x0002

Definition at line 44 of file jsonfuncs.c.

◆ JB_PATH_FILL_GAPS

#define JB_PATH_FILL_GAPS   0x0020

Definition at line 50 of file jsonfuncs.c.

◆ JB_PATH_INSERT_AFTER

#define JB_PATH_INSERT_AFTER   0x0010

Definition at line 47 of file jsonfuncs.c.

◆ JB_PATH_INSERT_BEFORE

#define JB_PATH_INSERT_BEFORE   0x0008

Definition at line 46 of file jsonfuncs.c.

◆ JB_PATH_REPLACE

#define JB_PATH_REPLACE   0x0004

Definition at line 45 of file jsonfuncs.c.

◆ JsObjectFree

#define JsObjectFree (   jso)
Value:
do { \
if ((jso)->is_json) \
hash_destroy((jso)->val.json_hash); \
} while (0)
long val
Definition: informix.c:670

Definition at line 333 of file jsonfuncs.c.

◆ JsObjectIsEmpty

#define JsObjectIsEmpty (   jso)
Value:
((jso)->is_json \
? hash_get_num_entries((jso)->val.json_hash) == 0 \
: ((jso)->val.jsonb_cont == NULL || \
JsonContainerSize((jso)->val.jsonb_cont) == 0))
long hash_get_num_entries(HTAB *hashp)
Definition: dynahash.c:1341

Definition at line 327 of file jsonfuncs.c.

◆ JsValueIsNull

#define JsValueIsNull (   jsv)
Value:
((jsv)->is_json ? \
(!(jsv)->val.json.str || (jsv)->val.json.type == JSON_TOKEN_NULL) : \
(!(jsv)->val.jsonb || (jsv)->val.jsonb->type == jbvNull))
@ JSON_TOKEN_NULL
Definition: jsonapi.h:32
@ jbvNull
Definition: jsonb.h:228

Definition at line 318 of file jsonfuncs.c.

◆ JsValueIsString

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

Definition at line 323 of file jsonfuncs.c.

Typedef Documentation

◆ AlenState

typedef struct AlenState AlenState

◆ ArrayIOData

typedef struct ArrayIOData ArrayIOData

◆ ColumnIOData

typedef struct ColumnIOData ColumnIOData

Definition at line 1 of file jsonfuncs.c.

◆ CompositeIOData

◆ DomainIOData

typedef struct DomainIOData DomainIOData

◆ EachState

typedef struct EachState EachState

◆ ElementsState

typedef struct ElementsState ElementsState

◆ GetState

typedef struct GetState GetState

◆ IterateJsonStringValuesState

◆ JHashState

typedef struct JHashState JHashState

◆ JsObject

typedef struct JsObject JsObject

◆ JsonHashEntry

typedef struct JsonHashEntry JsonHashEntry

◆ JsValue

typedef struct JsValue JsValue

◆ OkeysState

typedef struct OkeysState OkeysState

◆ PopulateArrayContext

◆ PopulateArrayState

◆ PopulateRecordCache

◆ PopulateRecordsetState

◆ RecordIOData

typedef struct RecordIOData RecordIOData

Definition at line 1 of file jsonfuncs.c.

◆ ScalarIOData

typedef struct ScalarIOData ScalarIOData

◆ StripnullState

◆ TransformJsonStringValuesState

◆ TypeCat

typedef enum TypeCat TypeCat

Enumeration Type Documentation

◆ TypeCat

enum TypeCat
Enumerator
TYPECAT_SCALAR 
TYPECAT_ARRAY 
TYPECAT_COMPOSITE 
TYPECAT_COMPOSITE_DOMAIN 
TYPECAT_DOMAIN 

Definition at line 198 of file jsonfuncs.c.

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

Function Documentation

◆ alen_array_element_start()

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

Definition at line 1925 of file jsonfuncs.c.

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

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

Referenced by json_array_length().

◆ alen_object_start()

static JsonParseErrorType alen_object_start ( void *  state)
static

Definition at line 1897 of file jsonfuncs.c.

1898 {
1899  AlenState *_state = (AlenState *) state;
1900 
1901  /* json structure check */
1902  if (_state->lex->lex_level == 0)
1903  ereport(ERROR,
1904  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1905  errmsg("cannot get array length of a non-array")));
1906 
1907  return JSON_SUCCESS;
1908 }
int errcode(int sqlerrcode)
Definition: elog.c:859
int errmsg(const char *fmt,...)
Definition: elog.c:1072
#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 1911 of file jsonfuncs.c.

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

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

3454 {
3456  MemoryContextAlloc(mcxt,
3457  offsetof(RecordIOData, columns) +
3458  ncolumns * sizeof(ColumnIOData));
3459 
3460  data->record_type = InvalidOid;
3461  data->record_typmod = 0;
3462  data->ncolumns = ncolumns;
3463  MemSet(data->columns, 0, sizeof(ColumnIOData) * ncolumns);
3464 
3465  return data;
3466 }
#define MemSet(start, val, len)
Definition: c.h:1020
struct ColumnIOData ColumnIOData
Definition: jsonfuncs.c:161
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:1180
const void * data
#define InvalidOid
Definition: postgres_ext.h:36

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

Referenced by populate_record().

◆ each_array_start()

static JsonParseErrorType each_array_start ( void *  state)
static

Definition at line 2165 of file jsonfuncs.c.

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

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

Referenced by each_worker().

◆ each_object_field_end()

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

Definition at line 2117 of file jsonfuncs.c.

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

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

References JSON_SUCCESS, JSON_TOKEN_STRING, EachState::lex, JsonLexContext::lex_level, EachState::next_scalar, EachState::normalize_results, EachState::result_start, JsonLexContext::token_start, and JsonLexContext::token_type.

Referenced by each_worker().

◆ each_scalar()

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

Definition at line 2179 of file jsonfuncs.c.

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

2056 {
2057  text *json = PG_GETARG_TEXT_PP(0);
2058  JsonLexContext lex;
2059  JsonSemAction *sem;
2060  ReturnSetInfo *rsi;
2061  EachState *state;
2062 
2063  state = palloc0(sizeof(EachState));
2064  sem = palloc0(sizeof(JsonSemAction));
2065 
2066  rsi = (ReturnSetInfo *) fcinfo->resultinfo;
2067 
2069  state->tuple_store = rsi->setResult;
2070  state->ret_tdesc = rsi->setDesc;
2071 
2072  sem->semstate = (void *) state;
2074  sem->scalar = each_scalar;
2077 
2078  state->normalize_results = as_text;
2079  state->next_scalar = false;
2080  state->lex = makeJsonLexContext(&lex, json, true);
2082  "json_each temporary cxt",
2084 
2086 
2087  MemoryContextDelete(state->tmp_cxt);
2088  freeJsonLexContext(&lex);
2089 
2090  PG_RETURN_NULL();
2091 }
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:309
#define PG_RETURN_NULL()
Definition: fmgr.h:345
void InitMaterializedSRF(FunctionCallInfo fcinfo, bits32 flags)
Definition: funcapi.c:76
#define MAT_SRF_BLESS
Definition: funcapi.h:297
void freeJsonLexContext(JsonLexContext *lex)
Definition: jsonapi.c:482
JsonLexContext * makeJsonLexContext(JsonLexContext *lex, text *json, bool need_escapes)
Definition: jsonfuncs.c:537
static JsonParseErrorType each_object_field_end(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:2117
static JsonParseErrorType each_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:2179
static JsonParseErrorType each_object_field_start(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:2095
static JsonParseErrorType each_array_start(void *state)
Definition: jsonfuncs.c:2165
#define pg_parse_json_or_ereport(lex, sem)
Definition: jsonfuncs.h:47
void * palloc0(Size size)
Definition: mcxt.c:1346
MemoryContext CurrentMemoryContext
Definition: mcxt.c:143
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:454
#define AllocSetContextCreate
Definition: memutils.h:129
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:160
fmNodePtr resultinfo
Definition: fmgr.h:89
json_ofield_action object_field_start
Definition: jsonapi.h:139
json_scalar_action scalar
Definition: jsonapi.h:143
void * semstate
Definition: jsonapi.h:134
json_struct_action array_start
Definition: jsonapi.h:137
json_ofield_action object_field_end
Definition: jsonapi.h:140
TupleDesc setDesc
Definition: execnodes.h:340
Tuplestorestate * setResult
Definition: execnodes.h:339
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 1971 of file jsonfuncs.c.

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

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

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

References cstring_to_text_with_len(), CStringGetTextDatum, heap_form_tuple(), JSON_SUCCESS, len, ElementsState::lex, JsonLexContext::lex_level, MemoryContextReset(), MemoryContextSwitchTo(), ElementsState::next_scalar, ElementsState::normalize_results, ElementsState::normalized_scalar, PointerGetDatum(), JsonLexContext::prev_token_terminator, ElementsState::result_start, ElementsState::ret_tdesc, ElementsState::tmp_cxt, ElementsState::tuple_store, tuplestore_puttuple(), val, and values.

Referenced by elements_worker().

◆ elements_array_element_start()

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

Definition at line 2347 of file jsonfuncs.c.

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

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

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

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

Referenced by elements_worker().

◆ elements_scalar()

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

Definition at line 2430 of file jsonfuncs.c.

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

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

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

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, JsonSemAction::array_element_end, JsonSemAction::array_element_start, CurrentMemoryContext, elements_array_element_end(), elements_array_element_start(), elements_object_start(), elements_scalar(), freeJsonLexContext(), funcname, InitMaterializedSRF(), makeJsonLexContext(), MAT_SRF_BLESS, MAT_SRF_USE_EXPECTED_DESC, MemoryContextDelete(), JsonSemAction::object_start, palloc0(), PG_GETARG_TEXT_PP, pg_parse_json_or_ereport, PG_RETURN_NULL, FunctionCallInfoBaseData::resultinfo, JsonSemAction::scalar, sem, JsonSemAction::semstate, ReturnSetInfo::setDesc, and ReturnSetInfo::setResult.

Referenced by json_array_elements(), and json_array_elements_text().

◆ elements_worker_jsonb()

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

Definition at line 2217 of file jsonfuncs.c.

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

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

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

Referenced by get_worker().

◆ get_array_element_start()

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

Definition at line 1350 of file jsonfuncs.c.

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

References GetState::array_cur_index, JSON_SUCCESS, JSON_TOKEN_STRING, GetState::lex, JsonLexContext::lex_level, GetState::next_scalar, GetState::normalize_results, GetState::path_indexes, GetState::pathok, GetState::result_start, JsonLexContext::token_start, JsonLexContext::token_type, and GetState::tresult.

Referenced by get_worker().

◆ get_array_end()

static JsonParseErrorType get_array_end ( void *  state)
static

Definition at line 1332 of file jsonfuncs.c.

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

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

Referenced by get_worker().

◆ get_array_start()

static JsonParseErrorType get_array_start ( void *  state)
static

Definition at line 1292 of file jsonfuncs.c.

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

Definition at line 3787 of file jsonfuncs.c.

3789 {
3790  HASHCTL ctl;
3791  HTAB *tab;
3792  JHashState *state;
3793  JsonSemAction *sem;
3794 
3795  ctl.keysize = NAMEDATALEN;
3796  ctl.entrysize = sizeof(JsonHashEntry);
3797  ctl.hcxt = CurrentMemoryContext;
3798  tab = hash_create("json object hashtable",
3799  100,
3800  &ctl,
3802 
3803  state = palloc0(sizeof(JHashState));
3804  sem = palloc0(sizeof(JsonSemAction));
3805 
3806  state->function_name = funcname;
3807  state->hash = tab;
3808  state->lex = makeJsonLexContextCstringLen(NULL, json, len,
3809  GetDatabaseEncoding(), true);
3810 
3811  sem->semstate = (void *) state;
3813  sem->scalar = hash_scalar;
3816 
3817  if (!pg_parse_json_or_errsave(state->lex, sem, escontext))
3818  {
3819  hash_destroy(state->hash);
3820  tab = NULL;
3821  }
3822 
3823  freeJsonLexContext(state->lex);
3824 
3825  return tab;
3826 }
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, char *json, int len, int encoding, bool need_escapes)
Definition: jsonapi.c:326
static JsonParseErrorType hash_array_start(void *state)
Definition: jsonfuncs.c:3906
static JsonParseErrorType hash_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:3919
struct JsonHashEntry JsonHashEntry
bool pg_parse_json_or_errsave(JsonLexContext *lex, JsonSemAction *sem, Node *escontext)
Definition: jsonfuncs.c:516
static JsonParseErrorType hash_object_field_end(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:3855
static JsonParseErrorType hash_object_field_start(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:3829
int GetDatabaseEncoding(void)
Definition: mbutils.c:1261
#define NAMEDATALEN
tree ctl
Definition: radixtree.h:1847
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 1497 of file jsonfuncs.c.

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

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

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

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

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

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

Referenced by get_worker().

◆ get_object_field_start()

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

Definition at line 1194 of file jsonfuncs.c.

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

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

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

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

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

References array_contains_nulls(), Assert, deconstruct_array_builtin(), get_worker(), i, palloc(), PG_GETARG_ARRAYTYPE_P, PG_GETARG_TEXT_PP, PG_RETURN_NULL, PG_RETURN_TEXT_P, strtoint(), and TextDatumGetCString.

Referenced by json_extract_path(), and json_extract_path_text().

◆ get_record_type_from_argument()

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

Definition at line 3612 of file jsonfuncs.c.

3615 {
3616  cache->argtype = get_fn_expr_argtype(fcinfo->flinfo, 0);
3617  prepare_column_cache(&cache->c,
3618  cache->argtype, -1,
3619  cache->fn_mcxt, false);
3620  if (cache->c.typcat != TYPECAT_COMPOSITE &&
3621  cache->c.typcat != TYPECAT_COMPOSITE_DOMAIN)
3622  ereport(ERROR,
3623  (errcode(ERRCODE_DATATYPE_MISMATCH),
3624  /* translator: %s is a function name, eg json_to_record */
3625  errmsg("first argument of %s must be a row type",
3626  funcname)));
3627 }
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:3241
TypeCat typcat
Definition: jsonfuncs.c:214
FmgrInfo * flinfo
Definition: fmgr.h:87
ColumnIOData c
Definition: jsonfuncs.c:239
MemoryContext fn_mcxt
Definition: jsonfuncs.c:240

References PopulateRecordCache::argtype, PopulateRecordCache::c, ereport, errcode(), errmsg(), ERROR, FunctionCallInfoBaseData::flinfo, PopulateRecordCache::fn_mcxt, funcname, get_fn_expr_argtype(), prepare_column_cache(), ColumnIOData::typcat, TYPECAT_COMPOSITE, and TYPECAT_COMPOSITE_DOMAIN.

Referenced by populate_record_worker(), and populate_recordset_worker().

◆ get_record_type_from_query()

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

Definition at line 3638 of file jsonfuncs.c.

3641 {
3642  TupleDesc tupdesc;
3643  MemoryContext old_cxt;
3644 
3645  if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
3646  ereport(ERROR,
3647  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3648  /* translator: %s is a function name, eg json_to_record */
3649  errmsg("could not determine row type for result of %s",
3650  funcname),
3651  errhint("Provide a non-null record argument, "
3652  "or call the function in the FROM clause "
3653  "using a column definition list.")));
3654 
3655  Assert(tupdesc);
3656  cache->argtype = tupdesc->tdtypeid;
3657 
3658  /* If we go through this more than once, avoid memory leak */
3659  if (cache->c.io.composite.tupdesc)
3661 
3662  /* Save identified tupdesc */
3663  old_cxt = MemoryContextSwitchTo(cache->fn_mcxt);
3664  cache->c.io.composite.tupdesc = CreateTupleDescCopy(tupdesc);
3665  cache->c.io.composite.base_typid = tupdesc->tdtypeid;
3666  cache->c.io.composite.base_typmod = tupdesc->tdtypmod;
3667  MemoryContextSwitchTo(old_cxt);
3668 }
int errhint(const char *fmt,...)
Definition: elog.c:1319
TypeFuncClass get_call_result_type(FunctionCallInfo fcinfo, Oid *resultTypeId, TupleDesc *resultTupleDesc)
Definition: funcapi.c:276
@ TYPEFUNC_COMPOSITE
Definition: funcapi.h:149
CompositeIOData composite
Definition: jsonfuncs.c:220
union ColumnIOData::@26 io
int32 base_typmod
Definition: jsonfuncs.c:183
TupleDesc tupdesc
Definition: jsonfuncs.c:180
int32 tdtypmod
Definition: tupdesc.h:83
Oid tdtypeid
Definition: tupdesc.h:82
void FreeTupleDesc(TupleDesc tupdesc)
Definition: tupdesc.c:331
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
Definition: tupdesc.c:133

References PopulateRecordCache::argtype, Assert, CompositeIOData::base_typid, CompositeIOData::base_typmod, PopulateRecordCache::c, ColumnIOData::composite, CreateTupleDescCopy(), ereport, errcode(), errhint(), errmsg(), ERROR, PopulateRecordCache::fn_mcxt, FreeTupleDesc(), funcname, get_call_result_type(), ColumnIOData::io, MemoryContextSwitchTo(), TupleDescData::tdtypeid, TupleDescData::tdtypmod, CompositeIOData::tupdesc, and TYPEFUNC_COMPOSITE.

Referenced by populate_record_worker(), and populate_recordset_worker().

◆ get_scalar()

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

Definition at line 1442 of file jsonfuncs.c.

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

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

Referenced by get_worker().

◆ get_worker()

static text * get_worker ( text json,
char **  tpath,
int *  ipath,
int  npath,
bool  normalize_results 
)
static

Definition at line 1100 of file jsonfuncs.c.

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

References JsonSemAction::array_element_end, JsonSemAction::array_element_start, JsonSemAction::array_end, JsonSemAction::array_start, Assert, freeJsonLexContext(), get_array_element_end(), get_array_element_start(), get_array_end(), get_array_start(), get_object_end(), get_object_field_end(), get_object_field_start(), get_object_start(), get_scalar(), makeJsonLexContext(), JsonSemAction::object_end, JsonSemAction::object_field_end, JsonSemAction::object_field_start, JsonSemAction::object_start, palloc(), palloc0(), pg_parse_json_or_ereport, JsonSemAction::scalar, sem, and JsonSemAction::semstate.

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

◆ hash_array_start()

static JsonParseErrorType hash_array_start ( void *  state)
static

Definition at line 3906 of file jsonfuncs.c.

3907 {
3908  JHashState *_state = (JHashState *) state;
3909 
3910  if (_state->lex->lex_level == 0)
3911  ereport(ERROR,
3912  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3913  errmsg("cannot call %s on an array", _state->function_name)));
3914 
3915  return JSON_SUCCESS;
3916 }
const char * function_name
Definition: jsonfuncs.c:138
JsonLexContext * lex
Definition: jsonfuncs.c:137

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

Referenced by get_json_object_as_hash().

◆ hash_object_field_end()

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

Definition at line 3855 of file jsonfuncs.c.

3856 {
3857  JHashState *_state = (JHashState *) state;
3858  JsonHashEntry *hashentry;
3859  bool found;
3860 
3861  /*
3862  * Ignore nested fields.
3863  */
3864  if (_state->lex->lex_level > 1)
3865  return JSON_SUCCESS;
3866 
3867  /*
3868  * Ignore field names >= NAMEDATALEN - they can't match a record field.
3869  * (Note: without this test, the hash code would truncate the string at
3870  * NAMEDATALEN-1, and could then match against a similarly-truncated
3871  * record field name. That would be a reasonable behavior, but this code
3872  * has previously insisted on exact equality, so we keep this behavior.)
3873  */
3874  if (strlen(fname) >= NAMEDATALEN)
3875  return JSON_SUCCESS;
3876 
3877  hashentry = hash_search(_state->hash, fname, HASH_ENTER, &found);
3878 
3879  /*
3880  * found being true indicates a duplicate. We don't do anything about
3881  * that, a later field with the same name overrides the earlier field.
3882  */
3883 
3884  hashentry->type = _state->saved_token_type;
3885  Assert(isnull == (hashentry->type == JSON_TOKEN_NULL));
3886 
3887  if (_state->save_json_start != NULL)
3888  {
3889  int len = _state->lex->prev_token_terminator - _state->save_json_start;
3890  char *val = palloc((len + 1) * sizeof(char));
3891 
3892  memcpy(val, _state->save_json_start, len);
3893  val[len] = '\0';
3894  hashentry->val = val;
3895  }
3896  else
3897  {
3898  /* must have had a scalar instead */
3899  hashentry->val = _state->saved_scalar;
3900  }
3901 
3902  return JSON_SUCCESS;
3903 }
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:955
@ HASH_ENTER
Definition: hsearch.h:114
char * saved_scalar
Definition: jsonfuncs.c:140
JsonTokenType saved_token_type
Definition: jsonfuncs.c:142
char * save_json_start
Definition: jsonfuncs.c:141
HTAB * hash
Definition: jsonfuncs.c:139
char * val
Definition: jsonfuncs.c:149
JsonTokenType type
Definition: jsonfuncs.c:150

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

Referenced by get_json_object_as_hash().

◆ hash_object_field_start()

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

Definition at line 3829 of file jsonfuncs.c.

3830 {
3831  JHashState *_state = (JHashState *) state;
3832 
3833  if (_state->lex->lex_level > 1)
3834  return JSON_SUCCESS;
3835 
3836  /* remember token type */
3837  _state->saved_token_type = _state->lex->token_type;
3838 
3839  if (_state->lex->token_type == JSON_TOKEN_ARRAY_START ||
3841  {
3842  /* remember start position of the whole text of the subobject */
3843  _state->save_json_start = _state->lex->token_start;
3844  }
3845  else
3846  {
3847  /* must be a scalar */
3848  _state->save_json_start = NULL;
3849  }
3850 
3851  return JSON_SUCCESS;
3852 }
@ JSON_TOKEN_OBJECT_START
Definition: jsonapi.h:24
@ JSON_TOKEN_ARRAY_START
Definition: jsonapi.h:26

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

Referenced by get_json_object_as_hash().

◆ hash_scalar()

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

Definition at line 3919 of file jsonfuncs.c.

3920 {
3921  JHashState *_state = (JHashState *) state;
3922 
3923  if (_state->lex->lex_level == 0)
3924  ereport(ERROR,
3925  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3926  errmsg("cannot call %s on a scalar", _state->function_name)));
3927 
3928  if (_state->lex->lex_level == 1)
3929  {
3930  _state->saved_scalar = token;
3931  /* saved_token_type must already be set in hash_object_field_start() */
3932  Assert(_state->saved_token_type == tokentype);
3933  }
3934 
3935  return JSON_SUCCESS;
3936 }

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

5688 {
5689  JsonLexContext lex;
5690  JsonSemAction *sem = palloc0(sizeof(JsonSemAction));
5692 
5693  state->lex = makeJsonLexContext(&lex, json, true);
5694  state->action = action;
5695  state->action_state = action_state;
5696  state->flags = flags;
5697 
5698  sem->semstate = (void *) state;
5701 
5703  freeJsonLexContext(&lex);
5704 }
static JsonParseErrorType iterate_values_object_field_start(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:5739
static JsonParseErrorType iterate_values_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:5711

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

5620 {
5621  JsonbIterator *it;
5622  JsonbValue v;
5624 
5625  it = JsonbIteratorInit(&jb->root);
5626 
5627  /*
5628  * Just recursively iterating over jsonb and call callback on all
5629  * corresponding elements
5630  */
5631  while ((type = JsonbIteratorNext(&it, &v, false)) != WJB_DONE)
5632  {
5633  if (type == WJB_KEY)
5634  {
5635  if (flags & jtiKey)
5636  action(state, v.val.string.val, v.val.string.len);
5637 
5638  continue;
5639  }
5640  else if (!(type == WJB_VALUE || type == WJB_ELEM))
5641  {
5642  /* do not call callback for composite JsonbValue */
5643  continue;
5644  }
5645 
5646  /* JsonbValue is a value of object or element of array */
5647  switch (v.type)
5648  {
5649  case jbvString:
5650  if (flags & jtiString)
5651  action(state, v.val.string.val, v.val.string.len);
5652  break;
5653  case jbvNumeric:
5654  if (flags & jtiNumeric)
5655  {
5656  char *val;
5657 
5659  NumericGetDatum(v.val.numeric)));
5660 
5661  action(state, val, strlen(val));
5662  pfree(val);
5663  }
5664  break;
5665  case jbvBool:
5666  if (flags & jtiBool)
5667  {
5668  if (v.val.boolean)
5669  action(state, "true", 4);
5670  else
5671  action(state, "false", 5);
5672  }
5673  break;
5674  default:
5675  /* do not call callback for composite JsonbValue */
5676  break;
5677  }
5678  }
5679 }
Datum numeric_out(PG_FUNCTION_ARGS)
Definition: numeric.c:807
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:642
@ jbvNumeric
Definition: jsonb.h:230
@ jbvBool
Definition: jsonb.h:231
@ WJB_VALUE
Definition: jsonb.h:24
@ jtiKey
Definition: jsonfuncs.h:27
@ jtiNumeric
Definition: jsonfuncs.h:29
@ jtiBool
Definition: jsonfuncs.h:30
@ jtiString
Definition: jsonfuncs.h:28
void pfree(void *pointer)
Definition: mcxt.c:1520
static Datum NumericGetDatum(Numeric X)
Definition: numeric.h:73
static char * DatumGetCString(Datum X)
Definition: postgres.h:335
const char * type

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

Referenced by jsonb_to_tsvector_worker().

◆ iterate_values_object_field_start()

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

Definition at line 5739 of file jsonfuncs.c.

5740 {
5742 
5743  if (_state->flags & jtiKey)
5744  {
5745  char *val = pstrdup(fname);
5746 
5747  _state->action(_state->action_state, val, strlen(val));
5748  }
5749 
5750  return JSON_SUCCESS;
5751 }
char * pstrdup(const char *in)
Definition: mcxt.c:1695
JsonIterateStringValuesAction action
Definition: jsonfuncs.c:67

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

Referenced by iterate_json_values().

◆ iterate_values_scalar()

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

Definition at line 5711 of file jsonfuncs.c.

5712 {
5714 
5715  switch (tokentype)
5716  {
5717  case JSON_TOKEN_STRING:
5718  if (_state->flags & jtiString)
5719  _state->action(_state->action_state, token, strlen(token));
5720  break;
5721  case JSON_TOKEN_NUMBER:
5722  if (_state->flags & jtiNumeric)
5723  _state->action(_state->action_state, token, strlen(token));
5724  break;
5725  case JSON_TOKEN_TRUE:
5726  case JSON_TOKEN_FALSE:
5727  if (_state->flags & jtiBool)
5728  _state->action(_state->action_state, token, strlen(token));
5729  break;
5730  default:
5731  /* do not call callback for any other token */
5732  break;
5733  }
5734 
5735  return JSON_SUCCESS;
5736 }
@ JSON_TOKEN_FALSE
Definition: jsonapi.h:31
@ JSON_TOKEN_TRUE
Definition: jsonapi.h:30
@ JSON_TOKEN_NUMBER
Definition: jsonapi.h:23

References IterateJsonStringValuesState::action, IterateJsonStringValuesState::action_state, IterateJsonStringValuesState::flags, JSON_SUCCESS, JSON_TOKEN_FALSE, JSON_TOKEN_NUMBER, JSON_TOKEN_STRING, JSON_TOKEN_TRUE, jtiBool, jtiNumeric, jtiString, and token.

Referenced by iterate_json_values().

◆ IteratorConcat()

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

Definition at line 5030 of file jsonfuncs.c.

5032 {
5033  JsonbValue v1,
5034  v2,
5035  *res = NULL;
5036  JsonbIteratorToken r1,
5037  r2,
5038  rk1,
5039  rk2;
5040 
5041  rk1 = JsonbIteratorNext(it1, &v1, false);
5042  rk2 = JsonbIteratorNext(it2, &v2, false);
5043 
5044  /*
5045  * JsonbIteratorNext reports raw scalars as if they were single-element
5046  * arrays; hence we only need consider "object" and "array" cases here.
5047  */
5048  if (rk1 == WJB_BEGIN_OBJECT && rk2 == WJB_BEGIN_OBJECT)
5049  {
5050  /*
5051  * Both inputs are objects.
5052  *
5053  * Append all the tokens from v1 to res, except last WJB_END_OBJECT
5054  * (because res will not be finished yet).
5055  */
5056  pushJsonbValue(state, rk1, NULL);
5057  while ((r1 = JsonbIteratorNext(it1, &v1, true)) != WJB_END_OBJECT)
5058  pushJsonbValue(state, r1, &v1);
5059 
5060  /*
5061  * Append all the tokens from v2 to res, including last WJB_END_OBJECT
5062  * (the concatenation will be completed). Any duplicate keys will
5063  * automatically override the value from the first object.
5064  */
5065  while ((r2 = JsonbIteratorNext(it2, &v2, true)) != WJB_DONE)
5066  res = pushJsonbValue(state, r2, r2 != WJB_END_OBJECT ? &v2 : NULL);
5067  }
5068  else if (rk1 == WJB_BEGIN_ARRAY && rk2 == WJB_BEGIN_ARRAY)
5069  {
5070  /*
5071  * Both inputs are arrays.
5072  */
5073  pushJsonbValue(state, rk1, NULL);
5074 
5075  while ((r1 = JsonbIteratorNext(it1, &v1, true)) != WJB_END_ARRAY)
5076  {
5077  Assert(r1 == WJB_ELEM);
5078  pushJsonbValue(state, r1, &v1);
5079  }
5080 
5081  while ((r2 = JsonbIteratorNext(it2, &v2, true)) != WJB_END_ARRAY)
5082  {
5083  Assert(r2 == WJB_ELEM);
5084  pushJsonbValue(state, WJB_ELEM, &v2);
5085  }
5086 
5087  res = pushJsonbValue(state, WJB_END_ARRAY, NULL /* signal to sort */ );
5088  }
5089  else if (rk1 == WJB_BEGIN_OBJECT)
5090  {
5091  /*
5092  * We have object || array.
5093  */
5094  Assert(rk2 == WJB_BEGIN_ARRAY);
5095 
5097 
5099  while ((r1 = JsonbIteratorNext(it1, &v1, true)) != WJB_DONE)
5100  pushJsonbValue(state, r1, r1 != WJB_END_OBJECT ? &v1 : NULL);
5101 
5102  while ((r2 = JsonbIteratorNext(it2, &v2, true)) != WJB_DONE)
5103  res = pushJsonbValue(state, r2, r2 != WJB_END_ARRAY ? &v2 : NULL);
5104  }
5105  else
5106  {
5107  /*
5108  * We have array || object.
5109  */
5110  Assert(rk1 == WJB_BEGIN_ARRAY);
5111  Assert(rk2 == WJB_BEGIN_OBJECT);
5112 
5114 
5115  while ((r1 = JsonbIteratorNext(it1, &v1, true)) != WJB_END_ARRAY)
5116  pushJsonbValue(state, r1, &v1);
5117 
5119  while ((r2 = JsonbIteratorNext(it2, &v2, true)) != WJB_DONE)
5120  pushJsonbValue(state, r2, r2 != WJB_END_OBJECT ? &v2 : NULL);
5121 
5123  }
5124 
5125  return res;
5126 }
@ WJB_END_ARRAY
Definition: jsonb.h:27
@ WJB_END_OBJECT
Definition: jsonb.h:29
@ WJB_BEGIN_OBJECT
Definition: jsonb.h:28
@ WJB_BEGIN_ARRAY
Definition: jsonb.h:26
JsonbValue * pushJsonbValue(JsonbParseState **pstate, JsonbIteratorToken seq, JsonbValue *jbval)
Definition: jsonb_util.c:566

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

Referenced by jsonb_concat().

◆ JsObjectGetField()

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

Definition at line 3469 of file jsonfuncs.c.

3470 {
3471  jsv->is_json = obj->is_json;
3472 
3473  if (jsv->is_json)
3474  {
3475  JsonHashEntry *hashentry = hash_search(obj->val.json_hash, field,
3476  HASH_FIND, NULL);
3477 
3478  jsv->val.json.type = hashentry ? hashentry->type : JSON_TOKEN_NULL;
3479  jsv->val.json.str = jsv->val.json.type == JSON_TOKEN_NULL ? NULL :
3480  hashentry->val;
3481  jsv->val.json.len = jsv->val.json.str ? -1 : 0; /* null-terminated */
3482 
3483  return hashentry != NULL;
3484  }
3485  else
3486  {
3487  jsv->val.jsonb = !obj->val.jsonb_cont ? NULL :
3488  getKeyJsonValueFromContainer(obj->val.jsonb_cont, field, strlen(field),
3489  NULL);
3490 
3491  return jsv->val.jsonb != NULL;
3492  }
3493 }
@ HASH_FIND
Definition: hsearch.h:113
JsonbValue * getKeyJsonValueFromContainer(JsonbContainer *container, const char *keyVal, int keyLen, JsonbValue *res)
Definition: jsonb_util.c:398
bool is_json
Definition: jsonfuncs.c:309
JsonbContainer * jsonb_cont
Definition: jsonfuncs.c:313
HTAB * json_hash
Definition: jsonfuncs.c:312
union JsObject::@29 val
union JsValue::@27 val
JsonbValue * jsonb
Definition: jsonfuncs.c:303
struct JsValue::@27::@28 json
bool is_json
Definition: jsonfuncs.c:293

References getKeyJsonValueFromContainer(), HASH_FIND, hash_search(), JsValue::is_json, JsObject::is_json, JsValue::json, JsObject::json_hash, JSON_TOKEN_NULL, JsValue::jsonb, JsObject::jsonb_cont, JsonHashEntry::type, JsonHashEntry::val, JsValue::val, and JsObject::val.

Referenced by populate_record().

◆ json_array_element()

Datum json_array_element ( PG_FUNCTION_ARGS  )

Definition at line 919 of file jsonfuncs.c.

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

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

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

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

References elements_worker().

◆ json_array_elements_text()

Datum json_array_elements_text ( PG_FUNCTION_ARGS  )

Definition at line 2299 of file jsonfuncs.c.

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

References elements_worker().

◆ json_array_length()

Datum json_array_length ( PG_FUNCTION_ARGS  )

Definition at line 1849 of file jsonfuncs.c.

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

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

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

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

References each_worker().

◆ json_each_text()

Datum json_each_text ( PG_FUNCTION_ARGS  )

Definition at line 1959 of file jsonfuncs.c.

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

References each_worker().

◆ json_errsave_error()

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

Definition at line 638 of file jsonfuncs.c.

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

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

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

◆ json_extract_path()

Datum json_extract_path ( PG_FUNCTION_ARGS  )

Definition at line 1006 of file jsonfuncs.c.

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

References get_path_all().

◆ json_extract_path_text()

Datum json_extract_path_text ( PG_FUNCTION_ARGS  )

Definition at line 1012 of file jsonfuncs.c.

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

References get_path_all().

◆ json_get_first_token()

JsonTokenType json_get_first_token ( text json,
bool  throw_error 
)

Definition at line 5926 of file jsonfuncs.c.

5927 {
5928  JsonLexContext lex;
5929  JsonParseErrorType result;
5930 
5931  makeJsonLexContext(&lex, json, false);
5932 
5933  /* Lex exactly one token from the input and check its type. */
5934  result = json_lex(&lex);
5935 
5936  if (result == JSON_SUCCESS)
5937  return lex.token_type;
5938 
5939  if (throw_error)
5940  json_errsave_error(result, &lex, NULL);
5941 
5942  return JSON_TOKEN_INVALID; /* invalid json */
5943 }
JsonParseErrorType json_lex(JsonLexContext *lex)
Definition: jsonapi.c:1308
@ JSON_TOKEN_INVALID
Definition: jsonapi.h:21

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

Referenced by ExecEvalJsonIsPredicate().

◆ json_object_field()

Datum json_object_field ( PG_FUNCTION_ARGS  )

Definition at line 843 of file jsonfuncs.c.

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

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

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

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

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

References populate_record_worker().

◆ json_populate_recordset()

Datum json_populate_recordset ( PG_FUNCTION_ARGS  )

Definition at line 3964 of file jsonfuncs.c.

3965 {
3966  return populate_recordset_worker(fcinfo, "json_populate_recordset",
3967  true, true);
3968 }
static Datum populate_recordset_worker(FunctionCallInfo fcinfo, const char *funcname, bool is_json, bool have_record_arg)
Definition: jsonfuncs.c:4017

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

Definition at line 3335 of file jsonfuncs.c.

3340 {
3341  JsValue jsv = {0};
3342  JsonbValue jbv;
3343 
3344  jsv.is_json = json_type == JSONOID;
3345 
3346  if (*isnull)
3347  {
3348  if (jsv.is_json)
3349  jsv.val.json.str = NULL;
3350  else
3351  jsv.val.jsonb = NULL;
3352  }
3353  else if (jsv.is_json)
3354  {
3355  text *json = DatumGetTextPP(json_val);
3356 
3357  jsv.val.json.str = VARDATA_ANY(json);
3358  jsv.val.json.len = VARSIZE_ANY_EXHDR(json);
3359  jsv.val.json.type = JSON_TOKEN_INVALID; /* not used in
3360  * populate_composite() */
3361  }
3362  else
3363  {
3364  Jsonb *jsonb = DatumGetJsonbP(json_val);
3365 
3366  jsv.val.jsonb = &jbv;
3367 
3368  /* fill binary jsonb value pointing to jb */
3369  jbv.type = jbvBinary;
3370  jbv.val.binary.data = &jsonb->root;
3371  jbv.val.binary.len = VARSIZE(jsonb) - VARHDRSZ;
3372  }
3373 
3374  if (*cache == NULL)
3375  *cache = MemoryContextAllocZero(mcxt, sizeof(ColumnIOData));
3376 
3377  return populate_record_field(*cache, typid, typmod, NULL, mcxt,
3378  PointerGetDatum(NULL), &jsv, isnull,
3379  escontext);
3380 }
#define VARHDRSZ
Definition: c.h:692
#define DatumGetTextPP(X)
Definition: fmgr.h:292
@ 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)
Definition: jsonfuncs.c:3384
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition: mcxt.c:1214
#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, JsValue::json, JSON_TOKEN_INVALID, JsValue::jsonb, MemoryContextAllocZero(), PointerGetDatum(), populate_record_field(), Jsonb::root, JsonbValue::type, JsValue::val, JsonbValue::val, VARDATA_ANY, VARHDRSZ, VARSIZE, and VARSIZE_ANY_EXHDR.

Referenced by ExecEvalJsonCoercion().

◆ json_strip_nulls()

Datum json_strip_nulls ( PG_FUNCTION_ARGS  )

Definition at line 4470 of file jsonfuncs.c.

4471 {
4472  text *json = PG_GETARG_TEXT_PP(0);
4474  JsonLexContext lex;
4475  JsonSemAction *sem;
4476 
4477  state = palloc0(sizeof(StripnullState));
4478  sem = palloc0(sizeof(JsonSemAction));
4479 
4480  state->lex = makeJsonLexContext(&lex, json, true);
4481  state->strval = makeStringInfo();
4482  state->skip_next_null = false;
4483 
4484  sem->semstate = (void *) state;
4489  sem->scalar = sn_scalar;
4492 
4494 
4496  state->strval->len));
4497 }
static JsonParseErrorType sn_object_end(void *state)
Definition: jsonfuncs.c:4376
static JsonParseErrorType sn_array_element_start(void *state, bool isnull)
Definition: jsonfuncs.c:4436
static JsonParseErrorType sn_object_start(void *state)
Definition: jsonfuncs.c:4366
static JsonParseErrorType sn_array_start(void *state)
Definition: jsonfuncs.c:4386
static JsonParseErrorType sn_array_end(void *state)
Definition: jsonfuncs.c:4396
static JsonParseErrorType sn_object_field_start(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:4406
static JsonParseErrorType sn_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:4447
StringInfo makeStringInfo(void)
Definition: stringinfo.c:41

References JsonSemAction::array_element_start, JsonSemAction::array_end, JsonSemAction::array_start, cstring_to_text_with_len(), makeJsonLexContext(), makeStringInfo(), JsonSemAction::object_end, JsonSemAction::object_field_start, JsonSemAction::object_start, palloc0(), PG_GETARG_TEXT_PP, pg_parse_json_or_ereport, PG_RETURN_TEXT_P, JsonSemAction::scalar, sem, JsonSemAction::semstate, sn_array_element_start(), sn_array_end(), sn_array_start(), sn_object_end(), sn_object_field_start(), sn_object_start(), and sn_scalar().

◆ json_to_record()

Datum json_to_record ( PG_FUNCTION_ARGS  )

Definition at line 2499 of file jsonfuncs.c.

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

References populate_record_worker().

◆ json_to_recordset()

Datum json_to_recordset ( PG_FUNCTION_ARGS  )

Definition at line 3971 of file jsonfuncs.c.

3972 {
3973  return populate_recordset_worker(fcinfo, "json_to_recordset",
3974  true, false);
3975 }

References populate_recordset_worker().

◆ jsonb_array_element()

Datum jsonb_array_element ( PG_FUNCTION_ARGS  )

Definition at line 934 of file jsonfuncs.c.

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

References element(), getIthJsonbValueFromContainer(), JB_ROOT_COUNT, JB_ROOT_IS_ARRAY, JsonbValueToJsonb(), PG_GETARG_INT32, PG_GETARG_JSONB_P, PG_RETURN_JSONB_P, PG_RETURN_NULL, and Jsonb::root.

◆ jsonb_array_element_text()

Datum jsonb_array_element_text ( PG_FUNCTION_ARGS  )

Definition at line 977 of file jsonfuncs.c.

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

References element(), getIthJsonbValueFromContainer(), JB_ROOT_COUNT, JB_ROOT_IS_ARRAY, jbvNull, JsonbValueAsText(), PG_GETARG_INT32, PG_GETARG_JSONB_P, PG_RETURN_NULL, PG_RETURN_TEXT_P, Jsonb::root, and JsonbValue::type.

◆ jsonb_array_elements()

Datum jsonb_array_elements ( PG_FUNCTION_ARGS  )

Definition at line 2205 of file jsonfuncs.c.

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

References elements_worker_jsonb().

◆ jsonb_array_elements_text()

Datum jsonb_array_elements_text ( PG_FUNCTION_ARGS  )

Definition at line 2211 of file jsonfuncs.c.

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

References elements_worker_jsonb().

◆ jsonb_array_length()

Datum jsonb_array_length ( PG_FUNCTION_ARGS  )

Definition at line 1875 of file jsonfuncs.c.

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

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

4578 {
4579  Jsonb *jb1 = PG_GETARG_JSONB_P(0);
4580  Jsonb *jb2 = PG_GETARG_JSONB_P(1);
4581  JsonbParseState *state = NULL;
4582  JsonbValue *res;
4583  JsonbIterator *it1,
4584  *it2;
4585 
4586  /*
4587  * If one of the jsonb is empty, just return the other if it's not scalar
4588  * and both are of the same kind. If it's a scalar or they are of
4589  * different kinds we need to perform the concatenation even if one is
4590  * empty.
4591  */
4592  if (JB_ROOT_IS_OBJECT(jb1) == JB_ROOT_IS_OBJECT(jb2))
4593  {
4594  if (JB_ROOT_COUNT(jb1) == 0 && !JB_ROOT_IS_SCALAR(jb2))
4595  PG_RETURN_JSONB_P(jb2);
4596  else if (JB_ROOT_COUNT(jb2) == 0 && !JB_ROOT_IS_SCALAR(jb1))
4597  PG_RETURN_JSONB_P(jb1);
4598  }
4599 
4600  it1 = JsonbIteratorInit(&jb1->root);
4601  it2 = JsonbIteratorInit(&jb2->root);
4602 
4603  res = IteratorConcat(&it1, &it2, &state);
4604 
4605  Assert(res != NULL);
4606 
4608 }
static JsonbValue * IteratorConcat(JsonbIterator **it1, JsonbIterator **it2, JsonbParseState **state)
Definition: jsonfuncs.c:5030

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

4619 {
4620  Jsonb *in = PG_GETARG_JSONB_P(0);
4621  text *key = PG_GETARG_TEXT_PP(1);
4622  char *keyptr = VARDATA_ANY(key);
4623  int keylen = VARSIZE_ANY_EXHDR(key);
4624  JsonbParseState *state = NULL;
4625  JsonbIterator *it;
4626  JsonbValue v,
4627  *res = NULL;
4628  bool skipNested = false;
4630 
4631  if (JB_ROOT_IS_SCALAR(in))
4632  ereport(ERROR,
4633  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4634  errmsg("cannot delete from scalar")));
4635 
4636  if (JB_ROOT_COUNT(in) == 0)
4637  PG_RETURN_JSONB_P(in);
4638 
4639  it = JsonbIteratorInit(&in->root);
4640 
4641  while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE)
4642  {
4643  skipNested = true;
4644 
4645  if ((r == WJB_ELEM || r == WJB_KEY) &&
4646  (v.type == jbvString && keylen == v.val.string.len &&
4647  memcmp(keyptr, v.val.string.val, keylen) == 0))
4648  {
4649  /* skip corresponding value as well */
4650  if (r == WJB_KEY)
4651  (void) JsonbIteratorNext(&it, &v, true);
4652 
4653  continue;
4654  }
4655 
4656  res = pushJsonbValue(&state, r, r < WJB_BEGIN_ARRAY ? &v : NULL);
4657  }
4658 
4659  Assert(res != NULL);
4660 
4662 }

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

4672 {
4673  Jsonb *in = PG_GETARG_JSONB_P(0);
4674  ArrayType *keys = PG_GETARG_ARRAYTYPE_P(1);
4675  Datum *keys_elems;
4676  bool *keys_nulls;
4677  int keys_len;
4678  JsonbParseState *state = NULL;
4679  JsonbIterator *it;
4680  JsonbValue v,
4681  *res = NULL;
4682  bool skipNested = false;
4684 
4685  if (ARR_NDIM(keys) > 1)
4686  ereport(ERROR,
4687  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
4688  errmsg("wrong number of array subscripts")));
4689 
4690  if (JB_ROOT_IS_SCALAR(in))
4691  ereport(ERROR,
4692  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4693  errmsg("cannot delete from scalar")));
4694 
4695  if (JB_ROOT_COUNT(in) == 0)
4696  PG_RETURN_JSONB_P(in);
4697 
4698  deconstruct_array_builtin(keys, TEXTOID, &keys_elems, &keys_nulls, &keys_len);
4699 
4700  if (keys_len == 0)
4701  PG_RETURN_JSONB_P(in);
4702 
4703  it = JsonbIteratorInit(&in->root);
4704 
4705  while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE)
4706  {
4707  skipNested = true;
4708 
4709  if ((r == WJB_ELEM || r == WJB_KEY) && v.type == jbvString)
4710  {
4711  int i;
4712  bool found = false;
4713 
4714  for (i = 0; i < keys_len; i++)
4715  {
4716  char *keyptr;
4717  int keylen;
4718 
4719  if (keys_nulls[i])
4720  continue;
4721 
4722  /* We rely on the array elements not being toasted */
4723  keyptr = VARDATA_ANY(keys_elems[i]);
4724  keylen = VARSIZE_ANY_EXHDR(keys_elems[i]);
4725  if (keylen == v.val.string.len &&
4726  memcmp(keyptr, v.val.string.val, keylen) == 0)
4727  {
4728  found = true;
4729  break;
4730  }
4731  }
4732  if (found)
4733  {
4734  /* skip corresponding value as well */
4735  if (r == WJB_KEY)
4736  (void) JsonbIteratorNext(&it, &v, true);
4737 
4738  continue;
4739  }
4740  }
4741 
4742  res = pushJsonbValue(&state, r, r < WJB_BEGIN_ARRAY ? &v : NULL);
4743  }
4744 
4745  Assert(res != NULL);
4746 
4748 }
#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 4758 of file jsonfuncs.c.

4759 {
4760  Jsonb *in = PG_GETARG_JSONB_P(0);
4761  int idx = PG_GETARG_INT32(1);
4762  JsonbParseState *state = NULL;
4763  JsonbIterator *it;
4764  uint32 i = 0,
4765  n;
4766  JsonbValue v,
4767  *res = NULL;
4769 
4770  if (JB_ROOT_IS_SCALAR(in))
4771  ereport(ERROR,
4772  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4773  errmsg("cannot delete from scalar")));
4774 
4775  if (JB_ROOT_IS_OBJECT(in))
4776  ereport(ERROR,
4777  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4778  errmsg("cannot delete from object using integer index")));
4779 
4780  if (JB_ROOT_COUNT(in) == 0)
4781  PG_RETURN_JSONB_P(in);
4782 
4783  it = JsonbIteratorInit(&in->root);
4784 
4785  r = JsonbIteratorNext(&it, &v, false);
4786  Assert(r == WJB_BEGIN_ARRAY);
4787  n = v.val.array.nElems;
4788 
4789  if (idx < 0)
4790  {
4791  if (-idx > n)
4792  idx = n;
4793  else
4794  idx = n + idx;
4795  }
4796 
4797  if (idx >= n)
4798  PG_RETURN_JSONB_P(in);
4799 
4800  pushJsonbValue(&state, r, NULL);
4801 
4802  while ((r = JsonbIteratorNext(&it, &v, true)) != WJB_DONE)
4803  {
4804  if (r == WJB_ELEM)
4805  {
4806  if (i++ == idx)
4807  continue;
4808  }
4809 
4810  res = pushJsonbValue(&state, r, r < WJB_BEGIN_ARRAY ? &v : NULL);
4811  }
4812 
4813  Assert(res != NULL);
4814 
4816 }
Datum idx(PG_FUNCTION_ARGS)
Definition: _int_op.c:259

References Assert, ereport, errcode(), errmsg(), ERROR, i, idx(), JB_ROOT_COUNT, JB_ROOT_IS_OBJECT, JB_ROOT_IS_SCALAR, JsonbIteratorInit(), JsonbIteratorNext(), JsonbValueToJsonb(), PG_GETARG_INT32, PG_GETARG_JSONB_P, PG_RETURN_JSONB_P, pushJsonbValue(), res, Jsonb::root, JsonbValue::val, WJB_BEGIN_ARRAY, WJB_DONE, and WJB_ELEM.

◆ jsonb_delete_path()

Datum jsonb_delete_path ( PG_FUNCTION_ARGS  )

Definition at line 4938 of file jsonfuncs.c.

4939 {
4940  Jsonb *in = PG_GETARG_JSONB_P(0);
4941  ArrayType *path = PG_GETARG_ARRAYTYPE_P(1);
4942  JsonbValue *res = NULL;
4943  Datum *path_elems;
4944  bool *path_nulls;
4945  int path_len;
4946  JsonbIterator *it;
4947  JsonbParseState *st = NULL;
4948 
4949  if (ARR_NDIM(path) > 1)
4950  ereport(ERROR,
4951  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
4952  errmsg("wrong number of array subscripts")));
4953 
4954  if (JB_ROOT_IS_SCALAR(in))
4955  ereport(ERROR,
4956  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4957  errmsg("cannot delete path in scalar")));
4958 
4959  if (JB_ROOT_COUNT(in) == 0)
4960  PG_RETURN_JSONB_P(in);
4961 
4962  deconstruct_array_builtin(path, TEXTOID, &path_elems, &path_nulls, &path_len);
4963 
4964  if (path_len == 0)
4965  PG_RETURN_JSONB_P(in);
4966 
4967  it = JsonbIteratorInit(&in->root);
4968 
4969  res = setPath(&it, path_elems, path_nulls, path_len, &st,
4970  0, NULL, JB_PATH_DELETE);
4971 
4972  Assert(res != NULL);
4973 
4975 }
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:5158
#define JB_PATH_DELETE
Definition: jsonfuncs.c:44

References ARR_NDIM, Assert, deconstruct_array_builtin(), ereport, errcode(), errmsg(), ERROR, JB_PATH_DELETE, JB_ROOT_COUNT, JB_ROOT_IS_SCALAR, JsonbIteratorInit(), JsonbValueToJsonb(), PG_GETARG_ARRAYTYPE_P, PG_GETARG_JSONB_P, PG_RETURN_JSONB_P, res, Jsonb::root, and setPath().

Referenced by jsonb_set_lax().

◆ jsonb_each()

Datum jsonb_each ( PG_FUNCTION_ARGS  )

Definition at line 1953 of file jsonfuncs.c.

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

References each_worker_jsonb().

◆ jsonb_each_text()

Datum jsonb_each_text ( PG_FUNCTION_ARGS  )

Definition at line 1965 of file jsonfuncs.c.

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

References each_worker_jsonb().

◆ jsonb_extract_path()

Datum jsonb_extract_path ( PG_FUNCTION_ARGS  )

Definition at line 1485 of file jsonfuncs.c.

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

References get_jsonb_path_all().

◆ jsonb_extract_path_text()

Datum jsonb_extract_path_text ( PG_FUNCTION_ARGS  )

Definition at line 1491 of file jsonfuncs.c.

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

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

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

References Assert, cstring_to_text(), DatumGetTextPP, elog, ERROR, getIthJsonbValueFromContainer(), getKeyJsonValueFromContainer(), i, IsAJsonbScalar, JB_ROOT_IS_ARRAY, JB_ROOT_IS_OBJECT, JB_ROOT_IS_SCALAR, jbvBinary, jbvNull, JsonbToCString(), JsonbValueAsText(), JsonbValueToJsonb(), JsonContainerIsArray, JsonContainerIsObject, JsonContainerIsScalar, JsonContainerSize, PG_RETURN_JSONB_P, PointerGetDatum(), res, Jsonb::root, strtoint(), TextDatumGetCString, JsonbValue::type, JsonbValue::val, VARDATA_ANY, VARSIZE, and VARSIZE_ANY_EXHDR.

Referenced by get_jsonb_path_all(), jsonb_subscript_fetch(), and jsonb_subscript_fetch_old().

◆ jsonb_insert()

Datum jsonb_insert ( PG_FUNCTION_ARGS  )

Definition at line 4981 of file jsonfuncs.c.

4982 {
4983  Jsonb *in = PG_GETARG_JSONB_P(0);
4984  ArrayType *path = PG_GETARG_ARRAYTYPE_P(1);
4985  Jsonb *newjsonb = PG_GETARG_JSONB_P(2);
4987  bool after = PG_GETARG_BOOL(3);
4988  JsonbValue *res = NULL;
4989  Datum *path_elems;
4990  bool *path_nulls;
4991  int path_len;
4992  JsonbIterator *it;
4993  JsonbParseState *st = NULL;
4994 
4995  JsonbToJsonbValue(newjsonb, &newval);
4996 
4997  if (ARR_NDIM(path) > 1)
4998  ereport(ERROR,
4999  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
5000  errmsg("wrong number of array subscripts")));
5001 
5002  if (JB_ROOT_IS_SCALAR(in))
5003  ereport(ERROR,
5004  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
5005  errmsg("cannot set path in scalar")));
5006 
5007  deconstruct_array_builtin(path, TEXTOID, &path_elems, &path_nulls, &path_len);
5008 
5009  if (path_len == 0)
5010  PG_RETURN_JSONB_P(in);
5011 
5012  it = JsonbIteratorInit(&in->root);
5013 
5014  res = setPath(&it, path_elems, path_nulls, path_len, &st, 0, &newval,
5016 
5017  Assert(res != NULL);
5018 
5020 }
#define PG_GETARG_BOOL(n)
Definition: fmgr.h:274
#define newval
void JsonbToJsonbValue(Jsonb *jsonb, JsonbValue *val)
Definition: jsonb_util.c:72
#define JB_PATH_INSERT_BEFORE
Definition: jsonfuncs.c:46
#define JB_PATH_INSERT_AFTER
Definition: jsonfuncs.c:47

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

◆ jsonb_object_field()

Datum jsonb_object_field ( PG_FUNCTION_ARGS  )

Definition at line 859 of file jsonfuncs.c.

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

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

◆ jsonb_object_field_text()

Datum jsonb_object_field_text ( PG_FUNCTION_ARGS  )

Definition at line 897 of file jsonfuncs.c.

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

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

◆ jsonb_object_keys()

Datum jsonb_object_keys ( PG_FUNCTION_ARGS  )

Definition at line 565 of file jsonfuncs.c.

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

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

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

References populate_record_worker().

◆ jsonb_populate_record_valid()

Datum jsonb_populate_record_valid ( PG_FUNCTION_ARGS  )

Definition at line 2474 of file jsonfuncs.c.

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

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

◆ jsonb_populate_recordset()

Datum jsonb_populate_recordset ( PG_FUNCTION_ARGS  )

Definition at line 3950 of file jsonfuncs.c.

3951 {
3952  return populate_recordset_worker(fcinfo, "jsonb_populate_recordset",
3953  false, true);
3954 }

References populate_recordset_worker().

◆ jsonb_pretty()

Datum jsonb_pretty ( PG_FUNCTION_ARGS  )

Definition at line 4561 of file jsonfuncs.c.

4562 {
4563  Jsonb *jb = PG_GETARG_JSONB_P(0);
4565 
4566  JsonbToCStringIndent(str, &jb->root, VARSIZE(jb));
4567 
4569 }
const char * str
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 4822 of file jsonfuncs.c.

4823 {
4824  Jsonb *in = PG_GETARG_JSONB_P(0);
4825  ArrayType *path = PG_GETARG_ARRAYTYPE_P(1);
4826  Jsonb *newjsonb = PG_GETARG_JSONB_P(2);
4828  bool create = PG_GETARG_BOOL(3);
4829  JsonbValue *res = NULL;
4830  Datum *path_elems;
4831  bool *path_nulls;
4832  int path_len;
4833  JsonbIterator *it;
4834  JsonbParseState *st = NULL;
4835 
4836  JsonbToJsonbValue(newjsonb, &newval);
4837 
4838  if (ARR_NDIM(path) > 1)
4839  ereport(ERROR,
4840  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
4841  errmsg("wrong number of array subscripts")));
4842 
4843  if (JB_ROOT_IS_SCALAR(in))
4844  ereport(ERROR,
4845  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4846  errmsg("cannot set path in scalar")));
4847 
4848  if (JB_ROOT_COUNT(in) == 0 && !create)
4849  PG_RETURN_JSONB_P(in);
4850 
4851  deconstruct_array_builtin(path, TEXTOID, &path_elems, &path_nulls, &path_len);
4852 
4853  if (path_len == 0)
4854  PG_RETURN_JSONB_P(in);
4855 
4856  it = JsonbIteratorInit(&in->root);
4857 
4858  res = setPath(&it, path_elems, path_nulls, path_len, &st,
4859  0, &newval, create ? JB_PATH_CREATE : JB_PATH_REPLACE);
4860 
4861  Assert(res != NULL);
4862 
4864 }
#define JB_PATH_CREATE
Definition: jsonfuncs.c:43
#define JB_PATH_REPLACE
Definition: jsonfuncs.c:45

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

Referenced by jsonb_set_lax().

◆ jsonb_set_element()

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

Definition at line 1676 of file jsonfuncs.c.

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

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

Referenced by jsonb_subscript_assign().

◆ jsonb_set_lax()

Datum jsonb_set_lax ( PG_FUNCTION_ARGS  )

Definition at line 4871 of file jsonfuncs.c.

4872 {
4873  /* Jsonb *in = PG_GETARG_JSONB_P(0); */
4874  /* ArrayType *path = PG_GETARG_ARRAYTYPE_P(1); */
4875  /* Jsonb *newval = PG_GETARG_JSONB_P(2); */
4876  /* bool create = PG_GETARG_BOOL(3); */
4877  text *handle_null;
4878  char *handle_val;
4879 
4880  if (PG_ARGISNULL(0) || PG_ARGISNULL(1) || PG_ARGISNULL(3))
4881  PG_RETURN_NULL();
4882 
4883  /* could happen if they pass in an explicit NULL */
4884  if (PG_ARGISNULL(4))
4885  ereport(ERROR,
4886  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4887  errmsg("null_value_treatment must be \"delete_key\", \"return_target\", \"use_json_null\", or \"raise_exception\"")));
4888 
4889  /* if the new value isn't an SQL NULL just call jsonb_set */
4890  if (!PG_ARGISNULL(2))
4891  return jsonb_set(fcinfo);
4892 
4893  handle_null = PG_GETARG_TEXT_P(4);
4894  handle_val = text_to_cstring(handle_null);
4895 
4896  if (strcmp(handle_val, "raise_exception") == 0)
4897  {
4898  ereport(ERROR,
4899  (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
4900  errmsg("JSON value must not be null"),
4901  errdetail("Exception was raised because null_value_treatment is \"raise_exception\"."),
4902  errhint("To avoid, either change the null_value_treatment argument or ensure that an SQL NULL is not passed.")));
4903  return (Datum) 0; /* silence stupider compilers */
4904  }
4905  else if (strcmp(handle_val, "use_json_null") == 0)
4906  {
4907  Datum newval;
4908 
4910 
4911  fcinfo->args[2].value = newval;
4912  fcinfo->args[2].isnull = false;
4913  return jsonb_set(fcinfo);
4914  }
4915  else if (strcmp(handle_val, "delete_key") == 0)
4916  {
4917  return jsonb_delete_path(fcinfo);
4918  }
4919  else if (strcmp(handle_val, "return_target") == 0)
4920  {
4921  Jsonb *in = PG_GETARG_JSONB_P(0);
4922 
4923  PG_RETURN_JSONB_P(in);
4924  }
4925  else
4926  {
4927  ereport(ERROR,
4928  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4929  errmsg("null_value_treatment must be \"delete_key\", \"return_target\", \"use_json_null\", or \"raise_exception\"")));
4930  return (Datum) 0; /* silence stupider compilers */
4931  }
4932 }
int errdetail(const char *fmt,...)
Definition: elog.c:1205
#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:4938
Datum jsonb_set(PG_FUNCTION_ARGS)
Definition: jsonfuncs.c:4822
static Datum CStringGetDatum(const char *X)
Definition: postgres.h:350

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

◆ jsonb_strip_nulls()

Datum jsonb_strip_nulls ( PG_FUNCTION_ARGS  )

Definition at line 4503 of file jsonfuncs.c.

4504 {
4505  Jsonb *jb = PG_GETARG_JSONB_P(0);
4506  JsonbIterator *it;
4507  JsonbParseState *parseState = NULL;
4508  JsonbValue *res = NULL;
4509  JsonbValue v,
4510  k;
4512  bool last_was_key = false;
4513 
4514  if (JB_ROOT_IS_SCALAR(jb))
4515  PG_RETURN_POINTER(jb);
4516 
4517  it = JsonbIteratorInit(&jb->root);
4518 
4519  while ((type = JsonbIteratorNext(&it, &v, false)) != WJB_DONE)
4520  {
4521  Assert(!(type == WJB_KEY && last_was_key));
4522 
4523  if (type == WJB_KEY)
4524  {
4525  /* stash the key until we know if it has a null value */
4526  k = v;
4527  last_was_key = true;
4528  continue;
4529  }
4530 
4531  if (last_was_key)
4532  {
4533  /* if the last element was a key this one can't be */
4534  last_was_key = false;
4535 
4536  /* skip this field if value is null */
4537  if (type == WJB_VALUE && v.type == jbvNull)
4538  continue;
4539 
4540  /* otherwise, do a delayed push of the key */
4541  (void) pushJsonbValue(&parseState, WJB_KEY, &k);
4542  }
4543 
4544  if (type == WJB_VALUE || type == WJB_ELEM)
4545  res = pushJsonbValue(&parseState, type, &v);
4546  else
4547  res = pushJsonbValue(&parseState, type, NULL);
4548  }
4549 
4550  Assert(res != NULL);
4551 
4553 }
#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 2485 of file jsonfuncs.c.

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

References populate_record_worker().

◆ jsonb_to_recordset()

Datum jsonb_to_recordset ( PG_FUNCTION_ARGS  )

Definition at line 3957 of file jsonfuncs.c.

3958 {
3959  return populate_recordset_worker(fcinfo, "jsonb_to_recordset",
3960  false, false);
3961 }

References populate_recordset_worker().

◆ JsonbValueAsText()

static text * JsonbValueAsText ( JsonbValue v)
static

Definition at line 1802 of file jsonfuncs.c.

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

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

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

◆ JsValueToJsObject()

static bool JsValueToJsObject ( JsValue jsv,
JsObject jso,
Node escontext 
)
static

Definition at line 2978 of file jsonfuncs.c.

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

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

Referenced by populate_composite().

◆ makeJsonLexContext()

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

Definition at line 537 of file jsonfuncs.c.

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

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

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

Referenced by json_object_keys().

◆ okeys_object_field_start()

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

Definition at line 783 of file jsonfuncs.c.

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

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

Referenced by json_object_keys().

◆ okeys_scalar()

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

Definition at line 821 of file jsonfuncs.c.

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

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

5551 {
5552  JsonbIterator *it;
5553  JsonbValue v;
5555  uint32 flags = 0;
5556 
5557  it = JsonbIteratorInit(&jb->root);
5558 
5559  type = JsonbIteratorNext(&it, &v, false);
5560 
5561  /*
5562  * We iterate over array (scalar internally is represented as array, so,
5563  * we will accept it too) to check all its elements. Flag names are
5564  * chosen the same as jsonb_typeof uses.
5565  */
5566  if (type != WJB_BEGIN_ARRAY)
5567  ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
5568  errmsg("wrong flag type, only arrays and scalars are allowed")));
5569 
5570  while ((type = JsonbIteratorNext(&it, &v, false)) == WJB_ELEM)
5571  {
5572  if (v.type != jbvString)
5573  ereport(ERROR,
5574  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
5575  errmsg("flag array element is not a string"),
5576  errhint("Possible values are: \"string\", \"numeric\", \"boolean\", \"key\", and \"all\".")));
5577 
5578  if (v.val.string.len == 3 &&
5579  pg_strncasecmp(v.val.string.val, "all", 3) == 0)
5580  flags |= jtiAll;
5581  else if (v.val.string.len == 3 &&
5582  pg_strncasecmp(v.val.string.val, "key", 3) == 0)
5583  flags |= jtiKey;
5584  else if (v.val.string.len == 6 &&
5585  pg_strncasecmp(v.val.string.val, "string", 6) == 0)
5586  flags |= jtiString;
5587  else if (v.val.string.len == 7 &&
5588  pg_strncasecmp(v.val.string.val, "numeric", 7) == 0)
5589  flags |= jtiNumeric;
5590  else if (v.val.string.len == 7 &&
5591  pg_strncasecmp(v.val.string.val, "boolean", 7) == 0)
5592  flags |= jtiBool;
5593  else
5594  ereport(ERROR,
5595  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
5596  errmsg("wrong flag in flag array: \"%s\"",
5597  pnstrdup(v.val.string.val, v.val.string.len)),
5598  errhint("Possible values are: \"string\", \"numeric\", \"boolean\", \"key\", and \"all\".")));
5599  }
5600 
5601  /* expect end of array now */
5602  if (type != WJB_END_ARRAY)
5603  elog(ERROR, "unexpected end of flag array");
5604 
5605  /* get final WJB_DONE and free iterator */
5606  type = JsonbIteratorNext(&it, &v, false);
5607  if (type != WJB_DONE)
5608  elog(ERROR, "unexpected end of flag array");
5609 
5610  return flags;
5611 }
@ jtiAll
Definition: jsonfuncs.h:31
char * pnstrdup(const char *in, Size len)
Definition: mcxt.c:1706
int pg_strncasecmp(const char *s1, const char *s2, size_t n)
Definition: pgstrcasecmp.c:69

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

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

◆ pg_parse_json_or_errsave()

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

Definition at line 516 of file jsonfuncs.c.

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

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

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

◆ populate_array()

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

Definition at line 2911 of file jsonfuncs.c.

2917 {
2919  Datum result;
2920  int *lbs;
2921  int i;
2922 
2923  ctx.aio = aio;
2924  ctx.mcxt = mcxt;
2925  ctx.acxt = CurrentMemoryContext;
2926  ctx.astate = initArrayResult(aio->element_type, ctx.acxt, true);
2927  ctx.colname = colname;
2928  ctx.ndims = 0; /* unknown yet */
2929  ctx.dims = NULL;
2930  ctx.sizes = NULL;
2931  ctx.escontext = escontext;
2932 
2933  if (jsv->is_json)
2934  {
2935  /* Return null if an error was found. */
2936  if (!populate_array_json(&ctx, jsv->val.json.str,
2937  jsv->val.json.len >= 0 ? jsv->val.json.len
2938  : strlen(jsv->val.json.str)))
2939  {
2940  *isnull = true;
2941  return (Datum) 0;
2942  }
2943  }
2944  else
2945  {
2946  /* Return null if an error was found. */
2947  if (!populate_array_dim_jsonb(&ctx, jsv->val.jsonb, 1))
2948  {
2949  *isnull = true;
2950  return (Datum) 0;
2951  }
2952  ctx.dims[0] = ctx.sizes[0];
2953  }
2954 
2955  Assert(ctx.ndims > 0);
2956 
2957  lbs = palloc(sizeof(int) * ctx.ndims);
2958 
2959  for (i = 0; i < ctx.ndims; i++)
2960  lbs[i] = 1;
2961 
2962  result = makeMdArrayResult(ctx.astate, ctx.ndims, ctx.dims, lbs,
2963  ctx.acxt, true);
2964 
2965  pfree(ctx.dims);
2966  pfree(ctx.sizes);
2967  pfree(lbs);
2968