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 JsObjectIsEmpty(jso)
 
#define JsObjectFree(jso)
 

Typedefs

typedef struct OkeysState OkeysState
 
typedef struct
IterateJsonStringValuesState 
IterateJsonStringValuesState
 
typedef struct
TransformJsonStringValuesState 
TransformJsonStringValuesState
 
typedef struct GetState GetState
 
typedef struct AlenState AlenState
 
typedef struct EachState EachState
 
typedef struct ElementsState ElementsState
 
typedef struct JHashState JHashState
 
typedef struct JsonHashEntry JsonHashEntry
 
typedef struct ScalarIOData ScalarIOData
 
typedef struct ColumnIOData ColumnIOData
 
typedef struct RecordIOData RecordIOData
 
typedef struct ArrayIOData ArrayIOData
 
typedef struct CompositeIOData CompositeIOData
 
typedef struct DomainIOData DomainIOData
 
typedef enum TypeCat TypeCat
 
typedef struct
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:810
long val
Definition: informix.c:689

Definition at line 318 of file jsonfuncs.c.

Referenced by populate_composite().

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

Definition at line 312 of file jsonfuncs.c.

Referenced by populate_record().

#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 303 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 308 of file jsonfuncs.c.

Referenced by populate_record_field().

Typedef Documentation

Definition at line 152 of file jsonfuncs.c.

Definition at line 153 of file jsonfuncs.c.

Enumeration Type Documentation

enum TypeCat
Enumerator
TYPECAT_SCALAR 
TYPECAT_ARRAY 
TYPECAT_COMPOSITE 
TYPECAT_DOMAIN 

Definition at line 184 of file jsonfuncs.c.

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

Function Documentation

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

Definition at line 3967 of file jsonfuncs.c.

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

Referenced by setPathArray(), and setPathObject().

3968 {
3969  JsonbIterator *it;
3970  JsonbValue *o = &(*jbps)->contVal;
3971  JsonbValue v;
3972  JsonbIteratorToken type;
3973 
3974  it = JsonbIteratorInit(&jb->root);
3975 
3976  Assert(o->type == jbvArray || o->type == jbvObject);
3977 
3978  if (JB_ROOT_IS_SCALAR(jb))
3979  {
3980  (void) JsonbIteratorNext(&it, &v, false); /* skip array header */
3981  (void) JsonbIteratorNext(&it, &v, false); /* fetch scalar value */
3982 
3983  switch (o->type)
3984  {
3985  case jbvArray:
3986  (void) pushJsonbValue(jbps, WJB_ELEM, &v);
3987  break;
3988  case jbvObject:
3989  (void) pushJsonbValue(jbps, WJB_VALUE, &v);
3990  break;
3991  default:
3992  elog(ERROR, "unexpected parent of nested structure");
3993  }
3994  }
3995  else
3996  {
3997  while ((type = JsonbIteratorNext(&it, &v, false)) != WJB_DONE)
3998  {
3999  if (type == WJB_KEY || type == WJB_VALUE || type == WJB_ELEM)
4000  (void) pushJsonbValue(jbps, type, &v);
4001  else
4002  (void) pushJsonbValue(jbps, type, NULL);
4003  }
4004  }
4005 
4006 }
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 Assert(condition)
Definition: c.h:664
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 1618 of file jsonfuncs.c.

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

Referenced by json_array_length().

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

Definition at line 1594 of file jsonfuncs.c.

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

Referenced by json_array_length().

1595 {
1596  AlenState *_state = (AlenState *) state;
1597 
1598  /* json structure check */
1599  if (_state->lex->lex_level == 0)
1600  ereport(ERROR,
1601  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1602  errmsg("cannot get array length of a non-array")));
1603 }
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:94
#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 1606 of file jsonfuncs.c.

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

Referenced by json_array_length().

1607 {
1608  AlenState *_state = (AlenState *) state;
1609 
1610  /* json structure check */
1611  if (_state->lex->lex_level == 0)
1612  ereport(ERROR,
1613  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1614  errmsg("cannot get array length of a scalar")));
1615 }
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:94
#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 2982 of file jsonfuncs.c.

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

Referenced by populate_record().

2983 {
2984  RecordIOData *data = (RecordIOData *)
2985  MemoryContextAlloc(mcxt,
2986  offsetof(RecordIOData, columns) +
2987  ncolumns * sizeof(ColumnIOData));
2988 
2989  data->record_type = InvalidOid;
2990  data->record_typmod = 0;
2991  data->ncolumns = ncolumns;
2992  MemSet(data->columns, 0, sizeof(ColumnIOData) * ncolumns);
2993 
2994  return data;
2995 }
Oid record_type
Definition: hstore_io.c:753
struct ColumnIOData ColumnIOData
Definition: jsonfuncs.c:152
#define MemSet(start, val, len)
Definition: c.h:846
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:706
#define offsetof(type, field)
Definition: c.h:549
static void each_array_start ( void *  state)
static

Definition at line 1928 of file jsonfuncs.c.

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

Referenced by each_worker().

1929 {
1930  EachState *_state = (EachState *) state;
1931 
1932  /* json structure check */
1933  if (_state->lex->lex_level == 0)
1934  ereport(ERROR,
1935  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1936  errmsg("cannot deconstruct an array as an object")));
1937 }
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:101
#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 1882 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().

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

Definition at line 1862 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().

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

Definition at line 1940 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().

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

Definition at line 1798 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, 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().

1799 {
1800  text *json = PG_GETARG_TEXT_PP(0);
1801  JsonLexContext *lex;
1802  JsonSemAction *sem;
1803  ReturnSetInfo *rsi;
1804  MemoryContext old_cxt;
1805  TupleDesc tupdesc;
1806  EachState *state;
1807 
1808  lex = makeJsonLexContext(json, true);
1809  state = palloc0(sizeof(EachState));
1810  sem = palloc0(sizeof(JsonSemAction));
1811 
1812  rsi = (ReturnSetInfo *) fcinfo->resultinfo;
1813 
1814  if (!rsi || !IsA(rsi, ReturnSetInfo) ||
1815  (rsi->allowedModes & SFRM_Materialize) == 0 ||
1816  rsi->expectedDesc == NULL)
1817  ereport(ERROR,
1818  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1819  errmsg("set-valued function called in context that "
1820  "cannot accept a set")));
1821 
1823 
1824  (void) get_call_result_type(fcinfo, NULL, &tupdesc);
1825 
1826  /* make these in a sufficiently long-lived memory context */
1828 
1829  state->ret_tdesc = CreateTupleDescCopy(tupdesc);
1830  BlessTupleDesc(state->ret_tdesc);
1831  state->tuple_store =
1833  false, work_mem);
1834 
1835  MemoryContextSwitchTo(old_cxt);
1836 
1837  sem->semstate = (void *) state;
1839  sem->scalar = each_scalar;
1842 
1843  state->normalize_results = as_text;
1844  state->next_scalar = false;
1845  state->lex = lex;
1847  "json_each temporary cxt",
1849 
1850  pg_parse_json(lex, sem);
1851 
1852  MemoryContextDelete(state->tmp_cxt);
1853 
1854  rsi->setResult = state->tuple_store;
1855  rsi->setDesc = state->ret_tdesc;
1856 
1857  PG_RETURN_NULL();
1858 }
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
Definition: tupdesc.c:102
#define IsA(nodeptr, _type_)
Definition: nodes.h:560
Tuplestorestate * tuple_store
Definition: jsonfuncs.c:102
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:200
static void each_object_field_start(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:1862
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:1928
TupleDesc ret_tdesc
Definition: jsonfuncs.c:103
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:273
MemoryContext tmp_cxt
Definition: jsonfuncs.c:104
static void each_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:1940
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:101
TupleDesc BlessTupleDesc(TupleDesc tupdesc)
Definition: execTuples.c:1032
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:877
bool normalize_results
Definition: jsonfuncs.c:106
int work_mem
Definition: globals.c:113
int allowedModes
Definition: execnodes.h:268
SetFunctionReturnMode returnMode
Definition: execnodes.h:270
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:433
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:1882
#define PG_RETURN_NULL()
Definition: fmgr.h:305
bool next_scalar
Definition: jsonfuncs.c:107
static Datum each_worker_jsonb ( FunctionCallInfo  fcinfo,
const char *  funcname,
bool  as_text 
)
static

Definition at line 1662 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(), PG_GETARG_JSONB_P, 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().

1663 {
1664  Jsonb *jb = PG_GETARG_JSONB_P(0);
1665  ReturnSetInfo *rsi;
1666  Tuplestorestate *tuple_store;
1667  TupleDesc tupdesc;
1668  TupleDesc ret_tdesc;
1669  MemoryContext old_cxt,
1670  tmp_cxt;
1671  bool skipNested = false;
1672  JsonbIterator *it;
1673  JsonbValue v;
1675 
1676  if (!JB_ROOT_IS_OBJECT(jb))
1677  ereport(ERROR,
1678  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1679  errmsg("cannot call %s on a non-object",
1680  funcname)));
1681 
1682  rsi = (ReturnSetInfo *) fcinfo->resultinfo;
1683 
1684  if (!rsi || !IsA(rsi, ReturnSetInfo) ||
1685  (rsi->allowedModes & SFRM_Materialize) == 0 ||
1686  rsi->expectedDesc == NULL)
1687  ereport(ERROR,
1688  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1689  errmsg("set-valued function called in context that "
1690  "cannot accept a set")));
1691 
1693 
1694  if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
1695  ereport(ERROR,
1696  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1697  errmsg("function returning record called in context "
1698  "that cannot accept type record")));
1699 
1701 
1702  ret_tdesc = CreateTupleDescCopy(tupdesc);
1703  BlessTupleDesc(ret_tdesc);
1704  tuple_store =
1706  false, work_mem);
1707 
1708  MemoryContextSwitchTo(old_cxt);
1709 
1711  "jsonb_each temporary cxt",
1713 
1714  it = JsonbIteratorInit(&jb->root);
1715 
1716  while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE)
1717  {
1718  skipNested = true;
1719 
1720  if (r == WJB_KEY)
1721  {
1722  text *key;
1723  HeapTuple tuple;
1724  Datum values[2];
1725  bool nulls[2] = {false, false};
1726 
1727  /* Use the tmp context so we can clean up after each tuple is done */
1728  old_cxt = MemoryContextSwitchTo(tmp_cxt);
1729 
1730  key = cstring_to_text_with_len(v.val.string.val, v.val.string.len);
1731 
1732  /*
1733  * The next thing the iterator fetches should be the value, no
1734  * matter what shape it is.
1735  */
1736  r = JsonbIteratorNext(&it, &v, skipNested);
1737 
1738  values[0] = PointerGetDatum(key);
1739 
1740  if (as_text)
1741  {
1742  if (v.type == jbvNull)
1743  {
1744  /* a json null is an sql null in text mode */
1745  nulls[1] = true;
1746  values[1] = (Datum) NULL;
1747  }
1748  else
1749  {
1750  text *sv;
1751 
1752  if (v.type == jbvString)
1753  {
1754  /* In text mode, scalar strings should be dequoted */
1755  sv = cstring_to_text_with_len(v.val.string.val, v.val.string.len);
1756  }
1757  else
1758  {
1759  /* Turn anything else into a json string */
1760  StringInfo jtext = makeStringInfo();
1761  Jsonb *jb = JsonbValueToJsonb(&v);
1762 
1763  (void) JsonbToCString(jtext, &jb->root, 0);
1764  sv = cstring_to_text_with_len(jtext->data, jtext->len);
1765  }
1766 
1767  values[1] = PointerGetDatum(sv);
1768  }
1769  }
1770  else
1771  {
1772  /* Not in text mode, just return the Jsonb */
1773  Jsonb *val = JsonbValueToJsonb(&v);
1774 
1775  values[1] = PointerGetDatum(val);
1776  }
1777 
1778  tuple = heap_form_tuple(ret_tdesc, values, nulls);
1779 
1780  tuplestore_puttuple(tuple_store, tuple);
1781 
1782  /* clean up and switch back */
1783  MemoryContextSwitchTo(old_cxt);
1784  MemoryContextReset(tmp_cxt);
1785  }
1786  }
1787 
1788  MemoryContextDelete(tmp_cxt);
1789 
1790  rsi->setResult = tuple_store;
1791  rsi->setDesc = ret_tdesc;
1792 
1793  PG_RETURN_NULL();
1794 }
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
Definition: tupdesc.c:102
#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:695
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:1032
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:113
int allowedModes
Definition: execnodes.h:268
SetFunctionReturnMode returnMode
Definition: execnodes.h:270
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:164
ExprContext * econtext
Definition: execnodes.h:266
TupleDesc setDesc
Definition: execnodes.h:274
int errmsg(const char *fmt,...)
Definition: elog.c:797
Definition: c.h:433
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
#define PG_GETARG_JSONB_P(x)
Definition: jsonb.h:70
static void elements_array_element_end ( void *  state,
bool  isnull 
)
static

