diff options
Diffstat (limited to 'connectivity/source/drivers/odbcbase/OTools.cxx')
-rw-r--r-- | connectivity/source/drivers/odbcbase/OTools.cxx | 948 |
1 files changed, 948 insertions, 0 deletions
diff --git a/connectivity/source/drivers/odbcbase/OTools.cxx b/connectivity/source/drivers/odbcbase/OTools.cxx new file mode 100644 index 000000000000..f48ac3c08da0 --- /dev/null +++ b/connectivity/source/drivers/odbcbase/OTools.cxx @@ -0,0 +1,948 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************ + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_connectivity.hxx" +#include "odbc/OTools.hxx" +#include "odbc/OFunctions.hxx" +#include <com/sun/star/sdbc/DataType.hpp> +#include <osl/diagnose.h> +#include "odbc/OConnection.hxx" +#include "diagnose_ex.h" +#include <rtl/logfile.hxx> +#include <rtl/ustrbuf.hxx> + + +#include <string.h> +#include <string> +#include <algorithm> + +using namespace connectivity::odbc; +using namespace com::sun::star::uno; +using namespace com::sun::star::sdbc; +using namespace com::sun::star::util; + +void OTools::getValue( OConnection* _pConnection, + SQLHANDLE _aStatementHandle, + sal_Int32 columnIndex, + SQLSMALLINT _nType, + sal_Bool &_bWasNull, + const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& _xInterface, + void* _pValue, + SQLLEN _nSize) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "odbc", "Ocke.Janssen@sun.com", "OTools::getValue" ); + SQLLEN pcbValue = SQL_NULL_DATA; + OTools::ThrowException(_pConnection, + (*(T3SQLGetData)_pConnection->getOdbcFunction(ODBC3SQLGetData))(_aStatementHandle, + (SQLUSMALLINT)columnIndex, + _nType, + _pValue, + _nSize, + &pcbValue), + _aStatementHandle,SQL_HANDLE_STMT,_xInterface,sal_False); + _bWasNull = pcbValue == SQL_NULL_DATA; +} +// ----------------------------------------------------------------------------- +void OTools::bindParameter( OConnection* _pConnection, + SQLHANDLE _hStmt, + sal_Int32 nPos, + sal_Int8*& pDataBuffer, + sal_Int8* pLenBuffer, + SQLSMALLINT _nODBCtype, + sal_Bool _bUseWChar, + sal_Bool _bUseOldTimeDate, + const void* _pValue, + const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& _xInterface, + rtl_TextEncoding _nTextEncoding) + throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "odbc", "Ocke.Janssen@sun.com", "OTools::bindParameter" ); + SQLRETURN nRetcode; + SQLSMALLINT fSqlType; + SQLSMALLINT fCType; + SQLLEN nMaxLen = 0; + // void*& pData = pDataBuffer; + SQLLEN* pLen = (SQLLEN*)pLenBuffer; + SQLULEN nColumnSize=0; + SQLSMALLINT nDecimalDigits=0; + + OTools::getBindTypes(_bUseWChar,_bUseOldTimeDate,_nODBCtype,fCType,fSqlType); + + OTools::bindData(_nODBCtype,_bUseWChar,pDataBuffer,pLen,_pValue,_nTextEncoding,nColumnSize); + if ((nColumnSize == 0) && (fSqlType == SQL_CHAR || fSqlType == SQL_VARCHAR || fSqlType == SQL_LONGVARCHAR)) + nColumnSize = 1; + + if(fSqlType == SQL_LONGVARCHAR || fSqlType == SQL_LONGVARBINARY) + memcpy(pDataBuffer,&nPos,sizeof(nPos)); + + // 20.09.2001 OJ: Problems with mysql. mysql returns only CHAR as parameter type + // nRetcode = (*(T3SQLDescribeParam)_pConnection->getOdbcFunction(ODBC3SQLDescribeParam))(_hStmt,(SQLUSMALLINT)nPos,&fSqlType,&nColumnSize,&nDecimalDigits,&nNullable); + + nRetcode = (*(T3SQLBindParameter)_pConnection->getOdbcFunction(ODBC3SQLBindParameter))(_hStmt, + (SQLUSMALLINT)nPos, + SQL_PARAM_INPUT, + fCType, + fSqlType, + nColumnSize, + nDecimalDigits, + pDataBuffer, + nMaxLen, + pLen); + + OTools::ThrowException(_pConnection,nRetcode,_hStmt,SQL_HANDLE_STMT,_xInterface); +} +// ----------------------------------------------------------------------------- +void OTools::bindData( SQLSMALLINT _nOdbcType, + sal_Bool _bUseWChar, + sal_Int8 *&_pData, + SQLLEN*& pLen, + const void* _pValue, + rtl_TextEncoding _nTextEncoding, + SQLULEN& _nColumnSize) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "odbc", "Ocke.Janssen@sun.com", "OTools::bindData" ); + _nColumnSize = 0; + + switch (_nOdbcType) + { + case SQL_CHAR: + case SQL_VARCHAR: + case SQL_DECIMAL: + if(_bUseWChar) + { + *pLen = SQL_NTS; + ::rtl::OUString sStr(*(::rtl::OUString*)_pValue); + _nColumnSize = sStr.getLength(); + *((rtl::OUString*)_pData) = sStr; + + // Zeiger auf Char* + _pData = (sal_Int8*)((rtl::OUString*)_pData)->getStr(); + } + else + { + ::rtl::OString aString(::rtl::OUStringToOString(*(::rtl::OUString*)_pValue,_nTextEncoding)); + *pLen = SQL_NTS; + _nColumnSize = aString.getLength(); + memcpy(_pData,aString.getStr(),aString.getLength()); + ((sal_Int8*)_pData)[aString.getLength()] = '\0'; + } + break; + + case SQL_BIGINT: + *((sal_Int64*)_pData) = *(sal_Int64*)_pValue; + *pLen = sizeof(sal_Int64); + _nColumnSize = *pLen; + break; + + case SQL_NUMERIC: + if(_bUseWChar) + { + ::rtl::OUString aString = rtl::OUString::valueOf(*(double*)_pValue); + _nColumnSize = aString.getLength(); + *pLen = _nColumnSize; + *((rtl::OUString*)_pData) = aString; + // Zeiger auf Char* + _pData = (sal_Int8*)((rtl::OUString*)_pData)->getStr(); + } + else + { + ::rtl::OString aString = ::rtl::OString::valueOf(*(double*)_pValue); + _nColumnSize = aString.getLength(); + *pLen = _nColumnSize; + memcpy(_pData,aString.getStr(),aString.getLength()); + ((sal_Int8*)_pData)[_nColumnSize] = '\0'; + } break; + case SQL_BIT: + case SQL_TINYINT: + *((sal_Int8*)_pData) = *(sal_Int8*)_pValue; + *pLen = sizeof(sal_Int8); + break; + + case SQL_SMALLINT: + *((sal_Int16*)_pData) = *(sal_Int16*)_pValue; + *pLen = sizeof(sal_Int16); + break; + case SQL_INTEGER: + *((sal_Int32*)_pData) = *(sal_Int32*)_pValue; + *pLen = sizeof(sal_Int32); + break; + case SQL_FLOAT: + *((float*)_pData) = *(float*)_pValue; + *pLen = sizeof(float); + break; + case SQL_REAL: + case SQL_DOUBLE: + *((double*)_pData) = *(double*)_pValue; + *pLen = sizeof(double); + break; + case SQL_BINARY: + case SQL_VARBINARY: + { + const ::com::sun::star::uno::Sequence< sal_Int8 >* pSeq = static_cast< const ::com::sun::star::uno::Sequence< sal_Int8 >* >(_pValue); + OSL_ENSURE(pSeq,"OTools::bindData: Sequence is null!"); + + if(pSeq) + { + _pData = (sal_Int8*)pSeq->getConstArray(); + *pLen = pSeq->getLength(); + } + } + break; + case SQL_LONGVARBINARY: + { + sal_Int32 nLen = 0; + nLen = ((const ::com::sun::star::uno::Sequence< sal_Int8 > *)_pValue)->getLength(); + *pLen = (SQLLEN)SQL_LEN_DATA_AT_EXEC(nLen); + } + break; + case SQL_LONGVARCHAR: + { + sal_Int32 nLen = 0; + if(_bUseWChar) + nLen = sizeof(sal_Unicode) * ((::rtl::OUString*)_pValue)->getLength(); + else + { + ::rtl::OString aString(::rtl::OUStringToOString(*(::rtl::OUString*)_pValue,_nTextEncoding)); + nLen = aString.getLength(); + } + *pLen = (SQLLEN)SQL_LEN_DATA_AT_EXEC(nLen); + } break; + case SQL_DATE: + *(DATE_STRUCT*)_pData = *(DATE_STRUCT*)_pValue; + *pLen = (SQLLEN)sizeof(DATE_STRUCT); + _nColumnSize = 10; + break; + case SQL_TIME: + *(TIME_STRUCT*)_pData = *(TIME_STRUCT*)_pValue; + *pLen = (SQLLEN)sizeof(TIME_STRUCT); + _nColumnSize = 8; + break; + case SQL_TIMESTAMP: + *(TIMESTAMP_STRUCT*)_pData = *(TIMESTAMP_STRUCT*)_pValue; + *pLen = (SQLLEN)sizeof(TIMESTAMP_STRUCT); + _nColumnSize = 19; + break; + } +} +// ------------------------------------------------------------------------- +void OTools::bindValue( OConnection* _pConnection, + SQLHANDLE _aStatementHandle, + sal_Int32 columnIndex, + SQLSMALLINT _nType, + SQLSMALLINT _nMaxLen, + const void* _pValue, + void* _pData, + SQLLEN *pLen, + const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& _xInterface, + rtl_TextEncoding _nTextEncoding, + sal_Bool _bUseOldTimeDate) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "odbc", "Ocke.Janssen@sun.com", "OTools::bindValue" ); + SQLRETURN nRetcode; + SQLSMALLINT fSqlType; + SQLSMALLINT fCType; + SQLLEN nMaxLen = _nMaxLen; + + OTools::getBindTypes( sal_False, + _bUseOldTimeDate, + _nType, + fCType, + fSqlType); + + if (columnIndex != 0 && !_pValue) + { + *pLen = SQL_NULL_DATA; + nRetcode = (*(T3SQLBindCol)_pConnection->getOdbcFunction(ODBC3SQLBindCol))(_aStatementHandle, + (SQLUSMALLINT)columnIndex, + fCType, + _pData, + nMaxLen, + pLen + ); + } + else + { + try + { + switch (_nType) + { + case SQL_CHAR: + case SQL_VARCHAR: + //if(GetODBCConnection()->m_bUserWChar) +// { +// _nMaxLen = rCol.GetPrecision(); +// *pLen = SQL_NTS; +// *((rtl::OUString*)pData) = (rtl::OUString)_aValue; +// +// // Zeiger auf Char* +// pData = (void*)((rtl::OUString*)pData)->getStr(); +// } +// else + { + ::rtl::OString aString(::rtl::OUStringToOString(*(::rtl::OUString*)_pValue,_nTextEncoding)); + *pLen = SQL_NTS; + *((::rtl::OString*)_pData) = aString; + _nMaxLen = (SQLSMALLINT)aString.getLength(); + + // Zeiger auf Char* + _pData = (void*)aString.getStr(); + } break; + case SQL_BIGINT: + *((sal_Int64*)_pData) = *(sal_Int64*)_pValue; + *pLen = sizeof(sal_Int64); + break; + case SQL_DECIMAL: + case SQL_NUMERIC: + //if(GetODBCConnection()->m_bUserWChar) +// { +// rtl::OUString aString(rtl::OUString(SdbTools::ToString(ODbTypeConversion::toDouble(*pVariable),rCol.GetScale()))); +// *pLen = _nMaxLen; +// *((rtl::OUString*)_pData) = aString; +// // Zeiger auf Char* +// _pData = (void*)((rtl::OUString*)_pData)->getStr(); +// } +// else + { + ::rtl::OString aString = ::rtl::OString::valueOf(*(double*)_pValue); + _nMaxLen = (SQLSMALLINT)aString.getLength(); + *pLen = _nMaxLen; + *((::rtl::OString*)_pData) = aString; + // Zeiger auf Char* + _pData = (void*)((::rtl::OString*)_pData)->getStr(); + } break; + case SQL_BIT: + case SQL_TINYINT: + *((sal_Int8*)_pData) = *(sal_Int8*)_pValue; + *pLen = sizeof(sal_Int8); + break; + + case SQL_SMALLINT: + *((sal_Int16*)_pData) = *(sal_Int16*)_pValue; + *pLen = sizeof(sal_Int16); + break; + case SQL_INTEGER: + *((sal_Int32*)_pData) = *(sal_Int32*)_pValue; + *pLen = sizeof(sal_Int32); + break; + case SQL_FLOAT: + *((float*)_pData) = *(float*)_pValue; + *pLen = sizeof(float); + break; + case SQL_REAL: + case SQL_DOUBLE: + *((double*)_pData) = *(double*)_pValue; + *pLen = sizeof(double); + break; + case SQL_BINARY: + case SQL_VARBINARY: + // if (_pValue == ::getCppuType((const ::com::sun::star::uno::Sequence< sal_Int8 > *)0)) + { + _pData = (void*)((const ::com::sun::star::uno::Sequence< sal_Int8 > *)_pValue)->getConstArray(); + *pLen = ((const ::com::sun::star::uno::Sequence< sal_Int8 > *)_pValue)->getLength(); + } break; + case SQL_LONGVARBINARY: + { + _pData = (void*)(columnIndex); + sal_Int32 nLen = 0; + nLen = ((const ::com::sun::star::uno::Sequence< sal_Int8 > *)_pValue)->getLength(); + *pLen = (SQLLEN)SQL_LEN_DATA_AT_EXEC(nLen); + } + break; + case SQL_LONGVARCHAR: + { + _pData = (void*)(columnIndex); + sal_Int32 nLen = 0; + nLen = ((::rtl::OUString*)_pValue)->getLength(); + *pLen = (SQLLEN)SQL_LEN_DATA_AT_EXEC(nLen); + } break; + case SQL_DATE: + *pLen = sizeof(DATE_STRUCT); + *((DATE_STRUCT*)_pData) = *(DATE_STRUCT*)_pValue; + break; + case SQL_TIME: + *pLen = sizeof(TIME_STRUCT); + *((TIME_STRUCT*)_pData) = *(TIME_STRUCT*)_pValue; + break; + case SQL_TIMESTAMP: + *pLen = sizeof(TIMESTAMP_STRUCT); + *((TIMESTAMP_STRUCT*)_pData) = *(TIMESTAMP_STRUCT*)_pValue; + break; + } + } + catch ( ... ) + { + } + + nRetcode = (*(T3SQLBindCol)_pConnection->getOdbcFunction(ODBC3SQLBindCol))(_aStatementHandle, + (SQLUSMALLINT)columnIndex, + fCType, + _pData, + nMaxLen, + pLen + ); + } + + OTools::ThrowException(_pConnection,nRetcode,_aStatementHandle,SQL_HANDLE_STMT,_xInterface); +} +// ----------------------------------------------------------------------------- +void OTools::ThrowException(OConnection* _pConnection, + SQLRETURN _rRetCode, + SQLHANDLE _pContext, + SQLSMALLINT _nHandleType, + const Reference< XInterface >& _xInterface, + sal_Bool _bNoFound, + rtl_TextEncoding _nTextEncoding) throw(SQLException) +{ + switch(_rRetCode) + { + case SQL_NEED_DATA: + case SQL_STILL_EXECUTING: + case SQL_SUCCESS: + + case SQL_SUCCESS_WITH_INFO: + return; + case SQL_NO_DATA_FOUND: + if(_bNoFound) + return; // no need to throw a exception + case SQL_ERROR: break; + + + case SQL_INVALID_HANDLE: OSL_ENSURE(0,"SdbODBC3_SetStatus: SQL_INVALID_HANDLE"); + throw SQLException(); + } + + + // Zusaetliche Informationen zum letzten ODBC-Funktionsaufruf vorhanden. + // SQLError liefert diese Informationen. + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "odbc", "Ocke.Janssen@sun.com", "OTools::ThrowException" ); + + SDB_ODBC_CHAR szSqlState[5]; + SQLINTEGER pfNativeError; + SDB_ODBC_CHAR szErrorMessage[SQL_MAX_MESSAGE_LENGTH]; + szErrorMessage[0] = '\0'; + SQLSMALLINT pcbErrorMsg = 0; + + // Informationen zur letzten Operation: + // wenn hstmt != SQL_NULL_HSTMT ist (Benutzung von SetStatus in SdbCursor, SdbTable, ...), + // dann wird der Status des letzten Statements erfragt, sonst der Status des letzten + // Statements zu dieser Verbindung [was in unserem Fall wahrscheinlich gleichbedeutend ist, + // aber das Reference Manual drueckt sich da nicht so klar aus ...]. + // Entsprechend bei hdbc. + SQLRETURN n = (*(T3SQLGetDiagRec)_pConnection->getOdbcFunction(ODBC3SQLGetDiagRec))(_nHandleType,_pContext,1, + szSqlState, + &pfNativeError, + szErrorMessage,sizeof szErrorMessage - 1,&pcbErrorMsg); + OSL_UNUSED( n ); + OSL_ENSURE(n != SQL_INVALID_HANDLE,"SdbODBC3_SetStatus: SQLError returned SQL_INVALID_HANDLE"); + OSL_ENSURE(n == SQL_SUCCESS || n == SQL_SUCCESS_WITH_INFO || n == SQL_NO_DATA_FOUND || n == SQL_ERROR,"SdbODBC3_SetStatus: SQLError failed"); + + // Zum Return Code von SQLError siehe ODBC 2.0 Programmer's Reference Seite 287ff + throw SQLException( ::rtl::OUString((char *)szErrorMessage,pcbErrorMsg,_nTextEncoding), + _xInterface, + ::rtl::OUString((char *)szSqlState,5,_nTextEncoding), + pfNativeError, + Any() + ); + +} +// ------------------------------------------------------------------------- +Sequence<sal_Int8> OTools::getBytesValue(OConnection* _pConnection, + SQLHANDLE _aStatementHandle, + sal_Int32 columnIndex, + SQLSMALLINT _fSqlType, + sal_Bool &_bWasNull, + const Reference< XInterface >& _xInterface) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "odbc", "Ocke.Janssen@sun.com", "OTools::getBytesValue" ); + char aCharArray[2048]; + // Erstmal versuchen, die Daten mit dem kleinen Puffer + // abzuholen: + SQLLEN nMaxLen = sizeof aCharArray - 1; + // GETDATA(SQL_C_CHAR,aCharArray,nMaxLen); + SQLLEN pcbValue = 0; + OTools::ThrowException(_pConnection,(*(T3SQLGetData)_pConnection->getOdbcFunction(ODBC3SQLGetData))(_aStatementHandle, + (SQLUSMALLINT)columnIndex, + _fSqlType, + (SQLPOINTER)aCharArray, + nMaxLen, + &pcbValue), + _aStatementHandle,SQL_HANDLE_STMT,_xInterface); + + _bWasNull = pcbValue == SQL_NULL_DATA; + if(_bWasNull) + return Sequence<sal_Int8>(); + + SQLINTEGER nBytes = pcbValue != SQL_NO_TOTAL ? std::min(pcbValue, nMaxLen) : nMaxLen; + if ( ((pcbValue == SQL_NO_TOTAL) || pcbValue > nMaxLen) && aCharArray[nBytes-1] == 0 && nBytes > 0 ) + --nBytes; + Sequence<sal_Int8> aData((sal_Int8*)aCharArray, nBytes); + + + // Es handelt sich um Binaerdaten, um einen String, der fuer + // StarView zu lang ist oder der Treiber kann die Laenge der + // Daten nicht im voraus bestimmen - also als MemoryStream + // speichern. + while ((pcbValue == SQL_NO_TOTAL) || pcbValue > nMaxLen) + { + // Bei Strings wird der Puffer nie ganz ausgenutzt + // (das letzte Byte ist immer ein NULL-Byte, das + // aber bei pcbValue nicht mitgezaehlt wird) + if (pcbValue != SQL_NO_TOTAL && (pcbValue - nMaxLen) < nMaxLen) + nBytes = pcbValue - nMaxLen; + else + nBytes = nMaxLen; + + // Solange eine "truncation"-Warnung vorliegt, weiter Daten abholen + // GETDATA(SQL_C_CHAR,aCharArray, nLen + 1); + OTools::ThrowException(_pConnection,(*(T3SQLGetData)_pConnection->getOdbcFunction(ODBC3SQLGetData))(_aStatementHandle, + (SQLUSMALLINT)columnIndex, + SQL_C_BINARY, + &aCharArray, + (SQLINTEGER)nBytes, + &pcbValue), + _aStatementHandle,SQL_HANDLE_STMT,_xInterface); + sal_Int32 nLen = aData.getLength(); + aData.realloc(nLen + nBytes); + memcpy(aData.getArray() + nLen, aCharArray, nBytes); + } + return aData; +} +// ------------------------------------------------------------------------- +::rtl::OUString OTools::getStringValue(OConnection* _pConnection, + SQLHANDLE _aStatementHandle, + sal_Int32 columnIndex, + SQLSMALLINT _fSqlType, + sal_Bool &_bWasNull, + const Reference< XInterface >& _xInterface, + rtl_TextEncoding _nTextEncoding) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "odbc", "Ocke.Janssen@sun.com", "OTools::getStringValue" ); + ::rtl::OUStringBuffer aData; + switch(_fSqlType) + { + case SQL_WVARCHAR: + case SQL_WCHAR: + case SQL_WLONGVARCHAR: + { + sal_Unicode waCharArray[2048]; + // read the unicode data + SQLLEN nMaxLen = (sizeof(waCharArray) / sizeof(sal_Unicode)) - 1; + // GETDATA(SQL_C_WCHAR, waCharArray, nMaxLen + sizeof(sal_Unicode)); + + SQLLEN pcbValue=0; + OTools::ThrowException(_pConnection,(*(T3SQLGetData)_pConnection->getOdbcFunction(ODBC3SQLGetData))(_aStatementHandle, + (SQLUSMALLINT)columnIndex, + SQL_C_WCHAR, + &waCharArray, + (SQLLEN)nMaxLen*sizeof(sal_Unicode), + &pcbValue), + _aStatementHandle,SQL_HANDLE_STMT,_xInterface); + _bWasNull = pcbValue == SQL_NULL_DATA; + if(_bWasNull) + return ::rtl::OUString(); + // Bei Fehler bricht der GETDATA-Makro mit return ab, + // bei NULL mit break! + SQLLEN nRealSize = 0; + if ( pcbValue > -1 ) + nRealSize = pcbValue / sizeof(sal_Unicode); + SQLLEN nLen = pcbValue != SQL_NO_TOTAL ? std::min(nRealSize, nMaxLen) : (nMaxLen-1); + waCharArray[nLen] = 0; + aData.append(waCharArray,nLen); + + // Es handelt sich um Binaerdaten, um einen String, der fuer + // StarView zu lang ist oder der Treiber kann die Laenge der + // Daten nicht im voraus bestimmen - also als MemoryStream + // speichern. + while ((pcbValue == SQL_NO_TOTAL ) || nLen > nMaxLen) + { + // Bei Strings wird der Puffer nie ganz ausgenutzt + // (das letzte Byte ist immer ein NULL-Byte, das + // aber bei pcbValue nicht mitgezaehlt wird) + if (pcbValue != SQL_NO_TOTAL && (pcbValue - nMaxLen) < nMaxLen) + nLen = pcbValue - nMaxLen; + else + nLen = nMaxLen; + + // Solange eine "truncation"-Warnung vorliegt, weiter Daten abholen + // GETDATA(SQL_C_CHAR,waCharArray, nLen + 1); + OTools::ThrowException(_pConnection,(*(T3SQLGetData)_pConnection->getOdbcFunction(ODBC3SQLGetData))(_aStatementHandle, + (SQLUSMALLINT)columnIndex, + SQL_C_WCHAR, + &waCharArray, + (SQLLEN)nLen+1, + &pcbValue), + _aStatementHandle,SQL_HANDLE_STMT,_xInterface); + nRealSize = 0; + if ( pcbValue > -1 ) + nRealSize = pcbValue / sizeof(sal_Unicode); + nLen = pcbValue != SQL_NO_TOTAL ? std::min(nRealSize, nMaxLen) : (nMaxLen-1); + waCharArray[nLen] = 0; + + aData.append(::rtl::OUString(waCharArray)); + } + } + break; + default: + { + char aCharArray[2048]; + // Erstmal versuchen, die Daten mit dem kleinen Puffer + // abzuholen: + SQLLEN nMaxLen = sizeof aCharArray - 1; + // GETDATA(SQL_C_CHAR,aCharArray,nMaxLen); + SQLLEN pcbValue = 0; + OTools::ThrowException(_pConnection,(*(T3SQLGetData)_pConnection->getOdbcFunction(ODBC3SQLGetData))(_aStatementHandle, + (SQLUSMALLINT)columnIndex, + SQL_C_CHAR, + &aCharArray, + nMaxLen, + &pcbValue), + _aStatementHandle,SQL_HANDLE_STMT,_xInterface); + _bWasNull = pcbValue == SQL_NULL_DATA; + if(_bWasNull) + return ::rtl::OUString(); + + SQLLEN nLen = pcbValue != SQL_NO_TOTAL ? std::min(pcbValue, nMaxLen) : (nMaxLen-1); + aCharArray[nLen] = 0; + if ( ((pcbValue == SQL_NO_TOTAL) || pcbValue > nMaxLen) && aCharArray[nLen-1] == 0 && nLen > 0 ) + --nLen; + aData.append(::rtl::OUString((const sal_Char*)aCharArray,nLen, _nTextEncoding)); + + // Es handelt sich um Binaerdaten, um einen String, der fuer + // StarView zu lang ist oder der Treiber kann die Laenge der + // Daten nicht im voraus bestimmen - also als MemoryStream + // speichern. + while ((pcbValue == SQL_NO_TOTAL) || pcbValue > nMaxLen) + { + // Solange eine "truncation"-Warnung vorliegt, weiter Daten abholen + // GETDATA(SQL_C_CHAR,aCharArray, nLen + 1); + OTools::ThrowException(_pConnection,(*(T3SQLGetData)_pConnection->getOdbcFunction(ODBC3SQLGetData))(_aStatementHandle, + (SQLUSMALLINT)columnIndex, + SQL_C_CHAR, + &aCharArray, + (SQLINTEGER)nMaxLen, + &pcbValue), + _aStatementHandle,SQL_HANDLE_STMT,_xInterface); + nLen = pcbValue != SQL_NO_TOTAL ? std::min(pcbValue, nMaxLen) : (nMaxLen-1); + if ( ((pcbValue == SQL_NO_TOTAL) || pcbValue > nMaxLen) && aCharArray[nLen-1] == 0 && nLen > 0 ) + --nLen; + aCharArray[nLen] = 0; + + aData.append(::rtl::OUString((const sal_Char*)aCharArray,nLen,_nTextEncoding)); + } + + // delete all blanks + // aData.EraseTrailingChars(); + } + } + + return aData.makeStringAndClear(); +} +// ------------------------------------------------------------------------- +void OTools::GetInfo(OConnection* _pConnection, + SQLHANDLE _aConnectionHandle, + SQLUSMALLINT _nInfo, + ::rtl::OUString &_rValue, + const Reference< XInterface >& _xInterface, + rtl_TextEncoding _nTextEncoding) throw(SQLException, RuntimeException) +{ + char aValue[512]; + SQLSMALLINT nValueLen=0; + OTools::ThrowException(_pConnection, + (*(T3SQLGetInfo)_pConnection->getOdbcFunction(ODBC3SQLGetInfo))(_aConnectionHandle,_nInfo,aValue,(sizeof aValue)-1,&nValueLen), + _aConnectionHandle,SQL_HANDLE_DBC,_xInterface); + + _rValue = ::rtl::OUString(aValue,nValueLen,_nTextEncoding); +} +// ------------------------------------------------------------------------- +void OTools::GetInfo(OConnection* _pConnection, + SQLHANDLE _aConnectionHandle, + SQLUSMALLINT _nInfo, + sal_Int32 &_rValue, + const Reference< XInterface >& _xInterface) throw(SQLException, RuntimeException) +{ + SQLSMALLINT nValueLen; + _rValue = 0; // in case the driver uses only 16 of the 32 bits (as it does, for example, for SQL_CATALOG_LOCATION) + OTools::ThrowException(_pConnection, + (*(T3SQLGetInfo)_pConnection->getOdbcFunction(ODBC3SQLGetInfo))(_aConnectionHandle,_nInfo,&_rValue,sizeof _rValue,&nValueLen), + _aConnectionHandle,SQL_HANDLE_DBC,_xInterface); +} +// ------------------------------------------------------------------------- +void OTools::GetInfo(OConnection* _pConnection, + SQLHANDLE _aConnectionHandle, + SQLUSMALLINT _nInfo, + SQLUINTEGER &_rValue, + const Reference< XInterface >& _xInterface) throw(SQLException, RuntimeException) +{ + SQLSMALLINT nValueLen; + _rValue = 0; // in case the driver uses only 16 of the 32 bits (as it does, for example, for SQL_CATALOG_LOCATION) + OTools::ThrowException(_pConnection, + (*(T3SQLGetInfo)_pConnection->getOdbcFunction(ODBC3SQLGetInfo))(_aConnectionHandle,_nInfo,&_rValue,sizeof _rValue,&nValueLen), + _aConnectionHandle,SQL_HANDLE_DBC,_xInterface); +} +// ------------------------------------------------------------------------- +void OTools::GetInfo(OConnection* _pConnection, + SQLHANDLE _aConnectionHandle, + SQLUSMALLINT _nInfo, + SQLUSMALLINT &_rValue, + const Reference< XInterface >& _xInterface) throw(SQLException, RuntimeException) +{ + SQLSMALLINT nValueLen; + _rValue = 0; // in case the driver uses only 16 of the 32 bits (as it does, for example, for SQL_CATALOG_LOCATION) + OTools::ThrowException(_pConnection, + (*(T3SQLGetInfo)_pConnection->getOdbcFunction(ODBC3SQLGetInfo))(_aConnectionHandle,_nInfo,&_rValue,sizeof _rValue,&nValueLen), + _aConnectionHandle,SQL_HANDLE_DBC,_xInterface); +} +// ------------------------------------------------------------------------- +void OTools::GetInfo(OConnection* _pConnection, + SQLHANDLE _aConnectionHandle, + SQLUSMALLINT _nInfo, + sal_Bool &_rValue, + const Reference< XInterface >& _xInterface) throw(SQLException, RuntimeException) +{ + SQLSMALLINT nValueLen; + OTools::ThrowException(_pConnection, + (*(T3SQLGetInfo)_pConnection->getOdbcFunction(ODBC3SQLGetInfo))(_aConnectionHandle,_nInfo,&_rValue,sizeof _rValue,&nValueLen), + _aConnectionHandle,SQL_HANDLE_DBC,_xInterface); +} +// ------------------------------------------------------------------------- +sal_Int32 OTools::MapOdbcType2Jdbc(sal_Int32 _nType) +{ + sal_Int32 nValue = DataType::VARCHAR; + switch(_nType) + { + case SQL_BIT: + nValue = DataType::BIT; + break; + case SQL_TINYINT: + nValue = DataType::TINYINT; + break; + case SQL_SMALLINT: + nValue = DataType::SMALLINT; + break; + case SQL_INTEGER: + nValue = DataType::INTEGER; + break; + case SQL_BIGINT: + nValue = DataType::BIGINT; + break; + case SQL_FLOAT: + nValue = DataType::FLOAT; + break; + case SQL_REAL: + nValue = DataType::REAL; + break; + case SQL_DOUBLE: + nValue = DataType::DOUBLE; + break; + case SQL_NUMERIC: + nValue = DataType::NUMERIC; + break; + case SQL_DECIMAL: + nValue = DataType::DECIMAL; + break; + case SQL_WCHAR: + case SQL_CHAR: + nValue = DataType::CHAR; + break; + case SQL_WVARCHAR: + case SQL_VARCHAR: + nValue = DataType::VARCHAR; + break; + case SQL_WLONGVARCHAR: + case SQL_LONGVARCHAR: + nValue = DataType::LONGVARCHAR; + break; + case SQL_TYPE_DATE: + case SQL_DATE: + nValue = DataType::DATE; + break; + case SQL_TYPE_TIME: + case SQL_TIME: + nValue = DataType::TIME; + break; + case SQL_TYPE_TIMESTAMP: + case SQL_TIMESTAMP: + nValue = DataType::TIMESTAMP; + break; + case SQL_BINARY: + nValue = DataType::BINARY; + break; + case SQL_VARBINARY: + case SQL_GUID: + nValue = DataType::VARBINARY; + break; + case SQL_LONGVARBINARY: + nValue = DataType::LONGVARBINARY; + break; + default: + OSL_ASSERT(!"Invalid type"); + } + return nValue; +} +//-------------------------------------------------------------------- +// jdbcTypeToOdbc +// Convert the JDBC SQL type to the correct ODBC type +//-------------------------------------------------------------------- +sal_Int32 OTools::jdbcTypeToOdbc(sal_Int32 jdbcType) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "odbc", "Ocke.Janssen@sun.com", "OTools::jdbcTypeToOdbc" ); + // For the most part, JDBC types match ODBC types. We'll + // just convert the ones that we know are different + + sal_Int32 odbcType = jdbcType; + + switch (jdbcType) + { + case DataType::DATE: + odbcType = SQL_DATE; + break; + case DataType::TIME: + odbcType = SQL_TIME; + break; + case DataType::TIMESTAMP: + odbcType = SQL_TIMESTAMP; + break; + } + + return odbcType; +} +//----------------------------------------------------------------------------- +void OTools::getBindTypes(sal_Bool _bUseWChar, + sal_Bool _bUseOldTimeDate, + SQLSMALLINT _nOdbcType, + SQLSMALLINT& fCType, + SQLSMALLINT& fSqlType + ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "odbc", "Ocke.Janssen@sun.com", "OTools::getBindTypes" ); + switch(_nOdbcType) + { + case SQL_CHAR: if(_bUseWChar) + { + fCType = SQL_C_WCHAR; + fSqlType = SQL_WCHAR; + } + else + { + fCType = SQL_C_CHAR; + fSqlType = SQL_CHAR; + } + break; + case SQL_VARCHAR: if(_bUseWChar) + { + fCType = SQL_C_WCHAR; + fSqlType = SQL_WVARCHAR; + } + else + { + fCType = SQL_C_CHAR; + fSqlType = SQL_VARCHAR; + } + break; + case SQL_LONGVARCHAR: if(_bUseWChar) + { + fCType = SQL_C_WCHAR; + fSqlType = SQL_WLONGVARCHAR; + } + else + { + fCType = SQL_C_CHAR; + fSqlType = SQL_LONGVARCHAR; + } + break; + case SQL_DECIMAL: fCType = _bUseWChar ? SQL_C_WCHAR : SQL_C_CHAR; + fSqlType = SQL_DECIMAL; break; + case SQL_NUMERIC: fCType = _bUseWChar ? SQL_C_WCHAR : SQL_C_CHAR; + fSqlType = SQL_NUMERIC; break; + case SQL_BIT: fCType = SQL_C_TINYINT; + fSqlType = SQL_INTEGER; break; + case SQL_TINYINT: fCType = SQL_C_TINYINT; + fSqlType = SQL_TINYINT; break; + case SQL_SMALLINT: fCType = SQL_C_SHORT; + fSqlType = SQL_SMALLINT; break; + case SQL_INTEGER: fCType = SQL_C_LONG; + fSqlType = SQL_INTEGER; break; + case SQL_BIGINT: fCType = SQL_C_SBIGINT; + fSqlType = SQL_BIGINT; break; + case SQL_FLOAT: fCType = SQL_C_FLOAT; + fSqlType = SQL_FLOAT; break; + case SQL_REAL: fCType = SQL_C_DOUBLE; + fSqlType = SQL_REAL; break; + case SQL_DOUBLE: fCType = SQL_C_DOUBLE; + fSqlType = SQL_DOUBLE; break; + case SQL_BINARY: fCType = SQL_C_BINARY; + fSqlType = SQL_BINARY; break; + case SQL_VARBINARY: + fCType = SQL_C_BINARY; + fSqlType = SQL_VARBINARY; break; + case SQL_LONGVARBINARY: fCType = SQL_C_BINARY; + fSqlType = SQL_LONGVARBINARY; break; + case SQL_DATE: + if(_bUseOldTimeDate) + { + fCType = SQL_C_DATE; + fSqlType = SQL_DATE; + } + else + { + fCType = SQL_C_TYPE_DATE; + fSqlType = SQL_TYPE_DATE; + } + break; + case SQL_TIME: + if(_bUseOldTimeDate) + { + fCType = SQL_C_TIME; + fSqlType = SQL_TIME; + } + else + { + fCType = SQL_C_TYPE_TIME; + fSqlType = SQL_TYPE_TIME; + } + break; + case SQL_TIMESTAMP: + if(_bUseOldTimeDate) + { + fCType = SQL_C_TIMESTAMP; + fSqlType = SQL_TIMESTAMP; + } + else + { + fCType = SQL_C_TYPE_TIMESTAMP; + fSqlType = SQL_TYPE_TIMESTAMP; + } + break; + default: fCType = SQL_C_BINARY; + fSqlType = SQL_LONGVARBINARY; break; + } +} + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |