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

Macro Definition Documentation

◆ JB_PATH_CONSISTENT_POSITION

#define JB_PATH_CONSISTENT_POSITION   0x0040

Definition at line 50 of file jsonfuncs.c.

◆ JB_PATH_CREATE

#define JB_PATH_CREATE   0x0001

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

◆ JB_PATH_DELETE

#define JB_PATH_DELETE   0x0002

Definition at line 43 of file jsonfuncs.c.

◆ JB_PATH_FILL_GAPS

#define JB_PATH_FILL_GAPS   0x0020

Definition at line 49 of file jsonfuncs.c.

◆ JB_PATH_INSERT_AFTER

#define JB_PATH_INSERT_AFTER   0x0010

Definition at line 46 of file jsonfuncs.c.

◆ JB_PATH_INSERT_BEFORE

#define JB_PATH_INSERT_BEFORE   0x0008

Definition at line 45 of file jsonfuncs.c.

◆ JB_PATH_REPLACE

#define JB_PATH_REPLACE   0x0004

Definition at line 44 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 331 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 325 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 316 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 321 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 197 of file jsonfuncs.c.

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

Function Documentation

◆ alen_array_element_start()

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

Definition at line 1918 of file jsonfuncs.c.

1919 {
1920  AlenState *_state = (AlenState *) state;
1921 
1922  /* just count up all the level 1 elements */
1923  if (_state->lex->lex_level == 1)
1924  _state->count++;
1925 
1926  return JSON_SUCCESS;
1927 }
@ JSON_SUCCESS
Definition: jsonapi.h:38
int count
Definition: jsonfuncs.c:103
JsonLexContext * lex
Definition: jsonfuncs.c:102
int lex_level
Definition: jsonapi.h:83
Definition: regguts.h:318

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

1891 {
1892  AlenState *_state = (AlenState *) state;
1893 
1894  /* json structure check */
1895  if (_state->lex->lex_level == 0)
1896  ereport(ERROR,
1897  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1898  errmsg("cannot get array length of a non-array")));
1899 
1900  return JSON_SUCCESS;
1901 }
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 1904 of file jsonfuncs.c.

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

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

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

2159 {
2160  EachState *_state = (EachState *) state;
2161 
2162  /* json structure check */
2163  if (_state->lex->lex_level == 0)
2164  ereport(ERROR,
2165  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2166  errmsg("cannot deconstruct an array as an object")));
2167 
2168  return JSON_SUCCESS;
2169 }
JsonLexContext * lex
Definition: jsonfuncs.c:109

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

2111 {
2112  EachState *_state = (EachState *) state;
2113  MemoryContext old_cxt;
2114  int len;
2115  text *val;
2116  HeapTuple tuple;
2117  Datum values[2];
2118  bool nulls[2] = {false, false};
2119 
2120  /* skip over nested objects */
2121  if (_state->lex->lex_level != 1)
2122  return JSON_SUCCESS;
2123 
2124  /* use the tmp context so we can clean up after each tuple is done */
2125  old_cxt = MemoryContextSwitchTo(_state->tmp_cxt);
2126 
2127  values[0] = CStringGetTextDatum(fname);
2128 
2129  if (isnull && _state->normalize_results)
2130  {
2131  nulls[1] = true;
2132  values[1] = (Datum) 0;
2133  }
2134  else if (_state->next_scalar)
2135  {
2137  _state->next_scalar = false;
2138  }
2139  else
2140  {
2141  len = _state->lex->prev_token_terminator - _state->result_start;
2143  values[1] = PointerGetDatum(val);
2144  }
2145 
2146  tuple = heap_form_tuple(_state->ret_tdesc, values, nulls);
2147 
2148  tuplestore_puttuple(_state->tuple_store, tuple);
2149 
2150  /* clean up and switch back */
2151  MemoryContextSwitchTo(old_cxt);
2152  MemoryContextReset(_state->tmp_cxt);
2153 
2154  return JSON_SUCCESS;
2155 }
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:1020
void MemoryContextReset(MemoryContext context)
Definition: mcxt.c:314
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:114
TupleDesc ret_tdesc
Definition: jsonfuncs.c:111
char * result_start
Definition: jsonfuncs.c:113
char * normalized_scalar
Definition: jsonfuncs.c:116
Tuplestorestate * tuple_store
Definition: jsonfuncs.c:110
MemoryContext tmp_cxt
Definition: jsonfuncs.c:112
bool next_scalar
Definition: jsonfuncs.c:115
char * prev_token_terminator
Definition: jsonapi.h:81
Definition: c.h:671
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 2088 of file jsonfuncs.c.

