summaryrefslogtreecommitdiff
path: root/contrib/jsonb_plpython/jsonb_plpython.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/jsonb_plpython/jsonb_plpython.c')
-rw-r--r--contrib/jsonb_plpython/jsonb_plpython.c67
1 files changed, 39 insertions, 28 deletions
diff --git a/contrib/jsonb_plpython/jsonb_plpython.c b/contrib/jsonb_plpython/jsonb_plpython.c
index 2892e88c58b..7e8e1d6674f 100644
--- a/contrib/jsonb_plpython/jsonb_plpython.c
+++ b/contrib/jsonb_plpython/jsonb_plpython.c
@@ -26,8 +26,8 @@ static PLy_elog_impl_t PLy_elog_impl_p;
static PyObject *decimal_constructor;
static PyObject *PLyObject_FromJsonbContainer(JsonbContainer *jsonb);
-static JsonbValue *PLyObject_ToJsonbValue(PyObject *obj,
- JsonbParseState **jsonb_state, bool is_elem);
+static void PLyObject_ToJsonbValue(PyObject *obj,
+ JsonbInState *jsonb_state, bool is_elem);
typedef PyObject *(*PLyUnicode_FromStringAndSize_t)
(const char *s, Py_ssize_t size);
@@ -261,12 +261,11 @@ PLyObject_FromJsonbContainer(JsonbContainer *jsonb)
*
* Transform Python dict to JsonbValue.
*/
-static JsonbValue *
-PLyMapping_ToJsonbValue(PyObject *obj, JsonbParseState **jsonb_state)
+static void
+PLyMapping_ToJsonbValue(PyObject *obj, JsonbInState *jsonb_state)
{
Py_ssize_t pcount;
PyObject *volatile items;
- JsonbValue *volatile out;
pcount = PyMapping_Size(obj);
items = PyMapping_Items(obj);
@@ -297,19 +296,17 @@ PLyMapping_ToJsonbValue(PyObject *obj, JsonbParseState **jsonb_state)
PLyUnicode_ToJsonbValue(key, &jbvKey);
}
- (void) pushJsonbValue(jsonb_state, WJB_KEY, &jbvKey);
- (void) PLyObject_ToJsonbValue(value, jsonb_state, false);
+ pushJsonbValue(jsonb_state, WJB_KEY, &jbvKey);
+ PLyObject_ToJsonbValue(value, jsonb_state, false);
}
- out = pushJsonbValue(jsonb_state, WJB_END_OBJECT, NULL);
+ pushJsonbValue(jsonb_state, WJB_END_OBJECT, NULL);
}
PG_FINALLY();
{
Py_DECREF(items);
}
PG_END_TRY();
-
- return out;
}
/*
@@ -318,8 +315,8 @@ PLyMapping_ToJsonbValue(PyObject *obj, JsonbParseState **jsonb_state)
* Transform python list to JsonbValue. Expects transformed PyObject and
* a state required for jsonb construction.
*/
-static JsonbValue *
-PLySequence_ToJsonbValue(PyObject *obj, JsonbParseState **jsonb_state)
+static void
+PLySequence_ToJsonbValue(PyObject *obj, JsonbInState *jsonb_state)
{
Py_ssize_t i;
Py_ssize_t pcount;
@@ -336,7 +333,7 @@ PLySequence_ToJsonbValue(PyObject *obj, JsonbParseState **jsonb_state)
value = PySequence_GetItem(obj, i);
Assert(value);
- (void) PLyObject_ToJsonbValue(value, jsonb_state, true);
+ PLyObject_ToJsonbValue(value, jsonb_state, true);
Py_XDECREF(value);
value = NULL;
}
@@ -348,7 +345,7 @@ PLySequence_ToJsonbValue(PyObject *obj, JsonbParseState **jsonb_state)
}
PG_END_TRY();
- return pushJsonbValue(jsonb_state, WJB_END_ARRAY, NULL);
+ pushJsonbValue(jsonb_state, WJB_END_ARRAY, NULL);
}
/*
@@ -406,17 +403,23 @@ PLyNumber_ToJsonbValue(PyObject *obj, JsonbValue *jbvNum)
*
* Transform python object to JsonbValue.
*/
-static JsonbValue *
-PLyObject_ToJsonbValue(PyObject *obj, JsonbParseState **jsonb_state, bool is_elem)
+static void
+PLyObject_ToJsonbValue(PyObject *obj, JsonbInState *jsonb_state, bool is_elem)
{
JsonbValue *out;
if (!PyUnicode_Check(obj))
{
if (PySequence_Check(obj))
- return PLySequence_ToJsonbValue(obj, jsonb_state);
+ {
+ PLySequence_ToJsonbValue(obj, jsonb_state);
+ return;
+ }
else if (PyMapping_Check(obj))
- return PLyMapping_ToJsonbValue(obj, jsonb_state);
+ {
+ PLyMapping_ToJsonbValue(obj, jsonb_state);
+ return;
+ }
}
out = palloc_object(JsonbValue);
@@ -443,10 +446,20 @@ PLyObject_ToJsonbValue(PyObject *obj, JsonbParseState **jsonb_state, bool is_ele
errmsg("Python type \"%s\" cannot be transformed to jsonb",
PLyObject_AsString((PyObject *) obj->ob_type))));
- /* Push result into 'jsonb_state' unless it is raw scalar value. */
- return (*jsonb_state ?
- pushJsonbValue(jsonb_state, is_elem ? WJB_ELEM : WJB_VALUE, out) :
- out);
+ if (jsonb_state->parseState)
+ {
+ /* We're in an array or object, so push value as element or field. */
+ pushJsonbValue(jsonb_state, is_elem ? WJB_ELEM : WJB_VALUE, out);
+ }
+ else
+ {
+ /*
+ * We are at top level, so it's a raw scalar. If we just shove the
+ * scalar value into jsonb_state->result, JsonbValueToJsonb will take
+ * care of wrapping it into a dummy array.
+ */
+ jsonb_state->result = out;
+ }
}
/*
@@ -458,13 +471,11 @@ PG_FUNCTION_INFO_V1(plpython_to_jsonb);
Datum
plpython_to_jsonb(PG_FUNCTION_ARGS)
{
- PyObject *obj;
- JsonbValue *out;
- JsonbParseState *jsonb_state = NULL;
+ PyObject *obj = (PyObject *) PG_GETARG_POINTER(0);
+ JsonbInState jsonb_state = {0};
- obj = (PyObject *) PG_GETARG_POINTER(0);
- out = PLyObject_ToJsonbValue(obj, &jsonb_state, true);
- PG_RETURN_POINTER(JsonbValueToJsonb(out));
+ PLyObject_ToJsonbValue(obj, &jsonb_state, true);
+ PG_RETURN_POINTER(JsonbValueToJsonb(jsonb_state.result));
}
/*