OCI-21560 OCIObjectNew OCI_TYPECODE_TABLE - PullRequest
0 голосов
/ 08 ноября 2018

Я застрял с этой проблемой на некоторое время.Я прошел через тонны кода / примеров и документов по этому (хотя и немного).

Я пытаюсь сделать следующее: Чтение и запись таблиц PL / SQL через параметры процедуры IN / OUT с использованием OCI из C.

Пакет Oracle определяется следующим образом:

DROP PACKAGE pkg_test;
DROP TYPE ARRRECNR;
DROP TYPE ARRRECDATA;

CREATE OR REPLACE TYPE ARRRECNR IS TABLE OF NUMBER(8);
/
CREATE OR REPLACE TYPE ARRRECDATA IS TABLE OF VARCHAR2(4000);
/

CREATE OR REPLACE PACKAGE pkg_test
IS
    PROCEDURE test_proc1 (
      p_RecordNr In ARRRECNR,
      p_RecordData In ARRRECDATA,
      p_RecCount OUT Number,
      p_outrecorddata OUT ARRRECDATA
    );
END;
/

CREATE OR REPLACE PACKAGE BODY pkg_test
IS
   PROCEDURE test_proc1 (
      p_RecordNr In ARRRECNR,
      p_RecordData In ARRRECDATA,
      p_RecCount OUT Number,
      p_OutRecordData OUT ARRRECDATA
  ) IS
BEGIN
    p_RecCount = 0;
    p_OutRecordData := ARRRECDATA();
   FOR I IN 1..p_RecordData.COUNT
   LOOP
      p_OutRecordData.extend();
      p_OutRecordData(I) := p_RecordData(I) || ' ' || to_char(p_RecordNr(I));
      p_RecCount := p_RecCount + I;
    END LOOP;
END test_proc1;

END pkg_test;
/

И теперь я пытаюсь вызвать следующий PL / SQL:

BEGIN
    pkg_test.test_proc1 (
        P_RECORDNR => :P_RECORDNR,
        P_RECORDDATA => :P_RECORDDATA,
        P_RECCOUNT => :P_RECCOUNT,
        P_OUTRECORDDATA => :P_OUTRECORDDATA
    );
END
/

И вызов C(OCI) выглядит следующим образом:

status = OCIStmtPrepare2(..., &stmthp,...
                         NULL /*const OraText *key*/,
                         0 /*ub4 keylen*/,
                         OCI_NTV_SYNTAX,
                         OCI_DEFAULT);

if (status != OCI_SUCCESS) { return -1; }

OCIBind *bindpp_P_RECCOUNT = NULL;
sword P_RECCOUNT = 0;
status = OCIBindByName(stmthp, &bindpp_P_RECCOUNT, errhp,
            (text *)":P_RECCOUNT", strlen(":P_RECCOUNT"),
            (ub1 *)&P_RECCOUNT, (sword)sizeof(P_RECCOUNT),
            SQLT_INT, (dvoid *)0, (ub2 *)0, (ub2)0, (ub4)0, (ub4 *)0,
            OCI_DEFAULT);
if (status != OCI_SUCCESS) { return -1; }

OCIBind *bindpp_P_RECORDNR = NULL;
status = OCIBindByName(stmthp, &bindpp_P_RECORDNR, errhp, (text *)":P_RECORDNR",
                     -1, NULL /*void *valuep*/,
                     (sb4)sizeof(OCITable *) /*sb4 value_sz*/,
                     SQLT_NTY /*ub2 dty*/,
                      NULL /*void *indp*/,
                      NULL /*ub2 *alenp*/,
                      NULL /*ub2 *rcodep*/,
                      0 /*ub4 maxarr_len*/,
                      NULL /*ub4 *curelep*/,
                     OCI_DEFAULT /*ub4 mode*/);
if (status != OCI_SUCCESS) { return -1; }