Definition at line 2198 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, 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().

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

Definition at line 2178 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().

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

Definition at line 2242 of file jsonfuncs.c.

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

Referenced by elements_worker().

2243 {
2244  ElementsState *_state = (ElementsState *) state;
2245 
2246  /* json structure check */
2247  if (_state->lex->lex_level == 0)
2248  ereport(ERROR,
2249  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2250  errmsg("cannot call %s on a non-array",
2251  _state->function_name)));
2252 }
const char * function_name
Definition: jsonfuncs.c:115
JsonLexContext * lex
Definition: jsonfuncs.c:114
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 2255 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().

2256 {
2257  ElementsState *_state = (ElementsState *) state;
2258 
2259  /* json structure check */
2260  if (_state->lex->lex_level == 0)
2261  ereport(ERROR,
2262  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2263  errmsg("cannot call %s on a scalar",
2264  _state->function_name)));
2265 
2266  /* supply de-escaped value if required */
2267  if (_state->next_scalar)
2268  _state->normalized_scalar = token;
2269 }
const char * function_name
Definition: jsonfuncs.c:115
JsonLexContext * lex
Definition: jsonfuncs.c:114
bool next_scalar
Definition: jsonfuncs.c:121
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:122
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 2112 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, 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().

2113 {
2114  text *json = PG_GETARG_TEXT_PP(0);
2115 
2116  /* elements only needs escaped strings when as_text */
2117  JsonLexContext *lex = makeJsonLexContext(json, as_text);
2118  JsonSemAction *sem;
2119  ReturnSetInfo *rsi;
2120  MemoryContext old_cxt;
2121  TupleDesc tupdesc;
2123 
2124  state = palloc0(sizeof(ElementsState));
2125  sem = palloc0(sizeof(JsonSemAction));
2126 
2127  rsi = (ReturnSetInfo *) fcinfo->resultinfo;
2128 
2129  if (!rsi || !IsA(rsi, ReturnSetInfo) ||
2130  (rsi->allowedModes & SFRM_Materialize) == 0 ||
2131  rsi->expectedDesc == NULL)
2132  ereport(ERROR,
2133  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2134  errmsg("set-valued function called in context that "
2135  "cannot accept a set")));
2136 
2138 
2139  /* it's a simple type, so don't use get_call_result_type() */
2140  tupdesc = rsi->expectedDesc;
2141 
2142  /* make these in a sufficiently long-lived memory context */
2144 
2145  state->ret_tdesc = CreateTupleDescCopy(tupdesc);
2146  BlessTupleDesc(state->ret_tdesc);
2147  state->tuple_store =
2149  false, work_mem);
2150 
2151  MemoryContextSwitchTo(old_cxt);
2152 
2153  sem->semstate = (void *) state;
2155  sem->scalar = elements_scalar;
2158 
2159  state->function_name = funcname;
2160  state->normalize_results = as_text;
2161  state->next_scalar = false;
2162  state->lex = lex;
2164  "json_array_elements temporary cxt",
2166 
2167  pg_parse_json(lex, sem);
2168 
2169  MemoryContextDelete(state->tmp_cxt);
2170 
2171  rsi->setResult = state->tuple_store;
2172  rsi->setDesc = state->ret_tdesc;
2173 
2174  PG_RETURN_NULL();
2175 }
bool normalize_results
Definition: jsonfuncs.c:120
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
Definition: tupdesc.c:102
#define IsA(nodeptr, _type_)
Definition: nodes.h:560
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:200
const char * function_name
Definition: jsonfuncs.c:115
JsonLexContext * lex
Definition: jsonfuncs.c:114
static void elements_object_start(void *state)
Definition: jsonfuncs.c:2242
bool next_scalar
Definition: jsonfuncs.c:121
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:117
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:1032
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:2178
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:2198
void * palloc0(Size size)
Definition: mcxt.c:877
static void elements_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:2255
json_aelem_action array_element_start
Definition: jsonapi.h:91
Tuplestorestate * tuple_store
Definition: jsonfuncs.c:116
int work_mem
Definition: globals.c:113
int allowedModes
Definition: execnodes.h:268
SetFunctionReturnMode returnMode
Definition: execnodes.h:270
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:118
Definition: c.h:433
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 1976 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(), PG_GETARG_JSONB_P, 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().

1978 {
1979  Jsonb *jb = PG_GETARG_JSONB_P(0);
1980  ReturnSetInfo *rsi;
1981  Tuplestorestate *tuple_store;
1982  TupleDesc tupdesc;
1983  TupleDesc ret_tdesc;
1984  MemoryContext old_cxt,
1985  tmp_cxt;
1986  bool skipNested = false;
1987  JsonbIterator *it;
1988  JsonbValue v;
1990 
1991  if (JB_ROOT_IS_SCALAR(jb))
1992  ereport(ERROR,
1993  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1994  errmsg("cannot extract elements from a scalar")));
1995  else if (!JB_ROOT_IS_ARRAY(jb))
1996  ereport(ERROR,
1997  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1998  errmsg("cannot extract elements from an object")));
1999 
2000  rsi = (ReturnSetInfo *) fcinfo->resultinfo;
2001 
2002  if (!rsi || !IsA(rsi, ReturnSetInfo) ||
2003  (rsi->allowedModes & SFRM_Materialize) == 0 ||
2004  rsi->expectedDesc == NULL)
2005  ereport(ERROR,
2006  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2007  errmsg("set-valued function called in context that "
2008  "cannot accept a set")));
2009 
2011 
2012  /* it's a simple type, so don't use get_call_result_type() */
2013  tupdesc = rsi->expectedDesc;
2014 
2016 
2017  ret_tdesc = CreateTupleDescCopy(tupdesc);
2018  BlessTupleDesc(ret_tdesc);
2019  tuple_store =
2021  false, work_mem);
2022 
2023  MemoryContextSwitchTo(old_cxt);
2024 
2026  "jsonb_array_elements temporary cxt",
2028 
2029  it = JsonbIteratorInit(&jb->root);
2030 
2031  while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE)
2032  {
2033  skipNested = true;
2034 
2035  if (r == WJB_ELEM)
2036  {
2037  HeapTuple tuple;
2038  Datum values[1];
2039  bool nulls[1] = {false};
2040 
2041  /* use the tmp context so we can clean up after each tuple is done */
2042  old_cxt = MemoryContextSwitchTo(tmp_cxt);
2043 
2044  if (!as_text)
2045  {
2046  Jsonb *val = JsonbValueToJsonb(&v);
2047 
2048  values[0] = PointerGetDatum(val);
2049  }
2050  else
2051  {
2052  if (v.type == jbvNull)
2053  {
2054  /* a json null is an sql null in text mode */
2055  nulls[0] = true;
2056  values[0] = (Datum) NULL;
2057  }
2058  else
2059  {
2060  text *sv;
2061 
2062  if (v.type == jbvString)
2063  {
2064  /* in text mode scalar strings should be dequoted */
2065  sv = cstring_to_text_with_len(v.val.string.val, v.val.string.len);
2066  }
2067  else
2068  {
2069  /* turn anything else into a json string */
2070  StringInfo jtext = makeStringInfo();
2071  Jsonb *jb = JsonbValueToJsonb(&v);
2072 
2073  (void) JsonbToCString(jtext, &jb->root, 0);
2074  sv = cstring_to_text_with_len(jtext->data, jtext->len);
2075  }
2076 
2077  values[0] = PointerGetDatum(sv);
2078  }
2079  }
2080 
2081  tuple = heap_form_tuple(ret_tdesc, values, nulls);
2082 
2083  tuplestore_puttuple(tuple_store, tuple);
2084 
2085  /* clean up and switch back */
2086  MemoryContextSwitchTo(old_cxt);
2087  MemoryContextReset(tmp_cxt);
2088  }
2089  }
2090 
2091  MemoryContextDelete(tmp_cxt);
2092 
2093  rsi->setResult = tuple_store;
2094  rsi->setDesc = ret_tdesc;
2095 
2096  PG_RETURN_NULL();
2097 }
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
Definition: tupdesc.c:102
#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:695
#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:1032
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:113
int allowedModes
Definition: execnodes.h:268
SetFunctionReturnMode returnMode
Definition: execnodes.h:270
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:164
ExprContext * econtext
Definition: execnodes.h:266
TupleDesc setDesc
Definition: execnodes.h:274
int errmsg(const char *fmt,...)
Definition: elog.c:797
Definition: c.h:433
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
#define PG_GETARG_JSONB_P(x)
Definition: jsonb.h:70
static JsonbValue * findJsonbValueFromContainerLen ( JsonbContainer container,
uint32  flags,
char *  key,
uint32  keylen 
)
static

Definition at line 3758 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().

3760 {
3761  JsonbValue k;
3762 
3763  k.type = jbvString;
3764  k.val.string.val = key;
3765  k.val.string.len = keylen;
3766 
3767  return findJsonbValueFromContainer(container, flags, &k);
3768 }
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 1281 of file jsonfuncs.c.

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

Referenced by get_worker().

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

Definition at line 1235 of file jsonfuncs.c.

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

Referenced by get_worker().

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

Definition at line 1219 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().

1220 {
1221  GetState *_state = (GetState *) state;
1222  int lex_level = _state->lex->lex_level;
1223 
1224  if (lex_level == 0 && _state->npath == 0)
1225  {
1226  /* Special case: return the entire array */
1227  char *start = _state->result_start;
1228  int len = _state->lex->prev_token_terminator - start;
1229 
1230  _state->tresult = cstring_to_text_with_len(start, len);
1231  }
1232 }
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 1186 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().

1187 {
1188  GetState *_state = (GetState *) state;
1189  int lex_level = _state->lex->lex_level;
1190 
1191  if (lex_level < _state->npath)
1192  {
1193  /* Initialize counting of elements in this array */
1194  _state->array_cur_index[lex_level] = -1;
1195 
1196  /* INT_MIN value is reserved to represent invalid subscript */
1197  if (_state->path_indexes[lex_level] < 0 &&
1198  _state->path_indexes[lex_level] != INT_MIN)
1199  {
1200  /* Negative subscript -- convert to positive-wise subscript */
1201  int nelements = json_count_array_elements(_state->lex);
1202 
1203  if (-_state->path_indexes[lex_level] <= nelements)
1204  _state->path_indexes[lex_level] += nelements;
1205  }
1206  }
1207  else if (lex_level == 0 && _state->npath == 0)
1208  {
1209  /*
1210  * Special case: we should match the entire array. We only need this
1211  * at the outermost level because at nested levels the match will have
1212  * been started by the outer field or array element callback.
1213  */
1214  _state->result_start = _state->lex->token_start;
1215  }
1216 }
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 3266 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().

3267 {
3268  HASHCTL ctl;
3269  HTAB *tab;
3270  JHashState *state;
3271  JsonLexContext *lex = makeJsonLexContextCstringLen(json, len, true);
3272  JsonSemAction *sem;
3273 
3274  memset(&ctl, 0, sizeof(ctl));
3275  ctl.keysize = NAMEDATALEN;
3276  ctl.entrysize = sizeof(JsonHashEntry);
3277  ctl.hcxt = CurrentMemoryContext;
3278  tab = hash_create("json object hashtable",
3279  100,
3280  &ctl,
3282 
3283  state = palloc0(sizeof(JHashState));
3284  sem = palloc0(sizeof(JsonSemAction));
3285 
3286  state->function_name = funcname;
3287  state->hash = tab;
3288  state->lex = lex;
3289 
3290  sem->semstate = (void *) state;
3292  sem->scalar = hash_scalar;
3295 
3296  pg_parse_json(lex, sem);
3297 
3298  return tab;
3299 }
#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:3326
json_scalar_action scalar
Definition: jsonapi.h:93
#define NAMEDATALEN
Definition: dynahash.c:208
void pg_parse_json(JsonLexContext *lex, JsonSemAction *sem)
Definition: json.c:331
HTAB * hash
Definition: jsonfuncs.c:130
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:3302
const char * function_name
Definition: jsonfuncs.c:129
void * palloc0(Size size)
Definition: mcxt.c:877
HTAB * hash_create(const char *tabname, long nelem, HASHCTL *info, int flags)
Definition: dynahash.c:316
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:128
static void hash_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:3386
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:3375
static Datum get_jsonb_path_all ( FunctionCallInfo  fcinfo,
bool  as_text 
)
static

Definition at line 1376 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, PG_GETARG_ARRAYTYPE_P, PG_GETARG_JSONB_P, PG_RETURN_JSONB_P, 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().

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

Definition at line 1076 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().

1077 {
1078  GetState *_state = (GetState *) state;
1079  int lex_level = _state->lex->lex_level;
1080 
1081  if (lex_level == 0 && _state->npath == 0)
1082  {
1083  /* Special case: return the entire object */
1084  char *start = _state->result_start;
1085  int len = _state->lex->prev_token_terminator - start;
1086 
1087  _state->tresult = cstring_to_text_with_len(start, len);
1088  }
1089 }
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 1137 of file jsonfuncs.c.

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

Referenced by get_worker().

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

Definition at line 1092 of file jsonfuncs.c.

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

Referenced by get_worker().

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

Definition at line 1059 of file jsonfuncs.c.

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

Referenced by get_worker().

1060 {
1061  GetState *_state = (GetState *) state;
1062  int lex_level = _state->lex->lex_level;
1063 
1064  if (lex_level == 0 && _state->npath == 0)
1065  {
1066  /*
1067  * Special case: we should match the entire object. We only need this
1068  * at outermost level because at nested levels the match will have
1069  * been started by the outer field or array element callback.
1070  */
1071  _state->result_start = _state->lex->token_start;
1072  }
1073 }
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 923 of file jsonfuncs.c.

References array_contains_nulls(), Assert, deconstruct_array(), get_worker(), i, 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().

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

Definition at line 1323 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, JsonLexContext::prev_token_terminator, and GetState::tresult.

Referenced by get_worker().

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

Definition at line 1003 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, 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().

1008 {
1009  JsonLexContext *lex = makeJsonLexContext(json, true);
1010  JsonSemAction *sem = palloc0(sizeof(JsonSemAction));
1011  GetState *state = palloc0(sizeof(GetState));
1012 
1013  Assert(npath >= 0);
1014 
1015  state->lex = lex;
1016  /* is it "_as_text" variant? */
1017  state->normalize_results = normalize_results;
1018  state->npath = npath;
1019  state->path_names = tpath;
1020  state->path_indexes = ipath;
1021  state->pathok = palloc0(sizeof(bool) * npath);
1022  state->array_cur_index = palloc(sizeof(int) * npath);
1023 
1024  if (npath > 0)
1025  state->pathok[0] = true;
1026 
1027  sem->semstate = (void *) state;
1028 
1029  /*
1030  * Not all variants need all the semantic routines. Only set the ones that
1031  * are actually needed for maximum efficiency.
1032  */
1033  sem->scalar = get_scalar;
1034  if (npath == 0)
1035  {
1037  sem->object_end = get_object_end;
1039  sem->array_end = get_array_end;
1040  }
1041  if (tpath != NULL)
1042  {
1045  }
1046  if (ipath != NULL)
1047  {
1051  }
1052 
1053  pg_parse_json(lex, sem);
1054 
1055  return state->tresult;
1056 }
json_struct_action array_end
Definition: jsonapi.h:88
static void get_array_end(void *state)
Definition: jsonfuncs.c:1219
int * array_cur_index
Definition: jsonfuncs.c:87
static void get_array_element_start(void *state, bool isnull)
Definition: jsonfuncs.c:1235
json_struct_action object_end
Definition: jsonapi.h:86
static void get_object_start(void *state)
Definition: jsonfuncs.c:1059
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:1137
JsonLexContext * lex
Definition: jsonfuncs.c:78
static void get_object_end(void *state)
Definition: jsonfuncs.c:1076
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:1281
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:1323
void * palloc0(Size size)
Definition: mcxt.c:877
static void get_array_start(void *state)
Definition: jsonfuncs.c:1186
json_aelem_action array_element_start
Definition: jsonapi.h:91
char ** path_names
Definition: jsonfuncs.c:84
#define Assert(condition)
Definition: c.h:664
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:848
static void get_object_field_start(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:1092
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 3375 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().

3376 {
3377  JHashState *_state = (JHashState *) state;
3378 
3379  if (_state->lex->lex_level == 0)
3380  ereport(ERROR,
3381  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3382  errmsg("cannot call %s on an array", _state->function_name)));
3383 }
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:129
Definition: regguts.h:298
JsonLexContext * lex
Definition: jsonfuncs.c:128
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 3326 of file jsonfuncs.c.

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

Referenced by get_json_object_as_hash().

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

Definition at line 3302 of file jsonfuncs.c.

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

Referenced by get_json_object_as_hash().

3303 {
3304  JHashState *_state = (JHashState *) state;
3305 
3306  if (_state->lex->lex_level > 1)
3307  return;
3308 
3309  /* remember token type */
3310  _state->saved_token_type = _state->lex->token_type;
3311 
3312  if (_state->lex->token_type == JSON_TOKEN_ARRAY_START ||
3314  {
3315  /* remember start position of the whole text of the subobject */
3316  _state->save_json_start = _state->lex->token_start;
3317  }
3318  else
3319  {
3320  /* must be a scalar */
3321  _state->save_json_start = NULL;
3322  }
3323 }
JsonTokenType token_type
Definition: jsonapi.h:58
int lex_level
Definition: jsonapi.h:59
char * save_json_start
Definition: jsonfuncs.c:132
JsonTokenType saved_token_type
Definition: jsonfuncs.c:133
char * token_start
Definition: jsonapi.h:55
Definition: regguts.h:298
JsonLexContext * lex
Definition: jsonfuncs.c:128
static void hash_scalar ( void *  state,
char *  token,
JsonTokenType  tokentype 
)
static

Definition at line 3386 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().

3387 {
3388  JHashState *_state = (JHashState *) state;
3389 
3390  if (_state->lex->lex_level == 0)
3391  ereport(ERROR,
3392  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3393  errmsg("cannot call %s on a scalar", _state->function_name)));
3394 
3395  if (_state->lex->lex_level == 1)
3396  {
3397  _state->saved_scalar = token;
3398  /* saved_token_type must already be set in hash_object_field_start() */
3399  Assert(_state->saved_token_type == tokentype);
3400  }
3401 }
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:133
#define ereport(elevel, rest)
Definition: elog.h:122
const char * function_name
Definition: jsonfuncs.c:129
#define Assert(condition)
Definition: c.h:664
Definition: regguts.h:298
JsonLexContext * lex
Definition: jsonfuncs.c:128
char * saved_scalar
Definition: jsonfuncs.c:131
int errmsg(const char *fmt,...)
Definition: elog.c:797
void iterate_json_string_values ( text json,
void *  action_state,
JsonIterateStringValuesAction  action 
)

Definition at line 4837 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().

4838 {
4839  JsonLexContext *lex = makeJsonLexContext(json, true);
4840  JsonSemAction *sem = palloc0(sizeof(JsonSemAction));
4842 
4843  state->lex = lex;
4844  state->action = action;
4845  state->action_state = action_state;
4846 
4847  sem->semstate = (void *) state;
4849 
4850  pg_parse_json(lex, sem);
4851 }
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:877
Definition: regguts.h:298
static void iterate_string_values_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:4858
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 4815 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().

4816 {
4817  JsonbIterator *it;
4818  JsonbValue v;
4819  JsonbIteratorToken type;
4820 
4821  it = JsonbIteratorInit(&jb->root);
4822 
4823  while ((type = JsonbIteratorNext(&it, &v, false)) != WJB_DONE)
4824  {
4825  if ((type == WJB_VALUE || type == WJB_ELEM) && v.type == jbvString)
4826  {
4827  action(state, v.val.string.val, v.val.string.len);
4828  }
4829  }
4830 }
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 4858 of file jsonfuncs.c.

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

Referenced by iterate_json_string_values().

4859 {
4861 
4862  if (tokentype == JSON_TOKEN_STRING)
4863  _state->action(_state->action_state, token, strlen(token));
4864 }
JsonIterateStringValuesAction action
Definition: jsonfuncs.c:60
Definition: regguts.h:298
static JsonbValue * IteratorConcat ( JsonbIterator **  it1,
JsonbIterator **  it2,
JsonbParseState **  state 
)
static

Definition at line 4415 of file jsonfuncs.c.

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

Referenced by jsonb_concat().

4417 {
4418  JsonbValue v1,
4419  v2,
4420  *res = NULL;
4421  JsonbIteratorToken r1,
4422  r2,
4423  rk1,
4424  rk2;
4425 
4426  r1 = rk1 = JsonbIteratorNext(it1, &v1, false);
4427  r2 = rk2 = JsonbIteratorNext(it2, &v2, false);
4428 
4429  /*
4430  * Both elements are objects.
4431  */
4432  if (rk1 == WJB_BEGIN_OBJECT && rk2 == WJB_BEGIN_OBJECT)
4433  {
4434  /*
4435  * Append the all tokens from v1 to res, except last WJB_END_OBJECT
4436  * (because res will not be finished yet).
4437  */
4438  pushJsonbValue(state, r1, NULL);
4439  while ((r1 = JsonbIteratorNext(it1, &v1, true)) != WJB_END_OBJECT)
4440  pushJsonbValue(state, r1, &v1);
4441 
4442  /*
4443  * Append the all tokens from v2 to res, include last WJB_END_OBJECT
4444  * (the concatenation will be completed).
4445  */
4446  while ((r2 = JsonbIteratorNext(it2, &v2, true)) != 0)
4447  res = pushJsonbValue(state, r2, r2 != WJB_END_OBJECT ? &v2 : NULL);
4448  }
4449 
4450  /*
4451  * Both elements are arrays (either can be scalar).
4452  */
4453  else if (rk1 == WJB_BEGIN_ARRAY && rk2 == WJB_BEGIN_ARRAY)
4454  {
4455  pushJsonbValue(state, r1, NULL);
4456 
4457  while ((r1 = JsonbIteratorNext(it1, &v1, true)) != WJB_END_ARRAY)
4458  {
4459  Assert(r1 == WJB_ELEM);
4460  pushJsonbValue(state, r1, &v1);
4461  }
4462 
4463  while ((r2 = JsonbIteratorNext(it2, &v2, true)) != WJB_END_ARRAY)
4464  {
4465  Assert(r2 == WJB_ELEM);
4466  pushJsonbValue(state, WJB_ELEM, &v2);
4467  }
4468 
4469  res = pushJsonbValue(state, WJB_END_ARRAY, NULL /* signal to sort */ );
4470  }
4471  /* have we got array || object or object || array? */
4472  else if (((rk1 == WJB_BEGIN_ARRAY && !(*it1)->isScalar) && rk2 == WJB_BEGIN_OBJECT) ||
4473  (rk1 == WJB_BEGIN_OBJECT && (rk2 == WJB_BEGIN_ARRAY && !(*it2)->isScalar)))
4474  {
4475 
4476  JsonbIterator **it_array = rk1 == WJB_BEGIN_ARRAY ? it1 : it2;
4477  JsonbIterator **it_object = rk1 == WJB_BEGIN_OBJECT ? it1 : it2;
4478 
4479  bool prepend = (rk1 == WJB_BEGIN_OBJECT);
4480 
4481  pushJsonbValue(state, WJB_BEGIN_ARRAY, NULL);
4482 
4483  if (prepend)
4484  {
4485  pushJsonbValue(state, WJB_BEGIN_OBJECT, NULL);
4486  while ((r1 = JsonbIteratorNext(it_object, &v1, true)) != 0)
4487  pushJsonbValue(state, r1, r1 != WJB_END_OBJECT ? &v1 : NULL);
4488 
4489  while ((r2 = JsonbIteratorNext(it_array, &v2, true)) != 0)
4490  res = pushJsonbValue(state, r2, r2 != WJB_END_ARRAY ? &v2 : NULL);
4491  }
4492  else
4493  {
4494  while ((r1 = JsonbIteratorNext(it_array, &v1, true)) != WJB_END_ARRAY)
4495  pushJsonbValue(state, r1, &v1);
4496 
4497  pushJsonbValue(state, WJB_BEGIN_OBJECT, NULL);
4498  while ((r2 = JsonbIteratorNext(it_object, &v2, true)) != 0)
4499  pushJsonbValue(state, r2, r2 != WJB_END_OBJECT ? &v2 : NULL);
4500 
4501  res = pushJsonbValue(state, WJB_END_ARRAY, NULL);
4502  }
4503  }
4504  else
4505  {
4506  /*
4507  * This must be scalar || object or object || scalar, as that's all
4508  * that's left. Both of these make no sense, so error out.
4509  */
4510  ereport(ERROR,
4511  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4512  errmsg("invalid concatenation of jsonb objects")));
4513  }
4514 
4515  return res;
4516 }
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 Assert(condition)
Definition: c.h:664
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 2998 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, JsonHashEntry::type, JsonHashEntry::val, JsValue::val, and JsObject::val.

