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

Go to the source code of this file.

Functions

 PG_MODULE_MAGIC_EXT (.name="jsonb_plperl",.version=PG_VERSION)
 
static SVJsonb_to_SV (JsonbContainer *jsonb)
 
static void SV_to_JsonbValue (SV *in, JsonbInState *jsonb_state, bool is_elem)
 
static SVJsonbValue_to_SV (JsonbValue *jbv)
 
static void AV_to_JsonbValue (AV *in, JsonbInState *jsonb_state)
 
static void HV_to_JsonbValue (HV *obj, JsonbInState *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)
 

Function Documentation

◆ AV_to_JsonbValue()

static void AV_to_JsonbValue ( AV in,
JsonbInState jsonb_state 
)
static

Definition at line 135 of file jsonb_plperl.c.

136{
137 dTHX;
138 SSize_t pcount = av_len(in) + 1;
139 SSize_t i;
140
142
143 for (i = 0; i < pcount; i++)
144 {
145 SV **value = av_fetch(in, i, FALSE);
146
147 if (value)
149 }
150
152}
static struct @175 value
int i
Definition isn.c:77
@ WJB_END_ARRAY
Definition jsonb.h:27
@ WJB_BEGIN_ARRAY
Definition jsonb.h:26
static void SV_to_JsonbValue(SV *in, JsonbInState *jsonb_state, bool is_elem)
void pushJsonbValue(JsonbInState *pstate, JsonbIteratorToken seq, JsonbValue *jbval)
Definition jsonb_util.c:583
#define dTHX
Definition ppport.h:11306
static int fb(int x)

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

Referenced by SV_to_JsonbValue().

◆ HV_to_JsonbValue()

static void HV_to_JsonbValue ( HV obj,
JsonbInState jsonb_state 
)
static

Definition at line 155 of file jsonb_plperl.c.

156{
157 dTHX;
159 SV *val;
160 char *kstr;
161 I32 klen;
162
163 key.type = jbvString;
164
166
167 (void) hv_iterinit(obj);
168
169 while ((val = hv_iternextsv(obj, &kstr, &klen)))
170 {
171 key.val.string.val = pnstrdup(kstr, klen);
172 key.val.string.len = klen;
175 }
176
178}
long val
Definition informix.c:689
@ jbvString
Definition jsonb.h:231
@ WJB_KEY
Definition jsonb.h:23
@ WJB_END_OBJECT
Definition jsonb.h:29
@ WJB_BEGIN_OBJECT
Definition jsonb.h:28
char * pnstrdup(const char *in, Size len)
Definition mcxt.c:1921

References dTHX, fb(), jbvString, pnstrdup(), pushJsonbValue(), SV_to_JsonbValue(), val, WJB_BEGIN_OBJECT, WJB_END_OBJECT, and WJB_KEY.

Referenced by SV_to_JsonbValue().

◆ jsonb_to_plperl()

Datum jsonb_to_plperl ( PG_FUNCTION_ARGS  )

Definition at line 303 of file jsonb_plperl.c.

304{
305 dTHX;
306 Jsonb *in = PG_GETARG_JSONB_P(0);
307 SV *sv = Jsonb_to_SV(&in->root);
308
309 return PointerGetDatum(sv);
310}
#define PG_GETARG_JSONB_P(x)
Definition jsonb.h:418
static SV * Jsonb_to_SV(JsonbContainer *jsonb)
#define PointerGetDatum(X)
Definition postgres.h:354
Definition jsonb.h:215
JsonbContainer root
Definition jsonb.h:217

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

◆ Jsonb_to_SV()

static SV * Jsonb_to_SV ( JsonbContainer jsonb)
static

Definition at line 63 of file jsonb_plperl.c.