2089 {
2090  EachState *_state = (EachState *) state;
2091 
2092  /* save a pointer to where the value starts */
2093  if (_state->lex->lex_level == 1)
2094  {
2095  /*
2096  * next_scalar will be reset in the object_field_end handler, and
2097  * since we know the value is a scalar there is no danger of it being
2098  * on while recursing down the tree.
2099  */
2100  if (_state->normalize_results && _state->lex->token_type == JSON_TOKEN_STRING)
2101  _state->next_scalar = true;
2102  else
2103  _state->result_start = _state->lex->token_start;
2104  }
2105 
2106  return JSON_SUCCESS;
2107 }
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 2172 of file jsonfuncs.c.

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

2049 {
2050  text *json = PG_GETARG_TEXT_PP(0);
2051  JsonLexContext *lex;
2052  JsonSemAction *sem;
2053  ReturnSetInfo *rsi;
2054  EachState *state;
2055 
2056  lex = makeJsonLexContext(json, true);
2057  state = palloc0(sizeof(EachState));
2058  sem = palloc0(sizeof(JsonSemAction));
2059 
2060  rsi = (ReturnSetInfo *) fcinfo->resultinfo;
2061 
2063  state->tuple_store = rsi->setResult;
2064  state->ret_tdesc = rsi->setDesc;
2065 
2066  sem->semstate = (void *) state;
2068  sem->scalar = each_scalar;
2071 
2072  state->normalize_results = as_text;
2073  state->next_scalar = false;
2074  state->lex = lex;
2076  "json_each temporary cxt",
2078 
2079  pg_parse_json_or_ereport(lex, sem);
2080 
2081  MemoryContextDelete(state->tmp_cxt);
2082 
2083  PG_RETURN_NULL();
2084 }
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:309
#define PG_RETURN_NULL()
Definition: fmgr.h:345
void InitMaterializedSRF(FunctionCallInfo fcinfo, bits32 flags)
Definition: funcapi.c:76
#define MAT_SRF_BLESS
Definition: funcapi.h:296
static JsonParseErrorType each_object_field_end(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:2110
JsonLexContext * makeJsonLexContext(text *json, bool need_escapes)
Definition: jsonfuncs.c:528
static JsonParseErrorType each_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:2172
static JsonParseErrorType each_object_field_start(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:2088
static JsonParseErrorType each_array_start(void *state)
Definition: jsonfuncs.c:2158
#define pg_parse_json_or_ereport(lex, sem)
Definition: jsonfuncs.h:46
void * palloc0(Size size)
Definition: mcxt.c:1241
MemoryContext CurrentMemoryContext
Definition: mcxt.c:135
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:387
#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 1964 of file jsonfuncs.c.

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

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

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

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

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

2407 {
2408  ElementsState *_state = (ElementsState *) state;
2409 
2410  /* json structure check */
2411  if (_state->lex->lex_level == 0)
2412  ereport(ERROR,
2413  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2414  errmsg("cannot call %s on a non-array",
2415  _state->function_name)));
2416 
2417  return JSON_SUCCESS;
2418 }
const char * function_name
Definition: jsonfuncs.c:123

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

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

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

2299 {
2300  text *json = PG_GETARG_TEXT_PP(0);
2301 
2302  /* elements only needs escaped strings when as_text */
2303  JsonLexContext *lex = makeJsonLexContext(json, as_text);
2304  JsonSemAction *sem;
2305  ReturnSetInfo *rsi;
2307 
2308  state = palloc0(sizeof(ElementsState));
2309  sem = palloc0(sizeof(JsonSemAction));
2310 
2312  rsi = (ReturnSetInfo *) fcinfo->resultinfo;
2313  state->tuple_store = rsi->setResult;
2314  state->ret_tdesc = rsi->setDesc;
2315 
2316  sem->semstate = (void *) state;
2318  sem->scalar = elements_scalar;
2321 
2322  state->function_name = funcname;
2323  state->normalize_results = as_text;
2324  state->next_scalar = false;
2325  state->lex = lex;
2327  "json_array_elements temporary cxt",
2329 
2330  pg_parse_json_or_ereport(lex, sem);
2331 
2332  MemoryContextDelete(state->tmp_cxt);
2333 
2334  PG_RETURN_NULL();
2335 }
#define MAT_SRF_USE_EXPECTED_DESC
Definition: funcapi.h:295
static JsonParseErrorType elements_object_start(void *state)
Definition: jsonfuncs.c:2406
static JsonParseErrorType elements_array_element_end(void *state, bool isnull)
Definition: jsonfuncs.c:2360
static JsonParseErrorType elements_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:2421
static JsonParseErrorType elements_array_element_start(void *state, bool isnull)
Definition: jsonfuncs.c:2338
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 2210 of file jsonfuncs.c.

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

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

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

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

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

1324 {
1325  GetState *_state = (GetState *) state;
1326  int lex_level = _state->lex->lex_level;
1327 
1328  if (lex_level == 0 && _state->npath == 0)
1329  {
1330  /* Special case: return the entire array */
1331  char *start = _state->result_start;
1332  int len = _state->lex->prev_token_terminator - start;
1333 
1334  _state->tresult = cstring_to_text_with_len(start, len);
1335  }
1336 
1337  return JSON_SUCCESS;
1338 }
int npath
Definition: jsonfuncs.c:91

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

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

3545 {
3546  HASHCTL ctl;
3547  HTAB *tab;
3548  JHashState *state;
3550  JsonSemAction *sem;
3551 
3552  ctl.keysize = NAMEDATALEN;
3553  ctl.entrysize = sizeof(JsonHashEntry);
3554  ctl.hcxt = CurrentMemoryContext;
3555  tab = hash_create("json object hashtable",
3556  100,
3557  &ctl,
3559 
3560  state = palloc0(sizeof(JHashState));
3561  sem = palloc0(sizeof(JsonSemAction));
3562 
3563  state->function_name = funcname;
3564  state->hash = tab;
3565  state->lex = lex;
3566 
3567  sem->semstate = (void *) state;
3569  sem->scalar = hash_scalar;
3572 
3573  pg_parse_json_or_ereport(lex, sem);
3574 
3575  return tab;
3576 }
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:3656
static JsonParseErrorType hash_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:3669
struct JsonHashEntry JsonHashEntry
static JsonParseErrorType hash_object_field_end(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:3605
static JsonParseErrorType hash_object_field_start(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:3579
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 1488 of file jsonfuncs.c.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

1097 {
1098  JsonLexContext *lex = makeJsonLexContext(json, true);
1099  JsonSemAction *sem = palloc0(sizeof(JsonSemAction));
1100  GetState *state = palloc0(sizeof(GetState));
1101 
1102  Assert(npath >= 0);
1103 
1104  state->lex = lex;
1105  /* is it "_as_text" variant? */
1106  state->normalize_results = normalize_results;
1107  state->npath = npath;
1108  state->path_names = tpath;
1109  state->path_indexes = ipath;
1110  state->pathok = palloc0(sizeof(bool) * npath);
1111  state->array_cur_index = palloc(sizeof(int) * npath);
1112 
1113  if (npath > 0)
1114  state->pathok[0] = true;
1115 
1116  sem->semstate = (void *) state;
1117 
1118  /*
1119  * Not all variants need all the semantic routines. Only set the ones that
1120  * are actually needed for maximum efficiency.
1121  */
1122  sem->scalar = get_scalar;
1123  if (npath == 0)
1124  {
1126  sem->object_end = get_object_end;
1128  sem->array_end = get_array_end;
1129  }
1130  if (tpath != NULL)
1131  {
1134  }
1135  if (ipath != NULL)
1136  {
1140  }
1141 
1142  pg_parse_json_or_ereport(lex, sem);
1143 
1144  return state->tresult;
1145 }
static JsonParseErrorType get_array_element_end(void *state, bool isnull)
Definition: jsonfuncs.c:1389
static JsonParseErrorType get_object_field_start(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:1185
static JsonParseErrorType get_object_start(void *state)
Definition: jsonfuncs.c:1148
static JsonParseErrorType get_array_start(void *state)
Definition: jsonfuncs.c:1283
static JsonParseErrorType get_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:1433
static JsonParseErrorType get_object_end(void *state)
Definition: jsonfuncs.c:1167
static JsonParseErrorType get_object_field_end(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:1232
static JsonParseErrorType get_array_end(void *state)
Definition: jsonfuncs.c:1323
static JsonParseErrorType get_array_element_start(void *state, bool isnull)
Definition: jsonfuncs.c:1341
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 3656 of file jsonfuncs.c.

3657 {
3658  JHashState *_state = (JHashState *) state;
3659 
3660  if (_state->lex->lex_level == 0)
3661  ereport(ERROR,
3662  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3663  errmsg("cannot call %s on an array", _state->function_name)));
3664 
3665  return JSON_SUCCESS;
3666 }
const char * function_name
Definition: jsonfuncs.c:137
JsonLexContext * lex
Definition: jsonfuncs.c:136

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

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

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

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

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

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

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

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

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

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

Referenced by jsonb_to_tsvector_worker().

◆ iterate_values_object_field_start()

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

Definition at line 5484 of file jsonfuncs.c.

5485 {
5487 
5488  if (_state->flags & jtiKey)
5489  {
5490  char *val = pstrdup(fname);
5491 
5492  _state->action(_state->action_state, val, strlen(val));
5493  }
5494 
5495  return JSON_SUCCESS;
5496 }
char * pstrdup(const char *in)
Definition: mcxt.c:1624
JsonIterateStringValuesAction action
Definition: jsonfuncs.c:66

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

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

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

3236 {
3237  jsv->is_json = obj->is_json;
3238 
3239  if (jsv->is_json)
3240  {
3241  JsonHashEntry *hashentry = hash_search(obj->val.json_hash, field,
3242  HASH_FIND, NULL);
3243 
3244  jsv->val.json.type = hashentry ? hashentry->type : JSON_TOKEN_NULL;
3245  jsv->val.json.str = jsv->val.json.type == JSON_TOKEN_NULL ? NULL :
3246  hashentry->val;
3247  jsv->val.json.len = jsv->val.json.str ? -1 : 0; /* null-terminated */
3248 
3249  return hashentry != NULL;
3250  }
3251  else
3252  {
3253  jsv->val.jsonb = !obj->val.jsonb_cont ? NULL :
3254  getKeyJsonValueFromContainer(obj->val.jsonb_cont, field, strlen(field),
3255  NULL);
3256 
3257  return jsv->val.jsonb != NULL;
3258  }
3259 }
@ 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:307
JsonbContainer * jsonb_cont
Definition: jsonfuncs.c:311
HTAB * json_hash
Definition: jsonfuncs.c:310
union JsObject::@25 val
JsonbValue * jsonb
Definition: jsonfuncs.c:301
bool is_json
Definition: jsonfuncs.c:291
struct JsValue::@23::@24 json
union JsValue::@23 val

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

Referenced by populate_record().

◆ json_array_element()

Datum json_array_element ( PG_FUNCTION_ARGS  )

Definition at line 911 of file jsonfuncs.c.

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

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

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

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

References elements_worker().

◆ json_array_elements_text()

Datum json_array_elements_text ( PG_FUNCTION_ARGS  )

Definition at line 2292 of file jsonfuncs.c.

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

References elements_worker().

◆ json_array_length()

Datum json_array_length ( PG_FUNCTION_ARGS  )

Definition at line 1840 of file jsonfuncs.c.

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

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

◆ json_each()

Datum json_each ( PG_FUNCTION_ARGS  )

Definition at line 1940 of file jsonfuncs.c.

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

References each_worker().

◆ json_each_text()

Datum json_each_text ( PG_FUNCTION_ARGS  )

Definition at line 1952 of file jsonfuncs.c.

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

References each_worker().

◆ json_errsave_error()

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

Definition at line 628 of file jsonfuncs.c.

630 {
634  errsave(escontext,
635  (errcode(ERRCODE_UNTRANSLATABLE_CHARACTER),
636  errmsg("unsupported Unicode escape sequence"),
638  report_json_context(lex)));
639  else if (error == JSON_SEM_ACTION_FAILED)
640  {
641  /* semantic action function had better have reported something */
642  if (!SOFT_ERROR_OCCURRED(escontext))
643  elog(ERROR, "JSON semantic action function did not provide error information");
644  }
645  else
646  errsave(escontext,
647  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
648  errmsg("invalid input syntax for type %s", "json"),
650  report_json_context(lex)));
651 }
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:664
#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_typeof(), and pg_parse_json_or_errsave().

◆ json_extract_path()

Datum json_extract_path ( PG_FUNCTION_ARGS  )

Definition at line 998 of file jsonfuncs.c.

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

References get_path_all().

◆ json_extract_path_text()

Datum json_extract_path_text ( PG_FUNCTION_ARGS  )

Definition at line 1004 of file jsonfuncs.c.

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

References get_path_all().

◆ json_object_field()

Datum json_object_field ( PG_FUNCTION_ARGS  )

Definition at line 835 of file jsonfuncs.c.

836 {
837  text *json = PG_GETARG_TEXT_PP(0);
838  text *fname = PG_GETARG_TEXT_PP(1);
839  char *fnamestr = text_to_cstring(fname);
840  text *result;
841 
842  result = get_worker(json, &fnamestr, NULL, 1, false);
843 
844  if (result != NULL)
845  PG_RETURN_TEXT_P(result);
846  else
847  PG_RETURN_NULL();
848 }
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 873 of file jsonfuncs.c.

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

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

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

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

References populate_record_worker().

◆ json_populate_recordset()

Datum json_populate_recordset ( PG_FUNCTION_ARGS  )

Definition at line 3714 of file jsonfuncs.c.

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

References populate_recordset_worker().

◆ json_strip_nulls()

Datum json_strip_nulls ( PG_FUNCTION_ARGS  )

Definition at line 4215 of file jsonfuncs.c.

4216 {
4217  text *json = PG_GETARG_TEXT_PP(0);
4219  JsonLexContext *lex;
4220  JsonSemAction *sem;
4221 
4222  lex = makeJsonLexContext(json, true);
4223  state = palloc0(sizeof(StripnullState));
4224  sem = palloc0(sizeof(JsonSemAction));
4225 
4226  state->strval = makeStringInfo();
4227  state->skip_next_null = false;
4228  state->lex = lex;
4229 
4230  sem->semstate = (void *) state;
4232  sem->object_end = sn_object_end;
4233  sem->array_start = sn_array_start;
4234  sem->array_end = sn_array_end;
4235  sem->scalar = sn_scalar;
4238 
4239  pg_parse_json_or_ereport(lex, sem);
4240 
4242  state->strval->len));
4243 }
static JsonParseErrorType sn_object_end(void *state)
Definition: jsonfuncs.c:4121
static JsonParseErrorType sn_array_element_start(void *state, bool isnull)
Definition: jsonfuncs.c:4181
static JsonParseErrorType sn_object_start(void *state)
Definition: jsonfuncs.c:4111
static JsonParseErrorType sn_array_start(void *state)
Definition: jsonfuncs.c:4131
static JsonParseErrorType sn_array_end(void *state)
Definition: jsonfuncs.c:4141
static JsonParseErrorType sn_object_field_start(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:4151
static JsonParseErrorType sn_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:4192
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 2473 of file jsonfuncs.c.

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

References populate_record_worker().

◆ json_to_recordset()

Datum json_to_recordset ( PG_FUNCTION_ARGS  )

Definition at line 3721 of file jsonfuncs.c.

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

References populate_recordset_worker().

◆ jsonb_array_element()

Datum jsonb_array_element ( PG_FUNCTION_ARGS  )

Definition at line 926 of file jsonfuncs.c.

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

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

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

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

References elements_worker_jsonb().

◆ jsonb_array_elements_text()

Datum jsonb_array_elements_text ( PG_FUNCTION_ARGS  )

Definition at line 2204 of file jsonfuncs.c.

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

References elements_worker_jsonb().

◆ jsonb_array_length()

Datum jsonb_array_length ( PG_FUNCTION_ARGS  )

Definition at line 1868 of file jsonfuncs.c.

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

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

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

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

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

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

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

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

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

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

References each_worker_jsonb().

◆ jsonb_each_text()

Datum jsonb_each_text ( PG_FUNCTION_ARGS  )

Definition at line 1958 of file jsonfuncs.c.

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

References each_worker_jsonb().

◆ jsonb_extract_path()

Datum jsonb_extract_path ( PG_FUNCTION_ARGS  )

Definition at line 1476 of file jsonfuncs.c.

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

References get_jsonb_path_all().

◆ jsonb_extract_path_text()

Datum jsonb_extract_path_text ( PG_FUNCTION_ARGS  )

Definition at line 1482 of file jsonfuncs.c.

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

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

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

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

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

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

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

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

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

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

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

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

References populate_record_worker().

◆ jsonb_populate_recordset()

Datum jsonb_populate_recordset ( PG_FUNCTION_ARGS  )

Definition at line 3700 of file jsonfuncs.c.

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

References populate_recordset_worker().

◆ jsonb_pretty()

Datum jsonb_pretty ( PG_FUNCTION_ARGS  )

Definition at line 4307 of file jsonfuncs.c.

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

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

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

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

1669 {
1670  JsonbValue *res;
1671  JsonbParseState *state = NULL;
1672  JsonbIterator *it;
1673  bool *path_nulls = palloc0(path_len * sizeof(bool));
1674 
1675  if (newval->type == jbvArray && newval->val.array.rawScalar)
1676  *newval = newval->val.array.elems[0];
1677 
1678  it = JsonbIteratorInit(&jb->root);
1679 
1680  res = setPath(&it, path, path_nulls, path_len, &state, 0, newval,
1683 
1684  pfree(path_nulls);
1685 
1687 }
@ jbvArray
Definition: jsonb.h:233
#define JB_PATH_CONSISTENT_POSITION
Definition: jsonfuncs.c:50
#define JB_PATH_FILL_GAPS
Definition: jsonfuncs.c:49

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

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

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

References Assert(), JB_ROOT_IS_SCALAR, jbvNull, JsonbIteratorInit(), JsonbIteratorNext(), JsonbValueToJsonb(), PG_GETARG_JSONB_P, PG_RETURN_POINTER, pushJsonbValue(), res, Jsonb::root, generate_unaccent_rules::type, JsonbValue::type, WJB_DONE, WJB_ELEM, WJB_KEY, and WJB_VALUE.

◆ jsonb_to_record()

Datum jsonb_to_record ( PG_FUNCTION_ARGS  )

Definition at line 2459 of file jsonfuncs.c.

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

References populate_record_worker().

◆ jsonb_to_recordset()

Datum jsonb_to_recordset ( PG_FUNCTION_ARGS  )

Definition at line 3707 of file jsonfuncs.c.

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

References populate_recordset_worker().

◆ JsonbValueAsText()

static text * JsonbValueAsText ( JsonbValue v)
static

Definition at line 1793 of file jsonfuncs.c.

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

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

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

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

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

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

◆ okeys_array_start()

static JsonParseErrorType okeys_array_start ( void *  state)
static

Definition at line 798 of file jsonfuncs.c.

799 {
800  OkeysState *_state = (OkeysState *) state;
801 
802  /* top level must be a json object */
803  if (_state->lex->lex_level == 0)
804  ereport(ERROR,
805  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
806  errmsg("cannot call %s on an array",
807  "json_object_keys")));
808 
809  return JSON_SUCCESS;
810 }
JsonLexContext * lex
Definition: jsonfuncs.c:55

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

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

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

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

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

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

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

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

◆ pg_parse_json_or_errsave()

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

Definition at line 507 of file jsonfuncs.c.

509 {
510  JsonParseErrorType result;
511 
512  result = pg_parse_json(lex, sem);
513  if (result != JSON_SUCCESS)
514  {
515  json_errsave_error(result, lex, escontext);
516  return false;
517  }
518  return true;
519 }
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 2801 of file jsonfuncs.c.

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

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

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

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

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

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

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

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

2733 {
2734  JsonbContainer *jbc = jbv->val.binary.data;
2735  JsonbIterator *it;
2736  JsonbIteratorToken tok;
2737  JsonbValue val;
2738  JsValue jsv;
2739 
2741 
2742  if (jbv->type != jbvBinary || !JsonContainerIsArray(jbc))
2743  populate_array_report_expected_array(ctx, ndim - 1);
2744 
2746 
2747  it = JsonbIteratorInit(jbc);
2748 
2749  tok = JsonbIteratorNext(&it, &val, true);
2750  Assert(tok == WJB_BEGIN_ARRAY);
2751 
2752  tok = JsonbIteratorNext(&it, &val, true);
2753 
2754  /*
2755  * If the number of dimensions is not yet known and we have found end of
2756  * the array, or the first child element is not an array, then assign the
2757  * number of dimensions now.
2758  */
2759  if (ctx->ndims <= 0 &&
2760  (tok == WJB_END_ARRAY ||
2761  (tok == WJB_ELEM &&
2762  (val.type != jbvBinary ||
2763  !JsonContainerIsArray(val.val.binary.data)))))
2764  populate_array_assign_ndims(ctx, ndim);
2765 
2766  jsv.is_json = false;
2767  jsv.val.jsonb = &val;
2768 
2769  /* process all the array elements */
2770  while (tok == WJB_ELEM)
2771  {
2772  /*
2773  * Recurse only if the dimensions of dimensions is still unknown or if
2774  * it is not the innermost dimension.
2775  */
2776  if (ctx->ndims > 0 && ndim >= ctx->ndims)
2777  populate_array_element(ctx, ndim, &jsv);
2778  else
2779  {
2780  /* populate child sub-array */
2781  populate_array_dim_jsonb(ctx, &val, ndim + 1);
2782 
2783  /* number of dimensions should be already known */
2784  Assert(ctx->ndims > 0 && ctx->dims);
2785 
2786  populate_array_check_dimension(ctx, ndim);
2787  }
2788 
2789  tok = JsonbIteratorNext(&it, &val, true);
2790  }
2791 
2792  Assert(tok == WJB_END_ARRAY);
2793 
2794  /* free iterator, iterating until WJB_DONE */
2795  tok = JsonbIteratorNext(&it, &val, true);
2796  Assert(tok == WJB_DONE && !it);
2797 }
static void populate_array_element(PopulateArrayContext *ctx, int ndim, JsValue *jsv)
Definition: jsonfuncs.c:2565
void check_stack_depth(void)
Definition: postgres.c:3461

References Assert(), check_stack_depth(), PopulateArrayContext::dims, JsValue::is_json, jbvBinary, JsValue::jsonb, JsonbIteratorInit(), JsonbIteratorNext(), JsonContainerIsArray, JsonContainerIsScalar, PopulateArrayContext::ndims, populate_array_assign_ndims(), populate_array_check_dimension(), populate_array_element(), populate_array_report_expected_array(), JsonbValue::type, JsValue::val, JsonbValue::val, val, WJB_BEGIN_ARRAY, WJB_DONE, WJB_ELEM, and WJB_END_ARRAY.

Referenced by populate_array().

◆ populate_array_element()

static void populate_array_element ( PopulateArrayContext ctx,
int  ndim,
JsValue jsv 
)
static

Definition at line 2565 of file jsonfuncs.c.

2566 {
2567  Datum element;
2568  bool element_isnull;
2569 
2570  /* populate the array element */
2572  ctx->aio->element_type,
2573  ctx->aio->element_typmod,
2574  NULL, ctx->mcxt, PointerGetDatum(NULL),
2575  jsv, &element_isnull);
2576 
2577  accumArrayResult(ctx->astate, element, element_isnull,
2578  ctx->aio->element_type, ctx->acxt);
2579 
2580  Assert(ndim > 0);
2581  ctx->sizes[ndim - 1]++; /* increment current dimension counter */
2582 }
ArrayBuildState * accumArrayResult(ArrayBuildState *astate, Datum dvalue, bool disnull, Oid element_type, MemoryContext rcontext)
Definition: arrayfuncs.c:5319
static Datum populate_record_field(ColumnIOData *col, Oid typid, int32 typmod, const char *colname, MemoryContext mcxt, Datum defaultval, JsValue *jsv, bool *isnull)
Definition: jsonfuncs.c:3154
int32 element_typmod
Definition: jsonfuncs.c:168
ColumnIOData * element_info
Definition: jsonfuncs.c:166

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

Referenced by populate_array_dim_jsonb(), and populate_array_element_end().

◆ populate_array_element_end()

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

Definition at line 2636 of file jsonfuncs.c.

2637 {
2639  PopulateArrayContext *ctx = state->ctx;
2640  int ndim = state->lex->lex_level;
2641 
2642  Assert(ctx->ndims > 0);
2643 
2644  if (ndim == ctx->ndims)
2645  {
2646  JsValue jsv;
2647 
2648  jsv.is_json = true;
2649  jsv.val.json.type = state->element_type;
2650 
2651  if (isnull)
2652  {
2653  Assert(jsv.val.json.type == JSON_TOKEN_NULL);
2654  jsv.val.json.str = NULL;
2655  jsv.val.json.len = 0;
2656  }
2657  else if (state->element_scalar)
2658  {
2659  jsv.val.json.str = state->element_scalar;
2660  jsv.val.json.len = -1; /* null-terminated */
2661  }
2662  else
2663  {
2664  jsv.val.json.str = state->element_start;
2665  jsv.val.json.len = (state->lex->prev_token_terminator -
2666  state->element_start) * sizeof(char);
2667  }
2668 
2669  populate_array_element(ctx, ndim, &jsv);
2670  }
2671 
2672  return JSON_SUCCESS;
2673 }

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

Referenced by populate_array_json().

◆ populate_array_element_start()

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

Definition at line 2618 of file jsonfuncs.c.

2619 {
2621  int ndim = state->lex->lex_level;
2622 
2623  if (state->ctx->ndims <= 0 || ndim == state->ctx->ndims)
2624  {
2625  /* remember current array element start */
2626  state->element_start = state->lex->token_start;
2627  state->element_type = state->lex->token_type;
2628  state->element_scalar = NULL;
2629  }
2630 
2631  return JSON_SUCCESS;
2632 }

References JSON_SUCCESS.

Referenced by populate_array_json().

◆ populate_array_json()

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

Definition at line 2701 of file jsonfuncs.c.

2702 {
2704  JsonSemAction sem;
2705 
2707  state.ctx = ctx;
2708 
2709  memset(&sem, 0, sizeof(sem));
2710  sem.semstate = (void *) &state;
2716 
2717  pg_parse_json_or_ereport(state.lex, &sem);
2718 
2719  /* number of dimensions should be already known */
2720  Assert(ctx->ndims > 0 && ctx->dims);
2721 
2722  pfree(state.lex);
2723 }
static JsonParseErrorType populate_array_scalar(void *_state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:2677
static JsonParseErrorType populate_array_object_start(void *_state)
Definition: jsonfuncs.c:2586
static JsonParseErrorType populate_array_element_end(void *_state, bool isnull)
Definition: jsonfuncs.c:2636
static JsonParseErrorType populate_array_element_start(void *_state, bool isnull)
Definition: jsonfuncs.c:2618
static JsonParseErrorType populate_array_array_end(void *_state)
Definition: jsonfuncs.c:2601

References JsonSemAction::array_element_end, JsonSemAction::