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)
 
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)
 
static HeapTupleHeader populate_record (TupleDesc tupdesc, RecordIOData **record_p, HeapTupleHeader defaultval, MemoryContext mcxt, JsObject *obj)
 
static void get_record_type_from_argument (FunctionCallInfo fcinfo, const char *funcname, PopulateRecordCache *cache)
 
static void get_record_type_from_query (FunctionCallInfo fcinfo, const char *funcname, PopulateRecordCache *cache)
 
static void JsValueToJsObject (JsValue *jsv, JsObject *jso)
 
static Datum populate_composite (CompositeIOData *io, Oid typid, const char *colname, MemoryContext mcxt, HeapTupleHeader defaultval, JsValue *jsv, bool isnull)
 
static Datum populate_scalar (ScalarIOData *io, Oid typid, int32 typmod, JsValue *jsv)
 
static void prepare_column_cache (ColumnIOData *column, Oid typid, int32 typmod, MemoryContext mcxt, bool need_scalar)
 
static Datum populate_record_field (ColumnIOData *col, Oid typid, int32 typmod, const char *colname, MemoryContext mcxt, Datum defaultval, JsValue *jsv, bool *isnull)
 
static RecordIODataallocate_record_info (MemoryContext mcxt, int ncolumns)
 
static bool JsObjectGetField (JsObject *obj, char *field, JsValue *jsv)
 
static void populate_recordset_record (PopulateRecordsetState *state, JsObject *obj)
 
static void populate_array_json (PopulateArrayContext *ctx, char *json, int len)
 
static void populate_array_dim_jsonb (PopulateArrayContext *ctx, JsonbValue *jbv, int ndim)
 
static void populate_array_report_expected_array (PopulateArrayContext *ctx, int ndim)
 
static void populate_array_assign_ndims (PopulateArrayContext *ctx, int ndims)
 
static void populate_array_check_dimension (PopulateArrayContext *ctx, int ndim)
 
static void populate_array_element (PopulateArrayContext *ctx, int ndim, JsValue *jsv)
 
static Datum populate_array (ArrayIOData *aio, const char *colname, MemoryContext mcxt, JsValue *jsv)
 
static Datum populate_domain (DomainIOData *io, Oid typid, const char *colname, MemoryContext mcxt, JsValue *jsv, bool isnull)
 
static JsonbValueIteratorConcat (JsonbIterator **it1, JsonbIterator **it2, JsonbParseState **state)
 
static JsonbValuesetPath (JsonbIterator **it, Datum *path_elems, bool *path_nulls, int path_len, JsonbParseState **st, int level, JsonbValue *newval, int op_type)
 
static void setPathObject (JsonbIterator **it, Datum *path_elems, bool *path_nulls, int path_len, JsonbParseState **st, int level, JsonbValue *newval, uint32 npairs, int op_type)
 
static void setPathArray (JsonbIterator **it, Datum *path_elems, bool *path_nulls, int path_len, JsonbParseState **st, int level, JsonbValue *newval, uint32 nelems, int op_type)
 
static 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 (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_to_record (PG_FUNCTION_ARGS)
 
Datum json_populate_record (PG_FUNCTION_ARGS)
 
Datum json_to_record (PG_FUNCTION_ARGS)
 
static void update_cached_tupdesc (CompositeIOData *io, MemoryContext mcxt)
 
Datum jsonb_populate_recordset (PG_FUNCTION_ARGS)
 
Datum jsonb_to_recordset (PG_FUNCTION_ARGS)
 
Datum json_populate_recordset (PG_FUNCTION_ARGS)
 
Datum json_to_recordset (PG_FUNCTION_ARGS)
 
Datum json_strip_nulls (PG_FUNCTION_ARGS)
 
Datum jsonb_strip_nulls (PG_FUNCTION_ARGS)
 
Datum jsonb_pretty (PG_FUNCTION_ARGS)
 
Datum jsonb_concat (PG_FUNCTION_ARGS)
 
Datum jsonb_delete (PG_FUNCTION_ARGS)
 
Datum jsonb_delete_array (PG_FUNCTION_ARGS)
 
Datum jsonb_delete_idx (PG_FUNCTION_ARGS)
 
Datum jsonb_set (PG_FUNCTION_ARGS)
 
Datum jsonb_set_lax (PG_FUNCTION_ARGS)
 
Datum jsonb_delete_path (PG_FUNCTION_ARGS)
 
Datum jsonb_insert (PG_FUNCTION_ARGS)
 
uint32 parse_jsonb_index_flags (Jsonb *jb)
 
void iterate_jsonb_values (Jsonb *jb, uint32 flags, void *state, JsonIterateStringValuesAction action)
 
void iterate_json_values (text *json, uint32 flags, void *action_state, JsonIterateStringValuesAction action)
 
Jsonbtransform_jsonb_string_values (Jsonb *jsonb, void *action_state, JsonTransformStringValuesAction transform_action)
 
texttransform_json_string_values (text *json, void *action_state, JsonTransformStringValuesAction transform_action)
 
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:664

Definition at line 332 of file jsonfuncs.c.

◆ JsObjectIsEmpty

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

Definition at line 326 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 317 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 322 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 1919 of file jsonfuncs.c.

1920 {
1921  AlenState *_state = (AlenState *) state;
1922 
1923  /* just count up all the level 1 elements */
1924  if (_state->lex->lex_level == 1)
1925  _state->count++;
1926 
1927  return JSON_SUCCESS;
1928 }
@ JSON_SUCCESS
Definition: jsonapi.h:38
int count
Definition: jsonfuncs.c:104
JsonLexContext * lex
Definition: jsonfuncs.c:103
int lex_level
Definition: jsonapi.h:83
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 1891 of file jsonfuncs.c.

1892 {
1893  AlenState *_state = (AlenState *) state;
1894 
1895  /* json structure check */
1896  if (_state->lex->lex_level == 0)
1897  ereport(ERROR,
1898  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1899  errmsg("cannot get array length of a non-array")));
1900 
1901  return JSON_SUCCESS;
1902 }
int errcode(int sqlerrcode)
Definition: elog.c:858
int errmsg(const char *fmt,...)
Definition: elog.c:1069
#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 1905 of file jsonfuncs.c.

1906 {
1907  AlenState *_state = (AlenState *) state;
1908 
1909  /* json structure check */
1910  if (_state->lex->lex_level == 0)
1911  ereport(ERROR,
1912  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1913  errmsg("cannot get array length of a scalar")));
1914 
1915  return JSON_SUCCESS;
1916 }

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

3221 {
3223  MemoryContextAlloc(mcxt,
3224  offsetof(RecordIOData, columns) +
3225  ncolumns * sizeof(ColumnIOData));
3226 
3227  data->record_type = InvalidOid;
3228  data->record_typmod = 0;
3229  data->ncolumns = ncolumns;
3230  MemSet(data->columns, 0, sizeof(ColumnIOData) * ncolumns);
3231 
3232  return data;
3233 }
#define MemSet(start, val, len)
Definition: c.h:1009
struct ColumnIOData ColumnIOData
Definition: jsonfuncs.c:161
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:1021
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 2159 of file jsonfuncs.c.

2160 {
2161  EachState *_state = (EachState *) state;
2162 
2163  /* json structure check */
2164  if (_state->lex->lex_level == 0)
2165  ereport(ERROR,
2166  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2167  errmsg("cannot deconstruct an array as an object")));
2168 
2169  return JSON_SUCCESS;
2170 }
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 2111 of file jsonfuncs.c.

2112 {
2113  EachState *_state = (EachState *) state;
2114  MemoryContext old_cxt;
2115  int len;
2116  text *val;
2117  HeapTuple tuple;
2118  Datum values[2];
2119  bool nulls[2] = {false, false};
2120 
2121  /* skip over nested objects */
2122  if (_state->lex->lex_level != 1)
2123  return JSON_SUCCESS;
2124 
2125  /* use the tmp context so we can clean up after each tuple is done */
2126  old_cxt = MemoryContextSwitchTo(_state->tmp_cxt);
2127 
2128  values[0] = CStringGetTextDatum(fname);
2129 
2130  if (isnull && _state->normalize_results)
2131  {
2132  nulls[1] = true;
2133  values[1] = (Datum) 0;
2134  }
2135  else if (_state->next_scalar)
2136  {
2138  _state->next_scalar = false;
2139  }
2140  else
2141  {
2142  len = _state->lex->prev_token_terminator - _state->result_start;
2144  values[1] = PointerGetDatum(val);
2145  }
2146 
2147  tuple = heap_form_tuple(_state->ret_tdesc, values, nulls);
2148 
2149  tuplestore_puttuple(_state->tuple_store, tuple);
2150 
2151  /* clean up and switch back */
2152  MemoryContextSwitchTo(old_cxt);
2153  MemoryContextReset(_state->tmp_cxt);
2154 
2155  return JSON_SUCCESS;
2156 }
static Datum values[MAXATTR]
Definition: bootstrap.c:156
#define CStringGetTextDatum(s)
Definition: builtins.h:94
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:1108
void MemoryContextReset(MemoryContext context)
Definition: mcxt.c:330
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:138
const void size_t len
static Datum PointerGetDatum(const void *X)
Definition: postgres.h:322
uintptr_t Datum
Definition: postgres.h:64
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:81
Definition: c.h:676
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:194

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

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

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

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

2050 {
2051  text *json = PG_GETARG_TEXT_PP(0);
2052  JsonLexContext *lex;
2053  JsonSemAction *sem;
2054  ReturnSetInfo *rsi;
2055  EachState *state;
2056 
2057  lex = makeJsonLexContext(json, true);
2058  state = palloc0(sizeof(EachState));
2059  sem = palloc0(sizeof(JsonSemAction));
2060 
2061  rsi = (ReturnSetInfo *) fcinfo->resultinfo;
2062 
2064  state->tuple_store = rsi->setResult;
2065  state->ret_tdesc = rsi->setDesc;
2066 
2067  sem->semstate = (void *) state;
2069  sem->scalar = each_scalar;
2072 
2073  state->normalize_results = as_text;
2074  state->next_scalar = false;
2075  state->lex = lex;
2077  "json_each temporary cxt",
2079 
2080  pg_parse_json_or_ereport(lex, sem);
2081 
2082  MemoryContextDelete(state->tmp_cxt);
2083 
2084  PG_RETURN_NULL();
2085 }
#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
static JsonParseErrorType each_object_field_end(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:2111
JsonLexContext * makeJsonLexContext(text *json, bool need_escapes)
Definition: jsonfuncs.c:529
static JsonParseErrorType each_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:2173
static JsonParseErrorType each_object_field_start(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:2089
static JsonParseErrorType each_array_start(void *state)
Definition: jsonfuncs.c:2159
#define pg_parse_json_or_ereport(lex, sem)
Definition: jsonfuncs.h:46
void * palloc0(Size size)
Definition: mcxt.c:1257
MemoryContext CurrentMemoryContext
Definition: mcxt.c:135
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:403
#define AllocSetContextCreate
Definition: memutils.h:129
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:153
fmNodePtr resultinfo
Definition: fmgr.h:89
json_ofield_action object_field_start
Definition: jsonapi.h:119
json_scalar_action scalar
Definition: jsonapi.h:123
void * semstate
Definition: jsonapi.h:114
json_struct_action array_start
Definition: jsonapi.h:117
json_ofield_action object_field_end
Definition: jsonapi.h:120
TupleDesc setDesc
Definition: execnodes.h:334
Tuplestorestate * setResult
Definition: execnodes.h:333

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

Referenced by json_each(), and json_each_text().

◆ each_worker_jsonb()

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

Definition at line 1965 of file jsonfuncs.c.

1966 {
1967  Jsonb *jb = PG_GETARG_JSONB_P(0);
1968  ReturnSetInfo *rsi;
1969  MemoryContext old_cxt,
1970  tmp_cxt;
1971  bool skipNested = false;
1972  JsonbIterator *it;
1973  JsonbValue v;
1975 
1976  if (!JB_ROOT_IS_OBJECT(jb))
1977  ereport(ERROR,
1978  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1979  errmsg("cannot call %s on a non-object",
1980  funcname)));
1981 
1982  rsi = (ReturnSetInfo *) fcinfo->resultinfo;
1984 
1986  "jsonb_each temporary cxt",
1988 
1989  it = JsonbIteratorInit(&jb->root);
1990 
1991  while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE)
1992  {
1993  skipNested = true;
1994 
1995  if (r == WJB_KEY)
1996  {
1997  text *key;
1998  Datum values[2];
1999  bool nulls[2] = {false, false};
2000 
2001  /* Use the tmp context so we can clean up after each tuple is done */
2002  old_cxt = MemoryContextSwitchTo(tmp_cxt);
2003 
2004  key = cstring_to_text_with_len(v.val.string.val, v.val.string.len);
2005 
2006  /*
2007  * The next thing the iterator fetches should be the value, no
2008  * matter what shape it is.
2009  */
2010  r = JsonbIteratorNext(&it, &v, skipNested);
2011  Assert(r != WJB_DONE);
2012 
2013  values[0] = PointerGetDatum(key);
2014 
2015  if (as_text)
2016  {
2017  if (v.type == jbvNull)
2018  {
2019  /* a json null is an sql null in text mode */
2020  nulls[1] = true;
2021  values[1] = (Datum) NULL;
2022  }
2023  else
2025  }
2026  else
2027  {
2028  /* Not in text mode, just return the Jsonb */
2029  Jsonb *val = JsonbValueToJsonb(&v);
2030 
2031  values[1] = PointerGetDatum(val);
2032  }
2033 
2034  tuplestore_putvalues(rsi->setResult, rsi->setDesc, values, nulls);
2035 
2036  /* clean up and switch back */
2037  MemoryContextSwitchTo(old_cxt);
2038  MemoryContextReset(tmp_cxt);
2039  }
2040  }
2041 
2042  MemoryContextDelete(tmp_cxt);
2043 
2044  PG_RETURN_NULL();
2045 }
#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:819
Jsonb * JsonbValueToJsonb(JsonbValue *val)
Definition: jsonb_util.c:94
JsonbIteratorToken JsonbIteratorNext(JsonbIterator **it, JsonbValue *val, bool skipNested)
Definition: jsonb_util.c:855
static text * JsonbValueAsText(JsonbValue *v)
Definition: jsonfuncs.c:1794
Assert(fmt[strlen(fmt) - 1] !='\n')
enum jbvType type
Definition: jsonb.h:255
char * val
Definition: jsonb.h:264
Definition: jsonb.h:213
JsonbContainer root
Definition: jsonb.h:215
void tuplestore_putvalues(Tuplestorestate *state, TupleDesc tdesc, Datum *values, bool *isnull)
Definition: tuplestore.c:750

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, Assert(), cstring_to_text_with_len(), CurrentMemoryContext, ereport, errcode(), errmsg(), ERROR, 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 2361 of file jsonfuncs.c.

