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/typcache.h"
Include dependency graph for jsonfuncs.c:

Go to the source code of this file.

Data Structures

struct  OkeysState
 
struct  GetState
 
struct  AlenState
 
struct  EachState
 
struct  ElementsState
 
struct  JhashState
 
struct  JsonHashEntry
 
struct  ColumnIOData
 
struct  RecordIOData
 
struct  PopulateRecordsetState
 
struct  StripnullState
 

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)
 

Typedefs

typedef struct OkeysState OkeysState
 
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 ColumnIOData ColumnIOData
 
typedef struct RecordIOData RecordIOData
 
typedef struct
PopulateRecordsetState 
PopulateRecordsetState
 
typedef struct StripnullState StripnullState
 

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 (text *json, const char *funcname)
 
static Datum populate_record_worker (FunctionCallInfo fcinfo, const char *funcname, bool have_record_arg)
 
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 void make_row_from_rec_and_jsonb (Jsonb *element, PopulateRecordsetState *state)
 
static Datum populate_recordset_worker (FunctionCallInfo fcinfo, const char *funcname, bool have_record_arg)
 
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)
 
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)
 

Macro Definition Documentation

#define JB_PATH_CREATE   0x0001

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

Referenced by setPathArray(), and setPathObject().

#define JB_PATH_DELETE   0x0002

Definition at line 38 of file jsonfuncs.c.

Referenced by jsonb_delete_path(), and setPathObject().

#define JB_PATH_INSERT_AFTER   0x0010

Definition at line 41 of file jsonfuncs.c.

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

#define JB_PATH_INSERT_BEFORE   0x0008

Definition at line 40 of file jsonfuncs.c.

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

#define JB_PATH_REPLACE   0x0004

Definition at line 39 of file jsonfuncs.c.

Referenced by jsonb_set(), and setPathArray().

Typedef Documentation

Function Documentation

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

Definition at line 3291 of file jsonfuncs.c.

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

Referenced by setPathArray(), and setPathObject().

3292 {
3293  JsonbIterator *it;
3294  JsonbValue *o = &(*jbps)->contVal;
3295  JsonbValue v;
3296  JsonbIteratorToken type;
3297 
3298  it = JsonbIteratorInit(&jb->root);
3299 
3300  Assert(o->type == jbvArray || o->type == jbvObject);
3301 
3302  if (JB_ROOT_IS_SCALAR(jb))
3303  {
3304  (void) JsonbIteratorNext(&it, &v, false); /* skip array header */
3305  (void) JsonbIteratorNext(&it, &v, false); /* fetch scalar value */
3306 
3307  switch (o->type)
3308  {
3309  case jbvArray:
3310  (void) pushJsonbValue(jbps, WJB_ELEM, &v);
3311  break;
3312  case jbvObject:
3313  (void) pushJsonbValue(jbps, WJB_VALUE, &v);
3314  break;
3315  default:
3316  elog(ERROR, "unexpected parent of nested structure");
3317  }
3318  }
3319  else
3320  {
3321  while ((type = JsonbIteratorNext(&it, &v, false)) != WJB_DONE)
3322  {
3323  if (type == WJB_KEY || type == WJB_VALUE || type == WJB_ELEM)
3324  (void) pushJsonbValue(jbps, type, &v);
3325  else
3326  (void) pushJsonbValue(jbps, type, NULL);
3327  }
3328  }
3329 
3330 }
Definition: jsonb.h:22
#define JB_ROOT_IS_SCALAR(jbp_)
Definition: jsonb.h:223
JsonbValue * pushJsonbValue(JsonbParseState **pstate, JsonbIteratorToken seq, JsonbValue *jbval)
Definition: jsonb_util.c:517
#define ERROR
Definition: elog.h:43
Definition: jsonb.h:23
JsonbIteratorToken
Definition: jsonb.h:20
JsonbContainer root
Definition: jsonb.h:218
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:671
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 1413 of file jsonfuncs.c.

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

Referenced by json_array_length().

1414 {
1415  AlenState *_state = (AlenState *) state;
1416 
1417  /* just count up all the level 1 elements */
1418  if (_state->lex->lex_level == 1)
1419  _state->count++;
1420 }
int count
Definition: jsonfuncs.c:74
int lex_level
Definition: jsonapi.h:58
JsonLexContext * lex
Definition: jsonfuncs.c:73
Definition: regguts.h:298
static void alen_object_start ( void *  state)
static

Definition at line 1389 of file jsonfuncs.c.

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

Referenced by json_array_length().

1390 {
1391  AlenState *_state = (AlenState *) state;
1392 
1393  /* json structure check */
1394  if (_state->lex->lex_level == 0)
1395  ereport(ERROR,
1396  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1397  errmsg("cannot get array length of a non-array")));
1398 }
int errcode(int sqlerrcode)
Definition: elog.c:575
int lex_level
Definition: jsonapi.h:58
#define ERROR
Definition: elog.h:43
JsonLexContext * lex
Definition: jsonfuncs.c:73
#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 1401 of file jsonfuncs.c.

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

Referenced by json_array_length().

1402 {
1403  AlenState *_state = (AlenState *) state;
1404 
1405  /* json structure check */
1406  if (_state->lex->lex_level == 0)
1407  ereport(ERROR,
1408  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1409  errmsg("cannot get array length of a scalar")));
1410 }
int errcode(int sqlerrcode)
Definition: elog.c:575
int lex_level
Definition: jsonapi.h:58
#define ERROR
Definition: elog.h:43
JsonLexContext * lex
Definition: jsonfuncs.c:73
#define ereport(elevel, rest)
Definition: elog.h:122
Definition: regguts.h:298
int errmsg(const char *fmt,...)
Definition: elog.c:797
static void each_array_start ( void *  state)
static

Definition at line 1723 of file jsonfuncs.c.

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

Referenced by each_worker().

1724 {
1725  EachState *_state = (EachState *) state;
1726 
1727  /* json structure check */
1728  if (_state->lex->lex_level == 0)
1729  ereport(ERROR,
1730  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1731  errmsg("cannot deconstruct an array as an object")));
1732 }
int errcode(int sqlerrcode)
Definition: elog.c:575
int lex_level
Definition: jsonapi.h:58
#define ERROR
Definition: elog.h:43
JsonLexContext * lex
Definition: jsonfuncs.c:80
#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 1677 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().

1678 {
1679  EachState *_state = (EachState *) state;
1680  MemoryContext old_cxt;
1681  int len;
1682  text *val;
1683  HeapTuple tuple;
1684  Datum values[2];
1685  bool nulls[2] = {false, false};
1686 
1687  /* skip over nested objects */
1688  if (_state->lex->lex_level != 1)
1689  return;
1690 
1691  /* use the tmp context so we can clean up after each tuple is done */
1692  old_cxt = MemoryContextSwitchTo(_state->tmp_cxt);
1693 
1694  values[0] = CStringGetTextDatum(fname);
1695 
1696  if (isnull && _state->normalize_results)
1697  {
1698  nulls[1] = true;
1699  values[1] = (Datum) 0;
1700  }
1701  else if (_state->next_scalar)
1702  {
1703  values[1] = CStringGetTextDatum(_state->normalized_scalar);
1704  _state->next_scalar = false;
1705  }
1706  else
1707  {
1708  len = _state->lex->prev_token_terminator - _state->result_start;
1709  val = cstring_to_text_with_len(_state->result_start, len);
1710  values[1] = PointerGetDatum(val);
1711  }
1712 
1713  tuple = heap_form_tuple(_state->ret_tdesc, values, nulls);
1714 
1715  tuplestore_puttuple(_state->tuple_store, tuple);
1716 
1717  /* clean up and switch back */
1718  MemoryContextSwitchTo(old_cxt);
1719  MemoryContextReset(_state->tmp_cxt);
1720 }
Tuplestorestate * tuple_store
Definition: jsonfuncs.c:81
#define PointerGetDatum(X)
Definition: postgres.h:564
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
char * prev_token_terminator
Definition: jsonapi.h:56
void MemoryContextReset(MemoryContext context)
Definition: mcxt.c:135
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:692
TupleDesc ret_tdesc
Definition: jsonfuncs.c:82
int lex_level
Definition: jsonapi.h:58
MemoryContext tmp_cxt
Definition: jsonfuncs.c:83
char * result_start
Definition: jsonfuncs.c:84
JsonLexContext * lex
Definition: jsonfuncs.c:80
void tuplestore_puttuple(Tuplestorestate *state, HeapTuple tuple)
Definition: tuplestore.c:715
text * cstring_to_text_with_len(const char *s, int len)
Definition: varlena.c:163
uintptr_t Datum
Definition: postgres.h:374
bool normalize_results
Definition: jsonfuncs.c:85
char * normalized_scalar
Definition: jsonfuncs.c:87
Definition: regguts.h:298
static Datum values[MAXATTR]
Definition: bootstrap.c:162
#define CStringGetTextDatum(s)
Definition: builtins.h:90
Definition: c.h:435
long val
Definition: informix.c:689
bool next_scalar
Definition: jsonfuncs.c:86
static void each_object_field_start ( void *  state,
char *  fname,
bool  isnull 
)
static

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

1658 {
1659  EachState *_state = (EachState *) state;
1660 
1661  /* save a pointer to where the value starts */
1662  if (_state->lex->lex_level == 1)
1663  {
1664  /*
1665  * next_scalar will be reset in the object_field_end handler, and
1666  * since we know the value is a scalar there is no danger of it being
1667  * on while recursing down the tree.
1668  */
1669  if (_state->normalize_results && _state->lex->token_type == JSON_TOKEN_STRING)
1670  _state->next_scalar = true;
1671  else
1672  _state->result_start = _state->lex->token_start;
1673  }
1674 }
JsonTokenType token_type
Definition: jsonapi.h:57
int lex_level
Definition: jsonapi.h:58
char * result_start
Definition: jsonfuncs.c:84
JsonLexContext * lex
Definition: jsonfuncs.c:80
char * token_start
Definition: jsonapi.h:54
bool normalize_results
Definition: jsonfuncs.c:85
Definition: regguts.h:298
bool next_scalar
Definition: jsonfuncs.c:86
static void each_scalar ( void *  state,
char *  token,
JsonTokenType  tokentype 
)
static

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

1736 {
1737  EachState *_state = (EachState *) state;
1738 
1739  /* json structure check */
1740  if (_state->lex->lex_level == 0)
1741  ereport(ERROR,
1742  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1743  errmsg("cannot deconstruct a scalar")));
1744 
1745  /* supply de-escaped value if required */
1746  if (_state->next_scalar)
1747  _state->normalized_scalar = token;
1748 }
int errcode(int sqlerrcode)
Definition: elog.c:575
int lex_level
Definition: jsonapi.h:58
#define ERROR
Definition: elog.h:43
JsonLexContext * lex
Definition: jsonfuncs.c:80
#define ereport(elevel, rest)
Definition: elog.h:122
char * normalized_scalar
Definition: jsonfuncs.c:87
Definition: regguts.h:298
int errmsg(const char *fmt,...)
Definition: elog.c:797
bool next_scalar
Definition: jsonfuncs.c:86
static Datum each_worker ( FunctionCallInfo  fcinfo,
bool  as_text 
)
static

Definition at line 1593 of file jsonfuncs.c.

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate(), ReturnSetInfo::allowedModes, JsonSemAction::array_start, BlessTupleDesc(), CreateTupleDescCopy(), CurrentMemoryContext, each_array_start(), each_object_field_end(), each_object_field_start(), each_scalar(), ReturnSetInfo::econtext, ExprContext::ecxt_per_query_memory, ereport, errcode(), errmsg(), ERROR, ReturnSetInfo::expectedDesc, get_call_result_type(), IsA, EachState::lex, makeJsonLexContext(), MemoryContextDelete(), MemoryContextSwitchTo(), EachState::next_scalar, EachState::normalize_results, NULL, JsonSemAction::object_field_end, JsonSemAction::object_field_start, palloc0(), PG_GETARG_TEXT_P, 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().

1594 {
1595  text *json = PG_GETARG_TEXT_P(0);
1596  JsonLexContext *lex;
1597  JsonSemAction *sem;
1598  ReturnSetInfo *rsi;
1599  MemoryContext old_cxt;
1600  TupleDesc tupdesc;
1601  EachState *state;
1602 
1603  lex = makeJsonLexContext(json, true);
1604  state = palloc0(sizeof(EachState));
1605  sem = palloc0(sizeof(JsonSemAction));
1606 
1607  rsi = (ReturnSetInfo *) fcinfo->resultinfo;
1608 
1609  if (!rsi || !IsA(rsi, ReturnSetInfo) ||
1610  (rsi->allowedModes & SFRM_Materialize) == 0 ||
1611  rsi->expectedDesc == NULL)
1612  ereport(ERROR,
1613  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1614  errmsg("set-valued function called in context that "
1615  "cannot accept a set")));
1616 
1618 
1619  (void) get_call_result_type(fcinfo, NULL, &tupdesc);
1620 
1621  /* make these in a sufficiently long-lived memory context */
1623 
1624  state->ret_tdesc = CreateTupleDescCopy(tupdesc);
1625  BlessTupleDesc(state->ret_tdesc);
1626  state->tuple_store =
1628  false, work_mem);
1629 
1630  MemoryContextSwitchTo(old_cxt);
1631 
1632  sem->semstate = (void *) state;
1634  sem->scalar = each_scalar;
1637 
1638  state->normalize_results = as_text;
1639  state->next_scalar = false;
1640  state->lex = lex;
1642  "json_each temporary cxt",
1644 
1645  pg_parse_json(lex, sem);
1646 
1647  MemoryContextDelete(state->tmp_cxt);
1648 
1649  rsi->setResult = state->tuple_store;
1650  rsi->setDesc = state->ret_tdesc;
1651 
1652  PG_RETURN_NULL();
1653 }
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
Definition: tupdesc.c:141
#define IsA(nodeptr, _type_)
Definition: nodes.h:559
Tuplestorestate * tuple_store
Definition: jsonfuncs.c:81
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:200
static void each_object_field_start(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:1657
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:92
static void each_array_start(void *state)
Definition: jsonfuncs.c:1723
TupleDesc ret_tdesc
Definition: jsonfuncs.c:82
MemoryContext tmp_cxt
Definition: jsonfuncs.c:83
static void each_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:1735
TupleDesc expectedDesc
Definition: execnodes.h:198
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:145
JsonLexContext * lex
Definition: jsonfuncs.c:80
TupleDesc BlessTupleDesc(TupleDesc tupdesc)
Definition: execTuples.c:1031
fmNodePtr resultinfo
Definition: fmgr.h:73
MemoryContext CurrentMemoryContext
Definition: mcxt.c:37
#define ereport(elevel, rest)
Definition: elog.h:122
json_ofield_action object_field_end
Definition: jsonapi.h:89
Tuplestorestate * tuplestore_begin_heap(bool randomAccess, bool interXact, int maxKBytes)
Definition: tuplestore.c:316
MemoryContext AllocSetContextCreate(MemoryContext parent, const char *name, Size minContextSize, Size initBlockSize, Size maxBlockSize)
Definition: aset.c:440
void * palloc0(Size size)
Definition: mcxt.c:920
bool normalize_results
Definition: jsonfuncs.c:85
int work_mem
Definition: globals.c:112
int allowedModes
Definition: execnodes.h:199
SetFunctionReturnMode returnMode
Definition: execnodes.h:201
#define NULL
Definition: c.h:226
json_struct_action array_start
Definition: jsonapi.h:86
Definition: regguts.h:298
MemoryContext ecxt_per_query_memory
Definition: execnodes.h:133
Tuplestorestate * setResult
Definition: execnodes.h:204
ExprContext * econtext
Definition: execnodes.h:197
TupleDesc setDesc
Definition: execnodes.h:205
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define PG_GETARG_TEXT_P(n)
Definition: fmgr.h:269
Definition: c.h:435
json_ofield_action object_field_start
Definition: jsonapi.h:88
void * semstate
Definition: jsonapi.h:83
static void each_object_field_end(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:1677
#define PG_RETURN_NULL()
Definition: fmgr.h:289
bool next_scalar
Definition: jsonfuncs.c:86
static Datum each_worker_jsonb ( FunctionCallInfo  fcinfo,
const char *  funcname,
bool  as_text 
)
static

Definition at line 1457 of file jsonfuncs.c.

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

Referenced by jsonb_each(), and jsonb_each_text().

1458 {
1459  Jsonb *jb = PG_GETARG_JSONB(0);
1460  ReturnSetInfo *rsi;
1461  Tuplestorestate *tuple_store;
1462  TupleDesc tupdesc;
1463  TupleDesc ret_tdesc;
1464  MemoryContext old_cxt,
1465  tmp_cxt;
1466  bool skipNested = false;
1467  JsonbIterator *it;
1468  JsonbValue v;
1470 
1471  if (!JB_ROOT_IS_OBJECT(jb))
1472  ereport(ERROR,
1473  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1474  errmsg("cannot call %s on a non-object",
1475  funcname)));
1476 
1477  rsi = (ReturnSetInfo *) fcinfo->resultinfo;
1478 
1479  if (!rsi || !IsA(rsi, ReturnSetInfo) ||
1480  (rsi->allowedModes & SFRM_Materialize) == 0 ||
1481  rsi->expectedDesc == NULL)
1482  ereport(ERROR,
1483  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1484  errmsg("set-valued function called in context that "
1485  "cannot accept a set")));
1486 
1488 
1489  if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
1490  ereport(ERROR,
1491  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1492  errmsg("function returning record called in context "
1493  "that cannot accept type record")));
1494 
1496 
1497  ret_tdesc = CreateTupleDescCopy(tupdesc);
1498  BlessTupleDesc(ret_tdesc);
1499  tuple_store =
1501  false, work_mem);
1502 
1503  MemoryContextSwitchTo(old_cxt);
1504 
1506  "jsonb_each temporary cxt",
1508 
1509  it = JsonbIteratorInit(&jb->root);
1510 
1511  while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE)
1512  {
1513  skipNested = true;
1514 
1515  if (r == WJB_KEY)
1516  {
1517  text *key;
1518  HeapTuple tuple;
1519  Datum values[2];
1520  bool nulls[2] = {false, false};
1521 
1522  /* Use the tmp context so we can clean up after each tuple is done */
1523  old_cxt = MemoryContextSwitchTo(tmp_cxt);
1524 
1525  key = cstring_to_text_with_len(v.val.string.val, v.val.string.len);
1526 
1527  /*
1528  * The next thing the iterator fetches should be the value, no
1529  * matter what shape it is.
1530  */
1531  r = JsonbIteratorNext(&it, &v, skipNested);
1532 
1533  values[0] = PointerGetDatum(key);
1534 
1535  if (as_text)
1536  {
1537  if (v.type == jbvNull)
1538  {
1539  /* a json null is an sql null in text mode */
1540  nulls[1] = true;
1541  values[1] = (Datum) NULL;
1542  }
1543  else
1544  {
1545  text *sv;
1546 
1547  if (v.type == jbvString)
1548  {
1549  /* In text mode, scalar strings should be dequoted */
1550  sv = cstring_to_text_with_len(v.val.string.val, v.val.string.len);
1551  }
1552  else
1553  {
1554  /* Turn anything else into a json string */
1555  StringInfo jtext = makeStringInfo();
1556  Jsonb *jb = JsonbValueToJsonb(&v);
1557 
1558  (void) JsonbToCString(jtext, &jb->root, 0);
1559  sv = cstring_to_text_with_len(jtext->data, jtext->len);
1560  }
1561 
1562  values[1] = PointerGetDatum(sv);
1563  }
1564  }
1565  else
1566  {
1567  /* Not in text mode, just return the Jsonb */
1568  Jsonb *val = JsonbValueToJsonb(&v);
1569 
1570  values[1] = PointerGetDatum(val);
1571  }
1572 
1573  tuple = heap_form_tuple(ret_tdesc, values, nulls);
1574 
1575  tuplestore_puttuple(tuple_store, tuple);
1576 
1577  /* clean up and switch back */
1578  MemoryContextSwitchTo(old_cxt);
1579  MemoryContextReset(tmp_cxt);
1580  }
1581  }
1582 
1583  MemoryContextDelete(tmp_cxt);
1584 
1585  rsi->setResult = tuple_store;
1586  rsi->setDesc = ret_tdesc;
1587 
1588  PG_RETURN_NULL();
1589 }
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
Definition: tupdesc.c:141
#define IsA(nodeptr, _type_)
Definition: nodes.h:559
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:564
char * val
Definition: jsonb.h:259
StringInfo makeStringInfo(void)
Definition: stringinfo.c:29
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
Definition: jsonb.h:22
int errcode(int sqlerrcode)
Definition: elog.c:575
void MemoryContextReset(MemoryContext context)
Definition: mcxt.c:135
Definition: jsonb.h:231
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:692
TupleDesc expectedDesc
Definition: execnodes.h:198
#define ERROR
Definition: elog.h:43
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:145
void tuplestore_puttuple(Tuplestorestate *state, HeapTuple tuple)
Definition: tuplestore.c:715
TupleDesc BlessTupleDesc(TupleDesc tupdesc)
Definition: execTuples.c:1031
text * cstring_to_text_with_len(const char *s, int len)
Definition: varlena.c:163
fmNodePtr resultinfo
Definition: fmgr.h:73
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:316
MemoryContext AllocSetContextCreate(MemoryContext parent, const char *name, Size minContextSize, Size initBlockSize, Size maxBlockSize)
Definition: aset.c:440
uintptr_t Datum
Definition: postgres.h:374
int work_mem
Definition: globals.c:112
int allowedModes
Definition: execnodes.h:199
SetFunctionReturnMode returnMode
Definition: execnodes.h:201
#define NULL
Definition: c.h:226
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:133
enum jbvType type
Definition: jsonb.h:250
Tuplestorestate * setResult
Definition: execnodes.h:204
static Datum values[MAXATTR]
Definition: bootstrap.c:162
ExprContext * econtext
Definition: execnodes.h:197
#define PG_GETARG_JSONB(x)
Definition: jsonb.h:70
TupleDesc setDesc
Definition: execnodes.h:205
int errmsg(const char *fmt,...)
Definition: elog.c:797
Definition: c.h:435
long val
Definition: informix.c:689
#define PG_RETURN_NULL()
Definition: fmgr.h:289
JsonbIteratorToken JsonbIteratorNext(JsonbIterator **it, JsonbValue *val, bool skipNested)
Definition: jsonb_util.c:754
static void elements_array_element_end ( void *  state,
bool  isnull 
)
static

