On Wed, 12 Aug 2009 05:06:14 -0700 (PDT)
Tarun Pasrija <tarun....@in.ibm.com> wrote:
[snip]
> stmt, name, second_name, weight = ibm_db.callproc(conn,
> 'schemaName.match_animal', (name, second_name, weight))
> #schemaName is optional if schema name not specified than it uses
> current default schema
[snip]
If the schema name isn't specified, the current path should be searched
to qualify the procedure name. See the entries for the "CURRENT
PATH" [1] special register and the "SET PATH" [2] statement in the
InfoCenter.
I haven't checked the code, but I'm assuming it doesn't *really*
qualify the procedure name and then call it - but simply leaves the
qualification to the database, in which case this is just a
documentation bug.
[1]
http://publib.boulder.ibm.com/infocenter/db2luw/v9r7/topic/com.ibm.db2.luw.sql.ref.doc/doc/r0005877.html
[2]
http://publib.boulder.ibm.com/infocenter/db2luw/v9r7/topic/com.ibm.db2.luw.sql.ref.doc/doc/r0001014.html
Cheers,
Dave.
>
> Just to clarify the real reason for all this complex stuff...
>
> the core of the issue is the new signature of the callProc method. If
> you look at it, removes the need for the developer to do prepare/
> bindParams. What this means is now the implementation has to do this
> i.e. bindParams. So how does it know how to bind the parameters ?
Typically, by asking the database to describe the type of each
parameter with the SQLDescribeParam() [1] and SQLNumParams() [2] API
calls after performing SQLPrepare() [3] on a CALL statement.
How does one construct the CALL statement with the right number of
markers in the first place? Look at the number of elements in the tuple
of parameters passed to callproc() at a guess (if a parameter is a pure
OUT parameter instead of INOUT, then the value can simply be ignored;
it will simply serve to inform the method of the number of parameters
to utilize).
> how
> many, what types etc - it uses the catalog API and more specifically
> SQLProcedureColumns to figure out # of columns and their types etc.
There should never be any need to query the catalog at all. The process
of preparing the statement (with SQLPrepare) will cause the optimizer
to determine the type and direction of all parameters at which point
one can simply ask the database about them (with the aforementioned
calls).
Incidentally, I'd strongly discourage any such catalog querying method
anyway on the grounds that getting the name parsing correct is *hard*.
Again, I haven't looked at the code but I wonder how it would handle a
pathologically silly, but still perfectly valid example like:
callproc(conn, '"My Silly.""Schema""\nName".SOME_PROC', (
foo, bar, baz))
Would the code correctly ignore the period in the schema name,
maintain the mixed case, strip the surrounding double quotes, replace
the doubled double-quotes with single double-quotes and then use the
result in the query? If it would then I'm most impressed, although it's
still the wrong tactic here...
> Now comes the issue - the catalog API's do not honor CURRENT PATH (or
> CURRENT SCHEMA).
And with good reason, because while the catalog APIs are standard (in as
much as they're defined by ODBC which is the basis of DB2's CLI), the
CURRENT SCHEMA and CURRENT PATH special registers are DB2 specific (I'm
not sure if they're part of the SQL standard in general, but if they
are they're another largely ignored part - also with good reason ;-).
Hence, the catalog APIs have no means of representing these concepts
(obviously a straight query against the catalog views like
SYSCAT.ROUTINEPARMS would, but SYSCAT is DB2 for LUW specific, and
you're targetting several other platforms too, so this isn't a
solution either).
Cheers,
Dave.
On Mon, 17 Aug 2009 10:01:02 -0700 (PDT)
Tarun Pasrija <tarun....@in.ibm.com> wrote:
> Checking back the infocenter for SQLDescribeParam
> http://publib.boulder.ibm.com/infocenter/db2luw/v9r7/topic/com.ibm.db2.luw.apdv.cli.doc/doc/r0000582.html
>
> Excerpt:-
> SQLDescribeParam() does not return the type (input, input/output, or
> output) of a parameter in an SQL statement. Except in calls to stored
> procedures, all parameters in SQL statements are input parameters. To
> determine the type of each parameter in a call to a stored procedure,
> call SQLProcedureColumns().
Ah, I'd missed that bit. How annoying.
> However, having a solution using SQLProcedureColumns would be a
> problem like you correctly mentioned that the naming convention
> defining the procedure name and schema name can have multiple special
> characters enclosed inside quotes.
Indeed. DB2's particularly "generous" with delimited identifiers even
allowing things like newline characters within them (I vaguely recall
testing it once and finding the only thing I couldn't reliably include
in a delimited identifier was a NULL (\0) character!).
Thankfully there's rarely any case for a driver to perform name parsing
(there are exceptions to that, but they're generally only for cases of
databases or drivers which are dealing with badly designed interfaces;
not the case here).
> Thus, we have come to a following workaroung, which works fine(though
> we are verifying its correctness).
> Instead of calling catalogue for extracting information, we bind the
> params for all IN/OUT/INOUT as INOUT which I believe is a superset of
> all.
Interesting. Personally, in such a circumstance I would've been tempted
to alter the prototype of the callproc function so that the direction
would be included with each parameter value, e.g.:
# Somewhere in the driver definition
(IN, OUT, INOUT) = range(3)
# Example client code
(stmt, b, c) = callproc(conn, 'FOO', (
('a', IN), ('b', INOUT), (None, OUT)))
However, if binding all parameters as INOUT works in all scenarios
(INOUT as IN, OUT, and INOUT) then it's a nice solution which keeps the
callproc prototype pleasantly simple.
Cheers,
Dave.