On 15/01/2013 17:52, Charles Jardine wrote:
On 15/01/13 16:01, Martin J. Evans wrote:
On 15/01/13 15:04, Charles Jardine wrote:

Are you saying that, in the case of a NULL variable, the indicator
variable does not indicate nullity?

I am saying when you have:

procedure fred(pcur OUT SYS_REFCURSOR) as
begin
pcur := NULL;
end;

then the output parameter DBD::Oracle sees appears to be a valid Oracle
statement as you can call OCIAttrGet for OCI_ATTR_STMT_STATE and it
works. The following snippet illustrates this:

OCIAttrGet_stmhp_stat2(imp_sth, (OCIStmt*)phs->desc_h, &stmt_state, 0,
                                OCI_ATTR_STMT_STATE, status);

The desc_h in the parameters must be an OCIStmt * or surely this would
not work.

In this case the REF CURSOR variable in question is explicitly null.
I would expect the value returned via OCI to be accompanied by an
indicator variable with a value of -1,indicating a null value.
If this is the case, the value of the output variable is,
to quote the OCI manual, 'unchanged'. It should be ignored.

I am suggesting that the indicator variable should be tested before
the looking at the value. If indicator is -1, the value could be
the cursor returned by a previous execution of the same statement
handle.

Thanks Charles.

I think your explanation means DBD::Oracle is even more broken than I thought wrt to output cursors.

Looks like I need to do a bit more reading. Thanks for the pointer.

Out of interest I looked at the code a little more and see the descriptor in the D::O's phs is freed and reallocated pre-execute. The parameter is also rebound. In pp_exec_rset it does (note my comment labelled MJE):

if (pre_exec) { /* pre-execute - allocate a statement handle - MJE it does not do this now */
        sword status;

        /* extproc deallocates everything for us */
        if (is_extproc)
            return 1;

        /* MJE what is the following test supposed to be - always true? */
        if (!phs->desc_h || 1) { /* XXX phs->desc_t != OCI_HTYPE_STMT) */
            if (phs->desc_h) {
OCIHandleFree_log_stat(imp_sth, phs->desc_h, phs->desc_t, status);
                phs->desc_h = NULL;
            }
            phs->desc_t = OCI_HTYPE_STMT;
OCIHandleAlloc_ok(imp_sth, imp_sth->envhp, &phs->desc_h, phs->desc_t, status);
         }

        phs->progv = (char*)&phs->desc_h;
        phs->maxlen = 0;

OCIBindByName_log_stat(imp_sth, imp_sth->stmhp, &phs->bndhp, imp_sth->errhp,
            (text*)phs->name,
            (sb4)strlen(phs->name),
            phs->progv,
            0,
            (ub2)phs->ftype,
            NULL, /* using &phs->indp triggers ORA-01001 errors! */
            NULL,
            0,
            0,
            NULL,
            OCI_DEFAULT,
            status);

However, as you said the phs->indp is -1 as you said. I will correct my change and make it check indp first.

As you know there is a lot of OCI code in DBD::Oracle and I'm not familiar with it all by a long way so I'm always grateful for any pointers/help.

Martin

Reply via email to