Definition at line 1993 of file jsonfuncs.c.

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

Referenced by elements_worker().

1994 {
1995  ElementsState *_state = (ElementsState *) state;
1996  MemoryContext old_cxt;
1997  int len;
1998  text *val;
1999  HeapTuple tuple;
2000  Datum values[1];
2001  bool nulls[1] = {false};
2002 
2003  /* skip over nested objects */
2004  if (_state->lex->lex_level != 1)
2005  return;
2006 
2007  /* use the tmp context so we can clean up after each tuple is done */
2008  old_cxt = MemoryContextSwitchTo(_state->tmp_cxt);
2009 
2010  if (isnull && _state->normalize_results)
2011  {
2012  nulls[0] = true;
2013  values[0] = (Datum) NULL;
2014  }
2015  else if (_state->next_scalar)
2016  {
2017  values[0] = CStringGetTextDatum(_state->normalized_scalar);
2018  _state->next_scalar = false;
2019  }
2020  else
2021  {
2022  len = _state->lex->prev_token_terminator - _state->result_start;
2023  val = cstring_to_text_with_len(_state->result_start, len);
2024  values[0] = PointerGetDatum(val);
2025  }
2026 
2027  tuple = heap_form_tuple(_state->ret_tdesc, values, nulls);
2028 
2029  tuplestore_puttuple(_state->tuple_store, tuple);
2030 
2031  /* clean up and switch back */
2032  MemoryContextSwitchTo(old_cxt);
2033  MemoryContextReset(_state->tmp_cxt);
2034 }
bool normalize_results
Definition: jsonfuncs.c:99
JsonLexContext * lex
Definition: jsonfuncs.c:93
bool next_scalar
Definition: jsonfuncs.c:100
#define PointerGetDatum(X)
Definition: postgres.h:564
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
char * prev_token_terminator
Definition: jsonapi.h:56
void MemoryContextReset(MemoryContext context)
Definition: mcxt.c:135
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:692
int lex_level
Definition: jsonapi.h:58
TupleDesc ret_tdesc
Definition: jsonfuncs.c:96
void tuplestore_puttuple(Tuplestorestate *state, HeapTuple tuple)
Definition: tuplestore.c:715
text * cstring_to_text_with_len(const char *s, int len)
Definition: varlena.c:163
uintptr_t Datum
Definition: postgres.h:374
Tuplestorestate * tuple_store
Definition: jsonfuncs.c:95
#define NULL
Definition: c.h:226
char * result_start
Definition: jsonfuncs.c:98
Definition: regguts.h:298
static Datum values[MAXATTR]
Definition: bootstrap.c:162
char * normalized_scalar
Definition: jsonfuncs.c:101
#define CStringGetTextDatum(s)
Definition: builtins.h:90
MemoryContext tmp_cxt
Definition: jsonfuncs.c:97
Definition: c.h:435
long val
Definition: informix.c:689
static void elements_array_element_start ( void *  state,
bool  isnull 
)
static

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

1974 {
1975  ElementsState *_state = (ElementsState *) state;
1976 
1977  /* save a pointer to where the value starts */
1978  if (_state->lex->lex_level == 1)
1979  {
1980  /*
1981  * next_scalar will be reset in the array_element_end handler, and
1982  * since we know the value is a scalar there is no danger of it being
1983  * on while recursing down the tree.
1984  */
1985  if (_state->normalize_results && _state->lex->token_type == JSON_TOKEN_STRING)
1986  _state->next_scalar = true;
1987  else
1988  _state->result_start = _state->lex->token_start;
1989  }
1990 }
bool normalize_results
Definition: jsonfuncs.c:99
JsonLexContext * lex
Definition: jsonfuncs.c:93
bool next_scalar
Definition: jsonfuncs.c:100
JsonTokenType token_type
Definition: jsonapi.h:57
int lex_level
Definition: jsonapi.h:58
char * token_start
Definition: jsonapi.h:54
char * result_start
Definition: jsonfuncs.c:98
Definition: regguts.h:298
static void elements_object_start ( void *  state)
static

Definition at line 2037 of file jsonfuncs.c.

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

Referenced by elements_worker().

2038 {
2039  ElementsState *_state = (ElementsState *) state;
2040 
2041  /* json structure check */
2042  if (_state->lex->lex_level == 0)
2043  ereport(ERROR,
2044  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2045  errmsg("cannot call %s on a non-array",
2046  _state->function_name)));
2047 }
const char * function_name
Definition: jsonfuncs.c:94
JsonLexContext * lex
Definition: jsonfuncs.c:93
int errcode(int sqlerrcode)
Definition: elog.c:575
int lex_level
Definition: jsonapi.h:58
#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 2050 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().

2051 {
2052  ElementsState *_state = (ElementsState *) state;
2053 
2054  /* json structure check */
2055  if (_state->lex->lex_level == 0)
2056  ereport(ERROR,
2057  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2058  errmsg("cannot call %s on a scalar",
2059  _state->function_name)));
2060 
2061  /* supply de-escaped value if required */
2062  if (_state->next_scalar)
2063  _state->normalized_scalar = token;
2064 }
const char * function_name
Definition: jsonfuncs.c:94
JsonLexContext * lex
Definition: jsonfuncs.c:93
bool next_scalar
Definition: jsonfuncs.c:100
int errcode(int sqlerrcode)
Definition: elog.c:575
int lex_level
Definition: jsonapi.h:58
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:122
Definition: regguts.h:298
char * normalized_scalar
Definition: jsonfuncs.c:101
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 1907 of file jsonfuncs.c.

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate(), ReturnSetInfo::allowedModes, JsonSemAction::array_element_end, JsonSemAction::array_element_start, BlessTupleDesc(), CreateTupleDescCopy(), CurrentMemoryContext, ReturnSetInfo::econtext, ExprContext::ecxt_per_query_memory, elements_array_element_end(), elements_array_element_start(), elements_object_start(), elements_scalar(), ereport, errcode(), errmsg(), ERROR, ReturnSetInfo::expectedDesc, ElementsState::function_name, IsA, ElementsState::lex, makeJsonLexContext(), MemoryContextDelete(), MemoryContextSwitchTo(), ElementsState::next_scalar, ElementsState::normalize_results, NULL, JsonSemAction::object_start, palloc0(), PG_GETARG_TEXT_P, 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().

1908 {
1909  text *json = PG_GETARG_TEXT_P(0);
1910 
1911  /* elements only needs escaped strings when as_text */
1912  JsonLexContext *lex = makeJsonLexContext(json, as_text);
1913  JsonSemAction *sem;
1914  ReturnSetInfo *rsi;
1915  MemoryContext old_cxt;
1916  TupleDesc tupdesc;
1918 
1919  state = palloc0(sizeof(ElementsState));
1920  sem = palloc0(sizeof(JsonSemAction));
1921 
1922  rsi = (ReturnSetInfo *) fcinfo->resultinfo;
1923 
1924  if (!rsi || !IsA(rsi, ReturnSetInfo) ||
1925  (rsi->allowedModes & SFRM_Materialize) == 0 ||
1926  rsi->expectedDesc == NULL)
1927  ereport(ERROR,
1928  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1929  errmsg("set-valued function called in context that "
1930  "cannot accept a set")));
1931 
1933 
1934  /* it's a simple type, so don't use get_call_result_type() */
1935  tupdesc = rsi->expectedDesc;
1936 
1937  /* make these in a sufficiently long-lived memory context */
1939 
1940  state->ret_tdesc = CreateTupleDescCopy(tupdesc);
1941  BlessTupleDesc(state->ret_tdesc);
1942  state->tuple_store =
1944  false, work_mem);
1945 
1946  MemoryContextSwitchTo(old_cxt);
1947 
1948  sem->semstate = (void *) state;
1950  sem->scalar = elements_scalar;
1953 
1954  state->function_name = funcname;
1955  state->normalize_results = as_text;
1956  state->next_scalar = false;
1957  state->lex = lex;
1959  "json_array_elements temporary cxt",
1961 
1962  pg_parse_json(lex, sem);
1963 
1964  MemoryContextDelete(state->tmp_cxt);
1965 
1966  rsi->setResult = state->tuple_store;
1967  rsi->setDesc = state->ret_tdesc;
1968 
1969  PG_RETURN_NULL();
1970 }
bool normalize_results
Definition: jsonfuncs.c:99
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
Definition: tupdesc.c:141
#define IsA(nodeptr, _type_)
Definition: nodes.h:559
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:200
const char * function_name
Definition: jsonfuncs.c:94
JsonLexContext * lex
Definition: jsonfuncs.c:93
static void elements_object_start(void *state)
Definition: jsonfuncs.c:2037
bool next_scalar
Definition: jsonfuncs.c:100
json_struct_action object_start
Definition: jsonapi.h:84
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
int errcode(int sqlerrcode)
Definition: elog.c:575
json_scalar_action scalar
Definition: jsonapi.h:92
TupleDesc expectedDesc
Definition: execnodes.h:198
TupleDesc ret_tdesc
Definition: jsonfuncs.c:96
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:145
TupleDesc BlessTupleDesc(TupleDesc tupdesc)
Definition: execTuples.c:1031
fmNodePtr resultinfo
Definition: fmgr.h:73
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:1973
Tuplestorestate * tuplestore_begin_heap(bool randomAccess, bool interXact, int maxKBytes)
Definition: tuplestore.c:316
MemoryContext AllocSetContextCreate(MemoryContext parent, const char *name, Size minContextSize, Size initBlockSize, Size maxBlockSize)
Definition: aset.c:440
static void elements_array_element_end(void *state, bool isnull)
Definition: jsonfuncs.c:1993
void * palloc0(Size size)
Definition: mcxt.c:920
static void elements_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:2050
json_aelem_action array_element_start
Definition: jsonapi.h:90
Tuplestorestate * tuple_store
Definition: jsonfuncs.c:95
int work_mem
Definition: globals.c:112
int allowedModes
Definition: execnodes.h:199
SetFunctionReturnMode returnMode
Definition: execnodes.h:201
#define NULL
Definition: c.h:226
Definition: regguts.h:298
MemoryContext ecxt_per_query_memory
Definition: execnodes.h:133
Tuplestorestate * setResult
Definition: execnodes.h:204
ExprContext * econtext
Definition: execnodes.h:197
TupleDesc setDesc
Definition: execnodes.h:205
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define PG_GETARG_TEXT_P(n)
Definition: fmgr.h:269
MemoryContext tmp_cxt
Definition: jsonfuncs.c:97
Definition: c.h:435
void * semstate
Definition: jsonapi.h:83
#define PG_RETURN_NULL()
Definition: fmgr.h:289
json_aelem_action array_element_end
Definition: jsonapi.h:91
static Datum elements_worker_jsonb ( FunctionCallInfo  fcinfo,
const char *  funcname,
bool  as_text 
)
static

Definition at line 1771 of file jsonfuncs.c.

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

Referenced by jsonb_array_elements(), and jsonb_array_elements_text().

1773 {
1774  Jsonb *jb = PG_GETARG_JSONB(0);
1775  ReturnSetInfo *rsi;
1776  Tuplestorestate *tuple_store;
1777  TupleDesc tupdesc;
1778  TupleDesc ret_tdesc;
1779  MemoryContext old_cxt,
1780  tmp_cxt;
1781  bool skipNested = false;
1782  JsonbIterator *it;
1783  JsonbValue v;
1785 
1786  if (JB_ROOT_IS_SCALAR(jb))
1787  ereport(ERROR,
1788  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1789  errmsg("cannot extract elements from a scalar")));
1790  else if (!JB_ROOT_IS_ARRAY(jb))
1791  ereport(ERROR,
1792  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1793  errmsg("cannot extract elements from an object")));
1794 
1795  rsi = (ReturnSetInfo *) fcinfo->resultinfo;
1796 
1797  if (!rsi || !IsA(rsi, ReturnSetInfo) ||
1798  (rsi->allowedModes & SFRM_Materialize) == 0 ||
1799  rsi->expectedDesc == NULL)
1800  ereport(ERROR,
1801  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1802  errmsg("set-valued function called in context that "
1803  "cannot accept a set")));
1804 
1806 
1807  /* it's a simple type, so don't use get_call_result_type() */
1808  tupdesc = rsi->expectedDesc;
1809 
1811 
1812  ret_tdesc = CreateTupleDescCopy(tupdesc);
1813  BlessTupleDesc(ret_tdesc);
1814  tuple_store =
1816  false, work_mem);
1817 
1818  MemoryContextSwitchTo(old_cxt);
1819 
1821  "jsonb_array_elements temporary cxt",
1823 
1824  it = JsonbIteratorInit(&jb->root);
1825 
1826  while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE)
1827  {
1828  skipNested = true;
1829 
1830  if (r == WJB_ELEM)
1831  {
1832  HeapTuple tuple;
1833  Datum values[1];
1834  bool nulls[1] = {false};
1835 
1836  /* use the tmp context so we can clean up after each tuple is done */
1837  old_cxt = MemoryContextSwitchTo(tmp_cxt);
1838 
1839  if (!as_text)
1840  {
1841  Jsonb *val = JsonbValueToJsonb(&v);
1842 
1843  values[0] = PointerGetDatum(val);
1844  }
1845  else
1846  {
1847  if (v.type == jbvNull)
1848  {
1849  /* a json null is an sql null in text mode */
1850  nulls[0] = true;
1851  values[0] = (Datum) NULL;
1852  }
1853  else
1854  {
1855  text *sv;
1856 
1857  if (v.type == jbvString)
1858  {
1859  /* in text mode scalar strings should be dequoted */
1860  sv = cstring_to_text_with_len(v.val.string.val, v.val.string.len);
1861  }
1862  else
1863  {
1864  /* turn anything else into a json string */
1865  StringInfo jtext = makeStringInfo();
1866  Jsonb *jb = JsonbValueToJsonb(&v);
1867 
1868  (void) JsonbToCString(jtext, &jb->root, 0);
1869  sv = cstring_to_text_with_len(jtext->data, jtext->len);
1870  }
1871 
1872  values[0] = PointerGetDatum(sv);
1873  }
1874  }
1875 
1876  tuple = heap_form_tuple(ret_tdesc, values, nulls);
1877 
1878  tuplestore_puttuple(tuple_store, tuple);
1879 
1880  /* clean up and switch back */
1881  MemoryContextSwitchTo(old_cxt);
1882  MemoryContextReset(tmp_cxt);
1883  }
1884  }
1885 
1886  MemoryContextDelete(tmp_cxt);
1887 
1888  rsi->setResult = tuple_store;
1889  rsi->setDesc = ret_tdesc;
1890 
1891  PG_RETURN_NULL();
1892 }
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
Definition: tupdesc.c:141
#define IsA(nodeptr, _type_)
Definition: nodes.h:559
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:564
char * val
Definition: jsonb.h:259
StringInfo makeStringInfo(void)
Definition: stringinfo.c:29
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
Definition: jsonb.h:22
int errcode(int sqlerrcode)
Definition: elog.c:575
void MemoryContextReset(MemoryContext context)
Definition: mcxt.c:135
Definition: jsonb.h:231
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:692
#define JB_ROOT_IS_SCALAR(jbp_)
Definition: jsonb.h:223
TupleDesc expectedDesc
Definition: execnodes.h:198
#define ERROR
Definition: elog.h:43
#define JB_ROOT_IS_ARRAY(jbp_)
Definition: jsonb.h:225
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:145
void tuplestore_puttuple(Tuplestorestate *state, HeapTuple tuple)
Definition: tuplestore.c:715
TupleDesc BlessTupleDesc(TupleDesc tupdesc)
Definition: execTuples.c:1031
text * cstring_to_text_with_len(const char *s, int len)
Definition: varlena.c:163
fmNodePtr resultinfo
Definition: fmgr.h:73
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:316
MemoryContext AllocSetContextCreate(MemoryContext parent, const char *name, Size minContextSize, Size initBlockSize, Size maxBlockSize)
Definition: aset.c:440
uintptr_t Datum
Definition: postgres.h:374
int work_mem
Definition: globals.c:112
int allowedModes
Definition: execnodes.h:199
SetFunctionReturnMode returnMode
Definition: execnodes.h:201
#define NULL
Definition: c.h:226
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:133
enum jbvType type
Definition: jsonb.h:250
Tuplestorestate * setResult
Definition: execnodes.h:204
static Datum values[MAXATTR]
Definition: bootstrap.c:162
ExprContext * econtext
Definition: execnodes.h:197
#define PG_GETARG_JSONB(x)
Definition: jsonb.h:70
TupleDesc setDesc
Definition: execnodes.h:205
int errmsg(const char *fmt,...)
Definition: elog.c:797
Definition: c.h:435
long val
Definition: informix.c:689
#define PG_RETURN_NULL()
Definition: fmgr.h:289
JsonbIteratorToken JsonbIteratorNext(JsonbIterator **it, JsonbValue *val, bool skipNested)
Definition: jsonb_util.c:754
Definition: jsonb.h:25
static JsonbValue * findJsonbValueFromContainerLen ( JsonbContainer container,
uint32  flags,
char *  key,
uint32  keylen 
)
static

Definition at line 3082 of file jsonfuncs.c.

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

Referenced by get_jsonb_path_all(), jsonb_object_field(), jsonb_object_field_text(), make_row_from_rec_and_jsonb(), and populate_record_worker().

3084 {
3085  JsonbValue k;
3086 
3087  k.type = jbvString;
3088  k.val.string.val = key;
3089  k.val.string.len = keylen;
3090 
3091  return findJsonbValueFromContainer(container, flags, &k);
3092 }
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 1076 of file jsonfuncs.c.

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

Referenced by get_worker().

1077 {
1078  GetState *_state = (GetState *) state;
1079  bool get_last = false;
1080  int lex_level = _state->lex->lex_level;
1081 
1082  /* same tests as in get_array_element_start */
1083  if (lex_level <= _state->npath &&
1084  _state->pathok[lex_level - 1] &&
1085  _state->path_indexes != NULL &&
1086  _state->array_cur_index[lex_level - 1] == _state->path_indexes[lex_level - 1])
1087  {
1088  if (lex_level < _state->npath)
1089  {
1090  /* done with this element so reset pathok */
1091  _state->pathok[lex_level] = false;
1092  }
1093  else
1094  {
1095  /* end of path, so we want this value */
1096  get_last = true;
1097  }
1098  }
1099 
1100  /* same logic as for objects */
1101  if (get_last && _state->result_start != NULL)
1102  {
1103  if (isnull && _state->normalize_results)
1104  _state->tresult = (text *) NULL;
1105  else
1106  {
1107  char *start = _state->result_start;
1108  int len = _state->lex->prev_token_terminator - start;
1109 
1110  _state->tresult = cstring_to_text_with_len(start, len);
1111  }
1112 
1113  _state->result_start = NULL;
1114  }
1115 }
int * array_cur_index
Definition: jsonfuncs.c:67
char * prev_token_terminator
Definition: jsonapi.h:56
int lex_level
Definition: jsonapi.h:58
JsonLexContext * lex
Definition: jsonfuncs.c:58
char * result_start
Definition: jsonfuncs.c:60
text * tresult
Definition: jsonfuncs.c:59
text * cstring_to_text_with_len(const char *s, int len)
Definition: varlena.c:163
bool * pathok
Definition: jsonfuncs.c:66
bool normalize_results
Definition: jsonfuncs.c:61
#define NULL
Definition: c.h:226
Definition: regguts.h:298
int * path_indexes
Definition: jsonfuncs.c:65
Definition: c.h:435
static void get_array_element_start ( void *  state,
bool  isnull 
)
static

Definition at line 1030 of file jsonfuncs.c.

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

Referenced by get_worker().

1031 {
1032  GetState *_state = (GetState *) state;
1033  bool get_next = false;
1034  int lex_level = _state->lex->lex_level;
1035 
1036  /* Update array element counter */
1037  if (lex_level <= _state->npath)
1038  _state->array_cur_index[lex_level - 1]++;
1039 
1040  if (lex_level <= _state->npath &&
1041  _state->pathok[lex_level - 1] &&
1042  _state->path_indexes != NULL &&
1043  _state->array_cur_index[lex_level - 1] == _state->path_indexes[lex_level - 1])
1044  {
1045  if (lex_level < _state->npath)
1046  {
1047  /* if not at end of path just mark path ok */
1048  _state->pathok[lex_level] = true;
1049  }
1050  else
1051  {
1052  /* end of path, so we want this value */
1053  get_next = true;
1054  }
1055  }
1056 
1057  /* same logic as for objects */
1058  if (get_next)
1059  {
1060  _state->tresult = NULL;
1061  _state->result_start = NULL;
1062 
1063  if (_state->normalize_results &&
1064  _state->lex->token_type == JSON_TOKEN_STRING)
1065  {
1066  _state->next_scalar = true;
1067  }
1068  else
1069  {
1070  _state->result_start = _state->lex->token_start;
1071  }
1072  }
1073 }
int * array_cur_index
Definition: jsonfuncs.c:67
JsonTokenType token_type
Definition: jsonapi.h:57
int lex_level
Definition: jsonapi.h:58
JsonLexContext * lex
Definition: jsonfuncs.c:58
char * result_start
Definition: jsonfuncs.c:60
text * tresult
Definition: jsonfuncs.c:59
char * token_start
Definition: jsonapi.h:54
bool * pathok
Definition: jsonfuncs.c:66
bool normalize_results
Definition: jsonfuncs.c:61
bool next_scalar
Definition: jsonfuncs.c:62
#define NULL
Definition: c.h:226
Definition: regguts.h:298
int * path_indexes
Definition: jsonfuncs.c:65
static void get_array_end ( void *  state)
static

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

1015 {
1016  GetState *_state = (GetState *) state;
1017  int lex_level = _state->lex->lex_level;
1018 
1019  if (lex_level == 0 && _state->npath == 0)
1020  {
1021  /* Special case: return the entire array */
1022  char *start = _state->result_start;
1023  int len = _state->lex->prev_token_terminator - start;
1024 
1025  _state->tresult = cstring_to_text_with_len(start, len);
1026  }
1027 }
char * prev_token_terminator
Definition: jsonapi.h:56
int lex_level
Definition: jsonapi.h:58
JsonLexContext * lex
Definition: jsonfuncs.c:58
char * result_start
Definition: jsonfuncs.c:60
text * tresult
Definition: jsonfuncs.c:59
text * cstring_to_text_with_len(const char *s, int len)
Definition: varlena.c:163
int npath
Definition: jsonfuncs.c:63
Definition: regguts.h:298
static void get_array_start ( void *  state)
static

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

982 {
983  GetState *_state = (GetState *) state;
984  int lex_level = _state->lex->lex_level;
985 
986  if (lex_level < _state->npath)
987  {
988  /* Initialize counting of elements in this array */
989  _state->array_cur_index[lex_level] = -1;
990 
991  /* INT_MIN value is reserved to represent invalid subscript */
992  if (_state->path_indexes[lex_level] < 0 &&
993  _state->path_indexes[lex_level] != INT_MIN)
994  {
995  /* Negative subscript -- convert to positive-wise subscript */
996  int nelements = json_count_array_elements(_state->lex);
997 
998  if (-_state->path_indexes[lex_level] <= nelements)
999  _state->path_indexes[lex_level] += nelements;
1000  }
1001  }
1002  else if (lex_level == 0 && _state->npath == 0)
1003  {
1004  /*
1005  * Special case: we should match the entire array. We only need this
1006  * at the outermost level because at nested levels the match will have
1007  * been started by the outer field or array element callback.
1008  */
1009  _state->result_start = _state->lex->token_start;
1010  }
1011 }
int * array_cur_index
Definition: jsonfuncs.c:67
int lex_level
Definition: jsonapi.h:58
JsonLexContext * lex
Definition: jsonfuncs.c:58
char * result_start
Definition: jsonfuncs.c:60
int npath
Definition: jsonfuncs.c:63
int json_count_array_elements(JsonLexContext *lex)
Definition: json.c:366
char * token_start
Definition: jsonapi.h:54
Definition: regguts.h:298
int * path_indexes
Definition: jsonfuncs.c:65
static HTAB * get_json_object_as_hash ( text json,
const char *  funcname 
)
static

Definition at line 2377 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, makeJsonLexContext(), NAMEDATALEN, JsonSemAction::object_field_end, JsonSemAction::object_field_start, palloc0(), pg_parse_json(), JsonSemAction::scalar, and JsonSemAction::semstate.

Referenced by populate_record_worker().

2378 {
2379  HASHCTL ctl;
2380  HTAB *tab;
2381  JHashState *state;
2382  JsonLexContext *lex = makeJsonLexContext(json, true);
2383  JsonSemAction *sem;
2384 
2385  memset(&ctl, 0, sizeof(ctl));
2386  ctl.keysize = NAMEDATALEN;
2387  ctl.entrysize = sizeof(JsonHashEntry);
2388  ctl.hcxt = CurrentMemoryContext;
2389  tab = hash_create("json object hashtable",
2390  100,
2391  &ctl,
2393 
2394  state = palloc0(sizeof(JHashState));
2395  sem = palloc0(sizeof(JsonSemAction));
2396 
2397  state->function_name = funcname;
2398  state->hash = tab;
2399  state->lex = lex;
2400 
2401  sem->semstate = (void *) state;
2403  sem->scalar = hash_scalar;
2406 
2407  pg_parse_json(lex, sem);
2408 
2409  return tab;
2410 }
#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:2434
json_scalar_action scalar
Definition: jsonapi.h:92
#define NAMEDATALEN
Definition: dynahash.c:193
JsonLexContext * makeJsonLexContext(text *json, bool need_escapes)
Definition: json.c:300
void pg_parse_json(JsonLexContext *lex, JsonSemAction *sem)
Definition: json.c:331
MemoryContext CurrentMemoryContext
Definition: mcxt.c:37
json_ofield_action object_field_end
Definition: jsonapi.h:89
JsonLexContext * lex
Definition: jsonfuncs.c:107
static void hash_object_field_start(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:2413
void * palloc0(Size size)
Definition: mcxt.c:920
HTAB * hash_create(const char *tabname, long nelem, HASHCTL *info, int flags)
Definition: dynahash.c:301
HTAB * hash
Definition: jsonfuncs.c:109
Size keysize
Definition: hsearch.h:72
json_struct_action array_start
Definition: jsonapi.h:86
Definition: regguts.h:298
struct JsonHashEntry JsonHashEntry
static void hash_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:2492
json_ofield_action object_field_start
Definition: jsonapi.h:88
void * semstate
Definition: jsonapi.h:83
static void hash_array_start(void *state)
Definition: jsonfuncs.c:2481
const char * function_name
Definition: jsonfuncs.c:108
static Datum get_jsonb_path_all ( FunctionCallInfo  fcinfo,
bool  as_text 
)
static

Definition at line 1171 of file jsonfuncs.c.

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

Referenced by jsonb_extract_path(), and jsonb_extract_path_text().

1172 {
1173  Jsonb *jb = PG_GETARG_JSONB(0);
1174  ArrayType *path = PG_GETARG_ARRAYTYPE_P(1);
1175  Jsonb *res;
1176  Datum *pathtext;
1177  bool *pathnulls;
1178  int npath;
1179  int i;
1180  bool have_object = false,
1181  have_array = false;
1182  JsonbValue *jbvp = NULL;
1183  JsonbValue tv;
1184  JsonbContainer *container;
1185 
1186  /*
1187  * If the array contains any null elements, return NULL, on the grounds
1188  * that you'd have gotten NULL if any RHS value were NULL in a nested
1189  * series of applications of the -> operator. (Note: because we also
1190  * return NULL for error cases such as no-such-field, this is true
1191  * regardless of the contents of the rest of the array.)
1192  */
1193  if (array_contains_nulls(path))
1194  PG_RETURN_NULL();
1195 
1196  deconstruct_array(path, TEXTOID, -1, false, 'i',
1197  &pathtext, &pathnulls, &npath);
1198 
1199  /* Identify whether we have object, array, or scalar at top-level */
1200  container = &jb->root;
1201 
1202  if (JB_ROOT_IS_OBJECT(jb))
1203  have_object = true;
1204  else if (JB_ROOT_IS_ARRAY(jb) && !JB_ROOT_IS_SCALAR(jb))
1205  have_array = true;
1206  else
1207  {
1209  /* Extract the scalar value, if it is what we'll return */
1210  if (npath <= 0)
1211  jbvp = getIthJsonbValueFromContainer(container, 0);
1212  }
1213 
1214  /*
1215  * If the array is empty, return the entire LHS object, on the grounds
1216  * that we should do zero field or element extractions. For the
1217  * non-scalar case we can just hand back the object without much work. For
1218  * the scalar case, fall through and deal with the value below the loop.
1219  * (This inconsistency arises because there's no easy way to generate a
1220  * JsonbValue directly for root-level containers.)
1221  */
1222  if (npath <= 0 && jbvp == NULL)
1223  {
1224  if (as_text)
1225  {
1227  container,
1228  VARSIZE(jb))));
1229  }
1230  else
1231  {
1232  /* not text mode - just hand back the jsonb */
1233  PG_RETURN_JSONB(jb);
1234  }
1235  }
1236 
1237  for (i = 0; i < npath; i++)
1238  {
1239  if (have_object)
1240  {
1241  jbvp = findJsonbValueFromContainerLen(container,
1242  JB_FOBJECT,
1243  VARDATA_ANY(pathtext[i]),
1244  VARSIZE_ANY_EXHDR(pathtext[i]));
1245  }
1246  else if (have_array)
1247  {
1248  long lindex;
1249  uint32 index;
1250  char *indextext = TextDatumGetCString(pathtext[i]);
1251  char *endptr;
1252 
1253  errno = 0;
1254  lindex = strtol(indextext, &endptr, 10);
1255  if (endptr == indextext || *endptr != '\0' || errno != 0 ||
1256  lindex > INT_MAX || lindex < INT_MIN)
1257  PG_RETURN_NULL();
1258 
1259  if (lindex >= 0)
1260  {
1261  index = (uint32) lindex;
1262  }
1263  else
1264  {
1265  /* Handle negative subscript */
1266  uint32 nelements;
1267 
1268  /* Container must be array, but make sure */
1269  if (!JsonContainerIsArray(container))
1270  elog(ERROR, "not a jsonb array");
1271 
1272  nelements = JsonContainerSize(container);
1273 
1274  if (-lindex > nelements)
1275  PG_RETURN_NULL();
1276  else
1277  index = nelements + lindex;
1278  }
1279 
1280  jbvp = getIthJsonbValueFromContainer(container, index);
1281  }
1282  else
1283  {
1284  /* scalar, extraction yields a null */
1285  PG_RETURN_NULL();
1286  }
1287 
1288  if (jbvp == NULL)
1289  PG_RETURN_NULL();
1290  else if (i == npath - 1)
1291  break;
1292 
1293  if (jbvp->type == jbvBinary)
1294  {
1295  JsonbIterator *it = JsonbIteratorInit((JsonbContainer *) jbvp->val.binary.data);
1297 
1298  r = JsonbIteratorNext(&it, &tv, true);
1299  container = (JsonbContainer *) jbvp->val.binary.data;
1300  have_object = r == WJB_BEGIN_OBJECT;
1301  have_array = r == WJB_BEGIN_ARRAY;
1302  }
1303  else
1304  {
1305  have_object = jbvp->type == jbvObject;
1306  have_array = jbvp->type == jbvArray;
1307  }
1308  }
1309 
1310  if (as_text)
1311  {
1312  /* special-case outputs for string and null values */
1313  if (jbvp->type == jbvString)
1315  jbvp->val.string.len));
1316  if (jbvp->type == jbvNull)
1317  PG_RETURN_NULL();
1318  }
1319 
1320  res = JsonbValueToJsonb(jbvp);
1321 
1322  if (as_text)
1323  {
1325  &res->root,
1326  VARSIZE(res))));
1327  }
1328  else
1329  {
1330  /* not text mode - just hand back the jsonb */
1331  PG_RETURN_JSONB(res);
1332  }
1333 }
#define JB_ROOT_IS_OBJECT(jbp_)
Definition: jsonb.h:224
#define VARDATA_ANY(PTR)
Definition: postgres.h:349
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:306
char * val
Definition: jsonb.h:259
static JsonbValue * findJsonbValueFromContainerLen(JsonbContainer *container, uint32 flags, char *key, uint32 keylen)
Definition: jsonfuncs.c:3082
Definition: jsonb.h:231
#define JB_ROOT_IS_SCALAR(jbp_)
Definition: jsonb.h:223
Definition: type.h:90
#define PG_GETARG_ARRAYTYPE_P(n)
Definition: array.h:244
#define ERROR
Definition: elog.h:43
#define PG_RETURN_JSONB(x)
Definition: jsonb.h:71
#define JB_ROOT_IS_ARRAY(jbp_)
Definition: jsonb.h:225
text * cstring_to_text_with_len(const char *s, int len)
Definition: varlena.c:163
#define JsonContainerSize(jc)
Definition: jsonb.h:209
unsigned int uint32
Definition: c.h:265
#define JsonContainerIsArray(jc)
Definition: jsonb.h:212
JsonbIteratorToken
Definition: jsonb.h:20
JsonbContainer root
Definition: jsonb.h:218
#define TextDatumGetCString(d)
Definition: builtins.h:91
uintptr_t Datum
Definition: postgres.h:374
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:314
text * cstring_to_text(const char *s)
Definition: varlena.c:151
JsonbValue * getIthJsonbValueFromContainer(JsonbContainer *container, uint32 i)
Definition: jsonb_util.c:419
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:671
JsonbIterator * JsonbIteratorInit(JsonbContainer *container)
Definition: jsonb_util.c:718
#define JB_FOBJECT
Definition: jsonb.h:205
char * JsonbToCString(StringInfo out, JsonbContainer *in, int estimated_len)
Definition: jsonb.c:428
enum jbvType type
Definition: jsonb.h:250
void deconstruct_array(ArrayType *array, Oid elmtype, int elmlen, bool elmbyval, char elmalign, Datum **elemsp, bool **nullsp, int *nelemsp)
Definition: arrayfuncs.c:3475
#define PG_GETARG_JSONB(x)
Definition: jsonb.h:70
#define VARSIZE_ANY_EXHDR(PTR)
Definition: postgres.h:342
int i
#define elog
Definition: elog.h:219
bool array_contains_nulls(ArrayType *array)
Definition: arrayfuncs.c:3542
#define PG_RETURN_NULL()
Definition: fmgr.h:289
JsonbIteratorToken JsonbIteratorNext(JsonbIterator **it, JsonbValue *val, bool skipNested)
Definition: jsonb_util.c:754
static void get_object_end ( void *  state)
static

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