2362 {
2363  ElementsState *_state = (ElementsState *) state;
2364  MemoryContext old_cxt;
2365  int len;
2366  text *val;
2367  HeapTuple tuple;
2368  Datum values[1];
2369  bool nulls[1] = {false};
2370 
2371  /* skip over nested objects */
2372  if (_state->lex->lex_level != 1)
2373  return JSON_SUCCESS;
2374 
2375  /* use the tmp context so we can clean up after each tuple is done */
2376  old_cxt = MemoryContextSwitchTo(_state->tmp_cxt);
2377 
2378  if (isnull && _state->normalize_results)
2379  {
2380  nulls[0] = true;
2381  values[0] = (Datum) NULL;
2382  }
2383  else if (_state->next_scalar)
2384  {
2386  _state->next_scalar = false;
2387  }
2388  else
2389  {
2390  len = _state->lex->prev_token_terminator - _state->result_start;
2392  values[0] = PointerGetDatum(val);
2393  }
2394 
2395  tuple = heap_form_tuple(_state->ret_tdesc, values, nulls);
2396 
2397  tuplestore_puttuple(_state->tuple_store, tuple);
2398 
2399  /* clean up and switch back */
2400  MemoryContextSwitchTo(old_cxt);
2401  MemoryContextReset(_state->tmp_cxt);
2402 
2403  return JSON_SUCCESS;
2404 }
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 2339 of file jsonfuncs.c.

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

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

2408 {
2409  ElementsState *_state = (ElementsState *) state;
2410 
2411  /* json structure check */
2412  if (_state->lex->lex_level == 0)
2413  ereport(ERROR,
2414  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2415  errmsg("cannot call %s on a non-array",
2416  _state->function_name)));
2417 
2418  return JSON_SUCCESS;
2419 }
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 2422 of file jsonfuncs.c.

2423 {
2424  ElementsState *_state = (ElementsState *) state;
2425 
2426  /* json structure check */
2427  if (_state->lex->lex_level == 0)
2428  ereport(ERROR,
2429  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2430  errmsg("cannot call %s on a scalar",
2431  _state->function_name)));
2432 
2433  /* supply de-escaped value if required */
2434  if (_state->next_scalar)
2435  _state->normalized_scalar = token;
2436 
2437  return JSON_SUCCESS;
2438 }

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

2300 {
2301  text *json = PG_GETARG_TEXT_PP(0);
2302 
2303  /* elements only needs escaped strings when as_text */
2304  JsonLexContext *lex = makeJsonLexContext(json, as_text);
2305  JsonSemAction *sem;
2306  ReturnSetInfo *rsi;
2308 
2309  state = palloc0(sizeof(ElementsState));
2310  sem = palloc0(sizeof(JsonSemAction));
2311 
2313  rsi = (ReturnSetInfo *) fcinfo->resultinfo;
2314  state->tuple_store = rsi->setResult;
2315  state->ret_tdesc = rsi->setDesc;
2316 
2317  sem->semstate = (void *) state;
2319  sem->scalar = elements_scalar;
2322 
2323  state->function_name = funcname;
2324  state->normalize_results = as_text;
2325  state->next_scalar = false;
2326  state->lex = lex;
2328  "json_array_elements temporary cxt",
2330 
2331  pg_parse_json_or_ereport(lex, sem);
2332 
2333  MemoryContextDelete(state->tmp_cxt);
2334 
2335  PG_RETURN_NULL();
2336 }
#define MAT_SRF_USE_EXPECTED_DESC
Definition: funcapi.h:296
static JsonParseErrorType elements_object_start(void *state)
Definition: jsonfuncs.c:2407
static JsonParseErrorType elements_array_element_end(void *state, bool isnull)
Definition: jsonfuncs.c:2361
static JsonParseErrorType elements_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:2422
static JsonParseErrorType elements_array_element_start(void *state, bool isnull)
Definition: jsonfuncs.c:2339
json_struct_action object_start
Definition: jsonapi.h:115
json_aelem_action array_element_start
Definition: jsonapi.h:121
json_aelem_action array_element_end
Definition: jsonapi.h:122

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(), 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, 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 2211 of file jsonfuncs.c.

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

1391 {
1392  GetState *_state = (GetState *) state;
1393  bool get_last = false;
1394  int lex_level = _state->lex->lex_level;
1395 
1396  /* same tests as in get_array_element_start */
1397  if (lex_level <= _state->npath &&
1398  _state->pathok[lex_level - 1] &&
1399  _state->path_indexes != NULL &&
1400  _state->array_cur_index[lex_level - 1] == _state->path_indexes[lex_level - 1])
1401  {
1402  if (lex_level < _state->npath)
1403  {
1404  /* done with this element so reset pathok */
1405  _state->pathok[lex_level] = false;
1406  }
1407  else
1408  {
1409  /* end of path, so we want this value */
1410  get_last = true;
1411  }
1412  }
1413 
1414  /* same logic as for objects */
1415  if (get_last && _state->result_start != NULL)
1416  {
1417  if (isnull && _state->normalize_results)
1418  _state->tresult = (text *) NULL;
1419  else
1420  {
1421  char *start = _state->result_start;
1422  int len = _state->lex->prev_token_terminator - start;
1423 
1424  _state->tresult = cstring_to_text_with_len(start, len);
1425  }
1426 
1427  _state->result_start = NULL;
1428  }
1429 
1430  return JSON_SUCCESS;
1431 }
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, 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 1342 of file jsonfuncs.c.

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

1325 {
1326  GetState *_state = (GetState *) state;
1327  int lex_level = _state->lex->lex_level;
1328 
1329  if (lex_level == 0 && _state->npath == 0)
1330  {
1331  /* Special case: return the entire array */
1332  char *start = _state->result_start;
1333  int len = _state->lex->prev_token_terminator - start;
1334 
1335  _state->tresult = cstring_to_text_with_len(start, len);
1336  }
1337 
1338  return JSON_SUCCESS;
1339 }
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, and GetState::tresult.

Referenced by get_worker().

◆ get_array_start()

static JsonParseErrorType get_array_start ( void *  state)
static

Definition at line 1284 of file jsonfuncs.c.

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

Definition at line 3545 of file jsonfuncs.c.

