PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
jsonfuncs.c File Reference
#include "postgres.h"
#include <limits.h>
#include "access/htup_details.h"
#include "catalog/pg_type.h"
#include "fmgr.h"
#include "funcapi.h"
#include "lib/stringinfo.h"
#include "mb/pg_wchar.h"
#include "miscadmin.h"
#include "utils/array.h"
#include "utils/builtins.h"
#include "utils/hsearch.h"
#include "utils/json.h"
#include "utils/jsonapi.h"
#include "utils/jsonb.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  PopulateRecordsetState
 
struct  PopulateRecordCache
 
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 JsValueIsNull(jsv)
 
#define JsValueIsString(jsv)
 
#define JsObjectSize(jso)
 
#define JsObjectIsEmpty(jso)   (JsObjectSize(jso) == 0)
 
#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
PopulateRecordsetState 
PopulateRecordsetState
 
typedef struct PopulateRecordCache PopulateRecordCache
 
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_DOMAIN = 'd' }
 

Functions

static void okeys_object_field_start (void *state, char *fname, bool isnull)
 
static void okeys_array_start (void *state)
 
static void okeys_scalar (void *state, char *token, JsonTokenType tokentype)
 
static void get_object_start (void *state)
 
static void get_object_end (void *state)
 
static void get_object_field_start (void *state, char *fname, bool isnull)
 
static void get_object_field_end (void *state, char *fname, bool isnull)
 
static void get_array_start (void *state)
 
static void get_array_end (void *state)
 
static void get_array_element_start (void *state, bool isnull)
 
static void get_array_element_end (void *state, bool isnull)
 
static void 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 void alen_object_start (void *state)
 
static void alen_scalar (void *state, char *token, JsonTokenType tokentype)
 
static void 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 void each_object_field_start (void *state, char *fname, bool isnull)
 
static void each_object_field_end (void *state, char *fname, bool isnull)
 
static void each_array_start (void *state)
 
static void 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 void elements_object_start (void *state)
 
static void elements_array_element_start (void *state, bool isnull)
 
static void elements_array_element_end (void *state, bool isnull)
 
static void elements_scalar (void *state, char *token, JsonTokenType tokentype)
 
static HTABget_json_object_as_hash (char *json, int len, const char *funcname)
 
static void populate_array_object_start (void *_state)
 
static void populate_array_array_end (void *_state)
 
static void populate_array_element_start (void *_state, bool isnull)
 
static void populate_array_element_end (void *_state, bool isnull)
 
static void populate_array_scalar (void *_state, char *token, JsonTokenType tokentype)
 
static void hash_object_field_start (void *state, char *fname, bool isnull)
 
static void hash_object_field_end (void *state, char *fname, bool isnull)
 
static void hash_array_start (void *state)
 
static void hash_scalar (void *state, char *token, JsonTokenType tokentype)
 
static void populate_recordset_object_field_start (void *state, char *fname, bool isnull)
 
static void populate_recordset_object_field_end (void *state, char *fname, bool isnull)
 
static void populate_recordset_scalar (void *state, char *token, JsonTokenType tokentype)
 
static void populate_recordset_object_start (void *state)
 
static void populate_recordset_object_end (void *state)
 
static void populate_recordset_array_start (void *state)
 
static void populate_recordset_array_element_start (void *state, bool isnull)
 
static void sn_object_start (void *state)
 
static void sn_object_end (void *state)
 
static void sn_array_start (void *state)
 
static void sn_array_end (void *state)
 
static void sn_object_field_start (void *state, char *fname, bool isnull)
 
static void sn_array_element_start (void *state, bool isnull)
 
static void sn_scalar (void *state, char *token, JsonTokenType tokentype)
 
static Datum populate_recordset_worker (FunctionCallInfo fcinfo, const char *funcname, bool have_record_arg)
 
static Datum populate_record_worker (FunctionCallInfo fcinfo, const char *funcname, bool have_record_arg)
 
static HeapTupleHeader populate_record (TupleDesc tupdesc, RecordIOData **record_p, HeapTupleHeader defaultval, MemoryContext mcxt, JsObject *obj)
 
static Datum populate_record_field (ColumnIOData *col, Oid typid, int32 typmod, const char *colname, MemoryContext mcxt, Datum defaultval, JsValue *jsv, bool *isnull)
 
static void JsValueToJsObject (JsValue *jsv, JsObject *jso)
 
static Datum populate_composite (CompositeIOData *io, Oid typid, int32 typmod, const char *colname, MemoryContext mcxt, HeapTupleHeader defaultval, JsValue *jsv)
 
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 json)
 
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 JsonbValuefindJsonbValueFromContainerLen (JsonbContainer *container, uint32 flags, char *key, uint32 keylen)
 
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, Jsonb *newval, int op_type)
 
static void setPathObject (JsonbIterator **it, Datum *path_elems, bool *path_nulls, int path_len, JsonbParseState **st, int level, Jsonb *newval, uint32 npairs, int op_type)
 
static void setPathArray (JsonbIterator **it, Datum *path_elems, bool *path_nulls, int path_len, JsonbParseState **st, int level, Jsonb *newval, uint32 nelems, int op_type)
 
static void addJsonbToParseState (JsonbParseState **jbps, Jsonb *jb)
 
static void iterate_string_values_scalar (void *state, char *token, JsonTokenType tokentype)
 
static void transform_string_values_object_start (void *state)
 
static void transform_string_values_object_end (void *state)
 
static void transform_string_values_array_start (void *state)
 
static void transform_string_values_array_end (void *state)
 
static void transform_string_values_object_field_start (void *state, char *fname, bool isnull)
 
static void transform_string_values_array_element_start (void *state, bool isnull)
 
static void transform_string_values_scalar (void *state, char *token, JsonTokenType tokentype)
 
Datum jsonb_object_keys (PG_FUNCTION_ARGS)
 
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 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)
 
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_delete_path (PG_FUNCTION_ARGS)
 
Datum jsonb_insert (PG_FUNCTION_ARGS)
 
void iterate_jsonb_string_values (Jsonb *jb, void *state, JsonIterateStringValuesAction action)
 
void iterate_json_string_values (text *json, 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

#define JB_PATH_CREATE   0x0001

Definition at line 38 of file jsonfuncs.c.

Referenced by jsonb_set(), and setPathArray().

#define JB_PATH_CREATE_OR_INSERT   (JB_PATH_INSERT_BEFORE | JB_PATH_INSERT_AFTER | JB_PATH_CREATE)

Definition at line 43 of file jsonfuncs.c.

Referenced by setPathArray(), and setPathObject().

#define JB_PATH_DELETE   0x0002

Definition at line 39 of file jsonfuncs.c.

Referenced by jsonb_delete_path(), and setPathObject().

#define JB_PATH_INSERT_AFTER   0x0010

Definition at line 42 of file jsonfuncs.c.

Referenced by jsonb_insert(), setPathArray(), and setPathObject().

#define JB_PATH_INSERT_BEFORE   0x0008

Definition at line 41 of file jsonfuncs.c.

Referenced by jsonb_insert(), setPathArray(), and setPathObject().

#define JB_PATH_REPLACE   0x0004

Definition at line 40 of file jsonfuncs.c.

Referenced by jsonb_set(), and setPathArray().

#define JsObjectFree (   jso)
Value:
do { \
if ((jso)->is_json) \
hash_destroy((jso)->val.json_hash); \
} while (0)
void hash_destroy(HTAB *hashp)
Definition: dynahash.c:793
long val
Definition: informix.c:689

Definition at line 318 of file jsonfuncs.c.

Referenced by populate_composite().

#define JsObjectIsEmpty (   jso)    (JsObjectSize(jso) == 0)

Definition at line 316 of file jsonfuncs.c.

Referenced by populate_record().

#define JsObjectSize (   jso)
Value:
((jso)->is_json \
? hash_get_num_entries((jso)->val.json_hash) \
: !(jso)->val.jsonb_cont || JsonContainerSize((jso)->val.jsonb_cont))
long hash_get_num_entries(HTAB *hashp)
Definition: dynahash.c:1297
#define JsonContainerSize(jc)
Definition: jsonb.h:209
long val
Definition: informix.c:689

Definition at line 311 of file jsonfuncs.c.

#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))
Definition: jsonb.h:231
long val
Definition: informix.c:689

Definition at line 302 of file jsonfuncs.c.

Referenced by populate_record_field().

#define JsValueIsString (   jsv)
Value:
((jsv)->is_json ? (jsv)->val.json.type == JSON_TOKEN_STRING \
: ((jsv)->val.jsonb && (jsv)->val.jsonb->type == jbvString))
long val
Definition: informix.c:689

Definition at line 307 of file jsonfuncs.c.

Referenced by populate_record_field().

Typedef Documentation

Definition at line 151 of file jsonfuncs.c.

Definition at line 152 of file jsonfuncs.c.

Enumeration Type Documentation

enum TypeCat
Enumerator
TYPECAT_SCALAR 
TYPECAT_ARRAY 
TYPECAT_COMPOSITE 
TYPECAT_DOMAIN 

Definition at line 183 of file jsonfuncs.c.

184 {
185  TYPECAT_SCALAR = 's',
186  TYPECAT_ARRAY = 'a',
187  TYPECAT_COMPOSITE = 'c',
188  TYPECAT_DOMAIN = 'd'
189 } TypeCat;
TypeCat
Definition: jsonfuncs.c:183

Function Documentation

static void addJsonbToParseState ( JsonbParseState **  jbps,
Jsonb jb 
)
static

Definition at line 3951 of file jsonfuncs.c.

References Assert, elog, ERROR, JB_ROOT_IS_SCALAR, jbvArray, jbvObject, JsonbIteratorInit(), JsonbIteratorNext(), NULL, pushJsonbValue(), Jsonb::root, JsonbValue::type, WJB_DONE, WJB_ELEM, WJB_KEY, and WJB_VALUE.

Referenced by setPathArray(), and setPathObject().

3952 {
3953  JsonbIterator *it;
3954  JsonbValue *o = &(*jbps)->contVal;
3955  JsonbValue v;
3956  JsonbIteratorToken type;
3957 
3958  it = JsonbIteratorInit(&jb->root);
3959 
3960  Assert(o->type == jbvArray || o->type == jbvObject);
3961 
3962  if (JB_ROOT_IS_SCALAR(jb))
3963  {
3964  (void) JsonbIteratorNext(&it, &v, false); /* skip array header */
3965  (void) JsonbIteratorNext(&it, &v, false); /* fetch scalar value */
3966 
3967  switch (o->type)
3968  {
3969  case jbvArray:
3970  (void) pushJsonbValue(jbps, WJB_ELEM, &v);
3971  break;
3972  case jbvObject:
3973  (void) pushJsonbValue(jbps, WJB_VALUE, &v);
3974  break;
3975  default:
3976  elog(ERROR, "unexpected parent of nested structure");
3977  }
3978  }
3979  else
3980  {
3981  while ((type = JsonbIteratorNext(&it, &v, false)) != WJB_DONE)
3982  {
3983  if (type == WJB_KEY || type == WJB_VALUE || type == WJB_ELEM)
3984  (void) pushJsonbValue(jbps, type, &v);
3985  else
3986  (void) pushJsonbValue(jbps, type, NULL);
3987  }
3988  }
3989 
3990 }
Definition: jsonb.h:22
#define JB_ROOT_IS_SCALAR(jbp_)
Definition: jsonb.h:223
JsonbValue * pushJsonbValue(JsonbParseState **pstate, JsonbIteratorToken seq, JsonbValue *jbval)
Definition: jsonb_util.c:517
#define ERROR
Definition: elog.h:43
Definition: jsonb.h:23
JsonbIteratorToken
Definition: jsonb.h:20
JsonbContainer root
Definition: jsonb.h:218
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
JsonbIterator * JsonbIteratorInit(JsonbContainer *container)
Definition: jsonb_util.c:718
enum jbvType type
Definition: jsonb.h:250
#define elog
Definition: elog.h:219
JsonbIteratorToken JsonbIteratorNext(JsonbIterator **it, JsonbValue *val, bool skipNested)
Definition: jsonb_util.c:754
Definition: jsonb.h:25
static void alen_array_element_start ( void *  state,
bool  isnull 
)
static

Definition at line 1617 of file jsonfuncs.c.

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

Referenced by json_array_length().

1618 {
1619  AlenState *_state = (AlenState *) state;
1620 
1621  /* just count up all the level 1 elements */
1622  if (_state->lex->lex_level == 1)
1623  _state->count++;
1624 }
int count
Definition: jsonfuncs.c:94
int lex_level
Definition: jsonapi.h:59
JsonLexContext * lex
Definition: jsonfuncs.c:93
Definition: regguts.h:298
static void alen_object_start ( void *  state)
static

Definition at line 1593 of file jsonfuncs.c.

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

Referenced by json_array_length().

1594 {
1595  AlenState *_state = (AlenState *) state;
1596 
1597  /* json structure check */
1598  if (_state->lex->lex_level == 0)
1599  ereport(ERROR,
1600  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1601  errmsg("cannot get array length of a non-array")));
1602 }
int errcode(int sqlerrcode)
Definition: elog.c:575
int lex_level
Definition: jsonapi.h:59
#define ERROR
Definition: elog.h:43
JsonLexContext * lex
Definition: jsonfuncs.c:93
#define ereport(elevel, rest)
Definition: elog.h:122
Definition: regguts.h:298
int errmsg(const char *fmt,...)
Definition: elog.c:797
static void alen_scalar ( void *  state,
char *  token,
JsonTokenType  tokentype 
)
static

Definition at line 1605 of file jsonfuncs.c.

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

Referenced by json_array_length().

1606 {
1607  AlenState *_state = (AlenState *) state;
1608 
1609  /* json structure check */
1610  if (_state->lex->lex_level == 0)
1611  ereport(ERROR,
1612  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1613  errmsg("cannot get array length of a scalar")));
1614 }
int errcode(int sqlerrcode)
Definition: elog.c:575
int lex_level
Definition: jsonapi.h:59
#define ERROR
Definition: elog.h:43
JsonLexContext * lex
Definition: jsonfuncs.c:93
#define ereport(elevel, rest)
Definition: elog.h:122
Definition: regguts.h:298
int errmsg(const char *fmt,...)
Definition: elog.c:797
static RecordIOData * allocate_record_info ( MemoryContext  mcxt,
int  ncolumns 
)
static

Definition at line 2966 of file jsonfuncs.c.

References RecordIOData::columns, InvalidOid, MemoryContextAlloc(), MemSet, RecordIOData::ncolumns, offsetof, RecordIOData::record_type, and RecordIOData::record_typmod.

Referenced by populate_record().

2967 {
2968  RecordIOData *data = (RecordIOData *)
2969  MemoryContextAlloc(mcxt,
2970  offsetof(RecordIOData, columns) +
2971  ncolumns * sizeof(ColumnIOData));
2972 
2973  data->record_type = InvalidOid;
2974  data->record_typmod = 0;
2975  data->ncolumns = ncolumns;
2976  MemSet(data->columns, 0, sizeof(ColumnIOData) * ncolumns);
2977 
2978  return data;
2979 }
Oid record_type
Definition: hstore_io.c:753
struct ColumnIOData ColumnIOData
Definition: jsonfuncs.c:151
#define MemSet(start, val, len)
Definition: c.h:857
int32 record_typmod
Definition: hstore_io.c:754
ColumnIOData columns[FLEXIBLE_ARRAY_MEMBER]
Definition: hstore_io.c:756
#define InvalidOid
Definition: postgres_ext.h:36
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:707
#define offsetof(type, field)
Definition: c.h:555
static void each_array_start ( void *  state)
static

Definition at line 1927 of file jsonfuncs.c.

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

Referenced by each_worker().

1928 {
1929  EachState *_state = (EachState *) state;
1930 
1931  /* json structure check */
1932  if (_state->lex->lex_level == 0)
1933  ereport(ERROR,
1934  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1935  errmsg("cannot deconstruct an array as an object")));
1936 }
int errcode(int sqlerrcode)
Definition: elog.c:575
int lex_level
Definition: jsonapi.h:59
#define ERROR
Definition: elog.h:43
JsonLexContext * lex
Definition: jsonfuncs.c:100
#define ereport(elevel, rest)
Definition: elog.h:122
Definition: regguts.h:298
int errmsg(const char *fmt,...)
Definition: elog.c:797
static void each_object_field_end ( void *  state,
char *  fname,
bool  isnull 
)
static

Definition at line 1881 of file jsonfuncs.c.

References cstring_to_text_with_len(), CStringGetTextDatum, heap_form_tuple(), 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().

1882 {
1883  EachState *_state = (EachState *) state;
1884  MemoryContext old_cxt;
1885  int len;
1886  text *val;
1887  HeapTuple tuple;
1888  Datum values[2];
1889  bool nulls[2] = {false, false};
1890 
1891  /* skip over nested objects */
1892  if (_state->lex->lex_level != 1)
1893  return;
1894 
1895  /* use the tmp context so we can clean up after each tuple is done */
1896  old_cxt = MemoryContextSwitchTo(_state->tmp_cxt);
1897 
1898  values[0] = CStringGetTextDatum(fname);
1899 
1900  if (isnull && _state->normalize_results)
1901  {
1902  nulls[1] = true;
1903  values[1] = (Datum) 0;
1904  }
1905  else if (_state->next_scalar)
1906  {
1907  values[1] = CStringGetTextDatum(_state->normalized_scalar);
1908  _state->next_scalar = false;
1909  }
1910  else
1911  {
1912  len = _state->lex->prev_token_terminator - _state->result_start;
1913  val = cstring_to_text_with_len(_state->result_start, len);
1914  values[1] = PointerGetDatum(val);
1915  }
1916 
1917  tuple = heap_form_tuple(_state->ret_tdesc, values, nulls);
1918 
1919  tuplestore_puttuple(_state->tuple_store, tuple);
1920 
1921  /* clean up and switch back */
1922  MemoryContextSwitchTo(old_cxt);
1923  MemoryContextReset(_state->tmp_cxt);
1924 }
Tuplestorestate * tuple_store
Definition: jsonfuncs.c:101
#define PointerGetDatum(X)
Definition: postgres.h:562
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
char * prev_token_terminator
Definition: jsonapi.h:57
void MemoryContextReset(MemoryContext context)
Definition: mcxt.c:135
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:692
TupleDesc ret_tdesc
Definition: jsonfuncs.c:102
int lex_level
Definition: jsonapi.h:59
MemoryContext tmp_cxt
Definition: jsonfuncs.c:103
char * result_start
Definition: jsonfuncs.c:104
JsonLexContext * lex
Definition: jsonfuncs.c:100
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:161
uintptr_t Datum
Definition: postgres.h:372
bool normalize_results
Definition: jsonfuncs.c:105
char * normalized_scalar
Definition: jsonfuncs.c:107
Definition: regguts.h:298
static Datum values[MAXATTR]
Definition: bootstrap.c:163
#define CStringGetTextDatum(s)
Definition: builtins.h:91
Definition: c.h:439
long val
Definition: informix.c:689
bool next_scalar
Definition: jsonfuncs.c:106
static void each_object_field_start ( void *  state,
char *  fname,
bool  isnull 
)
static

Definition at line 1861 of file jsonfuncs.c.

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

1862 {
1863  EachState *_state = (EachState *) state;
1864 
1865  /* save a pointer to where the value starts */
1866  if (_state->lex->lex_level == 1)
1867  {
1868  /*
1869  * next_scalar will be reset in the object_field_end handler, and
1870  * since we know the value is a scalar there is no danger of it being
1871  * on while recursing down the tree.
1872  */
1873  if (_state->normalize_results && _state->lex->token_type == JSON_TOKEN_STRING)
1874  _state->next_scalar = true;
1875  else
1876  _state->result_start = _state->lex->token_start;
1877  }
1878 }
JsonTokenType token_type
Definition: jsonapi.h:58
int lex_level
Definition: jsonapi.h:59
char * result_start
Definition: jsonfuncs.c:104
JsonLexContext * lex
Definition: jsonfuncs.c:100
char * token_start
Definition: jsonapi.h:55
bool normalize_results
Definition: jsonfuncs.c:105
Definition: regguts.h:298
bool next_scalar
Definition: jsonfuncs.c:106
static void each_scalar ( void *  state,
char *  token,
JsonTokenType  tokentype 
)
static

