PostgreSQL Source Code  git master
jsonb_plperl.c File Reference
#include "postgres.h"
#include <math.h>
#include "fmgr.h"
#include "plperl.h"
#include "plperl_helpers.h"
#include "utils/jsonb.h"
#include "utils/fmgrprotos.h"
Include dependency graph for jsonb_plperl.c:

Go to the source code of this file.

Functions

static SV * Jsonb_to_SV (JsonbContainer *jsonb)
 
static JsonbValueSV_to_JsonbValue (SV *obj, JsonbParseState **ps, bool is_elem)
 
static SV * JsonbValue_to_SV (JsonbValue *jbv)
 
static JsonbValueAV_to_JsonbValue (AV *in, JsonbParseState **jsonb_state)
 
static JsonbValueHV_to_JsonbValue (HV *obj, JsonbParseState **jsonb_state)
 
 PG_FUNCTION_INFO_V1 (jsonb_to_plperl)
 
Datum jsonb_to_plperl (PG_FUNCTION_ARGS)
 
 PG_FUNCTION_INFO_V1 (plperl_to_jsonb)
 
Datum plperl_to_jsonb (PG_FUNCTION_ARGS)
 

Variables

 PG_MODULE_MAGIC
 

Function Documentation

◆ AV_to_JsonbValue()

static JsonbValue* AV_to_JsonbValue ( AV *  in,
JsonbParseState **  jsonb_state 
)
static

Definition at line 129 of file jsonb_plperl.c.

References dTHX, FALSE, i, pushJsonbValue(), SV_to_JsonbValue(), value, WJB_BEGIN_ARRAY, and WJB_END_ARRAY.

Referenced by SV_to_JsonbValue().

130 {
131  dTHX;
132  SSize_t pcount = av_len(in) + 1;
133  SSize_t i;
134 
135  pushJsonbValue(jsonb_state, WJB_BEGIN_ARRAY, NULL);
136 
137  for (i = 0; i < pcount; i++)
138  {
139  SV **value = av_fetch(in, i, FALSE);
140 
141  if (value)
142  (void) SV_to_JsonbValue(*value, jsonb_state, true);
143  }
144 
145  return pushJsonbValue(jsonb_state, WJB_END_ARRAY, NULL);
146 }
#define dTHX
Definition: ppport.h:3208
#define FALSE
Definition: ecpglib.h:39
static struct @145 value
static JsonbValue * SV_to_JsonbValue(SV *obj, JsonbParseState **ps, bool is_elem)
Definition: jsonb_plperl.c:175
JsonbValue * pushJsonbValue(JsonbParseState **pstate, JsonbIteratorToken seq, JsonbValue *jbval)
Definition: jsonb_util.c:558
int i

◆ HV_to_JsonbValue()

static JsonbValue* HV_to_JsonbValue ( HV *  obj,
JsonbParseState **  jsonb_state 
)
static

Definition at line 149 of file jsonb_plperl.c.

References dTHX, jbvString, sort-test::key, pnstrdup(), pushJsonbValue(), SV_to_JsonbValue(), JsonbValue::type, JsonbValue::val, val, WJB_BEGIN_OBJECT, WJB_END_OBJECT, and WJB_KEY.

Referenced by SV_to_JsonbValue().

150 {
151  dTHX;
152  JsonbValue key;
153  SV *val;
154  char *kstr;
155  I32 klen;
156 
157  key.type = jbvString;
158 
159  pushJsonbValue(jsonb_state, WJB_BEGIN_OBJECT, NULL);
160 
161  (void) hv_iterinit(obj);
162 
163  while ((val = hv_iternextsv(obj, &kstr, &klen)))
164  {
165  key.val.string.val = pnstrdup(kstr, klen);
166  key.val.string.len = klen;
167  pushJsonbValue(jsonb_state, WJB_KEY, &key);
168  (void) SV_to_JsonbValue(val, jsonb_state, false);
169  }
170 
171  return pushJsonbValue(jsonb_state, WJB_END_OBJECT, NULL);
172 }
char * pnstrdup(const char *in, Size len)
Definition: mcxt.c:1197
#define dTHX
Definition: ppport.h:3208
char * val
Definition: jsonb.h:272
static JsonbValue * SV_to_JsonbValue(SV *obj, JsonbParseState **ps, bool is_elem)
Definition: jsonb_plperl.c:175
JsonbValue * pushJsonbValue(JsonbParseState **pstate, JsonbIteratorToken seq, JsonbValue *jbval)
Definition: jsonb_util.c:558
Definition: jsonb.h:23
enum jbvType type
Definition: jsonb.h:263
long val
Definition: informix.c:684

◆ jsonb_to_plperl()

Datum jsonb_to_plperl ( PG_FUNCTION_ARGS  )

Definition at line 278 of file jsonb_plperl.c.

References dTHX, Jsonb_to_SV(), PG_FUNCTION_INFO_V1(), PG_GETARG_JSONB_P, plperl_to_jsonb(), PointerGetDatum, and Jsonb::root.

Referenced by SV_to_JsonbValue().

279 {
280  dTHX;
281  Jsonb *in = PG_GETARG_JSONB_P(0);
282  SV *sv = Jsonb_to_SV(&in->root);
283 
284  return PointerGetDatum(sv);
285 }
Definition: jsonb.h:220
#define dTHX
Definition: ppport.h:3208
#define PointerGetDatum(X)
Definition: postgres.h:556
JsonbContainer root
Definition: jsonb.h:223
static SV * Jsonb_to_SV(JsonbContainer *jsonb)
Definition: jsonb_plperl.c:60
#define PG_GETARG_JSONB_P(x)
Definition: jsonb.h:74

◆ Jsonb_to_SV()

static SV * Jsonb_to_SV ( JsonbContainer jsonb)
static

Definition at line 60 of file jsonb_plperl.c.

References av, dTHX, elog, ERROR, JsonbIteratorInit(), JsonbIteratorNext(), JsonbValue_to_SV(), JsonbValue::val, val, value, WJB_BEGIN_ARRAY, WJB_BEGIN_OBJECT, WJB_DONE, WJB_ELEM, WJB_END_ARRAY, WJB_KEY, and WJB_VALUE.

Referenced by jsonb_to_plperl(), and JsonbValue_to_SV().

61 {
62  dTHX;
63  JsonbValue v;
64  JsonbIterator *it;
66 
67  it = JsonbIteratorInit(jsonb);
68  r = JsonbIteratorNext(&it, &v, true);
69 
70  switch (r)
71  {
72  case WJB_BEGIN_ARRAY:
73  if (v.val.array.rawScalar)
74  {
75  JsonbValue tmp;
76 
77  if ((r = JsonbIteratorNext(&it, &v, true)) != WJB_ELEM ||
78  (r = JsonbIteratorNext(&it, &tmp, true)) != WJB_END_ARRAY ||
79  (r = JsonbIteratorNext(&it, &tmp, true)) != WJB_DONE)
80  elog(ERROR, "unexpected jsonb token: %d", r);
81 
82  return JsonbValue_to_SV(&v);
83  }
84  else
85  {
86  AV *av = newAV();
87 
88  while ((r = JsonbIteratorNext(&it, &v, true)) != WJB_DONE)
89  {
90  if (r == WJB_ELEM)
91  av_push(av, JsonbValue_to_SV(&v));
92  }
93 
94  return newRV((SV *) av);
95  }
96 
97  case WJB_BEGIN_OBJECT:
98  {
99  HV *hv = newHV();
100 
101  while ((r = JsonbIteratorNext(&it, &v, true)) != WJB_DONE)
102  {
103  if (r == WJB_KEY)
104  {
105  /* json key in v, json value in val */
106  JsonbValue val;
107 
108  if (JsonbIteratorNext(&it, &val, true) == WJB_VALUE)
109  {
110  SV *value = JsonbValue_to_SV(&val);
111 
112  (void) hv_store(hv,
113  v.val.string.val, v.val.string.len,
114  value, 0);
115  }
116  }
117  }
118 
119  return newRV((SV *) hv);
120  }
121 
122  default:
123  elog(ERROR, "unexpected jsonb token: %d", r);
124  return NULL;
125  }
126 }
#define dTHX
Definition: ppport.h:3208
char * val
Definition: jsonb.h:272
Definition: jsonb.h:22
static struct @145 value
#define ERROR
Definition: elog.h:43
static SV * JsonbValue_to_SV(JsonbValue *jbv)
Definition: jsonb_plperl.c:18
Definition: jsonb.h:23
JsonbIteratorToken
Definition: jsonb.h:20
struct @18::@19 av[32]
JsonbIterator * JsonbIteratorInit(JsonbContainer *container)
Definition: jsonb_util.c:759
#define elog(elevel,...)
Definition: elog.h:226
long val
Definition: informix.c:684
JsonbIteratorToken JsonbIteratorNext(JsonbIterator **it, JsonbValue *val, bool skipNested)
Definition: jsonb_util.c:795
Definition: jsonb.h:25

◆ JsonbValue_to_SV()

static SV* JsonbValue_to_SV ( JsonbValue jbv)
static

Definition at line 18 of file jsonb_plperl.c.

References cstr2sv(), DatumGetCString, DirectFunctionCall1, dTHX, elog, ERROR, jbvBinary, jbvBool, jbvNull, jbvNumeric, jbvString, Jsonb_to_SV(), numeric_out(), NumericGetDatum, pfree(), PL_sv_no, PL_sv_yes, pnstrdup(), generate_unaccent_rules::str, JsonbValue::type, and JsonbValue::val.

