diff --git a/regress/expected/cypher_call.out b/regress/expected/cypher_call.out index 6980abe4b..bb1185b96 100644 --- a/regress/expected/cypher_call.out +++ b/regress/expected/cypher_call.out @@ -240,6 +240,58 @@ SELECT * FROM cypher('cypher_call', $$ CALL sqrt(64) YIELD sqrt CALL agtype_sum( ERROR: duplicate variable "sqrt" LINE 1: ...LL sqrt(64) YIELD sqrt CALL agtype_sum(2,2) YIELD agtype_sum... ^ +-- Fix CALL/YIELD issues +CREATE OR REPLACE FUNCTION myfunc(i agtype) +RETURNS agtype +LANGUAGE plpgsql +AS $$ +DECLARE + result agtype; +BEGIN + RETURN ag_catalog.age_sqrt(i); +END; +$$; +-- should have no errors +SELECT * FROM cypher('cypher_call', $$ CALL ag_catalog.age_sqrt(64) YIELD age_sqrt RETURN age_sqrt $$) as (sqrt agtype); + sqrt +------ + 8.0 +(1 row) + +SELECT * FROM cypher('cypher_call', $$ CALL myfunc(25) YIELD myfunc RETURN myfunc $$) as (result agtype); + result +-------- + 5.0 +(1 row) + +SELECT * FROM cypher('cypher_call', $$ CALL ag_catalog.myfunc(25) YIELD myfunc RETURN myfunc $$) as (result agtype); + result +-------- + 5.0 +(1 row) + +-- should error +SELECT * FROM cypher('cypher_call', $$ CALL myfunc() YIELD myfunc RETURN myfunc $$) as (result agtype); +ERROR: function myfunc does not exist +LINE 1: SELECT * FROM cypher('cypher_call', $$ CALL myfunc() YIELD m... + ^ +HINT: If the function is from an external extension, make sure the extension is installed and the function is in the search path. +SELECT * FROM cypher('cypher_call', $$ CALL myfunz(25) YIELD myfunc RETURN myfunc $$) as (result agtype); +ERROR: function myfunz does not exist +LINE 1: SELECT * FROM cypher('cypher_call', $$ CALL myfunz(25) YIELD... + ^ +HINT: If the function is from an external extension, make sure the extension is installed and the function is in the search path. +SELECT * FROM cypher('cypher_call', $$ CALL ag_catalog.myfunc() YIELD myfunc RETURN myfunc $$) as (result agtype); +ERROR: function ag_catalog.myfunc() does not exist +LINE 1: ...T * FROM cypher('cypher_call', $$ CALL ag_catalog.myfunc() Y... + ^ +HINT: No function matches the given name and argument types. You might need to add explicit type casts. +SELECT * FROM cypher('cypher_call', $$ CALL ag_catalog.myfunz(25) YIELD myfunc RETURN myfunc $$) as (result agtype); +ERROR: function ag_catalog.myfunz(agtype) does not exist +LINE 1: ...OM cypher('cypher_call', $$ CALL ag_catalog.myfunz(25) YIELD... + ^ +HINT: No function matches the given name and argument types. You might need to add explicit type casts. +DROP FUNCTION myfunc; DROP SCHEMA call_stmt_test CASCADE; NOTICE: drop cascades to function call_stmt_test.add_agtype(agtype,agtype) SELECT drop_graph('cypher_call', true); diff --git a/regress/sql/cypher_call.sql b/regress/sql/cypher_call.sql index 917276806..ee1468755 100644 --- a/regress/sql/cypher_call.sql +++ b/regress/sql/cypher_call.sql @@ -104,5 +104,30 @@ SELECT * FROM cypher('cypher_call', $$ CALL sqrt(64) YIELD sqrt AS sqrt1 CALL sq SELECT * FROM cypher('cypher_call', $$ CALL sqrt(64) YIELD sqrt AS sqrt1 CALL sqrt(81) YIELD sqrt AS sqrt1 RETURN sqrt1, sqrt1 $$) as (a agtype, b agtype); SELECT * FROM cypher('cypher_call', $$ CALL sqrt(64) YIELD sqrt CALL agtype_sum(2,2) YIELD agtype_sum AS sqrt RETURN sqrt, sqrt $$) as (a agtype, b agtype); +-- Fix CALL/YIELD issues +CREATE OR REPLACE FUNCTION myfunc(i agtype) +RETURNS agtype +LANGUAGE plpgsql +AS $$ +DECLARE + result agtype; +BEGIN + RETURN ag_catalog.age_sqrt(i); +END; +$$; + +-- should have no errors +SELECT * FROM cypher('cypher_call', $$ CALL ag_catalog.age_sqrt(64) YIELD age_sqrt RETURN age_sqrt $$) as (sqrt agtype); +SELECT * FROM cypher('cypher_call', $$ CALL myfunc(25) YIELD myfunc RETURN myfunc $$) as (result agtype); +SELECT * FROM cypher('cypher_call', $$ CALL ag_catalog.myfunc(25) YIELD myfunc RETURN myfunc $$) as (result agtype); + +-- should error +SELECT * FROM cypher('cypher_call', $$ CALL myfunc() YIELD myfunc RETURN myfunc $$) as (result agtype); +SELECT * FROM cypher('cypher_call', $$ CALL myfunz(25) YIELD myfunc RETURN myfunc $$) as (result agtype); +SELECT * FROM cypher('cypher_call', $$ CALL ag_catalog.myfunc() YIELD myfunc RETURN myfunc $$) as (result agtype); +SELECT * FROM cypher('cypher_call', $$ CALL ag_catalog.myfunz(25) YIELD myfunc RETURN myfunc $$) as (result agtype); + +DROP FUNCTION myfunc; + DROP SCHEMA call_stmt_test CASCADE; SELECT drop_graph('cypher_call', true); diff --git a/src/backend/parser/cypher_clause.c b/src/backend/parser/cypher_clause.c index 172e6305a..93e710ab4 100644 --- a/src/backend/parser/cypher_clause.c +++ b/src/backend/parser/cypher_clause.c @@ -1153,7 +1153,7 @@ static Query *transform_cypher_call_subquery(cypher_parsestate *cpstate, EXPR_KIND_FROM_FUNCTION)); /* retrieve the column name from funccall */ - colName = strVal(linitial(self->funccall->funcname)); + colName = strVal(llast(self->funccall->funcname)); /* make a targetentry from the funcexpr node */ tle = makeTargetEntry((Expr *) node, @@ -3957,7 +3957,7 @@ static List *transform_map_to_ind_recursive(cypher_parsestate *cpstate, * * Transforms the map to a list of equality irrespective of * value type. For example, - * + * * x.name = 'xyz' * x.map = {"city": "abc", "street": {"name": "pqr", "number": 123}} * x.list = [9, 8, 7] @@ -4011,7 +4011,7 @@ static List *transform_map_to_ind_top_level(cypher_parsestate *cpstate, qual = (Node *)make_op(pstate, op, lhs, rhs, last_srf, -1); quals = lappend(quals, qual); } - + return quals; } diff --git a/src/backend/parser/cypher_expr.c b/src/backend/parser/cypher_expr.c index 390bfb392..993957c83 100644 --- a/src/backend/parser/cypher_expr.c +++ b/src/backend/parser/cypher_expr.c @@ -2036,7 +2036,7 @@ static Node *transform_FuncCall(cypher_parsestate *cpstate, FuncCall *fn) targs = lcons(c, targs); } } - /* + /* * If it's not in age, check if it's a potential call to some function * in another installed extension. */ @@ -2055,14 +2055,13 @@ static Node *transform_FuncCall(cypher_parsestate *cpstate, FuncCall *fn) procform, extension); return retval; } + /* + * Else we have a function that is in the search_path, and not + * qualified, but is not in an extension. Pass it through. + */ else { - ereport(ERROR, - (errcode(ERRCODE_UNDEFINED_FUNCTION), - errmsg("function %s does not exist", name), - errhint("If the function is from an external extension, " - "make sure the extension is installed and the " - "function is in the search path."))); + fname = fn->funcname; } } /* no function found */