summaryrefslogtreecommitdiff
path: root/src/test
diff options
context:
space:
mode:
authorMichael Paquier <michael@paquier.xyz>2025-11-26 10:53:16 +0900
committerMichael Paquier <michael@paquier.xyz>2025-11-26 10:53:16 +0900
commite1405aa5e3acd55a77838b0b7944198735ffccdf (patch)
tree18c05d4a8ee68a45f5af8bf46945510ac0cf6884 /src/test
parent44eba8f06e5568be35fa3d112ab781e931fe04ae (diff)
Add input function for data type pg_dependencies
pg_dependencies is used as data type for the contents of dependencies extended statistics. This new input function consumes the format that has been established by e76defbcf09e for the output function of pg_dependencies, enforcing some sanity checks for: - Checks for the input object, which should be a one-dimension array with correct attributes and values. - The key names: "attributes", "dependency", "degree". All are required, other key names are blocked. - Value types for each key: "attributes" requires an array of integers, "dependency" an attribute number, "degree" a float. - List of attributes. In this case, it is possible that some dependencies are not listed in the statistics data, as items with a degree of 0 are discarded when building the statistics. This commit includes checks for simple scenarios, like duplicated attributes, or overlapping values between the list of "attributes" and the "dependency" value. Even if the input function considers the input as valid, a value still needs to be cross-checked with the attributes defined in a statistics object at import. - Based on the discussion, the checks on the values are loose, as there is also an argument for potentially stats injection. For example, "degree" should be defined in [0.0,1.0], but a check is not enforced. This is required for a follow-up patch that aims to implement the import of extended statistics. Some tests are added to check the code paths of the JSON parser checking the shape of the pg_dependencies inputs, with 91% of code coverage reached. The tests are located in their own new test file, for clarity. Author: Corey Huinker <corey.huinker@gmail.com> Reviewed-by: Jian He <jian.universality@gmail.com> Reviewed-by: Chao Li <li.evan.chao@gmail.com> Reviewed-by: Michael Paquier <michael@paquier.xyz> Reviewed-by: Yuefei Shi <shiyuefei1004@gmail.com> Discussion: https://postgr.es/m/CADkLM=dpz3KFnqP-dgJ-zvRvtjsa8UZv8wDAQdqho=qN3kX0Zg@mail.gmail.com
Diffstat (limited to 'src/test')
-rw-r--r--src/test/regress/expected/pg_dependencies.out540
-rw-r--r--src/test/regress/parallel_schedule2
-rw-r--r--src/test/regress/sql/pg_dependencies.sql133
3 files changed, 674 insertions, 1 deletions
diff --git a/src/test/regress/expected/pg_dependencies.out b/src/test/regress/expected/pg_dependencies.out
new file mode 100644
index 00000000000..5c6fe667517
--- /dev/null
+++ b/src/test/regress/expected/pg_dependencies.out
@@ -0,0 +1,540 @@
+-- Tests for type pg_distinct
+-- Invalid inputs
+SELECT 'null'::pg_dependencies;
+ERROR: malformed pg_dependencies: "null"
+LINE 1: SELECT 'null'::pg_dependencies;
+ ^
+DETAIL: Unexpected scalar.
+SELECT '{"a": 1}'::pg_dependencies;
+ERROR: malformed pg_dependencies: "{"a": 1}"
+LINE 1: SELECT '{"a": 1}'::pg_dependencies;
+ ^
+DETAIL: Initial element must be an array.
+SELECT '[]'::pg_dependencies;
+ERROR: malformed pg_dependencies: "[]"
+LINE 1: SELECT '[]'::pg_dependencies;
+ ^
+DETAIL: Item array cannot be empty.
+SELECT '{}'::pg_dependencies;
+ERROR: malformed pg_dependencies: "{}"
+LINE 1: SELECT '{}'::pg_dependencies;
+ ^
+DETAIL: Initial element must be an array.
+SELECT '[null]'::pg_dependencies;
+ERROR: malformed pg_dependencies: "[null]"
+LINE 1: SELECT '[null]'::pg_dependencies;
+ ^
+DETAIL: Item list elements cannot be null.
+SELECT * FROM pg_input_error_info('null', 'pg_dependencies');
+ message | detail | hint | sql_error_code
+-----------------------------------+--------------------+------+----------------
+ malformed pg_dependencies: "null" | Unexpected scalar. | | 22P02
+(1 row)
+
+SELECT * FROM pg_input_error_info('{"a": 1}', 'pg_dependencies');
+ message | detail | hint | sql_error_code
+---------------------------------------+-----------------------------------+------+----------------
+ malformed pg_dependencies: "{"a": 1}" | Initial element must be an array. | | 22P02
+(1 row)
+
+SELECT * FROM pg_input_error_info('[]', 'pg_dependencies');
+ message | detail | hint | sql_error_code
+---------------------------------+-----------------------------+------+----------------
+ malformed pg_dependencies: "[]" | Item array cannot be empty. | | 22P02
+(1 row)
+
+SELECT * FROM pg_input_error_info('{}', 'pg_dependencies');
+ message | detail | hint | sql_error_code
+---------------------------------+-----------------------------------+------+----------------
+ malformed pg_dependencies: "{}" | Initial element must be an array. | | 22P02
+(1 row)
+
+SELECT * FROM pg_input_error_info('[null]', 'pg_dependencies');
+ message | detail | hint | sql_error_code
+-------------------------------------+------------------------------------+------+----------------
+ malformed pg_dependencies: "[null]" | Item list elements cannot be null. | | 22P02
+(1 row)
+
+-- Invalid keys
+SELECT '[{"attributes_invalid" : [2,3], "dependency" : 4}]'::pg_dependencies;
+ERROR: malformed pg_dependencies: "[{"attributes_invalid" : [2,3], "dependency" : 4}]"
+LINE 1: SELECT '[{"attributes_invalid" : [2,3], "dependency" : 4}]':...
+ ^
+DETAIL: Only allowed keys are "attributes", "dependency" and "degree".
+SELECT '[{"attributes" : [2,3], "invalid" : 3, "dependency" : 4}]'::pg_dependencies;
+ERROR: malformed pg_dependencies: "[{"attributes" : [2,3], "invalid" : 3, "dependency" : 4}]"
+LINE 1: SELECT '[{"attributes" : [2,3], "invalid" : 3, "dependency" ...
+ ^
+DETAIL: Only allowed keys are "attributes", "dependency" and "degree".
+SELECT * FROM pg_input_error_info('[{"attributes_invalid" : [2,3], "dependency" : 4}]', 'pg_dependencies');
+ message | detail | hint | sql_error_code
+---------------------------------------------------------------------------------+----------------------------------------------------------------+------+----------------
+ malformed pg_dependencies: "[{"attributes_invalid" : [2,3], "dependency" : 4}]" | Only allowed keys are "attributes", "dependency" and "degree". | | 22P02
+(1 row)
+
+SELECT * FROM pg_input_error_info('[{"attributes" : [2,3], "invalid" : 3, "dependency" : 4}]', 'pg_dependencies');
+ message | detail | hint | sql_error_code
+----------------------------------------------------------------------------------------+----------------------------------------------------------------+------+----------------
+ malformed pg_dependencies: "[{"attributes" : [2,3], "invalid" : 3, "dependency" : 4}]" | Only allowed keys are "attributes", "dependency" and "degree". | | 22P02
+(1 row)
+
+-- Missing keys
+SELECT '[{"attributes" : [2,3], "dependency" : 4}]'::pg_dependencies;
+ERROR: malformed pg_dependencies: "[{"attributes" : [2,3], "dependency" : 4}]"
+LINE 1: SELECT '[{"attributes" : [2,3], "dependency" : 4}]'::pg_depe...
+ ^
+DETAIL: Item must contain "degree" key.
+SELECT '[{"attributes" : [2,3], "degree" : 1.000}]'::pg_dependencies;
+ERROR: malformed pg_dependencies: "[{"attributes" : [2,3], "degree" : 1.000}]"
+LINE 1: SELECT '[{"attributes" : [2,3], "degree" : 1.000}]'::pg_depe...
+ ^
+DETAIL: Item must contain "dependency" key.
+SELECT '[{"attributes" : [2,3], "dependency" : 4}]'::pg_dependencies;
+ERROR: malformed pg_dependencies: "[{"attributes" : [2,3], "dependency" : 4}]"
+LINE 1: SELECT '[{"attributes" : [2,3], "dependency" : 4}]'::pg_depe...
+ ^
+DETAIL: Item must contain "degree" key.
+SELECT * FROM pg_input_error_info('[{"attributes" : [2,3], "dependency" : 4}]', 'pg_dependencies');
+ message | detail | hint | sql_error_code
+-------------------------------------------------------------------------+---------------------------------+------+----------------
+ malformed pg_dependencies: "[{"attributes" : [2,3], "dependency" : 4}]" | Item must contain "degree" key. | | 22P02
+(1 row)
+
+SELECT * FROM pg_input_error_info('[{"attributes" : [2,3], "degree" : 1.000}]', 'pg_dependencies');
+ message | detail | hint | sql_error_code
+-------------------------------------------------------------------------+-------------------------------------+------+----------------
+ malformed pg_dependencies: "[{"attributes" : [2,3], "degree" : 1.000}]" | Item must contain "dependency" key. | | 22P02
+(1 row)
+
+SELECT * FROM pg_input_error_info('[{"attributes" : [2,3], "dependency" : 4}]', 'pg_dependencies');
+ message | detail | hint | sql_error_code
+-------------------------------------------------------------------------+---------------------------------+------+----------------
+ malformed pg_dependencies: "[{"attributes" : [2,3], "dependency" : 4}]" | Item must contain "degree" key. | | 22P02
+(1 row)
+
+-- Valid keys, too many attributes
+SELECT '[{"attributes" : [1,2,3,4,5,6,7,8], "dependency" : 4, "degree": 1.000}]'::pg_dependencies;
+ERROR: malformed pg_dependencies: "[{"attributes" : [1,2,3,4,5,6,7,8], "dependency" : 4, "degree": 1.000}]"
+LINE 1: SELECT '[{"attributes" : [1,2,3,4,5,6,7,8], "dependency" : 4...
+ ^
+DETAIL: The "attributes" key must contain an array of at least 1 and no more than 7 elements.
+SELECT * FROM pg_input_error_info('[{"attributes" : [1,2,3,4,5,6,7,8], "dependency" : 4, "degree": 1.000}]', 'pg_dependencies');
+ message | detail | hint | sql_error_code
+------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------+------+----------------
+ malformed pg_dependencies: "[{"attributes" : [1,2,3,4,5,6,7,8], "dependency" : 4, "degree": 1.000}]" | The "attributes" key must contain an array of at least 1 and no more than 7 elements. | | 22P02
+(1 row)
+
+-- Special characters
+SELECT '[{"attributes" : ["\ud83d",3], "dependency" : 4, "degree": 0.250}]'::pg_dependencies;
+ERROR: malformed pg_dependencies: "[{"attributes" : ["\ud83d",3], "dependency" : 4, "degree": 0.250}]"
+LINE 1: SELECT '[{"attributes" : ["\ud83d",3], "dependency" : 4, "de...
+ ^
+DETAIL: Must be valid JSON.
+SELECT '[{"attributes" : [2,3], "dependency" : "\ud83d", "degree": 0.250}]'::pg_dependencies;
+ERROR: malformed pg_dependencies: "[{"attributes" : [2,3], "dependency" : "\ud83d", "degree": 0.250}]"
+LINE 1: SELECT '[{"attributes" : [2,3], "dependency" : "\ud83d", "de...
+ ^
+DETAIL: Must be valid JSON.
+SELECT '[{"attributes" : [2,3], "dependency" : 4, "degree": "\ud83d"}]'::pg_dependencies;
+ERROR: malformed pg_dependencies: "[{"attributes" : [2,3], "dependency" : 4, "degree": "\ud83d"}]"
+LINE 1: SELECT '[{"attributes" : [2,3], "dependency" : 4, "degree": ...
+ ^
+DETAIL: Must be valid JSON.
+SELECT '[{"\ud83d" : [2,3], "dependency" : 4, "degree": 0.250}]'::pg_dependencies;
+ERROR: malformed pg_dependencies: "[{"\ud83d" : [2,3], "dependency" : 4, "degree": 0.250}]"
+LINE 1: SELECT '[{"\ud83d" : [2,3], "dependency" : 4, "degree": 0.25...
+ ^
+DETAIL: Must be valid JSON.
+SELECT * FROM pg_input_error_info('[{"attributes" : ["\ud83d",3], "dependency" : 4, "degree": 0.250}]', 'pg_dependencies');
+ message | detail | hint | sql_error_code
+-------------------------------------------------------------------------------------------------+---------------------+------+----------------
+ malformed pg_dependencies: "[{"attributes" : ["\ud83d",3], "dependency" : 4, "degree": 0.250}]" | Must be valid JSON. | | 22P02
+(1 row)
+
+SELECT * FROM pg_input_error_info('[{"attributes" : [2,3], "dependency" : "\ud83d", "degree": 0.250}]', 'pg_dependencies');
+ message | detail | hint | sql_error_code
+-------------------------------------------------------------------------------------------------+---------------------+------+----------------
+ malformed pg_dependencies: "[{"attributes" : [2,3], "dependency" : "\ud83d", "degree": 0.250}]" | Must be valid JSON. | | 22P02
+(1 row)
+
+SELECT * FROM pg_input_error_info('[{"attributes" : [2,3], "dependency" : 4, "degree": "\ud83d"}]', 'pg_dependencies');
+ message | detail | hint | sql_error_code
+---------------------------------------------------------------------------------------------+---------------------+------+----------------
+ malformed pg_dependencies: "[{"attributes" : [2,3], "dependency" : 4, "degree": "\ud83d"}]" | Must be valid JSON. | | 22P02
+(1 row)
+
+SELECT * FROM pg_input_error_info('[{"\ud83d" : [2,3], "dependency" : 4, "degree": 0.250}]', 'pg_dependencies');
+ message | detail | hint | sql_error_code
+--------------------------------------------------------------------------------------+---------------------+------+----------------
+ malformed pg_dependencies: "[{"\ud83d" : [2,3], "dependency" : 4, "degree": 0.250}]" | Must be valid JSON. | | 22P02
+(1 row)
+
+-- Valid keys, invalid values
+SELECT '[{"attributes" : null, "dependency" : 4, "degree": 1.000}]'::pg_dependencies;
+ERROR: malformed pg_dependencies: "[{"attributes" : null, "dependency" : 4, "degree": 1.000}]"
+LINE 1: SELECT '[{"attributes" : null, "dependency" : 4, "degree": 1...
+ ^
+DETAIL: Unexpected scalar.
+SELECT '[{"attributes" : [2,null], "dependency" : 4, "degree": 1.000}]'::pg_dependencies;
+ERROR: malformed pg_dependencies: "[{"attributes" : [2,null], "dependency" : 4, "degree": 1.000}]"
+LINE 1: SELECT '[{"attributes" : [2,null], "dependency" : 4, "degree...
+ ^
+DETAIL: Attribute number array cannot be null.
+SELECT '[{"attributes" : [2,3], "dependency" : null, "degree": 1.000}]'::pg_dependencies;
+ERROR: malformed pg_dependencies: "[{"attributes" : [2,3], "dependency" : null, "degree": 1.000}]"
+LINE 1: SELECT '[{"attributes" : [2,3], "dependency" : null, "degree...
+ ^
+DETAIL: Invalid "dependency" value.
+SELECT '[{"attributes" : [2,"a"], "dependency" : 4, "degree": 1.000}]'::pg_dependencies;
+ERROR: malformed pg_dependencies: "[{"attributes" : [2,"a"], "dependency" : 4, "degree": 1.000}]"
+LINE 1: SELECT '[{"attributes" : [2,"a"], "dependency" : 4, "degree"...
+ ^
+DETAIL: Invalid "attributes" value.
+SELECT '[{"attributes" : [2,3], "dependency" : "a", "degree": 1.000}]'::pg_dependencies;
+ERROR: malformed pg_dependencies: "[{"attributes" : [2,3], "dependency" : "a", "degree": 1.000}]"
+LINE 1: SELECT '[{"attributes" : [2,3], "dependency" : "a", "degree"...
+ ^
+DETAIL: Invalid "dependency" value.
+SELECT '[{"attributes" : [2,3], "dependency" : [], "degree": 1.000}]'::pg_dependencies;
+ERROR: malformed pg_dependencies: "[{"attributes" : [2,3], "dependency" : [], "degree": 1.000}]"
+LINE 1: SELECT '[{"attributes" : [2,3], "dependency" : [], "degree":...
+ ^
+DETAIL: Array found in unexpected place.
+SELECT '[{"attributes" : [2,3], "dependency" : [null], "degree": 1.000}]'::pg_dependencies;
+ERROR: malformed pg_dependencies: "[{"attributes" : [2,3], "dependency" : [null], "degree": 1.000}]"
+LINE 1: SELECT '[{"attributes" : [2,3], "dependency" : [null], "degr...
+ ^
+DETAIL: Array found in unexpected place.
+SELECT '[{"attributes" : [2,3], "dependency" : [1,null], "degree": 1.000}]'::pg_dependencies;
+ERROR: malformed pg_dependencies: "[{"attributes" : [2,3], "dependency" : [1,null], "degree": 1.000}]"
+LINE 1: SELECT '[{"attributes" : [2,3], "dependency" : [1,null], "de...
+ ^
+DETAIL: Array found in unexpected place.
+SELECT '[{"attributes" : 1, "dependency" : 4, "degree": 1.000}]'::pg_dependencies;
+ERROR: malformed pg_dependencies: "[{"attributes" : 1, "dependency" : 4, "degree": 1.000}]"
+LINE 1: SELECT '[{"attributes" : 1, "dependency" : 4, "degree": 1.00...
+ ^
+DETAIL: Unexpected scalar.
+SELECT '[{"attributes" : "a", "dependency" : 4, "degree": 1.000}]'::pg_dependencies;
+ERROR: malformed pg_dependencies: "[{"attributes" : "a", "dependency" : 4, "degree": 1.000}]"
+LINE 1: SELECT '[{"attributes" : "a", "dependency" : 4, "degree": 1....
+ ^
+DETAIL: Unexpected scalar.
+SELECT '[{"attributes" : [2,3], "dependency" : 4, "degree": NaN}]'::pg_dependencies;
+ERROR: malformed pg_dependencies: "[{"attributes" : [2,3], "dependency" : 4, "degree": NaN}]"
+LINE 1: SELECT '[{"attributes" : [2,3], "dependency" : 4, "degree": ...
+ ^
+DETAIL: Must be valid JSON.
+SELECT * FROM pg_input_error_info('[{"attributes" : null, "dependency" : 4, "degree": 1.000}]', 'pg_dependencies');
+ message | detail | hint | sql_error_code
+-----------------------------------------------------------------------------------------+--------------------+------+----------------
+ malformed pg_dependencies: "[{"attributes" : null, "dependency" : 4, "degree": 1.000}]" | Unexpected scalar. | | 22P02
+(1 row)
+
+SELECT * FROM pg_input_error_info('[{"attributes" : [2,null], "dependency" : 4, "degree": 1.000}]', 'pg_dependencies');
+ message | detail | hint | sql_error_code
+---------------------------------------------------------------------------------------------+----------------------------------------+------+----------------
+ malformed pg_dependencies: "[{"attributes" : [2,null], "dependency" : 4, "degree": 1.000}]" | Attribute number array cannot be null. | | 22P02
+(1 row)
+
+SELECT * FROM pg_input_error_info('[{"attributes" : [2,3], "dependency" : null, "degree": 1.000}]', 'pg_dependencies');
+ message | detail | hint | sql_error_code
+---------------------------------------------------------------------------------------------+-----------------------------+------+----------------
+ malformed pg_dependencies: "[{"attributes" : [2,3], "dependency" : null, "degree": 1.000}]" | Invalid "dependency" value. | | 22P02
+(1 row)
+
+SELECT * FROM pg_input_error_info('[{"attributes" : [2,"a"], "dependency" : 4, "degree": 1.000}]', 'pg_dependencies');
+ message | detail | hint | sql_error_code
+--------------------------------------------------------------------------------------------+-----------------------------+------+----------------
+ malformed pg_dependencies: "[{"attributes" : [2,"a"], "dependency" : 4, "degree": 1.000}]" | Invalid "attributes" value. | | 22P02
+(1 row)
+
+SELECT * FROM pg_input_error_info('[{"attributes" : [2,3], "dependency" : "a", "degree": 1.000}]', 'pg_dependencies');
+ message | detail | hint | sql_error_code
+--------------------------------------------------------------------------------------------+-----------------------------+------+----------------
+ malformed pg_dependencies: "[{"attributes" : [2,3], "dependency" : "a", "degree": 1.000}]" | Invalid "dependency" value. | | 22P02
+(1 row)
+
+SELECT * FROM pg_input_error_info('[{"attributes" : [2,3], "dependency" : [], "degree": 1.000}]', 'pg_dependencies');
+ message | detail | hint | sql_error_code
+-------------------------------------------------------------------------------------------+----------------------------------+------+----------------
+ malformed pg_dependencies: "[{"attributes" : [2,3], "dependency" : [], "degree": 1.000}]" | Array found in unexpected place. | | 22P02
+(1 row)
+
+SELECT * FROM pg_input_error_info('[{"attributes" : [2,3], "dependency" : [null], "degree": 1.000}]', 'pg_dependencies');
+ message | detail | hint | sql_error_code
+-----------------------------------------------------------------------------------------------+----------------------------------+------+----------------
+ malformed pg_dependencies: "[{"attributes" : [2,3], "dependency" : [null], "degree": 1.000}]" | Array found in unexpected place. | | 22P02
+(1 row)
+
+SELECT * FROM pg_input_error_info('[{"attributes" : [2,3], "dependency" : [1,null], "degree": 1.000}]', 'pg_dependencies');
+ message | detail | hint | sql_error_code
+-------------------------------------------------------------------------------------------------+----------------------------------+------+----------------
+ malformed pg_dependencies: "[{"attributes" : [2,3], "dependency" : [1,null], "degree": 1.000}]" | Array found in unexpected place. | | 22P02
+(1 row)
+
+SELECT * FROM pg_input_error_info('[{"attributes" : 1, "dependency" : 4, "degree": 1.000}]', 'pg_dependencies');
+ message | detail | hint | sql_error_code
+--------------------------------------------------------------------------------------+--------------------+------+----------------
+ malformed pg_dependencies: "[{"attributes" : 1, "dependency" : 4, "degree": 1.000}]" | Unexpected scalar. | | 22P02
+(1 row)
+
+SELECT * FROM pg_input_error_info('[{"attributes" : "a", "dependency" : 4, "degree": 1.000}]', 'pg_dependencies');
+ message | detail | hint | sql_error_code
+----------------------------------------------------------------------------------------+--------------------+------+----------------
+ malformed pg_dependencies: "[{"attributes" : "a", "dependency" : 4, "degree": 1.000}]" | Unexpected scalar. | | 22P02
+(1 row)
+
+SELECT * FROM pg_input_error_info('[{"attributes" : [2,3], "dependency" : 4, "degree": NaN}]', 'pg_dependencies');
+ message | detail | hint | sql_error_code
+----------------------------------------------------------------------------------------+---------------------+------+----------------
+ malformed pg_dependencies: "[{"attributes" : [2,3], "dependency" : 4, "degree": NaN}]" | Must be valid JSON. | | 22P02
+(1 row)
+
+SELECT '[{"attributes": [], "dependency": 2, "degree": 1}]' ::pg_dependencies;
+ERROR: malformed pg_dependencies: "[{"attributes": [], "dependency": 2, "degree": 1}]"
+LINE 1: SELECT '[{"attributes": [], "dependency": 2, "degree": 1}]' ...
+ ^
+DETAIL: The "attributes" key must be an non-empty array.
+SELECT '[{"attributes" : {"a": 1}, "dependency" : 4, "degree": "1.2"}]'::pg_dependencies;
+ERROR: malformed pg_dependencies: "[{"attributes" : {"a": 1}, "dependency" : 4, "degree": "1.2"}]"
+LINE 1: SELECT '[{"attributes" : {"a": 1}, "dependency" : 4, "degree...
+ ^
+DETAIL: Value of "attributes" must be an array of attribute numbers.
+SELECT * FROM pg_input_error_info('[{"attributes": [], "dependency": 2, "degree": 1}]', 'pg_dependencies');
+ message | detail | hint | sql_error_code
+---------------------------------------------------------------------------------+--------------------------------------------------+------+----------------
+ malformed pg_dependencies: "[{"attributes": [], "dependency": 2, "degree": 1}]" | The "attributes" key must be an non-empty array. | | 22P02
+(1 row)
+
+SELECT * FROM pg_input_error_info('[{"attributes" : {"a": 1}, "dependency" : 4, "degree": "1.2"}]', 'pg_dependencies');
+ message | detail | hint | sql_error_code
+---------------------------------------------------------------------------------------------+--------------------------------------------------------------+------+----------------
+ malformed pg_dependencies: "[{"attributes" : {"a": 1}, "dependency" : 4, "degree": "1.2"}]" | Value of "attributes" must be an array of attribute numbers. | | 22P02
+(1 row)
+
+SELECT '[{"dependency" : 4, "degree": "1.2"}]'::pg_dependencies;
+ERROR: malformed pg_dependencies: "[{"dependency" : 4, "degree": "1.2"}]"
+LINE 1: SELECT '[{"dependency" : 4, "degree": "1.2"}]'::pg_dependenc...
+ ^
+DETAIL: Item must contain "attributes" key
+SELECT '[{"attributes" : [1,2,3,4,5,6,7], "dependency" : 0, "degree": "1.2"}]'::pg_dependencies;
+ERROR: malformed pg_dependencies: "[{"attributes" : [1,2,3,4,5,6,7], "dependency" : 0, "degree": "1.2"}]"
+LINE 1: SELECT '[{"attributes" : [1,2,3,4,5,6,7], "dependency" : 0, ...
+ ^
+DETAIL: Invalid "dependency" value: 0.
+SELECT '[{"attributes" : [1,2,3,4,5,6,7], "dependency" : -9, "degree": "1.2"}]'::pg_dependencies;
+ERROR: malformed pg_dependencies: "[{"attributes" : [1,2,3,4,5,6,7], "dependency" : -9, "degree": "1.2"}]"
+LINE 1: SELECT '[{"attributes" : [1,2,3,4,5,6,7], "dependency" : -9,...
+ ^
+DETAIL: Invalid "dependency" value: -9.
+SELECT '[{"attributes": [1,2], "dependency": 2, "degree": 1}]' ::pg_dependencies;
+ERROR: malformed pg_dependencies: "[{"attributes": [1,2], "dependency": 2, "degree": 1}]"
+LINE 1: SELECT '[{"attributes": [1,2], "dependency": 2, "degree": 1}...
+ ^
+DETAIL: Item "dependency" value 2 found in the "attributes" list.
+SELECT '[{"attributes" : [1, {}], "dependency" : 1, "degree": "1.2"}]'::pg_dependencies;
+ERROR: malformed pg_dependencies: "[{"attributes" : [1, {}], "dependency" : 1, "degree": "1.2"}]"
+LINE 1: SELECT '[{"attributes" : [1, {}], "dependency" : 1, "degree"...
+ ^
+DETAIL: Attribute lists can only contain attribute numbers.
+SELECT '[{"attributes" : [1,2], "dependency" : {}, "degree": 1.0}]'::pg_dependencies;
+ERROR: malformed pg_dependencies: "[{"attributes" : [1,2], "dependency" : {}, "degree": 1.0}]"
+LINE 1: SELECT '[{"attributes" : [1,2], "dependency" : {}, "degree":...
+ ^
+DETAIL: Value of "dependency" must be an integer.
+SELECT '[{"attributes" : [1,2], "dependency" : 3, "degree": {}}]'::pg_dependencies;
+ERROR: malformed pg_dependencies: "[{"attributes" : [1,2], "dependency" : 3, "degree": {}}]"
+LINE 1: SELECT '[{"attributes" : [1,2], "dependency" : 3, "degree": ...
+ ^
+DETAIL: Value of "degree" must be an integer.
+SELECT '[{"attributes" : [1,2], "dependency" : 1, "degree": "a"}]'::pg_dependencies;
+ERROR: malformed pg_dependencies: "[{"attributes" : [1,2], "dependency" : 1, "degree": "a"}]"
+LINE 1: SELECT '[{"attributes" : [1,2], "dependency" : 1, "degree": ...
+ ^
+DETAIL: Invalid "degree" value.
+SELECT * FROM pg_input_error_info('[{"dependency" : 4, "degree": "1.2"}]', 'pg_dependencies');
+ message | detail | hint | sql_error_code
+--------------------------------------------------------------------+------------------------------------+------+----------------
+ malformed pg_dependencies: "[{"dependency" : 4, "degree": "1.2"}]" | Item must contain "attributes" key | | 22P02
+(1 row)
+
+SELECT * FROM pg_input_error_info('[{"attributes" : [1,2,3,4,5,6,7], "dependency" : 0, "degree": "1.2"}]', 'pg_dependencies');
+ message | detail | hint | sql_error_code
+----------------------------------------------------------------------------------------------------+--------------------------------+------+----------------
+ malformed pg_dependencies: "[{"attributes" : [1,2,3,4,5,6,7], "dependency" : 0, "degree": "1.2"}]" | Invalid "dependency" value: 0. | | 22P02
+(1 row)
+
+SELECT * FROM pg_input_error_info('[{"attributes" : [1,2,3,4,5,6,7], "dependency" : -9, "degree": "1.2"}]', 'pg_dependencies');
+ message | detail | hint | sql_error_code
+-----------------------------------------------------------------------------------------------------+---------------------------------+------+----------------
+ malformed pg_dependencies: "[{"attributes" : [1,2,3,4,5,6,7], "dependency" : -9, "degree": "1.2"}]" | Invalid "dependency" value: -9. | | 22P02
+(1 row)
+
+SELECT * FROM pg_input_error_info('[{"attributes": [1,2], "dependency": 2, "degree": 1}]' , 'pg_dependencies');
+ message | detail | hint | sql_error_code
+------------------------------------------------------------------------------------+-----------------------------------------------------------+------+----------------
+ malformed pg_dependencies: "[{"attributes": [1,2], "dependency": 2, "degree": 1}]" | Item "dependency" value 2 found in the "attributes" list. | | 22P02
+(1 row)
+
+SELECT * FROM pg_input_error_info('[{"attributes" : [1, {}], "dependency" : 1, "degree": "1.2"}]', 'pg_dependencies');
+ message | detail | hint | sql_error_code
+--------------------------------------------------------------------------------------------+-----------------------------------------------------+------+----------------
+ malformed pg_dependencies: "[{"attributes" : [1, {}], "dependency" : 1, "degree": "1.2"}]" | Attribute lists can only contain attribute numbers. | | 22P02
+(1 row)
+
+SELECT * FROM pg_input_error_info('[{"attributes" : [1,2], "dependency" : {}, "degree": 1.0}]', 'pg_dependencies');
+ message | detail | hint | sql_error_code
+-----------------------------------------------------------------------------------------+-------------------------------------------+------+----------------
+ malformed pg_dependencies: "[{"attributes" : [1,2], "dependency" : {}, "degree": 1.0}]" | Value of "dependency" must be an integer. | | 22P02
+(1 row)
+
+SELECT * FROM pg_input_error_info('[{"attributes" : [1,2], "dependency" : 3, "degree": {}}]', 'pg_dependencies');
+ message | detail | hint | sql_error_code
+---------------------------------------------------------------------------------------+---------------------------------------+------+----------------
+ malformed pg_dependencies: "[{"attributes" : [1,2], "dependency" : 3, "degree": {}}]" | Value of "degree" must be an integer. | | 22P02
+(1 row)
+
+SELECT * FROM pg_input_error_info('[{"attributes" : [1,2], "dependency" : 1, "degree": "a"}]', 'pg_dependencies');
+ message | detail | hint | sql_error_code
+----------------------------------------------------------------------------------------+-------------------------+------+----------------
+ malformed pg_dependencies: "[{"attributes" : [1,2], "dependency" : 1, "degree": "a"}]" | Invalid "degree" value. | | 22P02
+(1 row)
+
+-- Funky degree values, which do not fail.
+SELECT '[{"attributes" : [2], "dependency" : 4, "degree": "NaN"}]'::pg_dependencies;
+ pg_dependencies
+-------------------------------------------------------
+ [{"attributes": [2], "dependency": 4, "degree": NaN}]
+(1 row)
+
+SELECT '[{"attributes" : [2], "dependency" : 4, "degree": "-inf"}]'::pg_dependencies;
+ pg_dependencies
+-------------------------------------------------------------
+ [{"attributes": [2], "dependency": 4, "degree": -Infinity}]
+(1 row)
+
+SELECT '[{"attributes" : [2], "dependency" : 4, "degree": "inf"}]'::pg_dependencies;
+ pg_dependencies
+------------------------------------------------------------
+ [{"attributes": [2], "dependency": 4, "degree": Infinity}]
+(1 row)
+
+SELECT '[{"attributes" : [2], "dependency" : 4, "degree": "-inf"}]'::pg_dependencies::text::pg_dependencies;
+ERROR: malformed pg_dependencies: "[{"attributes": [2], "dependency": 4, "degree": -Infinity}]"
+DETAIL: Must be valid JSON.
+-- Duplicated keys
+SELECT '[{"attributes" : [2,3], "attributes": [1,2], "dependency" : 4, "degree": 1.000}]'::pg_dependencies;
+ERROR: malformed pg_dependencies: "[{"attributes" : [2,3], "attributes": [1,2], "dependency" : 4, "degree": 1.000}]"
+LINE 1: SELECT '[{"attributes" : [2,3], "attributes": [1,2], "depend...
+ ^
+DETAIL: Multiple "attributes" keys are not allowed.
+SELECT '[{"attributes" : [2,3], "dependency" : 4, "dependency": 4, "degree": 1.000}]'::pg_dependencies;
+ERROR: malformed pg_dependencies: "[{"attributes" : [2,3], "dependency" : 4, "dependency": 4, "degree": 1.000}]"
+LINE 1: SELECT '[{"attributes" : [2,3], "dependency" : 4, "dependenc...
+ ^
+DETAIL: Multiple "dependency" keys are not allowed.
+SELECT '[{"attributes" : [2,3], "dependency": 4, "degree": 1.000, "degree": 1.000}]'::pg_dependencies;
+ERROR: malformed pg_dependencies: "[{"attributes" : [2,3], "dependency": 4, "degree": 1.000, "degree": 1.000}]"
+LINE 1: SELECT '[{"attributes" : [2,3], "dependency": 4, "degree": 1...
+ ^
+DETAIL: Multiple "degree" keys are not allowed.
+SELECT * FROM pg_input_error_info('[{"attributes" : [2,3], "attributes": [1,2], "dependency" : 4, "degree": 1.000}]', 'pg_dependencies');
+ message | detail | hint | sql_error_code
+---------------------------------------------------------------------------------------------------------------+---------------------------------------------+------+----------------
+ malformed pg_dependencies: "[{"attributes" : [2,3], "attributes": [1,2], "dependency" : 4, "degree": 1.000}]" | Multiple "attributes" keys are not allowed. | | 22P02
+(1 row)
+
+SELECT * FROM pg_input_error_info('[{"attributes" : [2,3], "dependency" : 4, "dependency": 4, "degree": 1.000}]', 'pg_dependencies');
+ message | detail | hint | sql_error_code
+-----------------------------------------------------------------------------------------------------------+---------------------------------------------+------+----------------
+ malformed pg_dependencies: "[{"attributes" : [2,3], "dependency" : 4, "dependency": 4, "degree": 1.000}]" | Multiple "dependency" keys are not allowed. | | 22P02
+(1 row)
+
+SELECT * FROM pg_input_error_info('[{"attributes" : [2,3], "dependency": 4, "degree": 1.000, "degree": 1.000}]', 'pg_dependencies');
+ message | detail | hint | sql_error_code
+----------------------------------------------------------------------------------------------------------+-----------------------------------------+------+----------------
+ malformed pg_dependencies: "[{"attributes" : [2,3], "dependency": 4, "degree": 1.000, "degree": 1.000}]" | Multiple "degree" keys are not allowed. | | 22P02
+(1 row)
+
+-- Invalid attnums
+SELECT '[{"attributes" : [0,2], "dependency" : 4, "degree": 0.500}]'::pg_dependencies;
+ERROR: malformed pg_dependencies: "[{"attributes" : [0,2], "dependency" : 4, "degree": 0.500}]"
+LINE 1: SELECT '[{"attributes" : [0,2], "dependency" : 4, "degree": ...
+ ^
+DETAIL: Invalid "attributes" element: 0.
+SELECT '[{"attributes" : [-7,-9], "dependency" : 4, "degree": 0.500}]'::pg_dependencies;
+ERROR: malformed pg_dependencies: "[{"attributes" : [-7,-9], "dependency" : 4, "degree": 0.500}]"
+LINE 1: SELECT '[{"attributes" : [-7,-9], "dependency" : 4, "degree"...
+ ^
+DETAIL: Invalid "attributes" element: -9.
+SELECT * FROM pg_input_error_info('[{"attributes" : [0,2], "dependency" : 4, "degree": 0.500}]', 'pg_dependencies');
+ message | detail | hint | sql_error_code
+------------------------------------------------------------------------------------------+----------------------------------+------+----------------
+ malformed pg_dependencies: "[{"attributes" : [0,2], "dependency" : 4, "degree": 0.500}]" | Invalid "attributes" element: 0. | | 22P02
+(1 row)
+
+SELECT * FROM pg_input_error_info('[{"attributes" : [-7,-9], "dependency" : 4, "degree": 0.500}]', 'pg_dependencies');
+ message | detail | hint | sql_error_code
+--------------------------------------------------------------------------------------------+-----------------------------------+------+----------------
+ malformed pg_dependencies: "[{"attributes" : [-7,-9], "dependency" : 4, "degree": 0.500}]" | Invalid "attributes" element: -9. | | 22P02
+(1 row)
+
+-- Duplicated attributes
+SELECT '[{"attributes" : [2,2], "dependency" : 4, "degree": 0.500}]'::pg_dependencies;
+ERROR: malformed pg_dependencies: "[{"attributes" : [2,2], "dependency" : 4, "degree": 0.500}]"
+LINE 1: SELECT '[{"attributes" : [2,2], "dependency" : 4, "degree": ...
+ ^
+DETAIL: Invalid "attributes" element: 2 cannot follow 2.
+SELECT * FROM pg_input_error_info('[{"attributes" : [2,2], "dependency" : 4, "degree": 0.500}]', 'pg_dependencies');
+ message | detail | hint | sql_error_code
+------------------------------------------------------------------------------------------+--------------------------------------------------+------+----------------
+ malformed pg_dependencies: "[{"attributes" : [2,2], "dependency" : 4, "degree": 0.500}]" | Invalid "attributes" element: 2 cannot follow 2. | | 22P02
+(1 row)
+
+-- Duplicated attribute lists.
+SELECT '[{"attributes" : [2,3], "dependency" : 4, "degree": 1.000},
+ {"attributes" : [2,3], "dependency" : 4, "degree": 1.000}]'::pg_dependencies;
+ERROR: malformed pg_dependencies: "[{"attributes" : [2,3], "dependency" : 4, "degree": 1.000},
+ {"attributes" : [2,3], "dependency" : 4, "degree": 1.000}]"
+LINE 1: SELECT '[{"attributes" : [2,3], "dependency" : 4, "degree": ...
+ ^
+DETAIL: Duplicate "attributes" array: [2, 3] with "dependency": 4.
+SELECT * FROM pg_input_error_info('[{"attributes" : [2,3], "dependency" : 4, "degree": 1.000},
+ {"attributes" : [2,3], "dependency" : 4, "degree": 1.000}]', 'pg_dependencies');
+ message | detail | hint | sql_error_code
+-----------------------------------------------------------------------------------------+------------------------------------------------------------+------+----------------
+ malformed pg_dependencies: "[{"attributes" : [2,3], "dependency" : 4, "degree": 1.000},+| Duplicate "attributes" array: [2, 3] with "dependency": 4. | | 22P02
+ {"attributes" : [2,3], "dependency" : 4, "degree": 1.000}]" | | |
+(1 row)
+
+-- Valid inputs
+SELECT '[{"attributes" : [2,3], "dependency" : 4, "degree": 0.250},
+ {"attributes" : [2,-1], "dependency" : 4, "degree": 0.500},
+ {"attributes" : [2,3,-1], "dependency" : 4, "degree": 0.750},
+ {"attributes" : [2,3,-1,-2], "dependency" : 4, "degree": 1.000}]'::pg_dependencies;
+ pg_dependencies
+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+ [{"attributes": [2, 3], "dependency": 4, "degree": 0.250000}, {"attributes": [2, -1], "dependency": 4, "degree": 0.500000}, {"attributes": [2, 3, -1], "dependency": 4, "degree": 0.750000}, {"attributes": [2, 3, -1, -2], "dependency": 4, "degree": 1.000000}]
+(1 row)
+
+SELECT * FROM pg_input_error_info('[{"attributes" : [2,3], "dependency" : 4, "degree": 0.250},
+ {"attributes" : [2,-1], "dependency" : 4, "degree": 0.500},
+ {"attributes" : [2,3,-1], "dependency" : 4, "degree": 0.750},
+ {"attributes" : [2,3,-1,-2], "dependency" : 4, "degree": 1.000}]', 'pg_dependencies');
+ message | detail | hint | sql_error_code
+---------+--------+------+----------------
+ | | |
+(1 row)
+
+-- Partially-covered attribute lists, possible as items with a degree of 0
+-- are discarded.
+SELECT '[{"attributes" : [2,3], "dependency" : 4, "degree": 1.000},
+ {"attributes" : [1,-1], "dependency" : 4, "degree": 1.000},
+ {"attributes" : [2,3,-1], "dependency" : 4, "degree": 1.000},
+ {"attributes" : [2,3,-1,-2], "dependency" : 4, "degree": 1.000}]'::pg_dependencies;
+ pg_dependencies
+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+ [{"attributes": [2, 3], "dependency": 4, "degree": 1.000000}, {"attributes": [1, -1], "dependency": 4, "degree": 1.000000}, {"attributes": [2, 3, -1], "dependency": 4, "degree": 1.000000}, {"attributes": [2, 3, -1, -2], "dependency": 4, "degree": 1.000000}]
+(1 row)
+
diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule
index f3f0b5f2f31..cc6d799bcea 100644
--- a/src/test/regress/parallel_schedule
+++ b/src/test/regress/parallel_schedule
@@ -28,7 +28,7 @@ test: strings md5 numerology point lseg line box path polygon circle date time t
# geometry depends on point, lseg, line, box, path, polygon, circle
# horology depends on date, time, timetz, timestamp, timestamptz, interval
# ----------
-test: geometry horology tstypes regex type_sanity opr_sanity misc_sanity comments expressions unicode xid mvcc database stats_import pg_ndistinct
+test: geometry horology tstypes regex type_sanity opr_sanity misc_sanity comments expressions unicode xid mvcc database stats_import pg_ndistinct pg_dependencies
# ----------
# Load huge amounts of data
diff --git a/src/test/regress/sql/pg_dependencies.sql b/src/test/regress/sql/pg_dependencies.sql
new file mode 100644
index 00000000000..7935c540e3c
--- /dev/null
+++ b/src/test/regress/sql/pg_dependencies.sql
@@ -0,0 +1,133 @@
+-- Tests for type pg_distinct
+
+-- Invalid inputs
+SELECT 'null'::pg_dependencies;
+SELECT '{"a": 1}'::pg_dependencies;
+SELECT '[]'::pg_dependencies;
+SELECT '{}'::pg_dependencies;
+SELECT '[null]'::pg_dependencies;
+SELECT * FROM pg_input_error_info('null', 'pg_dependencies');
+SELECT * FROM pg_input_error_info('{"a": 1}', 'pg_dependencies');
+SELECT * FROM pg_input_error_info('[]', 'pg_dependencies');
+SELECT * FROM pg_input_error_info('{}', 'pg_dependencies');
+SELECT * FROM pg_input_error_info('[null]', 'pg_dependencies');
+
+-- Invalid keys
+SELECT '[{"attributes_invalid" : [2,3], "dependency" : 4}]'::pg_dependencies;
+SELECT '[{"attributes" : [2,3], "invalid" : 3, "dependency" : 4}]'::pg_dependencies;
+SELECT * FROM pg_input_error_info('[{"attributes_invalid" : [2,3], "dependency" : 4}]', 'pg_dependencies');
+SELECT * FROM pg_input_error_info('[{"attributes" : [2,3], "invalid" : 3, "dependency" : 4}]', 'pg_dependencies');
+
+-- Missing keys
+SELECT '[{"attributes" : [2,3], "dependency" : 4}]'::pg_dependencies;
+SELECT '[{"attributes" : [2,3], "degree" : 1.000}]'::pg_dependencies;
+SELECT '[{"attributes" : [2,3], "dependency" : 4}]'::pg_dependencies;
+SELECT * FROM pg_input_error_info('[{"attributes" : [2,3], "dependency" : 4}]', 'pg_dependencies');
+SELECT * FROM pg_input_error_info('[{"attributes" : [2,3], "degree" : 1.000}]', 'pg_dependencies');
+SELECT * FROM pg_input_error_info('[{"attributes" : [2,3], "dependency" : 4}]', 'pg_dependencies');
+
+-- Valid keys, too many attributes
+SELECT '[{"attributes" : [1,2,3,4,5,6,7,8], "dependency" : 4, "degree": 1.000}]'::pg_dependencies;
+SELECT * FROM pg_input_error_info('[{"attributes" : [1,2,3,4,5,6,7,8], "dependency" : 4, "degree": 1.000}]', 'pg_dependencies');
+
+-- Special characters
+SELECT '[{"attributes" : ["\ud83d",3], "dependency" : 4, "degree": 0.250}]'::pg_dependencies;
+SELECT '[{"attributes" : [2,3], "dependency" : "\ud83d", "degree": 0.250}]'::pg_dependencies;
+SELECT '[{"attributes" : [2,3], "dependency" : 4, "degree": "\ud83d"}]'::pg_dependencies;
+SELECT '[{"\ud83d" : [2,3], "dependency" : 4, "degree": 0.250}]'::pg_dependencies;
+SELECT * FROM pg_input_error_info('[{"attributes" : ["\ud83d",3], "dependency" : 4, "degree": 0.250}]', 'pg_dependencies');
+SELECT * FROM pg_input_error_info('[{"attributes" : [2,3], "dependency" : "\ud83d", "degree": 0.250}]', 'pg_dependencies');
+SELECT * FROM pg_input_error_info('[{"attributes" : [2,3], "dependency" : 4, "degree": "\ud83d"}]', 'pg_dependencies');
+SELECT * FROM pg_input_error_info('[{"\ud83d" : [2,3], "dependency" : 4, "degree": 0.250}]', 'pg_dependencies');
+
+-- Valid keys, invalid values
+SELECT '[{"attributes" : null, "dependency" : 4, "degree": 1.000}]'::pg_dependencies;
+SELECT '[{"attributes" : [2,null], "dependency" : 4, "degree": 1.000}]'::pg_dependencies;
+SELECT '[{"attributes" : [2,3], "dependency" : null, "degree": 1.000}]'::pg_dependencies;
+SELECT '[{"attributes" : [2,"a"], "dependency" : 4, "degree": 1.000}]'::pg_dependencies;
+SELECT '[{"attributes" : [2,3], "dependency" : "a", "degree": 1.000}]'::pg_dependencies;
+SELECT '[{"attributes" : [2,3], "dependency" : [], "degree": 1.000}]'::pg_dependencies;
+SELECT '[{"attributes" : [2,3], "dependency" : [null], "degree": 1.000}]'::pg_dependencies;
+SELECT '[{"attributes" : [2,3], "dependency" : [1,null], "degree": 1.000}]'::pg_dependencies;
+SELECT '[{"attributes" : 1, "dependency" : 4, "degree": 1.000}]'::pg_dependencies;
+SELECT '[{"attributes" : "a", "dependency" : 4, "degree": 1.000}]'::pg_dependencies;
+SELECT '[{"attributes" : [2,3], "dependency" : 4, "degree": NaN}]'::pg_dependencies;
+SELECT * FROM pg_input_error_info('[{"attributes" : null, "dependency" : 4, "degree": 1.000}]', 'pg_dependencies');
+SELECT * FROM pg_input_error_info('[{"attributes" : [2,null], "dependency" : 4, "degree": 1.000}]', 'pg_dependencies');
+SELECT * FROM pg_input_error_info('[{"attributes" : [2,3], "dependency" : null, "degree": 1.000}]', 'pg_dependencies');
+SELECT * FROM pg_input_error_info('[{"attributes" : [2,"a"], "dependency" : 4, "degree": 1.000}]', 'pg_dependencies');
+SELECT * FROM pg_input_error_info('[{"attributes" : [2,3], "dependency" : "a", "degree": 1.000}]', 'pg_dependencies');
+SELECT * FROM pg_input_error_info('[{"attributes" : [2,3], "dependency" : [], "degree": 1.000}]', 'pg_dependencies');
+SELECT * FROM pg_input_error_info('[{"attributes" : [2,3], "dependency" : [null], "degree": 1.000}]', 'pg_dependencies');
+SELECT * FROM pg_input_error_info('[{"attributes" : [2,3], "dependency" : [1,null], "degree": 1.000}]', 'pg_dependencies');
+SELECT * FROM pg_input_error_info('[{"attributes" : 1, "dependency" : 4, "degree": 1.000}]', 'pg_dependencies');
+SELECT * FROM pg_input_error_info('[{"attributes" : "a", "dependency" : 4, "degree": 1.000}]', 'pg_dependencies');
+SELECT * FROM pg_input_error_info('[{"attributes" : [2,3], "dependency" : 4, "degree": NaN}]', 'pg_dependencies');
+
+SELECT '[{"attributes": [], "dependency": 2, "degree": 1}]' ::pg_dependencies;
+SELECT '[{"attributes" : {"a": 1}, "dependency" : 4, "degree": "1.2"}]'::pg_dependencies;
+SELECT * FROM pg_input_error_info('[{"attributes": [], "dependency": 2, "degree": 1}]', 'pg_dependencies');
+SELECT * FROM pg_input_error_info('[{"attributes" : {"a": 1}, "dependency" : 4, "degree": "1.2"}]', 'pg_dependencies');
+
+SELECT '[{"dependency" : 4, "degree": "1.2"}]'::pg_dependencies;
+SELECT '[{"attributes" : [1,2,3,4,5,6,7], "dependency" : 0, "degree": "1.2"}]'::pg_dependencies;
+SELECT '[{"attributes" : [1,2,3,4,5,6,7], "dependency" : -9, "degree": "1.2"}]'::pg_dependencies;
+SELECT '[{"attributes": [1,2], "dependency": 2, "degree": 1}]' ::pg_dependencies;
+SELECT '[{"attributes" : [1, {}], "dependency" : 1, "degree": "1.2"}]'::pg_dependencies;
+SELECT '[{"attributes" : [1,2], "dependency" : {}, "degree": 1.0}]'::pg_dependencies;
+SELECT '[{"attributes" : [1,2], "dependency" : 3, "degree": {}}]'::pg_dependencies;
+SELECT '[{"attributes" : [1,2], "dependency" : 1, "degree": "a"}]'::pg_dependencies;
+SELECT * FROM pg_input_error_info('[{"dependency" : 4, "degree": "1.2"}]', 'pg_dependencies');
+SELECT * FROM pg_input_error_info('[{"attributes" : [1,2,3,4,5,6,7], "dependency" : 0, "degree": "1.2"}]', 'pg_dependencies');
+SELECT * FROM pg_input_error_info('[{"attributes" : [1,2,3,4,5,6,7], "dependency" : -9, "degree": "1.2"}]', 'pg_dependencies');
+SELECT * FROM pg_input_error_info('[{"attributes": [1,2], "dependency": 2, "degree": 1}]' , 'pg_dependencies');
+SELECT * FROM pg_input_error_info('[{"attributes" : [1, {}], "dependency" : 1, "degree": "1.2"}]', 'pg_dependencies');
+SELECT * FROM pg_input_error_info('[{"attributes" : [1,2], "dependency" : {}, "degree": 1.0}]', 'pg_dependencies');
+SELECT * FROM pg_input_error_info('[{"attributes" : [1,2], "dependency" : 3, "degree": {}}]', 'pg_dependencies');
+SELECT * FROM pg_input_error_info('[{"attributes" : [1,2], "dependency" : 1, "degree": "a"}]', 'pg_dependencies');
+
+-- Funky degree values, which do not fail.
+SELECT '[{"attributes" : [2], "dependency" : 4, "degree": "NaN"}]'::pg_dependencies;
+SELECT '[{"attributes" : [2], "dependency" : 4, "degree": "-inf"}]'::pg_dependencies;
+SELECT '[{"attributes" : [2], "dependency" : 4, "degree": "inf"}]'::pg_dependencies;
+SELECT '[{"attributes" : [2], "dependency" : 4, "degree": "-inf"}]'::pg_dependencies::text::pg_dependencies;
+
+-- Duplicated keys
+SELECT '[{"attributes" : [2,3], "attributes": [1,2], "dependency" : 4, "degree": 1.000}]'::pg_dependencies;
+SELECT '[{"attributes" : [2,3], "dependency" : 4, "dependency": 4, "degree": 1.000}]'::pg_dependencies;
+SELECT '[{"attributes" : [2,3], "dependency": 4, "degree": 1.000, "degree": 1.000}]'::pg_dependencies;
+SELECT * FROM pg_input_error_info('[{"attributes" : [2,3], "attributes": [1,2], "dependency" : 4, "degree": 1.000}]', 'pg_dependencies');
+SELECT * FROM pg_input_error_info('[{"attributes" : [2,3], "dependency" : 4, "dependency": 4, "degree": 1.000}]', 'pg_dependencies');
+SELECT * FROM pg_input_error_info('[{"attributes" : [2,3], "dependency": 4, "degree": 1.000, "degree": 1.000}]', 'pg_dependencies');
+
+-- Invalid attnums
+SELECT '[{"attributes" : [0,2], "dependency" : 4, "degree": 0.500}]'::pg_dependencies;
+SELECT '[{"attributes" : [-7,-9], "dependency" : 4, "degree": 0.500}]'::pg_dependencies;
+SELECT * FROM pg_input_error_info('[{"attributes" : [0,2], "dependency" : 4, "degree": 0.500}]', 'pg_dependencies');
+SELECT * FROM pg_input_error_info('[{"attributes" : [-7,-9], "dependency" : 4, "degree": 0.500}]', 'pg_dependencies');
+
+-- Duplicated attributes
+SELECT '[{"attributes" : [2,2], "dependency" : 4, "degree": 0.500}]'::pg_dependencies;
+SELECT * FROM pg_input_error_info('[{"attributes" : [2,2], "dependency" : 4, "degree": 0.500}]', 'pg_dependencies');
+
+-- Duplicated attribute lists.
+SELECT '[{"attributes" : [2,3], "dependency" : 4, "degree": 1.000},
+ {"attributes" : [2,3], "dependency" : 4, "degree": 1.000}]'::pg_dependencies;
+SELECT * FROM pg_input_error_info('[{"attributes" : [2,3], "dependency" : 4, "degree": 1.000},
+ {"attributes" : [2,3], "dependency" : 4, "degree": 1.000}]', 'pg_dependencies');
+
+-- Valid inputs
+SELECT '[{"attributes" : [2,3], "dependency" : 4, "degree": 0.250},
+ {"attributes" : [2,-1], "dependency" : 4, "degree": 0.500},
+ {"attributes" : [2,3,-1], "dependency" : 4, "degree": 0.750},
+ {"attributes" : [2,3,-1,-2], "dependency" : 4, "degree": 1.000}]'::pg_dependencies;
+SELECT * FROM pg_input_error_info('[{"attributes" : [2,3], "dependency" : 4, "degree": 0.250},
+ {"attributes" : [2,-1], "dependency" : 4, "degree": 0.500},
+ {"attributes" : [2,3,-1], "dependency" : 4, "degree": 0.750},
+ {"attributes" : [2,3,-1,-2], "dependency" : 4, "degree": 1.000}]', 'pg_dependencies');
+-- Partially-covered attribute lists, possible as items with a degree of 0
+-- are discarded.
+SELECT '[{"attributes" : [2,3], "dependency" : 4, "degree": 1.000},
+ {"attributes" : [1,-1], "dependency" : 4, "degree": 1.000},
+ {"attributes" : [2,3,-1], "dependency" : 4, "degree": 1.000},
+ {"attributes" : [2,3,-1,-2], "dependency" : 4, "degree": 1.000}]'::pg_dependencies;