PostgreSQL Source Code: contrib/jsonb_plpython/jsonb_plpython.c Source File (original) (raw)
2
6#include "utils/fmgrprotos.h"
9
11 .name = "jsonb_plpython",
12 .version = PG_VERSION
13);
14
15
16typedef char *(*PLyObject_AsString_t) (PyObject *plrv);
18
21
22
23
24
25
27
31
32typedef PyObject *(*PLyUnicode_FromStringAndSize_t)
33 (const char *s, Py_ssize_t size);
35
36
37
38
39void
41{
42
46 true, NULL);
50 true, NULL);
54 true, NULL);
55}
56
57
58#define PLyObject_AsString (PLyObject_AsString_p)
59#define PLyUnicode_FromStringAndSize (PLyUnicode_FromStringAndSize_p)
60#undef PLy_elog
61#define PLy_elog (PLy_elog_impl_p)
62
63
64
65
66
67
68static PyObject *
70{
72
74}
75
76
77
78
79
80
81static void
83{
86 jbvElem->val.string.len = strlen(jbvElem->val.string.val);
87}
88
89
90
91
92
93
94static PyObject *
96{
97 switch (jsonbValue->type)
98 {
100 Py_RETURN_NONE;
101
104
106 {
108 char *str;
109
112
114 }
115
118
120 if (jsonbValue->val.boolean)
121 Py_RETURN_TRUE;
122 else
123 Py_RETURN_FALSE;
124
125 default:
126 elog(ERROR, "unexpected jsonb value type: %d", jsonbValue->type);
127 return NULL;
128 }
129}
130
131
132
133
134
135
136static PyObject *
138{
142 PyObject *result;
143
146
147 switch (r)
148 {
150 if (v.val.array.rawScalar)
151 {
153
157 elog(ERROR, "unexpected jsonb token: %d", r);
158
160 }
161 else
162 {
163 PyObject *volatile elem = NULL;
164
165 result = PyList_New(0);
166 if (!result)
167 return NULL;
168
170 {
172 {
174 continue;
175
177
178 PyList_Append(result, elem);
179 Py_XDECREF(elem);
180 elem = NULL;
181 }
182 }
184 {
185 Py_XDECREF(elem);
186 Py_XDECREF(result);
188 }
190 }
191 break;
192
194 {
195 PyObject *volatile result_v = PyDict_New();
196 PyObject *volatile key = NULL;
197 PyObject *volatile val = NULL;
198
199 if (!result_v)
200 return NULL;
201
203 {
205 {
207 continue;
208
210 if ()
211 {
212 Py_XDECREF(result_v);
213 result_v = NULL;
214 break;
215 }
216
218 elog(ERROR, "unexpected jsonb token: %d", r);
219
221 if ()
222 {
223 Py_XDECREF(key);
224 key = NULL;
225 Py_XDECREF(result_v);
226 result_v = NULL;
227 break;
228 }
229
230 PyDict_SetItem(result_v, key, val);
231
232 Py_XDECREF(key);
233 key = NULL;
234 Py_XDECREF(val);
235 val = NULL;
236 }
237 }
239 {
240 Py_XDECREF(result_v);
241 Py_XDECREF(key);
242 Py_XDECREF(val);
244 }
246
247 result = result_v;
248 }
249 break;
250
251 default:
252 elog(ERROR, "unexpected jsonb token: %d", r);
253 return NULL;
254 }
255
256 return result;
257}
258
259
260
261
262
263
264static void
266{
267 Py_ssize_t pcount;
268 PyObject *volatile items;
269
270 pcount = PyMapping_Size(obj);
271 items = PyMapping_Items(obj);
272
274 {
275 Py_ssize_t i;
276
278
279 for (i = 0; i < pcount; i++)
280 {
282 PyObject *item = PyList_GetItem(items, i);
283 PyObject *key = PyTuple_GetItem(item, 0);
284 PyObject *value = PyTuple_GetItem(item, 1);
285
286
287 if (key == Py_None)
288 {
290 jbvKey.val.string.len = 0;
291 jbvKey.val.string.val = "";
292 }
293 else
294 {
295
297 }
298
301 }
302
304 }
306 {
307 Py_DECREF(items);
308 }
310}
311
312
313
314
315
316
317
318static void
320{
321 Py_ssize_t i;
322 Py_ssize_t pcount;
323 PyObject *volatile value = NULL;
324
325 pcount = PySequence_Size(obj);
326
328
330 {
331 for (i = 0; i < pcount; i++)
332 {
333 value = PySequence_GetItem(obj, i);
335
337 Py_XDECREF(value);
339 }
340 }
342 {
343 Py_XDECREF(value);
345 }
347
349}
350
351
352
353
354
355
358{
361
363 {
365
371 }
373 {
375 (errcode(ERRCODE_DATATYPE_MISMATCH),
376 errmsg("could not convert value \"%s\" to jsonb", str)));
377 }
379
381
382
383
384
385
388 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
389 errmsg("cannot convert NaN to jsonb")));
392 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
393 errmsg("cannot convert infinity to jsonb")));
394
396 jbvNum->val.numeric = num;
397
398 return jbvNum;
399}
400
401
402
403
404
405
406static void
408{
410
411 if (!PyUnicode_Check(obj))
412 {
413 if (PySequence_Check(obj))
414 {
416 return;
417 }
418 else if (PyMapping_Check(obj))
419 {
421 return;
422 }
423 }
424
426
427 if (obj == Py_None)
429 else if (PyUnicode_Check(obj))
431
432
433
434
435
436 else if (PyBool_Check(obj))
437 {
439 out->val.boolean = (obj == Py_True);
440 }
441 else if (PyNumber_Check(obj))
443 else
445 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
446 errmsg("Python type \"%s\" cannot be transformed to jsonb",
448
450 {
451
453 }
454 else
455 {
456
457
458
459
460
461 jsonb_state->result = out;
462 }
463}
464
465
466
467
468
469
473{
476
479}
480
481
482
483
484
485
489{
490 PyObject *result;
492
493
494
495
496
497
499 {
500 PyObject *decimal_module = PyImport_ImportModule("cdecimal");
501
502 if (!decimal_module)
503 {
504 PyErr_Clear();
505 decimal_module = PyImport_ImportModule("decimal");
506 }
507 Assert(decimal_module);
509 }
510
512 if (!result)
513 PLy_elog(ERROR, "transformation from jsonb to Python failed");
514
516}
Datum numeric_out(PG_FUNCTION_ARGS)
Datum numeric_in(PG_FUNCTION_ARGS)
bool numeric_is_nan(Numeric num)
bool numeric_is_inf(Numeric num)
#define AssertVariableIsOfType(varname, typename)
void * load_external_function(const char *filename, const char *funcname, bool signalNotFound, void **filehandle)
int errcode(int sqlerrcode)
int errmsg(const char *fmt,...)
#define ereport(elevel,...)
#define palloc_object(type)
#define PG_GETARG_POINTER(n)
#define DirectFunctionCall1(func, arg1)
#define DirectFunctionCall3(func, arg1, arg2, arg3)
#define PG_RETURN_POINTER(x)
Assert(PointerIsAligned(start, uint64))
#define PG_GETARG_JSONB_P(x)
static void PLyMapping_ToJsonbValue(PyObject *obj, JsonbInState *jsonb_state)
#define PLyUnicode_FromStringAndSize
static void PLyObject_ToJsonbValue(PyObject *obj, JsonbInState *jsonb_state, bool is_elem)
PG_MODULE_MAGIC_EXT(.name="jsonb_plpython",.version=PG_VERSION)
static PLy_elog_impl_t PLy_elog_impl_p
static JsonbValue * PLyNumber_ToJsonbValue(PyObject *obj, JsonbValue *jbvNum)
PyObject *(* PLyUnicode_FromStringAndSize_t)(const char *s, Py_ssize_t size)
Datum plpython_to_jsonb(PG_FUNCTION_ARGS)
void(* PLy_elog_impl_t)(int elevel, const char *fmt,...)
static PyObject * PLyObject_FromJsonbValue(JsonbValue *jsonbValue)
PG_FUNCTION_INFO_V1(plpython_to_jsonb)
static PLyObject_AsString_t PLyObject_AsString_p
static void PLySequence_ToJsonbValue(PyObject *obj, JsonbInState *jsonb_state)
char *(* PLyObject_AsString_t)(PyObject *plrv)
static PyObject * decimal_constructor
Datum jsonb_to_plpython(PG_FUNCTION_ARGS)
static PLyUnicode_FromStringAndSize_t PLyUnicode_FromStringAndSize_p
static void PLyUnicode_ToJsonbValue(PyObject *obj, JsonbValue *jbvElem)
static PyObject * PLyObject_FromJsonbContainer(JsonbContainer *jsonb)
#define PLyObject_AsString
static PyObject * PLyUnicode_FromJsonbValue(JsonbValue *jbv)
void pushJsonbValue(JsonbInState *pstate, JsonbIteratorToken seq, JsonbValue *jbval)
JsonbIterator * JsonbIteratorInit(JsonbContainer *container)
JsonbIteratorToken JsonbIteratorNext(JsonbIterator **it, JsonbValue *val, bool skipNested)
Jsonb * JsonbValueToJsonb(JsonbValue *val)
void pfree(void *pointer)
static Numeric DatumGetNumeric(Datum X)
static Datum NumericGetDatum(Numeric X)
void PLy_elog_impl(int elevel, const char *fmt,...)
static Datum PointerGetDatum(const void *X)
static Datum ObjectIdGetDatum(Oid X)
static char * DatumGetCString(Datum X)
static Datum CStringGetDatum(const char *X)
static Datum Int32GetDatum(int32 X)
JsonbParseState * parseState