From 864c0d394b569b6585f1d8f157fc5d48c74b4211 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kuzey=20G=C3=B6k?= <59634400+northaxosky@users.noreply.github.com> Date: Tue, 17 Oct 2023 15:44:37 -0700 Subject: [PATCH] Refinement of FOR JSON PATH & Nested Functionality (#205) Currently FOR JSON PATH is implemented in Babelfish using string manipulation. This change will implement FOR JSON PATH using PostgreSQL's JsonbValue and HTAB. The reason for this change is because the current implementation of FOR JSON PATH does not support the full functionality of the feature. Nested outputs determined by aliases in the SELECT statement are not supported. By implementing FOR JSON PATH using JsonbValue and HTAB, we provide an efficient solution that also supports nested json objects, while also setting the foundation for FOR JSON AUTO to be implemented. BABELFISH_EXTENSIONS CHANGES: Switched from String Manipulation implementation of FOR JSON PATH to an implementation using JsonbValue. Wrapper function to add a value to JsonbValue and handle datatype checks. Supporting functions to determine path to insert a JsonbValue object and key for HashTable. Create json and insert into existing json functions that are used when dealing with nested json objects. Implemented Nested Output tracking using PostgreSQL's HTAB library (HashTable) Corrected the tests to showcase the new functionality of nested json objects Added another set of tests to more thoroughly test the nested json object functionality. POSTGRESQL_MODIFIED_FOR_BABELFISH CHANGES: Created a public wrapper function in jsonb.h to call add_jsonb() from forjson.c TEST CASES: Added a test that checks the functionality and accuracy of the nested json feature. Includes cases with multiple layers, deeply nested layers, values in different stages of json layers, nested null outputs. Organized version upgrade tests so previous versions use previous implementation of FOR JSON PATH and updated the schedule for each version. Modified existing test cases to correctly showcase the nested functionality if the given test uses alias that cause nested json objects to be created. Changed the expected outputs to include spaces as JsonbValue does when converted to a string. Task: BABEL-3407 Signed-off-by: Kuzey Gok Co-authored-by: Jake Owen --- src/backend/utils/adt/jsonb.c | 12 +++++++++++- src/include/utils/jsonb.h | 3 ++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/backend/utils/adt/jsonb.c b/src/backend/utils/adt/jsonb.c index d253ae66fa8..bf2d5968774 100644 --- a/src/backend/utils/adt/jsonb.c +++ b/src/backend/utils/adt/jsonb.c @@ -598,6 +598,16 @@ JsonbToCStringWorker(StringInfo out, JsonbContainer *in, int estimated_len, bool return out->data; } +void +jsonb_get_value(Datum val, bool is_null, JsonbValue *json, Oid val_type) +{ + JsonbInState state; + memset(&state, 0, sizeof(JsonbInState)); + + add_jsonb(val, is_null, &state, val_type, false); + *json = *(state.res); +} + static void add_indent(StringInfo out, bool indent, int level) { @@ -2083,4 +2093,4 @@ jsonb_float8(PG_FUNCTION_ARGS) PG_FREE_IF_COPY(in, 0); PG_RETURN_DATUM(retValue); -} +} \ No newline at end of file diff --git a/src/include/utils/jsonb.h b/src/include/utils/jsonb.h index 40851595881..24aae3976f8 100644 --- a/src/include/utils/jsonb.h +++ b/src/include/utils/jsonb.h @@ -415,4 +415,5 @@ extern Datum jsonb_set_element(Jsonb *jb, Datum *path, int path_len, JsonbValue *newval); extern Datum jsonb_get_element(Jsonb *jb, Datum *path, int npath, bool *isnull, bool as_text); -#endif /* __JSONB_H__ */ +extern void jsonb_get_value(Datum val, bool is_null, JsonbValue *json, Oid val_type); +#endif /* __JSONB_H__ */ \ No newline at end of file