错误:在获取或执行和获取之前定义未完成

时间:2015-05-27 13:34:21

标签: c database oracle oci

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

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:在获取或执行和获取之前未定义。我的应用程序说列数与查询匹配,绑定没问题。我不知道该怎么做。

1 个答案:

答案 0 :(得分:1)

你需要移动这一行:

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

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

在您使用executeStatement执行任何操作之前,它可能是structureHandler中的第一个OCI调用。但无论如何,它需要在for (int a = 0; a < numcols; ++a)循环之前。

我认为在早期版本(9i及之前的版本?)中强行执行的命令并不强烈,但现在您必须先准备好才能定义绑定变量。