872 {
873  GetState *_state = (GetState *) state;
874  int lex_level = _state->lex->lex_level;
875 
876  if (lex_level == 0 && _state->npath == 0)
877  {
878  /* Special case: return the entire object */
879  char *start = _state->result_start;
880  int len = _state->lex->prev_token_terminator - start;
881 
882  _state->tresult = cstring_to_text_with_len(start, len);
883  }
884 }
char * prev_token_terminator
Definition: jsonapi.h:56
int lex_level
Definition: jsonapi.h:58
JsonLexContext * lex
Definition: jsonfuncs.c:58
char * result_start
Definition: jsonfuncs.c:60
text * tresult
Definition: jsonfuncs.c:59
text * cstring_to_text_with_len(const char *s, int len)
Definition: varlena.c:163
int npath
Definition: jsonfuncs.c:63
Definition: regguts.h:298
static void get_object_field_end ( void *  state,
char *  fname,
bool  isnull 
)
static

Definition at line 932 of file jsonfuncs.c.

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

Referenced by get_worker().

933 {
934  GetState *_state = (GetState *) state;
935  bool get_last = false;
936  int lex_level = _state->lex->lex_level;
937 
938  /* same tests as in get_object_field_start */
939  if (lex_level <= _state->npath &&
940  _state->pathok[lex_level - 1] &&
941  _state->path_names != NULL &&
942  _state->path_names[lex_level - 1] != NULL &&
943  strcmp(fname, _state->path_names[lex_level - 1]) == 0)
944  {
945  if (lex_level < _state->npath)
946  {
947  /* done with this field so reset pathok */
948  _state->pathok[lex_level] = false;
949  }
950  else
951  {
952  /* end of path, so we want this value */
953  get_last = true;
954  }
955  }
956 
957  /* for as_text scalar case, our work is already done */
958  if (get_last && _state->result_start != NULL)
959  {
960  /*
961  * make a text object from the string from the prevously noted json
962  * start up to the end of the previous token (the lexer is by now
963  * ahead of us on whatever came after what we're interested in).
964  */
965  if (isnull && _state->normalize_results)
966  _state->tresult = (text *) NULL;
967  else
968  {
969  char *start = _state->result_start;
970  int len = _state->lex->prev_token_terminator - start;
971 
972  _state->tresult = cstring_to_text_with_len(start, len);
973  }
974 
975  /* this should be unnecessary but let's do it for cleanliness: */
976  _state->result_start = NULL;
977  }
978 }
char * prev_token_terminator
Definition: jsonapi.h:56
int lex_level
Definition: jsonapi.h:58
JsonLexContext * lex
Definition: jsonfuncs.c:58
char * result_start
Definition: jsonfuncs.c:60
text * tresult
Definition: jsonfuncs.c:59
text * cstring_to_text_with_len(const char *s, int len)
Definition: varlena.c:163
bool * pathok
Definition: jsonfuncs.c:66
bool normalize_results
Definition: jsonfuncs.c:61
char ** path_names
Definition: jsonfuncs.c:64
#define NULL
Definition: c.h:226
Definition: regguts.h:298
Definition: c.h:435
static void get_object_field_start ( void *  state,
char *  fname,
bool  isnull 
)
static

Definition at line 887 of file jsonfuncs.c.

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

Referenced by get_worker().

888 {
889  GetState *_state = (GetState *) state;
890  bool get_next = false;
891  int lex_level = _state->lex->lex_level;
892 
893  if (lex_level <= _state->npath &&
894  _state->pathok[lex_level - 1] &&
895  _state->path_names != NULL &&
896  _state->path_names[lex_level - 1] != NULL &&
897  strcmp(fname, _state->path_names[lex_level - 1]) == 0)
898  {
899  if (lex_level < _state->npath)
900  {
901  /* if not at end of path just mark path ok */
902  _state->pathok[lex_level] = true;
903  }
904  else
905  {
906  /* end of path, so we want this value */
907  get_next = true;
908  }
909  }
910 
911  if (get_next)
912  {
913  /* this object overrides any previous matching object */
914  _state->tresult = NULL;
915  _state->result_start = NULL;
916 
917  if (_state->normalize_results &&
918  _state->lex->token_type == JSON_TOKEN_STRING)
919  {
920  /* for as_text variants, tell get_scalar to set it for us */
921  _state->next_scalar = true;
922  }
923  else
924  {
925  /* for non-as_text variants, just note the json starting point */
926  _state->result_start = _state->lex->token_start;
927  }
928  }
929 }
JsonTokenType token_type
Definition: jsonapi.h:57
int lex_level
Definition: jsonapi.h:58
JsonLexContext * lex
Definition: jsonfuncs.c:58
char * result_start
Definition: jsonfuncs.c:60
text * tresult
Definition: jsonfuncs.c:59
char * token_start
Definition: jsonapi.h:54
bool * pathok
Definition: jsonfuncs.c:66
bool normalize_results
Definition: jsonfuncs.c:61
bool next_scalar
Definition: jsonfuncs.c:62
char ** path_names
Definition: jsonfuncs.c:64
#define NULL
Definition: c.h:226
Definition: regguts.h:298
static void get_object_start ( void *  state)
static

Definition at line 854 of file jsonfuncs.c.

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

Referenced by get_worker().

855 {
856  GetState *_state = (GetState *) state;
857  int lex_level = _state->lex->lex_level;
858 
859  if (lex_level == 0 && _state->npath == 0)
860  {
861  /*
862  * Special case: we should match the entire object. We only need this
863  * at outermost level because at nested levels the match will have
864  * been started by the outer field or array element callback.
865  */
866  _state->result_start = _state->lex->token_start;
867  }
868 }
int lex_level
Definition: jsonapi.h:58
JsonLexContext * lex
Definition: jsonfuncs.c:58
char * result_start
Definition: jsonfuncs.c:60
int npath
Definition: jsonfuncs.c:63
char * token_start
Definition: jsonapi.h:54
Definition: regguts.h:298
static Datum get_path_all ( FunctionCallInfo  fcinfo,
bool  as_text 
)
static

Definition at line 718 of file jsonfuncs.c.

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

Referenced by json_extract_path(), and json_extract_path_text().

719 {
720  text *json = PG_GETARG_TEXT_P(0);
721  ArrayType *path = PG_GETARG_ARRAYTYPE_P(1);
722  text *result;
723  Datum *pathtext;
724  bool *pathnulls;
725  int npath;
726  char **tpath;
727  int *ipath;
728  int i;
729 
730  /*
731  * If the array contains any null elements, return NULL, on the grounds
732  * that you'd have gotten NULL if any RHS value were NULL in a nested
733  * series of applications of the -> operator. (Note: because we also
734  * return NULL for error cases such as no-such-field, this is true
735  * regardless of the contents of the rest of the array.)
736  */
737  if (array_contains_nulls(path))
738  PG_RETURN_NULL();
739 
740  deconstruct_array(path, TEXTOID, -1, false, 'i',
741  &pathtext, &pathnulls, &npath);
742 
743  tpath = palloc(npath * sizeof(char *));
744  ipath = palloc(npath * sizeof(int));
745 
746  for (i = 0; i < npath; i++)
747  {
748  Assert(!pathnulls[i]);
749  tpath[i] = TextDatumGetCString(pathtext[i]);
750 
751  /*
752  * we have no idea at this stage what structure the document is so
753  * just convert anything in the path that we can to an integer and set
754  * all the other integers to INT_MIN which will never match.
755  */
756  if (*tpath[i] != '\0')
757  {
758  long ind;
759  char *endptr;
760 
761  errno = 0;
762  ind = strtol(tpath[i], &endptr, 10);
763  if (*endptr == '\0' && errno == 0 && ind <= INT_MAX && ind >= INT_MIN)
764  ipath[i] = (int) ind;
765  else
766  ipath[i] = INT_MIN;
767  }
768  else
769  ipath[i] = INT_MIN;
770  }
771 
772  result = get_worker(json, tpath, ipath, npath, as_text);
773 
774  if (result != NULL)
775  PG_RETURN_TEXT_P(result);
776  else
777  PG_RETURN_NULL();
778 }
#define TEXTOID
Definition: pg_type.h:324
#define PG_GETARG_ARRAYTYPE_P(n)
Definition: array.h:244
#define TextDatumGetCString(d)
Definition: builtins.h:91
uintptr_t Datum
Definition: postgres.h:374
static text * get_worker(text *json, char **tpath, int *ipath, int npath, bool normalize_results)
Definition: jsonfuncs.c:798
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:314
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:671
void deconstruct_array(ArrayType *array, Oid elmtype, int elmlen, bool elmbyval, char elmalign, Datum **elemsp, bool **nullsp, int *nelemsp)
Definition: arrayfuncs.c:3475
void * palloc(Size size)
Definition: mcxt.c:891
#define PG_GETARG_TEXT_P(n)
Definition: fmgr.h:269
int i
Definition: c.h:435
bool array_contains_nulls(ArrayType *array)
Definition: arrayfuncs.c:3542
#define PG_RETURN_NULL()
Definition: fmgr.h:289
static void get_scalar ( void *  state,
char *  token,
JsonTokenType  tokentype 
)
static

Definition at line 1118 of file jsonfuncs.c.

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

Referenced by get_worker().

1119 {
1120  GetState *_state = (GetState *) state;
1121  int lex_level = _state->lex->lex_level;
1122 
1123  /* Check for whole-object match */
1124  if (lex_level == 0 && _state->npath == 0)
1125  {
1126  if (_state->normalize_results && tokentype == JSON_TOKEN_STRING)
1127  {
1128  /* we want the de-escaped string */
1129  _state->next_scalar = true;
1130  }
1131  else if (_state->normalize_results && tokentype == JSON_TOKEN_NULL)
1132  {
1133  _state->tresult = (text *) NULL;
1134  }
1135  else
1136  {
1137  /*
1138  * This is a bit hokey: we will suppress whitespace after the
1139  * scalar token, but not whitespace before it. Probably not worth
1140  * doing our own space-skipping to avoid that.
1141  */
1142  char *start = _state->lex->input;
1143  int len = _state->lex->prev_token_terminator - start;
1144 
1145  _state->tresult = cstring_to_text_with_len(start, len);
1146  }
1147  }
1148 
1149  if (_state->next_scalar)
1150  {
1151  /* a de-escaped text value is wanted, so supply it */
1152  _state->tresult = cstring_to_text(token);
1153  /* make sure the next call to get_scalar doesn't overwrite it */
1154  _state->next_scalar = false;
1155  }
1156 }
char * prev_token_terminator
Definition: jsonapi.h:56
int lex_level
Definition: jsonapi.h:58
JsonLexContext * lex
Definition: jsonfuncs.c:58
text * tresult
Definition: jsonfuncs.c:59
text * cstring_to_text_with_len(const char *s, int len)
Definition: varlena.c:163
int npath
Definition: jsonfuncs.c:63
bool normalize_results
Definition: jsonfuncs.c:61
bool next_scalar
Definition: jsonfuncs.c:62
text * cstring_to_text(const char *s)
Definition: varlena.c:151
#define NULL
Definition: c.h:226
char * input
Definition: jsonapi.h:52
Definition: regguts.h:298
Definition: c.h:435
static text * get_worker ( text json,
char **  tpath,
int *  ipath,
int  npath,
bool  normalize_results 
)
static

Definition at line 798 of file jsonfuncs.c.

References GetState::array_cur_index, JsonSemAction::array_element_end, JsonSemAction::array_element_start, JsonSemAction::array_end, JsonSemAction::array_start, Assert, get_array_element_end(), get_array_element_start(), get_array_end(), get_array_start(), get_object_end(), get_object_field_end(), get_object_field_start(), get_object_start(), get_scalar(), GetState::lex, makeJsonLexContext(), GetState::normalize_results, GetState::npath, NULL, JsonSemAction::object_end, JsonSemAction::object_field_end, JsonSemAction::object_field_start, JsonSemAction::object_start, palloc(), palloc0(), GetState::path_indexes, GetState::path_names, GetState::pathok, pg_parse_json(), JsonSemAction::scalar, JsonSemAction::semstate, and GetState::tresult.

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

803 {
804  JsonLexContext *lex = makeJsonLexContext(json, true);
805  JsonSemAction *sem = palloc0(sizeof(JsonSemAction));
806  GetState *state = palloc0(sizeof(GetState));
807 
808  Assert(npath >= 0);
809 
810  state->lex = lex;
811  /* is it "_as_text" variant? */
812  state->normalize_results = normalize_results;
813  state->npath = npath;
814  state->path_names = tpath;
815  state->path_indexes = ipath;
816  state->pathok = palloc0(sizeof(bool) * npath);
817  state->array_cur_index = palloc(sizeof(int) * npath);
818 
819  if (npath > 0)
820  state->pathok[0] = true;
821 
822  sem->semstate = (void *) state;
823 
824  /*
825  * Not all variants need all the semantic routines. Only set the ones that
826  * are actually needed for maximum efficiency.
827  */
828  sem->scalar = get_scalar;
829  if (npath == 0)
830  {
832  sem->object_end = get_object_end;
834  sem->array_end = get_array_end;
835  }
836  if (tpath != NULL)
837  {
840  }
841  if (ipath != NULL)
842  {
846  }
847 
848  pg_parse_json(lex, sem);
849 
850  return state->tresult;
851 }
json_struct_action array_end
Definition: jsonapi.h:87
static void get_array_end(void *state)
Definition: jsonfuncs.c:1014
int * array_cur_index
Definition: jsonfuncs.c:67
static void get_array_element_start(void *state, bool isnull)
Definition: jsonfuncs.c:1030
json_struct_action object_end
Definition: jsonapi.h:85
static void get_object_start(void *state)
Definition: jsonfuncs.c:854
json_struct_action object_start
Definition: jsonapi.h:84
json_scalar_action scalar
Definition: jsonapi.h:92
static void get_object_field_end(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:932
JsonLexContext * lex
Definition: jsonfuncs.c:58
static void get_object_end(void *state)
Definition: jsonfuncs.c:871
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:59
int npath
Definition: jsonfuncs.c:63
json_ofield_action object_field_end
Definition: jsonapi.h:89
static void get_array_element_end(void *state, bool isnull)
Definition: jsonfuncs.c:1076
bool * pathok
Definition: jsonfuncs.c:66
bool normalize_results
Definition: jsonfuncs.c:61
static void get_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:1118
void * palloc0(Size size)
Definition: mcxt.c:920
static void get_array_start(void *state)
Definition: jsonfuncs.c:981
json_aelem_action array_element_start
Definition: jsonapi.h:90
char ** path_names
Definition: jsonfuncs.c:64
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:671
json_struct_action array_start
Definition: jsonapi.h:86
Definition: regguts.h:298
int * path_indexes
Definition: jsonfuncs.c:65
void * palloc(Size size)
Definition: mcxt.c:891
static void get_object_field_start(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:887
json_ofield_action object_field_start
Definition: jsonapi.h:88
void * semstate
Definition: jsonapi.h:83
json_aelem_action array_element_end
Definition: jsonapi.h:91
static void hash_array_start ( void *  state)
static

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

2482 {
2483  JHashState *_state = (JHashState *) state;
2484 
2485  if (_state->lex->lex_level == 0)
2486  ereport(ERROR,
2487  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2488  errmsg("cannot call %s on an array", _state->function_name)));
2489 }
int errcode(int sqlerrcode)
Definition: elog.c:575
int lex_level
Definition: jsonapi.h:58
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:122
JsonLexContext * lex
Definition: jsonfuncs.c:107
Definition: regguts.h:298
int errmsg(const char *fmt,...)
Definition: elog.c:797
const char * function_name
Definition: jsonfuncs.c:108
static void hash_object_field_end ( void *  state,
char *  fname,
bool  isnull 
)
static

Definition at line 2434 of file jsonfuncs.c.

References JhashState::hash, HASH_ENTER, hash_search(), JsonHashEntry::isnull, JhashState::lex, JsonLexContext::lex_level, NAMEDATALEN, NULL, palloc(), JsonLexContext::prev_token_terminator, JhashState::save_json_start, JhashState::saved_scalar, JsonHashEntry::val, and val.

Referenced by get_json_object_as_hash().

2435 {
2436  JHashState *_state = (JHashState *) state;
2437  JsonHashEntry *hashentry;
2438  bool found;
2439 
2440  /*
2441  * Ignore nested fields.
2442  */
2443  if (_state->lex->lex_level > 1)
2444  return;
2445 
2446  /*
2447  * Ignore field names >= NAMEDATALEN - they can't match a record field.
2448  * (Note: without this test, the hash code would truncate the string at
2449  * NAMEDATALEN-1, and could then match against a similarly-truncated
2450  * record field name. That would be a reasonable behavior, but this code
2451  * has previously insisted on exact equality, so we keep this behavior.)
2452  */
2453  if (strlen(fname) >= NAMEDATALEN)
2454  return;
2455 
2456  hashentry = hash_search(_state->hash, fname, HASH_ENTER, &found);
2457 
2458  /*
2459  * found being true indicates a duplicate. We don't do anything about
2460  * that, a later field with the same name overrides the earlier field.
2461  */
2462 
2463  hashentry->isnull = isnull;
2464  if (_state->save_json_start != NULL)
2465  {
2466  int len = _state->lex->prev_token_terminator - _state->save_json_start;
2467  char *val = palloc((len + 1) * sizeof(char));
2468 
2469  memcpy(val, _state->save_json_start, len);
2470  val[len] = '\0';
2471  hashentry->val = val;
2472  }
2473  else
2474  {
2475  /* must have had a scalar instead */
2476  hashentry->val = _state->saved_scalar;
2477  }
2478 }
char * saved_scalar
Definition: jsonfuncs.c:110
char * prev_token_terminator
Definition: jsonapi.h:56
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:885
int lex_level
Definition: jsonapi.h:58
#define NAMEDATALEN
char * val
Definition: jsonfuncs.c:118
JsonLexContext * lex
Definition: jsonfuncs.c:107
HTAB * hash
Definition: jsonfuncs.c:109
#define NULL
Definition: c.h:226
Definition: regguts.h:298
void * palloc(Size size)
Definition: mcxt.c:891
char * save_json_start
Definition: jsonfuncs.c:111
long val
Definition: informix.c:689
static void hash_object_field_start ( void *  state,
char *  fname,
bool  isnull 
)
static

Definition at line 2413 of file jsonfuncs.c.

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

Referenced by get_json_object_as_hash().

2414 {
2415  JHashState *_state = (JHashState *) state;
2416 
2417  if (_state->lex->lex_level > 1)
2418  return;
2419 
2420  if (_state->lex->token_type == JSON_TOKEN_ARRAY_START ||
2422  {
2423  /* remember start position of the whole text of the subobject */
2424  _state->save_json_start = _state->lex->token_start;
2425  }
2426  else
2427  {
2428  /* must be a scalar */
2429  _state->save_json_start = NULL;
2430  }
2431 }
JsonTokenType token_type
Definition: jsonapi.h:57
int lex_level
Definition: jsonapi.h:58
JsonLexContext * lex
Definition: jsonfuncs.c:107
char * token_start
Definition: jsonapi.h:54
#define NULL
Definition: c.h:226
Definition: regguts.h:298
char * save_json_start
Definition: jsonfuncs.c:111
static void hash_scalar ( void *  state,
char *  token,
JsonTokenType  tokentype 
)
static

Definition at line 2492 of file jsonfuncs.c.

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

Referenced by get_json_object_as_hash().

2493 {
2494  JHashState *_state = (JHashState *) state;
2495 
2496  if (_state->lex->lex_level == 0)
2497  ereport(ERROR,
2498  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2499  errmsg("cannot call %s on a scalar", _state->function_name)));
2500 
2501  if (_state->lex->lex_level == 1)
2502  _state->saved_scalar = token;
2503 }
char * saved_scalar
Definition: jsonfuncs.c:110
int errcode(int sqlerrcode)
Definition: elog.c:575
int lex_level
Definition: jsonapi.h:58
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:122
JsonLexContext * lex
Definition: jsonfuncs.c:107
Definition: regguts.h:298
int errmsg(const char *fmt,...)
Definition: elog.c:797
const char * function_name
Definition: jsonfuncs.c:108
static JsonbValue * IteratorConcat ( JsonbIterator **  it1,
JsonbIterator **  it2,
JsonbParseState **  state 
)
static

Definition at line 3739 of file jsonfuncs.c.

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

Referenced by jsonb_concat().

3741 {
3742  JsonbValue v1,
3743  v2,
3744  *res = NULL;
3745  JsonbIteratorToken r1,
3746  r2,
3747  rk1,
3748  rk2;
3749 
3750  r1 = rk1 = JsonbIteratorNext(it1, &v1, false);
3751  r2 = rk2 = JsonbIteratorNext(it2, &v2, false);
3752 
3753  /*
3754  * Both elements are objects.
3755  */
3756  if (rk1 == WJB_BEGIN_OBJECT && rk2 == WJB_BEGIN_OBJECT)
3757  {
3758  /*
3759  * Append the all tokens from v1 to res, except last WJB_END_OBJECT
3760  * (because res will not be finished yet).
3761  */
3762  pushJsonbValue(state, r1, NULL);
3763  while ((r1 = JsonbIteratorNext(it1, &v1, true)) != WJB_END_OBJECT)
3764  pushJsonbValue(state, r1, &v1);
3765 
3766  /*
3767  * Append the all tokens from v2 to res, include last WJB_END_OBJECT
3768  * (the concatenation will be completed).
3769  */
3770  while ((r2 = JsonbIteratorNext(it2, &v2, true)) != 0)
3771  res = pushJsonbValue(state, r2, r2 != WJB_END_OBJECT ? &v2 : NULL);
3772  }
3773 
3774  /*
3775  * Both elements are arrays (either can be scalar).
3776  */
3777  else if (rk1 == WJB_BEGIN_ARRAY && rk2 == WJB_BEGIN_ARRAY)
3778  {
3779  pushJsonbValue(state, r1, NULL);
3780 
3781  while ((r1 = JsonbIteratorNext(it1, &v1, true)) != WJB_END_ARRAY)
3782  {
3783  Assert(r1 == WJB_ELEM);
3784  pushJsonbValue(state, r1, &v1);
3785  }
3786 
3787  while ((r2 = JsonbIteratorNext(it2, &v2, true)) != WJB_END_ARRAY)
3788  {
3789  Assert(r2 == WJB_ELEM);
3790  pushJsonbValue(state, WJB_ELEM, &v2);
3791  }
3792 
3793  res = pushJsonbValue(state, WJB_END_ARRAY, NULL /* signal to sort */ );
3794  }
3795  /* have we got array || object or object || array? */
3796  else if (((rk1 == WJB_BEGIN_ARRAY && !(*it1)->isScalar) && rk2 == WJB_BEGIN_OBJECT) ||
3797  (rk1 == WJB_BEGIN_OBJECT && (rk2 == WJB_BEGIN_ARRAY && !(*it2)->isScalar)))
3798  {
3799 
3800  JsonbIterator **it_array = rk1 == WJB_BEGIN_ARRAY ? it1 : it2;
3801  JsonbIterator **it_object = rk1 == WJB_BEGIN_OBJECT ? it1 : it2;
3802 
3803  bool prepend = (rk1 == WJB_BEGIN_OBJECT);
3804 
3806 
3807  if (prepend)
3808  {
3810  while ((r1 = JsonbIteratorNext(it_object, &v1, true)) != 0)
3811  pushJsonbValue(state, r1, r1 != WJB_END_OBJECT ? &v1 : NULL);
3812 
3813  while ((r2 = JsonbIteratorNext(it_array, &v2, true)) != 0)
3814  res = pushJsonbValue(state, r2, r2 != WJB_END_ARRAY ? &v2 : NULL);
3815  }
3816  else
3817  {
3818  while ((r1 = JsonbIteratorNext(it_array, &v1, true)) != WJB_END_ARRAY)
3819  pushJsonbValue(state, r1, &v1);
3820 
3822  while ((r2 = JsonbIteratorNext(it_object, &v2, true)) != 0)
3823  pushJsonbValue(state, r2, r2 != WJB_END_OBJECT ? &v2 : NULL);
3824 
3825  res = pushJsonbValue(state, WJB_END_ARRAY, NULL);
3826  }
3827  }
3828  else
3829  {
3830  /*
3831  * This must be scalar || object or object || scalar, as that's all
3832  * that's left. Both of these make no sense, so error out.
3833  */
3834  ereport(ERROR,
3835  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3836  errmsg("invalid concatenation of jsonb objects")));
3837  }
3838 
3839  return res;
3840 }
int errcode(int sqlerrcode)
Definition: elog.c:575
JsonbValue * pushJsonbValue(JsonbParseState **pstate, JsonbIteratorToken seq, JsonbValue *jbval)
Definition: jsonb_util.c:517
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:122
JsonbIteratorToken
Definition: jsonb.h:20
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:671
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
Datum json_array_element ( PG_FUNCTION_ARGS  )

Definition at line 586 of file jsonfuncs.c.

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

587 {
588  text *json = PG_GETARG_TEXT_P(0);
589  int element = PG_GETARG_INT32(1);
590  text *result;
591 
592  result = get_worker(json, NULL, &element, 1, false);
593 
594  if (result != NULL)
595  PG_RETURN_TEXT_P(result);
596  else
597  PG_RETURN_NULL();
598 }
#define PG_GETARG_INT32(n)
Definition: fmgr.h:225
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:798
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:314
#define NULL
Definition: c.h:226
#define PG_GETARG_TEXT_P(n)
Definition: fmgr.h:269
Definition: c.h:435
#define PG_RETURN_NULL()
Definition: fmgr.h:289
Datum json_array_element_text ( PG_FUNCTION_ARGS  )

Definition at line 629 of file jsonfuncs.c.

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

630 {
631  text *json = PG_GETARG_TEXT_P(0);
632  int element = PG_GETARG_INT32(1);
633  text *result;
634 
635  result = get_worker(json, NULL, &element, 1, true);
636 
637  if (result != NULL)
638  PG_RETURN_TEXT_P(result);
639  else
640  PG_RETURN_NULL();
641 }
#define PG_GETARG_INT32(n)
Definition: fmgr.h:225
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:798
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:314
#define NULL
Definition: c.h:226
#define PG_GETARG_TEXT_P(n)
Definition: fmgr.h:269
Definition: c.h:435
#define PG_RETURN_NULL()
Definition: fmgr.h:289
Datum json_array_elements ( PG_FUNCTION_ARGS  )

Definition at line 1895 of file jsonfuncs.c.

References elements_worker().

1896 {
1897  return elements_worker(fcinfo, "json_array_elements", false);
1898 }
static Datum elements_worker(FunctionCallInfo fcinfo, const char *funcname, bool as_text)
Definition: jsonfuncs.c:1907
Datum json_array_elements_text ( PG_FUNCTION_ARGS  )

Definition at line 1901 of file jsonfuncs.c.

References elements_worker().

1902 {
1903  return elements_worker(fcinfo, "json_array_elements_text", true);
1904 }
static Datum elements_worker(FunctionCallInfo fcinfo, const char *funcname, bool as_text)
Definition: jsonfuncs.c:1907
Datum json_array_length ( PG_FUNCTION_ARGS  )

Definition at line 1339 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_P, pg_parse_json(), PG_RETURN_INT32, JsonSemAction::scalar, and JsonSemAction::semstate.

1340 {
1341  text *json = PG_GETARG_TEXT_P(0);
1342  AlenState *state;
1343  JsonLexContext *lex;
1344  JsonSemAction *sem;
1345 
1346  lex = makeJsonLexContext(json, false);
1347  state = palloc0(sizeof(AlenState));
1348  sem = palloc0(sizeof(JsonSemAction));
1349 
1350  /* palloc0 does this for us */
1351 #if 0
1352  state->count = 0;
1353 #endif
1354  state->lex = lex;
1355 
1356  sem->semstate = (void *) state;
1358  sem->scalar = alen_scalar;
1360 
1361  pg_parse_json(lex, sem);
1362 
1363  PG_RETURN_INT32(state->count);
1364 }
json_struct_action object_start
Definition: jsonapi.h:84
#define PG_RETURN_INT32(x)
Definition: fmgr.h:298
json_scalar_action scalar
Definition: jsonapi.h:92
int count
Definition: jsonfuncs.c:74
static void alen_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:1401
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:73
void * palloc0(Size size)
Definition: mcxt.c:920
json_aelem_action array_element_start
Definition: jsonapi.h:90
Definition: regguts.h:298
#define PG_GETARG_TEXT_P(n)
Definition: fmgr.h:269
static void alen_object_start(void *state)
Definition: jsonfuncs.c:1389
Definition: c.h:435
static void alen_array_element_start(void *state, bool isnull)
Definition: jsonfuncs.c:1413
void * semstate
Definition: jsonapi.h:83
Datum json_each ( PG_FUNCTION_ARGS  )

Definition at line 1433 of file jsonfuncs.c.

References each_worker().

1434 {
1435  return each_worker(fcinfo, false);
1436 }
static Datum each_worker(FunctionCallInfo fcinfo, bool as_text)
Definition: jsonfuncs.c:1593
Datum json_each_text ( PG_FUNCTION_ARGS  )

Definition at line 1445 of file jsonfuncs.c.

References each_worker().

1446 {
1447  return each_worker(fcinfo, true);
1448 }
static Datum each_worker(FunctionCallInfo fcinfo, bool as_text)
Definition: jsonfuncs.c:1593
Datum json_extract_path ( PG_FUNCTION_ARGS  )

Definition at line 703 of file jsonfuncs.c.

References get_path_all().

704 {
705  return get_path_all(fcinfo, false);
706 }
static Datum get_path_all(FunctionCallInfo fcinfo, bool as_text)
Definition: jsonfuncs.c:718
Datum json_extract_path_text ( PG_FUNCTION_ARGS  )

Definition at line 709 of file jsonfuncs.c.

References get_path_all().

710 {
711  return get_path_all(fcinfo, true);
712 }
static Datum get_path_all(FunctionCallInfo fcinfo, bool as_text)
Definition: jsonfuncs.c:718
Datum json_object_field ( PG_FUNCTION_ARGS  )

Definition at line 483 of file jsonfuncs.c.

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

484 {
485  text *json = PG_GETARG_TEXT_P(0);
486  text *fname = PG_GETARG_TEXT_PP(1);
487  char *fnamestr = text_to_cstring(fname);
488  text *result;
489 
490  result = get_worker(json, &fnamestr, NULL, 1, false);
491 
492  if (result != NULL)
493  PG_RETURN_TEXT_P(result);
494  else
495  PG_RETURN_NULL();
496 }
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:270
static text * get_worker(text *json, char **tpath, int *ipath, int npath, bool normalize_results)
Definition: jsonfuncs.c:798
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:314
#define NULL
Definition: c.h:226
char * text_to_cstring(const text *t)
Definition: varlena.c:184
#define PG_GETARG_TEXT_P(n)
Definition: fmgr.h:269
Definition: c.h:435
#define PG_RETURN_NULL()
Definition: fmgr.h:289
Datum json_object_field_text ( PG_FUNCTION_ARGS  )

Definition at line 519 of file jsonfuncs.c.

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

520 {
521  text *json = PG_GETARG_TEXT_P(0);
522  text *fname = PG_GETARG_TEXT_PP(1);
523  char *fnamestr = text_to_cstring(fname);
524  text *result;
525 
526  result = get_worker(json, &fnamestr, NULL, 1, true);
527 
528  if (result != NULL)
529  PG_RETURN_TEXT_P(result);
530  else
531  PG_RETURN_NULL();
532 }
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:270
static text * get_worker(text *json, char **tpath, int *ipath, int npath, bool normalize_results)
Definition: jsonfuncs.c:798
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:314
#define NULL
Definition: c.h:226
char * text_to_cstring(const text *t)
Definition: varlena.c:184
#define PG_GETARG_TEXT_P(n)
Definition: fmgr.h:269
Definition: c.h:435
#define PG_RETURN_NULL()
Definition: fmgr.h:289
Datum json_object_keys ( PG_FUNCTION_ARGS  )

Definition at line 366 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_P, 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.

367 {
368  FuncCallContext *funcctx;
369  OkeysState *state;
370  int i;
371 
372  if (SRF_IS_FIRSTCALL())
373  {
374  text *json = PG_GETARG_TEXT_P(0);
375  JsonLexContext *lex = makeJsonLexContext(json, true);
376  JsonSemAction *sem;
377  MemoryContext oldcontext;
378 
379  funcctx = SRF_FIRSTCALL_INIT();
380  oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
381 
382  state = palloc(sizeof(OkeysState));
383  sem = palloc0(sizeof(JsonSemAction));
384 
385  state->lex = lex;
386  state->result_size = 256;
387  state->result_count = 0;
388  state->sent_count = 0;
389  state->result = palloc(256 * sizeof(char *));
390 
391  sem->semstate = (void *) state;
393  sem->scalar = okeys_scalar;
395  /* remainder are all NULL, courtesy of palloc0 above */
396 
397  pg_parse_json(lex, sem);
398  /* keys are now in state->result */
399 
400  pfree(lex->strval->data);
401  pfree(lex->strval);
402  pfree(lex);
403  pfree(sem);
404 
405  MemoryContextSwitchTo(oldcontext);
406  funcctx->user_fctx = (void *) state;
407  }
408 
409  funcctx = SRF_PERCALL_SETUP();
410  state = (OkeysState *) funcctx->user_fctx;
411 
412  if (state->sent_count < state->result_count)
413  {
414  char *nxt = state->result[state->sent_count++];
415 
416  SRF_RETURN_NEXT(funcctx, CStringGetTextDatum(nxt));
417  }
418 
419  /* cleanup to reduce or eliminate memory leaks */
420  for (i = 0; i < state->result_count; i++)
421  pfree(state->result[i]);
422  pfree(state->result);
423  pfree(state);
424 
425  SRF_RETURN_DONE(funcctx);
426 }
int result_count
Definition: jsonfuncs.c:51
#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:450
json_scalar_action scalar
Definition: jsonapi.h:92
int sent_count
Definition: jsonfuncs.c:52
#define SRF_PERCALL_SETUP()
Definition: funcapi.h:289
#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:992
void pg_parse_json(JsonLexContext *lex, JsonSemAction *sem)
Definition: json.c:331
StringInfo strval
Definition: jsonapi.h:61
static void okeys_object_field_start(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:429
char ** result
Definition: jsonfuncs.c:49
void * palloc0(Size size)
Definition: mcxt.c:920
JsonLexContext * lex
Definition: jsonfuncs.c:48
json_struct_action array_start
Definition: jsonapi.h:86
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:463
int result_size
Definition: jsonfuncs.c:50
void * user_fctx
Definition: funcapi.h:90
void * palloc(Size size)
Definition: mcxt.c:891
#define PG_GETARG_TEXT_P(n)
Definition: fmgr.h:269
int i
#define CStringGetTextDatum(s)
Definition: builtins.h:90
Definition: c.h:435
json_ofield_action object_field_start
Definition: jsonapi.h:88
void * semstate
Definition: jsonapi.h:83
#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 2091 of file jsonfuncs.c.

References populate_record_worker().

2092 {
2093  return populate_record_worker(fcinfo, "json_populate_record", true);
2094 }
static Datum populate_record_worker(FunctionCallInfo fcinfo, const char *funcname, bool have_record_arg)
Definition: jsonfuncs.c:2103
Datum json_populate_recordset ( PG_FUNCTION_ARGS  )

Definition at line 2529 of file jsonfuncs.c.

References populate_recordset_worker().

2530 {
2531  return populate_recordset_worker(fcinfo, "json_populate_recordset", true);
2532 }
static Datum populate_recordset_worker(FunctionCallInfo fcinfo, const char *funcname, bool have_record_arg)
Definition: jsonfuncs.c:2662
Datum json_strip_nulls ( PG_FUNCTION_ARGS  )

Definition at line 3194 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_P, 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.

3195 {
3196  text *json = PG_GETARG_TEXT_P(0);
3198  JsonLexContext *lex;
3199  JsonSemAction *sem;
3200 
3201  lex = makeJsonLexContext(json, true);
3202  state = palloc0(sizeof(StripnullState));
3203  sem = palloc0(sizeof(JsonSemAction));
3204 
3205  state->strval = makeStringInfo();
3206  state->skip_next_null = false;
3207  state->lex = lex;
3208 
3209  sem->semstate = (void *) state;
3211  sem->object_end = sn_object_end;
3212  sem->array_start = sn_array_start;
3213  sem->array_end = sn_array_end;
3214  sem->scalar = sn_scalar;
3217 
3218  pg_parse_json(lex, sem);
3219 
3221  state->strval->len));
3222 
3223 }
json_struct_action array_end
Definition: jsonapi.h:87
bool skip_next_null
Definition: jsonfuncs.c:160
static void sn_object_start(void *state)
Definition: jsonfuncs.c:3104
json_struct_action object_end
Definition: jsonapi.h:85
static void sn_array_element_start(void *state, bool isnull)
Definition: jsonfuncs.c:3164
static void sn_object_field_start(void *state, char *fname, bool isnull)
Definition: jsonfuncs.c:3136
StringInfo makeStringInfo(void)
Definition: stringinfo.c:29
json_struct_action object_start
Definition: jsonapi.h:84
json_scalar_action scalar
Definition: jsonapi.h:92
JsonLexContext * makeJsonLexContext(text *json, bool need_escapes)
Definition: json.c:300
static void sn_array_start(void *state)
Definition: jsonfuncs.c:3120
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:163
JsonLexContext * lex
Definition: jsonfuncs.c:158
static void sn_object_end(void *state)
Definition: jsonfuncs.c:3112
void * palloc0(Size size)
Definition: mcxt.c:920
json_aelem_action array_element_start
Definition: jsonapi.h:90
static void sn_scalar(void *state, char *token, JsonTokenType tokentype)
Definition: jsonfuncs.c:3173
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:314
json_struct_action array_start
Definition: jsonapi.h:86
Definition: regguts.h:298
#define PG_GETARG_TEXT_P(n)
Definition: fmgr.h:269
StringInfo strval
Definition: jsonfuncs.c:159
Definition: c.h:435
json_ofield_action object_field_start
Definition: jsonapi.h:88
static void sn_array_end(void *state)
Definition: jsonfuncs.c:3128
void * semstate
Definition: jsonapi.h:83
Datum json_to_record ( PG_FUNCTION_ARGS  )

Definition at line 2097 of file jsonfuncs.c.

References populate_record_worker().

2098 {
2099  return populate_record_worker(fcinfo, "json_to_record", false);
2100 }
static Datum populate_record_worker(FunctionCallInfo fcinfo, const char *funcname, bool have_record_arg)
Definition: jsonfuncs.c:2103
Datum json_to_recordset ( PG_FUNCTION_ARGS  )

Definition at line 2535 of file jsonfuncs.c.

References populate_recordset_worker().

2536 {
2537  return populate_recordset_worker(fcinfo, "json_to_recordset", false);
2538 }
static Datum populate_recordset_worker(FunctionCallInfo fcinfo, const char *funcname, bool have_record_arg)
Definition: jsonfuncs.c:2662
Datum jsonb_array_element ( PG_FUNCTION_ARGS  )

Definition at line 601 of file jsonfuncs.c.

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

602 {
603  Jsonb *jb = PG_GETARG_JSONB(0);
604  int element = PG_GETARG_INT32(1);
605  JsonbValue *v;
606 
607  if (!JB_ROOT_IS_ARRAY(jb))
608  PG_RETURN_NULL();
609 
610  /* Handle negative subscript */
611  if (element < 0)
612  {
613  uint32 nelements = JB_ROOT_COUNT(jb);
614 
615  if (-element > nelements)
616  PG_RETURN_NULL();
617  else
618  element += nelements;
619  }
620 
621  v = getIthJsonbValueFromContainer(&jb->root, element);
622  if (v != NULL)
624 
625  PG_RETURN_NULL();
626 }
#define PG_GETARG_INT32(n)
Definition: fmgr.h:225
Jsonb * JsonbValueToJsonb(JsonbValue *val)
Definition: jsonb_util.c:79
Definition: jsonb.h:215
#define JB_ROOT_COUNT(jbp_)
Definition: jsonb.h:222
#define PG_RETURN_JSONB(x)
Definition: jsonb.h:71
#define JB_ROOT_IS_ARRAY(jbp_)
Definition: jsonb.h:225
unsigned int uint32
Definition: c.h:265
static chr element(struct vars *v, const chr *startp, const chr *endp)
Definition: regc_locale.c:380
JsonbContainer root
Definition: jsonb.h:218
JsonbValue * getIthJsonbValueFromContainer(JsonbContainer *container, uint32 i)
Definition: jsonb_util.c:419
#define NULL
Definition: c.h:226
#define PG_GETARG_JSONB(x)
Definition: jsonb.h:70
#define PG_RETURN_NULL()
Definition: fmgr.h:289
Datum jsonb_array_element_text ( PG_FUNCTION_ARGS  )

Definition at line 644 of file jsonfuncs.c.

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

645 {
646  Jsonb *jb = PG_GETARG_JSONB(0);
647  int element = PG_GETARG_INT32(1);
648  JsonbValue *v;
649 
650  if (!JB_ROOT_IS_ARRAY(jb))
651  PG_RETURN_NULL();
652 
653  /* Handle negative subscript */
654  if (element < 0)
655  {
656  uint32 nelements = JB_ROOT_COUNT(jb);
657 
658  if (-element > nelements)
659  PG_RETURN_NULL();
660  else
661  element += nelements;
662  }
663 
664  v = getIthJsonbValueFromContainer(&jb->root, element);
665  if (v != NULL)
666  {
667  text *result = NULL;
668 
669  switch (v->type)
670  {
671  case jbvNull:
672  break;
673  case jbvBool:
674  result = cstring_to_text(v->val.boolean ? "true" : "false");
675  break;
676  case jbvString:
677  result = cstring_to_text_with_len(v->val.string.val, v->val.string.len);
678  break;
679  case jbvNumeric:
681  PointerGetDatum(v->val.numeric))));
682  break;
683  case jbvBinary:
684  {
685  StringInfo jtext = makeStringInfo();
686 
687  (void) JsonbToCString(jtext, v->val.binary.data, -1);
688  result = cstring_to_text_with_len(jtext->data, jtext->len);
689  }
690  break;
691  default:
692  elog(ERROR, "unrecognized jsonb type: %d", (int) v->type);
693  }
694 
695  if (result)
696  PG_RETURN_TEXT_P(result);
697  }
698 
699  PG_RETURN_NULL();
700 }
#define PG_GETARG_INT32(n)
Definition: fmgr.h:225
Definition: jsonb.h:215
#define PointerGetDatum(X)
Definition: postgres.h:564
char * val
Definition: jsonb.h:259
Definition: jsonb.h:234
StringInfo makeStringInfo(void)
Definition: stringinfo.c:29
Datum numeric_out(PG_FUNCTION_ARGS)
Definition: numeric.c:641
#define JB_ROOT_COUNT(jbp_)
Definition: jsonb.h:222
Definition: jsonb.h:231
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:555
#define ERROR
Definition: elog.h:43
#define DatumGetCString(X)
Definition: postgres.h:574
#define JB_ROOT_IS_ARRAY(jbp_)
Definition: jsonb.h:225
text * cstring_to_text_with_len(const char *s, int len)
Definition: varlena.c:163
unsigned int uint32
Definition: c.h:265
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:314
text * cstring_to_text(const char *s)
Definition: varlena.c:151
JsonbValue * getIthJsonbValueFromContainer(JsonbContainer *container, uint32 i)
Definition: jsonb_util.c:419
#define NULL
Definition: c.h:226
char * JsonbToCString(StringInfo out, JsonbContainer *in, int estimated_len)
Definition: jsonb.c:428
enum jbvType type
Definition: jsonb.h:250
#define PG_GETARG_JSONB(x)
Definition: jsonb.h:70
Definition: c.h:435
#define elog
Definition: elog.h:219
#define PG_RETURN_NULL()
Definition: fmgr.h:289
Datum jsonb_array_elements ( PG_FUNCTION_ARGS  )

Definition at line 1759 of file jsonfuncs.c.

References elements_worker_jsonb().

1760 {
1761  return elements_worker_jsonb(fcinfo, "jsonb_array_elements", false);
1762 }
static Datum elements_worker_jsonb(FunctionCallInfo fcinfo, const char *funcname, bool as_text)
Definition: jsonfuncs.c:1771
Datum jsonb_array_elements_text ( PG_FUNCTION_ARGS  )

Definition at line 1765 of file jsonfuncs.c.

References elements_worker_jsonb().

1766 {
1767  return elements_worker_jsonb(fcinfo, "jsonb_array_elements_text", true);
1768 }
static Datum elements_worker_jsonb(FunctionCallInfo fcinfo, const char *funcname, bool as_text)
Definition: jsonfuncs.c:1771
Datum jsonb_array_length ( PG_FUNCTION_ARGS  )

Definition at line 1367 of file jsonfuncs.c.

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

1368 {
1369  Jsonb *jb = PG_GETARG_JSONB(0);
1370 
1371  if (JB_ROOT_IS_SCALAR(jb))
1372  ereport(ERROR,
1373  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1374  errmsg("cannot get array length of a scalar")));
1375  else if (!JB_ROOT_IS_ARRAY(jb))
1376  ereport(ERROR,
1377  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1378  errmsg("cannot get array length of a non-array")));
1379 
1381 }
Definition: jsonb.h:215
#define PG_RETURN_INT32(x)
Definition: fmgr.h:298
#define JB_ROOT_COUNT(jbp_)
Definition: jsonb.h:222
int errcode(int sqlerrcode)
Definition: elog.c:575
#define JB_ROOT_IS_SCALAR(jbp_)
Definition: jsonb.h:223
#define ERROR
Definition: elog.h:43
#define JB_ROOT_IS_ARRAY(jbp_)
Definition: jsonb.h:225
#define ereport(elevel, rest)
Definition: elog.h:122
#define PG_GETARG_JSONB(x)
Definition: jsonb.h:70
int errmsg(const char *fmt,...)
Definition: elog.c:797
Datum jsonb_concat ( PG_FUNCTION_ARGS  )

Definition at line 3354 of file jsonfuncs.c.

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

3355 {
3356  Jsonb *jb1 = PG_GETARG_JSONB(0);
3357  Jsonb *jb2 = PG_GETARG_JSONB(1);
3359  JsonbValue *res;
3360  JsonbIterator *it1,
3361  *it2;
3362 
3363  /*
3364  * If one of the jsonb is empty, just return the other if it's not scalar
3365  * and both are of the same kind. If it's a scalar or they are of
3366  * different kinds we need to perform the concatenation even if one is
3367  * empty.
3368  */
3369  if (JB_ROOT_IS_OBJECT(jb1) == JB_ROOT_IS_OBJECT(jb2))
3370  {
3371  if (JB_ROOT_COUNT(jb1) == 0 && !JB_ROOT_IS_SCALAR(jb2))
3372  PG_RETURN_JSONB(jb2);
3373  else if (JB_ROOT_COUNT(jb2) == 0 && !JB_ROOT_IS_SCALAR(jb1))
3374  PG_RETURN_JSONB(jb1);
3375  }
3376 
3377  it1 = JsonbIteratorInit(&jb1->root);
3378  it2 = JsonbIteratorInit(&jb2->root);
3379 
3380  res = IteratorConcat(&it1, &it2, &state);
3381 
3382  Assert(res != NULL);
3383 
3385 }
#define JB_ROOT_IS_OBJECT(jbp_)
Definition: jsonb.h:224
Jsonb * JsonbValueToJsonb(JsonbValue *val)
Definition: jsonb_util.c:79
Definition: jsonb.h:215
#define JB_ROOT_COUNT(jbp_)
Definition: jsonb.h:222
#define JB_ROOT_IS_SCALAR(jbp_)
Definition: jsonb.h:223
#define PG_RETURN_JSONB(x)
Definition: jsonb.h:71
JsonbContainer root
Definition: jsonb.h:218
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:671
JsonbIterator * JsonbIteratorInit(JsonbContainer *container)
Definition: jsonb_util.c:718
Definition: regguts.h:298
#define PG_GETARG_JSONB(x)
Definition: jsonb.h:70
static JsonbValue * IteratorConcat(JsonbIterator **it1, JsonbIterator **it2, JsonbParseState **state)
Definition: jsonfuncs.c:3739
Datum jsonb_delete ( PG_FUNCTION_ARGS  )

Definition at line 3395 of file jsonfuncs.c.

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