Definition at line 1939 of file jsonfuncs.c.

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

Referenced by each_worker().

1940 {
1941  EachState *_state = (EachState *) state;
1942 
1943  /* json structure check */
1944  if (_state->lex->lex_level == 0)
1945  ereport(ERROR,
1946  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1947  errmsg("cannot deconstruct a scalar")));
1948 
1949  /* supply de-escaped value if required */
1950  if (_state->next_scalar)
1951  _state->normalized_scalar = token;
1952 }
int errcode(int sqlerrcode)
Definition: elog.c:575
int lex_level
Definition: jsonapi.h:59
#define ERROR
Definition: elog.h:43
JsonLexContext * lex
Definition: jsonfuncs.c:100
#define ereport(elevel, rest)
Definition: elog.h:122
char * normalized_scalar
Definition: jsonfuncs.c:107
Definition: regguts.h:298
int errmsg(const char *fmt,...)
Definition: elog.c:797
bool next_scalar
Definition: jsonfuncs.c:106
static Datum each_worker ( FunctionCallInfo  fcinfo,
bool  as_text 
)
static

Definition at line 1797 of file jsonfuncs.c.

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate(), ReturnSetInfo::allowedModes, JsonSemAction::array_start, BlessTupleDesc(), CreateTupleDescCopy(), CurrentMemoryContext, each_array_start(), each_object_field_end(), each_object_field_start(), each_scalar(), ReturnSetInfo::econtext, ExprContext::ecxt_per_query_memory, ereport, errcode(), errmsg(), ERROR, ReturnSetInfo::expectedDesc, get_call_result_type(), IsA, EachState::lex, makeJsonLexContext(), MemoryContextDelete(), MemoryContextSwitchTo(), EachState::next_scalar, EachState::normalize_results, NULL, JsonSemAction::object_field_end, JsonSemAction::object_field_start, palloc0(), PG_GETARG_TEXT_PP, pg_parse_json(), PG_RETURN_NULL, FunctionCallInfoData::resultinfo, EachState::ret_tdesc, ReturnSetInfo::returnMode, JsonSemAction::scalar, JsonSemAction::semstate, ReturnSetInfo::setDesc, ReturnSetInfo::setResult, SFRM_Materialize, SFRM_Materialize_Random, EachState::tmp_cxt, EachState::tuple_store, tuplestore_begin_heap(), and work_mem.

Referenced by json_each(), and json_each_text().

1798 {
1799  text *json = PG_GETARG_TEXT_PP(0);
1800  JsonLexContext *lex;
1801  JsonSemAction *sem;
1802  ReturnSetInfo *rsi;
1803  MemoryContext old_cxt;
1804  TupleDesc tupdesc;
1805  EachState *state;
1806 
1807  lex = makeJsonLexContext(json, true);
1808  state = palloc0(sizeof(EachState));
1809  sem = palloc0(sizeof(JsonSemAction));
1810 
1811  rsi = (ReturnSetInfo *) fcinfo->resultinfo;
1812 
1813  if (!rsi || !IsA(rsi, ReturnSetInfo) ||
1814  (rsi->allowedModes & SFRM_Materialize) == 0 ||
1815  rsi->expectedDesc == NULL)
1816  ereport(ERROR,
1817  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1818  errmsg("set-valued function called in context that "
1819  "cannot accept a set")));
1820 
1822 
1823  (void) get_call_result_type(fcinfo, NULL, &tupdesc);
1824 
1825  /* make these in a sufficiently long-lived memory context */
1827 
1828  state->ret_tdesc = CreateTupleDescCopy(tupdesc);
1829  BlessTupleDesc(state->ret_tdesc);
1830  state->tuple_store =
1832  false, work_mem);
1833 
1834  MemoryContextSwitchTo(old_cxt);
1835 
1836  sem->semstate = (void *) state;
1838  sem->scalar = each_scalar;
1841 
1842  state->normalize_results = as_text;
1843  state->next_scalar = false;
1844  state->lex = lex;
1846  "json_each temporary cxt",
1848 
1849  pg_parse_json(lex, sem);
1850 
1851  MemoryContextDelete(state->tmp_cxt);
1852 
1853  rsi->setResult = state->tuple_store;
1854  rsi->setDesc = state->ret_tdesc;
1855 
1856  PG_RETURN_NULL();
1857 }
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
Definition: tupdesc.c:141
#define IsA(nodeptr, _type_)
Definition: nodes.h:560
Tuplestorestate * tuple_store
Definition: jsonfuncs.c:101
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:200
static void each_object_field_start(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:1861
TypeFuncClass get_call_result_type(FunctionCallInfo fcinfo, Oid *resultTypeId, TupleDesc *resultTupleDesc)
Definition: funcapi.c:211
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
int errcode(int sqlerrcode)
Definition: elog.c:575
json_scalar_action scalar
Definition: jsonapi.h:93
static void each_array_start(void *state)
Definition: jsonfuncs.c:1927
TupleDesc ret_tdesc
Definition: jsonfuncs.c:102
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:273
MemoryContext tmp_cxt
Definition: jsonfuncs.c:103
static void each_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:1939
TupleDesc expectedDesc
Definition: execnodes.h:267
JsonLexContext * makeJsonLexContext(text *json, bool need_escapes)
Definition: json.c:300
#define ERROR
Definition: elog.h:43
void pg_parse_json(JsonLexContext *lex, JsonSemAction *sem)
Definition: json.c:331
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:165
JsonLexContext * lex
Definition: jsonfuncs.c:100
TupleDesc BlessTupleDesc(TupleDesc tupdesc)
Definition: execTuples.c:1031
fmNodePtr resultinfo
Definition: fmgr.h:81
MemoryContext CurrentMemoryContext
Definition: mcxt.c:37
#define ereport(elevel, rest)
Definition: elog.h:122
json_ofield_action object_field_end
Definition: jsonapi.h:90
Tuplestorestate * tuplestore_begin_heap(bool randomAccess, bool interXact, int maxKBytes)
Definition: tuplestore.c:318
MemoryContext AllocSetContextCreate(MemoryContext parent, const char *name, Size minContextSize, Size initBlockSize, Size maxBlockSize)
Definition: aset.c:322
void * palloc0(Size size)
Definition: mcxt.c:878
bool normalize_results
Definition: jsonfuncs.c:105
int work_mem
Definition: globals.c:112
int allowedModes
Definition: execnodes.h:268
SetFunctionReturnMode returnMode
Definition: execnodes.h:270
#define NULL
Definition: c.h:229
json_struct_action array_start
Definition: jsonapi.h:87
Definition: regguts.h:298
MemoryContext ecxt_per_query_memory
Definition: execnodes.h:202
Tuplestorestate * setResult
Definition: execnodes.h:273
ExprContext * econtext
Definition: execnodes.h:266
TupleDesc setDesc
Definition: execnodes.h:274
int errmsg(const char *fmt,...)
Definition: elog.c:797
Definition: c.h:439
json_ofield_action object_field_start
Definition: jsonapi.h:89
void * semstate
Definition: jsonapi.h:84
static void each_object_field_end(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:1881
#define PG_RETURN_NULL()
Definition: fmgr.h:305
bool next_scalar
Definition: jsonfuncs.c:106
static Datum each_worker_jsonb ( FunctionCallInfo  fcinfo,
const char *  funcname,
bool  as_text 
)
static

Definition at line 1661 of file jsonfuncs.c.

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate(), ReturnSetInfo::allowedModes, BlessTupleDesc(), CreateTupleDescCopy(), cstring_to_text_with_len(), CurrentMemoryContext, StringInfoData::data, ReturnSetInfo::econtext, ExprContext::ecxt_per_query_memory, ereport, errcode(), errmsg(), ERROR, ReturnSetInfo::expectedDesc, get_call_result_type(), heap_form_tuple(), IsA, JB_ROOT_IS_OBJECT, jbvNull, jbvString, JsonbIteratorInit(), JsonbIteratorNext(), JsonbToCString(), JsonbValueToJsonb(), StringInfoData::len, makeStringInfo(), MemoryContextDelete(), MemoryContextReset(), MemoryContextSwitchTo(), NULL, PG_GETARG_JSONB, PG_RETURN_NULL, PointerGetDatum, FunctionCallInfoData::resultinfo, ReturnSetInfo::returnMode, Jsonb::root, ReturnSetInfo::setDesc, ReturnSetInfo::setResult, SFRM_Materialize, SFRM_Materialize_Random, tuplestore_begin_heap(), tuplestore_puttuple(), JsonbValue::type, TYPEFUNC_COMPOSITE, JsonbValue::val, val, values, WJB_DONE, WJB_KEY, and work_mem.

Referenced by jsonb_each(), and jsonb_each_text().

1662 {
1663  Jsonb *jb = PG_GETARG_JSONB(0);
1664  ReturnSetInfo *rsi;
1665  Tuplestorestate *tuple_store;
1666  TupleDesc tupdesc;
1667  TupleDesc ret_tdesc;
1668  MemoryContext old_cxt,
1669  tmp_cxt;
1670  bool skipNested = false;
1671  JsonbIterator *it;
1672  JsonbValue v;
1674 
1675  if (!JB_ROOT_IS_OBJECT(jb))
1676  ereport(ERROR,
1677  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1678  errmsg("cannot call %s on a non-object",
1679  funcname)));
1680 
1681  rsi = (ReturnSetInfo *) fcinfo->resultinfo;
1682 
1683  if (!rsi || !IsA(rsi, ReturnSetInfo) ||
1684  (rsi->allowedModes & SFRM_Materialize) == 0 ||
1685  rsi->expectedDesc == NULL)
1686  ereport(ERROR,
1687  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1688  errmsg("set-valued function called in context that "
1689  "cannot accept a set")));
1690 
1692 
1693  if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
1694  ereport(ERROR,
1695  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1696  errmsg("function returning record called in context "
1697  "that cannot accept type record")));
1698 
1700 
1701  ret_tdesc = CreateTupleDescCopy(tupdesc);
1702  BlessTupleDesc(ret_tdesc);
1703  tuple_store =
1705  false, work_mem);
1706 
1707  MemoryContextSwitchTo(old_cxt);
1708 
1710  "jsonb_each temporary cxt",
1712 
1713  it = JsonbIteratorInit(&jb->root);
1714 
1715  while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE)
1716  {
1717  skipNested = true;
1718 
1719  if (r == WJB_KEY)
1720  {
1721  text *key;
1722  HeapTuple tuple;
1723  Datum values[2];
1724  bool nulls[2] = {false, false};
1725 
1726  /* Use the tmp context so we can clean up after each tuple is done */
1727  old_cxt = MemoryContextSwitchTo(tmp_cxt);
1728 
1729  key = cstring_to_text_with_len(v.val.string.val, v.val.string.len);
1730 
1731  /*
1732  * The next thing the iterator fetches should be the value, no
1733  * matter what shape it is.
1734  */
1735  r = JsonbIteratorNext(&it, &v, skipNested);
1736 
1737  values[0] = PointerGetDatum(key);
1738 
1739  if (as_text)
1740  {
1741  if (v.type == jbvNull)
1742  {
1743  /* a json null is an sql null in text mode */
1744  nulls[1] = true;
1745  values[1] = (Datum) NULL;
1746  }
1747  else
1748  {
1749  text *sv;
1750 
1751  if (v.type == jbvString)
1752  {
1753  /* In text mode, scalar strings should be dequoted */
1754  sv = cstring_to_text_with_len(v.val.string.val, v.val.string.len);
1755  }
1756  else
1757  {
1758  /* Turn anything else into a json string */
1759  StringInfo jtext = makeStringInfo();
1760  Jsonb *jb = JsonbValueToJsonb(&v);
1761 
1762  (void) JsonbToCString(jtext, &jb->root, 0);
1763  sv = cstring_to_text_with_len(jtext->data, jtext->len);
1764  }
1765 
1766  values[1] = PointerGetDatum(sv);
1767  }
1768  }
1769  else
1770  {
1771  /* Not in text mode, just return the Jsonb */
1772  Jsonb *val = JsonbValueToJsonb(&v);
1773 
1774  values[1] = PointerGetDatum(val);
1775  }
1776 
1777  tuple = heap_form_tuple(ret_tdesc, values, nulls);
1778 
1779  tuplestore_puttuple(tuple_store, tuple);
1780 
1781  /* clean up and switch back */
1782  MemoryContextSwitchTo(old_cxt);
1783  MemoryContextReset(tmp_cxt);
1784  }
1785  }
1786 
1787  MemoryContextDelete(tmp_cxt);
1788 
1789  rsi->setResult = tuple_store;
1790  rsi->setDesc = ret_tdesc;
1791 
1792  PG_RETURN_NULL();
1793 }
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
Definition: tupdesc.c:141
#define IsA(nodeptr, _type_)
Definition: nodes.h:560
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:200
#define JB_ROOT_IS_OBJECT(jbp_)
Definition: jsonb.h:224
TypeFuncClass get_call_result_type(FunctionCallInfo fcinfo, Oid *resultTypeId, TupleDesc *resultTupleDesc)
Definition: funcapi.c:211
Jsonb * JsonbValueToJsonb(JsonbValue *val)
Definition: jsonb_util.c:79
Definition: jsonb.h:215
#define PointerGetDatum(X)
Definition: postgres.h:562
char * val
Definition: jsonb.h:259
StringInfo makeStringInfo(void)
Definition: stringinfo.c:28
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
Definition: jsonb.h:22
int errcode(int sqlerrcode)
Definition: elog.c:575
void MemoryContextReset(MemoryContext context)
Definition: mcxt.c:135
Definition: jsonb.h:231
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:692
TupleDesc expectedDesc
Definition: execnodes.h:267
#define ERROR
Definition: elog.h:43
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:165
void tuplestore_puttuple(Tuplestorestate *state, HeapTuple tuple)
Definition: tuplestore.c:730
TupleDesc BlessTupleDesc(TupleDesc tupdesc)
Definition: execTuples.c:1031
text * cstring_to_text_with_len(const char *s, int len)
Definition: varlena.c:161
fmNodePtr resultinfo
Definition: fmgr.h:81
Definition: jsonb.h:23
MemoryContext CurrentMemoryContext
Definition: mcxt.c:37
#define ereport(elevel, rest)
Definition: elog.h:122
JsonbIteratorToken
Definition: jsonb.h:20
JsonbContainer root
Definition: jsonb.h:218
Tuplestorestate * tuplestore_begin_heap(bool randomAccess, bool interXact, int maxKBytes)
Definition: tuplestore.c:318
MemoryContext AllocSetContextCreate(MemoryContext parent, const char *name, Size minContextSize, Size initBlockSize, Size maxBlockSize)
Definition: aset.c:322
uintptr_t Datum
Definition: postgres.h:372
int work_mem
Definition: globals.c:112
int allowedModes
Definition: execnodes.h:268
SetFunctionReturnMode returnMode
Definition: execnodes.h:270
#define NULL
Definition: c.h:229
JsonbIterator * JsonbIteratorInit(JsonbContainer *container)
Definition: jsonb_util.c:718
char * JsonbToCString(StringInfo out, JsonbContainer *in, int estimated_len)
Definition: jsonb.c:428
MemoryContext ecxt_per_query_memory
Definition: execnodes.h:202
enum jbvType type
Definition: jsonb.h:250
Tuplestorestate * setResult
Definition: execnodes.h:273
static Datum values[MAXATTR]
Definition: bootstrap.c:163
ExprContext * econtext
Definition: execnodes.h:266
#define PG_GETARG_JSONB(x)
Definition: jsonb.h:70
TupleDesc setDesc
Definition: execnodes.h:274
int errmsg(const char *fmt,...)
Definition: elog.c:797
Definition: c.h:439
long val
Definition: informix.c:689
#define PG_RETURN_NULL()
Definition: fmgr.h:305
JsonbIteratorToken JsonbIteratorNext(JsonbIterator **it, JsonbValue *val, bool skipNested)
Definition: jsonb_util.c:754
static void elements_array_element_end ( void *  state,
bool  isnull 
)
static

Definition at line 2197 of file jsonfuncs.c.

References cstring_to_text_with_len(), CStringGetTextDatum, heap_form_tuple(), ElementsState::lex, JsonLexContext::lex_level, MemoryContextReset(), MemoryContextSwitchTo(), ElementsState::next_scalar, ElementsState::normalize_results, ElementsState::normalized_scalar, NULL, 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().

2198 {
2199  ElementsState *_state = (ElementsState *) state;
2200  MemoryContext old_cxt;
2201  int len;
2202  text *val;
2203  HeapTuple tuple;
2204  Datum values[1];
2205  bool nulls[1] = {false};
2206 
2207  /* skip over nested objects */
2208  if (_state->lex->lex_level != 1)
2209  return;
2210 
2211  /* use the tmp context so we can clean up after each tuple is done */
2212  old_cxt = MemoryContextSwitchTo(_state->tmp_cxt);
2213 
2214  if (isnull && _state->normalize_results)
2215  {
2216  nulls[0] = true;
2217  values[0] = (Datum) NULL;
2218  }
2219  else if (_state->next_scalar)
2220  {
2221  values[0] = CStringGetTextDatum(_state->normalized_scalar);
2222  _state->next_scalar = false;
2223  }
2224  else
2225  {
2226  len = _state->lex->prev_token_terminator - _state->result_start;
2227  val = cstring_to_text_with_len(_state->result_start, len);
2228  values[0] = PointerGetDatum(val);
2229  }
2230 
2231  tuple = heap_form_tuple(_state->ret_tdesc, values, nulls);
2232 
2233  tuplestore_puttuple(_state->tuple_store, tuple);
2234 
2235  /* clean up and switch back */
2236  MemoryContextSwitchTo(old_cxt);
2237  MemoryContextReset(_state->tmp_cxt);
2238 }
bool normalize_results
Definition: jsonfuncs.c:119
JsonLexContext * lex
Definition: jsonfuncs.c:113
bool next_scalar
Definition: jsonfuncs.c:120
#define PointerGetDatum(X)
Definition: postgres.h:562
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
char * prev_token_terminator
Definition: jsonapi.h:57
void MemoryContextReset(MemoryContext context)
Definition: mcxt.c:135
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:692
int lex_level
Definition: jsonapi.h:59
TupleDesc ret_tdesc
Definition: jsonfuncs.c:116
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:161
uintptr_t Datum
Definition: postgres.h:372
Tuplestorestate * tuple_store
Definition: jsonfuncs.c:115
#define NULL
Definition: c.h:229
char * result_start
Definition: jsonfuncs.c:118
Definition: regguts.h:298
static Datum values[MAXATTR]
Definition: bootstrap.c:163
char * normalized_scalar
Definition: jsonfuncs.c:121
#define CStringGetTextDatum(s)
Definition: builtins.h:91
MemoryContext tmp_cxt
Definition: jsonfuncs.c:117
Definition: c.h:439
long val
Definition: informix.c:689
static void elements_array_element_start ( void *  state,
bool  isnull 
)
static

Definition at line 2177 of file jsonfuncs.c.

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

2178 {
2179  ElementsState *_state = (ElementsState *) state;
2180 
2181  /* save a pointer to where the value starts */
2182  if (_state->lex->lex_level == 1)
2183  {
2184  /*
2185  * next_scalar will be reset in the array_element_end handler, and
2186  * since we know the value is a scalar there is no danger of it being
2187  * on while recursing down the tree.
2188  */
2189  if (_state->normalize_results && _state->lex->token_type == JSON_TOKEN_STRING)
2190  _state->next_scalar = true;
2191  else
2192  _state->result_start = _state->lex->token_start;
2193  }
2194 }
bool normalize_results
Definition: jsonfuncs.c:119
JsonLexContext * lex
Definition: jsonfuncs.c:113
bool next_scalar
Definition: jsonfuncs.c:120
JsonTokenType token_type
Definition: jsonapi.h:58
int lex_level
Definition: jsonapi.h:59
char * token_start
Definition: jsonapi.h:55
char * result_start
Definition: jsonfuncs.c:118
Definition: regguts.h:298
static void elements_object_start ( void *  state)
static

Definition at line 2241 of file jsonfuncs.c.

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

Referenced by elements_worker().