3546 {
3547  HASHCTL ctl;
3548  HTAB *tab;
3549  JHashState *state;
3551  JsonSemAction *sem;
3552 
3553  ctl.keysize = NAMEDATALEN;
3554  ctl.entrysize = sizeof(JsonHashEntry);
3555  ctl.hcxt = CurrentMemoryContext;
3556  tab = hash_create("json object hashtable",
3557  100,
3558  &ctl,
3560 
3561  state = palloc0(sizeof(JHashState));
3562  sem = palloc0(sizeof(JsonSemAction));
3563 
3564  state->function_name = funcname;
3565  state->hash = tab;
3566  state->lex = lex;
3567 
3568  sem->semstate = (void *) state;
3570  sem->scalar = hash_scalar;
3573 
3574  pg_parse_json_or_ereport(lex, sem);
3575 
3576  return tab;
3577 }
HTAB * hash_create(const char *tabname, long nelem, const HASHCTL *info, int flags)
Definition: dynahash.c:350
#define HASH_STRINGS
Definition: hsearch.h:96
#define HASH_CONTEXT
Definition: hsearch.h:102
#define HASH_ELEM
Definition: hsearch.h:95
JsonLexContext * makeJsonLexContextCstringLen(char *json, int len, int encoding, bool need_escapes)
Definition: jsonapi.c:145
static JsonParseErrorType hash_array_start(void *state)
Definition: jsonfuncs.c:3657
static JsonParseErrorType hash_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:3670
struct JsonHashEntry JsonHashEntry
static JsonParseErrorType hash_object_field_end(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:3606
static JsonParseErrorType hash_object_field_start(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:3580
int GetDatabaseEncoding(void)
Definition: mbutils.c:1268
#define NAMEDATALEN
Size keysize
Definition: hsearch.h:75
Size entrysize
Definition: hsearch.h:76
MemoryContext hcxt
Definition: hsearch.h:86
Definition: dynahash.c:220

References JsonSemAction::array_start, CurrentMemoryContext, HASHCTL::entrysize, funcname, GetDatabaseEncoding(), hash_array_start(), HASH_CONTEXT, hash_create(), HASH_ELEM, hash_object_field_end(), hash_object_field_start(), hash_scalar(), HASH_STRINGS, HASHCTL::hcxt, HASHCTL::keysize, len, makeJsonLexContextCstringLen(), NAMEDATALEN, JsonSemAction::object_field_end, JsonSemAction::object_field_start, palloc0(), pg_parse_json_or_ereport, JsonSemAction::scalar, and JsonSemAction::semstate.

Referenced by JsValueToJsObject().

◆ get_jsonb_path_all()

static Datum get_jsonb_path_all ( FunctionCallInfo  fcinfo,
bool  as_text 
)
static

Definition at line 1489 of file jsonfuncs.c.

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

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

1169 {
1170  GetState *_state = (GetState *) state;
1171  int lex_level = _state->lex->lex_level;
1172 
1173  if (lex_level == 0 && _state->npath == 0)
1174  {
1175  /* Special case: return the entire object */
1176  char *start = _state->result_start;
1177  int len = _state->lex->prev_token_terminator - start;
1178 
1179  _state->tresult = cstring_to_text_with_len(start, len);
1180  }
1181 
1182  return JSON_SUCCESS;
1183 }

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

Referenced by get_worker().

◆ get_object_field_end()

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

Definition at line 1233 of file jsonfuncs.c.

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

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

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

1150 {
1151  GetState *_state = (GetState *) state;
1152  int lex_level = _state->lex->lex_level;
1153 
1154  if (lex_level == 0 && _state->npath == 0)
1155  {
1156  /*
1157  * Special case: we should match the entire object. We only need this
1158  * at outermost level because at nested levels the match will have
1159  * been started by the outer field or array element callback.
1160  */
1161  _state->result_start = _state->lex->token_start;
1162  }
1163 
1164  return JSON_SUCCESS;
1165 }

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

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

3380 {
3381  cache->argtype = get_fn_expr_argtype(fcinfo->flinfo, 0);
3382  prepare_column_cache(&cache->c,
3383  cache->argtype, -1,
3384  cache->fn_mcxt, false);
3385  if (cache->c.typcat != TYPECAT_COMPOSITE &&
3386  cache->c.typcat != TYPECAT_COMPOSITE_DOMAIN)
3387  ereport(ERROR,
3388  (errcode(ERRCODE_DATATYPE_MISMATCH),
3389  /* translator: %s is a function name, eg json_to_record */
3390  errmsg("first argument of %s must be a row type",
3391  funcname)));
3392 }
Oid get_fn_expr_argtype(FmgrInfo *flinfo, int argnum)
Definition: fmgr.c:1893
static void prepare_column_cache(ColumnIOData *column, Oid typid, int32 typmod, MemoryContext mcxt, bool need_scalar)
Definition: jsonfuncs.c:3068
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 3403 of file jsonfuncs.c.

3406 {
3407  TupleDesc tupdesc;
3408  MemoryContext old_cxt;
3409 
3410  if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
3411  ereport(ERROR,
3412  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3413  /* translator: %s is a function name, eg json_to_record */
3414  errmsg("could not determine row type for result of %s",
3415  funcname),
3416  errhint("Provide a non-null record argument, "
3417  "or call the function in the FROM clause "
3418  "using a column definition list.")));
3419 
3420  Assert(tupdesc);
3421  cache->argtype = tupdesc->tdtypeid;
3422 
3423  /* If we go through this more than once, avoid memory leak */
3424  if (cache->c.io.composite.tupdesc)
3426 
3427  /* Save identified tupdesc */
3428  old_cxt = MemoryContextSwitchTo(cache->fn_mcxt);
3429  cache->c.io.composite.tupdesc = CreateTupleDescCopy(tupdesc);
3430  cache->c.io.composite.base_typid = tupdesc->tdtypeid;
3431  cache->c.io.composite.base_typmod = tupdesc->tdtypmod;
3432  MemoryContextSwitchTo(old_cxt);
3433 }
int errhint(const char *fmt,...)
Definition: elog.c:1316
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::@23 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:309
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
Definition: tupdesc.c:111

References PopulateRecordCache::argtype, Assert(), CompositeIOData::base_typid, CompositeIOData::base_typmod, PopulateRecordCache::c, ColumnIOData::composite, CreateTupleDescCopy(), ereport, errcode(), errhint(), errmsg(), ERROR, PopulateRecordCache::fn_mcxt, FreeTupleDesc(), 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 1434 of file jsonfuncs.c.

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

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

1098 {
1099  JsonLexContext *lex = makeJsonLexContext(json, true);
1100  JsonSemAction *sem = palloc0(sizeof(JsonSemAction));
1101  GetState *state = palloc0(sizeof(GetState));
1102 
1103  Assert(npath >= 0);
1104 
1105  state->lex = lex;
1106  /* is it "_as_text" variant? */
1107  state->normalize_results = normalize_results;
1108  state->npath = npath;
1109  state->path_names = tpath;
1110  state->path_indexes = ipath;
1111  state->pathok = palloc0(sizeof(bool) * npath);
1112  state->array_cur_index = palloc(sizeof(int) * npath);
1113 
1114  if (npath > 0)
1115  state->pathok[0] = true;
1116 
1117  sem->semstate = (void *) state;
1118 
1119  /*
1120  * Not all variants need all the semantic routines. Only set the ones that
1121  * are actually needed for maximum efficiency.
1122  */
1123  sem->scalar = get_scalar;
1124  if (npath == 0)
1125  {
1127  sem->object_end = get_object_end;
1129  sem->array_end = get_array_end;
1130  }
1131  if (tpath != NULL)
1132  {
1135  }
1136  if (ipath != NULL)
1137  {
1141  }
1142 
1143  pg_parse_json_or_ereport(lex, sem);
1144 
1145  return state->tresult;
1146 }
static JsonParseErrorType get_array_element_end(void *state, bool isnull)
Definition: jsonfuncs.c:1390
static JsonParseErrorType get_object_field_start(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:1186
static JsonParseErrorType get_object_start(void *state)
Definition: jsonfuncs.c:1149
static JsonParseErrorType get_array_start(void *state)
Definition: jsonfuncs.c:1284
static JsonParseErrorType get_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:1434
static JsonParseErrorType get_object_end(void *state)
Definition: jsonfuncs.c:1168
static JsonParseErrorType get_object_field_end(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:1233
static JsonParseErrorType get_array_end(void *state)
Definition: jsonfuncs.c:1324
static JsonParseErrorType get_array_element_start(void *state, bool isnull)
Definition: jsonfuncs.c:1342
json_struct_action array_end
Definition: jsonapi.h:118
json_struct_action object_end
Definition: jsonapi.h:116

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

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

◆ hash_array_start()

static JsonParseErrorType hash_array_start ( void *  state)
static

Definition at line 3657 of file jsonfuncs.c.

3658 {
3659  JHashState *_state = (JHashState *) state;
3660 
3661  if (_state->lex->lex_level == 0)
3662  ereport(ERROR,
3663  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3664  errmsg("cannot call %s on an array", _state->function_name)));
3665 
3666  return JSON_SUCCESS;
3667 }
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 3606 of file jsonfuncs.c.

3607 {
3608  JHashState *_state = (JHashState *) state;
3609  JsonHashEntry *hashentry;
3610  bool found;
3611 
3612  /*
3613  * Ignore nested fields.
3614  */
3615  if (_state->lex->lex_level > 1)
3616  return JSON_SUCCESS;
3617 
3618  /*
3619  * Ignore field names >= NAMEDATALEN - they can't match a record field.
3620  * (Note: without this test, the hash code would truncate the string at
3621  * NAMEDATALEN-1, and could then match against a similarly-truncated
3622  * record field name. That would be a reasonable behavior, but this code
3623  * has previously insisted on exact equality, so we keep this behavior.)
3624  */
3625  if (strlen(fname) >= NAMEDATALEN)
3626  return JSON_SUCCESS;
3627 
3628  hashentry = hash_search(_state->hash, fname, HASH_ENTER, &found);
3629 
3630  /*
3631  * found being true indicates a duplicate. We don't do anything about
3632  * that, a later field with the same name overrides the earlier field.
3633  */
3634 
3635  hashentry->type = _state->saved_token_type;
3636  Assert(isnull == (hashentry->type == JSON_TOKEN_NULL));
3637 
3638  if (_state->save_json_start != NULL)
3639  {
3640  int len = _state->lex->prev_token_terminator - _state->save_json_start;
3641  char *val = palloc((len + 1) * sizeof(char));
3642 
3643  memcpy(val, _state->save_json_start, len);
3644  val[len] = '\0';
3645  hashentry->val = val;
3646  }
3647  else
3648  {
3649  /* must have had a scalar instead */
3650  hashentry->val = _state->saved_scalar;
3651  }
3652 
3653  return JSON_SUCCESS;
3654 }
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:953
@ HASH_ENTER
Definition: hsearch.h:114
char * saved_scalar
Definition: jsonfuncs.c: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 3580 of file jsonfuncs.c.

3581 {
3582  JHashState *_state = (JHashState *) state;
3583 
3584  if (_state->lex->lex_level > 1)
3585  return JSON_SUCCESS;
3586 
3587  /* remember token type */
3588  _state->saved_token_type = _state->lex->token_type;
3589 
3590  if (_state->lex->token_type == JSON_TOKEN_ARRAY_START ||
3592  {
3593  /* remember start position of the whole text of the subobject */
3594  _state->save_json_start = _state->lex->token_start;
3595  }
3596  else
3597  {
3598  /* must be a scalar */
3599  _state->save_json_start = NULL;
3600  }
3601 
3602  return JSON_SUCCESS;
3603 }
@ 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 3670 of file jsonfuncs.c.

3671 {
3672  JHashState *_state = (JHashState *) state;
3673 
3674  if (_state->lex->lex_level == 0)
3675  ereport(ERROR,
3676  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3677  errmsg("cannot call %s on a scalar", _state->function_name)));
3678 
3679  if (_state->lex->lex_level == 1)
3680  {
3681  _state->saved_scalar = token;
3682  /* saved_token_type must already be set in hash_object_field_start() */
3683  Assert(_state->saved_token_type == tokentype);
3684  }
3685 
3686  return JSON_SUCCESS;
3687 }

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

5435 {
5436  JsonLexContext *lex = makeJsonLexContext(json, true);
5437  JsonSemAction *sem = palloc0(sizeof(JsonSemAction));
5439 
5440  state->lex = lex;
5441  state->action = action;
5442  state->action_state = action_state;
5443  state->flags = flags;
5444 
5445  sem->semstate = (void *) state;
5448 
5449  pg_parse_json_or_ereport(lex, sem);
5450 }
static JsonParseErrorType iterate_values_object_field_start(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:5485
static JsonParseErrorType iterate_values_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:5457

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

Referenced by json_to_tsvector_worker().

◆ iterate_jsonb_values()

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

Definition at line 5365 of file jsonfuncs.c.

5367 {
5368  JsonbIterator *it;
5369  JsonbValue v;
5371 
5372  it = JsonbIteratorInit(&jb->root);
5373 
5374  /*
5375  * Just recursively iterating over jsonb and call callback on all
5376  * corresponding elements
5377  */
5378  while ((type = JsonbIteratorNext(&it, &v, false)) != WJB_DONE)
5379  {
5380  if (type == WJB_KEY)
5381  {
5382  if (flags & jtiKey)
5383  action(state, v.val.string.val, v.val.string.len);
5384 
5385  continue;
5386  }
5387  else if (!(type == WJB_VALUE || type == WJB_ELEM))
5388  {
5389  /* do not call callback for composite JsonbValue */
5390  continue;
5391  }
5392 
5393  /* JsonbValue is a value of object or element of array */
5394  switch (v.type)
5395  {
5396  case jbvString:
5397  if (flags & jtiString)
5398  action(state, v.val.string.val, v.val.string.len);
5399  break;
5400  case jbvNumeric:
5401  if (flags & jtiNumeric)
5402  {
5403  char *val;
5404 
5406  NumericGetDatum(v.val.numeric)));
5407 
5408  action(state, val, strlen(val));
5409  pfree(val);
5410  }
5411  break;
5412  case jbvBool:
5413  if (flags & jtiBool)
5414  {
5415  if (v.val.boolean)
5416  action(state, "true", 4);
5417  else
5418  action(state, "false", 5);
5419  }
5420  break;
5421  default:
5422  /* do not call callback for composite JsonbValue */
5423  break;
5424  }
5425  }
5426 }
Datum numeric_out(PG_FUNCTION_ARGS)
Definition: numeric.c:806
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:642
@ jbvNumeric
Definition: jsonb.h:230
@ jbvBool
Definition: jsonb.h:231
@ WJB_VALUE
Definition: jsonb.h:24
@ jtiKey
Definition: jsonfuncs.h:26
@ jtiNumeric
Definition: jsonfuncs.h:28
@ jtiBool
Definition: jsonfuncs.h:29
@ jtiString
Definition: jsonfuncs.h:27
void pfree(void *pointer)
Definition: mcxt.c:1456
static Datum NumericGetDatum(Numeric X)
Definition: numeric.h:72
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 5485 of file jsonfuncs.c.

5486 {
5488 
5489  if (_state->flags & jtiKey)
5490  {
5491  char *val = pstrdup(fname);
5492 
5493  _state->action(_state->action_state, val, strlen(val));
5494  }
5495 
5496  return JSON_SUCCESS;
5497 }
char * pstrdup(const char *in)
Definition: mcxt.c:1644
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 5457 of file jsonfuncs.c.

5458 {
5460 
5461  switch (tokentype)
5462  {
5463  case JSON_TOKEN_STRING:
5464  if (_state->flags & jtiString)
5465  _state->action(_state->action_state, token, strlen(token));
5466  break;
5467  case JSON_TOKEN_NUMBER:
5468  if (_state->flags & jtiNumeric)
5469  _state->action(_state->action_state, token, strlen(token));
5470  break;
5471  case JSON_TOKEN_TRUE:
5472  case JSON_TOKEN_FALSE:
5473  if (_state->flags & jtiBool)
5474  _state->action(_state->action_state, token, strlen(token));
5475  break;
5476  default:
5477  /* do not call callback for any other token */
5478  break;
5479  }
5480 
5481  return JSON_SUCCESS;
5482 }
@ 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 4777 of file jsonfuncs.c.

4779 {
4780  JsonbValue v1,
4781  v2,
4782  *res = NULL;
4783  JsonbIteratorToken r1,
4784  r2,
4785  rk1,
4786  rk2;
4787 
4788  rk1 = JsonbIteratorNext(it1, &v1, false);
4789  rk2 = JsonbIteratorNext(it2, &v2, false);
4790 
4791  /*
4792  * JsonbIteratorNext reports raw scalars as if they were single-element
4793  * arrays; hence we only need consider "object" and "array" cases here.
4794  */
4795  if (rk1 == WJB_BEGIN_OBJECT && rk2 == WJB_BEGIN_OBJECT)
4796  {
4797  /*
4798  * Both inputs are objects.
4799  *
4800  * Append all the tokens from v1 to res, except last WJB_END_OBJECT
4801  * (because res will not be finished yet).
4802  */
4803  pushJsonbValue(state, rk1, NULL);
4804  while ((r1 = JsonbIteratorNext(it1, &v1, true)) != WJB_END_OBJECT)
4805  pushJsonbValue(state, r1, &v1);
4806 
4807  /*
4808  * Append all the tokens from v2 to res, including last WJB_END_OBJECT
4809  * (the concatenation will be completed). Any duplicate keys will
4810  * automatically override the value from the first object.
4811  */
4812  while ((r2 = JsonbIteratorNext(it2, &v2, true)) != WJB_DONE)
4813  res = pushJsonbValue(state, r2, r2 != WJB_END_OBJECT ? &v2 : NULL);
4814  }
4815  else if (rk1 == WJB_BEGIN_ARRAY && rk2 == WJB_BEGIN_ARRAY)
4816  {
4817  /*
4818  * Both inputs are arrays.
4819  */
4820  pushJsonbValue(state, rk1, NULL);
4821 
4822  while ((r1 = JsonbIteratorNext(it1, &v1, true)) != WJB_END_ARRAY)
4823  {
4824  Assert(r1 == WJB_ELEM);
4825  pushJsonbValue(state, r1, &v1);
4826  }
4827 
4828  while ((r2 = JsonbIteratorNext(it2, &v2, true)) != WJB_END_ARRAY)
4829  {
4830  Assert(r2 == WJB_ELEM);
4831  pushJsonbValue(state, WJB_ELEM, &v2);
4832  }
4833 
4834  res = pushJsonbValue(state, WJB_END_ARRAY, NULL /* signal to sort */ );
4835  }
4836  else if (rk1 == WJB_BEGIN_OBJECT)
4837  {
4838  /*
4839  * We have object || array.
4840  */
4841  Assert(rk2 == WJB_BEGIN_ARRAY);
4842 
4844 
4846  while ((r1 = JsonbIteratorNext(it1, &v1, true)) != WJB_DONE)
4847  pushJsonbValue(state, r1, r1 != WJB_END_OBJECT ? &v1 : NULL);
4848 
4849  while ((r2 = JsonbIteratorNext(it2, &v2, true)) != WJB_DONE)
4850  res = pushJsonbValue(state, r2, r2 != WJB_END_ARRAY ? &v2 : NULL);
4851  }
4852  else
4853  {
4854  /*
4855  * We have array || object.
4856  */
4857  Assert(rk1 == WJB_BEGIN_ARRAY);
4858  Assert(rk2 == WJB_BEGIN_OBJECT);
4859 
4861 
4862  while ((r1 = JsonbIteratorNext(it1, &v1, true)) != WJB_END_ARRAY)
4863  pushJsonbValue(state, r1, &v1);
4864 
4866  while ((r2 = JsonbIteratorNext(it2, &v2, true)) != WJB_DONE)
4867  pushJsonbValue(state, r2, r2 != WJB_END_OBJECT ? &v2 : NULL);
4868 
4870  }
4871 
4872  return res;
4873 }
@ WJB_END_ARRAY
Definition: jsonb.h:27
@ WJB_END_OBJECT
Definition: jsonb.h:29
@ WJB_BEGIN_OBJECT
Definition: jsonb.h:28
@ WJB_BEGIN_ARRAY
Definition: jsonb.h:26
JsonbValue * pushJsonbValue(JsonbParseState **pstate, JsonbIteratorToken seq, JsonbValue *jbval)
Definition: jsonb_util.c:568

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

Referenced by jsonb_concat().

◆ JsObjectGetField()

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

Definition at line 3236 of file jsonfuncs.c.

3237 {
3238  jsv->is_json = obj->is_json;
3239 
3240  if (jsv->is_json)
3241  {
3242  JsonHashEntry *hashentry = hash_search(obj->val.json_hash, field,
3243  HASH_FIND, NULL);
3244 
3245  jsv->val.json.type = hashentry ? hashentry->type : JSON_TOKEN_NULL;
3246  jsv->val.json.str = jsv->val.json.type == JSON_TOKEN_NULL ? NULL :
3247  hashentry->val;
3248  jsv->val.json.len = jsv->val.json.str ? -1 : 0; /* null-terminated */
3249 
3250  return hashentry != NULL;
3251  }
3252  else
3253  {
3254  jsv->val.jsonb = !obj->val.jsonb_cont ? NULL :
3255  getKeyJsonValueFromContainer(obj->val.jsonb_cont, field, strlen(field),
3256  NULL);
3257 
3258  return jsv->val.jsonb != NULL;
3259  }
3260 }
@ HASH_FIND
Definition: hsearch.h:113
JsonbValue * getKeyJsonValueFromContainer(JsonbContainer *container, const char *keyVal, int keyLen, JsonbValue *res)
Definition: jsonb_util.c:400
bool is_json
Definition: jsonfuncs.c:308
JsonbContainer * jsonb_cont
Definition: jsonfuncs.c:312
HTAB * json_hash
Definition: jsonfuncs.c:311
union JsObject::@26 val
union JsValue::@24 val
JsonbValue * jsonb
Definition: jsonfuncs.c:302
bool is_json
Definition: jsonfuncs.c:292
struct JsValue::@24::@25 json

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

913 {
914  text *json = PG_GETARG_TEXT_PP(0);
915  int element = PG_GETARG_INT32(1);
916  text *result;
917 
918  result = get_worker(json, NULL, &element, 1, false);
919 
920  if (result != NULL)
921  PG_RETURN_TEXT_P(result);
922  else
923  PG_RETURN_NULL();
924 }
#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 955 of file jsonfuncs.c.

956 {
957  text *json = PG_GETARG_TEXT_PP(0);
958  int element = PG_GETARG_INT32(1);
959  text *result;
960 
961  result = get_worker(json, NULL, &element, 1, true);
962 
963  if (result != NULL)
964  PG_RETURN_TEXT_P(result);
965  else
966  PG_RETURN_NULL();
967 }

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

2288 {
2289  return elements_worker(fcinfo, "json_array_elements", false);
2290 }
static Datum elements_worker(FunctionCallInfo fcinfo, const char *funcname, bool as_text)
Definition: jsonfuncs.c:2299

References elements_worker().

◆ json_array_elements_text()

Datum json_array_elements_text ( PG_FUNCTION_ARGS  )

Definition at line 2293 of file jsonfuncs.c.

2294 {
2295  return elements_worker(fcinfo, "json_array_elements_text", true);
2296 }

References elements_worker().

◆ json_array_length()

Datum json_array_length ( PG_FUNCTION_ARGS  )

Definition at line 1841 of file jsonfuncs.c.

1842 {
1843  text *json = PG_GETARG_TEXT_PP(0);
1844  AlenState *state;
1845  JsonLexContext *lex;
1846  JsonSemAction *sem;
1847 
1848  lex = makeJsonLexContext(json, false);
1849  state = palloc0(sizeof(AlenState));
1850  sem = palloc0(sizeof(JsonSemAction));
1851 
1852  /* palloc0 does this for us */
1853 #if 0
1854  state->count = 0;
1855 #endif
1856  state->lex = lex;
1857 
1858  sem->semstate = (void *) state;
1860  sem->scalar = alen_scalar;
1862 
1863  pg_parse_json_or_ereport(lex, sem);
1864 
1865  PG_RETURN_INT32(state->count);
1866 }
#define PG_RETURN_INT32(x)
Definition: fmgr.h:354
static JsonParseErrorType alen_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:1905
static JsonParseErrorType alen_object_start(void *state)
Definition: jsonfuncs.c:1891
static JsonParseErrorType alen_array_element_start(void *state, bool isnull)
Definition: jsonfuncs.c:1919

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

◆ json_categorize_type()

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

Definition at line 5698 of file jsonfuncs.c.

5700 {
5701  bool typisvarlena;
5702 
5703  /* Look through any domain */
5704  typoid = getBaseType(typoid);
5705 
5706  *outfuncoid = InvalidOid;
5707 
5708  switch (typoid)
5709  {
5710  case BOOLOID:
5711  *outfuncoid = F_BOOLOUT;
5712  *tcategory = JSONTYPE_BOOL;
5713  break;
5714 
5715  case INT2OID:
5716  case INT4OID:
5717  case INT8OID:
5718  case FLOAT4OID:
5719  case FLOAT8OID:
5720  case NUMERICOID:
5721  getTypeOutputInfo(typoid, outfuncoid, &typisvarlena);
5722  *tcategory = JSONTYPE_NUMERIC;
5723  break;
5724 
5725  case DATEOID:
5726  *outfuncoid = F_DATE_OUT;
5727  *tcategory = JSONTYPE_DATE;
5728  break;
5729 
5730  case TIMESTAMPOID:
5731  *outfuncoid = F_TIMESTAMP_OUT;
5732  *tcategory = JSONTYPE_TIMESTAMP;
5733  break;
5734 
5735  case TIMESTAMPTZOID:
5736  *outfuncoid = F_TIMESTAMPTZ_OUT;
5737  *tcategory = JSONTYPE_TIMESTAMPTZ;
5738  break;
5739 
5740  case JSONOID:
5741  getTypeOutputInfo(typoid, outfuncoid, &typisvarlena);
5742  *tcategory = JSONTYPE_JSON;
5743  break;
5744 
5745  case JSONBOID:
5746  getTypeOutputInfo(typoid, outfuncoid, &typisvarlena);
5747  *tcategory = is_jsonb ? JSONTYPE_JSONB : JSONTYPE_JSON;
5748  break;
5749 
5750  default:
5751  /* Check for arrays and composites */
5752  if (OidIsValid(get_element_type(typoid)) || typoid == ANYARRAYOID
5753  || typoid == ANYCOMPATIBLEARRAYOID || typoid == RECORDARRAYOID)
5754  {
5755  *outfuncoid = F_ARRAY_OUT;
5756  *tcategory = JSONTYPE_ARRAY;
5757  }
5758  else if (type_is_rowtype(typoid)) /* includes RECORDOID */
5759  {
5760  *outfuncoid = F_RECORD_OUT;
5761  *tcategory = JSONTYPE_COMPOSITE;
5762  }
5763  else
5764  {
5765  /*
5766  * It's probably the general case. But let's look for a cast
5767  * to json (note: not to jsonb even if is_jsonb is true), if
5768  * it's not built-in.
5769  */
5770  *tcategory = JSONTYPE_OTHER;
5771  if (typoid >= FirstNormalObjectId)
5772  {
5773  Oid castfunc;
5774  CoercionPathType ctype;
5775 
5776  ctype = find_coercion_pathway(JSONOID, typoid,
5778  &castfunc);
5779  if (ctype == COERCION_PATH_FUNC && OidIsValid(castfunc))
5780  {
5781  *outfuncoid = castfunc;
5782  *tcategory = JSONTYPE_CAST;
5783  }
5784  else
5785  {
5786  /* non builtin type with no cast */
5787  getTypeOutputInfo(typoid, outfuncoid, &typisvarlena);
5788  }
5789  }
5790  else
5791  {
5792  /* any other builtin type */
5793  getTypeOutputInfo(typoid, outfuncoid, &typisvarlena);
5794  }
5795  }
5796  break;
5797  }
5798 }
#define OidIsValid(objectId)
Definition: c.h:764
@ JSONTYPE_JSON
Definition: jsonfuncs.h:75
@ JSONTYPE_TIMESTAMP
Definition: jsonfuncs.h:73
@ JSONTYPE_NUMERIC
Definition: jsonfuncs.h:71
@ JSONTYPE_DATE
Definition: jsonfuncs.h:72
@ JSONTYPE_BOOL
Definition: jsonfuncs.h:70
@ JSONTYPE_OTHER
Definition: jsonfuncs.h:80
@ JSONTYPE_CAST
Definition: jsonfuncs.h:79
@ JSONTYPE_COMPOSITE
Definition: jsonfuncs.h:78
@ JSONTYPE_ARRAY
Definition: jsonfuncs.h:77
@ JSONTYPE_TIMESTAMPTZ
Definition: jsonfuncs.h:74
@ JSONTYPE_JSONB
Definition: jsonfuncs.h:76
Oid get_element_type(Oid typid)
Definition: lsyscache.c:2741
bool type_is_rowtype(Oid typid)
Definition: lsyscache.c:2637
void getTypeOutputInfo(Oid type, Oid *typOutput, bool *typIsVarlena)
Definition: lsyscache.c:2889
Oid getBaseType(Oid typid)
Definition: lsyscache.c:2503
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:644
#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 1941 of file jsonfuncs.c.

1942 {
1943  return each_worker(fcinfo, false);
1944 }
static Datum each_worker(FunctionCallInfo fcinfo, bool as_text)
Definition: jsonfuncs.c:2049

References each_worker().

◆ json_each_text()

Datum json_each_text ( PG_FUNCTION_ARGS  )

Definition at line 1953 of file jsonfuncs.c.

1954 {
1955  return each_worker(fcinfo, true);
1956 }

References each_worker().

◆ json_errsave_error()

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

Definition at line 629 of file jsonfuncs.c.

631 {
635  errsave(escontext,
636  (errcode(ERRCODE_UNTRANSLATABLE_CHARACTER),
637  errmsg("unsupported Unicode escape sequence"),
639  report_json_context(lex)));
640  else if (error == JSON_SEM_ACTION_FAILED)
641  {
642  /* semantic action function had better have reported something */
643  if (!SOFT_ERROR_OCCURRED(escontext))
644  elog(ERROR, "JSON semantic action function did not provide error information");
645  }
646  else
647  errsave(escontext,
648  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
649  errmsg("invalid input syntax for type %s", "json"),
651  report_json_context(lex)));
652 }
int errdetail_internal(const char *fmt,...)
Definition: elog.c:1229
#define errsave(context,...)
Definition: elog.h:260
char * json_errdetail(JsonParseErrorType error, JsonLexContext *lex)
Definition: jsonapi.c:1136
@ JSON_SEM_ACTION_FAILED
Definition: jsonapi.h:57
@ JSON_UNICODE_CODE_POINT_ZERO
Definition: jsonapi.h:51
@ JSON_UNICODE_UNTRANSLATABLE
Definition: jsonapi.h:54
@ JSON_UNICODE_HIGH_ESCAPE
Definition: jsonapi.h:53
static int report_json_context(JsonLexContext *lex)
Definition: jsonfuncs.c:665
#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 999 of file jsonfuncs.c.

1000 {
1001  return get_path_all(fcinfo, false);
1002 }
static Datum get_path_all(FunctionCallInfo fcinfo, bool as_text)
Definition: jsonfuncs.c:1014

References get_path_all().

◆ json_extract_path_text()

Datum json_extract_path_text ( PG_FUNCTION_ARGS  )

Definition at line 1005 of file jsonfuncs.c.

1006 {
1007  return get_path_all(fcinfo, true);
1008 }

References get_path_all().

◆ json_get_first_token()

JsonTokenType json_get_first_token ( text json,
bool  throw_error 
)

Definition at line 5671 of file jsonfuncs.c.

5672 {
5673  JsonLexContext *lex;
5674  JsonParseErrorType result;
5675 
5676  lex = makeJsonLexContext(json, false);
5677 
5678  /* Lex exactly one token from the input and check its type. */
5679  result = json_lex(lex);
5680 
5681  if (result == JSON_SUCCESS)
5682  return lex->token_type;
5683 
5684  if (throw_error)
5685  json_errsave_error(result, lex, NULL);
5686 
5687  return JSON_TOKEN_INVALID; /* invalid json */
5688 }
JsonParseErrorType json_lex(JsonLexContext *lex)
Definition: jsonapi.c:552
@ 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 836 of file jsonfuncs.c.

837 {
838  text *json = PG_GETARG_TEXT_PP(0);
839  text *fname = PG_GETARG_TEXT_PP(1);
840  char *fnamestr = text_to_cstring(fname);
841  text *result;
842 
843  result = get_worker(json, &fnamestr, NULL, 1, false);
844 
845  if (result != NULL)
846  PG_RETURN_TEXT_P(result);
847  else
848  PG_RETURN_NULL();
849 }
char * text_to_cstring(const text *t)
Definition: varlena.c:215

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

875 {
876  text *json = PG_GETARG_TEXT_PP(0);
877  text *fname = PG_GETARG_TEXT_PP(1);
878  char *fnamestr = text_to_cstring(fname);
879  text *result;
880 
881  result = get_worker(json, &fnamestr, NULL, 1, true);
882 
883  if (result != NULL)
884  PG_RETURN_TEXT_P(result);
885  else
886  PG_RETURN_NULL();
887 }

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

721 {
722  FuncCallContext *funcctx;
723  OkeysState *state;
724 
725  if (SRF_IS_FIRSTCALL())
726  {
727  text *json = PG_GETARG_TEXT_PP(0);
728  JsonLexContext *lex = makeJsonLexContext(json, true);
729  JsonSemAction *sem;
730  MemoryContext oldcontext;
731 
732  funcctx = SRF_FIRSTCALL_INIT();
733  oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
734 
735  state = palloc(sizeof(OkeysState));
736  sem = palloc0(sizeof(JsonSemAction));
737 
738  state->lex = lex;
739  state->result_size = 256;
740  state->result_count = 0;
741  state->sent_count = 0;
742  state->result = palloc(256 * sizeof(char *));
743 
744  sem->semstate = (void *) state;
746  sem->scalar = okeys_scalar;
748  /* remainder are all NULL, courtesy of palloc0 above */
749 
750  pg_parse_json_or_ereport(lex, sem);
751  /* keys are now in state->result */
752 
753  pfree(lex->strval->data);
754  pfree(lex->strval);
755  pfree(lex);
756  pfree(sem);
757 
758  MemoryContextSwitchTo(oldcontext);
759  funcctx->user_fctx = (void *) state;
760  }
761 
762  funcctx = SRF_PERCALL_SETUP();
763  state = (OkeysState *) funcctx->user_fctx;
764 
765  if (state->sent_count < state->result_count)
766  {
767  char *nxt = state->result[state->sent_count++];
768 
769  SRF_RETURN_NEXT(funcctx, CStringGetTextDatum(nxt));
770  }
771 
772  SRF_RETURN_DONE(funcctx);
773 }
#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:799
static JsonParseErrorType okeys_object_field_start(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:776
static JsonParseErrorType okeys_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:814
void * user_fctx
Definition: funcapi.h:82
MemoryContext multi_call_memory_ctx
Definition: funcapi.h:101
StringInfo strval
Definition: jsonapi.h:86

References JsonSemAction::array_start, CStringGetTextDatum, StringInfoData::data, if(), makeJsonLexContext(), MemoryContextSwitchTo(), FuncCallContext::multi_call_memory_ctx, JsonSemAction::object_field_start, okeys_array_start(), okeys_object_field_start(), okeys_scalar(), palloc(), palloc0(), pfree(), PG_GETARG_TEXT_PP, pg_parse_json_or_ereport, JsonSemAction::scalar, JsonSemAction::semstate, SRF_FIRSTCALL_INIT, SRF_IS_FIRSTCALL, SRF_PERCALL_SETUP, SRF_RETURN_DONE, SRF_RETURN_NEXT, JsonLexContext::strval, and FuncCallContext::user_fctx.

◆ json_populate_record()

Datum json_populate_record ( PG_FUNCTION_ARGS  )

Definition at line 2467 of file jsonfuncs.c.

2468 {
2469  return populate_record_worker(fcinfo, "json_populate_record",
2470  true, true);
2471 }
static Datum populate_record_worker(FunctionCallInfo fcinfo, const char *funcname, bool is_json, bool have_record_arg)
Definition: jsonfuncs.c:3440

References populate_record_worker().

◆ json_populate_recordset()

Datum json_populate_recordset ( PG_FUNCTION_ARGS  )

Definition at line 3715 of file jsonfuncs.c.

3716 {
3717  return populate_recordset_worker(fcinfo, "json_populate_recordset",
3718  true, true);
3719 }
static Datum populate_recordset_worker(FunctionCallInfo fcinfo, const char *funcname, bool is_json, bool have_record_arg)
Definition: jsonfuncs.c:3766

References populate_recordset_worker().

◆ json_strip_nulls()

Datum json_strip_nulls ( PG_FUNCTION_ARGS  )

Definition at line 4216 of file jsonfuncs.c.

4217 {
4218  text *json = PG_GETARG_TEXT_PP(0);
4220  JsonLexContext *lex;
4221  JsonSemAction *sem;
4222 
4223  lex = makeJsonLexContext(json, true);
4224  state = palloc0(sizeof(StripnullState));
4225  sem = palloc0(sizeof(JsonSemAction));
4226 
4227  state->strval = makeStringInfo();
4228  state->skip_next_null = false;
4229  state->lex = lex;
4230 
4231  sem->semstate = (void *) state;
4233  sem->object_end = sn_object_end;
4234  sem->array_start = sn_array_start;
4235  sem->array_end = sn_array_end;
4236  sem->scalar = sn_scalar;
4239 
4240  pg_parse_json_or_ereport(lex, sem);
4241 
4243  state->strval->len));
4244 }
static JsonParseErrorType sn_object_end(void *state)
Definition: jsonfuncs.c:4122
static JsonParseErrorType sn_array_element_start(void *state, bool isnull)
Definition: jsonfuncs.c:4182
static JsonParseErrorType sn_object_start(void *state)
Definition: jsonfuncs.c:4112
static JsonParseErrorType sn_array_start(void *state)
Definition: jsonfuncs.c:4132
static JsonParseErrorType sn_array_end(void *state)
Definition: jsonfuncs.c:4142
static JsonParseErrorType sn_object_field_start(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:4152
static JsonParseErrorType sn_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:4193
StringInfo makeStringInfo(void)
Definition: stringinfo.c:41

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

◆ json_to_record()

Datum json_to_record ( PG_FUNCTION_ARGS  )

Definition at line 2474 of file jsonfuncs.c.

2475 {
2476  return populate_record_worker(fcinfo, "json_to_record",
2477  true, false);
2478 }

References populate_record_worker().

◆ json_to_recordset()

Datum json_to_recordset ( PG_FUNCTION_ARGS  )

Definition at line 3722 of file jsonfuncs.c.

3723 {
3724  return populate_recordset_worker(fcinfo, "json_to_recordset",
3725  true, false);
3726 }

References populate_recordset_worker().

◆ jsonb_array_element()

Datum jsonb_array_element ( PG_FUNCTION_ARGS  )

Definition at line 927 of file jsonfuncs.c.

928 {
929  Jsonb *jb = PG_GETARG_JSONB_P(0);
930  int element = PG_GETARG_INT32(1);
931  JsonbValue *v;
932 
933  if (!JB_ROOT_IS_ARRAY(jb))
934  PG_RETURN_NULL();
935 
936  /* Handle negative subscript */
937  if (element < 0)
938  {
939  uint32 nelements = JB_ROOT_COUNT(jb);
940 
941  if (-element > nelements)
942  PG_RETURN_NULL();
943  else
944  element += nelements;
945  }
946 
948  if (v != NULL)
950 
951  PG_RETURN_NULL();
952 }
unsigned int uint32
Definition: c.h:495
#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:470

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

◆ jsonb_array_element_text()

Datum jsonb_array_element_text ( PG_FUNCTION_ARGS  )

Definition at line 970 of file jsonfuncs.c.

971 {
972  Jsonb *jb = PG_GETARG_JSONB_P(0);
973  int element = PG_GETARG_INT32(1);
974  JsonbValue *v;
975 
976  if (!JB_ROOT_IS_ARRAY(jb))
977  PG_RETURN_NULL();
978 
979  /* Handle negative subscript */
980  if (element < 0)
981  {
982  uint32 nelements = JB_ROOT_COUNT(jb);
983 
984  if (-element > nelements)
985  PG_RETURN_NULL();
986  else
987  element += nelements;
988  }
989 
991 
992  if (v != NULL && v->type != jbvNull)
994 
995  PG_RETURN_NULL();
996 }

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

2200 {
2201  return elements_worker_jsonb(fcinfo, "jsonb_array_elements", false);
2202 }
static Datum elements_worker_jsonb(FunctionCallInfo fcinfo, const char *funcname, bool as_text)
Definition: jsonfuncs.c:2211

References elements_worker_jsonb().

◆ jsonb_array_elements_text()

Datum jsonb_array_elements_text ( PG_FUNCTION_ARGS  )

Definition at line 2205 of file jsonfuncs.c.

2206 {
2207  return elements_worker_jsonb(fcinfo, "jsonb_array_elements_text", true);
2208 }

References elements_worker_jsonb().

◆ jsonb_array_length()

Datum jsonb_array_length ( PG_FUNCTION_ARGS  )

Definition at line 1869 of file jsonfuncs.c.

1870 {
1871  Jsonb *jb = PG_GETARG_JSONB_P(0);
1872 
1873  if (JB_ROOT_IS_SCALAR(jb))
1874  ereport(ERROR,
1875  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1876  errmsg("cannot get array length of a scalar")));
1877  else if (!JB_ROOT_IS_ARRAY(jb))
1878  ereport(ERROR,
1879  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1880  errmsg("cannot get array length of a non-array")));
1881 
1883 }

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

