Skip to content

fix(catalog): leave the types of polymorphic SQL function parameters unknown in the body - #942

Open
psteinroe wants to merge 1 commit into
test/regress-function-bodiesfrom
fix/polymorphic-function-params
Open

psteinroe wants to merge 1 commit into
test/regress-function-bodiesfrom
fix/polymorphic-function-params

Conversation

@psteinroe

Copy link
Copy Markdown
Collaborator

Stacked on #939.

The typecheck rules gave the parameters of a SQL function their declared types inside the body, including polymorphic ones. With $1 anyelement, a call like array_prepend($1, $2) was matched against array_prepend(anycompatible, anycompatiblearray) with anyelement as the actual argument type, which no candidate accepts:

create function formarray(anyelement, variadic anyarray) returns anyarray as $$
  select array_prepend($1, $2);
$$ language sql immutable strict;
-- before: functionArgumentMismatch: Function array_prepend(anyelement, anyarray) does not exist.
-- after: nothing

This is the false positive #939 found in polymorphism.sql.

Postgres never analyses such a body with the declared types. When check_function_bodies is on, fmgr_sql_validator only raw-parses the body of a function with polymorphic arguments. At call time, prepare_sql_fn_parse_info swaps each polymorphic parameter type for the type of the call's argument before it parses the body (functions.c#L286). So the type of a polymorphic parameter in the body is whatever the caller passes, and we can't know it from the body. BEGIN ATOMIC bodies, which are analysed at creation with the declared types, aren't affected: Postgres rejects polymorphic arguments there ("SQL function with unquoted function body cannot have polymorphic arguments").

The fix: function_param_type now returns unknown for parameters of a pseudo-type. Polymorphic types are the only pseudo-types SQL functions accept as parameters (pg_proc.c#L873). Expressions that use these parameters are therefore unknown, and nothing is reported for them. Parameters of concrete types (including arrays) still have their declared types.

Tests: a new functionArgumentMismatch/function_parameters.sql spec. It checks that a concrete parameter is still checked (length(n) with n int is reported) and that array_prepend($1, $2) and length(a) with polymorphic parameters aren't. The polymorphism entry is gone from the harness's KNOWN_FALSE_POSITIVES, which is now empty. The regression snapshots only lose their "Known false positives" section.

Not covered: we don't infer the result types of polymorphic SQL functions at call sites from the body. That already went through the function's declared signature and is unchanged.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant