Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit a734d83

Browse files
author
Nikita Glukhov
committed
Add numeric transform for plpython
1 parent 3680cd0 commit a734d83

File tree

6 files changed

+460
-52
lines changed

6 files changed

+460
-52
lines changed

contrib/jsonb_plpython/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# contrib/jsonb_plpython/Makefile
22

33
MODULE_big = jsonb_plpython$(python_majorversion)
4-
OBJS = jsonb_plpython.o jsonb_lazy.o $(WIN32RES)
4+
OBJS = jsonb_plpython.o jsonb_lazy.o numeric_plpython.o $(WIN32RES)
55
PGFILEDESC = "jsonb_plpython - transform between jsonb and plpythonu"
66

77
PG_CPPFLAGS = -I$(top_srcdir)/src/pl/plpython $(python_includespec) -DPLPYTHON_LIBNAME='"plpython$(python_majorversion)"'

contrib/jsonb_plpython/jsonb_plpython.c

Lines changed: 9 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include "plpy_main.h"
66
#include "plpy_typeio.h"
77
#include "jsonb_plpython.h"
8+
#include "numeric_plpython.h"
89
#include "utils/jsonb.h"
910
#include "utils/fmgrprotos.h"
1011
#include "utils/numeric.h"
@@ -13,8 +14,11 @@ PG_MODULE_MAGIC;
1314

1415
void _PG_init(void);
1516

16-
typedef void (*PLy_elog_impl_t) (int elevel, const char *fmt,...);
17-
static PLy_elog_impl_t PLy_elog_impl_p;
17+
PLyObject_AsString_t PLyObject_AsString_p;
18+
PLy_elog_impl_t PLy_elog_impl_p;
19+
#if PY_MAJOR_VERSION >= 3
20+
PLyUnicode_FromStringAndSize_t PLyUnicode_FromStringAndSize_p;
21+
#endif
1822

1923
PLy_get_global_memory_context_t PLy_get_global_memory_context_p;
2024
PLyObject_AsString_t PLyObject_AsString_p;
@@ -37,12 +41,6 @@ static JsonbValue *PLyObject_ToJsonbValue(PyObject *obj,
3741
PLyJsonb_FromJsonbContainer(jbc, len)
3842
#endif
3943

40-
#if PY_MAJOR_VERSION >= 3
41-
typedef PyObject *(*PLyUnicode_FromStringAndSize_t)
42-
(const char *s, Py_ssize_t size);
43-
static PLyUnicode_FromStringAndSize_t PLyUnicode_FromStringAndSize_p;
44-
#endif
45-
4644
/*
4745
* Module initialize function: fetch function pointers for cross-module calls.
4846
*/
@@ -134,6 +132,7 @@ PLyObject_FromJsonbValue(JsonbValue *jsonbValue)
134132
#endif
135133
return PyInt_FromLong((long) intval);
136134

135+
return PLyObject_FromNumeric(jsonbValue->val.numeric);
137136
num = NumericGetDatum(jsonbValue->val.numeric);
138137
str = DatumGetCString(DirectFunctionCall1(numeric_out, num));
139138

@@ -415,60 +414,19 @@ PLySequence_ToJsonbValue(PyObject *obj, JsonbParseState **jsonb_state)
415414
static JsonbValue *
416415
PLyNumber_ToJsonbValue(PyObject *obj, JsonbValue *jbvNum)
417416
{
418-
Numeric num;
419-
char *str;
420-
421417
jbvNum->type = jbvNumeric;
422-
423-
if (PyInt_Check(obj))
424-
{
425-
long val = PyInt_AsLong(obj);
426-
427-
if (val != -1 || !PyErr_Occurred())
428-
{
429-
jbvNum->val.numeric =
430-
DatumGetNumeric(DirectFunctionCall1(int8_numeric,
431-
Int64GetDatum((int64) val)));
432-
return jbvNum;
433-
}
434-
435-
PyErr_Clear();
436-
}
437-
438-
str = PLyObject_AsString(obj);
439-
440-
PG_TRY();
441-
{
442-
Datum numd;
443-
444-
numd = DirectFunctionCall3(numeric_in,
445-
CStringGetDatum(str),
446-
ObjectIdGetDatum(InvalidOid),
447-
Int32GetDatum(-1));
448-
num = DatumGetNumeric(numd);
449-
}
450-
PG_CATCH();
451-
{
452-
ereport(ERROR,
453-
(errcode(ERRCODE_DATATYPE_MISMATCH),
454-
(errmsg("could not convert value \"%s\" to jsonb", str))));
455-
}
456-
PG_END_TRY();
457-
458-
pfree(str);
418+
jbvNum->val.numeric = PLyNumber_ToNumeric(obj);
459419

460420
/*
461421
* jsonb doesn't allow NaN (per JSON specification), so we have to prevent
462422
* it here explicitly. (Infinity is also not allowed in jsonb, but
463423
* numeric_in above already catches that.)
464424
*/
465-
if (numeric_is_nan(num))
425+
if (numeric_is_nan(jbvNum->val.numeric))
466426
ereport(ERROR,
467427
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
468428
(errmsg("cannot convert NaN to jsonb"))));
469429

470-
jbvNum->val.numeric = num;
471-
472430
return jbvNum;
473431
}
474432

