-
Notifications
You must be signed in to change notification settings - Fork 97
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Refinement of FOR JSON PATH & Nested Functionality (#1929)
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: Jake Owen <[email protected]>
- Loading branch information
Showing
32 changed files
with
2,959 additions
and
85 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
63 changes: 63 additions & 0 deletions
63
test/JDBC/expected/forjson-before-14_10-or-15_5-vu-cleanup.out
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
-- FOR JSON PATH clause without nested support | ||
DROP VIEW forjson_vu_v_people | ||
GO | ||
|
||
DROP VIEW forjson_vu_v_countries | ||
GO | ||
|
||
-- Multiple tables without nested support | ||
DROP VIEW forjson_vu_v_join | ||
GO | ||
|
||
-- ROOT directive without specifying value | ||
DROP VIEW forjson_vu_v_root | ||
GO | ||
|
||
-- ROOT directive with specifying ROOT value | ||
DROP VIEW forjson_vu_v_root_value | ||
GO | ||
|
||
-- ROOT directive with specifying ROOT value with empty string | ||
DROP VIEW forjson_vu_v_empty_root | ||
GO | ||
|
||
-- WITHOUT_ARRAY_WRAPPERS directive | ||
DROP VIEW forjson_vu_v_without_array_wrapper | ||
GO | ||
|
||
-- INCLUDE_NULL_VALUES directive | ||
DROP VIEW forjson_vu_v_include_null_values | ||
GO | ||
|
||
-- Multiple Directives | ||
DROP VIEW forjson_vu_v_root_include_null_values | ||
GO | ||
|
||
DROP VIEW forjson_vu_v_without_array_wrapper_include_null_values | ||
GO | ||
|
||
|
||
-- Test case with parameters | ||
DROP PROCEDURE forjson_vu_p_params1 | ||
GO | ||
|
||
DROP PROCEDURE forjson_vu_p_params2 | ||
GO | ||
|
||
-- All null values test | ||
DROP VIEW forjson_vu_v_nulls | ||
GO | ||
|
||
-- Test for all parser rules | ||
DROP VIEW forjson_vu_v_order_by | ||
GO | ||
|
||
-- Display Table Contents | ||
DROP TABLE forjson_vu_t_people | ||
GO | ||
|
||
DROP TABLE forjson_vu_t_countries | ||
GO | ||
|
||
DROP TABLE forjson_vu_t_values | ||
GO |
208 changes: 208 additions & 0 deletions
208
test/JDBC/expected/forjson-before-14_10-or-15_5-vu-prepare.out
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,208 @@ | ||
CREATE TABLE forjson_vu_t_people ( | ||
[Id] INT, | ||
[FirstName] VARCHAR(25), | ||
[LastName] VARCHAR(25), | ||
[State] VARCHAR(25) ) | ||
GO | ||
|
||
INSERT INTO forjson_vu_t_people values | ||
(1,'Divya','Kumar',NULL), | ||
(2,NULL,'Khanna','Bengaluru'), | ||
(3,'Tom','Mehta','Kolkata'), | ||
(4,'Kane',NULL,'Delhi') | ||
GO | ||
~~ROW COUNT: 4~~ | ||
|
||
|
||
CREATE TABLE forjson_vu_t_countries ( | ||
[Id] INT, | ||
[Age] INT, | ||
[Country] VARCHAR(25)) | ||
GO | ||
|
||
INSERT INTO forjson_vu_t_countries values | ||
(1,25, 'India'), | ||
(2,40, 'USA'), | ||
(3,30, 'India'), | ||
(4,20, NULL), | ||
(5,10, 'USA') | ||
GO | ||
~~ROW COUNT: 5~~ | ||
|
||
|
||
CREATE TABLE forjson_vu_t_values ( | ||
[Id] INT, | ||
[value] VARCHAR(25) ) | ||
GO | ||
|
||
INSERT INTO forjson_vu_t_values values | ||
(1,NULL), | ||
(2,NULL), | ||
(3,NULL) | ||
GO | ||
~~ROW COUNT: 3~~ | ||
|
||
|
||
-- FOR JSON PATH clause without nested support | ||
CREATE VIEW forjson_vu_v_people AS | ||
SELECT ( | ||
SELECT Id AS EmpId, | ||
FirstName AS "Name.FirstName", | ||
LastName AS "Name.LastName", | ||
State | ||
FROM forjson_vu_t_people | ||
FOR JSON PATH | ||
) c1 | ||
GO | ||
|
||
CREATE VIEW forjson_vu_v_countries AS | ||
SELECT ( | ||
SELECT Id, | ||
Age, | ||
Country | ||
FROM forjson_vu_t_countries | ||
FOR JSON PATH | ||
) c1 | ||
GO | ||
|
||
-- Multiple tables without nested support | ||
CREATE VIEW forjson_vu_v_join AS | ||
SELECT ( | ||
SELECT E.FirstName AS 'Person.Name', | ||
E.LastName AS 'Person.Surname', | ||
D.Age AS 'Employee.Price', | ||
D.Country AS 'Employee.Quantity' | ||
FROM forjson_vu_t_people E | ||
INNER JOIN forjson_vu_t_countries D | ||
ON E.Id = D.Id | ||
FOR JSON PATH | ||
) c1 | ||
GO | ||
|
||
-- ROOT directive without specifying value | ||
CREATE VIEW forjson_vu_v_root AS | ||
SELECT ( | ||
SELECT FirstName, | ||
LastName | ||
FROM forjson_vu_t_people | ||
FOR JSON PATH, ROOT | ||
) c1 | ||
GO | ||
|
||
-- ROOT directive with specifying ROOT value | ||
CREATE VIEW forjson_vu_v_root_value AS | ||
SELECT ( | ||
SELECT FirstName, | ||
LastName | ||
FROM forjson_vu_t_people | ||
FOR JSON PATH, ROOT('Employee') | ||
) c1 | ||
GO | ||
|
||
-- ROOT directive with specifying ROOT value with empty string | ||
CREATE VIEW forjson_vu_v_empty_root AS | ||
SELECT ( | ||
SELECT FirstName, | ||
LastName | ||
FROM forjson_vu_t_people | ||
FOR JSON PATH, ROOT('') | ||
) c1 | ||
GO | ||
|
||
-- WITHOUT_ARRAY_WRAPPERS directive | ||
CREATE VIEW forjson_vu_v_without_array_wrapper AS | ||
SELECT ( | ||
SELECT FirstName, | ||
LastName | ||
FROM forjson_vu_t_people | ||
FOR JSON PATH, WITHOUT_ARRAY_WRAPPER | ||
) c1 | ||
GO | ||
|
||
-- INCLUDE_NULL_VALUES directive | ||
CREATE VIEW forjson_vu_v_include_null_values AS | ||
SELECT ( | ||
SELECT FirstName, | ||
LastName | ||
FROM forjson_vu_t_people | ||
FOR JSON PATH, INCLUDE_NULL_VALUES | ||
) c1 | ||
GO | ||
|
||
-- Multiple Directives | ||
CREATE VIEW forjson_vu_v_root_include_null_values AS | ||
SELECT ( | ||
SELECT Id, | ||
Age, | ||
Country | ||
FROM forjson_vu_t_countries | ||
FOR JSON PATH, ROOT('Employee'), INCLUDE_NULL_VALUES | ||
) c1 | ||
GO | ||
|
||
CREATE VIEW forjson_vu_v_without_array_wrapper_include_null_values AS | ||
SELECT ( | ||
SELECT Id, | ||
Age, | ||
Country | ||
FROM forjson_vu_t_countries | ||
FOR JSON PATH, WITHOUT_ARRAY_WRAPPER, INCLUDE_NULL_VALUES | ||
) c1 | ||
GO | ||
|
||
-- Throws error as ROOT and WITHOUT_ARRAY_WRAPPER cannot be used together | ||
CREATE VIEW forjson_vu_v_root_and_without_array_wrapper AS | ||
SELECT ( | ||
SELECT Id, | ||
Age, | ||
Country | ||
FROM forjson_vu_t_countries | ||
FOR JSON PATH, ROOT, WITHOUT_ARRAY_WRAPPER | ||
) c1 | ||
GO | ||
~~ERROR (Code: 33557097)~~ | ||
|
||
~~ERROR (Message: ROOT option and WITHOUT_ARRAY_WRAPPER option cannot be used together in FOR JSON. Remove one of these options)~~ | ||
|
||
|
||
-- Test case with parameters | ||
CREATE PROCEDURE forjson_vu_p_params1 @id int AS | ||
SELECT ( | ||
SELECT Firstname AS [Name], | ||
State | ||
FROM forjson_vu_t_people | ||
WHERE Id = @id | ||
FOR JSON PATH | ||
) c1 | ||
GO | ||
|
||
CREATE PROCEDURE forjson_vu_p_params2 @id int AS | ||
SELECT ( | ||
SELECT Firstname AS [nam"@e], | ||
State AS [State"@] | ||
FROM forjson_vu_t_people | ||
WHERE Id = @id | ||
FOR JSON PATH | ||
) c1 | ||
GO | ||
|
||
-- All null values test | ||
CREATE VIEW forjson_vu_v_nulls AS | ||
SELECT ( | ||
SELECT value | ||
FROM forjson_vu_t_values | ||
FOR JSON PATH | ||
) c1 | ||
GO | ||
|
||
-- Test for all parser rules | ||
CREATE VIEW forjson_vu_v_order_by AS | ||
SELECT ( | ||
SELECT Id, | ||
Age, | ||
Country | ||
FROM forjson_vu_t_countries | ||
ORDER BY Age | ||
FOR JSON PATH | ||
) C1 | ||
GO |
Oops, something went wrong.