2242 {
2243  ElementsState *_state = (ElementsState *) state;
2244 
2245  /* json structure check */
2246  if (_state->lex->lex_level == 0)
2247  ereport(ERROR,
2248  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2249  errmsg("cannot call %s on a non-array",
2250  _state->function_name)));
2251 }
const char * function_name
Definition: jsonfuncs.c:114
JsonLexContext * lex
Definition: jsonfuncs.c:113
int errcode(int sqlerrcode)
Definition: elog.c:575
int lex_level
Definition: jsonapi.h:59
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:122
Definition: regguts.h:298
int errmsg(const char *fmt,...)
Definition: elog.c:797
static void elements_scalar ( void *  state,
char *  token,
JsonTokenType  tokentype 
)
static

Definition at line 2254 of file jsonfuncs.c.

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

Referenced by elements_worker().

2255 {
2256  ElementsState *_state = (ElementsState *) state;
2257 
2258  /* json structure check */
2259  if (_state->lex->lex_level == 0)
2260  ereport(ERROR,
2261  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2262  errmsg("cannot call %s on a scalar",
2263  _state->function_name)));
2264 
2265  /* supply de-escaped value if required */
2266  if (_state->next_scalar)
2267  _state->normalized_scalar = token;
2268 }
const char * function_name
Definition: jsonfuncs.c:114
JsonLexContext * lex
Definition: jsonfuncs.c:113
bool next_scalar
Definition: jsonfuncs.c:120
int errcode(int sqlerrcode)
Definition: elog.c:575
int lex_level
Definition: jsonapi.h:59
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:122
Definition: regguts.h:298
char * normalized_scalar
Definition: jsonfuncs.c:121
int errmsg(const char *fmt,...)
Definition: elog.c:797
static Datum elements_worker ( FunctionCallInfo  fcinfo,
const char *  funcname,
bool  as_text 
)
static

Definition at line 2111 of file jsonfuncs.c.

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate(), ReturnSetInfo::allowedModes, JsonSemAction::array_element_end, JsonSemAction::array_element_start, BlessTupleDesc(), CreateTupleDescCopy(), CurrentMemoryContext, ReturnSetInfo::econtext, ExprContext::ecxt_per_query_memory, elements_array_element_end(), elements_array_element_start(), elements_object_start(), elements_scalar(), ereport, errcode(), errmsg(), ERROR, ReturnSetInfo::expectedDesc, ElementsState::function_name, IsA, ElementsState::lex, makeJsonLexContext(), MemoryContextDelete(), MemoryContextSwitchTo(), ElementsState::next_scalar, ElementsState::normalize_results, NULL, JsonSemAction::object_start, palloc0(), PG_GETARG_TEXT_PP, pg_parse_json(), PG_RETURN_NULL, FunctionCallInfoData::resultinfo, ElementsState::ret_tdesc, ReturnSetInfo::returnMode, JsonSemAction::scalar, JsonSemAction::semstate, ReturnSetInfo::setDesc, ReturnSetInfo::setResult, SFRM_Materialize, SFRM_Materialize_Random, ElementsState::tmp_cxt, ElementsState::tuple_store, tuplestore_begin_heap(), and work_mem.

Referenced by json_array_elements(), and json_array_elements_text().

2112 {
2113  text *json = PG_GETARG_TEXT_PP(0);
2114 
2115  /* elements only needs escaped strings when as_text */
2116  JsonLexContext *lex = makeJsonLexContext(json, as_text);
2117  JsonSemAction *sem;
2118  ReturnSetInfo *rsi;
2119  MemoryContext old_cxt;
2120  TupleDesc tupdesc;
2122 
2123  state = palloc0(sizeof(ElementsState));
2124  sem = palloc0(sizeof(JsonSemAction));
2125 
2126  rsi = (ReturnSetInfo *) fcinfo->resultinfo;
2127 
2128  if (!rsi || !IsA(rsi, ReturnSetInfo) ||
2129  (rsi->allowedModes & SFRM_Materialize) == 0 ||
2130  rsi->expectedDesc == NULL)
2131  ereport(ERROR,
2132  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2133  errmsg("set-valued function called in context that "
2134  "cannot accept a set")));
2135 
2137 
2138  /* it's a simple type, so don't use get_call_result_type() */
2139  tupdesc = rsi->expectedDesc;
2140 
2141  /* make these in a sufficiently long-lived memory context */
2143 
2144  state->ret_tdesc = CreateTupleDescCopy(tupdesc);
2145  BlessTupleDesc(state->ret_tdesc);
2146  state->tuple_store =
2148  false, work_mem);
2149 
2150  MemoryContextSwitchTo(old_cxt);
2151 
2152  sem->semstate = (void *) state;
2154  sem->scalar = elements_scalar;
2157 
2158  state->function_name = funcname;
2159  state->normalize_results = as_text;
2160  state->next_scalar = false;
2161  state->lex = lex;
2163  "json_array_elements temporary cxt",
2165 
2166  pg_parse_json(lex, sem);
2167 
2168  MemoryContextDelete(state->tmp_cxt);
2169 
2170  rsi->setResult = state->tuple_store;
2171  rsi->setDesc = state->ret_tdesc;
2172 
2173  PG_RETURN_NULL();
2174 }
bool normalize_results
Definition: jsonfuncs.c:119
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
Definition: tupdesc.c:141
#define IsA(nodeptr, _type_)
Definition: nodes.h:560
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:200
const char * function_name
Definition: jsonfuncs.c:114
JsonLexContext * lex
Definition: jsonfuncs.c:113
static void elements_object_start(void *state)
Definition: jsonfuncs.c:2241
bool next_scalar
Definition: jsonfuncs.c:120
json_struct_action object_start
Definition: jsonapi.h:85
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
int errcode(int sqlerrcode)
Definition: elog.c:575
json_scalar_action scalar
Definition: jsonapi.h:93
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:273
TupleDesc expectedDesc
Definition: execnodes.h:267
TupleDesc ret_tdesc
Definition: jsonfuncs.c:116
JsonLexContext * makeJsonLexContext(text *json, bool need_escapes)
Definition: json.c:300
#define ERROR
Definition: elog.h:43
void pg_parse_json(JsonLexContext *lex, JsonSemAction *sem)
Definition: json.c:331
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:165
TupleDesc BlessTupleDesc(TupleDesc tupdesc)
Definition: execTuples.c:1031
fmNodePtr resultinfo
Definition: fmgr.h:81
MemoryContext CurrentMemoryContext
Definition: mcxt.c:37
#define ereport(elevel, rest)
Definition: elog.h:122
static void elements_array_element_start(void *state, bool isnull)
Definition: jsonfuncs.c:2177
Tuplestorestate * tuplestore_begin_heap(bool randomAccess, bool interXact, int maxKBytes)
Definition: tuplestore.c:318
MemoryContext AllocSetContextCreate(MemoryContext parent, const char *name, Size minContextSize, Size initBlockSize, Size maxBlockSize)
Definition: aset.c:322
static void elements_array_element_end(void *state, bool isnull)
Definition: jsonfuncs.c:2197
void * palloc0(Size size)
Definition: mcxt.c:878
static void elements_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:2254
json_aelem_action array_element_start
Definition: jsonapi.h:91
Tuplestorestate * tuple_store
Definition: jsonfuncs.c:115
int work_mem
Definition: globals.c:112
int allowedModes
Definition: execnodes.h:268
SetFunctionReturnMode returnMode
Definition: execnodes.h:270
#define NULL
Definition: c.h:229
Definition: regguts.h:298
MemoryContext ecxt_per_query_memory
Definition: execnodes.h:202
Tuplestorestate * setResult
Definition: execnodes.h:273
ExprContext * econtext
Definition: execnodes.h:266
TupleDesc setDesc
Definition: execnodes.h:274
int errmsg(const char *fmt,...)
Definition: elog.c:797
MemoryContext tmp_cxt
Definition: jsonfuncs.c:117
Definition: c.h:439
void * semstate
Definition: jsonapi.h:84
#define PG_RETURN_NULL()
Definition: fmgr.h:305
json_aelem_action array_element_end
Definition: jsonapi.h:92
static Datum elements_worker_jsonb ( FunctionCallInfo  fcinfo,
const char *  funcname,
bool  as_text 
)
static

Definition at line 1975 of file jsonfuncs.c.

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate(), ReturnSetInfo::allowedModes, BlessTupleDesc(), CreateTupleDescCopy(), cstring_to_text_with_len(), CurrentMemoryContext, StringInfoData::data, ReturnSetInfo::econtext, ExprContext::ecxt_per_query_memory, ereport, errcode(), errmsg(), ERROR, ReturnSetInfo::expectedDesc, heap_form_tuple(), IsA, JB_ROOT_IS_ARRAY, JB_ROOT_IS_SCALAR, jbvNull, jbvString, JsonbIteratorInit(), JsonbIteratorNext(), JsonbToCString(), JsonbValueToJsonb(), StringInfoData::len, makeStringInfo(), MemoryContextDelete(), MemoryContextReset(), MemoryContextSwitchTo(), NULL, PG_GETARG_JSONB, PG_RETURN_NULL, PointerGetDatum, FunctionCallInfoData::resultinfo, ReturnSetInfo::returnMode, Jsonb::root, ReturnSetInfo::setDesc, ReturnSetInfo::setResult, SFRM_Materialize, SFRM_Materialize_Random, tuplestore_begin_heap(), tuplestore_puttuple(), JsonbValue::type, JsonbValue::val, val, values, WJB_DONE, WJB_ELEM, and work_mem.

Referenced by jsonb_array_elements(), and jsonb_array_elements_text().

1977 {
1978  Jsonb *jb = PG_GETARG_JSONB(0);
1979  ReturnSetInfo *rsi;
1980  Tuplestorestate *tuple_store;
1981  TupleDesc tupdesc;
1982  TupleDesc ret_tdesc;
1983  MemoryContext old_cxt,
1984  tmp_cxt;
1985  bool skipNested = false;
1986  JsonbIterator *it;
1987  JsonbValue v;
1989 
1990  if (JB_ROOT_IS_SCALAR(jb))
1991  ereport(ERROR,
1992  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1993  errmsg("cannot extract elements from a scalar")));
1994  else if (!JB_ROOT_IS_ARRAY(jb))
1995  ereport(ERROR,
1996  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1997  errmsg("cannot extract elements from an object")));
1998 
1999  rsi = (ReturnSetInfo *) fcinfo->resultinfo;
2000 
2001  if (!rsi || !IsA(rsi, ReturnSetInfo) ||
2002  (rsi->allowedModes & SFRM_Materialize) == 0 ||
2003  rsi->expectedDesc == NULL)
2004  ereport(ERROR,
2005  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2006  errmsg("set-valued function called in context that "
2007  "cannot accept a set")));
2008 
2010 
2011  /* it's a simple type, so don't use get_call_result_type() */
2012  tupdesc = rsi->expectedDesc;
2013 
2015 
2016  ret_tdesc = CreateTupleDescCopy(tupdesc);
2017  BlessTupleDesc(ret_tdesc);
2018  tuple_store =
2020  false, work_mem);
2021 
2022  MemoryContextSwitchTo(old_cxt);
2023 
2025  "jsonb_array_elements temporary cxt",
2027 
2028  it = JsonbIteratorInit(&jb->root);
2029 
2030  while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE)
2031  {
2032  skipNested = true;
2033 
2034  if (r == WJB_ELEM)
2035  {
2036  HeapTuple tuple;
2037  Datum values[1];
2038  bool nulls[1] = {false};
2039 
2040  /* use the tmp context so we can clean up after each tuple is done */
2041  old_cxt = MemoryContextSwitchTo(tmp_cxt);
2042 
2043  if (!as_text)
2044  {
2045  Jsonb *val = JsonbValueToJsonb(&v);
2046 
2047  values[0] = PointerGetDatum(val);
2048  }
2049  else
2050  {
2051  if (v.type == jbvNull)
2052  {
2053  /* a json null is an sql null in text mode */
2054  nulls[0] = true;
2055  values[0] = (Datum) NULL;
2056  }
2057  else
2058  {
2059  text *sv;
2060 
2061  if (v.type == jbvString)
2062  {
2063  /* in text mode scalar strings should be dequoted */
2064  sv = cstring_to_text_with_len(v.val.string.val, v.val.string.len);
2065  }
2066  else
2067  {
2068  /* turn anything else into a json string */
2069  StringInfo jtext = makeStringInfo();
2070  Jsonb *jb = JsonbValueToJsonb(&v);
2071 
2072  (void) JsonbToCString(jtext, &jb->root, 0);
2073  sv = cstring_to_text_with_len(jtext->data, jtext->len);
2074  }
2075 
2076  values[0] = PointerGetDatum(sv);
2077  }
2078  }
2079 
2080  tuple = heap_form_tuple(ret_tdesc, values, nulls);
2081 
2082  tuplestore_puttuple(tuple_store, tuple);
2083 
2084  /* clean up and switch back */
2085  MemoryContextSwitchTo(old_cxt);
2086  MemoryContextReset(tmp_cxt);
2087  }
2088  }
2089 
2090  MemoryContextDelete(tmp_cxt);
2091 
2092  rsi->setResult = tuple_store;
2093  rsi->setDesc = ret_tdesc;
2094 
2095  PG_RETURN_NULL();
2096 }
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
Definition: tupdesc.c:141
#define IsA(nodeptr, _type_)
Definition: nodes.h:560
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:200
Jsonb * JsonbValueToJsonb(JsonbValue *val)
Definition: jsonb_util.c:79
Definition: jsonb.h:215
#define PointerGetDatum(X)
Definition: postgres.h:562
char * val
Definition: jsonb.h:259
StringInfo makeStringInfo(void)
Definition: stringinfo.c:28
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
Definition: jsonb.h:22
int errcode(int sqlerrcode)
Definition: elog.c:575
void MemoryContextReset(MemoryContext context)
Definition: mcxt.c:135
Definition: jsonb.h:231
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:692
#define JB_ROOT_IS_SCALAR(jbp_)
Definition: jsonb.h:223
TupleDesc expectedDesc
Definition: execnodes.h:267
#define ERROR
Definition: elog.h:43
#define JB_ROOT_IS_ARRAY(jbp_)
Definition: jsonb.h:225
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:165
void tuplestore_puttuple(Tuplestorestate *state, HeapTuple tuple)
Definition: tuplestore.c:730
TupleDesc BlessTupleDesc(TupleDesc tupdesc)
Definition: execTuples.c:1031
text * cstring_to_text_with_len(const char *s, int len)
Definition: varlena.c:161
fmNodePtr resultinfo
Definition: fmgr.h:81
MemoryContext CurrentMemoryContext
Definition: mcxt.c:37
#define ereport(elevel, rest)
Definition: elog.h:122
JsonbIteratorToken
Definition: jsonb.h:20
JsonbContainer root
Definition: jsonb.h:218
Tuplestorestate * tuplestore_begin_heap(bool randomAccess, bool interXact, int maxKBytes)
Definition: tuplestore.c:318
MemoryContext AllocSetContextCreate(MemoryContext parent, const char *name, Size minContextSize, Size initBlockSize, Size maxBlockSize)
Definition: aset.c:322
uintptr_t Datum
Definition: postgres.h:372
int work_mem
Definition: globals.c:112
int allowedModes
Definition: execnodes.h:268
SetFunctionReturnMode returnMode
Definition: execnodes.h:270
#define NULL
Definition: c.h:229
JsonbIterator * JsonbIteratorInit(JsonbContainer *container)
Definition: jsonb_util.c:718
char * JsonbToCString(StringInfo out, JsonbContainer *in, int estimated_len)
Definition: jsonb.c:428
MemoryContext ecxt_per_query_memory
Definition: execnodes.h:202
enum jbvType type
Definition: jsonb.h:250
Tuplestorestate * setResult
Definition: execnodes.h:273
static Datum values[MAXATTR]
Definition: bootstrap.c:163
ExprContext * econtext
Definition: execnodes.h:266
#define PG_GETARG_JSONB(x)
Definition: jsonb.h:70
TupleDesc setDesc
Definition: execnodes.h:274
int errmsg(const char *fmt,...)
Definition: elog.c:797
Definition: c.h:439
long val
Definition: informix.c:689
#define PG_RETURN_NULL()
Definition: fmgr.h:305
JsonbIteratorToken JsonbIteratorNext(JsonbIterator **it, JsonbValue *val, bool skipNested)
Definition: jsonb_util.c:754
Definition: jsonb.h:25
static JsonbValue * findJsonbValueFromContainerLen ( JsonbContainer container,
uint32  flags,
char *  key,
uint32  keylen 
)
static

Definition at line 3742 of file jsonfuncs.c.

References findJsonbValueFromContainer(), jbvString, JsonbValue::type, and JsonbValue::val.

Referenced by get_jsonb_path_all(), JsObjectGetField(), jsonb_object_field(), and jsonb_object_field_text().

3744 {
3745  JsonbValue k;
3746 
3747  k.type = jbvString;
3748  k.val.string.val = key;
3749  k.val.string.len = keylen;
3750 
3751  return findJsonbValueFromContainer(container, flags, &k);
3752 }
char * val
Definition: jsonb.h:259
enum jbvType type
Definition: jsonb.h:250
JsonbValue * findJsonbValueFromContainer(JsonbContainer *container, uint32 flags, JsonbValue *key)
Definition: jsonb_util.c:327
static void get_array_element_end ( void *  state,
bool  isnull 
)
static

Definition at line 1280 of file jsonfuncs.c.

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

Referenced by get_worker().

1281 {
1282  GetState *_state = (GetState *) state;
1283  bool get_last = false;
1284  int lex_level = _state->lex->lex_level;
1285 
1286  /* same tests as in get_array_element_start */
1287  if (lex_level <= _state->npath &&
1288  _state->pathok[lex_level - 1] &&
1289  _state->path_indexes != NULL &&
1290  _state->array_cur_index[lex_level - 1] == _state->path_indexes[lex_level - 1])
1291  {
1292  if (lex_level < _state->npath)
1293  {
1294  /* done with this element so reset pathok */
1295  _state->pathok[lex_level] = false;
1296  }
1297  else
1298  {
1299  /* end of path, so we want this value */
1300  get_last = true;
1301  }
1302  }
1303 
1304  /* same logic as for objects */
1305  if (get_last && _state->result_start != NULL)
1306  {
1307  if (isnull && _state->normalize_results)
1308  _state->tresult = (text *) NULL;
1309  else
1310  {
1311  char *start = _state->result_start;
1312  int len = _state->lex->prev_token_terminator - start;
1313 
1314  _state->tresult = cstring_to_text_with_len(start, len);
1315  }
1316 
1317  _state->result_start = NULL;
1318  }
1319 }
int * array_cur_index
Definition: jsonfuncs.c:87
char * prev_token_terminator
Definition: jsonapi.h:57
int lex_level
Definition: jsonapi.h:59
JsonLexContext * lex
Definition: jsonfuncs.c:78
char * result_start
Definition: jsonfuncs.c:80
text * tresult
Definition: jsonfuncs.c:79
text * cstring_to_text_with_len(const char *s, int len)
Definition: varlena.c:161
bool * pathok
Definition: jsonfuncs.c:86
bool normalize_results
Definition: jsonfuncs.c:81
#define NULL
Definition: c.h:229
Definition: regguts.h:298
int * path_indexes
Definition: jsonfuncs.c:85
Definition: c.h:439
static void get_array_element_start ( void *  state,
bool  isnull 
)
static

Definition at line 1234 of file jsonfuncs.c.

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

Referenced by get_worker().

1235 {
1236  GetState *_state = (GetState *) state;
1237  bool get_next = false;
1238  int lex_level = _state->lex->lex_level;
1239 
1240  /* Update array element counter */
1241  if (lex_level <= _state->npath)
1242  _state->array_cur_index[lex_level - 1]++;
1243 
1244  if (lex_level <= _state->npath &&
1245  _state->pathok[lex_level - 1] &&
1246  _state->path_indexes != NULL &&
1247  _state->array_cur_index[lex_level - 1] == _state->path_indexes[lex_level - 1])
1248  {
1249  if (lex_level < _state->npath)
1250  {
1251  /* if not at end of path just mark path ok */
1252  _state->pathok[lex_level] = true;
1253  }
1254  else
1255  {
1256  /* end of path, so we want this value */
1257  get_next = true;
1258  }
1259  }
1260 
1261  /* same logic as for objects */
1262  if (get_next)
1263  {
1264  _state->tresult = NULL;
1265  _state->result_start = NULL;
1266 
1267  if (_state->normalize_results &&
1268  _state->lex->token_type == JSON_TOKEN_STRING)
1269  {
1270  _state->next_scalar = true;
1271  }
1272  else
1273  {
1274  _state->result_start = _state->lex->token_start;
1275  }
1276  }
1277 }
int * array_cur_index
Definition: jsonfuncs.c:87
JsonTokenType token_type
Definition: jsonapi.h:58
int lex_level
Definition: jsonapi.h:59
JsonLexContext * lex
Definition: jsonfuncs.c:78
char * result_start
Definition: jsonfuncs.c:80
text * tresult
Definition: jsonfuncs.c:79
char * token_start
Definition: jsonapi.h:55
bool * pathok
Definition: jsonfuncs.c:86
bool normalize_results
Definition: jsonfuncs.c:81
bool next_scalar
Definition: jsonfuncs.c:82
#define NULL
Definition: c.h:229
Definition: regguts.h:298
int * path_indexes
Definition: jsonfuncs.c:85
static void get_array_end ( void *  state)
static

Definition at line 1218 of file jsonfuncs.c.

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

Referenced by get_worker().

1219 {
1220  GetState *_state = (GetState *) state;
1221  int lex_level = _state->lex->lex_level;
1222 
1223  if (lex_level == 0 && _state->npath == 0)
1224  {
1225  /* Special case: return the entire array */
1226  char *start = _state->result_start;
1227  int len = _state->lex->prev_token_terminator - start;
1228 
1229  _state->tresult = cstring_to_text_with_len(start, len);
1230  }
1231 }
char * prev_token_terminator
Definition: jsonapi.h:57
int lex_level
Definition: jsonapi.h:59
JsonLexContext * lex
Definition: jsonfuncs.c:78
char * result_start
Definition: jsonfuncs.c:80
text * tresult
Definition: jsonfuncs.c:79
text * cstring_to_text_with_len(const char *s, int len)
Definition: varlena.c:161
int npath
Definition: jsonfuncs.c:83
Definition: regguts.h:298
static void get_array_start ( void *  state)
static

Definition at line 1185 of file jsonfuncs.c.

References GetState::array_cur_index, json_count_array_elements(), GetState::lex, JsonLexContext::lex_level, GetState::npath, GetState::path_indexes, GetState::result_start, and JsonLexContext::token_start.

Referenced by get_worker().

1186 {
1187  GetState *_state = (GetState *) state;
1188  int lex_level = _state->lex->lex_level;
1189 
1190  if (lex_level < _state->npath)
1191  {
1192  /* Initialize counting of elements in this array */
1193  _state->array_cur_index[lex_level] = -1;
1194 
1195  /* INT_MIN value is reserved to represent invalid subscript */
1196  if (_state->path_indexes[lex_level] < 0 &&
1197  _state->path_indexes[lex_level] != INT_MIN)
1198  {
1199  /* Negative subscript -- convert to positive-wise subscript */
1200  int nelements = json_count_array_elements(_state->lex);
1201 
1202  if (-_state->path_indexes[lex_level] <= nelements)
1203  _state->path_indexes[lex_level] += nelements;
1204  }
1205  }
1206  else if (lex_level == 0 && _state->npath == 0)
1207  {
1208  /*
1209  * Special case: we should match the entire array. We only need this
1210  * at the outermost level because at nested levels the match will have
1211  * been started by the outer field or array element callback.
1212  */
1213  _state->result_start = _state->lex->token_start;
1214  }
1215 }
int * array_cur_index
Definition: jsonfuncs.c:87
int lex_level
Definition: jsonapi.h:59
JsonLexContext * lex
Definition: jsonfuncs.c:78
char * result_start
Definition: jsonfuncs.c:80
int npath
Definition: jsonfuncs.c:83
int json_count_array_elements(JsonLexContext *lex)
Definition: json.c:366
char * token_start
Definition: jsonapi.h:55
Definition: regguts.h:298
int * path_indexes
Definition: jsonfuncs.c:85
static HTAB * get_json_object_as_hash ( char *  json,
int  len,
const char *  funcname 
)
static

Definition at line 3250 of file jsonfuncs.c.

References JsonSemAction::array_start, CurrentMemoryContext, HASHCTL::entrysize, JHashState::function_name, JHashState::hash, hash_array_start(), HASH_CONTEXT, hash_create(), HASH_ELEM, hash_object_field_end(), hash_object_field_start(), hash_scalar(), HASHCTL::hcxt, HASHCTL::keysize, JHashState::lex, makeJsonLexContextCstringLen(), NAMEDATALEN, JsonSemAction::object_field_end, JsonSemAction::object_field_start, palloc0(), pg_parse_json(), JsonSemAction::scalar, and JsonSemAction::semstate.

Referenced by JsValueToJsObject().

3251 {
3252  HASHCTL ctl;
3253  HTAB *tab;
3254  JHashState *state;
3255  JsonLexContext *lex = makeJsonLexContextCstringLen(json, len, true);
3256  JsonSemAction *sem;
3257 
3258  memset(&ctl, 0, sizeof(ctl));
3259  ctl.keysize = NAMEDATALEN;
3260  ctl.entrysize = sizeof(JsonHashEntry);
3261  ctl.hcxt = CurrentMemoryContext;
3262  tab = hash_create("json object hashtable",
3263  100,
3264  &ctl,
3266 
3267  state = palloc0(sizeof(JHashState));
3268  sem = palloc0(sizeof(JsonSemAction));
3269 
3270  state->function_name = funcname;
3271  state->hash = tab;
3272  state->lex = lex;
3273 
3274  sem->semstate = (void *) state;
3276  sem->scalar = hash_scalar;
3279 
3280  pg_parse_json(lex, sem);
3281 
3282  return tab;
3283 }
#define HASH_CONTEXT
Definition: hsearch.h:93
#define HASH_ELEM
Definition: hsearch.h:87
MemoryContext hcxt
Definition: hsearch.h:78
Size entrysize
Definition: hsearch.h:73
static void hash_object_field_end(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:3310
json_scalar_action scalar
Definition: jsonapi.h:93
#define NAMEDATALEN
Definition: dynahash.c:193
void pg_parse_json(JsonLexContext *lex, JsonSemAction *sem)
Definition: json.c:331
HTAB * hash
Definition: jsonfuncs.c:129
MemoryContext CurrentMemoryContext
Definition: mcxt.c:37
json_ofield_action object_field_end
Definition: jsonapi.h:90
static void hash_object_field_start(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:3286
const char * function_name
Definition: jsonfuncs.c:128
void * palloc0(Size size)
Definition: mcxt.c:878
HTAB * hash_create(const char *tabname, long nelem, HASHCTL *info, int flags)
Definition: dynahash.c:301
Size keysize
Definition: hsearch.h:72
json_struct_action array_start
Definition: jsonapi.h:87
Definition: regguts.h:298
JsonLexContext * makeJsonLexContextCstringLen(char *json, int len, bool need_escapes)
Definition: json.c:308
struct JsonHashEntry JsonHashEntry
JsonLexContext * lex
Definition: jsonfuncs.c:127
static void hash_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:3370
json_ofield_action object_field_start
Definition: jsonapi.h:89
void * semstate
Definition: jsonapi.h:84
static void hash_array_start(void *state)
Definition: jsonfuncs.c:3359
static Datum get_jsonb_path_all ( FunctionCallInfo  fcinfo,
bool  as_text 
)
static

Definition at line 1375 of file jsonfuncs.c.

References array_contains_nulls(), Assert, cstring_to_text(), cstring_to_text_with_len(), deconstruct_array(), elog, ERROR, findJsonbValueFromContainerLen(), getIthJsonbValueFromContainer(), i, JB_FOBJECT, JB_ROOT_IS_ARRAY, JB_ROOT_IS_OBJECT, JB_ROOT_IS_SCALAR, jbvArray, jbvBinary, jbvNull, jbvObject, jbvString, JsonbIteratorInit(), JsonbIteratorNext(), JsonbToCString(), JsonbValueToJsonb(), JsonContainerIsArray, JsonContainerSize, NULL, PG_GETARG_ARRAYTYPE_P, PG_GETARG_JSONB, PG_RETURN_JSONB, PG_RETURN_NULL, PG_RETURN_TEXT_P, Jsonb::root, TextDatumGetCString, TEXTOID, JsonbValue::type, JsonbValue::val, VARDATA, VARHDRSZ, VARSIZE, WJB_BEGIN_ARRAY, and WJB_BEGIN_OBJECT.

Referenced by jsonb_extract_path(), and jsonb_extract_path_text().

1376 {
1377  Jsonb *jb = PG_GETARG_JSONB(0);
1378  ArrayType *path = PG_GETARG_ARRAYTYPE_P(1);
1379  Jsonb *res;
1380  Datum *pathtext;
1381  bool *pathnulls;
1382  int npath;
1383  int i;
1384  bool have_object = false,
1385  have_array = false;
1386  JsonbValue *jbvp = NULL;
1387  JsonbValue tv;
1388  JsonbContainer *container;
1389 
1390  /*
1391  * If the array contains any null elements, return NULL, on the grounds
1392  * that you'd have gotten NULL if any RHS value were NULL in a nested
1393  * series of applications of the -> operator. (Note: because we also
1394  * return NULL for error cases such as no-such-field, this is true
1395  * regardless of the contents of the rest of the array.)
1396  */
1397  if (array_contains_nulls(path))
1398  PG_RETURN_NULL();
1399 
1400  deconstruct_array(path, TEXTOID, -1, false, 'i',
1401  &pathtext, &pathnulls, &npath);
1402 
1403  /* Identify whether we have object, array, or scalar at top-level */
1404  container = &jb->root;
1405 
1406  if (JB_ROOT_IS_OBJECT(jb))
1407  have_object = true;
1408  else if (JB_ROOT_IS_ARRAY(jb) && !JB_ROOT_IS_SCALAR(jb))
1409  have_array = true;
1410  else
1411  {
1413  /* Extract the scalar value, if it is what we'll return */
1414  if (npath <= 0)
1415  jbvp = getIthJsonbValueFromContainer(container, 0);
1416  }
1417 
1418  /*
1419  * If the array is empty, return the entire LHS object, on the grounds
1420  * that we should do zero field or element extractions. For the
1421  * non-scalar case we can just hand back the object without much work. For
1422  * the scalar case, fall through and deal with the value below the loop.
1423  * (This inconsistency arises because there's no easy way to generate a
1424  * JsonbValue directly for root-level containers.)
1425  */
1426  if (npath <= 0 && jbvp == NULL)
1427  {
1428  if (as_text)
1429  {
1431  container,
1432  VARSIZE(jb))));
1433  }
1434  else
1435  {
1436  /* not text mode - just hand back the jsonb */
1437  PG_RETURN_JSONB(jb);
1438  }
1439  }
1440 
1441  for (i = 0; i < npath; i++)
1442  {
1443  if (have_object)
1444  {
1445  jbvp = findJsonbValueFromContainerLen(container,
1446  JB_FOBJECT,
1447  VARDATA(pathtext[i]),
1448  VARSIZE(pathtext[i]) - VARHDRSZ);
1449  }
1450  else if (have_array)
1451  {
1452  long lindex;
1453  uint32 index;
1454  char *indextext = TextDatumGetCString(pathtext[i]);
1455  char *endptr;
1456 
1457  errno = 0;
1458  lindex = strtol(indextext, &endptr, 10);
1459  if (endptr == indextext || *endptr != '\0' || errno != 0 ||
1460  lindex > INT_MAX || lindex < INT_MIN)
1461  PG_RETURN_NULL();
1462 
1463  if (lindex >= 0)
1464  {
1465  index = (uint32) lindex;
1466  }
1467  else
1468  {
1469  /* Handle negative subscript */
1470  uint32 nelements;
1471 
1472  /* Container must be array, but make sure */
1473  if (!JsonContainerIsArray(container))
1474  elog(ERROR, "not a jsonb array");
1475 
1476  nelements = JsonContainerSize(container);
1477 
1478  if (-lindex > nelements)
1479  PG_RETURN_NULL();
1480  else
1481  index = nelements + lindex;
1482  }
1483 
1484  jbvp = getIthJsonbValueFromContainer(container, index);
1485  }
1486  else
1487  {
1488  /* scalar, extraction yields a null */
1489  PG_RETURN_NULL();
1490  }
1491 
1492  if (jbvp == NULL)
1493  PG_RETURN_NULL();
1494  else if (i == npath - 1)
1495  break;
1496 
1497  if (jbvp->type == jbvBinary)
1498  {
1499  JsonbIterator *it = JsonbIteratorInit((JsonbContainer *) jbvp->val.binary.data);
1501 
1502  r = JsonbIteratorNext(&it, &tv, true);
1503  container = (JsonbContainer *) jbvp->val.binary.data;
1504  have_object = r == WJB_BEGIN_OBJECT;
1505  have_array = r == WJB_BEGIN_ARRAY;
1506  }
1507  else
1508  {
1509  have_object = jbvp->type == jbvObject;
1510  have_array = jbvp->type == jbvArray;
1511  }
1512  }
1513 
1514  if (as_text)
1515  {
1516  /* special-case outputs for string and null values */
1517  if (jbvp->type == jbvString)
1519  jbvp->val.string.len));
1520  if (jbvp->type == jbvNull)
1521  PG_RETURN_NULL();
1522  }
1523 
1524  res = JsonbValueToJsonb(jbvp);
1525 
1526  if (as_text)
1527  {
1529  &res->root,
1530  VARSIZE(res))));
1531  }
1532  else
1533  {
1534  /* not text mode - just hand back the jsonb */
1535  PG_RETURN_JSONB(res);
1536  }
1537 }
#define JB_ROOT_IS_OBJECT(jbp_)
Definition: jsonb.h:224
#define VARDATA(PTR)
Definition: postgres.h:303
Jsonb * JsonbValueToJsonb(JsonbValue *val)
Definition: jsonb_util.c:79
Definition: jsonb.h:215
#define TEXTOID
Definition: pg_type.h:324
#define VARSIZE(PTR)
Definition: postgres.h:304
#define VARHDRSZ
Definition: c.h:445
char * val
Definition: jsonb.h:259
static JsonbValue * findJsonbValueFromContainerLen(JsonbContainer *container, uint32 flags, char *key, uint32 keylen)
Definition: jsonfuncs.c:3742
Definition: jsonb.h:231
#define JB_ROOT_IS_SCALAR(jbp_)
Definition: jsonb.h:223
Definition: type.h:90
#define PG_GETARG_ARRAYTYPE_P(n)
Definition: array.h:244
#define ERROR
Definition: elog.h:43
#define PG_RETURN_JSONB(x)
Definition: jsonb.h:71
#define JB_ROOT_IS_ARRAY(jbp_)
Definition: jsonb.h:225
text * cstring_to_text_with_len(const char *s, int len)
Definition: varlena.c:161
#define JsonContainerSize(jc)
Definition: jsonb.h:209
unsigned int uint32
Definition: c.h:268
#define JsonContainerIsArray(jc)
Definition: jsonb.h:212
JsonbIteratorToken
Definition: jsonb.h:20
JsonbContainer root
Definition: jsonb.h:218
#define TextDatumGetCString(d)
Definition: builtins.h:92
uintptr_t Datum
Definition: postgres.h:372
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:330
text * cstring_to_text(const char *s)
Definition: varlena.c:149
JsonbValue * getIthJsonbValueFromContainer(JsonbContainer *container, uint32 i)
Definition: jsonb_util.c:419
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
JsonbIterator * JsonbIteratorInit(JsonbContainer *container)
Definition: jsonb_util.c:718
#define JB_FOBJECT
Definition: jsonb.h:205
char * JsonbToCString(StringInfo out, JsonbContainer *in, int estimated_len)
Definition: jsonb.c:428
enum jbvType type
Definition: jsonb.h:250
void deconstruct_array(ArrayType *array, Oid elmtype, int elmlen, bool elmbyval, char elmalign, Datum **elemsp, bool **nullsp, int *nelemsp)
Definition: arrayfuncs.c:3475
#define PG_GETARG_JSONB(x)
Definition: jsonb.h:70
int i
#define elog
Definition: elog.h:219
bool array_contains_nulls(ArrayType *array)
Definition: arrayfuncs.c:3542
#define PG_RETURN_NULL()
Definition: fmgr.h:305
JsonbIteratorToken JsonbIteratorNext(JsonbIterator **it, JsonbValue *val, bool skipNested)
Definition: jsonb_util.c:754
static void get_object_end ( void *  state)
static

Definition at line 1075 of file jsonfuncs.c.

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

Referenced by get_worker().

1076 {
1077  GetState *_state = (GetState *) state;
1078  int lex_level = _state->lex->lex_level;
1079 
1080  if (lex_level == 0 && _state->npath == 0)
1081  {
1082  /* Special case: return the entire object */
1083  char *start = _state->result_start;
1084  int len = _state->lex->prev_token_terminator - start;
1085 
1086  _state->tresult = cstring_to_text_with_len(start, len);
1087  }
1088 }
char * prev_token_terminator
Definition: jsonapi.h:57
int lex_level
Definition: jsonapi.h:59
JsonLexContext * lex
Definition: jsonfuncs.c:78
char * result_start
Definition: jsonfuncs.c:80
text * tresult
Definition: jsonfuncs.c:79
text * cstring_to_text_with_len(const char *s, int len)
Definition: varlena.c:161
int npath
Definition: jsonfuncs.c:83
Definition: regguts.h:298
static void get_object_field_end ( void *  state,
char *  fname,
bool  isnull 
)
static

Definition at line 1136 of file jsonfuncs.c.

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

Referenced by get_worker().

1137 {
1138  GetState *_state = (GetState *) state;
1139  bool get_last = false;
1140  int lex_level = _state->lex->lex_level;
1141 
1142  /* same tests as in get_object_field_start */
1143  if (lex_level <= _state->npath &&
1144  _state->pathok[lex_level - 1] &&
1145  _state->path_names != NULL &&
1146  _state->path_names[lex_level - 1] != NULL &&
1147  strcmp(fname, _state->path_names[lex_level - 1]) == 0)
1148  {
1149  if (lex_level < _state->npath)
1150  {
1151  /* done with this field so reset pathok */
1152  _state->pathok[lex_level] = false;
1153  }
1154  else
1155  {
1156  /* end of path, so we want this value */
1157  get_last = true;
1158  }
1159  }
1160 
1161  /* for as_text scalar case, our work is already done */
1162  if (get_last && _state->result_start != NULL)
1163  {
1164  /*
1165  * make a text object from the string from the prevously noted json
1166  * start up to the end of the previous token (the lexer is by now
1167  * ahead of us on whatever came after what we're interested in).
1168  */
1169  if (isnull && _state->normalize_results)
1170  _state->tresult = (text *) NULL;
1171  else
1172  {
1173  char *start = _state->result_start;
1174  int len = _state->lex->prev_token_terminator - start;
1175 
1176  _state->tresult = cstring_to_text_with_len(start, len);
1177  }
1178 
1179  /* this should be unnecessary but let's do it for cleanliness: */
1180  _state->result_start = NULL;
1181  }
1182 }
char * prev_token_terminator
Definition: jsonapi.h:57
int lex_level
Definition: jsonapi.h:59
JsonLexContext * lex
Definition: jsonfuncs.c:78
char * result_start
Definition: jsonfuncs.c:80
text * tresult
Definition: jsonfuncs.c:79
text * cstring_to_text_with_len(const char *s, int len)
Definition: varlena.c:161
bool * pathok
Definition: jsonfuncs.c:86
bool normalize_results
Definition: jsonfuncs.c:81
char ** path_names
Definition: jsonfuncs.c:84
#define NULL
Definition: c.h:229
Definition: regguts.h:298
Definition: c.h:439
static void get_object_field_start ( void *  state,
char *  fname,
bool  isnull 
)
static

Definition at line 1091 of file jsonfuncs.c.

