CALL versus procedures with output-only arguments
I'm not too happy with this:
regression=# create procedure p1(out x int) language plpgsql
regression-# as 'begin x := 42; end';
CREATE PROCEDURE
regression=# call p1();
ERROR: procedure p1() does not exist
LINE 1: call p1();
^
HINT: No procedure matches the given name and argument types. You might need to add explicit type casts.
regression=# call p1(null);
x
----
42
(1 row)
I can see that that makes some sense within plpgsql, where the CALL
ought to provide a plpgsql variable for each OUT argument. But it
seems moderately insane for calls from SQL. It certainly fails
to match the documentation [1]https://www.postgresql.org/docs/devel/sql-call.html, which says fairly explicitly that
the argument list items match the *input* arguments of the procedure,
and further notes that plpgsql handles output arguments differently.
I think we ought to fix this so that OUT-only arguments are ignored
when calling from SQL not plpgsql. This is less than simple, since
the parser doesn't actually have any context that would let it know
which one we're doing, but I think we could hack that up somehow.
(The RawParseMode mechanism seems like one way we could pass the
info, and there are probably others.)
Alternatively, if we're going to stick with this behavior, we have
to change the docs to explain it. Either way it seems like an
open item for v14. (For those who've forgotten, OUT-only procedure
arguments are a new thing in v14.)
regards, tom lane
čt 20. 5. 2021 v 19:53 odesílatel Tom Lane <tgl@sss.pgh.pa.us> napsal:
I'm not too happy with this:
regression=# create procedure p1(out x int) language plpgsql
regression-# as 'begin x := 42; end';
CREATE PROCEDUREregression=# call p1();
ERROR: procedure p1() does not exist
LINE 1: call p1();
^
HINT: No procedure matches the given name and argument types. You might
need to add explicit type casts.regression=# call p1(null);
x
----
42
(1 row)I can see that that makes some sense within plpgsql, where the CALL
ought to provide a plpgsql variable for each OUT argument. But it
seems moderately insane for calls from SQL. It certainly fails
to match the documentation [1], which says fairly explicitly that
the argument list items match the *input* arguments of the procedure,
and further notes that plpgsql handles output arguments differently.I think we ought to fix this so that OUT-only arguments are ignored
when calling from SQL not plpgsql. This is less than simple, since
the parser doesn't actually have any context that would let it know
which one we're doing, but I think we could hack that up somehow.
(The RawParseMode mechanism seems like one way we could pass the
info, and there are probably others.)
+1
Pavel
Show quoted text
Alternatively, if we're going to stick with this behavior, we have
to change the docs to explain it. Either way it seems like an
open item for v14. (For those who've forgotten, OUT-only procedure
arguments are a new thing in v14.)regards, tom lane
I wrote:
I think we ought to fix this so that OUT-only arguments are ignored
when calling from SQL not plpgsql.
I'm working on a patch to make it act that way. I've got some issues
yet to fix with named arguments (which seem rather undertested BTW,
since the patch is passing check-world even though I know it will
crash instantly on cases with CALL+named-args+out-only-args).
Before I spend too much time on it though, I wanted to mention that
it includes undoing 2453ea142's decision to include OUT arguments
in pg_proc.proargtypes for procedures (but not for any other kind of
routine). I thought that was a terrible decision and I'm very happy
to revert it, but is anyone likely to complain loudly?
regards, tom lane
On 5/23/21 8:01 PM, Tom Lane wrote:
I wrote:
I think we ought to fix this so that OUT-only arguments are ignored
when calling from SQL not plpgsql.I'm working on a patch to make it act that way. I've got some issues
yet to fix with named arguments (which seem rather undertested BTW,
since the patch is passing check-world even though I know it will
crash instantly on cases with CALL+named-args+out-only-args).Before I spend too much time on it though, I wanted to mention that
it includes undoing 2453ea142's decision to include OUT arguments
in pg_proc.proargtypes for procedures (but not for any other kind of
routine). I thought that was a terrible decision and I'm very happy
to revert it, but is anyone likely to complain loudly?
Possibly, Will take a look. IIRC we have based some other things on this.
cheers
andrew
--
Andrew Dunstan
EDB: https://www.enterprisedb.com
Andrew Dunstan <andrew@dunslane.net> writes:
On 5/23/21 8:01 PM, Tom Lane wrote:
Before I spend too much time on it though, I wanted to mention that
it includes undoing 2453ea142's decision to include OUT arguments
in pg_proc.proargtypes for procedures (but not for any other kind of
routine). I thought that was a terrible decision and I'm very happy
to revert it, but is anyone likely to complain loudly?
Possibly, Will take a look. IIRC we have based some other things on this.
There's 9213462c5, which I *think* just needs to be reverted along
with much of 2453ea142. But I don't have a JDBC setup to check it
with.
regards, tom lane
I wrote:
I think we ought to fix this so that OUT-only arguments are ignored
when calling from SQL not plpgsql.
Here's a draft patch for that. The docs probably need some more
fiddling, but I think the code is in good shape. (I'm unsure about
the JDBC compatibility issue, and would appreciate someone else
testing that.)
I'm working on a patch to make it act that way. I've got some issues
yet to fix with named arguments (which seem rather undertested BTW,
since the patch is passing check-world even though I know it will
crash instantly on cases with CALL+named-args+out-only-args).
After I'd finished fixing that, I realized that HEAD is really pretty
broken for the case. For example
regression=# CREATE PROCEDURE test_proc10(IN a int, OUT b int, IN c int)
regression-# LANGUAGE plpgsql
regression-# AS $$
regression$# BEGIN
regression$# RAISE NOTICE 'a: %, b: %, c: %', a, b, c;
regression$# b := a - c;
regression$# END;
regression$# $$;
CREATE PROCEDURE
regression=# DO $$
regression$# DECLARE _a int; _b int; _c int;
regression$# BEGIN
regression$# _a := 10; _b := 30; _c := 7;
regression$# CALL test_proc10(a => _a, b => _b, c => _c);
regression$# RAISE NOTICE '_a: %, _b: %, _c: %', _a, _b, _c;
regression$# END$$;
ERROR: procedure test_proc10(a => integer, b => integer, c => integer) does not exist
LINE 1: CALL test_proc10(a => _a, b => _b, c => _c)
^
HINT: No procedure matches the given name and argument types. You might need to add explicit type casts.
QUERY: CALL test_proc10(a => _a, b => _b, c => _c)
CONTEXT: PL/pgSQL function inline_code_block line 5 at CALL
So even if you object to what I'm trying to do here, there is
work to be done.
regards, tom lane
Attachments:
reconsider-out-args-1.patchtext/x-diff; charset=us-ascii; name=reconsider-out-args-1.patchDownload+621-297
On 24.05.21 02:01, Tom Lane wrote:
I wrote:
I think we ought to fix this so that OUT-only arguments are ignored
when calling from SQL not plpgsql.I'm working on a patch to make it act that way. I've got some issues
yet to fix with named arguments (which seem rather undertested BTW,
since the patch is passing check-world even though I know it will
crash instantly on cases with CALL+named-args+out-only-args).Before I spend too much time on it though, I wanted to mention that
it includes undoing 2453ea142's decision to include OUT arguments
in pg_proc.proargtypes for procedures (but not for any other kind of
routine). I thought that was a terrible decision and I'm very happy
to revert it, but is anyone likely to complain loudly?
I don't understand why you want to change this. The argument resolution
of CALL is specified in the SQL standard; we shouldn't just make up our
own system.
Peter Eisentraut <peter.eisentraut@enterprisedb.com> writes:
On 24.05.21 02:01, Tom Lane wrote:
I think we ought to fix this so that OUT-only arguments are ignored
when calling from SQL not plpgsql.
I don't understand why you want to change this. The argument resolution
of CALL is specified in the SQL standard; we shouldn't just make up our
own system.
I don't really see how you can argue that the existing behavior is
more spec-compliant than what I'm suggesting. What I read in the spec
(SQL:2021 10.4 <routine invocation> SR 9) h) iii) 1)) is
1) If Pi is an output SQL parameter, then XAi shall be a <target
specification>.
(where <target specification> more or less reduces to "variable").
Now, sure, that's what we've got in plpgsql, and I'm not proposing
to change that. But in plain SQL, as of HEAD, you are supposed to
write NULL, or a random literal, or indeed anything at all *except*
a variable. How is that more standard-compliant than not writing
anything?
Also, one could argue that the behavior I'm suggesting is completely
spec-compliant if one assumes that the OUT parameters have some sort
of default, allowing them to be omitted from the call.
More generally, there are enough deviations from spec in what we do
to perform ambiguous-call resolution that it seems rather silly to
hang your hat on this particular point.
Now as against that, we are giving up a whole lot of consistency.
As of HEAD:
* The rules for what is a conflict of signatures are different
for functions and procedures.
* The rules for how to identify a target routine in ALTER, DROP,
etc are different for functions and procedures. That's especially
nasty in ALTER/DROP ROUTINE, where we don't have a syntax cue
as to whether or not to ignore OUT parameters.
* The rules for how to call functions and procedures with OUT
parameters from SQL are different.
* Client code that looks at pg_proc.proargtypes is almost certainly
going to be broken.
I don't like any of those side-effects, and I don't want to pay
those prices for what seems to me to be a bogus claim of improved
spec compliance.
regards, tom lane
On 25.05.21 17:20, Tom Lane wrote:
I don't really see how you can argue that the existing behavior is
more spec-compliant than what I'm suggesting. What I read in the spec
(SQL:2021 10.4 <routine invocation> SR 9) h) iii) 1)) is1) If Pi is an output SQL parameter, then XAi shall be a <target
specification>.(where <target specification> more or less reduces to "variable").
Now, sure, that's what we've got in plpgsql, and I'm not proposing
to change that. But in plain SQL, as of HEAD, you are supposed to
write NULL, or a random literal, or indeed anything at all *except*
a variable. How is that more standard-compliant than not writing
anything?
I concede that the current implementation is not fully standards
compliant in this respect. Maybe we need to rethink how we can satisfy
this better. For example, in some other implementations, you write CALL
p(?), (where ? is the parameter placeholder), so it's sort of an output
parameter. However, changing it so that the entire way the parameters
are counted is different seems a much greater departure.
More generally, there are enough deviations from spec in what we do
to perform ambiguous-call resolution that it seems rather silly to
hang your hat on this particular point.
I don't know what you mean by this. Some stuff is different in the
details, but you *can* write conforming code if you avoid the extremely
complicated cases. With your proposal, everything is always different,
and we might as well remove the CALL statement and name it something
else because users migrating from other systems won't be able to use it
properly.
Now as against that, we are giving up a whole lot of consistency.
As of HEAD:* The rules for what is a conflict of signatures are different
for functions and procedures.
But that's the fault of the way it was done for functions. That doesn't
mean we have to repeat it for procedures. I mean, sure it would be
better if it were consistent. But SQL-standard syntax should behave in
SQL standard ways. Creating, altering, and dropping procedures is meant
to be portable between SQL implementations. If we change this in subtle
ways so that DROP PROCEDURE p(int, int) drops a different procedure in
different SQL implementations, that seems super-dangerous and annoying.
I wrote:
* The rules for how to identify a target routine in ALTER, DROP,
etc are different for functions and procedures. That's especially
nasty in ALTER/DROP ROUTINE, where we don't have a syntax cue
as to whether or not to ignore OUT parameters.
Just to enlarge on that point a bit:
regression=# create function foo(int, out int) language sql
regression-# as 'select $1';
CREATE FUNCTION
regression=# create procedure foo(int, out int) language sql
regression-# as 'select $1';
CREATE PROCEDURE
IMO this should have failed, but since it doesn't:
regression=# drop routine foo(int, out int);
DROP ROUTINE
Which object was dropped, and what is the argument for that one
being the right one?
Experinentation shows that in HEAD, what is dropped is the procedure,
and indeed the DROP will fail if you try to use it on the function.
That is a compatibility break, because in previous versions this
worked:
regression=# create function foo(int, out int) language sql
as 'select $1';
CREATE FUNCTION
regression=# drop routine foo(int, out int);
DROP ROUTINE
The fact that you now have to be aware of these details to use
ALTER/DROP ROUTINE seems like a pretty serious loss of user
friendliness, as well as compatibility.
regards, tom lane
On Tue, May 25, 2021 at 2:20 PM Tom Lane <tgl@sss.pgh.pa.us> wrote:
Just to enlarge on that point a bit:
regression=# create function foo(int, out int) language sql
regression-# as 'select $1';
CREATE FUNCTION
regression=# create procedure foo(int, out int) language sql
regression-# as 'select $1';
CREATE PROCEDUREIMO this should have failed, but since it doesn't:
regression=# drop routine foo(int, out int);
DROP ROUTINEWhich object was dropped, and what is the argument for that one
being the right one?Experinentation shows that in HEAD, what is dropped is the procedure,
and indeed the DROP will fail if you try to use it on the function.
That is a compatibility break, because in previous versions this
worked:regression=# create function foo(int, out int) language sql
as 'select $1';
CREATE FUNCTION
regression=# drop routine foo(int, out int);
DROP ROUTINEThe fact that you now have to be aware of these details to use
ALTER/DROP ROUTINE seems like a pretty serious loss of user
friendliness, as well as compatibility.
I'm also concerned about the behavior here. I noticed it when this
commit went in, and it seemed concerning to me then, and it still
does. Nevertheless, I'm not convinced that your proposal is an
improvement. Suppose we have foo(int, out int) and also foo(int).
Then, if I understand correctly, under your proposal, foo(4) will call
the former within plpgsql code, because in that context the OUT
parameters must be included, and the latter from SQL code, because in
that context they must be emitted. I suspect in practice what will
happen is that you'll end up with both interpretations even within the
body of a plpgsql function, because plpgsql functions tend to include
SQL queries where, I presume, the SQL interpretation must apply. It
seems that it will be very difficult for users to know which set of
rules apply in which contexts.
Now, that being said, the status quo is also pretty bad, because we
have one set of rules for functions and another for procedures. I
believe that users will expect those to behave in similar ways, and
will be sad and surprised when they don't.
But on the third hand, Peter is also correct when he says that there's
not much use in implementing standard features with non-standard
semantics. The fact that we've chosen to make OUT parameters do some
random thing that is not what other systems do is, indeed, not great
for migrations. So doubling down on that questionable choice is also
not great. In a green field I think we ought to go the other way and
make OUT parameters as consistent with the standard as we can, and
have that handling be the same for procedures and for functions, but
it seems impossible to imagine making such a large compatibility break
with our own previous releases, however much the spec may dictate it.
I don't see any really great choice here, but in some sense your
proposal seems like the worst of all the options. It does not reverse
the patch's choice to treat functions and procedures differently, so
users will still have to deal with that inconsistency. But in addition
the handling of procedures will itself be inconsistent based on
context.
--
Robert Haas
EDB: http://www.enterprisedb.com
Peter Eisentraut <peter.eisentraut@enterprisedb.com> writes:
On 25.05.21 17:20, Tom Lane wrote:
I don't really see how you can argue that the existing behavior is
more spec-compliant than what I'm suggesting. What I read in the spec
(SQL:2021 10.4 <routine invocation> SR 9) h) iii) 1)) is
1) If Pi is an output SQL parameter, then XAi shall be a <target
specification>.
I concede that the current implementation is not fully standards
compliant in this respect. Maybe we need to rethink how we can satisfy
this better. For example, in some other implementations, you write CALL
p(?), (where ? is the parameter placeholder), so it's sort of an output
parameter. However, changing it so that the entire way the parameters
are counted is different seems a much greater departure.
I'd expect to be able to write something like that in contexts where
there's a reasonable way to name an output parameter. Like, say,
plpgsql. Or JDBC --- I think they already use a notation like that
for output parameters from functions, and transform it after the fact.
As things work in HEAD, they'll have to have a different special hack
for procedures than they do for functions. But none of this applies
to bare-SQL CALL.
More generally, there are enough deviations from spec in what we do
to perform ambiguous-call resolution that it seems rather silly to
hang your hat on this particular point.
I don't know what you mean by this.
Well, let's take an example. If OUT parameters are part of the
signature, then I'm allowed to do this:
regression=# create procedure p1(in x int, out y int)
regression-# language sql as 'select $1';
CREATE PROCEDURE
regression=# create procedure p1(in x int, out y float8)
language sql as 'select $1';
CREATE PROCEDURE
regression=# call p1(42, null);
y
----
42
(1 row)
I'm surprised that that worked rather than throwing an ambiguity
error. I wonder which procedure it called, and where in the spec
you can find chapter and verse saying that that one and not the other
one is right.
It gets even sillier though, because experimentation shows that it
was the int one that was preferred:
regression=# create or replace procedure p1(in x int, out y float8)
language sql as 'select $1+1';
CREATE PROCEDURE
regression=# call p1(42, null);
y
----
42
(1 row)
That seems kind of backwards really, considering that float8 is
further up the numeric hierarchy. But let's keep going:
regression=# create procedure p1(in x int, out y text)
language sql as 'select $1+2';
CREATE PROCEDURE
regression=# call p1(42, null);
y
----
44
(1 row)
So text is preferred to either int or float8. I know why that
happened: we have a preference for matching UNKNOWN to string types.
But I challenge you to provide any argument that this behavior is
spec-compliant.
More generally, the point I'm trying to make is that our rules
for resolving an ambiguous function differ in a whole lot of
details from what SQL says. That ship sailed a couple of
decades ago, so I'm not excited about adopting a fundamentally
bad design in pursuit of trying to make one small detail of
that behavior slightly closer to SQL.
[ thinks a bit ]
A lot of what I'm exercised about here is not the question of
how many parameters we write in CALL, but the choice to redefine
proargtypes (and thereby change what is considered the routine's
signature). With the infrastructure in the patch I proposed,
it'd be possible to revert the signature changes and still
write dummy output parameters in CALL -- we'd just make CALL
set include_out_parameters=true all the time. I do not think that
solution is superior to what I did in the patch, but if we can't
have a meeting of the minds on CALL, doing that much would still
be an improvement.
regards, tom lane
Robert Haas <robertmhaas@gmail.com> writes:
I'm also concerned about the behavior here. I noticed it when this
commit went in, and it seemed concerning to me then, and it still
does. Nevertheless, I'm not convinced that your proposal is an
improvement. Suppose we have foo(int, out int) and also foo(int).
Then, if I understand correctly, under your proposal, foo(4) will call
the former within plpgsql code, because in that context the OUT
parameters must be included, and the latter from SQL code, because in
that context they must be emitted.
No, you misunderstand my proposal. The thing that I most urgently
want to do is to prevent that situation from ever arising, by not
allowing those two procedures to coexist, just as you can't have
two functions with such signatures.
If procedures are required to have distinct signatures when considering
input parameters only, then a fortiori they are distinct when also
considering output parameters. So my proposal cannot make a CALL
that includes output parameters ambiguous if it was not before.
I don't see any really great choice here, but in some sense your
proposal seems like the worst of all the options. It does not reverse
the patch's choice to treat functions and procedures differently, so
users will still have to deal with that inconsistency.
You're definitely confused, because reversing that choice is *exactly*
what I'm on about. The question of whether SQL-level CALL should act
differently from plpgsql CALL is pretty secondary.
regards, tom lane
On Tue, May 25, 2021 at 3:10 PM Tom Lane <tgl@sss.pgh.pa.us> wrote:
No, you misunderstand my proposal. The thing that I most urgently
want to do is to prevent that situation from ever arising, by not
allowing those two procedures to coexist, just as you can't have
two functions with such signatures.If procedures are required to have distinct signatures when considering
input parameters only, then a fortiori they are distinct when also
considering output parameters. So my proposal cannot make a CALL
that includes output parameters ambiguous if it was not before.
Oh, OK.
I'm not sure what I think about that yet. It certainly seems to make
things less confusing. But on the other hand, I think that the
standard - or some competing systems - may have cases where they
disambiguate calls based on output arguments only. Granted, if we
prohibit that now, we can always change our minds and allow it later
if we are sure we've got everything figured out, whereas if we don't
prohibit now, backward compatibility will make it hard to prohibit it
later. But on the other hand I don't really fully understand Peter's
thinking here, so I'm a little reluctant to jump to the conclusion
that he's lost the way.
I don't see any really great choice here, but in some sense your
proposal seems like the worst of all the options. It does not reverse
the patch's choice to treat functions and procedures differently, so
users will still have to deal with that inconsistency.You're definitely confused, because reversing that choice is *exactly*
what I'm on about. The question of whether SQL-level CALL should act
differently from plpgsql CALL is pretty secondary.
I understood the reverse from the first post on the thread, so perhaps
it is more that your thinking has developed than that I am confused.
However, it's possible that I only think that because I'm confused.
--
Robert Haas
EDB: http://www.enterprisedb.com
Robert Haas <robertmhaas@gmail.com> writes:
On Tue, May 25, 2021 at 3:10 PM Tom Lane <tgl@sss.pgh.pa.us> wrote:
You're definitely confused, because reversing that choice is *exactly*
what I'm on about. The question of whether SQL-level CALL should act
differently from plpgsql CALL is pretty secondary.
I understood the reverse from the first post on the thread, so perhaps
it is more that your thinking has developed than that I am confused.
Yeah, the odd behavior of CALL is where I started from, but now I think
the main problem is with the signature (ie, allowing procedures with
signatures that differ only in OUT parameter positions). If we got
rid of that choice then it'd be possible to document that you should
only ever write NULL for OUT-parameter positions, because the type
of such an argument would never be significant for disambiguation.
We could consider going further and actually enforcing use of NULL,
or inventing some other syntactic placeholder such as the '?' that
Peter was speculating about. But I'm not sure that that adds much.
Relevant to this is that my proposed patch gets rid of the existing
behavior that such arguments actually get evaluated. That would
need to be documented, unless we go with the placeholder approach.
But I've not spent time on the documentation yet.
regards, tom lane
On 25.05.21 22:21, Tom Lane wrote:
Yeah, the odd behavior of CALL is where I started from, but now I think
the main problem is with the signature (ie, allowing procedures with
signatures that differ only in OUT parameter positions). If we got
rid of that choice then it'd be possible to document that you should
only ever write NULL for OUT-parameter positions, because the type
of such an argument would never be significant for disambiguation.
AFAICT, your patch does not main the property that
CREATE PROCEDURE p1(OUT int, OUT int)
corresponds to
DROP PROCEDURE p1(int, int)
which would be bad.
I'm not opposed to reverting the feature if we can't find a good
solution in a hurry. The main value is of this feature is for
migrations, so I want to be sure that whatever we settle on doesn't back
us into a corner with respect to that.
We could perhaps also just disable the SQL-level calling until a better
solution arises. AFAICT, things work okay in PL/pgSQL, because OUT
parameters are tied to a typed target there.
Peter Eisentraut <peter.eisentraut@enterprisedb.com> writes:
AFAICT, your patch does not main the property that
CREATE PROCEDURE p1(OUT int, OUT int)
corresponds to
DROP PROCEDURE p1(int, int)
which would be bad.
Why? If it actually works that way right now, I'd maintain
strenously that it's broken. The latter should be referring
to a procedure with two IN arguments. Even if the SQL spec
allows fuzziness about that, we cannot afford to, because we
have a more generous view of overloading than the spec does.
(As far as I could tell from looking at the spec yesterday,
they think that you aren't allowed to have two procedures
with the same name/schema and same number of arguments,
regardless of the details of those arguments. Up with that
I will not put.)
I'm not opposed to reverting the feature if we can't find a good
solution in a hurry.
I'm not looking to revert the feature. I mainly want a saner catalog
representation, and less inconsistency in object naming (which is
tightly tied to the first thing).
regards, tom lane
Here's a stripped-down patch that drops the change in what should be
in CALL argument lists, and just focuses on reverting the change in
pg_proc.proargtypes and the consequent mess for ALTER/DROP ROUTINE.
I spent some more effort on the docs, too.
regards, tom lane
Attachments:
reconsider-out-args-2.patchtext/x-diff; charset=us-ascii; name=reconsider-out-args-2.patchDownload+625-252
On 26.05.21 19:28, Tom Lane wrote:
Peter Eisentraut <peter.eisentraut@enterprisedb.com> writes:
AFAICT, your patch does not main the property that
CREATE PROCEDURE p1(OUT int, OUT int)
corresponds to
DROP PROCEDURE p1(int, int)
which would be bad.Why? If it actually works that way right now, I'd maintain
strenously that it's broken. The latter should be referring
to a procedure with two IN arguments. Even if the SQL spec
allows fuzziness about that, we cannot afford to, because we
have a more generous view of overloading than the spec does.
There is no fuzziness in the spec about this. See subclause <specific
routine designator>. It just talks about arguments, nothing about input
or output arguments. I don't find any ambiguity there. I don't see why
we want to reinvent this here.
If I have two procedures
p1(IN int, IN int, OUT int, OUT int)
p1(OUT int, OUT int)
then a DROP, or ALTER, or GRANT, etc. on p1(int, int) should operate on
the second one in a spec-compliant implementation, but you propose to
have it operate on the first one. That kind of discrepancy would be
really bad to have. It would be very difficult for migration tools to
check or handle this in a robust way.
(As far as I could tell from looking at the spec yesterday,
they think that you aren't allowed to have two procedures
with the same name/schema and same number of arguments,
regardless of the details of those arguments. Up with that
I will not put.)
I don't see that.
Peter Eisentraut <peter.eisentraut@enterprisedb.com> writes:
On 26.05.21 19:28, Tom Lane wrote:
Why? If it actually works that way right now, I'd maintain
strenously that it's broken. The latter should be referring
to a procedure with two IN arguments. Even if the SQL spec
allows fuzziness about that, we cannot afford to, because we
have a more generous view of overloading than the spec does.
There is no fuzziness in the spec about this. See subclause <specific
routine designator>. It just talks about arguments, nothing about input
or output arguments. I don't find any ambiguity there. I don't see why
we want to reinvent this here.
I agree that the spec isn't ambiguous: it says that you should be able
to uniquely identify a routine from the list of only its argument types,
without distinguishing whether those arguments are IN or OUT or INOUT,
*and* without distinguishing whether the routine is a procedure or
function.
However, that doesn't work for Postgres functions, nor for Postgres
routines (since those must include functions). I do not think that we
should confuse our users and effectively break ALTER/DROP ROUTINE in
order to make it sort-of work for procedures. The are-we-exactly-
compatible-with-the-spec ship sailed a couple of decades ago.
If I have two procedures
p1(IN int, IN int, OUT int, OUT int)
p1(OUT int, OUT int)
then a DROP, or ALTER, or GRANT, etc. on p1(int, int) should operate on
the second one in a spec-compliant implementation, but you propose to
have it operate on the first one. That kind of discrepancy would be
really bad to have.
We already have that situation for functions. I think having procedures
work differently from functions is much worse than your complaint here;
and I do not see why being spec-compliant for one case when we are not
for the other is a good situation to be in.
We could, perhaps, insist that ALTER/DROP include OUT parameters when
it is being applied to a procedure, rather than treating them as being
effectively noise words as we do now. I'd still want to revert the
definition of proargtypes, which would have implications for which
procedure signatures are considered distinct --- but it looks to me
like we would still be allowing more combinations than the spec does.
(As far as I could tell from looking at the spec yesterday,
they think that you aren't allowed to have two procedures
with the same name/schema and same number of arguments,
regardless of the details of those arguments. Up with that
I will not put.)
I don't see that.
It's under CREATE PROCEDURE. 11.60 <SQL-invoked routine> SR 20 says
20) Case:
a) If R is an SQL-invoked procedure, then S shall not include another
SQL-invoked procedure whose <schema qualified routine name> is
equivalent to RN and whose number of SQL parameters is PN.
Case b) has different and laxer rules for what you can do with functions,
but it still looks like they'd forbid a lot of situations that we allow.
I think that these restrictive overloading rules have a whole lot to do
with the fact that they feel that you don't need IN/OUT argument labeling
to correctly identify a function or procedure. But, as I said, that ship
sailed for us a long time ago.
regards, tom lane