<div dir="ltr"><div><font face="monospace, monospace">Hi folks,</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">As PostgreSQL has had named parameters in stored procedures since version 9.0, I</font></div><div><font face="monospace, monospace">have taken to adding support for the feature in the DBAPI-complicant Python</font></div><div><font face="monospace, monospace">wrapper, psycopg2: <a href="https://github.com/psycopg/psycopg2/pull/16/files">https://github.com/psycopg/psycopg2/pull/16/files</a>.</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">The feature allows the "callproc" method to be invoked, in addition to the</font></div><div><font face="monospace, monospace">standard, tuple-y way, like this: cur.callproc('some_proc', { some_param:</font></div><div><font face="monospace, monospace">'some_value', ... })</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">While implementing the feature I stumbled upon the DBAPI spec for callproc:</font></div><div><font face="monospace, monospace"><a href="http://legacy.python.org/dev/peps/pep-0249/#callproc">http://legacy.python.org/dev/peps/pep-0249/#callproc</a>. It states that "the result</font></div><div><font face="monospace, monospace">of the call is returned as modified copy of the input sequence. Input parameters</font></div><div><font face="monospace, monospace">are left untouched, output and input/output parameters replaced with possibly</font></div><div><font face="monospace, monospace">new values." It then goes onto say that "The procedure may also provide a result</font></div><div><font face="monospace, monospace">set as output."</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">I would like to challenge the former requirement, and make the latter</font></div><div><font face="monospace, monospace">statement a strict requirement.</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">The former requirement of returning the modified input sequence effectively</font></div><div><font face="monospace, monospace">forces cur.callproc to examine its result set and copy it over the input</font></div><div><font face="monospace, monospace">sequence. This is not only redundant, but in fact undefined for result sets with</font></div><div><font face="monospace, monospace">more than one row. The requirement's definition is moreover self-contradictory,</font></div><div><font face="monospace, monospace">because output parameters are not *in* the input sequence.</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">The aforementioned result set is a sufficient and intuitive tool for extracting</font></div><div><font face="monospace, monospace">data from a stored procedure call. As mechanisms for returning data, stored</font></div><div><font face="monospace, monospace">procedures are not very different from queries. All queries yield result sets.</font></div><div><font face="monospace, monospace">All stored procedures yield result sets. Some queries yield empty result sets.</font></div><div><font face="monospace, monospace">Some stored procedures yield empty result sets. As such, I would argue that,</font></div><div><font face="monospace, monospace">like a query (e.g. cur.execute on a SELECT statement) cur.callproc *must* endow</font></div><div><font face="monospace, monospace">the cursor with a result set.</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">I propose changing the DBAPI spec on callproc to be as follows:</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">(This method is optional since not all databases provide stored</font></div><div><font face="monospace, monospace">procedures.)</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">Call a stored database procedure with the given name. The sequence of parameters</font></div><div><font face="monospace, monospace">must contain one entry for each argument that the procedure expects. Overloaded</font></div><div><font face="monospace, monospace">procedures are supported. If the underlying database supports named parameters</font></div><div><font face="monospace, monospace">in stored procedures, the sequence of parameters may be given as a</font></div><div><font face="monospace, monospace">dictionary-like object mapping parameter names to values.</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">The procedure must provide a result set as output. This is then made available</font></div><div><font face="monospace, monospace">through the standard fetch* methods.</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">Return values are not defined.</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">Thank you,</font></div><div><font face="monospace, monospace">Milosz</font></div></div>