Referenced by populate_record().

2999 {
3000  jsv->is_json = obj->is_json;
3001 
3002  if (jsv->is_json)
3003  {
3004  JsonHashEntry *hashentry = hash_search(obj->val.json_hash, field,
3005  HASH_FIND, NULL);
3006 
3007  jsv->val.json.type = hashentry ? hashentry->type : JSON_TOKEN_NULL;
3008  jsv->val.json.str = jsv->val.json.type == JSON_TOKEN_NULL ? NULL :
3009  hashentry->val;
3010  jsv->val.json.len = jsv->val.json.str ? -1 : 0; /* null-terminated */
3011 
3012  return hashentry != NULL;
3013  }
3014  else
3015  {
3016  jsv->val.jsonb = !obj->val.jsonb_cont ? NULL :
3018  field, strlen(field));
3019 
3020  return jsv->val.jsonb != NULL;
3021  }
3022 }
bool is_json
Definition: jsonfuncs.c:294
static JsonbValue * findJsonbValueFromContainerLen(JsonbContainer *container, uint32 flags, char *key, uint32 keylen)
Definition: jsonfuncs.c:3758
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:902
JsonTokenType type
Definition: jsonfuncs.c:141
JsonbContainer * jsonb_cont
Definition: jsonfuncs.c:298
char * val
Definition: jsonfuncs.c:140
union JsValue::@30 val
union JsObject::@32 val
bool is_json
Definition: jsonfuncs.c:278
HTAB * json_hash
Definition: jsonfuncs.c:297
#define JB_FOBJECT
Definition: jsonb.h:205
struct JsValue::@30::@31 json
JsonbValue * jsonb
Definition: jsonfuncs.c:288
Datum json_array_element ( PG_FUNCTION_ARGS  )

Definition at line 791 of file jsonfuncs.c.

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

792 {
793  text *json = PG_GETARG_TEXT_PP(0);
794  int element = PG_GETARG_INT32(1);
795  text *result;
796 
797  result = get_worker(json, NULL, &element, 1, false);
798 
799  if (result != NULL)
800  PG_RETURN_TEXT_P(result);
801  else
802  PG_RETURN_NULL();
803 }
#define PG_GETARG_INT32(n)
Definition: fmgr.h:234
return result
Definition: formatting.c:1633
#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:1003
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:331
Definition: c.h:433
#define PG_RETURN_NULL()
Definition: fmgr.h:305
Datum json_array_element_text ( PG_FUNCTION_ARGS  )

Definition at line 834 of file jsonfuncs.c.

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

835 {
836  text *json = PG_GETARG_TEXT_PP(0);
837  int element = PG_GETARG_INT32(1);
838  text *result;
839 
840  result = get_worker(json, NULL, &element, 1, true);
841 
842  if (result != NULL)
843  PG_RETURN_TEXT_P(result);
844  else
845  PG_RETURN_NULL();
846 }
#define PG_GETARG_INT32(n)
Definition: fmgr.h:234
return result
Definition: formatting.c:1633
#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:1003
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:331
Definition: c.h:433
#define PG_RETURN_NULL()
Definition: fmgr.h:305
Datum json_array_elements ( PG_FUNCTION_ARGS  )

Definition at line 2100 of file jsonfuncs.c.

References elements_worker().

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

Definition at line 2106 of file jsonfuncs.c.

References elements_worker().

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

Definition at line 1544 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.

1545 {
1546  text *json = PG_GETARG_TEXT_PP(0);
1547  AlenState *state;
1548  JsonLexContext *lex;
1549  JsonSemAction *sem;
1550 
1551  lex = makeJsonLexContext(json, false);
1552  state = palloc0(sizeof(AlenState));
1553  sem = palloc0(sizeof(JsonSemAction));
1554 
1555  /* palloc0 does this for us */
1556 #if 0
1557  state->count = 0;
1558 #endif
1559  state->lex = lex;
1560 
1561  sem->semstate = (void *) state;
1563  sem->scalar = alen_scalar;
1565 
1566  pg_parse_json(lex, sem);
1567 
1568  PG_RETURN_INT32(state->count);
1569 }
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:95
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:273
static void alen_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:1606
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:94
void * palloc0(Size size)
Definition: mcxt.c:877
json_aelem_action array_element_start
Definition: jsonapi.h:91
Definition: regguts.h:298
static void alen_object_start(void *state)
Definition: jsonfuncs.c:1594
Definition: c.h:433
static void alen_array_element_start(void *state, bool isnull)
Definition: jsonfuncs.c:1618
void * semstate
Definition: jsonapi.h:84
Datum json_each ( PG_FUNCTION_ARGS  )

Definition at line 1638 of file jsonfuncs.c.

References each_worker().

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

Definition at line 1650 of file jsonfuncs.c.

References each_worker().

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

Definition at line 908 of file jsonfuncs.c.

References get_path_all().

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

Definition at line 914 of file jsonfuncs.c.

References get_path_all().

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

Definition at line 688 of file jsonfuncs.c.

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

689 {
690  text *json = PG_GETARG_TEXT_PP(0);
691  text *fname = PG_GETARG_TEXT_PP(1);
692  char *fnamestr = text_to_cstring(fname);
693  text *result;
694 
695  result = get_worker(json, &fnamestr, NULL, 1, false);
696 
697  if (result != NULL)
698  PG_RETURN_TEXT_P(result);
699  else
700  PG_RETURN_NULL();
701 }
return result
Definition: formatting.c:1633
#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:1003
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:331
char * text_to_cstring(const text *t)
Definition: varlena.c:182
Definition: c.h:433
#define PG_RETURN_NULL()
Definition: fmgr.h:305
Datum json_object_field_text ( PG_FUNCTION_ARGS  )

Definition at line 724 of file jsonfuncs.c.

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

725 {
726  text *json = PG_GETARG_TEXT_PP(0);
727  text *fname = PG_GETARG_TEXT_PP(1);
728  char *fnamestr = text_to_cstring(fname);
729  text *result;
730 
731  result = get_worker(json, &fnamestr, NULL, 1, true);
732 
733  if (result != NULL)
734  PG_RETURN_TEXT_P(result);
735  else
736  PG_RETURN_NULL();
737 }
return result
Definition: formatting.c:1633
#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:1003
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:331
char * text_to_cstring(const text *t)
Definition: varlena.c:182
Definition: c.h:433
#define PG_RETURN_NULL()
Definition: fmgr.h:305
Datum json_object_keys ( PG_FUNCTION_ARGS  )

Definition at line 571 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.

572 {
573  FuncCallContext *funcctx;
574  OkeysState *state;
575  int i;
576 
577  if (SRF_IS_FIRSTCALL())
578  {
579  text *json = PG_GETARG_TEXT_PP(0);
580  JsonLexContext *lex = makeJsonLexContext(json, true);
581  JsonSemAction *sem;
582  MemoryContext oldcontext;
583 
584  funcctx = SRF_FIRSTCALL_INIT();
585  oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
586 
587  state = palloc(sizeof(OkeysState));
588  sem = palloc0(sizeof(JsonSemAction));
589 
590  state->lex = lex;
591  state->result_size = 256;
592  state->result_count = 0;
593  state->sent_count = 0;
594  state->result = palloc(256 * sizeof(char *));
595 
596  sem->semstate = (void *) state;
598  sem->scalar = okeys_scalar;
600  /* remainder are all NULL, courtesy of palloc0 above */
601 
602  pg_parse_json(lex, sem);
603  /* keys are now in state->result */
604 
605  pfree(lex->strval->data);
606  pfree(lex->strval);
607  pfree(lex);
608  pfree(sem);
609 
610  MemoryContextSwitchTo(oldcontext);
611  funcctx->user_fctx = (void *) state;
612  }
613 
614  funcctx = SRF_PERCALL_SETUP();
615  state = (OkeysState *) funcctx->user_fctx;
616 
617  if (state->sent_count < state->result_count)
618  {
619  char *nxt = state->result[state->sent_count++];
620 
621  SRF_RETURN_NEXT(funcctx, CStringGetTextDatum(nxt));
622  }
623 
624  /* cleanup to reduce or eliminate memory leaks */
625  for (i = 0; i < state->result_count; i++)
626  pfree(state->result[i]);
627  pfree(state->result);
628  pfree(state);
629 
630  SRF_RETURN_DONE(funcctx);
631 }
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:655
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:949
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:634
char ** result
Definition: jsonfuncs.c:50
void * palloc0(Size size)
Definition: mcxt.c:877
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:668
int result_size
Definition: jsonfuncs.c:51
void * user_fctx
Definition: funcapi.h:90
void * palloc(Size size)
Definition: mcxt.c:848
int i
#define CStringGetTextDatum(s)
Definition: builtins.h:91
Definition: c.h:433
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 2296 of file jsonfuncs.c.