References JSON_TOKEN_STRING, GetState::lex, JsonLexContext::lex_level, GetState::next_scalar, GetState::normalize_results, NULL, GetState::path_names, GetState::pathok, GetState::result_start, JsonLexContext::token_start, JsonLexContext::token_type, and GetState::tresult.

Referenced by get_worker().

1092 {
1093  GetState *_state = (GetState *) state;
1094  bool get_next = false;
1095  int lex_level = _state->lex->lex_level;
1096 
1097  if (lex_level <= _state->npath &&
1098  _state->pathok[lex_level - 1] &&
1099  _state->path_names != NULL &&
1100  _state->path_names[lex_level - 1] != NULL &&
1101  strcmp(fname, _state->path_names[lex_level - 1]) == 0)
1102  {
1103  if (lex_level < _state->npath)
1104  {
1105  /* if not at end of path just mark path ok */
1106  _state->pathok[lex_level] = true;
1107  }
1108  else
1109  {
1110  /* end of path, so we want this value */
1111  get_next = true;
1112  }
1113  }
1114 
1115  if (get_next)
1116  {
1117  /* this object overrides any previous matching object */
1118  _state->tresult = NULL;
1119  _state->result_start = NULL;
1120 
1121  if (_state->normalize_results &&
1122  _state->lex->token_type == JSON_TOKEN_STRING)
1123  {
1124  /* for as_text variants, tell get_scalar to set it for us */
1125  _state->next_scalar = true;
1126  }
1127  else
1128  {
1129  /* for non-as_text variants, just note the json starting point */
1130  _state->result_start = _state->lex->token_start;
1131  }
1132  }
1133 }
JsonTokenType token_type
Definition: jsonapi.h:58
int lex_level
Definition: jsonapi.h:59
JsonLexContext * lex
Definition: jsonfuncs.c:78
char * result_start
Definition: jsonfuncs.c:80
text * tresult
Definition: jsonfuncs.c:79
char * token_start
Definition: jsonapi.h:55
bool * pathok
Definition: jsonfuncs.c:86
bool normalize_results
Definition: jsonfuncs.c:81
bool next_scalar
Definition: jsonfuncs.c:82
char ** path_names
Definition: jsonfuncs.c:84
#define NULL
Definition: c.h:229
Definition: regguts.h:298
static void get_object_start ( void *  state)
static

Definition at line 1058 of file jsonfuncs.c.

References GetState::lex, JsonLexContext::lex_level, GetState::npath, GetState::result_start, and JsonLexContext::token_start.

Referenced by get_worker().

1059 {
1060  GetState *_state = (GetState *) state;
1061  int lex_level = _state->lex->lex_level;
1062 
1063  if (lex_level == 0 && _state->npath == 0)
1064  {
1065  /*
1066  * Special case: we should match the entire object. We only need this
1067  * at outermost level because at nested levels the match will have
1068  * been started by the outer field or array element callback.
1069  */
1070  _state->result_start = _state->lex->token_start;
1071  }
1072 }
int lex_level
Definition: jsonapi.h:59
JsonLexContext * lex
Definition: jsonfuncs.c:78
char * result_start
Definition: jsonfuncs.c:80
int npath
Definition: jsonfuncs.c:83
char * token_start
Definition: jsonapi.h:55
Definition: regguts.h:298
static Datum get_path_all ( FunctionCallInfo  fcinfo,
bool  as_text 
)
static

Definition at line 922 of file jsonfuncs.c.

References array_contains_nulls(), Assert, deconstruct_array(), get_worker(), i, NULL, palloc(), PG_GETARG_ARRAYTYPE_P, PG_GETARG_TEXT_PP, PG_RETURN_NULL, PG_RETURN_TEXT_P, result, TextDatumGetCString, and TEXTOID.

Referenced by json_extract_path(), and json_extract_path_text().

923 {
924  text *json = PG_GETARG_TEXT_PP(0);
925  ArrayType *path = PG_GETARG_ARRAYTYPE_P(1);
926  text *result;
927  Datum *pathtext;
928  bool *pathnulls;
929  int npath;
930  char **tpath;
931  int *ipath;
932  int i;
933 
934  /*
935  * If the array contains any null elements, return NULL, on the grounds
936  * that you'd have gotten NULL if any RHS value were NULL in a nested
937  * series of applications of the -> operator. (Note: because we also
938  * return NULL for error cases such as no-such-field, this is true
939  * regardless of the contents of the rest of the array.)
940  */
941  if (array_contains_nulls(path))
942  PG_RETURN_NULL();
943 
944  deconstruct_array(path, TEXTOID, -1, false, 'i',
945  &pathtext, &pathnulls, &npath);
946 
947  tpath = palloc(npath * sizeof(char *));
948  ipath = palloc(npath * sizeof(int));
949 
950  for (i = 0; i < npath; i++)
951  {
952  Assert(!pathnulls[i]);
953  tpath[i] = TextDatumGetCString(pathtext[i]);
954 
955  /*
956  * we have no idea at this stage what structure the document is so
957  * just convert anything in the path that we can to an integer and set
958  * all the other integers to INT_MIN which will never match.
959  */
960  if (*tpath[i] != '\0')
961  {
962  long ind;
963  char *endptr;
964 
965  errno = 0;
966  ind = strtol(tpath[i], &endptr, 10);
967  if (*endptr == '\0' && errno == 0 && ind <= INT_MAX && ind >= INT_MIN)
968  ipath[i] = (int) ind;
969  else
970  ipath[i] = INT_MIN;
971  }
972  else
973  ipath[i] = INT_MIN;
974  }
975 
976  result = get_worker(json, tpath, ipath, npath, as_text);
977 
978  if (result != NULL)
979  PG_RETURN_TEXT_P(result);
980  else
981  PG_RETURN_NULL();
982 }
#define TEXTOID
Definition: pg_type.h:324
return result
Definition: formatting.c:1632
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:273
#define PG_GETARG_ARRAYTYPE_P(n)
Definition: array.h:244
#define TextDatumGetCString(d)
Definition: builtins.h:92
uintptr_t Datum
Definition: postgres.h:372
static text * get_worker(text *json, char **tpath, int *ipath, int npath, bool normalize_results)
Definition: jsonfuncs.c:1002
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:330
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
void deconstruct_array(ArrayType *array, Oid elmtype, int elmlen, bool elmbyval, char elmalign, Datum **elemsp, bool **nullsp, int *nelemsp)
Definition: arrayfuncs.c:3475
void * palloc(Size size)
Definition: mcxt.c:849
int i
Definition: c.h:439
bool array_contains_nulls(ArrayType *array)
Definition: arrayfuncs.c:3542
#define PG_RETURN_NULL()
Definition: fmgr.h:305
static void get_scalar ( void *  state,
char *  token,
JsonTokenType  tokentype 
)
static

Definition at line 1322 of file jsonfuncs.c.

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

Referenced by get_worker().

1323 {
1324  GetState *_state = (GetState *) state;
1325  int lex_level = _state->lex->lex_level;
1326 
1327  /* Check for whole-object match */
1328  if (lex_level == 0 && _state->npath == 0)
1329  {
1330  if (_state->normalize_results && tokentype == JSON_TOKEN_STRING)
1331  {
1332  /* we want the de-escaped string */
1333  _state->next_scalar = true;
1334  }
1335  else if (_state->normalize_results && tokentype == JSON_TOKEN_NULL)
1336  {
1337  _state->tresult = (text *) NULL;
1338  }
1339  else
1340  {
1341  /*
1342  * This is a bit hokey: we will suppress whitespace after the
1343  * scalar token, but not whitespace before it. Probably not worth
1344  * doing our own space-skipping to avoid that.
1345  */
1346  char *start = _state->lex->input;
1347  int len = _state->lex->prev_token_terminator - start;
1348 
1349  _state->tresult = cstring_to_text_with_len(start, len);
1350  }
1351  }
1352 
1353  if (_state->next_scalar)
1354  {
1355  /* a de-escaped text value is wanted, so supply it */
1356  _state->tresult = cstring_to_text(token);
1357  /* make sure the next call to get_scalar doesn't overwrite it */
1358  _state->next_scalar = false;
1359  }
1360 }
char * prev_token_terminator
Definition: jsonapi.h:57
int lex_level
Definition: jsonapi.h:59
JsonLexContext * lex
Definition: jsonfuncs.c:78
text * tresult
Definition: jsonfuncs.c:79
text * cstring_to_text_with_len(const char *s, int len)
Definition: varlena.c:161
int npath
Definition: jsonfuncs.c:83
bool normalize_results
Definition: jsonfuncs.c:81
bool next_scalar
Definition: jsonfuncs.c:82
text * cstring_to_text(const char *s)
Definition: varlena.c:149
#define NULL
Definition: c.h:229
char * input
Definition: jsonapi.h:53
Definition: regguts.h:298
Definition: c.h:439
static text * get_worker ( text json,
char **  tpath,
int *  ipath,
int  npath,
bool  normalize_results 
)
static

Definition at line 1002 of file jsonfuncs.c.

References GetState::array_cur_index, 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(), GetState::lex, makeJsonLexContext(), GetState::normalize_results, GetState::npath, NULL, JsonSemAction::object_end, JsonSemAction::object_field_end, JsonSemAction::object_field_start, JsonSemAction::object_start, palloc(), palloc0(), GetState::path_indexes, GetState::path_names, GetState::pathok, pg_parse_json(), JsonSemAction::scalar, JsonSemAction::semstate, and GetState::tresult.

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

1007 {
1008  JsonLexContext *lex = makeJsonLexContext(json, true);
1009  JsonSemAction *sem = palloc0(sizeof(JsonSemAction));
1010  GetState *state = palloc0(sizeof(GetState));
1011 
1012  Assert(npath >= 0);
1013 
1014  state->lex = lex;
1015  /* is it "_as_text" variant? */
1016  state->normalize_results = normalize_results;
1017  state->npath = npath;
1018  state->path_names = tpath;
1019  state->path_indexes = ipath;
1020  state->pathok = palloc0(sizeof(bool) * npath);
1021  state->array_cur_index = palloc(sizeof(int) * npath);
1022 
1023  if (npath > 0)
1024  state->pathok[0] = true;
1025 
1026  sem->semstate = (void *) state;
1027 
1028  /*
1029  * Not all variants need all the semantic routines. Only set the ones that
1030  * are actually needed for maximum efficiency.
1031  */
1032  sem->scalar = get_scalar;
1033  if (npath == 0)
1034  {
1036  sem->object_end = get_object_end;
1038  sem->array_end = get_array_end;
1039  }
1040  if (tpath != NULL)
1041  {
1044  }
1045  if (ipath != NULL)
1046  {
1050  }
1051 
1052  pg_parse_json(lex, sem);
1053 
1054  return state->tresult;
1055 }
json_struct_action array_end
Definition: jsonapi.h:88
static void get_array_end(void *state)
Definition: jsonfuncs.c:1218
int * array_cur_index
Definition: jsonfuncs.c:87
static void get_array_element_start(void *state, bool isnull)
Definition: jsonfuncs.c:1234
json_struct_action object_end
Definition: jsonapi.h:86
static void get_object_start(void *state)
Definition: jsonfuncs.c:1058
json_struct_action object_start
Definition: jsonapi.h:85
json_scalar_action scalar
Definition: jsonapi.h:93
static void get_object_field_end(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:1136
JsonLexContext * lex
Definition: jsonfuncs.c:78
static void get_object_end(void *state)
Definition: jsonfuncs.c:1075
JsonLexContext * makeJsonLexContext(text *json, bool need_escapes)
Definition: json.c:300
void pg_parse_json(JsonLexContext *lex, JsonSemAction *sem)
Definition: json.c:331
text * tresult
Definition: jsonfuncs.c:79
int npath
Definition: jsonfuncs.c:83
json_ofield_action object_field_end
Definition: jsonapi.h:90
static void get_array_element_end(void *state, bool isnull)
Definition: jsonfuncs.c:1280
bool * pathok
Definition: jsonfuncs.c:86
bool normalize_results
Definition: jsonfuncs.c:81
static void get_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:1322
void * palloc0(Size size)
Definition: mcxt.c:878
static void get_array_start(void *state)
Definition: jsonfuncs.c:1185
json_aelem_action array_element_start
Definition: jsonapi.h:91
char ** path_names
Definition: jsonfuncs.c:84
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
json_struct_action array_start
Definition: jsonapi.h:87
Definition: regguts.h:298
int * path_indexes
Definition: jsonfuncs.c:85
void * palloc(Size size)
Definition: mcxt.c:849
static void get_object_field_start(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:1091
json_ofield_action object_field_start
Definition: jsonapi.h:89
void * semstate
Definition: jsonapi.h:84
json_aelem_action array_element_end
Definition: jsonapi.h:92
static void hash_array_start ( void *  state)
static

Definition at line 3359 of file jsonfuncs.c.

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

Referenced by get_json_object_as_hash().

3360 {
3361  JHashState *_state = (JHashState *) state;
3362 
3363  if (_state->lex->lex_level == 0)
3364  ereport(ERROR,
3365  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3366  errmsg("cannot call %s on an array", _state->function_name)));
3367 }
int errcode(int sqlerrcode)
Definition: elog.c:575
int lex_level
Definition: jsonapi.h:59
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:122
const char * function_name
Definition: jsonfuncs.c:128
Definition: regguts.h:298
JsonLexContext * lex
Definition: jsonfuncs.c:127
int errmsg(const char *fmt,...)
Definition: elog.c:797
static void hash_object_field_end ( void *  state,
char *  fname,
bool  isnull 
)
static

Definition at line 3310 of file jsonfuncs.c.

References Assert, JHashState::hash, HASH_ENTER, hash_search(), JSON_TOKEN_NULL, JHashState::lex, JsonLexContext::lex_level, NAMEDATALEN, NULL, 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().

3311 {
3312  JHashState *_state = (JHashState *) state;
3313  JsonHashEntry *hashentry;
3314  bool found;
3315 
3316  /*
3317  * Ignore nested fields.
3318  */
3319  if (_state->lex->lex_level > 1)
3320  return;
3321 
3322  /*
3323  * Ignore field names >= NAMEDATALEN - they can't match a record field.
3324  * (Note: without this test, the hash code would truncate the string at
3325  * NAMEDATALEN-1, and could then match against a similarly-truncated
3326  * record field name. That would be a reasonable behavior, but this code
3327  * has previously insisted on exact equality, so we keep this behavior.)
3328  */
3329  if (strlen(fname) >= NAMEDATALEN)
3330  return;
3331 
3332  hashentry = hash_search(_state->hash, fname, HASH_ENTER, &found);
3333 
3334  /*
3335  * found being true indicates a duplicate. We don't do anything about
3336  * that, a later field with the same name overrides the earlier field.
3337  */
3338 
3339  hashentry->type = _state->saved_token_type;
3340  Assert(isnull == (hashentry->type == JSON_TOKEN_NULL));
3341 
3342  if (_state->save_json_start != NULL)
3343  {
3344  int len = _state->lex->prev_token_terminator - _state->save_json_start;
3345  char *val = palloc((len + 1) * sizeof(char));
3346 
3347  memcpy(val, _state->save_json_start, len);
3348  val[len] = '\0';
3349  hashentry->val = val;
3350  }
3351  else
3352  {
3353  /* must have had a scalar instead */
3354  hashentry->val = _state->saved_scalar;
3355  }
3356 }
char * prev_token_terminator
Definition: jsonapi.h:57
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:885
JsonTokenType type
Definition: jsonfuncs.c:140
int lex_level
Definition: jsonapi.h:59
char * save_json_start
Definition: jsonfuncs.c:131
#define NAMEDATALEN
JsonTokenType saved_token_type
Definition: jsonfuncs.c:132
char * val
Definition: jsonfuncs.c:139
HTAB * hash
Definition: jsonfuncs.c:129
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
Definition: regguts.h:298
JsonLexContext * lex
Definition: jsonfuncs.c:127
char * saved_scalar
Definition: jsonfuncs.c:130
void * palloc(Size size)
Definition: mcxt.c:849
long val
Definition: informix.c:689
static void hash_object_field_start ( void *  state,
char *  fname,
bool  isnull 
)
static

Definition at line 3286 of file jsonfuncs.c.

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

Referenced by get_json_object_as_hash().

3287 {
3288  JHashState *_state = (JHashState *) state;
3289 
3290  if (_state->lex->lex_level > 1)
3291  return;
3292 
3293  /* remember token type */
3294  _state->saved_token_type = _state->lex->token_type;
3295 
3296  if (_state->lex->token_type == JSON_TOKEN_ARRAY_START ||
3298  {
3299  /* remember start position of the whole text of the subobject */
3300  _state->save_json_start = _state->lex->token_start;
3301  }
3302  else
3303  {
3304  /* must be a scalar */
3305  _state->save_json_start = NULL;
3306  }
3307 }
JsonTokenType token_type
Definition: jsonapi.h:58
int lex_level
Definition: jsonapi.h:59
char * save_json_start
Definition: jsonfuncs.c:131
JsonTokenType saved_token_type
Definition: jsonfuncs.c:132
char * token_start
Definition: jsonapi.h:55
#define NULL
Definition: c.h:229
Definition: regguts.h:298
JsonLexContext * lex
Definition: jsonfuncs.c:127
static void hash_scalar ( void *  state,
char *  token,
JsonTokenType  tokentype 
)
static

Definition at line 3370 of file jsonfuncs.c.

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

Referenced by get_json_object_as_hash().

3371 {
3372  JHashState *_state = (JHashState *) state;
3373 
3374  if (_state->lex->lex_level == 0)
3375  ereport(ERROR,
3376  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3377  errmsg("cannot call %s on a scalar", _state->function_name)));
3378 
3379  if (_state->lex->lex_level == 1)
3380  {
3381  _state->saved_scalar = token;
3382  /* saved_token_type must already be set in hash_object_field_start() */
3383  Assert(_state->saved_token_type == tokentype);
3384  }
3385 }
int errcode(int sqlerrcode)
Definition: elog.c:575
int lex_level
Definition: jsonapi.h:59
#define ERROR
Definition: elog.h:43
JsonTokenType saved_token_type
Definition: jsonfuncs.c:132
#define ereport(elevel, rest)
Definition: elog.h:122
const char * function_name
Definition: jsonfuncs.c:128
#define Assert(condition)
Definition: c.h:675
Definition: regguts.h:298
JsonLexContext * lex
Definition: jsonfuncs.c:127
char * saved_scalar
Definition: jsonfuncs.c:130
int errmsg(const char *fmt,...)
Definition: elog.c:797
void iterate_json_string_values ( text json,
void *  action_state,
JsonIterateStringValuesAction  action 
)

Definition at line 4821 of file jsonfuncs.c.

References IterateJsonStringValuesState::action, IterateJsonStringValuesState::action_state, iterate_string_values_scalar(), IterateJsonStringValuesState::lex, makeJsonLexContext(), palloc0(), pg_parse_json(), JsonSemAction::scalar, and JsonSemAction::semstate.

Referenced by json_to_tsvector_byid().

4822 {
4823  JsonLexContext *lex = makeJsonLexContext(json, true);
4824  JsonSemAction *sem = palloc0(sizeof(JsonSemAction));
4826 
4827  state->lex = lex;
4828  state->action = action;
4829  state->action_state = action_state;
4830 
4831  sem->semstate = (void *) state;
4833 
4834  pg_parse_json(lex, sem);
4835 }
JsonIterateStringValuesAction action
Definition: jsonfuncs.c:60
json_scalar_action scalar
Definition: jsonapi.h:93
JsonLexContext * makeJsonLexContext(text *json, bool need_escapes)
Definition: json.c:300
void pg_parse_json(JsonLexContext *lex, JsonSemAction *sem)
Definition: json.c:331
void * palloc0(Size size)
Definition: mcxt.c:878
Definition: regguts.h:298
static void iterate_string_values_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:4842
JsonLexContext * lex
Definition: jsonfuncs.c:59
void * semstate
Definition: jsonapi.h:84
void iterate_jsonb_string_values ( Jsonb jb,
void *  state,
JsonIterateStringValuesAction  action 
)

Definition at line 4799 of file jsonfuncs.c.

References jbvString, JsonbIteratorInit(), JsonbIteratorNext(), Jsonb::root, JsonbValue::type, JsonbValue::val, WJB_DONE, WJB_ELEM, and WJB_VALUE.

Referenced by jsonb_to_tsvector_byid().

4800 {
4801  JsonbIterator *it;
4802  JsonbValue v;
4803  JsonbIteratorToken type;
4804 
4805  it = JsonbIteratorInit(&jb->root);
4806 
4807  while ((type = JsonbIteratorNext(&it, &v, false)) != WJB_DONE)
4808  {
4809  if ((type == WJB_VALUE || type == WJB_ELEM) && v.type == jbvString)
4810  {
4811  action(state, v.val.string.val, v.val.string.len);
4812  }
4813  }
4814 }
char * val
Definition: jsonb.h:259
Definition: jsonb.h:22
JsonbIteratorToken
Definition: jsonb.h:20
JsonbContainer root
Definition: jsonb.h:218
JsonbIterator * JsonbIteratorInit(JsonbContainer *container)
Definition: jsonb_util.c:718
Definition: regguts.h:298
enum jbvType type
Definition: jsonb.h:250
JsonbIteratorToken JsonbIteratorNext(JsonbIterator **it, JsonbValue *val, bool skipNested)
Definition: jsonb_util.c:754
Definition: jsonb.h:25
static void iterate_string_values_scalar ( void *  state,
char *  token,
JsonTokenType  tokentype 
)
static

Definition at line 4842 of file jsonfuncs.c.

References IterateJsonStringValuesState::action, IterateJsonStringValuesState::action_state, and JSON_TOKEN_STRING.

Referenced by iterate_json_string_values().

4843 {
4845 
4846  if (tokentype == JSON_TOKEN_STRING)
4847  (*_state->action) (_state->action_state, token, strlen(token));
4848 }
JsonIterateStringValuesAction action
Definition: jsonfuncs.c:60
Definition: regguts.h:298
static JsonbValue * IteratorConcat ( JsonbIterator **  it1,
JsonbIterator **  it2,
JsonbParseState **  state 
)
static

Definition at line 4399 of file jsonfuncs.c.

References Assert, ereport, errcode(), errmsg(), ERROR, JsonbIteratorNext(), NULL, pushJsonbValue(), WJB_BEGIN_ARRAY, WJB_BEGIN_OBJECT, WJB_ELEM, WJB_END_ARRAY, and WJB_END_OBJECT.

Referenced by jsonb_concat().

4401 {
4402  JsonbValue v1,
4403  v2,
4404  *res = NULL;
4405  JsonbIteratorToken r1,
4406  r2,
4407  rk1,
4408  rk2;
4409 
4410  r1 = rk1 = JsonbIteratorNext(it1, &v1, false);
4411  r2 = rk2 = JsonbIteratorNext(it2, &v2, false);
4412 
4413  /*
4414  * Both elements are objects.
4415  */
4416  if (rk1 == WJB_BEGIN_OBJECT && rk2 == WJB_BEGIN_OBJECT)
4417  {
4418  /*
4419  * Append the all tokens from v1 to res, except last WJB_END_OBJECT
4420  * (because res will not be finished yet).
4421  */
4422  pushJsonbValue(state, r1, NULL);
4423  while ((r1 = JsonbIteratorNext(it1, &v1, true)) != WJB_END_OBJECT)
4424  pushJsonbValue(state, r1, &v1);
4425 
4426  /*
4427  * Append the all tokens from v2 to res, include last WJB_END_OBJECT
4428  * (the concatenation will be completed).
4429  */
4430  while ((r2 = JsonbIteratorNext(it2, &v2, true)) != 0)
4431  res = pushJsonbValue(state, r2, r2 != WJB_END_OBJECT ? &v2 : NULL);
4432  }
4433 
4434  /*
4435  * Both elements are arrays (either can be scalar).
4436  */
4437  else if (rk1 == WJB_BEGIN_ARRAY && rk2 == WJB_BEGIN_ARRAY)
4438  {
4439  pushJsonbValue(state, r1, NULL);
4440 
4441  while ((r1 = JsonbIteratorNext(it1, &v1, true)) != WJB_END_ARRAY)
4442  {
4443  Assert(r1 == WJB_ELEM);
4444  pushJsonbValue(state, r1, &v1);
4445  }
4446 
4447  while ((r2 = JsonbIteratorNext(it2, &v2, true)) != WJB_END_ARRAY)
4448  {
4449  Assert(r2 == WJB_ELEM);
4450  pushJsonbValue(state, WJB_ELEM, &v2);
4451  }
4452 
4453  res = pushJsonbValue(state, WJB_END_ARRAY, NULL /* signal to sort */ );
4454  }
4455  /* have we got array || object or object || array? */
4456  else if (((rk1 == WJB_BEGIN_ARRAY && !(*it1)->isScalar) && rk2 == WJB_BEGIN_OBJECT) ||
4457  (rk1 == WJB_BEGIN_OBJECT && (rk2 == WJB_BEGIN_ARRAY && !(*it2)->isScalar)))
4458  {
4459 
4460  JsonbIterator **it_array = rk1 == WJB_BEGIN_ARRAY ? it1 : it2;
4461  JsonbIterator **it_object = rk1 == WJB_BEGIN_OBJECT ? it1 : it2;
4462 
4463  bool prepend = (rk1 == WJB_BEGIN_OBJECT);
4464 
4466 
4467  if (prepend)
4468  {
4470  while ((r1 = JsonbIteratorNext(it_object, &v1, true)) != 0)
4471  pushJsonbValue(state, r1, r1 != WJB_END_OBJECT ? &v1 : NULL);
4472 
4473  while ((r2 = JsonbIteratorNext(it_array, &v2, true)) != 0)
4474  res = pushJsonbValue(state, r2, r2 != WJB_END_ARRAY ? &v2 : NULL);
4475  }
4476  else
4477  {
4478  while ((r1 = JsonbIteratorNext(it_array, &v1, true)) != WJB_END_ARRAY)
4479  pushJsonbValue(state, r1, &v1);
4480 
4482  while ((r2 = JsonbIteratorNext(it_object, &v2, true)) != 0)
4483  pushJsonbValue(state, r2, r2 != WJB_END_OBJECT ? &v2 : NULL);
4484 
4485  res = pushJsonbValue(state, WJB_END_ARRAY, NULL);
4486  }
4487  }
4488  else
4489  {
4490  /*
4491  * This must be scalar || object or object || scalar, as that's all
4492  * that's left. Both of these make no sense, so error out.
4493  */
4494  ereport(ERROR,
4495  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4496  errmsg("invalid concatenation of jsonb objects")));
4497  }
4498 
4499  return res;
4500 }
int errcode(int sqlerrcode)
Definition: elog.c:575
JsonbValue * pushJsonbValue(JsonbParseState **pstate, JsonbIteratorToken seq, JsonbValue *jbval)
Definition: jsonb_util.c:517
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:122
JsonbIteratorToken
Definition: jsonb.h:20
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
int errmsg(const char *fmt,...)
Definition: elog.c:797
JsonbIteratorToken JsonbIteratorNext(JsonbIterator **it, JsonbValue *val, bool skipNested)
Definition: jsonb_util.c:754
Definition: jsonb.h:25
static bool JsObjectGetField ( JsObject obj,
char *  field,
JsValue jsv 
)
static

