2015-05-27 1 views
0

Мое приложение получает запрос из внешнего источника (файл конфигурации), так что ему нужно получить столбцы из результата запроса. У меня есть кусок кода:ОШИБКА: определение не выполнено до извлечения или выполнения и извлечения

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: определить не сделано до извлечения или executeand выборки. В моем приложении указано, что количество столбцов соответствует запросу и привязке в порядке. Я понятия не имею, что делать.

ответ

1

Вы должны переместить эту строку:

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

... прежде чем начать вызов OCIDefineByPos(statementHandler, ...).

Это может быть первый вызов OCI в executeStatement действительно, прежде чем что-либо сделать с structureHandler. Во всяком случае, это должно быть до цикла for (int a = 0; a < numcols; ++a).

Я считаю, что порядок не был применен так же строго в ранних версиях (9i и раньше?), Но теперь вам нужно подготовить, прежде чем вы сможете определить переменные связывания.

+0

Теперь у меня есть ошибка сегментации. –

+1

@PingwinTux - я не ошибаюсь; Я должен был сделать часть кода, и только кажется, что он распознает числовые столбцы и ошибочно присваивает номер ('select 10 from dual' показывает' ROW INT 3009', например), поэтому я делаю что-то другое в любом случае ... Является ли ошибка в коде, который вы опубликовали, или где-то еще? –

+0

Действительно, ошибка сегментации была связана с указателем на char []. Целые числа не сбрасываются, но значения все еще ошибочны. Кажется, что указатели, указанные в OCIDefineByPos, недействительны. –

Смежные вопросы