【问题标题】:ERROR: Define not done before fetch or execute and fetch错误:在获取或执行和获取之前定义未完成
【发布时间】:2015-05-27 13:34:20
【问题描述】:

我的应用程序从外部源(配置文件)接收查询,因此它必须从查询结果中获取列。我有一段代码:

typedef union _DbField {
    text text[512];
    sword integer;
    double precise;
} DbField;

typedef struct _Arg {
    size_t argSize;
    DbField field;
} Arg;
OCIEnv *envhp;
OCISession *authp = (OCISession *) 0;
OCIError *errhp;
OCISvcCtx *svchp;
OCIServer *srvhp;
OCIStmt *statementHandler;
OCIDefine *defnp = (OCIDefine *) 0;
sword status;

...

//int main()

    status = OCIEnvCreate((OCIEnv **) &envhp, (ub4) OCI_DEFAULT, (dvoid *) 0,
            (dvoid * (*)(dvoid *, size_t)) 0, (dvoid * (*)(dvoid *, dvoid *, size_t)) 0,
            (void (*)(dvoid *, dvoid *)) 0, (size_t) 0, (dvoid **) 0);

    checkError(0, __LINE__);

    status = OCIHandleAlloc((dvoid *) envhp, (dvoid **) &errhp, OCI_HTYPE_ERROR, (size_t) 0,
            (dvoid **) 0);
    checkError(0, __LINE__);

    status = OCIHandleAlloc((dvoid *) envhp, (dvoid **) &srvhp, OCI_HTYPE_SERVER, (size_t) 0,
            (dvoid **) 0);
    checkError(0, __LINE__);

    status = OCIHandleAlloc((dvoid *) envhp, (dvoid **) &svchp, OCI_HTYPE_SVCCTX, (size_t) 0,
            (dvoid **) 0);
    checkError(0, __LINE__);

    status = OCIHandleAlloc((dvoid *) envhp, (dvoid **) &statementHandler, OCI_HTYPE_STMT,
            (size_t) 0, (dvoid **) 0);
    checkError(0, __LINE__);

    status = OCIServerAttach(srvhp, errhp, (text *) connection->dbName, (sb4) strlen((char *) connection->dbName), 0);
    status = OCIServerAttach(srvhp, errhp, (text *) "", (sb4) strlen((char *) ""), 0);
    checkError(0, __LINE__);

    status = OCIAttrSet((dvoid *) svchp, OCI_HTYPE_SVCCTX, (dvoid *) srvhp, (ub4) 0,
    OCI_ATTR_SERVER, (OCIError *) errhp);
    if (status != 0) {
        printf("HANDLER ERROR %d !!!\n\n", status);
        exit(2);
    }

    (void) OCIHandleAlloc((dvoid *) envhp, (dvoid **) &authp, (ub4) OCI_HTYPE_SESSION,
            (size_t) 0, (dvoid **) 0);

    (void) OCIAttrSet((dvoid *) authp, (ub4) OCI_HTYPE_SESSION, (dvoid *) connection->userName,
            (ub4) strlen((char *) connection->userName), (ub4) OCI_ATTR_USERNAME, errhp);

    (void) OCIAttrSet((dvoid *) authp, (ub4) OCI_HTYPE_SESSION,
            (dvoid *) connection->userPassword,
            (ub4) strlen((char *) connection->userPassword), (ub4) OCI_ATTR_PASSWORD, errhp);

    status = OCISessionBegin(svchp, errhp, authp, OCI_CRED_RDBMS, (ub4) OCI_DEFAULT);

    (void) OCIAttrSet((dvoid *) svchp, (ub4) OCI_HTYPE_SVCCTX, (dvoid *) authp, (ub4) 0,
            (ub4) OCI_ATTR_SESSION, errhp);
    errhp, OCIHandleAlloc((dvoid *) envhp, (dvoid **) &statementHandler, OCI_HTYPE_STMT,
            (size_t) 0, (dvoid **) 0);

    executeStatement("SELECT * FROM logs order by log_id");


//end of int main()

static inline sword executeStatement(char *statement) {
    int rowsFetched = 0;
    int forSecond = 0;
    ub4 numcols = 0;
    ub2 dtype = 0;
    OCIStmt *structureHandler;
    OCIParam *colhd = (OCIParam *) 0;
    char *statementCopy = malloc(strlen(statement));
    memcpy(statementCopy, statement, strlen(statement));

    status = OCIHandleAlloc((dvoid *) envhp, (dvoid **) &structureHandler, OCI_HTYPE_STMT, (size_t) 0, (dvoid **) 0);
    checkError(1, __LINE__);

    status = OCIStmtPrepare(structureHandler, errhp, statementCopy, (ub4) strlen((char *) statement), (ub4)OCI_NTV_SYNTAX, (ub4) OCI_NO_SHARING);
    checkError(1, __LINE__);
    status = OCIStmtExecute(svchp, structureHandler, errhp, (ub4) 1, (ub4) 0,(const OCISnapshot *) NULL, (OCISnapshot *) NULL, (ub4) OCI_DESCRIBE_ONLY);
    checkError(1, __LINE__);
    OCIAttrGet((dvoid *)structureHandler, OCI_HTYPE_STMT, (dvoid *)&numcols, (ub4 *)0, OCI_ATTR_PARAM_COUNT, errhp);
    ub2 colTypes[numcols];
    Arg columns[numcols];
    for (int a = 0; a < numcols; ++a) {
        OCIParamGet((dvoid *)structureHandler, OCI_HTYPE_STMT, errhp, (dvoid **)&colhd, a+1);
        OCIAttrGet((dvoid *)colhd, OCI_DTYPE_PARAM,(dvoid *)&dtype, (ub4 *)0, OCI_ATTR_DATA_TYPE, errhp);
        colTypes[a] = dtype;
        printf("Coltype %d\t\t", colTypes[a]);
        if (colTypes[a] == SQLT_INT || colTypes[a] == SQLT_NUM) {
            columns[a].argSize = sizeof(int);
            printf("Param is %d INT, size %d ", a, columns[a].argSize);
            status = OCIDefineByPos(statementHandler, &defnp, errhp, a+1, (dvoid *)&(columns[a].field.integer), (sword) columns[a].argSize, colTypes[a], (dvoid *) 0, (ub2 *) 0, (ub2 *) 0, OCI_DEFAULT);
            if (status == 0) {
                printf("Param %d bind OK\n", a+1);
            } else {
                printf("Binding %d param caused error!!!\n", a+1);
            }
            fflush(stdout);
        } else if (colTypes[a] == SQLT_STR || colTypes[a] == SQLT_CLOB) {
            columns[a].argSize = sizeof(char)*1024;
            status = OCIDefineByPos(statementHandler, &defnp, errhp, a+1, (dvoid *)&(columns[a].field.text), (sword) columns[a].argSize, colTypes[a], (dvoid *) 0, (ub2 *) 0, (ub2 *) 0, OCI_DEFAULT);
            printf("Param is %d STR, size %d ", a, columns[a].argSize);
            if (status == 0) {
                printf("Param %d bind OK\n", a+1);
            } else {
                printf("Binding %d param caused error!!!\n", a+1);
            }
            fflush(stdout);
        } else if (colTypes[a] == SQLT_TIMESTAMP) {
            columns[a].argSize = sizeof(char)*768;
            status = OCIDefineByPos(statementHandler, &defnp, errhp, a+1, (dvoid *)&(columns[a].field.text), (sword) columns[a].argSize, colTypes[a], (dvoid *) 0, (ub2 *) 0, (ub2 *) 0, OCI_DEFAULT);
            printf("Param is %d TIMESTAMP, size %d ", a, columns[a].argSize);
            if (status == 0) {
                printf("Param %d bind OK\n", a+1);
            } else {
                printf("Binding %d param caused error!!!\n", a+1);
            }
            fflush(stdout);
        } else {
            //Other types are not needed for me right now
            perror("Invalid column type\n\n");
            printf("Other type for [%d]: %d\n", a, colTypes[a]);
            fflush(stdout);
            exit(3);
        }

    }

    status = OCIStmtPrepare(statementHandler, errhp, statement, (ub4) strlen((char *) statement), (ub4)OCI_NTV_SYNTAX, (ub4) OCI_DEFAULT);
    checkError(0, __LINE__);
    //ERROR IN LINE ABOVE
    status = OCIStmtExecute(svchp, statementHandler, errhp, (ub4) 1, (ub4) 0,(const OCISnapshot *) NULL, (OCISnapshot *) NULL, (ub4) OCI_DEFAULT);
    checkError(0, __LINE__);

    status = OCIAttrGet(statementHandler, OCI_HTYPE_STMT, (void*)&rowsFetched, NULL, OCI_ATTR_ROWS_FETCHED, errhp);
    printf("Total rows: %d, status %d.\n", rowsFetched, status);

    if (rowsFetched == 0) {
        printf("No data!\n");
        return OCI_NO_DATA;
    }

    do {
        printf("ROW ");
        for (int a = 0; a < numcols; ++a) {
            if (colTypes[a] == SQLT_INT || colTypes[a] == SQLT_NUM) {
                printf(" INT %d", columns[a].field.integer);
            } else if (colTypes[a] == SQLT_STR || colTypes[a] == SQLT_CLOB) {
                printf(" TXT %s", columns[a].field.text);
            } else if (colTypes[a] == SQLT_TIMESTAMP) {
                printf(" TIMESTAMP %s", columns[a].field.text);
            } else {
                perror("Invalid column type\n\n");
                printf("Other type for [%d]: %d\n", a, colTypes[a]);
                fflush(stdout);
                exit(3);
            }
        }
        printf("\n");
        status = OCIStmtFetch2(statementHandler, errhp, 1, OCI_DEFAULT, (sb4) 1, OCI_DEFAULT);
    } while (status != OCI_NO_DATA && status != OCI_ERROR);

    return OCI_SUCCESS;
}