OCIBind *bindpp_P_RECORDDATA = NULL;
status = OCIBindByName(stmthp, &bindpp_P_RECORDDATA, errhp, ":P_RECORDDATA", (sb4)-1,
                      NULL /*void *valuep*/, (sb4)sizeof(OCITable *) /*sb4 value_sz*/,
                     SQLT_NTY /*ub2 dty*/, NULL /*void *indp*/, NULL /*ub2 *alenp*/,
                      NULL /*ub2 *rcodep*/, 0 /*ub4 maxarr_len*/, NULL /*ub4 *curelep*/,
                     OCI_DEFAULT /*ub4 mode*/);
if (status != OCI_SUCCESS) { return -1; }

OCIBind *bindpp_P_OUTRECORDDATA = NULL;
status = OCIBindByName(stmthp, &bindpp_P_OUTRECORDDATA, errhp, ":P_OUTRECORDDATA",(sb4)-1,
                      NULL /*void *valuep*/,(sb4)sizeof(OCITable *) /*sb4 value_sz*/,
                     SQLT_NTY /*ub2 dty*/,
                      NULL /*void *indp*/, NULL /*ub2 *alenp*/, NULL /*ub2 *rcodep*/,
                      0 /*ub4 maxarr_len*/, NULL /*ub4 *curelep*/, OCI_DEFAULT /*ub4 mode*/);
if (status != OCI_SUCCESS) { return -1; }

OCIType *ArrRecNr = NULL;
status = OCITypeByName(envhp, errhp, svchp, NULL, 0,
                      "ARRRECNR", (ub4)strlen("ARRRECNR"),
                      NULL, 0, OCI_DURATION_SESSION,
                     OCI_TYPEGET_ALL, &ArrRecNr);
if (status != OCI_SUCCESS || !ArrRecNr) { return -1; }


OCIType *ArrRecData = NULL;
status = OCITypeByName(envhp, errhp, svchp, NULL, 0,
                      "ARRRECDATA", (ub4)strlen("ARRRECDATA"),
                      NULL, 0, OCI_DURATION_SESSION,
                     OCI_TYPEGET_ALL, &ArrRecData);
if (status != OCI_SUCCESS || !ArrRecData) { return -1; }

OCITable *in_P_RECORDNR = NULL;
status = OCIObjectNew(envhp, errhp, svchp,
                     OCI_TYPECODE_TABLE, bindpp_P_RECORDNR,
                      NULL, OCI_DURATION_SESSION,
                      TRUE, &in_P_RECORDNR);

if (status != OCI_SUCCESS)
{
    printf("\nOCIObjectNew(envhp %p, errhp %p, svchp %p,\n"
      "OCI_TYPECODE_TABLE %d, bindpp_P_RECORDNR %p\n"
      "NULL %p, OCI_DURATION_SESSION %d\n"
      "TRUE %d, &in_P_RECORDNR %p)\n",
     envhp, errhp, svchp,
     OCI_TYPECODE_TABLE, bindpp_P_RECORDNR,
      NULL, OCI_DURATION_SESSION,
      TRUE, &in_P_RECORDNR);
    return -1;
}

Полный код

При попытке вызвать OCIBindByName возникает следующая ошибка:

 OCI-21560: argument 4 is null, invalid, or out of range

Сервер

Oracle Database 11g Express Edition Release 11.2.0.2.0 - 64bit Production
PL/SQL Release 11.2.0.2.0 - Production
CORE    11.2.0.2.0      Production
TNS for Linux: Version 11.2.0.2.0 - Production
NLSRTL Version 11.2.0.2.0 - Production

Клиент

 instantclient_12_1

Я проверил все входные данныепараметры и 4-й не NULL:

OCIObjectNew(
    envhp 0000027D223CE9B0,
    errhp 0000027D223FC590,
    svchp 0000027D223FB808,
    OCI_TYPECODE_TABLE 248,
    bindpp_P_RECORDNR 0000027D23D6B1B0,
    NULL 0000000000000000,
    OCI_DURATION_SESSION 10,
    TRUE 1,
    &in_P_RECORDNR 000000BCD47FFE00
)

Чего мне не хватает?

...