Referenced by Jsonb_to_SV().

19 {
20  dTHX;
21 
22  switch (jbv->type)
23  {
24  case jbvBinary:
25  return Jsonb_to_SV(jbv->val.binary.data);
26 
27  case jbvNumeric:
28  {
30  NumericGetDatum(jbv->val.numeric)));
31  SV *result = newSVnv(SvNV(cstr2sv(str)));
32 
33  pfree(str);
34  return result;
35  }
36 
37  case jbvString:
38  {
39  char *str = pnstrdup(jbv->val.string.val,
40  jbv->val.string.len);
41  SV *result = cstr2sv(str);
42 
43  pfree(str);
44  return result;
45  }
46 
47  case jbvBool:
48  return newSVnv(SvNV(jbv->val.boolean ? &PL_sv_yes : &PL_sv_no));
49 
50  case jbvNull:
51  return newSV(0);
52 
53  default:
54  elog(ERROR, "unexpected jsonb value type: %d", jbv->type);
55  return NULL;
56  }
57 }
char * pnstrdup(const char *in, Size len)
Definition: mcxt.c:1197
#define dTHX
Definition: ppport.h:3208
char * val
Definition: jsonb.h:272
#define NumericGetDatum(X)
Definition: numeric.h:51
Definition: jsonb.h:239
Datum numeric_out(PG_FUNCTION_ARGS)
Definition: numeric.c:655
Definition: jsonb.h:236
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:617
void pfree(void *pointer)
Definition: mcxt.c:1056
#define ERROR
Definition: elog.h:43
#define DatumGetCString(X)
Definition: postgres.h:566
#define PL_sv_yes
Definition: ppport.h:4130
static SV * cstr2sv(const char *str)
static SV * Jsonb_to_SV(JsonbContainer *jsonb)
Definition: jsonb_plperl.c:60
enum jbvType type
Definition: jsonb.h:263
#define elog(elevel,...)
Definition: elog.h:226
#define PL_sv_no
Definition: ppport.h:4128

◆ PG_FUNCTION_INFO_V1() [1/2]

PG_FUNCTION_INFO_V1 ( jsonb_to_plperl  )

◆ PG_FUNCTION_INFO_V1() [2/2]

PG_FUNCTION_INFO_V1 ( plperl_to_jsonb  )

◆ plperl_to_jsonb()

Datum plperl_to_jsonb ( PG_FUNCTION_ARGS  )

Definition at line 291 of file jsonb_plperl.c.

References dTHX, JsonbValueToJsonb(), PG_GETARG_POINTER, PG_RETURN_JSONB_P, and SV_to_JsonbValue().

Referenced by jsonb_to_plperl().

292 {
293  dTHX;
294  JsonbParseState *jsonb_state = NULL;
295  SV *in = (SV *) PG_GETARG_POINTER(0);
296  JsonbValue *out = SV_to_JsonbValue(in, &jsonb_state, true);
297  Jsonb *result = JsonbValueToJsonb(out);
298 
299  PG_RETURN_JSONB_P(result);
300 }
Jsonb * JsonbValueToJsonb(JsonbValue *val)
Definition: jsonb_util.c:84
Definition: jsonb.h:220
#define dTHX
Definition: ppport.h:3208
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:271
static JsonbValue * SV_to_JsonbValue(SV *obj, JsonbParseState **ps, bool is_elem)
Definition: jsonb_plperl.c:175
#define PG_RETURN_JSONB_P(x)
Definition: jsonb.h:76

◆ SV_to_JsonbValue()

static JsonbValue * SV_to_JsonbValue ( SV *  obj,
JsonbParseState **  ps,
bool  is_elem 
)
static

Definition at line 175 of file jsonb_plperl.c.

References AV_to_JsonbValue(), CStringGetDatum, DatumGetNumeric, DirectFunctionCall1, DirectFunctionCall3, dTHX, ereport, errcode(), errmsg(), ERROR, float8_numeric(), Float8GetDatum(), HV_to_JsonbValue(), Int32GetDatum, Int64GetDatum(), int8_numeric(), InvalidOid, isinf(), jbvNull, jbvNumeric, jbvString, jsonb_to_plperl(), numeric_in(), ObjectIdGetDatum, palloc(), PG_FUNCTION_INFO_V1(), pushJsonbValue(), sv2cstr(), SvPV_nolen, JsonbValue::type, JsonbValue::val, WJB_ELEM, and WJB_VALUE.

Referenced by AV_to_JsonbValue(), HV_to_JsonbValue(), and plperl_to_jsonb().

