//mhb TODO, check if the sqltype defined here match from c# RETCODE SQL_API _SQLColConvert ( pODBCStmt pStmt, void* pTgtDataPtr, Long* pTgtDataSizePtr, const wchar_t* pSrcColData, pARDItem pARDCol, bool isSigned ) { //check out this for SQL data type to C data type mapping //http://msdn.microsoft.com/en-us/library/ms714556(v=vs.85).aspx // note // this function actually determines the conversion // required to transfer the data Word pSrcDataType = pARDCol->SrcDataType; Word pTgtDataType = pARDCol->DataConciseType; Long pTgtDataSize = pARDCol->DataSize; __ODBCLOG ( _ODBCLogMsg ( LogLevel_DEBUG, "_SQLColConvert called" ) ); __ODBCLOG ( _ODBCLogMsg ( LogLevel_DEBUG, "The SrcDataType is %d, the TgtDataType is %d, the TgtDataSize is %d", pSrcDataType, pTgtDataType, pTgtDataSize ) ); // TARGET TYPE IS LEFT TO OUR DRIVER // check if target type is open if ( pTgtDataType == SQL_DEFAULT ) { __ODBCLOG ( _ODBCLogMsg ( LogLevel_DEBUG, "pTgtDataType is SQL_DEFAULT, use default type mapping." ) ); // determine targettype based on data-source type // check out this http://msdn.microsoft.com/en-us/library/ms716298(v=vs.85).aspx for default type mapping switch ( pSrcDataType ) { case SQL_CHAR: pTgtDataType = SQL_C_CHAR; break; case SQL_VARCHAR: pTgtDataType = SQL_C_CHAR; break; case SQL_WCHAR: pTgtDataType = SQL_C_WCHAR; break; case SQL_WVARCHAR: pTgtDataType = SQL_C_WCHAR; break; case SQL_DECIMAL: pTgtDataType = SQL_C_CHAR; break; case SQL_BIT: pTgtDataType = SQL_C_BIT; break; case SQL_TINYINT: if ( isSigned ) { pTgtDataType = SQL_C_STINYINT; } else { pTgtDataType = SQL_C_UTINYINT; } break; case SQL_SMALLINT: if ( isSigned ) { pTgtDataType = SQL_C_SSHORT; } else { pTgtDataType = SQL_C_USHORT; } break; case SQL_INTEGER: if ( isSigned ) { pTgtDataType = SQL_C_SLONG; } else { pTgtDataType = SQL_C_ULONG; } break; case SQL_BIGINT: if ( isSigned ) { pTgtDataType = SQL_C_SBIGINT; } else { pTgtDataType = SQL_C_UBIGINT; } break; case SQL_FLOAT: pTgtDataType = SQL_C_FLOAT; break; case SQL_DOUBLE: pTgtDataType = SQL_C_DOUBLE; break; case SQL_TYPE_DATE: pTgtDataType = SQL_C_CHAR; break; case SQL_TYPE_TIME: pTgtDataType = SQL_C_CHAR; break; case SQL_TYPE_TIMESTAMP: pTgtDataType = SQL_C_CHAR; break; //case SQL_C_SLONG: //case SQL_C_ULONG: // unsigned long //case SQL_C_USHORT: //case SQL_C_SSHORT: //case SQL_NUMERIC: //case SQL_REAL: // pTgtDataType = pSrcDataType; // break; default: __ODBCPOPMSG ( _ODBCPopMsg ( "The data type %d not implemented", pSrcDataType ) ); return SQL_ERROR; break; } } else { __ODBCLOG ( _ODBCLogMsg ( LogLevel_DEBUG, "pTgtDataType is NOT SQL_DEFAULT, it is %d", pTgtDataType ) ); } // TARGET TYPE IS CHAR // as an optimization, check if the application // or target data type is char. since the data from // server is already in char format. the data can // easily be transferred without incurring any // conversion overhead unique_ptr<char[]> pTextInAnsi ( wchar2char ( pSrcColData ) ); // check if char type if ( pTgtDataType == SQL_CHAR || pTgtDataType == SQL_VARCHAR ) { // only in case of src data being bool a conversion is required if ( pSrcDataType == SQL_BIT ) { // prepare a converted single char bool string Char src[2]; if ( pTextInAnsi.get() == NULL ) { src[0] = '0'; } else { src[0] = ( pTextInAnsi.get() [0] == 'T' || pTextInAnsi.get() [0] == '1' || pTextInAnsi.get() [0] == 't' ) ? '1' : '0'; } src[1] = 0; // transfer the bool string return _SQLCopyCharData ( _DIAGSTMT ( pStmt ), pTgtDataPtr, pARDCol->DataSize, pTgtDataSizePtr, 32, src, -1 ); } else { // transfer the string as it is return _SQLCopyCharData ( _DIAGSTMT ( pStmt ), pTgtDataPtr, pARDCol->DataSize, pTgtDataSizePtr, 32, pTextInAnsi.get(), -1 ); } } if ( pTgtDataType == SQL_WCHAR || pTgtDataType == SQL_WVARCHAR ) { return _SQLCopyWCharDataW ( _DIAGSTMT ( pStmt ), pTgtDataPtr, pARDCol->DataSize, pTgtDataSizePtr, 32, pSrcColData, -1 ); } // TARGET TYPE IS NOT CHAR // try using a numeric conversion switch ( _SQLCopyNumData ( _DIAGSTMT ( pStmt ), pTgtDataPtr, pTgtDataType, pTextInAnsi.get(), pSrcDataType , pTgtDataSizePtr ) ) { case -1: return SQL_ERROR; case 0: return SQL_SUCCESS; default: break; } // try using a date/time conversion switch ( _SQLCopyDateTimeData ( _DIAGSTMT ( pStmt ), pTgtDataPtr, pTgtDataType, pTextInAnsi.get(), pSrcDataType ) ) { case -1: return SQL_ERROR; case 0: return SQL_SUCCESS; default: break; } // try using SQL_BIT data type ie bool if ( pTgtDataType == SQL_BIT ) { __ODBCLOG ( _ODBCLogMsg ( LogLevel_DEBUG, "the target data type is SQL_C_BIT" ) ); // prepare a converted single char bool string if ( pTextInAnsi.get() == NULL ) { * ( ( char* ) pTgtDataPtr ) = 0; } else { * ( ( char* ) pTgtDataPtr ) = ( pTextInAnsi.get() [0] == 'T' || pTextInAnsi.get() [0] == '1' || pTextInAnsi.get() [0] == 't' ) ? 1 : 0; } return SQL_SUCCESS; } // error condition __ODBCPOPMSG ( _ODBCPopMsg ( "_SQLColConvert - Unknown data type, Target: %d, Source: %d", pTgtDataType, pSrcDataType ) ); _SQLPutDiagRow ( SQL_HANDLE_STMT, pStmt, "_SQLColConvert", "01000", -1, "Unknown data type, Target: %d, Source: %d", pTgtDataType, pSrcDataType ); return SQL_ERROR; }
RETCODE SQL_API SQLGetDiagFieldW ( SQLSMALLINT pHandleType, SQLHANDLE pHandle, SQLSMALLINT pRecNum, SQLSMALLINT pFldID, SQLPOINTER pDataPtr, SQLSMALLINT pDataSize, SQLSMALLINT* pDataSizePtr ) { __ODBCLOG ( _ODBCLogMsg ( LogLevel_DEBUG, "SQLGetDiagFieldW called, HandleType: %d, RecNum: %d, InfoType: %d, BufLen: %d", pHandleType, pRecNum, pFldID, pDataSize ) ); bool c; pODBCDiag diag; pODBCDiagRow diagrow; SQLSMALLINT dummySize = 0;//used when pDataSizePtr is NULL if ( pDataSizePtr == NULL ) { pDataSizePtr = &dummySize; } __CHK_HANDLE ( pHandle, pHandleType, SQL_ERROR ); diag = _SQLGetDiagHandle ( pHandleType, pHandle ); if ( !diag ) { return SQL_ERROR; } // field may be in diag header c = FALSE; // check the field type - header fields switch ( pFldID ) { case SQL_DIAG_CURSOR_ROW_COUNT: case SQL_DIAG_ROW_COUNT: // rows affected by update/insert if ( pHandleType == SQL_HANDLE_STMT ) { if ( pDataPtr ) { * ( ( SQLLEN* ) pDataPtr ) = ( pHandle ) ? ( ( pODBCStmt ) pHandle )->RowCount : 0; } return SQL_SUCCESS; } else { return SQL_ERROR; } case SQL_DIAG_DYNAMIC_FUNCTION: if ( pHandleType == SQL_HANDLE_STMT ) { _SQLCopyWCharDataW ( diag, pDataPtr, pDataSize, pDataSizePtr, 16, ( ( pODBCStmt ) pHandle )->Stmt, ( ( pODBCStmt ) pHandle )->StmtLen ); return SQL_SUCCESS; } else { return SQL_ERROR; } return SQL_ERROR; case SQL_DIAG_DYNAMIC_FUNCTION_CODE: if ( pHandleType == SQL_HANDLE_STMT ) { if ( pDataPtr ) { * ( ( StrPtr ) pDataPtr ) = 1; } // ??? debug test only _SQLCopyWCharDataW ( diag, pDataPtr, pDataSize, pDataSizePtr, 16, ( ( pODBCStmt ) pHandle )->Stmt, ( ( ( pODBCStmt ) pHandle )->StmtLen ) ); return SQL_SUCCESS; } else { return SQL_ERROR; } case SQL_DIAG_NUMBER: { // number of rows in diag Word i; // check if there r any diag rows if ( diag->DiagRows ) { // loop to count the rows for ( i = 1, diagrow = diag->DiagRows; diagrow != NULL; diagrow = diagrow->Next, i ++ ); if ( pDataPtr ) { * ( ( Word* ) pDataPtr ) = i; } } else if ( pDataPtr ) { * ( ( Word* ) pDataPtr ) = 0; } return SQL_SUCCESS; } break; default: c = TRUE; } // check if only a header field was required if ( c == FALSE ) { return SQL_SUCCESS; } // check row and buffer if ( pRecNum <= 0 || pDataSize < 0 ) { __ODBCPOPMSG ( _ODBCPopMsg ( "GetDiagField xxx1" ) ); return SQL_ERROR; } // now get the desired row first if ( ( diagrow = _SQLGetDiagRowX ( diag, pRecNum ) ) == NULL ) { return SQL_NO_DATA; } // now set info as per the field required switch ( pFldID ) { case SQL_DIAG_CLASS_ORIGIN: _SQLCopyWCharData ( diag, pDataPtr, pDataSize, pDataSizePtr, 16, "ODBC 3.0", -1 ); break; case SQL_DIAG_COLUMN_NUMBER: // needs to be implemented if ( pDataPtr ) { * ( ( Long* ) pDataPtr ) = diagrow->Col; } break; case SQL_DIAG_CONNECTION_NAME: if ( pDataPtr ) { * ( ( char* ) pDataPtr ) = 0; } if ( pDataSizePtr ) { *pDataSizePtr = 0; } break; case SQL_DIAG_MESSAGE_TEXT: return _SQLCopyWCharData ( diag, pDataPtr, pDataSize, pDataSizePtr, 16, diagrow->Msg, -1 ); case SQL_DIAG_NATIVE: if ( pDataPtr ) { * ( ( Long* ) pDataPtr ) = diagrow->NativeErrorCode; } if ( pDataSizePtr ) { *pDataSizePtr = 0; } break; case SQL_DIAG_ROW_NUMBER: // needs to be implemented if ( pDataPtr ) { * ( ( Long* ) pDataPtr ) = diagrow->Row; } break; case SQL_DIAG_SERVER_NAME: { CStrPtr svr; // if handle type is connection if ( pHandleType == SQL_HANDLE_DBC ) { svr = ( ( pODBCConn ) pHandle )->Server; } else if ( pHandleType == SQL_HANDLE_STMT && ( ( pODBCStmt ) pHandle )->Conn ) { svr = ( ( pODBCStmt ) pHandle )->Conn->Server; } else { svr = ""; } return _SQLCopyWCharData ( diag, pDataPtr, pDataSize, pDataSizePtr, 16, svr, -1 ); } case SQL_DIAG_SQLSTATE: return _SQLCopyWCharData ( diag, pDataPtr, pDataSize, pDataSizePtr, 16, diagrow->State, -1 ); case SQL_DIAG_SUBCLASS_ORIGIN: // ??? dummy return _SQLCopyWCharData ( diag, pDataPtr, pDataSize, pDataSizePtr, 16, diagrow->State, -1 ); default: __ODBCPOPMSG ( _ODBCPopMsg ( "SQLGetDiagField called, HandleType: %d, RecNum: %d, InfoType: %d, BufLen: %d", pHandleType, pRecNum, pFldID, pDataSize ) ); return SQL_ERROR; } return SQL_SUCCESS; }
RETCODE SQL_API _SQLCopyWCharData ( pODBCDiag pDiag, void* pTgtDataPtr, Long pDataBufSize, void* pSizePtr, Word pSizePtrSize, CStrPtr pSrcData, Long pSrcDataSize ) { unique_ptr<wchar_t[]> pWCS ( char2wchar ( pSrcData ) ); return _SQLCopyWCharDataW ( pDiag, pTgtDataPtr, pDataBufSize, pSizePtr, pSizePtrSize, pWCS.get(), pSrcDataSize ); }