4325 {
4326  Jsonb *jb1 = PG_GETARG_JSONB_P(0);
4327  Jsonb *jb2 = PG_GETARG_JSONB_P(1);
4328  JsonbParseState *state = NULL;
4329  JsonbValue *res;
4330  JsonbIterator *it1,
4331  *it2;
4332 
4333  /*
4334  * If one of the jsonb is empty, just return the other if it's not scalar
4335  * and both are of the same kind. If it's a scalar or they are of
4336  * different kinds we need to perform the concatenation even if one is
4337  * empty.
4338  */
4339  if (JB_ROOT_IS_OBJECT(jb1) == JB_ROOT_IS_OBJECT(jb2))
4340  {
4341  if (JB_ROOT_COUNT(jb1) == 0 && !JB_ROOT_IS_SCALAR(jb2))
4342  PG_RETURN_JSONB_P(jb2);
4343  else if (JB_ROOT_COUNT(jb2) == 0 && !JB_ROOT_IS_SCALAR(jb1))
4344  PG_RETURN_JSONB_P(jb1);
4345  }
4346 
4347  it1 = JsonbIteratorInit(&jb1->root);
4348  it2 = JsonbIteratorInit(&jb2->root);
4349 
4350  res = IteratorConcat(&it1, &it2, &state);
4351 
4352  Assert(res != NULL);
4353 
4355 }
static JsonbValue * IteratorConcat(JsonbIterator **it1, JsonbIterator **it2, JsonbParseState **state)
Definition: jsonfuncs.c:4777

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