64{
65 dTHX;
66 JsonbValue v;
69
70 /* this can recurse via JsonbValue_to_SV() */
72
73 it = JsonbIteratorInit(jsonb);
74 r = JsonbIteratorNext(&it, &v, true);
75
76 switch (r)
77 {
78 case WJB_BEGIN_ARRAY:
79 if (v.val.array.rawScalar)
80 {
81 JsonbValue tmp;
82
83 if ((r = JsonbIteratorNext(&it, &v, true)) != WJB_ELEM ||
84 (r = JsonbIteratorNext(&it, &tmp, true)) != WJB_END_ARRAY ||
85 (r = JsonbIteratorNext(&it, &tmp, true)) != WJB_DONE)
86 elog(ERROR, "unexpected jsonb token: %d", r);
87
88 return JsonbValue_to_SV(&v);
89 }
90 else
91 {
92 AV *av = newAV();
93
94 while ((r = JsonbIteratorNext(&it, &v, true)) != WJB_DONE)
95 {
96 if (r == WJB_ELEM)
98 }
99
100 return newRV((SV *) av);
101 }
102
103 case WJB_BEGIN_OBJECT:
104 {
105 HV *hv = newHV();
106
107 while ((r = JsonbIteratorNext(&it, &v, true)) != WJB_DONE)
108 {
109 if (r == WJB_KEY)
110 {
111 /* json key in v, json value in val */
113
114 if (JsonbIteratorNext(&it, &val, true) == WJB_VALUE)
115 {
117
118 (void) hv_store(hv,
119 v.val.string.val, v.val.string.len,
120 value, 0);
121 }
122 }
123 }
124
125 return newRV((SV *) hv);
126 }
127
128 default:
129 elog(ERROR, "unexpected jsonb token: %d", r);
130 return NULL;
131 }
132}
#define ERROR
Definition elog.h:40
#define elog(elevel,...)
Definition elog.h:228
JsonbIteratorToken
Definition jsonb.h:21
@ WJB_DONE
Definition jsonb.h:22
@ WJB_VALUE
Definition jsonb.h:24
@ WJB_ELEM
Definition jsonb.h:25
static SV * JsonbValue_to_SV(JsonbValue *jbv)
JsonbIterator * JsonbIteratorInit(JsonbContainer *container)
Definition jsonb_util.c:935
JsonbIteratorToken JsonbIteratorNext(JsonbIterator **it, JsonbValue *val, bool skipNested)
Definition jsonb_util.c:973
struct @10::@11 av[32]
void check_stack_depth(void)
Definition stack_depth.c:96
char * val
Definition jsonb.h:266

References av, check_stack_depth(), dTHX, elog, ERROR, fb(), 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().

◆ JsonbValue_to_SV()

static SV * JsonbValue_to_SV ( JsonbValue jbv)
static

Definition at line 21 of file jsonb_plperl.c.

22{
23 dTHX;
24
25 switch (jbv->type)
26 {
27 case jbvBinary:
28 return Jsonb_to_SV(jbv->val.binary.data);
29
30 case jbvNumeric:
31 {
33 NumericGetDatum(jbv->val.numeric)));
35
36 pfree(str);
37 return result;
38 }
39
40 case jbvString:
41 {
42 char *str = pnstrdup(jbv->val.string.val,
43 jbv->val.string.len);
44 SV *result = cstr2sv(str);
45
46 pfree(str);
47 return result;
48 }
49
50 case jbvBool:
51 return newSVnv(SvNV(jbv->val.boolean ? &PL_sv_yes : &PL_sv_no));
52
53 case jbvNull:
54 return newSV(0);
55
56 default:
57 elog(ERROR, "unexpected jsonb value type: %d", jbv->type);
58 return NULL;
59 }
60}
Datum numeric_out(PG_FUNCTION_ARGS)
Definition numeric.c:799
uint32 result
#define DirectFunctionCall1(func, arg1)
Definition fmgr.h:688
const char * str
@ jbvNumeric
Definition jsonb.h:232
@ jbvBool
Definition jsonb.h:233
@ jbvBinary
Definition jsonb.h:238
@ jbvNull
Definition jsonb.h:230
void pfree(void *pointer)
Definition mcxt.c:1619
static Datum NumericGetDatum(Numeric X)
Definition numeric.h:76
static SV * cstr2sv(const char *str)
Definition plperl.h:147
static char * DatumGetCString(Datum X)
Definition postgres.h:365
#define PL_sv_yes
Definition ppport.h:11781
#define PL_sv_no
Definition ppport.h:11779

References cstr2sv(), DatumGetCString(), DirectFunctionCall1, dTHX, elog, ERROR, fb(), jbvBinary, jbvBool, jbvNull, jbvNumeric, jbvString, Jsonb_to_SV(), numeric_out(), NumericGetDatum(), pfree(), PL_sv_no, PL_sv_yes, pnstrdup(), result, and str.

Referenced by Jsonb_to_SV().

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

◆ PG_MODULE_MAGIC_EXT()

PG_MODULE_MAGIC_EXT ( name = "jsonb_plperl",
version = PG_VERSION 
)

◆ plperl_to_jsonb()

Datum plperl_to_jsonb ( PG_FUNCTION_ARGS  )

Definition at line 316 of file jsonb_plperl.c.

317{
318 dTHX;
319 SV *in = (SV *) PG_GETARG_POINTER(0);
321
322 SV_to_JsonbValue(in, &jsonb_state, true);
324}
#define PG_GETARG_POINTER(n)
Definition fmgr.h:277
#define PG_RETURN_JSONB_P(x)
Definition jsonb.h:420
Jsonb * JsonbValueToJsonb(JsonbValue *val)
Definition jsonb_util.c:96

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

◆ SV_to_JsonbValue()

static void SV_to_JsonbValue ( SV in,
JsonbInState jsonb_state,
bool  is_elem 
)
static

Definition at line 181 of file jsonb_plperl.c.