Definition at line 2982 of file jsonfuncs.c.

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

Referenced by populate_record().

2983 {
2984  jsv->is_json = obj->is_json;
2985 
2986  if (jsv->is_json)
2987  {
2988  JsonHashEntry *hashentry = hash_search(obj->val.json_hash, field,
2989  HASH_FIND, NULL);
2990 
2991  jsv->val.json.type = hashentry ? hashentry->type : JSON_TOKEN_NULL;
2992  jsv->val.json.str = jsv->val.json.type == JSON_TOKEN_NULL ? NULL :
2993  hashentry->val;
2994  jsv->val.json.len = jsv->val.json.str ? -1 : 0; /* null-terminated */
2995 
2996  return hashentry != NULL;
2997  }
2998  else
2999  {
3000  jsv->val.jsonb = !obj->val.jsonb_cont ? NULL :
3002  field, strlen(field));
3003 
3004  return jsv->val.jsonb != NULL;
3005  }
3006 }
struct JsValue::@31::@32 json
bool is_json
Definition: jsonfuncs.c:293
static JsonbValue * findJsonbValueFromContainerLen(JsonbContainer *container, uint32 flags, char *key, uint32 keylen)
Definition: jsonfuncs.c:3742
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:885
JsonTokenType type
Definition: jsonfuncs.c:140
JsonbContainer * jsonb_cont
Definition: jsonfuncs.c:297
union JsObject::@33 val
char * val
Definition: jsonfuncs.c:139
union JsValue::@31 val
bool is_json
Definition: jsonfuncs.c:277
HTAB * json_hash
Definition: jsonfuncs.c:296
#define NULL
Definition: c.h:229
#define JB_FOBJECT
Definition: jsonb.h:205
JsonbValue * jsonb
Definition: jsonfuncs.c:287
Datum json_array_element ( PG_FUNCTION_ARGS  )

Definition at line 790 of file jsonfuncs.c.

References element(), get_worker(), NULL, PG_GETARG_INT32, PG_GETARG_TEXT_PP, PG_RETURN_NULL, PG_RETURN_TEXT_P, and result.

791 {
792  text *json = PG_GETARG_TEXT_PP(0);
793  int element = PG_GETARG_INT32(1);
794  text *result;
795 
796  result = get_worker(json, NULL, &element, 1, false);
797 
798  if (result != NULL)
799  PG_RETURN_TEXT_P(result);
800  else
801  PG_RETURN_NULL();
802 }
#define PG_GETARG_INT32(n)
Definition: fmgr.h:234
return result
Definition: formatting.c:1632
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:273
static chr element(struct vars *v, const chr *startp, const chr *endp)
Definition: regc_locale.c:380
static text * get_worker(text *json, char **tpath, int *ipath, int npath, bool normalize_results)
Definition: jsonfuncs.c:1002
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:330
#define NULL
Definition: c.h:229
Definition: c.h:439
#define PG_RETURN_NULL()
Definition: fmgr.h:305
Datum json_array_element_text ( PG_FUNCTION_ARGS  )

Definition at line 833 of file jsonfuncs.c.

References element(), get_worker(), NULL, PG_GETARG_INT32, PG_GETARG_TEXT_PP, PG_RETURN_NULL, PG_RETURN_TEXT_P, and result.

834 {
835  text *json = PG_GETARG_TEXT_PP(0);
836  int element = PG_GETARG_INT32(1);
837  text *result;
838 
839  result = get_worker(json, NULL, &element, 1, true);
840 
841  if (result != NULL)
842  PG_RETURN_TEXT_P(result);
843  else
844  PG_RETURN_NULL();
845 }
#define PG_GETARG_INT32(n)
Definition: fmgr.h:234
return result
Definition: formatting.c:1632
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:273
static chr element(struct vars *v, const chr *startp, const chr *endp)
Definition: regc_locale.c:380
static text * get_worker(text *json, char **tpath, int *ipath, int npath, bool normalize_results)
Definition: jsonfuncs.c:1002
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:330
#define NULL
Definition: c.h:229
Definition: c.h:439
#define PG_RETURN_NULL()
Definition: fmgr.h:305
Datum json_array_elements ( PG_FUNCTION_ARGS  )

Definition at line 2099 of file jsonfuncs.c.

References elements_worker().

2100 {
2101  return elements_worker(fcinfo, "json_array_elements", false);
2102 }
static Datum elements_worker(FunctionCallInfo fcinfo, const char *funcname, bool as_text)
Definition: jsonfuncs.c:2111
Datum json_array_elements_text ( PG_FUNCTION_ARGS  )

Definition at line 2105 of file jsonfuncs.c.

References elements_worker().

2106 {
2107  return elements_worker(fcinfo, "json_array_elements_text", true);
2108 }
static Datum elements_worker(FunctionCallInfo fcinfo, const char *funcname, bool as_text)
Definition: jsonfuncs.c:2111
Datum json_array_length ( PG_FUNCTION_ARGS  )

Definition at line 1543 of file jsonfuncs.c.

References alen_array_element_start(), alen_object_start(), alen_scalar(), JsonSemAction::array_element_start, AlenState::count, AlenState::lex, makeJsonLexContext(), JsonSemAction::object_start, palloc0(), PG_GETARG_TEXT_PP, pg_parse_json(), PG_RETURN_INT32, JsonSemAction::scalar, and JsonSemAction::semstate.

1544 {
1545  text *json = PG_GETARG_TEXT_PP(0);
1546  AlenState *state;
1547  JsonLexContext *lex;
1548  JsonSemAction *sem;
1549 
1550  lex = makeJsonLexContext(json, false);
1551  state = palloc0(sizeof(AlenState));
1552  sem = palloc0(sizeof(JsonSemAction));
1553 
1554  /* palloc0 does this for us */
1555 #if 0
1556  state->count = 0;
1557 #endif
1558  state->lex = lex;
1559 
1560  sem->semstate = (void *) state;
1562  sem->scalar = alen_scalar;
1564 
1565  pg_parse_json(lex, sem);
1566 
1567  PG_RETURN_INT32(state->count);
1568 }
json_struct_action object_start
Definition: jsonapi.h:85
#define PG_RETURN_INT32(x)
Definition: fmgr.h:314
json_scalar_action scalar
Definition: jsonapi.h:93
int count
Definition: jsonfuncs.c:94
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:273
static void alen_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:1605
JsonLexContext * makeJsonLexContext(text *json, bool need_escapes)
Definition: json.c:300
void pg_parse_json(JsonLexContext *lex, JsonSemAction *sem)
Definition: json.c:331
JsonLexContext * lex
Definition: jsonfuncs.c:93
void * palloc0(Size size)
Definition: mcxt.c:878
json_aelem_action array_element_start
Definition: jsonapi.h:91
Definition: regguts.h:298
static void alen_object_start(void *state)
Definition: jsonfuncs.c:1593
Definition: c.h:439
static void alen_array_element_start(void *state, bool isnull)
Definition: jsonfuncs.c:1617
void * semstate
Definition: jsonapi.h:84
Datum json_each ( PG_FUNCTION_ARGS  )

Definition at line 1637 of file jsonfuncs.c.

References each_worker().

1638 {
1639  return each_worker(fcinfo, false);
1640 }
static Datum each_worker(FunctionCallInfo fcinfo, bool as_text)
Definition: jsonfuncs.c:1797
Datum json_each_text ( PG_FUNCTION_ARGS  )

Definition at line 1649 of file jsonfuncs.c.

References each_worker().

1650 {
1651  return each_worker(fcinfo, true);
1652 }
static Datum each_worker(FunctionCallInfo fcinfo, bool as_text)
Definition: jsonfuncs.c:1797
Datum json_extract_path ( PG_FUNCTION_ARGS  )

Definition at line 907 of file jsonfuncs.c.

References get_path_all().

908 {
909  return get_path_all(fcinfo, false);
910 }
static Datum get_path_all(FunctionCallInfo fcinfo, bool as_text)
Definition: jsonfuncs.c:922
Datum json_extract_path_text ( PG_FUNCTION_ARGS  )

Definition at line 913 of file jsonfuncs.c.

References get_path_all().

914 {
915  return get_path_all(fcinfo, true);
916 }
static Datum get_path_all(FunctionCallInfo fcinfo, bool as_text)
Definition: jsonfuncs.c:922
Datum json_object_field ( PG_FUNCTION_ARGS  )

Definition at line 687 of file jsonfuncs.c.

References get_worker(), NULL, PG_GETARG_TEXT_PP, PG_RETURN_NULL, PG_RETURN_TEXT_P, result, and text_to_cstring().

688 {
689  text *json = PG_GETARG_TEXT_PP(0);
690  text *fname = PG_GETARG_TEXT_PP(1);
691  char *fnamestr = text_to_cstring(fname);
692  text *result;
693 
694  result = get_worker(json, &fnamestr, NULL, 1, false);
695 
696  if (result != NULL)
697  PG_RETURN_TEXT_P(result);
698  else
699  PG_RETURN_NULL();
700 }
return result
Definition: formatting.c:1632
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:273
static text * get_worker(text *json, char **tpath, int *ipath, int npath, bool normalize_results)
Definition: jsonfuncs.c:1002
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:330
#define NULL
Definition: c.h:229
char * text_to_cstring(const text *t)
Definition: varlena.c:182
Definition: c.h:439
#define PG_RETURN_NULL()
Definition: fmgr.h:305
Datum json_object_field_text ( PG_FUNCTION_ARGS  )

Definition at line 723 of file jsonfuncs.c.

References get_worker(), NULL, PG_GETARG_TEXT_PP, PG_RETURN_NULL, PG_RETURN_TEXT_P, result, and text_to_cstring().

724 {
725  text *json = PG_GETARG_TEXT_PP(0);
726  text *fname = PG_GETARG_TEXT_PP(1);
727  char *fnamestr = text_to_cstring(fname);
728  text *result;
729 
730  result = get_worker(json, &fnamestr, NULL, 1, true);
731 
732  if (result != NULL)
733  PG_RETURN_TEXT_P(result);
734  else
735  PG_RETURN_NULL();
736 }
return result
Definition: formatting.c:1632
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:273
static text * get_worker(text *json, char **tpath, int *ipath, int npath, bool normalize_results)
Definition: jsonfuncs.c:1002
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:330
#define NULL
Definition: c.h:229
char * text_to_cstring(const text *t)
Definition: varlena.c:182
Definition: c.h:439
#define PG_RETURN_NULL()
Definition: fmgr.h:305
Datum json_object_keys ( PG_FUNCTION_ARGS  )

Definition at line 570 of file jsonfuncs.c.

References JsonSemAction::array_start, CStringGetTextDatum, StringInfoData::data, i, OkeysState::lex, 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(), OkeysState::result, OkeysState::result_count, OkeysState::result_size, JsonSemAction::scalar, JsonSemAction::semstate, OkeysState::sent_count, SRF_FIRSTCALL_INIT, SRF_IS_FIRSTCALL, SRF_PERCALL_SETUP, SRF_RETURN_DONE, SRF_RETURN_NEXT, JsonLexContext::strval, and FuncCallContext::user_fctx.