References populate_record_worker().

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

Definition at line 3427 of file jsonfuncs.c.

References populate_recordset_worker().

3428 {
3429  return populate_recordset_worker(fcinfo, "json_populate_recordset", true);
3430 }
static Datum populate_recordset_worker(FunctionCallInfo fcinfo, const char *funcname, bool have_record_arg)
Definition: jsonfuncs.c:3460
Datum json_strip_nulls ( PG_FUNCTION_ARGS  )

Definition at line 3870 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.

3871 {
3872  text *json = PG_GETARG_TEXT_PP(0);
3874  JsonLexContext *lex;
3875  JsonSemAction *sem;
3876 
3877  lex = makeJsonLexContext(json, true);
3878  state = palloc0(sizeof(StripnullState));
3879  sem = palloc0(sizeof(JsonSemAction));
3880 
3881  state->strval = makeStringInfo();
3882  state->skip_next_null = false;
3883  state->lex = lex;
3884 
3885  sem->semstate = (void *) state;
3887  sem->object_end = sn_object_end;
3888  sem->array_start = sn_array_start;
3889  sem->array_end = sn_array_end;
3890  sem->scalar = sn_scalar;
3893 
3894  pg_parse_json(lex, sem);
3895 
3897  state->strval->len));
3898 
3899 }
json_struct_action array_end
Definition: jsonapi.h:88
bool skip_next_null
Definition: jsonfuncs.c:272
static void sn_object_start(void *state)
Definition: jsonfuncs.c:3780
json_struct_action object_end
Definition: jsonapi.h:86
static void sn_array_element_start(void *state, bool isnull)
Definition: jsonfuncs.c:3840
static void sn_object_field_start(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:3812
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:3796
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:270
static void sn_object_end(void *state)
Definition: jsonfuncs.c:3788
void * palloc0(Size size)
Definition: mcxt.c:877
json_aelem_action array_element_start
Definition: jsonapi.h:91
static void sn_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:3849
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:331
json_struct_action array_start
Definition: jsonapi.h:87
Definition: regguts.h:298
StringInfo strval
Definition: jsonfuncs.c:271
Definition: c.h:433
json_ofield_action object_field_start
Definition: jsonapi.h:89
static void sn_array_end(void *state)
Definition: jsonfuncs.c:3804
void * semstate
Definition: jsonapi.h:84
Datum json_to_record ( PG_FUNCTION_ARGS  )

Definition at line 2302 of file jsonfuncs.c.

References populate_record_worker().

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

Definition at line 3433 of file jsonfuncs.c.

References populate_recordset_worker().

3434 {
3435  return populate_recordset_worker(fcinfo, "json_to_recordset", false);
3436 }
static Datum populate_recordset_worker(FunctionCallInfo fcinfo, const char *funcname, bool have_record_arg)
Definition: jsonfuncs.c:3460
Datum jsonb_array_element ( PG_FUNCTION_ARGS  )

Definition at line 806 of file jsonfuncs.c.

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

807 {
808  Jsonb *jb = PG_GETARG_JSONB_P(0);
809  int element = PG_GETARG_INT32(1);
810  JsonbValue *v;
811 
812  if (!JB_ROOT_IS_ARRAY(jb))
813  PG_RETURN_NULL();
814 
815  /* Handle negative subscript */
816  if (element < 0)
817  {
818  uint32 nelements = JB_ROOT_COUNT(jb);
819 
820  if (-element > nelements)
821  PG_RETURN_NULL();
822  else
823  element += nelements;
824  }
825 
826  v = getIthJsonbValueFromContainer(&jb->root, element);
827  if (v != NULL)
829 
830  PG_RETURN_NULL();
831 }
#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 JB_ROOT_IS_ARRAY(jbp_)
Definition: jsonb.h:225
unsigned int uint32
Definition: c.h:258
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 PG_RETURN_JSONB_P(x)
Definition: jsonb.h:71
#define PG_RETURN_NULL()
Definition: fmgr.h:305
#define PG_GETARG_JSONB_P(x)
Definition: jsonb.h:70
Datum jsonb_array_element_text ( PG_FUNCTION_ARGS  )

Definition at line 849 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(), numeric_out(), PG_GETARG_INT32, PG_GETARG_JSONB_P, PG_RETURN_NULL, PG_RETURN_TEXT_P, PointerGetDatum, result, Jsonb::root, JsonbValue::type, and JsonbValue::val.

850 {
851  Jsonb *jb = PG_GETARG_JSONB_P(0);
852  int element = PG_GETARG_INT32(1);
853  JsonbValue *v;
854 
855  if (!JB_ROOT_IS_ARRAY(jb))
856  PG_RETURN_NULL();
857 
858  /* Handle negative subscript */
859  if (element < 0)
860  {
861  uint32 nelements = JB_ROOT_COUNT(jb);
862 
863  if (-element > nelements)
864  PG_RETURN_NULL();
865  else
866  element += nelements;
867  }
868 
869  v = getIthJsonbValueFromContainer(&jb->root, element);
870  if (v != NULL)
871  {
872  text *result = NULL;
873 
874  switch (v->type)
875  {
876  case jbvNull:
877  break;
878  case jbvBool:
879  result = cstring_to_text(v->val.boolean ? "true" : "false");
880  break;
881  case jbvString:
882  result = cstring_to_text_with_len(v->val.string.val, v->val.string.len);
883  break;
884  case jbvNumeric:
886  PointerGetDatum(v->val.numeric))));
887  break;
888  case jbvBinary:
889  {
890  StringInfo jtext = makeStringInfo();
891 
892  (void) JsonbToCString(jtext, v->val.binary.data, -1);
893  result = cstring_to_text_with_len(jtext->data, jtext->len);
894  }
895  break;
896  default:
897  elog(ERROR, "unrecognized jsonb type: %d", (int) v->type);
898  }
899 
900  if (result)
901  PG_RETURN_TEXT_P(result);
902  }
903 
904  PG_RETURN_NULL();
905 }
#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:651
#define JB_ROOT_COUNT(jbp_)
Definition: jsonb.h:222
return result
Definition: formatting.c:1633
Definition: jsonb.h:231
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:585
#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:258
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:331
text * cstring_to_text(const char *s)
Definition: varlena.c:149
JsonbValue * getIthJsonbValueFromContainer(JsonbContainer *container, uint32 i)
Definition: jsonb_util.c:419
char * JsonbToCString(StringInfo out, JsonbContainer *in, int estimated_len)
Definition: jsonb.c:428
enum jbvType type
Definition: jsonb.h:250
Definition: c.h:433
#define elog
Definition: elog.h:219
#define PG_RETURN_NULL()
Definition: fmgr.h:305
#define PG_GETARG_JSONB_P(x)
Definition: jsonb.h:70
Datum jsonb_array_elements ( PG_FUNCTION_ARGS  )

Definition at line 1964 of file jsonfuncs.c.

References elements_worker_jsonb().

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

Definition at line 1970 of file jsonfuncs.c.

References elements_worker_jsonb().

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

Definition at line 1572 of file jsonfuncs.c.

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

1573 {
1574  Jsonb *jb = PG_GETARG_JSONB_P(0);
1575 
1576  if (JB_ROOT_IS_SCALAR(jb))
1577  ereport(ERROR,
1578  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1579  errmsg("cannot get array length of a scalar")));
1580  else if (!JB_ROOT_IS_ARRAY(jb))
1581  ereport(ERROR,
1582  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1583  errmsg("cannot get array length of a non-array")));
1584 
1586 }
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
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define PG_GETARG_JSONB_P(x)
Definition: jsonb.h:70
Datum jsonb_concat ( PG_FUNCTION_ARGS  )

Definition at line 4030 of file jsonfuncs.c.

References Assert, IteratorConcat(), JB_ROOT_COUNT, JB_ROOT_IS_OBJECT, JB_ROOT_IS_SCALAR, JsonbIteratorInit(), JsonbValueToJsonb(), PG_GETARG_JSONB_P, PG_RETURN_JSONB_P, and Jsonb::root.

4031 {
4032  Jsonb *jb1 = PG_GETARG_JSONB_P(0);
4033  Jsonb *jb2 = PG_GETARG_JSONB_P(1);
4034  JsonbParseState *state = NULL;
4035  JsonbValue *res;
4036  JsonbIterator *it1,
4037  *it2;
4038 
4039  /*
4040  * If one of the jsonb is empty, just return the other if it's not scalar
4041  * and both are of the same kind. If it's a scalar or they are of
4042  * different kinds we need to perform the concatenation even if one is
4043  * empty.
4044  */
4045  if (JB_ROOT_IS_OBJECT(jb1) == JB_ROOT_IS_OBJECT(jb2))
4046  {
4047  if (JB_ROOT_COUNT(jb1) == 0 && !JB_ROOT_IS_SCALAR(jb2))
4048  PG_RETURN_JSONB_P(jb2);
4049  else if (JB_ROOT_COUNT(jb2) == 0 && !JB_ROOT_IS_SCALAR(jb1))
4050  PG_RETURN_JSONB_P(jb1);
4051  }
4052 
4053  it1 = JsonbIteratorInit(&jb1->root);
4054  it2 = JsonbIteratorInit(&jb2->root);
4055 
4056  res = IteratorConcat(&it1, &it2, &state);
4057 
4058  Assert(res != NULL);
4059 
4061 }
#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
JsonbContainer root
Definition: jsonb.h:218
#define Assert(condition)
Definition: c.h:664
JsonbIterator * JsonbIteratorInit(JsonbContainer *container)
Definition: jsonb_util.c:718
Definition: regguts.h:298
static JsonbValue * IteratorConcat(JsonbIterator **it1, JsonbIterator **it2, JsonbParseState **state)
Definition: jsonfuncs.c:4415
#define PG_RETURN_JSONB_P(x)
Definition: jsonb.h:71
#define PG_GETARG_JSONB_P(x)
Definition: jsonb.h:70
Datum jsonb_delete ( PG_FUNCTION_ARGS  )

