Re: Stored procedures and out parameters

Поиск
Список
Период
Сортировка
От Shay Rojansky
Тема Re: Stored procedures and out parameters
Дата
Msg-id CADT4RqDZBQFn24_OsT0BK=J=hNJ1r4MkpHnsVA_4zsgVqJxuKA@mail.gmail.com
обсуждение исходный текст
Ответ на Re: Stored procedures and out parameters  ("David G. Johnston" <david.g.johnston@gmail.com>)
Ответы Re: Stored procedures and out parameters
Список pgsql-hackers
Apologies for disappearing from this conversation for a week.

First off, on the .NET side I have the exact same issue that Vladimir Sitnikov described for the Java side. The .NET database API (ADO.NET) has a standard, portable way for calling "server-side code". Since stored procedures are in PostgreSQL, this portable API was implemented years ago to invoke functions, which were the only thing in existence (so Npgsql issues SELECT * FROM function()). Now that stored procedures have been introduced, it's impossible to change what the portable API means without massive backwards compatibility issues for all programs which already rely on the API calling *functions*.

In other words, I really do hope that on the PostgreSQL side you consider allowing both functions and procedures to be invoked via CALL. Npgsql (and likely pgjdbc) would then be able to change the portable API to send CALL instead of SELECT, avoiding all backwards compatibility issues (they would do that only for PostgreSQL 11 and above). For now I'm telling users on the beta version to avoid the API altogether (writing CALL SQL manually), which as Vladimir wrote above is bad for portability.

> If you "DESCRIBE CALL my_func()" you get back a NoData response; it doesn't try to inspect the RETURNS clause of the function even though in theory it could.  The client is using CALL so that is it should expect to receive.  That said I'm not entirely clear whether the NoData response is a fixed bug or not...

Uh, this sounds like something we really need to understand... How is a driver supposed to know what data types are being returned if it can't use Describe? DataRow messages contain only field lengths and values, so having a type OID is critical for knowing how to interpret the data, and that currently is only available by sending a Describe on a statement... Npgsql currently always sends a describe as part of statement execution (for server-prepared messages the describe is done only once, at preparation-time). Vladimir, are you doing things differently here?


On Tue, Jul 24, 2018 at 7:57 PM, David G. Johnston <david.g.johnston@gmail.com> wrote:
On Tue, Jul 24, 2018 at 11:31 AM, Daniel Verite <daniel@manitou-mail.org> wrote:
        David G. Johnston wrote:

> > 2. A stored procedure can decide dynamically of
> > the structure of the resultset(s) it returns,
> > and the caller will discover it as they're returned, not
> > before.
> >
>
> The function itself doesn't care - this concern is about SELECT vs CALL
> invocation only, not the script definition.

It does care, because CREATE FUNCTION has a RETURNS clause and
matching RETURN statements in the body, whereas CREATE PROCEDURE
doesn't and (will?) have a different syntax for producing resultsets.

​But why does whatever code that implements CALL have to care?

In Object Oriented terms why can not both procedures and functions implement a "EXECUTE_VIA_CALL" interface; while functions additionally implement a "EXECUTE_VIA_SELECT" interface - the one that they do today.

ISTM that any (most) function could be trivially ​rewritten into a procedure (or wrapped by one) in a mechanical fashion which could then be executed via CALL.  I'm proposing that instead of having people write their own wrappers we figure out what the mechanical wrapper looks like, ideally based upon the public API of the function, and create it on-the-fly whenever said function is executed via a CALL statement.

As for the invocation, that's just the starting point.  At this point
the driver doesn't know from '{call x}' whether x is a procedure or a
function in Postgres, hence the request for a syntax that would work
for both.  Okay, but aside from that, if there are results, the driver
needs to get them in a way that works without knowing wether it's a
function or procedure. How would that happen?

I'm saying that the driver needs to rewrite {call x} as "CALL x()" and expect optional resultsets and optional output arguments.  For functions invoked as procedures this would be a single resultset with zero output arguments.  Which is exactly the same end-user result that is received today when "SELECT * FROM x()" is used.


Back to the first message of the thread, Shay Rojansky was saying:

  "However, connecting via Npgsql, which uses the extended protocol, I
  see something quite different. As a response to a Describe PostgreSQL
  message, I get back a NoData response rather than a RowDescription
  message"

Why would a Describe on a "CALL myproc()" even work if we
accept the premise that myproc() does not advertise what it may return,
contrary to a "SELECT * FROM function()"?
This issue goes beyond a "syntactic bridge" between CALL and SELECT.

​If you "DESCRIBE CALL my_func()" you get back a NoData response; it doesn't try to inspect the RETURNS clause of the function even though in theory it could.  The client is using CALL so that is it should expect to receive.  That said I'm not entirely clear whether the NoData response is a fixed bug or not...

David J.

В списке pgsql-hackers по дате отправления:

Предыдущее
От: David Rowley
Дата:
Сообщение: ATTACH/DETACH PARTITION CONCURRENTLY
Следующее
От: Tom Lane
Дата:
Сообщение: Re: [Patch] Create a new session in postmaster by calling setsid()