3396 {
3397  Jsonb *in = PG_GETARG_JSONB(0);
3398  text *key = PG_GETARG_TEXT_PP(1);
3399  char *keyptr = VARDATA_ANY(key);
3400  int keylen = VARSIZE_ANY_EXHDR(key);
3402  JsonbIterator *it;
3403  JsonbValue v,
3404  *res = NULL;
3405  bool skipNested = false;
3407 
3408  if (JB_ROOT_IS_SCALAR(in))
3409  ereport(ERROR,
3410  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3411  errmsg("cannot delete from scalar")));
3412 
3413  if (JB_ROOT_COUNT(in) == 0)
3414  PG_RETURN_JSONB(in);
3415 
3416  it = JsonbIteratorInit(&in->root);
3417 
3418  while ((r = JsonbIteratorNext(&it, &v, skipNested)) != 0)
3419  {
3420  skipNested = true;
3421 
3422  if ((r == WJB_ELEM || r == WJB_KEY) &&
3423  (v.type == jbvString && keylen == v.val.string.len &&
3424  memcmp(keyptr, v.val.string.val, keylen) == 0))
3425  {
3426  /* skip corresponding value as well */
3427  if (r == WJB_KEY)
3428  JsonbIteratorNext(&it, &v, true);
3429 
3430  continue;
3431  }
3432 
3433  res = pushJsonbValue(&state, r, r < WJB_BEGIN_ARRAY ? &v : NULL);
3434  }
3435 
3436  Assert(res != NULL);
3437 
3439 }
#define VARDATA_ANY(PTR)
Definition: postgres.h:349
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:270
JsonbValue * pushJsonbValue(JsonbParseState **pstate, JsonbIteratorToken seq, JsonbValue *jbval)
Definition: jsonb_util.c:517
#define ERROR
Definition: elog.h:43
#define PG_RETURN_JSONB(x)
Definition: jsonb.h:71
Definition: jsonb.h:23
#define ereport(elevel, rest)
Definition: elog.h:122
JsonbIteratorToken
Definition: jsonb.h:20
JsonbContainer root
Definition: jsonb.h:218
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:671
JsonbIterator * JsonbIteratorInit(JsonbContainer *container)
Definition: jsonb_util.c:718
Definition: regguts.h:298
enum jbvType type
Definition: jsonb.h:250
#define PG_GETARG_JSONB(x)
Definition: jsonb.h:70
#define VARSIZE_ANY_EXHDR(PTR)
Definition: postgres.h:342
int errmsg(const char *fmt,...)
Definition: elog.c:797
Definition: c.h:435
JsonbIteratorToken JsonbIteratorNext(JsonbIterator **it, JsonbValue *val, bool skipNested)
Definition: jsonb_util.c:754
Definition: jsonb.h:25
Datum jsonb_delete_array ( PG_FUNCTION_ARGS  )

Definition at line 3448 of file jsonfuncs.c.

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

3449 {
3450  Jsonb *in = PG_GETARG_JSONB(0);
3451  ArrayType *keys = PG_GETARG_ARRAYTYPE_P(1);
3452  Datum *keys_elems;
3453  bool *keys_nulls;
3454  int keys_len;
3456  JsonbIterator *it;
3457  JsonbValue v,
3458  *res = NULL;
3459  bool skipNested = false;
3461 
3462  if (ARR_NDIM(keys) > 1)
3463  ereport(ERROR,
3464  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
3465  errmsg("wrong number of array subscripts")));
3466 
3467  if (JB_ROOT_IS_SCALAR(in))
3468  ereport(ERROR,
3469  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3470  errmsg("cannot delete from scalar")));
3471 
3472  if (JB_ROOT_COUNT(in) == 0)
3473  PG_RETURN_JSONB(in);
3474 
3475  deconstruct_array(keys, TEXTOID, -1, false, 'i',
3476  &keys_elems, &keys_nulls, &keys_len);
3477 
3478  if (keys_len == 0)
3479  PG_RETURN_JSONB(in);
3480 
3481  it = JsonbIteratorInit(&in->root);
3482 
3483  while ((r = JsonbIteratorNext(&it, &v, skipNested)) != 0)
3484  {
3485  skipNested = true;
3486 
3487  if ((r == WJB_ELEM || r == WJB_KEY) && v.type == jbvString)
3488  {
3489  int i;
3490  bool found = false;
3491 
3492  for (i = 0; i < keys_len; i++)
3493  {
3494  char *keyptr;
3495  int keylen;
3496 
3497  if (keys_nulls[i])
3498  continue;
3499 
3500  keyptr = VARDATA_ANY(keys_elems[i]);
3501  keylen = VARSIZE_ANY_EXHDR(keys_elems[i]);
3502  if (keylen == v.val.string.len &&
3503  memcmp(keyptr, v.val.string.val, keylen) == 0)
3504  {
3505  found = true;
3506  break;
3507  }
3508  }
3509  if (found)
3510  {
3511  /* skip corresponding value as well */
3512  if (r == WJB_KEY)
3513  JsonbIteratorNext(&it, &v, true);
3514 
3515  continue;
3516  }
3517  }
3518 
3519  res = pushJsonbValue(&state, r, r < WJB_BEGIN_ARRAY ? &v : NULL);
3520  }
3521 
3522  Assert(res != NULL);
3523 
3525 }
#define VARDATA_ANY(PTR)
Definition: postgres.h:349
Jsonb * JsonbValueToJsonb(JsonbValue *val)
Definition: jsonb_util.c:79
Definition: jsonb.h:215
#define TEXTOID
Definition: pg_type.h:324
char * val
Definition: jsonb.h:259
#define JB_ROOT_COUNT(jbp_)
Definition: jsonb.h:222
int errcode(int sqlerrcode)
Definition: elog.c:575
#define JB_ROOT_IS_SCALAR(jbp_)
Definition: jsonb.h:223
JsonbValue * pushJsonbValue(JsonbParseState **pstate, JsonbIteratorToken seq, JsonbValue *jbval)
Definition: jsonb_util.c:517
#define PG_GETARG_ARRAYTYPE_P(n)
Definition: array.h:244
#define ERROR
Definition: elog.h:43
#define PG_RETURN_JSONB(x)
Definition: jsonb.h:71
Definition: jsonb.h:23
#define ereport(elevel, rest)
Definition: elog.h:122
JsonbIteratorToken
Definition: jsonb.h:20
JsonbContainer root
Definition: jsonb.h:218
uintptr_t Datum
Definition: postgres.h:374
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:671
JsonbIterator * JsonbIteratorInit(JsonbContainer *container)
Definition: jsonb_util.c:718
Definition: regguts.h:298
#define ARR_NDIM(a)
Definition: array.h:271
enum jbvType type
Definition: jsonb.h:250
void deconstruct_array(ArrayType *array, Oid elmtype, int elmlen, bool elmbyval, char elmalign, Datum **elemsp, bool **nullsp, int *nelemsp)
Definition: arrayfuncs.c:3475
#define PG_GETARG_JSONB(x)
Definition: jsonb.h:70
#define VARSIZE_ANY_EXHDR(PTR)
Definition: postgres.h:342
int errmsg(const char *fmt,...)
Definition: elog.c:797
int i
JsonbIteratorToken JsonbIteratorNext(JsonbIterator **it, JsonbValue *val, bool skipNested)
Definition: jsonb_util.c:754
Definition: jsonb.h:25
Datum jsonb_delete_idx ( PG_FUNCTION_ARGS  )

Definition at line 3535 of file jsonfuncs.c.

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

3536 {
3537  Jsonb *in = PG_GETARG_JSONB(0);
3538  int idx = PG_GETARG_INT32(1);
3540  JsonbIterator *it;
3541  uint32 i = 0,
3542  n;
3543  JsonbValue v,
3544  *res = NULL;
3546 
3547  if (JB_ROOT_IS_SCALAR(in))
3548  ereport(ERROR,
3549  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3550  errmsg("cannot delete from scalar")));
3551 
3552  if (JB_ROOT_IS_OBJECT(in))
3553  ereport(ERROR,
3554  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3555  errmsg("cannot delete from object using integer index")));
3556 
3557  if (JB_ROOT_COUNT(in) == 0)
3558  PG_RETURN_JSONB(in);
3559 
3560  it = JsonbIteratorInit(&in->root);
3561 
3562  r = JsonbIteratorNext(&it, &v, false);
3563  Assert(r == WJB_BEGIN_ARRAY);
3564  n = v.val.array.nElems;
3565 
3566  if (idx < 0)
3567  {
3568  if (-idx > n)
3569  idx = n;
3570  else
3571  idx = n + idx;
3572  }
3573 
3574  if (idx >= n)
3575  PG_RETURN_JSONB(in);
3576 
3577  pushJsonbValue(&state, r, NULL);
3578 
3579  while ((r = JsonbIteratorNext(&it, &v, true)) != 0)
3580  {
3581  if (r == WJB_ELEM)
3582  {
3583  if (i++ == idx)
3584  continue;
3585  }
3586 
3587  res = pushJsonbValue(&state, r, r < WJB_BEGIN_ARRAY ? &v : NULL);
3588  }
3589 
3590  Assert(res != NULL);
3591 
3593 }
#define PG_GETARG_INT32(n)
Definition: fmgr.h:225
#define JB_ROOT_IS_OBJECT(jbp_)
Definition: jsonb.h:224
Jsonb * JsonbValueToJsonb(JsonbValue *val)
Definition: jsonb_util.c:79
Definition: jsonb.h:215
char * val
Definition: jsonb.h:259
#define JB_ROOT_COUNT(jbp_)
Definition: jsonb.h:222
int errcode(int sqlerrcode)
Definition: elog.c:575
Datum idx(PG_FUNCTION_ARGS)
Definition: _int_op.c:264
#define JB_ROOT_IS_SCALAR(jbp_)
Definition: jsonb.h:223
JsonbValue * pushJsonbValue(JsonbParseState **pstate, JsonbIteratorToken seq, JsonbValue *jbval)
Definition: jsonb_util.c:517
#define ERROR
Definition: elog.h:43
#define PG_RETURN_JSONB(x)
Definition: jsonb.h:71
unsigned int uint32
Definition: c.h:265
#define ereport(elevel, rest)
Definition: elog.h:122
JsonbIteratorToken
Definition: jsonb.h:20
JsonbContainer root
Definition: jsonb.h:218
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:671
JsonbIterator * JsonbIteratorInit(JsonbContainer *container)
Definition: jsonb_util.c:718
Definition: regguts.h:298
#define PG_GETARG_JSONB(x)
Definition: jsonb.h:70
int errmsg(const char *fmt,...)
Definition: elog.c:797
int i
JsonbIteratorToken JsonbIteratorNext(JsonbIterator **it, JsonbValue *val, bool skipNested)
Definition: jsonb_util.c:754
Definition: jsonb.h:25
Datum jsonb_delete_path ( PG_FUNCTION_ARGS  )

Definition at line 3647 of file jsonfuncs.c.

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

3648 {
3649  Jsonb *in = PG_GETARG_JSONB(0);
3650  ArrayType *path = PG_GETARG_ARRAYTYPE_P(1);
3651  JsonbValue *res = NULL;
3652  Datum *path_elems;
3653  bool *path_nulls;
3654  int path_len;
3655  JsonbIterator *it;
3656  JsonbParseState *st = NULL;
3657 
3658  if (ARR_NDIM(path) > 1)
3659  ereport(ERROR,
3660  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
3661  errmsg("wrong number of array subscripts")));
3662 
3663  if (JB_ROOT_IS_SCALAR(in))
3664  ereport(ERROR,
3665  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3666  errmsg("cannot delete path in scalar")));
3667 
3668  if (JB_ROOT_COUNT(in) == 0)
3669  PG_RETURN_JSONB(in);
3670 
3671  deconstruct_array(path, TEXTOID, -1, false, 'i',
3672  &path_elems, &path_nulls, &path_len);
3673 
3674  if (path_len == 0)
3675  PG_RETURN_JSONB(in);
3676 
3677  it = JsonbIteratorInit(&in->root);
3678 
3679  res = setPath(&it, path_elems, path_nulls, path_len, &st,
3680  0, NULL, JB_PATH_DELETE);
3681 
3682  Assert(res != NULL);
3683 
3685 }
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:3857
#define JB_ROOT_COUNT(jbp_)
Definition: jsonb.h:222
int errcode(int sqlerrcode)
Definition: elog.c:575
#define JB_ROOT_IS_SCALAR(jbp_)
Definition: jsonb.h:223
#define PG_GETARG_ARRAYTYPE_P(n)
Definition: array.h:244
#define ERROR
Definition: elog.h:43
#define PG_RETURN_JSONB(x)
Definition: jsonb.h:71
#define ereport(elevel, rest)
Definition: elog.h:122
JsonbContainer root
Definition: jsonb.h:218
uintptr_t Datum
Definition: postgres.h:374
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:671
JsonbIterator * JsonbIteratorInit(JsonbContainer *container)
Definition: jsonb_util.c:718
#define ARR_NDIM(a)
Definition: array.h:271
void deconstruct_array(ArrayType *array, Oid elmtype, int elmlen, bool elmbyval, char elmalign, Datum **elemsp, bool **nullsp, int *nelemsp)
Definition: arrayfuncs.c:3475
#define PG_GETARG_JSONB(x)
Definition: jsonb.h:70
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define JB_PATH_DELETE
Definition: jsonfuncs.c:38
Datum jsonb_each ( PG_FUNCTION_ARGS  )

Definition at line 1439 of file jsonfuncs.c.

References each_worker_jsonb().

1440 {
1441  return each_worker_jsonb(fcinfo, "jsonb_each", false);
1442 }
static Datum each_worker_jsonb(FunctionCallInfo fcinfo, const char *funcname, bool as_text)
Definition: jsonfuncs.c:1457
Datum jsonb_each_text ( PG_FUNCTION_ARGS  )

Definition at line 1451 of file jsonfuncs.c.

References each_worker_jsonb().

1452 {
1453  return each_worker_jsonb(fcinfo, "jsonb_each_text", true);
1454 }
static Datum each_worker_jsonb(FunctionCallInfo fcinfo, const char *funcname, bool as_text)
Definition: jsonfuncs.c:1457
Datum jsonb_extract_path ( PG_FUNCTION_ARGS  )

Definition at line 1159 of file jsonfuncs.c.

References get_jsonb_path_all().

1160 {
1161  return get_jsonb_path_all(fcinfo, false);
1162 }
static Datum get_jsonb_path_all(FunctionCallInfo fcinfo, bool as_text)
Definition: jsonfuncs.c:1171
Datum jsonb_extract_path_text ( PG_FUNCTION_ARGS  )

Definition at line 1165 of file jsonfuncs.c.

References get_jsonb_path_all().

1166 {
1167  return get_jsonb_path_all(fcinfo, true);
1168 }
static Datum get_jsonb_path_all(FunctionCallInfo fcinfo, bool as_text)
Definition: jsonfuncs.c:1171
Datum jsonb_insert ( PG_FUNCTION_ARGS  )

Definition at line 3692 of file jsonfuncs.c.

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

3693 {
3694  Jsonb *in = PG_GETARG_JSONB(0);
3695  ArrayType *path = PG_GETARG_ARRAYTYPE_P(1);
3697  bool after = PG_GETARG_BOOL(3);
3698  JsonbValue *res = NULL;
3699  Datum *path_elems;
3700  bool *path_nulls;
3701  int path_len;
3702  JsonbIterator *it;
3703  JsonbParseState *st = NULL;
3704 
3705  if (ARR_NDIM(path) > 1)
3706  ereport(ERROR,
3707  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
3708  errmsg("wrong number of array subscripts")));
3709 
3710  if (JB_ROOT_IS_SCALAR(in))
3711  ereport(ERROR,
3712  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3713  errmsg("cannot set path in scalar")));
3714 
3715  deconstruct_array(path, TEXTOID, -1, false, 'i',
3716  &path_elems, &path_nulls, &path_len);
3717 
3718  if (path_len == 0)
3719  PG_RETURN_JSONB(in);
3720 
3721  it = JsonbIteratorInit(&in->root);
3722 
3723  res = setPath(&it, path_elems, path_nulls, path_len, &st, 0, newval,
3725 
3726  Assert(res != NULL);
3727 
3729 }
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:3857
int errcode(int sqlerrcode)
Definition: elog.c:575
#define PG_GETARG_BOOL(n)
Definition: fmgr.h:230
#define JB_PATH_INSERT_BEFORE
Definition: jsonfuncs.c:40
#define JB_ROOT_IS_SCALAR(jbp_)
Definition: jsonb.h:223
#define JB_PATH_INSERT_AFTER
Definition: jsonfuncs.c:41
#define PG_GETARG_ARRAYTYPE_P(n)
Definition: array.h:244
#define ERROR
Definition: elog.h:43
#define PG_RETURN_JSONB(x)
Definition: jsonb.h:71
#define ereport(elevel, rest)
Definition: elog.h:122
JsonbContainer root
Definition: jsonb.h:218
uintptr_t Datum
Definition: postgres.h:374
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:671
JsonbIterator * JsonbIteratorInit(JsonbContainer *container)
Definition: jsonb_util.c:718
#define newval
#define ARR_NDIM(a)
Definition: array.h:271
void deconstruct_array(ArrayType *array, Oid elmtype, int elmlen, bool elmbyval, char elmalign, Datum **elemsp, bool **nullsp, int *nelemsp)
Definition: arrayfuncs.c:3475
#define PG_GETARG_JSONB(x)
Definition: jsonb.h:70
int errmsg(const char *fmt,...)
Definition: elog.c:797
Datum jsonb_object_field ( PG_FUNCTION_ARGS  )

Definition at line 499 of file jsonfuncs.c.

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