4366 {
4367  Jsonb *in = PG_GETARG_JSONB_P(0);
4368  text *key = PG_GETARG_TEXT_PP(1);
4369  char *keyptr = VARDATA_ANY(key);
4370  int keylen = VARSIZE_ANY_EXHDR(key);
4371  JsonbParseState *state = NULL;
4372  JsonbIterator *it;
4373  JsonbValue v,
4374  *res = NULL;
4375  bool skipNested = false;
4377 
4378  if (JB_ROOT_IS_SCALAR(in))
4379  ereport(ERROR,
4380  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4381  errmsg("cannot delete from scalar")));
4382 
4383  if (JB_ROOT_COUNT(in) == 0)
4384  PG_RETURN_JSONB_P(in);
4385 
4386  it = JsonbIteratorInit(&in->root);
4387 
4388  while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE)
4389  {
4390  skipNested = true;
4391 
4392  if ((r == WJB_ELEM || r == WJB_KEY) &&
4393  (v.type == jbvString && keylen == v.val.string.len &&
4394  memcmp(keyptr, v.val.string.val, keylen) == 0))
4395  {
4396  /* skip corresponding value as well */
4397  if (r == WJB_KEY)
4398  (void) JsonbIteratorNext(&it, &v, true);
4399 
4400  continue;
4401  }
4402 
4403  res = pushJsonbValue(&state, r, r < WJB_BEGIN_ARRAY ? &v : NULL);
4404  }
4405 
4406  Assert(res != NULL);
4407 
4409 }
#define VARDATA_ANY(PTR)
Definition: varatt.h:324
#define VARSIZE_ANY_EXHDR(PTR)
Definition: varatt.h:317

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

4419 {
4420  Jsonb *in = PG_GETARG_JSONB_P(0);
4421  ArrayType *keys = PG_GETARG_ARRAYTYPE_P(1);
4422  Datum *keys_elems;
4423  bool *keys_nulls;
4424  int keys_len;
4425  JsonbParseState *state = NULL;
4426  JsonbIterator *it;
4427  JsonbValue v,
4428  *res = NULL;
4429  bool skipNested = false;
4431 
4432  if (ARR_NDIM(keys) > 1)
4433  ereport(ERROR,
4434  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
4435  errmsg("wrong number of array subscripts")));
4436 
4437  if (JB_ROOT_IS_SCALAR(in))
4438  ereport(ERROR,
4439  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4440  errmsg("cannot delete from scalar")));
4441 
4442  if (JB_ROOT_COUNT(in) == 0)
4443  PG_RETURN_JSONB_P(in);
4444 
4445  deconstruct_array_builtin(keys, TEXTOID, &keys_elems, &keys_nulls, &keys_len);
4446 
4447  if (keys_len == 0)
4448  PG_RETURN_JSONB_P(in);
4449 
4450  it = JsonbIteratorInit(&in->root);
4451 
4452  while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE)
4453  {
4454  skipNested = true;
4455 
4456  if ((r == WJB_ELEM || r == WJB_KEY) && v.type == jbvString)
4457  {
4458  int i;
4459  bool found = false;
4460 
4461  for (i = 0; i < keys_len; i++)
4462  {
4463  char *keyptr;
4464  int keylen;
4465 
4466  if (keys_nulls[i])
4467  continue;
4468 
4469  /* We rely on the array elements not being toasted */
4470  keyptr = VARDATA_ANY(keys_elems[i]);
4471  keylen = VARSIZE_ANY_EXHDR(keys_elems[i]);
4472  if (keylen == v.val.string.len &&
4473  memcmp(keyptr, v.val.string.val, keylen) == 0)
4474  {
4475  found = true;
4476  break;
4477  }
4478  }
4479  if (found)
4480  {
4481  /* skip corresponding value as well */
4482  if (r == WJB_KEY)
4483  (void) JsonbIteratorNext(&it, &v, true);
4484 
4485  continue;
4486  }
4487  }
4488 
4489  res = pushJsonbValue(&state, r, r < WJB_BEGIN_ARRAY ? &v : NULL);
4490  }
4491 
4492  Assert(res != NULL);
4493 
4495 }
#define ARR_NDIM(a)
Definition: array.h:283

References ARR_NDIM, Assert(), deconstruct_array_builtin(), ereport, errcode(), errmsg(), ERROR, i, JB_ROOT_COUNT, JB_ROOT_IS_SCALAR, jbvString, JsonbIteratorInit(), JsonbIteratorNext(), JsonbValueToJsonb(), PG_GETARG_ARRAYTYPE_P, PG_GETARG_JSONB_P, PG_RETURN_JSONB_P, pushJsonbValue(), res, Jsonb::root, JsonbValue::type, JsonbValue::val, VARDATA_ANY, VARSIZE_ANY_EXHDR, WJB_BEGIN_ARRAY, WJB_DONE, WJB_ELEM, and WJB_KEY.

◆ jsonb_delete_idx()

Datum jsonb_delete_idx ( PG_FUNCTION_ARGS  )

Definition at line 4505 of file jsonfuncs.c.

4506 {
4507  Jsonb *in = PG_GETARG_JSONB_P(0);
4508  int idx = PG_GETARG_INT32(1);
4509  JsonbParseState *state = NULL;
4510  JsonbIterator *it;
4511  uint32 i = 0,
4512  n;
4513  JsonbValue v,
4514  *res = NULL;
4516 
4517  if (JB_ROOT_IS_SCALAR(in))
4518  ereport(ERROR,
4519  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4520  errmsg("cannot delete from scalar")));
4521 
4522  if (JB_ROOT_IS_OBJECT(in))
4523  ereport(ERROR,
4524  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4525  errmsg("cannot delete from object using integer index")));
4526 
4527  if (JB_ROOT_COUNT(in) == 0)
4528  PG_RETURN_JSONB_P(in);
4529 
4530  it = JsonbIteratorInit(&in->root);
4531 
4532  r = JsonbIteratorNext(&it, &v, false);
4533  Assert(r == WJB_BEGIN_ARRAY);
4534  n = v.val.array.nElems;
4535 
4536  if (idx < 0)
4537  {
4538  if (-idx > n)
4539  idx = n;
4540  else
4541  idx = n + idx;
4542  }
4543 
4544  if (idx >= n)
4545  PG_RETURN_JSONB_P(in);
4546 
4547  pushJsonbValue(&state, r, NULL);
4548 
4549  while ((r = JsonbIteratorNext(&it, &v, true)) != WJB_DONE)
4550  {
4551  if (r == WJB_ELEM)
4552  {
4553  if (i++ == idx)
4554  continue;
4555  }
4556 
4557  res = pushJsonbValue(&state, r, r < WJB_BEGIN_ARRAY ? &v : NULL);
4558  }
4559 
4560  Assert(res != NULL);
4561 
4563 }
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 4685 of file jsonfuncs.c.

4686 {
4687  Jsonb *in = PG_GETARG_JSONB_P(0);
4688  ArrayType *path = PG_GETARG_ARRAYTYPE_P(1);
4689  JsonbValue *res = NULL;
4690  Datum *path_elems;
4691  bool *path_nulls;
4692  int path_len;
4693  JsonbIterator *it;
4694  JsonbParseState *st = NULL;
4695 
4696  if (ARR_NDIM(path) > 1)
4697  ereport(ERROR,
4698  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
4699  errmsg("wrong number of array subscripts")));
4700 
4701  if (JB_ROOT_IS_SCALAR(in))
4702  ereport(ERROR,
4703  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4704  errmsg("cannot delete path in scalar")));
4705 
4706  if (JB_ROOT_COUNT(in) == 0)
4707  PG_RETURN_JSONB_P(in);
4708 
4709  deconstruct_array_builtin(path, TEXTOID, &path_elems, &path_nulls, &path_len);
4710 
4711  if (path_len == 0)
4712  PG_RETURN_JSONB_P(in);
4713 
4714  it = JsonbIteratorInit(&in->root);
4715 
4716  res = setPath(&it, path_elems, path_nulls, path_len, &st,
4717  0, NULL, JB_PATH_DELETE);
4718 
4719  Assert(res != NULL);
4720 
4722 }
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:4905
#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 1947 of file jsonfuncs.c.

1948 {
1949  return each_worker_jsonb(fcinfo, "jsonb_each", false);
1950 }
static Datum each_worker_jsonb(FunctionCallInfo fcinfo, const char *funcname, bool as_text)
Definition: jsonfuncs.c:1965

References each_worker_jsonb().

◆ jsonb_each_text()

Datum jsonb_each_text ( PG_FUNCTION_ARGS  )

Definition at line 1959 of file jsonfuncs.c.

1960 {
1961  return each_worker_jsonb(fcinfo, "jsonb_each_text", true);
1962 }

References each_worker_jsonb().

◆ jsonb_extract_path()

Datum jsonb_extract_path ( PG_FUNCTION_ARGS  )

Definition at line 1477 of file jsonfuncs.c.

1478 {
1479  return get_jsonb_path_all(fcinfo, false);
1480 }
static Datum get_jsonb_path_all(FunctionCallInfo fcinfo, bool as_text)
Definition: jsonfuncs.c:1489

References get_jsonb_path_all().

◆ jsonb_extract_path_text()

Datum jsonb_extract_path_text ( PG_FUNCTION_ARGS  )

Definition at line 1483 of file jsonfuncs.c.

1484 {
1485  return get_jsonb_path_all(fcinfo, true);
1486 }

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

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

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

4729 {
4730  Jsonb *in = PG_GETARG_JSONB_P(0);
4731  ArrayType *path = PG_GETARG_ARRAYTYPE_P(1);
4732  Jsonb *newjsonb = PG_GETARG_JSONB_P(2);
4734  bool after = PG_GETARG_BOOL(3);
4735  JsonbValue *res = NULL;
4736  Datum *path_elems;
4737  bool *path_nulls;
4738  int path_len;
4739  JsonbIterator *it;
4740  JsonbParseState *st = NULL;
4741 
4742  JsonbToJsonbValue(newjsonb, &newval);
4743 
4744  if (ARR_NDIM(path) > 1)
4745  ereport(ERROR,
4746  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
4747  errmsg("wrong number of array subscripts")));
4748 
4749  if (JB_ROOT_IS_SCALAR(in))
4750  ereport(ERROR,
4751  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4752  errmsg("cannot set path in scalar")));
4753 
4754  deconstruct_array_builtin(path, TEXTOID, &path_elems, &path_nulls, &path_len);
4755 
4756  if (path_len == 0)
4757  PG_RETURN_JSONB_P(in);
4758 
4759  it = JsonbIteratorInit(&in->root);
4760 
4761  res = setPath(&it, path_elems, path_nulls, path_len, &st, 0, &newval,
4763 
4764  Assert(res != NULL);
4765 
4767 }
#define PG_GETARG_BOOL(n)
Definition: fmgr.h:274
#define newval
void JsonbToJsonbValue(Jsonb *jsonb, JsonbValue *val)
Definition: jsonb_util.c:74
#define JB_PATH_INSERT_BEFORE
Definition: jsonfuncs.c: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 852 of file jsonfuncs.c.

853 {
854  Jsonb *jb = PG_GETARG_JSONB_P(0);
855  text *key = PG_GETARG_TEXT_PP(1);
856  JsonbValue *v;
857  JsonbValue vbuf;
858 
859  if (!JB_ROOT_IS_OBJECT(jb))
860  PG_RETURN_NULL();
861 
863  VARDATA_ANY(key),
865  &vbuf);
866 
867  if (v != NULL)
869 
870  PG_RETURN_NULL();
871 }

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

891 {
892  Jsonb *jb = PG_GETARG_JSONB_P(0);
893  text *key = PG_GETARG_TEXT_PP(1);
894  JsonbValue *v;
895  JsonbValue vbuf;
896 
897  if (!JB_ROOT_IS_OBJECT(jb))
898  PG_RETURN_NULL();
899 
901  VARDATA_ANY(key),
903  &vbuf);
904 
905  if (v != NULL && v->type != jbvNull)
907 
908  PG_RETURN_NULL();
909 }

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

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

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

2454 {
2455  return populate_record_worker(fcinfo, "jsonb_populate_record",
2456  false, true);
2457 }

References populate_record_worker().

◆ jsonb_populate_recordset()

Datum jsonb_populate_recordset ( PG_FUNCTION_ARGS  )

Definition at line 3701 of file jsonfuncs.c.

3702 {
3703  return populate_recordset_worker(fcinfo, "jsonb_populate_recordset",
3704  false, true);
3705 }

References populate_recordset_worker().

◆ jsonb_pretty()

Datum jsonb_pretty ( PG_FUNCTION_ARGS  )

Definition at line 4308 of file jsonfuncs.c.

4309 {
4310  Jsonb *jb = PG_GETARG_JSONB_P(0);
4312 
4313  JsonbToCStringIndent(str, &jb->root, VARSIZE(jb));
4314 
4316 }
char * JsonbToCStringIndent(StringInfo out, JsonbContainer *in, int estimated_len)
Definition: jsonb.c:487

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

◆ jsonb_set()

Datum jsonb_set ( PG_FUNCTION_ARGS  )

Definition at line 4569 of file jsonfuncs.c.

4570 {
4571  Jsonb *in = PG_GETARG_JSONB_P(0);
4572  ArrayType *path = PG_GETARG_ARRAYTYPE_P(1);
4573  Jsonb *newjsonb = PG_GETARG_JSONB_P(2);
4575  bool create = PG_GETARG_BOOL(3);
4576  JsonbValue *res = NULL;
4577  Datum *path_elems;
4578  bool *path_nulls;
4579  int path_len;
4580  JsonbIterator *it;
4581  JsonbParseState *st = NULL;
4582 
4583  JsonbToJsonbValue(newjsonb, &newval);
4584 
4585  if (ARR_NDIM(path) > 1)
4586  ereport(ERROR,
4587  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
4588  errmsg("wrong number of array subscripts")));
4589 
4590  if (JB_ROOT_IS_SCALAR(in))
4591  ereport(ERROR,
4592  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4593  errmsg("cannot set path in scalar")));
4594 
4595  if (JB_ROOT_COUNT(in) == 0 && !create)
4596  PG_RETURN_JSONB_P(in);
4597 
4598  deconstruct_array_builtin(path, TEXTOID, &path_elems, &path_nulls, &path_len);
4599 
4600  if (path_len == 0)
4601  PG_RETURN_JSONB_P(in);
4602 
4603  it = JsonbIteratorInit(&in->root);
4604 
4605  res = setPath(&it, path_elems, path_nulls, path_len, &st,
4606  0, &newval, create ? JB_PATH_CREATE : JB_PATH_REPLACE);
4607 
4608  Assert(res != NULL);
4609 
4611 }
#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 1668 of file jsonfuncs.c.

1670 {
1671  JsonbValue *res;
1672  JsonbParseState *state = NULL;
1673  JsonbIterator *it;
1674  bool *path_nulls = palloc0(path_len * sizeof(bool));
1675 
1676  if (newval->type == jbvArray && newval->val.array.rawScalar)
1677  *newval = newval->val.array.elems[0];
1678 
1679  it = JsonbIteratorInit(&jb->root);
1680 
1681  res = setPath(&it, path, path_nulls, path_len, &state, 0, newval,
1684 
1685  pfree(path_nulls);
1686 
1688 }
@ 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 4618 of file jsonfuncs.c.

4619 {
4620  /* Jsonb *in = PG_GETARG_JSONB_P(0); */
4621  /* ArrayType *path = PG_GETARG_ARRAYTYPE_P(1); */
4622  /* Jsonb *newval = PG_GETARG_JSONB_P(2); */
4623  /* bool create = PG_GETARG_BOOL(3); */
4624  text *handle_null;
4625  char *handle_val;
4626 
4627  if (PG_ARGISNULL(0) || PG_ARGISNULL(1) || PG_ARGISNULL(3))
4628  PG_RETURN_NULL();
4629 
4630  /* could happen if they pass in an explicit NULL */
4631  if (PG_ARGISNULL(4))
4632  ereport(ERROR,
4633  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4634  errmsg("null_value_treatment must be \"delete_key\", \"return_target\", \"use_json_null\", or \"raise_exception\"")));
4635 
4636  /* if the new value isn't an SQL NULL just call jsonb_set */
4637  if (!PG_ARGISNULL(2))
4638  return jsonb_set(fcinfo);
4639 
4640  handle_null = PG_GETARG_TEXT_P(4);
4641  handle_val = text_to_cstring(handle_null);
4642 
4643  if (strcmp(handle_val, "raise_exception") == 0)
4644  {
4645  ereport(ERROR,
4646  (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
4647  errmsg("JSON value must not be null"),
4648  errdetail("Exception was raised because null_value_treatment is \"raise_exception\"."),
4649  errhint("To avoid, either change the null_value_treatment argument or ensure that an SQL NULL is not passed.")));
4650  return (Datum) 0; /* silence stupider compilers */
4651  }
4652  else if (strcmp(handle_val, "use_json_null") == 0)
4653  {
4654  Datum newval;
4655 
4657 
4658  fcinfo->args[2].value = newval;
4659  fcinfo->args[2].isnull = false;
4660  return jsonb_set(fcinfo);
4661  }
4662  else if (strcmp(handle_val, "delete_key") == 0)
4663  {
4664  return jsonb_delete_path(fcinfo);
4665  }
4666  else if (strcmp(handle_val, "return_target") == 0)
4667  {
4668  Jsonb *in = PG_GETARG_JSONB_P(0);
4669 
4670  PG_RETURN_JSONB_P(in);
4671  }
4672  else
4673  {
4674  ereport(ERROR,
4675  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4676  errmsg("null_value_treatment must be \"delete_key\", \"return_target\", \"use_json_null\", or \"raise_exception\"")));
4677  return (Datum) 0; /* silence stupider compilers */
4678  }
4679 }
int errdetail(const char *fmt,...)
Definition: elog.c:1202
#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:77
Datum jsonb_delete_path(PG_FUNCTION_ARGS)
Definition: jsonfuncs.c:4685
Datum jsonb_set(PG_FUNCTION_ARGS)
Definition: jsonfuncs.c:4569
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 4250 of file jsonfuncs.c.

4251 {
4252  Jsonb *jb = PG_GETARG_JSONB_P(0);
4253  JsonbIterator *it;
4254  JsonbParseState *parseState = NULL;
4255  JsonbValue *res = NULL;
4256  JsonbValue v,
4257  k;
4259  bool last_was_key = false;
4260 
4261  if (JB_ROOT_IS_SCALAR(jb))
4262  PG_RETURN_POINTER(jb);
4263 
4264  it = JsonbIteratorInit(&jb->root);
4265 
4266  while ((type = JsonbIteratorNext(&it, &v, false)) != WJB_DONE)
4267  {
4268  Assert(!(type == WJB_KEY && last_was_key));
4269 
4270  if (type == WJB_KEY)
4271  {
4272  /* stash the key until we know if it has a null value */
4273  k = v;
4274  last_was_key = true;
4275  continue;
4276  }
4277 
4278  if (last_was_key)
4279  {
4280  /* if the last element was a key this one can't be */
4281  last_was_key = false;
4282 
4283  /* skip this field if value is null */
4284  if (type == WJB_VALUE && v.type == jbvNull)
4285  continue;
4286 
4287  /* otherwise, do a delayed push of the key */
4288  (void) pushJsonbValue(&parseState, WJB_KEY, &k);
4289  }
4290 
4291  if (type == WJB_VALUE || type == WJB_ELEM)
4292  res = pushJsonbValue(&parseState, type, &v);
4293  else
4294  res = pushJsonbValue(&parseState, type, NULL);
4295  }
4296 
4297  Assert(res != NULL);
4298 
4300 }
#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 2460 of file jsonfuncs.c.

2461 {
2462  return populate_record_worker(fcinfo, "jsonb_to_record",
2463  false, false);
2464 }

References populate_record_worker().

◆ jsonb_to_recordset()

Datum jsonb_to_recordset ( PG_FUNCTION_ARGS  )

Definition at line 3708 of file jsonfuncs.c.

3709 {
3710  return populate_recordset_worker(fcinfo, "jsonb_to_recordset",
3711  false, false);
3712 }

References populate_recordset_worker().

◆ JsonbValueAsText()

static text * JsonbValueAsText ( JsonbValue v)
static

Definition at line 1794 of file jsonfuncs.c.

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

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

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

◆ JsValueToJsObject()

static void JsValueToJsObject ( JsValue jsv,
JsObject jso 
)
static

Definition at line 2849 of file jsonfuncs.c.

2850 {
2851  jso->is_json = jsv->is_json;
2852 
2853  if (jsv->is_json)
2854  {
2855  /* convert plain-text json into a hash table */
2856  jso->val.json_hash =
2857  get_json_object_as_hash(jsv->val.json.str,
2858  jsv->val.json.len >= 0
2859  ? jsv->val.json.len
2860  : strlen(jsv->val.json.str),
2861  "populate_composite");
2862  }
2863  else
2864  {
2865  JsonbValue *jbv = jsv->val.jsonb;
2866 
2867  if (jbv->type == jbvBinary &&
2868  JsonContainerIsObject(jbv->val.binary.data))
2869  {
2870  jso->val.jsonb_cont = jbv->val.binary.data;
2871  }
2872  else
2873  {
2874  bool is_scalar;
2875 
2876  is_scalar = IsAJsonbScalar(jbv) ||
2877  (jbv->type == jbvBinary &&
2878  JsonContainerIsScalar(jbv->val.binary.data));
2879  ereport(ERROR,
2880  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2881  is_scalar
2882  ? errmsg("cannot call %s on a scalar",
2883  "populate_composite")
2884  : errmsg("cannot call %s on an array",
2885  "populate_composite")));
2886  }
2887  }
2888 }
static HTAB * get_json_object_as_hash(char *json, int len, const char *funcname)
Definition: jsonfuncs.c:3545

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

Referenced by populate_composite().

◆ makeJsonLexContext()

JsonLexContext* makeJsonLexContext ( text json,
bool  need_escapes 
)

Definition at line 529 of file jsonfuncs.c.

530 {
531  /*
532  * Most callers pass a detoasted datum, but it's not clear that they all
533  * do. pg_detoast_datum_packed() is cheap insurance.
534  */
535  json = pg_detoast_datum_packed(json);
536 
538  VARSIZE_ANY_EXHDR(json),
540  need_escapes);
541 }
struct varlena * pg_detoast_datum_packed(struct varlena *datum)
Definition: fmgr.c:1847

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

800 {
801  OkeysState *_state = (OkeysState *) state;
802 
803  /* top level must be a json object */
804  if (_state->lex->lex_level == 0)
805  ereport(ERROR,
806  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
807  errmsg("cannot call %s on an array",
808  "json_object_keys")));
809 
810  return JSON_SUCCESS;
811 }
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 776 of file jsonfuncs.c.

777 {
778  OkeysState *_state = (OkeysState *) state;
779 
780  /* only collecting keys for the top level object */
781  if (_state->lex->lex_level != 1)
782  return JSON_SUCCESS;
783 
784  /* enlarge result array if necessary */
785  if (_state->result_count >= _state->result_size)
786  {
787  _state->result_size *= 2;
788  _state->result = (char **)
789  repalloc(_state->result, sizeof(char *) * _state->result_size);
790  }
791 
792  /* save a copy of the field name */
793  _state->result[_state->result_count++] = pstrdup(fname);
794 
795  return JSON_SUCCESS;
796 }
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1476
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 814 of file jsonfuncs.c.

815 {
816  OkeysState *_state = (OkeysState *) state;
817 
818  /* top level must be a json object */
819  if (_state->lex->lex_level == 0)
820  ereport(ERROR,
821  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
822  errmsg("cannot call %s on a scalar",
823  "json_object_keys")));
824 
825  return JSON_SUCCESS;
826 }

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

5298 {
5299  JsonbIterator *it;
5300  JsonbValue v;
5302  uint32 flags = 0;
5303 
5304  it = JsonbIteratorInit(&jb->root);
5305 
5306  type = JsonbIteratorNext(&it, &v, false);
5307 
5308  /*
5309  * We iterate over array (scalar internally is represented as array, so,
5310  * we will accept it too) to check all its elements. Flag names are
5311  * chosen the same as jsonb_typeof uses.
5312  */
5313  if (type != WJB_BEGIN_ARRAY)
5314  ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
5315  errmsg("wrong flag type, only arrays and scalars are allowed")));
5316 
5317  while ((type = JsonbIteratorNext(&it, &v, false)) == WJB_ELEM)
5318  {
5319  if (v.type != jbvString)
5320  ereport(ERROR,
5321  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
5322  errmsg("flag array element is not a string"),
5323  errhint("Possible values are: \"string\", \"numeric\", \"boolean\", \"key\", and \"all\".")));
5324 
5325  if (v.val.string.len == 3 &&
5326  pg_strncasecmp(v.val.string.val, "all", 3) == 0)
5327  flags |= jtiAll;
5328  else if (v.val.string.len == 3 &&
5329  pg_strncasecmp(v.val.string.val, "key", 3) == 0)
5330  flags |= jtiKey;
5331  else if (v.val.string.len == 6 &&
5332  pg_strncasecmp(v.val.string.val, "string", 6) == 0)
5333  flags |= jtiString;
5334  else if (v.val.string.len == 7 &&
5335  pg_strncasecmp(v.val.string.val, "numeric", 7) == 0)
5336  flags |= jtiNumeric;
5337  else if (v.val.string.len == 7 &&
5338  pg_strncasecmp(v.val.string.val, "boolean", 7) == 0)
5339  flags |= jtiBool;
5340  else
5341  ereport(ERROR,
5342  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
5343  errmsg("wrong flag in flag array: \"%s\"",
5344  pnstrdup(v.val.string.val, v.val.string.len)),
5345  errhint("Possible values are: \"string\", \"numeric\", \"boolean\", \"key\", and \"all\".")));
5346  }
5347 
5348  /* expect end of array now */
5349  if (type != WJB_END_ARRAY)
5350  elog(ERROR, "unexpected end of flag array");
5351 
5352  /* get final WJB_DONE and free iterator */
5353  type = JsonbIteratorNext(&it, &v, false);
5354  if (type != WJB_DONE)
5355  elog(ERROR, "unexpected end of flag array");
5356 
5357  return flags;
5358 }
@ jtiAll
Definition: jsonfuncs.h:30
char * pnstrdup(const char *in, Size len)
Definition: mcxt.c:1655
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 508 of file jsonfuncs.c.

510 {
511  JsonParseErrorType result;
512 
513  result = pg_parse_json(lex, sem);
514  if (result != JSON_SUCCESS)
515  {
516  json_errsave_error(result, lex, escontext);
517  return false;
518  }
519  return true;
520 }
JsonParseErrorType pg_parse_json(JsonLexContext *lex, JsonSemAction *sem)
Definition: jsonapi.c:169

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

Referenced by json_in(), and jsonb_from_cstring().

◆ populate_array()

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

Definition at line 2802 of file jsonfuncs.c.

2806 {
2808  Datum result;
2809  int *lbs;
2810  int i;
2811 
2812  ctx.aio = aio;
2813  ctx.mcxt = mcxt;
2814  ctx.acxt = CurrentMemoryContext;
2815  ctx.astate = initArrayResult(aio->element_type, ctx.acxt, true);
2816  ctx.colname = colname;
2817  ctx.ndims = 0; /* unknown yet */
2818  ctx.dims = NULL;
2819  ctx.sizes = NULL;
2820 
2821  if (jsv->is_json)
2822  populate_array_json(&ctx, jsv->val.json.str,
2823  jsv->val.json.len >= 0 ? jsv->val.json.len
2824  : strlen(jsv->val.json.str));
2825  else
2826  {
2827  populate_array_dim_jsonb(&ctx, jsv->val.jsonb, 1);
2828  ctx.dims[0] = ctx.sizes[0];
2829  }
2830 
2831  Assert(ctx.ndims > 0);
2832 
2833  lbs = palloc(sizeof(int) * ctx.ndims);
2834 
2835  for (i = 0; i < ctx.ndims; i++)
2836  lbs[i] = 1;
2837 
2838  result = makeMdArrayResult(ctx.astate, ctx.ndims, ctx.dims, lbs,
2839  ctx.acxt, true);
2840 
2841  pfree(ctx.dims);
2842  pfree(ctx.sizes);
2843  pfree(lbs);
2844 
2845  return result;
2846 }
ArrayBuildState * initArrayResult(Oid element_type, MemoryContext rcontext, bool subcontext)
Definition: arrayfuncs.c:5240
Datum makeMdArrayResult(ArrayBuildState *astate, int ndims, int *dims, int *lbs, MemoryContext rcontext, bool release)
Definition: arrayfuncs.c:5399
static void populate_array_json(PopulateArrayContext *ctx, char *json, int len)
Definition: jsonfuncs.c:2702
static void populate_array_dim_jsonb(PopulateArrayContext *ctx, JsonbValue *jbv, int ndim)
Definition: jsonfuncs.c:2731
Oid element_type
Definition: jsonfuncs.c:168
ArrayBuildState * astate
Definition: jsonfuncs.c:260
MemoryContext mcxt
Definition: jsonfuncs.c:263
ArrayIOData * aio
Definition: jsonfuncs.c:261
MemoryContext acxt
Definition: jsonfuncs.c:262
const char * colname
Definition: jsonfuncs.c:264

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

Referenced by populate_record_field().

◆ populate_array_array_end()

static JsonParseErrorType populate_array_array_end ( void *  _state)
static

Definition at line 2602 of file jsonfuncs.c.

2603 {
2605  PopulateArrayContext *ctx = state->ctx;
2606  int ndim = state->lex->lex_level;
2607 
2608  if (ctx->ndims <= 0)
2609  populate_array_assign_ndims(ctx, ndim + 1);
2610 
2611  if (ndim < ctx->ndims)
2612  populate_array_check_dimension(ctx, ndim);
2613 
2614  return JSON_SUCCESS;
2615 }
static void populate_array_check_dimension(PopulateArrayContext *ctx, int ndim)
Definition: jsonfuncs.c:2544
static void populate_array_assign_ndims(PopulateArrayContext *ctx, int ndims)
Definition: jsonfuncs.c:2525

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

Referenced by populate_array_json().

◆ populate_array_assign_ndims()

static void populate_array_assign_ndims ( PopulateArrayContext ctx,
int  ndims 
)
static

Definition at line 2525 of file jsonfuncs.c.

2526 {
2527  int i;
2528 
2529  Assert(ctx->ndims <= 0);
2530 
2531  if (ndims <= 0)
2533 
2534  ctx->ndims = ndims;
2535  ctx->dims = palloc(sizeof(int) * ndims);
2536  ctx->sizes = palloc0(sizeof(int) * ndims);
2537 
2538  for (i = 0; i < ndims; i++)
2539  ctx->dims[i] = -1; /* dimensions are unknown yet */
2540 }
static void populate_array_report_expected_array(PopulateArrayContext *ctx, int ndim)
Definition: jsonfuncs.c:2482

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

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

◆ populate_array_check_dimension()

static void populate_array_check_dimension ( PopulateArrayContext ctx,
int  ndim 
)
static

Definition at line 2544 of file jsonfuncs.c.

2545 {
2546  int dim = ctx->sizes[ndim]; /* current dimension counter */
2547 
2548  if (ctx->dims[ndim] == -1)
2549  ctx->dims[ndim] = dim; /* assign dimension if not yet known */
2550  else if (ctx->dims[ndim] != dim)
2551  ereport(ERROR,
2552  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2553  errmsg("malformed JSON array"),
2554  errdetail("Multidimensional arrays must have "
2555  "sub-arrays with matching dimensions.")));
2556 
2557  /* reset the current array dimension size counter */
2558  ctx->sizes[ndim] = 0;
2559 
2560  /* increment the parent dimension counter if it is a nested sub-array */
2561  if (ndim > 0)
2562  ctx->sizes[ndim - 1]++;
2563 }

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

Referenced by populate_array_array_end(), and populate_array_dim_jsonb().

◆ populate_array_dim_jsonb()

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

Definition at line 2731 of file jsonfuncs.c.

2734 {
2735  JsonbContainer *jbc = jbv->val.binary.data;
2736  JsonbIterator *it;
2737  JsonbIteratorToken tok;
2738  JsonbValue val;
2739  JsValue jsv;
2740 
2742 
2743  if (jbv->type != jbvBinary || !JsonContainerIsArray(jbc))
2744  populate_array_report_expected_array(ctx, ndim - 1);
2745 
2747 
2748  it = JsonbIteratorInit(jbc);
2749 
2750  tok = JsonbIteratorNext(&it, &val, true);
2751  Assert(tok == WJB_BEGIN_ARRAY);
2752 
2753  tok = JsonbIteratorNext(&it, &val, true);
2754 
2755  /*
2756  * If the number of dimensions is not yet known and we have found end of
2757  * the array, or the first child element is not an array, then assign the
2758  * number of dimensions now.
2759  */
2760  if (ctx->ndims <= 0 &&
2761  (tok == WJB_END_ARRAY ||
2762  (tok == WJB_ELEM &&
2763  (val.type != jbvBinary ||
2764  !JsonContainerIsArray(val.val.binary.data)))))
2765  populate_array_assign_ndims(ctx, ndim);
2766 
2767  jsv.is_json = false;
2768  jsv.val.jsonb = &val;
2769 
2770  /* process all the array elements */
2771  while (tok == WJB_ELEM)
2772  {
2773  /*
2774  * Recurse only if the dimensions of dimensions is still unknown or if
2775  * it is not the innermost dimension.
2776  */
2777  if (ctx->ndims > 0 && ndim >= ctx->ndims)
2778  populate_array_element(ctx, ndim, &jsv);
2779  else
2780  {
2781  /* populate child sub-array */
2782  populate_array_dim_jsonb(ctx, &val, ndim + 1);
2783 
2784  /* number of dimensions should be already known */
2785  Assert