contrib/jsonb_plpython/jsonb_plpython.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#include "postgres.h"
22
#include "plpython.h"
33
#include "utils/jsonb.h"
4+
#include "plpy_typeio.h"
45

56
/* Python wrapper for jsonb container */
67
typedef struct PLyJsonb
@@ -33,6 +34,19 @@ extern void PLyKey_ToJsonbValue(PyObject *key, JsonbValue *jbv);
3334
extern PyObject *PLyObject_FromJsonbContainer(JsonbContainer *jsonb);
3435
extern PyObject *PLyObject_FromJsonbValue(JsonbValue *jsonbValue);
3536

37+
/* for PLyObject_AsString in plpy_typeio.c */
38+
typedef char *(*PLyObject_AsString_t) (PyObject *plrv);
39+
extern PLyObject_AsString_t PLyObject_AsString_p;
40+
41+
typedef void (*PLy_elog_impl_t) (int elevel, const char *fmt,...);
42+
extern PLy_elog_impl_t PLy_elog_impl_p;
43+
44+
#if PY_MAJOR_VERSION >= 3
45+
typedef PyObject *(*PLyUnicode_FromStringAndSize_t)
46+
(const char *s, Py_ssize_t size);
47+
extern PLyUnicode_FromStringAndSize_t PLyUnicode_FromStringAndSize_p;
48+
#endif
49+
3650
typedef MemoryContext (*PLy_get_global_memory_context_t) (void);
3751
extern PLy_get_global_memory_context_t PLy_get_global_memory_context_p;
3852

contrib/jsonb_plpython/jsonb_plpythonu--1.0.sql

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,16 @@ CREATE TRANSFORM FOR jsonb LANGUAGE plpythonu (
1717
);
1818

1919
COMMENT ON TRANSFORM FOR jsonb LANGUAGE plpythonu IS 'transform between jsonb and Python';
20+
21+
CREATE FUNCTION numeric_to_plpython(val internal) RETURNS internal
22+
LANGUAGE C STRICT IMMUTABLE
23+
AS 'MODULE_PATHNAME';
24+
25+
CREATE FUNCTION plpython_to_numeric(val internal) RETURNS numeric
26+
LANGUAGE C STRICT IMMUTABLE
27+
AS 'MODULE_PATHNAME';
28+
29+
CREATE TRANSFORM FOR numeric LANGUAGE plpythonu (
30+
FROM SQL WITH FUNCTION numeric_to_plpython(internal),
31+
TO SQL WITH FUNCTION plpython_to_numeric(internal)
32+
);

0 commit comments

Comments
 (0)