500 {
501  Jsonb *jb = PG_GETARG_JSONB(0);
502  text *key = PG_GETARG_TEXT_PP(1);
503  JsonbValue *v;
504 
505  if (!JB_ROOT_IS_OBJECT(jb))
506  PG_RETURN_NULL();
507 
509  VARDATA_ANY(key),
510  VARSIZE_ANY_EXHDR(key));
511 
512  if (v != NULL)
514 
515  PG_RETURN_NULL();
516 }
#define JB_ROOT_IS_OBJECT(jbp_)
Definition: jsonb.h:224
#define VARDATA_ANY(PTR)
Definition: postgres.h:349
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:3082
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:270
#define PG_RETURN_JSONB(x)
Definition: jsonb.h:71
JsonbContainer root
Definition: jsonb.h:218
#define NULL
Definition: c.h:226
#define JB_FOBJECT
Definition: jsonb.h:205
#define PG_GETARG_JSONB(x)
Definition: jsonb.h:70
#define VARSIZE_ANY_EXHDR(PTR)
Definition: postgres.h:342
Definition: c.h:435
#define PG_RETURN_NULL()
Definition: fmgr.h:289
Datum jsonb_object_field_text ( PG_FUNCTION_ARGS  )

Definition at line 535 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(), NULL, numeric_out(), PG_GETARG_JSONB, PG_GETARG_TEXT_PP, PG_RETURN_NULL, PG_RETURN_TEXT_P, PointerGetDatum, Jsonb::root, JsonbValue::type, JsonbValue::val, VARDATA_ANY, and VARSIZE_ANY_EXHDR.

536 {
537  Jsonb *jb = PG_GETARG_JSONB(0);
538  text *key = PG_GETARG_TEXT_PP(1);
539  JsonbValue *v;
540 
541  if (!JB_ROOT_IS_OBJECT(jb))
542  PG_RETURN_NULL();
543 
545  VARDATA_ANY(key),
546  VARSIZE_ANY_EXHDR(key));
547 
548  if (v != NULL)
549  {
550  text *result = NULL;
551 
552  switch (v->type)
553  {
554  case jbvNull:
555  break;
556  case jbvBool:
557  result = cstring_to_text(v->val.boolean ? "true" : "false");
558  break;
559  case jbvString:
560  result = cstring_to_text_with_len(v->val.string.val, v->val.string.len);
561  break;
562  case jbvNumeric:
564  PointerGetDatum(v->val.numeric))));
565  break;
566  case jbvBinary:
567  {
568  StringInfo jtext = makeStringInfo();
569 
570  (void) JsonbToCString(jtext, v->val.binary.data, -1);
571  result = cstring_to_text_with_len(jtext->data, jtext->len);
572  }
573  break;
574  default:
575  elog(ERROR, "unrecognized jsonb type: %d", (int) v->type);
576  }
577 
578  if (result)
579  PG_RETURN_TEXT_P(result);
580  }
581 
582  PG_RETURN_NULL();
583 }
#define JB_ROOT_IS_OBJECT(jbp_)
Definition: jsonb.h:224
#define VARDATA_ANY(PTR)
Definition: postgres.h:349
Definition: jsonb.h:215
#define PointerGetDatum(X)
Definition: postgres.h:564
char * val
Definition: jsonb.h:259
Definition: jsonb.h:234
StringInfo makeStringInfo(void)
Definition: stringinfo.c:29
Datum numeric_out(PG_FUNCTION_ARGS)
Definition: numeric.c:641
static JsonbValue * findJsonbValueFromContainerLen(JsonbContainer *container, uint32 flags, char *key, uint32 keylen)
Definition: jsonfuncs.c:3082
Definition: jsonb.h:231
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:555
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:270
#define ERROR
Definition: elog.h:43
#define DatumGetCString(X)
Definition: postgres.h:574
text * cstring_to_text_with_len(const char *s, int len)
Definition: varlena.c:163
JsonbContainer root
Definition: jsonb.h:218
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:314
text * cstring_to_text(const char *s)
Definition: varlena.c:151
#define NULL
Definition: c.h:226
#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
#define PG_GETARG_JSONB(x)
Definition: jsonb.h:70
#define VARSIZE_ANY_EXHDR(PTR)
Definition: postgres.h:342
Definition: c.h:435
#define elog
Definition: elog.h:219
#define PG_RETURN_NULL()
Definition: fmgr.h:289
Datum jsonb_object_keys ( PG_FUNCTION_ARGS  )

Definition at line 288 of file jsonfuncs.c.

References CStringGetTextDatum, ereport, errcode(), errmsg(), ERROR, i, JB_ROOT_COUNT, JB_ROOT_IS_ARRAY, JB_ROOT_IS_SCALAR, JsonbIteratorInit(), JsonbIteratorNext(), MemoryContextSwitchTo(), FuncCallContext::multi_call_memory_ctx, palloc(), pfree(), PG_GETARG_JSONB, OkeysState::result, OkeysState::result_count, OkeysState::result_size, Jsonb::root, OkeysState::sent_count, SRF_FIRSTCALL_INIT, SRF_IS_FIRSTCALL, SRF_PERCALL_SETUP, SRF_RETURN_DONE, SRF_RETURN_NEXT, FuncCallContext::user_fctx, JsonbValue::val, WJB_DONE, and WJB_KEY.

289 {
290  FuncCallContext *funcctx;
291  OkeysState *state;
292  int i;
293 
294  if (SRF_IS_FIRSTCALL())
295  {
296  MemoryContext oldcontext;
297  Jsonb *jb = PG_GETARG_JSONB(0);
298  bool skipNested = false;
299  JsonbIterator *it;
300  JsonbValue v;
302 
303  if (JB_ROOT_IS_SCALAR(jb))
304  ereport(ERROR,
305  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
306  errmsg("cannot call %s on a scalar",
307  "jsonb_object_keys")));
308  else if (JB_ROOT_IS_ARRAY(jb))
309  ereport(ERROR,
310  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
311  errmsg("cannot call %s on an array",
312  "jsonb_object_keys")));
313 
314  funcctx = SRF_FIRSTCALL_INIT();
315  oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
316 
317  state = palloc(sizeof(OkeysState));
318 
319  state->result_size = JB_ROOT_COUNT(jb);
320  state->result_count = 0;
321  state->sent_count = 0;
322  state->result = palloc(state->result_size * sizeof(char *));
323 
324  it = JsonbIteratorInit(&jb->root);
325 
326  while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE)
327  {
328  skipNested = true;
329 
330  if (r == WJB_KEY)
331  {
332  char *cstr;
333 
334  cstr = palloc(v.val.string.len + 1 * sizeof(char));
335  memcpy(cstr, v.val.string.val, v.val.string.len);
336  cstr[v.val.string.len] = '\0';
337  state->result[state->result_count++] = cstr;
338  }
339  }
340 
341  MemoryContextSwitchTo(oldcontext);
342  funcctx->user_fctx = (void *) state;
343  }
344 
345  funcctx = SRF_PERCALL_SETUP();
346  state = (OkeysState *) funcctx->user_fctx;
347 
348  if (state->sent_count < state->result_count)
349  {
350  char *nxt = state->result[state->sent_count++];
351 
352  SRF_RETURN_NEXT(funcctx, CStringGetTextDatum(nxt));
353  }
354 
355  /* cleanup to reduce or eliminate memory leaks */
356  for (i = 0; i < state->result_count; i++)
357  pfree(state->result[i]);
358  pfree(state->result);
359  pfree(state);
360 
361  SRF_RETURN_DONE(funcctx);
362 }
int result_count
Definition: jsonfuncs.c:51
Definition: jsonb.h:215
#define SRF_IS_FIRSTCALL()
Definition: funcapi.h:285
char * val
Definition: jsonb.h:259
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
Definition: jsonb.h:22
#define JB_ROOT_COUNT(jbp_)
Definition: jsonb.h:222
int errcode(int sqlerrcode)
Definition: elog.c:575
int sent_count
Definition: jsonfuncs.c:52
#define JB_ROOT_IS_SCALAR(jbp_)
Definition: jsonb.h:223
#define SRF_PERCALL_SETUP()
Definition: funcapi.h:289
#define SRF_RETURN_NEXT(_funcctx, _result)
Definition: funcapi.h:291
void pfree(void *pointer)
Definition: mcxt.c:992
#define ERROR
Definition: elog.h:43
#define JB_ROOT_IS_ARRAY(jbp_)
Definition: jsonb.h:225
Definition: jsonb.h:23
#define ereport(elevel, rest)
Definition: elog.h:122
JsonbIteratorToken
Definition: jsonb.h:20
JsonbContainer root
Definition: jsonb.h:218
char ** result
Definition: jsonfuncs.c:49
JsonbIterator * JsonbIteratorInit(JsonbContainer *container)
Definition: jsonb_util.c:718
Definition: regguts.h:298
MemoryContext multi_call_memory_ctx
Definition: funcapi.h:109
int result_size
Definition: jsonfuncs.c:50
#define PG_GETARG_JSONB(x)
Definition: jsonb.h:70
void * user_fctx
Definition: funcapi.h:90
void * palloc(Size size)
Definition: mcxt.c:891
int errmsg(const char *fmt,...)
Definition: elog.c:797
int i
#define CStringGetTextDatum(s)
Definition: builtins.h:90
JsonbIteratorToken JsonbIteratorNext(JsonbIterator **it, JsonbValue *val, bool skipNested)
Definition: jsonb_util.c:754
#define SRF_RETURN_DONE(_funcctx)
Definition: funcapi.h:309
#define SRF_FIRSTCALL_INIT()
Definition: funcapi.h:287
Datum jsonb_populate_record ( PG_FUNCTION_ARGS  )

Definition at line 2079 of file jsonfuncs.c.

References populate_record_worker().

2080 {
2081  return populate_record_worker(fcinfo, "jsonb_populate_record", true);
2082 }
static Datum populate_record_worker(FunctionCallInfo fcinfo, const char *funcname, bool have_record_arg)
Definition: jsonfuncs.c:2103
Datum jsonb_populate_recordset ( PG_FUNCTION_ARGS  )

Definition at line 2517 of file jsonfuncs.c.

References populate_recordset_worker().

2518 {
2519  return populate_recordset_worker(fcinfo, "jsonb_populate_recordset", true);
2520 }
static Datum populate_recordset_worker(FunctionCallInfo fcinfo, const char *funcname, bool have_record_arg)
Definition: jsonfuncs.c:2662
Datum jsonb_pretty ( PG_FUNCTION_ARGS  )

Definition at line 3338 of file jsonfuncs.c.

References cstring_to_text_with_len(), StringInfoData::data, JsonbToCStringIndent(), StringInfoData::len, makeStringInfo(), PG_GETARG_JSONB, PG_RETURN_TEXT_P, Jsonb::root, and VARSIZE.

3339 {
3340  Jsonb *jb = PG_GETARG_JSONB(0);
3341  StringInfo str = makeStringInfo();
3342 
3343  JsonbToCStringIndent(str, &jb->root, VARSIZE(jb));
3344 
3346 }
Definition: jsonb.h:215
#define VARSIZE(PTR)
Definition: postgres.h:306
StringInfo makeStringInfo(void)
Definition: stringinfo.c:29
char * JsonbToCStringIndent(StringInfo out, JsonbContainer *in, int estimated_len)
Definition: jsonb.c:437
text * cstring_to_text_with_len(const char *s, int len)
Definition: varlena.c:163
JsonbContainer root
Definition: jsonb.h:218
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:314
#define PG_GETARG_JSONB(x)
Definition: jsonb.h:70
Datum jsonb_set ( PG_FUNCTION_ARGS  )

Definition at line 3600 of file jsonfuncs.c.

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

3601 {
3602  Jsonb *in = PG_GETARG_JSONB(0);
3603  ArrayType *path = PG_GETARG_ARRAYTYPE_P(1);
3605  bool create = PG_GETARG_BOOL(3);
3606  JsonbValue *res = NULL;
3607  Datum *path_elems;
3608  bool *path_nulls;
3609  int path_len;
3610  JsonbIterator *it;
3611  JsonbParseState *st = NULL;
3612 
3613  if (ARR_NDIM(path) > 1)
3614  ereport(ERROR,
3615  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
3616  errmsg("wrong number of array subscripts")));
3617 
3618  if (JB_ROOT_IS_SCALAR(in))
3619  ereport(ERROR,
3620  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3621  errmsg("cannot set path in scalar")));
3622 
3623  if (JB_ROOT_COUNT(in) == 0 && !create)
3624  PG_RETURN_JSONB(in);
3625 
3626  deconstruct_array(path, TEXTOID, -1, false, 'i',
3627  &path_elems, &path_nulls, &path_len);
3628 
3629  if (path_len == 0)
3630  PG_RETURN_JSONB(in);
3631 
3632  it = JsonbIteratorInit(&in->root);
3633 
3634  res = setPath(&it, path_elems, path_nulls, path_len, &st,
3635  0, newval, create ? JB_PATH_CREATE : JB_PATH_REPLACE);
3636 
3637  Assert(res != NULL);
3638 
3640 }
Jsonb * JsonbValueToJsonb(JsonbValue *val)
Definition: jsonb_util.c:79
Definition: jsonb.h:215
#define TEXTOID
Definition: pg_type.h:324
#define JB_PATH_REPLACE
Definition: jsonfuncs.c:39
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:3857
#define JB_ROOT_COUNT(jbp_)
Definition: jsonb.h:222
int errcode(int sqlerrcode)
Definition: elog.c:575
#define PG_GETARG_BOOL(n)
Definition: fmgr.h:230
#define JB_ROOT_IS_SCALAR(jbp_)
Definition: jsonb.h:223
#define JB_PATH_CREATE
Definition: jsonfuncs.c:37
#define PG_GETARG_ARRAYTYPE_P(n)
Definition: array.h:244
#define ERROR
Definition: elog.h:43
#define PG_RETURN_JSONB(x)
Definition: jsonb.h:71
#define ereport(elevel, rest)
Definition: elog.h:122
JsonbContainer root
Definition: jsonb.h:218
uintptr_t Datum
Definition: postgres.h:374
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:671
JsonbIterator * JsonbIteratorInit(JsonbContainer *container)
Definition: jsonb_util.c:718
#define newval
#define ARR_NDIM(a)
Definition: array.h:271
void deconstruct_array(ArrayType *array, Oid elmtype, int elmlen, bool elmbyval, char elmalign, Datum **elemsp, bool **nullsp, int *nelemsp)
Definition: arrayfuncs.c:3475
#define PG_GETARG_JSONB(x)
Definition: jsonb.h:70
int errmsg(const char *fmt,...)
Definition: elog.c:797
Datum jsonb_strip_nulls ( PG_FUNCTION_ARGS  )

Definition at line 3229 of file jsonfuncs.c.

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

3230 {
3231  Jsonb *jb = PG_GETARG_JSONB(0);
3232  JsonbIterator *it;
3233  JsonbParseState *parseState = NULL;
3234  JsonbValue *res = NULL;
3235  JsonbValue v,
3236  k;
3237  JsonbIteratorToken type;
3238  bool last_was_key = false;
3239 
3240  if (JB_ROOT_IS_SCALAR(jb))
3241  PG_RETURN_POINTER(jb);
3242 
3243  it = JsonbIteratorInit(&jb->root);
3244 
3245  while ((type = JsonbIteratorNext(&it, &v, false)) != WJB_DONE)
3246  {
3247  Assert(!(type == WJB_KEY && last_was_key));
3248 
3249  if (type == WJB_KEY)
3250  {
3251  /* stash the key until we know if it has a null value */
3252  k = v;
3253  last_was_key = true;
3254  continue;
3255  }
3256 
3257  if (last_was_key)
3258  {
3259  /* if the last element was a key this one can't be */
3260  last_was_key = false;
3261 
3262  /* skip this field if value is null */
3263  if (type == WJB_VALUE && v.type == jbvNull)
3264  continue;
3265 
3266  /* otherwise, do a delayed push of the key */
3267  (void) pushJsonbValue(&parseState, WJB_KEY, &k);
3268  }
3269 
3270  if (type == WJB_VALUE || type == WJB_ELEM)
3271  res = pushJsonbValue(&parseState, type, &v);
3272  else
3273  res = pushJsonbValue(&parseState, type, NULL);
3274  }
3275 
3276  Assert(res != NULL);
3277 
3279 }
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:305
Jsonb * JsonbValueToJsonb(JsonbValue *val)
Definition: jsonb_util.c:79
Definition: jsonb.h:215
Definition: jsonb.h:22
Definition: jsonb.h:231
#define JB_ROOT_IS_SCALAR(jbp_)
Definition: jsonb.h:223
JsonbValue * pushJsonbValue(JsonbParseState **pstate, JsonbIteratorToken seq, JsonbValue *jbval)
Definition: jsonb_util.c:517
Definition: jsonb.h:23
JsonbIteratorToken
Definition: jsonb.h:20
JsonbContainer root
Definition: jsonb.h:218
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:671
JsonbIterator * JsonbIteratorInit(JsonbContainer *container)
Definition: jsonb_util.c:718
enum jbvType type
Definition: jsonb.h:250
#define PG_GETARG_JSONB(x)
Definition: jsonb.h:70
JsonbIteratorToken JsonbIteratorNext(JsonbIterator **it, JsonbValue *val, bool skipNested)
Definition: jsonb_util.c:754
Definition: jsonb.h:25
Datum jsonb_to_record ( PG_FUNCTION_ARGS  )

Definition at line 2085 of file jsonfuncs.c.

References populate_record_worker().

2086 {
2087  return populate_record_worker(fcinfo, "jsonb_to_record", false);
2088 }
static Datum populate_record_worker(FunctionCallInfo fcinfo, const char *funcname, bool have_record_arg)
Definition: jsonfuncs.c:2103
Datum jsonb_to_recordset ( PG_FUNCTION_ARGS  )

Definition at line 2523 of file jsonfuncs.c.

References populate_recordset_worker().

2524 {
2525  return populate_recordset_worker(fcinfo, "jsonb_to_recordset", false);
2526 }
static Datum populate_recordset_worker(FunctionCallInfo fcinfo, const char *funcname, bool have_record_arg)
Definition: jsonfuncs.c:2662