Definition at line 4071 of file jsonfuncs.c.

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

4072 {
4073  Jsonb *in = PG_GETARG_JSONB_P(0);
4074  text *key = PG_GETARG_TEXT_PP(1);
4075  char *keyptr = VARDATA_ANY(key);
4076  int keylen = VARSIZE_ANY_EXHDR(key);
4077  JsonbParseState *state = NULL;
4078  JsonbIterator *it;
4079  JsonbValue v,
4080  *res = NULL;
4081  bool skipNested = false;
4083 
4084  if (JB_ROOT_IS_SCALAR(in))
4085  ereport(ERROR,
4086  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4087  errmsg("cannot delete from scalar")));
4088 
4089  if (JB_ROOT_COUNT(in) == 0)
4090  PG_RETURN_JSONB_P(in);
4091 
4092  it = JsonbIteratorInit(&in->root);
4093 
4094  while ((r = JsonbIteratorNext(&it, &v, skipNested)) != 0)
4095  {
4096  skipNested = true;
4097 
4098  if ((r == WJB_ELEM || r == WJB_KEY) &&
4099  (v.type == jbvString && keylen == v.val.string.len &&
4100  memcmp(keyptr, v.val.string.val, keylen) == 0))
4101  {
4102  /* skip corresponding value as well */
4103  if (r == WJB_KEY)
4104  JsonbIteratorNext(&it, &v, true);
4105 
4106  continue;
4107  }
4108 
4109  res = pushJsonbValue(&state, r, r < WJB_BEGIN_ARRAY ? &v : NULL);
4110  }
4111 
4112  Assert(res != NULL);
4113 
4115 }
#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
Definition: jsonb.h:23
#define ereport(elevel, rest)
Definition: elog.h:122
JsonbIteratorToken
Definition: jsonb.h:20
JsonbContainer root
Definition: jsonb.h:218
#define Assert(condition)
Definition: c.h:664
JsonbIterator * JsonbIteratorInit(JsonbContainer *container)
Definition: jsonb_util.c:718
Definition: regguts.h:298
enum jbvType type
Definition: jsonb.h:250
#define VARSIZE_ANY_EXHDR(PTR)
Definition: postgres.h:340
int errmsg(const char *fmt,...)
Definition: elog.c:797
Definition: c.h:433
#define PG_RETURN_JSONB_P(x)
Definition: jsonb.h:71
JsonbIteratorToken JsonbIteratorNext(JsonbIterator **it, JsonbValue *val, bool skipNested)
Definition: jsonb_util.c:754
Definition: jsonb.h:25
#define PG_GETARG_JSONB_P(x)
Definition: jsonb.h:70
Datum jsonb_delete_array ( PG_FUNCTION_ARGS  )

Definition at line 4124 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(), PG_GETARG_ARRAYTYPE_P, PG_GETARG_JSONB_P, PG_RETURN_JSONB_P, pushJsonbValue(), Jsonb::root, TEXTOID, JsonbValue::type, JsonbValue::val, VARDATA_ANY, VARSIZE_ANY_EXHDR, WJB_BEGIN_ARRAY, WJB_ELEM, and WJB_KEY.

4125 {
4126  Jsonb *in = PG_GETARG_JSONB_P(0);
4127  ArrayType *keys = PG_GETARG_ARRAYTYPE_P(1);
4128  Datum *keys_elems;
4129  bool *keys_nulls;
4130  int keys_len;
4131  JsonbParseState *state = NULL;
4132  JsonbIterator *it;
4133  JsonbValue v,
4134  *res = NULL;
4135  bool skipNested = false;
4137 
4138  if (ARR_NDIM(keys) > 1)
4139  ereport(ERROR,
4140  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
4141  errmsg("wrong number of array subscripts")));
4142 
4143  if (JB_ROOT_IS_SCALAR(in))
4144  ereport(ERROR,
4145  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4146  errmsg("cannot delete from scalar")));
4147 
4148  if (JB_ROOT_COUNT(in) == 0)
4149  PG_RETURN_JSONB_P(in);
4150 
4151  deconstruct_array(keys, TEXTOID, -1, false, 'i',
4152  &keys_elems, &keys_nulls, &keys_len);
4153 
4154  if (keys_len == 0)
4155  PG_RETURN_JSONB_P(in);
4156 
4157  it = JsonbIteratorInit(&in->root);
4158 
4159  while ((r = JsonbIteratorNext(&it, &v, skipNested)) != 0)
4160  {
4161  skipNested = true;
4162 
4163  if ((r == WJB_ELEM || r == WJB_KEY) && v.type == jbvString)
4164  {
4165  int i;
4166  bool found = false;
4167 
4168  for (i = 0; i < keys_len; i++)
4169  {
4170  char *keyptr;
4171  int keylen;
4172 
4173  if (keys_nulls[i])
4174  continue;
4175 
4176  keyptr = VARDATA_ANY(keys_elems[i]);
4177  keylen = VARSIZE_ANY_EXHDR(keys_elems[i]);
4178  if (keylen == v.val.string.len &&
4179  memcmp(keyptr, v.val.string.val, keylen) == 0)
4180  {
4181  found = true;
4182  break;
4183  }
4184  }
4185  if (found)
4186  {
4187  /* skip corresponding value as well */
4188  if (r == WJB_KEY)
4189  JsonbIteratorNext(&it, &v, true);
4190 
4191  continue;
4192  }
4193  }
4194 
4195  res = pushJsonbValue(&state, r, r < WJB_BEGIN_ARRAY ? &v : NULL);
4196  }
4197 
4198  Assert(res != NULL);
4199 
4201 }
#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
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 Assert(condition)
Definition: c.h:664
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:3476
#define VARSIZE_ANY_EXHDR(PTR)
Definition: postgres.h:340
int errmsg(const char *fmt,...)
Definition: elog.c:797
int i
#define PG_RETURN_JSONB_P(x)
Definition: jsonb.h:71
JsonbIteratorToken JsonbIteratorNext(JsonbIterator **it, JsonbValue *val, bool skipNested)
Definition: jsonb_util.c:754
Definition: jsonb.h:25
#define PG_GETARG_JSONB_P(x)
Definition: jsonb.h:70
Datum jsonb_delete_idx ( PG_FUNCTION_ARGS  )

Definition at line 4211 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(), PG_GETARG_INT32, PG_GETARG_JSONB_P, PG_RETURN_JSONB_P, pushJsonbValue(), Jsonb::root, JsonbValue::val, WJB_BEGIN_ARRAY, and WJB_ELEM.

4212 {
4213  Jsonb *in = PG_GETARG_JSONB_P(0);
4214  int idx = PG_GETARG_INT32(1);
4215  JsonbParseState *state = NULL;
4216  JsonbIterator *it;
4217  uint32 i = 0,
4218  n;
4219  JsonbValue v,
4220  *res = NULL;
4222 
4223  if (JB_ROOT_IS_SCALAR(in))
4224  ereport(ERROR,
4225  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4226  errmsg("cannot delete from scalar")));
4227 
4228  if (JB_ROOT_IS_OBJECT(in))
4229  ereport(ERROR,
4230  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4231  errmsg("cannot delete from object using integer index")));
4232 
4233  if (JB_ROOT_COUNT(in) == 0)
4234  PG_RETURN_JSONB_P(in);
4235 
4236  it = JsonbIteratorInit(&in->root);
4237 
4238  r = JsonbIteratorNext(&it, &v, false);
4239  Assert(r == WJB_BEGIN_ARRAY);
4240  n = v.val.array.nElems;
4241 
4242  if (idx < 0)
4243  {
4244  if (-idx > n)
4245  idx = n;
4246  else
4247  idx = n + idx;
4248  }
4249 
4250  if (idx >= n)
4251  PG_RETURN_JSONB_P(in);
4252 
4253  pushJsonbValue(&state, r, NULL);
4254 
4255  while ((r = JsonbIteratorNext(&it, &v, true)) != 0)
4256  {
4257  if (r == WJB_ELEM)
4258  {
4259  if (i++ == idx)
4260  continue;
4261  }
4262 
4263  res = pushJsonbValue(&state, r, r < WJB_BEGIN_ARRAY ? &v : NULL);
4264  }
4265 
4266  Assert(res != NULL);
4267 
4269 }
#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
unsigned int uint32
Definition: c.h:258
#define ereport(elevel, rest)
Definition: elog.h:122
JsonbIteratorToken
Definition: jsonb.h:20
JsonbContainer root
Definition: jsonb.h:218
#define Assert(condition)
Definition: c.h:664
JsonbIterator * JsonbIteratorInit(JsonbContainer *container)
Definition: jsonb_util.c:718
Definition: regguts.h:298
int errmsg(const char *fmt,...)
Definition: elog.c:797
int i
#define PG_RETURN_JSONB_P(x)
Definition: jsonb.h:71
JsonbIteratorToken JsonbIteratorNext(JsonbIterator **it, JsonbValue *val, bool skipNested)
Definition: jsonb_util.c:754
Definition: jsonb.h:25
#define PG_GETARG_JSONB_P(x)
Definition: jsonb.h:70
Datum jsonb_delete_path ( PG_FUNCTION_ARGS  )

