diff options
Diffstat (limited to 'contrib/jsonb_plpython')
| -rw-r--r-- | contrib/jsonb_plpython/jsonb_plpython.c | 67 |
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)); } /* |
