if (fpmode == FUNC_PARAM_DEFAULT)
fpmode = FUNC_PARAM_IN;
- typtup = LookupTypeName(NULL, t, NULL, false);
+ typtup = LookupTypeName(pstate, t, NULL, false);
if (typtup)
{
if (!((Form_pg_type) GETSTRUCT(typtup))->typisdefined)
ereport(ERROR,
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
errmsg("SQL function cannot accept shell type %s",
- TypeNameToString(t))));
+ TypeNameToString(t)),
+ parser_errposition(pstate, t->location)));
/* We don't allow creating aggregates on shell types either */
else if (objtype == OBJECT_AGGREGATE)
ereport(ERROR,
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
errmsg("aggregate cannot accept shell type %s",
- TypeNameToString(t))));
+ TypeNameToString(t)),
+ parser_errposition(pstate, t->location)));
else
ereport(NOTICE,
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
errmsg("argument type %s is only a shell",
- TypeNameToString(t))));
+ TypeNameToString(t)),
+ parser_errposition(pstate, t->location)));
}
toid = typeTypeId(typtup);
ReleaseSysCache(typtup);
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("type %s does not exist",
- TypeNameToString(t))));
+ TypeNameToString(t)),
+ parser_errposition(pstate, t->location)));
toid = InvalidOid; /* keep compiler quiet */
}
if (objtype == OBJECT_AGGREGATE)
ereport(ERROR,
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
- errmsg("aggregates cannot accept set arguments")));
+ errmsg("aggregates cannot accept set arguments"),
+ parser_errposition(pstate, fp->location)));
else if (objtype == OBJECT_PROCEDURE)
ereport(ERROR,
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
- errmsg("procedures cannot accept set arguments")));
+ errmsg("procedures cannot accept set arguments"),
+ parser_errposition(pstate, fp->location)));
else
ereport(ERROR,
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
- errmsg("functions cannot accept set arguments")));
+ errmsg("functions cannot accept set arguments"),
+ parser_errposition(pstate, fp->location)));
}
/* handle input parameters */
if (varCount > 0)
ereport(ERROR,
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
- errmsg("VARIADIC parameter must be the last input parameter")));
+ errmsg("VARIADIC parameter must be the last input parameter"),
+ parser_errposition(pstate, fp->location)));
inTypes[inCount++] = toid;
isinput = true;
if (parameterTypes_list)
if (varCount > 0)
ereport(ERROR,
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
- errmsg("VARIADIC parameter must be the last parameter")));
+ errmsg("VARIADIC parameter must be the last parameter"),
+ parser_errposition(pstate, fp->location)));
/* Procedures with output parameters always return RECORD */
*requiredResultType = RECORDOID;
}
if (!OidIsValid(get_element_type(toid)))
ereport(ERROR,
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
- errmsg("VARIADIC parameter must be an array")));
+ errmsg("VARIADIC parameter must be an array"),
+ parser_errposition(pstate, fp->location)));
break;
}
}
ereport(ERROR,
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
errmsg("parameter name \"%s\" used more than once",
- fp->name)));
+ fp->name),
+ parser_errposition(pstate, fp->location)));
}
paramNames[i] = CStringGetTextDatum(fp->name);
if (!isinput)
ereport(ERROR,
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
- errmsg("only input parameters can have default values")));
+ errmsg("only input parameters can have default values"),
+ parser_errposition(pstate, fp->location)));
def = transformExpr(pstate, fp->defexpr,
EXPR_KIND_FUNCTION_DEFAULT);
contain_var_clause(def))
ereport(ERROR,
(errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
- errmsg("cannot use table references in parameter default value")));
+ errmsg("cannot use table references in parameter default value"),
+ parser_errposition(pstate, fp->location)));
/*
* transformExpr() should have already rejected subqueries,
if (isinput && have_defaults)
ereport(ERROR,
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
- errmsg("input parameters after one with a default value must also have defaults")));
+ errmsg("input parameters after one with a default value must also have defaults"),
+ parser_errposition(pstate, fp->location)));
/*
* For procedures, we also can't allow OUT parameters after one
if (objtype == OBJECT_PROCEDURE && have_defaults)
ereport(ERROR,
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
- errmsg("procedure OUT parameters cannot appear after one with a default value")));
+ errmsg("procedure OUT parameters cannot appear after one with a default value"),
+ parser_errposition(pstate, fp->location)));
}
i++;
loc = ((const Constraint *) expr)->location;
break;
case T_FunctionParameter:
- /* just use typename's location */
- loc = exprLocation((Node *) ((const FunctionParameter *) expr)->argType);
+ loc = ((const FunctionParameter *) expr)->location;
break;
case T_XmlSerialize:
/* XMLSERIALIZE keyword should always be the first thing */
int location);
static Node *makeXmlExpr(XmlExprOp op, char *name, List *named_args,
List *args, int location);
-static List *mergeTableFuncParameters(List *func_args, List *columns);
+static List *mergeTableFuncParameters(List *func_args, List *columns, core_yyscan_t yyscanner);
static TypeName *TableFuncTypeName(List *columns);
static RangeVar *makeRangeVarFromAnyName(List *names, int position, core_yyscan_t yyscanner);
static RangeVar *makeRangeVarFromQualifiedName(char *name, List *namelist, int location,
n->is_procedure = false;
n->replace = $2;
n->funcname = $4;
- n->parameters = mergeTableFuncParameters($5, $9);
+ n->parameters = mergeTableFuncParameters($5, $9, yyscanner);
n->returnType = TableFuncTypeName($9);
n->returnType->location = @7;
n->options = $11;
n->argType = $3;
n->mode = $1;
n->defexpr = NULL;
+ n->location = @1;
$$ = n;
}
| param_name arg_class func_type
n->argType = $3;
n->mode = $2;
n->defexpr = NULL;
+ n->location = @1;
$$ = n;
}
| param_name func_type
n->argType = $2;
n->mode = FUNC_PARAM_DEFAULT;
n->defexpr = NULL;
+ n->location = @1;
$$ = n;
}
| arg_class func_type
n->argType = $2;
n->mode = $1;
n->defexpr = NULL;
+ n->location = @1;
$$ = n;
}
| func_type
n->argType = $1;
n->mode = FUNC_PARAM_DEFAULT;
n->defexpr = NULL;
+ n->location = @1;
$$ = n;
}
;
n->argType = $2;
n->mode = FUNC_PARAM_TABLE;
n->defexpr = NULL;
+ n->location = @1;
$$ = n;
}
;
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("an ordered-set aggregate with a VARIADIC direct argument must have one VARIADIC aggregated argument of the same data type"),
- parser_errposition(exprLocation((Node *) firsto))));
+ parser_errposition(firsto->location)));
/* OK, drop the duplicate VARIADIC argument from the internal form */
orderedargs = NIL;
* Merge the input and output parameters of a table function.
*/
static List *
-mergeTableFuncParameters(List *func_args, List *columns)
+mergeTableFuncParameters(List *func_args, List *columns, core_yyscan_t yyscanner)
{
ListCell *lc;
p->mode != FUNC_PARAM_VARIADIC)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("OUT and INOUT arguments aren't allowed in TABLE functions")));
+ errmsg("OUT and INOUT arguments aren't allowed in TABLE functions"),
+ parser_errposition(p->location)));
}
return list_concat(func_args, columns);
*/
/* yyyymmddN */
-#define CATALOG_VERSION_NO 202410242
+#define CATALOG_VERSION_NO 202410311
#endif
TypeName *argType; /* TypeName for parameter type */
FunctionParameterMode mode; /* IN/OUT/etc */
Node *defexpr; /* raw default expr, or NULL if not given */
+ ParseLoc location; /* token location, or -1 if unknown */
} FunctionParameter;
typedef struct AlterFunctionStmt
AS 'textout'
LANGUAGE internal STABLE STRICT ;
NOTICE: argument type text_w_default is only a shell
+LINE 1: CREATE FUNCTION text_w_default_out(text_w_default)
+ ^
NOTICE: DDL test: type simple, tag CREATE FUNCTION
CREATE TYPE employee_type AS (name TEXT, salary NUMERIC);
NOTICE: DDL test: type simple, tag CREATE TYPE
create function int8alias1out(int8alias1) returns cstring
strict immutable language internal as 'int8out';
NOTICE: argument type int8alias1 is only a shell
+LINE 1: create function int8alias1out(int8alias1) returns cstring
+ ^
NOTICE: DDL test: type simple, tag CREATE FUNCTION
create type int8alias1 (
input = int8alias1in,
create function int8alias2out(int8alias2) returns cstring
strict immutable language internal as 'int8out';
NOTICE: argument type int8alias2 is only a shell
+LINE 1: create function int8alias2out(int8alias2) returns cstring
+ ^
NOTICE: DDL test: type simple, tag CREATE FUNCTION
create type int8alias2 (
input = int8alias2in,
AS 'textout'
LANGUAGE internal STRICT IMMUTABLE;
NOTICE: argument type casttesttype is only a shell
+LINE 1: CREATE FUNCTION casttesttype_out(casttesttype)
+ ^
CREATE TYPE casttesttype (
internallength = variable,
input = casttesttype_in,
AS 'textout'
LANGUAGE internal STRICT IMMUTABLE;
NOTICE: argument type casttesttype is only a shell
+LINE 1: CREATE FUNCTION casttesttype_out(casttesttype)
+ ^
CREATE TYPE casttesttype (
internallength = variable,
input = casttesttype_in,
CREATE PROCEDURE ptestx(a VARIADIC int[], b OUT int) LANGUAGE SQL
AS $$ SELECT a[1] $$;
ERROR: VARIADIC parameter must be the last parameter
+LINE 1: CREATE PROCEDURE ptestx(a VARIADIC int[], b OUT int) LANGUAG...
+ ^
CREATE PROCEDURE ptestx(a int DEFAULT 42, b OUT int) LANGUAGE SQL
AS $$ SELECT a $$;
ERROR: procedure OUT parameters cannot appear after one with a default value
+LINE 1: CREATE PROCEDURE ptestx(a int DEFAULT 42, b OUT int) LANGUAG...
+ ^
ALTER PROCEDURE ptest1(text) STRICT;
ERROR: invalid attribute in procedure definition
LINE 1: ALTER PROCEDURE ptest1(text) STRICT;
AS :'regresslib'
LANGUAGE C STRICT IMMUTABLE;
NOTICE: argument type widget is only a shell
+LINE 1: CREATE FUNCTION widget_out(widget)
+ ^
CREATE FUNCTION int44in(cstring)
RETURNS city_budget
AS :'regresslib'
AS :'regresslib'
LANGUAGE C STRICT IMMUTABLE;
NOTICE: argument type city_budget is only a shell
+LINE 1: CREATE FUNCTION int44out(city_budget)
+ ^
CREATE TYPE widget (
internallength = 24,
input = widget_in,
AS 'int4out'
LANGUAGE internal STRICT IMMUTABLE;
NOTICE: argument type int42 is only a shell
+LINE 1: CREATE FUNCTION int42_out(int42)
+ ^
CREATE FUNCTION text_w_default_in(cstring)
RETURNS text_w_default
AS 'textin'
AS 'textout'
LANGUAGE internal STRICT IMMUTABLE;
NOTICE: argument type text_w_default is only a shell
+LINE 1: CREATE FUNCTION text_w_default_out(text_w_default)
+ ^
CREATE TYPE int42 (
internallength = 4,
input = int42_in,
CREATE FUNCTION base_fn_out(base_type) RETURNS cstring AS 'boolout'
LANGUAGE internal IMMUTABLE STRICT;
NOTICE: argument type base_type is only a shell
+LINE 1: CREATE FUNCTION base_fn_out(base_type) RETURNS cstring AS 'b...
+ ^
CREATE TYPE base_type(INPUT = base_fn_in, OUTPUT = base_fn_out);
DROP FUNCTION base_fn_in(cstring); -- error
ERROR: cannot drop function base_fn_in(cstring) because other objects depend on it
CREATE FUNCTION myvarcharout(myvarchar) RETURNS cstring
LANGUAGE internal IMMUTABLE PARALLEL SAFE STRICT AS 'varcharout';
NOTICE: argument type myvarchar is only a shell
+LINE 1: CREATE FUNCTION myvarcharout(myvarchar) RETURNS cstring
+ ^
CREATE FUNCTION myvarcharsend(myvarchar) RETURNS bytea
LANGUAGE internal STABLE PARALLEL SAFE STRICT AS 'varcharsend';
NOTICE: argument type myvarchar is only a shell
+LINE 1: CREATE FUNCTION myvarcharsend(myvarchar) RETURNS bytea
+ ^
CREATE FUNCTION myvarcharrecv(internal, oid, integer) RETURNS myvarchar
LANGUAGE internal STABLE PARALLEL SAFE STRICT AS 'varcharrecv';
NOTICE: return type myvarchar is only a shell
create function int8alias1out(int8alias1) returns cstring
strict immutable language internal as 'int8out';
NOTICE: argument type int8alias1 is only a shell
+LINE 1: create function int8alias1out(int8alias1) returns cstring
+ ^
create type int8alias1 (
input = int8alias1in,
output = int8alias1out,
create function int8alias2out(int8alias2) returns cstring
strict immutable language internal as 'int8out';
NOTICE: argument type int8alias2 is only a shell
+LINE 1: create function int8alias2out(int8alias2) returns cstring
+ ^
create type int8alias2 (
input = int8alias2in,
output = int8alias2out,
create function myintout(myint) returns cstring strict immutable language
internal as 'int4out';
NOTICE: argument type myint is only a shell
+LINE 1: create function myintout(myint) returns cstring strict immut...
+ ^
create function myinthash(myint) returns integer strict immutable language
internal as 'hashint4';
NOTICE: argument type myint is only a shell
+LINE 1: create function myinthash(myint) returns integer strict immu...
+ ^
create type myint (input = myintin, output = myintout, like = int4);
create cast (int4 as myint) without function;
create cast (myint as int4) without function;
create function xfloat4out(xfloat4) returns cstring immutable strict
language internal as 'int4out';
NOTICE: argument type xfloat4 is only a shell
+LINE 1: create function xfloat4out(xfloat4) returns cstring immutabl...
+ ^
create type xfloat4 (input = xfloat4in, output = xfloat4out, like = float4);
create cast (xfloat4 as float4) without function;
create cast (float4 as xfloat4) without function;
create function xfloat4out(xfloat4) returns cstring immutable strict
language internal as 'int4out';
NOTICE: argument type xfloat4 is only a shell
+LINE 1: create function xfloat4out(xfloat4) returns cstring immutabl...
+ ^
create type xfloat4 (input = xfloat4in, output = xfloat4out, like = float4);
create cast (xfloat4 as float4) without function;
create cast (float4 as xfloat4) without function;
create function xfloat8out(xfloat8) returns cstring immutable strict
language internal as 'int8out';
NOTICE: argument type xfloat8 is only a shell
+LINE 1: create function xfloat8out(xfloat8) returns cstring immutabl...
+ ^
create type xfloat8 (input = xfloat8in, output = xfloat8out, like = float8);
create cast (xfloat8 as float8) without function;
create cast (float8 as xfloat8) without function;
select $1 + $2;
$$ language sql;
ERROR: input parameters after one with a default value must also have defaults
+LINE 1: create function dfunc(a int = 1, b int) returns int as $$
+ ^
-- however, this should work:
create function dfunc(a int = 1, out sum int, b int = 2) as $$
select $1 + $2;
select 1;
$$ language sql;
ERROR: only input parameters can have default values
+LINE 1: create function dfunc(out int = 20) returns int as $$
+ ^
-- polymorphic parameter test
create function dfunc(anyelement = 'World'::text) returns text as $$
select 'Hello, ' || $1::text;
--fail, named parameters are not unique
create function testpolym(a int, a int) returns int as $$ select 1;$$ language sql;
ERROR: parameter name "a" used more than once
+LINE 1: create function testpolym(a int, a int) returns int as $$ se...
+ ^
create function testpolym(int, out a int, out a int) returns int as $$ select 1;$$ language sql;
ERROR: parameter name "a" used more than once
+LINE 1: create function testpolym(int, out a int, out a int) returns...
+ ^
create function testpolym(out a int, inout a int) returns int as $$ select 1;$$ language sql;
ERROR: parameter name "a" used more than once
+LINE 1: create function testpolym(out a int, inout a int) returns in...
+ ^
create function testpolym(a int, inout a int) returns int as $$ select 1;$$ language sql;
ERROR: parameter name "a" used more than once
+LINE 1: create function testpolym(a int, inout a int) returns int as...
+ ^
-- valid
create function testpolym(a int, out a int) returns int as $$ select $1;$$ language sql;
select testpolym(37);