Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implemented age_tail function #1281

Merged
merged 1 commit into from
Oct 16, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions age--1.4.0.sql
Original file line number Diff line number Diff line change
Expand Up @@ -3562,6 +3562,14 @@ RETURNS NULL ON NULL INPUT
PARALLEL SAFE
AS 'MODULE_PATHNAME';

CREATE FUNCTION ag_catalog.age_tail(variadic "any")
RETURNS agtype
LANGUAGE c
IMMUTABLE
RETURNS NULL ON NULL INPUT
PARALLEL SAFE
AS 'MODULE_PATHNAME';

CREATE FUNCTION ag_catalog.age_properties(agtype)
RETURNS agtype
LANGUAGE c
Expand Down
39 changes: 39 additions & 0 deletions regress/expected/expr.out
Original file line number Diff line number Diff line change
Expand Up @@ -6709,6 +6709,45 @@ SELECT * from cypher('list', $$RETURN range(0, null, -3)$$) as (range agtype);
ERROR: range(): neither start or end can be NULL
SELECT * from cypher('list', $$RETURN range(0, -10.0, -3.0)$$) as (range agtype);
ERROR: range() unsupported argument type
-- tail()
-- should return the last elements of the list
SELECT * FROM cypher('list', $$ RETURN tail([1,2,3,4,5]) $$) AS (tail agtype);
tail
--------------
[2, 3, 4, 5]
(1 row)

SELECT * FROM cypher('list', $$ RETURN tail(["a","b","c","d","e"]) $$) AS (tail agtype);
tail
----------------------
["b", "c", "d", "e"]
(1 row)

-- should return null
SELECT * FROM cypher('list', $$ RETURN tail([1]) $$) AS (tail agtype);
tail
------

(1 row)

SELECT * FROM cypher('list', $$ RETURN tail([]) $$) AS (tail agtype);
tail
------

(1 row)

-- should throw errors
SELECT * FROM cypher('list', $$ RETURN tail(123) $$) AS (tail agtype);
ERROR: tail() argument must resolve to a list or null
SELECT * FROM cypher('list', $$ RETURN tail(abc) $$) AS (tail agtype);
ERROR: could not find rte for abc
LINE 1: SELECT * FROM cypher('list', $$ RETURN tail(abc) $$) AS (tai...
^
SELECT * FROM cypher('list', $$ RETURN tail() $$) AS (tail agtype);
ERROR: function ag_catalog.age_tail() does not exist
LINE 1: SELECT * FROM cypher('list', $$ RETURN tail() $$) AS (tail a...
^
HINT: No function matches the given name and argument types. You might need to add explicit type casts.
-- labels()
SELECT * from cypher('list', $$CREATE (u:People {name: "John"}) RETURN u$$) as (Vertices agtype);
vertices
Expand Down
11 changes: 11 additions & 0 deletions regress/sql/expr.sql
Original file line number Diff line number Diff line change
Expand Up @@ -2730,6 +2730,17 @@ SELECT * from cypher('list', $$RETURN range(-10, 10, -1)$$) as (range agtype);
SELECT * from cypher('list', $$RETURN range(null, -10, -3)$$) as (range agtype);
SELECT * from cypher('list', $$RETURN range(0, null, -3)$$) as (range agtype);
SELECT * from cypher('list', $$RETURN range(0, -10.0, -3.0)$$) as (range agtype);
-- tail()
-- should return the last elements of the list
SELECT * FROM cypher('list', $$ RETURN tail([1,2,3,4,5]) $$) AS (tail agtype);
SELECT * FROM cypher('list', $$ RETURN tail(["a","b","c","d","e"]) $$) AS (tail agtype);
-- should return null
SELECT * FROM cypher('list', $$ RETURN tail([1]) $$) AS (tail agtype);
SELECT * FROM cypher('list', $$ RETURN tail([]) $$) AS (tail agtype);
-- should throw errors
SELECT * FROM cypher('list', $$ RETURN tail(123) $$) AS (tail agtype);
SELECT * FROM cypher('list', $$ RETURN tail(abc) $$) AS (tail agtype);
SELECT * FROM cypher('list', $$ RETURN tail() $$) AS (tail agtype);
-- labels()
SELECT * from cypher('list', $$CREATE (u:People {name: "John"}) RETURN u$$) as (Vertices agtype);
SELECT * from cypher('list', $$CREATE (u:People {name: "Larry"}) RETURN u$$) as (Vertices agtype);
Expand Down
77 changes: 77 additions & 0 deletions src/backend/utils/adt/agtype.c
Original file line number Diff line number Diff line change
Expand Up @@ -5007,6 +5007,83 @@ Datum age_last(PG_FUNCTION_ARGS)
PG_RETURN_POINTER(agtype_value_to_agtype(agtv_result));
}


PG_FUNCTION_INFO_V1(age_tail);
/*
* Returns a list containing all the elements, excluding the first one, from a list.
*/
Datum age_tail(PG_FUNCTION_ARGS)
{
Oid arg_type;
agtype *agt_arg = NULL;
agtype *agt_result = NULL;
agtype_in_state agis_result;
int count;
int i;

/* check number of arguments */
if (PG_NARGS() < 1 || PG_NARGS() > 1)
{
ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("age_tail() requires only one argument")));
}

/* get the data type */
arg_type = get_fn_expr_argtype(fcinfo->flinfo, 0);

/* check the data type */
if (arg_type != AGTYPEOID)
{
ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("age_tail() argument must be of type agtype")));
}

/* check for null */
if (PG_ARGISNULL(0))
{
PG_RETURN_NULL();
}

agt_arg = AG_GET_ARG_AGTYPE_P(0);
/* check for an array */
if (!AGT_ROOT_IS_ARRAY(agt_arg) || AGT_ROOT_IS_SCALAR(agt_arg))
{
ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("tail() argument must resolve to a list or null")));
}

count = AGT_ROOT_COUNT(agt_arg);

/* if we have an empty list or only one element in the list, return null */
if (count <= 1)
{
PG_RETURN_NULL();
}

/* clear the result structure */
MemSet(&agis_result, 0, sizeof(agtype_in_state));

/* push the beginning of the array */
agis_result.res = push_agtype_value(&agis_result.parse_state,
WAGT_BEGIN_ARRAY, NULL);

/* iterate through the list beginning with the second item */
for (i = 1; i < count; i++)
{
agis_result.res = push_agtype_value(&agis_result.parse_state, WAGT_ELEM,
get_ith_agtype_value_from_container(&agt_arg->root, i));
}

/* push the end of the array */
agis_result.res = push_agtype_value(&agis_result.parse_state,
WAGT_END_ARRAY, NULL);

agt_result = agtype_value_to_agtype(agis_result.res);
pfree_agtype_value(agis_result.res);

PG_RETURN_POINTER(agt_result);
}

PG_FUNCTION_INFO_V1(age_properties);

Datum age_properties(PG_FUNCTION_ARGS)
Expand Down