176 {
177  dTHX;
178  JsonbValue out; /* result */
179 
180  /* Dereference references recursively. */
181  while (SvROK(in))
182  in = SvRV(in);
183 
184  switch (SvTYPE(in))
185  {
186  case SVt_PVAV:
187  return AV_to_JsonbValue((AV *) in, jsonb_state);
188 
189  case SVt_PVHV:
190  return HV_to_JsonbValue((HV *) in, jsonb_state);
191 
192  default:
193  if (!SvOK(in))
194  {
195  out.type = jbvNull;
196  }
197  else if (SvUOK(in))
198  {
199  /*
200  * If UV is >=64 bits, we have no better way to make this
201  * happen than converting to text and back. Given the low
202  * usage of UV in Perl code, it's not clear it's worth working
203  * hard to provide alternate code paths.
204  */
205  const char *strval = SvPV_nolen(in);
206 
207  out.type = jbvNumeric;
208  out.val.numeric =
210  CStringGetDatum(strval),
212  Int32GetDatum(-1)));
213  }
214  else if (SvIOK(in))
215  {
216  IV ival = SvIV(in);
217 
218  out.type = jbvNumeric;
219  out.val.numeric =
221  Int64GetDatum((int64) ival)));
222  }
223  else if (SvNOK(in))
224  {
225  double nval = SvNV(in);
226 
227  /*
228  * jsonb doesn't allow infinity or NaN (per JSON
229  * specification), but the numeric type that is used for the
230  * storage accepts NaN, so we have to prevent it here
231  * explicitly. We don't really have to check for isinf()
232  * here, as numeric doesn't allow it and it would be caught
233  * later, but it makes for a nicer error message.
234  */
235  if (isinf(nval))
236  ereport(ERROR,
237  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
238  (errmsg("cannot convert infinity to jsonb"))));
239  if (isnan(nval))
240  ereport(ERROR,
241  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
242  (errmsg("cannot convert NaN to jsonb"))));
243 
244  out.type = jbvNumeric;
245  out.val.numeric =
247  Float8GetDatum(nval)));
248  }
249  else if (SvPOK(in))
250  {
251  out.type = jbvString;
252  out.val.string.val = sv2cstr(in);
253  out.val.string.len = strlen(out.val.string.val);
254  }
255  else
256  {
257  /*
258  * XXX It might be nice if we could include the Perl type in
259  * the error message.
260  */
261  ereport(ERROR,
262  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
263  (errmsg("cannot transform this Perl type to jsonb"))));
264  return NULL;
265  }
266  }
267 
268  /* Push result into 'jsonb_state' unless it is a raw scalar. */
269  return *jsonb_state
270  ? pushJsonbValue(jsonb_state, is_elem ? WJB_ELEM : WJB_VALUE, &out)
271  : memcpy(palloc(sizeof(JsonbValue)), &out, sizeof(JsonbValue));
272 }
static JsonbValue * HV_to_JsonbValue(HV *obj, JsonbParseState **jsonb_state)
Definition: jsonb_plperl.c:149
#define dTHX
Definition: ppport.h:3208
char * val
Definition: jsonb.h:272
int errcode(int sqlerrcode)
Definition: elog.c:570
Definition: jsonb.h:236
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:617
Datum int8_numeric(PG_FUNCTION_ARGS)
Definition: numeric.c:3285
Datum Float8GetDatum(float8 X)
Definition: fmgr.c:1723
JsonbValue * pushJsonbValue(JsonbParseState **pstate, JsonbIteratorToken seq, JsonbValue *jbval)
Definition: jsonb_util.c:558
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
#define SvPV_nolen(sv)
Definition: ppport.h:5057
int isinf(double x)
#define CStringGetDatum(X)
Definition: postgres.h:578
Datum numeric_in(PG_FUNCTION_ARGS)
Definition: numeric.c:573
Datum Int64GetDatum(int64 X)
Definition: fmgr.c:1699
#define ereport(elevel, rest)
Definition: elog.h:141
#define DirectFunctionCall3(func, arg1, arg2, arg3)
Definition: fmgr.h:621
static JsonbValue * AV_to_JsonbValue(AV *in, JsonbParseState **jsonb_state)
Definition: jsonb_plperl.c:129
Datum float8_numeric(PG_FUNCTION_ARGS)
Definition: numeric.c:3383
#define InvalidOid
Definition: postgres_ext.h:36
#define DatumGetNumeric(X)
Definition: numeric.h:49
enum jbvType type
Definition: jsonb.h:263
#define Int32GetDatum(X)
Definition: postgres.h:479
void * palloc(Size size)
Definition: mcxt.c:949
int errmsg(const char *fmt,...)
Definition: elog.c:784
Definition: jsonb.h:25
static char * sv2cstr(SV *sv)

Variable Documentation

◆ PG_MODULE_MAGIC

PG_MODULE_MAGIC

Definition at line 11 of file jsonb_plperl.c.