Definition at line 4323 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(), PG_GETARG_ARRAYTYPE_P, PG_GETARG_JSONB_P, PG_RETURN_JSONB_P, Jsonb::root, setPath(), and TEXTOID.

4324 {
4325  Jsonb *in = PG_GETARG_JSONB_P(0);
4326  ArrayType *path = PG_GETARG_ARRAYTYPE_P(1);
4327  JsonbValue *res = NULL;
4328  Datum *path_elems;
4329  bool *path_nulls;
4330  int path_len;
4331  JsonbIterator *it;
4332  JsonbParseState *st = NULL;
4333 
4334  if (ARR_NDIM(path) > 1)
4335  ereport(ERROR,
4336  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
4337  errmsg("wrong number of array subscripts")));
4338 
4339  if (JB_ROOT_IS_SCALAR(in))
4340  ereport(ERROR,
4341  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4342  errmsg("cannot delete path in scalar")));
4343 
4344  if (JB_ROOT_COUNT(in) == 0)
4345  PG_RETURN_JSONB_P(in);
4346 
4347  deconstruct_array(path, TEXTOID, -1, false, 'i',
4348  &path_elems, &path_nulls, &path_len);
4349 
4350  if (path_len == 0)
4351  PG_RETURN_JSONB_P(in);
4352 
4353  it = JsonbIteratorInit(&in->root);
4354 
4355  res = setPath(&it, path_elems, path_nulls, path_len, &st,
4356  0, NULL, JB_PATH_DELETE);
4357 
4358  Assert(res != NULL);
4359 
4361 }
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:4533
#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 ereport(elevel, rest)
Definition: elog.h:122
JsonbContainer root
Definition: jsonb.h:218
uintptr_t Datum
Definition: postgres.h:372
#define Assert(condition)
Definition: c.h:664
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:3476
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define PG_RETURN_JSONB_P(x)
Definition: jsonb.h:71
#define JB_PATH_DELETE
Definition: jsonfuncs.c:39
#define PG_GETARG_JSONB_P(x)
Definition: jsonb.h:70
Datum jsonb_each ( PG_FUNCTION_ARGS  )

Definition at line 1644 of file jsonfuncs.c.

References each_worker_jsonb().

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

Definition at line 1656 of file jsonfuncs.c.

References each_worker_jsonb().

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

Definition at line 1364 of file jsonfuncs.c.

References get_jsonb_path_all().

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

Definition at line 1370 of file jsonfuncs.c.

References get_jsonb_path_all().

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

Definition at line 4368 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, PG_GETARG_ARRAYTYPE_P, PG_GETARG_BOOL, PG_GETARG_JSONB_P, PG_RETURN_JSONB_P, Jsonb::root, setPath(), and TEXTOID.

4369 {
4370  Jsonb *in = PG_GETARG_JSONB_P(0);
4371  ArrayType *path = PG_GETARG_ARRAYTYPE_P(1);
4373  bool after = PG_GETARG_BOOL(3);
4374  JsonbValue *res = NULL;
4375  Datum *path_elems;
4376  bool *path_nulls;
4377  int path_len;
4378  JsonbIterator *it;
4379  JsonbParseState *st = NULL;
4380 
4381  if (ARR_NDIM(path) > 1)
4382  ereport(ERROR,
4383  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
4384  errmsg("wrong number of array subscripts")));
4385 
4386  if (JB_ROOT_IS_SCALAR(in))
4387  ereport(ERROR,
4388  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4389  errmsg("cannot set path in scalar")));
4390 
4391  deconstruct_array(path, TEXTOID, -1, false, 'i',
4392  &path_elems, &path_nulls, &path_len);
4393 
4394  if (path_len == 0)
4395  PG_RETURN_JSONB_P(in);
4396 
4397  it = JsonbIteratorInit(&in->root);
4398 
4399  res = setPath(&it, path_elems, path_nulls, path_len, &st, 0, newval,
4401 
4402  Assert(res != NULL);
4403 
4405 }
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:4533
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 ereport(elevel, rest)
Definition: elog.h:122
JsonbContainer root
Definition: jsonb.h:218
uintptr_t Datum
Definition: postgres.h:372
#define Assert(condition)
Definition: c.h:664
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:3476
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define PG_RETURN_JSONB_P(x)
Definition: jsonb.h:71
#define PG_GETARG_JSONB_P(x)
Definition: jsonb.h:70
Datum jsonb_object_field ( PG_FUNCTION_ARGS  )

Definition at line 704 of file jsonfuncs.c.

References findJsonbValueFromContainerLen(), JB_FOBJECT, JB_ROOT_IS_OBJECT, JsonbValueToJsonb(), PG_GETARG_JSONB_P, PG_GETARG_TEXT_PP, PG_RETURN_JSONB_P, PG_RETURN_NULL, Jsonb::root, VARDATA_ANY, and VARSIZE_ANY_EXHDR.

705 {
706  Jsonb *jb = PG_GETARG_JSONB_P(0);
707  text *key = PG_GETARG_TEXT_PP(1);
708  JsonbValue *v;
709 
710  if (!JB_ROOT_IS_OBJECT(jb))
711  PG_RETURN_NULL();
712 
714  VARDATA_ANY(key),
715  VARSIZE_ANY_EXHDR(key));
716 
717  if (v != NULL)
719 
720  PG_RETURN_NULL();
721 }
#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:3758
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:273
JsonbContainer root
Definition: jsonb.h:218
#define JB_FOBJECT
Definition: jsonb.h:205
#define VARSIZE_ANY_EXHDR(PTR)
Definition: postgres.h:340
Definition: c.h:433
#define PG_RETURN_JSONB_P(x)
Definition: jsonb.h:71
#define PG_RETURN_NULL()
Definition: fmgr.h:305
#define PG_GETARG_JSONB_P(x)
Definition: jsonb.h:70
Datum jsonb_object_field_text ( PG_FUNCTION_ARGS  )

Definition at line 740 of file jsonfuncs.c.

References cstring_to_text(), cstring_to_text_with_len(), StringInfoData::data, DatumGetCString, DirectFunctionCall1, elog, ERROR, findJsonbValueFromContainerLen(), JB_FOBJECT, JB_ROOT_IS_OBJECT, jbvBinary, jbvBool, jbvNull, jbvNumeric, jbvString, JsonbToCString(), StringInfoData::len, makeStringInfo(), numeric_out(), PG_GETARG_JSONB_P, PG_GETARG_TEXT_PP, PG_RETURN_NULL, PG_RETURN_TEXT_P, PointerGetDatum, result, Jsonb::root, JsonbValue::type, JsonbValue::val, VARDATA_ANY, and VARSIZE_ANY_EXHDR.

741 {
742  Jsonb *jb = PG_GETARG_JSONB_P(0);
743  text *key = PG_GETARG_TEXT_PP(1);
744  JsonbValue *v;
745 
746  if (!JB_ROOT_IS_OBJECT(jb))
747  PG_RETURN_NULL();
748 
750  VARDATA_ANY(key),
751  VARSIZE_ANY_EXHDR(key));
752 
753  if (v != NULL)
754  {
755  text *result = NULL;
756 
757  switch (v->type)
758  {
759  case jbvNull:
760  break;
761  case jbvBool:
762  result = cstring_to_text(v->val.boolean ? "true" : "false");
763  break;
764  case jbvString:
765  result = cstring_to_text_with_len(v->val.string.val, v->val.string.len);
766  break;
767  case jbvNumeric:
769  PointerGetDatum(v->val.numeric))));
770  break;
771  case jbvBinary:
772  {
773  StringInfo jtext = makeStringInfo();
774 
775  (void) JsonbToCString(jtext, v->val.binary.data, -1);
776  result = cstring_to_text_with_len(jtext->data, jtext->len);
777  }
778  break;
779  default:
780  elog(ERROR, "unrecognized jsonb type: %d", (int) v->type);
781  }
782 
783  if (result)
784  PG_RETURN_TEXT_P(result);
785  }
786 
787  PG_RETURN_NULL();
788 }
#define JB_ROOT_IS_OBJECT(jbp_)
Definition: jsonb.h:224
#define VARDATA_ANY(PTR)
Definition: postgres.h:347
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:651
static JsonbValue * findJsonbValueFromContainerLen(JsonbContainer *container, uint32 flags, char *key, uint32 keylen)
Definition: jsonfuncs.c:3758
return result
Definition: formatting.c:1633
Definition: jsonb.h:231
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:585
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:273
#define ERROR
Definition: elog.h:43
#define DatumGetCString(X)
Definition: postgres.h:572
text * cstring_to_text_with_len(const char *s, int len)
Definition: varlena.c:161
JsonbContainer root
Definition: jsonb.h:218
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:331
text * cstring_to_text(const char *s)
Definition: varlena.c:149
#define JB_FOBJECT
Definition: jsonb.h:205