2012-02-18 2 views
0

このコードでMSSQL ODBC 10.0クライアントドライバと9.0で出力パラメータを設定する際に問題が発生します。私の縛り方向が正しく設定されていることを確認できます。出力パラメータにMSSQLが設定されていないODBC

私はSQLMoreResultsも呼び出していますが、私のストアドプロシージャにはNOCOUNTが設定されており、別のODBCベースのライブラリでうまく動作します。

残念ながら、私はSQL文を実行すると成功しますが、SQLMoreResultsはそれ以上の結果はないと常に言いますが、すべての結果セットを通過するまでこれらのパラメータは設定されません。私が使用する1つの出力パラメータはbigintです。

残念ながら、私はODBC開発の複雑さをすべて知りませんし、欠けているものがあるはずです。私はステートメントハンドルを再利用しようとしますが、SQLProcedureColumnsへの最初の呼び出しの後にリセットし、バインドされた変数を削除します。それから私は元に戻る。

私が迷っている場所についてのアイデアはありますか?

bool ODBCConnection::Execute() 
{ 
    LLOG("Execute " << (void *)this << " " << (void *)session); 
    if(session->hstmt == SQL_NULL_HANDLE) 
     return false; 
    if(IsCurrent()) 
     session->current = NULL; 
    session->FlushConnections(); 
    last_insert_table.Clear(); 
    number.Clear(); 
    text.Clear(); 
    time.Clear(); 
    CParser p(statement); 

    /* parse for stored procedure */ 

    bool isStoredProcedure = false; 

    if (p.Char('{')) 
    { 
     p.Spaces(); 

      String procedure_name; 

      p.Id("?"); 
      p.Id("="); 

     if (p.Id("call") || p.Id("CALL")) { 
      procedure_name = p.ReadId(); 
      isStoredProcedure = true; 
      //Cout() << "Proc name: " << procedure_name << "\n"; 
     } 

     SQLSetEnvAttr(session->henv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER) SQL_OV_ODBC3, SQL_IS_INTEGER); 

     SDWORD  cbValue5; 
     SDWORD  cbValue4; 
     SQLSMALLINT ParameterType = SQL_PARAM_INPUT; 

     if (!IsOk(SQLProcedureColumns (
         session->hstmt, 
         NULL, 
         0, 
         NULL, 
         0, 
         (SQLCHAR *)~procedure_name, 
         procedure_name.GetLength(), 
         NULL, 
         0 
       ))) { 
      SQLFreeStmt(session->hstmt, SQL_CLOSE); 
      return false; 
     } 

     char parameter_name [20]; 

     if (!IsOk(SQLBindCol(
         session->hstmt, 
         4, // Column 4 returns column name 
         SQL_C_CHAR, 
         parameter_name, 
         sizeof(parameter_name), 
         &cbValue4 
       ))) { 
     } 

     if (!IsOk(SQLBindCol(
         session->hstmt, 
         5, // Column 5 returns whether parameter is input or output 
         SQL_C_SHORT, 
         &ParameterType, 
         0, 
         &cbValue5 
       ))) { 
     } 

     int i = 0; 
     while (SQLFetch(session->hstmt) == SQL_SUCCESS) { 
      Param& p = param[i]; 

      Cout() << ParameterType << "\n";  

      /*switch (ParameterType) { 
       case SQL_PARAM_INPUT: 
       case SQL_PARAM_OUTPUT: 
       case SQL_PARAM_INPUT_OUTPUT: 
        p.direction = ParameterType; 
        break; 

       case 5: 
        p.direction = SQL_PARAM_OUTPUT; 
        break; 
       default: 
        break; 
      }*/ 

      if(ParameterType == 5) 
       p.direction = SQL_PARAM_OUTPUT; 
      else 
       p.direction = ParameterType; 

      i++; 
     } 

     SQLFreeStmt(session->hstmt, SQL_CLOSE); 
     SQLFreeStmt(session->hstmt, SQL_RESET_PARAMS); 
     SQLFreeStmt(session->hstmt, SQL_UNBIND); 
    } 

    if((p.Id("insert") || p.Id("INSERT")) && (p.Id("into") || p.Id("INTO")) && p.IsId()) 
     last_insert_table = p.ReadId(); 

    if(!IsOk(SQLPrepare(session->hstmt, (SQLCHAR *)~statement, statement.GetCount()))) 
      return false; 

    parse = false; 
    bparam = param; 
    param.Clear(); 

    for(int i = 0; i < bparam.GetCount(); i++) { 
     Param& p = bparam[i]; 
     SQLSMALLINT  DataType; 
     SQLULEN   ParameterSize; 
     SQLSMALLINT  DecimalDigits; 
     SQLSMALLINT  Nullable; 

     Cout() << "Direction: " << p.direction << "\n"; 
     Cout() << "Length: " << p.li << "\n"; 

     if(!IsOk(SQLDescribeParam(session->hstmt, i + 1, &DataType, &ParameterSize, &DecimalDigits, &Nullable))) 
      return false; 
     if(!IsOk(SQLBindParameter(session->hstmt, i + 1, p.direction, p.ctype, DataType, 
            ParameterSize, DecimalDigits, (SQLPOINTER)~p.data, p.data.GetLength(), 
            &p.li))) 
      return false; 
    } 
    SQLSMALLINT ncol; 


    if(!isStoredProcedure) 
    { 

     if(!IsOk(SQLExecute(session->hstmt)) || !IsOk(SQLNumResultCols(session->hstmt, &ncol))) { 
      Cout() << "SQLExecute crashed\n"; 
      SQLFreeStmt(session->hstmt, SQL_CLOSE); 
      return false; 
     } 
    } 
    else 
    { 
     Cout() << "statement: " << statement << "\n"; 

     if(!IsOk(SQLExecute(session->hstmt))) { 
      Cout() << "SQLExecute crashed\n"; 
      SQLFreeStmt(session->hstmt, SQL_CLOSE); 
      return false; 
     } 

     Cout() << "Calling SQLMoreResults...\n"; 

     //SQLFreeStmt(session->hstmt, SQL_CLOSE); 
     int iReturn = SQLMoreResults(session->hstmt); 

     Cout() << "SQLMoreResults return code: " << iReturn << "\n"; 

     while (iReturn == SQL_SUCCESS || iReturn == SQL_SUCCESS_WITH_INFO) 
     { 
      iReturn = SQLMoreResults(session->hstmt); 
     } ; 
     //SQLFreeStmt(session->hstmt, SQL_RESET_PARAMS); 
     //SQLFreeStmt(session->hstmt, SQL_UNBIND); 
     ncol = 0; 
    } 

    session->current = this; 
    info.Clear(); 
    binary.Clear(); 
    for(int i = 1; i <= ncol; i++) { 
     SQLCHAR  ColumnName[256]; 
     SQLSMALLINT NameLength; 
     SQLSMALLINT DataType; 
     SQLULEN  ColumnSize; 
     SQLSMALLINT DecimalDigits; 
     SQLSMALLINT Nullable; 
     if(!IsOk(SQLDescribeCol(session->hstmt, i, ColumnName, 255, &NameLength, &DataType, 
           &ColumnSize, &DecimalDigits, &Nullable))) 
      return false; 
     binary.Add(false); 
     SqlColumnInfo& f = info.Add(); 
     f.nullable = Nullable != SQL_NO_NULLS; 
     f.binary = false; 
     f.precision = DecimalDigits; 
     f.scale = 0; 
     f.width = ColumnSize; 
     f.name = (char *)ColumnName; 
     switch(DataType) { 
     case SQL_DECIMAL: 
     case SQL_NUMERIC: 
     case SQL_SMALLINT: 
     case SQL_INTEGER: 
     case SQL_REAL: 
     case SQL_FLOAT: 
     case SQL_DOUBLE: 
     case SQL_BIT: 
     case SQL_TINYINT: 
      f.type = DOUBLE_V; 
      break; 
     case SQL_BIGINT: 
      f.type = INT64_V; 
      break; 
     case SQL_TYPE_DATE: 
     case SQL_TYPE_TIMESTAMP: 
      f.type = TIME_V; 
      break; 
     case SQL_BINARY: 
     case SQL_VARBINARY: 
     case SQL_LONGVARBINARY: 
      f.type = STRING_V; 
      f.binary = true; 
      binary.Top() = true; 
      break; 
     default: 
      f.type = STRING_V; 
      break; 
     } 
    } 
    SQLLEN rc; 
    SQLRowCount(session->hstmt, &rc); 
    rowsprocessed = rc; 


    return true; 
} 
+0

ODBC管理者のODBCトレースをオンにして、後でログを参照するか、どこかに投稿して読んでみてください。 – bohica

答えて

0

気にしないで、私はばかげていました。私のパラメータバインディングは実際にはデータのコピーにバインドされ、実際のデータ自体にはバインドされませんでした。助けようとした皆様に感謝します。

0

SQLProfileを有効にしましたか?たぶんそれを起動し、実際のSQLがデータベースに当たるのを見て、それらのSQL文を取ってSSMSで直接実行して、期待通りのことを確認してください。

+0

いいえ、私はしなかっただけです。私は設定されて、正しいストアドプロシージャコールの最後に私の出力パラメータで選択しています。 sp_unprepareも毎回呼び出されていますが、カラム入力/出力情報を取得する必要があります。 – jjacksonRIAB