571 {
572  FuncCallContext *funcctx;
573  OkeysState *state;
574  int i;
575 
576  if (SRF_IS_FIRSTCALL())
577  {
578  text *json = PG_GETARG_TEXT_PP(0);
579  JsonLexContext *lex = makeJsonLexContext(json, true);
580  JsonSemAction *sem;
581  MemoryContext oldcontext;
582 
583  funcctx = SRF_FIRSTCALL_INIT();
584  oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
585 
586  state = palloc(sizeof(OkeysState));
587  sem = palloc0(sizeof(JsonSemAction));
588 
589  state->lex = lex;
590  state->result_size = 256;
591  state->result_count = 0;
592  state->sent_count = 0;
593  state->result = palloc(256 * sizeof(char *));
594 
595  sem->semstate = (void *) state;
597  sem->scalar = okeys_scalar;
599  /* remainder are all NULL, courtesy of palloc0 above */
600 
601  pg_parse_json(lex, sem);
602  /* keys are now in state->result */
603 
604  pfree(lex->strval->data);
605  pfree(lex->strval);
606  pfree(lex);
607  pfree(sem);
608 
609  MemoryContextSwitchTo(oldcontext);
610  funcctx->user_fctx = (void *) state;
611  }
612 
613  funcctx = SRF_PERCALL_SETUP();
614  state = (OkeysState *) funcctx->user_fctx;
615 
616  if (state->sent_count < state->result_count)
617  {
618  char *nxt = state->result[state->sent_count++];
619 
620  SRF_RETURN_NEXT(funcctx, CStringGetTextDatum(nxt));
621  }
622 
623  /* cleanup to reduce or eliminate memory leaks */
624  for (i = 0; i < state->result_count; i++)
625  pfree(state->result[i]);
626  pfree(state->result);
627  pfree(state);
628 
629  SRF_RETURN_DONE(funcctx);
630 }
int result_count
Definition: jsonfuncs.c:52
#define SRF_IS_FIRSTCALL()
Definition: funcapi.h:285
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
static void okeys_array_start(void *state)
Definition: jsonfuncs.c:654
json_scalar_action scalar
Definition: jsonapi.h:93
int sent_count
Definition: jsonfuncs.c:53
#define SRF_PERCALL_SETUP()
Definition: funcapi.h:289
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:273
#define SRF_RETURN_NEXT(_funcctx, _result)
Definition: funcapi.h:291
JsonLexContext * makeJsonLexContext(text *json, bool need_escapes)
Definition: json.c:300
void pfree(void *pointer)
Definition: mcxt.c:950
void pg_parse_json(JsonLexContext *lex, JsonSemAction *sem)
Definition: json.c:331
StringInfo strval
Definition: jsonapi.h:62
static void okeys_object_field_start(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:633
char ** result
Definition: jsonfuncs.c:50
void * palloc0(Size size)
Definition: mcxt.c:878
JsonLexContext * lex
Definition: jsonfuncs.c:49
json_struct_action array_start
Definition: jsonapi.h:87
Definition: regguts.h:298
MemoryContext multi_call_memory_ctx
Definition: funcapi.h:109
static void okeys_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:667
int result_size
Definition: jsonfuncs.c:51
void * user_fctx
Definition: funcapi.h:90
void * palloc(Size size)
Definition: mcxt.c:849
int i
#define CStringGetTextDatum(s)
Definition: builtins.h:91
Definition: c.h:439
json_ofield_action object_field_start
Definition: jsonapi.h:89
void * semstate
Definition: jsonapi.h:84
#define SRF_RETURN_DONE(_funcctx)
Definition: funcapi.h:309
#define SRF_FIRSTCALL_INIT()
Definition: funcapi.h:287
Datum json_populate_record ( PG_FUNCTION_ARGS  )

Definition at line 2295 of file jsonfuncs.c.

References populate_record_worker().

2296 {
2297  return populate_record_worker(fcinfo, "json_populate_record", true);
2298 }
static Datum populate_record_worker(FunctionCallInfo fcinfo, const char *funcname, bool have_record_arg)
Definition: jsonfuncs.c:3118
Datum json_populate_recordset ( PG_FUNCTION_ARGS  )

Definition at line 3411 of file jsonfuncs.c.

References populate_recordset_worker().

3412 {
3413  return populate_recordset_worker(fcinfo, "json_populate_recordset", true);
3414 }
static Datum populate_recordset_worker(FunctionCallInfo fcinfo, const char *funcname, bool have_record_arg)
Definition: jsonfuncs.c:3444
Datum json_strip_nulls ( PG_FUNCTION_ARGS  )

Definition at line 3854 of file jsonfuncs.c.

References JsonSemAction::array_element_start, JsonSemAction::array_end, JsonSemAction::array_start, cstring_to_text_with_len(), StringInfoData::data, StringInfoData::len, StripnullState::lex, makeJsonLexContext(), makeStringInfo(), JsonSemAction::object_end, JsonSemAction::object_field_start, JsonSemAction::object_start, palloc0(), PG_GETARG_TEXT_PP, pg_parse_json(), PG_RETURN_TEXT_P, JsonSemAction::scalar, JsonSemAction::semstate, StripnullState::skip_next_null, sn_array_element_start(), sn_array_end(), sn_array_start(), sn_object_end(), sn_object_field_start(), sn_object_start(), sn_scalar(), and StripnullState::strval.

3855 {
3856  text *json = PG_GETARG_TEXT_PP(0);
3858  JsonLexContext *lex;
3859  JsonSemAction *sem;
3860 
3861  lex = makeJsonLexContext(json, true);
3862  state = palloc0(sizeof(StripnullState));
3863  sem = palloc0(sizeof(JsonSemAction));
3864 
3865  state->strval = makeStringInfo();
3866  state->skip_next_null = false;
3867  state->lex = lex;
3868 
3869  sem->semstate = (void *) state;
3871  sem->object_end = sn_object_end;
3872  sem->array_start = sn_array_start;
3873  sem->array_end = sn_array_end;
3874  sem->scalar = sn_scalar;
3877 
3878  pg_parse_json(lex, sem);
3879 
3881  state->strval->len));
3882 
3883 }
json_struct_action array_end
Definition: jsonapi.h:88
bool skip_next_null
Definition: jsonfuncs.c:271
static void sn_object_start(void *state)
Definition: jsonfuncs.c:3764
json_struct_action object_end
Definition: jsonapi.h:86
static void sn_array_element_start(void *state, bool isnull)
Definition: jsonfuncs.c:3824
static void sn_object_field_start(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:3796
StringInfo makeStringInfo(void)
Definition: stringinfo.c:28
json_struct_action object_start
Definition: jsonapi.h:85
json_scalar_action scalar
Definition: jsonapi.h:93
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:273
JsonLexContext * makeJsonLexContext(text *json, bool need_escapes)
Definition: json.c:300
static void sn_array_start(void *state)
Definition: jsonfuncs.c:3780
void pg_parse_json(JsonLexContext *lex, JsonSemAction *sem)
Definition: json.c:331
text * cstring_to_text_with_len(const char *s, int len)
Definition: varlena.c:161
JsonLexContext * lex
Definition: jsonfuncs.c:269
static void sn_object_end(void *state)
Definition: jsonfuncs.c:3772
void * palloc0(Size size)
Definition: mcxt.c:878
json_aelem_action array_element_start
Definition: jsonapi.h:91
static void sn_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:3833
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:330
json_struct_action array_start
Definition: jsonapi.h:87
Definition: regguts.h:298
StringInfo strval
Definition: jsonfuncs.c:270
Definition: c.h:439
json_ofield_action object_field_start
Definition: jsonapi.h:89
static void sn_array_end(void *state)
Definition: jsonfuncs.c:3788
void * semstate
Definition: jsonapi.h:84
Datum json_to_record ( PG_FUNCTION_ARGS  )

Definition at line 2301 of file jsonfuncs.c.

References populate_record_worker().

2302 {
2303  return populate_record_worker(fcinfo, "json_to_record", false);
2304 }
static Datum populate_record_worker(FunctionCallInfo fcinfo, const char *funcname, bool have_record_arg)
Definition: jsonfuncs.c:3118
Datum json_to_recordset ( PG_FUNCTION_ARGS  )

Definition at line 3417 of file jsonfuncs.c.

References populate_recordset_worker().

3418 {
3419  return populate_recordset_worker(fcinfo, "json_to_recordset", false);
3420 }
static Datum populate_recordset_worker(FunctionCallInfo fcinfo, const char *funcname, bool have_record_arg)
Definition: jsonfuncs.c:3444
Datum jsonb_array_element ( PG_FUNCTION_ARGS  )

Definition at line 805 of file jsonfuncs.c.

References element(), getIthJsonbValueFromContainer(), JB_ROOT_COUNT, JB_ROOT_IS_ARRAY, JsonbValueToJsonb(), NULL, PG_GETARG_INT32, PG_GETARG_JSONB, PG_RETURN_JSONB, PG_RETURN_NULL, and Jsonb::root.

806 {
807  Jsonb *jb = PG_GETARG_JSONB(0);
808  int element = PG_GETARG_INT32(1);
809  JsonbValue *v;
810 
811  if (!JB_ROOT_IS_ARRAY(jb))
812  PG_RETURN_NULL();
813 
814  /* Handle negative subscript */
815  if (element < 0)
816  {
817  uint32 nelements = JB_ROOT_COUNT(jb);
818 
819  if (-element > nelements)
820  PG_RETURN_NULL();
821  else
822  element += nelements;
823  }
824 
825  v = getIthJsonbValueFromContainer(&jb->root, element);
826  if (v != NULL)
828 
829  PG_RETURN_NULL();
830 }
#define PG_GETARG_INT32(n)
Definition: fmgr.h:234
Jsonb * JsonbValueToJsonb(JsonbValue *val)
Definition: jsonb_util.c:79
Definition: jsonb.h:215
#define JB_ROOT_COUNT(jbp_)
Definition: jsonb.h:222
#define PG_RETURN_JSONB(x)
Definition: jsonb.h:71
#define JB_ROOT_IS_ARRAY(jbp_)
Definition: jsonb.h:225
unsigned int uint32
Definition: c.h:268
static chr element(struct vars *v, const chr *startp, const chr *endp)
Definition: regc_locale.c:380
JsonbContainer root
Definition: jsonb.h:218
JsonbValue * getIthJsonbValueFromContainer(JsonbContainer *container, uint32 i)
Definition: jsonb_util.c:419
#define NULL
Definition: c.h:229
#define PG_GETARG_JSONB(x)
Definition: jsonb.h:70
#define PG_RETURN_NULL()
Definition: fmgr.h:305
Datum jsonb_array_element_text ( PG_FUNCTION_ARGS  )

Definition at line 848 of file jsonfuncs.c.

References cstring_to_text(), cstring_to_text_with_len(), StringInfoData::data, DatumGetCString, DirectFunctionCall1, element(), elog, ERROR, getIthJsonbValueFromContainer(), JB_ROOT_COUNT, JB_ROOT_IS_ARRAY, jbvBinary, jbvBool, jbvNull, jbvNumeric, jbvString, JsonbToCString(), StringInfoData::len, makeStringInfo(), NULL, numeric_out(), PG_GETARG_INT32, PG_GETARG_JSONB, PG_RETURN_NULL, PG_RETURN_TEXT_P, PointerGetDatum, result, Jsonb::root, JsonbValue::type, and JsonbValue::val.

849 {
850  Jsonb *jb = PG_GETARG_JSONB(0);
851  int element = PG_GETARG_INT32(1);
852  JsonbValue *v;
853 
854  if (!JB_ROOT_IS_ARRAY(jb))
855  PG_RETURN_NULL();
856 
857  /* Handle negative subscript */
858  if (element < 0)
859  {
860  uint32 nelements = JB_ROOT_COUNT(jb);
861 
862  if (-element > nelements)
863  PG_RETURN_NULL();
864  else
865  element += nelements;
866  }
867 
868  v = getIthJsonbValueFromContainer(&jb->root, element);
869  if (v != NULL)
870  {
871  text *result = NULL;
872 
873  switch (v->type)
874  {
875  case jbvNull:
876  break;
877  case jbvBool:
878  result = cstring_to_text(v->val.boolean ? "true" : "false");
879  break;
880  case jbvString:
881  result = cstring_to_text_with_len(v->val.string.val, v->val.string.len);
882  break;
883  case jbvNumeric:
885  PointerGetDatum(v->val.numeric))));
886  break;
887  case jbvBinary:
888  {
889  StringInfo jtext = makeStringInfo();
890 
891  (void) JsonbToCString(jtext, v->val.binary.data, -1);
892  result = cstring_to_text_with_len(jtext->data, jtext->len);
893  }
894  break;
895  default:
896  elog(ERROR, "unrecognized jsonb type: %d", (int) v->type);
897  }
898 
899  if (result)
900  PG_RETURN_TEXT_P(result);
901  }
902 
903  PG_RETURN_NULL();
904 }
#define PG_GETARG_INT32(n)
Definition: fmgr.h:234
Definition: jsonb.h:215
#define PointerGetDatum(X)
Definition: postgres.h:562
char * val
Definition: jsonb.h:259
Definition: jsonb.h:234
StringInfo makeStringInfo(void)
Definition: stringinfo.c:28
Datum numeric_out(PG_FUNCTION_ARGS)
Definition: numeric.c:641
#define JB_ROOT_COUNT(jbp_)
Definition: jsonb.h:222
return result
Definition: formatting.c:1632
Definition: jsonb.h:231
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:584
#define ERROR
Definition: elog.h:43
#define DatumGetCString(X)
Definition: postgres.h:572
#define JB_ROOT_IS_ARRAY(jbp_)
Definition: jsonb.h:225
text * cstring_to_text_with_len(const char *s, int len)
Definition: varlena.c:161
unsigned int uint32
Definition: c.h:268
static chr element(struct vars *v, const chr *startp, const chr *endp)
Definition: regc_locale.c:380
JsonbContainer root
Definition: jsonb.h:218
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:330
text * cstring_to_text(const char *s)
Definition: varlena.c:149
JsonbValue * getIthJsonbValueFromContainer(JsonbContainer *container, uint32 i)
Definition: jsonb_util.c:419
#define NULL
Definition: c.h:229
char * JsonbToCString(StringInfo out, JsonbContainer *in, int estimated_len)
Definition: jsonb.c:428
enum jbvType type
Definition: jsonb.h:250
#define PG_GETARG_JSONB(x)
Definition: jsonb.h:70
Definition: c.h:439
#define elog
Definition: elog.h:219
#define PG_RETURN_NULL()
Definition: fmgr.h:305
Datum jsonb_array_elements ( PG_FUNCTION_ARGS  )

Definition at line 1963 of file jsonfuncs.c.

References elements_worker_jsonb().

1964 {
1965  return elements_worker_jsonb(fcinfo, "jsonb_array_elements", false);
1966 }
static Datum elements_worker_jsonb(FunctionCallInfo fcinfo, const char *funcname, bool as_text)
Definition: jsonfuncs.c:1975
Datum jsonb_array_elements_text ( PG_FUNCTION_ARGS  )

Definition at line 1969 of file jsonfuncs.c.

References elements_worker_jsonb().

1970 {
1971  return elements_worker_jsonb(fcinfo, "jsonb_array_elements_text", true);
1972 }
static Datum elements_worker_jsonb(FunctionCallInfo fcinfo, const char *funcname, bool as_text)
Definition: jsonfuncs.c:1975
Datum jsonb_array_length ( PG_FUNCTION_ARGS  )

Definition at line 1571 of file jsonfuncs.c.

References ereport, errcode(), errmsg(), ERROR, JB_ROOT_COUNT, JB_ROOT_IS_ARRAY, JB_ROOT_IS_SCALAR, PG_GETARG_JSONB, and PG_RETURN_INT32.

1572 {
1573  Jsonb *jb = PG_GETARG_JSONB(0);
1574 
1575  if (JB_ROOT_IS_SCALAR(jb))
1576  ereport(ERROR,
1577  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1578  errmsg("cannot get array length of a scalar")));
1579  else if (!JB_ROOT_IS_ARRAY(jb))
1580  ereport(ERROR,
1581  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1582  errmsg("cannot get array length of a non-array")));
1583 
1585 }
Definition: jsonb.h:215
#define PG_RETURN_INT32(x)
Definition: fmgr.h:314
#define JB_ROOT_COUNT(jbp_)
Definition: jsonb.h:222
int errcode(int sqlerrcode)
Definition: elog.c:575
#define JB_ROOT_IS_SCALAR(jbp_)
Definition: jsonb.h:223
#define ERROR
Definition: elog.h:43
#define JB_ROOT_IS_ARRAY(jbp_)
Definition: jsonb.h:225
#define ereport(elevel, rest)
Definition: elog.h:122
#define PG_GETARG_JSONB(x)
Definition: jsonb.h:70
int errmsg(const char *fmt,...)
Definition: elog.c:797
Datum jsonb_concat ( PG_FUNCTION_ARGS  )

Definition at line 4014 of file jsonfuncs.c.

References Assert, IteratorConcat(), JB_ROOT_COUNT, JB_ROOT_IS_OBJECT, JB_ROOT_IS_SCALAR, JsonbIteratorInit(), JsonbValueToJsonb(), NULL, PG_GETARG_JSONB, PG_RETURN_JSONB, and Jsonb::root.

4015 {
4016  Jsonb *jb1 = PG_GETARG_JSONB(0);
4017  Jsonb *jb2 = PG_GETARG_JSONB(1);
4019  JsonbValue *res;
4020  JsonbIterator *it1,
4021  *it2;
4022 
4023  /*
4024  * If one of the jsonb is empty, just return the other if it's not scalar
4025  * and both are of the same kind. If it's a scalar or they are of
4026  * different kinds we need to perform the concatenation even if one is
4027  * empty.
4028  */
4029  if (JB_ROOT_IS_OBJECT(jb1) == JB_ROOT_IS_OBJECT(jb2))
4030  {
4031  if (JB_ROOT_COUNT(jb1) == 0 && !JB_ROOT_IS_SCALAR(jb2))
4032  PG_RETURN_JSONB(jb2);
4033  else if (JB_ROOT_COUNT(jb2) == 0 && !JB_ROOT_IS_SCALAR(jb1))
4034  PG_RETURN_JSONB(jb1);
4035  }
4036 
4037  it1 = JsonbIteratorInit(&jb1->root);
4038  it2 = JsonbIteratorInit(&jb2->root);
4039 
4040  res = IteratorConcat(&it1, &it2, &state);
4041 
4042  Assert(res != NULL);
4043 
4045 }
#define JB_ROOT_IS_OBJECT(jbp_)
Definition: jsonb.h:224
Jsonb * JsonbValueToJsonb(JsonbValue *val)
Definition: jsonb_util.c:79
Definition: jsonb.h:215
#define JB_ROOT_COUNT(jbp_)
Definition: jsonb.h:222
#define JB_ROOT_IS_SCALAR(jbp_)
Definition: jsonb.h:223
#define PG_RETURN_JSONB(x)
Definition: jsonb.h:71
JsonbContainer root
Definition: jsonb.h:218
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
JsonbIterator * JsonbIteratorInit(JsonbContainer *container)
Definition: jsonb_util.c:718
Definition: regguts.h:298
#define PG_GETARG_JSONB(x)
Definition: jsonb.h:70
static JsonbValue * IteratorConcat(JsonbIterator **it1, JsonbIterator **it2, JsonbParseState **state)
Definition: jsonfuncs.c:4399
Datum jsonb_delete ( PG_FUNCTION_ARGS  )

Definition at line 4055 of file jsonfuncs.c.

References Assert, ereport, errcode(), errmsg(), ERROR, JB_ROOT_COUNT, JB_ROOT_IS_SCALAR, jbvString, JsonbIteratorInit(), JsonbIteratorNext(), JsonbValueToJsonb(), NULL, PG_GETARG_JSONB, PG_GETARG_TEXT_PP, PG_RETURN_JSONB, pushJsonbValue(), Jsonb::root, JsonbValue::type, JsonbValue::val, VARDATA_ANY, VARSIZE_ANY_EXHDR, WJB_BEGIN_ARRAY, WJB_ELEM, and WJB_KEY.

4056 {
4057  Jsonb *in = PG_GETARG_JSONB(0);
4058  text *key = PG_GETARG_TEXT_PP(1);
4059  char *keyptr = VARDATA_ANY(key);
4060  int keylen = VARSIZE_ANY_EXHDR(key);
4062  JsonbIterator *it;
4063  JsonbValue v,
4064  *res = NULL;
4065  bool skipNested = false;
4067 
4068  if (JB_ROOT_IS_SCALAR(in))
4069  ereport(ERROR,
4070  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4071  errmsg("cannot delete from scalar")));
4072 
4073  if (JB_ROOT_COUNT(in) == 0)
4074  PG_RETURN_JSONB(in);
4075 
4076  it = JsonbIteratorInit(&in->root);
4077 
4078  while ((r = JsonbIteratorNext(&it, &v, skipNested)) != 0)
4079  {
4080  skipNested = true;
4081 
4082  if ((r == WJB_ELEM || r == WJB_KEY) &&
4083  (v.type == jbvString && keylen == v.val.string.len &&
4084  memcmp(keyptr, v.val.string.val, keylen) == 0))
4085  {
4086  /* skip corresponding value as well */
4087  if (r == WJB_KEY)
4088  JsonbIteratorNext(&it, &v, true);
4089 
4090  continue;
4091  }
4092 
4093  res = pushJsonbValue(&state, r, r < WJB_BEGIN_ARRAY ? &v : NULL);
4094  }
4095 
4096  Assert(res != NULL);
4097 
4099 }
#define VARDATA_ANY(PTR)
Definition: postgres.h:347
Jsonb * JsonbValueToJsonb(JsonbValue *val)
Definition: jsonb_util.c:79
Definition: jsonb.h:215
char * val
Definition: jsonb.h:259
#define JB_ROOT_COUNT(jbp_)
Definition: jsonb.h:222
int errcode(int sqlerrcode)
Definition: elog.c:575
#define JB_ROOT_IS_SCALAR(jbp_)
Definition: jsonb.h:223
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:273
JsonbValue * pushJsonbValue(JsonbParseState **pstate, JsonbIteratorToken seq, JsonbValue *jbval)
Definition: jsonb_util.c:517
#define ERROR
Definition: elog.h:43
#define PG_RETURN_JSONB(x)
Definition: jsonb.h:71
Definition: jsonb.h:23
#define ereport(elevel, rest)
Definition: elog.h:122
JsonbIteratorToken
Definition: jsonb.h:20
JsonbContainer root
Definition: jsonb.h:218
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
JsonbIterator * JsonbIteratorInit(JsonbContainer *container)
Definition: jsonb_util.c:718
Definition: regguts.h:298
enum jbvType type
Definition: jsonb.h:250
#define PG_GETARG_JSONB(x)
Definition: jsonb.h:70
#define VARSIZE_ANY_EXHDR(PTR)
Definition: postgres.h:340
int errmsg(const char *fmt,...)
Definition: elog.c:797
Definition: c.h:439
JsonbIteratorToken JsonbIteratorNext(JsonbIterator **it, JsonbValue *val, bool skipNested)
Definition: jsonb_util.c:754
Definition: jsonb.h:25
Datum jsonb_delete_array ( PG_FUNCTION_ARGS  )

Definition at line 4108 of file jsonfuncs.c.

References ARR_NDIM, Assert, deconstruct_array(), ereport, errcode(), errmsg(), ERROR, i, JB_ROOT_COUNT, JB_ROOT_IS_SCALAR, jbvString, JsonbIteratorInit(), JsonbIteratorNext(), JsonbValueToJsonb(), NULL, PG_GETARG_ARRAYTYPE_P, PG_GETARG_JSONB, PG_RETURN_JSONB, pushJsonbValue(), Jsonb::root, TEXTOID, JsonbValue::type, JsonbValue::val, VARDATA_ANY, VARSIZE_ANY_EXHDR, WJB_BEGIN_ARRAY, WJB_ELEM, and WJB_KEY.

4109 {
4110  Jsonb *in = PG_GETARG_JSONB(0);
4111  ArrayType *keys = PG_GETARG_ARRAYTYPE_P(1);
4112  Datum *keys_elems;
4113  bool *keys_nulls;
4114  int keys_len;
4116  JsonbIterator *it;
4117  JsonbValue v,
4118  *res = NULL;
4119  bool skipNested = false;
4121 
4122  if (ARR_NDIM(keys) > 1)
4123  ereport(ERROR,
4124  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
4125  errmsg("wrong number of array subscripts")));
4126 
4127  if (JB_ROOT_IS_SCALAR(in))
4128  ereport(ERROR,
4129  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4130  errmsg("cannot delete from scalar")));
4131 
4132  if (JB_ROOT_COUNT(in) == 0)
4133  PG_RETURN_JSONB(in);
4134 
4135  deconstruct_array(keys, TEXTOID, -1, false, 'i',
4136  &keys_elems, &keys_nulls, &keys_len);
4137 
4138  if (keys_len == 0)
4139  PG_RETURN_JSONB(in);
4140 
4141  it = JsonbIteratorInit(&in->root);
4142 
4143  while ((r = JsonbIteratorNext(&it, &v, skipNested)) != 0)
4144  {
4145  skipNested = true;
4146 
4147  if ((r == WJB_ELEM || r == WJB_KEY) && v.type == jbvString)
4148  {
4149  int i;
4150  bool found = false;
4151 
4152  for (i = 0; i < keys_len; i++)
4153  {
4154  char *keyptr;
4155  int keylen;
4156 
4157  if (keys_nulls[i])
4158  continue;
4159 
4160  keyptr = VARDATA_ANY(keys_elems[i]);
4161  keylen = VARSIZE_ANY_EXHDR(keys_elems[i]);
4162  if (keylen == v.val.string.len &&
4163  memcmp(keyptr, v.val.string.val, keylen) == 0)
4164  {
4165  found = true;
4166  break;
4167  }
4168  }
4169  if (found)
4170  {
4171  /* skip corresponding value as well */
4172  if (r == WJB_KEY)
4173  JsonbIteratorNext(&it, &v, true);
4174 
4175  continue;
4176  }
4177  }
4178 
4179  res = pushJsonbValue(&state, r, r < WJB_BEGIN_ARRAY ? &v : NULL);
4180  }
4181 
4182  Assert(res != NULL);
4183 
4185 }
#define VARDATA_ANY(PTR)
Definition: postgres.h:347
Jsonb * JsonbValueToJsonb(JsonbValue *val)
Definition: jsonb_util.c:79
Definition: jsonb.h:215
#define TEXTOID
Definition: pg_type.h:324
char * val
Definition: jsonb.h:259
#define JB_ROOT_COUNT(jbp_)
Definition: jsonb.h:222
int errcode(int sqlerrcode)
Definition: elog.c:575
#define JB_ROOT_IS_SCALAR(jbp_)
Definition: jsonb.h:223
JsonbValue * pushJsonbValue(JsonbParseState **pstate, JsonbIteratorToken seq, JsonbValue *jbval)
Definition: jsonb_util.c:517
#define PG_GETARG_ARRAYTYPE_P(n)
Definition: array.h:244
#define ERROR
Definition: elog.h:43
#define PG_RETURN_JSONB(x)
Definition: jsonb.h:71
Definition: jsonb.h:23
#define ereport(elevel, rest)
Definition: elog.h:122
JsonbIteratorToken
Definition: jsonb.h:20
JsonbContainer root
Definition: jsonb.h:218
uintptr_t Datum
Definition: postgres.h:372
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
JsonbIterator * JsonbIteratorInit(JsonbContainer *container)
Definition: jsonb_util.c:718
Definition: regguts.h:298
#define ARR_NDIM(a)
Definition: array.h:271
enum jbvType type
Definition: jsonb.h:250
void deconstruct_array(ArrayType *array, Oid elmtype, int elmlen, bool elmbyval, char elmalign, Datum **elemsp, bool **nullsp, int *nelemsp)
Definition: arrayfuncs.c:3475
#define PG_GETARG_JSONB(x)
Definition: jsonb.h:70
#define VARSIZE_ANY_EXHDR(PTR)
Definition: postgres.h:340
int errmsg(const char *fmt,...)
Definition: elog.c:797
int i
JsonbIteratorToken JsonbIteratorNext(JsonbIterator **it, JsonbValue *val, bool skipNested)
Definition: jsonb_util.c:754
Definition: jsonb.h:25
Datum jsonb_delete_idx ( PG_FUNCTION_ARGS  )

Definition at line 4195 of file jsonfuncs.c.

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

4196 {
4197  Jsonb *in = PG_GETARG_JSONB(0);
4198  int idx = PG_GETARG_INT32(1);
4200  JsonbIterator *it;
4201  uint32 i = 0,
4202  n;
4203  JsonbValue v,
4204  *res = NULL;
4206 
4207  if (JB_ROOT_IS_SCALAR(in))
4208  ereport(ERROR,
4209  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4210  errmsg("cannot delete from scalar")));
4211 
4212  if (JB_ROOT_IS_OBJECT(in))
4213  ereport(ERROR,
4214  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4215  errmsg("cannot delete from object using integer index")));
4216 
4217  if (JB_ROOT_COUNT(in) == 0)
4218  PG_RETURN_JSONB(in);
4219 
4220  it = JsonbIteratorInit(&in->root);
4221 
4222  r = JsonbIteratorNext(&it, &v, false);
4223  Assert(r == WJB_BEGIN_ARRAY);
4224  n = v.val.array.nElems;
4225 
4226  if (idx < 0)
4227  {
4228  if (-idx > n)
4229  idx = n;
4230  else
4231  idx = n + idx;
4232  }
4233 
4234  if (idx >= n)
4235  PG_RETURN_JSONB(in);
4236 
4237  pushJsonbValue(&state, r, NULL);
4238 
4239  while ((r = JsonbIteratorNext(&it, &v, true)) != 0)
4240  {
4241  if (r == WJB_ELEM)
4242  {
4243  if (i++ == idx)
4244  continue;
4245  }
4246 
4247  res = pushJsonbValue(&state, r, r < WJB_BEGIN_ARRAY ? &v : NULL);
4248  }
4249 
4250  Assert(res != NULL);
4251 
4253 }
#define PG_GETARG_INT32(n)
Definition: fmgr.h:234
#define JB_ROOT_IS_OBJECT(jbp_)
Definition: jsonb.h:224
Jsonb * JsonbValueToJsonb(JsonbValue *val)
Definition: jsonb_util.c:79
Definition: jsonb.h:215
char * val
Definition: jsonb.h:259
#define JB_ROOT_COUNT(jbp_)
Definition: jsonb.h:222
int errcode(int sqlerrcode)
Definition: elog.c:575
Datum idx(PG_FUNCTION_ARGS)
Definition: _int_op.c:264
#define JB_ROOT_IS_SCALAR(jbp_)
Definition: jsonb.h:223
JsonbValue * pushJsonbValue(JsonbParseState **pstate, JsonbIteratorToken seq, JsonbValue *jbval)
Definition: jsonb_util.c:517
#define ERROR
Definition: elog.h:43
#define PG_RETURN_JSONB(x)
Definition: jsonb.h:71
unsigned int uint32
Definition: c.h:268
#define ereport(elevel, rest)
Definition: elog.h:122
JsonbIteratorToken
Definition: jsonb.h:20
JsonbContainer root
Definition: jsonb.h:218
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
JsonbIterator * JsonbIteratorInit(JsonbContainer *container)
Definition: jsonb_util.c:718
Definition: regguts.h:298
#define PG_GETARG_JSONB(x)
Definition: jsonb.h:70
int errmsg(const char *fmt,...)
Definition: elog.c:797
int i
JsonbIteratorToken JsonbIteratorNext(JsonbIterator **it, JsonbValue *val, bool skipNested)
Definition: jsonb_util.c:754
Definition: jsonb.h:25
Datum jsonb_delete_path ( PG_FUNCTION_ARGS  )

Definition at line 4307 of file jsonfuncs.c.

References ARR_NDIM, Assert, deconstruct_array(), ereport, errcode(), errmsg(), ERROR, JB_PATH_DELETE, JB_ROOT_COUNT, JB_ROOT_IS_SCALAR, JsonbIteratorInit(), JsonbValueToJsonb(), NULL, PG_GETARG_ARRAYTYPE_P, PG_GETARG_JSONB, PG_RETURN_JSONB, Jsonb::root, setPath(), and TEXTOID.

4308 {
4309  Jsonb *in = PG_GETARG_JSONB(0);
4310  ArrayType *path = PG_GETARG_ARRAYTYPE_P(1);
4311  JsonbValue *res = NULL;
4312  Datum *path_elems;
4313  bool *path_nulls;
4314  int path_len;
4315  JsonbIterator *it;
4316  JsonbParseState *st = NULL;
4317 
4318  if (ARR_NDIM(path) > 1)
4319  ereport(ERROR,
4320  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
4321  errmsg("wrong number of array subscripts")));
4322 
4323  if (JB_ROOT_IS_SCALAR(in))
4324  ereport(ERROR,
4325  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4326  errmsg("cannot delete path in scalar")));
4327 
4328  if (JB_ROOT_COUNT(in) == 0)
4329  PG_RETURN_JSONB(in);
4330 
4331  deconstruct_array(path, TEXTOID, -1, false, 'i',
4332  &path_elems, &path_nulls, &path_len);
4333 
4334  if (path_len == 0)
4335  PG_RETURN_JSONB(in);
4336 
4337  it = JsonbIteratorInit(&in->root);
4338 
4339  res = setPath(&it, path_elems, path_nulls, path_len, &st,
4340  0, NULL, JB_PATH_DELETE);
4341 
4342  Assert(res != NULL);
4343 
4345 }
Jsonb * JsonbValueToJsonb(JsonbValue *val)
Definition: jsonb_util.c:79
Definition: jsonb.h:215
#define TEXTOID
Definition: pg_type.h:324
static JsonbValue * setPath(JsonbIterator **it, Datum *path_elems, bool *path_nulls, int path_len, JsonbParseState **st, int level, Jsonb *newval, int op_type)
Definition: jsonfuncs.c:4517
#define JB_ROOT_COUNT(jbp_)
Definition: jsonb.h:222
int errcode(int sqlerrcode)
Definition: elog.c:575
#define JB_ROOT_IS_SCALAR(jbp_)
Definition: jsonb.h:223
#define PG_GETARG_ARRAYTYPE_P(n)
Definition: array.h:244
#define ERROR
Definition: elog.h:43
#define PG_RETURN_JSONB(x)
Definition: jsonb.h:71
#define ereport(elevel, rest)
Definition: elog.h:122
JsonbContainer root
Definition: jsonb.h:218
uintptr_t Datum
Definition: postgres.h:372
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
JsonbIterator * JsonbIteratorInit(JsonbContainer *container)
Definition: jsonb_util.c:718
#define ARR_NDIM(a)
Definition: array.h:271
void deconstruct_array(ArrayType *array, Oid elmtype, int elmlen, bool elmbyval, char elmalign, Datum **elemsp, bool **nullsp, int *nelemsp)
Definition: arrayfuncs.c:3475
#define PG_GETARG_JSONB(x)
Definition: jsonb.h:70
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define JB_PATH_DELETE
Definition: jsonfuncs.c:39
Datum jsonb_each ( PG_FUNCTION_ARGS  )

Definition at line 1643 of file jsonfuncs.c.

References each_worker_jsonb().

1644 {
1645  return each_worker_jsonb(fcinfo, "jsonb_each", false);
1646 }
static Datum each_worker_jsonb(FunctionCallInfo fcinfo, const char *funcname, bool as_text)
Definition: jsonfuncs.c:1661
Datum jsonb_each_text ( PG_FUNCTION_ARGS  )

Definition at line 1655 of file jsonfuncs.c.

References each_worker_jsonb().

1656 {
1657  return each_worker_jsonb(fcinfo, "jsonb_each_text", true);
1658 }
static Datum each_worker_jsonb(FunctionCallInfo fcinfo, const char *funcname, bool as_text)
Definition: jsonfuncs.c:1661
Datum jsonb_extract_path ( PG_FUNCTION_ARGS  )

Definition at line 1363 of file jsonfuncs.c.

References get_jsonb_path_all().

1364 {
1365  return get_jsonb_path_all(fcinfo, false);
1366 }
static Datum get_jsonb_path_all(FunctionCallInfo fcinfo, bool as_text)
Definition: jsonfuncs.c:1375
Datum jsonb_extract_path_text ( PG_FUNCTION_ARGS  )

Definition at line 1369 of file jsonfuncs.c.

References get_jsonb_path_all().

1370 {
1371  return get_jsonb_path_all(fcinfo, true);
1372 }
static Datum get_jsonb_path_all(FunctionCallInfo fcinfo, bool as_text)
Definition: jsonfuncs.c:1375
Datum jsonb_insert ( PG_FUNCTION_ARGS  )

Definition at line 4352 of file jsonfuncs.c.

References ARR_NDIM, Assert, deconstruct_array(), ereport, errcode(), errmsg(), ERROR, JB_PATH_INSERT_AFTER, JB_PATH_INSERT_BEFORE, JB_ROOT_IS_SCALAR, JsonbIteratorInit(), JsonbValueToJsonb(), newval, NULL, PG_GETARG_ARRAYTYPE_P, PG_GETARG_BOOL, PG_GETARG_JSONB, PG_RETURN_JSONB, Jsonb::root, setPath(), and TEXTOID.

4353 {
4354  Jsonb *in = PG_GETARG_JSONB(0);
4355  ArrayType *path = PG_GETARG_ARRAYTYPE_P(1);
4357  bool after = PG_GETARG_BOOL(3);
4358  JsonbValue *res = NULL;
4359  Datum *path_elems;
4360  bool *path_nulls;
4361  int path_len;
4362  JsonbIterator *it;
4363  JsonbParseState *st = NULL;
4364 
4365  if (ARR_NDIM(path) > 1)
4366  ereport(ERROR,
4367  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
4368  errmsg("wrong number of array subscripts")));
4369 
4370  if (JB_ROOT_IS_SCALAR(in))
4371  ereport(ERROR,
4372  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4373  errmsg("cannot set path in scalar")));
4374 
4375  deconstruct_array(path, TEXTOID, -1, false, 'i',
4376  &path_elems, &path_nulls, &path_len);
4377 
4378  if (path_len == 0)
4379  PG_RETURN_JSONB(in);
4380 
4381  it = JsonbIteratorInit(&in->root);
4382 
4383  res = setPath(&it, path_elems, path_nulls, path_len, &st, 0, newval,
4385 
4386  Assert(res != NULL);
4387 
4389 }
Jsonb * JsonbValueToJsonb(JsonbValue *val)
Definition: jsonb_util.c:79
Definition: jsonb.h:215
#define TEXTOID
Definition: pg_type.h:324
static JsonbValue * setPath(JsonbIterator **it, Datum *path_elems, bool *path_nulls, int path_len, JsonbParseState **st, int level, Jsonb *newval, int op_type)
Definition: jsonfuncs.c:4517
int errcode(int sqlerrcode)
Definition: elog.c:575
#define PG_GETARG_BOOL(n)
Definition: fmgr.h:239
#define JB_PATH_INSERT_BEFORE
Definition: jsonfuncs.c:41
#define JB_ROOT_IS_SCALAR(jbp_)
Definition: jsonb.h:223
#define JB_PATH_INSERT_AFTER
Definition: jsonfuncs.c:42
#define PG_GETARG_ARRAYTYPE_P(n)
Definition: array.h:244
#define ERROR
Definition: elog.h:43
#define PG_RETURN_JSONB(x)
Definition: jsonb.h:71
#define ereport(elevel, rest)
Definition: elog.h:122
JsonbContainer root
Definition: jsonb.h:218
uintptr_t Datum
Definition: postgres.h:372
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
JsonbIterator * JsonbIteratorInit(JsonbContainer *container)
Definition: jsonb_util.c:718
#define newval
#define ARR_NDIM(a)
Definition: array.h:271
void deconstruct_array(ArrayType *array, Oid elmtype, int elmlen, bool elmbyval, char elmalign, Datum **elemsp, bool **nullsp, int *nelemsp)
Definition: arrayfuncs.c:3475
#define PG_GETARG_JSONB(x)
Definition: jsonb.h:70
int errmsg(const char *fmt,...)
Definition: elog.c:797
Datum jsonb_object_field ( PG_FUNCTION_ARGS  )

Definition at line 703 of file jsonfuncs.c.

References findJsonbValueFromContainerLen(), JB_FOBJECT, JB_ROOT_IS_OBJECT, JsonbValueToJsonb(), NULL, PG_GETARG_JSONB, PG_GETARG_TEXT_PP, PG_RETURN_JSONB, PG_RETURN_NULL, Jsonb::root, VARDATA_ANY, and VARSIZE_ANY_EXHDR.

704 {
705  Jsonb *jb = PG_GETARG_JSONB(0);
706  text *key = PG_GETARG_TEXT_PP(1);
707  JsonbValue *v;
708 
709  if (!JB_ROOT_IS_OBJECT(jb))
710  PG_RETURN_NULL();
711 
713  VARDATA_ANY(key),
714  VARSIZE_ANY_EXHDR(key));
715 
716  if (v != NULL)
718 
719  PG_RETURN_NULL();
720 }
#define JB_ROOT_IS_OBJECT(jbp_)
Definition: jsonb.h:224
#define VARDATA_ANY(PTR)
Definition: postgres.h:347
Jsonb * JsonbValueToJsonb(JsonbValue *val)
Definition: jsonb_util.c:79
Definition: jsonb.h:215
static JsonbValue * findJsonbValueFromContainerLen(JsonbContainer *container, uint32 flags, char *key, uint32 keylen)
Definition: jsonfuncs.c:3742
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:273
#define PG_RETURN_JSONB(x)
Definition: jsonb.h:71
JsonbContainer root
Definition: jsonb.h:218
#define NULL
Definition: c.h:229
#define JB_FOBJECT
Definition: jsonb.h:205
#define PG_GETARG_JSONB(x)
Definition: jsonb.h:70
#define VARSIZE_ANY_EXHDR(PTR)
Definition: postgres.h:340
Definition: c.h:439
#define PG_RETURN_NULL()
Definition: fmgr.h:305