diff --git a/debian/changelog b/debian/changelog
index 26ff8df455b4f5582ecd5261b1edd946609b4a7b..19392079696601aaa9934437b1bf6e0288855269 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,9 @@
+postgresql-15-age (1.5.0~rc0-1) unstable; urgency=medium
+
+ * New upstream version 1.5.0~rc0.
+
+ -- Christoph Berg <myon@debian.org> Thu, 11 Jan 2024 11:18:41 +0100
+
postgresql-15-age (1.4.0~rc0-1) unstable; urgency=medium
* New upstream version.
diff --git a/debian/patches/big-endian b/debian/patches/big-endian
index 4918521b5ed5e27bff2b47bb3f47143b2b326b58..d4a719ed13a3aea79b3c6cf1e9996c564192f4c2 100644
--- a/debian/patches/big-endian
+++ b/debian/patches/big-endian
@@ -1,6 +1,6 @@
--- a/regress/sql/cypher_match.sql
+++ b/regress/sql/cypher_match.sql
-@@ -724,7 +724,7 @@ SELECT drop_graph('for_isEmpty', true);
+@@ -725,7 +725,7 @@ SELECT drop_graph('for_isEmpty', true);
SELECT * FROM cypher('cypher_match', $$
MATCH (u)
RETURN DISTINCT u.id
@@ -9,7 +9,7 @@
SELECT * FROM cypher('cypher_match', $$
CREATE (u:duplicate)-[:dup_edge {id:1 }]->(:other_v)
-@@ -743,7 +743,7 @@ $$) AS (i agtype);
+@@ -744,7 +744,7 @@ $$) AS (i agtype);
SELECT * FROM cypher('cypher_match', $$
MATCH p=(:duplicate)-[]-(:other_v)
RETURN DISTINCT p
@@ -20,7 +20,7 @@
-- Limit
--- a/regress/expected/cypher_match.out
+++ b/regress/expected/cypher_match.out
-@@ -1527,13 +1527,13 @@ NOTICE: graph "for_isEmpty" has been dr
+@@ -1520,13 +1520,13 @@ NOTICE: graph "for_isEmpty" has been dr
SELECT * FROM cypher('cypher_match', $$
MATCH (u)
RETURN DISTINCT u.id
@@ -36,7 +36,7 @@
(4 rows)
SELECT * FROM cypher('cypher_match', $$
-@@ -1563,7 +1563,7 @@ $$) AS (i agtype);
+@@ -1556,7 +1556,7 @@ $$) AS (i agtype);
SELECT * FROM cypher('cypher_match', $$
MATCH p=(:duplicate)-[]-(:other_v)
RETURN DISTINCT p
@@ -47,7 +47,7 @@
[{"id": 3377699720527873, "label": "duplicate", "properties": {}}::vertex, {"id": 3659174697238529, "label": "dup_edge", "end_id": 3940649673949185, "start_id": 3377699720527873, "properties": {"id": 1}}::edge, {"id": 3940649673949185, "label": "other_v", "properties": {}}::vertex]::path
--- /dev/null
+++ b/regress/expected/agtype_1.out
-@@ -0,0 +1,3201 @@
+@@ -0,0 +1,3916 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
@@ -264,6 +264,18 @@
+ 2.0::numeric
+(1 row)
+
++SELECT agtype_sub('[1, 2, 3]', '1');
++ agtype_sub
++------------
++ [1, 3]
++(1 row)
++
++SELECT agtype_sub('{"a": 1, "b": 2, "c": 3}', '"a"');
++ agtype_sub
++------------------
++ {"b": 2, "c": 3}
++(1 row)
++
+SELECT agtype_neg('-1');
+ agtype_neg
+------------
@@ -743,6 +755,521 @@
+(1 row)
+
+--
++-- Test operator - for extended functionality
++--
++SELECT '{"a":1 , "b":2, "c":3}'::agtype - '"a"';
++ ?column?
++------------------
++ {"b": 2, "c": 3}
++(1 row)
++
++SELECT '{"a":null , "b":2, "c":3}'::agtype - '"a"';
++ ?column?
++------------------
++ {"b": 2, "c": 3}
++(1 row)
++
++SELECT '{"a":1 , "b":2, "c":3}'::agtype - '"b"';
++ ?column?
++------------------
++ {"a": 1, "c": 3}
++(1 row)
++
++SELECT '{"a":1 , "b":2, "c":3}'::agtype - '"c"';
++ ?column?
++------------------
++ {"a": 1, "b": 2}
++(1 row)
++
++SELECT '{"a":1 , "b":2, "c":3}'::agtype - '"d"';
++ ?column?
++--------------------------
++ {"a": 1, "b": 2, "c": 3}
++(1 row)
++
++SELECT '{"a":1 , "b":2, "c":3}'::agtype - '""';
++ ?column?
++--------------------------
++ {"a": 1, "b": 2, "c": 3}
++(1 row)
++
++SELECT '{"a":1 , "b":2, "c":3}'::agtype - '"1"';
++ ?column?
++--------------------------
++ {"a": 1, "b": 2, "c": 3}
++(1 row)
++
++SELECT '{"a":1 , "b":2, "c":3, "1": 4}'::agtype - '"1"';
++ ?column?
++--------------------------
++ {"a": 1, "b": 2, "c": 3}
++(1 row)
++
++SELECT '{"a":1 , "b":2, "c":3}'::agtype - age_tostring('a');
++ ?column?
++------------------
++ {"b": 2, "c": 3}
++(1 row)
++
++SELECT '{"a":1 , "b":2, "c":3}'::agtype - age_tostring(1);
++ ?column?
++--------------------------
++ {"a": 1, "b": 2, "c": 3}
++(1 row)
++
++SELECT '{"a":1 , "b":2, "c":3, "1": 4}'::agtype - age_tostring(1);
++ ?column?
++--------------------------
++ {"a": 1, "b": 2, "c": 3}
++(1 row)
++
++SELECT '{}'::agtype - '"a"';
++ ?column?
++----------
++ {}
++(1 row)
++
++SELECT '["a","b","c"]'::agtype - 3;
++ ?column?
++-----------------
++ ["a", "b", "c"]
++(1 row)
++
++SELECT '["a","b","c"]'::agtype - 2;
++ ?column?
++------------
++ ["a", "b"]
++(1 row)
++
++SELECT '["a","b","c"]'::agtype - 1;
++ ?column?
++------------
++ ["a", "c"]
++(1 row)
++
++SELECT '["a","b","c"]'::agtype - 0;
++ ?column?
++------------
++ ["b", "c"]
++(1 row)
++
++SELECT '["a","b","c"]'::agtype - -1;
++ ?column?
++------------
++ ["a", "b"]
++(1 row)
++
++SELECT '["a","b","c"]'::agtype - -2;
++ ?column?
++------------
++ ["a", "c"]
++(1 row)
++
++SELECT '["a","b","c"]'::agtype - -3;
++ ?column?
++------------
++ ["b", "c"]
++(1 row)
++
++SELECT '["a","b","c"]'::agtype - -4;
++ ?column?
++-----------------
++ ["a", "b", "c"]
++(1 row)
++
++SELECT '["a","b","c"]'::agtype - '2';
++ ?column?
++------------
++ ["a", "b"]
++(1 row)
++
++SELECT '["a","b","c"]'::agtype - -(true::int);
++ ?column?
++------------
++ ["a", "b"]
++(1 row)
++
++SELECT '[]'::agtype - 1;
++ ?column?
++----------
++ []
++(1 row)
++
++SELECT '{"a":1 , "b":2, "c":3}'::agtype - '["b"]'::agtype;
++ ?column?
++------------------
++ {"a": 1, "c": 3}
++(1 row)
++
++SELECT '{"a":1 , "b":2, "c":3}'::agtype - '["c","b"]'::agtype;
++ ?column?
++----------
++ {"a": 1}
++(1 row)
++
++SELECT '{"a":1 , "b":2, "c":3}'::agtype - '[]'::agtype;
++ ?column?
++--------------------------
++ {"a": 1, "b": 2, "c": 3}
++(1 row)
++
++SELECT '["a","b","c"]'::agtype - '[]';
++ ?column?
++-----------------
++ ["a", "b", "c"]
++(1 row)
++
++SELECT '["a","b","c"]'::agtype - '[1]';
++ ?column?
++------------
++ ["a", "c"]
++(1 row)
++
++SELECT '[1, 2, 3, 4, 5, 6]'::agtype - '[9]';
++ ?column?
++--------------------
++ [1, 2, 3, 4, 5, 6]
++(1 row)
++
++SELECT '["a","b","c"]'::agtype - '[1, -1]';
++ ?column?
++----------
++ ["a"]
++(1 row)
++
++SELECT '["a","b","c"]'::agtype - '[1, -1, 3, 4]';
++ ?column?
++----------
++ ["a"]
++(1 row)
++
++SELECT '["a","b","c"]'::agtype - '[1, -1, 3, 4, 0]';
++ ?column?
++----------
++ []
++(1 row)
++
++SELECT '["a","b","c"]'::agtype - '[-1, 1, 3, 4, 1]';
++ ?column?
++----------
++ ["a"]
++(1 row)
++
++SELECT '["a","b","c"]'::agtype - '[-1, 1, 3, 4, 0]';
++ ?column?
++----------
++ []
++(1 row)
++
++SELECT '["a","b","c"]'::agtype - '[1, 1]';
++ ?column?
++------------
++ ["a", "c"]
++(1 row)
++
++SELECT '["a","b","c"]'::agtype - '[1, 1, 1]';
++ ?column?
++------------
++ ["a", "c"]
++(1 row)
++
++SELECT '["a","b","c"]'::agtype - '[1, 1, -1]';
++ ?column?
++----------
++ ["a"]
++(1 row)
++
++SELECT '["a","b","c"]'::agtype - '[1, 1, -1, -1]';
++ ?column?
++----------
++ ["a"]
++(1 row)
++
++SELECT '["a","b","c"]'::agtype - '[-2, -4, -5, -1]';
++ ?column?
++----------
++ ["a"]
++(1 row)
++
++SELECT '[1, 2, 3, 4, 5, 6]'::agtype - '[0, 4, 3, 2]';
++ ?column?
++----------
++ [2, 6]
++(1 row)
++
++SELECT '[1, 2, 3, 4, 5, 6]'::agtype - '[0, 4, 3, 2, -1]';
++ ?column?
++----------
++ [2]
++(1 row)
++
++SELECT '[1, 2, 3, 4, 5, 6]'::agtype - '[3, 3, 4, 4, 6, 8, 9]';
++ ?column?
++--------------
++ [1, 2, 3, 6]
++(1 row)
++
++SELECT '[1, 2, 3, 4, 5, 6]'::agtype - '[8, 9, -7, -6]';
++ ?column?
++-----------------
++ [2, 3, 4, 5, 6]
++(1 row)
++
++-- multiple sub operations
++SELECT '{"a":1 , "b":2, "c":3, "1": 4}'::agtype - age_tostring(1) - age_tostring(1);
++ ?column?
++--------------------------
++ {"a": 1, "b": 2, "c": 3}
++(1 row)
++
++SELECT '{"a":1 , "b":2, "c":3, "1": 4}'::agtype - age_tostring(1) - age_tostring('a');
++ ?column?
++------------------
++ {"b": 2, "c": 3}
++(1 row)
++
++SELECT '{"a":1 , "b":2, "c":3, "1": 4}'::agtype - age_tostring(1) - age_tostring('a') - age_tostring('e') - age_tostring('c');
++ ?column?
++----------
++ {"b": 2}
++(1 row)
++
++SELECT '{"a":1 , "b":2, "c":3}'::agtype - '["c","b"]' - '["a"]';
++ ?column?
++----------
++ {}
++(1 row)
++
++SELECT '{"a":1 , "b":2, "c":3}'::agtype - '["c","b"]' - '["e"]' - '["a"]';
++ ?column?
++----------
++ {}
++(1 row)
++
++SELECT '{"a":1 , "b":2, "c":3}'::agtype - '["c","b"]' - '[]';
++ ?column?
++----------
++ {"a": 1}
++(1 row)
++
++SELECT '["a","b","c"]'::agtype - '[-1]' - '[-1]';
++ ?column?
++----------
++ ["a"]
++(1 row)
++
++SELECT '["a","b","c"]'::agtype - '[-1]' - '[-2]' - '[-2]';
++ ?column?
++----------
++ ["b"]
++(1 row)
++
++SELECT '["a","b","c"]'::agtype - '[-1]' - '[]' - '[-2]';
++ ?column?
++----------
++ ["b"]
++(1 row)
++
++SELECT '["a","b","c"]'::agtype - '[-1]' - '[4]' - '[-2]';
++ ?column?
++----------
++ ["b"]
++(1 row)
++
++SELECT '[1, 2, 3, 4, 5, 6]'::agtype - '[8, 9, -7, -6]' - '1';
++ ?column?
++--------------
++ [2, 4, 5, 6]
++(1 row)
++
++SELECT '[1, 2, 3, 4, 5, 6]'::agtype - '[8, 9, -7, -6]' - '[1, 0]';
++ ?column?
++-----------
++ [4, 5, 6]
++(1 row)
++
++SELECT '[1, 2, 3, 4, 5, 6]'::agtype - '[8, 9, -7, -6]' - 3 - '[]';
++ ?column?
++--------------
++ [2, 3, 4, 6]
++(1 row)
++
++-- errors out
++SELECT '["a","b","c"]'::agtype - '["1"]';
++ERROR: expected agtype integer, not agtype string
++SELECT '["a","b","c"]'::agtype - '[null]';
++ERROR: expected agtype integer, not agtype NULL
++SELECT '["a","b","c"]'::agtype - '"1"';
++ERROR: expected agtype integer, not agtype string
++SELECT '["a","b","c"]'::agtype - 'null';
++ERROR: expected agtype integer, not agtype NULL
++SELECT '["a","b","c"]'::agtype - '[-1]' - '["-2"]' - '[-2]';
++ERROR: expected agtype integer, not agtype string
++SELECT '{"a":1 , "b":2, "c":3}'::agtype - '[1]';
++ERROR: expected agtype string, not agtype integer
++SELECT '{"a":1 , "b":2, "c":3}'::agtype - '[null]';
++ERROR: expected agtype string, not agtype NULL
++SELECT '{"a":1 , "b":2, "c":3}'::agtype - '1';
++ERROR: expected agtype string, not agtype integer
++SELECT '{"a":1 , "b":2, "c":3}'::agtype - 'null';
++ERROR: expected agtype string, not agtype NULL
++SELECT '{"a":1 , "b":2, "c":3}'::agtype - '["c","b"]' - '[1]' - '["a"]';
++ERROR: expected agtype string, not agtype integer
++SELECT 'null'::agtype - '1';
++ERROR: Invalid input parameter types for agtype_sub
++SELECT 'null'::agtype - '[1]';
++ERROR: must be object or array, not a scalar value
++SELECT '{"id": 1125899906842625, "label": "Vertex", "properties": {"a": "xyz", "b": true, "c": -19.888, "e": {"f": "abcdef", "g": {}, "h": [[], {}]}, "i": {"j": 199, "k": {"l": "mnopq"}}}}::vertex'::agtype - '"a"';
++ERROR: Invalid input parameter types for agtype_sub
++SELECT '{"id": 1125899906842625, "label": "Vertex", "properties": {"a": "xyz", "b": true, "c": -19.888, "e": {"f": "abcdef", "g": {}, "h": [[], {}]}, "i": {"j": 199, "k": {"l": "mnopq"}}}}::vertex'::agtype - '["a"]';
++ERROR: must be object or array, not a scalar value
++SELECT '{"id": 1125899906842625, "label": "Vertex", "properties": {"a": "xyz", "b": true, "c": -19.888, "e": {"f": "abcdef", "g": {}, "h": [[], {}]}, "i": {"j": 199, "k": {"l": "mnopq"}}}}::vertex'::agtype - '[1]';
++ERROR: must be object or array, not a scalar value
++SELECT '{"id": 1688849860263951, "label": "e_var", "end_id": 281474976710664, "start_id": 281474976710663, "properties": {"id": 0}}::edge'::agtype - '{"id": 1688849860263951, "label": "e_var", "end_id": 281474976710664, "start_id": 281474976710663, "properties": {"id": 0}}::edge'::agtype;
++ERROR: Invalid input parameter types for agtype_sub
++SELECT '{"id": 1125899906842625, "label": "Vertex", "properties": {"a": "xyz", "b": true, "c": -19.888, "e": {"f": "abcdef", "g": {}, "h": [[], {}]}, "i": {"j": 199, "k": {"l": "mnopq"}}}}::vertex'::agtype - '[]';
++ERROR: must be object or array, not a scalar value
++--
++-- Test operator + for extended functionality
++--
++SELECT '[1, 2, 3]'::agtype + '[4, 5]'::agtype;
++ ?column?
++-----------------
++ [1, 2, 3, 4, 5]
++(1 row)
++
++SELECT '[1, 2, true, "string", 1.4::numeric]'::agtype + '[4.5, -5::numeric, {"a": true}]'::agtype;
++ ?column?
++---------------------------------------------------------------------
++ [1, 2, true, "string", 1.4::numeric, 4.5, -5::numeric, {"a": true}]
++(1 row)
++
++SELECT '[{"a":1 , "b":2, "c":3}]'::agtype + '[]';
++ ?column?
++----------------------------
++ [{"a": 1, "b": 2, "c": 3}]
++(1 row)
++
++SELECT '[{"a":1 , "b":2, "c":3}]'::agtype + '[{"d": 4}]';
++ ?column?
++--------------------------------------
++ [{"a": 1, "b": 2, "c": 3}, {"d": 4}]
++(1 row)
++
++SELECT '{"a":1 , "b":2, "c":3}'::agtype + '["b", 2, {"d": 4}]'::agtype;
++ ?column?
++----------------------------------------------
++ [{"a": 1, "b": 2, "c": 3}, "b", 2, {"d": 4}]
++(1 row)
++
++SELECT '["b", 2, {"d": 4}]'::agtype + '{"a":1 , "b":2, "c":3}'::agtype;
++ ?column?
++----------------------------------------------
++ ["b", 2, {"d": 4}, {"a": 1, "b": 2, "c": 3}]
++(1 row)
++
++SELECT '{"id": 1125899906842625, "label": "Vertex", "properties": {"a": "xyz", "b": true, "c": -19.888, "e": {"f": "abcdef", "g": {}, "h": [[], {}]}, "i": {"j": 199, "k": {"l": "mnopq"}}}}::vertex'::agtype + '[1]';
++ ?column?
++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
++ [{"id": 1125899906842625, "label": "Vertex", "properties": {"a": "xyz", "b": true, "c": -19.888, "e": {"f": "abcdef", "g": {}, "h": [[], {}]}, "i": {"j": 199, "k": {"l": "mnopq"}}}}::vertex, 1]
++(1 row)
++
++SELECT '{"id": 1125899906842625, "label": "Vertex", "properties": {"a": "xyz", "b": true, "c": -19.888}}::vertex'::agtype + '[1, "e", true]';
++ ?column?
++--------------------------------------------------------------------------------------------------------------------------
++ [{"id": 1125899906842625, "label": "Vertex", "properties": {"a": "xyz", "b": true, "c": -19.888}}::vertex, 1, "e", true]
++(1 row)
++
++SELECT '[]'::agtype + '{}';
++ ?column?
++----------
++ [{}]
++(1 row)
++
++SELECT '[]'::agtype + '{"a": 1}';
++ ?column?
++------------
++ [{"a": 1}]
++(1 row)
++
++SELECT '{"a":1 , "b":2, "c":3}'::agtype + '{"b": 2}';
++ ?column?
++--------------------------
++ {"a": 1, "b": 2, "c": 3}
++(1 row)
++
++SELECT '{"a":1 , "b":2, "c":3}'::agtype + '{"": 2}';
++ ?column?
++---------------------------------
++ {"": 2, "a": 1, "b": 2, "c": 3}
++(1 row)
++
++SELECT '{"a":1 , "b":2, "c":3}'::agtype + '{"a":1 , "b":2, "c":3}';
++ ?column?
++--------------------------
++ {"a": 1, "b": 2, "c": 3}
++(1 row)
++
++SELECT '{"a":1 , "b":2, "c":3}'::agtype + '{}';
++ ?column?
++--------------------------
++ {"a": 1, "b": 2, "c": 3}
++(1 row)
++
++SELECT '{}'::agtype + '{}';
++ ?column?
++----------
++ {}
++(1 row)
++
++SELECT '1'::agtype + '[{"a":1 , "b":2, "c":3}]'::agtype;
++ ?column?
++-------------------------------
++ [1, {"a": 1, "b": 2, "c": 3}]
++(1 row)
++
++SELECT '{"id": 1125899906842625, "label": "Vertex", "properties": {"a": "xyz", "b": true, "c": -19.888}}::vertex'::agtype + '{"d": 4}';
++ ?column?
++----------------------------------------------------------------------------------------------------------------------
++ [{"id": 1125899906842625, "label": "Vertex", "properties": {"a": "xyz", "b": true, "c": -19.888}}::vertex, {"d": 4}]
++(1 row)
++
++SELECT '{"id": 1125899906842625, "label": "Vertex", "properties": {"a": "xyz", "b": true, "c": -19.888}}::vertex'::agtype + '{"id": 1125899906842625, "label": "Vertex", "properties": {"a": "xyz", "b": true, "c": -19.888}}::vertex'::agtype;
++ ?column?
++----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
++ [{"id": 1125899906842625, "label": "Vertex", "properties": {"a": "xyz", "b": true, "c": -19.888}}::vertex, {"id": 1125899906842625, "label": "Vertex", "properties": {"a": "xyz", "b": true, "c": -19.888}}::vertex]
++(1 row)
++
++SELECT '[{"id": 1688849860263938, "label": "v2", "properties": {"id": "middle"}}::vertex, {"id": 1970324836974594, "label": "e2", "end_id": 1688849860263937, "start_id": 1688849860263938, "properties": {}}::edge, {"id": 1688849860263937, "label": "v2", "properties": {"id": "initial"}}::vertex]::path'::agtype + ' [{"id": 1688849860263938, "label": "v2", "properties": {"id": "middle"}}::vertex, {"id": 1970324836974594, "label": "e2", "end_id": 1688849860263937, "start_id": 1688849860263938, "properties": {}}::edge, {"id": 1688849860263937, "label": "v2", "properties": {"id": "initial"}}::vertex]::path'::agtype;
++ ?column?
++--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
++ [[{"id": 1688849860263938, "label": "v2", "properties": {"id": "middle"}}::vertex, {"id": 1970324836974594, "label": "e2", "end_id": 1688849860263937, "start_id": 1688849860263938, "properties": {}}::edge, {"id": 1688849860263937, "label": "v2", "properties": {"id": "initial"}}::vertex]::path, [{"id": 1688849860263938, "label": "v2", "properties": {"id": "middle"}}::vertex, {"id": 1970324836974594, "label": "e2", "end_id": 1688849860263937, "start_id": 1688849860263938, "properties": {}}::edge, {"id": 1688849860263937, "label": "v2", "properties": {"id": "initial"}}::vertex]::path]
++(1 row)
++
++SELECT '[{"id": 1688849860263938, "label": "v2", "properties": {"id": "middle"}}::vertex, {"id": 1970324836974594, "label": "e2", "end_id": 1688849860263937, "start_id": 1688849860263938, "properties": {}}::edge, {"id": 1688849860263937, "label": "v2", "properties": {"id": "initial"}}::vertex]::path'::agtype + '{"id": 1125899906842625, "label": "Vertex", "properties": {"a": "xyz", "b": true, "c": -19.888, "e": {"f": "abcdef", "g": {}, "h": [[], {}]}, "i": {"j": 199, "k": {"l": "mnopq"}}}}::vertex'::agtype;
++ ?column?
++------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
++ [[{"id": 1688849860263938, "label": "v2", "properties": {"id": "middle"}}::vertex, {"id": 1970324836974594, "label": "e2", "end_id": 1688849860263937, "start_id": 1688849860263938, "properties": {}}::edge, {"id": 1688849860263937, "label": "v2", "properties": {"id": "initial"}}::vertex]::path, {"id": 1125899906842625, "label": "Vertex", "properties": {"a": "xyz", "b": true, "c": -19.888, "e": {"f": "abcdef", "g": {}, "h": [[], {}]}, "i": {"j": 199, "k": {"l": "mnopq"}}}}::vertex]
++(1 row)
++
++SELECT '{"id": 1688849860263951, "label": "e_var", "end_id": 281474976710664, "start_id": 281474976710663, "properties": {"id": 0}}::edge'::agtype + '{"id": 1688849860263951, "label": "e_var", "end_id": 281474976710664, "start_id": 281474976710663, "properties": {"id": 0}}::edge'::agtype;
++ ?column?
++------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
++ [{"id": 1688849860263951, "label": "e_var", "end_id": 281474976710664, "start_id": 281474976710663, "properties": {"id": 0}}::edge, {"id": 1688849860263951, "label": "e_var", "end_id": 281474976710664, "start_id": 281474976710663, "properties": {"id": 0}}::edge]
++(1 row)
++
++SELECT '{"id": 1688849860263951, "label": "e_var", "end_id": 281474976710664, "start_id": 281474976710663, "properties": {"id": 0}}::edge'::agtype + '{"id": 1125899906842625, "label": "Vertex", "properties": {"a": "xyz", "b": true, "c": -19.888}}::vertex'::agtype;
++ ?column?
++-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
++ [{"id": 1688849860263951, "label": "e_var", "end_id": 281474976710664, "start_id": 281474976710663, "properties": {"id": 0}}::edge, {"id": 1125899906842625, "label": "Vertex", "properties": {"a": "xyz", "b": true, "c": -19.888}}::vertex]
++(1 row)
++
++-- errors out
++SELECT '1'::agtype + '{"a":1 , "b":2, "c":3}'::agtype;
++ERROR: invalid left operand for agtype concatenation
++SELECT '{"a":1 , "b":2, "c":3}'::agtype + '"string"';
++ERROR: invalid right operand for agtype concatenation
++--
+-- Test overloaded agytype any operators +, -, *, /, %
+--
+SELECT '3'::agtype + 3;
@@ -2267,29 +2794,112 @@
+ 0
+(1 row)
+
-+--
-+-- Test boolean to integer cast
-+--
-+SELECT agtype_to_int4(agtype_in('true'));
-+ agtype_to_int4
++-- should return SQL NULL
++SELECT agtype_to_int8(agtype_in('null'));
++ agtype_to_int8
+----------------
-+ 1
++
+(1 row)
+
-+SELECT agtype_to_int4(agtype_in('false'));
-+ agtype_to_int4
++SELECT agtype_to_int8(NULL);
++ agtype_to_int8
++----------------
++
++(1 row)
++
++-- non agtype input
++SELECT agtype_to_int8(1);
++ agtype_to_int8
++----------------
++ 1
++(1 row)
++
++SELECT agtype_to_int8(3.14);
++ agtype_to_int8
++----------------
++ 3
++(1 row)
++
++SELECT agtype_to_int8(3.14::numeric);
++ agtype_to_int8
++----------------
++ 3
++(1 row)
++
++SELECT agtype_to_int8('3');
++ agtype_to_int8
++----------------
++ 3
++(1 row)
++
++SELECT agtype_to_int8(true);
++ agtype_to_int8
++----------------
++ 1
++(1 row)
++
++SELECT agtype_to_int8(false);
++ agtype_to_int8
+----------------
+ 0
+(1 row)
+
-+SELECT agtype_to_int4(agtype_in('null'));
++SELECT agtype_to_int8('3.14');
++ agtype_to_int8
++----------------
++ 3
++(1 row)
++
++SELECT agtype_to_int8('true');
++ agtype_to_int8
++----------------
++ 1
++(1 row)
++
++SELECT agtype_to_int8('false');
++ agtype_to_int8
++----------------
++ 0
++(1 row)
++
++-- should fail
++SELECT agtype_to_int8('neither');
++ERROR: invalid input syntax for type agtype
++DETAIL: Expected agtype value, but found "neither".
++CONTEXT: agtype data, line 1: neither
++SELECT agtype_to_int8('NaN');
++ERROR: bigint out of range
++SELECT agtype_to_int8('Inf');
++ERROR: bigint out of range
++SELECT agtype_to_int8(NaN);
++ERROR: column "nan" does not exist
++LINE 1: SELECT agtype_to_int8(NaN);
++ ^
++SELECT agtype_to_int8(Inf);
++ERROR: column "inf" does not exist
++LINE 1: SELECT agtype_to_int8(Inf);
++ ^
++SELECT agtype_to_int8('{"name":"John"}');
++ERROR: invalid agtype string to int8 type: 17
++SELECT agtype_to_int8('[1,2,3]');
++ERROR: invalid agtype string to int8 type: 16
++--
++-- Test boolean to integer cast
++--
++SELECT agtype_to_int4(agtype_in('true'));
+ agtype_to_int4
+----------------
-+
++ 1
++(1 row)
++
++SELECT agtype_to_int4(agtype_in('false'));
++ agtype_to_int4
++----------------
++ 0
+(1 row)
+
+--
-+-- Test agtype to integer cast
++-- Test agtype to integer4 cast
+--
+SELECT agtype_to_int4(agtype_in('1'));
+ agtype_to_int4
@@ -2311,11 +2921,236 @@
+
+-- These should all fail
+SELECT agtype_to_int4(agtype_in('"string"'));
-+ERROR: invalid input syntax for type integer: "string"
++ERROR: invalid input syntax for type agtype
++DETAIL: Expected agtype value, but found "string".
++CONTEXT: agtype data, line 1: string
+SELECT agtype_to_int4(agtype_in('[1, 2, 3]'));
+ERROR: cannot cast agtype array to type int
+SELECT agtype_to_int4(agtype_in('{"int":1}'));
+ERROR: cannot cast agtype object to type int
++-- should return SQL NULL
++SELECT agtype_to_int4(agtype_in('null'));
++ agtype_to_int4
++----------------
++
++(1 row)
++
++SELECT agtype_to_int4(NULL);
++ agtype_to_int4
++----------------
++
++(1 row)
++
++-- non agtype input
++SELECT agtype_to_int4(1);
++ agtype_to_int4
++----------------
++ 1
++(1 row)
++
++SELECT agtype_to_int4(3.14);
++ agtype_to_int4
++----------------
++ 3
++(1 row)
++
++SELECT agtype_to_int4(3.14::numeric);
++ agtype_to_int4
++----------------
++ 3
++(1 row)
++
++SELECT agtype_to_int4('3');
++ agtype_to_int4
++----------------
++ 3
++(1 row)
++
++SELECT agtype_to_int4(true);
++ agtype_to_int4
++----------------
++ 1
++(1 row)
++
++SELECT agtype_to_int4(false);
++ agtype_to_int4
++----------------
++ 0
++(1 row)
++
++SELECT agtype_to_int4('3.14');
++ agtype_to_int4
++----------------
++ 3
++(1 row)
++
++SELECT agtype_to_int4('true');
++ agtype_to_int4
++----------------
++ 1
++(1 row)
++
++SELECT agtype_to_int4('false');
++ agtype_to_int4
++----------------
++ 0
++(1 row)
++
++-- should error
++SELECT agtype_to_int4('neither');
++ERROR: invalid input syntax for type agtype
++DETAIL: Expected agtype value, but found "neither".
++CONTEXT: agtype data, line 1: neither
++SELECT agtype_to_int4('NaN');
++ERROR: integer out of range
++SELECT agtype_to_int4('Inf');
++ERROR: integer out of range
++SELECT agtype_to_int4(NaN);
++ERROR: column "nan" does not exist
++LINE 1: SELECT agtype_to_int4(NaN);
++ ^
++SELECT agtype_to_int4(Inf);
++ERROR: column "inf" does not exist
++LINE 1: SELECT agtype_to_int4(Inf);
++ ^
++SELECT agtype_to_int4('{"name":"John"}');
++ERROR: invalid agtype string to int4 type: 17
++SELECT agtype_to_int4('[1,2,3]');
++ERROR: invalid agtype string to int4 type: 16
++--
++-- Test boolean to integer2 cast
++--
++SELECT agtype_to_int2(agtype_in('true'));
++ agtype_to_int2
++----------------
++ 1
++(1 row)
++
++SELECT agtype_to_int2(agtype_in('false'));
++ agtype_to_int2
++----------------
++ 0
++(1 row)
++
++--
++-- Test agtype to integer2 cast
++--
++SELECT agtype_to_int2(agtype_in('1'));
++ agtype_to_int2
++----------------
++ 1
++(1 row)
++
++SELECT agtype_to_int2(agtype_in('1.45'));
++ agtype_to_int2
++----------------
++ 1
++(1 row)
++
++SELECT agtype_to_int2(agtype_in('1.444::numeric'));
++ agtype_to_int2
++----------------
++ 1
++(1 row)
++
++-- These should all fail
++SELECT agtype_to_int2(agtype_in('"string"'));
++ERROR: invalid input syntax for type agtype
++DETAIL: Expected agtype value, but found "string".
++CONTEXT: agtype data, line 1: string
++SELECT agtype_to_int2(agtype_in('[1, 2, 3]'));
++ERROR: cannot cast agtype array to type int
++SELECT agtype_to_int2(agtype_in('{"int":1}'));
++ERROR: cannot cast agtype object to type int
++-- should return SQL NULL
++SELECT agtype_to_int2(agtype_in('null'));
++ agtype_to_int2
++----------------
++
++(1 row)
++
++SELECT agtype_to_int2(NULL);
++ agtype_to_int2
++----------------
++
++(1 row)
++
++-- non agtype input
++SELECT agtype_to_int2(1);
++ agtype_to_int2
++----------------
++ 1
++(1 row)
++
++SELECT agtype_to_int2(3.14);
++ agtype_to_int2
++----------------
++ 3
++(1 row)
++
++SELECT agtype_to_int2(3.14::numeric);
++ agtype_to_int2
++----------------
++ 3
++(1 row)
++
++SELECT agtype_to_int2('3');
++ agtype_to_int2
++----------------
++ 3
++(1 row)
++
++SELECT agtype_to_int2(true);
++ agtype_to_int2
++----------------
++ 1
++(1 row)
++
++SELECT agtype_to_int2(false);
++ agtype_to_int2
++----------------
++ 0
++(1 row)
++
++SELECT agtype_to_int2('3.14');
++ agtype_to_int2
++----------------
++ 3
++(1 row)
++
++SELECT agtype_to_int2('true');
++ agtype_to_int2
++----------------
++ 1
++(1 row)
++
++SELECT agtype_to_int2('false');
++ agtype_to_int2
++----------------
++ 0
++(1 row)
++
++-- should error
++SELECT agtype_to_int2('neither');
++ERROR: invalid input syntax for type agtype
++DETAIL: Expected agtype value, but found "neither".
++CONTEXT: agtype data, line 1: neither
++SELECT agtype_to_int2('NaN');
++ERROR: smallint out of range
++SELECT agtype_to_int2('Inf');
++ERROR: smallint out of range
++SELECT agtype_to_int2(NaN);
++ERROR: column "nan" does not exist
++LINE 1: SELECT agtype_to_int2(NaN);
++ ^
++SELECT agtype_to_int2(Inf);
++ERROR: column "inf" does not exist
++LINE 1: SELECT agtype_to_int2(Inf);
++ ^
++SELECT agtype_to_int2('{"name":"John"}');
++ERROR: invalid agtype string to int2 type: 17
++SELECT agtype_to_int2('[1,2,3]');
++ERROR: invalid agtype string to int2 type: 16
+--
+-- Test agtype to int[]
+--
@@ -2337,6 +3172,18 @@
+ {6,7,4}
+(1 row)
+
++-- should error
++SELECT agtype_to_int4_array(bool('true'));
++ERROR: argument must resolve to agtype
++SELECT agtype_to_int4_array((1,2,3,4,5));
++ERROR: argument must resolve to agtype
++-- should return SQL NULL
++SELECT agtype_to_int4_array(NULL);
++ agtype_to_int4_array
++----------------------
++
++(1 row)
++
+--
+-- Map Literal
+--
@@ -2401,66 +3248,6 @@
+ERROR: AGTV_INTEGER is not a valid key type
+SELECT agtype_access_operator('{"bool":false, "int":3, "float":3.14}', '2.0');
+ERROR: AGTV_FLOAT is not a valid key type
-+SELECT i, pg_typeof(i) FROM (SELECT '{"bool":true, "array":[1,3,{"bool":false, "int":3, "float":3.14},7], "float":3.14}'::agtype->'array'->2->'float' as i) a;
-+ i | pg_typeof
-+------+-----------
-+ 3.14 | agtype
-+(1 row)
-+
-+SELECT i, pg_typeof(i) FROM (SELECT '{"bool":true, "array":[1,3,{"bool":false, "int":3, "float":3.14},7], "float":3.14}'::agtype->'array'->2->>'float' as i) a;
-+ i | pg_typeof
-+------+-----------
-+ 3.14 | text
-+(1 row)
-+
-+SELECT i, pg_typeof(i) FROM (SELECT '{}'::agtype->'array' as i) a;
-+ i | pg_typeof
-+---+-----------
-+ | agtype
-+(1 row)
-+
-+SELECT i, pg_typeof(i) FROM (SELECT '[]'::agtype->0 as i) a;
-+ i | pg_typeof
-+---+-----------
-+ | agtype
-+(1 row)
-+
-+SELECT i, pg_typeof(i) FROM (SELECT '[0, 1]'::agtype->2 as i) a;
-+ i | pg_typeof
-+---+-----------
-+ | agtype
-+(1 row)
-+
-+SELECT i, pg_typeof(i) FROM (SELECT '[0, 1]'::agtype->3 as i) a;
-+ i | pg_typeof
-+---+-----------
-+ | agtype
-+(1 row)
-+
-+SELECT i, pg_typeof(i) FROM (SELECT '{"bool":false, "int":3, "float":3.14}'::agtype->'true' as i) a;
-+ i | pg_typeof
-+---+-----------
-+ | agtype
-+(1 row)
-+
-+SELECT i, pg_typeof(i) FROM (SELECT '{"bool":false, "int":3, "float":3.14}'::agtype->2 as i) a;
-+ i | pg_typeof
-+---+-----------
-+ | agtype
-+(1 row)
-+
-+SELECT i, pg_typeof(i) FROM (SELECT '{"bool":false, "int":3, "float":3.14}'::agtype->'true'->2 as i) a;
-+ i | pg_typeof
-+---+-----------
-+ | agtype
-+(1 row)
-+
-+SELECT i, pg_typeof(i) FROM (SELECT '{"bool":false, "int":3, "float":3.14}'::agtype->'true'->>2 as i) a;
-+ i | pg_typeof
-+---+-----------
-+ | text
-+(1 row)
-+
+-- Test duplicate keys and null value
+-- expected: only the latest key, among duplicates, will be kept; and null will be removed
+SELECT * FROM create_graph('agtype_null_duplicate_test');
@@ -2788,102 +3575,6 @@
+
+(1 row)
+
-+SELECT agtype_contains('{"id": 1}','{"id": 1}');
-+ agtype_contains
-+-----------------
-+ t
-+(1 row)
-+
-+SELECT agtype_contains('{"id": 1}','{"id": 2}');
-+ agtype_contains
-+-----------------
-+ f
-+(1 row)
-+
-+SELECT '{"id": 1}'::agtype @> '{"id": 1}';
-+ ?column?
-+----------
-+ t
-+(1 row)
-+
-+SELECT '{"id": 1}'::agtype @> '{"id": 2}';
-+ ?column?
-+----------
-+ f
-+(1 row)
-+
-+SELECT agtype_exists('{"id": 1}','id');
-+ agtype_exists
-+---------------
-+ t
-+(1 row)
-+
-+SELECT agtype_exists('{"id": 1}','not_id');
-+ agtype_exists
-+---------------
-+ f
-+(1 row)
-+
-+SELECT '{"id": 1}'::agtype ? 'id';
-+ ?column?
-+----------
-+ t
-+(1 row)
-+
-+SELECT '{"id": 1}'::agtype ? 'not_id';
-+ ?column?
-+----------
-+ f
-+(1 row)
-+
-+SELECT agtype_exists_any('{"id": 1}', array['id']);
-+ agtype_exists_any
-+-------------------
-+ t
-+(1 row)
-+
-+SELECT agtype_exists_any('{"id": 1}', array['not_id']);
-+ agtype_exists_any
-+-------------------
-+ f
-+(1 row)
-+
-+SELECT '{"id": 1}'::agtype ?| array['id'];
-+ ?column?
-+----------
-+ t
-+(1 row)
-+
-+SELECT '{"id": 1}'::agtype ?| array['not_id'];
-+ ?column?
-+----------
-+ f
-+(1 row)
-+
-+SELECT agtype_exists_all('{"id": 1}', array['id']);
-+ agtype_exists_all
-+-------------------
-+ t
-+(1 row)
-+
-+SELECT agtype_exists_all('{"id": 1}', array['not_id']);
-+ agtype_exists_all
-+-------------------
-+ f
-+(1 row)
-+
-+SELECT '{"id": 1}'::agtype ?& array['id'];
-+ ?column?
-+----------
-+ t
-+(1 row)
-+
-+SELECT '{"id": 1}'::agtype ?& array['not_id'];
-+ ?column?
-+----------
-+ f
-+(1 row)
-+
+--
+-- Test STARTS WITH, ENDS WITH, and CONTAINS
+--
@@ -3242,6 +3933,30 @@
+ -1
+(1 row)
+
++--Int2 to Agtype in agtype_volatile_wrapper
++SELECT ag_catalog.agtype_volatile_wrapper(1::int2);
++ agtype_volatile_wrapper
++-------------------------
++ 1
++(1 row)
++
++SELECT ag_catalog.agtype_volatile_wrapper(32767::int2);
++ agtype_volatile_wrapper
++-------------------------
++ 32767
++(1 row)
++
++SELECT ag_catalog.agtype_volatile_wrapper(-32767::int2);
++ agtype_volatile_wrapper
++-------------------------
++ -32767
++(1 row)
++
++-- These should fail
++SELECT ag_catalog.agtype_volatile_wrapper(32768::int2);
++ERROR: smallint out of range
++SELECT ag_catalog.agtype_volatile_wrapper(-32768::int2);
++ERROR: smallint out of range
+--
+-- Cleanup
+--
diff --git a/debian/patches/extra-instance-args b/debian/patches/extra-instance-args
index ff4845f858c74ce74eea416abcddbf43f5f2f020..dc6664ab79e2e6c59742c019a24718e2c1c1c0ba 100644
--- a/debian/patches/extra-instance-args
+++ b/debian/patches/extra-instance-args
@@ -1,12 +1,12 @@
--- a/Makefile
+++ b/Makefile
-@@ -104,6 +104,9 @@ REGRESS = scan \
+@@ -114,6 +114,9 @@ REGRESS = scan \
srcdir=`pwd`
ag_regress_dir = $(srcdir)/regress
+# Set extension_destdir/dynamic_library_path
+# Set max_parallel_workers to suppress a "CONTEXT: parallel worker" in regression tests
+export PGOPTIONS = -cextension_destdir=$(CURDIR)/debian/postgresql-15-age -cdynamic_library_path=$(CURDIR)/debian/postgresql-15-age/usr/lib/postgresql/15/lib:/usr/lib/postgresql/15/lib -cmax_parallel_workers=0
- REGRESS_OPTS = --load-extension=age --inputdir=$(ag_regress_dir) --outputdir=$(ag_regress_dir) --temp-instance=$(ag_regress_dir)/instance --port=61958 --encoding=UTF-8
+ REGRESS_OPTS = --load-extension=age --inputdir=$(ag_regress_dir) --outputdir=$(ag_regress_dir) --temp-instance=$(ag_regress_dir)/instance --port=61958 --encoding=UTF-8 --temp-config $(ag_regress_dir)/age_regression.conf
ag_regress_out = instance/ log/ results/ regression.*