标记行中的此代码导致错误 ORA-24374:define not done before fetch 或 executeand fetch。我的应用程序说列数与查询匹配并且绑定正常。我不知道该怎么办。

【问题讨论】:

    标签: c database oracle oracle-call-interface


    【解决方案1】:

    你需要移动这条线:

    status = OCIStmtPrepare(statementHandler, errhp, statement, (ub4) strlen((char *) statement), (ub4)OCI_NTV_SYNTAX, (ub4) OCI_DEFAULT);
    

    ...在您开始致电OCIDefineByPos(statementHandler, ...)之前。

    在你对structureHandler 做任何事情之前,这可能是executeStatement 中的第一个OCI 调用。但无论如何,它必须在for (int a = 0; a &lt; numcols; ++a) 循环之前。

    我相信在早期版本(9i 及之前的版本?)中没有强制执行该顺序,但现在您必须在定义绑定变量之前做好准备。

    【讨论】:

    • 现在我有分段错误。
    • @PingwinTux - 我没有错;我不得不编写一些代码,它似乎只能识别数字列并且得到错误的数字(例如select 10 from dual 显示ROW INT 3009),所以无论如何我都在做一些不同的事情......如果在您发布的代码还是其他地方?
    • 确实,分段错误与指向 char[] 的指针有关。整数不会崩溃,但值仍然是错误的。似乎给 OCIDefineByPos 的指针是无效的。
    • @PingwinTux - 你似乎在混淆类型; SQLT_INT 和 SQLT_NUM 不可互换。如果您强制绑定使用 SQLT_INT(因为您绑定到结构中的 int),它将获得正确的值。当然,您可能不仅要处理整数。对于您的 sigsegv,.text 字段的绑定不需要&amp;?
    • 现在我有正确的数字。所以,我应该有 status = OCIDefineByPos(statementHandler, &defnp, errhp, a+1, (dvoid *)(columns[a].text), (sword) 列[a].argSize, colTypes[a], (dvoid *) 0, (ub2 *) 0, (ub2 *) 0, OCI_DEFAULT);对于 char[512] 类型?
    猜你喜欢
    • 2013-10-17
    • 2015-09-25
    • 1970-01-01
    • 1970-01-01
    • 2018-04-12
    • 2015-07-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多