182{
183 dTHX;
184 JsonbValue out; /* result */
185
186 /* this can recurse via AV_to_JsonbValue() or HV_to_JsonbValue() */
188
189 /* Dereference references recursively. */
190 while (SvROK(in))
191 {
192 /*
193 * It's possible for circular references to make this an infinite
194 * loop. Checking for such a situation seems like much more trouble
195 * than it's worth, but let's provide a way to break out of the loop.
196 */
198 in = SvRV(in);
199 }
200
201 switch (SvTYPE(in))
202 {
203 case SVt_PVAV:
205 return;
206
207 case SVt_PVHV:
209 return;
210
211 default:
212 if (!SvOK(in))
213 {
214 out.type = jbvNull;
215 }
216 else if (SvUOK(in))
217 {
218 /*
219 * If UV is >=64 bits, we have no better way to make this
220 * happen than converting to text and back. Given the low
221 * usage of UV in Perl code, it's not clear it's worth working
222 * hard to provide alternate code paths.
223 */
224 const char *strval = SvPV_nolen(in);
225
226 out.type = jbvNumeric;
227 out.val.numeric =
229 CStringGetDatum(strval),
231 Int32GetDatum(-1)));
232 }
233 else if (SvIOK(in))
234 {
235 IV ival = SvIV(in);
236
237 out.type = jbvNumeric;
238 out.val.numeric = int64_to_numeric(ival);
239 }
240 else if (SvNOK(in))
241 {
242 double nval = SvNV(in);
243
244 /*
245 * jsonb doesn't allow infinity or NaN (per JSON
246 * specification), but the numeric type that is used for the
247 * storage accepts those, so we have to reject them here
248 * explicitly.
249 */
250 if (isinf(nval))
253 errmsg("cannot convert infinity to jsonb")));
254 if (isnan(nval))
257 errmsg("cannot convert NaN to jsonb")));
258
259 out.type = jbvNumeric;
260 out.val.numeric =
263 }
264 else if (SvPOK(in))
265 {
266 out.type = jbvString;
267 out.val.string.val = sv2cstr(in);
268 out.val.string.len = strlen(out.val.string.val);
269 }
270 else
271 {
272 /*
273 * XXX It might be nice if we could include the Perl type in
274 * the error message.
275 */
278 errmsg("cannot transform this Perl type to jsonb")));
279 }
280 }
281
282 if (jsonb_state->parseState)
283 {
284 /* We're in an array or object, so push value as element or field. */
286 }
287 else
288 {
289 /*
290 * We are at top level, so it's a raw scalar. If we just shove the
291 * scalar value into jsonb_state->result, JsonbValueToJsonb will take
292 * care of wrapping it into a dummy array.
293 */
295 memcpy(jsonb_state->result, &out, sizeof(JsonbValue));
296 }
297}
Datum float8_numeric(PG_FUNCTION_ARGS)
Definition numeric.c:4544
Numeric int64_to_numeric(int64 val)
Definition numeric.c:4270
Datum numeric_in(PG_FUNCTION_ARGS)
Definition numeric.c:626
memcpy(sums, checksumBaseOffsets, sizeof(checksumBaseOffsets))
int errcode(int sqlerrcode)
Definition elog.c:875
#define ereport(elevel,...)
Definition elog.h:152
#define palloc_object(type)
Definition fe_memutils.h:89
#define DirectFunctionCall3(func, arg1, arg2, arg3)
Definition fmgr.h:692
static void HV_to_JsonbValue(HV *obj, JsonbInState *jsonb_state)
static void AV_to_JsonbValue(AV *in, JsonbInState *jsonb_state)
#define CHECK_FOR_INTERRUPTS()
Definition miscadmin.h:125
static Numeric DatumGetNumeric(Datum X)
Definition numeric.h:64
static char * errmsg
static char * sv2cstr(SV *sv)
Definition plperl.h:89
static Datum ObjectIdGetDatum(Oid X)
Definition postgres.h:252
static Datum Float8GetDatum(float8 X)
Definition postgres.h:515
static Datum CStringGetDatum(const char *X)
Definition postgres.h:383
static Datum Int32GetDatum(int32 X)
Definition postgres.h:212
#define InvalidOid
#define SvPV_nolen(sv)
Definition ppport.h:14072
enum jbvType type
Definition jsonb.h:257

References AV_to_JsonbValue(), CHECK_FOR_INTERRUPTS, check_stack_depth(), CStringGetDatum(), DatumGetNumeric(), DirectFunctionCall1, DirectFunctionCall3, dTHX, ereport, errcode(), errmsg, ERROR, fb(), float8_numeric(), Float8GetDatum(), HV_to_JsonbValue(), Int32GetDatum(), int64_to_numeric(), InvalidOid, jbvNull, jbvNumeric, jbvString, memcpy(), numeric_in(), ObjectIdGetDatum(), palloc_object, 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().