diff options
Diffstat (limited to 'connectivity/source/commontools')
41 files changed, 17756 insertions, 0 deletions
diff --git a/connectivity/source/commontools/AutoRetrievingBase.cxx b/connectivity/source/commontools/AutoRetrievingBase.cxx new file mode 100644 index 000000000000..5f84bc5f0e93 --- /dev/null +++ b/connectivity/source/commontools/AutoRetrievingBase.cxx @@ -0,0 +1,71 @@ +/************************************************************************* + * + * 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 "AutoRetrievingBase.hxx" + +namespace connectivity +{ + ::rtl::OUString OAutoRetrievingBase::getTransformedGeneratedStatement(const ::rtl::OUString& _sInsertStatement) const + { + ::rtl::OUString sStmt = _sInsertStatement; + OSL_ENSURE( m_bAutoRetrievingEnabled,"Illegal call here. isAutoRetrievingEnabled is false!"); + sStmt = sStmt.toAsciiUpperCase(); + ::rtl::OUString sStatement; + if ( sStmt.compareToAscii("INSERT",6) == 0 ) + { + sStatement = m_sGeneratedValueStatement; + static const ::rtl::OUString sColumn(RTL_CONSTASCII_USTRINGPARAM("$column")); + static const ::rtl::OUString sTable(RTL_CONSTASCII_USTRINGPARAM("$table")); + sal_Int32 nIndex = 0; + nIndex = sStatement.indexOf(sColumn,nIndex); + if ( -1 != nIndex ) + { // we need a column + } + nIndex = 0; + nIndex = sStatement.indexOf(sTable,nIndex); + if ( -1 != nIndex ) + { // we need a table name + sal_Int32 nIntoIndex = sStmt.indexOf(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("INTO "))); + sStmt = sStmt.copy(nIntoIndex+5); + do + { + if ( sStmt.indexOf(' ') == 0 ) + sStmt = sStmt.copy(1); + } + while (sStmt.indexOf(' ') == 0 ); + + nIntoIndex = 0; + ::rtl::OUString sTableName = sStmt.getToken(0,' ',nIntoIndex); + sStatement = sStatement.replaceAt(nIndex,sTable.getLength(),sTableName); + } + } + return sStatement; + } +} + diff --git a/connectivity/source/commontools/BlobHelper.cxx b/connectivity/source/commontools/BlobHelper.cxx new file mode 100644 index 000000000000..1b7ad15ca394 --- /dev/null +++ b/connectivity/source/commontools/BlobHelper.cxx @@ -0,0 +1,69 @@ +/************************************************************************* + * + * 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 "connectivity/BlobHelper.hxx" +#include <comphelper/seqstream.hxx> +#include "connectivity/dbexception.hxx" + +using namespace connectivity; +using namespace dbtools; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::uno; + +BlobHelper::BlobHelper(const ::com::sun::star::uno::Sequence< sal_Int8 >& _val) : m_aValue(_val) +{ +} +// ----------------------------------------------------------------------------- +::sal_Int64 SAL_CALL BlobHelper::length( ) throw (::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException) +{ + return m_aValue.getLength(); +} +// ----------------------------------------------------------------------------- +::com::sun::star::uno::Sequence< ::sal_Int8 > SAL_CALL BlobHelper::getBytes( ::sal_Int64 pos, ::sal_Int32 _length ) throw (::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException) +{ + if ( sal_Int32(pos + _length) > m_aValue.getLength() ) + throw ::com::sun::star::sdbc::SQLException(); + return ::com::sun::star::uno::Sequence< ::sal_Int8 >(m_aValue.getConstArray() + sal_Int32(pos),_length); +} +// ----------------------------------------------------------------------------- +::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > SAL_CALL BlobHelper::getBinaryStream( ) throw (::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException) +{ + return new ::comphelper::SequenceInputStream(m_aValue); +} +// ----------------------------------------------------------------------------- +::sal_Int64 SAL_CALL BlobHelper::position( const ::com::sun::star::uno::Sequence< ::sal_Int8 >& /*pattern*/, ::sal_Int64 /*start*/ ) throw (::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException) +{ + ::dbtools::throwFeatureNotImplementedException( "XBlob::position", *this ); + return 0; +} +// ----------------------------------------------------------------------------- +::sal_Int64 SAL_CALL BlobHelper::positionOfBlob( const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XBlob >& /*pattern*/, ::sal_Int64 /*start*/ ) throw (::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException) +{ + ::dbtools::throwFeatureNotImplementedException( "XBlob::positionOfBlob", *this ); + return 0; +} diff --git a/connectivity/source/commontools/CommonTools.cxx b/connectivity/source/commontools/CommonTools.cxx new file mode 100644 index 000000000000..b9d3e8bec1b5 --- /dev/null +++ b/connectivity/source/commontools/CommonTools.cxx @@ -0,0 +1,369 @@ +/************************************************************************* + * + * 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 <stdio.h> +#include "connectivity/CommonTools.hxx" +#include "connectivity/dbtools.hxx" +#include <com/sun/star/util/Date.hpp> +#include <com/sun/star/util/Time.hpp> +#include <com/sun/star/util/DateTime.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/lang/XComponent.hpp> +#include <comphelper/extract.hxx> +#include <cppuhelper/interfacecontainer.h> +#include "TConnection.hxx" +#include <comphelper/types.hxx> +#include <com/sun/star/java/XJavaVM.hpp> +#include <rtl/process.h> + +using namespace ::comphelper; +inline sal_Unicode rtl_ascii_toUpperCase( sal_Unicode ch ) +{ + return ch >= 0x0061 && ch <= 0x007a ? ch + 0x20 : ch; +} + +namespace connectivity +{ + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::lang; + using namespace ::com::sun::star::beans; + using namespace dbtools; + namespace starjava = com::sun::star::java; + //------------------------------------------------------------------------------ + const sal_Unicode CHAR_PLACE = '_'; + const sal_Unicode CHAR_WILD = '%'; + // ------------------------------------------------------------------------- + sal_Bool match(const sal_Unicode* pWild, const sal_Unicode* pStr, const sal_Unicode cEscape) + { + int pos=0; + int flag=0; + + while ( *pWild || flag ) + { + switch (*pWild) + { + case CHAR_PLACE: + if ( *pStr == 0 ) + return sal_False; + break; + default: + if (*pWild && (*pWild == cEscape) && ((*(pWild+1)== CHAR_PLACE) || (*(pWild+1) == CHAR_WILD)) ) + pWild++; + if ( rtl_ascii_toUpperCase(*pWild) != rtl_ascii_toUpperCase(*pStr) ) + if ( !pos ) + return sal_False; + else + pWild += pos; + else + break; // ACHTUNG laeuft unter bestimmten + // Umstaenden in den nachsten case rein!! + case CHAR_WILD: + while ( *pWild == CHAR_WILD ) + pWild++; + if ( *pWild == 0 ) + return sal_True; + flag = 1; + pos = 0; + if ( *pStr == 0 ) + return ( *pWild == 0 ); + while ( *pStr && *pStr != *pWild ) + { + if ( *pWild == CHAR_PLACE ) { + pWild++; + while ( *pWild == CHAR_WILD ) + pWild++; + } + pStr++; + if ( *pStr == 0 ) + return ( *pWild == 0 ); + } + break; + } + if ( *pWild != 0 ) + pWild++; + if ( *pStr != 0 ) + pStr++; + else + flag = 0; + if ( flag ) + pos--; + } + return ( *pStr == 0 ) && ( *pWild == 0 ); + } + //------------------------------------------------------------------ + rtl::OUString toDateString(const ::com::sun::star::util::Date& rDate) + { + sal_Char s[11]; + snprintf(s, + sizeof(s), + "%04d-%02d-%02d", + (int)rDate.Year, + (int)rDate.Month, + (int)rDate.Day); + s[10] = 0; + return rtl::OUString::createFromAscii(s); + } + + //------------------------------------------------------------------ + rtl::OUString toTimeString(const ::com::sun::star::util::Time& rTime) + { + sal_Char s[9]; + snprintf(s, + sizeof(s), + "%02d:%02d:%02d", + (int)rTime.Hours, + (int)rTime.Minutes, + (int)rTime.Seconds); + s[8] = 0; + return rtl::OUString::createFromAscii(s); + } + + //------------------------------------------------------------------ + rtl::OUString toDateTimeString(const ::com::sun::star::util::DateTime& rDateTime) + { + sal_Char s[21]; + snprintf(s, + sizeof(s), + "%04d-%02d-%02d %02d:%02d:%02d", + (int)rDateTime.Year, + (int)rDateTime.Month, + (int)rDateTime.Day, + (int)rDateTime.Hours, + (int)rDateTime.Minutes, + (int)rDateTime.Seconds); + s[20] = 0; + return rtl::OUString::createFromAscii(s); + } + + + //-------------------------------------------------------------------------------------------------- + rtl::OUString toString(const Any& rValue) + { + rtl::OUString aRes; + TypeClass aDestinationClass = rValue.getValueType().getTypeClass(); + + switch (aDestinationClass) + { + case TypeClass_CHAR: + aRes = ::rtl::OUString::valueOf(*(sal_Unicode*)rValue.getValue()); + break; + case TypeClass_FLOAT: + aRes = ::rtl::OUString::valueOf(*(float*)rValue.getValue()); + break; + case TypeClass_DOUBLE: + aRes = ::rtl::OUString::valueOf(*(double*)rValue.getValue()); + break; + case TypeClass_BOOLEAN: + aRes = ::rtl::OUString::valueOf((sal_Int32)*(sal_Bool*)rValue.getValue()); + break; + case TypeClass_BYTE: + case TypeClass_SHORT: + case TypeClass_LONG: + aRes = ::rtl::OUString::valueOf(*(sal_Int32*)rValue.getValue()); + break; + case TypeClass_HYPER: + { + sal_Int64 nValue = 0; + OSL_VERIFY( rValue >>= nValue ); + aRes = ::rtl::OUString::valueOf(nValue); + } + case TypeClass_STRING: + rValue >>= aRes; + break; + case TypeClass_STRUCT: + if (rValue.getValueType() == ::getCppuType((const ::com::sun::star::util::Date*)0)) + { + ::com::sun::star::util::Date aDate; + rValue >>= aDate; + aRes = toDateString(aDate); + } + else if (rValue.getValueType() == ::getCppuType((const ::com::sun::star::util::DateTime*)0)) + { + ::com::sun::star::util::DateTime aDT; + rValue >>= aDT; + aRes = toDateTimeString(aDT); + } + else if (rValue.getValueType() == ::getCppuType((const ::com::sun::star::util::Time*)0)) + { + ::com::sun::star::util::Time aTime; + rValue >>= aTime; + aRes = toTimeString(aTime); + } + + break; + default: + ; + } + return aRes; + } + + // ----------------------------------------------------------------------------- + ::rtl::Reference< jvmaccess::VirtualMachine > getJavaVM(const Reference<XMultiServiceFactory >& _rxFactory) + { + ::rtl::Reference< jvmaccess::VirtualMachine > aRet; + OSL_ENSURE(_rxFactory.is(),"No XMultiServiceFactory a.v.!"); + if(!_rxFactory.is()) + return aRet; + + try + { + Reference< starjava::XJavaVM > xVM(_rxFactory->createInstance( + rtl::OUString::createFromAscii("com.sun.star.java.JavaVirtualMachine")), UNO_QUERY); + + OSL_ENSURE(_rxFactory.is(),"InitJava: I have no factory!"); + if (!xVM.is() || !_rxFactory.is()) + throw Exception(); // -2; + + Sequence<sal_Int8> processID(16); + rtl_getGlobalProcessId( (sal_uInt8*) processID.getArray() ); + processID.realloc(17); + processID[16] = 0; + + Any uaJVM = xVM->getJavaVM( processID ); + + if (!uaJVM.hasValue()) + throw Exception(); // -5 + else + { + sal_Int32 nValue = 0; + jvmaccess::VirtualMachine* pJVM = NULL; + if ( uaJVM >>= nValue ) + pJVM = reinterpret_cast< jvmaccess::VirtualMachine* > (nValue); + else + { + sal_Int64 nTemp = 0; + uaJVM >>= nTemp; + pJVM = reinterpret_cast< jvmaccess::VirtualMachine* > (nTemp); + } + aRet = pJVM; + } + } + catch (Exception&) + { + } + + return aRet; + } + //------------------------------------------------------------------------------ + sal_Bool existsJavaClassByName( const ::rtl::Reference< jvmaccess::VirtualMachine >& _pJVM,const ::rtl::OUString& _sClassName ) + { + sal_Bool bRet = sal_False; +#ifdef SOLAR_JAVA + if ( _pJVM.is() ) + { + jvmaccess::VirtualMachine::AttachGuard aGuard(_pJVM); + JNIEnv* pEnv = aGuard.getEnvironment(); + if( pEnv ) + { + ::rtl::OString sClassName = ::rtl::OUStringToOString(_sClassName, RTL_TEXTENCODING_ASCII_US); + sClassName = sClassName.replace('.','/'); + jobject out = pEnv->FindClass(sClassName); + bRet = out != NULL; + pEnv->DeleteLocalRef( out ); + } + } +#endif + return bRet; + } + +} + +#include <ctype.h> //isdigit +namespace dbtools +{ +//------------------------------------------------------------------ +sal_Bool isCharOk(sal_Unicode c,const ::rtl::OUString& _rSpecials) +{ + + return ( ((c >= 97) && (c <= 122)) || ((c >= 65) && (c <= 90)) || ((c >= 48) && (c <= 57)) || + c == '_' || _rSpecials.indexOf(c) != -1); +} + +//------------------------------------------------------------------------------ +sal_Bool isValidSQLName(const ::rtl::OUString& rName,const ::rtl::OUString& _rSpecials) +{ + // Ueberpruefung auf korrekte Namensgebung im SQL Sinne + // Dieses ist wichtig fuer Tabellennamen beispielsweise + const sal_Unicode* pStr = rName.getStr(); + if (*pStr > 127 || isdigit(*pStr)) + return sal_False; + + for (; *pStr; ++pStr ) + if(!isCharOk(*pStr,_rSpecials)) + return sal_False; + + if ( rName.getLength() + && ( (rName.toChar() == '_') + || ( (rName.toChar() >= '0') + && (rName.toChar() <= '9') + ) + ) + ) + return sal_False; + // the SQL-Standard requires the first character to be an alphabetic character, which + // isn't easy to decide in UniCode ... + // So we just prohibit the characters which already lead to problems .... + // 11.04.00 - 74902 - FS + + return sal_True; +} +//------------------------------------------------------------------ +// Erzeugt einen neuen Namen falls noetig +::rtl::OUString convertName2SQLName(const ::rtl::OUString& rName,const ::rtl::OUString& _rSpecials) +{ + if(isValidSQLName(rName,_rSpecials)) + return rName; + ::rtl::OUString aNewName(rName); + const sal_Unicode* pStr = rName.getStr(); + sal_Int32 nLength = rName.getLength(); + sal_Bool bValid(*pStr < 128 && !isdigit(*pStr)); + for (sal_Int32 i=0; bValid && i < nLength; ++pStr,++i ) + if(!isCharOk(*pStr,_rSpecials)) + { + aNewName = aNewName.replace(*pStr,'_'); + pStr = aNewName.getStr() + i; + } + + if ( !bValid ) + aNewName = ::rtl::OUString(); + + return aNewName; +} +//------------------------------------------------------------------------------ +::rtl::OUString quoteName(const ::rtl::OUString& _rQuote, const ::rtl::OUString& _rName) +{ + ::rtl::OUString sName = _rName; + if(_rQuote.getLength() && _rQuote.toChar() != ' ') + sName = _rQuote + _rName + _rQuote; + return sName; +} + + +} diff --git a/connectivity/source/commontools/ConnectionWrapper.cxx b/connectivity/source/commontools/ConnectionWrapper.cxx new file mode 100644 index 000000000000..61d3b06cb25d --- /dev/null +++ b/connectivity/source/commontools/ConnectionWrapper.cxx @@ -0,0 +1,267 @@ +/************************************************************************* + * + * 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" +#ifndef _CONNECTIVITY_CONNECTIONWRAPPER_HXX_ +#include "connectivity/ConnectionWrapper.hxx" +#endif +#include <com/sun/star/sdbc/ColumnValue.hpp> +#include <com/sun/star/sdbc/XRow.hpp> +#include <com/sun/star/lang/DisposedException.hpp> +#include <comphelper/uno3.hxx> +#include <comphelper/sequence.hxx> +#include <cppuhelper/typeprovider.hxx> +#include <com/sun/star/reflection/XProxyFactory.hpp> +#include <rtl/digest.h> +#include <algorithm> + +#include <algorithm> + +using namespace connectivity; +//------------------------------------------------------------------------------ +using namespace com::sun::star::uno; +using namespace com::sun::star::lang; +using namespace com::sun::star::beans; +using namespace com::sun::star::sdbc; +using namespace ::com::sun::star::reflection; +// -------------------------------------------------------------------------------- +OConnectionWrapper::OConnectionWrapper() +{ + +} +// ----------------------------------------------------------------------------- +void OConnectionWrapper::setDelegation(Reference< XAggregation >& _rxProxyConnection,oslInterlockedCount& _rRefCount) +{ + OSL_ENSURE(_rxProxyConnection.is(),"OConnectionWrapper: Connection must be valid!"); + osl_incrementInterlockedCount( &_rRefCount ); + if (_rxProxyConnection.is()) + { + // transfer the (one and only) real ref to the aggregate to our member + m_xProxyConnection = _rxProxyConnection; + _rxProxyConnection = NULL; + ::comphelper::query_aggregation(m_xProxyConnection,m_xConnection); + m_xTypeProvider.set(m_xConnection,UNO_QUERY); + m_xUnoTunnel.set(m_xConnection,UNO_QUERY); + m_xServiceInfo.set(m_xConnection,UNO_QUERY); + + // set ourself as delegator + Reference<XInterface> xIf = static_cast< XUnoTunnel* >( this ); + m_xProxyConnection->setDelegator( xIf ); + + } + osl_decrementInterlockedCount( &_rRefCount ); +} +// ----------------------------------------------------------------------------- +void OConnectionWrapper::setDelegation(const Reference< XConnection >& _xConnection + ,const Reference< XMultiServiceFactory>& _xORB + ,oslInterlockedCount& _rRefCount) +{ + OSL_ENSURE(_xConnection.is(),"OConnectionWrapper: Connection must be valid!"); + osl_incrementInterlockedCount( &_rRefCount ); + + m_xConnection = _xConnection; + m_xTypeProvider.set(m_xConnection,UNO_QUERY); + m_xUnoTunnel.set(m_xConnection,UNO_QUERY); + m_xServiceInfo.set(m_xConnection,UNO_QUERY); + + Reference< XProxyFactory > xProxyFactory(_xORB->createInstance(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.reflection.ProxyFactory"))),UNO_QUERY); + Reference< XAggregation > xConProxy = xProxyFactory->createProxy(_xConnection); + if (xConProxy.is()) + { + // transfer the (one and only) real ref to the aggregate to our member + m_xProxyConnection = xConProxy; + + // set ourself as delegator + Reference<XInterface> xIf = static_cast< XUnoTunnel* >( this ); + m_xProxyConnection->setDelegator( xIf ); + + } + osl_decrementInterlockedCount( &_rRefCount ); +} +// ----------------------------------------------------------------------------- +void OConnectionWrapper::disposing() +{ +m_xConnection.clear(); +} +//----------------------------------------------------------------------------- +OConnectionWrapper::~OConnectionWrapper() +{ + if (m_xProxyConnection.is()) + m_xProxyConnection->setDelegator(NULL); +} + +// XServiceInfo +// -------------------------------------------------------------------------------- +::rtl::OUString SAL_CALL OConnectionWrapper::getImplementationName( ) throw (::com::sun::star::uno::RuntimeException) +{ + return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.sdbc.drivers.OConnectionWrapper" ) ); +} + +// -------------------------------------------------------------------------------- +::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL OConnectionWrapper::getSupportedServiceNames( ) throw(::com::sun::star::uno::RuntimeException) +{ + // first collect the services which are supported by our aggregate + Sequence< ::rtl::OUString > aSupported; + if ( m_xServiceInfo.is() ) + aSupported = m_xServiceInfo->getSupportedServiceNames(); + + // append our own service, if necessary + ::rtl::OUString sConnectionService( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.sdbc.Connection" ) ); + if ( 0 == ::comphelper::findValue( aSupported, sConnectionService, sal_True ).getLength() ) + { + sal_Int32 nLen = aSupported.getLength(); + aSupported.realloc( nLen + 1 ); + aSupported[ nLen ] = sConnectionService; + } + + // outta here + return aSupported; +} + +// -------------------------------------------------------------------------------- +sal_Bool SAL_CALL OConnectionWrapper::supportsService( const ::rtl::OUString& _rServiceName ) throw(::com::sun::star::uno::RuntimeException) +{ + return ::comphelper::findValue( getSupportedServiceNames(), _rServiceName, sal_True ).getLength() != 0; +} + +// -------------------------------------------------------------------------------- +Any SAL_CALL OConnectionWrapper::queryInterface( const Type& _rType ) throw (RuntimeException) +{ + Any aReturn = OConnection_BASE::queryInterface(_rType); + return aReturn.hasValue() ? aReturn : (m_xProxyConnection.is() ? m_xProxyConnection->queryAggregation(_rType) : aReturn); +} +// -------------------------------------------------------------------------------- +Sequence< Type > SAL_CALL OConnectionWrapper::getTypes( ) throw (::com::sun::star::uno::RuntimeException) +{ + return ::comphelper::concatSequences( + OConnection_BASE::getTypes(), + m_xTypeProvider->getTypes() + ); +} +// ----------------------------------------------------------------------------- +// com::sun::star::lang::XUnoTunnel +sal_Int64 SAL_CALL OConnectionWrapper::getSomething( const Sequence< sal_Int8 >& rId ) throw(RuntimeException) +{ + if (rId.getLength() == 16 && 0 == rtl_compareMemory(getUnoTunnelImplementationId().getConstArray(), rId.getConstArray(), 16 ) ) + return reinterpret_cast< sal_Int64 >( this ); + + if(m_xUnoTunnel.is()) + return m_xUnoTunnel->getSomething(rId); + return 0; +} + +// ----------------------------------------------------------------------------- +Sequence< sal_Int8 > OConnectionWrapper::getUnoTunnelImplementationId() +{ + static ::cppu::OImplementationId * pId = 0; + if (! pId) + { + ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ); + if (! pId) + { + static ::cppu::OImplementationId aId; + pId = &aId; + } + } + return pId->getImplementationId(); +} +// ----------------------------------------------------------------------------- +namespace +{ + class TPropertyValueLessFunctor : public ::std::binary_function< ::com::sun::star::beans::PropertyValue,::com::sun::star::beans::PropertyValue,bool> + { + public: + TPropertyValueLessFunctor() + {} + bool operator() (const ::com::sun::star::beans::PropertyValue& lhs, const ::com::sun::star::beans::PropertyValue& rhs) const + { + return !!(lhs.Name.equalsIgnoreAsciiCase( rhs.Name )); + } + }; + +} + +// ----------------------------------------------------------------------------- +// creates a unique id out of the url and sequence of properties +void OConnectionWrapper::createUniqueId( const ::rtl::OUString& _rURL + ,Sequence< PropertyValue >& _rInfo + ,sal_uInt8* _pBuffer + ,const ::rtl::OUString& _rUserName + ,const ::rtl::OUString& _rPassword) +{ + // first we create the digest we want to have + rtlDigest aDigest = rtl_digest_create( rtl_Digest_AlgorithmSHA1 ); + rtlDigestError aError = rtl_digest_update(aDigest,_rURL.getStr(),_rURL.getLength()*sizeof(sal_Unicode)); + if ( _rUserName.getLength() ) + aError = rtl_digest_update(aDigest,_rUserName.getStr(),_rUserName.getLength()*sizeof(sal_Unicode)); + if ( _rPassword.getLength() ) + aError = rtl_digest_update(aDigest,_rPassword.getStr(),_rPassword.getLength()*sizeof(sal_Unicode)); + // now we need to sort the properties + PropertyValue* pBegin = _rInfo.getArray(); + PropertyValue* pEnd = pBegin + _rInfo.getLength(); + ::std::sort(pBegin,pEnd,TPropertyValueLessFunctor()); + + pBegin = _rInfo.getArray(); + pEnd = pBegin + _rInfo.getLength(); + for (; pBegin != pEnd; ++pBegin) + { + // we only include strings an integer values + ::rtl::OUString sValue; + if ( pBegin->Value >>= sValue ) + ; + else + { + sal_Int32 nValue = 0; + if ( pBegin->Value >>= nValue ) + sValue = ::rtl::OUString::valueOf(nValue); + else + { + Sequence< ::rtl::OUString> aSeq; + if ( pBegin->Value >>= aSeq ) + { + const ::rtl::OUString* pSBegin = aSeq.getConstArray(); + const ::rtl::OUString* pSEnd = pSBegin + aSeq.getLength(); + for(;pSBegin != pSEnd;++pSBegin) + aError = rtl_digest_update(aDigest,pSBegin->getStr(),pSBegin->getLength()*sizeof(sal_Unicode)); + } + } + } + if ( sValue.getLength() > 0 ) + { + // we don't have to convert this into UTF8 because we don't store on a file system + aError = rtl_digest_update(aDigest,sValue.getStr(),sValue.getLength()*sizeof(sal_Unicode)); + } + } + + aError = rtl_digest_get(aDigest,_pBuffer,RTL_DIGEST_LENGTH_SHA1); + // we have to destroy the digest + rtl_digest_destroy(aDigest); +} +// ----------------------------------------------------------------------------- + + diff --git a/connectivity/source/commontools/DateConversion.cxx b/connectivity/source/commontools/DateConversion.cxx new file mode 100644 index 000000000000..9f5be37f208f --- /dev/null +++ b/connectivity/source/commontools/DateConversion.cxx @@ -0,0 +1,520 @@ +/************************************************************************* + * + * 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 "connectivity/dbconversion.hxx" +#include <connectivity/dbtools.hxx> +#include <com/sun/star/script/XTypeConverter.hpp> +#include <com/sun/star/sdbc/DataType.hpp> +#include <com/sun/star/util/NumberFormat.hpp> +#include <com/sun/star/util/XNumberFormatTypes.hpp> +#include <com/sun/star/sdb/XColumnUpdate.hpp> +#include <com/sun/star/sdb/XColumn.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <comphelper/extract.hxx> +#include "TConnection.hxx" +#include "diagnose_ex.h" +#include <comphelper/numbers.hxx> +#include <rtl/ustrbuf.hxx> + + +using namespace ::connectivity; +using namespace ::comphelper; +using namespace ::com::sun::star::script; +using namespace ::com::sun::star::sdb; +using namespace ::com::sun::star::sdbc; +using namespace ::dbtools; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::util; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::util; +using namespace ::com::sun::star::beans; +// ----------------------------------------------------------------------------- +::rtl::OUString DBTypeConversion::toSQLString(sal_Int32 eType, const Any& _rVal, sal_Bool bQuote, + const Reference< XTypeConverter >& _rxTypeConverter) +{ + ::rtl::OUStringBuffer aRet; + if (_rVal.hasValue()) + { + try + { + switch (eType) + { + case DataType::INTEGER: + case DataType::BIT: + case DataType::BOOLEAN: + case DataType::TINYINT: + case DataType::SMALLINT: + if (_rVal.getValueType().getTypeClass() == ::com::sun::star::uno::TypeClass_BOOLEAN) + { + if (::cppu::any2bool(_rVal)) + aRet.appendAscii("1"); + else + aRet.appendAscii("0"); + } + else + { + ::rtl::OUString sTemp; + _rxTypeConverter->convertToSimpleType(_rVal, TypeClass_STRING) >>= sTemp; + aRet.append(sTemp); + } + break; + case DataType::CHAR: + case DataType::VARCHAR: + case DataType::LONGVARCHAR: + if (bQuote) + aRet.appendAscii("'"); + { + ::rtl::OUString aTemp; + _rxTypeConverter->convertToSimpleType(_rVal, TypeClass_STRING) >>= aTemp; + sal_Int32 nIndex = (sal_Int32)-1; + const ::rtl::OUString sQuot(RTL_CONSTASCII_USTRINGPARAM("\'")); + const ::rtl::OUString sQuotToReplace(RTL_CONSTASCII_USTRINGPARAM("\'\'")); + do + { + nIndex += 2; + nIndex = aTemp.indexOf(sQuot,nIndex); + if(nIndex != -1) + aTemp = aTemp.replaceAt(nIndex,sQuot.getLength(),sQuotToReplace); + } while (nIndex != -1); + + aRet.append(aTemp); + } + if (bQuote) + aRet.appendAscii("'"); + break; + case DataType::REAL: + case DataType::DOUBLE: + case DataType::DECIMAL: + case DataType::NUMERIC: + case DataType::BIGINT: + default: + { + ::rtl::OUString sTemp; + _rxTypeConverter->convertToSimpleType(_rVal, TypeClass_STRING) >>= sTemp; + aRet.append(sTemp); + } + break; + case DataType::TIMESTAMP: + { + DateTime aDateTime; + bool bOk = false; + if (_rVal.getValueType().getTypeClass() == ::com::sun::star::uno::TypeClass_DOUBLE) + { + double nValue = 0.0; + _rVal >>= nValue; + aDateTime = DBTypeConversion::toDateTime(nValue); + bOk = true; + } + else if (_rVal.getValueType().getTypeClass() == ::com::sun::star::uno::TypeClass_STRING) + { + ::rtl::OUString sValue; + _rVal >>= sValue; + aDateTime = DBTypeConversion::toDateTime(sValue); + bOk = true; + } + else + bOk = _rVal >>= aDateTime; + + OSL_VERIFY_RES( bOk, "DBTypeConversion::toSQLString: _rVal is not datetime!"); + // check if this is really a timestamp or only a date + if ( bOk ) + { + if (bQuote) + aRet.appendAscii("{TS '"); + aRet.append(DBTypeConversion::toDateTimeString(aDateTime)); + if (bQuote) + aRet.appendAscii("'}"); + break; + } + break; + } + case DataType::DATE: + { + Date aDate; + bool bOk = false; + if (_rVal.getValueType().getTypeClass() == ::com::sun::star::uno::TypeClass_DOUBLE) + { + double nValue = 0.0; + _rVal >>= nValue; + aDate = DBTypeConversion::toDate(nValue); + bOk = true; + } + else if (_rVal.getValueType().getTypeClass() == ::com::sun::star::uno::TypeClass_STRING) + { + ::rtl::OUString sValue; + _rVal >>= sValue; + aDate = DBTypeConversion::toDate(sValue); + bOk = true; + } + else + bOk = _rVal >>= aDate; + OSL_VERIFY_RES( bOk, "DBTypeConversion::toSQLString: _rVal is not date!"); + if (bQuote) + aRet.appendAscii("{D '"); + aRet.append(DBTypeConversion::toDateString(aDate)); + if (bQuote) + aRet.appendAscii("'}"); + } break; + case DataType::TIME: + { + Time aTime; + bool bOk = false; + if (_rVal.getValueType().getTypeClass() == ::com::sun::star::uno::TypeClass_DOUBLE) + { + double nValue = 0.0; + _rVal >>= nValue; + aTime = DBTypeConversion::toTime(nValue); + bOk = true; + } + else if (_rVal.getValueType().getTypeClass() == ::com::sun::star::uno::TypeClass_STRING) + { + ::rtl::OUString sValue; + _rVal >>= sValue; + aTime = DBTypeConversion::toTime(sValue); + bOk = true; + } + else + bOk = _rVal >>= aTime; + OSL_VERIFY_RES( bOk,"DBTypeConversion::toSQLString: _rVal is not time!"); + if (bQuote) + aRet.appendAscii("{T '"); + aRet.append(DBTypeConversion::toTimeString(aTime)); + if (bQuote) + aRet.appendAscii("'}"); + } break; + } + } + catch ( const Exception& ) + { + OSL_ENSURE(0,"TypeConversion Error"); + } + } + else + aRet.appendAscii(" NULL "); + return aRet.makeStringAndClear(); +} +// ----------------------------------------------------------------------------- +Date DBTypeConversion::getNULLDate(const Reference< XNumberFormatsSupplier > &xSupplier) +{ + OSL_ENSURE(xSupplier.is(), "getNULLDate : the formatter doesn't implement a supplier !"); + if (xSupplier.is()) + { + try + { + // get the null date + Date aDate; + xSupplier->getNumberFormatSettings()->getPropertyValue(::rtl::OUString::createFromAscii("NullDate")) >>= aDate; + return aDate; + } + catch ( const Exception& ) + { + } + } + + return getStandardDate(); +} +// ----------------------------------------------------------------------------- +void DBTypeConversion::setValue(const Reference<XColumnUpdate>& xVariant, + const Reference<XNumberFormatter>& xFormatter, + const Date& rNullDate, + const ::rtl::OUString& rString, + sal_Int32 nKey, + sal_Int16 nFieldType, + sal_Int16 nKeyType) throw(::com::sun::star::lang::IllegalArgumentException) +{ + double fValue = 0; + if (rString.getLength()) + { + // Muss der String formatiert werden? + sal_Int16 nTypeClass = nKeyType & ~NumberFormat::DEFINED; + sal_Bool bTextFormat = nTypeClass == NumberFormat::TEXT; + sal_Int32 nKeyToUse = bTextFormat ? 0 : nKey; + sal_Int16 nRealUsedTypeClass = nTypeClass; + // bei einem Text-Format muessen wir dem Formatter etwas mehr Freiheiten einraeumen, sonst + // wirft convertStringToNumber eine NotNumericException + try + { + fValue = xFormatter->convertStringToNumber(nKeyToUse, rString); + sal_Int32 nRealUsedKey = xFormatter->detectNumberFormat(0, rString); + if (nRealUsedKey != nKeyToUse) + nRealUsedTypeClass = getNumberFormatType(xFormatter, nRealUsedKey) & ~NumberFormat::DEFINED; + + // und noch eine Sonderbehandlung, diesmal fuer Prozent-Formate + if ((NumberFormat::NUMBER == nRealUsedTypeClass) && (NumberFormat::PERCENT == nTypeClass)) + { // die Formatierung soll eigentlich als Prozent erfolgen, aber der String stellt nur eine + // einfache Nummer dar -> anpassen + ::rtl::OUString sExpanded(rString); + static ::rtl::OUString s_sPercentSymbol = ::rtl::OUString::createFromAscii("%"); + // need a method to add a sal_Unicode to a string, 'til then we use a static string + sExpanded += s_sPercentSymbol; + fValue = xFormatter->convertStringToNumber(nKeyToUse, sExpanded); + } + + switch (nRealUsedTypeClass) + { + case NumberFormat::DATE: + case NumberFormat::DATETIME: + case NumberFormat::TIME: + DBTypeConversion::setValue(xVariant,rNullDate,fValue,nRealUsedTypeClass); + // xVariant->updateDouble(toStandardDbDate(rNullDate, fValue)); + break; + case NumberFormat::CURRENCY: + case NumberFormat::NUMBER: + case NumberFormat::SCIENTIFIC: + case NumberFormat::FRACTION: + case NumberFormat::PERCENT: + xVariant->updateDouble(fValue); + break; + default: + xVariant->updateString(rString); + } + } + catch(const Exception& ) + { + xVariant->updateString(rString); + } + } + else + { + switch (nFieldType) + { + case ::com::sun::star::sdbc::DataType::CHAR: + case ::com::sun::star::sdbc::DataType::VARCHAR: + case ::com::sun::star::sdbc::DataType::LONGVARCHAR: + xVariant->updateString(rString); + break; + default: + xVariant->updateNull(); + } + } +} + +//------------------------------------------------------------------------------ +void DBTypeConversion::setValue(const Reference<XColumnUpdate>& xVariant, + const Date& rNullDate, + const double& rValue, + sal_Int16 nKeyType) throw(::com::sun::star::lang::IllegalArgumentException) +{ + switch (nKeyType & ~NumberFormat::DEFINED) + { + case NumberFormat::DATE: + xVariant->updateDate(toDate( rValue, rNullDate)); + break; + case NumberFormat::DATETIME: + xVariant->updateTimestamp(toDateTime(rValue,rNullDate)); + break; + case NumberFormat::TIME: + xVariant->updateTime(toTime(rValue)); + break; + default: + { + double nValue = rValue; +// Reference<XPropertySet> xProp(xVariant,UNO_QUERY); +// if ( xProp.is() +// && xProp->getPropertySetInfo()->hasPropertyByName(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_ISSIGNED)) +// && !::comphelper::getBOOL(xProp->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_ISSIGNED))) ) +// { +// switch (::comphelper::getINT32(xProp->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_TYPE)))) +// { +// case DataType::TINYINT: +// nValue = static_cast<sal_uInt8>(rValue); +// break; +// case DataType::SMALLINT: +// nValue = static_cast<sal_uInt16>(rValue); +// break; +// case DataType::INTEGER: +// nValue = static_cast<sal_uInt32>(rValue); +// break; +// case DataType::BIGINT: +// nValue = static_cast<sal_uInt64>(rValue); +// break; +// } +// } + xVariant->updateDouble(nValue); + } + } +} + +//------------------------------------------------------------------------------ +double DBTypeConversion::getValue(const Reference<XColumn>& xVariant, + const Date& rNullDate, + sal_Int16 nKeyType) +{ + try + { + switch (nKeyType & ~NumberFormat::DEFINED) + { + case NumberFormat::DATE: + return toDouble( xVariant->getDate(), rNullDate); + case NumberFormat::DATETIME: + return toDouble(xVariant->getTimestamp(),rNullDate); + case NumberFormat::TIME: + return toDouble(xVariant->getTime()); + default: + { + Reference<XPropertySet> xProp(xVariant,UNO_QUERY); + if ( xProp.is() + && xProp->getPropertySetInfo()->hasPropertyByName(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_ISSIGNED)) + && !::comphelper::getBOOL(xProp->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_ISSIGNED))) ) + { + switch (::comphelper::getINT32(xProp->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_TYPE)))) + { + case DataType::TINYINT: + return static_cast<double>(static_cast<sal_uInt8>(xVariant->getByte())); + case DataType::SMALLINT: + return static_cast<double>(static_cast<sal_uInt16>(xVariant->getShort())); + case DataType::INTEGER: + return static_cast<double>(static_cast<sal_uInt32>(xVariant->getInt())); + case DataType::BIGINT: + return static_cast<double>(static_cast<sal_uInt64>(xVariant->getLong())); + } + } + + return xVariant->getDouble(); + } + } + } + catch(const Exception& ) + { + return 0.0; + } +} +//------------------------------------------------------------------------------ +::rtl::OUString DBTypeConversion::getValue(const Reference< XPropertySet>& _xColumn, + const Reference<XNumberFormatter>& _xFormatter, + const ::com::sun::star::lang::Locale& _rLocale, + const Date& _rNullDate) +{ + OSL_ENSURE(_xColumn.is() && _xFormatter.is(), "DBTypeConversion::getValue: invalid arg !"); + if (!_xColumn.is() || !_xFormatter.is()) + return ::rtl::OUString(); + + sal_Int32 nKey(0); + try + { + _xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_FORMATKEY)) >>= nKey; + } + catch (const Exception& ) + { + OSL_ENSURE(false, "DBTypeConversion::getValue: caught an exception while asking for the format key!"); + } + + if (!nKey) + { + Reference<XNumberFormats> xFormats( _xFormatter->getNumberFormatsSupplier()->getNumberFormats() ); + Reference<XNumberFormatTypes> xTypeList(_xFormatter->getNumberFormatsSupplier()->getNumberFormats(), UNO_QUERY); + + nKey = ::dbtools::getDefaultNumberFormat(_xColumn, + Reference< XNumberFormatTypes > (xFormats, UNO_QUERY), + _rLocale); + + } + + sal_Int16 nKeyType = getNumberFormatType(_xFormatter, nKey) & ~NumberFormat::DEFINED; + + return DBTypeConversion::getValue(Reference< XColumn > (_xColumn, UNO_QUERY), _xFormatter, _rNullDate, nKey, nKeyType); +} + +//------------------------------------------------------------------------------ +::rtl::OUString DBTypeConversion::getValue(const Reference<XColumn>& xVariant, + const Reference<XNumberFormatter>& xFormatter, + const Date& rNullDate, + sal_Int32 nKey, + sal_Int16 nKeyType) +{ + ::rtl::OUString aString; + if (xVariant.is()) + { + try + { + switch (nKeyType & ~NumberFormat::DEFINED) + { + case NumberFormat::DATE: + case NumberFormat::DATETIME: + { + // get a value which represents the given date, relative to the given null date + double fValue = getValue(xVariant, rNullDate, nKeyType); + if ( !xVariant->wasNull() ) + { + // get the null date of the formatter + Date aFormatterNullDate( rNullDate ); + try + { + Reference< XPropertySet > xFormatterSettings; + Reference< XNumberFormatsSupplier > xSupplier( xFormatter->getNumberFormatsSupplier( ) ); + if ( xSupplier.is() ) + xFormatterSettings = xSupplier->getNumberFormatSettings(); + if ( xFormatterSettings.is() ) + xFormatterSettings->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "NullDate" ) ) ) >>= aFormatterNullDate; + } + catch( const Exception& ) + { + OSL_ENSURE( sal_False, "DBTypeConversion::getValue: caught an exception while retrieving the formatter's NullDate!" ); + } + // get a value which represents the given date, relative to the null date of the formatter + fValue -= toDays( rNullDate, aFormatterNullDate ); + // format this value + aString = xFormatter->convertNumberToString( nKey, fValue ); + } + } + break; + case NumberFormat::TIME: + case NumberFormat::NUMBER: + case NumberFormat::SCIENTIFIC: + case NumberFormat::FRACTION: + case NumberFormat::PERCENT: + { + double fValue = xVariant->getDouble(); + if (!xVariant->wasNull()) + aString = xFormatter->convertNumberToString(nKey, fValue); + } break; + case NumberFormat::CURRENCY: + { + double fValue = xVariant->getDouble(); + if (!xVariant->wasNull()) + aString = xFormatter->getInputString(nKey, fValue); + } break; + case NumberFormat::TEXT: + aString = xFormatter->formatString(nKey, xVariant->getString()); + break; + default: + aString = xVariant->getString(); + } + } + catch(const Exception& ) + { + aString = xVariant->getString(); + } + } + return aString; +} +//------------------------------------------------------------------ diff --git a/connectivity/source/commontools/DriversConfig.cxx b/connectivity/source/commontools/DriversConfig.cxx new file mode 100755 index 000000000000..48c2736cd05a --- /dev/null +++ b/connectivity/source/commontools/DriversConfig.cxx @@ -0,0 +1,262 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ +#include "connectivity/DriversConfig.hxx" +#include <tools/wldcrd.hxx> + +using namespace connectivity; +using namespace utl; +using namespace ::com::sun::star; + +namespace +{ + void lcl_convert(const uno::Sequence< ::rtl::OUString >& _aSource,uno::Any& _rDest) + { + uno::Sequence<uno::Any> aRet(_aSource.getLength()); + uno::Any* pAny = aRet.getArray(); + const ::rtl::OUString* pIter = _aSource.getConstArray(); + const ::rtl::OUString* pEnd = pIter + _aSource.getLength(); + for (;pIter != pEnd ; ++pIter,++pAny) + { + *pAny <<= *pIter; + } + _rDest <<= aRet; + } + void lcl_fillValues(const ::utl::OConfigurationNode& _aURLPatternNode,const ::rtl::OUString& _sNode,::comphelper::NamedValueCollection& _rValues) + { + const ::utl::OConfigurationNode aPropertiesNode = _aURLPatternNode.openNode(_sNode); + if ( aPropertiesNode.isValid() ) + { + uno::Sequence< ::rtl::OUString > aStringSeq; + static const ::rtl::OUString s_sValue(RTL_CONSTASCII_USTRINGPARAM("/Value")); + const uno::Sequence< ::rtl::OUString > aProperties = aPropertiesNode.getNodeNames(); + const ::rtl::OUString* pPropertiesIter = aProperties.getConstArray(); + const ::rtl::OUString* pPropertiesEnd = pPropertiesIter + aProperties.getLength(); + for (;pPropertiesIter != pPropertiesEnd ; ++pPropertiesIter) + { + uno::Any aValue = aPropertiesNode.getNodeValue(*pPropertiesIter + s_sValue); + if ( aValue >>= aStringSeq ) + { + lcl_convert(aStringSeq,aValue); + } + _rValues.put(*pPropertiesIter,aValue); + } // for (;pPropertiesIter != pPropertiesEnd ; ++pPropertiesIter,++pNamedIter) + } // if ( aPropertiesNode.isValid() ) + } + void lcl_readURLPatternNode(const ::utl::OConfigurationTreeRoot& _aInstalled,const ::rtl::OUString& _sEntry,TInstalledDriver& _rInstalledDriver) + { + const ::utl::OConfigurationNode aURLPatternNode = _aInstalled.openNode(_sEntry); + if ( aURLPatternNode.isValid() ) + { + static const ::rtl::OUString s_sParentURLPattern(RTL_CONSTASCII_USTRINGPARAM("ParentURLPattern")); + static const ::rtl::OUString s_sDriver(RTL_CONSTASCII_USTRINGPARAM("Driver")); + static const ::rtl::OUString s_sDriverTypeDisplayName(RTL_CONSTASCII_USTRINGPARAM("DriverTypeDisplayName")); + static const ::rtl::OUString s_sProperties(RTL_CONSTASCII_USTRINGPARAM("Properties")); + static const ::rtl::OUString s_sFeatures(RTL_CONSTASCII_USTRINGPARAM("Features")); + static const ::rtl::OUString s_sMetaData(RTL_CONSTASCII_USTRINGPARAM("MetaData")); + ::rtl::OUString sParentURLPattern; + aURLPatternNode.getNodeValue(s_sParentURLPattern) >>= sParentURLPattern; + if ( sParentURLPattern.getLength() ) + lcl_readURLPatternNode(_aInstalled,sParentURLPattern,_rInstalledDriver); + + ::rtl::OUString sDriverFactory; + aURLPatternNode.getNodeValue(s_sDriver) >>= sDriverFactory; + if ( sDriverFactory.getLength() ) + _rInstalledDriver.sDriverFactory = sDriverFactory; + + ::rtl::OUString sDriverTypeDisplayName; + aURLPatternNode.getNodeValue(s_sDriverTypeDisplayName) >>= sDriverTypeDisplayName; + OSL_ENSURE(sDriverTypeDisplayName.getLength(),"No valid DriverTypeDisplayName property!"); + if ( sDriverTypeDisplayName.getLength() ) + _rInstalledDriver.sDriverTypeDisplayName = sDriverTypeDisplayName; + + lcl_fillValues(aURLPatternNode,s_sProperties,_rInstalledDriver.aProperties); + lcl_fillValues(aURLPatternNode,s_sFeatures,_rInstalledDriver.aFeatures); + lcl_fillValues(aURLPatternNode,s_sMetaData,_rInstalledDriver.aMetaData); + } + } +} +// ----------------------------------------------------------------------------- +DriversConfigImpl::DriversConfigImpl() +{ +} +// ----------------------------------------------------------------------------- +void DriversConfigImpl::Load(const uno::Reference< lang::XMultiServiceFactory >& _rxORB) const +{ + if ( m_aDrivers.empty() ) + { + if ( !m_aInstalled.isValid() ) + { + static const ::rtl::OUString s_sNodeName(RTL_CONSTASCII_USTRINGPARAM("org.openoffice.Office.DataAccess.Drivers/Installed")); ///Installed + m_aInstalled = ::utl::OConfigurationTreeRoot::createWithServiceFactory(_rxORB, s_sNodeName, -1, ::utl::OConfigurationTreeRoot::CM_READONLY); + } + + if ( m_aInstalled.isValid() ) + { + const uno::Sequence< ::rtl::OUString > aURLPatterns = m_aInstalled.getNodeNames(); + const ::rtl::OUString* pPatternIter = aURLPatterns.getConstArray(); + const ::rtl::OUString* pPatternEnd = pPatternIter + aURLPatterns.getLength(); + for (;pPatternIter != pPatternEnd ; ++pPatternIter) + { + TInstalledDriver aInstalledDriver; + lcl_readURLPatternNode(m_aInstalled,*pPatternIter,aInstalledDriver); + if ( aInstalledDriver.sDriverFactory.getLength() ) + m_aDrivers.insert(TInstalledDrivers::value_type(*pPatternIter,aInstalledDriver)); + } + } // if ( m_aInstalled.isValid() ) + } +} +// ----------------------------------------------------------------------------- +DriversConfig::DriversConfig(const uno::Reference< lang::XMultiServiceFactory >& _rxORB) +:m_xORB(_rxORB) +{ +} + +// ----------------------------------------------------------------------------- +DriversConfig::~DriversConfig() +{ +} + +// ----------------------------------------------------------------------------- +DriversConfig::DriversConfig( const DriversConfig& _rhs ) +{ + *this = _rhs; +} + +// ----------------------------------------------------------------------------- +DriversConfig& DriversConfig::operator=( const DriversConfig& _rhs ) +{ + if ( this != &_rhs ) + { + m_aNode = _rhs.m_aNode; + } + return *this; +} + +// ----------------------------------------------------------------------------- +::rtl::OUString DriversConfig::getDriverFactoryName(const ::rtl::OUString& _sURL) const +{ + const TInstalledDrivers& rDrivers = m_aNode->getInstalledDrivers(m_xORB); + ::rtl::OUString sRet; + ::rtl::OUString sOldPattern; + TInstalledDrivers::const_iterator aIter = rDrivers.begin(); + TInstalledDrivers::const_iterator aEnd = rDrivers.end(); + for(;aIter != aEnd;++aIter) + { + WildCard aWildCard(aIter->first); + if ( sOldPattern.getLength() < aIter->first.getLength() && aWildCard.Matches(_sURL) ) + { + sRet = aIter->second.sDriverFactory; + sOldPattern = aIter->first; + } + } + + return sRet; +} +// ----------------------------------------------------------------------------- +::rtl::OUString DriversConfig::getDriverTypeDisplayName(const ::rtl::OUString& _sURL) const +{ + const TInstalledDrivers& rDrivers = m_aNode->getInstalledDrivers(m_xORB); + ::rtl::OUString sRet; + ::rtl::OUString sOldPattern; + TInstalledDrivers::const_iterator aIter = rDrivers.begin(); + TInstalledDrivers::const_iterator aEnd = rDrivers.end(); + for(;aIter != aEnd;++aIter) + { + WildCard aWildCard(aIter->first); + if ( sOldPattern.getLength() < aIter->first.getLength() && aWildCard.Matches(_sURL) ) + { + sRet = aIter->second.sDriverTypeDisplayName; + sOldPattern = aIter->first; + } + } + + return sRet; +} +// ----------------------------------------------------------------------------- +const ::comphelper::NamedValueCollection& DriversConfig::getProperties(const ::rtl::OUString& _sURL) const +{ + return impl_get(_sURL,1); +} +// ----------------------------------------------------------------------------- +const ::comphelper::NamedValueCollection& DriversConfig::getFeatures(const ::rtl::OUString& _sURL) const +{ + return impl_get(_sURL,0); +} +// ----------------------------------------------------------------------------- +const ::comphelper::NamedValueCollection& DriversConfig::getMetaData(const ::rtl::OUString& _sURL) const +{ + return impl_get(_sURL,2); +} +// ----------------------------------------------------------------------------- +const ::comphelper::NamedValueCollection& DriversConfig::impl_get(const ::rtl::OUString& _sURL,sal_Int32 _nProps) const +{ + const TInstalledDrivers& rDrivers = m_aNode->getInstalledDrivers(m_xORB); + const ::comphelper::NamedValueCollection* pRet = NULL; + ::rtl::OUString sOldPattern; + TInstalledDrivers::const_iterator aIter = rDrivers.begin(); + TInstalledDrivers::const_iterator aEnd = rDrivers.end(); + for(;aIter != aEnd;++aIter) + { + WildCard aWildCard(aIter->first); + if ( sOldPattern.getLength() < aIter->first.getLength() && aWildCard.Matches(_sURL) ) + { + switch(_nProps) + { + case 0: + pRet = &aIter->second.aFeatures; + break; + case 1: + pRet = &aIter->second.aProperties; + break; + case 2: + pRet = &aIter->second.aMetaData; + break; + } + sOldPattern = aIter->first; + } + } // for(;aIter != aEnd;++aIter) + if ( pRet == NULL ) + { + static const ::comphelper::NamedValueCollection s_sEmpty; + pRet = &s_sEmpty; + } + return *pRet; +} +// ----------------------------------------------------------------------------- +uno::Sequence< ::rtl::OUString > DriversConfig::getURLs() const +{ + const TInstalledDrivers& rDrivers = m_aNode->getInstalledDrivers(m_xORB); + uno::Sequence< ::rtl::OUString > aRet(rDrivers.size()); + ::rtl::OUString* pIter = aRet.getArray(); + TInstalledDrivers::const_iterator aIter = rDrivers.begin(); + TInstalledDrivers::const_iterator aEnd = rDrivers.end(); + for(;aIter != aEnd;++aIter,++pIter) + { + *pIter = aIter->first; + } + return aRet; +} diff --git a/connectivity/source/commontools/FDatabaseMetaDataResultSet.cxx b/connectivity/source/commontools/FDatabaseMetaDataResultSet.cxx new file mode 100644 index 000000000000..52e76f834ab5 --- /dev/null +++ b/connectivity/source/commontools/FDatabaseMetaDataResultSet.cxx @@ -0,0 +1,913 @@ +/************************************************************************* + * + * 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 "ParameterSubstitution.hxx" +#include "FDatabaseMetaDataResultSet.hxx" +#include "FDatabaseMetaDataResultSetMetaData.hxx" +#include <com/sun/star/sdbc/DataType.hpp> +#include <com/sun/star/sdbc/ColumnSearch.hpp> +#include <com/sun/star/sdbc/KeyRule.hpp> +#include <com/sun/star/sdbc/ProcedureResult.hpp> +#include <com/sun/star/sdbc/IndexType.hpp> +#include <comphelper/property.hxx> +#include <com/sun/star/lang/DisposedException.hpp> +#include <com/sun/star/sdbc/ResultSetConcurrency.hpp> +#include <com/sun/star/sdbc/ResultSetType.hpp> +#include <com/sun/star/sdbc/FetchDirection.hpp> +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <cppuhelper/typeprovider.hxx> +#include <comphelper/sequence.hxx> +#include <cppuhelper/factory.hxx> +#include <cppuhelper/implementationentry.hxx> +#include "connectivity/dbexception.hxx" +#include "TConnection.hxx" + +using namespace connectivity; +using namespace dbtools; +using namespace cppu; +//------------------------------------------------------------------------------ +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::lang; +// ------------------------------------------------------------------------- +ODatabaseMetaDataResultSet::ODatabaseMetaDataResultSet() + :ODatabaseMetaDataResultSet_BASE(m_aMutex) + ,::comphelper::OPropertyContainer(ODatabaseMetaDataResultSet_BASE::rBHelper) + ,m_aStatement(NULL) + ,m_xMetaData(NULL) + ,m_bBOF(sal_True) + ,m_bEOF(sal_True) +{ + construct(); +} + +// ------------------------------------------------------------------------- +ODatabaseMetaDataResultSet::ODatabaseMetaDataResultSet( MetaDataResultSetType _eType ) + :ODatabaseMetaDataResultSet_BASE(m_aMutex) + ,::comphelper::OPropertyContainer(ODatabaseMetaDataResultSet_BASE::rBHelper) + ,m_aStatement(NULL) + ,m_xMetaData(NULL) + ,m_bBOF(sal_True) + ,m_bEOF(sal_True) +{ + construct(); + + setType(_eType); +} + +// ------------------------------------------------------------------------- +ODatabaseMetaDataResultSet::~ODatabaseMetaDataResultSet() +{ +} +// ------------------------------------------------------------------------- +void ODatabaseMetaDataResultSet::construct() +{ + registerProperty(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_FETCHSIZE), PROPERTY_ID_FETCHSIZE, 0,&m_nFetchSize, ::getCppuType(reinterpret_cast<sal_Int32*>(NULL))); + registerProperty(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_RESULTSETTYPE), PROPERTY_ID_RESULTSETTYPE, PropertyAttribute::READONLY,&m_nResultSetType, ::getCppuType(reinterpret_cast<sal_Int32*>(NULL))); + registerProperty(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_FETCHDIRECTION), PROPERTY_ID_FETCHDIRECTION, 0, &m_nFetchDirection, ::getCppuType(reinterpret_cast<sal_Int32*>(NULL))); + registerProperty(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_RESULTSETCONCURRENCY), PROPERTY_ID_RESULTSETCONCURRENCY, PropertyAttribute::READONLY,&m_nResultSetConcurrency, ::getCppuType(reinterpret_cast<sal_Int32*>(NULL))); +} +// ----------------------------------------------------------------------------- +void ODatabaseMetaDataResultSet::setType(MetaDataResultSetType _eType) +{ + switch( _eType ) + { + case eCatalogs: setCatalogsMap(); break; + case eSchemas: setSchemasMap(); break; + case eColumnPrivileges: setColumnPrivilegesMap(); break; + case eColumns: setColumnsMap(); break; + case eTables: setTablesMap(); break; + case eTableTypes: setTableTypes(); break; + case eProcedureColumns: setProcedureColumnsMap(); break; + case eProcedures: setProceduresMap(); break; + case eExportedKeys: setExportedKeysMap(); break; + case eImportedKeys: setImportedKeysMap(); break; + case ePrimaryKeys: setPrimaryKeysMap(); break; + case eIndexInfo: setIndexInfoMap(); break; + case eTablePrivileges: setTablePrivilegesMap(); break; + case eCrossReference: setCrossReferenceMap(); break; + case eTypeInfo: setTypeInfoMap(); break; + case eBestRowIdentifier: setBestRowIdentifierMap(); break; + case eVersionColumns: setVersionColumnsMap(); break; + default: + OSL_ENSURE(0,"Wrong type!"); + } +} +// ------------------------------------------------------------------------- +void ODatabaseMetaDataResultSet::disposing(void) +{ + OPropertySetHelper::disposing(); + + ::osl::MutexGuard aGuard(m_aMutex); + m_aStatement = NULL; +m_xMetaData.clear(); + m_aRowsIter = m_aRows.end(); + m_aRows.clear(); + m_aRowsIter = m_aRows.end(); +} +// ----------------------------------------------------------------------------- +void SAL_CALL ODatabaseMetaDataResultSet::acquire() throw() +{ + ODatabaseMetaDataResultSet_BASE::acquire(); +} +// ----------------------------------------------------------------------------- +void SAL_CALL ODatabaseMetaDataResultSet::release() throw() +{ + ODatabaseMetaDataResultSet_BASE::release(); +} +// ------------------------------------------------------------------------- +Any SAL_CALL ODatabaseMetaDataResultSet::queryInterface( const Type & rType ) throw(RuntimeException) +{ + Any aRet = OPropertySetHelper::queryInterface(rType); + return aRet.hasValue() ? aRet : ODatabaseMetaDataResultSet_BASE::queryInterface(rType); +} +// ------------------------------------------------------------------------- +Sequence< Type > SAL_CALL ODatabaseMetaDataResultSet::getTypes( ) throw(RuntimeException) +{ + ::cppu::OTypeCollection aTypes( ::getCppuType( (const Reference< ::com::sun::star::beans::XMultiPropertySet > *)0 ), + ::getCppuType( (const Reference< ::com::sun::star::beans::XFastPropertySet > *)0 ), + ::getCppuType( (const Reference< ::com::sun::star::beans::XPropertySet > *)0 )); + + return ::comphelper::concatSequences(aTypes.getTypes(),ODatabaseMetaDataResultSet_BASE::getTypes()); +} +// ----------------------------------------------------------------------------- +void ODatabaseMetaDataResultSet::setRows(const ORows& _rRows) +{ + m_aRows = _rRows; + m_bBOF = sal_True; + m_bEOF = m_aRows.empty(); +} +// ------------------------------------------------------------------------- +sal_Int32 SAL_CALL ODatabaseMetaDataResultSet::findColumn( const ::rtl::OUString& columnName ) throw(SQLException, RuntimeException) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(ODatabaseMetaDataResultSet_BASE::rBHelper.bDisposed ); + + + Reference< XResultSetMetaData > xMeta = getMetaData(); + sal_Int32 nLen = xMeta->getColumnCount(); + sal_Int32 i = 1; + for(;i<=nLen;++i) + if(xMeta->isCaseSensitive(i) ? columnName == xMeta->getColumnName(i) : + columnName.equalsIgnoreAsciiCase(xMeta->getColumnName(i)) + ) + break; + return i; +} +// ----------------------------------------------------------------------------- +void ODatabaseMetaDataResultSet::checkIndex(sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException) +{ + if(columnIndex >= (sal_Int32)(*m_aRowsIter).size() || columnIndex < 1) + ::dbtools::throwInvalidIndexException(*this); +} +// ------------------------------------------------------------------------- +Reference< ::com::sun::star::io::XInputStream > SAL_CALL ODatabaseMetaDataResultSet::getBinaryStream( sal_Int32 /*columnIndex*/ ) throw(SQLException, RuntimeException) +{ + return NULL; +} +// ------------------------------------------------------------------------- +Reference< ::com::sun::star::io::XInputStream > SAL_CALL ODatabaseMetaDataResultSet::getCharacterStream( sal_Int32 /*columnIndex*/ ) throw(SQLException, RuntimeException) +{ + return NULL; +} + +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL ODatabaseMetaDataResultSet::getBoolean( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + return getValue(columnIndex); +} +// ------------------------------------------------------------------------- + +sal_Int8 SAL_CALL ODatabaseMetaDataResultSet::getByte( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + return getValue(columnIndex); +} +// ------------------------------------------------------------------------- + +Sequence< sal_Int8 > SAL_CALL ODatabaseMetaDataResultSet::getBytes( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + return getValue(columnIndex); +} +// ------------------------------------------------------------------------- + +::com::sun::star::util::Date SAL_CALL ODatabaseMetaDataResultSet::getDate( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + return getValue(columnIndex); +} +// ------------------------------------------------------------------------- + +double SAL_CALL ODatabaseMetaDataResultSet::getDouble( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + return getValue(columnIndex); +} +// ------------------------------------------------------------------------- + +float SAL_CALL ODatabaseMetaDataResultSet::getFloat( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + return getValue(columnIndex); +} +// ------------------------------------------------------------------------- + +sal_Int32 SAL_CALL ODatabaseMetaDataResultSet::getInt( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + return getValue(columnIndex); +} + +// ------------------------------------------------------------------------- + +sal_Int32 SAL_CALL ODatabaseMetaDataResultSet::getRow( ) throw(SQLException, RuntimeException) +{ + return 0; +} +// ------------------------------------------------------------------------- + +sal_Int64 SAL_CALL ODatabaseMetaDataResultSet::getLong( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + return getValue(columnIndex); +} +// ------------------------------------------------------------------------- + +Reference< XResultSetMetaData > SAL_CALL ODatabaseMetaDataResultSet::getMetaData( ) throw(SQLException, RuntimeException) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(ODatabaseMetaDataResultSet_BASE::rBHelper.bDisposed ); + + + if(!m_xMetaData.is()) + m_xMetaData = new ODatabaseMetaDataResultSetMetaData(); + + return m_xMetaData; +} +// ------------------------------------------------------------------------- +Reference< XArray > SAL_CALL ODatabaseMetaDataResultSet::getArray( sal_Int32 /*columnIndex*/ ) throw(SQLException, RuntimeException) +{ + return NULL; +} + +// ------------------------------------------------------------------------- + +Reference< XClob > SAL_CALL ODatabaseMetaDataResultSet::getClob( sal_Int32 /*columnIndex*/ ) throw(SQLException, RuntimeException) +{ + return NULL; +} +// ------------------------------------------------------------------------- +Reference< XBlob > SAL_CALL ODatabaseMetaDataResultSet::getBlob( sal_Int32 /*columnIndex*/ ) throw(SQLException, RuntimeException) +{ + return NULL; +} +// ------------------------------------------------------------------------- + +Reference< XRef > SAL_CALL ODatabaseMetaDataResultSet::getRef( sal_Int32 /*columnIndex*/ ) throw(SQLException, RuntimeException) +{ + return NULL; +} +// ------------------------------------------------------------------------- + +Any SAL_CALL ODatabaseMetaDataResultSet::getObject( sal_Int32 columnIndex, const Reference< ::com::sun::star::container::XNameAccess >& /*typeMap*/ ) throw(SQLException, RuntimeException) +{ + return getValue(columnIndex).makeAny(); +} +// ------------------------------------------------------------------------- + +sal_Int16 SAL_CALL ODatabaseMetaDataResultSet::getShort( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + return getValue(columnIndex); +} +// ------------------------------------------------------------------------- + +::rtl::OUString SAL_CALL ODatabaseMetaDataResultSet::getString( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + return getValue(columnIndex); +} + +// ------------------------------------------------------------------------- + + +::com::sun::star::util::Time SAL_CALL ODatabaseMetaDataResultSet::getTime( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + return getValue(columnIndex); +} +// ------------------------------------------------------------------------- + + +::com::sun::star::util::DateTime SAL_CALL ODatabaseMetaDataResultSet::getTimestamp( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + return getValue(columnIndex); +} +// ------------------------------------------------------------------------- + +sal_Bool SAL_CALL ODatabaseMetaDataResultSet::isAfterLast( ) throw(SQLException, RuntimeException) +{ + return m_bEOF; +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL ODatabaseMetaDataResultSet::isFirst( ) throw(SQLException, RuntimeException) +{ + ::dbtools::throwFunctionSequenceException(*this); + return sal_False; +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL ODatabaseMetaDataResultSet::isLast( ) throw(SQLException, RuntimeException) +{ + ::dbtools::throwFunctionSequenceException(*this); + return sal_False; +} +// ------------------------------------------------------------------------- +void SAL_CALL ODatabaseMetaDataResultSet::beforeFirst( ) throw(SQLException, RuntimeException) +{ + ::dbtools::throwFunctionSequenceException(*this); +} +// ------------------------------------------------------------------------- +void SAL_CALL ODatabaseMetaDataResultSet::afterLast( ) throw(SQLException, RuntimeException) +{ + ::dbtools::throwFunctionSequenceException(*this); +} +// ------------------------------------------------------------------------- + +void SAL_CALL ODatabaseMetaDataResultSet::close( ) throw(SQLException, RuntimeException) +{ + { + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(ODatabaseMetaDataResultSet_BASE::rBHelper.bDisposed ); + + } + dispose(); +} +// ------------------------------------------------------------------------- + +sal_Bool SAL_CALL ODatabaseMetaDataResultSet::first( ) throw(SQLException, RuntimeException) +{ + ::dbtools::throwFunctionSequenceException(*this); + return sal_False; +} +// ------------------------------------------------------------------------- + +sal_Bool SAL_CALL ODatabaseMetaDataResultSet::last( ) throw(SQLException, RuntimeException) +{ + ::dbtools::throwFunctionSequenceException(*this); + return sal_False; +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL ODatabaseMetaDataResultSet::absolute( sal_Int32 /*row*/ ) throw(SQLException, RuntimeException) +{ + ::dbtools::throwFunctionSequenceException(*this); + return sal_False; +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL ODatabaseMetaDataResultSet::relative( sal_Int32 /*row*/ ) throw(SQLException, RuntimeException) +{ + ::dbtools::throwFunctionSequenceException(*this); + return sal_False; +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL ODatabaseMetaDataResultSet::previous( ) throw(SQLException, RuntimeException) +{ + ::dbtools::throwFunctionSequenceException(*this); + return sal_False; +} +// ------------------------------------------------------------------------- +Reference< XInterface > SAL_CALL ODatabaseMetaDataResultSet::getStatement( ) throw(SQLException, RuntimeException) +{ + return m_aStatement.get(); +} +// ------------------------------------------------------------------------- + +sal_Bool SAL_CALL ODatabaseMetaDataResultSet::rowDeleted( ) throw(SQLException, RuntimeException) +{ + ::dbtools::throwFunctionSequenceException(*this); + return sal_False; +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL ODatabaseMetaDataResultSet::rowInserted( ) throw(SQLException, RuntimeException) +{ + ::dbtools::throwFunctionSequenceException(*this); + return sal_False; +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL ODatabaseMetaDataResultSet::rowUpdated( ) throw(SQLException, RuntimeException) +{ + ::dbtools::throwFunctionSequenceException(*this); + return sal_False; +} +// ------------------------------------------------------------------------- + +sal_Bool SAL_CALL ODatabaseMetaDataResultSet::isBeforeFirst( ) throw(SQLException, RuntimeException) +{ + return m_bBOF; +} +// ------------------------------------------------------------------------- + +sal_Bool SAL_CALL ODatabaseMetaDataResultSet::next( ) throw(SQLException, RuntimeException) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(ODatabaseMetaDataResultSet_BASE::rBHelper.bDisposed ); + + if ( m_bBOF ) + { + m_aRowsIter = m_aRows.begin(); + m_bBOF = sal_False; + } + else + { + if ( m_bEOF ) + throwFunctionSequenceException( *this ); + else + if ( m_aRowsIter != m_aRows.end() ) + ++m_aRowsIter; + } + + bool bSuccess = m_aRowsIter != m_aRows.end(); + if ( !bSuccess ) + { + m_bEOF = sal_True; + m_bBOF = m_aRows.empty(); + } + return bSuccess; +} +// ------------------------------------------------------------------------- + +sal_Bool SAL_CALL ODatabaseMetaDataResultSet::wasNull( ) throw(SQLException, RuntimeException) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(ODatabaseMetaDataResultSet_BASE::rBHelper.bDisposed ); + + + if(m_aRowsIter == m_aRows.end() || !(*m_aRowsIter)[m_nColPos].isValid()) + return sal_True; + + return (*m_aRowsIter)[m_nColPos]->getValue().isNull(); +} +// ------------------------------------------------------------------------- +void SAL_CALL ODatabaseMetaDataResultSet::refreshRow( ) throw(SQLException, RuntimeException) +{ +} +// ------------------------------------------------------------------------- + +void SAL_CALL ODatabaseMetaDataResultSet::cancel( ) throw(RuntimeException) +{ +} +// ------------------------------------------------------------------------- +void SAL_CALL ODatabaseMetaDataResultSet::clearWarnings( ) throw(SQLException, RuntimeException) +{ +} +// ------------------------------------------------------------------------- +Any SAL_CALL ODatabaseMetaDataResultSet::getWarnings( ) throw(SQLException, RuntimeException) +{ + return Any(); +} +// ------------------------------------------------------------------------- +::cppu::IPropertyArrayHelper* ODatabaseMetaDataResultSet::createArrayHelper( ) const +{ + Sequence< Property > aProps; + describeProperties(aProps); + return new ::cppu::OPropertyArrayHelper(aProps); +} +// ------------------------------------------------------------------------- +::cppu::IPropertyArrayHelper & ODatabaseMetaDataResultSet::getInfoHelper() +{ + return *const_cast<ODatabaseMetaDataResultSet*>(this)->getArrayHelper(); +} +// ------------------------------------------------------------------------- +void ODatabaseMetaDataResultSet::setProceduresMap() +{ + ODatabaseMetaDataResultSetMetaData* pMetaData = new ODatabaseMetaDataResultSetMetaData(); + pMetaData->setProceduresMap(); + m_xMetaData = pMetaData; +} +// ------------------------------------------------------------------------- +void ODatabaseMetaDataResultSet::setCatalogsMap() +{ + ODatabaseMetaDataResultSetMetaData* pMetaData = new ODatabaseMetaDataResultSetMetaData(); + pMetaData->setCatalogsMap(); + m_xMetaData = pMetaData; +} +// ------------------------------------------------------------------------- +void ODatabaseMetaDataResultSet::setSchemasMap() +{ + ODatabaseMetaDataResultSetMetaData* pMetaData = new ODatabaseMetaDataResultSetMetaData(); + pMetaData->setSchemasMap(); + m_xMetaData = pMetaData; +} +// ------------------------------------------------------------------------- +void ODatabaseMetaDataResultSet::setColumnPrivilegesMap() +{ + ODatabaseMetaDataResultSetMetaData* pMetaData = new ODatabaseMetaDataResultSetMetaData(); + pMetaData->setColumnPrivilegesMap(); + m_xMetaData = pMetaData; +} +// ------------------------------------------------------------------------- +void ODatabaseMetaDataResultSet::setColumnsMap() +{ + + ODatabaseMetaDataResultSetMetaData* pMetaData = new ODatabaseMetaDataResultSetMetaData(); + pMetaData->setColumnsMap(); + m_xMetaData = pMetaData; +} +// ------------------------------------------------------------------------- +void ODatabaseMetaDataResultSet::setTablesMap() +{ + + ODatabaseMetaDataResultSetMetaData* pMetaData = new ODatabaseMetaDataResultSetMetaData(); + pMetaData->setTablesMap(); + m_xMetaData = pMetaData; +} +// ------------------------------------------------------------------------- +void ODatabaseMetaDataResultSet::setProcedureColumnsMap() +{ + ODatabaseMetaDataResultSetMetaData* pMetaData = new ODatabaseMetaDataResultSetMetaData(); + pMetaData->setProcedureColumnsMap(); + m_xMetaData = pMetaData; +} +// ------------------------------------------------------------------------- +void ODatabaseMetaDataResultSet::setPrimaryKeysMap() +{ + ODatabaseMetaDataResultSetMetaData* pMetaData = new ODatabaseMetaDataResultSetMetaData(); + pMetaData->setPrimaryKeysMap(); + m_xMetaData = pMetaData; +} +// ------------------------------------------------------------------------- +void ODatabaseMetaDataResultSet::setIndexInfoMap() +{ + ODatabaseMetaDataResultSetMetaData* pMetaData = new ODatabaseMetaDataResultSetMetaData(); + pMetaData->setIndexInfoMap(); + m_xMetaData = pMetaData; +} +// ------------------------------------------------------------------------- +void ODatabaseMetaDataResultSet::setTablePrivilegesMap() +{ + ODatabaseMetaDataResultSetMetaData* pMetaData = new ODatabaseMetaDataResultSetMetaData(); + pMetaData->setTablePrivilegesMap(); + m_xMetaData = pMetaData; +} +// ------------------------------------------------------------------------- +void ODatabaseMetaDataResultSet::setCrossReferenceMap() +{ + ODatabaseMetaDataResultSetMetaData* pMetaData = new ODatabaseMetaDataResultSetMetaData(); + pMetaData->setCrossReferenceMap(); + m_xMetaData = pMetaData; +} +// ------------------------------------------------------------------------- +void ODatabaseMetaDataResultSet::setVersionColumnsMap() +{ + ODatabaseMetaDataResultSetMetaData* pMetaData = new ODatabaseMetaDataResultSetMetaData(); + pMetaData->setVersionColumnsMap(); + m_xMetaData = pMetaData; +} +// ------------------------------------------------------------------------- +void ODatabaseMetaDataResultSet::setBestRowIdentifierMap() +{ + ODatabaseMetaDataResultSetMetaData* pMetaData = new ODatabaseMetaDataResultSetMetaData(); + pMetaData->setBestRowIdentifierMap(); + m_xMetaData = pMetaData; +} +// ------------------------------------------------------------------------- +void ODatabaseMetaDataResultSet::setTypeInfoMap() +{ + ODatabaseMetaDataResultSetMetaData* pMetaData = new ODatabaseMetaDataResultSetMetaData(); + pMetaData->setTypeInfoMap(); + m_xMetaData = pMetaData; +} +// ------------------------------------------------------------------------- +void ODatabaseMetaDataResultSet::setTableTypes() +{ + ODatabaseMetaDataResultSetMetaData* pMetaData = new ODatabaseMetaDataResultSetMetaData(); + pMetaData->setTableTypes(); + m_xMetaData = pMetaData; +} +// ------------------------------------------------------------------------- +void ODatabaseMetaDataResultSet::setExportedKeysMap() +{ + ODatabaseMetaDataResultSetMetaData* pMetaData = new ODatabaseMetaDataResultSetMetaData(); + pMetaData->setExportedKeysMap(); + m_xMetaData = pMetaData; +} +// ------------------------------------------------------------------------- +void ODatabaseMetaDataResultSet::setImportedKeysMap() +{ + ODatabaseMetaDataResultSetMetaData* pMetaData = new ODatabaseMetaDataResultSetMetaData(); + pMetaData->setImportedKeysMap(); + m_xMetaData = pMetaData; +} +// ----------------------------------------------------------------------------- +Reference< ::com::sun::star::beans::XPropertySetInfo > SAL_CALL ODatabaseMetaDataResultSet::getPropertySetInfo( ) throw(RuntimeException) +{ + return ::cppu::OPropertySetHelper::createPropertySetInfo(getInfoHelper()); +} +// ----------------------------------------------------------------------------- +ORowSetValueDecorator& ORowSetValueDecorator::operator=(const ORowSetValue& _aValue) +{ + m_aValue = _aValue; + return *this; +} +// ----------------------------------------------------------------------------- +const ORowSetValue& ODatabaseMetaDataResultSet::getValue(sal_Int32 columnIndex) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(ODatabaseMetaDataResultSet_BASE::rBHelper.bDisposed ); + + if ( isBeforeFirst() || isAfterLast() ) + ::dbtools::throwFunctionSequenceException( *this ); + + checkIndex(columnIndex ); + m_nColPos = columnIndex; + + if(m_aRowsIter != m_aRows.end() && (*m_aRowsIter)[columnIndex].isValid()) + return *(*m_aRowsIter)[columnIndex]; + return m_aEmptyValue; +} +// ----------------------------------------------------------------------------- +/// return an empty ORowSetValueDecorator +ORowSetValueDecoratorRef ODatabaseMetaDataResultSet::getEmptyValue() +{ + static ORowSetValueDecoratorRef aEmptyValueRef = new ORowSetValueDecorator(); + return aEmptyValueRef; +} +// ----------------------------------------------------------------------------- +/// return an ORowSetValueDecorator with 0 as value +ORowSetValueDecoratorRef ODatabaseMetaDataResultSet::get0Value() +{ + static ORowSetValueDecoratorRef a0ValueRef = new ORowSetValueDecorator((sal_Int32)0); + return a0ValueRef; +} +// ----------------------------------------------------------------------------- +/// return an ORowSetValueDecorator with 1 as value +ORowSetValueDecoratorRef ODatabaseMetaDataResultSet::get1Value() +{ + static ORowSetValueDecoratorRef a1ValueRef = new ORowSetValueDecorator((sal_Int32)1); + return a1ValueRef; +} +// ----------------------------------------------------------------------------- +/// return an ORowSetValueDecorator with ColumnSearch::BASIC as value +ORowSetValueDecoratorRef ODatabaseMetaDataResultSet::getBasicValue() +{ + static ORowSetValueDecoratorRef aValueRef = new ORowSetValueDecorator(ColumnSearch::BASIC); + return aValueRef; +} +// ----------------------------------------------------------------------------- +ORowSetValueDecoratorRef ODatabaseMetaDataResultSet::getSelectValue() +{ + static ORowSetValueDecoratorRef aValueRef = new ORowSetValueDecorator(::rtl::OUString::createFromAscii("SELECT")); + return aValueRef; +} +// ----------------------------------------------------------------------------- +ORowSetValueDecoratorRef ODatabaseMetaDataResultSet::getInsertValue() +{ + static ORowSetValueDecoratorRef aValueRef = new ORowSetValueDecorator(::rtl::OUString::createFromAscii("INSERT")); + return aValueRef; +} +// ----------------------------------------------------------------------------- +ORowSetValueDecoratorRef ODatabaseMetaDataResultSet::getDeleteValue() +{ + static ORowSetValueDecoratorRef aValueRef = new ORowSetValueDecorator(::rtl::OUString::createFromAscii("DELETE")); + return aValueRef; +} +// ----------------------------------------------------------------------------- +ORowSetValueDecoratorRef ODatabaseMetaDataResultSet::getUpdateValue() +{ + static ORowSetValueDecoratorRef aValueRef = new ORowSetValueDecorator(::rtl::OUString::createFromAscii("UPDATE")); + return aValueRef; +} +// ----------------------------------------------------------------------------- +ORowSetValueDecoratorRef ODatabaseMetaDataResultSet::getCreateValue() +{ + static ORowSetValueDecoratorRef aValueRef = new ORowSetValueDecorator(::rtl::OUString::createFromAscii("CREATE")); + return aValueRef; +} +// ----------------------------------------------------------------------------- +ORowSetValueDecoratorRef ODatabaseMetaDataResultSet::getReadValue() +{ + static ORowSetValueDecoratorRef aValueRef = new ORowSetValueDecorator(::rtl::OUString::createFromAscii("READ")); + return aValueRef; +} +// ----------------------------------------------------------------------------- +ORowSetValueDecoratorRef ODatabaseMetaDataResultSet::getAlterValue() +{ + static ORowSetValueDecoratorRef aValueRef = new ORowSetValueDecorator(::rtl::OUString::createFromAscii("ALTER")); + return aValueRef; +} +// ----------------------------------------------------------------------------- +ORowSetValueDecoratorRef ODatabaseMetaDataResultSet::getDropValue() +{ + static ORowSetValueDecoratorRef aValueRef = new ORowSetValueDecorator(::rtl::OUString::createFromAscii("DROP")); + return aValueRef; +} +// ----------------------------------------------------------------------------- +ORowSetValueDecoratorRef ODatabaseMetaDataResultSet::getQuoteValue() +{ + static ORowSetValueDecoratorRef aValueRef = new ORowSetValueDecorator(::rtl::OUString::createFromAscii("'")); + return aValueRef; +} +// ----------------------------------------------------------------------------- +void SAL_CALL ODatabaseMetaDataResultSet::initialize( const Sequence< Any >& _aArguments ) throw (Exception, RuntimeException) +{ + if ( _aArguments.getLength() == 2 ) + { + sal_Int32 nResultSetType = 0; + if ( _aArguments[0] >>= nResultSetType) + { + setType(static_cast<MetaDataResultSetType>(nResultSetType)); + Sequence< Sequence<Any> > aRows; + if ( _aArguments[1] >>= aRows ) + { + ORows aRowsToSet; + const Sequence<Any>* pRowsIter = aRows.getConstArray(); + const Sequence<Any>* pRowsEnd = pRowsIter + aRows.getLength(); + for (; pRowsIter != pRowsEnd;++pRowsIter) + { + ORow aRowToSet; + const Any* pRowIter = pRowsIter->getConstArray(); + const Any* pRowEnd = pRowIter + pRowsIter->getLength(); + for (; pRowIter != pRowEnd;++pRowIter) + { + ORowSetValueDecoratorRef aValue; + switch( pRowIter->getValueTypeClass() ) + { + case TypeClass_BOOLEAN: + { + sal_Bool bValue = sal_False; + *pRowIter >>= bValue; + aValue = new ORowSetValueDecorator(ORowSetValue(bValue)); + } + break; + case TypeClass_BYTE: + { + sal_Int8 nValue(0); + *pRowIter >>= nValue; + aValue = new ORowSetValueDecorator(ORowSetValue(nValue)); + } + break; + case TypeClass_SHORT: + case TypeClass_UNSIGNED_SHORT: + { + sal_Int16 nValue(0); + *pRowIter >>= nValue; + aValue = new ORowSetValueDecorator(ORowSetValue(nValue)); + } + break; + case TypeClass_LONG: + case TypeClass_UNSIGNED_LONG: + { + sal_Int32 nValue(0); + *pRowIter >>= nValue; + aValue = new ORowSetValueDecorator(ORowSetValue(nValue)); + } + break; + case TypeClass_HYPER: + case TypeClass_UNSIGNED_HYPER: + { + sal_Int64 nValue(0); + *pRowIter >>= nValue; + aValue = new ORowSetValueDecorator(ORowSetValue(nValue)); + } + break; + case TypeClass_FLOAT: + { + float nValue(0.0); + *pRowIter >>= nValue; + aValue = new ORowSetValueDecorator(ORowSetValue(nValue)); + } + break; + case TypeClass_DOUBLE: + { + double nValue(0.0); + *pRowIter >>= nValue; + aValue = new ORowSetValueDecorator(ORowSetValue(nValue)); + } + break; + case TypeClass_STRING: + { + ::rtl::OUString sValue; + *pRowIter >>= sValue; + aValue = new ORowSetValueDecorator(ORowSetValue(sValue)); + } + break; + default: + break; + } + aRowToSet.push_back(aValue); + } + aRowsToSet.push_back(aRowToSet); + } // for (; pRowsIter != pRowsEnd;++pRowsIter + setRows(aRowsToSet); + } + } + } +} +// XServiceInfo + // -------------------------------------------------------------------------------- + //------------------------------------------------------------------------------ + rtl::OUString ODatabaseMetaDataResultSet::getImplementationName_Static( ) throw(RuntimeException) + { + return ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("org.openoffice.comp.helper.DatabaseMetaDataResultSet")); + } + //------------------------------------------------------------------------------ + Sequence< ::rtl::OUString > ODatabaseMetaDataResultSet::getSupportedServiceNames_Static( ) throw (RuntimeException) + { + Sequence< ::rtl::OUString > aSNS( 1 ); + aSNS[0] = ::rtl::OUString::createFromAscii("com.sun.star.sdbc.ResultSet"); + return aSNS; + } + //------------------------------------------------------------------ + ::rtl::OUString SAL_CALL ODatabaseMetaDataResultSet::getImplementationName( ) throw(RuntimeException) + { + return getImplementationName_Static(); + } + + //------------------------------------------------------------------ + sal_Bool SAL_CALL ODatabaseMetaDataResultSet::supportsService( const ::rtl::OUString& _rServiceName ) throw(RuntimeException) + { + Sequence< ::rtl::OUString > aSupported(getSupportedServiceNames()); + const ::rtl::OUString* pSupported = aSupported.getConstArray(); + const ::rtl::OUString* pEnd = pSupported + aSupported.getLength(); + for (;pSupported != pEnd && !pSupported->equals(_rServiceName); ++pSupported) + ; + + return pSupported != pEnd; + } + //------------------------------------------------------------------ + Sequence< ::rtl::OUString > SAL_CALL ODatabaseMetaDataResultSet::getSupportedServiceNames( ) throw(RuntimeException) + { + return getSupportedServiceNames_Static(); + } + // ------------------------------------------------------------------------- + namespace connectivity + { + Reference< XInterface > SAL_CALL ODatabaseMetaDataResultSet_CreateInstance(const Reference< XComponentContext >& ) throw( Exception ) + { + return *(new ODatabaseMetaDataResultSet()); + } + } + +// ----------------------------------------------------------------------------- +namespace +{ + cppu::ImplementationEntry entries[] = { + { &ODatabaseMetaDataResultSet_CreateInstance, &ODatabaseMetaDataResultSet::getImplementationName_Static, &ODatabaseMetaDataResultSet::getSupportedServiceNames_Static, + &cppu::createSingleComponentFactory, 0, 0 }, + { &ParameterSubstitution::create, &ParameterSubstitution::getImplementationName_Static, &ParameterSubstitution::getSupportedServiceNames_Static, + &cppu::createSingleComponentFactory, 0, 0 }, + { 0, 0, 0, 0, 0, 0 } + }; +} +using ::rtl::OUString; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Sequence; +using ::com::sun::star::registry::XRegistryKey; +using ::com::sun::star::registry::InvalidRegistryException; +using ::com::sun::star::registry::InvalidValueException; +using ::com::sun::star::lang::XMultiServiceFactory; + +//========================================================================== +//= registration +//========================================================================== +extern "C" +{ + +//--------------------------------------------------------------------------------------- +SAL_DLLPUBLIC_EXPORT void SAL_CALL component_getImplementationEnvironment(const sal_Char** _ppEnvTypeName, uno_Environment** /*_ppEnv*/) +{ + *_ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME; +} + +//--------------------------------------------------------------------------------------- +SAL_DLLPUBLIC_EXPORT sal_Bool SAL_CALL component_writeInfo(void* serviceManager, com::sun::star::registry::XRegistryKey* registryKey) +{ + return cppu::component_writeInfoHelper(serviceManager, registryKey, entries); +} +//--------------------------------------------------------------------------------------- +SAL_DLLPUBLIC_EXPORT void* SAL_CALL component_getFactory(const sal_Char* implName, ::com::sun::star::lang::XMultiServiceFactory* serviceManager, void* registryKey) +{ + return cppu::component_getFactoryHelper(implName, serviceManager, registryKey, entries); +} + +} // extern "C" diff --git a/connectivity/source/commontools/FDatabaseMetaDataResultSetMetaData.cxx b/connectivity/source/commontools/FDatabaseMetaDataResultSetMetaData.cxx new file mode 100644 index 000000000000..97e7201a53ff --- /dev/null +++ b/connectivity/source/commontools/FDatabaseMetaDataResultSetMetaData.cxx @@ -0,0 +1,692 @@ +/************************************************************************* + * + * 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 "FDatabaseMetaDataResultSetMetaData.hxx" +#include <com/sun/star/sdbc/DataType.hpp> +#include <com/sun/star/sdbc/ProcedureResult.hpp> +#include <com/sun/star/sdbc/ColumnValue.hpp> + +using namespace connectivity; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::lang; + +// ------------------------------------------------------------------------- +ODatabaseMetaDataResultSetMetaData::~ODatabaseMetaDataResultSetMetaData() +{ +} +// ------------------------------------------------------------------------- +sal_Int32 SAL_CALL ODatabaseMetaDataResultSetMetaData::getColumnDisplaySize( sal_Int32 column ) throw(SQLException, RuntimeException) +{ + if(m_mColumns.size() && (m_mColumnsIter = m_mColumns.find(column)) != m_mColumns.end()) + return (*m_mColumnsIter).second.getColumnDisplaySize(); + + return 0; +} +// ------------------------------------------------------------------------- + +sal_Int32 SAL_CALL ODatabaseMetaDataResultSetMetaData::getColumnType( sal_Int32 column ) throw(SQLException, RuntimeException) +{ + if(m_mColumns.size() && (m_mColumnsIter = m_mColumns.find(column)) != m_mColumns.end()) + return (*m_mColumnsIter).second.getColumnType(); + return 1; +} +// ------------------------------------------------------------------------- + +sal_Int32 SAL_CALL ODatabaseMetaDataResultSetMetaData::getColumnCount( ) throw(SQLException, RuntimeException) +{ + return m_mColumns.size(); +} +// ------------------------------------------------------------------------- + +sal_Bool SAL_CALL ODatabaseMetaDataResultSetMetaData::isCaseSensitive( sal_Int32 column ) throw(SQLException, RuntimeException) +{ + if(m_mColumns.size() && (m_mColumnsIter = m_mColumns.find(column)) != m_mColumns.end()) + return (*m_mColumnsIter).second.isCaseSensitive(); + return sal_True; +} +// ------------------------------------------------------------------------- + +::rtl::OUString SAL_CALL ODatabaseMetaDataResultSetMetaData::getSchemaName( sal_Int32 /*column*/ ) throw(SQLException, RuntimeException) +{ + return ::rtl::OUString(); +} +// ------------------------------------------------------------------------- + +::rtl::OUString SAL_CALL ODatabaseMetaDataResultSetMetaData::getColumnName( sal_Int32 column ) throw(SQLException, RuntimeException) +{ + if(m_mColumns.size() && (m_mColumnsIter = m_mColumns.find(column)) != m_mColumns.end()) + return (*m_mColumnsIter).second.getColumnName(); + return ::rtl::OUString(); +} +// ------------------------------------------------------------------------- +::rtl::OUString SAL_CALL ODatabaseMetaDataResultSetMetaData::getTableName( sal_Int32 column ) throw(SQLException, RuntimeException) +{ + if(m_mColumns.size() && (m_mColumnsIter = m_mColumns.find(column)) != m_mColumns.end()) + return (*m_mColumnsIter).second.getTableName(); + return ::rtl::OUString(); +} +// ------------------------------------------------------------------------- +::rtl::OUString SAL_CALL ODatabaseMetaDataResultSetMetaData::getCatalogName( sal_Int32 /*column*/ ) throw(SQLException, RuntimeException) +{ + return ::rtl::OUString(); +} +// ------------------------------------------------------------------------- +::rtl::OUString SAL_CALL ODatabaseMetaDataResultSetMetaData::getColumnTypeName( sal_Int32 column ) throw(SQLException, RuntimeException) +{ + if(m_mColumns.size() && (m_mColumnsIter = m_mColumns.find(column)) != m_mColumns.end()) + return (*m_mColumnsIter).second.getColumnTypeName(); + return ::rtl::OUString(); +} +// ------------------------------------------------------------------------- +::rtl::OUString SAL_CALL ODatabaseMetaDataResultSetMetaData::getColumnLabel( sal_Int32 column ) throw(SQLException, RuntimeException) +{ + if(m_mColumns.size() && (m_mColumnsIter = m_mColumns.find(column)) != m_mColumns.end()) + return (*m_mColumnsIter).second.getColumnLabel(); + return getColumnName(column); +} +// ------------------------------------------------------------------------- +::rtl::OUString SAL_CALL ODatabaseMetaDataResultSetMetaData::getColumnServiceName( sal_Int32 column ) throw(SQLException, RuntimeException) +{ + if(m_mColumns.size() && (m_mColumnsIter = m_mColumns.find(column)) != m_mColumns.end()) + return (*m_mColumnsIter).second.getColumnServiceName(); + return ::rtl::OUString(); +} +// ------------------------------------------------------------------------- + +sal_Bool SAL_CALL ODatabaseMetaDataResultSetMetaData::isCurrency( sal_Int32 column ) throw(SQLException, RuntimeException) +{ + if(m_mColumns.size() && (m_mColumnsIter = m_mColumns.find(column)) != m_mColumns.end()) + return (*m_mColumnsIter).second.isCurrency(); + return sal_False; +} +// ------------------------------------------------------------------------- + +sal_Bool SAL_CALL ODatabaseMetaDataResultSetMetaData::isAutoIncrement( sal_Int32 column ) throw(SQLException, RuntimeException) +{ + if(m_mColumns.size() && (m_mColumnsIter = m_mColumns.find(column)) != m_mColumns.end()) + return (*m_mColumnsIter).second.isAutoIncrement(); + return sal_False; +} +// ------------------------------------------------------------------------- + + +sal_Bool SAL_CALL ODatabaseMetaDataResultSetMetaData::isSigned( sal_Int32 column ) throw(SQLException, RuntimeException) +{ + if(m_mColumns.size() && (m_mColumnsIter = m_mColumns.find(column)) != m_mColumns.end()) + return (*m_mColumnsIter).second.isSigned(); + return sal_False; +} +// ------------------------------------------------------------------------- +sal_Int32 SAL_CALL ODatabaseMetaDataResultSetMetaData::getPrecision( sal_Int32 column ) throw(SQLException, RuntimeException) +{ + if(m_mColumns.size() && (m_mColumnsIter = m_mColumns.find(column)) != m_mColumns.end()) + return (*m_mColumnsIter).second.getPrecision(); + return 0; +} +// ------------------------------------------------------------------------- +sal_Int32 SAL_CALL ODatabaseMetaDataResultSetMetaData::getScale( sal_Int32 column ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException) +{ + if(m_mColumns.size() && (m_mColumnsIter = m_mColumns.find(column)) != m_mColumns.end()) + return (*m_mColumnsIter).second.getScale(); + + return 0; +} +// ------------------------------------------------------------------------- + +sal_Int32 SAL_CALL ODatabaseMetaDataResultSetMetaData::isNullable( sal_Int32 column ) throw(SQLException, RuntimeException) +{ + if(m_mColumns.size() && (m_mColumnsIter = m_mColumns.find(column)) != m_mColumns.end()) + return (*m_mColumnsIter).second.isNullable(); + + return sal_False; +} +// ------------------------------------------------------------------------- + +sal_Bool SAL_CALL ODatabaseMetaDataResultSetMetaData::isSearchable( sal_Int32 column ) throw(SQLException, RuntimeException) +{ + if(m_mColumns.size() && (m_mColumnsIter = m_mColumns.find(column)) != m_mColumns.end()) + return (*m_mColumnsIter).second.isSearchable(); + return sal_True; +} +// ------------------------------------------------------------------------- + +sal_Bool SAL_CALL ODatabaseMetaDataResultSetMetaData::isReadOnly( sal_Int32 /*column*/ ) throw(SQLException, RuntimeException) +{ +// if(m_mColumns.size() && (m_mColumnsIter = m_mColumns.find(column)) != m_mColumns.end()) +// return (*m_mColumnsIter).second.isReadOnly(); + + return sal_True; +} +// ------------------------------------------------------------------------- + +sal_Bool SAL_CALL ODatabaseMetaDataResultSetMetaData::isDefinitelyWritable( sal_Int32 /*column*/ ) throw(SQLException, RuntimeException) +{ +// if(m_mColumns.size() && (m_mColumnsIter = m_mColumns.find(column)) != m_mColumns.end()) +// return (*m_mColumnsIter).second.isDefinitelyWritable(); + + return sal_False; +; +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL ODatabaseMetaDataResultSetMetaData::isWritable( sal_Int32 column ) throw(SQLException, RuntimeException) +{ +// if(m_mColumns.size() && (m_mColumnsIter = m_mColumns.find(column)) != m_mColumns.end()) +// return (*m_mColumnsIter).second.isWritable(); + return isDefinitelyWritable(column); +} +// ------------------------------------------------------------------------- +void ODatabaseMetaDataResultSetMetaData::setColumnPrivilegesMap() +{ + setColumnMap(); + m_mColumns[5] = OColumn(::rtl::OUString(),::rtl::OUString::createFromAscii("GRANTOR"), + ColumnValue::NULLABLE, + 3,3,0, + DataType::VARCHAR); + m_mColumns[6] = OColumn(::rtl::OUString(),::rtl::OUString::createFromAscii("GRANTEE"), + ColumnValue::NULLABLE, + 3,3,0, + DataType::VARCHAR); + m_mColumns[7] = OColumn(::rtl::OUString(),::rtl::OUString::createFromAscii("PRIVILEGE"), + ColumnValue::NULLABLE, + 3,3,0, + DataType::VARCHAR); + m_mColumns[8] = OColumn(::rtl::OUString(),::rtl::OUString::createFromAscii("IS_GRANTABLE"), + ColumnValue::NULLABLE, + 3,3,0, + DataType::VARCHAR); +} +// ----------------------------------------------------------------------------- +void ODatabaseMetaDataResultSetMetaData::setTableNameMap() +{ + m_mColumns[1] = OColumn(::rtl::OUString(),::rtl::OUString::createFromAscii("TABLE_CAT"), + ColumnValue::NULLABLE, + 3,3,0, + DataType::VARCHAR); + m_mColumns[2] = OColumn(::rtl::OUString(),::rtl::OUString::createFromAscii("TABLE_SCHEM"), + ColumnValue::NULLABLE, + 3,3,0, + DataType::VARCHAR); + m_mColumns[3] = OColumn(::rtl::OUString(),::rtl::OUString::createFromAscii("TABLE_NAME"), + ColumnValue::NO_NULLS, + 3,3,0, + DataType::VARCHAR); +} +// ----------------------------------------------------------------------------- +void ODatabaseMetaDataResultSetMetaData::setColumnMap() +{ + setTableNameMap(); + m_mColumns[4] = OColumn(::rtl::OUString(),::rtl::OUString::createFromAscii("COLUMN_NAME"), + ColumnValue::NO_NULLS, + 3,3,0, + DataType::VARCHAR); +} +// ------------------------------------------------------------------------- +void ODatabaseMetaDataResultSetMetaData::setColumnsMap() +{ + setColumnMap(); + + m_mColumns[5] = OColumn(::rtl::OUString(),::rtl::OUString::createFromAscii("DATA_TYPE"), + ColumnValue::NO_NULLS, + 0,0,0, + DataType::INTEGER); + m_mColumns[6] = OColumn(::rtl::OUString(),::rtl::OUString::createFromAscii("TYPE_NAME"), + ColumnValue::NO_NULLS, + 0,0,0, + DataType::VARCHAR); + m_mColumns[7] = OColumn(::rtl::OUString(),::rtl::OUString::createFromAscii("COLUMN_SIZE"), + ColumnValue::NO_NULLS, + 3,3,0, + DataType::INTEGER); + m_mColumns[8] = OColumn(::rtl::OUString(),::rtl::OUString::createFromAscii("BUFFER_LENGTH"), + ColumnValue::NULLABLE, + 3,3,0, + DataType::INTEGER); + m_mColumns[9] = OColumn(::rtl::OUString(),::rtl::OUString::createFromAscii("DECIMAL_DIGITS"), + ColumnValue::NO_NULLS, + 0,0,0, + DataType::INTEGER); + m_mColumns[10] = OColumn(::rtl::OUString(),::rtl::OUString::createFromAscii("NUM_PREC_RADIX"), + ColumnValue::NO_NULLS, + 0,0,0, + DataType::INTEGER); + m_mColumns[11] = OColumn(::rtl::OUString(),::rtl::OUString::createFromAscii("NULLABLE"), + ColumnValue::NO_NULLS, + 1,1,0, + DataType::INTEGER); + m_mColumns[12] = OColumn(::rtl::OUString(),::rtl::OUString::createFromAscii("REMARKS"), + ColumnValue::NULLABLE, + 0,0,0, + DataType::VARCHAR); + m_mColumns[13] = OColumn(::rtl::OUString(),::rtl::OUString::createFromAscii("COLUMN_DEF"), + ColumnValue::NULLABLE, + 0,0,0, + DataType::VARCHAR); + m_mColumns[14] = OColumn(::rtl::OUString(),::rtl::OUString::createFromAscii("SQL_DATA_TYPE"), + ColumnValue::NO_NULLS, + 1,1,0, + DataType::INTEGER); + m_mColumns[15] = OColumn(::rtl::OUString(),::rtl::OUString::createFromAscii("SQL_DATETIME_SUB"), + ColumnValue::NO_NULLS, + 1,1,0, + DataType::INTEGER); + m_mColumns[16] = OColumn(::rtl::OUString(),::rtl::OUString::createFromAscii("CHAR_OCTET_LENGTH"), + ColumnValue::NO_NULLS, + 1,1,0, + DataType::INTEGER); + m_mColumns[17] = OColumn(::rtl::OUString(),::rtl::OUString::createFromAscii("ORDINAL_POSITION"), + ColumnValue::NO_NULLS, + 1,1,0, + DataType::INTEGER); + m_mColumns[18] = OColumn(::rtl::OUString(),::rtl::OUString::createFromAscii("IS_NULLABLE"), + ColumnValue::NO_NULLS, + 1,1,0, + DataType::VARCHAR); +} +// ------------------------------------------------------------------------- +void ODatabaseMetaDataResultSetMetaData::setTablesMap() +{ + setTableNameMap(); + m_mColumns[4] = OColumn(::rtl::OUString(),::rtl::OUString::createFromAscii("TABLE_TYPE"), + ColumnValue::NO_NULLS, + 0,0,0, + DataType::VARCHAR); + m_mColumns[5] = OColumn(::rtl::OUString(),::rtl::OUString::createFromAscii("REMARKS"), + ColumnValue::NULLABLE, + 0,0,0, + DataType::VARCHAR); +} +// ------------------------------------------------------------------------- +void ODatabaseMetaDataResultSetMetaData::setProcedureNameMap() +{ + m_mColumns[1] = OColumn(::rtl::OUString(),::rtl::OUString::createFromAscii("PROCEDURE_CAT"), + ColumnValue::NULLABLE, + 0,0,0, + DataType::VARCHAR); + m_mColumns[2] = OColumn(::rtl::OUString(),::rtl::OUString::createFromAscii("PROCEDURE_SCHEM"), + ColumnValue::NULLABLE, + 0,0,0, + DataType::VARCHAR); + m_mColumns[3] = OColumn(::rtl::OUString(),::rtl::OUString::createFromAscii("PROCEDURE_NAME"), + ColumnValue::NO_NULLS, + 0,0,0, + DataType::VARCHAR); +} +// ------------------------------------------------------------------------- +void ODatabaseMetaDataResultSetMetaData::setProcedureColumnsMap() +{ + setProcedureNameMap(); + m_mColumns[4] = OColumn(::rtl::OUString(),::rtl::OUString::createFromAscii("COLUMN_NAME"), + ColumnValue::NO_NULLS, + 0,0,0, + DataType::VARCHAR); + m_mColumns[5] = OColumn(::rtl::OUString(),::rtl::OUString::createFromAscii("COLUMN_TYPE"), + ColumnValue::NO_NULLS, + 0,0,0, + DataType::INTEGER); + m_mColumns[6] = OColumn(::rtl::OUString(),::rtl::OUString::createFromAscii("DATA_TYPE"), + ColumnValue::NO_NULLS, + 0,0,0, + DataType::INTEGER); + m_mColumns[7] = OColumn(::rtl::OUString(),::rtl::OUString::createFromAscii("TYPE_NAME"), + ColumnValue::NULLABLE, + 0,0,0, + DataType::VARCHAR); + m_mColumns[8] = OColumn(::rtl::OUString(),::rtl::OUString::createFromAscii("PRECISION"), + ColumnValue::NO_NULLS, + 0,0,0, + DataType::INTEGER); + m_mColumns[9] = OColumn(::rtl::OUString(),::rtl::OUString::createFromAscii("LENGTH"), + ColumnValue::NO_NULLS, + 0,0,0, + DataType::INTEGER); + m_mColumns[10] = OColumn(::rtl::OUString(),::rtl::OUString::createFromAscii("SCALE"), + ColumnValue::NO_NULLS, + 0,0,0, + DataType::INTEGER); + m_mColumns[11] = OColumn(::rtl::OUString(),::rtl::OUString::createFromAscii("RADIX"), + ColumnValue::NO_NULLS, + 0,0,0, + DataType::INTEGER); + m_mColumns[12] = OColumn(::rtl::OUString(),::rtl::OUString::createFromAscii("NULLABLE"), + ColumnValue::NO_NULLS, + 0,0,0, + DataType::INTEGER); + m_mColumns[13] = OColumn(::rtl::OUString(),::rtl::OUString::createFromAscii("REMARKS"), + ColumnValue::NULLABLE, + 0,0,0, + DataType::VARCHAR); + +} +// ------------------------------------------------------------------------- +void ODatabaseMetaDataResultSetMetaData::setPrimaryKeysMap() +{ + setColumnMap(); + m_mColumns[5] = OColumn(::rtl::OUString(),::rtl::OUString::createFromAscii("KEY_SEQ"), + ColumnValue::NO_NULLS, + 1,1,0, + DataType::INTEGER); + m_mColumns[6] = OColumn(::rtl::OUString(),::rtl::OUString::createFromAscii("PK_NAME"), + ColumnValue::NULLABLE, + 0,0,0, + DataType::VARCHAR); +} +// ------------------------------------------------------------------------- +void ODatabaseMetaDataResultSetMetaData::setIndexInfoMap() +{ + setTableNameMap(); + m_mColumns[4] = OColumn(::rtl::OUString(),::rtl::OUString::createFromAscii("NON_UNIQUE"), + ColumnValue::NO_NULLS, + 1,1,0, + DataType::BIT); + m_mColumns[5] = OColumn(::rtl::OUString(),::rtl::OUString::createFromAscii("INDEX_QUALIFIER"), + ColumnValue::NULLABLE, + 0,0,0, + DataType::VARCHAR); + m_mColumns[6] = OColumn(::rtl::OUString(),::rtl::OUString::createFromAscii("INDEX_NAME"), + ColumnValue::NULLABLE, + 0,0,0, + DataType::VARCHAR); + m_mColumns[7] = OColumn(::rtl::OUString(),::rtl::OUString::createFromAscii("TYPE"), + ColumnValue::NO_NULLS, + 0,0,0, + DataType::INTEGER); + m_mColumns[8] = OColumn(::rtl::OUString(),::rtl::OUString::createFromAscii("ORDINAL_POSITION"), + ColumnValue::NO_NULLS, + 0,0,0, + DataType::INTEGER); + m_mColumns[9] = OColumn(::rtl::OUString(),::rtl::OUString::createFromAscii("COLUMN_NAME"), + ColumnValue::NO_NULLS, + 0,0,0, + DataType::VARCHAR); + m_mColumns[10] = OColumn(::rtl::OUString(),::rtl::OUString::createFromAscii("ASC_OR_DESC"), + ColumnValue::NULLABLE, + 0,0,0, + DataType::VARCHAR); + m_mColumns[11] = OColumn(::rtl::OUString(),::rtl::OUString::createFromAscii("CARDINALITY"), + ColumnValue::NO_NULLS, + 0,0,0, + DataType::INTEGER); + m_mColumns[12] = OColumn(::rtl::OUString(),::rtl::OUString::createFromAscii("PAGES"), + ColumnValue::NO_NULLS, + 0,0,0, + DataType::INTEGER); + m_mColumns[13] = OColumn(::rtl::OUString(),::rtl::OUString::createFromAscii("FILTER_CONDITION"), + ColumnValue::NULLABLE, + 0,0,0, + DataType::VARCHAR); +} +// ------------------------------------------------------------------------- +void ODatabaseMetaDataResultSetMetaData::setTablePrivilegesMap() +{ + setTableNameMap(); + m_mColumns[4] = OColumn(::rtl::OUString(),::rtl::OUString::createFromAscii("GRANTOR"), + ColumnValue::NULLABLE, + 0,0,0, + DataType::VARCHAR); + m_mColumns[5] = OColumn(::rtl::OUString(),::rtl::OUString::createFromAscii("GRANTEE"), + ColumnValue::NO_NULLS, + 0,0,0, + DataType::VARCHAR); + m_mColumns[6] = OColumn(::rtl::OUString(),::rtl::OUString::createFromAscii("PRIVILEGE"), + ColumnValue::NULLABLE, + 0,0,0, + DataType::VARCHAR); + m_mColumns[7] = OColumn(::rtl::OUString(),::rtl::OUString::createFromAscii("IS_GRANTABLE"), + ColumnValue::NULLABLE, + 0,0,0, + DataType::VARCHAR); +} +// ------------------------------------------------------------------------- +void ODatabaseMetaDataResultSetMetaData::setCrossReferenceMap() +{ + m_mColumns[1] = OColumn(::rtl::OUString(),::rtl::OUString::createFromAscii("PKTABLE_CAT"), + ColumnValue::NULLABLE, + 0,0,0, + DataType::VARCHAR); + m_mColumns[2] = OColumn(::rtl::OUString(),::rtl::OUString::createFromAscii("PKTABLE_SCHEM"), + ColumnValue::NULLABLE, + 0,0,0, + DataType::VARCHAR); + m_mColumns[3] = OColumn(::rtl::OUString(),::rtl::OUString::createFromAscii("PKTABLE_NAME"), + ColumnValue::NO_NULLS, + 0,0,0, + DataType::VARCHAR); + m_mColumns[4] = OColumn(::rtl::OUString(),::rtl::OUString::createFromAscii("PKCOLUMN_NAME"), + ColumnValue::NO_NULLS, + 0,0,0, + DataType::VARCHAR); + m_mColumns[5] = OColumn(::rtl::OUString(),::rtl::OUString::createFromAscii("FKTABLE_CAT"), + ColumnValue::NULLABLE, + 0,0,0, + DataType::VARCHAR); + m_mColumns[6] = OColumn(::rtl::OUString(),::rtl::OUString::createFromAscii("FKTABLE_SCHEM"), + ColumnValue::NULLABLE, + 0,0,0, + DataType::VARCHAR); + m_mColumns[7] = OColumn(::rtl::OUString(),::rtl::OUString::createFromAscii("FKTABLE_NAME"), + ColumnValue::NO_NULLS, + 0,0,0, + DataType::VARCHAR); + m_mColumns[8] = OColumn(::rtl::OUString(),::rtl::OUString::createFromAscii("FKCOLUMN_NAME"), + ColumnValue::NO_NULLS, + 0,0,0, + DataType::VARCHAR); + + m_mColumns[9] = OColumn(::rtl::OUString(),::rtl::OUString::createFromAscii("KEY_SEQ"), + ColumnValue::NO_NULLS, + 1,1,0, + DataType::INTEGER); + m_mColumns[10] = OColumn(::rtl::OUString(),::rtl::OUString::createFromAscii("UPDATE_RULE"), + ColumnValue::NO_NULLS, + 1,1,0, + DataType::INTEGER); + m_mColumns[11] = OColumn(::rtl::OUString(),::rtl::OUString::createFromAscii("DELETE_RULE"), + ColumnValue::NO_NULLS, + 1,1,0, + DataType::INTEGER); + m_mColumns[12] = OColumn(::rtl::OUString(),::rtl::OUString::createFromAscii("FK_NAME"), + ColumnValue::NULLABLE, + 0,0,0, + DataType::VARCHAR); + m_mColumns[13] = OColumn(::rtl::OUString(),::rtl::OUString::createFromAscii("PK_NAME"), + ColumnValue::NULLABLE, + 0,0,0, + DataType::VARCHAR); + m_mColumns[14] = OColumn(::rtl::OUString(),::rtl::OUString::createFromAscii("DEFERRABILITY"), + ColumnValue::NO_NULLS, + 1,1,0, + DataType::INTEGER); +} +// ------------------------------------------------------------------------- +void ODatabaseMetaDataResultSetMetaData::setTypeInfoMap() +{ + m_mColumns[1] = OColumn(::rtl::OUString(),::rtl::OUString::createFromAscii("TYPE_NAME"), + ColumnValue::NO_NULLS, + 0,0,0, + DataType::VARCHAR); + m_mColumns[2] = OColumn(::rtl::OUString(),::rtl::OUString::createFromAscii("DATA_TYPE"), + ColumnValue::NO_NULLS, + 1,1,0, + DataType::INTEGER); + m_mColumns[3] = OColumn(::rtl::OUString(),::rtl::OUString::createFromAscii("PRECISION"), + ColumnValue::NO_NULLS, + 1,1,0, + DataType::INTEGER); + m_mColumns[4] = OColumn(::rtl::OUString(),::rtl::OUString::createFromAscii("LITERAL_PREFIX"), + ColumnValue::NULLABLE, + 0,0,0, + DataType::VARCHAR); + m_mColumns[5] = OColumn(::rtl::OUString(),::rtl::OUString::createFromAscii("LITERAL_SUFFIX"), + ColumnValue::NULLABLE, + 0,0,0, + DataType::VARCHAR); + m_mColumns[6] = OColumn(::rtl::OUString(),::rtl::OUString::createFromAscii("CREATE_PARAMS"), + ColumnValue::NULLABLE, + 0,0,0, + DataType::VARCHAR); + m_mColumns[7] = OColumn(::rtl::OUString(),::rtl::OUString::createFromAscii("NULLABLE"), + ColumnValue::NO_NULLS, + 1,1,0, + DataType::INTEGER); + m_mColumns[8] = OColumn(::rtl::OUString(),::rtl::OUString::createFromAscii("CASE_SENSITIVE"), + ColumnValue::NO_NULLS, + 1,1,0, + DataType::BIT); + m_mColumns[9] = OColumn(::rtl::OUString(),::rtl::OUString::createFromAscii("SEARCHABLE"), + ColumnValue::NO_NULLS, + 1,1,0, + DataType::INTEGER); + m_mColumns[10] = OColumn(::rtl::OUString(),::rtl::OUString::createFromAscii("UNSIGNED_ATTRIBUTE"), + ColumnValue::NO_NULLS, + 1,1,0, + DataType::BIT); + m_mColumns[11] = OColumn(::rtl::OUString(),::rtl::OUString::createFromAscii("FIXED_PREC_SCALE"), + ColumnValue::NO_NULLS, + 1,1,0, + DataType::BIT); + m_mColumns[12] = OColumn(::rtl::OUString(),::rtl::OUString::createFromAscii("AUTO_INCREMENT"), + ColumnValue::NO_NULLS, + 1,1,0, + DataType::BIT); + m_mColumns[13] = OColumn(::rtl::OUString(),::rtl::OUString::createFromAscii("LOCAL_TYPE_NAME"), + ColumnValue::NO_NULLS, + 0,0,0, + DataType::VARCHAR); + m_mColumns[14] = OColumn(::rtl::OUString(),::rtl::OUString::createFromAscii("MINIMUM_SCALE"), + ColumnValue::NO_NULLS, + 0,0,0, + DataType::INTEGER); + m_mColumns[15] = OColumn(::rtl::OUString(),::rtl::OUString::createFromAscii("MAXIMUM_SCALE"), + ColumnValue::NO_NULLS, + 0,0,0, + DataType::INTEGER); + m_mColumns[16] = OColumn(::rtl::OUString(),::rtl::OUString::createFromAscii("SQL_DATA_TYPE"), + ColumnValue::NO_NULLS, + 1,1,0, + DataType::INTEGER); + m_mColumns[17] = OColumn(::rtl::OUString(),::rtl::OUString::createFromAscii("SQL_DATETIME_SUB"), + ColumnValue::NO_NULLS, + 1,1,0, + DataType::INTEGER); + m_mColumns[18] = OColumn(::rtl::OUString(),::rtl::OUString::createFromAscii("NUM_PREC_RADIX"), + ColumnValue::NO_NULLS, + 1,1,0, + DataType::INTEGER); +} +// ------------------------------------------------------------------------- +void ODatabaseMetaDataResultSetMetaData::setProceduresMap() +{ + setProcedureNameMap(); + m_mColumns[4] = OColumn(::rtl::OUString(),::rtl::OUString::createFromAscii("RESERVED1"), + ColumnValue::NULLABLE, + 0,0,0, + DataType::VARCHAR); + m_mColumns[5] = OColumn(::rtl::OUString(),::rtl::OUString::createFromAscii("RESERVED2"), + ColumnValue::NULLABLE, + 0,0,0, + DataType::VARCHAR); + m_mColumns[6] = OColumn(::rtl::OUString(),::rtl::OUString::createFromAscii("RESERVED3"), + ColumnValue::NULLABLE, + 0,0,0, + DataType::VARCHAR); + m_mColumns[7] = OColumn(::rtl::OUString(),::rtl::OUString::createFromAscii("REMARKS"), + ColumnValue::NULLABLE, + 0,0,0, + DataType::VARCHAR); + m_mColumns[8] = OColumn(::rtl::OUString(),::rtl::OUString::createFromAscii("PROCEDURE_TYPE"), + ColumnValue::NO_NULLS, + 1,1,0, + DataType::INTEGER); +} +// ------------------------------------------------------------------------- +void ODatabaseMetaDataResultSetMetaData::setTableTypes() +{ + m_mColumns[1] = OColumn(::rtl::OUString(),::rtl::OUString::createFromAscii("TABLE_TYPE"), + ColumnValue::NULLABLE, + 0,0,0, + DataType::VARCHAR); +} +// ------------------------------------------------------------------------- +void ODatabaseMetaDataResultSetMetaData::setCatalogsMap() +{ + m_mColumns[1] = OColumn(::rtl::OUString(),::rtl::OUString::createFromAscii("TABLE_CAT"), + ColumnValue::NULLABLE, + 0,0,0, + DataType::VARCHAR); +} +// ------------------------------------------------------------------------- +void ODatabaseMetaDataResultSetMetaData::setSchemasMap() +{ + m_mColumns[1] = OColumn(::rtl::OUString(),::rtl::OUString::createFromAscii("TABLE_SCHEM"), + ColumnValue::NULLABLE, + 0,0,0, + DataType::VARCHAR); +} +// ------------------------------------------------------------------------- +void ODatabaseMetaDataResultSetMetaData::setVersionColumnsMap() +{ + m_mColumns[1] = OColumn(::rtl::OUString(),::rtl::OUString::createFromAscii("SCOPE"), + ColumnValue::NO_NULLS, + 0,0,0, + DataType::INTEGER); + m_mColumns[2] = OColumn(::rtl::OUString(),::rtl::OUString::createFromAscii("COLUMN_NAME"), + ColumnValue::NO_NULLS, + 0,0,0, + DataType::VARCHAR); + m_mColumns[3] = OColumn(::rtl::OUString(),::rtl::OUString::createFromAscii("DATA_TYPE"), + ColumnValue::NO_NULLS, + 0,0,0, + DataType::INTEGER); + m_mColumns[4] = OColumn(::rtl::OUString(),::rtl::OUString::createFromAscii("TYPE_NAME"), + ColumnValue::NO_NULLS, + 0,0,0, + DataType::VARCHAR); + m_mColumns[5] = OColumn(::rtl::OUString(),::rtl::OUString::createFromAscii("COLUMN_SIZE"), + ColumnValue::NO_NULLS, + 0,0,0, + DataType::INTEGER); + m_mColumns[6] = OColumn(::rtl::OUString(),::rtl::OUString::createFromAscii("BUFFER_LENGTH"), + ColumnValue::NO_NULLS, + 0,0,0, + DataType::INTEGER); + m_mColumns[7] = OColumn(::rtl::OUString(),::rtl::OUString::createFromAscii("DECIMAL_DIGITS"), + ColumnValue::NULLABLE, + 0,0,0, + DataType::INTEGER); + m_mColumns[8] = OColumn(::rtl::OUString(),::rtl::OUString::createFromAscii("PSEUDO_COLUMN"), + ColumnValue::NO_NULLS, + 0,0,0, + DataType::INTEGER); +} + + diff --git a/connectivity/source/commontools/FValue.cxx b/connectivity/source/commontools/FValue.cxx new file mode 100644 index 000000000000..aca181916b47 --- /dev/null +++ b/connectivity/source/commontools/FValue.cxx @@ -0,0 +1,2333 @@ +/************************************************************************* + * + * 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 <stdio.h> +#include "connectivity/FValue.hxx" +#include "connectivity/CommonTools.hxx" +#include <connectivity/dbconversion.hxx> +#include <cppuhelper/extract.hxx> +#include <com/sun/star/io/XInputStream.hpp> +#include <rtl/ustrbuf.hxx> +#include <rtl/logfile.hxx> + +using namespace ::dbtools; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::sdb; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::util; +using namespace ::com::sun::star::io; + +namespace connectivity +{ + +namespace { + static sal_Bool isStorageCompatible(sal_Int32 _eType1, sal_Int32 _eType2) + { + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbtools", "Ocke.Janssen@sun.com", "ORowSetValue::isStorageCompatible" ); + sal_Bool bIsCompatible = sal_True; + + if (_eType1 != _eType2) + { + RTL_LOGFILE_CONTEXT_TRACE( aLogger, "ORowSetValue::isStorageCompatible _eType1 != _eType2" ); + switch (_eType1) + { + case DataType::CHAR: + case DataType::VARCHAR: + case DataType::DECIMAL: + case DataType::NUMERIC: + case DataType::LONGVARCHAR: + bIsCompatible = (DataType::CHAR == _eType2) + || (DataType::VARCHAR == _eType2) + || (DataType::DECIMAL == _eType2) + || (DataType::NUMERIC == _eType2) + || (DataType::LONGVARCHAR == _eType2); + break; + + case DataType::DOUBLE: + case DataType::REAL: + bIsCompatible = (DataType::DOUBLE == _eType2) + || (DataType::REAL == _eType2); + break; + + case DataType::BINARY: + case DataType::VARBINARY: + case DataType::LONGVARBINARY: + bIsCompatible = (DataType::BINARY == _eType2) + || (DataType::VARBINARY == _eType2) + || (DataType::LONGVARBINARY == _eType2); + break; + + case DataType::INTEGER: + bIsCompatible = (DataType::SMALLINT == _eType2) + || (DataType::TINYINT == _eType2) + || (DataType::BIT == _eType2) + || (DataType::BOOLEAN == _eType2); + break; + case DataType::SMALLINT: + bIsCompatible = (DataType::TINYINT == _eType2) + || (DataType::BIT == _eType2) + || (DataType::BOOLEAN == _eType2); + break; + case DataType::TINYINT: + bIsCompatible = (DataType::BIT == _eType2) + || (DataType::BOOLEAN == _eType2); + break; + + case DataType::BLOB: + case DataType::CLOB: + case DataType::OBJECT: + bIsCompatible = (DataType::BLOB == _eType2) + || (DataType::CLOB == _eType2) + || (DataType::OBJECT == _eType2); + break; + + default: + bIsCompatible = sal_False; + } + } + return bIsCompatible; + } +} + +// ----------------------------------------------------------------------------- +#ifdef DBG_UTIL + +#include <vector> +#include <rtl/string.h> + +namespace tracing +{ + struct AllocationType + { + const sal_Char* pName; + sal_Int32 nAllocatedUnits; + + AllocationType( ) : pName( NULL ), nAllocatedUnits( 0 ) { } + }; + + // ============================================================================= + class AllocationTracer + { + public: + typedef ::std::vector< AllocationType > AllocationState; + static AllocationState s_aAllocated; + static ::osl::Mutex s_aMutex; + + public: + static void registerUnit( const sal_Char* _pName ); + static void revokeUnit( const sal_Char* _pName ); + + private: + static AllocationState::iterator getLocation( const sal_Char* _pName ); + }; + + // ============================================================================= + AllocationTracer::AllocationState::iterator AllocationTracer::getLocation( const sal_Char* _pName ) + { + AllocationState::iterator aLookFor = s_aAllocated.begin(); + for ( ; + aLookFor != s_aAllocated.end(); + ++aLookFor + ) + { + if ( 0 == rtl_str_compare( aLookFor->pName, _pName ) ) + // found + return aLookFor; + } + // not found + s_aAllocated.push_back( AllocationType() ); + aLookFor = s_aAllocated.end(); --aLookFor; + aLookFor->pName = _pName; // note that this assumes that _pName is a constant string .... + return aLookFor; + } + + // ============================================================================= + AllocationTracer::AllocationState AllocationTracer::s_aAllocated; + ::osl::Mutex AllocationTracer::s_aMutex; + + // ============================================================================= + void AllocationTracer::registerUnit( const sal_Char* _pName ) + { + ::osl::MutexGuard aGuard( s_aMutex ); + + AllocationState::iterator aPos = getLocation( _pName ); + ++aPos->nAllocatedUnits; + } + + // ============================================================================= + void AllocationTracer::revokeUnit( const sal_Char* _pName ) + { + ::osl::MutexGuard aGuard( s_aMutex ); + + AllocationState::iterator aPos = getLocation( _pName ); + --aPos->nAllocatedUnits; + } + +#define TRACE_ALLOC( type ) tracing::AllocationTracer::registerUnit( #type ); +#define TRACE_FREE( type ) tracing::AllocationTracer::revokeUnit( #type ); +} +#else +#define TRACE_ALLOC( type ) +#define TRACE_FREE( type ) +#endif + +// ----------------------------------------------------------------------------- +void ORowSetValue::setTypeKind(sal_Int32 _eType) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbtools", "Ocke.Janssen@sun.com", "ORowSetValue::setTypeKind" ); + if ( !m_bNull && !isStorageCompatible(_eType, m_eTypeKind) ) + { + switch(_eType) + { + case DataType::VARCHAR: + case DataType::CHAR: + case DataType::DECIMAL: + case DataType::NUMERIC: + case DataType::LONGVARCHAR: + (*this) = getString(); + break; + case DataType::BIGINT: + (*this) = getLong(); + break; + + case DataType::FLOAT: + (*this) = getFloat(); + break; + case DataType::DOUBLE: + case DataType::REAL: + (*this) = getDouble(); + break; + case DataType::TINYINT: + (*this) = getInt8(); + break; + case DataType::SMALLINT: + (*this) = getInt16(); + break; + case DataType::INTEGER: + (*this) = getInt32(); + break; + case DataType::BIT: + case DataType::BOOLEAN: + (*this) = getBool(); + break; + case DataType::DATE: + (*this) = getDate(); + break; + case DataType::TIME: + (*this) = getTime(); + break; + case DataType::TIMESTAMP: + (*this) = getDateTime(); + break; + case DataType::BINARY: + case DataType::VARBINARY: + case DataType::LONGVARBINARY: + (*this) = getSequence(); + break; + case DataType::BLOB: + case DataType::CLOB: + case DataType::OBJECT: + case DataType::OTHER: + (*this) = getAny(); + break; + default: + (*this) = getAny(); + OSL_ENSURE(0,"ORowSetValue:operator==(): UNSPUPPORTED TYPE!"); + } + } + + m_eTypeKind = _eType; +} + +// ----------------------------------------------------------------------------- +void ORowSetValue::free() +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbtools", "Ocke.Janssen@sun.com", "ORowSetValue::free" ); + if(!m_bNull) + { + switch(m_eTypeKind) + { + case DataType::CHAR: + case DataType::VARCHAR: + case DataType::DECIMAL: + case DataType::NUMERIC: + case DataType::LONGVARCHAR: + OSL_ENSURE(m_aValue.m_pString,"String pointer is null!"); + rtl_uString_release(m_aValue.m_pString); + m_aValue.m_pString = NULL; + break; + case DataType::INTEGER: + if ( !m_bSigned ) + { + delete (sal_Int64*)m_aValue.m_pValue; + TRACE_FREE( sal_Int64 ) + m_aValue.m_pValue = NULL; + } + break; + case DataType::BIGINT: + if ( m_bSigned ) + { + delete (sal_Int64*)m_aValue.m_pValue; + TRACE_FREE( sal_Int64 ) + m_aValue.m_pValue = NULL; + } + else + { + OSL_ENSURE(m_aValue.m_pString,"String pointer is null!"); + rtl_uString_release(m_aValue.m_pString); + m_aValue.m_pString = NULL; + } + break; + case DataType::FLOAT: + delete (float*)m_aValue.m_pValue; + TRACE_FREE( float ) + m_aValue.m_pValue = NULL; + break; + case DataType::DOUBLE: + case DataType::REAL: + delete (double*)m_aValue.m_pValue; + TRACE_FREE( double ) + m_aValue.m_pValue = NULL; + break; + case DataType::DATE: + delete (::com::sun::star::util::Date*)m_aValue.m_pValue; + TRACE_FREE( Date ) + m_aValue.m_pValue = NULL; + break; + case DataType::TIME: + delete (::com::sun::star::util::Time*)m_aValue.m_pValue; + TRACE_FREE( Time ) + m_aValue.m_pValue = NULL; + break; + case DataType::TIMESTAMP: + delete (::com::sun::star::util::DateTime*)m_aValue.m_pValue; + TRACE_FREE( DateTime ) + m_aValue.m_pValue = NULL; + break; + case DataType::BINARY: + case DataType::VARBINARY: + case DataType::LONGVARBINARY: + delete (Sequence<sal_Int8>*)m_aValue.m_pValue; + TRACE_FREE( Sequence_sal_Int8 ) + m_aValue.m_pValue = NULL; + break; + case DataType::BLOB: + case DataType::CLOB: + case DataType::OBJECT: + delete (Any*)m_aValue.m_pValue; + TRACE_FREE( Any ) + m_aValue.m_pValue = NULL; + break; + case DataType::BIT: + case DataType::TINYINT: + case DataType::SMALLINT: + case DataType::BOOLEAN: + break; + default: + if ( m_aValue.m_pValue ) + { + delete (Any*)m_aValue.m_pValue; + TRACE_FREE( Any ) + m_aValue.m_pValue = NULL; + } + break; + + } + m_bNull = sal_True; + } +} +// ----------------------------------------------------------------------------- +ORowSetValue& ORowSetValue::operator=(const ORowSetValue& _rRH) +{ + if(&_rRH == this) + return *this; + + if ( m_eTypeKind != _rRH.m_eTypeKind || (_rRH.m_bNull && !m_bNull) || m_bSigned != _rRH.m_bSigned) + free(); + + m_bBound = _rRH.m_bBound; + m_eTypeKind = _rRH.m_eTypeKind; + m_bSigned = _rRH.m_bSigned; + + if(m_bNull && !_rRH.m_bNull) + { + switch(_rRH.m_eTypeKind) + { + case DataType::CHAR: + case DataType::VARCHAR: + case DataType::DECIMAL: + case DataType::NUMERIC: + case DataType::LONGVARCHAR: + rtl_uString_acquire(_rRH.m_aValue.m_pString); + m_aValue.m_pString = _rRH.m_aValue.m_pString; + break; + case DataType::BIGINT: + if ( _rRH.m_bSigned ) + { + m_aValue.m_pValue = new sal_Int64(*(sal_Int64*)_rRH.m_aValue.m_pValue); + TRACE_ALLOC( sal_Int64 ) + } + else + { + rtl_uString_acquire(_rRH.m_aValue.m_pString); + m_aValue.m_pString = _rRH.m_aValue.m_pString; + } + break; + case DataType::FLOAT: + m_aValue.m_pValue = new float(*(float*)_rRH.m_aValue.m_pValue); + TRACE_ALLOC( float ) + break; + case DataType::DOUBLE: + case DataType::REAL: + m_aValue.m_pValue = new double(*(double*)_rRH.m_aValue.m_pValue); + TRACE_ALLOC( double ) + break; + case DataType::DATE: + m_aValue.m_pValue = new Date(*(Date*)_rRH.m_aValue.m_pValue); + TRACE_ALLOC( Date ) + break; + case DataType::TIME: + m_aValue.m_pValue = new Time(*(Time*)_rRH.m_aValue.m_pValue); + TRACE_ALLOC( Time ) + break; + case DataType::TIMESTAMP: + m_aValue.m_pValue = new DateTime(*(DateTime*)_rRH.m_aValue.m_pValue); + TRACE_ALLOC( DateTime ) + break; + case DataType::BINARY: + case DataType::VARBINARY: + case DataType::LONGVARBINARY: + m_aValue.m_pValue = new Sequence<sal_Int8>(*(Sequence<sal_Int8>*)_rRH.m_aValue.m_pValue); + TRACE_ALLOC( Sequence_sal_Int8 ) + break; + case DataType::BIT: + case DataType::BOOLEAN: + m_aValue.m_bBool = _rRH.m_aValue.m_bBool; + break; + case DataType::TINYINT: + if ( _rRH.m_bSigned ) + m_aValue.m_nInt8 = _rRH.m_aValue.m_nInt8; + else + m_aValue.m_nInt16 = _rRH.m_aValue.m_nInt16; + break; + case DataType::SMALLINT: + if ( _rRH.m_bSigned ) + m_aValue.m_nInt16 = _rRH.m_aValue.m_nInt16; + else + m_aValue.m_nInt32 = _rRH.m_aValue.m_nInt32; + break; + case DataType::INTEGER: + if ( _rRH.m_bSigned ) + m_aValue.m_nInt32 = _rRH.m_aValue.m_nInt32; + else + { + m_aValue.m_pValue = new sal_Int64(*(sal_Int64*)_rRH.m_aValue.m_pValue); + TRACE_ALLOC( sal_Int64 ) + } + break; + default: + m_aValue.m_pValue = new Any(*(Any*)_rRH.m_aValue.m_pValue); + TRACE_ALLOC( Any ) + } + } + else if(!_rRH.m_bNull) + { + switch(_rRH.m_eTypeKind) + { + case DataType::CHAR: + case DataType::VARCHAR: + case DataType::DECIMAL: + case DataType::NUMERIC: + case DataType::LONGVARCHAR: + (*this) = ::rtl::OUString(_rRH.m_aValue.m_pString); + break; + case DataType::BIGINT: + if ( _rRH.m_bSigned ) + (*this) = *(sal_Int64*)_rRH.m_aValue.m_pValue; + else + (*this) = ::rtl::OUString(_rRH.m_aValue.m_pString); + break; + case DataType::FLOAT: + (*this) = *(float*)_rRH.m_aValue.m_pValue; + break; + case DataType::DOUBLE: + case DataType::REAL: + (*this) = *(double*)_rRH.m_aValue.m_pValue; + break; + case DataType::DATE: + (*this) = *(Date*)_rRH.m_aValue.m_pValue; + break; + case DataType::TIME: + (*this) = *(Time*)_rRH.m_aValue.m_pValue; + break; + case DataType::TIMESTAMP: + (*this) = *(DateTime*)_rRH.m_aValue.m_pValue; + break; + case DataType::BINARY: + case DataType::VARBINARY: + case DataType::LONGVARBINARY: + (*this) = *(Sequence<sal_Int8>*)_rRH.m_aValue.m_pValue; + break; + case DataType::BIT: + case DataType::BOOLEAN: + m_aValue.m_bBool = _rRH.m_aValue.m_bBool; + break; + case DataType::TINYINT: + if ( _rRH.m_bSigned ) + m_aValue.m_nInt8 = _rRH.m_aValue.m_nInt8; + else + m_aValue.m_nInt16 = _rRH.m_aValue.m_nInt16; + break; + case DataType::SMALLINT: + if ( _rRH.m_bSigned ) + m_aValue.m_nInt16 = _rRH.m_aValue.m_nInt16; + else + m_aValue.m_nInt32 = _rRH.m_aValue.m_nInt32; + break; + case DataType::INTEGER: + if ( _rRH.m_bSigned ) + m_aValue.m_nInt32 = _rRH.m_aValue.m_nInt32; + else + *static_cast<sal_Int64*>(m_aValue.m_pValue) = *(sal_Int64*)_rRH.m_aValue.m_pValue; + break; + default: + (*(Any*)m_aValue.m_pValue) = (*(Any*)_rRH.m_aValue.m_pValue); + } + } + + m_bNull = _rRH.m_bNull; + // OJ: BUGID: 96277 + m_eTypeKind = _rRH.m_eTypeKind; + + return *this; +} +// ------------------------------------------------------------------------- + +ORowSetValue& ORowSetValue::operator=(const Date& _rRH) +{ + if(m_eTypeKind != DataType::DATE) + free(); + + if(m_bNull) + { + m_aValue.m_pValue = new Date(_rRH); + TRACE_ALLOC( Date ) + m_eTypeKind = DataType::DATE; + m_bNull = sal_False; + } + else + *(Date*)m_aValue.m_pValue = _rRH; + + return *this; +} +// ------------------------------------------------------------------------- +ORowSetValue& ORowSetValue::operator=(const Time& _rRH) +{ + if(m_eTypeKind != DataType::TIME) + free(); + + if(m_bNull) + { + m_aValue.m_pValue = new Time(_rRH); + TRACE_ALLOC( Time ) + m_eTypeKind = DataType::TIME; + m_bNull = sal_False; + } + else + *(Time*)m_aValue.m_pValue = _rRH; + + return *this; +} +// ------------------------------------------------------------------------- +ORowSetValue& ORowSetValue::operator=(const DateTime& _rRH) +{ + if(m_eTypeKind != DataType::TIMESTAMP) + free(); + if(m_bNull) + { + m_aValue.m_pValue = new DateTime(_rRH); + TRACE_ALLOC( DateTime ) + m_eTypeKind = DataType::TIMESTAMP; + m_bNull = sal_False; + } + else + *(DateTime*)m_aValue.m_pValue = _rRH; + + return *this; +} +// ------------------------------------------------------------------------- + +ORowSetValue& ORowSetValue::operator=(const ::rtl::OUString& _rRH) +{ + if(m_eTypeKind != DataType::VARCHAR || m_aValue.m_pString != _rRH.pData) + { + free(); + m_bNull = sal_False; + + m_aValue.m_pString = _rRH.pData; + rtl_uString_acquire(m_aValue.m_pString); + m_eTypeKind = DataType::VARCHAR; + } + + return *this; +} +// ------------------------------------------------------------------------- + +ORowSetValue& ORowSetValue::operator=(const double& _rRH) +{ + if( !isStorageCompatible(m_eTypeKind,DataType::DOUBLE) ) + free(); + + if(m_bNull) + { + m_aValue.m_pValue = new double(_rRH); + TRACE_ALLOC( double ) + m_eTypeKind = DataType::DOUBLE; + m_bNull = sal_False; + } + else + *(double*)m_aValue.m_pValue = _rRH; + + return *this; +} +// ----------------------------------------------------------------------------- +ORowSetValue& ORowSetValue::operator=(const float& _rRH) +{ + if(m_eTypeKind != DataType::FLOAT) + free(); + + if(m_bNull) + { + m_aValue.m_pValue = new float(_rRH); + TRACE_ALLOC( float ) + m_eTypeKind = DataType::FLOAT; + m_bNull = sal_False; + } + else + *(float*)m_aValue.m_pValue = _rRH; + + return *this; +} +// ------------------------------------------------------------------------- + +ORowSetValue& ORowSetValue::operator=(const sal_Int8& _rRH) +{ + if(m_eTypeKind != DataType::TINYINT ) + free(); + + m_aValue.m_nInt8 = _rRH; + m_eTypeKind = DataType::TINYINT; + m_bNull = sal_False; + return *this; +} +// ------------------------------------------------------------------------- + +ORowSetValue& ORowSetValue::operator=(const sal_Int16& _rRH) +{ + if(m_eTypeKind != DataType::SMALLINT ) + free(); + + m_aValue.m_nInt16 = _rRH; + m_eTypeKind = DataType::SMALLINT; + m_bNull = sal_False; + + return *this; +} +// ------------------------------------------------------------------------- + +ORowSetValue& ORowSetValue::operator=(const sal_Int32& _rRH) +{ + if(m_eTypeKind != DataType::INTEGER ) + free(); + + if ( m_bSigned ) + m_aValue.m_nInt32 = _rRH; + else + { + if ( m_bNull ) + { + m_aValue.m_pValue = new sal_Int64(_rRH); + TRACE_ALLOC( sal_Int64 ) + } + else + *static_cast<sal_Int64*>(m_aValue.m_pValue) = static_cast<sal_Int64>(_rRH); + } + + m_eTypeKind = DataType::INTEGER; + m_bNull = sal_False; + + return *this; +} +// ------------------------------------------------------------------------- + +ORowSetValue& ORowSetValue::operator=(const sal_Bool _rRH) +{ + if(m_eTypeKind != DataType::BIT && DataType::BOOLEAN != m_eTypeKind ) + free(); + + m_aValue.m_bBool = _rRH; + m_eTypeKind = DataType::BIT; + m_bNull = sal_False; + + return *this; +} +// ------------------------------------------------------------------------- +ORowSetValue& ORowSetValue::operator=(const sal_Int64& _rRH) +{ + if ( DataType::BIGINT != m_eTypeKind || !m_bSigned ) + free(); + + if ( m_bSigned ) + { + if(m_bNull) + { + m_aValue.m_pValue = new sal_Int64(_rRH); + TRACE_ALLOC( sal_Int64 ) + } + else + *static_cast<sal_Int64*>(m_aValue.m_pValue) = _rRH; + } + else + { + ::rtl::OUString aVal = ::rtl::OUString::valueOf(_rRH); + m_aValue.m_pString = aVal.pData; + rtl_uString_acquire(m_aValue.m_pString); + } + + m_eTypeKind = DataType::BIGINT; + m_bNull = sal_False; + + return *this; +} +// ------------------------------------------------------------------------- +ORowSetValue& ORowSetValue::operator=(const Sequence<sal_Int8>& _rRH) +{ + if (!isStorageCompatible(DataType::LONGVARBINARY,m_eTypeKind)) + free(); + + if (m_bNull) + { + m_aValue.m_pValue = new Sequence<sal_Int8>(_rRH); + TRACE_ALLOC( Sequence_sal_Int8 ) + } + else + *static_cast< Sequence< sal_Int8 >* >(m_aValue.m_pValue) = _rRH; + + m_eTypeKind = DataType::LONGVARBINARY; + m_bNull = sal_False; + + return *this; +} +// ------------------------------------------------------------------------- +ORowSetValue& ORowSetValue::operator=(const Any& _rAny) +{ + if (!isStorageCompatible(DataType::OBJECT,m_eTypeKind)) + free(); + + if ( m_bNull ) + { + m_aValue.m_pValue = new Any(_rAny); + TRACE_ALLOC( Any ) + } + else + *static_cast<Any*>(m_aValue.m_pValue) = _rAny; + + m_eTypeKind = DataType::OBJECT; + m_bNull = sal_False; + + return *this; +} +// ------------------------------------------------------------------------- + +sal_Bool operator==(const Date& _rLH,const Date& _rRH) +{ + return _rLH.Day == _rRH.Day && _rLH.Month == _rRH.Month && _rLH.Year == _rRH.Year; +} +// ------------------------------------------------------------------------- + +sal_Bool operator==(const Time& _rLH,const Time& _rRH) +{ + return _rLH.Minutes == _rRH.Minutes && _rLH.Hours == _rRH.Hours && _rLH.Seconds == _rRH.Seconds && _rLH.HundredthSeconds == _rRH.HundredthSeconds; +} +// ------------------------------------------------------------------------- + +sal_Bool operator==(const DateTime& _rLH,const DateTime& _rRH) +{ + return _rLH.Day == _rRH.Day && _rLH.Month == _rRH.Month && _rLH.Year == _rRH.Year && + _rLH.Minutes == _rRH.Minutes && _rLH.Hours == _rRH.Hours && _rLH.Seconds == _rRH.Seconds && _rLH.HundredthSeconds == _rRH.HundredthSeconds; +} +// ------------------------------------------------------------------------- + +bool ORowSetValue::operator==(const ORowSetValue& _rRH) const +{ + if(m_eTypeKind != _rRH.m_eTypeKind) + return false; + if ( m_bSigned != _rRH.m_bSigned ) + return false; + if(m_bNull != _rRH.isNull()) + return false; + if(m_bNull && _rRH.isNull()) + return true; + + bool bRet = false; + OSL_ENSURE(!m_bNull,"SHould not be null!"); + switch(m_eTypeKind) + { + case DataType::VARCHAR: + case DataType::CHAR: + case DataType::DECIMAL: + case DataType::NUMERIC: + case DataType::LONGVARCHAR: + { + ::rtl::OUString aVal1(m_aValue.m_pString); + ::rtl::OUString aVal2(_rRH.m_aValue.m_pString); + bRet = aVal1 == aVal2; + break; + } + + case DataType::FLOAT: + bRet = *(float*)m_aValue.m_pValue == *(float*)_rRH.m_aValue.m_pValue; + break; + case DataType::DOUBLE: + case DataType::REAL: + bRet = *(double*)m_aValue.m_pValue == *(double*)_rRH.m_aValue.m_pValue; + break; + case DataType::TINYINT: + bRet = m_bSigned ? ( m_aValue.m_nInt8 == _rRH.m_aValue.m_nInt8 ) : (m_aValue.m_nInt16 == _rRH.m_aValue.m_nInt16); + break; + case DataType::SMALLINT: + bRet = m_bSigned ? ( m_aValue.m_nInt16 == _rRH.m_aValue.m_nInt16 ) : (m_aValue.m_nInt32 == _rRH.m_aValue.m_nInt32); + break; + case DataType::INTEGER: + bRet = m_bSigned ? ( m_aValue.m_nInt32 == _rRH.m_aValue.m_nInt32 ) : (*(sal_Int64*)m_aValue.m_pValue == *(sal_Int64*)_rRH.m_aValue.m_pValue); + break; + case DataType::BIGINT: + if ( m_bSigned ) + bRet = *(sal_Int64*)m_aValue.m_pValue == *(sal_Int64*)_rRH.m_aValue.m_pValue; + else + { + ::rtl::OUString aVal1(m_aValue.m_pString); + ::rtl::OUString aVal2(_rRH.m_aValue.m_pString); + bRet = aVal1 == aVal2; + } + break; + case DataType::BIT: + case DataType::BOOLEAN: + bRet = m_aValue.m_bBool == _rRH.m_aValue.m_bBool; + break; + case DataType::DATE: + bRet = *(Date*)m_aValue.m_pValue == *(Date*)_rRH.m_aValue.m_pValue; + break; + case DataType::TIME: + bRet = *(Time*)m_aValue.m_pValue == *(Time*)_rRH.m_aValue.m_pValue; + break; + case DataType::TIMESTAMP: + bRet = *(DateTime*)m_aValue.m_pValue == *(DateTime*)_rRH.m_aValue.m_pValue; + break; + case DataType::BINARY: + case DataType::VARBINARY: + case DataType::LONGVARBINARY: + bRet = false; + break; + case DataType::BLOB: + case DataType::CLOB: + case DataType::OBJECT: + case DataType::OTHER: + bRet = false; + break; + default: + bRet = false; + OSL_ENSURE(0,"ORowSetValue::operator==(): UNSPUPPORTED TYPE!"); + break; + } + return bRet; +} +// ------------------------------------------------------------------------- +Any ORowSetValue::makeAny() const +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbtools", "Ocke.Janssen@sun.com", "ORowSetValue::makeAny" ); + Any rValue; + if(isBound() && !isNull()) + { + switch(getTypeKind()) + { + case DataType::CHAR: + case DataType::VARCHAR: + case DataType::DECIMAL: + case DataType::NUMERIC: + case DataType::LONGVARCHAR: + OSL_ENSURE(m_aValue.m_pString,"Value is null!"); + rValue <<= (::rtl::OUString)m_aValue.m_pString; + break; + case DataType::BIGINT: + if ( m_bSigned ) + { + OSL_ENSURE(m_aValue.m_pValue,"Value is null!"); + rValue <<= *(sal_Int64*)m_aValue.m_pValue; + } + else + { + OSL_ENSURE(m_aValue.m_pString,"Value is null!"); + rValue <<= (::rtl::OUString)m_aValue.m_pString; + } + break; + case DataType::FLOAT: + OSL_ENSURE(m_aValue.m_pValue,"Value is null!"); + rValue <<= *(float*)m_aValue.m_pValue; + break; + case DataType::DOUBLE: + case DataType::REAL: + OSL_ENSURE(m_aValue.m_pValue,"Value is null!"); + rValue <<= *(double*)m_aValue.m_pValue; + break; + case DataType::DATE: + OSL_ENSURE(m_aValue.m_pValue,"Value is null!"); + rValue <<= *(Date*)m_aValue.m_pValue; + break; + case DataType::TIME: + OSL_ENSURE(m_aValue.m_pValue,"Value is null!"); + rValue <<= *(Time*)m_aValue.m_pValue; + break; + case DataType::TIMESTAMP: + OSL_ENSURE(m_aValue.m_pValue,"Value is null!"); + rValue <<= *(DateTime*)m_aValue.m_pValue; + break; + case DataType::BINARY: + case DataType::VARBINARY: + case DataType::LONGVARBINARY: + OSL_ENSURE(m_aValue.m_pValue,"Value is null!"); + rValue <<= *(Sequence<sal_Int8>*)m_aValue.m_pValue; + break; + case DataType::BLOB: + case DataType::CLOB: + case DataType::OBJECT: + case DataType::OTHER: + rValue = getAny(); + break; + case DataType::BIT: + case DataType::BOOLEAN: + rValue.setValue( &m_aValue.m_bBool, ::getCppuBooleanType() ); + break; + case DataType::TINYINT: + if ( m_bSigned ) + rValue <<= m_aValue.m_nInt8; + else + rValue <<= m_aValue.m_nInt16; + break; + case DataType::SMALLINT: + if ( m_bSigned ) + rValue <<= m_aValue.m_nInt16; + else + rValue <<= m_aValue.m_nInt32; + break; + case DataType::INTEGER: + if ( m_bSigned ) + rValue <<= m_aValue.m_nInt32; + else + { + OSL_ENSURE(m_aValue.m_pValue,"Value is null!"); + rValue <<= *(sal_Int64*)m_aValue.m_pValue; + } + break; + default: + OSL_ENSURE(0,"ORowSetValue::makeAny(): UNSPUPPORTED TYPE!"); + rValue = getAny(); + break; + } + } + return rValue; +} +// ------------------------------------------------------------------------- +::rtl::OUString ORowSetValue::getString( ) const +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbtools", "Ocke.Janssen@sun.com", "ORowSetValue::getString" ); + ::rtl::OUString aRet; + if(!m_bNull) + { + switch(getTypeKind()) + { + case DataType::CHAR: + case DataType::VARCHAR: + case DataType::DECIMAL: + case DataType::NUMERIC: + case DataType::LONGVARCHAR: + aRet = m_aValue.m_pString; + break; + case DataType::BIGINT: + if ( m_bSigned ) + aRet = ::rtl::OUString::valueOf((sal_Int64)*this); + else + aRet = m_aValue.m_pString; + break; + case DataType::FLOAT: + aRet = ::rtl::OUString::valueOf((float)*this); + break; + case DataType::DOUBLE: + case DataType::REAL: + aRet = ::rtl::OUString::valueOf((double)*this); + break; + case DataType::DATE: + aRet = connectivity::toDateString(*this); + break; + case DataType::TIME: + aRet = connectivity::toTimeString(*this); + break; + case DataType::TIMESTAMP: + aRet = connectivity::toDateTimeString(*this); + break; + case DataType::BINARY: + case DataType::VARBINARY: + case DataType::LONGVARBINARY: + { + ::rtl::OUStringBuffer sVal = ::rtl::OUString::createFromAscii("0x"); + Sequence<sal_Int8> aSeq(getSequence()); + const sal_Int8* pBegin = aSeq.getConstArray(); + const sal_Int8* pEnd = pBegin + aSeq.getLength(); + for(;pBegin != pEnd;++pBegin) + sVal.append((sal_Int32)*pBegin,16); + aRet = sVal.makeStringAndClear(); + } + break; + case DataType::BIT: + case DataType::BOOLEAN: + aRet = ::rtl::OUString::valueOf((sal_Int32)(sal_Bool)*this); + break; + case DataType::TINYINT: + if ( m_bSigned ) + aRet = ::rtl::OUString::valueOf((sal_Int32)(sal_Int8)*this); + else + aRet = ::rtl::OUString::valueOf((sal_Int32)(sal_Int16)*this); + break; + case DataType::SMALLINT: + if ( m_bSigned ) + aRet = ::rtl::OUString::valueOf((sal_Int32)(sal_Int16)*this); + else + aRet = ::rtl::OUString::valueOf((sal_Int32)*this); + break; + case DataType::INTEGER: + if ( m_bSigned ) + aRet = ::rtl::OUString::valueOf((sal_Int32)*this); + else + aRet = ::rtl::OUString::valueOf((sal_Int64)*this); + break; + case DataType::CLOB: + { + Any aValue( getAny() ); + Reference< XClob > xClob; + if ( aValue >>= xClob ) + { + if ( xClob.is() ) + { + aRet = xClob->getSubString(1,(sal_Int32)xClob->length() ); + } + } + } + break; + default: + { + Any aValue = getAny(); + aValue >>= aRet; + break; + } + } + } + return aRet; +} +// ------------------------------------------------------------------------- +sal_Bool ORowSetValue::getBool() const +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbtools", "Ocke.Janssen@sun.com", "ORowSetValue::getBool" ); + sal_Bool bRet = sal_False; + if(!m_bNull) + { + switch(getTypeKind()) + { + case DataType::CHAR: + case DataType::VARCHAR: + case DataType::LONGVARCHAR: + { + const ::rtl::OUString sValue(m_aValue.m_pString); + const static ::rtl::OUString s_sTrue(RTL_CONSTASCII_USTRINGPARAM("true")); + const static ::rtl::OUString s_sFalse(RTL_CONSTASCII_USTRINGPARAM("false")); + if ( sValue.equalsIgnoreAsciiCase(s_sTrue) ) + { + bRet = sal_True; + break; + } + else if ( sValue.equalsIgnoreAsciiCase(s_sFalse) ) + { + bRet = sal_False; + break; + } + } + // run through + case DataType::DECIMAL: + case DataType::NUMERIC: + + bRet = ::rtl::OUString(m_aValue.m_pString).toInt32() != 0; + break; + case DataType::BIGINT: + if ( m_bSigned ) + bRet = *(sal_Int64*)m_aValue.m_pValue != 0; + else + bRet = ::rtl::OUString(m_aValue.m_pString).toInt64() != 0; + break; + case DataType::FLOAT: + bRet = *(float*)m_aValue.m_pValue != 0.0; + break; + case DataType::DOUBLE: + case DataType::REAL: + bRet = *(double*)m_aValue.m_pValue != 0.0; + break; + case DataType::DATE: + case DataType::TIME: + case DataType::TIMESTAMP: + case DataType::BINARY: + case DataType::VARBINARY: + case DataType::LONGVARBINARY: + OSL_ASSERT(!"getBool() for this type is not allowed!"); + break; + case DataType::BIT: + case DataType::BOOLEAN: + bRet = m_aValue.m_bBool; + break; + case DataType::TINYINT: + bRet = m_bSigned ? (m_aValue.m_nInt8 != 0) : (m_aValue.m_nInt16 != 0); + break; + case DataType::SMALLINT: + bRet = m_bSigned ? (m_aValue.m_nInt16 != 0) : (m_aValue.m_nInt32 != 0); + break; + case DataType::INTEGER: + bRet = m_bSigned ? (m_aValue.m_nInt32 != 0) : (*static_cast<sal_Int64*>(m_aValue.m_pValue) != sal_Int64(0)); + break; + default: + { + Any aValue = getAny(); + aValue >>= bRet; + break; + } + } + } + return bRet; +} +// ------------------------------------------------------------------------- +sal_Int8 ORowSetValue::getInt8() const +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbtools", "Ocke.Janssen@sun.com", "ORowSetValue::getInt8" ); + + + sal_Int8 nRet = 0; + if(!m_bNull) + { + switch(getTypeKind()) + { + case DataType::CHAR: + case DataType::VARCHAR: + case DataType::DECIMAL: + case DataType::NUMERIC: + case DataType::LONGVARCHAR: + nRet = sal_Int8(::rtl::OUString(m_aValue.m_pString).toInt32()); + break; + case DataType::BIGINT: + if ( m_bSigned ) + nRet = sal_Int8(*(sal_Int64*)m_aValue.m_pValue); + else + nRet = sal_Int8(::rtl::OUString(m_aValue.m_pString).toInt32()); + break; + case DataType::FLOAT: + nRet = sal_Int8(*(float*)m_aValue.m_pValue); + break; + case DataType::DOUBLE: + case DataType::REAL: + nRet = sal_Int8(*(double*)m_aValue.m_pValue); + break; + case DataType::DATE: + case DataType::TIME: + case DataType::TIMESTAMP: + case DataType::BINARY: + case DataType::VARBINARY: + case DataType::LONGVARBINARY: + case DataType::BLOB: + case DataType::CLOB: + OSL_ASSERT(!"getInt8() for this type is not allowed!"); + break; + case DataType::BIT: + case DataType::BOOLEAN: + nRet = m_aValue.m_bBool; + break; + case DataType::TINYINT: + if ( m_bSigned ) + nRet = m_aValue.m_nInt8; + else + nRet = static_cast<sal_Int8>(m_aValue.m_nInt16); + break; + case DataType::SMALLINT: + if ( m_bSigned ) + nRet = static_cast<sal_Int8>(m_aValue.m_nInt16); + else + nRet = static_cast<sal_Int8>(m_aValue.m_nInt32); + break; + case DataType::INTEGER: + if ( m_bSigned ) + nRet = static_cast<sal_Int8>(m_aValue.m_nInt32); + else + nRet = static_cast<sal_Int8>(*static_cast<sal_Int64*>(m_aValue.m_pValue)); + break; + default: + { + Any aValue = getAny(); + aValue >>= nRet; + break; + } + } + } + return nRet; +} +// ------------------------------------------------------------------------- +sal_Int16 ORowSetValue::getInt16() const +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbtools", "Ocke.Janssen@sun.com", "ORowSetValue::getInt16" ); + + + sal_Int16 nRet = 0; + if(!m_bNull) + { + switch(getTypeKind()) + { + case DataType::CHAR: + case DataType::VARCHAR: + case DataType::DECIMAL: + case DataType::NUMERIC: + case DataType::LONGVARCHAR: + nRet = sal_Int16(::rtl::OUString(m_aValue.m_pString).toInt32()); + break; + case DataType::BIGINT: + if ( m_bSigned ) + nRet = sal_Int16(*(sal_Int64*)m_aValue.m_pValue); + else + nRet = sal_Int16(::rtl::OUString(m_aValue.m_pString).toInt32()); + break; + case DataType::FLOAT: + nRet = sal_Int16(*(float*)m_aValue.m_pValue); + break; + case DataType::DOUBLE: + case DataType::REAL: + nRet = sal_Int16(*(double*)m_aValue.m_pValue); + break; + case DataType::DATE: + case DataType::TIME: + case DataType::TIMESTAMP: + case DataType::BINARY: + case DataType::VARBINARY: + case DataType::LONGVARBINARY: + case DataType::BLOB: + case DataType::CLOB: + OSL_ASSERT(!"getInt16() for this type is not allowed!"); + break; + case DataType::BIT: + case DataType::BOOLEAN: + nRet = m_aValue.m_bBool; + break; + case DataType::TINYINT: + if ( m_bSigned ) + nRet = m_aValue.m_nInt8; + else + nRet = m_aValue.m_nInt16; + break; + case DataType::SMALLINT: + if ( m_bSigned ) + nRet = m_aValue.m_nInt16; + else + nRet = static_cast<sal_Int16>(m_aValue.m_nInt32); + break; + case DataType::INTEGER: + if ( m_bSigned ) + nRet = static_cast<sal_Int16>(m_aValue.m_nInt32); + else + nRet = static_cast<sal_Int16>(*static_cast<sal_Int64*>(m_aValue.m_pValue)); + break; + default: + { + Any aValue = getAny(); + aValue >>= nRet; + break; + } + } + } + return nRet; +} +// ------------------------------------------------------------------------- +sal_Int32 ORowSetValue::getInt32() const +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbtools", "Ocke.Janssen@sun.com", "ORowSetValue::getInt32" ); + sal_Int32 nRet = 0; + if(!m_bNull) + { + switch(getTypeKind()) + { + case DataType::CHAR: + case DataType::VARCHAR: + case DataType::DECIMAL: + case DataType::NUMERIC: + case DataType::LONGVARCHAR: + nRet = ::rtl::OUString(m_aValue.m_pString).toInt32(); + break; + case DataType::BIGINT: + if ( m_bSigned ) + nRet = sal_Int32(*(sal_Int64*)m_aValue.m_pValue); + else + nRet = ::rtl::OUString(m_aValue.m_pString).toInt32(); + break; + case DataType::FLOAT: + nRet = sal_Int32(*(float*)m_aValue.m_pValue); + break; + case DataType::DOUBLE: + case DataType::REAL: + nRet = sal_Int32(*(double*)m_aValue.m_pValue); + break; + case DataType::DATE: + nRet = dbtools::DBTypeConversion::toDays(*(::com::sun::star::util::Date*)m_aValue.m_pValue); + break; + case DataType::TIME: + case DataType::TIMESTAMP: + case DataType::BINARY: + case DataType::VARBINARY: + case DataType::LONGVARBINARY: + case DataType::BLOB: + case DataType::CLOB: + OSL_ASSERT(!"getInt32() for this type is not allowed!"); + break; + case DataType::BIT: + case DataType::BOOLEAN: + nRet = m_aValue.m_bBool; + break; + case DataType::TINYINT: + if ( m_bSigned ) + nRet = m_aValue.m_nInt8; + else + nRet = m_aValue.m_nInt16; + break; + case DataType::SMALLINT: + if ( m_bSigned ) + nRet = m_aValue.m_nInt16; + else + nRet = m_aValue.m_nInt32; + break; + case DataType::INTEGER: + if ( m_bSigned ) + nRet = m_aValue.m_nInt32; + else + nRet = static_cast<sal_Int32>(*static_cast<sal_Int64*>(m_aValue.m_pValue)); + break; + default: + { + Any aValue = getAny(); + aValue >>= nRet; + break; + } + } + } + return nRet; +} +// ------------------------------------------------------------------------- +sal_Int64 ORowSetValue::getLong() const +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbtools", "Ocke.Janssen@sun.com", "ORowSetValue::getLong" ); + sal_Int64 nRet = 0; + if(!m_bNull) + { + switch(getTypeKind()) + { + case DataType::CHAR: + case DataType::VARCHAR: + case DataType::DECIMAL: + case DataType::NUMERIC: + case DataType::LONGVARCHAR: + nRet = ::rtl::OUString(m_aValue.m_pString).toInt64(); + break; + case DataType::BIGINT: + if ( m_bSigned ) + nRet = *(sal_Int64*)m_aValue.m_pValue; + else + nRet = ::rtl::OUString(m_aValue.m_pString).toInt64(); + break; + case DataType::FLOAT: + nRet = sal_Int64(*(float*)m_aValue.m_pValue); + break; + case DataType::DOUBLE: + case DataType::REAL: + nRet = sal_Int64(*(double*)m_aValue.m_pValue); + break; + case DataType::DATE: + nRet = dbtools::DBTypeConversion::toDays(*(::com::sun::star::util::Date*)m_aValue.m_pValue); + break; + case DataType::TIME: + case DataType::TIMESTAMP: + case DataType::BINARY: + case DataType::VARBINARY: + case DataType::LONGVARBINARY: + case DataType::BLOB: + case DataType::CLOB: + OSL_ASSERT(!"getInt32() for this type is not allowed!"); + break; + case DataType::BIT: + case DataType::BOOLEAN: + nRet = m_aValue.m_bBool; + break; + case DataType::TINYINT: + if ( m_bSigned ) + nRet = m_aValue.m_nInt8; + else + nRet = m_aValue.m_nInt16; + break; + case DataType::SMALLINT: + if ( m_bSigned ) + nRet = m_aValue.m_nInt16; + else + nRet = m_aValue.m_nInt32; + break; + case DataType::INTEGER: + if ( m_bSigned ) + nRet = m_aValue.m_nInt32; + else + nRet = *(sal_Int64*)m_aValue.m_pValue; + break; + default: + { + Any aValue = getAny(); + aValue >>= nRet; + break; + } + } + } + return nRet; +} +// ------------------------------------------------------------------------- +float ORowSetValue::getFloat() const +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbtools", "Ocke.Janssen@sun.com", "ORowSetValue::getFloat" ); + float nRet = 0; + if(!m_bNull) + { + switch(getTypeKind()) + { + case DataType::CHAR: + case DataType::VARCHAR: + case DataType::DECIMAL: + case DataType::NUMERIC: + case DataType::LONGVARCHAR: + nRet = ::rtl::OUString(m_aValue.m_pString).toFloat(); + break; + case DataType::BIGINT: + if ( m_bSigned ) + nRet = float(*(sal_Int64*)m_aValue.m_pValue); + else + nRet = ::rtl::OUString(m_aValue.m_pString).toFloat(); + break; + case DataType::FLOAT: + nRet = *(float*)m_aValue.m_pValue; + break; + case DataType::DOUBLE: + case DataType::REAL: + nRet = (float)*(double*)m_aValue.m_pValue; + break; + case DataType::DATE: + nRet = (float)dbtools::DBTypeConversion::toDouble(*(::com::sun::star::util::Date*)m_aValue.m_pValue); + break; + case DataType::TIME: + nRet = (float)dbtools::DBTypeConversion::toDouble(*(::com::sun::star::util::Time*)m_aValue.m_pValue); + break; + case DataType::TIMESTAMP: + nRet = (float)dbtools::DBTypeConversion::toDouble(*(::com::sun::star::util::DateTime*)m_aValue.m_pValue); + break; + case DataType::BINARY: + case DataType::VARBINARY: + case DataType::LONGVARBINARY: + case DataType::BLOB: + case DataType::CLOB: + OSL_ASSERT(!"getDouble() for this type is not allowed!"); + break; + case DataType::BIT: + case DataType::BOOLEAN: + nRet = m_aValue.m_bBool; + break; + case DataType::TINYINT: + if ( m_bSigned ) + nRet = m_aValue.m_nInt8; + else + nRet = m_aValue.m_nInt16; + break; + case DataType::SMALLINT: + if ( m_bSigned ) + nRet = m_aValue.m_nInt16; + else + nRet = (float)m_aValue.m_nInt32; + break; + case DataType::INTEGER: + if ( m_bSigned ) + nRet = (float)m_aValue.m_nInt32; + else + nRet = float(*(sal_Int64*)m_aValue.m_pValue); + break; + default: + { + Any aValue = getAny(); + aValue >>= nRet; + break; + } + } + } + return nRet; +} +// ------------------------------------------------------------------------- +double ORowSetValue::getDouble() const +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbtools", "Ocke.Janssen@sun.com", "ORowSetValue::getDouble" ); + + + double nRet = 0; + if(!m_bNull) + { + switch(getTypeKind()) + { + case DataType::CHAR: + case DataType::VARCHAR: + case DataType::DECIMAL: + case DataType::NUMERIC: + case DataType::LONGVARCHAR: + nRet = ::rtl::OUString(m_aValue.m_pString).toDouble(); + break; + case DataType::BIGINT: + if ( m_bSigned ) + nRet = double(*(sal_Int64*)m_aValue.m_pValue); + else + nRet = ::rtl::OUString(m_aValue.m_pString).toDouble(); + break; + case DataType::FLOAT: + nRet = *(float*)m_aValue.m_pValue; + break; + case DataType::DOUBLE: + case DataType::REAL: + nRet = *(double*)m_aValue.m_pValue; + break; + case DataType::DATE: + nRet = dbtools::DBTypeConversion::toDouble(*(::com::sun::star::util::Date*)m_aValue.m_pValue); + break; + case DataType::TIME: + nRet = dbtools::DBTypeConversion::toDouble(*(::com::sun::star::util::Time*)m_aValue.m_pValue); + break; + case DataType::TIMESTAMP: + nRet = dbtools::DBTypeConversion::toDouble(*(::com::sun::star::util::DateTime*)m_aValue.m_pValue); + break; + case DataType::BINARY: + case DataType::VARBINARY: + case DataType::LONGVARBINARY: + case DataType::BLOB: + case DataType::CLOB: + OSL_ASSERT(!"getDouble() for this type is not allowed!"); + break; + case DataType::BIT: + case DataType::BOOLEAN: + nRet = m_aValue.m_bBool; + break; + case DataType::TINYINT: + if ( m_bSigned ) + nRet = m_aValue.m_nInt8; + else + nRet = m_aValue.m_nInt16; + break; + case DataType::SMALLINT: + if ( m_bSigned ) + nRet = m_aValue.m_nInt16; + else + nRet = m_aValue.m_nInt32; + break; + case DataType::INTEGER: + if ( m_bSigned ) + nRet = m_aValue.m_nInt32; + else + nRet = double(*(sal_Int64*)m_aValue.m_pValue); + break; + default: + { + Any aValue = getAny(); + aValue >>= nRet; + break; + } + } + } + return nRet; +} +// ------------------------------------------------------------------------- +void ORowSetValue::setFromDouble(const double& _rVal,sal_Int32 _nDatatype) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbtools", "Ocke.Janssen@sun.com", "ORowSetValue::setFromDouble" ); + free(); + + m_bNull = sal_False; + switch(_nDatatype) + { + case DataType::CHAR: + case DataType::VARCHAR: + case DataType::DECIMAL: + case DataType::NUMERIC: + case DataType::LONGVARCHAR: + { + ::rtl::OUString aVal = ::rtl::OUString::valueOf(_rVal); + m_aValue.m_pString = aVal.pData; + rtl_uString_acquire(m_aValue.m_pString); + } + break; + case DataType::BIGINT: + if ( m_bSigned ) + { + m_aValue.m_pValue = new sal_Int64((sal_Int64)_rVal); + TRACE_ALLOC( sal_Int64 ) + } + else + { + ::rtl::OUString aVal = ::rtl::OUString::valueOf(_rVal); + m_aValue.m_pString = aVal.pData; + rtl_uString_acquire(m_aValue.m_pString); + } + break; + case DataType::FLOAT: + m_aValue.m_pValue = new float((float)_rVal); + TRACE_ALLOC( float ) + break; + case DataType::DOUBLE: + case DataType::REAL: + m_aValue.m_pValue = new double(_rVal); + TRACE_ALLOC( double ) + break; + case DataType::DATE: + m_aValue.m_pValue = new Date(dbtools::DBTypeConversion::toDate(_rVal)); + TRACE_ALLOC( Date ) + break; + case DataType::TIME: + m_aValue.m_pValue = new Time(dbtools::DBTypeConversion::toTime(_rVal)); + TRACE_ALLOC( Time ) + break; + case DataType::TIMESTAMP: + m_aValue.m_pValue = new DateTime(dbtools::DBTypeConversion::toDateTime(_rVal)); + TRACE_ALLOC( DateTime ) + break; + case DataType::BINARY: + case DataType::VARBINARY: + case DataType::LONGVARBINARY: + case DataType::BLOB: + case DataType::CLOB: + OSL_ASSERT(!"setFromDouble() for this type is not allowed!"); + break; + case DataType::BIT: + case DataType::BOOLEAN: + m_aValue.m_bBool = _rVal != 0.0; + break; + case DataType::TINYINT: + if ( m_bSigned ) + m_aValue.m_nInt8 = sal_Int8(_rVal); + else + m_aValue.m_nInt16 = sal_Int16(_rVal); + break; + case DataType::SMALLINT: + if ( m_bSigned ) + m_aValue.m_nInt16 = sal_Int16(_rVal); + else + m_aValue.m_nInt32 = sal_Int32(_rVal); + break; + case DataType::INTEGER: + if ( m_bSigned ) + m_aValue.m_nInt32 = sal_Int32(_rVal); + else + { + m_aValue.m_pValue = new sal_Int64((sal_Int64)_rVal); + TRACE_ALLOC( sal_Int64 ) + } + break; + default: + { + m_aValue.m_pValue = new Any(_rVal); + break; + } + } + m_eTypeKind = _nDatatype; +} +// ----------------------------------------------------------------------------- +Sequence<sal_Int8> ORowSetValue::getSequence() const +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbtools", "Ocke.Janssen@sun.com", "ORowSetValue::getSequence" ); + Sequence<sal_Int8> aSeq; + if (!m_bNull) + { + switch(m_eTypeKind) + { + case DataType::OBJECT: + case DataType::CLOB: + case DataType::BLOB: + { + Reference<XInputStream> xStream; + const Any aValue = makeAny(); + if(aValue.hasValue()) + { + Reference<XBlob> xBlob(aValue,UNO_QUERY); + if ( xBlob.is() ) + xStream = xBlob->getBinaryStream(); + else + { + Reference<XClob> xClob(aValue,UNO_QUERY); + if ( xClob.is() ) + xStream = xClob->getCharacterStream(); + } + if(xStream.is()) + { + const sal_uInt32 nBytesToRead = 65535; + sal_uInt32 nRead; + + do + { + ::com::sun::star::uno::Sequence< sal_Int8 > aReadSeq; + + nRead = xStream->readSomeBytes( aReadSeq, nBytesToRead ); + + if( nRead ) + { + const sal_uInt32 nOldLength = aSeq.getLength(); + aSeq.realloc( nOldLength + nRead ); + rtl_copyMemory( aSeq.getArray() + nOldLength, aReadSeq.getConstArray(), aReadSeq.getLength() ); + } + } + while( nBytesToRead == nRead ); + xStream->closeInput(); + } + } + } + break; + case DataType::VARCHAR: + case DataType::LONGVARCHAR: + { + ::rtl::OUString sVal(m_aValue.m_pString); + aSeq = Sequence<sal_Int8>(reinterpret_cast<const sal_Int8*>(sVal.getStr()),sizeof(sal_Unicode)*sVal.getLength()); + } + break; + case DataType::BINARY: + case DataType::VARBINARY: + case DataType::LONGVARBINARY: + aSeq = *static_cast< Sequence<sal_Int8>*>(m_aValue.m_pValue); + break; + default: + { + Any aValue = getAny(); + aValue >>= aSeq; + break; + } + } + } + return aSeq; + +} +// ----------------------------------------------------------------------------- +::com::sun::star::util::Date ORowSetValue::getDate() const +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbtools", "Ocke.Janssen@sun.com", "ORowSetValue::getDate" ); + ::com::sun::star::util::Date aValue; + if(!m_bNull) + { + switch(m_eTypeKind) + { + case DataType::CHAR: + case DataType::VARCHAR: + case DataType::LONGVARCHAR: + aValue = DBTypeConversion::toDate(getString()); + break; + case DataType::DECIMAL: + case DataType::NUMERIC: + aValue = DBTypeConversion::toDate((double)*this); + break; + case DataType::FLOAT: + case DataType::DOUBLE: + case DataType::REAL: + aValue = DBTypeConversion::toDate((double)*this); + break; + + case DataType::DATE: + aValue = *static_cast< ::com::sun::star::util::Date*>(m_aValue.m_pValue); + break; + case DataType::TIMESTAMP: + { + ::com::sun::star::util::DateTime* pDateTime = static_cast< ::com::sun::star::util::DateTime*>(m_aValue.m_pValue); + aValue.Day = pDateTime->Day; + aValue.Month = pDateTime->Month; + aValue.Year = pDateTime->Year; + } + break; + default: + { + Any aAnyValue = getAny(); + aAnyValue >>= aValue; + break; + } + } + } + return aValue; +} +// ----------------------------------------------------------------------------- +::com::sun::star::util::Time ORowSetValue::getTime() const +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbtools", "Ocke.Janssen@sun.com", "ORowSetValue::getTime" ); + ::com::sun::star::util::Time aValue; + if(!m_bNull) + { + switch(m_eTypeKind) + { + case DataType::CHAR: + case DataType::VARCHAR: + case DataType::LONGVARCHAR: + aValue = DBTypeConversion::toTime(getString()); + break; + case DataType::DECIMAL: + case DataType::NUMERIC: + aValue = DBTypeConversion::toTime((double)*this); + break; + case DataType::FLOAT: + case DataType::DOUBLE: + case DataType::REAL: + aValue = DBTypeConversion::toTime((double)*this); + break; + case DataType::TIMESTAMP: + { + ::com::sun::star::util::DateTime* pDateTime = static_cast< ::com::sun::star::util::DateTime*>(m_aValue.m_pValue); + aValue.HundredthSeconds = pDateTime->HundredthSeconds; + aValue.Seconds = pDateTime->Seconds; + aValue.Minutes = pDateTime->Minutes; + aValue.Hours = pDateTime->Hours; + } + break; + case DataType::TIME: + aValue = *static_cast< ::com::sun::star::util::Time*>(m_aValue.m_pValue); + break; + default: + { + Any aAnyValue = getAny(); + aAnyValue >>= aValue; + break; + } + } + } + return aValue; +} +// ----------------------------------------------------------------------------- +::com::sun::star::util::DateTime ORowSetValue::getDateTime() const +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbtools", "Ocke.Janssen@sun.com", "ORowSetValue::getDateTime" ); + ::com::sun::star::util::DateTime aValue; + if(!m_bNull) + { + switch(m_eTypeKind) + { + case DataType::CHAR: + case DataType::VARCHAR: + case DataType::LONGVARCHAR: + aValue = DBTypeConversion::toDateTime(getString()); + break; + case DataType::DECIMAL: + case DataType::NUMERIC: + aValue = DBTypeConversion::toDateTime((double)*this); + break; + case DataType::FLOAT: + case DataType::DOUBLE: + case DataType::REAL: + aValue = DBTypeConversion::toDateTime((double)*this); + break; + case DataType::DATE: + { + ::com::sun::star::util::Date* pDate = static_cast< ::com::sun::star::util::Date*>(m_aValue.m_pValue); + aValue.Day = pDate->Day; + aValue.Month = pDate->Month; + aValue.Year = pDate->Year; + } + break; + case DataType::TIME: + { + ::com::sun::star::util::Time* pTime = static_cast< ::com::sun::star::util::Time*>(m_aValue.m_pValue); + aValue.HundredthSeconds = pTime->HundredthSeconds; + aValue.Seconds = pTime->Seconds; + aValue.Minutes = pTime->Minutes; + aValue.Hours = pTime->Hours; + } + break; + case DataType::TIMESTAMP: + aValue = *static_cast< ::com::sun::star::util::DateTime*>(m_aValue.m_pValue); + break; + default: + { + Any aAnyValue = getAny(); + aAnyValue >>= aValue; + break; + } + } + } + return aValue; +} +// ----------------------------------------------------------------------------- +void ORowSetValue::setSigned(sal_Bool _bMod) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbtools", "Ocke.Janssen@sun.com", "ORowSetValue::setSigned" ); + if ( m_bSigned != _bMod ) + { + m_bSigned = _bMod; + if ( !m_bNull ) + { + sal_Int32 nType = m_eTypeKind; + switch(m_eTypeKind) + { + case DataType::BIGINT: + if ( m_bSigned ) // now we are signed, so we were unsigned and need to call getString() + { + m_bSigned = !m_bSigned; + const ::rtl::OUString sValue = getString(); + free(); + m_bSigned = !m_bSigned; + (*this) = sValue; + } + else + { + m_bSigned = !m_bSigned; + const sal_Int64 nValue = getLong(); + free(); + m_bSigned = !m_bSigned; + (*this) = nValue; + } + break; + case DataType::TINYINT: + if ( m_bSigned ) + (*this) = getInt8(); + else + { + m_bSigned = !m_bSigned; + (*this) = getInt16(); + m_bSigned = !m_bSigned; + } + break; + case DataType::SMALLINT: + if ( m_bSigned ) + (*this) = getInt16(); + else + { + m_bSigned = !m_bSigned; + (*this) = getInt32(); + m_bSigned = !m_bSigned; + } + break; + case DataType::INTEGER: + if ( m_bSigned ) + (*this) = getInt32(); + else + { + m_bSigned = !m_bSigned; + (*this) = getLong(); + m_bSigned = !m_bSigned; + } + break; + } + m_eTypeKind = nType; + } + } +} + +// ----------------------------------------------------------------------------- +namespace detail +{ + class SAL_NO_VTABLE IValueSource + { + public: + virtual ::rtl::OUString getString() const = 0; + virtual sal_Bool getBoolean() const = 0; + virtual sal_Int8 getByte() const = 0; + virtual sal_Int16 getShort() const = 0; + virtual sal_Int32 getInt() const = 0; + virtual sal_Int64 getLong() const = 0; + virtual float getFloat() const = 0; + virtual double getDouble() const = 0; + virtual Date getDate() const = 0; + virtual Time getTime() const = 0; + virtual DateTime getTimestamp() const = 0; + virtual Sequence< sal_Int8 > getBytes() const = 0; + virtual Reference< XInputStream > getBinaryStream() const = 0; + virtual Reference< XInputStream > getCharacterStream() const = 0; + virtual Reference< XBlob > getBlob() const = 0; + virtual Reference< XClob > getClob() const = 0; + virtual Any getObject() const = 0; + virtual sal_Bool wasNull() const = 0; + + virtual ~IValueSource() { } + }; + + class RowValue : public IValueSource + { + public: + RowValue( const Reference< XRow >& _xRow, const sal_Int32 _nPos ) + :m_xRow( _xRow ) + ,m_nPos( _nPos ) + { + } + + // IValueSource + virtual ::rtl::OUString getString() const { return m_xRow->getString( m_nPos ); }; + virtual sal_Bool getBoolean() const { return m_xRow->getBoolean( m_nPos ); }; + virtual sal_Int8 getByte() const { return m_xRow->getByte( m_nPos ); }; + virtual sal_Int16 getShort() const { return m_xRow->getShort( m_nPos ); } + virtual sal_Int32 getInt() const { return m_xRow->getInt( m_nPos ); } + virtual sal_Int64 getLong() const { return m_xRow->getLong( m_nPos ); } + virtual float getFloat() const { return m_xRow->getFloat( m_nPos ); }; + virtual double getDouble() const { return m_xRow->getDouble( m_nPos ); }; + virtual Date getDate() const { return m_xRow->getDate( m_nPos ); }; + virtual Time getTime() const { return m_xRow->getTime( m_nPos ); }; + virtual DateTime getTimestamp() const { return m_xRow->getTimestamp( m_nPos ); }; + virtual Sequence< sal_Int8 > getBytes() const { return m_xRow->getBytes( m_nPos ); }; + virtual Reference< XInputStream > getBinaryStream() const { return m_xRow->getBinaryStream( m_nPos ); }; + virtual Reference< XInputStream > getCharacterStream() const { return m_xRow->getCharacterStream( m_nPos ); }; + virtual Reference< XBlob > getBlob() const { return m_xRow->getBlob( m_nPos ); }; + virtual Reference< XClob > getClob() const { return m_xRow->getClob( m_nPos ); }; + virtual Any getObject() const { return m_xRow->getObject( m_nPos ,NULL); }; + virtual sal_Bool wasNull() const { return m_xRow->wasNull( ); }; + + private: + const Reference< XRow > m_xRow; + const sal_Int32 m_nPos; + }; + + class ColumnValue : public IValueSource + { + public: + ColumnValue( const Reference< XColumn >& _rxColumn ) + :m_xColumn( _rxColumn ) + { + } + + // IValueSource + virtual ::rtl::OUString getString() const { return m_xColumn->getString(); }; + virtual sal_Bool getBoolean() const { return m_xColumn->getBoolean(); }; + virtual sal_Int8 getByte() const { return m_xColumn->getByte(); }; + virtual sal_Int16 getShort() const { return m_xColumn->getShort(); } + virtual sal_Int32 getInt() const { return m_xColumn->getInt(); } + virtual sal_Int64 getLong() const { return m_xColumn->getLong(); } + virtual float getFloat() const { return m_xColumn->getFloat(); }; + virtual double getDouble() const { return m_xColumn->getDouble(); }; + virtual Date getDate() const { return m_xColumn->getDate(); }; + virtual Time getTime() const { return m_xColumn->getTime(); }; + virtual DateTime getTimestamp() const { return m_xColumn->getTimestamp(); }; + virtual Sequence< sal_Int8 > getBytes() const { return m_xColumn->getBytes(); }; + virtual Reference< XInputStream > getBinaryStream() const { return m_xColumn->getBinaryStream(); }; + virtual Reference< XInputStream > getCharacterStream() const { return m_xColumn->getCharacterStream(); }; + virtual Reference< XBlob > getBlob() const { return m_xColumn->getBlob(); }; + virtual Reference< XClob > getClob() const { return m_xColumn->getClob(); }; + virtual Any getObject() const { return m_xColumn->getObject( NULL ); }; + virtual sal_Bool wasNull() const { return m_xColumn->wasNull( ); }; + + private: + const Reference< XColumn > m_xColumn; + }; +} + +// ----------------------------------------------------------------------------- +void ORowSetValue::fill( const sal_Int32 _nType, const Reference< XColumn >& _rxColumn ) +{ + detail::ColumnValue aColumnValue( _rxColumn ); + impl_fill( _nType, sal_True, aColumnValue ); +} + +// ----------------------------------------------------------------------------- +void ORowSetValue::fill( sal_Int32 _nPos, sal_Int32 _nType, sal_Bool _bNullable, const Reference< XRow>& _xRow ) +{ + detail::RowValue aRowValue( _xRow, _nPos ); + impl_fill( _nType, _bNullable, aRowValue ); +} + +// ----------------------------------------------------------------------------- +void ORowSetValue::fill(sal_Int32 _nPos, + sal_Int32 _nType, + const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRow>& _xRow) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbtools", "Ocke.Janssen@sun.com", "ORowSetValue::fill (1)" ); + fill(_nPos,_nType,sal_True,_xRow); +} + +// ----------------------------------------------------------------------------- +void ORowSetValue::impl_fill( const sal_Int32 _nType, sal_Bool _bNullable, const detail::IValueSource& _rValueSource ) + +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbtools", "Ocke.Janssen@sun.com", "ORowSetValue::fill (2)" ); + sal_Bool bReadData = sal_True; + switch(_nType) + { + case DataType::CHAR: + case DataType::VARCHAR: + case DataType::DECIMAL: + case DataType::NUMERIC: + case DataType::LONGVARCHAR: + (*this) = _rValueSource.getString(); + break; + case DataType::BIGINT: + if ( isSigned() ) + (*this) = _rValueSource.getLong(); + else + (*this) = _rValueSource.getString(); + break; + case DataType::FLOAT: + (*this) = _rValueSource.getFloat(); + break; + case DataType::DOUBLE: + case DataType::REAL: + (*this) = _rValueSource.getDouble(); + break; + case DataType::DATE: + (*this) = _rValueSource.getDate(); + break; + case DataType::TIME: + (*this) = _rValueSource.getTime(); + break; + case DataType::TIMESTAMP: + (*this) = _rValueSource.getTimestamp(); + break; + case DataType::BINARY: + case DataType::VARBINARY: + case DataType::LONGVARBINARY: + (*this) = _rValueSource.getBytes(); + break; + case DataType::BIT: + case DataType::BOOLEAN: + (*this) = _rValueSource.getBoolean(); + break; + case DataType::TINYINT: + if ( isSigned() ) + (*this) = _rValueSource.getByte(); + else + (*this) = _rValueSource.getShort(); + break; + case DataType::SMALLINT: + if ( isSigned() ) + (*this) = _rValueSource.getShort(); + else + (*this) = _rValueSource.getInt(); + break; + case DataType::INTEGER: + if ( isSigned() ) + (*this) = _rValueSource.getInt(); + else + (*this) = _rValueSource.getLong(); + break; + case DataType::CLOB: + (*this) = ::com::sun::star::uno::makeAny(_rValueSource.getClob()); + setTypeKind(DataType::CLOB); + break; + case DataType::BLOB: + (*this) = ::com::sun::star::uno::makeAny(_rValueSource.getBlob()); + setTypeKind(DataType::BLOB); + break; + case DataType::OTHER: + (*this) = _rValueSource.getObject(); + setTypeKind(DataType::OTHER); + break; + default: + OSL_ENSURE( false, "ORowSetValue::fill: unsupported type!" ); + (*this) = _rValueSource.getObject(); + break; + } + if ( bReadData && _bNullable && _rValueSource.wasNull() ) + setNull(); + setTypeKind(_nType); +} +// ----------------------------------------------------------------------------- +void ORowSetValue::fill(const Any& _rValue) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbtools", "Ocke.Janssen@sun.com", "ORowSetValue::fill (3)" ); + switch (_rValue.getValueType().getTypeClass()) + { + case TypeClass_VOID: + setNull(); + break; + case TypeClass_BOOLEAN: + { + sal_Bool bValue( sal_False ); + _rValue >>= bValue; + (*this) = bValue; + break; + } + case TypeClass_CHAR: + { + sal_Unicode aDummy(0); + _rValue >>= aDummy; + (*this) = ::rtl::OUString(aDummy); + break; + } + case TypeClass_STRING: + { + ::rtl::OUString sDummy; + _rValue >>= sDummy; + (*this) = sDummy; + break; + } + case TypeClass_FLOAT: + { + float aDummy(0.0); + _rValue >>= aDummy; + (*this) = aDummy; + break; + } + case TypeClass_DOUBLE: + { + double aDummy(0.0); + _rValue >>= aDummy; + (*this) = aDummy; + break; + } + case TypeClass_BYTE: + { + sal_Int8 aDummy(0); + _rValue >>= aDummy; + (*this) = aDummy; + break; + } + case TypeClass_SHORT: + { + sal_Int16 aDummy(0); + _rValue >>= aDummy; + (*this) = aDummy; + break; + } + case TypeClass_LONG: + { + sal_Int32 aDummy(0); + _rValue >>= aDummy; + (*this) = aDummy; + break; + } + case TypeClass_UNSIGNED_SHORT: + { + sal_uInt16 nValue(0); + _rValue >>= nValue; + (*this) = static_cast<sal_Int32>(nValue); + setSigned(sal_False); + break; + } + case TypeClass_HYPER: + { + sal_Int64 nValue(0); + _rValue >>= nValue; + (*this) = nValue; + break; + } + case TypeClass_UNSIGNED_HYPER: + { + sal_uInt64 nValue(0); + _rValue >>= nValue; + (*this) = static_cast<sal_Int64>(nValue); + setSigned(sal_False); + break; + } + case TypeClass_UNSIGNED_LONG: + { + sal_uInt32 nValue(0); + _rValue >>= nValue; + (*this) = static_cast<sal_Int64>(nValue); + setSigned(sal_False); + break; + } + case TypeClass_ENUM: + { + sal_Int32 enumValue( 0 ); + ::cppu::enum2int( enumValue, _rValue ); + (*this) = enumValue; + } + break; + + case TypeClass_SEQUENCE: + { + Sequence<sal_Int8> aDummy; + if ( _rValue >>= aDummy ) + (*this) = aDummy; + else + OSL_ENSURE( false, "ORowSetValue::fill: unsupported sequence type!" ); + break; + } + + case TypeClass_STRUCT: + { + ::com::sun::star::util::Date aDate; + ::com::sun::star::util::Time aTime; + ::com::sun::star::util::DateTime aDateTime; + if ( _rValue >>= aDate ) + { + (*this) = aDate; + } + else if ( _rValue >>= aTime ) + { + (*this) = aTime; + } + else if ( _rValue >>= aDateTime ) + { + (*this) = aDateTime; + } + else + OSL_ENSURE( false, "ORowSetValue::fill: unsupported structure!" ); + + break; + } + case TypeClass_INTERFACE: + { + Reference< XClob > xClob; + if ( _rValue >>= xClob ) + { + (*this) = _rValue; + setTypeKind(DataType::CLOB); + } + else + { + Reference< XBlob > xBlob; + if ( _rValue >>= xBlob ) + { + (*this) = _rValue; + setTypeKind(DataType::BLOB); + } + else + { + (*this) = _rValue; + } + } + } + break; + + default: + OSL_ENSURE(0,"Unknown type"); + break; + } +} + +} // namespace connectivity diff --git a/connectivity/source/commontools/ParamterSubstitution.cxx b/connectivity/source/commontools/ParamterSubstitution.cxx new file mode 100644 index 000000000000..df76724aa008 --- /dev/null +++ b/connectivity/source/commontools/ParamterSubstitution.cxx @@ -0,0 +1,132 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ +#include "precompiled_connectivity.hxx" +#include "ParameterSubstitution.hxx" +#include "connectivity/sqlparse.hxx" +#include <comphelper/sequenceashashmap.hxx> + +namespace connectivity +{ + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::sdbc; + using namespace ::com::sun::star::lang; + using namespace ::com::sun::star; + + ParameterSubstitution::ParameterSubstitution(const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext >& _rxContext ) : m_xContext(_rxContext) + { + } + void SAL_CALL ParameterSubstitution::initialize( const uno::Sequence< uno::Any >& _aArguments ) throw (uno::Exception, uno::RuntimeException) + { + ::osl::MutexGuard aGuard(m_aMutex); + comphelper::SequenceAsHashMap aArgs(_aArguments); + uno::Reference< sdbc::XConnection > xConnection; + xConnection = aArgs.getUnpackedValueOrDefault(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ActiveConnection")),xConnection); + m_xConnection = xConnection; + } + //------------------------------------------------------------------------------ + rtl::OUString ParameterSubstitution::getImplementationName_Static( ) throw(RuntimeException) + { + return ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("org.openoffice.comp.helper.ParameterSubstitution")); + } + //------------------------------------------------------------------------------ + ::rtl::OUString SAL_CALL ParameterSubstitution::getImplementationName( ) throw(RuntimeException) + { + return getImplementationName_Static(); + } + //------------------------------------------------------------------ + sal_Bool SAL_CALL ParameterSubstitution::supportsService( const ::rtl::OUString& _rServiceName ) throw(RuntimeException) + { + Sequence< ::rtl::OUString > aSupported(getSupportedServiceNames()); + const ::rtl::OUString* pSupported = aSupported.getConstArray(); + const ::rtl::OUString* pEnd = pSupported + aSupported.getLength(); + for (;pSupported != pEnd && !pSupported->equals(_rServiceName); ++pSupported) + ; + + return pSupported != pEnd; + } + //------------------------------------------------------------------ + Sequence< ::rtl::OUString > SAL_CALL ParameterSubstitution::getSupportedServiceNames( ) throw(RuntimeException) + { + return getSupportedServiceNames_Static(); + } + //------------------------------------------------------------------ + Sequence< ::rtl::OUString > ParameterSubstitution::getSupportedServiceNames_Static( ) throw (RuntimeException) + { + Sequence< ::rtl::OUString > aSNS( 1 ); + aSNS[0] = ::rtl::OUString::createFromAscii("com.sun.star.sdb.ParameterSubstitution"); + return aSNS; + } + + //------------------------------------------------------------------ + Reference< XInterface > ParameterSubstitution::create(const Reference< XComponentContext >& _xContext) + { + return *(new ParameterSubstitution(_xContext)); + } + //------------------------------------------------------------------ + ::rtl::OUString SAL_CALL ParameterSubstitution::substituteVariables( const ::rtl::OUString& _sText, ::sal_Bool /*bSubstRequired*/ ) throw (::com::sun::star::container::NoSuchElementException, ::com::sun::star::uno::RuntimeException) + { + ::rtl::OUString sRet = _sText; + uno::Reference< sdbc::XConnection > xConnection = m_xConnection; + if ( xConnection.is() ) + { + try + { + uno::Reference< XMultiServiceFactory> xFac(m_xContext->getServiceManager(),uno::UNO_QUERY_THROW); + OSQLParser aParser( xFac ); + ::rtl::OUString sErrorMessage; + ::rtl::OUString sNewSql; + OSQLParseNode* pNode = aParser.parseTree(sErrorMessage,_sText); + if(pNode) + { // special handling for parameters + OSQLParseNode::substituteParameterNames(pNode); + pNode->parseNodeToStr( sNewSql, xConnection ); + delete pNode; + sRet = sNewSql; + } + } + catch(const Exception&) + { + } + } + return sRet; + } + //------------------------------------------------------------------ + ::rtl::OUString SAL_CALL ParameterSubstitution::reSubstituteVariables( const ::rtl::OUString& _sText ) throw (::com::sun::star::uno::RuntimeException) + { + return _sText; + } + //------------------------------------------------------------------ + ::rtl::OUString SAL_CALL ParameterSubstitution::getSubstituteVariableValue( const ::rtl::OUString& /*variable*/ ) throw (::com::sun::star::container::NoSuchElementException, ::com::sun::star::uno::RuntimeException) + { + throw container::NoSuchElementException(); + } + //------------------------------------------------------------------ + + +// ================================== +} // connectivity +// ================================== diff --git a/connectivity/source/commontools/RowFunctionParser.cxx b/connectivity/source/commontools/RowFunctionParser.cxx new file mode 100644 index 000000000000..3804ddfb259f --- /dev/null +++ b/connectivity/source/commontools/RowFunctionParser.cxx @@ -0,0 +1,499 @@ +/************************************************************************* + * + * 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" + +// Makes parser a static resource, +// we're synchronized externally. +// But watch out, the parser might have +// state not visible to this code! +#define BOOST_SPIRIT_SINGLE_GRAMMAR_INSTANCE +#if defined(VERBOSE) && defined(DBG_UTIL) +#include <typeinfo> +#define BOOST_SPIRIT_DEBUG +#endif +#include <boost/spirit/include/classic_core.hpp> +#include "RowFunctionParser.hxx" +#include <rtl/ustring.hxx> +#include <tools/fract.hxx> + + + +#if (OSL_DEBUG_LEVEL > 0) +#include <iostream> +#endif +#include <functional> +#include <algorithm> +#include <stack> + +namespace connectivity +{ +using namespace com::sun::star; + +namespace +{ +////////////////////// +////////////////////// +// EXPRESSION NODES +////////////////////// +////////////////////// +class ConstantValueExpression : public ExpressionNode +{ + ORowSetValueDecoratorRef maValue; + +public: + + ConstantValueExpression( ORowSetValueDecoratorRef rValue ) : + maValue( rValue ) + { + } + virtual ORowSetValueDecoratorRef evaluate(const ODatabaseMetaDataResultSet::ORow& /*_aRow*/ ) const + { + return maValue; + } + virtual void fill(const ODatabaseMetaDataResultSet::ORow& /*_aRow*/ ) const + { + } + virtual ExpressionFunct getType() const + { + return FUNC_CONST; + } + virtual ODatabaseMetaDataResultSet::ORow fillNode( std::vector< RowEquation >& /*rEquations*/, ExpressionNode* /* pOptionalArg */, sal_uInt32 /* nFlags */ ) + { + ODatabaseMetaDataResultSet::ORow aRet; + return aRet; + } +}; + + +/** ExpressionNode implementation for unary + function over two ExpressionNodes + */ +class BinaryFunctionExpression : public ExpressionNode +{ + const ExpressionFunct meFunct; + ExpressionNodeSharedPtr mpFirstArg; + ExpressionNodeSharedPtr mpSecondArg; + +public: + + BinaryFunctionExpression( const ExpressionFunct eFunct, const ExpressionNodeSharedPtr& rFirstArg, const ExpressionNodeSharedPtr& rSecondArg ) : + meFunct( eFunct ), + mpFirstArg( rFirstArg ), + mpSecondArg( rSecondArg ) + { + } + virtual ORowSetValueDecoratorRef evaluate(const ODatabaseMetaDataResultSet::ORow& _aRow ) const + { + ORowSetValueDecoratorRef aRet; + switch(meFunct) + { + case ENUM_FUNC_EQUATION: + aRet = new ORowSetValueDecorator(sal_Bool(mpFirstArg->evaluate(_aRow )->getValue() == mpSecondArg->evaluate(_aRow )->getValue()) ); + break; + case ENUM_FUNC_AND: + aRet = new ORowSetValueDecorator( sal_Bool(mpFirstArg->evaluate(_aRow )->getValue().getBool() && mpSecondArg->evaluate(_aRow )->getValue().getBool()) ); + break; + case ENUM_FUNC_OR: + aRet = new ORowSetValueDecorator( sal_Bool(mpFirstArg->evaluate(_aRow )->getValue().getBool() || mpSecondArg->evaluate(_aRow )->getValue().getBool()) ); + break; + default: + break; + } + return aRet; + } + virtual void fill(const ODatabaseMetaDataResultSet::ORow& _aRow ) const + { + switch(meFunct) + { + case ENUM_FUNC_EQUATION: + (*mpFirstArg->evaluate(_aRow )) = mpSecondArg->evaluate(_aRow )->getValue(); + break; + default: + break; + } + } + virtual ExpressionFunct getType() const + { + return meFunct; + } + virtual ODatabaseMetaDataResultSet::ORow fillNode( std::vector< RowEquation >& /*rEquations*/, ExpressionNode* /*pOptionalArg*/, sal_uInt32 /*nFlags*/ ) + { + ODatabaseMetaDataResultSet::ORow aRet; + return aRet; + } +}; + + +//////////////////////// +//////////////////////// +// FUNCTION PARSER +//////////////////////// +//////////////////////// + +typedef const sal_Char* StringIteratorT; + +struct ParserContext +{ + typedef ::std::stack< ExpressionNodeSharedPtr > OperandStack; + + // stores a stack of not-yet-evaluated operands. This is used + // by the operators (i.e. '+', '*', 'sin' etc.) to pop their + // arguments from. If all arguments to an operator are constant, + // the operator pushes a precalculated result on the stack, and + // a composite ExpressionNode otherwise. + OperandStack maOperandStack; +}; + +typedef ::boost::shared_ptr< ParserContext > ParserContextSharedPtr; + +/** Generate apriori constant value + */ + +class ConstantFunctor +{ + ParserContextSharedPtr mpContext; + +public: + + ConstantFunctor( const ParserContextSharedPtr& rContext ) : + mpContext( rContext ) + { + } + void operator()( StringIteratorT rFirst,StringIteratorT rSecond) const + { + rtl::OUString sVal( rFirst, rSecond - rFirst, RTL_TEXTENCODING_UTF8 ); + mpContext->maOperandStack.push( ExpressionNodeSharedPtr( new ConstantValueExpression( new ORowSetValueDecorator( sVal ) ) ) ); + } +}; + +/** Generate parse-dependent-but-then-constant value + */ +class IntConstantFunctor +{ + ParserContextSharedPtr mpContext; + +public: + IntConstantFunctor( const ParserContextSharedPtr& rContext ) : + mpContext( rContext ) + { + } + void operator()( sal_Int32 n ) const + { + mpContext->maOperandStack.push( ExpressionNodeSharedPtr( new ConstantValueExpression( new ORowSetValueDecorator( n ) ) ) ); + } + void operator()( StringIteratorT rFirst,StringIteratorT rSecond) const + { + rtl::OUString sVal( rFirst, rSecond - rFirst, RTL_TEXTENCODING_UTF8 ); + (void)sVal; + } +}; + +/** Implements a binary function over two ExpressionNodes + + @tpl Generator + Generator functor, to generate an ExpressionNode of + appropriate type + + */ +class BinaryFunctionFunctor +{ + const ExpressionFunct meFunct; + ParserContextSharedPtr mpContext; + +public: + + BinaryFunctionFunctor( const ExpressionFunct eFunct, const ParserContextSharedPtr& rContext ) : + meFunct( eFunct ), + mpContext( rContext ) + { + } + + void operator()( StringIteratorT, StringIteratorT ) const + { + ParserContext::OperandStack& rNodeStack( mpContext->maOperandStack ); + + if( rNodeStack.size() < 2 ) + throw ParseError( "Not enough arguments for binary operator" ); + + // retrieve arguments + ExpressionNodeSharedPtr pSecondArg( rNodeStack.top() ); + rNodeStack.pop(); + ExpressionNodeSharedPtr pFirstArg( rNodeStack.top() ); + rNodeStack.pop(); + + // create combined ExpressionNode + ExpressionNodeSharedPtr pNode = ExpressionNodeSharedPtr( new BinaryFunctionExpression( meFunct, pFirstArg, pSecondArg ) ); + // check for constness + rNodeStack.push( pNode ); + } +}; +/** ExpressionNode implementation for unary + function over one ExpressionNode + */ +class UnaryFunctionExpression : public ExpressionNode +{ + const ExpressionFunct meFunct; + ExpressionNodeSharedPtr mpArg; + +public: + UnaryFunctionExpression( const ExpressionFunct eFunct, const ExpressionNodeSharedPtr& rArg ) : + meFunct( eFunct ), + mpArg( rArg ) + { + } + virtual ORowSetValueDecoratorRef evaluate(const ODatabaseMetaDataResultSet::ORow& _aRow ) const + { + return _aRow[mpArg->evaluate(_aRow )->getValue().getInt32()]; + } + virtual void fill(const ODatabaseMetaDataResultSet::ORow& /*_aRow*/ ) const + { + } + virtual ExpressionFunct getType() const + { + return meFunct; + } + virtual ODatabaseMetaDataResultSet::ORow fillNode( std::vector< RowEquation >& /*rEquations*/, ExpressionNode* /* pOptionalArg */, sal_uInt32 /* nFlags */ ) + { + ODatabaseMetaDataResultSet::ORow aRet; + return aRet; + } +}; + +class UnaryFunctionFunctor +{ + const ExpressionFunct meFunct; + ParserContextSharedPtr mpContext; + +public : + + UnaryFunctionFunctor( const ExpressionFunct eFunct, const ParserContextSharedPtr& rContext ) : + meFunct( eFunct ), + mpContext( rContext ) + { + } + void operator()( StringIteratorT, StringIteratorT ) const + { + + ParserContext::OperandStack& rNodeStack( mpContext->maOperandStack ); + + if( rNodeStack.size() < 1 ) + throw ParseError( "Not enough arguments for unary operator" ); + + // retrieve arguments + ExpressionNodeSharedPtr pArg( rNodeStack.top() ); + rNodeStack.pop(); + + rNodeStack.push( ExpressionNodeSharedPtr( new UnaryFunctionExpression( meFunct, pArg ) ) ); + } +}; + +/* This class implements the following grammar (more or + less literally written down below, only slightly + obfuscated by the parser actions): + + basic_expression = + number | + '(' additive_expression ')' + + unary_expression = + basic_expression + + multiplicative_expression = + unary_expression ( ( '*' unary_expression )* | + ( '/' unary_expression )* ) + + additive_expression = + multiplicative_expression ( ( '+' multiplicative_expression )* | + ( '-' multiplicative_expression )* ) + + */ +class ExpressionGrammar : public ::boost::spirit::grammar< ExpressionGrammar > +{ +public: + /** Create an arithmetic expression grammar + + @param rParserContext + Contains context info for the parser + */ + ExpressionGrammar( const ParserContextSharedPtr& rParserContext ) : + mpParserContext( rParserContext ) + { + } + + template< typename ScannerT > class definition + { + public: + // grammar definition + definition( const ExpressionGrammar& self ) + { + using ::boost::spirit::str_p; + using ::boost::spirit::space_p; + using ::boost::spirit::range_p; + using ::boost::spirit::lexeme_d; + using ::boost::spirit::real_parser; + using ::boost::spirit::chseq_p; + using ::boost::spirit::ch_p; + using ::boost::spirit::int_p; + using ::boost::spirit::as_lower_d; + using ::boost::spirit::strlit; + using ::boost::spirit::inhibit_case; + + + typedef inhibit_case<strlit<> > token_t; + token_t COLUMN = as_lower_d[ "column" ]; + token_t OR_ = as_lower_d[ "or" ]; + token_t AND_ = as_lower_d[ "and" ]; + + integer = + int_p + [IntConstantFunctor(self.getContext())]; + + argument = + integer + | lexeme_d[ +( range_p('a','z') | range_p('A','Z') | range_p('0','9') ) ] + [ ConstantFunctor(self.getContext()) ] + ; + + unaryFunction = + (COLUMN >> '(' >> integer >> ')' ) + [ UnaryFunctionFunctor( UNARY_FUNC_COLUMN, self.getContext()) ] + ; + + assignment = + unaryFunction >> ch_p('=') >> argument + [ BinaryFunctionFunctor( ENUM_FUNC_EQUATION, self.getContext()) ] + ; + + andExpression = + assignment + | ( '(' >> orExpression >> ')' ) + | ( assignment >> AND_ >> assignment ) [ BinaryFunctionFunctor( ENUM_FUNC_AND, self.getContext()) ] + ; + + orExpression = + andExpression + | ( orExpression >> OR_ >> andExpression ) [ BinaryFunctionFunctor( ENUM_FUNC_OR, self.getContext()) ] + ; + + basicExpression = + orExpression + ; + + BOOST_SPIRIT_DEBUG_RULE(basicExpression); + BOOST_SPIRIT_DEBUG_RULE(unaryFunction); + BOOST_SPIRIT_DEBUG_RULE(assignment); + BOOST_SPIRIT_DEBUG_RULE(argument); + BOOST_SPIRIT_DEBUG_RULE(integer); + BOOST_SPIRIT_DEBUG_RULE(orExpression); + BOOST_SPIRIT_DEBUG_RULE(andExpression); + } + + const ::boost::spirit::rule< ScannerT >& start() const + { + return basicExpression; + } + + private: + // the constituents of the Spirit arithmetic expression grammar. + // For the sake of readability, without 'ma' prefix. + ::boost::spirit::rule< ScannerT > basicExpression; + ::boost::spirit::rule< ScannerT > unaryFunction; + ::boost::spirit::rule< ScannerT > assignment; + ::boost::spirit::rule< ScannerT > integer,argument; + ::boost::spirit::rule< ScannerT > orExpression,andExpression; + }; + + const ParserContextSharedPtr& getContext() const + { + return mpParserContext; + } + +private: + ParserContextSharedPtr mpParserContext; // might get modified during parsing +}; + +#ifdef BOOST_SPIRIT_SINGLE_GRAMMAR_INSTANCE +const ParserContextSharedPtr& getParserContext() +{ + static ParserContextSharedPtr lcl_parserContext( new ParserContext() ); + + // clear node stack (since we reuse the static object, that's + // the whole point here) + while( !lcl_parserContext->maOperandStack.empty() ) + lcl_parserContext->maOperandStack.pop(); + + return lcl_parserContext; +} +#endif +} + +ExpressionNodeSharedPtr FunctionParser::parseFunction( const ::rtl::OUString& _sFunction) +{ + // TODO(Q1): Check if a combination of the RTL_UNICODETOTEXT_FLAGS_* + // gives better conversion robustness here (we might want to map space + // etc. to ASCII space here) + const ::rtl::OString& rAsciiFunction( + rtl::OUStringToOString( _sFunction, RTL_TEXTENCODING_ASCII_US ) ); + + StringIteratorT aStart( rAsciiFunction.getStr() ); + StringIteratorT aEnd( rAsciiFunction.getStr()+rAsciiFunction.getLength() ); + + ParserContextSharedPtr pContext; + +#ifdef BOOST_SPIRIT_SINGLE_GRAMMAR_INSTANCE + // static parser context, because the actual + // Spirit parser is also a static object + pContext = getParserContext(); +#else + pContext.reset( new ParserContext() ); +#endif + + ExpressionGrammar aExpressionGrammer( pContext ); + + const ::boost::spirit::parse_info<StringIteratorT> aParseInfo( + ::boost::spirit::parse( aStart, + aEnd, + aExpressionGrammer, + ::boost::spirit::space_p ) ); + + OSL_DEBUG_ONLY(::std::cout.flush()); // needed to keep stdout and cout in sync + + // input fully congested by the parser? + if( !aParseInfo.full ) + throw ParseError( "RowFunctionParser::parseFunction(): string not fully parseable" ); + + // parser's state stack now must contain exactly _one_ ExpressionNode, + // which represents our formula. + if( pContext->maOperandStack.size() != 1 ) + throw ParseError( "RowFunctionParser::parseFunction(): incomplete or empty expression" ); + + return pContext->maOperandStack.top(); +} +} + diff --git a/connectivity/source/commontools/TColumnsHelper.cxx b/connectivity/source/commontools/TColumnsHelper.cxx new file mode 100644 index 000000000000..325fcfbd0f42 --- /dev/null +++ b/connectivity/source/commontools/TColumnsHelper.cxx @@ -0,0 +1,225 @@ +/************************************************************************* + * + * 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 "connectivity/TColumnsHelper.hxx" +#include "connectivity/sdbcx/VColumn.hxx" +#include "connectivity/sdbcx/VColumn.hxx" +#include <com/sun/star/sdbc/XRow.hpp> +#include <com/sun/star/sdbc/XResultSet.hpp> +#include <com/sun/star/sdbc/DataType.hpp> +#include <com/sun/star/sdbc/ColumnValue.hpp> +#include <com/sun/star/sdbcx/KeyType.hpp> +#include <com/sun/star/sdbcx/XColumnsSupplier.hpp> +#include <com/sun/star/sdbcx/XKeysSupplier.hpp> +#include <comphelper/types.hxx> +#include "connectivity/dbtools.hxx" +#include "TConnection.hxx" +#include "connectivity/TTableHelper.hxx" +#include <comphelper/property.hxx> + +using namespace ::comphelper; + + +using namespace connectivity::sdbcx; +using namespace connectivity; +using namespace dbtools; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::lang; +typedef connectivity::sdbcx::OCollection OCollection_TYPE; + +namespace connectivity +{ + class OColumnsHelperImpl + { + public: + OColumnsHelperImpl(sal_Bool _bCase) + : m_aColumnInfo(_bCase) + { + } + ColumnInformationMap m_aColumnInfo; + }; +} + +OColumnsHelper::OColumnsHelper( ::cppu::OWeakObject& _rParent + ,sal_Bool _bCase + ,::osl::Mutex& _rMutex + ,const TStringVector &_rVector + ,sal_Bool _bUseHardRef + ) : OCollection(_rParent,_bCase,_rMutex,_rVector,sal_False,_bUseHardRef) + ,m_pImpl(NULL) + ,m_pTable(NULL) +{ +} +// ----------------------------------------------------------------------------- +OColumnsHelper::~OColumnsHelper() +{ + delete m_pImpl; + m_pImpl = NULL; +} +// ----------------------------------------------------------------------------- + +sdbcx::ObjectType OColumnsHelper::createObject(const ::rtl::OUString& _rName) +{ + OSL_ENSURE(m_pTable,"NO Table set. Error!"); + Reference<XConnection> xConnection = m_pTable->getConnection(); + + if ( !m_pImpl ) + m_pImpl = new OColumnsHelperImpl(isCaseSensitive()); + + sal_Bool bQueryInfo = sal_True; + sal_Bool bAutoIncrement = sal_False; + sal_Bool bIsCurrency = sal_False; + sal_Int32 nDataType = DataType::OTHER; + + ColumnInformationMap::iterator aFind = m_pImpl->m_aColumnInfo.find(_rName); + if ( aFind == m_pImpl->m_aColumnInfo.end() ) // we have to fill it + { + ::rtl::OUString sComposedName = ::dbtools::composeTableNameForSelect( xConnection, m_pTable ); + collectColumnInformation(xConnection,sComposedName,::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("*")) ,m_pImpl->m_aColumnInfo); + aFind = m_pImpl->m_aColumnInfo.find(_rName); + } + if ( aFind != m_pImpl->m_aColumnInfo.end() ) + { + bQueryInfo = sal_False; + bAutoIncrement = aFind->second.first.first; + bIsCurrency = aFind->second.first.second; + nDataType = aFind->second.second; + } // if ( aFind != m_pImpl->m_aColumnInfo.end() ) + + sdbcx::ObjectType xRet; + const ColumnDesc* pColDesc = m_pTable->getColumnDescription(_rName); + if ( pColDesc ) + { + Reference<XPropertySet> xPr = m_pTable; + const Reference<XNameAccess> xPrimaryKeyColumns = getPrimaryKeyColumns_throw(xPr); + sal_Int32 nField11 = pColDesc->nField11; + if ( nField11 != ColumnValue::NO_NULLS && xPrimaryKeyColumns.is() && xPrimaryKeyColumns->hasByName(_rName) ) + { + nField11 = ColumnValue::NO_NULLS; + } // if ( xKeys.is() ) + connectivity::sdbcx::OColumn* pRet = new connectivity::sdbcx::OColumn(_rName, + pColDesc->aField6, + pColDesc->sField13, + pColDesc->sField12, + nField11, + pColDesc->nField7, + pColDesc->nField9, + pColDesc->nField5, + bAutoIncrement, + sal_False, + bIsCurrency, + isCaseSensitive()); + + xRet = pRet; + } + else + { + + xRet.set(::dbtools::createSDBCXColumn( m_pTable, + xConnection, + _rName, + isCaseSensitive(), + bQueryInfo, + bAutoIncrement, + bIsCurrency, + nDataType),UNO_QUERY); + } + return xRet; +} + +// ------------------------------------------------------------------------- +void OColumnsHelper::impl_refresh() throw(RuntimeException) +{ + if ( m_pTable ) + { + m_pImpl->m_aColumnInfo.clear(); + m_pTable->refreshColumns(); + } +} +// ------------------------------------------------------------------------- +Reference< XPropertySet > OColumnsHelper::createDescriptor() +{ + return new OColumn(sal_True); +} +// ----------------------------------------------------------------------------- +// XAppend +sdbcx::ObjectType OColumnsHelper::appendObject( const ::rtl::OUString& _rForName, const Reference< XPropertySet >& descriptor ) +{ + ::osl::MutexGuard aGuard(m_rMutex); + OSL_ENSURE(m_pTable,"OColumnsHelper::appendByDescriptor: Table is null!"); + if ( !m_pTable || m_pTable->isNew() ) + return cloneDescriptor( descriptor ); + + Reference<XDatabaseMetaData> xMetaData = m_pTable->getConnection()->getMetaData(); + ::rtl::OUString aSql = ::rtl::OUString::createFromAscii("ALTER TABLE "); + ::rtl::OUString aQuote = xMetaData->getIdentifierQuoteString( ); + + aSql += ::dbtools::composeTableName( xMetaData, m_pTable, ::dbtools::eInTableDefinitions, false, false, true ); + aSql += ::rtl::OUString::createFromAscii(" ADD "); + aSql += ::dbtools::createStandardColumnPart(descriptor,m_pTable->getConnection(),NULL,m_pTable->getTypeCreatePattern()); + + Reference< XStatement > xStmt = m_pTable->getConnection()->createStatement( ); + if ( xStmt.is() ) + { + xStmt->execute(aSql); + ::comphelper::disposeComponent(xStmt); + } + return createObject( _rForName ); +} +// ------------------------------------------------------------------------- +// XDrop +void OColumnsHelper::dropObject(sal_Int32 /*_nPos*/,const ::rtl::OUString _sElementName) +{ + OSL_ENSURE(m_pTable,"OColumnsHelper::dropByName: Table is null!"); + if ( m_pTable && !m_pTable->isNew() ) + { + ::rtl::OUString aSql = ::rtl::OUString::createFromAscii("ALTER TABLE "); + Reference<XDatabaseMetaData> xMetaData = m_pTable->getConnection()->getMetaData(); + ::rtl::OUString aQuote = xMetaData->getIdentifierQuoteString( ); + + aSql += ::dbtools::composeTableName( xMetaData, m_pTable, ::dbtools::eInTableDefinitions, false, false, true ); + aSql += ::rtl::OUString::createFromAscii(" DROP "); + aSql += ::dbtools::quoteName( aQuote,_sElementName); + + Reference< XStatement > xStmt = m_pTable->getConnection()->createStatement( ); + if ( xStmt.is() ) + { + xStmt->execute(aSql); + ::comphelper::disposeComponent(xStmt); + } + } +} +// ----------------------------------------------------------------------------- + + + diff --git a/connectivity/source/commontools/TConnection.cxx b/connectivity/source/commontools/TConnection.cxx new file mode 100644 index 000000000000..7f471d739186 --- /dev/null +++ b/connectivity/source/commontools/TConnection.cxx @@ -0,0 +1,106 @@ +/************************************************************************* + * + * 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 "TConnection.hxx" +#include <cppuhelper/typeprovider.hxx> +#include <comphelper/types.hxx> +#include <comphelper/officeresourcebundle.hxx> +#include <connectivity/dbexception.hxx> + +using namespace connectivity; +using namespace com::sun::star::uno; +using namespace com::sun::star::lang; +using namespace com::sun::star::sdbc; +using namespace com::sun::star::beans; +using namespace ::osl; + +//------------------------------------------------------------------------------ +OMetaConnection::OMetaConnection() + : OMetaConnection_BASE(m_aMutex) + , m_nTextEncoding(RTL_TEXTENCODING_MS_1252) +{ +} +//------------------------------------------------------------------------------ +void OMetaConnection::disposing() +{ + ::osl::MutexGuard aGuard(m_aMutex); + m_xMetaData = WeakReference< XDatabaseMetaData>(); + for (OWeakRefArray::iterator i = m_aStatements.begin(); m_aStatements.end() != i; ++i) + { + try + { + Reference< XInterface > xStatement( i->get() ); + ::comphelper::disposeComponent( xStatement ); + } + catch (DisposedException) + { + } + } + m_aStatements.clear(); +} +//XUnoTunnel +sal_Int64 SAL_CALL OMetaConnection::getSomething( const ::com::sun::star::uno::Sequence< sal_Int8 >& rId ) throw (::com::sun::star::uno::RuntimeException) +{ + return (rId.getLength() == 16 && 0 == rtl_compareMemory(getUnoTunnelImplementationId().getConstArray(), rId.getConstArray(), 16 ) ) + ? reinterpret_cast< sal_Int64 >( this ) + : (sal_Int64)0; +} +// ----------------------------------------------------------------------------- +Sequence< sal_Int8 > OMetaConnection::getUnoTunnelImplementationId() +{ + static ::cppu::OImplementationId * pId = 0; + if (! pId) + { + ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ); + if (! pId) + { + static ::cppu::OImplementationId aId; + pId = &aId; + } + } + return pId->getImplementationId(); +} +// ----------------------------------------------------------------------------- +::dbtools::OPropertyMap& OMetaConnection::getPropMap() +{ + static ::dbtools::OPropertyMap s_aPropertyNameMap; + return s_aPropertyNameMap; +} +// ----------------------------------------------------------------------------- +void OMetaConnection::throwGenericSQLException( sal_uInt16 _nErrorResourceId,const Reference< XInterface>& _xContext ) +{ + ::rtl::OUString sErrorMessage; + if ( _nErrorResourceId ) + sErrorMessage = m_aResources.getResourceString( _nErrorResourceId ); + Reference< XInterface> xContext = _xContext; + if ( !xContext.is() ) + xContext = *this; + ::dbtools::throwGenericSQLException( sErrorMessage, xContext); +} + diff --git a/connectivity/source/commontools/TDatabaseMetaDataBase.cxx b/connectivity/source/commontools/TDatabaseMetaDataBase.cxx new file mode 100644 index 000000000000..c0b2520b6cfb --- /dev/null +++ b/connectivity/source/commontools/TDatabaseMetaDataBase.cxx @@ -0,0 +1,333 @@ +/************************************************************************* + * + * 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 "TDatabaseMetaDataBase.hxx" +#include "RowFunctionParser.hxx" + +#include <comphelper/sequenceashashmap.hxx> +#include <comphelper/evtlistenerhlp.hxx> +#include <com/sun/star/lang/XComponent.hpp> +#include "resource/sharedresources.hxx" +#include "resource/common_res.hrc" +#include <connectivity/dbexception.hxx> + +using namespace com::sun::star::uno; +using namespace com::sun::star::lang; +using namespace com::sun::star::sdbc; +using namespace com::sun::star::lang; +using namespace com::sun::star::beans; +using namespace comphelper; +using namespace connectivity; + + +ODatabaseMetaDataBase::ODatabaseMetaDataBase(const Reference< XConnection >& _rxConnection,const Sequence< PropertyValue >& _rInfo) + : m_aConnectionInfo(_rInfo) + ,m_isCatalogAtStart(false,sal_False) + ,m_sCatalogSeparator(false,::rtl::OUString()) + ,m_sIdentifierQuoteString(false,::rtl::OUString()) + ,m_supportsCatalogsInTableDefinitions(false,sal_False) + ,m_supportsSchemasInTableDefinitions(false,sal_False) + ,m_supportsCatalogsInDataManipulation(false,sal_False) + ,m_supportsSchemasInDataManipulation(false,sal_False) + ,m_supportsMixedCaseQuotedIdentifiers(false,sal_False) + ,m_supportsAlterTableWithAddColumn(false,sal_False) + ,m_supportsAlterTableWithDropColumn(false,sal_False) + ,m_MaxStatements(false,0) + ,m_MaxTablesInSelect(false,0) + ,m_storesMixedCaseQuotedIdentifiers(false,sal_False) + , m_xConnection(_rxConnection) +{ + osl_incrementInterlockedCount( &m_refCount ); + { + m_xListenerHelper = new OEventListenerHelper(this); + Reference<XComponent> xCom(m_xConnection,UNO_QUERY); + if(xCom.is()) + xCom->addEventListener(m_xListenerHelper); + } + osl_decrementInterlockedCount( &m_refCount ); +} +// ------------------------------------------------------------------------- +ODatabaseMetaDataBase::~ODatabaseMetaDataBase() +{ +} + +// ----------------------------------------------------------------------------- +Sequence< PropertyValue > SAL_CALL ODatabaseMetaDataBase::getConnectionInfo( ) throw (RuntimeException) +{ + return m_aConnectionInfo; +} + +// ----------------------------------------------------------------------------- +void SAL_CALL ODatabaseMetaDataBase::disposing( const EventObject& /*Source*/ ) throw(RuntimeException) +{ + // cut off all references to the connection +m_xConnection.clear(); +m_xListenerHelper.clear(); +} +// ----------------------------------------------------------------------------- +Reference< XResultSet > SAL_CALL ODatabaseMetaDataBase::getTypeInfo( ) throw(SQLException, RuntimeException) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + if ( m_aTypeInfoRows.empty() ) + { + Reference< XResultSet > xRet = impl_getTypeInfo_throw(); + Reference< XRow > xRow(xRet,UNO_QUERY); + ::comphelper::SequenceAsHashMap aMap(m_aConnectionInfo); + Sequence< Any > aTypeInfoSettings; + aTypeInfoSettings = aMap.getUnpackedValueOrDefault(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("TypeInfoSettings")),aTypeInfoSettings); + + if ( xRow.is() ) + { + static sal_Int32 pTypes[] = { + DataType::VARCHAR + ,DataType::INTEGER + ,DataType::INTEGER + ,DataType::VARCHAR + ,DataType::VARCHAR + ,DataType::VARCHAR + ,DataType::INTEGER + ,DataType::BOOLEAN + ,DataType::INTEGER + ,DataType::BOOLEAN + ,DataType::BOOLEAN + ,DataType::BOOLEAN + ,DataType::VARCHAR + ,DataType::INTEGER + ,DataType::INTEGER + ,DataType::INTEGER + ,DataType::INTEGER + ,DataType::INTEGER + }; + ::std::vector<ExpressionNodeSharedPtr> aConditions; + if ( aTypeInfoSettings.getLength() > 1 && ((aTypeInfoSettings.getLength() % 2) == 0) ) + { + const Any* pIter = aTypeInfoSettings.getConstArray(); + const Any* pEnd = pIter + aTypeInfoSettings.getLength(); + try + { + for(;pIter != pEnd;++pIter) + aConditions.push_back(FunctionParser::parseFunction(::comphelper::getString(*pIter))); + } + catch(ParseError&) + { + ::connectivity::SharedResources aResources; + const ::rtl::OUString sError( aResources.getResourceString(STR_FORMULA_WRONG)); + ::dbtools::throwGenericSQLException(sError,*this); + } + } + + ::connectivity::ODatabaseMetaDataResultSet::ORows aTypeInfoRows; + while( xRet->next() ) + { + ::connectivity::ODatabaseMetaDataResultSet::ORow aRow; + aRow.push_back(ODatabaseMetaDataResultSet::getEmptyValue()); + sal_Int32* pType = pTypes; + for (sal_Int32 i = 1; i <= sal_Int32(sizeof(pTypes)/sizeof(pTypes[0])); ++i,++pType) + { + ORowSetValue aValue; + aValue.fill(i,*pType,xRow); + aRow.push_back(new ORowSetValueDecorator(aValue)); + } + + ::std::vector<ExpressionNodeSharedPtr>::iterator aIter = aConditions.begin(); + ::std::vector<ExpressionNodeSharedPtr>::iterator aEnd = aConditions.end(); + for (; aIter != aEnd; ++aIter) + { + if ( (*aIter)->evaluate(aRow)->getValue().getBool() ) + { + ++aIter; + (*aIter)->fill(aRow); + } + else + ++aIter; + } + aTypeInfoRows.push_back(aRow); + } + m_aTypeInfoRows = aTypeInfoRows; + } + } + ::connectivity::ODatabaseMetaDataResultSet* pResult = new ::connectivity::ODatabaseMetaDataResultSet(::connectivity::ODatabaseMetaDataResultSet::eTypeInfo); + Reference< XResultSet > xRet = pResult; + pResult->setRows(m_aTypeInfoRows); + return xRet; +} +// ------------------------------------------------------------------------- +Reference< XResultSet > SAL_CALL ODatabaseMetaDataBase::getExportedKeys( + const Any& /*catalog*/, const ::rtl::OUString& /*schema*/, const ::rtl::OUString& /*table*/ ) throw(SQLException, RuntimeException) +{ + return new ODatabaseMetaDataResultSet( ODatabaseMetaDataResultSet::eExportedKeys ); +} +// ------------------------------------------------------------------------- +Reference< XResultSet > SAL_CALL ODatabaseMetaDataBase::getImportedKeys( + const Any& /*catalog*/, const ::rtl::OUString& /*schema*/, const ::rtl::OUString& /*table*/ ) throw(SQLException, RuntimeException) +{ + return new ODatabaseMetaDataResultSet( ODatabaseMetaDataResultSet::eImportedKeys ); +} +// ------------------------------------------------------------------------- +Reference< XResultSet > SAL_CALL ODatabaseMetaDataBase::getPrimaryKeys( + const Any& /*catalog*/, const ::rtl::OUString& /*schema*/, const ::rtl::OUString& /*table*/ ) throw(SQLException, RuntimeException) +{ + return new ODatabaseMetaDataResultSet( ODatabaseMetaDataResultSet::ePrimaryKeys ); +} +// ------------------------------------------------------------------------- +Reference< XResultSet > SAL_CALL ODatabaseMetaDataBase::getIndexInfo( + const Any& /*catalog*/, const ::rtl::OUString& /*schema*/, const ::rtl::OUString& /*table*/, + sal_Bool /*unique*/, sal_Bool /*approximate*/ ) throw(SQLException, RuntimeException) +{ + return new ODatabaseMetaDataResultSet( ODatabaseMetaDataResultSet::eIndexInfo ); +} +// ------------------------------------------------------------------------- +Reference< XResultSet > SAL_CALL ODatabaseMetaDataBase::getBestRowIdentifier( + const Any& /*catalog*/, const ::rtl::OUString& /*schema*/, const ::rtl::OUString& /*table*/, sal_Int32 /*scope*/, + sal_Bool /*nullable*/ ) throw(SQLException, RuntimeException) +{ + return new ODatabaseMetaDataResultSet( ODatabaseMetaDataResultSet::eBestRowIdentifier ); +} +// ------------------------------------------------------------------------- +Reference< XResultSet > SAL_CALL ODatabaseMetaDataBase::getCrossReference( + const Any& /*primaryCatalog*/, const ::rtl::OUString& /*primarySchema*/, + const ::rtl::OUString& /*primaryTable*/, const Any& /*foreignCatalog*/, + const ::rtl::OUString& /*foreignSchema*/, const ::rtl::OUString& /*foreignTable*/ ) throw(SQLException, RuntimeException) +{ + return new ODatabaseMetaDataResultSet( ODatabaseMetaDataResultSet::eCrossReference ); +} +// ------------------------------------------------------------------------- +Reference< XConnection > SAL_CALL ODatabaseMetaDataBase::getConnection( ) throw(SQLException, RuntimeException) +{ + return m_xConnection; +} +// ------------------------------------------------------------------------- +Reference< XResultSet > SAL_CALL ODatabaseMetaDataBase::getProcedureColumns( + const Any& /*catalog*/, const ::rtl::OUString& /*schemaPattern*/, + const ::rtl::OUString& /*procedureNamePattern*/, const ::rtl::OUString& /*columnNamePattern*/ ) throw(SQLException, RuntimeException) +{ + return new ODatabaseMetaDataResultSet( ODatabaseMetaDataResultSet::eProcedureColumns ); +} +// ------------------------------------------------------------------------- +Reference< XResultSet > SAL_CALL ODatabaseMetaDataBase::getProcedures( + const Any& /*catalog*/, const ::rtl::OUString& /*schemaPattern*/, + const ::rtl::OUString& /*procedureNamePattern*/ ) throw(SQLException, RuntimeException) +{ + return new ODatabaseMetaDataResultSet( ODatabaseMetaDataResultSet::eProcedures ); +} +// ------------------------------------------------------------------------- +Reference< XResultSet > SAL_CALL ODatabaseMetaDataBase::getVersionColumns( + const Any& /*catalog*/, const ::rtl::OUString& /*schema*/, const ::rtl::OUString& /*table*/ ) throw(SQLException, RuntimeException) +{ + return new ODatabaseMetaDataResultSet( ODatabaseMetaDataResultSet::eVersionColumns ); +} +// ------------------------------------------------------------------------- +Reference< XResultSet > SAL_CALL ODatabaseMetaDataBase::getSchemas( ) throw(SQLException, RuntimeException) +{ + return new ODatabaseMetaDataResultSet( ODatabaseMetaDataResultSet::eSchemas ); +} +// ------------------------------------------------------------------------- +Reference< XResultSet > SAL_CALL ODatabaseMetaDataBase::getColumnPrivileges( + const Any& /*catalog*/, const ::rtl::OUString& /*schema*/, const ::rtl::OUString& /*table*/, + const ::rtl::OUString& /*columnNamePattern*/ ) throw(SQLException, RuntimeException) +{ + return new ODatabaseMetaDataResultSet( ODatabaseMetaDataResultSet::eColumnPrivileges ); +} +// ------------------------------------------------------------------------- +Reference< XResultSet > SAL_CALL ODatabaseMetaDataBase::getTablePrivileges( + const Any& /*catalog*/, const ::rtl::OUString& /*schema*/, const ::rtl::OUString& /*table*/) throw(SQLException, RuntimeException) +{ + return new ODatabaseMetaDataResultSet( ODatabaseMetaDataResultSet::eTablePrivileges ); +} +// ------------------------------------------------------------------------- +Reference< XResultSet > SAL_CALL ODatabaseMetaDataBase::getCatalogs( ) throw(SQLException, RuntimeException) +{ + return new ODatabaseMetaDataResultSet( ODatabaseMetaDataResultSet::eCatalogs ); +} +// ----------------------------------------------------------------------------- +::rtl::OUString SAL_CALL ODatabaseMetaDataBase::getIdentifierQuoteString( ) throw(SQLException, RuntimeException) +{ + return callImplMethod(m_sIdentifierQuoteString,::std::mem_fun_t< ::rtl::OUString ,ODatabaseMetaDataBase>(&ODatabaseMetaDataBase::impl_getIdentifierQuoteString_throw)); +} +// ----------------------------------------------------------------------------- +sal_Bool SAL_CALL ODatabaseMetaDataBase::isCatalogAtStart( ) throw(SQLException, RuntimeException) +{ + return callImplMethod(m_isCatalogAtStart,::std::mem_fun_t< sal_Bool,ODatabaseMetaDataBase>(&ODatabaseMetaDataBase::impl_isCatalogAtStart_throw)); +} +// ----------------------------------------------------------------------------- +::rtl::OUString SAL_CALL ODatabaseMetaDataBase::getCatalogSeparator( ) throw(SQLException, RuntimeException) +{ + return callImplMethod(m_sCatalogSeparator,::std::mem_fun_t< ::rtl::OUString,ODatabaseMetaDataBase>(&ODatabaseMetaDataBase::impl_getCatalogSeparator_throw)); +} +// ----------------------------------------------------------------------------- +sal_Bool SAL_CALL ODatabaseMetaDataBase::supportsCatalogsInTableDefinitions( ) throw(SQLException, RuntimeException) +{ + return callImplMethod(m_supportsCatalogsInTableDefinitions,::std::mem_fun_t< sal_Bool,ODatabaseMetaDataBase>(&ODatabaseMetaDataBase::impl_supportsCatalogsInTableDefinitions_throw)); +} +// ----------------------------------------------------------------------------- +sal_Bool SAL_CALL ODatabaseMetaDataBase::supportsSchemasInTableDefinitions( ) throw(SQLException, RuntimeException) +{ + return callImplMethod(m_supportsSchemasInTableDefinitions,::std::mem_fun_t< sal_Bool,ODatabaseMetaDataBase>(&ODatabaseMetaDataBase::impl_supportsSchemasInTableDefinitions_throw)); +} +// ----------------------------------------------------------------------------- +sal_Bool SAL_CALL ODatabaseMetaDataBase::supportsCatalogsInDataManipulation( ) throw(SQLException, RuntimeException) +{ + return callImplMethod(m_supportsCatalogsInDataManipulation,::std::mem_fun_t< sal_Bool,ODatabaseMetaDataBase>(&ODatabaseMetaDataBase::impl_supportsCatalogsInDataManipulation_throw)); +} +// ----------------------------------------------------------------------------- +sal_Bool SAL_CALL ODatabaseMetaDataBase::supportsSchemasInDataManipulation( ) throw(SQLException, RuntimeException) +{ + return callImplMethod(m_supportsSchemasInDataManipulation,::std::mem_fun_t< sal_Bool,ODatabaseMetaDataBase>(&ODatabaseMetaDataBase::impl_supportsSchemasInDataManipulation_throw)); +} +// ----------------------------------------------------------------------------- +sal_Bool SAL_CALL ODatabaseMetaDataBase::supportsMixedCaseQuotedIdentifiers( ) throw(SQLException, RuntimeException) +{ + return callImplMethod(m_supportsMixedCaseQuotedIdentifiers,::std::mem_fun_t< sal_Bool,ODatabaseMetaDataBase>(&ODatabaseMetaDataBase::impl_supportsMixedCaseQuotedIdentifiers_throw)); +} +// ----------------------------------------------------------------------------- +sal_Bool SAL_CALL ODatabaseMetaDataBase::supportsAlterTableWithAddColumn( ) throw(SQLException, RuntimeException) +{ + return callImplMethod(m_supportsAlterTableWithAddColumn,::std::mem_fun_t< sal_Bool,ODatabaseMetaDataBase>(&ODatabaseMetaDataBase::impl_supportsAlterTableWithAddColumn_throw)); +} +// ----------------------------------------------------------------------------- +sal_Bool SAL_CALL ODatabaseMetaDataBase::supportsAlterTableWithDropColumn( ) throw(SQLException, RuntimeException) +{ + return callImplMethod(m_supportsAlterTableWithDropColumn,::std::mem_fun_t< sal_Bool,ODatabaseMetaDataBase>(&ODatabaseMetaDataBase::impl_supportsAlterTableWithDropColumn_throw)); +} +// ----------------------------------------------------------------------------- +sal_Int32 SAL_CALL ODatabaseMetaDataBase::getMaxStatements( ) throw(SQLException, RuntimeException) +{ + return callImplMethod(m_MaxStatements,::std::mem_fun_t< sal_Int32,ODatabaseMetaDataBase>(&ODatabaseMetaDataBase::impl_getMaxStatements_throw)); +} +// ----------------------------------------------------------------------------- +sal_Int32 SAL_CALL ODatabaseMetaDataBase::getMaxTablesInSelect( ) throw(SQLException, RuntimeException) +{ + return callImplMethod(m_MaxTablesInSelect,::std::mem_fun_t< sal_Int32,ODatabaseMetaDataBase>(&ODatabaseMetaDataBase::impl_getMaxTablesInSelect_throw)); +} +// ----------------------------------------------------------------------------- +sal_Bool SAL_CALL ODatabaseMetaDataBase::storesMixedCaseQuotedIdentifiers( ) throw(SQLException, RuntimeException) +{ + return callImplMethod(m_storesMixedCaseQuotedIdentifiers,::std::mem_fun_t< sal_Bool,ODatabaseMetaDataBase>(&ODatabaseMetaDataBase::impl_storesMixedCaseQuotedIdentifiers_throw)); +} +// ----------------------------------------------------------------------------- diff --git a/connectivity/source/commontools/TIndex.cxx b/connectivity/source/commontools/TIndex.cxx new file mode 100644 index 000000000000..0987ba124777 --- /dev/null +++ b/connectivity/source/commontools/TIndex.cxx @@ -0,0 +1,110 @@ +/************************************************************************* + * + * 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 "connectivity/TIndex.hxx" +#include "connectivity/TIndexColumns.hxx" +#include <com/sun/star/sdbc/XRow.hpp> +#include <com/sun/star/sdbc/XResultSet.hpp> +#include "connectivity/TTableHelper.hxx" +#include "TConnection.hxx" + +using namespace connectivity; +using namespace connectivity::sdbcx; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::beans; +// using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::lang; +// ------------------------------------------------------------------------- +OIndexHelper::OIndexHelper( OTableHelper* _pTable) : connectivity::sdbcx::OIndex(sal_True) + , m_pTable(_pTable) +{ + construct(); + ::std::vector< ::rtl::OUString> aVector; + m_pColumns = new OIndexColumns(this,m_aMutex,aVector); +} +// ------------------------------------------------------------------------- +OIndexHelper::OIndexHelper( OTableHelper* _pTable, + const ::rtl::OUString& _Name, + const ::rtl::OUString& _Catalog, + sal_Bool _isUnique, + sal_Bool _isPrimaryKeyIndex, + sal_Bool _isClustered + ) : connectivity::sdbcx::OIndex(_Name, + _Catalog, + _isUnique, + _isPrimaryKeyIndex, + _isClustered,sal_True) + ,m_pTable(_pTable) +{ + construct(); + refreshColumns(); +} +// ------------------------------------------------------------------------- + +void OIndexHelper::refreshColumns() +{ + if ( !m_pTable ) + return; + + ::std::vector< ::rtl::OUString> aVector; + if ( !isNew() ) + { + ::dbtools::OPropertyMap& rPropMap = OMetaConnection::getPropMap(); + ::rtl::OUString aSchema,aTable; + m_pTable->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_SCHEMANAME)) >>= aSchema; + m_pTable->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_NAME)) >>= aTable; + + Reference< XResultSet > xResult = m_pTable->getMetaData()->getIndexInfo( + m_pTable->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_CATALOGNAME)), + aSchema,aTable,sal_False,sal_False); + + if ( xResult.is() ) + { + Reference< XRow > xRow(xResult,UNO_QUERY); + ::rtl::OUString aColName; + while( xResult->next() ) + { + if ( xRow->getString(6) == m_Name ) + { + aColName = xRow->getString(9); + if ( !xRow->wasNull() ) + aVector.push_back(aColName); + } + } + } + } + if(m_pColumns) + m_pColumns->reFill(aVector); + else + m_pColumns = new OIndexColumns(this,m_aMutex,aVector); +} +// ----------------------------------------------------------------------------- + diff --git a/connectivity/source/commontools/TIndexColumns.cxx b/connectivity/source/commontools/TIndexColumns.cxx new file mode 100644 index 000000000000..3c9ac59112f6 --- /dev/null +++ b/connectivity/source/commontools/TIndexColumns.cxx @@ -0,0 +1,127 @@ +/************************************************************************* + * + * 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 "connectivity/TIndexColumns.hxx" +#include "connectivity/sdbcx/VIndexColumn.hxx" +#include <com/sun/star/sdbc/XRow.hpp> +#include <com/sun/star/sdbc/XResultSet.hpp> +#include <com/sun/star/sdbc/DataType.hpp> +#include <com/sun/star/sdbc/ColumnValue.hpp> +#include <comphelper/property.hxx> +#include "connectivity/TIndex.hxx" +#include "connectivity/TTableHelper.hxx" +#include "TConnection.hxx" + +using namespace connectivity; +using namespace connectivity::sdbcx; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::beans; +// using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::lang; +// ------------------------------------------------------------------------- +OIndexColumns::OIndexColumns( OIndexHelper* _pIndex, + ::osl::Mutex& _rMutex, + const ::std::vector< ::rtl::OUString> &_rVector) + : connectivity::sdbcx::OCollection(*_pIndex,sal_True,_rMutex,_rVector) + ,m_pIndex(_pIndex) +{ +} +// ------------------------------------------------------------------------- +sdbcx::ObjectType OIndexColumns::createObject(const ::rtl::OUString& _rName) +{ + ::dbtools::OPropertyMap& rPropMap = OMetaConnection::getPropMap(); + ::rtl::OUString aSchema,aTable; + m_pIndex->getTable()->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_SCHEMANAME)) >>= aSchema; + m_pIndex->getTable()->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_NAME)) >>= aTable; + + Reference< XResultSet > xResult = m_pIndex->getTable()->getConnection()->getMetaData()->getIndexInfo( + m_pIndex->getTable()->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_CATALOGNAME)), + aSchema,aTable,sal_False,sal_False); + + sal_Bool bAsc = sal_True; + if ( xResult.is() ) + { + Reference< XRow > xRow(xResult,UNO_QUERY); + ::rtl::OUString aD(::rtl::OUString::createFromAscii("D")); + while( xResult->next() ) + { + if(xRow->getString(9) == _rName) + bAsc = xRow->getString(10) != aD; + } + } + + xResult = m_pIndex->getTable()->getConnection()->getMetaData()->getColumns( + m_pIndex->getTable()->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_CATALOGNAME)), + aSchema,aTable,_rName); + + sdbcx::ObjectType xRet; + if ( xResult.is() ) + { + Reference< XRow > xRow(xResult,UNO_QUERY); + while( xResult->next() ) + { + if ( xRow->getString(4) == _rName ) + { + sal_Int32 nDataType = xRow->getInt(5); + ::rtl::OUString aTypeName(xRow->getString(6)); + sal_Int32 nSize = xRow->getInt(7); + sal_Int32 nDec = xRow->getInt(9); + sal_Int32 nNull = xRow->getInt(11); + ::rtl::OUString aColumnDef(xRow->getString(13)); + + OIndexColumn* pRet = new OIndexColumn(bAsc, + _rName, + aTypeName, + aColumnDef, + nNull, + nSize, + nDec, + nDataType, + sal_False,sal_False,sal_False,sal_True); + xRet = pRet; + break; + } + } + } + + return xRet; +} +// ------------------------------------------------------------------------- +Reference< XPropertySet > OIndexColumns::createDescriptor() +{ + return new OIndexColumn(sal_True); +} +// ------------------------------------------------------------------------- +void OIndexColumns::impl_refresh() throw(RuntimeException) +{ + m_pIndex->refreshColumns(); +} +// ----------------------------------------------------------------------------- diff --git a/connectivity/source/commontools/TIndexes.cxx b/connectivity/source/commontools/TIndexes.cxx new file mode 100644 index 000000000000..1f77d51929d0 --- /dev/null +++ b/connectivity/source/commontools/TIndexes.cxx @@ -0,0 +1,262 @@ +/************************************************************************* + * + * 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 "connectivity/TIndexes.hxx" +#include "connectivity/TIndex.hxx" +#include <com/sun/star/sdbc/XRow.hpp> +#include <com/sun/star/sdbc/XResultSet.hpp> +#include <com/sun/star/sdbc/IndexType.hpp> +#include <connectivity/dbtools.hxx> +#include "connectivity/TTableHelper.hxx" +#include "TConnection.hxx" +#include <comphelper/extract.hxx> +#include <rtl/ustrbuf.hxx> +using namespace connectivity; +using namespace connectivity::sdbcx; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::lang; +using namespace cppu; + +typedef connectivity::sdbcx::OCollection OCollection_TYPE; +// ----------------------------------------------------------------------------- +OIndexesHelper::OIndexesHelper(OTableHelper* _pTable, + ::osl::Mutex& _rMutex, + const ::std::vector< ::rtl::OUString> &_rVector + ) + : OCollection(*_pTable,sal_True,_rMutex,_rVector) + ,m_pTable(_pTable) +{ +} +// ----------------------------------------------------------------------------- + +sdbcx::ObjectType OIndexesHelper::createObject(const ::rtl::OUString& _rName) +{ + Reference< XConnection> xConnection = m_pTable->getConnection(); + if ( !xConnection.is() ) + return NULL; + + sdbcx::ObjectType xRet; + ::rtl::OUString aName,aQualifier; + sal_Int32 nLen = _rName.indexOf('.'); + if ( nLen != -1 ) + { + aQualifier = _rName.copy(0,nLen); + aName = _rName.copy(nLen+1); + } + else + aName = _rName; + + ::dbtools::OPropertyMap& rPropMap = OMetaConnection::getPropMap(); + ::rtl::OUString aSchema,aTable; + m_pTable->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_SCHEMANAME)) >>= aSchema; + m_pTable->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_NAME)) >>= aTable; + + Any aCatalog = m_pTable->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_CATALOGNAME)); + Reference< XResultSet > xResult = m_pTable->getMetaData()->getIndexInfo(aCatalog,aSchema,aTable,sal_False,sal_False); + + if ( xResult.is() ) + { + Reference< XRow > xRow(xResult,UNO_QUERY); + while( xResult->next() ) + { + sal_Bool bUnique = !xRow->getBoolean(4); + if((!aQualifier.getLength() || xRow->getString(5) == aQualifier ) && xRow->getString(6) == aName) + { + sal_Int32 nClustered = xRow->getShort(7); + sal_Bool bPrimarKeyIndex = sal_False; + xRow.clear(); + xResult.clear(); + try + { + xResult = m_pTable->getMetaData()->getPrimaryKeys(aCatalog,aSchema,aTable); + xRow.set(xResult,UNO_QUERY); + + if ( xRow.is() && xResult->next() ) // there can be only one primary key + { + bPrimarKeyIndex = xRow->getString(6) == aName; + } + } + catch(Exception) + { + } + OIndexHelper* pRet = new OIndexHelper(m_pTable,aName,aQualifier,bUnique, + bPrimarKeyIndex, + nClustered == IndexType::CLUSTERED); + xRet = pRet; + break; + } + } + } + + return xRet; +} +// ------------------------------------------------------------------------- +void OIndexesHelper::impl_refresh() throw(RuntimeException) +{ + m_pTable->refreshIndexes(); +} +// ------------------------------------------------------------------------- +Reference< XPropertySet > OIndexesHelper::createDescriptor() +{ + return new OIndexHelper(m_pTable); +} +// ------------------------------------------------------------------------- +// XAppend +sdbcx::ObjectType OIndexesHelper::appendObject( const ::rtl::OUString& _rForName, const Reference< XPropertySet >& descriptor ) +{ + Reference< XConnection> xConnection = m_pTable->getConnection(); + if ( !xConnection.is() ) + return NULL; + if ( m_pTable->isNew() ) + return cloneDescriptor( descriptor ); + + if ( m_pTable->getIndexService().is() ) + { + m_pTable->getIndexService()->addIndex(m_pTable,descriptor); + } + else + { + ::dbtools::OPropertyMap& rPropMap = OMetaConnection::getPropMap(); + ::rtl::OUStringBuffer aSql( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("CREATE "))); + ::rtl::OUString aQuote = m_pTable->getMetaData()->getIdentifierQuoteString( ); + ::rtl::OUString aDot = ::rtl::OUString::createFromAscii("."); + + if(comphelper::getBOOL(descriptor->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_ISUNIQUE)))) + aSql.appendAscii("UNIQUE "); + aSql.appendAscii("INDEX "); + + + ::rtl::OUString aCatalog,aSchema,aTable; + dbtools::qualifiedNameComponents(m_pTable->getMetaData(),m_pTable->getName(),aCatalog,aSchema,aTable,::dbtools::eInDataManipulation); + ::rtl::OUString aComposedName; + + aComposedName = dbtools::composeTableName(m_pTable->getMetaData(),aCatalog,aSchema,aTable,sal_True,::dbtools::eInIndexDefinitions); + if ( _rForName.getLength() ) + { + aSql.append( ::dbtools::quoteName( aQuote, _rForName ) ); + aSql.appendAscii(" ON "); + aSql.append(aComposedName); + aSql.appendAscii(" ( "); + + Reference<XColumnsSupplier> xColumnSup(descriptor,UNO_QUERY); + Reference<XIndexAccess> xColumns(xColumnSup->getColumns(),UNO_QUERY); + Reference< XPropertySet > xColProp; + sal_Bool bAddIndexAppendix = ::dbtools::getBooleanDataSourceSetting( m_pTable->getConnection(), "AddIndexAppendix" ); + sal_Int32 nCount = xColumns->getCount(); + for(sal_Int32 i = 0 ; i < nCount; ++i) + { + xColProp.set(xColumns->getByIndex(i),UNO_QUERY); + aSql.append(::dbtools::quoteName( aQuote,comphelper::getString(xColProp->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_NAME))))); + + if ( bAddIndexAppendix ) + { + + aSql.appendAscii(any2bool(xColProp->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_ISASCENDING))) + ? + " ASC" + : + " DESC"); + } + aSql.appendAscii(","); + } + aSql.setCharAt(aSql.getLength()-1,')'); + } + else + { + aSql.append(aComposedName); + + Reference<XColumnsSupplier> xColumnSup(descriptor,UNO_QUERY); + Reference<XIndexAccess> xColumns(xColumnSup->getColumns(),UNO_QUERY); + Reference< XPropertySet > xColProp; + if(xColumns->getCount() != 1) + throw SQLException(); + + xColumns->getByIndex(0) >>= xColProp; + + aSql.append(aDot); + aSql.append(::dbtools::quoteName( aQuote,comphelper::getString(xColProp->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_NAME))))); + } + + Reference< XStatement > xStmt = m_pTable->getConnection()->createStatement( ); + if ( xStmt.is() ) + { + ::rtl::OUString sSql = aSql.makeStringAndClear(); + xStmt->execute(sSql); + ::comphelper::disposeComponent(xStmt); + } + } + + return createObject( _rForName ); +} +// ------------------------------------------------------------------------- +// XDrop +void OIndexesHelper::dropObject(sal_Int32 /*_nPos*/,const ::rtl::OUString _sElementName) +{ + Reference< XConnection> xConnection = m_pTable->getConnection(); + if( xConnection.is() && !m_pTable->isNew()) + { + if ( m_pTable->getIndexService().is() ) + { + m_pTable->getIndexService()->dropIndex(m_pTable,_sElementName); + } + else + { + ::rtl::OUString aName,aSchema; + sal_Int32 nLen = _sElementName.indexOf('.'); + if(nLen != -1) + aSchema = _sElementName.copy(0,nLen); + aName = _sElementName.copy(nLen+1); + + ::rtl::OUString aSql = ::rtl::OUString::createFromAscii("DROP INDEX "); + + ::rtl::OUString aComposedName = dbtools::composeTableName( m_pTable->getMetaData(), m_pTable, ::dbtools::eInIndexDefinitions, false, false, true ); + ::rtl::OUString sIndexName,sTemp; + sIndexName = dbtools::composeTableName( m_pTable->getMetaData(), sTemp, aSchema, aName, sal_True, ::dbtools::eInIndexDefinitions ); + + aSql += sIndexName + + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" ON ")) + + aComposedName; + + Reference< XStatement > xStmt = m_pTable->getConnection()->createStatement( ); + if ( xStmt.is() ) + { + xStmt->execute(aSql); + ::comphelper::disposeComponent(xStmt); + } + } + } +} +// ----------------------------------------------------------------------------- + + + diff --git a/connectivity/source/commontools/TKey.cxx b/connectivity/source/commontools/TKey.cxx new file mode 100644 index 000000000000..464335aa7b44 --- /dev/null +++ b/connectivity/source/commontools/TKey.cxx @@ -0,0 +1,119 @@ +/************************************************************************* + * + * 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 "connectivity/TKey.hxx" +#include "connectivity/TKeyColumns.hxx" +#include <com/sun/star/sdbc/XRow.hpp> +#include <com/sun/star/sdbc/XResultSet.hpp> +#include "TConnection.hxx" +#include "connectivity/TTableHelper.hxx" + +using namespace connectivity; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::beans; +// using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::lang; +// ------------------------------------------------------------------------- +OTableKeyHelper::OTableKeyHelper(OTableHelper* _pTable) : connectivity::sdbcx::OKey(sal_True) + ,m_pTable(_pTable) +{ + construct(); +} +// ------------------------------------------------------------------------- +OTableKeyHelper::OTableKeyHelper( OTableHelper* _pTable + ,const ::rtl::OUString& _Name + ,const sdbcx::TKeyProperties& _rProps + ) : connectivity::sdbcx::OKey(_Name,_rProps,sal_True) + ,m_pTable(_pTable) +{ + construct(); + refreshColumns(); +} +// ------------------------------------------------------------------------- +void OTableKeyHelper::refreshColumns() +{ + if ( !m_pTable ) + return; + + ::std::vector< ::rtl::OUString> aVector; + if ( !isNew() ) + { + aVector = m_aProps->m_aKeyColumnNames; + if ( aVector.empty() ) + { + ::dbtools::OPropertyMap& rPropMap = OMetaConnection::getPropMap(); + ::rtl::OUString aSchema,aTable; + m_pTable->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_SCHEMANAME)) >>= aSchema; + m_pTable->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_NAME)) >>= aTable; + + if ( m_Name.getLength() ) // foreign key + { + + Reference< XResultSet > xResult = m_pTable->getMetaData()->getImportedKeys(m_pTable->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_CATALOGNAME)), + aSchema,aTable); + + if ( xResult.is() ) + { + Reference< XRow > xRow(xResult,UNO_QUERY); + while( xResult->next() ) + { + ::rtl::OUString aForeignKeyColumn = xRow->getString(8); + if(xRow->getString(12) == m_Name) + aVector.push_back(aForeignKeyColumn); + } + } + } + + if ( aVector.empty() ) + { + const Reference< XResultSet > xResult = m_pTable->getMetaData()->getPrimaryKeys(m_pTable->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_CATALOGNAME)), + aSchema,aTable); + + if ( xResult.is() ) + { + const Reference< XRow > xRow(xResult,UNO_QUERY); + while( xResult->next() ) + aVector.push_back(xRow->getString(4)); + } // if ( xResult.is() ) + } + } + } + + + if ( m_pColumns ) + m_pColumns ->reFill(aVector); + else + m_pColumns = new OKeyColumnsHelper(this,m_aMutex,aVector); +} +// ----------------------------------------------------------------------------- + diff --git a/connectivity/source/commontools/TKeyColumns.cxx b/connectivity/source/commontools/TKeyColumns.cxx new file mode 100644 index 000000000000..18cb7cef14dd --- /dev/null +++ b/connectivity/source/commontools/TKeyColumns.cxx @@ -0,0 +1,145 @@ +/************************************************************************* + * + * 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 "connectivity/TKeyColumns.hxx" +#include "connectivity/sdbcx/VKeyColumn.hxx" +#include <com/sun/star/sdbc/XRow.hpp> +#include <com/sun/star/sdbc/XResultSet.hpp> +#include <com/sun/star/sdbc/DataType.hpp> +#include <com/sun/star/sdbc/ColumnValue.hpp> +#include <comphelper/extract.hxx> +#include <comphelper/property.hxx> +#include "TConnection.hxx" +#include "connectivity/TTableHelper.hxx" + +using namespace connectivity; +using namespace connectivity::sdbcx; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::beans; +// using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::lang; + +// ------------------------------------------------------------------------- +OKeyColumnsHelper::OKeyColumnsHelper( OTableKeyHelper* _pKey, + ::osl::Mutex& _rMutex, + const ::std::vector< ::rtl::OUString> &_rVector) + : connectivity::sdbcx::OCollection(*_pKey,sal_True,_rMutex,_rVector) + ,m_pKey(_pKey) +{ +} +// ------------------------------------------------------------------------- +sdbcx::ObjectType OKeyColumnsHelper::createObject(const ::rtl::OUString& _rName) +{ + ::dbtools::OPropertyMap& rPropMap = OMetaConnection::getPropMap(); + ::rtl::OUString aSchema,aTable; + m_pKey->getTable()->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_SCHEMANAME)) >>= aSchema; + m_pKey->getTable()->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_NAME)) >>= aTable; + + // frist get the related column to _rName + Reference< XResultSet > xResult = m_pKey->getTable()->getMetaData()->getImportedKeys( + m_pKey->getTable()->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_CATALOGNAME)),aSchema,aTable); + + ::rtl::OUString aRefColumnName; + if ( xResult.is() ) + { + Reference< XRow > xRow(xResult,UNO_QUERY); + ::rtl::OUString aTemp; + while(xResult->next()) + { + aTemp = xRow->getString(4); + if(xRow->getString(8) == _rName && m_pKey->getName() == xRow->getString(12)) + { + aRefColumnName = aTemp; + break; + } + } + } + + sdbcx::ObjectType xRet; + + // now describe the column _rName and set his related column + xResult = m_pKey->getTable()->getMetaData()->getColumns( + m_pKey->getTable()->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_CATALOGNAME)),aSchema,aTable,_rName); + + if ( xResult.is() ) + { + Reference< XRow > xRow(xResult,UNO_QUERY); + if ( xResult->next() ) + { + if ( xRow->getString(4) == _rName ) + { + sal_Int32 nDataType = xRow->getInt(5); + ::rtl::OUString aTypeName(xRow->getString(6)); + sal_Int32 nSize = xRow->getInt(7); + sal_Int32 nDec = xRow->getInt(9); + sal_Int32 nNull = xRow->getInt(11); + ::rtl::OUString sColumnDef; + try + { + sColumnDef = xRow->getString(13); + } + catch(const SQLException&) + { + // somethimes we get an error when asking for this param + } + + OKeyColumn* pRet = new OKeyColumn(aRefColumnName, + _rName, + aTypeName, + sColumnDef, + nNull, + nSize, + nDec, + nDataType, + sal_False, + sal_False, + sal_False, + isCaseSensitive()); + xRet = pRet; + } + } + } + + return xRet; +} +// ------------------------------------------------------------------------- +Reference< XPropertySet > OKeyColumnsHelper::createDescriptor() +{ + return new OKeyColumn(isCaseSensitive()); +} +// ------------------------------------------------------------------------- +void OKeyColumnsHelper::impl_refresh() throw(::com::sun::star::uno::RuntimeException) +{ + m_pKey->refreshColumns(); +} +// ----------------------------------------------------------------------------- + + diff --git a/connectivity/source/commontools/TKeys.cxx b/connectivity/source/commontools/TKeys.cxx new file mode 100644 index 000000000000..c4d5dfbf20e0 --- /dev/null +++ b/connectivity/source/commontools/TKeys.cxx @@ -0,0 +1,320 @@ +/************************************************************************* + * + * 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 "connectivity/TKeys.hxx" +#include "connectivity/TKey.hxx" +#include <com/sun/star/sdbc/XRow.hpp> +#include <com/sun/star/sdbc/XResultSet.hpp> +#include <com/sun/star/sdbcx/KeyType.hpp> +#include <com/sun/star/sdbc/KeyRule.hpp> +#include "connectivity/dbtools.hxx" +#include <comphelper/extract.hxx> +#include <comphelper/types.hxx> +#include <comphelper/property.hxx> +#include "TConnection.hxx" + +namespace connectivity +{ +using namespace comphelper; +using namespace connectivity::sdbcx; +using namespace dbtools; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::lang; + + + +OKeysHelper::OKeysHelper( OTableHelper* _pTable, + ::osl::Mutex& _rMutex, + const TStringVector& _rVector + ) : OKeys_BASE(*_pTable,sal_True,_rMutex,_rVector,sal_True) + ,m_pTable(_pTable) +{ +} +// ------------------------------------------------------------------------- +sdbcx::ObjectType OKeysHelper::createObject(const ::rtl::OUString& _rName) +{ + sdbcx::ObjectType xRet = NULL; + + if(_rName.getLength()) + { + OTableKeyHelper* pRet = new OTableKeyHelper(m_pTable,_rName,m_pTable->getKeyProperties(_rName)); + xRet = pRet; + } + + if(!xRet.is()) // we have a primary key with a system name + { + OTableKeyHelper* pRet = new OTableKeyHelper(m_pTable,_rName,m_pTable->getKeyProperties(_rName)); + xRet = pRet; + } + + return xRet; +} +// ------------------------------------------------------------------------- +void OKeysHelper::impl_refresh() throw(RuntimeException) +{ + m_pTable->refreshKeys(); +} +// ------------------------------------------------------------------------- +Reference< XPropertySet > OKeysHelper::createDescriptor() +{ + return new OTableKeyHelper(m_pTable); +} +// ----------------------------------------------------------------------------- +/** returns the keyrule string for the primary key +*/ +::rtl::OUString getKeyRuleString(sal_Bool _bUpdate,sal_Int32 _nKeyRule) +{ + const char* pKeyRule = NULL; + switch ( _nKeyRule ) + { + case KeyRule::CASCADE: + pKeyRule = _bUpdate ? " ON UPDATE CASCADE " : " ON DELETE CASCADE "; + break; + case KeyRule::RESTRICT: + pKeyRule = _bUpdate ? " ON UPDATE RESTRICT " : " ON DELETE RESTRICT "; + break; + case KeyRule::SET_NULL: + pKeyRule = _bUpdate ? " ON UPDATE SET NULL " : " ON DELETE SET NULL "; + break; + case KeyRule::SET_DEFAULT: + pKeyRule = _bUpdate ? " ON UPDATE SET DEFAULT " : " ON DELETE SET DEFAULT "; + break; + default: + ; + } + ::rtl::OUString sRet; + if ( pKeyRule ) + sRet = ::rtl::OUString::createFromAscii(pKeyRule); + return sRet; +} +// ------------------------------------------------------------------------- +void OKeysHelper::cloneDescriptorColumns( const sdbcx::ObjectType& _rSourceDescriptor, const sdbcx::ObjectType& _rDestDescriptor ) +{ + Reference< XColumnsSupplier > xColSupp( _rSourceDescriptor, UNO_QUERY_THROW ); + Reference< XIndexAccess > xSourceCols( xColSupp->getColumns(), UNO_QUERY_THROW ); + + xColSupp.set( _rDestDescriptor, UNO_QUERY_THROW ); + Reference< XAppend > xDestAppend( xColSupp->getColumns(), UNO_QUERY_THROW ); + + sal_Int32 nCount = xSourceCols->getCount(); + for ( sal_Int32 i=0; i< nCount; ++i ) + { + Reference< XPropertySet > xColProp( xSourceCols->getByIndex(i), UNO_QUERY ); + xDestAppend->appendByDescriptor( xColProp ); + } +} +// ------------------------------------------------------------------------- +// XAppend +sdbcx::ObjectType OKeysHelper::appendObject( const ::rtl::OUString& _rForName, const Reference< XPropertySet >& descriptor ) +{ + Reference< XConnection> xConnection = m_pTable->getConnection(); + if ( !xConnection.is() ) + return NULL; + if ( m_pTable->isNew() ) + { + Reference< XPropertySet > xNewDescriptor( cloneDescriptor( descriptor ) ); + cloneDescriptorColumns( descriptor, xNewDescriptor ); + return xNewDescriptor; + } + + const ::dbtools::OPropertyMap& rPropMap = OMetaConnection::getPropMap(); + sal_Int32 nKeyType = getINT32(descriptor->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_TYPE))); + sal_Int32 nUpdateRule = 0, nDeleteRule = 0; + ::rtl::OUString sReferencedName; + + if ( nKeyType == KeyType::FOREIGN ) + { + descriptor->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_REFERENCEDTABLE)) >>= sReferencedName; + descriptor->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_UPDATERULE)) >>= nUpdateRule; + descriptor->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_DELETERULE)) >>= nDeleteRule; + } + + if ( m_pTable->getKeyService().is() ) + { + m_pTable->getKeyService()->addKey(m_pTable,descriptor); + } + else + { + // if we're here, we belong to a table which is not new, i.e. already exists in the database. + // In this case, really append the new index. + ::rtl::OUStringBuffer aSql; + aSql.appendAscii("ALTER TABLE "); + ::rtl::OUString aQuote = m_pTable->getConnection()->getMetaData()->getIdentifierQuoteString( ); + ::rtl::OUString aDot = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(".")); + + aSql.append(composeTableName( m_pTable->getConnection()->getMetaData(), m_pTable, ::dbtools::eInTableDefinitions, false, false, true )); + aSql.appendAscii(" ADD "); + + if ( nKeyType == KeyType::PRIMARY ) + { + aSql.appendAscii(" PRIMARY KEY ("); + } + else if ( nKeyType == KeyType::FOREIGN ) + { + aSql.appendAscii(" FOREIGN KEY ("); + } + else + throw SQLException(); + + Reference<XColumnsSupplier> xColumnSup(descriptor,UNO_QUERY); + Reference<XIndexAccess> xColumns(xColumnSup->getColumns(),UNO_QUERY); + Reference< XPropertySet > xColProp; + for(sal_Int32 i = 0 ; i < xColumns->getCount() ; ++i) + { + if ( i > 0 ) + aSql.appendAscii(","); + ::cppu::extractInterface(xColProp,xColumns->getByIndex(i)); + aSql.append( ::dbtools::quoteName( aQuote,getString(xColProp->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_NAME)))) ); + + } + aSql.appendAscii(")"); + + if ( nKeyType == KeyType::FOREIGN ) + { + aSql.appendAscii(" REFERENCES "); + aSql.append(::dbtools::quoteTableName(m_pTable->getConnection()->getMetaData(),sReferencedName,::dbtools::eInTableDefinitions)); + aSql.appendAscii(" ("); + + for(sal_Int32 i=0;i<xColumns->getCount();++i) + { + if ( i > 0 ) + aSql.appendAscii(","); + xColumns->getByIndex(i) >>= xColProp; + aSql.append(::dbtools::quoteName( aQuote,getString(xColProp->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_RELATEDCOLUMN))))); + + } + aSql.appendAscii(")"); + aSql.append(getKeyRuleString(sal_True ,nUpdateRule)); + aSql.append(getKeyRuleString(sal_False ,nDeleteRule)); + } + + Reference< XStatement > xStmt = m_pTable->getConnection()->createStatement( ); + xStmt->execute(aSql.makeStringAndClear()); + } + // find the name which the database gave the new key + ::rtl::OUString sNewName( _rForName ); + try + { + ::rtl::OUString aSchema,aTable; + m_pTable->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_SCHEMANAME)) >>= aSchema; + m_pTable->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_NAME)) >>= aTable; + Reference< XResultSet > xResult; + sal_Int32 nColumn = 12; + if ( nKeyType == KeyType::FOREIGN ) + xResult = m_pTable->getMetaData()->getImportedKeys( m_pTable->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_CATALOGNAME)) + ,aSchema + ,aTable); + else + { + xResult = m_pTable->getMetaData()->getPrimaryKeys( m_pTable->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_CATALOGNAME)) + ,aSchema + ,aTable); + nColumn = 6; + } + if ( xResult.is() ) + { + Reference< XRow > xRow(xResult,UNO_QUERY); + while( xResult->next() ) + { + ::rtl::OUString sName = xRow->getString(nColumn); + if ( !m_pElements->exists(sName) ) // this name wasn't inserted yet so it must be te new one + { + descriptor->setPropertyValue( rPropMap.getNameByIndex( PROPERTY_ID_NAME ), makeAny( sName ) ); + sNewName = sName; + break; + } + } + ::comphelper::disposeComponent(xResult); + } + } + catch(const SQLException&) + { + } + + m_pTable->addKey(sNewName,sdbcx::TKeyProperties(new sdbcx::KeyProperties(sReferencedName,nKeyType,nUpdateRule,nDeleteRule))); + + return createObject( sNewName ); +} +// ----------------------------------------------------------------------------- +::rtl::OUString OKeysHelper::getDropForeignKey() const +{ + return ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" DROP CONSTRAINT ")); +} +// ------------------------------------------------------------------------- +// XDrop +void OKeysHelper::dropObject(sal_Int32 _nPos,const ::rtl::OUString _sElementName) +{ + Reference< XConnection> xConnection = m_pTable->getConnection(); + if ( xConnection.is() && !m_pTable->isNew() ) + { + Reference<XPropertySet> xKey(getObject(_nPos),UNO_QUERY); + if ( m_pTable->getKeyService().is() ) + { + m_pTable->getKeyService()->dropKey(m_pTable,xKey); + } + else + { + ::rtl::OUStringBuffer aSql; + aSql.appendAscii("ALTER TABLE "); + + aSql.append( composeTableName( m_pTable->getConnection()->getMetaData(), m_pTable,::dbtools::eInTableDefinitions, false, false, true )); + + sal_Int32 nKeyType = KeyType::PRIMARY; + if ( xKey.is() ) + { + ::dbtools::OPropertyMap& rPropMap = OMetaConnection::getPropMap(); + xKey->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_TYPE)) >>= nKeyType; + } + if ( KeyType::PRIMARY == nKeyType ) + { + aSql.appendAscii(" DROP PRIMARY KEY"); + } + else + { + aSql.append(getDropForeignKey()); + const ::rtl::OUString aQuote = m_pTable->getConnection()->getMetaData()->getIdentifierQuoteString(); + aSql.append( ::dbtools::quoteName( aQuote,_sElementName) ); + } + + Reference< XStatement > xStmt = m_pTable->getConnection()->createStatement( ); + if ( xStmt.is() ) + { + xStmt->execute(aSql.makeStringAndClear()); + ::comphelper::disposeComponent(xStmt); + } + } + } +} +// ----------------------------------------------------------------------------- +} // namespace connectivity +// ----------------------------------------------------------------------------- diff --git a/connectivity/source/commontools/TPrivilegesResultSet.cxx b/connectivity/source/commontools/TPrivilegesResultSet.cxx new file mode 100644 index 000000000000..a7e76f643bfe --- /dev/null +++ b/connectivity/source/commontools/TPrivilegesResultSet.cxx @@ -0,0 +1,155 @@ +/************************************************************************* + * + * 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 "TPrivilegesResultSet.hxx" + +using namespace connectivity; +//------------------------------------------------------------------------------ +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::lang; +//------------------------------------------------------------------------------ +OResultSetPrivileges::OResultSetPrivileges( const Reference< XDatabaseMetaData>& _rxMeta + , const Any& catalog + , const ::rtl::OUString& schemaPattern + , const ::rtl::OUString& tableNamePattern) + : ODatabaseMetaDataResultSet(eTablePrivileges) + , m_bResetValues(sal_True) +{ + osl_incrementInterlockedCount( &m_refCount ); + { + ::rtl::OUString sUserWorkingFor; + static Sequence< ::rtl::OUString > sTableTypes; + if ( sTableTypes.getLength() == 0 ) + { + // we want all catalogues, all schemas, all tables + sTableTypes.realloc(3); + sTableTypes[0] = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("VIEW")); + sTableTypes[1] = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("TABLE")); + sTableTypes[2] = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("%")); // just to be sure to include anything else .... + } + try + { + m_xTables = _rxMeta->getTables(catalog,schemaPattern,tableNamePattern,sTableTypes); + m_xRow = Reference< XRow>(m_xTables,UNO_QUERY); + + sUserWorkingFor = _rxMeta->getUserName(); + } + catch(Exception&) + { + } + + ODatabaseMetaDataResultSet::ORows aRows; + static ODatabaseMetaDataResultSet::ORow aRow(8); + aRow[5] = new ORowSetValueDecorator(sUserWorkingFor); + aRow[6] = ODatabaseMetaDataResultSet::getSelectValue(); + aRow[7] = new ORowSetValueDecorator(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("YES"))); + aRows.push_back(aRow); + aRow[6] = ODatabaseMetaDataResultSet::getInsertValue(); + aRows.push_back(aRow); + aRow[6] = ODatabaseMetaDataResultSet::getDeleteValue(); + aRows.push_back(aRow); + aRow[6] = ODatabaseMetaDataResultSet::getUpdateValue(); + aRows.push_back(aRow); + aRow[6] = ODatabaseMetaDataResultSet::getCreateValue(); + aRows.push_back(aRow); + aRow[6] = ODatabaseMetaDataResultSet::getReadValue(); + aRows.push_back(aRow); + aRow[6] = ODatabaseMetaDataResultSet::getAlterValue(); + aRows.push_back(aRow); + aRow[6] = ODatabaseMetaDataResultSet::getDropValue(); + aRows.push_back(aRow); + aRow[6] = new ORowSetValueDecorator(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("REFERENCE"))); + aRows.push_back(aRow); + + setRows(aRows); + } + osl_decrementInterlockedCount( &m_refCount ); +} +//------------------------------------------------------------------------------ +const ORowSetValue& OResultSetPrivileges::getValue(sal_Int32 columnIndex) +{ + switch(columnIndex) + { + case 1: + case 2: + case 3: + if ( m_xRow.is() && m_bResetValues ) + { + (*m_aRowsIter)[1] = new ORowSetValueDecorator(m_xRow->getString(1)); + if ( m_xRow->wasNull() ) + (*m_aRowsIter)[1]->setNull(); + (*m_aRowsIter)[2] = new ORowSetValueDecorator(m_xRow->getString(2)); + if ( m_xRow->wasNull() ) + (*m_aRowsIter)[2]->setNull(); + (*m_aRowsIter)[3] = new ORowSetValueDecorator(m_xRow->getString(3)); + if ( m_xRow->wasNull() ) + (*m_aRowsIter)[3]->setNull(); + + m_bResetValues = sal_False; + } + } + return ODatabaseMetaDataResultSet::getValue(columnIndex); +} +// ----------------------------------------------------------------------------- +void SAL_CALL OResultSetPrivileges::disposing(void) +{ + ODatabaseMetaDataResultSet::disposing(); +m_xTables.clear(); +m_xRow.clear(); +} +// ----------------------------------------------------------------------------- +sal_Bool SAL_CALL OResultSetPrivileges::next( ) throw(SQLException, RuntimeException) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(ODatabaseMetaDataResultSet_BASE::rBHelper.bDisposed ); + + sal_Bool bReturn = sal_False; + if ( m_xTables.is() ) + { + if ( m_bBOF ) + { + m_bResetValues = sal_True; + if ( !m_xTables->next() ) + return sal_False; + } + + bReturn = ODatabaseMetaDataResultSet::next(); + if ( !bReturn ) + { + m_bBOF = sal_False; + m_bResetValues = bReturn = m_xTables->next(); + } + } + return bReturn; +} +// ----------------------------------------------------------------------------- diff --git a/connectivity/source/commontools/TSkipDeletedSet.cxx b/connectivity/source/commontools/TSkipDeletedSet.cxx new file mode 100644 index 000000000000..2d144ab72941 --- /dev/null +++ b/connectivity/source/commontools/TSkipDeletedSet.cxx @@ -0,0 +1,278 @@ +/************************************************************************* + * + * 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 "TSkipDeletedSet.hxx" +#include <osl/diagnose.h> +#include <rtl/logfile.hxx> + +using namespace connectivity; +// ----------------------------------------------------------------------------- +OSkipDeletedSet::OSkipDeletedSet(IResultSetHelper* _pHelper) + : m_pHelper(_pHelper) + ,m_bDeletedVisible(false) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "commontools", "Ocke.Janssen@sun.com", "OSkipDeletedSet::OSkipDeletedSet" ); + m_aBookmarksPositions.reserve(256); +} +// ----------------------------------------------------------------------------- +OSkipDeletedSet::~OSkipDeletedSet() +{ + m_aBookmarksPositions.clear(); + //m_aBookmarks.clear(); +} +// ----------------------------------------------------------------------------- +sal_Bool OSkipDeletedSet::skipDeleted(IResultSetHelper::Movement _eCursorPosition, sal_Int32 _nOffset, sal_Bool _bRetrieveData) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "commontools", "Ocke.Janssen@sun.com", "OSkipDeletedSet::skipDeleted" ); + OSL_ENSURE(_eCursorPosition != IResultSetHelper::BOOKMARK,"OSkipDeletedSet::SkipDeleted can't be called for BOOKMARK"); + + IResultSetHelper::Movement eDelPosition = _eCursorPosition; + sal_Int32 nDelOffset = abs(_nOffset); + + switch (_eCursorPosition) + { + case IResultSetHelper::ABSOLUTE: + return moveAbsolute(_nOffset,_bRetrieveData); + case IResultSetHelper::FIRST: // set the movement when positioning failed + eDelPosition = IResultSetHelper::NEXT; + nDelOffset = 1; + break; + case IResultSetHelper::LAST: + eDelPosition = IResultSetHelper::PRIOR; // lsat row is invalid so position before + nDelOffset = 1; + break; + case IResultSetHelper::RELATIVE: + eDelPosition = (_nOffset >= 0) ? IResultSetHelper::NEXT : IResultSetHelper::PRIOR; + break; + default: + break; + } + + sal_Bool bDone = sal_True; + sal_Bool bDataFound = sal_False; + + if (_eCursorPosition == IResultSetHelper::LAST) + { + RTL_LOGFILE_CONTEXT_TRACE( aLogger, "OSkipDeletedSet::skipDeleted: last" ); + sal_Int32 nBookmark = 0; + // first position on the last known row + if ( m_aBookmarksPositions.empty() ) + { + bDataFound = m_pHelper->move(IResultSetHelper::FIRST, 0, _bRetrieveData); + if(bDataFound && (m_bDeletedVisible || !m_pHelper->isRowDeleted())) + //m_aBookmarksPositions.push_back(m_aBookmarks.insert(TInt2IntMap::value_type(m_pHelper->getDriverPos(),m_aBookmarksPositions.size()+1)).first); + m_aBookmarksPositions.push_back(m_pHelper->getDriverPos()); + } + else + { + // I already have a bookmark so we can positioned on that and look if it is the last one + nBookmark = (*m_aBookmarksPositions.rbegin())/*->first*/; + + bDataFound = m_pHelper->move(IResultSetHelper::BOOKMARK, nBookmark, _bRetrieveData); + OSL_ENSURE((m_bDeletedVisible || !m_pHelper->isRowDeleted()),"A bookmark should not be deleted!"); + } + + + // and than move forward until we are after the last row + while(bDataFound) + { + bDataFound = m_pHelper->move(IResultSetHelper::NEXT, 1, sal_False); // we don't need the data here + if( bDataFound && ( m_bDeletedVisible || !m_pHelper->isRowDeleted()) ) + { // we weren't on the last row we remember it and move on + m_aBookmarksPositions.push_back(m_pHelper->getDriverPos()); + //m_aBookmarksPositions.push_back(m_aBookmarks.insert(TInt2IntMap::value_type(m_pHelper->getDriverPos(),m_aBookmarksPositions.size()+1)).first); + } + else if(!bDataFound && !m_aBookmarksPositions.empty() ) + { + // i already know the last bookmark :-) + // now we only have to repositioning us to the last row + nBookmark = (*m_aBookmarksPositions.rbegin())/*->first*/; + bDataFound = m_pHelper->move(IResultSetHelper::BOOKMARK, nBookmark, _bRetrieveData); + break; + } + } + return bDataFound; + } + else if (_eCursorPosition != IResultSetHelper::RELATIVE) + { + bDataFound = m_pHelper->move(_eCursorPosition, _nOffset, _bRetrieveData); + bDone = bDataFound && (m_bDeletedVisible || !m_pHelper->isRowDeleted()); + } + else + { + bDataFound = m_pHelper->move(eDelPosition, 1, _bRetrieveData); + if (bDataFound && (m_bDeletedVisible || !m_pHelper->isRowDeleted())) + { + bDone = (--nDelOffset) == 0; + if ( !bDone ) + m_aBookmarksPositions.push_back(m_pHelper->getDriverPos()); + //m_aBookmarksPositions.push_back(m_aBookmarks.insert(TInt2IntMap::value_type(m_pHelper->getDriverPos(),m_aBookmarksPositions.size()+1)).first); + } + else + bDone = sal_False; + } + + while (bDataFound && !bDone) // solange iterieren bis man auf einem gueltigen Satz ist + { + bDataFound = m_pHelper->move(eDelPosition, 1, _bRetrieveData); + if (_eCursorPosition != IResultSetHelper::RELATIVE) + bDone = bDataFound && (m_bDeletedVisible || !m_pHelper->isRowDeleted()); + else if (bDataFound && (m_bDeletedVisible || !m_pHelper->isRowDeleted())) + { + bDone = (--nDelOffset) == 0; + if ( !bDone ) + m_aBookmarksPositions.push_back(m_pHelper->getDriverPos()); + //m_aBookmarksPositions.push_back(m_aBookmarks.insert(TInt2IntMap::value_type(m_pHelper->getDriverPos(),m_aBookmarksPositions.size()+1)).first); + } + else + bDone = sal_False; + } + + if(bDataFound && bDone ) + { + const sal_Int32 nDriverPos = m_pHelper->getDriverPos(); + if ( ::std::find(m_aBookmarksPositions.begin(),m_aBookmarksPositions.end(),nDriverPos) == m_aBookmarksPositions.end() ) + m_aBookmarksPositions.push_back(nDriverPos); + /*sal_Int32 nDriverPos = m_pHelper->getDriverPos(); + if(m_aBookmarks.find(nDriverPos) == m_aBookmarks.end()) + m_aBookmarksPositions.push_back(m_aBookmarks.insert(TInt2IntMap::value_type(nDriverPos,m_aBookmarksPositions.size()+1)).first);*/ + } + + return bDataFound; +} +// ------------------------------------------------------------------------- +sal_Bool OSkipDeletedSet::moveAbsolute(sal_Int32 _nPos,sal_Bool _bRetrieveData) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "commontools", "Ocke.Janssen@sun.com", "OSkipDeletedSet::moveAbsolute" ); + sal_Bool bDataFound = sal_False; + sal_Int32 nNewPos = _nPos; + if(nNewPos > 0) + { + if((sal_Int32)m_aBookmarksPositions.size() < nNewPos) + { + // bookmark isn't known yet + // start at the last known position + sal_Int32 nCurPos = 0,nLastBookmark = 1; + if ( m_aBookmarksPositions.empty() ) + { + bDataFound = m_pHelper->move(IResultSetHelper::FIRST, 0, _bRetrieveData ); + if(bDataFound && (m_bDeletedVisible || !m_pHelper->isRowDeleted())) + { + ++nCurPos; + m_aBookmarksPositions.push_back(m_pHelper->getDriverPos()); + //m_aBookmarksPositions.push_back(m_aBookmarks.insert(TInt2IntMap::value_type(m_pHelper->getDriverPos(),m_aBookmarksPositions.size()+1)).first); + --nNewPos; + } + } // if ( m_aBookmarksPositions.empty() ) + else + { + nLastBookmark = (*m_aBookmarksPositions.rbegin())/*->first*/; + nCurPos = /*(**/m_aBookmarksPositions.size()/*->second*/; + nNewPos = nNewPos - nCurPos; + bDataFound = m_pHelper->move(IResultSetHelper::BOOKMARK, nLastBookmark, _bRetrieveData); + } + + // now move to that row we need and don't count deleted rows + while (bDataFound && nNewPos) + { + bDataFound = m_pHelper->move(IResultSetHelper::NEXT, 1, _bRetrieveData); + if(bDataFound && (m_bDeletedVisible || !m_pHelper->isRowDeleted())) + { + ++nCurPos; + m_aBookmarksPositions.push_back(m_pHelper->getDriverPos()); + //m_aBookmarksPositions.push_back(m_aBookmarks.insert(TInt2IntMap::value_type(m_pHelper->getDriverPos(),m_aBookmarksPositions.size()+1)).first); + --nNewPos; + } + } + } + else + { + const sal_Int32 nBookmark = m_aBookmarksPositions[nNewPos-1]/*->first*/; + bDataFound = m_pHelper->move(IResultSetHelper::BOOKMARK,nBookmark, _bRetrieveData); + OSL_ENSURE((m_bDeletedVisible || !m_pHelper->isRowDeleted()),"moveAbsolute: row can't be deleted!"); + } + } + else + { + ++nNewPos; + bDataFound = skipDeleted(IResultSetHelper::LAST,0,nNewPos == 0); + + for(sal_Int32 i=nNewPos+1;bDataFound && i <= 0;++i) + bDataFound = skipDeleted(IResultSetHelper::PRIOR,1,i == 0); + + } + return bDataFound; +} +// ----------------------------------------------------------------------------- +void OSkipDeletedSet::clear() +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "commontools", "Ocke.Janssen@sun.com", "OSkipDeletedSet::clear" ); + ::std::vector<sal_Int32>().swap(m_aBookmarksPositions); + //TInt2IntMap().swap(m_aBookmarks); +} +// ----------------------------------------------------------------------------- +sal_Int32 OSkipDeletedSet::getMappedPosition(sal_Int32 _nPos) const +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "commontools", "Ocke.Janssen@sun.com", "OSkipDeletedSet::getMappedPosition" ); + ::std::vector<sal_Int32>::const_iterator aFind = ::std::find(m_aBookmarksPositions.begin(),m_aBookmarksPositions.end(),_nPos); + if ( aFind != m_aBookmarksPositions.end() ) + return (aFind - m_aBookmarksPositions.begin()) + 1; + /*TInt2IntMap::const_iterator aFind = m_aBookmarks.find(_nPos); + OSL_ENSURE(aFind != m_aBookmarks.end(),"OSkipDeletedSet::getMappedPosition() invalid bookmark!"); + return aFind->second;*/ + OSL_ENSURE(0,"Why!"); + return -1; +} +// ----------------------------------------------------------------------------- +void OSkipDeletedSet::insertNewPosition(sal_Int32 _nPos) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "commontools", "Ocke.Janssen@sun.com", "OSkipDeletedSet::insertNewPosition" ); + //OSL_ENSURE(m_aBookmarks.find(_nPos) == m_aBookmarks.end(),"OSkipDeletedSet::insertNewPosition: Invalid position"); + //m_aBookmarksPositions.push_back(m_aBookmarks.insert(TInt2IntMap::value_type(_nPos,m_aBookmarksPositions.size()+1)).first); + //OSL_ENSURE(::std::find(m_aBookmarksPositions.begin(),m_aBookmarksPositions.end(),_nPos) == m_aBookmarksPositions.end(),"Invalid driver pos"); + m_aBookmarksPositions.push_back(_nPos); +} +// ----------------------------------------------------------------------------- +void OSkipDeletedSet::deletePosition(sal_Int32 _nBookmark) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "commontools", "Ocke.Janssen@sun.com", "OSkipDeletedSet::deletePosition" ); + ::std::vector<sal_Int32>::iterator aFind = ::std::find(m_aBookmarksPositions.begin(),m_aBookmarksPositions.end(),_nBookmark); + if ( aFind != m_aBookmarksPositions.end() ) + { + //TInt2IntMap::iterator aFind = m_aBookmarks.find(_nPos); + //OSL_ENSURE(aFind != m_aBookmarks.end(),"OSkipDeletedSet::deletePosition() bookmark not found!"); + //TInt2IntMap::iterator aIter = aFind; + m_aBookmarksPositions.erase(aFind); + //for (; aFind != m_aBookmarksPositions.end() ; ++aIter) + // --(aFind->second); + } // if ( aFind != m_aBookmarksPositions.end() ) + //m_aBookmarksPositions.erase(m_aBookmarksPositions.begin() + aFind->second-1); + //m_aBookmarks.erase(_nPos); +} +// ----------------------------------------------------------------------------- diff --git a/connectivity/source/commontools/TSortIndex.cxx b/connectivity/source/commontools/TSortIndex.cxx new file mode 100644 index 000000000000..c69ff0b89de1 --- /dev/null +++ b/connectivity/source/commontools/TSortIndex.cxx @@ -0,0 +1,178 @@ +/************************************************************************* + * + * 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 "TSortIndex.hxx" +#include <algorithm> +#include <functional> + +using namespace connectivity; +//------------------------------------------------------------------ +/// binary_function Functor object for class OSortIndex::TIntValuePairVector::value_type returntype is bool +struct TKeyValueFunc : ::std::binary_function<OSortIndex::TIntValuePairVector::value_type,OSortIndex::TIntValuePairVector::value_type,bool> +{ + OSortIndex* pIndex; + + TKeyValueFunc(OSortIndex* _pIndex) : pIndex(_pIndex) + { + } + // return false if compared values are equal otherwise true + inline bool operator()(const OSortIndex::TIntValuePairVector::value_type& lhs,const OSortIndex::TIntValuePairVector::value_type& rhs) const + { + const ::std::vector<OKeyType>& aKeyType = pIndex->getKeyType(); + ::std::vector<OKeyType>::const_iterator aIter = aKeyType.begin(); + for (::std::vector<sal_Int16>::size_type i=0;aIter != aKeyType.end(); ++aIter,++i) + { + const bool nGreater = (pIndex->getAscending(i) == SQL_ASC) ? false : true; + const bool nLess = !nGreater; + + // compare depending for type + switch (*aIter) + { + case SQL_ORDERBYKEY_STRING: + { + sal_Int32 nRes = lhs.second->getKeyString(i).compareTo(rhs.second->getKeyString(i)); + if (nRes < 0) + return nLess; + else if (nRes > 0) + return nGreater; + } + break; + case SQL_ORDERBYKEY_DOUBLE: + { + double d1 = lhs.second->getKeyDouble(i); + double d2 = rhs.second->getKeyDouble(i); + + if (d1 < d2) + return nLess; + else if (d1 > d2) + return nGreater; + } + break; + case SQL_ORDERBYKEY_NONE: + break; + } + } + + // know we know that the values are equal + return false; + } +}; + +// ----------------------------------------------------------------------------- +::vos::ORef<OKeySet> OSortIndex::CreateKeySet() +{ + Freeze(); + + ::vos::ORef<OKeySet> pKeySet = new OKeySet(); + pKeySet->get().reserve(m_aKeyValues.size()); + ::std::transform(m_aKeyValues.begin() + ,m_aKeyValues.end() + ,::std::back_inserter(pKeySet->get()) + ,::std::select1st<TIntValuePairVector::value_type>()); + pKeySet->setFrozen(); + return pKeySet; +} +// ----------------------------------------------------------------------------- +OSortIndex::OSortIndex( const ::std::vector<OKeyType>& _aKeyType, + const ::std::vector<TAscendingOrder>& _aAscending) + :m_aKeyType(_aKeyType) + ,m_aAscending(_aAscending) + ,m_bFrozen(sal_False) +{ +} +//------------------------------------------------------------------ +OSortIndex::~OSortIndex() +{ +} +//------------------------------------------------------------------ +void OSortIndex::AddKeyValue(OKeyValue * pKeyValue) +{ + OSL_ENSURE(pKeyValue,"Can not be null here!"); + if(m_bFrozen) + { + m_aKeyValues.push_back(TIntValuePairVector::value_type(pKeyValue->getValue(),NULL)); + delete pKeyValue; + } + else + m_aKeyValues.push_back(TIntValuePairVector::value_type(pKeyValue->getValue(),pKeyValue)); +} + + +//------------------------------------------------------------------ +void OSortIndex::Freeze() +{ + OSL_ENSURE(! m_bFrozen,"OSortIndex::Freeze: already frozen!"); + // Sortierung: + if (m_aKeyType[0] != SQL_ORDERBYKEY_NONE) + // we will sort ourself when the first keyType say so + ::std::sort(m_aKeyValues.begin(),m_aKeyValues.end(),TKeyValueFunc(this)); + + TIntValuePairVector::iterator aIter = m_aKeyValues.begin(); + for(;aIter != m_aKeyValues.end();++aIter) + { + delete aIter->second; + aIter->second = NULL; + } + + m_bFrozen = sal_True; +} + +//------------------------------------------------------------------ +sal_Int32 OSortIndex::GetValue(sal_Int32 nPos) const +{ + OSL_ENSURE(nPos > 0,"OSortIndex::GetValue: nPos == 0"); + OSL_ENSURE((size_t)nPos <= m_aKeyValues.size(),"OSortIndex::GetValue: Zugriff ausserhalb der Array-Grenzen"); + + if (!m_bFrozen && m_aKeyType[0] != SQL_ORDERBYKEY_NONE) + { + OSL_ASSERT("OSortIndex::GetValue: Invalid use of index!"); + return 0; + } + return m_aKeyValues[nPos-1].first; +} +// ----------------------------------------------------------------------------- +OKeyValue::OKeyValue() +{ +} +// ----------------------------------------------------------------------------- +OKeyValue::OKeyValue(sal_Int32 nVal) +: m_nValue(nVal) +{ +} +// ----------------------------------------------------------------------------- +OKeyValue::~OKeyValue() +{ +} +// ----------------------------------------------------------------------------- +OKeyValue* OKeyValue::createKeyValue(sal_Int32 _nVal) +{ + return new OKeyValue(_nVal); +} +// ----------------------------------------------------------------------------- + diff --git a/connectivity/source/commontools/TTableHelper.cxx b/connectivity/source/commontools/TTableHelper.cxx new file mode 100644 index 000000000000..7d020e9fc4a6 --- /dev/null +++ b/connectivity/source/commontools/TTableHelper.cxx @@ -0,0 +1,630 @@ +/************************************************************************* + * + * 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 "connectivity/TTableHelper.hxx" +#include <com/sun/star/sdbc/XRow.hpp> +#include <com/sun/star/sdbc/XResultSet.hpp> +#include <com/sun/star/sdbcx/KeyType.hpp> +#include <com/sun/star/sdbc/KeyRule.hpp> +#include <cppuhelper/typeprovider.hxx> +#include <com/sun/star/lang/DisposedException.hpp> +#include <com/sun/star/sdbc/ColumnValue.hpp> +#include <comphelper/implementationreference.hxx> +#include <comphelper/sequence.hxx> +#include <comphelper/extract.hxx> +#include <comphelper/types.hxx> +#include "connectivity/dbtools.hxx" +#include "connectivity/sdbcx/VCollection.hxx" +#include <unotools/sharedunocomponent.hxx> +#include "TConnection.hxx" + +using namespace ::comphelper; +using namespace connectivity; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::lang; +namespace +{ + /// helper class for column property change events which holds the OComponentDefinition weak +typedef ::cppu::WeakImplHelper1 < XContainerListener > OTableContainerListener_BASE; +class OTableContainerListener : public OTableContainerListener_BASE +{ + OTableHelper* m_pComponent; + ::std::map< ::rtl::OUString,bool> m_aRefNames; + + OTableContainerListener(const OTableContainerListener&); + void operator =(const OTableContainerListener&); +protected: + virtual ~OTableContainerListener(){} +public: + OTableContainerListener(OTableHelper* _pComponent) : m_pComponent(_pComponent){} + virtual void SAL_CALL elementInserted( const ::com::sun::star::container::ContainerEvent& /*Event*/ ) throw (RuntimeException) + { + } + virtual void SAL_CALL elementRemoved( const ::com::sun::star::container::ContainerEvent& Event ) throw (RuntimeException) + { + ::rtl::OUString sName; + Event.Accessor >>= sName; + if ( m_aRefNames.find(sName) != m_aRefNames.end() ) + m_pComponent->refreshKeys(); + } + virtual void SAL_CALL elementReplaced( const ::com::sun::star::container::ContainerEvent& Event ) throw (RuntimeException) + { + ::rtl::OUString sOldComposedName,sNewComposedName; + Event.ReplacedElement >>= sOldComposedName; + Event.Accessor >>= sNewComposedName; + if ( sOldComposedName != sNewComposedName && m_aRefNames.find(sOldComposedName) != m_aRefNames.end() ) + m_pComponent->refreshKeys(); + } + // XEventListener + virtual void SAL_CALL disposing( const EventObject& /*_rSource*/ ) throw (RuntimeException) + { + } + void clear() { m_pComponent = NULL; } + inline void add(const ::rtl::OUString& _sRefName) { m_aRefNames.insert(::std::map< ::rtl::OUString,bool>::value_type(_sRefName,true)); } +}; +} +namespace connectivity +{ + ::rtl::OUString lcl_getServiceNameForSetting(const Reference< ::com::sun::star::sdbc::XConnection >& _xConnection,const ::rtl::OUString& i_sSetting) + { + ::rtl::OUString sSupportService; + Any aValue; + if ( ::dbtools::getDataSourceSetting(_xConnection,i_sSetting,aValue) ) + { + aValue >>= sSupportService; + } + return sSupportService; + } + struct OTableHelperImpl + { + TKeyMap m_aKeys; + // helper services which can be provided by extensions + Reference< ::com::sun::star::sdb::tools::XTableRename> m_xRename; + Reference< ::com::sun::star::sdb::tools::XTableAlteration> m_xAlter; + Reference< ::com::sun::star::sdb::tools::XKeyAlteration> m_xKeyAlter; + Reference< ::com::sun::star::sdb::tools::XIndexAlteration> m_xIndexAlter; + + Reference< ::com::sun::star::sdbc::XDatabaseMetaData > m_xMetaData; + Reference< ::com::sun::star::sdbc::XConnection > m_xConnection; + ::comphelper::ImplementationReference< OTableContainerListener,XContainerListener> + m_xTablePropertyListener; + ::std::vector< ColumnDesc > m_aColumnDesc; + OTableHelperImpl(const Reference< ::com::sun::star::sdbc::XConnection >& _xConnection) + : m_xConnection(_xConnection) + { + try + { + m_xMetaData = m_xConnection->getMetaData(); + Reference<XMultiServiceFactory> xFac(_xConnection,UNO_QUERY); + if ( xFac.is() ) + { + static const ::rtl::OUString s_sTableRename(RTL_CONSTASCII_USTRINGPARAM("TableRenameServiceName")); + m_xRename.set(xFac->createInstance(lcl_getServiceNameForSetting(m_xConnection,s_sTableRename)),UNO_QUERY); + static const ::rtl::OUString s_sTableAlteration(RTL_CONSTASCII_USTRINGPARAM("TableAlterationServiceName")); + m_xAlter.set(xFac->createInstance(lcl_getServiceNameForSetting(m_xConnection,s_sTableAlteration)),UNO_QUERY); + static const ::rtl::OUString s_sKeyAlteration(RTL_CONSTASCII_USTRINGPARAM("KeyAlterationServiceName")); + m_xKeyAlter.set(xFac->createInstance(lcl_getServiceNameForSetting(m_xConnection,s_sKeyAlteration)),UNO_QUERY); + static const ::rtl::OUString s_sIndexAlteration(RTL_CONSTASCII_USTRINGPARAM("IndexAlterationServiceName")); + m_xIndexAlter.set(xFac->createInstance(lcl_getServiceNameForSetting(m_xConnection,s_sIndexAlteration)),UNO_QUERY); + } + } + catch(const Exception&) + { + } + } + }; +} + +OTableHelper::OTableHelper( sdbcx::OCollection* _pTables, + const Reference< XConnection >& _xConnection, + sal_Bool _bCase) + :OTable_TYPEDEF(_pTables,_bCase) + ,m_pImpl(new OTableHelperImpl(_xConnection)) +{ +} +// ------------------------------------------------------------------------- +OTableHelper::OTableHelper( sdbcx::OCollection* _pTables, + const Reference< XConnection >& _xConnection, + sal_Bool _bCase, + const ::rtl::OUString& _Name, + const ::rtl::OUString& _Type, + const ::rtl::OUString& _Description , + const ::rtl::OUString& _SchemaName, + const ::rtl::OUString& _CatalogName + ) : OTable_TYPEDEF(_pTables, + _bCase, + _Name, + _Type, + _Description, + _SchemaName, + _CatalogName) + ,m_pImpl(new OTableHelperImpl(_xConnection)) +{ +} +// ----------------------------------------------------------------------------- +OTableHelper::~OTableHelper() +{ +} +// ----------------------------------------------------------------------------- +void SAL_CALL OTableHelper::disposing() +{ + ::osl::MutexGuard aGuard(m_aMutex); + if ( m_pImpl->m_xTablePropertyListener.is() ) + { + m_pTables->removeContainerListener(m_pImpl->m_xTablePropertyListener.getRef()); + m_pImpl->m_xTablePropertyListener->clear(); + m_pImpl->m_xTablePropertyListener.dispose(); + } + OTable_TYPEDEF::disposing(); + + m_pImpl->m_xConnection = NULL; + m_pImpl->m_xMetaData = NULL; + +} + +// ------------------------------------------------------------------------- +namespace +{ + /** collects ColumnDesc's from a resultset produced by XDatabaseMetaData::getColumns + */ + void lcl_collectColumnDescs_throw( const Reference< XResultSet >& _rxResult, ::std::vector< ColumnDesc >& _out_rColumns ) + { + Reference< XRow > xRow( _rxResult, UNO_QUERY_THROW ); + ::rtl::OUString sName; + OrdinalPosition nOrdinalPosition( 0 ); + while ( _rxResult->next() ) + { + sName = xRow->getString( 4 ); // COLUMN_NAME + sal_Int32 nField5 = xRow->getInt(5); + ::rtl::OUString aField6 = xRow->getString(6); + sal_Int32 nField7 = xRow->getInt(7) + , nField9 = xRow->getInt(9) + , nField11= xRow->getInt(11); + ::rtl::OUString sField12 = xRow->getString(12) + ,sField13 = xRow->getString(13); + nOrdinalPosition = xRow->getInt( 17 ); // ORDINAL_POSITION + _out_rColumns.push_back( ColumnDesc( sName,nField5,aField6,nField7,nField9,nField11,sField12,sField13, nOrdinalPosition ) ); + } + } + + /** checks a given array of ColumnDesc's whether it has reasonable ordinal positions. If not, + they will be normalized to be the array index. + */ + void lcl_sanitizeColumnDescs( ::std::vector< ColumnDesc >& _rColumns ) + { + if ( _rColumns.empty() ) + return; + + // collect all used ordinals + ::std::set< OrdinalPosition > aUsedOrdinals; + for ( ::std::vector< ColumnDesc >::iterator collect = _rColumns.begin(); + collect != _rColumns.end(); + ++collect + ) + aUsedOrdinals.insert( collect->nOrdinalPosition ); + + // we need to have as much different ordinals as we have different columns + bool bDuplicates = aUsedOrdinals.size() != _rColumns.size(); + // and it needs to be a continuous range + size_t nOrdinalsRange = *aUsedOrdinals.rbegin() - *aUsedOrdinals.begin() + 1; + bool bGaps = nOrdinalsRange != _rColumns.size(); + + // if that's not the case, normalize it + if ( bGaps || bDuplicates ) + { + OSL_ENSURE( false, "lcl_sanitizeColumnDescs: database did provide invalid ORDINAL_POSITION values!" ); + + OrdinalPosition nNormalizedPosition = 1; + for ( ::std::vector< ColumnDesc >::iterator normalize = _rColumns.begin(); + normalize != _rColumns.end(); + ++normalize + ) + normalize->nOrdinalPosition = nNormalizedPosition++; + return; + } + + // what's left is that the range might not be from 1 to <column count>, but for instance + // 0 to <column count>-1. + size_t nOffset = *aUsedOrdinals.begin() - 1; + for ( ::std::vector< ColumnDesc >::iterator offset = _rColumns.begin(); + offset != _rColumns.end(); + ++offset + ) + offset->nOrdinalPosition -= nOffset; + } +} + +// ------------------------------------------------------------------------- +void OTableHelper::refreshColumns() +{ + TStringVector aVector; + if(!isNew()) + { + Any aCatalog; + if ( m_CatalogName.getLength() ) + aCatalog <<= m_CatalogName; + + ::utl::SharedUNOComponent< XResultSet > xResult( getMetaData()->getColumns( + aCatalog, + m_SchemaName, + m_Name, + ::rtl::OUString::createFromAscii("%") + ) ); + + // collect the column names, together with their ordinal position + m_pImpl->m_aColumnDesc.clear(); + lcl_collectColumnDescs_throw( xResult, m_pImpl->m_aColumnDesc ); + + // ensure that the ordinal positions as obtained from the meta data do make sense + lcl_sanitizeColumnDescs( m_pImpl->m_aColumnDesc ); + + // sort by ordinal position + ::std::map< OrdinalPosition, ::rtl::OUString > aSortedColumns; + for ( ::std::vector< ColumnDesc >::const_iterator copy = m_pImpl->m_aColumnDesc.begin(); + copy != m_pImpl->m_aColumnDesc.end(); + ++copy + ) + aSortedColumns[ copy->nOrdinalPosition ] = copy->sName; + + // copy them to aVector, now that we have the proper ordering + ::std::transform( + aSortedColumns.begin(), + aSortedColumns.end(), + ::std::insert_iterator< TStringVector >( aVector, aVector.begin() ), + ::std::select2nd< ::std::map< OrdinalPosition, ::rtl::OUString >::value_type >() + ); + } + + if(m_pColumns) + m_pColumns->reFill(aVector); + else + m_pColumns = createColumns(aVector); +} +// ----------------------------------------------------------------------------- +const ColumnDesc* OTableHelper::getColumnDescription(const ::rtl::OUString& _sName) const +{ + const ColumnDesc* pRet = NULL; + ::std::vector< ColumnDesc >::const_iterator aEnd = m_pImpl->m_aColumnDesc.end(); + for (::std::vector< ColumnDesc >::const_iterator aIter = m_pImpl->m_aColumnDesc.begin();aIter != aEnd;++aIter) + { + if ( aIter->sName == _sName ) + { + pRet = &*aIter; + break; + } + } // for (::std::vector< ColumnDesc >::const_iterator aIter = m_pImpl->m_aColumnDesc.begin();aIter != aEnd;++aIter) + return pRet; +} +// ------------------------------------------------------------------------- +void OTableHelper::refreshPrimaryKeys(TStringVector& _rNames) +{ + Any aCatalog; + if ( m_CatalogName.getLength() ) + aCatalog <<= m_CatalogName; + Reference< XResultSet > xResult = getMetaData()->getPrimaryKeys(aCatalog,m_SchemaName,m_Name); + + if ( xResult.is() ) + { + sdbcx::TKeyProperties pKeyProps(new sdbcx::KeyProperties(::rtl::OUString(),KeyType::PRIMARY,0,0)); + ::rtl::OUString aPkName; + bool bAlreadyFetched = false; + const Reference< XRow > xRow(xResult,UNO_QUERY); + while ( xResult->next() ) + { + pKeyProps->m_aKeyColumnNames.push_back(xRow->getString(4)); + if ( !bAlreadyFetched ) + { + aPkName = xRow->getString(6); + bAlreadyFetched = true; + } + } + + m_pImpl->m_aKeys.insert(TKeyMap::value_type(aPkName,pKeyProps)); + _rNames.push_back(aPkName); + } // if ( xResult.is() && xResult->next() ) + ::comphelper::disposeComponent(xResult); +} +// ------------------------------------------------------------------------- +void OTableHelper::refreshForgeinKeys(TStringVector& _rNames) +{ + Any aCatalog; + if ( m_CatalogName.getLength() ) + aCatalog <<= m_CatalogName; + Reference< XResultSet > xResult = getMetaData()->getImportedKeys(aCatalog,m_SchemaName,m_Name); + Reference< XRow > xRow(xResult,UNO_QUERY); + + if ( xRow.is() ) + { + sdbcx::TKeyProperties pKeyProps; + ::rtl::OUString aName,sCatalog,aSchema,sOldFKName; + while( xResult->next() ) + { + // this must be outsid the "if" because we have to call in a right order + sCatalog = xRow->getString(1); + if ( xRow->wasNull() ) + sCatalog = ::rtl::OUString(); + aSchema = xRow->getString(2); + aName = xRow->getString(3); + + const ::rtl::OUString sForeignKeyColumn = xRow->getString(8); + const sal_Int32 nUpdateRule = xRow->getInt(10); + const sal_Int32 nDeleteRule = xRow->getInt(11); + const ::rtl::OUString sFkName = xRow->getString(12); + + if ( pKeyProps.get() ) + { + } + + + if ( sFkName.getLength() && !xRow->wasNull() ) + { + if ( sOldFKName != sFkName ) + { + if ( pKeyProps.get() ) + m_pImpl->m_aKeys.insert(TKeyMap::value_type(sOldFKName,pKeyProps)); + + const ::rtl::OUString sReferencedName = ::dbtools::composeTableName(getMetaData(),sCatalog,aSchema,aName,sal_False,::dbtools::eInDataManipulation); + pKeyProps.reset(new sdbcx::KeyProperties(sReferencedName,KeyType::FOREIGN,nUpdateRule,nDeleteRule)); + pKeyProps->m_aKeyColumnNames.push_back(sForeignKeyColumn); + _rNames.push_back(sFkName); + if ( m_pTables->hasByName(sReferencedName) ) + { + if ( !m_pImpl->m_xTablePropertyListener.is() ) + m_pImpl->m_xTablePropertyListener = ::comphelper::ImplementationReference< OTableContainerListener,XContainerListener>( new OTableContainerListener(this) ); + m_pTables->addContainerListener(m_pImpl->m_xTablePropertyListener.getRef()); + m_pImpl->m_xTablePropertyListener->add(sReferencedName); + } // if ( m_pTables->hasByName(sReferencedName) ) + sOldFKName = sFkName; + } // if ( sOldFKName != sFkName ) + else if ( pKeyProps.get() ) + { + pKeyProps->m_aKeyColumnNames.push_back(sForeignKeyColumn); + } + } + } // while( xResult->next() ) + if ( pKeyProps.get() ) + m_pImpl->m_aKeys.insert(TKeyMap::value_type(sOldFKName,pKeyProps)); + ::comphelper::disposeComponent(xResult); + } +} +// ------------------------------------------------------------------------- +void OTableHelper::refreshKeys() +{ + m_pImpl->m_aKeys.clear(); + + TStringVector aNames; + + if(!isNew()) + { + refreshPrimaryKeys(aNames); + refreshForgeinKeys(aNames); + m_pKeys = createKeys(aNames); + } // if(!isNew()) + else if (!m_pKeys ) + m_pKeys = createKeys(aNames); + /*if(m_pKeys) + m_pKeys->reFill(aVector); + else*/ + +} +// ------------------------------------------------------------------------- +void OTableHelper::refreshIndexes() +{ + TStringVector aVector; + if(!isNew()) + { + // fill indexes + Any aCatalog; + if ( m_CatalogName.getLength() ) + aCatalog <<= m_CatalogName; + Reference< XResultSet > xResult = getMetaData()->getIndexInfo(aCatalog,m_SchemaName,m_Name,sal_False,sal_False); + + if(xResult.is()) + { + Reference< XRow > xRow(xResult,UNO_QUERY); + ::rtl::OUString aName; + ::rtl::OUString sCatalogSep = getMetaData()->getCatalogSeparator(); + ::rtl::OUString sPreviousRoundName; + while( xResult->next() ) + { + aName = xRow->getString(5); + if(aName.getLength()) + aName += sCatalogSep; + aName += xRow->getString(6); + if ( aName.getLength() ) + { + // don't insert the name if the last one we inserted was the same + if (sPreviousRoundName != aName) + aVector.push_back(aName); + } + sPreviousRoundName = aName; + } + ::comphelper::disposeComponent(xResult); + } + } + + if(m_pIndexes) + m_pIndexes->reFill(aVector); + else + m_pIndexes = createIndexes(aVector); +} +// ----------------------------------------------------------------------------- +::rtl::OUString OTableHelper::getRenameStart() const +{ + ::rtl::OUString sSql(RTL_CONSTASCII_USTRINGPARAM("RENAME ")); + if ( m_Type == ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("VIEW")) ) + sSql += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" VIEW ")); + else + sSql += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" TABLE ")); + + return sSql; +} +// ------------------------------------------------------------------------- +// XRename +void SAL_CALL OTableHelper::rename( const ::rtl::OUString& newName ) throw(SQLException, ElementExistException, RuntimeException) +{ + ::osl::MutexGuard aGuard(m_aMutex); + checkDisposed( +#ifdef GCC + ::connectivity::sdbcx::OTableDescriptor_BASE::rBHelper.bDisposed +#else + rBHelper.bDisposed +#endif + ); + + if(!isNew()) + { + if ( m_pImpl->m_xRename.is() ) + { + m_pImpl->m_xRename->rename(this,newName); + } + else + { + ::rtl::OUString sSql = getRenameStart(); + ::rtl::OUString sQuote = getMetaData()->getIdentifierQuoteString( ); + + ::rtl::OUString sCatalog,sSchema,sTable; + ::dbtools::qualifiedNameComponents(getMetaData(),newName,sCatalog,sSchema,sTable,::dbtools::eInDataManipulation); + + ::rtl::OUString sComposedName; + sComposedName = ::dbtools::composeTableName(getMetaData(),m_CatalogName,m_SchemaName,m_Name,sal_True,::dbtools::eInDataManipulation); + sSql += sComposedName + + ::rtl::OUString::createFromAscii(" TO "); + sComposedName = ::dbtools::composeTableName(getMetaData(),sCatalog,sSchema,sTable,sal_True,::dbtools::eInDataManipulation); + sSql += sComposedName; + + Reference< XStatement > xStmt = m_pImpl->m_xConnection->createStatement( ); + if ( xStmt.is() ) + { + xStmt->execute(sSql); + ::comphelper::disposeComponent(xStmt); + } + } + + OTable_TYPEDEF::rename(newName); + } + else + ::dbtools::qualifiedNameComponents(getMetaData(),newName,m_CatalogName,m_SchemaName,m_Name,::dbtools::eInTableDefinitions); +} +// ----------------------------------------------------------------------------- +Reference< XDatabaseMetaData> OTableHelper::getMetaData() const +{ + return m_pImpl->m_xMetaData; +} +// ------------------------------------------------------------------------- +void SAL_CALL OTableHelper::alterColumnByIndex( sal_Int32 index, const Reference< XPropertySet >& descriptor ) throw(SQLException, ::com::sun::star::lang::IndexOutOfBoundsException, RuntimeException) +{ + ::osl::MutexGuard aGuard(m_aMutex); + checkDisposed( +#ifdef GCC + ::connectivity::sdbcx::OTableDescriptor_BASE::rBHelper.bDisposed +#else + rBHelper.bDisposed +#endif + ); + + Reference< XPropertySet > xOld; + if(::cppu::extractInterface(xOld,m_pColumns->getByIndex(index)) && xOld.is()) + alterColumnByName(getString(xOld->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_NAME))),descriptor); +} + +// ------------------------------------------------------------------------- +::rtl::OUString SAL_CALL OTableHelper::getName() throw(RuntimeException) +{ + ::rtl::OUString sComposedName; + sComposedName = ::dbtools::composeTableName(getMetaData(),m_CatalogName,m_SchemaName,m_Name,sal_False,::dbtools::eInDataManipulation); + return sComposedName; +} +// ----------------------------------------------------------------------------- +void SAL_CALL OTableHelper::acquire() throw() +{ + OTable_TYPEDEF::acquire(); +} +// ----------------------------------------------------------------------------- +void SAL_CALL OTableHelper::release() throw() +{ + OTable_TYPEDEF::release(); +} +// ----------------------------------------------------------------------------- +sdbcx::TKeyProperties OTableHelper::getKeyProperties(const ::rtl::OUString& _sName) const +{ + sdbcx::TKeyProperties pKeyProps; + TKeyMap::const_iterator aFind = m_pImpl->m_aKeys.find(_sName); + if ( aFind != m_pImpl->m_aKeys.end() ) + { + pKeyProps = aFind->second; + } + else // only a fall back + { + OSL_ENSURE(0,"No key with the given name found"); + pKeyProps.reset(new sdbcx::KeyProperties()); + } + + return pKeyProps; +} +// ----------------------------------------------------------------------------- +void OTableHelper::addKey(const ::rtl::OUString& _sName,const sdbcx::TKeyProperties& _aKeyProperties) +{ + m_pImpl->m_aKeys.insert(TKeyMap::value_type(_sName,_aKeyProperties)); +} +// ----------------------------------------------------------------------------- +::rtl::OUString OTableHelper::getTypeCreatePattern() const +{ + return ::rtl::OUString(); +} +// ----------------------------------------------------------------------------- +Reference< XConnection> OTableHelper::getConnection() const +{ + return m_pImpl->m_xConnection; +} +// ----------------------------------------------------------------------------- +Reference< ::com::sun::star::sdb::tools::XTableRename> OTableHelper::getRenameService() const +{ + return m_pImpl->m_xRename; +} +// ----------------------------------------------------------------------------- +Reference< ::com::sun::star::sdb::tools::XTableAlteration> OTableHelper::getAlterService() const +{ + return m_pImpl->m_xAlter; +} +// ----------------------------------------------------------------------------- +Reference< ::com::sun::star::sdb::tools::XKeyAlteration> OTableHelper::getKeyService() const +{ + return m_pImpl->m_xKeyAlter; +} +// ----------------------------------------------------------------------------- +Reference< ::com::sun::star::sdb::tools::XIndexAlteration> OTableHelper::getIndexService() const +{ + return m_pImpl->m_xIndexAlter; +} +// ----------------------------------------------------------------------------- diff --git a/connectivity/source/commontools/conncleanup.cxx b/connectivity/source/commontools/conncleanup.cxx new file mode 100644 index 000000000000..0d8547923e87 --- /dev/null +++ b/connectivity/source/commontools/conncleanup.cxx @@ -0,0 +1,247 @@ +/************************************************************************* + * + * 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 <connectivity/conncleanup.hxx> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/lang/XComponent.hpp> +#include <osl/diagnose.h> + +//......................................................................... +namespace dbtools +{ +//......................................................................... + + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::beans; + using namespace ::com::sun::star::sdbc; + using namespace ::com::sun::star::lang; + + //===================================================================== + static const ::rtl::OUString& getActiveConnectionPropertyName() + { + static const ::rtl::OUString s_sActiveConnectionPropertyName = ::rtl::OUString::createFromAscii("ActiveConnection"); + return s_sActiveConnectionPropertyName; + } + + //===================================================================== + //= OAutoConnectionDisposer + //===================================================================== + //--------------------------------------------------------------------- + OAutoConnectionDisposer::OAutoConnectionDisposer(const Reference< XRowSet >& _rxRowSet, const Reference< XConnection >& _rxConnection) + :m_xRowSet( _rxRowSet ) + ,m_bRSListening( sal_False ) + ,m_bPropertyListening( sal_False ) + { + Reference< XPropertySet > xProps(_rxRowSet, UNO_QUERY); + OSL_ENSURE(xProps.is(), "OAutoConnectionDisposer::OAutoConnectionDisposer: invalid rowset (no XPropertySet)!"); + + if (!xProps.is()) + return; + + try + { + xProps->setPropertyValue( getActiveConnectionPropertyName(), makeAny( _rxConnection ) ); + m_xOriginalConnection = _rxConnection; + startPropertyListening( xProps ); + } + catch( const Exception& ) + { + OSL_ENSURE( sal_False, "OAutoConnectionDisposer::OAutoConnectionDisposer: caught an exception!" ); + } + } + + //--------------------------------------------------------------------- + void OAutoConnectionDisposer::startPropertyListening( const Reference< XPropertySet >& _rxRowSet ) + { + try + { + _rxRowSet->addPropertyChangeListener( getActiveConnectionPropertyName(), this ); + m_bPropertyListening = sal_True; + } + catch( const Exception& ) + { + OSL_ENSURE( sal_False, "OAutoConnectionDisposer::startPropertyListening: caught an exception!" ); + } + } + + //--------------------------------------------------------------------- + void OAutoConnectionDisposer::stopPropertyListening( const Reference< XPropertySet >& _rxEventSource ) + { + // prevent deletion of ourself while we're herein + Reference< XInterface > xKeepAlive(static_cast< XWeak* >(this)); + + try + { // remove ourself as property change listener + OSL_ENSURE( _rxEventSource.is(), "OAutoConnectionDisposer::stopPropertyListening: invalid event source (no XPropertySet)!" ); + if ( _rxEventSource.is() ) + { + _rxEventSource->removePropertyChangeListener( getActiveConnectionPropertyName(), this ); + m_bPropertyListening = sal_False; + } + } + catch( const Exception& ) + { + OSL_ENSURE( sal_False, "OAutoConnectionDisposer::stopPropertyListening: caught an exception!" ); + } + } + + //--------------------------------------------------------------------- + void OAutoConnectionDisposer::startRowSetListening() + { + OSL_ENSURE( !m_bRSListening, "OAutoConnectionDisposer::startRowSetListening: already listening!" ); + try + { + if ( !m_bRSListening ) + m_xRowSet->addRowSetListener( this ); + } + catch( const Exception& ) + { + OSL_ENSURE( sal_False, "OAutoConnectionDisposer::startRowSetListening: caught an exception!" ); + } + m_bRSListening = sal_True; + } + + //--------------------------------------------------------------------- + void OAutoConnectionDisposer::stopRowSetListening() + { + OSL_ENSURE( m_bRSListening, "OAutoConnectionDisposer::stopRowSetListening: not listening!" ); + try + { + m_xRowSet->removeRowSetListener( this ); + } + catch( const Exception& ) + { + OSL_ENSURE( sal_False, "OAutoConnectionDisposer::stopRowSetListening: caught an exception!" ); + } + m_bRSListening = sal_False; + } + + //--------------------------------------------------------------------- + void SAL_CALL OAutoConnectionDisposer::propertyChange( const PropertyChangeEvent& _rEvent ) throw (RuntimeException) + { + if ( _rEvent.PropertyName.equals( getActiveConnectionPropertyName() ) ) + { // somebody set a new ActiveConnection + + Reference< XConnection > xNewConnection; + _rEvent.NewValue >>= xNewConnection; + + if ( isRowSetListening() ) + { + // we're listening at the row set, this means that the row set does not have our + // m_xOriginalConnection as active connection anymore + // So there are two possibilities + // a. somebody sets a new connection which is not our original one + // b. somebody sets a new connection, which is exactly the original one + // a. we're not interested in a, but in b: In this case, we simply need to move to the state + // we had originally: listen for property changes, do not listen for row set changes, and + // do not dispose the connection until the row set does not need it anymore + if ( xNewConnection.get() == m_xOriginalConnection.get() ) + { + stopRowSetListening(); + } + } + else + { + // start listening at the row set. We're allowed to dispose the old connection as soon + // as the RowSet changed + + // Unfortunately, the our database form implementations sometimes fire the change of their + // ActiveConnection twice. This is a error in forms/source/component/DatabaseForm.cxx, but + // changing this would require incompatible changes we can't do for a while. + // So for the moment, we have to live with it here. + // + // The only scenario where this doubled notification causes problems is when the connection + // of the form is reset to the one we're responsible for (m_xOriginalConnection), so we + // check this here. + // + // Yes, this is a HACK :( + // + // 94407 - 08.11.2001 - fs@openoffice.org + if ( xNewConnection.get() != m_xOriginalConnection.get() ) + { +#if OSL_DEBUG_LEVEL > 0 + Reference< XConnection > xOldConnection; + _rEvent.OldValue >>= xOldConnection; + OSL_ENSURE( xOldConnection.get() == m_xOriginalConnection.get(), "OAutoConnectionDisposer::propertyChange: unexpected (original) property value!" ); +#endif + startRowSetListening(); + } + } + } + } + + //--------------------------------------------------------------------- + void SAL_CALL OAutoConnectionDisposer::disposing( const EventObject& _rSource ) throw (RuntimeException) + { + // the rowset is beeing disposed, and nobody has set a new ActiveConnection in the meantime + if ( isRowSetListening() ) + stopRowSetListening(); + + clearConnection(); + + if ( isPropertyListening() ) + stopPropertyListening( Reference< XPropertySet >( _rSource.Source, UNO_QUERY ) ); + } + //--------------------------------------------------------------------- + void OAutoConnectionDisposer::clearConnection() + { + try + { + // dispose the old connection + Reference< XComponent > xComp(m_xOriginalConnection, UNO_QUERY); + if (xComp.is()) + xComp->dispose(); + m_xOriginalConnection.clear(); + } + catch(Exception&) + { + OSL_ENSURE(sal_False, "OAutoConnectionDisposer::clearConnection: caught an exception!"); + } + } + //--------------------------------------------------------------------- + void SAL_CALL OAutoConnectionDisposer::cursorMoved( const ::com::sun::star::lang::EventObject& /*event*/ ) throw (::com::sun::star::uno::RuntimeException) + { + } + //--------------------------------------------------------------------- + void SAL_CALL OAutoConnectionDisposer::rowChanged( const ::com::sun::star::lang::EventObject& /*event*/ ) throw (::com::sun::star::uno::RuntimeException) + { + } + //--------------------------------------------------------------------- + void SAL_CALL OAutoConnectionDisposer::rowSetChanged( const ::com::sun::star::lang::EventObject& /*event*/ ) throw (::com::sun::star::uno::RuntimeException) + { + stopRowSetListening(); + clearConnection(); + + } + //--------------------------------------------------------------------- + +//......................................................................... +} // namespace dbtools +//......................................................................... + diff --git a/connectivity/source/commontools/dbcharset.cxx b/connectivity/source/commontools/dbcharset.cxx new file mode 100644 index 000000000000..7cd722781cda --- /dev/null +++ b/connectivity/source/commontools/dbcharset.cxx @@ -0,0 +1,232 @@ +/************************************************************************* + * + * 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 <connectivity/dbcharset.hxx> +#include "diagnose_ex.h" +#include <osl/diagnose.h> +#include <rtl/tencinfo.h> + +//......................................................................... +namespace dbtools +{ +//......................................................................... + + //========================================================================= + //= OCharsetMap + //========================================================================= + //------------------------------------------------------------------------- + OCharsetMap::OCharsetMap() + { + } + + //------------------------------------------------------------------------- + void OCharsetMap::lateConstruct() + { + const rtl_TextEncoding eFirstEncoding = RTL_TEXTENCODING_DONTKNOW; + const rtl_TextEncoding eLastEncoding = 100; // TODO: a define in rtl/textenc.h would be fine here ... + OSL_ENSURE( 0 == eFirstEncoding, "OCharsetMap::OCharsetMap: somebody changed the numbers!" ); + + rtl_TextEncodingInfo aInfo; aInfo.StructSize = sizeof( rtl_TextEncodingInfo ); + for ( rtl_TextEncoding eEncoding = eFirstEncoding; eEncoding < eLastEncoding; ++eEncoding ) + { + if ( ( RTL_TEXTENCODING_DONTKNOW == eEncoding ) // this is always allowed - it has the special meaning "system encoding" + || ( rtl_getTextEncodingInfo( eEncoding, &aInfo ) + && approveEncoding( eEncoding, aInfo ) + ) + ) + { + m_aEncodings.insert( eEncoding ); + } + } + + OSL_ENSURE( find( RTL_TEXTENCODING_MS_1252 ) != end(), "OCharsetMap::lateConstruct: missing compatibility encoding ANSI!" ); + OSL_ENSURE( find( RTL_TEXTENCODING_APPLE_ROMAN ) != end(), "OCharsetMap::lateConstruct: missing compatibility encoding macintosh!" ); + OSL_ENSURE( find( RTL_TEXTENCODING_IBM_437 ) != end(), "OCharsetMap::lateConstruct: missing compatibility encoding IBM437!" ); + OSL_ENSURE( find( RTL_TEXTENCODING_IBM_850) != end(), "OCharsetMap::lateConstruct: missing compatibility encoding IBM850!" ); + OSL_ENSURE( find( RTL_TEXTENCODING_IBM_860 ) != end(), "OCharsetMap::lateConstruct: missing compatibility encoding IBM860!" ); + OSL_ENSURE( find( RTL_TEXTENCODING_IBM_861 ) != end(), "OCharsetMap::lateConstruct: missing compatibility encoding IBM861!" ); + OSL_ENSURE( find( RTL_TEXTENCODING_IBM_863 ) != end(), "OCharsetMap::lateConstruct: missing compatibility encoding IBM863!" ); + OSL_ENSURE( find( RTL_TEXTENCODING_IBM_865 ) != end(), "OCharsetMap::lateConstruct: missing compatibility encoding IBM865!" ); + OSL_ENSURE( find( RTL_TEXTENCODING_IBM_866 ) != end(), "OCharsetMap::lateConstruct: missing compatibility encoding IBM866!" ); + OSL_ENSURE( find( RTL_TEXTENCODING_DONTKNOW ) != end(), "OCharsetMap::lateConstruct: missing compatibility encoding SYSTEM!" ); + OSL_ENSURE( find( RTL_TEXTENCODING_UTF8 ) != end(), "OCharsetMap::lateConstruct: missing compatibility encoding UTF-8!" ); + OSL_ENSURE( find( RTL_TEXTENCODING_BIG5_HKSCS ) != end(), "OCharsetMap::lateConstruct: missing compatibility encoding Big5-HKSCS!" ); + } + + //------------------------------------------------------------------------- + sal_Bool OCharsetMap::approveEncoding( const rtl_TextEncoding _eEncoding, const rtl_TextEncodingInfo& _rInfo ) const + { + sal_Bool bIsMimeEncoding = 0 != ( _rInfo.Flags & RTL_TEXTENCODING_INFO_MIME ); + OSL_ENSURE( !bIsMimeEncoding || rtl_getMimeCharsetFromTextEncoding( _eEncoding ), + "OCharsetMap::OCharsetMap: inconsistence in rtl!" ); + OSL_UNUSED( _eEncoding ); + return bIsMimeEncoding; + } + + //------------------------------------------------------------------------- + OCharsetMap::~OCharsetMap() + { + } + + //------------------------------------------------------------------------- + OCharsetMap::CharsetIterator OCharsetMap::begin() const + { + ensureConstructed( ); + return CharsetIterator(this, m_aEncodings.begin() ); + } + + //------------------------------------------------------------------------- + OCharsetMap::CharsetIterator OCharsetMap::find(const rtl_TextEncoding _eEncoding) const + { + ensureConstructed( ); + return CharsetIterator( this, m_aEncodings.find( _eEncoding ) ); + } + + //------------------------------------------------------------------------- + OCharsetMap::CharsetIterator OCharsetMap::find(const ::rtl::OUString& _rIanaName, const IANA&) const + { + ensureConstructed( ); + + rtl_TextEncoding eEncoding = RTL_TEXTENCODING_DONTKNOW; + if ( _rIanaName.getLength() ) + { + // byte string conversion + ::rtl::OString sMimeByteString( _rIanaName.getStr(), _rIanaName.getLength(), RTL_TEXTENCODING_ASCII_US ); + // look up + eEncoding = rtl_getTextEncodingFromMimeCharset( sMimeByteString.getStr() ); + + if ( RTL_TEXTENCODING_DONTKNOW == eEncoding ) + { // if we're here, the name is not empty, but unknown -> this is an invalid name + return end(); + } + } + + return find( eEncoding ); + } + + //------------------------------------------------------------------------- + OCharsetMap::CharsetIterator OCharsetMap::end() const + { + ensureConstructed( ); + + return CharsetIterator( this, m_aEncodings.end() ); + } + + //========================================================================= + //= CharsetIteratorDerefHelper + //========================================================================= + //------------------------------------------------------------------------- + CharsetIteratorDerefHelper::CharsetIteratorDerefHelper( const CharsetIteratorDerefHelper& _rSource ) + :m_eEncoding( _rSource.m_eEncoding ) + ,m_aIanaName( _rSource.m_aIanaName ) + { + } + + //------------------------------------------------------------------------- + CharsetIteratorDerefHelper:: CharsetIteratorDerefHelper(const rtl_TextEncoding _eEncoding, const ::rtl::OUString& _rIanaName ) + :m_eEncoding( _eEncoding ) + ,m_aIanaName( _rIanaName ) + { + } + + //------------------------------------------------------------------------- + CharsetIteratorDerefHelper::CharsetIteratorDerefHelper() + :m_eEncoding(RTL_TEXTENCODING_DONTKNOW) + { + } + + //========================================================================= + //= OCharsetMap::CharsetIterator + //========================================================================= + //------------------------------------------------------------------------- + OCharsetMap::CharsetIterator::CharsetIterator(const OCharsetMap* _pContainer, OCharsetMap::TextEncBag::const_iterator _aPos ) + :m_pContainer( _pContainer ) + ,m_aPos( _aPos ) + { + OSL_ENSURE( m_pContainer, "OCharsetMap::CharsetIterator::CharsetIterator : invalid container!" ); + } + + //------------------------------------------------------------------------- + OCharsetMap::CharsetIterator::CharsetIterator(const CharsetIterator& _rSource) + :m_pContainer( _rSource.m_pContainer ) + ,m_aPos( _rSource.m_aPos ) + { + } + + //------------------------------------------------------------------------- + OCharsetMap::CharsetIterator::~CharsetIterator() + { + } + + //------------------------------------------------------------------------- + CharsetIteratorDerefHelper OCharsetMap::CharsetIterator::operator*() const + { + OSL_ENSURE( m_aPos != m_pContainer->m_aEncodings.end(), "OCharsetMap::CharsetIterator::operator*: invalid position!"); + + rtl_TextEncoding eEncoding = *m_aPos; + ::rtl::OUString sIanaName; + + if ( RTL_TEXTENCODING_DONTKNOW != eEncoding ) + { // it's not the virtual "system charset" + const char* pIanaName = rtl_getMimeCharsetFromTextEncoding( eEncoding ); + OSL_ENSURE( pIanaName, "OCharsetMap::CharsetIterator: invalid mime name!" ); + if ( pIanaName ) + sIanaName = ::rtl::OUString::createFromAscii( pIanaName ); + } + return CharsetIteratorDerefHelper( eEncoding, sIanaName ); + } + + //------------------------------------------------------------------------- + const OCharsetMap::CharsetIterator& OCharsetMap::CharsetIterator::operator++() + { + OSL_ENSURE( m_aPos != m_pContainer->m_aEncodings.end(), "OCharsetMap::CharsetIterator::operator++ : invalid position!" ); + if ( m_aPos != m_pContainer->m_aEncodings.end()) + ++m_aPos; + return *this; + } + + //------------------------------------------------------------------------- + const OCharsetMap::CharsetIterator& OCharsetMap::CharsetIterator::operator--() + { + OSL_ENSURE( m_aPos != m_pContainer->m_aEncodings.begin(), "OCharsetMap::CharsetIterator::operator-- : invalid position!" ); + if ( m_aPos != m_pContainer->m_aEncodings.begin() ) + --m_aPos; + return *this; + } + + //------------------------------------------------------------------------- + bool operator==(const OCharsetMap::CharsetIterator& lhs, const OCharsetMap::CharsetIterator& rhs) + { + return ( lhs.m_pContainer == rhs.m_pContainer ) && ( lhs.m_aPos == rhs.m_aPos ); + } + +//......................................................................... +} // namespace dbtools +//......................................................................... + diff --git a/connectivity/source/commontools/dbconversion.cxx b/connectivity/source/commontools/dbconversion.cxx new file mode 100644 index 000000000000..6149b4748c30 --- /dev/null +++ b/connectivity/source/commontools/dbconversion.cxx @@ -0,0 +1,490 @@ +/************************************************************************* + * + * 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 <connectivity/dbconversion.hxx> +#include <connectivity/dbcharset.hxx> +#include <osl/diagnose.h> +#ifndef _INC_STDIO +#include <stdio.h> +#endif +#include <com/sun/star/sdbc/SQLException.hpp> +#include <com/sun/star/util/Date.hpp> +#include <com/sun/star/util/Time.hpp> +#include <com/sun/star/util/DateTime.hpp> +#include <rtl/ustrbuf.hxx> + +#define MAX_DAYS 3636532 + +//......................................................................... +namespace dbtools +{ +//......................................................................... + + + using namespace ::comphelper; + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::util; + using namespace ::com::sun::star::sdb; + using namespace ::com::sun::star::sdbc; + using namespace ::com::sun::star::lang; + using namespace ::com::sun::star::beans; + + + //------------------------------------------------------------------------------ + ::com::sun::star::util::Date DBTypeConversion::getStandardDate() + { + static ::com::sun::star::util::Date STANDARD_DB_DATE(1,1,1900); + return STANDARD_DB_DATE; + } + //------------------------------------------------------------------------------ + ::rtl::OUString DBTypeConversion::toDateString(const Date& rDate) + { + sal_Char s[11]; + snprintf(s, + sizeof(s), + "%04d-%02d-%02d", + (int)rDate.Year, + (int)rDate.Month, + (int)rDate.Day); + s[10] = 0; + return ::rtl::OUString::createFromAscii(s); + } + //------------------------------------------------------------------ + ::rtl::OUString DBTypeConversion::toTimeString(const Time& rTime) + { + sal_Char s[9]; + snprintf(s, + sizeof(s), + "%02d:%02d:%02d", + (int)rTime.Hours, + (int)rTime.Minutes, + (int)rTime.Seconds); + s[8] = 0; + return ::rtl::OUString::createFromAscii(s); + } + + //------------------------------------------------------------------ + ::rtl::OUString DBTypeConversion::toDateTimeString(const DateTime& _rDateTime) + { + Date aDate(_rDateTime.Day,_rDateTime.Month,_rDateTime.Year); + ::rtl::OUStringBuffer aTemp(toDateString(aDate)); + aTemp.appendAscii(" "); + Time aTime(0,_rDateTime.Seconds,_rDateTime.Minutes,_rDateTime.Hours); + aTemp.append( toTimeString(aTime) ); + aTemp.appendAscii("."); + aTemp.append( static_cast<sal_Int32>(_rDateTime.HundredthSeconds)); + return aTemp.makeStringAndClear(); + } + //------------------------------------------------------------------------------ + Date DBTypeConversion::toDate(sal_Int32 _nVal) + { + Date aReturn; + aReturn.Day = (sal_uInt16)(_nVal % 100); + aReturn.Month = (sal_uInt16)((_nVal / 100) % 100); + aReturn.Year = (sal_uInt16)(_nVal / 10000); + return aReturn; + } + + //------------------------------------------------------------------------------ + Time DBTypeConversion::toTime(sal_Int32 _nVal) + { + Time aReturn; + aReturn.Hours = (sal_uInt16)(((sal_uInt32)(_nVal >= 0 ? _nVal : _nVal*-1)) / 1000000); + aReturn.Minutes = (sal_uInt16)((((sal_uInt32)(_nVal >= 0 ? _nVal : _nVal*-1)) / 10000) % 100); + aReturn.Seconds = (sal_uInt16)((((sal_uInt32)(_nVal >= 0 ? _nVal : _nVal*-1)) / 100) % 100); + aReturn.HundredthSeconds = (sal_uInt16)(((sal_uInt32)(_nVal >= 0 ? _nVal : _nVal*-1)) % 100); + return aReturn; + } + + const double fMilliSecondsPerDay = 86400000.0; + //------------------------------------------------------------------------------ + sal_Int32 DBTypeConversion::toINT32(const Date& rVal) + { + return ((sal_Int32)(rVal.Day%100)) + + (((sal_Int32)(rVal.Month%100))*100) + + (((sal_Int32) rVal.Year%10000)*10000); + } + + //------------------------------------------------------------------------------ + sal_Int32 DBTypeConversion::toINT32(const Time& rVal) + { + // Zeit normalisieren + sal_Int32 nSeconds = rVal.Seconds + rVal.HundredthSeconds / 100; + sal_Int32 nHundredthSeconds = rVal.HundredthSeconds % 100; + sal_Int32 nMinutes = rVal.Minutes + nSeconds / 60; + nSeconds = nSeconds % 60; + sal_Int32 nHours = rVal.Hours + nMinutes / 60; + nMinutes = nMinutes % 60; + + // Zeit zusammenbauen + return (sal_Int32)(nHundredthSeconds + (nSeconds*100) + (nMinutes*10000) + (nHours*1000000)); + } + + //------------------------------------------------------------------------------ + sal_Int64 DBTypeConversion::toINT64(const DateTime& rVal) + { + // Zeit normalisieren + sal_Int32 nSeconds = rVal.Seconds + rVal.HundredthSeconds / 100; + sal_Int32 nHundredthSeconds = rVal.HundredthSeconds % 100; + sal_Int32 nMinutes = rVal.Minutes + nSeconds / 60; + nSeconds = nSeconds % 60; + sal_Int32 nHours = rVal.Hours + nMinutes / 60; + nMinutes = nMinutes % 60; + + // Zeit zusammenbauen + sal_Int32 nTime = (sal_Int32)(nHundredthSeconds + (nSeconds*100) + (nMinutes*10000) + (nHours*1000000)); + sal_Int32 nDate = ((sal_Int32)(rVal.Day%100)) + (((sal_Int32)(rVal.Month%100))*100) + (((sal_Int32) rVal.Year%10000)*10000); + sal_Int64 nRet; + + nRet = (sal_Int64) nTime; + nRet <<= 32; + nRet += nDate; + + return nRet; + } + + //------------------------------------------------------------------------------ + sal_Int32 DBTypeConversion::getMsFromTime(const Time& rVal) + { + sal_Int32 nHour = rVal.Hours; + sal_Int32 nMin = rVal.Minutes; + sal_Int32 nSec = rVal.Seconds; + sal_Int32 n100Sec = rVal.HundredthSeconds; + + return ((nHour*3600000)+(nMin*60000)+(nSec*1000)+(n100Sec*10)); + } + + //------------------------------------------------------------------------------ + static sal_Int32 aDaysInMonth[12] = { 31, 28, 31, 30, 31, 30, + 31, 31, 30, 31, 30, 31 }; + + //------------------------------------------------------------------------------ + static sal_Bool implIsLeapYear(sal_Int32 _nYear) + { + return ( ( ((_nYear % 4) == 0) + && ((_nYear % 100) != 0) + ) + ) + || ((_nYear % 400) == 0) + ; + } + + //------------------------------------------------------------------------------ + static sal_Int32 implDaysInMonth(sal_Int32 _nMonth, sal_Int32 _nYear) + { + OSL_ENSURE(_nMonth > 0 && _nMonth < 13,"Month as invalid value!"); + if (_nMonth != 2) + return aDaysInMonth[_nMonth-1]; + else + { + if (implIsLeapYear(_nYear)) + return aDaysInMonth[_nMonth-1] + 1; + else + return aDaysInMonth[_nMonth-1]; + } + } + + //------------------------------------------------------------------------------ + static sal_Int32 implRelativeToAbsoluteNull(const Date& _rDate) + { + sal_Int32 nDays = 0; + + // ripped this code from the implementation of tools::Date + sal_Int32 nNormalizedYear = _rDate.Year - 1; + nDays = nNormalizedYear * 365; + // leap years + nDays += (nNormalizedYear / 4) - (nNormalizedYear / 100) + (nNormalizedYear / 400); + + for (sal_Int32 i = 1; i < _rDate.Month; ++i) + nDays += implDaysInMonth(i, _rDate.Year); + + nDays += _rDate.Day; + return nDays; + } + //------------------------------------------------------------------------------ + static void implBuildFromRelative( sal_Int32 nDays, sal_uInt16& rDay, sal_uInt16& rMonth, sal_uInt16& rYear) + { + sal_Int32 nTempDays; + sal_Int32 i = 0; + sal_Bool bCalc; + + do + { + nTempDays = nDays; + rYear = (sal_uInt16)((nTempDays / 365) - i); + nTempDays -= (rYear-1) * 365; + nTempDays -= ((rYear-1) / 4) - ((rYear-1) / 100) + ((rYear-1) / 400); + bCalc = sal_False; + if ( nTempDays < 1 ) + { + i++; + bCalc = sal_True; + } + else + { + if ( nTempDays > 365 ) + { + if ( (nTempDays != 366) || !implIsLeapYear( rYear ) ) + { + i--; + bCalc = sal_True; + } + } + } + } + while ( bCalc ); + + rMonth = 1; + while ( nTempDays > implDaysInMonth( rMonth, rYear ) ) + { + nTempDays -= implDaysInMonth( rMonth, rYear ); + rMonth++; + } + rDay = (sal_uInt16)nTempDays; + } + //------------------------------------------------------------------------------ + sal_Int32 DBTypeConversion::toDays(const Date& _rVal, const Date& _rNullDate) + { + return implRelativeToAbsoluteNull(_rVal) - implRelativeToAbsoluteNull(_rNullDate); + } + + //------------------------------------------------------------------------------ + double DBTypeConversion::toDouble(const Date& rVal, const Date& _rNullDate) + { + return (double)toDays(rVal, _rNullDate); + } + + //------------------------------------------------------------------------------ + double DBTypeConversion::toDouble(const Time& rVal) + { + return (double)getMsFromTime(rVal) / fMilliSecondsPerDay; + } + + //------------------------------------------------------------------------------ + double DBTypeConversion::toDouble(const DateTime& _rVal, const Date& _rNullDate) + { + sal_Int64 nTime = toDays(Date(_rVal.Day, _rVal.Month, _rVal.Year), _rNullDate); + Time aTimePart; + + aTimePart.Hours = _rVal.Hours; + aTimePart.Minutes = _rVal.Minutes; + aTimePart.Seconds = _rVal.Seconds; + aTimePart.HundredthSeconds = _rVal.HundredthSeconds; + + return ((double)nTime) + toDouble(aTimePart); + } + // ------------------------------------------------------------------------- + static void addDays(sal_Int32 nDays, Date& _rDate) + { + sal_Int32 nTempDays = implRelativeToAbsoluteNull( _rDate ); + + nTempDays += nDays; + if ( nTempDays > MAX_DAYS ) + { + _rDate.Day = 31; + _rDate.Month = 12; + _rDate.Year = 9999; + } + else if ( nTempDays <= 0 ) + { + _rDate.Day = 1; + _rDate.Month = 1; + _rDate.Year = 00; + } + else + implBuildFromRelative( nTempDays, _rDate.Day, _rDate.Month, _rDate.Year ); + } + // ----------------------------------------------------------------------- + static void subDays( sal_Int32 nDays, Date& _rDate ) + { + sal_Int32 nTempDays = implRelativeToAbsoluteNull( _rDate ); + + nTempDays -= nDays; + if ( nTempDays > MAX_DAYS ) + { + _rDate.Day = 31; + _rDate.Month = 12; + _rDate.Year = 9999; + } + else if ( nTempDays <= 0 ) + { + _rDate.Day = 1; + _rDate.Month = 1; + _rDate.Year = 00; + } + else + implBuildFromRelative( nTempDays, _rDate.Day, _rDate.Month, _rDate.Year ); + } + // ------------------------------------------------------------------------- + Date DBTypeConversion::toDate(double dVal, const Date& _rNullDate) + { + Date aRet = _rNullDate; + + if (dVal >= 0) + addDays((sal_Int32)dVal,aRet); + else + subDays((sal_uInt32)(-dVal),aRet); + // x -= (sal_uInt32)(-nDays); + + return aRet; + } + // ------------------------------------------------------------------------- + Time DBTypeConversion::toTime(double dVal) + { + sal_Int32 nDays = (sal_Int32)dVal; + sal_Int32 nMS = sal_Int32((dVal - (double)nDays) * fMilliSecondsPerDay + 0.5); + + sal_Int16 nSign; + if ( nMS < 0 ) + { + nMS *= -1; + nSign = -1; + } + else + nSign = 1; + + Time xRet; + // Zeit normalisieren + // we have to sal_Int32 here because otherwise we get an overflow + sal_Int32 nHundredthSeconds = nMS/10; + sal_Int32 nSeconds = nHundredthSeconds / 100; + sal_Int32 nMinutes = nSeconds / 60; + + xRet.HundredthSeconds = (sal_uInt16)(nHundredthSeconds % 100); + xRet.Seconds = (sal_uInt16)(nSeconds % 60); + xRet.Hours = (sal_uInt16)(nMinutes / 60); + xRet.Minutes = (sal_uInt16)(nMinutes % 60); + + // Zeit zusammenbauen + sal_Int32 nTime = (sal_Int32)(xRet.HundredthSeconds + (xRet.Seconds*100) + (xRet.Minutes*10000) + (xRet.Hours*1000000)) * nSign; + + if(nTime < 0) + { + xRet.HundredthSeconds = 99; + xRet.Minutes = 59; + xRet.Seconds = 59; + xRet.Hours = 23; + } + return xRet; + } + //------------------------------------------------------------------------------ + DateTime DBTypeConversion::toDateTime(double dVal, const Date& _rNullDate) + { + Date aDate = toDate(dVal, _rNullDate); + Time aTime = toTime(dVal); + + DateTime xRet; + + xRet.Day = aDate.Day; + xRet.Month = aDate.Month; + xRet.Year = aDate.Year; + + xRet.HundredthSeconds = aTime.HundredthSeconds; + xRet.Minutes = aTime.Minutes; + xRet.Seconds = aTime.Seconds; + xRet.Hours = aTime.Hours; + + + return xRet; + } + //------------------------------------------------------------------------------ + Date DBTypeConversion::toDate(const ::rtl::OUString& _sSQLString) + { + // get the token out of a string + static sal_Unicode sDateSep = '-'; + + sal_Int32 nIndex = 0; + sal_uInt16 nYear = 0, + nMonth = 0, + nDay = 0; + nYear = (sal_uInt16)_sSQLString.getToken(0,sDateSep,nIndex).toInt32(); + if(nIndex != -1) + { + nMonth = (sal_uInt16)_sSQLString.getToken(0,sDateSep,nIndex).toInt32(); + if(nIndex != -1) + nDay = (sal_uInt16)_sSQLString.getToken(0,sDateSep,nIndex).toInt32(); + } + + return Date(nDay,nMonth,nYear); + } + + //----------------------------------------------------------------------------- + DateTime DBTypeConversion::toDateTime(const ::rtl::OUString& _sSQLString) + { + //@see http://java.sun.com/j2se/1.4.2/docs/api/java/sql/Timestamp.html#valueOf(java.lang.String) + //@see http://java.sun.com/j2se/1.4.2/docs/api/java/sql/Date.html#valueOf(java.lang.String) + //@see http://java.sun.com/j2se/1.4.2/docs/api/java/sql/Time.html#valueOf(java.lang.String) + + // the date part + Date aDate = toDate(_sSQLString); + Time aTime; + sal_Int32 nSeparation = _sSQLString.indexOf( ' ' ); + if ( -1 != nSeparation ) + aTime = toTime( _sSQLString.copy( nSeparation ) ); + + return DateTime(aTime.HundredthSeconds,aTime.Seconds,aTime.Minutes,aTime.Hours,aDate.Day,aDate.Month,aDate.Year); + } + + //----------------------------------------------------------------------------- + Time DBTypeConversion::toTime(const ::rtl::OUString& _sSQLString) + { + static sal_Unicode sTimeSep = ':'; + + sal_Int32 nIndex = 0; + sal_uInt16 nHour = 0, + nMinute = 0, + nSecond = 0, + nHundredthSeconds = 0; + nHour = (sal_uInt16)_sSQLString.getToken(0,sTimeSep,nIndex).toInt32(); + if(nIndex != -1) + { + nMinute = (sal_uInt16)_sSQLString.getToken(0,sTimeSep,nIndex).toInt32(); + if(nIndex != -1) + { + nSecond = (sal_uInt16)_sSQLString.getToken(0,sTimeSep,nIndex).toInt32(); + nIndex = 0; + ::rtl::OUString sNano(_sSQLString.getToken(1,'.',nIndex)); + if ( sNano.getLength() ) + { + // our time struct only supports hundredth seconds + sNano = sNano.copy(0,::std::min<sal_Int32>(sNano.getLength(),2)); + const static ::rtl::OUString s_Zeros(RTL_CONSTASCII_USTRINGPARAM("00")); + sNano += s_Zeros.copy(0,s_Zeros.getLength() - sNano.getLength()); + nHundredthSeconds = static_cast<sal_uInt16>(sNano.toInt32()); + } + } + } + return Time(nHundredthSeconds,nSecond,nMinute,nHour); + } + +//......................................................................... +} // namespace dbtools +//......................................................................... + + diff --git a/connectivity/source/commontools/dbexception.cxx b/connectivity/source/commontools/dbexception.cxx new file mode 100644 index 000000000000..e266a5a83d4f --- /dev/null +++ b/connectivity/source/commontools/dbexception.cxx @@ -0,0 +1,564 @@ +/************************************************************************* + * + * 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 <connectivity/dbexception.hxx> +#include <comphelper/types.hxx> +#include <cppuhelper/exc_hlp.hxx> +#include <osl/diagnose.h> +#include <com/sun/star/sdb/SQLContext.hpp> +#include <com/sun/star/sdbc/SQLWarning.hpp> +#include <com/sun/star/sdb/SQLErrorEvent.hpp> +#include "TConnection.hxx" +#include "resource/common_res.hrc" +#include "resource/sharedresources.hxx" + +//......................................................................... +namespace dbtools +{ +//......................................................................... + + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::sdb; + using namespace ::com::sun::star::sdbc; + using namespace ::comphelper; + using namespace ::connectivity; + +//============================================================================== +//= SQLExceptionInfo - encapsulating the type info of an SQLException-derived class +//============================================================================== +//------------------------------------------------------------------------------ +SQLExceptionInfo::SQLExceptionInfo() + :m_eType(UNDEFINED) +{ +} + +//------------------------------------------------------------------------------ +SQLExceptionInfo::SQLExceptionInfo(const ::com::sun::star::sdbc::SQLException& _rError) +{ + m_aContent <<= _rError; + implDetermineType(); +} + +//------------------------------------------------------------------------------ +SQLExceptionInfo::SQLExceptionInfo(const ::com::sun::star::sdbc::SQLWarning& _rError) +{ + m_aContent <<= _rError; + implDetermineType(); +} + +//------------------------------------------------------------------------------ +SQLExceptionInfo::SQLExceptionInfo(const ::com::sun::star::sdb::SQLContext& _rError) +{ + m_aContent <<= _rError; + implDetermineType(); +} + +//------------------------------------------------------------------------------ +SQLExceptionInfo::SQLExceptionInfo( const ::rtl::OUString& _rSimpleErrorMessage ) +{ + SQLException aError; + aError.Message = _rSimpleErrorMessage; + m_aContent <<= aError; + implDetermineType(); +} + +//------------------------------------------------------------------------------ +SQLExceptionInfo::SQLExceptionInfo(const SQLExceptionInfo& _rCopySource) + :m_aContent(_rCopySource.m_aContent) + ,m_eType(_rCopySource.m_eType) +{ +} + +//------------------------------------------------------------------------------ +const SQLExceptionInfo& SQLExceptionInfo::operator=(const ::com::sun::star::sdbc::SQLException& _rError) +{ + m_aContent <<= _rError; + implDetermineType(); + return *this; +} + +//------------------------------------------------------------------------------ +const SQLExceptionInfo& SQLExceptionInfo::operator=(const ::com::sun::star::sdbc::SQLWarning& _rError) +{ + m_aContent <<= _rError; + implDetermineType(); + return *this; +} + +//------------------------------------------------------------------------------ +const SQLExceptionInfo& SQLExceptionInfo::operator=(const ::com::sun::star::sdb::SQLContext& _rError) +{ + m_aContent <<= _rError; + implDetermineType(); + return *this; +} + +//------------------------------------------------------------------------------ +const SQLExceptionInfo& SQLExceptionInfo::operator=(const ::com::sun::star::sdb::SQLErrorEvent& _rErrorEvent) +{ + m_aContent = _rErrorEvent.Reason; + implDetermineType(); + return *this; +} + +//------------------------------------------------------------------------------ +const SQLExceptionInfo& SQLExceptionInfo::operator=(const ::com::sun::star::uno::Any& _rCaughtSQLException) +{ + m_aContent = _rCaughtSQLException; + implDetermineType(); + return *this; +} + +//------------------------------------------------------------------------------ +SQLExceptionInfo::SQLExceptionInfo(const ::com::sun::star::sdb::SQLErrorEvent& _rError) +{ + m_aContent = _rError.Reason; + implDetermineType(); +} + +//------------------------------------------------------------------------------ +SQLExceptionInfo::SQLExceptionInfo(const staruno::Any& _rError) +{ + const staruno::Type& aSQLExceptionType = ::getCppuType(reinterpret_cast< ::com::sun::star::sdbc::SQLException*>(NULL)); + sal_Bool bValid = isAssignableFrom(aSQLExceptionType, _rError.getValueType()); + if (bValid) + m_aContent = _rError; + // no assertion here : if used with the NextException member of an SQLException bValid==sal_False is allowed. + + implDetermineType(); +} + +//------------------------------------------------------------------------------ +void SQLExceptionInfo::implDetermineType() +{ + staruno::Type aContentType = m_aContent.getValueType(); + + const Type& aSQLExceptionType = ::getCppuType( reinterpret_cast< SQLException* >( NULL ) ); + const Type& aSQLWarningType = ::getCppuType( reinterpret_cast< SQLWarning* >( NULL ) ); + const Type& aSQLContextType = ::getCppuType( reinterpret_cast< SQLContext* >( NULL ) ); + + if ( isAssignableFrom( aSQLContextType, m_aContent.getValueType() ) ) + m_eType = SQL_CONTEXT; + else if ( isAssignableFrom( aSQLWarningType, m_aContent.getValueType() ) ) + m_eType = SQL_WARNING; + else if ( isAssignableFrom( aSQLExceptionType, m_aContent.getValueType() ) ) + m_eType = SQL_EXCEPTION; + else + { + m_eType = UNDEFINED; + m_aContent.clear(); + } +} + +//------------------------------------------------------------------------------ +sal_Bool SQLExceptionInfo::isKindOf(TYPE _eType) const +{ + switch (_eType) + { + case SQL_CONTEXT: + return (m_eType == SQL_CONTEXT); + case SQL_WARNING: + return (m_eType == SQL_CONTEXT) || (m_eType == SQL_WARNING); + case SQL_EXCEPTION: + return (m_eType == SQL_CONTEXT) || (m_eType == SQL_WARNING) || (m_eType == SQL_EXCEPTION); + case UNDEFINED: + return (m_eType == UNDEFINED); + } + return sal_False; +} + +//------------------------------------------------------------------------------ +SQLExceptionInfo::operator const ::com::sun::star::sdbc::SQLException*() const +{ + OSL_ENSURE(isKindOf(SQL_EXCEPTION), "SQLExceptionInfo::operator SQLException* : invalid call !"); + return reinterpret_cast<const ::com::sun::star::sdbc::SQLException*>(m_aContent.getValue()); +} + +//------------------------------------------------------------------------------ +SQLExceptionInfo::operator const ::com::sun::star::sdbc::SQLWarning*() const +{ + OSL_ENSURE(isKindOf(SQL_WARNING), "SQLExceptionInfo::operator SQLException* : invalid call !"); + return reinterpret_cast<const ::com::sun::star::sdbc::SQLWarning*>(m_aContent.getValue()); +} + +//------------------------------------------------------------------------------ +SQLExceptionInfo::operator const ::com::sun::star::sdb::SQLContext*() const +{ + OSL_ENSURE(isKindOf(SQL_CONTEXT), "SQLExceptionInfo::operator SQLException* : invalid call !"); + return reinterpret_cast<const ::com::sun::star::sdb::SQLContext*>(m_aContent.getValue()); +} + +//------------------------------------------------------------------------------ +void SQLExceptionInfo::prepend( const ::rtl::OUString& _rErrorMessage, const sal_Char* _pAsciiSQLState, const sal_Int32 _nErrorCode ) +{ + SQLException aException; + aException.Message = _rErrorMessage; + aException.ErrorCode = _nErrorCode; + aException.SQLState = ::rtl::OUString::createFromAscii( _pAsciiSQLState ? _pAsciiSQLState : "S1000" ); + aException.NextException = m_aContent; + m_aContent <<= aException; + + m_eType = SQL_EXCEPTION; +} + +//------------------------------------------------------------------------------ +void SQLExceptionInfo::append( TYPE _eType, const ::rtl::OUString& _rErrorMessage, const sal_Char* _pAsciiSQLState, const sal_Int32 _nErrorCode ) +{ + // create the to-be-appended exception + Any aAppend; + switch ( _eType ) + { + case SQL_EXCEPTION: aAppend <<= SQLException(); break; + case SQL_WARNING: aAppend <<= SQLWarning(); break; + case SQL_CONTEXT: aAppend <<= SQLContext(); break; + default: + OSL_ENSURE( false, "SQLExceptionInfo::append: invalid exception type: this will crash!" ); + break; + } + + SQLException* pAppendException( static_cast< SQLException* >( const_cast< void* >( aAppend.getValue() ) ) ); + pAppendException->Message = _rErrorMessage; + pAppendException->SQLState = ::rtl::OUString::createFromAscii( _pAsciiSQLState ); + pAppendException->ErrorCode = _nErrorCode; + + // find the end of the current chain + Any* pChainIterator = &m_aContent; + SQLException* pLastException = NULL; + const Type& aSQLExceptionType( ::getCppuType< SQLException >() ); + while ( pChainIterator ) + { + if ( !pChainIterator->hasValue() ) + break; + + if ( !isAssignableFrom( aSQLExceptionType, pChainIterator->getValueType() ) ) + break; + + pLastException = static_cast< SQLException* >( const_cast< void* >( pChainIterator->getValue() ) ); + pChainIterator = &pLastException->NextException; + } + + // append + if ( pLastException ) + pLastException->NextException = aAppend; + else + { + m_aContent = aAppend; + m_eType = _eType; + } +} + +//------------------------------------------------------------------------------ +void SQLExceptionInfo::doThrow() +{ + if ( m_aContent.getValueTypeClass() == TypeClass_EXCEPTION ) + ::cppu::throwException( m_aContent ); + throw RuntimeException(); +} + +//============================================================================== +//= SQLExceptionIteratorHelper +//============================================================================== + +//------------------------------------------------------------------------------ +SQLExceptionIteratorHelper::SQLExceptionIteratorHelper( const SQLExceptionInfo& _rChainStart ) + :m_pCurrent( NULL ) + ,m_eCurrentType( SQLExceptionInfo::UNDEFINED ) +{ + if ( _rChainStart.isValid() ) + { + m_pCurrent = (const SQLException*)_rChainStart; + m_eCurrentType = _rChainStart.getType(); + } +} + +//------------------------------------------------------------------------------ +SQLExceptionIteratorHelper::SQLExceptionIteratorHelper( const ::com::sun::star::sdbc::SQLException& _rChainStart ) + :m_pCurrent( &_rChainStart ) + ,m_eCurrentType( SQLExceptionInfo::SQL_EXCEPTION ) +{ +} + +//------------------------------------------------------------------------------ +SQLExceptionIteratorHelper::SQLExceptionIteratorHelper( const ::com::sun::star::sdbc::SQLWarning& _rChainStart ) + :m_pCurrent( &_rChainStart ) + ,m_eCurrentType( SQLExceptionInfo::SQL_WARNING ) +{ +} + +//------------------------------------------------------------------------------ +SQLExceptionIteratorHelper::SQLExceptionIteratorHelper( const ::com::sun::star::sdb::SQLContext& _rChainStart ) + :m_pCurrent( &_rChainStart ) + ,m_eCurrentType( SQLExceptionInfo::SQL_CONTEXT ) +{ +} + +//------------------------------------------------------------------------------ +void SQLExceptionIteratorHelper::current( SQLExceptionInfo& _out_rInfo ) const +{ + switch ( m_eCurrentType ) + { + case SQLExceptionInfo::SQL_EXCEPTION: + _out_rInfo = *m_pCurrent; + break; + + case SQLExceptionInfo::SQL_WARNING: + _out_rInfo = *static_cast< const SQLWarning* >( m_pCurrent ); + break; + + case SQLExceptionInfo::SQL_CONTEXT: + _out_rInfo = *static_cast< const SQLContext* >( m_pCurrent ); + break; + + default: + _out_rInfo = Any(); + break; + } +} + +//------------------------------------------------------------------------------ +const ::com::sun::star::sdbc::SQLException* SQLExceptionIteratorHelper::next() +{ + OSL_ENSURE( hasMoreElements(), "SQLExceptionIteratorHelper::next : invalid call (please use hasMoreElements)!" ); + + const ::com::sun::star::sdbc::SQLException* pReturn = current(); + if ( !m_pCurrent ) + return pReturn; + + // check for the next element within the chain + const Type aTypeException( ::cppu::UnoType< SQLException >::get() ); + + Type aNextElementType = m_pCurrent->NextException.getValueType(); + if ( !isAssignableFrom( aTypeException, aNextElementType ) ) + { + // no SQLException at all in the next chain element + m_pCurrent = NULL; + m_eCurrentType = SQLExceptionInfo::UNDEFINED; + return pReturn; + } + + m_pCurrent = static_cast< const SQLException* >( m_pCurrent->NextException.getValue() ); + + // no finally determine the proper type of the exception + const Type aTypeContext( ::cppu::UnoType< SQLContext >::get() ); + if ( isAssignableFrom( aTypeContext, aNextElementType ) ) + { + m_eCurrentType = SQLExceptionInfo::SQL_CONTEXT; + return pReturn; + } + + const Type aTypeWarning( ::cppu::UnoType< SQLWarning >::get() ); + if ( isAssignableFrom( aTypeWarning, aNextElementType ) ) + { + m_eCurrentType = SQLExceptionInfo::SQL_WARNING; + return pReturn; + } + + // a simple SQLException + m_eCurrentType = SQLExceptionInfo::SQL_EXCEPTION; + return pReturn; +} + +//------------------------------------------------------------------------------ +void SQLExceptionIteratorHelper::next( SQLExceptionInfo& _out_rInfo ) +{ + current( _out_rInfo ); + next(); +} + +//------------------------------------------------------------ +void throwFunctionSequenceException(const Reference< XInterface >& _Context, const Any& _Next) throw ( ::com::sun::star::sdbc::SQLException ) +{ + ::connectivity::SharedResources aResources; + throw SQLException( + aResources.getResourceString(STR_ERRORMSG_SEQUENCE), + _Context, + getStandardSQLState( SQL_FUNCTION_SEQUENCE_ERROR ), + 0, + _Next + ); +} +// ----------------------------------------------------------------------------- +void throwInvalidIndexException(const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& _Context, + const ::com::sun::star::uno::Any& _Next) throw ( ::com::sun::star::sdbc::SQLException ) +{ + ::connectivity::SharedResources aResources; + throw SQLException( + aResources.getResourceString(STR_INVALID_INDEX), + _Context, + getStandardSQLState( SQL_INVALID_DESCRIPTOR_INDEX ), + 0, + _Next + ); +} +// ----------------------------------------------------------------------------- +void throwFunctionNotSupportedException(const ::rtl::OUString& _rMsg, + const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& _Context, + const ::com::sun::star::uno::Any& _Next) throw ( ::com::sun::star::sdbc::SQLException ) +{ + throw SQLException( + _rMsg, + _Context, + getStandardSQLState( SQL_FUNCTION_NOT_SUPPORTED ), + 0, + _Next + ); +} +// ----------------------------------------------------------------------------- +void throwFunctionNotSupportedException( const sal_Char* _pAsciiFunctionName, const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& _rxContext, + const ::com::sun::star::uno::Any* _pNextException ) throw ( ::com::sun::star::sdbc::SQLException ) +{ + ::connectivity::SharedResources aResources; + const ::rtl::OUString sError( aResources.getResourceStringWithSubstitution( + STR_UNSUPPORTED_FUNCTION, + "$functionname$", ::rtl::OUString::createFromAscii( _pAsciiFunctionName ) + ) ); + throw SQLException( + sError, + _rxContext, + getStandardSQLState( SQL_FUNCTION_NOT_SUPPORTED ), + 0, + _pNextException ? *_pNextException : Any() + ); +} +// ----------------------------------------------------------------------------- +void throwGenericSQLException(const ::rtl::OUString& _rMsg, const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& _rxSource) + throw (::com::sun::star::sdbc::SQLException) +{ + throwGenericSQLException(_rMsg, _rxSource, Any()); +} + +// ----------------------------------------------------------------------------- +void throwGenericSQLException(const ::rtl::OUString& _rMsg, const Reference< XInterface >& _rxSource, const Any& _rNextException) + throw (SQLException) +{ + throw SQLException( _rMsg, _rxSource, getStandardSQLState( SQL_GENERAL_ERROR ), 0, _rNextException); +} + +// ----------------------------------------------------------------------------- +void throwFeatureNotImplementedException( const sal_Char* _pAsciiFeatureName, const Reference< XInterface >& _rxContext, const Any* _pNextException ) + throw (SQLException) +{ + ::connectivity::SharedResources aResources; + const ::rtl::OUString sError( aResources.getResourceStringWithSubstitution( + STR_UNSUPPORTED_FEATURE, + "$featurename$", ::rtl::OUString::createFromAscii( _pAsciiFeatureName ) + ) ); + + throw SQLException( + sError, + _rxContext, + getStandardSQLState( SQL_FEATURE_NOT_IMPLEMENTED ), + 0, + _pNextException ? *_pNextException : Any() + ); +} + +// ----------------------------------------------------------------------------- +void throwSQLException( const sal_Char* _pAsciiMessage, const sal_Char* _pAsciiState, + const Reference< XInterface >& _rxContext, const sal_Int32 _nErrorCode, const Any* _pNextException ) throw (SQLException) +{ + throw SQLException( + ::rtl::OUString::createFromAscii( _pAsciiMessage ), + _rxContext, + ::rtl::OUString::createFromAscii( _pAsciiState ), + _nErrorCode, + _pNextException ? *_pNextException : Any() + ); +} + +// ----------------------------------------------------------------------------- +void throwSQLException( const sal_Char* _pAsciiMessage, StandardSQLState _eSQLState, + const Reference< XInterface >& _rxContext, const sal_Int32 _nErrorCode, + const Any* _pNextException ) throw (SQLException) +{ + throwSQLException( _pAsciiMessage, getStandardSQLStateAscii( _eSQLState ), _rxContext, _nErrorCode, _pNextException ); +} + +// ----------------------------------------------------------------------------- +void throwSQLException( const ::rtl::OUString& _rMessage, StandardSQLState _eSQLState, + const Reference< XInterface >& _rxContext, const sal_Int32 _nErrorCode, + const Any* _pNextException ) throw (SQLException) +{ + throw SQLException( + _rMessage, + _rxContext, + getStandardSQLState( _eSQLState ), + _nErrorCode, + _pNextException ? *_pNextException : Any() + ); +} + +// ----------------------------------------------------------------------------- +const sal_Char* getStandardSQLStateAscii( StandardSQLState _eState ) +{ + const sal_Char* pAsciiState = NULL; + switch ( _eState ) + { + case SQL_WRONG_PARAMETER_NUMBER: pAsciiState = "07001"; break; + case SQL_INVALID_DESCRIPTOR_INDEX: pAsciiState = "07009"; break; + case SQL_UNABLE_TO_CONNECT: pAsciiState = "08001"; break; + case SQL_NUMERIC_OUT_OF_RANGE: pAsciiState = "22003"; break; + case SQL_INVALID_DATE_TIME: pAsciiState = "22007"; break; + case SQL_INVALID_CURSOR_STATE: pAsciiState = "24000"; break; + case SQL_TABLE_OR_VIEW_EXISTS: pAsciiState = "42S01"; break; + case SQL_TABLE_OR_VIEW_NOT_FOUND: pAsciiState = "42S02"; break; + case SQL_INDEX_ESISTS: pAsciiState = "42S11"; break; + case SQL_INDEX_NOT_FOUND: pAsciiState = "42S12"; break; + case SQL_COLUMN_EXISTS: pAsciiState = "42S21"; break; + case SQL_COLUMN_NOT_FOUND: pAsciiState = "42S22"; break; + case SQL_GENERAL_ERROR: pAsciiState = "HY000"; break; + case SQL_INVALID_SQL_DATA_TYPE: pAsciiState = "HY004"; break; + case SQL_OPERATION_CANCELED: pAsciiState = "HY008"; break; + case SQL_FUNCTION_SEQUENCE_ERROR: pAsciiState = "HY010"; break; + case SQL_INVALID_CURSOR_POSITION: pAsciiState = "HY109"; break; + case SQL_INVALID_BOOKMARK_VALUE: pAsciiState = "HY111"; break; + case SQL_FEATURE_NOT_IMPLEMENTED: pAsciiState = "HYC00"; break; + case SQL_FUNCTION_NOT_SUPPORTED: pAsciiState = "IM001"; break; + case SQL_CONNECTION_DOES_NOT_EXIST: pAsciiState = "08003"; break; + + default: + break; + } + if ( !pAsciiState ) + throw RuntimeException(); + return pAsciiState; +} + +// ----------------------------------------------------------------------------- +::rtl::OUString getStandardSQLState( StandardSQLState _eState ) +{ + return ::rtl::OUString::createFromAscii( getStandardSQLStateAscii( _eState ) ); +} + +// ----------------------------------------------------------------------------- +//......................................................................... +} // namespace dbtools +//......................................................................... + + diff --git a/connectivity/source/commontools/dbmetadata.cxx b/connectivity/source/commontools/dbmetadata.cxx new file mode 100644 index 000000000000..04754ecb2f19 --- /dev/null +++ b/connectivity/source/commontools/dbmetadata.cxx @@ -0,0 +1,448 @@ +/************************************************************************* + * + * 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 "connectivity/dbmetadata.hxx" +#include "connectivity/dbexception.hxx" +#include "connectivity/DriversConfig.hxx" +#include "resource/common_res.hrc" +#include "resource/sharedresources.hxx" + +/** === begin UNO includes === **/ +#include <com/sun/star/lang/IllegalArgumentException.hpp> +#include <com/sun/star/container/XChild.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/beans/XPropertySetInfo.hpp> +#include <com/sun/star/sdb/BooleanComparisonMode.hpp> +#include <com/sun/star/sdbc/XDatabaseMetaData2.hpp> +#include <com/sun/star/sdbcx/XUsersSupplier.hpp> +#include <com/sun/star/sdbcx/XDataDefinitionSupplier.hpp> +#include <com/sun/star/sdbc/XDriverAccess.hpp> +/** === end UNO includes === **/ + +#include <tools/diagnose_ex.h> +#include <comphelper/namedvaluecollection.hxx> +#include <comphelper/componentcontext.hxx> +#include <comphelper/processfactory.hxx> + +#include <boost/optional.hpp> + +//........................................................................ +namespace dbtools +{ +//........................................................................ + + /** === begin UNO using === **/ + using ::com::sun::star::uno::Reference; + using ::com::sun::star::sdbc::XConnection; + using ::com::sun::star::sdbc::XConnection; + using ::com::sun::star::sdbc::XDatabaseMetaData; + using ::com::sun::star::sdbc::XDatabaseMetaData2; + using ::com::sun::star::lang::IllegalArgumentException; + using ::com::sun::star::uno::Exception; + using ::com::sun::star::uno::Any; + using ::com::sun::star::container::XChild; + using ::com::sun::star::uno::UNO_QUERY_THROW; + using ::com::sun::star::beans::XPropertySet; + using ::com::sun::star::uno::Sequence; + using ::com::sun::star::beans::PropertyValue; + using ::com::sun::star::beans::XPropertySetInfo; + using ::com::sun::star::uno::UNO_QUERY; + using ::com::sun::star::sdbcx::XUsersSupplier; + using ::com::sun::star::sdbcx::XDataDefinitionSupplier; + using ::com::sun::star::sdbc::XDriverAccess; + using ::com::sun::star::uno::UNO_SET_THROW; + /** === end UNO using === **/ + namespace BooleanComparisonMode = ::com::sun::star::sdb::BooleanComparisonMode; + + //==================================================================== + //= DatabaseMetaData_Impl + //==================================================================== + struct DatabaseMetaData_Impl + { + Reference< XConnection > xConnection; + Reference< XDatabaseMetaData > xConnectionMetaData; + ::connectivity::DriversConfig aDriverConfig; + + ::boost::optional< ::rtl::OUString > sCachedIdentifierQuoteString; + ::boost::optional< ::rtl::OUString > sCachedCatalogSeparator; + + DatabaseMetaData_Impl() + :xConnection() + ,xConnectionMetaData() + ,aDriverConfig( ::comphelper::getProcessServiceFactory() ) + ,sCachedIdentifierQuoteString() + ,sCachedCatalogSeparator() + { + } + }; + + //-------------------------------------------------------------------- + namespace + { + //................................................................ + static void lcl_construct( DatabaseMetaData_Impl& _metaDataImpl, const Reference< XConnection >& _connection ) + { + _metaDataImpl.xConnection = _connection; + if ( !_metaDataImpl.xConnection.is() ) + return; + + _metaDataImpl.xConnectionMetaData = _connection->getMetaData(); + if ( !_metaDataImpl.xConnectionMetaData.is() ) + throw IllegalArgumentException(); + } + + //................................................................ + static void lcl_checkConnected( const DatabaseMetaData_Impl& _metaDataImpl ) + { + if ( !_metaDataImpl.xConnection.is() || !_metaDataImpl.xConnectionMetaData.is() ) + { + ::connectivity::SharedResources aResources; + const ::rtl::OUString sError( aResources.getResourceString(STR_NO_CONNECTION_GIVEN)); + throwSQLException( sError, SQL_CONNECTION_DOES_NOT_EXIST, NULL ); + } + } + + //................................................................ + static bool lcl_getDriverSetting( const sal_Char* _asciiName, const DatabaseMetaData_Impl& _metaData, Any& _out_setting ) + { + lcl_checkConnected( _metaData ); + const ::comphelper::NamedValueCollection& rDriverMetaData = _metaData.aDriverConfig.getMetaData( _metaData.xConnectionMetaData->getURL() ); + if ( !rDriverMetaData.has( _asciiName ) ) + return false; + _out_setting = rDriverMetaData.get( _asciiName ); + return true; + } + + //................................................................ + static bool lcl_getConnectionSetting( const sal_Char* _asciiName, const DatabaseMetaData_Impl& _metaData, Any& _out_setting ) + { + try + { + Reference< XChild > xConnectionAsChild( _metaData.xConnection, UNO_QUERY ); + if ( xConnectionAsChild.is() ) + { + Reference< XPropertySet > xDataSource( xConnectionAsChild->getParent(), UNO_QUERY_THROW ); + Reference< XPropertySet > xDataSourceSettings( + xDataSource->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Settings" ) ) ), + UNO_QUERY_THROW ); + + _out_setting = xDataSourceSettings->getPropertyValue( ::rtl::OUString::createFromAscii( _asciiName ) ); + } + else + { + Reference< XDatabaseMetaData2 > xExtendedMetaData( _metaData.xConnectionMetaData, UNO_QUERY_THROW ); + ::comphelper::NamedValueCollection aSettings( xExtendedMetaData->getConnectionInfo() ); + _out_setting = aSettings.get( _asciiName ); + return _out_setting.hasValue(); + } + return true; + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + return false; + } + + //................................................................ + static const ::rtl::OUString& lcl_getConnectionStringSetting( + const DatabaseMetaData_Impl& _metaData, ::boost::optional< ::rtl::OUString >& _cachedSetting, + ::rtl::OUString (SAL_CALL XDatabaseMetaData::*_getter)() ) + { + if ( !_cachedSetting ) + { + lcl_checkConnected( _metaData ); + try + { + _cachedSetting.reset( (_metaData.xConnectionMetaData.get()->*_getter)() ); + } + catch( const Exception& ) { DBG_UNHANDLED_EXCEPTION(); } + } + return *_cachedSetting; + } + } + + //==================================================================== + //= DatabaseMetaData + //==================================================================== + //-------------------------------------------------------------------- + DatabaseMetaData::DatabaseMetaData() + :m_pImpl( new DatabaseMetaData_Impl ) + { + } + + //-------------------------------------------------------------------- + DatabaseMetaData::DatabaseMetaData( const Reference< XConnection >& _connection ) + :m_pImpl( new DatabaseMetaData_Impl ) + { + lcl_construct( *m_pImpl, _connection ); + } + + //-------------------------------------------------------------------- + DatabaseMetaData::DatabaseMetaData( const DatabaseMetaData& _copyFrom ) + :m_pImpl( new DatabaseMetaData_Impl( *_copyFrom.m_pImpl ) ) + { + } + + //-------------------------------------------------------------------- + DatabaseMetaData& DatabaseMetaData::operator=( const DatabaseMetaData& _copyFrom ) + { + if ( this == &_copyFrom ) + return *this; + + m_pImpl.reset( new DatabaseMetaData_Impl( *_copyFrom.m_pImpl ) ); + return *this; + } + + //-------------------------------------------------------------------- + DatabaseMetaData::~DatabaseMetaData() + { + } + + //-------------------------------------------------------------------- + bool DatabaseMetaData::isConnected() const + { + return m_pImpl->xConnection.is(); + } + + //-------------------------------------------------------------------- + bool DatabaseMetaData::supportsSubqueriesInFrom() const + { + lcl_checkConnected( *m_pImpl ); + + bool supportsSubQueries = false; + try + { + sal_Int32 maxTablesInselect = m_pImpl->xConnectionMetaData->getMaxTablesInSelect(); + supportsSubQueries = ( maxTablesInselect > 1 ) || ( maxTablesInselect == 0 ); + // TODO: is there a better way to determine this? The above is not really true. More precise, + // it's a *very* generous heuristics ... + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + return supportsSubQueries; + } + + //-------------------------------------------------------------------- + bool DatabaseMetaData::supportsPrimaryKeys() const + { + lcl_checkConnected( *m_pImpl ); + + bool doesSupportPrimaryKeys = false; + try + { + Any setting; + if ( !( lcl_getConnectionSetting( "PrimaryKeySupport", *m_pImpl, setting ) ) + || !( setting >>= doesSupportPrimaryKeys ) + ) + doesSupportPrimaryKeys = m_pImpl->xConnectionMetaData->supportsCoreSQLGrammar(); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + return doesSupportPrimaryKeys; + } + + //-------------------------------------------------------------------- + const ::rtl::OUString& DatabaseMetaData::getIdentifierQuoteString() const + { + return lcl_getConnectionStringSetting( *m_pImpl, m_pImpl->sCachedIdentifierQuoteString, &XDatabaseMetaData::getIdentifierQuoteString ); + } + + //-------------------------------------------------------------------- + const ::rtl::OUString& DatabaseMetaData::getCatalogSeparator() const + { + return lcl_getConnectionStringSetting( *m_pImpl, m_pImpl->sCachedCatalogSeparator, &XDatabaseMetaData::getCatalogSeparator ); + } + + //-------------------------------------------------------------------- + bool DatabaseMetaData::restrictIdentifiersToSQL92() const + { + lcl_checkConnected( *m_pImpl ); + + bool restrict( false ); + Any setting; + if ( lcl_getConnectionSetting( "EnableSQL92Check", *m_pImpl, setting ) ) + OSL_VERIFY( setting >>= restrict ); + return restrict; + } + + //-------------------------------------------------------------------- + bool DatabaseMetaData::generateASBeforeCorrelationName() const + { + bool doGenerate( true ); + Any setting; + if ( lcl_getConnectionSetting( "GenerateASBeforeCorrelationName", *m_pImpl, setting ) ) + OSL_VERIFY( setting >>= doGenerate ); + return doGenerate; + } + //-------------------------------------------------------------------- + bool DatabaseMetaData::shouldEscapeDateTime() const + { + bool doGenerate( true ); + Any setting; + if ( lcl_getConnectionSetting( "EscapeDateTime", *m_pImpl, setting ) ) + OSL_VERIFY( setting >>= doGenerate ); + return doGenerate; + } + //-------------------------------------------------------------------- + bool DatabaseMetaData::isAutoIncrementPrimaryKey() const + { + bool is( true ); + Any setting; + if ( lcl_getDriverSetting( "AutoIncrementIsPrimaryKey", *m_pImpl, setting ) ) + OSL_VERIFY( setting >>= is ); + return is; + } + //-------------------------------------------------------------------- + sal_Int32 DatabaseMetaData::getBooleanComparisonMode() const + { + sal_Int32 mode( BooleanComparisonMode::EQUAL_INTEGER ); + Any setting; + if ( lcl_getConnectionSetting( "BooleanComparisonMode", *m_pImpl, setting ) ) + OSL_VERIFY( setting >>= mode ); + return mode; + } + //-------------------------------------------------------------------- + bool DatabaseMetaData::supportsRelations() const + { + lcl_checkConnected( *m_pImpl ); + bool bSupport = false; + try + { + bSupport = m_pImpl->xConnectionMetaData->supportsIntegrityEnhancementFacility(); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + try + { + if ( !bSupport ) + { + const ::rtl::OUString url = m_pImpl->xConnectionMetaData->getURL(); + char pMySQL[] = "sdbc:mysql"; + bSupport = url.matchAsciiL(pMySQL,(sizeof(pMySQL)/sizeof(pMySQL[0]))-1); + } + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + return bSupport; + } + + //-------------------------------------------------------------------- + bool DatabaseMetaData::supportsColumnAliasInOrderBy() const + { + bool doGenerate( true ); + Any setting; + if ( lcl_getConnectionSetting( "ColumnAliasInOrderBy", *m_pImpl, setting ) ) + OSL_VERIFY( setting >>= doGenerate ); + return doGenerate; + } + + //-------------------------------------------------------------------- + bool DatabaseMetaData::supportsUserAdministration( const ::comphelper::ComponentContext& _rContext ) const + { + lcl_checkConnected( *m_pImpl ); + + bool isSupported( false ); + try + { + // find the XUsersSupplier interface + // - either directly at the connection + Reference< XUsersSupplier > xUsersSupp( m_pImpl->xConnection, UNO_QUERY ); + if ( !xUsersSupp.is() ) + { + // - or at the driver manager + Reference< XDriverAccess > xDriverManager( + _rContext.createComponent( "com.sun.star.sdbc.DriverManager" ), UNO_QUERY_THROW ); + Reference< XDataDefinitionSupplier > xDriver( xDriverManager->getDriverByURL( m_pImpl->xConnectionMetaData->getURL() ), UNO_QUERY ); + if ( xDriver.is() ) + xUsersSupp.set( xDriver->getDataDefinitionByConnection( m_pImpl->xConnection ), UNO_QUERY ); + } + + isSupported = ( xUsersSupp.is() && xUsersSupp->getUsers().is() ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + return isSupported; + } + + //-------------------------------------------------------------------- + bool DatabaseMetaData::displayEmptyTableFolders() const + { + bool doDisplay( true ); +#ifdef IMPLEMENTED_LATER + Any setting; + if ( lcl_getConnectionSetting( "DisplayEmptyTableFolders", *m_pImpl, setting ) ) + OSL_VERIFY( setting >>= doDisplay ); +#else + try + { + Reference< XDatabaseMetaData > xMeta( m_pImpl->xConnectionMetaData, UNO_SET_THROW ); + ::rtl::OUString sConnectionURL( xMeta->getURL() ); + doDisplay = sConnectionURL.compareToAscii( RTL_CONSTASCII_STRINGPARAM( "sdbc:mysql:mysqlc" ) ) == 0; + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } +#endif + return doDisplay; + } + //-------------------------------------------------------------------- + bool DatabaseMetaData::supportsThreads() const + { + bool bSupported( true ); + try + { + Reference< XDatabaseMetaData > xMeta( m_pImpl->xConnectionMetaData, UNO_SET_THROW ); + ::rtl::OUString sConnectionURL( xMeta->getURL() ); + bSupported = sConnectionURL.compareToAscii( RTL_CONSTASCII_STRINGPARAM( "sdbc:mysql:mysqlc" ) ) != 0; + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + return bSupported; + } + +//........................................................................ +} // namespace dbtools +//........................................................................ + diff --git a/connectivity/source/commontools/dbtools.cxx b/connectivity/source/commontools/dbtools.cxx new file mode 100644 index 000000000000..05bcf997268f --- /dev/null +++ b/connectivity/source/commontools/dbtools.cxx @@ -0,0 +1,2173 @@ +/************************************************************************* + * + * 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 "connectivity/CommonTools.hxx" +#include "diagnose_ex.h" +#include "TConnection.hxx" +#include "connectivity/ParameterCont.hxx" + +/** === begin UNO includes === **/ +#include <com/sun/star/awt/XWindow.hpp> +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/container/XChild.hpp> +#include <com/sun/star/form/FormComponentType.hpp> +#include <com/sun/star/io/XInputStream.hpp> +#include <com/sun/star/lang/DisposedException.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/sdb/BooleanComparisonMode.hpp> +#include <com/sun/star/sdb/CommandType.hpp> +#include <com/sun/star/sdb/ParametersRequest.hpp> +#include <com/sun/star/sdb/RowSetVetoException.hpp> +#include <com/sun/star/sdb/SQLContext.hpp> +#include <com/sun/star/sdb/XCompletedConnection.hpp> +#include <com/sun/star/sdb/XInteractionSupplyParameters.hpp> +#include <com/sun/star/sdb/XOfficeDatabaseDocument.hpp> +#include <com/sun/star/sdb/XParametersSupplier.hpp> +#include <com/sun/star/sdb/XQueriesSupplier.hpp> +#include <com/sun/star/sdb/XSingleSelectQueryComposer.hpp> +#include <com/sun/star/sdbc/DataType.hpp> +#include <com/sun/star/sdbc/XConnection.hpp> +#include <com/sun/star/sdbc/XDataSource.hpp> +#include <com/sun/star/sdbc/XDriverManager.hpp> +#include <com/sun/star/sdbc/XParameters.hpp> +#include <com/sun/star/sdbc/XRow.hpp> +#include <com/sun/star/sdbc/XRowSet.hpp> +#include <com/sun/star/sdbc/XRowUpdate.hpp> +#include <com/sun/star/sdbcx/KeyType.hpp> +#include <com/sun/star/sdbcx/Privilege.hpp> +#include <com/sun/star/sdbcx/XColumnsSupplier.hpp> +#include <com/sun/star/sdbcx/XKeysSupplier.hpp> +#include <com/sun/star/sdbcx/XTablesSupplier.hpp> +#include <com/sun/star/task/XInteractionHandler.hpp> +#include <com/sun/star/task/XInteractionRequest.hpp> +#include <com/sun/star/ui/dialogs/XExecutableDialog.hpp> +#include <com/sun/star/uno/XNamingService.hpp> +#include <com/sun/star/util/NumberFormat.hpp> +#include <com/sun/star/util/XNumberFormatsSupplier.hpp> +#include <com/sun/star/util/XNumberFormatTypes.hpp> +/** === end UNO includes === **/ + +#include <comphelper/extract.hxx> +#include <comphelper/interaction.hxx> +#include <comphelper/property.hxx> +#include <connectivity/conncleanup.hxx> +#include <connectivity/dbconversion.hxx> +#include <connectivity/dbexception.hxx> +#include <connectivity/dbtools.hxx> +#include <connectivity/statementcomposer.hxx> +#include <osl/diagnose.h> +#include <rtl/ustrbuf.hxx> +#include <tools/diagnose_ex.h> + +#include "resource/common_res.hrc" +#include "resource/sharedresources.hxx" +#include "OSubComponent.hxx" + +#include <algorithm> + +using namespace ::comphelper; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::io; +using namespace ::com::sun::star::awt; +using namespace ::com::sun::star::ui::dialogs; +using namespace ::com::sun::star::util; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::sdb; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::form; +using namespace connectivity; + +//......................................................................... +namespace dbtools +{ +//......................................................................... + + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::beans; + using namespace ::com::sun::star::util; + using namespace ::com::sun::star::task; + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::lang; + using namespace ::com::sun::star::sdbc; + using namespace ::com::sun::star::task; +// using namespace cppu; +// using namespace osl; + +//============================================================================== +//============================================================================== +namespace +{ + typedef sal_Bool (SAL_CALL XDatabaseMetaData::*FMetaDataSupport)(); +} +//============================================================================== +//============================================================================== +sal_Int32 getDefaultNumberFormat(const Reference< XPropertySet >& _xColumn, + const Reference< XNumberFormatTypes >& _xTypes, + const Locale& _rLocale) +{ + OSL_ENSURE(_xTypes.is() && _xColumn.is(), "dbtools::getDefaultNumberFormat: invalid arg !"); + if (!_xTypes.is() || !_xColumn.is()) + return NumberFormat::UNDEFINED; + + sal_Int32 nDataType = 0; + sal_Int32 nScale = 0; + try + { + // determine the datatype of the column + _xColumn->getPropertyValue(::rtl::OUString::createFromAscii("Type")) >>= nDataType; + + if (DataType::NUMERIC == nDataType || DataType::DECIMAL == nDataType) + _xColumn->getPropertyValue(::rtl::OUString::createFromAscii("Scale")) >>= nScale; + } + catch (Exception&) + { + return NumberFormat::UNDEFINED; + } + return getDefaultNumberFormat(nDataType, + nScale, + ::cppu::any2bool(_xColumn->getPropertyValue(::rtl::OUString::createFromAscii("IsCurrency"))), + _xTypes, + _rLocale); +} + +//------------------------------------------------------------------ +sal_Int32 getDefaultNumberFormat(sal_Int32 _nDataType, + sal_Int32 _nScale, + sal_Bool _bIsCurrency, + const Reference< XNumberFormatTypes >& _xTypes, + const Locale& _rLocale) +{ + OSL_ENSURE(_xTypes.is() , "dbtools::getDefaultNumberFormat: invalid arg !"); + if (!_xTypes.is()) + return NumberFormat::UNDEFINED; + + sal_Int32 nFormat = 0; + sal_Int32 nNumberType = _bIsCurrency ? NumberFormat::CURRENCY : NumberFormat::NUMBER; + switch (_nDataType) + { + case DataType::BIT: + case DataType::BOOLEAN: + nFormat = _xTypes->getStandardFormat(NumberFormat::LOGICAL, _rLocale); + break; + case DataType::TINYINT: + case DataType::SMALLINT: + case DataType::INTEGER: + case DataType::BIGINT: + case DataType::FLOAT: + case DataType::REAL: + case DataType::DOUBLE: + case DataType::NUMERIC: + case DataType::DECIMAL: + { + try + { + nFormat = _xTypes->getStandardFormat((sal_Int16)nNumberType, _rLocale); + if(_nScale > 0) + { + // generate a new format if necessary + Reference< XNumberFormats > xFormats(_xTypes, UNO_QUERY); + ::rtl::OUString sNewFormat = xFormats->generateFormat( 0L, _rLocale, sal_False, sal_False, (sal_Int16)_nScale, sal_True); + + // and add it to the formatter if necessary + nFormat = xFormats->queryKey(sNewFormat, _rLocale, sal_False); + if (nFormat == (sal_Int32)-1) + nFormat = xFormats->addNew(sNewFormat, _rLocale); + } + } + catch (Exception&) + { + nFormat = _xTypes->getStandardFormat((sal_Int16)nNumberType, _rLocale); + } + } break; + case DataType::CHAR: + case DataType::VARCHAR: + case DataType::LONGVARCHAR: + case DataType::CLOB: + nFormat = _xTypes->getStandardFormat(NumberFormat::TEXT, _rLocale); + break; + case DataType::DATE: + nFormat = _xTypes->getStandardFormat(NumberFormat::DATE, _rLocale); + break; + case DataType::TIME: + nFormat = _xTypes->getStandardFormat(NumberFormat::TIME, _rLocale); + break; + case DataType::TIMESTAMP: + nFormat = _xTypes->getStandardFormat(NumberFormat::DATETIME, _rLocale); + break; + case DataType::BINARY: + case DataType::VARBINARY: + case DataType::LONGVARBINARY: + case DataType::SQLNULL: + case DataType::OTHER: + case DataType::OBJECT: + case DataType::DISTINCT: + case DataType::STRUCT: + case DataType::ARRAY: + case DataType::BLOB: + case DataType::REF: + default: + nFormat = _xTypes->getStandardFormat(NumberFormat::UNDEFINED, _rLocale); + //nFormat = NumberFormat::UNDEFINED; + } + return nFormat; +} + +//============================================================================== +//------------------------------------------------------------------------------ +Reference< XConnection> findConnection(const Reference< XInterface >& xParent) +{ + Reference< XConnection> xConnection(xParent, UNO_QUERY); + if (!xConnection.is()) + { + Reference< XChild> xChild(xParent, UNO_QUERY); + if (xChild.is()) + xConnection = findConnection(xChild->getParent()); + } + return xConnection; +} + +//------------------------------------------------------------------------------ +Reference< XDataSource> getDataSource_allowException( + const ::rtl::OUString& _rsTitleOrPath, + const Reference< XMultiServiceFactory >& _rxFactory ) +{ + OSL_ENSURE( _rsTitleOrPath.getLength(), "getDataSource_allowException: invalid arg !" ); + + Reference< XNameAccess> xDatabaseContext( + _rxFactory->createInstance( + ::rtl::OUString::createFromAscii( "com.sun.star.sdb.DatabaseContext" ) ),UNO_QUERY ); + OSL_ENSURE( xDatabaseContext.is(), "getDataSource_allowException: could not obtain the database context!" ); + + return Reference< XDataSource >( xDatabaseContext->getByName( _rsTitleOrPath ), UNO_QUERY ); +} + +//------------------------------------------------------------------------------ +Reference< XDataSource > getDataSource( + const ::rtl::OUString& _rsTitleOrPath, + const Reference< XMultiServiceFactory >& _rxFactory ) +{ + Reference< XDataSource > xDS; + try + { + xDS = getDataSource_allowException( _rsTitleOrPath, _rxFactory ); + } + catch(Exception) + { + } + + return xDS; +} + +//------------------------------------------------------------------------------ +Reference< XConnection > getConnection_allowException( + const ::rtl::OUString& _rsTitleOrPath, + const ::rtl::OUString& _rsUser, + const ::rtl::OUString& _rsPwd, + const Reference< XMultiServiceFactory>& _rxFactory) +{ + Reference< XDataSource> xDataSource( getDataSource_allowException(_rsTitleOrPath, _rxFactory) ); + Reference<XConnection> xConnection; + if (xDataSource.is()) + { + // do it with interaction handler + if(!_rsUser.getLength() || !_rsPwd.getLength()) + { + Reference<XPropertySet> xProp(xDataSource,UNO_QUERY); + ::rtl::OUString sPwd, sUser; + sal_Bool bPwdReq = sal_False; + try + { + xProp->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_PASSWORD)) >>= sPwd; + bPwdReq = ::cppu::any2bool(xProp->getPropertyValue(::rtl::OUString::createFromAscii("IsPasswordRequired"))); + xProp->getPropertyValue(::rtl::OUString::createFromAscii("User")) >>= sUser; + } + catch(Exception&) + { + OSL_ENSURE(sal_False, "dbtools::getConnection: error while retrieving data source properties!"); + } + if(bPwdReq && !sPwd.getLength()) + { // password required, but empty -> connect using an interaction handler + Reference<XCompletedConnection> xConnectionCompletion(xProp, UNO_QUERY); + if (xConnectionCompletion.is()) + { // instantiate the default SDB interaction handler + Reference< XInteractionHandler > xHandler(_rxFactory->createInstance(::rtl::OUString::createFromAscii("com.sun.star.task.InteractionHandler")), UNO_QUERY); + OSL_ENSURE(xHandler.is(), "dbtools::getConnection service com.sun.star.task.InteractionHandler not available!"); + if (xHandler.is()) + { + xConnection = xConnectionCompletion->connectWithCompletion(xHandler); + } + } + } + else + xConnection = xDataSource->getConnection(sUser, sPwd); + } + if(!xConnection.is()) // try to get one if not already have one, just to make sure + xConnection = xDataSource->getConnection(_rsUser, _rsPwd); + } + return xConnection; +} + +//------------------------------------------------------------------------------ +Reference< XConnection> getConnection_withFeedback(const ::rtl::OUString& _rDataSourceName, + const ::rtl::OUString& _rUser, const ::rtl::OUString& _rPwd, const Reference< XMultiServiceFactory>& _rxFactory) + SAL_THROW ( (SQLException) ) +{ + Reference< XConnection > xReturn; + try + { + xReturn = getConnection_allowException(_rDataSourceName, _rUser, _rPwd, _rxFactory); + } + catch(SQLException&) + { + // allowed to pass + throw; + } + catch(Exception&) + { + OSL_ENSURE(sal_False, "::dbtools::getConnection_withFeedback: unexpected (non-SQL) exception caught!"); + } + return xReturn; +} + +//------------------------------------------------------------------------------ +Reference< XConnection> getConnection( + const ::rtl::OUString& _rsTitleOrPath, + const ::rtl::OUString& _rsUser, + const ::rtl::OUString& _rsPwd, + const Reference< XMultiServiceFactory>& _rxFactory) +{ + Reference< XConnection > xReturn; + try + { + xReturn = getConnection_allowException(_rsTitleOrPath, _rsUser, _rsPwd, _rxFactory); + } + catch(Exception&) + { + } + + // TODO: if there were not dozens of places which rely on getConnection not throwing an exception .... + // I would change this ... + + return xReturn; +} + +//------------------------------------------------------------------------------ +Reference< XConnection> getConnection(const Reference< XRowSet>& _rxRowSet) throw (RuntimeException) +{ + Reference< XConnection> xReturn; + Reference< XPropertySet> xRowSetProps(_rxRowSet, UNO_QUERY); + if (xRowSetProps.is()) + xRowSetProps->getPropertyValue(::rtl::OUString::createFromAscii("ActiveConnection")) >>= xReturn; + return xReturn; +} + +//------------------------------------------------------------------------------ +// helper function which allows to implement both the connectRowset and the ensureRowSetConnection semantics +// if connectRowset (which is deprecated) is removed, this function and one of its parameters are +// not needed anymore, the whole implementation can be moved into ensureRowSetConnection then) +SharedConnection lcl_connectRowSet(const Reference< XRowSet>& _rxRowSet, const Reference< XMultiServiceFactory>& _rxFactory, + bool _bSetAsActiveConnection, bool _bAttachAutoDisposer ) + SAL_THROW ( ( SQLException, WrappedTargetException, RuntimeException ) ) +{ + SharedConnection xConnection; + + do + { + Reference< XPropertySet> xRowSetProps(_rxRowSet, UNO_QUERY); + if ( !xRowSetProps.is() ) + break; + + // 1. already connected? + Reference< XConnection > xExistingConn( + xRowSetProps->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ActiveConnection" ) ) ), + UNO_QUERY ); + + if ( xExistingConn.is() + // 2. embedded in a database? + || isEmbeddedInDatabase( _rxRowSet, xExistingConn ) + // 3. is there a connection in the parent hierarchy? + || ( xExistingConn = findConnection( _rxRowSet ) ).is() + ) + { + if ( _bSetAsActiveConnection ) + { + xRowSetProps->setPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ActiveConnection" ) ), makeAny( xExistingConn ) ); + // no auto disposer needed, since we did not create the connection + } + + xConnection.reset( xExistingConn, SharedConnection::NoTakeOwnership ); + break; + } + + // build a connection with it's current settings (4. data source name, or 5. URL) + + const ::rtl::OUString sUserProp = ::rtl::OUString::createFromAscii("User"); + ::rtl::OUString sDataSourceName; + xRowSetProps->getPropertyValue(::rtl::OUString::createFromAscii("DataSourceName")) >>= sDataSourceName; + ::rtl::OUString sURL; + xRowSetProps->getPropertyValue(::rtl::OUString::createFromAscii("URL")) >>= sURL; + + Reference< XConnection > xPureConnection; + if (sDataSourceName.getLength()) + { // the row set's data source property is set + // -> try to connect, get user and pwd setting for that + ::rtl::OUString sUser, sPwd; + + if (hasProperty(sUserProp, xRowSetProps)) + xRowSetProps->getPropertyValue(sUserProp) >>= sUser; + if (hasProperty(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_PASSWORD), xRowSetProps)) + xRowSetProps->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_PASSWORD)) >>= sPwd; + + xPureConnection = getConnection_allowException( sDataSourceName, sUser, sPwd, _rxFactory ); + } + else if (sURL.getLength()) + { // the row set has no data source, but a connection url set + // -> try to connection with that url + Reference< XDriverManager > xDriverManager( + _rxFactory->createInstance( ::rtl::OUString::createFromAscii("com.sun.star.sdbc.ConnectionPool")), UNO_QUERY); + if (xDriverManager.is()) + { + ::rtl::OUString sUser, sPwd; + if (hasProperty(sUserProp, xRowSetProps)) + xRowSetProps->getPropertyValue(sUserProp) >>= sUser; + if (hasProperty(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_PASSWORD), xRowSetProps)) + xRowSetProps->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_PASSWORD)) >>= sPwd; + if (sUser.getLength()) + { // use user and pwd together with the url + Sequence< PropertyValue> aInfo(2); + aInfo.getArray()[0].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("user")); + aInfo.getArray()[0].Value <<= sUser; + aInfo.getArray()[1].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("password")); + aInfo.getArray()[1].Value <<= sPwd; + xPureConnection = xDriverManager->getConnectionWithInfo( sURL, aInfo ); + } + else + // just use the url + xPureConnection = xDriverManager->getConnection( sURL ); + } + } + xConnection.reset( + xPureConnection, + _bAttachAutoDisposer ? SharedConnection::NoTakeOwnership : SharedConnection::TakeOwnership + /* take ownership if and only if we're *not* going to auto-dispose the connection */ + ); + + // now if we created a connection, forward it to the row set + if ( xConnection.is() && _bSetAsActiveConnection ) + { + try + { + if ( _bAttachAutoDisposer ) + { + OAutoConnectionDisposer* pAutoDispose = new OAutoConnectionDisposer( _rxRowSet, xConnection ); + Reference< XPropertyChangeListener > xEnsureDelete(pAutoDispose); + } + else + xRowSetProps->setPropertyValue( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ActiveConnection" ) ), + makeAny( xConnection.getTyped() ) + ); + } + catch(Exception&) + { + OSL_ENSURE(0,"EXception when we set the new active connection!"); + } + } + } + while ( false ); + + return xConnection; +} + +//------------------------------------------------------------------------------ +Reference< XConnection> connectRowset(const Reference< XRowSet>& _rxRowSet, const Reference< XMultiServiceFactory>& _rxFactory, + sal_Bool _bSetAsActiveConnection ) SAL_THROW ( ( SQLException, WrappedTargetException, RuntimeException ) ) +{ + SharedConnection xConnection = lcl_connectRowSet( _rxRowSet, _rxFactory, _bSetAsActiveConnection, true ); + return xConnection.getTyped(); +} + +//------------------------------------------------------------------------------ +SharedConnection ensureRowSetConnection(const Reference< XRowSet>& _rxRowSet, const Reference< XMultiServiceFactory>& _rxFactory, + bool _bUseAutoConnectionDisposer ) SAL_THROW ( ( SQLException, WrappedTargetException, RuntimeException ) ) +{ + return lcl_connectRowSet( _rxRowSet, _rxFactory, true, _bUseAutoConnectionDisposer ); +} + +//------------------------------------------------------------------------------ +Reference< XNameAccess> getTableFields(const Reference< XConnection>& _rxConn,const ::rtl::OUString& _rName) +{ + Reference< XComponent > xDummy; + return getFieldsByCommandDescriptor( _rxConn, CommandType::TABLE, _rName, xDummy ); +} +//------------------------------------------------------------------------------ +Reference< XNameAccess> getPrimaryKeyColumns_throw(const Any& i_aTable) +{ + const Reference< XPropertySet > xTable(i_aTable,UNO_QUERY_THROW); + return getPrimaryKeyColumns_throw(xTable); +} +//------------------------------------------------------------------------------ +Reference< XNameAccess> getPrimaryKeyColumns_throw(const Reference< XPropertySet >& i_xTable) +{ + Reference<XNameAccess> xKeyColumns; + const Reference<XKeysSupplier> xKeySup(i_xTable,UNO_QUERY); + if ( xKeySup.is() ) + { + const Reference<XIndexAccess> xKeys = xKeySup->getKeys(); + if ( xKeys.is() ) + { + ::dbtools::OPropertyMap& rPropMap = OMetaConnection::getPropMap(); + const ::rtl::OUString sPropName = rPropMap.getNameByIndex(PROPERTY_ID_TYPE); + Reference<XPropertySet> xProp; + const sal_Int32 nCount = xKeys->getCount(); + for(sal_Int32 i = 0;i< nCount;++i) + { + xProp.set(xKeys->getByIndex(i),UNO_QUERY_THROW); + if ( xProp.is() ) + { + sal_Int32 nKeyType = 0; + xProp->getPropertyValue(sPropName) >>= nKeyType; + if(KeyType::PRIMARY == nKeyType) + { + const Reference<XColumnsSupplier> xKeyColsSup(xProp,UNO_QUERY_THROW); + xKeyColumns = xKeyColsSup->getColumns(); + break; + } + } + } + } + } + + return xKeyColumns; +} + +//------------------------------------------------------------------------------ +namespace +{ + enum FieldLookupState + { + HANDLE_TABLE, HANDLE_QUERY, HANDLE_SQL, RETRIEVE_OBJECT, RETRIEVE_COLUMNS, DONE, FAILED + }; +} + +//------------------------------------------------------------------------------ +Reference< XNameAccess > getFieldsByCommandDescriptor( const Reference< XConnection >& _rxConnection, + const sal_Int32 _nCommandType, const ::rtl::OUString& _rCommand, + Reference< XComponent >& _rxKeepFieldsAlive, SQLExceptionInfo* _pErrorInfo ) SAL_THROW( ( ) ) +{ + OSL_PRECOND( _rxConnection.is(), "::dbtools::getFieldsByCommandDescriptor: invalid connection!" ); + OSL_PRECOND( ( CommandType::TABLE == _nCommandType ) || ( CommandType::QUERY == _nCommandType ) || ( CommandType::COMMAND == _nCommandType ), + "::dbtools::getFieldsByCommandDescriptor: invalid command type!" ); + OSL_PRECOND( _rCommand.getLength(), "::dbtools::getFieldsByCommandDescriptor: invalid command (empty)!" ); + + Reference< XNameAccess > xFields; + + // reset the error + if ( _pErrorInfo ) + *_pErrorInfo = SQLExceptionInfo(); + // reset the ownership holder + _rxKeepFieldsAlive.clear(); + + // go for the fields + try + { + // some kind of state machine to ease the sharing of code + FieldLookupState eState = FAILED; + switch ( _nCommandType ) + { + case CommandType::TABLE: + eState = HANDLE_TABLE; + break; + case CommandType::QUERY: + eState = HANDLE_QUERY; + break; + case CommandType::COMMAND: + eState = HANDLE_SQL; + break; + } + + // needed in various states: + Reference< XNameAccess > xObjectCollection; + Reference< XColumnsSupplier > xSupplyColumns; + + // go! + while ( ( DONE != eState ) && ( FAILED != eState ) ) + { + switch ( eState ) + { + case HANDLE_TABLE: + { + // initial state for handling the tables + + // get the table objects + Reference< XTablesSupplier > xSupplyTables( _rxConnection, UNO_QUERY ); + if ( xSupplyTables.is() ) + xObjectCollection = xSupplyTables->getTables(); + // if something went wrong 'til here, then this will be handled in the next state + + // next state: get the object + eState = RETRIEVE_OBJECT; + } + break; + + case HANDLE_QUERY: + { + // initial state for handling the tables + + // get the table objects + Reference< XQueriesSupplier > xSupplyQueries( _rxConnection, UNO_QUERY ); + if ( xSupplyQueries.is() ) + xObjectCollection = xSupplyQueries->getQueries(); + // if something went wrong 'til here, then this will be handled in the next state + + // next state: get the object + eState = RETRIEVE_OBJECT; + } + break; + + case RETRIEVE_OBJECT: + // here we should have an object (aka query or table) collection, and are going + // to retrieve the desired object + + // next state: default to FAILED + eState = FAILED; + + OSL_ENSURE( xObjectCollection.is(), "::dbtools::getFieldsByCommandDescriptor: invalid connection (no sdb.Connection, or no Tables-/QueriesSupplier)!"); + if ( xObjectCollection.is() ) + { + if ( xObjectCollection.is() && xObjectCollection->hasByName( _rCommand ) ) + { + xObjectCollection->getByName( _rCommand ) >>= xSupplyColumns; + // (xSupplyColumns being NULL will be handled in the next state) + + // next: go for the columns + eState = RETRIEVE_COLUMNS; + } + } + break; + + case RETRIEVE_COLUMNS: + OSL_ENSURE( xSupplyColumns.is(), "::dbtools::getFieldsByCommandDescriptor: could not retrieve the columns supplier!" ); + + // next state: default to FAILED + eState = FAILED; + + if ( xSupplyColumns.is() ) + { + xFields = xSupplyColumns->getColumns(); + // that's it + eState = DONE; + } + break; + + case HANDLE_SQL: + { + ::rtl::OUString sStatementToExecute( _rCommand ); + + // well, the main problem here is to handle statements which contain a parameter + // If we would simply execute a parametrized statement, then this will fail because + // we cannot supply any parameter values. + // Thus, we try to analyze the statement, and to append a WHERE 0=1 filter criterion + // This should cause every driver to not really execute the statement, but to return + // an empty result set with the proper structure. We then can use this result set + // to retrieve the columns. + + try + { + Reference< XMultiServiceFactory > xComposerFac( _rxConnection, UNO_QUERY ); + + if ( xComposerFac.is() ) + { + Reference< XSingleSelectQueryComposer > xComposer(xComposerFac->createInstance( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.sdb.SingleSelectQueryComposer"))),UNO_QUERY); + if ( xComposer.is() ) + { + xComposer->setQuery( sStatementToExecute ); + + // Now set the filter to a dummy restriction which will result in an empty + // result set. + xComposer->setFilter( ::rtl::OUString::createFromAscii( "0=1" ) ); + sStatementToExecute = xComposer->getQuery( ); + } + } + } + catch( const Exception& ) + { + // silent this error, this was just a try. If we're here, we did not change sStatementToExecute, + // so it will still be _rCommand, which then will be executed without being touched + } + + // now execute + Reference< XPreparedStatement > xStatement = _rxConnection->prepareStatement( sStatementToExecute ); + // transfer ownership of this temporary object to the caller + _rxKeepFieldsAlive = _rxKeepFieldsAlive.query( xStatement ); + + // set the "MaxRows" to 0. This is just in case our attempt to append a 0=1 filter + // failed - in this case, the MaxRows restriction should at least ensure that there + // is no data returned (which would be potentially expensive) + Reference< XPropertySet > xStatementProps( xStatement,UNO_QUERY ); + try + { + if ( xStatementProps.is() ) + xStatementProps->setPropertyValue( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "MaxRows" ) ), + makeAny( sal_Int32( 0 ) ) + ); + } + catch( const Exception& ) + { + OSL_ENSURE( sal_False, "::dbtools::getFieldsByCommandDescriptor: could not set the MaxRows!" ); + // oh damn. Not much of a chance to recover, we will no retrieve the complete + // full blown result set + } + + xSupplyColumns = xSupplyColumns.query( xStatement->executeQuery() ); + // this should have given us a result set which does not contain any data, but + // the structural information we need + + // so the next state is to get the columns + eState = RETRIEVE_COLUMNS; + } + break; + + default: + OSL_ENSURE( sal_False, "::dbtools::getFieldsByCommandDescriptor: oops! unhandled state here!" ); + eState = FAILED; + } + } + } + catch( const SQLContext& e ) { if ( _pErrorInfo ) *_pErrorInfo = SQLExceptionInfo( e ); } + catch( const SQLWarning& e ) { if ( _pErrorInfo ) *_pErrorInfo = SQLExceptionInfo( e ); } + catch( const SQLException& e ) { if ( _pErrorInfo ) *_pErrorInfo = SQLExceptionInfo( e ); } + catch( const Exception& ) + { + OSL_ENSURE( sal_False, "::dbtools::getFieldsByCommandDescriptor: caught an exception while retrieving the fields!" ); + } + + return xFields; +} + +//------------------------------------------------------------------------------ +Sequence< ::rtl::OUString > getFieldNamesByCommandDescriptor( const Reference< XConnection >& _rxConnection, + const sal_Int32 _nCommandType, const ::rtl::OUString& _rCommand, + SQLExceptionInfo* _pErrorInfo ) SAL_THROW( ( ) ) +{ + // get the container for the fields + Reference< XComponent > xKeepFieldsAlive; + Reference< XNameAccess > xFieldContainer = getFieldsByCommandDescriptor( _rxConnection, _nCommandType, _rCommand, xKeepFieldsAlive, _pErrorInfo ); + + // get the names of the fields + Sequence< ::rtl::OUString > aNames; + if ( xFieldContainer.is() ) + aNames = xFieldContainer->getElementNames(); + + // clean up any temporary objects which have been created + disposeComponent( xKeepFieldsAlive ); + + // outta here + return aNames; +} + +//------------------------------------------------------------------------------ +SQLContext prependContextInfo(const SQLException& _rException, const Reference< XInterface >& _rxContext, const ::rtl::OUString& _rContextDescription, const ::rtl::OUString& _rContextDetails) +{ + return SQLContext( _rContextDescription, _rxContext, ::rtl::OUString(), 0, makeAny( _rException ), _rContextDetails ); +} +//------------------------------------------------------------------------------ +SQLException prependErrorInfo( const SQLException& _rChainedException, const Reference< XInterface >& _rxContext, + const ::rtl::OUString& _rAdditionalError, const StandardSQLState _eSQLState, const sal_Int32 _nErrorCode ) +{ + return SQLException( _rAdditionalError, _rxContext, + _eSQLState == SQL_ERROR_UNSPECIFIED ? ::rtl::OUString() : getStandardSQLState( _eSQLState ), + _nErrorCode, makeAny( _rChainedException ) ); +} + +//-------------------------------------------------------------------------- +namespace +{ + struct NameComponentSupport + { + const bool bCatalogs; + const bool bSchemas; + + NameComponentSupport( ) + :bCatalogs( true ) + ,bSchemas( true ) + { + } + + NameComponentSupport( const bool _bCatalogs, const bool _bSchemas ) + :bCatalogs( _bCatalogs ) + ,bSchemas( _bSchemas ) + { + } + }; + + NameComponentSupport lcl_getNameComponentSupport( const Reference< XDatabaseMetaData >& _rxMetaData, EComposeRule _eComposeRule ) + { + OSL_PRECOND( _rxMetaData.is(), "lcl_getNameComponentSupport: invalid meta data!" ); + + FMetaDataSupport pCatalogCall = &XDatabaseMetaData::supportsCatalogsInDataManipulation; + FMetaDataSupport pSchemaCall = &XDatabaseMetaData::supportsSchemasInDataManipulation; + bool bIgnoreMetaData = false; + + switch ( _eComposeRule ) + { + case eInTableDefinitions: + pCatalogCall = &XDatabaseMetaData::supportsCatalogsInTableDefinitions; + pSchemaCall = &XDatabaseMetaData::supportsSchemasInTableDefinitions; + break; + case eInIndexDefinitions: + pCatalogCall = &XDatabaseMetaData::supportsCatalogsInIndexDefinitions; + pSchemaCall = &XDatabaseMetaData::supportsSchemasInIndexDefinitions; + break; + case eInProcedureCalls: + pCatalogCall = &XDatabaseMetaData::supportsCatalogsInProcedureCalls; + pSchemaCall = &XDatabaseMetaData::supportsSchemasInProcedureCalls; + break; + case eInPrivilegeDefinitions: + pCatalogCall = &XDatabaseMetaData::supportsCatalogsInPrivilegeDefinitions; + pSchemaCall = &XDatabaseMetaData::supportsSchemasInPrivilegeDefinitions; + break; + case eComplete: + bIgnoreMetaData = true; + break; + case eInDataManipulation: + // already properly set above + break; + } + return NameComponentSupport( + bIgnoreMetaData ? true : (_rxMetaData.get()->*pCatalogCall)(), + bIgnoreMetaData ? true : (_rxMetaData.get()->*pSchemaCall)() + ); + } +} + +//-------------------------------------------------------------------------- +static ::rtl::OUString impl_doComposeTableName( const Reference< XDatabaseMetaData >& _rxMetaData, + const ::rtl::OUString& _rCatalog, const ::rtl::OUString& _rSchema, const ::rtl::OUString& _rName, + sal_Bool _bQuote, EComposeRule _eComposeRule ) +{ + OSL_ENSURE(_rxMetaData.is(), "impl_doComposeTableName : invalid meta data !"); + if ( !_rxMetaData.is() ) + return ::rtl::OUString(); + OSL_ENSURE(_rName.getLength(), "impl_doComposeTableName : at least the name should be non-empty !"); + + const ::rtl::OUString sQuoteString = _rxMetaData->getIdentifierQuoteString(); + const NameComponentSupport aNameComps( lcl_getNameComponentSupport( _rxMetaData, _eComposeRule ) ); + + ::rtl::OUStringBuffer aComposedName; + + ::rtl::OUString sCatalogSep; + sal_Bool bCatlogAtStart = sal_True; + if ( _rCatalog.getLength() && aNameComps.bCatalogs ) + { + sCatalogSep = _rxMetaData->getCatalogSeparator(); + bCatlogAtStart = _rxMetaData->isCatalogAtStart(); + + if ( bCatlogAtStart && sCatalogSep.getLength()) + { + aComposedName.append( _bQuote ? quoteName( sQuoteString, _rCatalog ) : _rCatalog ); + aComposedName.append( sCatalogSep ); + } + } + + if ( _rSchema.getLength() && aNameComps.bSchemas ) + { + aComposedName.append( _bQuote ? quoteName( sQuoteString, _rSchema ) : _rSchema ); + aComposedName.appendAscii( "." ); + } + + aComposedName.append( _bQuote ? quoteName( sQuoteString, _rName ) : _rName ); + + if ( _rCatalog.getLength() + && !bCatlogAtStart + && sCatalogSep.getLength() + && aNameComps.bCatalogs + ) + { + aComposedName.append( sCatalogSep ); + aComposedName.append( _bQuote ? quoteName( sQuoteString, _rCatalog ) : _rCatalog ); + } + + return aComposedName.makeStringAndClear(); +} + +//------------------------------------------------------------------------------ +::rtl::OUString quoteTableName(const Reference< XDatabaseMetaData>& _rxMeta + , const ::rtl::OUString& _rName + , EComposeRule _eComposeRule) +{ + ::rtl::OUString sCatalog, sSchema, sTable; + qualifiedNameComponents(_rxMeta,_rName,sCatalog,sSchema,sTable,_eComposeRule); + return impl_doComposeTableName( _rxMeta, sCatalog, sSchema, sTable, sal_True, _eComposeRule ); +} + +//------------------------------------------------------------------------------ +void qualifiedNameComponents(const Reference< XDatabaseMetaData >& _rxConnMetaData, const ::rtl::OUString& _rQualifiedName, ::rtl::OUString& _rCatalog, ::rtl::OUString& _rSchema, ::rtl::OUString& _rName,EComposeRule _eComposeRule) +{ + OSL_ENSURE(_rxConnMetaData.is(), "QualifiedNameComponents : invalid meta data!"); + + NameComponentSupport aNameComps( lcl_getNameComponentSupport( _rxConnMetaData, _eComposeRule ) ); + + ::rtl::OUString sSeparator = _rxConnMetaData->getCatalogSeparator(); + + ::rtl::OUString sName(_rQualifiedName); + // do we have catalogs ? + if ( aNameComps.bCatalogs ) + { + if (_rxConnMetaData->isCatalogAtStart()) + { + // search for the catalog name at the beginning + sal_Int32 nIndex = sName.indexOf(sSeparator); + if (-1 != nIndex) + { + _rCatalog = sName.copy(0, nIndex); + sName = sName.copy(nIndex + 1); + } + } + else + { + // Katalogname am Ende + sal_Int32 nIndex = sName.lastIndexOf(sSeparator); + if (-1 != nIndex) + { + _rCatalog = sName.copy(nIndex + 1); + sName = sName.copy(0, nIndex); + } + } + } + + if ( aNameComps.bSchemas ) + { + sal_Int32 nIndex = sName.indexOf((sal_Unicode)'.'); + // OSL_ENSURE(-1 != nIndex, "QualifiedNameComponents : no schema separator!"); + if ( nIndex != -1 ) + _rSchema = sName.copy(0, nIndex); + sName = sName.copy(nIndex + 1); + } + + _rName = sName; +} + +//------------------------------------------------------------------------------ +Reference< XNumberFormatsSupplier> getNumberFormats( + const Reference< XConnection>& _rxConn, + sal_Bool _bAlloweDefault, + const Reference< XMultiServiceFactory>& _rxFactory) +{ + // ask the parent of the connection (should be an DatabaseAccess) + Reference< XNumberFormatsSupplier> xReturn; + Reference< XChild> xConnAsChild(_rxConn, UNO_QUERY); + ::rtl::OUString sPropFormatsSupplier = ::rtl::OUString::createFromAscii("NumberFormatsSupplier"); + if (xConnAsChild.is()) + { + Reference< XPropertySet> xConnParentProps(xConnAsChild->getParent(), UNO_QUERY); + if (xConnParentProps.is() && hasProperty(sPropFormatsSupplier, xConnParentProps)) + xConnParentProps->getPropertyValue(sPropFormatsSupplier) >>= xReturn; + } + else if(_bAlloweDefault && _rxFactory.is()) + { + xReturn = Reference< XNumberFormatsSupplier>(_rxFactory->createInstance(::rtl::OUString::createFromAscii("com.sun.star.util.NumberFormatsSupplier")),UNO_QUERY); + } + return xReturn; +} + +//============================================================================== +//------------------------------------------------------------------------------ +void TransferFormComponentProperties( + const Reference< XPropertySet>& xOldProps, + const Reference< XPropertySet>& xNewProps, + const Locale& _rLocale) +{ +try +{ + OSL_ENSURE( xOldProps.is() && xNewProps.is(), "TransferFormComponentProperties: invalid source/dest!" ); + if ( !xOldProps.is() || !xNewProps.is() ) + return; + + // kopieren wir erst mal alle Props, die in Quelle und Ziel vorhanden sind und identische Beschreibungen haben + Reference< XPropertySetInfo> xOldInfo( xOldProps->getPropertySetInfo()); + Reference< XPropertySetInfo> xNewInfo( xNewProps->getPropertySetInfo()); + + Sequence< Property> aOldProperties = xOldInfo->getProperties(); + Sequence< Property> aNewProperties = xNewInfo->getProperties(); + int nNewLen = aNewProperties.getLength(); + + Property* pOldProps = aOldProperties.getArray(); + Property* pNewProps = aNewProperties.getArray(); + + ::rtl::OUString sPropDefaultControl(::rtl::OUString::createFromAscii("DefaultControl")); + ::rtl::OUString sPropLabelControl(::rtl::OUString::createFromAscii("LabelControl")); + ::rtl::OUString sPropFormatsSupplier(::rtl::OUString::createFromAscii("FormatsSupplier")); + ::rtl::OUString sPropCurrencySymbol(::rtl::OUString::createFromAscii("CurrencySymbol")); + ::rtl::OUString sPropDecimals(::rtl::OUString::createFromAscii("Decimals")); + ::rtl::OUString sPropEffectiveMin(::rtl::OUString::createFromAscii("EffectiveMin")); + ::rtl::OUString sPropEffectiveMax(::rtl::OUString::createFromAscii("EffectiveMax")); + ::rtl::OUString sPropEffectiveDefault(::rtl::OUString::createFromAscii("EffectiveDefault")); + ::rtl::OUString sPropDefaultText(::rtl::OUString::createFromAscii("DefaultText")); + ::rtl::OUString sPropDefaultDate(::rtl::OUString::createFromAscii("DefaultDate")); + ::rtl::OUString sPropDefaultTime(::rtl::OUString::createFromAscii("DefaultTime")); + ::rtl::OUString sPropValueMin(::rtl::OUString::createFromAscii("ValueMin")); + ::rtl::OUString sPropValueMax(::rtl::OUString::createFromAscii("ValueMax")); + ::rtl::OUString sPropDecimalAccuracy(::rtl::OUString::createFromAscii("DecimalAccuracy")); + ::rtl::OUString sPropClassId(::rtl::OUString::createFromAscii("ClassId")); + ::rtl::OUString sFormattedServiceName( ::rtl::OUString::createFromAscii( "com.sun.star.form.component.FormattedField" ) ); + + for (sal_Int16 i=0; i<aOldProperties.getLength(); ++i) + { + if ( (!pOldProps[i].Name.equals(sPropDefaultControl)) + && (!pOldProps[i].Name.equals(sPropLabelControl)) + ) + { + // binaere Suche + Property* pResult = ::std::lower_bound(pNewProps, pNewProps + nNewLen,pOldProps[i].Name, ::comphelper::PropertyStringLessFunctor()); + if ( pResult + && ( pResult != pNewProps + nNewLen && pResult->Name == pOldProps[i].Name ) + && ( (pResult->Attributes & PropertyAttribute::READONLY) == 0 ) + && ( pResult->Type.equals(pOldProps[i].Type)) ) + { // Attribute stimmen ueberein und Property ist nicht read-only + try + { + xNewProps->setPropertyValue(pResult->Name, xOldProps->getPropertyValue(pResult->Name)); + } + catch(IllegalArgumentException& e) + { + OSL_UNUSED( e ); +#ifdef DBG_UTIL + ::rtl::OUString sMessage = ::rtl::OUString::createFromAscii("TransferFormComponentProperties : could not transfer the value for property \""); + sMessage += pResult->Name; + sMessage += ::rtl::OUString::createFromAscii("\"");; + OSL_ENSURE(sal_False, ::rtl::OUStringToOString(sMessage, RTL_TEXTENCODING_ASCII_US)); +#endif + } + } + } + } + + + // fuer formatierte Felder (entweder alt oder neu) haben wir ein paar Sonderbehandlungen + Reference< XServiceInfo > xSI( xOldProps, UNO_QUERY ); + sal_Bool bOldIsFormatted = xSI.is() && xSI->supportsService( sFormattedServiceName ); + xSI = Reference< XServiceInfo >( xNewProps, UNO_QUERY ); + sal_Bool bNewIsFormatted = xSI.is() && xSI->supportsService( sFormattedServiceName ); + + if (!bOldIsFormatted && !bNewIsFormatted) + return; // nothing to do + + if (bOldIsFormatted && bNewIsFormatted) + // nein, wenn beide formatierte Felder sind, dann machen wir keinerlei Konvertierungen + // Das geht zu weit ;) + return; + + if (bOldIsFormatted) + { + // aus dem eingestellten Format ein paar Properties rausziehen und zum neuen Set durchschleifen + Any aFormatKey( xOldProps->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_FORMATKEY)) ); + if (aFormatKey.hasValue()) + { + Reference< XNumberFormatsSupplier> xSupplier; + xOldProps->getPropertyValue(sPropFormatsSupplier) >>= xSupplier; + if (xSupplier.is()) + { + Reference< XNumberFormats> xFormats(xSupplier->getNumberFormats()); + Reference< XPropertySet> xFormat(xFormats->getByKey(getINT32(aFormatKey))); + if (hasProperty(sPropCurrencySymbol, xFormat)) + { + Any aVal( xFormat->getPropertyValue(sPropCurrencySymbol) ); + if (aVal.hasValue() && hasProperty(sPropCurrencySymbol, xNewProps)) + // (wenn die Quelle das nicht gesetzt hat, dann auch nicht kopieren, um den + // Default-Wert nicht zu ueberschreiben + xNewProps->setPropertyValue(sPropCurrencySymbol, aVal); + } + if (hasProperty(sPropDecimals, xFormat) && hasProperty(sPropDecimals, xNewProps)) + xNewProps->setPropertyValue(sPropDecimals, xFormat->getPropertyValue(sPropDecimals)); + } + } + + // eine eventuelle-Min-Max-Konvertierung + Any aEffectiveMin( xOldProps->getPropertyValue(sPropEffectiveMin) ); + if (aEffectiveMin.hasValue()) + { // im Gegensatz zu ValueMin kann EffectiveMin void sein + if (hasProperty(sPropValueMin, xNewProps)) + { + OSL_ENSURE(aEffectiveMin.getValueType().getTypeClass() == TypeClass_DOUBLE, + "TransferFormComponentProperties : invalid property type !"); + xNewProps->setPropertyValue(sPropValueMin, aEffectiveMin); + } + } + Any aEffectiveMax( xOldProps->getPropertyValue(sPropEffectiveMax) ); + if (aEffectiveMax.hasValue()) + { // analog + if (hasProperty(sPropValueMax, xNewProps)) + { + OSL_ENSURE(aEffectiveMax.getValueType().getTypeClass() == TypeClass_DOUBLE, + "TransferFormComponentProperties : invalid property type !"); + xNewProps->setPropertyValue(sPropValueMax, aEffectiveMax); + } + } + + // dann koennen wir noch Default-Werte konvertieren und uebernehmen + Any aEffectiveDefault( xOldProps->getPropertyValue(sPropEffectiveDefault) ); + if (aEffectiveDefault.hasValue()) + { + sal_Bool bIsString = aEffectiveDefault.getValueType().getTypeClass() == TypeClass_STRING; + OSL_ENSURE(bIsString || aEffectiveDefault.getValueType().getTypeClass() == TypeClass_DOUBLE, + "TransferFormComponentProperties : invalid property type !"); + // die Effective-Properties sollten immer void oder string oder double sein .... + + if (hasProperty(sPropDefaultDate, xNewProps) && !bIsString) + { // (einen ::rtl::OUString in ein Datum zu konvertieren muss nicht immer klappen, denn das ganze kann ja an + // eine Textspalte gebunden gewesen sein, aber mit einem double koennen wir was anfangen) + Date aDate = DBTypeConversion::toDate(getDouble(aEffectiveDefault)); + xNewProps->setPropertyValue(sPropDefaultDate, makeAny(aDate)); + } + + if (hasProperty(sPropDefaultTime, xNewProps) && !bIsString) + { // voellig analog mit Zeit + Time aTime = DBTypeConversion::toTime(getDouble(aEffectiveDefault)); + xNewProps->setPropertyValue(sPropDefaultTime, makeAny(aTime)); + } + + if (hasProperty(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_DEFAULTVALUE), xNewProps) && !bIsString) + { // hier koennen wir einfach das double durchreichen + xNewProps->setPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_DEFAULTVALUE), aEffectiveDefault); + } + + if (hasProperty(sPropDefaultText, xNewProps) && bIsString) + { // und hier den ::rtl::OUString + xNewProps->setPropertyValue(sPropDefaultText, aEffectiveDefault); + } + + // nyi: die Uebersetzung zwischen doubles und ::rtl::OUString wuerde noch mehr Moeglichkeien eroeffnen + } + } + + // die andere Richtung : das neu Control soll formatiert sein + if (bNewIsFormatted) + { + // zuerst die Formatierung + // einen Supplier koennen wir nicht setzen, also muss das neue Set schon einen mitbringen + Reference< XNumberFormatsSupplier> xSupplier; + xNewProps->getPropertyValue(sPropFormatsSupplier) >>= xSupplier; + if (xSupplier.is()) + { + Reference< XNumberFormats> xFormats(xSupplier->getNumberFormats()); + + // Dezimal-Stellen + sal_Int16 nDecimals = 2; + if (hasProperty(sPropDecimalAccuracy, xOldProps)) + xOldProps->getPropertyValue(sPropDecimalAccuracy) >>= nDecimals; + + // Grund-Format (je nach ClassId des alten Sets) + sal_Int32 nBaseKey = 0; + if (hasProperty(sPropClassId, xOldProps)) + { + Reference< XNumberFormatTypes> xTypeList(xFormats, UNO_QUERY); + if (xTypeList.is()) + { + sal_Int16 nClassId = 0; + xOldProps->getPropertyValue(sPropClassId) >>= nClassId; + switch (nClassId) + { + case FormComponentType::DATEFIELD : + nBaseKey = xTypeList->getStandardFormat(NumberFormat::DATE, _rLocale); + break; + + case FormComponentType::TIMEFIELD : + nBaseKey = xTypeList->getStandardFormat(NumberFormat::TIME, _rLocale); + break; + + case FormComponentType::CURRENCYFIELD : + nBaseKey = xTypeList->getStandardFormat(NumberFormat::CURRENCY, _rLocale); + break; + } + } + } + + // damit koennen wir ein neues Format basteln ... + ::rtl::OUString sNewFormat = xFormats->generateFormat(nBaseKey, _rLocale, sal_False, sal_False, nDecimals, 0); + // kein Tausender-Trennzeichen, negative Zahlen nicht in Rot, keine fuehrenden Nullen + + // ... und zum FormatsSupplier hinzufuegen (wenn noetig) + sal_Int32 nKey = xFormats->queryKey(sNewFormat, _rLocale, sal_False); + if (nKey == (sal_Int32)-1) + { // noch nicht vorhanden in meinem Formatter ... + nKey = xFormats->addNew(sNewFormat, _rLocale); + } + + xNewProps->setPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_FORMATKEY), makeAny((sal_Int32)nKey)); + } + + // min-/max-Werte + Any aNewMin, aNewMax; + if (hasProperty(sPropValueMin, xOldProps)) + aNewMin = xOldProps->getPropertyValue(sPropValueMin); + if (hasProperty(sPropValueMax, xOldProps)) + aNewMax = xOldProps->getPropertyValue(sPropValueMax); + xNewProps->setPropertyValue(sPropEffectiveMin, aNewMin); + xNewProps->setPropertyValue(sPropEffectiveMax, aNewMax); + + // Default-Wert + Any aNewDefault; + if (hasProperty(sPropDefaultDate, xOldProps)) + { + Any aDate( xOldProps->getPropertyValue(sPropDefaultDate) ); + if (aDate.hasValue()) + aNewDefault <<= DBTypeConversion::toDouble(*(Date*)aDate.getValue()); + } + + if (hasProperty(sPropDefaultTime, xOldProps)) + { + Any aTime( xOldProps->getPropertyValue(sPropDefaultTime) ); + if (aTime.hasValue()) + aNewDefault <<= DBTypeConversion::toDouble(*(Time*)aTime.getValue()); + } + + // double oder ::rtl::OUString werden direkt uebernommen + if (hasProperty(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_DEFAULTVALUE), xOldProps)) + aNewDefault = xOldProps->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_DEFAULTVALUE)); + if (hasProperty(sPropDefaultText, xOldProps)) + aNewDefault = xOldProps->getPropertyValue(sPropDefaultText); + + if (aNewDefault.hasValue()) + xNewProps->setPropertyValue(sPropEffectiveDefault, aNewDefault); + } +} +catch(const Exception&) +{ + OSL_ENSURE( sal_False, "TransferFormComponentProperties: caught an exception!" ); +} +} + +//------------------------------------------------------------------------------ +sal_Bool canInsert(const Reference< XPropertySet>& _rxCursorSet) +{ + return ((_rxCursorSet.is() && (getINT32(_rxCursorSet->getPropertyValue(::rtl::OUString::createFromAscii("Privileges"))) & Privilege::INSERT) != 0)); +} + +//------------------------------------------------------------------------------ +sal_Bool canUpdate(const Reference< XPropertySet>& _rxCursorSet) +{ + return ((_rxCursorSet.is() && (getINT32(_rxCursorSet->getPropertyValue(::rtl::OUString::createFromAscii("Privileges"))) & Privilege::UPDATE) != 0)); +} + +//------------------------------------------------------------------------------ +sal_Bool canDelete(const Reference< XPropertySet>& _rxCursorSet) +{ + return ((_rxCursorSet.is() && (getINT32(_rxCursorSet->getPropertyValue(::rtl::OUString::createFromAscii("Privileges"))) & Privilege::DELETE) != 0)); +} +// ----------------------------------------------------------------------------- +Reference< XDataSource> findDataSource(const Reference< XInterface >& _xParent) +{ + Reference< XOfficeDatabaseDocument> xDatabaseDocument(_xParent, UNO_QUERY); + Reference< XDataSource> xDataSource; + if ( xDatabaseDocument.is() ) + xDataSource = xDatabaseDocument->getDataSource(); + if ( !xDataSource.is() ) + xDataSource.set(_xParent, UNO_QUERY); + if (!xDataSource.is()) + { + Reference< XChild> xChild(_xParent, UNO_QUERY); + if ( xChild.is() ) + xDataSource = findDataSource(xChild->getParent()); + } + return xDataSource; +} + +//------------------------------------------------------------------------------ +::rtl::OUString getComposedRowSetStatement( const Reference< XPropertySet >& _rxRowSet, const Reference< XMultiServiceFactory>& _rxFactory, + sal_Bool _bUseRowSetFilter, sal_Bool _bUseRowSetOrder, Reference< XSingleSelectQueryComposer >* _pxComposer ) + SAL_THROW( ( SQLException ) ) +{ + ::rtl::OUString sStatement; + try + { + Reference< XConnection> xConn = connectRowset( Reference< XRowSet >( _rxRowSet, UNO_QUERY ), _rxFactory, sal_True ); + if ( xConn.is() ) // implies _rxRowSet.is() + { + // build the statement the row set is based on (can't use the ActiveCommand property of the set + // as this reflects the status after the last execute, not the currently set properties) + + sal_Int32 nCommandType = CommandType::COMMAND; + ::rtl::OUString sCommand; + sal_Bool bEscapeProcessing = sal_False; + + OSL_VERIFY( _rxRowSet->getPropertyValue( ::rtl::OUString::createFromAscii( "CommandType" ) ) >>= nCommandType ); + OSL_VERIFY( _rxRowSet->getPropertyValue( ::rtl::OUString::createFromAscii( "Command" ) ) >>= sCommand ); + OSL_VERIFY( _rxRowSet->getPropertyValue( ::rtl::OUString::createFromAscii( "EscapeProcessing" ) ) >>= bEscapeProcessing ); + + StatementComposer aComposer( xConn, sCommand, nCommandType, bEscapeProcessing ); + // append sort + if ( _bUseRowSetOrder ) + aComposer.setOrder( getString( _rxRowSet->getPropertyValue( ::rtl::OUString::createFromAscii( "Order" ) ) ) ); + + // append filter + if ( _bUseRowSetFilter ) + { + sal_Bool bApplyFilter = sal_True; + _rxRowSet->getPropertyValue( ::rtl::OUString::createFromAscii( "ApplyFilter" ) ) >>= bApplyFilter; + if ( bApplyFilter ) + aComposer.setFilter( getString( _rxRowSet->getPropertyValue( ::rtl::OUString::createFromAscii( "Filter" ) ) ) ); + } + + sStatement = aComposer.getQuery(); + + if ( _pxComposer ) + { + *_pxComposer = aComposer.getComposer(); + aComposer.setDisposeComposer( false ); + } + } + } + catch( const SQLException& ) + { + throw; + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + + return sStatement; +} + +//------------------------------------------------------------------------------ +::rtl::OUString getComposedRowSetStatement( + const Reference< XPropertySet >& _rxRowSet, const Reference< XMultiServiceFactory>& _rxFactory, + sal_Bool _bUseRowSetFilter, sal_Bool _bUseRowSetOrder ) +{ + return getComposedRowSetStatement( _rxRowSet, _rxFactory, _bUseRowSetFilter, _bUseRowSetOrder, NULL ); +} + +//------------------------------------------------------------------------------ +Reference< XSingleSelectQueryComposer > getCurrentSettingsComposer( + const Reference< XPropertySet>& _rxRowSetProps, + const Reference< XMultiServiceFactory>& _rxFactory) +{ + Reference< XSingleSelectQueryComposer > xReturn; + try + { + getComposedRowSetStatement( _rxRowSetProps, _rxFactory, sal_True, sal_True, &xReturn ); + } + catch( const SQLException& ) + { + throw; + } + catch( const Exception& ) + { + OSL_ENSURE( sal_False, "::getCurrentSettingsComposer : caught an exception !" ); + } + + return xReturn; +} +//-------------------------------------------------------------------------- +::rtl::OUString composeTableName( const Reference< XDatabaseMetaData >& _rxMetaData, + const ::rtl::OUString& _rCatalog, + const ::rtl::OUString& _rSchema, + const ::rtl::OUString& _rName, + sal_Bool _bQuote, + EComposeRule _eComposeRule) +{ + return impl_doComposeTableName( _rxMetaData, _rCatalog, _rSchema, _rName, _bQuote, _eComposeRule ); +} + +// ----------------------------------------------------------------------------- +::rtl::OUString composeTableNameForSelect( const Reference< XConnection >& _rxConnection, + const ::rtl::OUString& _rCatalog, const ::rtl::OUString& _rSchema, const ::rtl::OUString& _rName ) +{ + sal_Bool bUseCatalogInSelect = isDataSourcePropertyEnabled( _rxConnection, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "UseCatalogInSelect" ) ), sal_True ); + sal_Bool bUseSchemaInSelect = isDataSourcePropertyEnabled( _rxConnection, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "UseSchemaInSelect" ) ), sal_True ); + + return impl_doComposeTableName( + _rxConnection->getMetaData(), + bUseCatalogInSelect ? _rCatalog : ::rtl::OUString(), + bUseSchemaInSelect ? _rSchema : ::rtl::OUString(), + _rName, + true, + eInDataManipulation + ); +} + +// ----------------------------------------------------------------------------- +namespace +{ + static void lcl_getTableNameComponents( const Reference<XPropertySet>& _xTable, + ::rtl::OUString& _out_rCatalog, ::rtl::OUString& _out_rSchema, ::rtl::OUString& _out_rName ) + { + ::dbtools::OPropertyMap& rPropMap = OMetaConnection::getPropMap(); + Reference< XPropertySetInfo > xInfo = _xTable->getPropertySetInfo(); + if ( xInfo.is() + && xInfo->hasPropertyByName(rPropMap.getNameByIndex(PROPERTY_ID_NAME)) ) + { + + ::rtl::OUString aCatalog; + ::rtl::OUString aSchema; + ::rtl::OUString aTable; + if ( xInfo->hasPropertyByName(rPropMap.getNameByIndex(PROPERTY_ID_CATALOGNAME)) + && xInfo->hasPropertyByName(rPropMap.getNameByIndex(PROPERTY_ID_SCHEMANAME)) ) + { + _xTable->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_CATALOGNAME)) >>= _out_rCatalog; + _xTable->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_SCHEMANAME)) >>= _out_rSchema; + } + _xTable->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_NAME)) >>= _out_rName; + } + else + OSL_ENSURE( false, "::dbtools::lcl_getTableNameComponents: this is no table object!" ); + } +} + +// ----------------------------------------------------------------------------- +::rtl::OUString composeTableNameForSelect( const Reference< XConnection >& _rxConnection, const Reference<XPropertySet>& _xTable ) +{ + ::rtl::OUString sCatalog, sSchema, sName; + lcl_getTableNameComponents( _xTable, sCatalog, sSchema, sName ); + + return composeTableNameForSelect( _rxConnection, sCatalog, sSchema, sName ); +} + +// ----------------------------------------------------------------------------- +::rtl::OUString composeTableName(const Reference<XDatabaseMetaData>& _xMetaData, + const Reference<XPropertySet>& _xTable, + EComposeRule _eComposeRule, + bool _bSuppressCatalog, + bool _bSuppressSchema, + bool _bQuote ) +{ + ::rtl::OUString sCatalog, sSchema, sName; + lcl_getTableNameComponents( _xTable, sCatalog, sSchema, sName ); + + return impl_doComposeTableName( + _xMetaData, + _bSuppressCatalog ? ::rtl::OUString() : sCatalog, + _bSuppressSchema ? ::rtl::OUString() : sSchema, + sName, + _bQuote, + _eComposeRule + ); +} +// ----------------------------------------------------------------------------- +sal_Int32 getSearchColumnFlag( const Reference< XConnection>& _rxConn,sal_Int32 _nDataType) +{ + sal_Int32 nSearchFlag = 0; + Reference<XResultSet> xSet = _rxConn->getMetaData()->getTypeInfo(); + if(xSet.is()) + { + Reference<XRow> xRow(xSet,UNO_QUERY); + while(xSet->next()) + { + if(xRow->getInt(2) == _nDataType) + { + nSearchFlag = xRow->getInt(9); + break; + } + } + } + return nSearchFlag; +} + +// ----------------------------------------------------------------------------- +::rtl::OUString createUniqueName( const Sequence< ::rtl::OUString >& _rNames, const ::rtl::OUString& _rBaseName, sal_Bool _bStartWithNumber ) +{ + ::std::set< ::rtl::OUString > aUsedNames; + ::std::copy( + _rNames.getConstArray(), + _rNames.getConstArray() + _rNames.getLength(), + ::std::insert_iterator< ::std::set< ::rtl::OUString > >( aUsedNames, aUsedNames.end() ) + ); + + ::rtl::OUString sName( _rBaseName ); + sal_Int32 nPos = 1; + if ( _bStartWithNumber ) + sName += ::rtl::OUString::valueOf( nPos ); + + while ( aUsedNames.find( sName ) != aUsedNames.end() ) + { + sName = _rBaseName; + sName += ::rtl::OUString::valueOf( ++nPos ); + } + return sName; +} + +// ----------------------------------------------------------------------------- +::rtl::OUString createUniqueName(const Reference<XNameAccess>& _rxContainer,const ::rtl::OUString& _rBaseName,sal_Bool _bStartWithNumber) +{ + Sequence< ::rtl::OUString > aElementNames; + + OSL_ENSURE( _rxContainer.is(), "createUniqueName: invalid container!" ); + if ( _rxContainer.is() ) + aElementNames = _rxContainer->getElementNames(); + + return createUniqueName( aElementNames, _rBaseName, _bStartWithNumber ); +} + +// ----------------------------------------------------------------------------- +void showError(const SQLExceptionInfo& _rInfo, + const Reference< XWindow>& _xParent, + const Reference< XMultiServiceFactory >& _xFactory) +{ + if (_rInfo.isValid()) + { + try + { + Sequence< Any > aArgs(2); + aArgs[0] <<= PropertyValue(::rtl::OUString::createFromAscii("SQLException"), 0, _rInfo.get(), PropertyState_DIRECT_VALUE); + aArgs[1] <<= PropertyValue(::rtl::OUString::createFromAscii("ParentWindow"), 0, makeAny(_xParent), PropertyState_DIRECT_VALUE); + + static ::rtl::OUString s_sDialogServiceName = ::rtl::OUString::createFromAscii("com.sun.star.sdb.ErrorMessageDialog"); + Reference< XExecutableDialog > xErrorDialog( + _xFactory->createInstanceWithArguments(s_sDialogServiceName, aArgs), UNO_QUERY); + if (xErrorDialog.is()) + xErrorDialog->execute(); + else + { + OSL_ENSURE(0,"dbtools::showError: no XExecutableDialog found!"); + } + } + catch(Exception&) + { + OSL_ENSURE(0,"showError: could not display the error message!"); + } + } +} + +// ------------------------------------------------------------------------- +sal_Bool implUpdateObject(const Reference< XRowUpdate >& _rxUpdatedObject, + const sal_Int32 _nColumnIndex, const Any& _rValue) SAL_THROW ( ( SQLException, RuntimeException ) ) +{ + sal_Bool bSuccessfullyReRouted = sal_True; + switch (_rValue.getValueTypeClass()) + { + case TypeClass_ANY: + { + Any aInnerValue; + _rValue >>= aInnerValue; + bSuccessfullyReRouted = implUpdateObject(_rxUpdatedObject, _nColumnIndex, aInnerValue); + } + break; + + case TypeClass_VOID: + _rxUpdatedObject->updateNull(_nColumnIndex); + break; + + case TypeClass_STRING: + _rxUpdatedObject->updateString(_nColumnIndex, *(rtl::OUString*)_rValue.getValue()); + break; + + case TypeClass_BOOLEAN: + _rxUpdatedObject->updateBoolean(_nColumnIndex, *(sal_Bool *)_rValue.getValue()); + break; + + case TypeClass_BYTE: + _rxUpdatedObject->updateByte(_nColumnIndex, *(sal_Int8 *)_rValue.getValue()); + break; + + case TypeClass_UNSIGNED_SHORT: + case TypeClass_SHORT: + _rxUpdatedObject->updateShort(_nColumnIndex, *(sal_Int16*)_rValue.getValue()); + break; + + case TypeClass_CHAR: + _rxUpdatedObject->updateString(_nColumnIndex,::rtl::OUString((sal_Unicode *)_rValue.getValue(),1)); + break; + + case TypeClass_UNSIGNED_LONG: + case TypeClass_LONG: + _rxUpdatedObject->updateInt(_nColumnIndex, *(sal_Int32*)_rValue.getValue()); + break; + + case TypeClass_HYPER: + { + sal_Int64 nValue = 0; + OSL_VERIFY( _rValue >>= nValue ); + _rxUpdatedObject->updateLong( _nColumnIndex, nValue ); + } + break; + + case TypeClass_FLOAT: + _rxUpdatedObject->updateFloat(_nColumnIndex, *(float*)_rValue.getValue()); + break; + + case TypeClass_DOUBLE: + _rxUpdatedObject->updateDouble(_nColumnIndex, *(double*)_rValue.getValue()); + break; + + case TypeClass_SEQUENCE: + if (_rValue.getValueType() == ::getCppuType((const Sequence< sal_Int8 > *)0)) + _rxUpdatedObject->updateBytes(_nColumnIndex, *(Sequence<sal_Int8>*)_rValue.getValue()); + else + bSuccessfullyReRouted = sal_False; + break; + case TypeClass_STRUCT: + if (_rValue.getValueType() == ::getCppuType((const DateTime*)0)) + _rxUpdatedObject->updateTimestamp(_nColumnIndex, *(DateTime*)_rValue.getValue()); + else if (_rValue.getValueType() == ::getCppuType((const Date*)0)) + _rxUpdatedObject->updateDate(_nColumnIndex, *(Date*)_rValue.getValue()); + else if (_rValue.getValueType() == ::getCppuType((const Time*)0)) + _rxUpdatedObject->updateTime(_nColumnIndex, *(Time*)_rValue.getValue()); + else + bSuccessfullyReRouted = sal_False; + break; + + case TypeClass_INTERFACE: + if (_rValue.getValueType() == ::getCppuType(static_cast<Reference< XInputStream>*>(NULL))) + { + Reference< XInputStream > xStream; + _rValue >>= xStream; + _rxUpdatedObject->updateBinaryStream(_nColumnIndex, xStream, xStream->available()); + break; + } + // run through + default: + bSuccessfullyReRouted = sal_False; + } + + return bSuccessfullyReRouted; +} +// ------------------------------------------------------------------------- +sal_Bool implSetObject( const Reference< XParameters >& _rxParameters, + const sal_Int32 _nColumnIndex, const Any& _rValue) SAL_THROW ( ( SQLException, RuntimeException ) ) +{ + sal_Bool bSuccessfullyReRouted = sal_True; + switch (_rValue.getValueTypeClass()) + { + case TypeClass_HYPER: + { + sal_Int64 nValue = 0; + OSL_VERIFY( _rValue >>= nValue ); + _rxParameters->setLong( _nColumnIndex, nValue ); + } + break; + + case TypeClass_ANY: + { + Any aInnerValue; + _rValue >>= aInnerValue; + bSuccessfullyReRouted = implSetObject(_rxParameters, _nColumnIndex, aInnerValue); + } + break; + + case TypeClass_VOID: + _rxParameters->setNull(_nColumnIndex,DataType::VARCHAR); + break; + + case TypeClass_STRING: + _rxParameters->setString(_nColumnIndex, *(rtl::OUString*)_rValue.getValue()); + break; + + case TypeClass_BOOLEAN: + _rxParameters->setBoolean(_nColumnIndex, *(sal_Bool *)_rValue.getValue()); + break; + + case TypeClass_BYTE: + _rxParameters->setByte(_nColumnIndex, *(sal_Int8 *)_rValue.getValue()); + break; + + case TypeClass_UNSIGNED_SHORT: + case TypeClass_SHORT: + _rxParameters->setShort(_nColumnIndex, *(sal_Int16*)_rValue.getValue()); + break; + + case TypeClass_CHAR: + _rxParameters->setString(_nColumnIndex, ::rtl::OUString((sal_Unicode *)_rValue.getValue(),1)); + break; + + case TypeClass_UNSIGNED_LONG: + case TypeClass_LONG: + _rxParameters->setInt(_nColumnIndex, *(sal_Int32*)_rValue.getValue()); + break; + + case TypeClass_FLOAT: + _rxParameters->setFloat(_nColumnIndex, *(float*)_rValue.getValue()); + break; + + case TypeClass_DOUBLE: + _rxParameters->setDouble(_nColumnIndex, *(double*)_rValue.getValue()); + break; + + case TypeClass_SEQUENCE: + if (_rValue.getValueType() == ::getCppuType((const Sequence< sal_Int8 > *)0)) + { + _rxParameters->setBytes(_nColumnIndex, *(Sequence<sal_Int8>*)_rValue.getValue()); + } + else + bSuccessfullyReRouted = sal_False; + break; + case TypeClass_STRUCT: + if (_rValue.getValueType() == ::getCppuType((const DateTime*)0)) + _rxParameters->setTimestamp(_nColumnIndex, *(DateTime*)_rValue.getValue()); + else if (_rValue.getValueType() == ::getCppuType((const Date*)0)) + _rxParameters->setDate(_nColumnIndex, *(Date*)_rValue.getValue()); + else if (_rValue.getValueType() == ::getCppuType((const Time*)0)) + _rxParameters->setTime(_nColumnIndex, *(Time*)_rValue.getValue()); + else + bSuccessfullyReRouted = sal_False; + break; + + case TypeClass_INTERFACE: + if (_rValue.getValueType() == ::getCppuType(static_cast<Reference< XInputStream>*>(NULL))) + { + Reference< XInputStream > xStream; + _rValue >>= xStream; + _rxParameters->setBinaryStream(_nColumnIndex, xStream, xStream->available()); + break; + } + // run through + default: + bSuccessfullyReRouted = sal_False; + + } + + return bSuccessfullyReRouted; +} + +//.................................................................. +namespace +{ + class OParameterWrapper : public ::cppu::WeakImplHelper1< XIndexAccess > + { + ::std::bit_vector m_aSet; + Reference<XIndexAccess> m_xSource; + public: + OParameterWrapper(const ::std::bit_vector& _aSet,const Reference<XIndexAccess>& _xSource) : m_aSet(_aSet),m_xSource(_xSource){} + private: + // ::com::sun::star::container::XElementAccess + virtual Type SAL_CALL getElementType() throw(RuntimeException) + { + return m_xSource->getElementType(); + } + virtual sal_Bool SAL_CALL hasElements( ) throw(RuntimeException) + { + if ( m_aSet.empty() ) + return m_xSource->hasElements(); + return ::std::count(m_aSet.begin(),m_aSet.end(),false) != 0; + } + // ::com::sun::star::container::XIndexAccess + virtual sal_Int32 SAL_CALL getCount( ) throw(RuntimeException) + { + if ( m_aSet.empty() ) + return m_xSource->getCount(); + return ::std::count(m_aSet.begin(),m_aSet.end(),false); + } + virtual Any SAL_CALL getByIndex( sal_Int32 Index ) throw(IndexOutOfBoundsException, WrappedTargetException, RuntimeException) + { + if ( m_aSet.empty() ) + return m_xSource->getByIndex(Index); + if ( m_aSet.size() < (size_t)Index ) + throw IndexOutOfBoundsException(); + + ::std::bit_vector::iterator aIter = m_aSet.begin(); + ::std::bit_vector::iterator aEnd = m_aSet.end(); + sal_Int32 i = 0; + sal_Int32 nParamPos = -1; + for(; aIter != aEnd && i <= Index; ++aIter) + { + ++nParamPos; + if ( !*aIter ) + { + ++i; + } + } + return m_xSource->getByIndex(nParamPos); + } + }; +} + +// ----------------------------------------------------------------------------- +void askForParameters(const Reference< XSingleSelectQueryComposer >& _xComposer, + const Reference<XParameters>& _xParameters, + const Reference< XConnection>& _xConnection, + const Reference< XInteractionHandler >& _rxHandler, + const ::std::bit_vector& _aParametersSet) +{ + OSL_ENSURE(_xComposer.is(),"dbtools::askForParameters XSQLQueryComposer is null!"); + OSL_ENSURE(_xParameters.is(),"dbtools::askForParameters XParameters is null!"); + OSL_ENSURE(_xConnection.is(),"dbtools::askForParameters XConnection is null!"); + OSL_ENSURE(_rxHandler.is(),"dbtools::askForParameters XInteractionHandler is null!"); + + // we have to set this here again because getCurrentSettingsComposer can force a setpropertyvalue + Reference<XParametersSupplier> xParameters = Reference<XParametersSupplier> (_xComposer, UNO_QUERY); + + Reference<XIndexAccess> xParamsAsIndicies = xParameters.is() ? xParameters->getParameters() : Reference<XIndexAccess>(); + Reference<XNameAccess> xParamsAsNames(xParamsAsIndicies, UNO_QUERY); + sal_Int32 nParamCount = xParamsAsIndicies.is() ? xParamsAsIndicies->getCount() : 0; + ::std::bit_vector aNewParameterSet( _aParametersSet ); + if ( nParamCount || ::std::count(aNewParameterSet.begin(),aNewParameterSet.end(),true) != nParamCount ) + { + static const ::rtl::OUString PROPERTY_NAME(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_NAME)); + aNewParameterSet.resize(nParamCount ,false); + typedef ::std::map< ::rtl::OUString, ::std::vector<sal_Int32> > TParameterPositions; + TParameterPositions aParameterNames; + for(sal_Int32 i = 0; i < nParamCount; ++i) + { + Reference<XPropertySet> xParam(xParamsAsIndicies->getByIndex(i),UNO_QUERY); + ::rtl::OUString sName; + xParam->getPropertyValue(PROPERTY_NAME) >>= sName; + + TParameterPositions::iterator aFind = aParameterNames.find(sName); + if ( aFind != aParameterNames.end() ) + aNewParameterSet[i] = true; + aParameterNames[sName].push_back(i+1); + } + // build an interaction request + // two continuations (Ok and Cancel) + OInteractionAbort* pAbort = new OInteractionAbort; + OParameterContinuation* pParams = new OParameterContinuation; + // the request + ParametersRequest aRequest; + Reference<XIndexAccess> xWrappedParameters = new OParameterWrapper(aNewParameterSet,xParamsAsIndicies); + aRequest.Parameters = xWrappedParameters; + aRequest.Connection = _xConnection; + OInteractionRequest* pRequest = new OInteractionRequest(makeAny(aRequest)); + Reference< XInteractionRequest > xRequest(pRequest); + // some knittings + pRequest->addContinuation(pAbort); + pRequest->addContinuation(pParams); + + // execute the request + _rxHandler->handle(xRequest); + + if (!pParams->wasSelected()) + { + // canceled by the user (i.e. (s)he canceled the dialog) + RowSetVetoException e; + e.ErrorCode = ParameterInteractionCancelled; + throw e; + } + + // now transfer the values from the continuation object to the parameter columns + Sequence< PropertyValue > aFinalValues = pParams->getValues(); + const PropertyValue* pFinalValues = aFinalValues.getConstArray(); + for (sal_Int32 i=0; i<aFinalValues.getLength(); ++i, ++pFinalValues) + { + Reference< XPropertySet > xParamColumn(xWrappedParameters->getByIndex(i),UNO_QUERY); + if (xParamColumn.is()) + { + ::rtl::OUString sName; + xParamColumn->getPropertyValue(PROPERTY_NAME) >>= sName; + OSL_ENSURE(sName.equals(pFinalValues->Name), "::dbaui::askForParameters: inconsistent parameter names!"); + + // determine the field type and ... + sal_Int32 nParamType = 0; + xParamColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_TYPE)) >>= nParamType; + // ... the scale of the parameter column + sal_Int32 nScale = 0; + if (hasProperty(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_SCALE), xParamColumn)) + xParamColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_SCALE)) >>= nScale; + // (the index of the parameters is one-based) + TParameterPositions::iterator aFind = aParameterNames.find(pFinalValues->Name); + ::std::vector<sal_Int32>::iterator aIterPos = aFind->second.begin(); + ::std::vector<sal_Int32>::iterator aEndPos = aFind->second.end(); + for(;aIterPos != aEndPos;++aIterPos) + { + if ( _aParametersSet.empty() || !_aParametersSet[(*aIterPos)-1] ) + { + _xParameters->setObjectWithInfo(*aIterPos, pFinalValues->Value, nParamType, nScale); + } + } + } + } + } +} +// ----------------------------------------------------------------------------- +void setObjectWithInfo(const Reference<XParameters>& _xParams, + sal_Int32 parameterIndex, + const Any& x, + sal_Int32 sqlType, + sal_Int32 scale) throw(SQLException, RuntimeException) +{ + ORowSetValue aVal; + aVal.fill(x); + setObjectWithInfo(_xParams,parameterIndex,aVal,sqlType,scale); +} +// ----------------------------------------------------------------------------- +void setObjectWithInfo(const Reference<XParameters>& _xParams, + sal_Int32 parameterIndex, + const ::connectivity::ORowSetValue& _rValue, + sal_Int32 sqlType, + sal_Int32 scale) throw(SQLException, RuntimeException) +{ + if ( _rValue.isNull() ) + _xParams->setNull(parameterIndex,sqlType); + else + { + switch(sqlType) + { + case DataType::DECIMAL: + case DataType::NUMERIC: + _xParams->setObjectWithInfo(parameterIndex,_rValue.makeAny(),sqlType,scale); + break; + case DataType::CHAR: + case DataType::VARCHAR: + case DataType::LONGVARCHAR: + _xParams->setString(parameterIndex,_rValue); + break; + case DataType::CLOB: + { + Any x(_rValue.makeAny()); + ::rtl::OUString sValue; + if ( x >>= sValue ) + _xParams->setString(parameterIndex,sValue); + else + { + Reference< XClob > xClob; + if(x >>= xClob) + _xParams->setClob(parameterIndex,xClob); + else + { + Reference< ::com::sun::star::io::XInputStream > xStream; + if(x >>= xStream) + _xParams->setCharacterStream(parameterIndex,xStream,xStream->available()); + } + } + } + break; + case DataType::BIGINT: + if ( _rValue.isSigned() ) + _xParams->setLong(parameterIndex,_rValue); + else + _xParams->setString(parameterIndex,_rValue); + break; + + case DataType::FLOAT: + _xParams->setFloat(parameterIndex,_rValue); + break; + case DataType::REAL: + case DataType::DOUBLE: + _xParams->setDouble(parameterIndex,_rValue); + break; + case DataType::DATE: + _xParams->setDate(parameterIndex,_rValue); + break; + case DataType::TIME: + _xParams->setTime(parameterIndex,_rValue); + break; + case DataType::TIMESTAMP: + _xParams->setTimestamp(parameterIndex,_rValue); + break; + case DataType::BINARY: + case DataType::VARBINARY: + case DataType::LONGVARBINARY: + case DataType::BLOB: + { + Any x(_rValue.makeAny()); + Sequence< sal_Int8> aBytes; + if(x >>= aBytes) + _xParams->setBytes(parameterIndex,aBytes); + else + { + Reference< XBlob > xBlob; + if(x >>= xBlob) + _xParams->setBlob(parameterIndex,xBlob); + else + { + Reference< XClob > xClob; + if(x >>= xClob) + _xParams->setClob(parameterIndex,xClob); + else + { + Reference< ::com::sun::star::io::XInputStream > xBinStream; + if(x >>= xBinStream) + _xParams->setBinaryStream(parameterIndex,xBinStream,xBinStream->available()); + } + } + } + } + break; + case DataType::BIT: + case DataType::BOOLEAN: + _xParams->setBoolean(parameterIndex,_rValue); + break; + case DataType::TINYINT: + if ( _rValue.isSigned() ) + _xParams->setByte(parameterIndex,_rValue); + else + _xParams->setShort(parameterIndex,_rValue); + break; + case DataType::SMALLINT: + if ( _rValue.isSigned() ) + _xParams->setShort(parameterIndex,_rValue); + else + _xParams->setInt(parameterIndex,_rValue); + break; + case DataType::INTEGER: + if ( _rValue.isSigned() ) + _xParams->setInt(parameterIndex,_rValue); + else + _xParams->setLong(parameterIndex,_rValue); + break; + default: + { + ::connectivity::SharedResources aResources; + const ::rtl::OUString sError( aResources.getResourceStringWithSubstitution( + STR_UNKNOWN_PARA_TYPE, + "$position$", ::rtl::OUString::valueOf(parameterIndex) + ) ); + ::dbtools::throwGenericSQLException(sError,NULL); + } + } + } +} + +// -------------------------------------------------------------------- +void getBoleanComparisonPredicate( const ::rtl::OUString& _rExpression, const sal_Bool _bValue, const sal_Int32 _nBooleanComparisonMode, + ::rtl::OUStringBuffer& _out_rSQLPredicate ) +{ + switch ( _nBooleanComparisonMode ) + { + case BooleanComparisonMode::IS_LITERAL: + _out_rSQLPredicate.append( _rExpression ); + if ( _bValue ) + _out_rSQLPredicate.appendAscii( " IS TRUE" ); + else + _out_rSQLPredicate.appendAscii( " IS FALSE" ); + break; + + case BooleanComparisonMode::EQUAL_LITERAL: + _out_rSQLPredicate.append( _rExpression ); + _out_rSQLPredicate.appendAscii( _bValue ? " = TRUE" : " = FALSE" ); + break; + + case BooleanComparisonMode::ACCESS_COMPAT: + if ( _bValue ) + { + _out_rSQLPredicate.appendAscii( " NOT ( ( " ); + _out_rSQLPredicate.append( _rExpression ); + _out_rSQLPredicate.appendAscii( " = 0 ) OR ( " ); + _out_rSQLPredicate.append( _rExpression ); + _out_rSQLPredicate.appendAscii( " IS NULL ) )" ); + } + else + { + _out_rSQLPredicate.append( _rExpression ); + _out_rSQLPredicate.appendAscii( " = 0" ); + } + break; + + case BooleanComparisonMode::EQUAL_INTEGER: + // fall through + default: + _out_rSQLPredicate.append( _rExpression ); + _out_rSQLPredicate.appendAscii( _bValue ? " = 1" : " = 0" ); + break; + } +} + +//......................................................................... +} // namespace dbtools +//......................................................................... + +//......................................................................... +namespace connectivity +{ +//......................................................................... + +void release(oslInterlockedCount& _refCount, + ::cppu::OBroadcastHelper& rBHelper, + Reference< XInterface >& _xInterface, + ::com::sun::star::lang::XComponent* _pObject) +{ + if (osl_decrementInterlockedCount( &_refCount ) == 0) + { + osl_incrementInterlockedCount( &_refCount ); + + if (!rBHelper.bDisposed && !rBHelper.bInDispose) + { + // remember the parent + Reference< XInterface > xParent; + { + ::osl::MutexGuard aGuard( rBHelper.rMutex ); + xParent = _xInterface; + _xInterface = NULL; + } + + // First dispose + _pObject->dispose(); + + // only the alive ref holds the object + OSL_ASSERT( _refCount == 1 ); + + // release the parent in the ~ + if (xParent.is()) + { + ::osl::MutexGuard aGuard( rBHelper.rMutex ); + _xInterface = xParent; + } + +// // destroy the object if xHoldAlive decrement the refcount to 0 +// m_pDerivedImplementation->WEAK::release(); + } + } + else + osl_incrementInterlockedCount( &_refCount ); +} + +void checkDisposed(sal_Bool _bThrow) throw ( DisposedException ) +{ + if (_bThrow) + throw DisposedException(); + +} +// ------------------------------------------------------------------------- + OSQLColumns::Vector::const_iterator find( OSQLColumns::Vector::const_iterator __first, + OSQLColumns::Vector::const_iterator __last, + const ::rtl::OUString& _rVal, + const ::comphelper::UStringMixEqual& _rCase) + { + ::rtl::OUString sName = OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_NAME); + return find(__first,__last,sName,_rVal,_rCase); + } + // ------------------------------------------------------------------------- + OSQLColumns::Vector::const_iterator findRealName( OSQLColumns::Vector::const_iterator __first, + OSQLColumns::Vector::const_iterator __last, + const ::rtl::OUString& _rVal, + const ::comphelper::UStringMixEqual& _rCase) + { + ::rtl::OUString sRealName = OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_REALNAME); + return find(__first,__last,sRealName,_rVal,_rCase); + } + // ------------------------------------------------------------------------- + OSQLColumns::Vector::const_iterator find( OSQLColumns::Vector::const_iterator __first, + OSQLColumns::Vector::const_iterator __last, + const ::rtl::OUString& _rProp, + const ::rtl::OUString& _rVal, + const ::comphelper::UStringMixEqual& _rCase) + { + while (__first != __last && !_rCase(getString((*__first)->getPropertyValue(_rProp)),_rVal)) + ++__first; + return __first; + } + +// ----------------------------------------------------------------------------- +} //namespace connectivity +// ----------------------------------------------------------------------------- + diff --git a/connectivity/source/commontools/dbtools2.cxx b/connectivity/source/commontools/dbtools2.cxx new file mode 100644 index 000000000000..c9a878fe1840 --- /dev/null +++ b/connectivity/source/commontools/dbtools2.cxx @@ -0,0 +1,974 @@ +/************************************************************************* + * + * 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 "connectivity/dbtools.hxx" +#include "connectivity/dbconversion.hxx" +#include "connectivity/dbcharset.hxx" +#include "connectivity/SQLStatementHelper.hxx" +#include <unotools/confignode.hxx> +#include "resource/sharedresources.hxx" +#include "resource/common_res.hrc" +#include <com/sun/star/sdbc/XConnection.hpp> +#include <com/sun/star/sdbc/ColumnValue.hpp> +#include <com/sun/star/sdbc/DataType.hpp> +#include <com/sun/star/sdbc/XRow.hpp> +#include <com/sun/star/sdbc/XResultSetMetaDataSupplier.hpp> +#include <com/sun/star/sdbcx/XKeysSupplier.hpp> +#include <com/sun/star/sdbc/XDriverAccess.hpp> +#include <com/sun/star/sdbcx/XDataDefinitionSupplier.hpp> +#include <com/sun/star/sdbcx/Privilege.hpp> +#include <com/sun/star/container/XIndexAccess.hpp> +#include <com/sun/star/container/XEnumerationAccess.hpp> +#include <com/sun/star/sdbc/KeyRule.hpp> +#include <com/sun/star/sdbcx/KeyType.hpp> +#include "TConnection.hxx" +#include "connectivity/sdbcx/VColumn.hxx" +#include <com/sun/star/frame/XModel.hpp> +#include <com/sun/star/container/XChild.hpp> + +#include <tools/diagnose_ex.h> +#include <unotools/sharedunocomponent.hxx> +#include <comphelper/configurationhelper.hxx> + +//......................................................................... +namespace dbtools +{ +//......................................................................... + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::beans; + using namespace ::com::sun::star::sdbc; + using namespace ::com::sun::star::sdbcx; + using namespace ::com::sun::star::lang; + using namespace ::com::sun::star::container; + using namespace ::com::sun::star::frame; + using namespace connectivity; + using namespace comphelper; + +::rtl::OUString createStandardColumnPart(const Reference< XPropertySet >& xColProp,const Reference< XConnection>& _xConnection,ISQLStatementHelper* _pHelper,const ::rtl::OUString& _sCreatePattern) +{ + + Reference<XDatabaseMetaData> xMetaData = _xConnection->getMetaData(); + + ::dbtools::OPropertyMap& rPropMap = OMetaConnection::getPropMap(); + + ::rtl::OUString sTypeName; + sal_Int32 nDataType = 0; + sal_Int32 nPrecision = 0; + sal_Int32 nScale = 0; + + const ::rtl::OUString sQuoteString = xMetaData->getIdentifierQuoteString(); + ::rtl::OUStringBuffer aSql = ::dbtools::quoteName(sQuoteString,::comphelper::getString(xColProp->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_NAME)))); + + aSql.appendAscii(" "); + + nDataType = nPrecision = nScale = 0; + sal_Bool bIsAutoIncrement = sal_False; + xColProp->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_TYPENAME)) >>= sTypeName; + xColProp->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_TYPE)) >>= nDataType; + xColProp->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_PRECISION)) >>= nPrecision; + xColProp->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_SCALE)) >>= nScale; + xColProp->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_ISAUTOINCREMENT)) >>= bIsAutoIncrement; + + // check if the user enter a specific string to create autoincrement values + ::rtl::OUString sAutoIncrementValue; + Reference<XPropertySetInfo> xPropInfo = xColProp->getPropertySetInfo(); + if ( xPropInfo.is() && xPropInfo->hasPropertyByName(rPropMap.getNameByIndex(PROPERTY_ID_AUTOINCREMENTCREATION)) ) + xColProp->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_AUTOINCREMENTCREATION)) >>= sAutoIncrementValue; + // look if we have to use precisions + sal_Bool bUseLiteral = sal_False; + ::rtl::OUString sPreFix,sPostFix,sCreateParams; + { + Reference<XResultSet> xRes = xMetaData->getTypeInfo(); + if(xRes.is()) + { + Reference<XRow> xRow(xRes,UNO_QUERY); + while(xRes->next()) + { + ::rtl::OUString sTypeName2Cmp = xRow->getString(1); + sal_Int32 nType = xRow->getShort(2); + sPreFix = xRow->getString (4); + sPostFix = xRow->getString (5); + sCreateParams = xRow->getString(6); + // first identical type will be used if typename is empty + if ( !sTypeName.getLength() && nType == nDataType ) + sTypeName = sTypeName2Cmp; + + if( sTypeName.equalsIgnoreAsciiCase(sTypeName2Cmp) && nType == nDataType && sCreateParams.getLength() && !xRow->wasNull()) + { + bUseLiteral = sal_True; + break; + } + } + } + } + + sal_Int32 nIndex = 0; + if ( sAutoIncrementValue.getLength() && (nIndex = sTypeName.indexOf(sAutoIncrementValue)) != -1 ) + { + sTypeName = sTypeName.replaceAt(nIndex,sTypeName.getLength() - nIndex,::rtl::OUString()); + } + + if ( (nPrecision > 0 || nScale > 0) && bUseLiteral ) + { + sal_Int32 nParenPos = sTypeName.indexOf('('); + if ( nParenPos == -1 ) + { + aSql.append(sTypeName); + aSql.appendAscii("("); + } + else + { + aSql.append(sTypeName.copy(0,++nParenPos)); + } + + if ( nPrecision > 0 && nDataType != DataType::TIMESTAMP ) + { + aSql.append(nPrecision); + if ( (nScale > 0) || (_sCreatePattern.getLength() && sCreateParams.indexOf(_sCreatePattern) != -1) ) + aSql.appendAscii(","); + } + if ( (nScale > 0) || (_sCreatePattern.getLength() && sCreateParams.indexOf(_sCreatePattern) != -1 ) || nDataType == DataType::TIMESTAMP ) + aSql.append(nScale); + + if ( nParenPos == -1 ) + aSql.appendAscii(")"); + else + { + nParenPos = sTypeName.indexOf(')',nParenPos); + aSql.append(sTypeName.copy(nParenPos)); + } + } + else + aSql.append(sTypeName); // simply add the type name + + ::rtl::OUString aDefault = ::comphelper::getString(xColProp->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_DEFAULTVALUE))); + if ( aDefault.getLength() ) + { + aSql.append(::rtl::OUString::createFromAscii(" DEFAULT ")); + aSql.append(sPreFix); + aSql.append(aDefault); + aSql.append(sPostFix); + } // if ( aDefault.getLength() ) + + if(::comphelper::getINT32(xColProp->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_ISNULLABLE))) == ColumnValue::NO_NULLS) + aSql.append(::rtl::OUString::createFromAscii(" NOT NULL")); + + if ( bIsAutoIncrement && sAutoIncrementValue.getLength()) + { + aSql.appendAscii(" "); + aSql.append(sAutoIncrementValue); + } + + if ( _pHelper ) + _pHelper->addComment(xColProp,aSql); + + return aSql.makeStringAndClear(); +} +// ----------------------------------------------------------------------------- + +::rtl::OUString createStandardCreateStatement(const Reference< XPropertySet >& descriptor,const Reference< XConnection>& _xConnection,ISQLStatementHelper* _pHelper,const ::rtl::OUString& _sCreatePattern) +{ + ::rtl::OUStringBuffer aSql = ::rtl::OUString::createFromAscii("CREATE TABLE "); + ::rtl::OUString sCatalog,sSchema,sTable,sComposedName; + + Reference<XDatabaseMetaData> xMetaData = _xConnection->getMetaData(); + ::dbtools::OPropertyMap& rPropMap = OMetaConnection::getPropMap(); + + descriptor->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_CATALOGNAME)) >>= sCatalog; + descriptor->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_SCHEMANAME)) >>= sSchema; + descriptor->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_NAME)) >>= sTable; + + sComposedName = ::dbtools::composeTableName( xMetaData, sCatalog, sSchema, sTable, sal_True, ::dbtools::eInTableDefinitions ); + if ( !sComposedName.getLength() ) + ::dbtools::throwFunctionSequenceException(_xConnection); + + aSql.append(sComposedName); + aSql.append(::rtl::OUString::createFromAscii(" (")); + + // columns + Reference<XColumnsSupplier> xColumnSup(descriptor,UNO_QUERY); + Reference<XIndexAccess> xColumns(xColumnSup->getColumns(),UNO_QUERY); + // check if there are columns + if(!xColumns.is() || !xColumns->getCount()) + ::dbtools::throwFunctionSequenceException(_xConnection); + + Reference< XPropertySet > xColProp; + + sal_Int32 nCount = xColumns->getCount(); + for(sal_Int32 i=0;i<nCount;++i) + { + if ( (xColumns->getByIndex(i) >>= xColProp) && xColProp.is() ) + { + aSql.append(createStandardColumnPart(xColProp,_xConnection,_pHelper,_sCreatePattern)); + aSql.appendAscii(","); + } + } + return aSql.makeStringAndClear(); +} +namespace +{ + ::rtl::OUString generateColumnNames(const Reference<XIndexAccess>& _xColumns,const Reference<XDatabaseMetaData>& _xMetaData) + { + ::dbtools::OPropertyMap& rPropMap = OMetaConnection::getPropMap(); + static const ::rtl::OUString sComma(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(","))); + + const ::rtl::OUString sQuote(_xMetaData->getIdentifierQuoteString()); + ::rtl::OUString sSql = ::rtl::OUString::createFromAscii(" ("); + Reference< XPropertySet > xColProp; + + sal_Int32 nColCount = _xColumns->getCount(); + for(sal_Int32 i=0;i<nColCount;++i) + { + if ( (_xColumns->getByIndex(i) >>= xColProp) && xColProp.is() ) + sSql += ::dbtools::quoteName(sQuote,::comphelper::getString(xColProp->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_NAME)))) + + sComma; + } + + if ( nColCount ) + sSql = sSql.replaceAt(sSql.getLength()-1,1,::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(")"))); + return sSql; + } +} +// ----------------------------------------------------------------------------- +::rtl::OUString createStandardKeyStatement(const Reference< XPropertySet >& descriptor,const Reference< XConnection>& _xConnection) +{ + Reference<XDatabaseMetaData> xMetaData = _xConnection->getMetaData(); + ::dbtools::OPropertyMap& rPropMap = OMetaConnection::getPropMap(); + + ::rtl::OUStringBuffer aSql; + // keys + Reference<XKeysSupplier> xKeySup(descriptor,UNO_QUERY); + Reference<XIndexAccess> xKeys = xKeySup->getKeys(); + if ( xKeys.is() ) + { + Reference< XPropertySet > xColProp; + Reference<XIndexAccess> xColumns; + Reference<XColumnsSupplier> xColumnSup; + ::rtl::OUString sCatalog,sSchema,sTable,sComposedName; + sal_Bool bPKey = sal_False; + for(sal_Int32 i=0;i<xKeys->getCount();++i) + { + if ( (xKeys->getByIndex(i) >>= xColProp) && xColProp.is() ) + { + + sal_Int32 nKeyType = ::comphelper::getINT32(xColProp->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_TYPE))); + + if ( nKeyType == KeyType::PRIMARY ) + { + if(bPKey) + ::dbtools::throwFunctionSequenceException(_xConnection); + + bPKey = sal_True; + xColumnSup = Reference<XColumnsSupplier>(xColProp,UNO_QUERY); + xColumns = Reference<XIndexAccess>(xColumnSup->getColumns(),UNO_QUERY); + if(!xColumns.is() || !xColumns->getCount()) + ::dbtools::throwFunctionSequenceException(_xConnection); + + const ::rtl::OUString sQuote = xMetaData->getIdentifierQuoteString(); + aSql.append(::rtl::OUString::createFromAscii(" PRIMARY KEY ")); + aSql.append(generateColumnNames(xColumns,xMetaData)); + } + else if(nKeyType == KeyType::UNIQUE) + { + xColumnSup = Reference<XColumnsSupplier>(xColProp,UNO_QUERY); + xColumns = Reference<XIndexAccess>(xColumnSup->getColumns(),UNO_QUERY); + if(!xColumns.is() || !xColumns->getCount()) + ::dbtools::throwFunctionSequenceException(_xConnection); + + const ::rtl::OUString sQuote = xMetaData->getIdentifierQuoteString(); + aSql.append(::rtl::OUString::createFromAscii(" UNIQUE ")); + aSql.append(generateColumnNames(xColumns,xMetaData)); + } + else if(nKeyType == KeyType::FOREIGN) + { + sal_Int32 nDeleteRule = getINT32(xColProp->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_DELETERULE))); + + xColumnSup = Reference<XColumnsSupplier>(xColProp,UNO_QUERY); + xColumns = Reference<XIndexAccess>(xColumnSup->getColumns(),UNO_QUERY); + if(!xColumns.is() || !xColumns->getCount()) + ::dbtools::throwFunctionSequenceException(_xConnection); + + aSql.append(::rtl::OUString::createFromAscii(" FOREIGN KEY ")); + ::rtl::OUString sRefTable = getString(xColProp->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_REFERENCEDTABLE))); + ::dbtools::qualifiedNameComponents(xMetaData, + sRefTable, + sCatalog, + sSchema, + sTable, + ::dbtools::eInDataManipulation); + sComposedName = ::dbtools::composeTableName( xMetaData, sCatalog, sSchema, sTable, sal_True, ::dbtools::eInTableDefinitions ); + + + if ( !sComposedName.getLength() ) + ::dbtools::throwFunctionSequenceException(_xConnection); + + aSql.append(generateColumnNames(xColumns,xMetaData)); + + switch(nDeleteRule) + { + case KeyRule::CASCADE: + aSql.append(::rtl::OUString::createFromAscii(" ON DELETE CASCADE ")); + break; + case KeyRule::RESTRICT: + aSql.append(::rtl::OUString::createFromAscii(" ON DELETE RESTRICT ")); + break; + case KeyRule::SET_NULL: + aSql.append(::rtl::OUString::createFromAscii(" ON DELETE SET NULL ")); + break; + case KeyRule::SET_DEFAULT: + aSql.append(::rtl::OUString::createFromAscii(" ON DELETE SET DEFAULT ")); + break; + default: + ; + } + } + } + } + } + + if ( aSql.getLength() ) + { + if ( aSql.charAt(aSql.getLength()-1) == ',' ) + aSql.setCharAt(aSql.getLength()-1,')'); + else + aSql.appendAscii(")"); + } + + return aSql.makeStringAndClear(); + +} +// ----------------------------------------------------------------------------- +::rtl::OUString createSqlCreateTableStatement( const Reference< XPropertySet >& descriptor, + const Reference< XConnection>& _xConnection, + ISQLStatementHelper* _pHelper, + const ::rtl::OUString& _sCreatePattern) +{ + ::rtl::OUString aSql = ::dbtools::createStandardCreateStatement(descriptor,_xConnection,_pHelper,_sCreatePattern); + const ::rtl::OUString sKeyStmt = ::dbtools::createStandardKeyStatement(descriptor,_xConnection); + if ( sKeyStmt.getLength() ) + aSql += sKeyStmt; + else + { + if ( aSql.lastIndexOf(',') == (aSql.getLength()-1) ) + aSql = aSql.replaceAt(aSql.getLength()-1,1,::rtl::OUString::createFromAscii(")")); + else + aSql += ::rtl::OUString::createFromAscii(")"); + } + return aSql; +} +namespace +{ + Reference<XPropertySet> lcl_createSDBCXColumn(const Reference<XNameAccess>& _xPrimaryKeyColumns, + const Reference<XConnection>& _xConnection, + const Any& _aCatalog, + const ::rtl::OUString& _aSchema, + const ::rtl::OUString& _aTable, + const ::rtl::OUString& _rQueryName, + const ::rtl::OUString& _rName, + sal_Bool _bCase, + sal_Bool _bQueryForInfo, + sal_Bool _bIsAutoIncrement, + sal_Bool _bIsCurrency, + sal_Int32 _nDataType) + { + Reference<XPropertySet> xProp; + Reference<XDatabaseMetaData> xMetaData = _xConnection->getMetaData(); + Reference< XResultSet > xResult = xMetaData->getColumns(_aCatalog, _aSchema, _aTable, _rQueryName); + + if ( xResult.is() ) + { + UStringMixEqual aMixCompare(_bCase); + Reference< XRow > xRow(xResult,UNO_QUERY); + while( xResult->next() ) + { + if ( aMixCompare(xRow->getString(4),_rName) ) + { + sal_Int32 nField5 = xRow->getInt(5); + ::rtl::OUString aField6 = xRow->getString(6); + sal_Int32 nField7 = xRow->getInt(7) + , nField9 = xRow->getInt(9) + , nField11= xRow->getInt(11); + ::rtl::OUString sField12 = xRow->getString(12), + sField13 = xRow->getString(13); + ::comphelper::disposeComponent(xRow); + + sal_Bool bAutoIncrement = _bIsAutoIncrement + ,bIsCurrency = _bIsCurrency; + if ( _bQueryForInfo ) + { + const ::rtl::OUString sQuote = xMetaData->getIdentifierQuoteString(); + ::rtl::OUString sQuotedName = ::dbtools::quoteName(sQuote,_rName); + ::rtl::OUString sComposedName; + sComposedName = composeTableNameForSelect(_xConnection, getString( _aCatalog ), _aSchema, _aTable ); + + ColumnInformationMap aInfo(_bCase); + collectColumnInformation(_xConnection,sComposedName,sQuotedName,aInfo); + ColumnInformationMap::iterator aIter = aInfo.begin(); + if ( aIter != aInfo.end() ) + { + bAutoIncrement = aIter->second.first.first; + bIsCurrency = aIter->second.first.second; + if ( DataType::OTHER == nField5 ) + nField5 = aIter->second.second; + } + } + else if ( DataType::OTHER == nField5 ) + nField5 = _nDataType; + + if ( nField11 != ColumnValue::NO_NULLS ) + { + try + { + if ( _xPrimaryKeyColumns.is() ) + { + if ( _xPrimaryKeyColumns->hasByName(_rName) ) + nField11 = ColumnValue::NO_NULLS; + + } + else + { + Reference< XResultSet > xPKeys = xMetaData->getPrimaryKeys( _aCatalog, _aSchema, _aTable ); + Reference< XRow > xPKeyRow( xPKeys, UNO_QUERY_THROW ); + while( xPKeys->next() ) // there can be only one primary key + { + ::rtl::OUString sKeyColumn = xPKeyRow->getString(4); + if ( aMixCompare(_rName,sKeyColumn) ) + { + nField11 = ColumnValue::NO_NULLS; + break; + } + } + } + } + catch(SQLException&) + { + OSL_ENSURE( false, "lcl_createSDBCXColumn: caught an exception!" ); + } + } + + connectivity::sdbcx::OColumn* pRet = new connectivity::sdbcx::OColumn(_rName, + aField6, + sField13, + sField12, + nField11, + nField7, + nField9, + nField5, + bAutoIncrement, + sal_False, + bIsCurrency, + _bCase); + + xProp = pRet; + break; + } + } + } + + return xProp; + } + //------------------------------------------------------------------ + Reference< XModel> lcl_getXModel(const Reference< XInterface>& _xIface) + { + Reference< XInterface > xParent = _xIface; + Reference< XModel > xModel(xParent,UNO_QUERY);; + while( xParent.is() && !xModel.is() ) + { + Reference<XChild> xChild(xParent,UNO_QUERY); + xParent.set(xChild.is() ? xChild->getParent() : Reference< XInterface >(),UNO_QUERY); + xModel.set(xParent,UNO_QUERY); + } + return xModel; + } +} +// ----------------------------------------------------------------------------- +Reference<XPropertySet> createSDBCXColumn(const Reference<XPropertySet>& _xTable, + const Reference<XConnection>& _xConnection, + const ::rtl::OUString& _rName, + sal_Bool _bCase, + sal_Bool _bQueryForInfo, + sal_Bool _bIsAutoIncrement, + sal_Bool _bIsCurrency, + sal_Int32 _nDataType) +{ + Reference<XPropertySet> xProp; + OSL_ENSURE(_xTable.is(),"Table is NULL!"); + if ( !_xTable.is() ) + return xProp; + + ::dbtools::OPropertyMap& rPropMap = OMetaConnection::getPropMap(); + Reference<XDatabaseMetaData> xMetaData = _xConnection->getMetaData(); + Any aCatalog; + aCatalog = _xTable->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_CATALOGNAME)); + + ::rtl::OUString aSchema, aTable; + _xTable->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_SCHEMANAME)) >>= aSchema; + _xTable->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_NAME)) >>= aTable; + + Reference<XNameAccess> xPrimaryKeyColumns = getPrimaryKeyColumns_throw(_xTable); + + xProp = lcl_createSDBCXColumn(xPrimaryKeyColumns,_xConnection,aCatalog, aSchema, aTable, _rName,_rName,_bCase,_bQueryForInfo,_bIsAutoIncrement,_bIsCurrency,_nDataType); + if ( !xProp.is() ) + { + xProp = lcl_createSDBCXColumn(xPrimaryKeyColumns,_xConnection,aCatalog, aSchema, aTable, ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("%")),_rName,_bCase,_bQueryForInfo,_bIsAutoIncrement,_bIsCurrency,_nDataType); + if ( !xProp.is() ) + xProp = new connectivity::sdbcx::OColumn(_rName, + ::rtl::OUString(),::rtl::OUString(),::rtl::OUString(), + ColumnValue::NULLABLE_UNKNOWN, + 0, + 0, + DataType::VARCHAR, + _bIsAutoIncrement, + sal_False, + _bIsCurrency, + _bCase); + + } + + return xProp; +} + +// ----------------------------------------------------------------------------- +bool getBooleanDataSourceSetting( const Reference< XConnection >& _rxConnection, const sal_Char* _pAsciiSettingName ) +{ + bool bValue( false ); + try + { + Reference< XPropertySet> xDataSourceProperties( findDataSource( _rxConnection ), UNO_QUERY ); + OSL_ENSURE( xDataSourceProperties.is(), "::dbtools::getBooleanDataSourceSetting: somebody is using this with a non-SDB-level connection!" ); + if ( xDataSourceProperties.is() ) + { + Reference< XPropertySet > xSettings( + xDataSourceProperties->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Settings") ) ), + UNO_QUERY_THROW + ); + OSL_VERIFY( xSettings->getPropertyValue( ::rtl::OUString::createFromAscii( _pAsciiSettingName ) ) >>= bValue ); + } + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + return bValue; +} +// ------------------------------------------------------------------------- +bool getDataSourceSetting( const Reference< XInterface >& _xChild, const ::rtl::OUString& _sAsciiSettingsName, + Any& /* [out] */ _rSettingsValue ) +{ + bool bIsPresent = false; + try + { + const Reference< XPropertySet> xDataSourceProperties( findDataSource( _xChild ), UNO_QUERY ); + OSL_ENSURE( xDataSourceProperties.is(), "getDataSourceSetting: invalid data source object!" ); + if ( !xDataSourceProperties.is() ) + return false; + + const Reference< XPropertySet > xSettings( + xDataSourceProperties->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Settings") ) ), + UNO_QUERY_THROW + ); + + _rSettingsValue = xSettings->getPropertyValue( _sAsciiSettingsName ); + bIsPresent = true; + } + catch( const Exception& ) + { + bIsPresent = false; + } + return bIsPresent; +} +// ------------------------------------------------------------------------- +bool getDataSourceSetting( const Reference< XInterface >& _rxDataSource, const sal_Char* _pAsciiSettingsName, + Any& /* [out] */ _rSettingsValue ) +{ + ::rtl::OUString sAsciiSettingsName = ::rtl::OUString::createFromAscii(_pAsciiSettingsName); + return getDataSourceSetting( _rxDataSource, sAsciiSettingsName,_rSettingsValue ); +} +// ----------------------------------------------------------------------------- +sal_Bool isDataSourcePropertyEnabled(const Reference<XInterface>& _xProp,const ::rtl::OUString& _sProperty,sal_Bool _bDefault) +{ + sal_Bool bEnabled = _bDefault; + try + { + Reference< XPropertySet> xProp(findDataSource(_xProp),UNO_QUERY); + if ( xProp.is() ) + { + Sequence< PropertyValue > aInfo; + xProp->getPropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Info"))) >>= aInfo; + const PropertyValue* pValue =::std::find_if(aInfo.getConstArray(), + aInfo.getConstArray() + aInfo.getLength(), + ::std::bind2nd(TPropertyValueEqualFunctor(),_sProperty)); + if ( pValue && pValue != (aInfo.getConstArray() + aInfo.getLength()) ) + pValue->Value >>= bEnabled; + } + } + catch(SQLException&) + { + DBG_UNHANDLED_EXCEPTION(); + } + return bEnabled; +} +// ----------------------------------------------------------------------------- +Reference< XTablesSupplier> getDataDefinitionByURLAndConnection( + const ::rtl::OUString& _rsUrl, + const Reference< XConnection>& _xConnection, + const Reference< XMultiServiceFactory>& _rxFactory) +{ + Reference< XTablesSupplier> xTablesSup; + try + { + Reference< XDriverAccess> xManager( + _rxFactory->createInstance( ::rtl::OUString::createFromAscii("com.sun.star.sdbc.DriverManager") ), + UNO_QUERY_THROW ); + Reference< XDataDefinitionSupplier > xSupp( xManager->getDriverByURL( _rsUrl ), UNO_QUERY ); + + if ( xSupp.is() ) + { + xTablesSup = xSupp->getDataDefinitionByConnection( _xConnection ); + OSL_ENSURE(xTablesSup.is(),"No table supplier!"); + } + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + return xTablesSup; +} + +// ----------------------------------------------------------------------------- +sal_Int32 getTablePrivileges(const Reference< XDatabaseMetaData>& _xMetaData, + const ::rtl::OUString& _sCatalog, + const ::rtl::OUString& _sSchema, + const ::rtl::OUString& _sTable) +{ + OSL_ENSURE(_xMetaData.is(),"Invalid metadata!"); + sal_Int32 nPrivileges = 0; + try + { + Any aVal; + if(_sCatalog.getLength()) + aVal <<= _sCatalog; + Reference< XResultSet > xPrivileges = _xMetaData->getTablePrivileges(aVal, _sSchema, _sTable); + Reference< XRow > xCurrentRow(xPrivileges, UNO_QUERY); + + if ( xCurrentRow.is() ) + { + ::rtl::OUString sUserWorkingFor = _xMetaData->getUserName(); + static const ::rtl::OUString sSELECT = ::rtl::OUString::createFromAscii("SELECT"); + static const ::rtl::OUString sINSERT = ::rtl::OUString::createFromAscii("INSERT"); + static const ::rtl::OUString sUPDATE = ::rtl::OUString::createFromAscii("UPDATE"); + static const ::rtl::OUString sDELETE = ::rtl::OUString::createFromAscii("DELETE"); + static const ::rtl::OUString sREAD = ::rtl::OUString::createFromAscii("READ"); + static const ::rtl::OUString sCREATE = ::rtl::OUString::createFromAscii("CREATE"); + static const ::rtl::OUString sALTER = ::rtl::OUString::createFromAscii("ALTER"); + static const ::rtl::OUString sREFERENCE = ::rtl::OUString::createFromAscii("REFERENCE"); + static const ::rtl::OUString sDROP = ::rtl::OUString::createFromAscii("DROP"); + // after creation the set is positioned before the first record, per definitionem +#ifdef DBG_UTIL + Reference< XResultSetMetaDataSupplier > xSup(xPrivileges,UNO_QUERY); + if ( xSup.is() ) + { + Reference< XResultSetMetaData > xRsMetaData = xSup->getMetaData(); + if ( xRsMetaData.is() ) + { + sal_Int32 nCount = xRsMetaData->getColumnCount(); + for (sal_Int32 i=1; i<=nCount; ++i) + { + ::rtl::OUString sColumnName = xRsMetaData->getColumnName(i); + } + } + } +#endif + + ::rtl::OUString sPrivilege, sGrantee; + while ( xPrivileges->next() ) + { +#ifdef DBG_UTIL + ::rtl::OUString sCat, sSchema, sName, sGrantor, sGrantable; + sCat = xCurrentRow->getString(1); + sSchema = xCurrentRow->getString(2); + sName = xCurrentRow->getString(3); + sGrantor = xCurrentRow->getString(4); +#endif + sGrantee = xCurrentRow->getString(5); + sPrivilege = xCurrentRow->getString(6); +#ifdef DBG_UTIL + sGrantable = xCurrentRow->getString(7); +#endif + + if (!sUserWorkingFor.equalsIgnoreAsciiCase(sGrantee)) + continue; + + if (sPrivilege.equalsIgnoreAsciiCase(sSELECT)) + nPrivileges |= Privilege::SELECT; + else if (sPrivilege.equalsIgnoreAsciiCase(sINSERT)) + nPrivileges |= Privilege::INSERT; + else if (sPrivilege.equalsIgnoreAsciiCase(sUPDATE)) + nPrivileges |= Privilege::UPDATE; + else if (sPrivilege.equalsIgnoreAsciiCase(sDELETE)) + nPrivileges |= Privilege::DELETE; + else if (sPrivilege.equalsIgnoreAsciiCase(sREAD)) + nPrivileges |= Privilege::READ; + else if (sPrivilege.equalsIgnoreAsciiCase(sCREATE)) + nPrivileges |= Privilege::CREATE; + else if (sPrivilege.equalsIgnoreAsciiCase(sALTER)) + nPrivileges |= Privilege::ALTER; + else if (sPrivilege.equalsIgnoreAsciiCase(sREFERENCE)) + nPrivileges |= Privilege::REFERENCE; + else if (sPrivilege.equalsIgnoreAsciiCase(sDROP)) + nPrivileges |= Privilege::DROP; + } + } + disposeComponent(xPrivileges); + } + catch(const SQLException& e) + { + static ::rtl::OUString sNotSupportedState = ::rtl::OUString::createFromAscii("IM001"); + // some drivers don't support any privileges so we assume that we are allowed to do all we want :-) + if(e.SQLState == sNotSupportedState) + nPrivileges |= Privilege::DROP | + Privilege::REFERENCE | + Privilege::ALTER | + Privilege::CREATE | + Privilege::READ | + Privilege::DELETE | + Privilege::UPDATE | + Privilege::INSERT | + Privilege::SELECT; + else + OSL_ENSURE(0,"Could not collect the privileges !"); + } + return nPrivileges; +} +// ----------------------------------------------------------------------------- +// we need some more information about the column +void collectColumnInformation(const Reference< XConnection>& _xConnection, + const ::rtl::OUString& _sComposedName, + const ::rtl::OUString& _rName, + ColumnInformationMap& _rInfo) +{ + static ::rtl::OUString STR_WHERE = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" WHERE ")); + + ::rtl::OUString sSelect = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("SELECT ")); + sSelect += _rName; + sSelect += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" FROM ")); + sSelect += _sComposedName; + sSelect += STR_WHERE; + sSelect += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("0 = 1")); + + try + { + ::utl::SharedUNOComponent< XStatement > xStmt( _xConnection->createStatement() ); + Reference< XPropertySet > xStatementProps( xStmt, UNO_QUERY_THROW ); + xStatementProps->setPropertyValue( OMetaConnection::getPropMap().getNameByIndex( PROPERTY_ID_ESCAPEPROCESSING ), makeAny( (sal_Bool)sal_False ) ); + Reference< XResultSet > xResult( xStmt->executeQuery( sSelect ), UNO_QUERY_THROW ); + Reference< XResultSetMetaDataSupplier > xSuppMeta( xResult, UNO_QUERY_THROW ); + Reference< XResultSetMetaData > xMeta( xSuppMeta->getMetaData(), UNO_QUERY_THROW ); + + sal_Int32 nCount = xMeta->getColumnCount(); + OSL_ENSURE( nCount != 0, "::dbtools::collectColumnInformation: result set has empty (column-less) meta data!" ); + for (sal_Int32 i=1; i <= nCount ; ++i) + { + _rInfo.insert(ColumnInformationMap::value_type(xMeta->getColumnName(i), + ColumnInformation(TBoolPair(xMeta->isAutoIncrement(i),xMeta->isCurrency(i)),xMeta->getColumnType(i)))); + } + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } +} + +// ----------------------------------------------------------------------------- +bool isEmbeddedInDatabase( const Reference< XInterface >& _rxComponent, Reference< XConnection >& _rxActualConnection ) +{ + bool bIsEmbedded = false; + try + { + Reference< XModel > xModel = lcl_getXModel( _rxComponent ); + + if ( xModel.is() ) + { + Sequence< PropertyValue > aArgs = xModel->getArgs(); + const PropertyValue* pIter = aArgs.getConstArray(); + const PropertyValue* pEnd = pIter + aArgs.getLength(); + for(;pIter != pEnd;++pIter) + { + if ( pIter->Name.equalsAscii("ComponentData") ) + { + Sequence<PropertyValue> aDocumentContext; + pIter->Value >>= aDocumentContext; + const PropertyValue* pContextIter = aDocumentContext.getConstArray(); + const PropertyValue* pContextEnd = pContextIter + aDocumentContext.getLength(); + for(;pContextIter != pContextEnd;++pContextIter) + { + if ( pContextIter->Name.equalsAscii( "ActiveConnection" ) + && ( pContextIter->Value >>= _rxActualConnection ) + ) + { + bIsEmbedded = true; + break; + } + } + break; + } + } + } + } + catch(Exception&) + { + // not intereseted in + } + return bIsEmbedded; +} +// ----------------------------------------------------------------------------- +namespace +{ + ::rtl::OUString lcl_getEncodingName( rtl_TextEncoding _eEncoding ) + { + ::rtl::OUString sEncodingName; + + OCharsetMap aCharsets; + OCharsetMap::CharsetIterator aEncodingPos = aCharsets.find( _eEncoding ); + OSL_ENSURE( aEncodingPos != aCharsets.end(), "lcl_getEncodingName: *which* encoding?" ); + if ( aEncodingPos != aCharsets.end() ) + sEncodingName = (*aEncodingPos).getIanaName(); + + return sEncodingName; + } +} + +// ----------------------------------------------------------------------------- +sal_Int32 DBTypeConversion::convertUnicodeString( const ::rtl::OUString& _rSource, ::rtl::OString& _rDest, rtl_TextEncoding _eEncoding ) SAL_THROW((com::sun::star::sdbc::SQLException)) +{ + if ( !rtl_convertUStringToString( &_rDest.pData, _rSource.getStr(), _rSource.getLength(), + _eEncoding, + RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR | + RTL_UNICODETOTEXT_FLAGS_UNDEFINED_REPLACE | + RTL_UNICODETOTEXT_FLAGS_PRIVATE_MAPTO0 | + RTL_UNICODETOTEXT_FLAGS_NOCOMPOSITE ) + ) + { + SharedResources aResources; + ::rtl::OUString sMessage = aResources.getResourceStringWithSubstitution( STR_CANNOT_CONVERT_STRING, + "$string$", _rSource, + "$charset$", lcl_getEncodingName( _eEncoding ) + ); + + throw SQLException( + sMessage, + NULL, + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "22018" ) ), + 22018, + Any() + ); + } + + return _rDest.getLength(); +} + +// ----------------------------------------------------------------------------- +sal_Int32 DBTypeConversion::convertUnicodeStringToLength( const ::rtl::OUString& _rSource, ::rtl::OString& _rDest, + sal_Int32 _nMaxLen, rtl_TextEncoding _eEncoding ) SAL_THROW((SQLException)) +{ + sal_Int32 nLen = convertUnicodeString( _rSource, _rDest, _eEncoding ); + if ( nLen > _nMaxLen ) + { + SharedResources aResources; + ::rtl::OUString sMessage = aResources.getResourceStringWithSubstitution( STR_STRING_LENGTH_EXCEEDED, + "$string$", _rSource, + "$maxlen$", ::rtl::OUString::valueOf( _nMaxLen ), + "$charset$", lcl_getEncodingName( _eEncoding ) + ); + + throw SQLException( + sMessage, + NULL, + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "22001" ) ), + 22001, + Any() + ); + } + + return nLen; +} +::rtl::OUString lcl_getReportEngines() +{ + static ::rtl::OUString s_sNodeName(RTL_CONSTASCII_USTRINGPARAM("org.openoffice.Office.DataAccess/ReportEngines")); + return s_sNodeName; +} +// ----------------------------------------------------------------------------- +::rtl::OUString lcl_getDefaultReportEngine() +{ + static ::rtl::OUString s_sNodeName(RTL_CONSTASCII_USTRINGPARAM("DefaultReportEngine")); + return s_sNodeName; +} +// ----------------------------------------------------------------------------- +::rtl::OUString lcl_getReportEngineNames() +{ + static ::rtl::OUString s_sNodeName(RTL_CONSTASCII_USTRINGPARAM("ReportEngineNames")); + return s_sNodeName; +} +// ----------------------------------------------------------------------------- +::rtl::OUString getDefaultReportEngineServiceName(const Reference< XMultiServiceFactory >& _rxORB) +{ + ::utl::OConfigurationTreeRoot aReportEngines = ::utl::OConfigurationTreeRoot::createWithServiceFactory( + _rxORB, lcl_getReportEngines(), -1, ::utl::OConfigurationTreeRoot::CM_READONLY); + + if ( aReportEngines.isValid() ) + { + ::rtl::OUString sDefaultReportEngineName; + aReportEngines.getNodeValue(lcl_getDefaultReportEngine()) >>= sDefaultReportEngineName; + if ( sDefaultReportEngineName.getLength() ) + { + ::utl::OConfigurationNode aReportEngineNames = aReportEngines.openNode(lcl_getReportEngineNames()); + if ( aReportEngineNames.isValid() ) + { + ::utl::OConfigurationNode aReportEngine = aReportEngineNames.openNode(sDefaultReportEngineName); + if ( aReportEngine.isValid() ) + { + ::rtl::OUString sRet; + const static ::rtl::OUString s_sService(RTL_CONSTASCII_USTRINGPARAM("ServiceName")); + aReportEngine.getNodeValue(s_sService) >>= sRet; + return sRet; + } + } + } + else + return ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.report.pentaho.SOReportJobFactory")); + } + else + return ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.report.pentaho.SOReportJobFactory")); + return ::rtl::OUString(); +} +// ----------------------------------------------------------------------------- +//......................................................................... +} // namespace dbtools +//......................................................................... + diff --git a/connectivity/source/commontools/filtermanager.cxx b/connectivity/source/commontools/filtermanager.cxx new file mode 100644 index 000000000000..bab2ec4ed144 --- /dev/null +++ b/connectivity/source/commontools/filtermanager.cxx @@ -0,0 +1,198 @@ +/************************************************************************* + * + * 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 "connectivity/filtermanager.hxx" + +/** === begin UNO includes === **/ +#include <com/sun/star/sdb/XSQLQueryComposerFactory.hpp> +/** === end UNO includes === **/ +#include "TConnection.hxx" +#include <osl/diagnose.h> +#include "connectivity/dbtools.hxx" + +//........................................................................ +namespace dbtools +{ +//........................................................................ + + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::sdbc; + using namespace ::com::sun::star::sdb; + using namespace ::com::sun::star::lang; + using namespace ::com::sun::star::beans; + using namespace connectivity; + + //==================================================================== + //= FilterManager + //==================================================================== + //-------------------------------------------------------------------- + FilterManager::FilterManager( const Reference< XMultiServiceFactory >& _rxORB ) + :m_xORB( _rxORB ) + ,m_aFilterComponents( FC_COMPONENT_COUNT ) + ,m_bApplyPublicFilter( true ) + { + } + + //-------------------------------------------------------------------- + void FilterManager::initialize( const Reference< XPropertySet >& _rxComponentAggregate ) + { + m_xComponentAggregate = _rxComponentAggregate; + OSL_ENSURE( m_xComponentAggregate.is(), "FilterManager::initialize: invalid arguments!" ); + + if ( m_xComponentAggregate.is() ) + m_xComponentAggregate->setPropertyValue( OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_APPLYFILTER), makeAny( (sal_Bool)sal_True ) ); + } + + //-------------------------------------------------------------------- + void FilterManager::dispose( ) + { + m_xComponentAggregate.clear(); + } + + //-------------------------------------------------------------------- + const ::rtl::OUString& FilterManager::getFilterComponent( FilterComponent _eWhich ) const + { + return m_aFilterComponents[ _eWhich ]; + } + + //-------------------------------------------------------------------- + void FilterManager::setFilterComponent( FilterComponent _eWhich, const ::rtl::OUString& _rComponent ) + { + m_aFilterComponents[ _eWhich ] = _rComponent; + try + { + if ( m_xComponentAggregate.is() && (( _eWhich != fcPublicFilter ) || m_bApplyPublicFilter ) ) + m_xComponentAggregate->setPropertyValue( OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_FILTER), makeAny( getComposedFilter() ) ); + } + catch( const Exception& ) + { + OSL_ENSURE( sal_False, "FilterManager::setFilterComponent: setting the filter failed!" ); + } + } + + //-------------------------------------------------------------------- + void FilterManager::setApplyPublicFilter( sal_Bool _bApply ) + { + if ( m_bApplyPublicFilter == _bApply ) + return; + + m_bApplyPublicFilter = _bApply; + + try + { + if ( m_xComponentAggregate.is() && getFilterComponent( fcPublicFilter ).getLength() ) + { // only if there changed something + m_xComponentAggregate->setPropertyValue( OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_FILTER), makeAny( getComposedFilter() ) ); + } + } + catch( const Exception& ) + { + OSL_ENSURE( sal_False, "FilterManager::setApplyPublicFilter: setting the filter failed!" ); + } + } + + //-------------------------------------------------------------------- + namespace + { + void lcl_ensureBracketed( ::rtl::OUString& /* [inout] */ _rExpression ) + { + OSL_ENSURE( _rExpression.getLength(), "lcl_ensureBracketed: expression is empty!" ); + if ( _rExpression.getLength() ) + { + if ( ( _rExpression.getStr()[0] != '(' ) || ( _rExpression.getStr()[ _rExpression.getLength() - 1 ] != ')' ) ) + { + ::rtl::OUString sComposed( RTL_CONSTASCII_USTRINGPARAM( "(" ) ); + sComposed += _rExpression; + sComposed += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ")" ) ); + _rExpression = sComposed; + } + } + } + } + //-------------------------------------------------------------------- + void FilterManager::appendFilterComponent( ::rtl::OUString& /* [inout] */ _rAppendTo, const ::rtl::OUString& _rComponent ) const + { + if ( _rAppendTo.getLength() ) + _rAppendTo += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( " AND " ) ); + + ::rtl::OUString sComponent( _rComponent ); + lcl_ensureBracketed( sComponent ); + _rAppendTo += sComponent; + } + + //-------------------------------------------------------------------- + bool FilterManager::isThereAtMostOneComponent( ::rtl::OUString& _rOnlyComponent ) const + { + sal_Int32 nOnlyNonEmpty = -1; + sal_Int32 i; + for ( i = getFirstApplicableFilterIndex(); i < FC_COMPONENT_COUNT; ++i ) + { + if ( m_aFilterComponents[ i ].getLength() ) + { + if ( nOnlyNonEmpty != -1 ) + // it's the second non-empty component + break; + else + nOnlyNonEmpty = i; + } + } + if ( nOnlyNonEmpty == -1 ) + { + _rOnlyComponent = ::rtl::OUString(); + return true; + } + + if ( i == FC_COMPONENT_COUNT ) + { + // we found only one non-empty filter component + _rOnlyComponent = m_aFilterComponents[ nOnlyNonEmpty ]; + return true; + } + return false; + } + + //-------------------------------------------------------------------- + ::rtl::OUString FilterManager::getComposedFilter( ) const + { + ::rtl::OUString sComposedFilter; + + // if we have only one non-empty component, then there's no need to compose anything + if ( isThereAtMostOneComponent( sComposedFilter ) ) + return sComposedFilter; + + // append the single components + for ( sal_Int32 i = getFirstApplicableFilterIndex(); i < FC_COMPONENT_COUNT; ++i ) + appendFilterComponent( sComposedFilter, m_aFilterComponents[ i ] ); + + return sComposedFilter; + } + +//........................................................................ +} // namespace dbtools +//........................................................................ diff --git a/connectivity/source/commontools/formattedcolumnvalue.cxx b/connectivity/source/commontools/formattedcolumnvalue.cxx new file mode 100644 index 000000000000..3707b7fdb65d --- /dev/null +++ b/connectivity/source/commontools/formattedcolumnvalue.cxx @@ -0,0 +1,338 @@ +/************************************************************************* + * + * 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 "connectivity/formattedcolumnvalue.hxx" +#include "connectivity/dbtools.hxx" +#include "connectivity/dbconversion.hxx" + +/** === begin UNO includes === **/ +#include <com/sun/star/util/XNumberFormatter.hpp> +#include <com/sun/star/util/Date.hpp> +#include <com/sun/star/sdbc/XConnection.hpp> +#include <com/sun/star/util/XNumberFormatTypes.hpp> +#include <com/sun/star/util/NumberFormat.hpp> +#include <com/sun/star/sdbc/DataType.hpp> +/** === end UNO includes === **/ + +//#include <unotools/syslocale.hxx> +#include <tools/diagnose_ex.h> +#include <i18npool/mslangid.hxx> +#include <comphelper/numbers.hxx> +#include <comphelper/componentcontext.hxx> +#include <unotools/sharedunocomponent.hxx> + +//........................................................................ +namespace dbtools +{ +//........................................................................ + + /** === begin UNO using === **/ + using ::com::sun::star::uno::Reference; + using ::com::sun::star::uno::UNO_QUERY; + using ::com::sun::star::uno::UNO_QUERY_THROW; + using ::com::sun::star::uno::UNO_SET_THROW; + using ::com::sun::star::uno::Exception; + using ::com::sun::star::uno::RuntimeException; + using ::com::sun::star::uno::Any; + using ::com::sun::star::uno::makeAny; + using ::com::sun::star::sdbc::XRowSet; + using ::com::sun::star::beans::XPropertySet; + using ::com::sun::star::util::XNumberFormatter; + using ::com::sun::star::util::Date; + using ::com::sun::star::sdbc::XConnection; + using ::com::sun::star::util::XNumberFormatsSupplier; + using ::com::sun::star::beans::XPropertySetInfo; + using ::com::sun::star::lang::Locale; + using ::com::sun::star::util::XNumberFormatTypes; + using ::com::sun::star::sdb::XColumn; + using ::com::sun::star::sdb::XColumnUpdate; + using ::com::sun::star::lang::XComponent; + /** === end UNO using === **/ + namespace DataType = ::com::sun::star::sdbc::DataType; + namespace NumberFormat = ::com::sun::star::util::NumberFormat; + + //==================================================================== + //= FormattedColumnValue_Data + //==================================================================== + struct FormattedColumnValue_Data + { + Reference< XNumberFormatter > m_xFormatter; + Date m_aNullDate; + sal_Int32 m_nFormatKey; + sal_Int32 m_nFieldType; + sal_Int16 m_nKeyType; + bool m_bNumericField; + + Reference< XColumn > m_xColumn; + Reference< XColumnUpdate > m_xColumnUpdate; + + FormattedColumnValue_Data() + :m_xFormatter() + ,m_aNullDate( DBTypeConversion::getStandardDate() ) + ,m_nFormatKey( 0 ) + ,m_nFieldType( DataType::OTHER ) + ,m_nKeyType( NumberFormat::UNDEFINED ) + ,m_bNumericField( false ) + ,m_xColumn() + ,m_xColumnUpdate() + { + } + }; + + //-------------------------------------------------------------------- + namespace + { + //................................................................ + void lcl_clear_nothrow( FormattedColumnValue_Data& _rData ) + { + _rData.m_xFormatter.clear(); + _rData.m_nFormatKey = 0; + _rData.m_nFieldType = DataType::OTHER; + _rData.m_nKeyType = NumberFormat::UNDEFINED; + _rData.m_bNumericField = false; + + _rData.m_xColumn.clear(); + _rData.m_xColumnUpdate.clear(); + } + + //................................................................ + void lcl_initColumnDataValue_nothrow( FormattedColumnValue_Data& _rData, + const Reference< XNumberFormatter >& i_rNumberFormatter, const Reference< XPropertySet >& _rxColumn ) + { + lcl_clear_nothrow( _rData ); + + OSL_PRECOND( i_rNumberFormatter.is(), "lcl_initColumnDataValue_nothrow: no number formats -> no formatted values!" ); + if ( !i_rNumberFormatter.is() ) + return; + + try + { + Reference< XNumberFormatsSupplier > xNumberFormatsSupp( i_rNumberFormatter->getNumberFormatsSupplier(), UNO_SET_THROW ); + + // remember the column + _rData.m_xColumn.set( _rxColumn, UNO_QUERY_THROW ); + _rData.m_xColumnUpdate.set( _rxColumn, UNO_QUERY ); + + // determine the field type, and whether it's a numeric field + OSL_VERIFY( _rxColumn->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Type" ) ) ) >>= _rData.m_nFieldType ); + + switch ( _rData.m_nFieldType ) + { + case DataType::DATE: + case DataType::TIME: + case DataType::TIMESTAMP: + case DataType::BIT: + case DataType::BOOLEAN: + case DataType::TINYINT: + case DataType::SMALLINT: + case DataType::INTEGER: + case DataType::REAL: + case DataType::BIGINT: + case DataType::DOUBLE: + case DataType::NUMERIC: + case DataType::DECIMAL: + _rData.m_bNumericField = true; + break; + default: + _rData.m_bNumericField = false; + break; + } + + // get the format key of our bound field + Reference< XPropertySetInfo > xPSI( _rxColumn->getPropertySetInfo(), UNO_QUERY_THROW ); + bool bHaveFieldFormat = false; + const ::rtl::OUString sFormatKeyProperty( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "FormatKey" ) ) ); + if ( xPSI->hasPropertyByName( sFormatKeyProperty ) ) + { + bHaveFieldFormat = ( _rxColumn->getPropertyValue( sFormatKeyProperty ) >>= _rData.m_nFormatKey ); + } + if ( !bHaveFieldFormat ) + { + // fall back to a format key as indicated by the field type + Locale aSystemLocale; + MsLangId::convertLanguageToLocale( MsLangId::getSystemLanguage(), aSystemLocale ); + Reference< XNumberFormatTypes > xNumTypes( xNumberFormatsSupp->getNumberFormats(), UNO_QUERY_THROW ); + _rData.m_nFormatKey = getDefaultNumberFormat( _rxColumn, xNumTypes, aSystemLocale ); + } + + // some more formatter settings + _rData.m_nKeyType = ::comphelper::getNumberFormatType( xNumberFormatsSupp->getNumberFormats(), _rData.m_nFormatKey ); + Reference< XPropertySet > xFormatSettings( xNumberFormatsSupp->getNumberFormatSettings(), UNO_QUERY_THROW ); + OSL_VERIFY( xFormatSettings->getPropertyValue( ::rtl::OUString::createFromAscii( "NullDate" ) ) >>= _rData.m_aNullDate ); + + // remember the formatter + _rData.m_xFormatter = i_rNumberFormatter; + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + } + + //................................................................ + void lcl_initColumnDataValue_nothrow( const ::comphelper::ComponentContext& i_rContext, FormattedColumnValue_Data& i_rData, + const Reference< XRowSet >& i_rRowSet, const Reference< XPropertySet >& i_rColumn ) + { + OSL_PRECOND( i_rRowSet.is(), "lcl_initColumnDataValue_nothrow: no row set!" ); + if ( !i_rRowSet.is() ) + return; + + Reference< XNumberFormatter > xNumberFormatter; + try + { + // get the number formats supplier of the connection of the form + Reference< XConnection > xConnection( getConnection( i_rRowSet ), UNO_QUERY_THROW ); + Reference< XNumberFormatsSupplier > xSupplier( getNumberFormats( xConnection, sal_True, i_rContext.getLegacyServiceFactory() ), UNO_SET_THROW ); + + // create a number formatter for it + xNumberFormatter.set( i_rContext.createComponent( "com.sun.star.util.NumberFormatter" ), UNO_QUERY_THROW ); + xNumberFormatter->attachNumberFormatsSupplier( xSupplier ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + + lcl_initColumnDataValue_nothrow( i_rData, xNumberFormatter, i_rColumn ); + } + } + + //==================================================================== + //= FormattedColumnValue + //==================================================================== + //-------------------------------------------------------------------- + FormattedColumnValue::FormattedColumnValue( const ::comphelper::ComponentContext& i_rContext, + const Reference< XRowSet >& _rxRowSet, const Reference< XPropertySet >& i_rColumn ) + :m_pData( new FormattedColumnValue_Data ) + { + lcl_initColumnDataValue_nothrow( i_rContext, *m_pData, _rxRowSet, i_rColumn ); + } + + //-------------------------------------------------------------------- + FormattedColumnValue::FormattedColumnValue( const Reference< XNumberFormatter >& i_rNumberFormatter, + const Reference< XPropertySet >& _rxColumn ) + :m_pData( new FormattedColumnValue_Data ) + { + lcl_initColumnDataValue_nothrow( *m_pData, i_rNumberFormatter, _rxColumn ); + } + + //-------------------------------------------------------------------- + void FormattedColumnValue::clear() + { + lcl_clear_nothrow( *m_pData ); + } + + //-------------------------------------------------------------------- + FormattedColumnValue::~FormattedColumnValue() + { + clear(); + } + + //-------------------------------------------------------------------- + sal_Int32 FormattedColumnValue::getFormatKey() const + { + return m_pData->m_nFormatKey; + } + + //-------------------------------------------------------------------- + sal_Int32 FormattedColumnValue::getFieldType() const + { + return m_pData->m_nFieldType; + } + + //-------------------------------------------------------------------- + sal_Int16 FormattedColumnValue::getKeyType() const + { + return m_pData->m_nKeyType; + } + + //-------------------------------------------------------------------- + bool FormattedColumnValue::isNumericField() const + { + return m_pData->m_bNumericField; + } + + //-------------------------------------------------------------------- + const Reference< XColumn >& FormattedColumnValue::getColumn() const + { + return m_pData->m_xColumn; + } + + //-------------------------------------------------------------------- + const Reference< XColumnUpdate >& FormattedColumnValue::getColumnUpdate() const + { + return m_pData->m_xColumnUpdate; + } + + //-------------------------------------------------------------------- + bool FormattedColumnValue::setFormattedValue( const ::rtl::OUString& _rFormattedStringValue ) const + { + OSL_PRECOND( m_pData->m_xColumnUpdate.is(), "FormattedColumnValue::setFormattedValue: no column!" ); + if ( !m_pData->m_xColumnUpdate.is() ) + return false; + + try + { + if ( m_pData->m_bNumericField ) + { + ::dbtools::DBTypeConversion::setValue( m_pData->m_xColumnUpdate, m_pData->m_xFormatter, m_pData->m_aNullDate, + _rFormattedStringValue, m_pData->m_nFormatKey, ::sal::static_int_cast< sal_Int16 >( m_pData->m_nFieldType ), + m_pData->m_nKeyType ); + } + else + { + m_pData->m_xColumnUpdate->updateString( _rFormattedStringValue ); + } + } + catch( const Exception& ) + { + return false; + } + return true; + } + + //-------------------------------------------------------------------- + ::rtl::OUString FormattedColumnValue::getFormattedValue() const + { + OSL_PRECOND( m_pData->m_xColumn.is(), "FormattedColumnValue::setFormattedValue: no column!" ); + + ::rtl::OUString sStringValue; + if ( m_pData->m_xColumn.is() ) + { + sStringValue = DBTypeConversion::getValue( + m_pData->m_xColumn, m_pData->m_xFormatter, m_pData->m_aNullDate, m_pData->m_nFormatKey, m_pData->m_nKeyType + ); + } + return sStringValue; + } + +//........................................................................ +} // namespace dbtools +//........................................................................ diff --git a/connectivity/source/commontools/makefile.mk b/connectivity/source/commontools/makefile.mk new file mode 100644 index 000000000000..cab216092241 --- /dev/null +++ b/connectivity/source/commontools/makefile.mk @@ -0,0 +1,103 @@ +#************************************************************************* +# +# 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. +# +#************************************************************************* + +PRJ=..$/.. + +PRJNAME=connectivity +TARGET=commontools + +# --- Settings ----------------------------------------------------- +.IF "$(DBGUTIL_OJ)"!="" +ENVCFLAGS+=/FR$(SLO)$/ +.ENDIF + +.INCLUDE : settings.mk +.INCLUDE : $(PRJ)$/dbtools.pmk + +# Disable optimization for SunCC SPARC and MACOSX (funny loops +# when parsing e.g. "x+width/2"), +# also http://gcc.gnu.org/PR22392 +.IF ("$(OS)$(CPU)"=="SOLARISS" && "$(COM)"!="GCC") || "$(OS)"=="MACOSX" || ("$(OS)"=="LINUX" && "$(CPU)"=="P") +NOOPTFILES= $(SLO)$/RowFunctionParser.obj +.ENDIF + +ENVCFLAGS += -DBOOST_SPIRIT_USE_OLD_NAMESPACE + +# --- Files -------------------------------------------------------- +EXCEPTIONSFILES=\ + $(SLO)$/predicateinput.obj \ + $(SLO)$/ConnectionWrapper.obj \ + $(SLO)$/TConnection.obj \ + $(SLO)$/conncleanup.obj \ + $(SLO)$/dbtools.obj \ + $(SLO)$/dbtools2.obj \ + $(SLO)$/dbexception.obj \ + $(SLO)$/CommonTools.obj \ + $(SLO)$/TColumnsHelper.obj \ + $(SLO)$/TTableHelper.obj \ + $(SLO)$/TKeys.obj \ + $(SLO)$/TKey.obj \ + $(SLO)$/TKeyColumns.obj \ + $(SLO)$/TIndexes.obj \ + $(SLO)$/TIndex.obj \ + $(SLO)$/TIndexColumns.obj \ + $(SLO)$/DateConversion.obj \ + $(SLO)$/FDatabaseMetaDataResultSetMetaData.obj \ + $(SLO)$/FDatabaseMetaDataResultSet.obj \ + $(SLO)$/TDatabaseMetaDataBase.obj \ + $(SLO)$/TPrivilegesResultSet.obj \ + $(SLO)$/TSkipDeletedSet.obj \ + $(SLO)$/dbmetadata.obj \ + $(SLO)$/TSortIndex.obj \ + $(SLO)$/dbcharset.obj \ + $(SLO)$/propertyids.obj \ + $(SLO)$/FValue.obj \ + $(SLO)$/paramwrapper.obj \ + $(SLO)$/statementcomposer.obj \ + $(SLO)$/RowFunctionParser.obj \ + $(SLO)$/sqlerror.obj \ + $(SLO)$/filtermanager.obj \ + $(SLO)$/parameters.obj \ + $(SLO)$/ParamterSubstitution.obj \ + $(SLO)$/DriversConfig.obj \ + $(SLO)$/formattedcolumnvalue.obj \ + $(SLO)$/BlobHelper.obj \ + $(SLO)$/warningscontainer.obj + +SLOFILES=\ + $(EXCEPTIONSFILES) \ + $(SLO)$/AutoRetrievingBase.obj \ + $(SLO)$/dbconversion.obj + + + + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk + + diff --git a/connectivity/source/commontools/parameters.cxx b/connectivity/source/commontools/parameters.cxx new file mode 100644 index 000000000000..1eb75415917e --- /dev/null +++ b/connectivity/source/commontools/parameters.cxx @@ -0,0 +1,1120 @@ +/************************************************************************* + * + * 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 "connectivity/parameters.hxx" + +/** === begin UNO includes === **/ +#include <com/sun/star/form/DatabaseParameterEvent.hpp> +#include <com/sun/star/sdbc/XParameters.hpp> +#include <com/sun/star/container/XChild.hpp> +#include <com/sun/star/sdbcx/XColumnsSupplier.hpp> +#include <com/sun/star/container/XEnumerationAccess.hpp> +#include <com/sun/star/sdb/XParametersSupplier.hpp> +#include <com/sun/star/sdb/XInteractionSupplyParameters.hpp> +#include <com/sun/star/sdb/ParametersRequest.hpp> +/** === end UNO includes === **/ + +#include <connectivity/dbtools.hxx> +#include "connectivity/filtermanager.hxx" +#include "TConnection.hxx" + +#include <tools/debug.hxx> +#include <tools/diagnose_ex.h> + +#include <comphelper/uno3.hxx> +#include <comphelper/proparrhlp.hxx> +#include <comphelper/broadcasthelper.hxx> +#include "connectivity/ParameterCont.hxx" +#include <rtl/ustrbuf.hxx> + +//........................................................................ +namespace dbtools +{ +//........................................................................ + + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::sdb; + using namespace ::com::sun::star::sdbc; + using namespace ::com::sun::star::sdbcx; + using namespace ::com::sun::star::lang; + using namespace ::com::sun::star::beans; + using namespace ::com::sun::star::task; + using namespace ::com::sun::star::form; + using namespace ::com::sun::star::container; + + using namespace ::comphelper; + using namespace ::connectivity; + + //==================================================================== + //= ParameterManager + //==================================================================== + //-------------------------------------------------------------------- + ParameterManager::ParameterManager( ::osl::Mutex& _rMutex, const Reference< XMultiServiceFactory >& _rxORB ) + :m_rMutex ( _rMutex ) + ,m_aParameterListeners( _rMutex ) + ,m_xORB ( _rxORB ) + ,m_pOuterParameters ( NULL ) + ,m_nInnerCount ( 0 ) + ,m_bUpToDate ( false ) + { + OSL_ENSURE( m_xORB.is(), "ParameterManager::ParameterManager: no service factory!" ); + } + + //-------------------------------------------------------------------- + void ParameterManager::initialize( const Reference< XPropertySet >& _rxComponent, const Reference< XAggregation >& _rxComponentAggregate ) + { + OSL_ENSURE( !m_xComponent.get().is(), "ParameterManager::initialize: already initialized!" ); + + m_xComponent = _rxComponent; + m_xAggregatedRowSet = _rxComponentAggregate; + if ( m_xAggregatedRowSet.is() ) + m_xAggregatedRowSet->queryAggregation( ::getCppuType( &m_xInnerParamUpdate ) ) >>= m_xInnerParamUpdate; + OSL_ENSURE( m_xComponent.get().is() && m_xInnerParamUpdate.is(), "ParameterManager::initialize: invalid arguments!" ); + if ( !m_xComponent.get().is() || !m_xInnerParamUpdate.is() ) + return; + } + + //-------------------------------------------------------------------- + void ParameterManager::dispose( ) + { + clearAllParameterInformation(); + + m_xComposer.clear(); + m_xParentComposer.clear(); + //m_xComponent.clear(); + m_xInnerParamUpdate.clear(); + m_xAggregatedRowSet.clear(); + } + + //-------------------------------------------------------------------- + void ParameterManager::clearAllParameterInformation() + { + m_xInnerParamColumns.clear(); + if ( m_pOuterParameters.is() ) + m_pOuterParameters->dispose(); + m_pOuterParameters = NULL; + m_nInnerCount = 0; + ParameterInformation aEmptyInfo; + m_aParameterInformation.swap( aEmptyInfo ); + m_aMasterFields.realloc( 0 ); + m_aDetailFields.realloc( 0 ); + m_sIdentifierQuoteString = ::rtl::OUString(); + ::std::vector< bool > aEmptyArray; + m_aParametersVisited.swap( aEmptyArray ); + m_bUpToDate = false; + } + + //-------------------------------------------------------------------- + void ParameterManager::disposing( const EventObject& /*_rDisposingEvent*/ ) + { + } + + //-------------------------------------------------------------------- + void ParameterManager::setAllParametersNull() SAL_THROW( ( SQLException, RuntimeException ) ) + { + OSL_PRECOND( isAlive(), "ParameterManager::setAllParametersNull: not initialized, or already disposed!" ); + if ( !isAlive() ) + return; + + for ( sal_Int32 i = 1; i <= m_nInnerCount; ++i ) + m_xInnerParamUpdate->setNull( i, DataType::VARCHAR ); + } + + //-------------------------------------------------------------------- + bool ParameterManager::initializeComposerByComponent( const Reference< XPropertySet >& _rxComponent ) + { + OSL_PRECOND( _rxComponent.is(), "ParameterManager::initializeComposerByComponent: invalid !" ); + + m_xComposer.clear(); + m_xInnerParamColumns.clear(); + m_nInnerCount = 0; + + // create and fill a composer + try + { + // get a query composer for the 's settings + m_xComposer.reset( getCurrentSettingsComposer( _rxComponent, m_xORB ), SharedQueryComposer::TakeOwnership ); + + // see if the composer found parameters + Reference< XParametersSupplier > xParamSupp( m_xComposer, UNO_QUERY ); + if ( xParamSupp.is() ) + m_xInnerParamColumns = xParamSupp->getParameters(); + + if ( m_xInnerParamColumns.is() ) + m_nInnerCount = m_xInnerParamColumns->getCount(); + } + catch( const SQLException& ) + { + } + + return m_xInnerParamColumns.is(); + } + + //-------------------------------------------------------------------- + void ParameterManager::collectInnerParameters( bool _bSecondRun ) + { + OSL_PRECOND( m_xInnerParamColumns.is(), "ParameterManager::collectInnerParameters: missing some internal data!" ); + if ( !m_xInnerParamColumns.is() ) + return; + + // strip previous index informations + if ( _bSecondRun ) + { + for ( ParameterInformation::iterator aParamInfo = m_aParameterInformation.begin(); + aParamInfo != m_aParameterInformation.end(); + ++aParamInfo + ) + { + aParamInfo->second.aInnerIndexes.clear(); + } + } + + // we need to map the parameter names (which is all we get from the 's + // MasterFields property) to indicies, which are needed by the XParameters + // interface of the row set) + Reference<XPropertySet> xParam; + for ( sal_Int32 i = 0; i < m_nInnerCount; ++i ) + { + try + { + xParam.clear(); + m_xInnerParamColumns->getByIndex( i ) >>= xParam; + + ::rtl::OUString sName; + xParam->getPropertyValue( OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_NAME) ) >>= sName; + + // only append additonal paramters when they are not already in the list + ParameterInformation::iterator aExistentPos = m_aParameterInformation.find( sName ); + OSL_ENSURE( !_bSecondRun || ( aExistentPos != m_aParameterInformation.end() ), + "ParameterManager::collectInnerParameters: the parameter information should already exist in the second run!" ); + + if ( aExistentPos == m_aParameterInformation.end() ) + { + aExistentPos = m_aParameterInformation.insert( ParameterInformation::value_type( + sName, xParam ) ).first; + } + else + aExistentPos->second.xComposerColumn = xParam; + + aExistentPos->second.aInnerIndexes.push_back( i ); + } + catch( const Exception& ) + { + OSL_ENSURE( sal_False, "ParameterManager::collectInnerParameters: caught an exception!" ); + } + } + } + + //-------------------------------------------------------------------- + ::rtl::OUString ParameterManager::createFilterConditionFromColumnLink( + const ::rtl::OUString& _rMasterColumn, const ::rtl::OUString& _rDetailLink, ::rtl::OUString& _rNewParamName ) + { + ::rtl::OUString sFilter; + + // format is: + // <detail_column> = :<new_param_name> + sFilter = quoteName( m_sIdentifierQuoteString, _rDetailLink ); + sFilter += ::rtl::OUString::createFromAscii( " = :" ); + + // generate a parameter name which is not already used + _rNewParamName = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "link_from_" ) ); + _rNewParamName += convertName2SQLName( _rMasterColumn, m_sSpecialCharacters ); + while ( m_aParameterInformation.find( _rNewParamName ) != m_aParameterInformation.end() ) + { + _rNewParamName += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "_" ) ); + } + + return sFilter += _rNewParamName; + } + + //-------------------------------------------------------------------- + void ParameterManager::classifyLinks( const Reference< XNameAccess >& _rxParentColumns, + const Reference< XNameAccess >& _rxColumns, ::std::vector< ::rtl::OUString >& _out_rAdditionalFilterComponents ) SAL_THROW(( Exception )) + { + OSL_PRECOND( m_aMasterFields.getLength() == m_aDetailFields.getLength(), + "ParameterManager::classifyLinks: master and detail fields should have the same length!" ); + OSL_ENSURE( _rxColumns.is(), "ParameterManager::classifyLinks: invalid columns!" ); + + if ( !_rxColumns.is() ) + return; + + // we may need to strip any links which are invalid, so here go the containers + // for temporarirly holding the new pairs + ::std::vector< ::rtl::OUString > aStrippedMasterFields; + ::std::vector< ::rtl::OUString > aStrippedDetailFields; + + bool bNeedExchangeLinks = false; + + // classify the links + const ::rtl::OUString* pMasterFields = m_aMasterFields.getConstArray(); + const ::rtl::OUString* pDetailFields = m_aDetailFields.getConstArray(); + const ::rtl::OUString* pDetailFieldsEnd = pDetailFields + m_aDetailFields.getLength(); + for ( ; pDetailFields < pDetailFieldsEnd; ++pDetailFields, ++pMasterFields ) + { + if ( !pMasterFields->getLength() || !pDetailFields->getLength() ) + continue; + + // if not even the master part of the relationship exists in the parent , the + // link is invalid as a whole + // #i63674# / 2006-03-28 / frank.schoenheit@sun.com + if ( !_rxParentColumns->hasByName( *pMasterFields ) ) + { + bNeedExchangeLinks = true; + continue; + } + + bool bValidLink = true; + + // is there an inner parameter with this name? That is, a parameter which is already part of + // the very original statement (not the one we create ourselve, with the additional parameters) + ParameterInformation::iterator aPos = m_aParameterInformation.find( *pDetailFields ); + if ( aPos != m_aParameterInformation.end() ) + { // there is an inner parameter with this name + aPos->second.eType = eLinkedByParamName; + aStrippedDetailFields.push_back( *pDetailFields ); + } + else + { + // does the detail name denote a column? + if ( _rxColumns->hasByName( *pDetailFields ) ) + { + ::rtl::OUString sNewParamName; + const ::rtl::OUString sFilterCondition = createFilterConditionFromColumnLink( *pMasterFields, *pDetailFields, sNewParamName ); + OSL_PRECOND( sNewParamName.getLength(), "ParameterManager::classifyLinks: createFilterConditionFromColumnLink returned nonsense!" ); + + // remember meta information about this new parameter + ::std::pair< ParameterInformation::iterator, bool > aInsertionPos = + m_aParameterInformation.insert( + ParameterInformation::value_type( sNewParamName, ParameterMetaData( NULL ) ) + ); + OSL_ENSURE( aInsertionPos.second, "ParameterManager::classifyLinks: there already was a parameter with this name!" ); + aInsertionPos.first->second.eType = eLinkedByColumnName; + + // remember the filter component + _out_rAdditionalFilterComponents.push_back( sFilterCondition ); + + // remember the new "detail field" for this link + aStrippedDetailFields.push_back( sNewParamName ); + bNeedExchangeLinks = true; + } + else + { + // the detail field neither denotes a column name, nor a parameter name + bValidLink = false; + bNeedExchangeLinks = true; + } + } + + if ( bValidLink ) + aStrippedMasterFields.push_back( *pMasterFields ); + } + OSL_POSTCOND( aStrippedMasterFields.size() == aStrippedDetailFields.size(), + "ParameterManager::classifyLinks: inconsistency in new link pairs!" ); + + if ( bNeedExchangeLinks ) + { + ::rtl::OUString *pFields = aStrippedMasterFields.empty() ? 0 : &aStrippedMasterFields[0]; + m_aMasterFields = Sequence< ::rtl::OUString >( pFields, aStrippedMasterFields.size() ); + pFields = aStrippedDetailFields.empty() ? 0 : &aStrippedDetailFields[0]; + m_aDetailFields = Sequence< ::rtl::OUString >( pFields, aStrippedDetailFields.size() ); + } + } + + //-------------------------------------------------------------------- + void ParameterManager::analyzeFieldLinks( FilterManager& _rFilterManager, bool& /* [out] */ _rColumnsInLinkDetails ) + { + OSL_PRECOND( isAlive(), "ParameterManager::analyzeFieldLinks: not initialized, or already disposed!" ); + if ( !isAlive() ) + return; + + _rColumnsInLinkDetails = false; + try + { + // the links as determined by the properties + Reference< XPropertySet > xProp = m_xComponent; + OSL_ENSURE(xProp.is(),"Some already released my component!"); + if ( xProp.is() ) + { + xProp->getPropertyValue( OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_MASTERFIELDS) ) >>= m_aMasterFields; + xProp->getPropertyValue( OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_DETAILFIELDS) ) >>= m_aDetailFields; + } + + { + // normalize to equal length + sal_Int32 nMasterLength = m_aMasterFields.getLength(); + sal_Int32 nDetailLength = m_aDetailFields.getLength(); + + if ( nMasterLength > nDetailLength ) + m_aMasterFields.realloc( nDetailLength ); + else if ( nDetailLength > nMasterLength ) + m_aDetailFields.realloc( nMasterLength ); + } + + Reference< XNameAccess > xColumns; + if ( !getColumns( xColumns, true ) ) + // already asserted in getColumns + return; + + Reference< XNameAccess > xParentColumns; + if ( !getParentColumns( xParentColumns, true ) ) + return; + + // classify the links - depending on what the detail fields in each link pair denotes + ::std::vector< ::rtl::OUString > aAdditionalFilterComponents; + classifyLinks( xParentColumns, xColumns, aAdditionalFilterComponents ); + + // did we find links where the detail field refers to a detail column (instead of a parameter name)? + if ( !aAdditionalFilterComponents.empty() ) + { + const static ::rtl::OUString s_sAnd( RTL_CONSTASCII_USTRINGPARAM( " AND " ) ); + // build a conjunction of all the filter components + ::rtl::OUStringBuffer sAdditionalFilter; + for ( ::std::vector< ::rtl::OUString >::const_iterator aComponent = aAdditionalFilterComponents.begin(); + aComponent != aAdditionalFilterComponents.end(); + ++aComponent + ) + { + if ( sAdditionalFilter.getLength() ) + sAdditionalFilter.append(s_sAnd); + + sAdditionalFilter.appendAscii("( ",((sal_Int32)(sizeof("( ")-1))); + sAdditionalFilter.append(*aComponent); + sAdditionalFilter.appendAscii(" )",((sal_Int32)(sizeof(" )")-1))); + } + + // now set this filter at the 's filter manager + _rFilterManager.setFilterComponent( FilterManager::fcLinkFilter, sAdditionalFilter.makeStringAndClear() ); + + _rColumnsInLinkDetails = true; + } + } + catch( const Exception& ) + { + OSL_ENSURE( sal_False, "ParameterManager::analyzeFieldLinks: caught an exception!" ); + } + } + + //-------------------------------------------------------------------- + void ParameterManager::createOuterParameters() + { + OSL_PRECOND( !m_pOuterParameters.is(), "ParameterManager::createOuterParameters: outer parameters not initialized!" ); + OSL_PRECOND( m_xInnerParamUpdate.is(), "ParameterManager::createOuterParameters: no write access to the inner parameters!" ); + if ( !m_xInnerParamUpdate.is() ) + return; + + m_pOuterParameters = new param::ParameterWrapperContainer; + +#if OSL_DEBUG_LEVEL > 0 + sal_Int32 nSmallestIndexLinkedByColumnName = -1; + sal_Int32 nLargestIndexNotLinkedByColumnName = -1; +#endif + ::rtl::OUString sName; + for ( ParameterInformation::iterator aParam = m_aParameterInformation.begin(); + aParam != m_aParameterInformation.end(); + ++aParam + ) + { +#if OSL_DEBUG_LEVEL > 0 + if ( aParam->second.aInnerIndexes.size() ) + if ( aParam->second.eType == eLinkedByColumnName ) + { + if ( nSmallestIndexLinkedByColumnName == -1 ) + nSmallestIndexLinkedByColumnName = aParam->second.aInnerIndexes[ 0 ]; + } + else + { + nLargestIndexNotLinkedByColumnName = aParam->second.aInnerIndexes[ aParam->second.aInnerIndexes.size() - 1 ]; + } +#endif + if ( aParam->second.eType != eFilledExternally ) + continue; + + // check which of the parameters have already been visited (e.g. filled via XParameters) + size_t nAlreadyVisited = 0; + for ( ::std::vector< sal_Int32 >::iterator aIndex = aParam->second.aInnerIndexes.begin(); + aIndex != aParam->second.aInnerIndexes.end(); + ++aIndex + ) + { + if ( ( m_aParametersVisited.size() > (size_t)*aIndex ) && m_aParametersVisited[ *aIndex ] ) + { // exclude this index + *aIndex = -1; + ++nAlreadyVisited; + } + } + if ( nAlreadyVisited == aParam->second.aInnerIndexes.size() ) + continue; + + // need a wrapper for this .... the "inner parameters" as supplied by a result set don't have a "Value" + // property, but the parameter listeners expect such a property. So we need an object "aggregating" + // xParam and supplying an additional property ("Value") + // (it's no real aggregation of course ...) + m_pOuterParameters->push_back( new param::ParameterWrapper( aParam->second.xComposerColumn, m_xInnerParamUpdate, aParam->second.aInnerIndexes ) ); + } + +#if OSL_DEBUG_LEVEL > 0 + OSL_ENSURE( ( nSmallestIndexLinkedByColumnName == -1 ) || ( nLargestIndexNotLinkedByColumnName == -1 ) || + ( nSmallestIndexLinkedByColumnName > nLargestIndexNotLinkedByColumnName ), + "ParameterManager::createOuterParameters: inconsistency!" ); + + // for the master-detail links, where the detail field denoted a column name, we created an addtional ("artificial") + // filter, and *appended* it to all other (potentially) existing filters of the row set. This means that the indexes + // for the parameters resulting from the artifical filter should be larger than any other parameter index, and this + // is what the assertion checks. + // If the assertion fails, then we would need another handling for the "parameters visited" flags, since they're based + // on parameter indexes *without* the artificial filter (because this filter is not visible from the outside). +#endif + } + + //-------------------------------------------------------------------- + void ParameterManager::updateParameterInfo( FilterManager& _rFilterManager ) + { + OSL_PRECOND( isAlive(), "ParameterManager::updateParameterInfo: not initialized, or already disposed!" ); + if ( !isAlive() ) + return; + + clearAllParameterInformation(); + cacheConnectionInfo(); + + // check whether the is based on a statement/query which requires parameters + Reference< XPropertySet > xProp = m_xComponent; + OSL_ENSURE(xProp.is(),"Some already released my component!"); + if ( xProp.is() ) + { + if ( !initializeComposerByComponent( xProp ) ) + { // okay, nothing to do + m_bUpToDate = true; + return; + } // if ( !initializeComposerByComponent( m_xComponent ) ) + } + OSL_POSTCOND( m_xInnerParamColumns.is(), "ParameterManager::updateParameterInfo: initializeComposerByComponent did nonsense (1)!" ); + + // collect all parameters which are defined by the "inner parameters" + collectInnerParameters( false ); + + // analyze the master-detail relationships + bool bColumnsInLinkDetails = false; + analyzeFieldLinks( _rFilterManager, bColumnsInLinkDetails ); + + if ( bColumnsInLinkDetails ) + { + // okay, in this case, analyzeFieldLinks modified the "real" filter at the RowSet, to contain + // an additional restriction (which we created ourself) + // So we need to update all information about our inner parameter columns + Reference< XPropertySet > xDirectRowSetProps; + m_xAggregatedRowSet->queryAggregation( ::getCppuType( &xDirectRowSetProps ) ) >>= xDirectRowSetProps; + OSL_VERIFY( initializeComposerByComponent( xDirectRowSetProps ) ); + collectInnerParameters( true ); + } + + if ( !m_nInnerCount ) + { // no parameters at all + m_bUpToDate = true; + return; + } + + // for what now remains as outer parameters, create the wrappers for the single + // parameter columns + createOuterParameters(); + + m_bUpToDate = true; + } + + //-------------------------------------------------------------------- + void ParameterManager::fillLinkedParameters( const Reference< XNameAccess >& _rxParentColumns ) + { + OSL_PRECOND( isAlive(), "ParameterManager::fillLinkedParameters: not initialized, or already disposed!" ); + if ( !isAlive() ) + return; + OSL_PRECOND( m_xInnerParamColumns.is(), "ParameterManager::fillLinkedParameters: no inner parameters found!" ); + OSL_ENSURE ( _rxParentColumns.is(), "ParameterManager::fillLinkedParameters: invalid parent columns!" ); + + try + { + // the master and detail field( name)s of the + const ::rtl::OUString* pMasterFields = m_aMasterFields.getConstArray(); + const ::rtl::OUString* pDetailFields = m_aDetailFields.getConstArray(); + + sal_Int32 nMasterLen = m_aMasterFields.getLength(); + Any aParamType, aScale, aValue; + + // loop through all master fields. For each of them, get the respective column from the + // parent , and forward it's current value as paramter value to the (inner) row set + for ( sal_Int32 i = 0; i < nMasterLen; ++i, ++pMasterFields, ++pDetailFields ) + { + // does the name denote a valid column in the parent? + if ( !_rxParentColumns->hasByName( *pMasterFields ) ) + { + OSL_ENSURE( sal_False, "ParameterManager::fillLinkedParameters: invalid master names should have been stripped long before!" ); + continue; + } + + // do we, for this name, know where to place the values? + ParameterInformation::const_iterator aParamInfo = m_aParameterInformation.find( *pDetailFields ); + if ( ( aParamInfo == m_aParameterInformation.end() ) + || ( aParamInfo->second.aInnerIndexes.empty() ) + ) + { + OSL_ENSURE( sal_False, "ParameterManager::fillLinkedParameters: nothing known about this detail field!" ); + continue; + } + + // the concrete master field + Reference< XPropertySet > xMasterField(_rxParentColumns->getByName( *pMasterFields ),UNO_QUERY); + + // the positions where we have to fill in values for the current parameter name + for ( ::std::vector< sal_Int32 >::const_iterator aPosition = aParamInfo->second.aInnerIndexes.begin(); + aPosition != aParamInfo->second.aInnerIndexes.end(); + ++aPosition + ) + { + // the concrete detail field + Reference< XPropertySet > xDetailField(m_xInnerParamColumns->getByIndex( *aPosition ),UNO_QUERY); + OSL_ENSURE( xDetailField.is(), "ParameterManager::fillLinkedParameters: invalid detail field!" ); + if ( !xDetailField.is() ) + continue; + + // type and scale of the parameter field + sal_Int32 nParamType = DataType::VARCHAR; + OSL_VERIFY( xDetailField->getPropertyValue( OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_TYPE) ) >>= nParamType ); + + sal_Int32 nScale = 0; + if ( xDetailField->getPropertySetInfo()->hasPropertyByName( OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_SCALE) ) ) + OSL_VERIFY( xDetailField->getPropertyValue( OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_SCALE) ) >>= nScale ); + + // transfer the param value + try + { + m_xInnerParamUpdate->setObjectWithInfo( + *aPosition + 1, // parameters are based at 1 + xMasterField->getPropertyValue( OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_VALUE) ), + nParamType, + nScale + ); + } + catch( const Exception& ) + { + OSL_ENSURE( sal_False, + ::rtl::OString( "ParameterManager::fillLinkedParameters: master-detail parameter number " ) + += ::rtl::OString::valueOf( sal_Int32( *aPosition + 1 ) ) + += ::rtl::OString( " could not be filled!" ) ); + } + } + } + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + } + + //-------------------------------------------------------------------- + bool ParameterManager::completeParameters( const Reference< XInteractionHandler >& _rxCompletionHandler, const Reference< XConnection > _rxConnection ) + { + OSL_PRECOND( isAlive(), "ParameterManager::completeParameters: not initialized, or already disposed!" ); + OSL_ENSURE ( _rxCompletionHandler.is(), "ParameterManager::completeParameters: invalid interaction handler!" ); + + // two continuations (Ok and Cancel) + OInteractionAbort* pAbort = new OInteractionAbort; + OParameterContinuation* pParams = new OParameterContinuation; + + // the request + ParametersRequest aRequest; + aRequest.Parameters = m_pOuterParameters.get(); + aRequest.Connection = _rxConnection; + OInteractionRequest* pRequest = new OInteractionRequest( makeAny( aRequest ) ); + Reference< XInteractionRequest > xRequest( pRequest ); + + // some knittings + pRequest->addContinuation( pAbort ); + pRequest->addContinuation( pParams ); + + // execute the request + try + { + _rxCompletionHandler->handle( xRequest ); + } + catch( const Exception& ) + { + OSL_ENSURE( sal_False, "ParameterManager::completeParameters: caught an exception while calling the handler!" ); + } + + if ( !pParams->wasSelected() ) + // canceled by the user (i.e. (s)he canceled the dialog) + return false; + + try + { + // transfer the values from the continuation object to the parameter columns + Sequence< PropertyValue > aFinalValues = pParams->getValues(); + const PropertyValue* pFinalValues = aFinalValues.getConstArray(); + for ( sal_Int32 i = 0; i < aFinalValues.getLength(); ++i, ++pFinalValues ) + { + Reference< XPropertySet > xParamColumn(aRequest.Parameters->getByIndex( i ),UNO_QUERY); + if ( xParamColumn.is() ) + { + #ifdef DBG_UTIL + ::rtl::OUString sName; + xParamColumn->getPropertyValue( OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_NAME) ) >>= sName; + OSL_ENSURE( sName == pFinalValues->Name, "ParameterManager::completeParameters: inconsistent parameter names!" ); + #endif + xParamColumn->setPropertyValue( OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_VALUE), pFinalValues->Value ); + // the property sets are wrapper classes, translating the Value property into a call to + // the appropriate XParameters interface + } + } + } + catch( const Exception& ) + { + OSL_ENSURE( sal_False, "ParameterManager::completeParameters: caught an exception while propagating the values!" ); + } + return true; + } + + //-------------------------------------------------------------------- + bool ParameterManager::consultParameterListeners( ::osl::ResettableMutexGuard& _rClearForNotifies ) + { + bool bCanceled = false; + + sal_Int32 nParamsLeft = m_pOuterParameters->getParameters().size(); + // TODO: shouldn't we subtract all the parameters which were already visited? + if ( nParamsLeft ) + { + ::cppu::OInterfaceIteratorHelper aIter( m_aParameterListeners ); + Reference< XPropertySet > xProp = m_xComponent; + OSL_ENSURE(xProp.is(),"Some already released my component!"); + DatabaseParameterEvent aEvent( xProp.get(), m_pOuterParameters.get() ); + + _rClearForNotifies.clear(); + while ( aIter.hasMoreElements() && !bCanceled ) + bCanceled = !static_cast< XDatabaseParameterListener* >( aIter.next() )->approveParameter( aEvent ); + _rClearForNotifies.reset(); + } + + return !bCanceled; + } + + //-------------------------------------------------------------------- + bool ParameterManager::fillParameterValues( const Reference< XInteractionHandler >& _rxCompletionHandler, ::osl::ResettableMutexGuard& _rClearForNotifies ) + { + OSL_PRECOND( isAlive(), "ParameterManager::fillParameterValues: not initialized, or already disposed!" ); + if ( !isAlive() ) + return true; + + if ( m_nInnerCount == 0 ) + // no parameters at all + return true; + + // fill the parameters from the master-detail relationship + Reference< XNameAccess > xParentColumns; + if ( getParentColumns( xParentColumns, false ) && xParentColumns->hasElements() && m_aMasterFields.getLength() ) + fillLinkedParameters( xParentColumns ); + + // let the user (via the interaction handler) fill all remaining parameters + Reference< XConnection > xConnection; + getConnection( xConnection ); + + if ( _rxCompletionHandler.is() ) + return completeParameters( _rxCompletionHandler, xConnection ); + + return consultParameterListeners( _rClearForNotifies ); + } + + //-------------------------------------------------------------------- + bool ParameterManager::getConnection( Reference< XConnection >& /* [out] */ _rxConnection ) + { + OSL_PRECOND( isAlive(), "ParameterManager::getConnection: not initialized, or already disposed!" ); + if ( !isAlive() ) + return false; + + _rxConnection.clear(); + try + { + Reference< XPropertySet > xProp = m_xComponent; + OSL_ENSURE(xProp.is(),"Some already released my component!"); + if ( xProp.is() ) + xProp->getPropertyValue( OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_ACTIVE_CONNECTION) ) >>= _rxConnection; + } + catch( const Exception& ) + { + OSL_ENSURE( sal_False, "ParameterManager::getConnection: could not retrieve the connection of the !" ); + } + return _rxConnection.is(); + } + + //-------------------------------------------------------------------- + void ParameterManager::cacheConnectionInfo() SAL_THROW(( )) + { + try + { + Reference< XConnection > xConnection; + getConnection( xConnection ); + Reference< XDatabaseMetaData > xMeta; + if ( xConnection.is() ) + xMeta = xConnection->getMetaData(); + if ( xMeta.is() ) + { + m_sIdentifierQuoteString = xMeta->getIdentifierQuoteString(); + m_sSpecialCharacters = xMeta->getExtraNameCharacters(); + } + } + catch( const Exception& ) + { + OSL_ENSURE( sal_False, "ParameterManager::cacheConnectionInfo: caught an exception!" ); + } + } + + //-------------------------------------------------------------------- + bool ParameterManager::getColumns( Reference< XNameAccess >& /* [out] */ _rxColumns, bool _bFromComposer ) SAL_THROW(( Exception )) + { + _rxColumns.clear(); + + Reference< XColumnsSupplier > xColumnSupp; + if ( _bFromComposer ) + xColumnSupp = xColumnSupp.query( m_xComposer ); + else + xColumnSupp.set( m_xComponent.get(),UNO_QUERY); + if ( xColumnSupp.is() ) + _rxColumns = xColumnSupp->getColumns(); + OSL_ENSURE( _rxColumns.is(), "ParameterManager::getColumns: could not retrieve the columns for the detail !" ); + + return _rxColumns.is(); + } + + //-------------------------------------------------------------------- + bool ParameterManager::getParentColumns( Reference< XNameAccess >& /* [out] */ _out_rxParentColumns, bool _bFromComposer ) + { + OSL_PRECOND( isAlive(), "ParameterManager::getParentColumns: not initialized, or already disposed!" ); + + _out_rxParentColumns.clear(); + try + { + // get the parent of the component we're working for + Reference< XChild > xAsChild( m_xComponent.get(), UNO_QUERY_THROW ); + Reference< XPropertySet > xParent( xAsChild->getParent(), UNO_QUERY ); + if ( !xParent.is() ) + return false; + + // the columns supplier: either from a composer, or directly from the + Reference< XColumnsSupplier > xParentColSupp; + if ( _bFromComposer ) + { + // re-create the parent composer all the time. Else, we'd have to bother with + // being a listener at its properties, its loaded state, and event the parent-relationship. + m_xParentComposer.reset( + getCurrentSettingsComposer( xParent, m_xORB ), + SharedQueryComposer::TakeOwnership + ); + xParentColSupp = xParentColSupp.query( m_xParentComposer ); + } + else + xParentColSupp = xParentColSupp.query( xParent ); + + // get the columns of the parent + if ( xParentColSupp.is() ) + _out_rxParentColumns = xParentColSupp->getColumns(); + } + catch( const Exception& ) + { + OSL_ENSURE( sal_False, "ParameterManager::getParentColumns: caught an exception!" ); + } + return _out_rxParentColumns.is(); + } + + //-------------------------------------------------------------------- + void ParameterManager::addParameterListener( const Reference< XDatabaseParameterListener >& _rxListener ) + { + if ( _rxListener.is() ) + m_aParameterListeners.addInterface( _rxListener ); + } + + //-------------------------------------------------------------------- + void ParameterManager::removeParameterListener( const Reference< XDatabaseParameterListener >& _rxListener ) + { + m_aParameterListeners.removeInterface( _rxListener ); + } + + //-------------------------------------------------------------------- + void ParameterManager::resetParameterValues( ) SAL_THROW(()) + { + OSL_PRECOND( isAlive(), "ParameterManager::resetParameterValues: not initialized, or already disposed!" ); + if ( !isAlive() ) + return; + + if ( !m_nInnerCount ) + // no parameters at all + return; + + try + { + Reference< XNameAccess > xColumns; + if ( !getColumns( xColumns, false ) ) + // already asserted in getColumns + return; + + Reference< XNameAccess > xParentColumns; + if ( !getParentColumns( xParentColumns, false ) ) + return; + + // loop through all links pairs + const ::rtl::OUString* pMasterFields = m_aMasterFields.getConstArray(); + const ::rtl::OUString* pDetailFields = m_aDetailFields.getConstArray(); + + Reference< XPropertySet > xMasterField; + Reference< XPropertySet > xDetailField; + + // now really .... + const ::rtl::OUString* pDetailFieldsEnd = pDetailFields + m_aDetailFields.getLength(); + for ( ; pDetailFields < pDetailFieldsEnd; ++pDetailFields, ++pMasterFields ) + { + if ( !xParentColumns->hasByName( *pMasterFields ) ) + { + // if this name is unknown in the parent columns, then we don't have a source + // for copying the value to the detail columns + OSL_ENSURE( sal_False, "ParameterManager::resetParameterValues: this should have been stripped long before!" ); + continue; + } + + // for all inner parameters which are bound to the name as specified by the + // slave element of the link, propagate the value from the master column to this + // parameter column + ParameterInformation::const_iterator aParamInfo = m_aParameterInformation.find( *pDetailFields ); + if ( ( aParamInfo == m_aParameterInformation.end() ) + || ( aParamInfo->second.aInnerIndexes.empty() ) + ) + { + OSL_ENSURE( sal_False, "ParameterManager::resetParameterValues: nothing known about this detail field!" ); + continue; + } + + xParentColumns->getByName( *pMasterFields ) >>= xMasterField; + if ( !xMasterField.is() ) + continue; + + for ( ::std::vector< sal_Int32 >::const_iterator aPosition = aParamInfo->second.aInnerIndexes.begin(); + aPosition != aParamInfo->second.aInnerIndexes.end(); + ++aPosition + ) + { + Reference< XPropertySet > xInnerParameter; + m_xInnerParamColumns->getByIndex( *aPosition ) >>= xInnerParameter; + if ( !xInnerParameter.is() ) + continue; + + ::rtl::OUString sParamColumnRealName; + xInnerParameter->getPropertyValue( OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_REALNAME) ) >>= sParamColumnRealName; + if ( xColumns->hasByName( sParamColumnRealName ) ) + { // our own columns have a column which's name equals the real name of the param column + // -> transfer the value property + xColumns->getByName( sParamColumnRealName ) >>= xDetailField; + if ( xDetailField.is() ) + xDetailField->setPropertyValue( OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_VALUE), xMasterField->getPropertyValue( OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_VALUE) ) ); + } + } + } + } + catch( const Exception& ) + { + OSL_ENSURE( sal_False, "ParameterManager::resetParameterValues: caught an exception!" ); + } + + } + + //-------------------------------------------------------------------- + void ParameterManager::externalParameterVisited( sal_Int32 _nIndex ) + { + if ( m_aParametersVisited.size() < (size_t)_nIndex ) + { + m_aParametersVisited.reserve( _nIndex ); + for ( sal_Int32 i = m_aParametersVisited.size(); i < _nIndex; ++i ) + m_aParametersVisited.push_back( false ); + } + m_aParametersVisited[ _nIndex - 1 ] = true; + } + +#define VISIT_PARAMETER( method ) \ + ::osl::MutexGuard aGuard( m_rMutex ); \ + OSL_ENSURE( m_xInnerParamUpdate.is(), "ParameterManager::XParameters::setXXX: no XParameters access to the RowSet!" ); \ + if ( !m_xInnerParamUpdate.is() ) \ + return; \ + m_xInnerParamUpdate->method; \ + externalParameterVisited( _nIndex ) \ + + //-------------------------------------------------------------------- + void ParameterManager::setNull( sal_Int32 _nIndex, sal_Int32 sqlType ) + { + VISIT_PARAMETER( setNull( _nIndex, sqlType ) ); + } + + //-------------------------------------------------------------------- + void ParameterManager::setObjectNull( sal_Int32 _nIndex, sal_Int32 sqlType, const ::rtl::OUString& typeName ) + { + VISIT_PARAMETER( setObjectNull( _nIndex, sqlType, typeName ) ); + } + + //-------------------------------------------------------------------- + void ParameterManager::setBoolean( sal_Int32 _nIndex, sal_Bool x ) + { + VISIT_PARAMETER( setBoolean( _nIndex, x ) ); + } + + //-------------------------------------------------------------------- + void ParameterManager::setByte( sal_Int32 _nIndex, sal_Int8 x ) + { + VISIT_PARAMETER( setByte( _nIndex, x ) ); + } + + //-------------------------------------------------------------------- + void ParameterManager::setShort( sal_Int32 _nIndex, sal_Int16 x ) + { + VISIT_PARAMETER( setShort( _nIndex, x ) ); + } + + //-------------------------------------------------------------------- + void ParameterManager::setInt( sal_Int32 _nIndex, sal_Int32 x ) + { + VISIT_PARAMETER( setInt( _nIndex, x ) ); + } + + //-------------------------------------------------------------------- + void ParameterManager::setLong( sal_Int32 _nIndex, sal_Int64 x ) + { + VISIT_PARAMETER( setLong( _nIndex, x ) ); + } + + //-------------------------------------------------------------------- + void ParameterManager::setFloat( sal_Int32 _nIndex, float x ) + { + VISIT_PARAMETER( setFloat( _nIndex, x ) ); + } + + //-------------------------------------------------------------------- + void ParameterManager::setDouble( sal_Int32 _nIndex, double x ) + { + VISIT_PARAMETER( setDouble( _nIndex, x ) ); + } + + //-------------------------------------------------------------------- + void ParameterManager::setString( sal_Int32 _nIndex, const ::rtl::OUString& x ) + { + VISIT_PARAMETER( setString( _nIndex, x ) ); + } + + //-------------------------------------------------------------------- + void ParameterManager::setBytes( sal_Int32 _nIndex, const ::com::sun::star::uno::Sequence< sal_Int8 >& x ) + { + VISIT_PARAMETER( setBytes( _nIndex, x ) ); + } + + //-------------------------------------------------------------------- + void ParameterManager::setDate( sal_Int32 _nIndex, const ::com::sun::star::util::Date& x ) + { + VISIT_PARAMETER( setDate( _nIndex, x ) ); + } + + //-------------------------------------------------------------------- + void ParameterManager::setTime( sal_Int32 _nIndex, const ::com::sun::star::util::Time& x ) + { + VISIT_PARAMETER( setTime( _nIndex, x ) ); + } + + //-------------------------------------------------------------------- + void ParameterManager::setTimestamp( sal_Int32 _nIndex, const ::com::sun::star::util::DateTime& x ) + { + VISIT_PARAMETER( setTimestamp( _nIndex, x ) ); + } + + //-------------------------------------------------------------------- + void ParameterManager::setBinaryStream( sal_Int32 _nIndex, const ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream>& x, sal_Int32 length ) + { + VISIT_PARAMETER( setBinaryStream( _nIndex, x, length ) ); + } + + //-------------------------------------------------------------------- + void ParameterManager::setCharacterStream( sal_Int32 _nIndex, const ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream>& x, sal_Int32 length ) + { + VISIT_PARAMETER( setCharacterStream( _nIndex, x, length ) ); + } + + //-------------------------------------------------------------------- + void ParameterManager::setObject( sal_Int32 _nIndex, const ::com::sun::star::uno::Any& x ) + { + VISIT_PARAMETER( setObject( _nIndex, x ) ); + } + + //-------------------------------------------------------------------- + void ParameterManager::setObjectWithInfo( sal_Int32 _nIndex, const ::com::sun::star::uno::Any& x, sal_Int32 targetSqlType, sal_Int32 scale ) + { + VISIT_PARAMETER( setObjectWithInfo( _nIndex, x, targetSqlType, scale ) ); + } + + //-------------------------------------------------------------------- + void ParameterManager::setRef( sal_Int32 _nIndex, const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRef>& x ) + { + VISIT_PARAMETER( setRef( _nIndex, x ) ); + } + + //-------------------------------------------------------------------- + void ParameterManager::setBlob( sal_Int32 _nIndex, const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XBlob>& x ) + { + VISIT_PARAMETER( setBlob( _nIndex, x ) ); + } + + //-------------------------------------------------------------------- + void ParameterManager::setClob( sal_Int32 _nIndex, const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XClob>& x ) + { + VISIT_PARAMETER( setClob( _nIndex, x ) ); + } + + //-------------------------------------------------------------------- + void ParameterManager::setArray( sal_Int32 _nIndex, const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XArray>& x ) + { + VISIT_PARAMETER( setArray( _nIndex, x ) ); + } + + //-------------------------------------------------------------------- + void ParameterManager::clearParameters( ) + { + if ( m_xInnerParamUpdate.is() ) + m_xInnerParamUpdate->clearParameters( ); + } + + //==================================================================== + //= OParameterContinuation + //==================================================================== + //-------------------------------------------------------------------- + void SAL_CALL OParameterContinuation::setParameters( const Sequence< PropertyValue >& _rValues ) throw( RuntimeException ) + { + m_aValues = _rValues; + } + +//........................................................................ +} // namespace frm +//........................................................................ + diff --git a/connectivity/source/commontools/paramwrapper.cxx b/connectivity/source/commontools/paramwrapper.cxx new file mode 100644 index 000000000000..cef4508e3b30 --- /dev/null +++ b/connectivity/source/commontools/paramwrapper.cxx @@ -0,0 +1,364 @@ +/************************************************************************* + * + * 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 <connectivity/paramwrapper.hxx> + +/** === begin UNO includes === **/ +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/sdbc/DataType.hpp> +#include <com/sun/star/lang/WrappedTargetException.hpp> +#include <com/sun/star/sdb/XParametersSupplier.hpp> +#include <com/sun/star/lang/DisposedException.hpp> +/** === end UNO includes === **/ + +#include <tools/diagnose_ex.h> +#include <comphelper/enumhelper.hxx> + +#define PROPERTY_ID_VALUE 1000 + +//........................................................................ +namespace dbtools +{ +namespace param +{ +//........................................................................ + + /** === begin UNO using === **/ + using ::com::sun::star::uno::Reference; + using ::com::sun::star::beans::XPropertySet; + using ::com::sun::star::sdbc::XParameters; + using ::com::sun::star::uno::Sequence; + using ::com::sun::star::uno::Type; + using ::com::sun::star::uno::RuntimeException; + using ::com::sun::star::uno::XWeak; + using ::com::sun::star::beans::XPropertySet; + using ::com::sun::star::beans::XFastPropertySet; + using ::com::sun::star::beans::XMultiPropertySet; + using ::com::sun::star::beans::XPropertySetInfo; + using ::com::sun::star::beans::Property; + using ::com::sun::star::uno::Exception; + using ::com::sun::star::uno::UNO_QUERY_THROW; + using ::com::sun::star::uno::Any; + using ::com::sun::star::lang::IllegalArgumentException; + using ::com::sun::star::sdbc::SQLException; + using ::com::sun::star::lang::WrappedTargetException; + using ::com::sun::star::lang::IndexOutOfBoundsException; + using ::com::sun::star::container::XEnumeration; + using ::com::sun::star::sdb::XSingleSelectQueryAnalyzer; + using ::com::sun::star::sdb::XParametersSupplier; + using ::com::sun::star::lang::DisposedException; + /** === end UNO using === **/ + namespace PropertyAttribute = ::com::sun::star::beans::PropertyAttribute; + namespace DataType = ::com::sun::star::sdbc::DataType; + + //==================================================================== + //= ParameterWrapper + //==================================================================== + //-------------------------------------------------------------------- + ParameterWrapper::ParameterWrapper( const Reference< XPropertySet >& _rxColumn ) + :PropertyBase( m_aBHelper ) + ,m_xDelegator( _rxColumn ) + { + if ( m_xDelegator.is() ) + m_xDelegatorPSI = m_xDelegator->getPropertySetInfo(); + if ( !m_xDelegatorPSI.is() ) + throw RuntimeException(); + } + + //-------------------------------------------------------------------- + ParameterWrapper::ParameterWrapper( const Reference< XPropertySet >& _rxColumn, + const Reference< XParameters >& _rxAllParameters, const ::std::vector< sal_Int32 >& _rIndexes ) + :PropertyBase( m_aBHelper ) + ,m_aIndexes( _rIndexes ) + ,m_xDelegator( _rxColumn ) + ,m_xValueDestination( _rxAllParameters ) + { + if ( m_xDelegator.is() ) + m_xDelegatorPSI = m_xDelegator->getPropertySetInfo(); + if ( !m_xDelegatorPSI.is() ) + throw RuntimeException(); + + OSL_ENSURE( !m_aIndexes.empty(), "ParameterWrapper::ParameterWrapper: sure about the indexes?" ); + } + + //-------------------------------------------------------------------- + ParameterWrapper::~ParameterWrapper() + { + } + + //-------------------------------------------------------------------- + IMPLEMENT_FORWARD_XINTERFACE2( ParameterWrapper, UnoBase, PropertyBase ) + + //-------------------------------------------------------------------- + Sequence< Type > SAL_CALL ParameterWrapper::getTypes( ) throw(RuntimeException) + { + Sequence< Type > aTypes( 4 ); + aTypes[ 1 ] = ::getCppuType( static_cast< Reference< XWeak >* >( NULL ) ); + aTypes[ 1 ] = ::getCppuType( static_cast< Reference< XPropertySet >* >( NULL ) ); + aTypes[ 2 ] = ::getCppuType( static_cast< Reference< XFastPropertySet >* >( NULL ) ); + aTypes[ 3 ] = ::getCppuType( static_cast< Reference< XMultiPropertySet >* >( NULL ) ); + return aTypes; + } + + //-------------------------------------------------------------------- + IMPLEMENT_GET_IMPLEMENTATION_ID( ParameterWrapper ) + + //-------------------------------------------------------------------- + ::rtl::OUString ParameterWrapper::impl_getPseudoAggregatePropertyName( sal_Int32 _nHandle ) const + { + Reference< XPropertySetInfo > xInfo = const_cast<ParameterWrapper*>( this )->getPropertySetInfo(); + Sequence< Property > aProperties = xInfo->getProperties(); + const Property* pProperties = aProperties.getConstArray(); + for ( sal_Int32 i = 0; i < aProperties.getLength(); ++i, ++pProperties ) + { + if ( pProperties->Handle == _nHandle ) + return pProperties->Name; + } + + OSL_ENSURE( sal_False, "ParameterWrapper::impl_getPseudoAggregatePropertyName: invalid argument!" ); + return ::rtl::OUString(); + } + + //-------------------------------------------------------------------- + Reference< XPropertySetInfo > ParameterWrapper::getPropertySetInfo() throw( RuntimeException ) + { + return createPropertySetInfo( getInfoHelper() ); + } + + //-------------------------------------------------------------------- + ::cppu::IPropertyArrayHelper& ParameterWrapper::getInfoHelper() + { + if ( !m_pInfoHelper.get() ) + { + Sequence< Property > aProperties; + try + { + aProperties = m_xDelegatorPSI->getProperties(); + sal_Int32 nProperties( aProperties.getLength() ); + aProperties.realloc( nProperties + 1 ); + aProperties[ nProperties ] = Property( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Value" ) ), + PROPERTY_ID_VALUE, + ::cppu::UnoType< Any >::get(), + PropertyAttribute::TRANSIENT | PropertyAttribute::MAYBEVOID + ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + + m_pInfoHelper.reset( new ::cppu::OPropertyArrayHelper( aProperties, false ) ); + } + return *m_pInfoHelper; + } + + //-------------------------------------------------------------------- + sal_Bool ParameterWrapper::convertFastPropertyValue(Any& rConvertedValue, Any& rOldValue, sal_Int32 nHandle, const Any& rValue) throw( IllegalArgumentException ) + { + OSL_ENSURE( PROPERTY_ID_VALUE == nHandle, "ParameterWrapper::convertFastPropertyValue: the only non-readonly prop should be our PROPERTY_VALUE!" ); + (void)nHandle; + + // we're lazy here ... + rOldValue = m_aValue.makeAny(); + rConvertedValue = rValue; + return sal_True; // assume "modified" ... + } + + //-------------------------------------------------------------------- + void ParameterWrapper::setFastPropertyValue_NoBroadcast( sal_Int32 nHandle, const Any& rValue ) throw( Exception ) + { + if ( nHandle == PROPERTY_ID_VALUE ) + { + try + { + // TODO : aParamType & nScale can be obtained within the constructor .... + sal_Int32 nParamType = DataType::VARCHAR; + OSL_VERIFY( m_xDelegator->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Type" ) ) ) >>= nParamType ); + + sal_Int32 nScale = 0; + if ( m_xDelegatorPSI->hasPropertyByName( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Scale" ) ) ) ) + OSL_VERIFY( m_xDelegator->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Scale" ) ) ) >>= nScale ); + + if ( m_xValueDestination.is() ) + { + for ( ::std::vector< sal_Int32 >::iterator aIter = m_aIndexes.begin(); aIter != m_aIndexes.end(); ++aIter ) + { + m_xValueDestination->setObjectWithInfo( *aIter + 1, rValue, nParamType, nScale ); + // (the index of the parameters is one-based) + } + } + + m_aValue = rValue; + } + catch( SQLException& e ) + { + WrappedTargetException aExceptionWrapper; + aExceptionWrapper.Context = e.Context; + aExceptionWrapper.Message = e.Message; + aExceptionWrapper.TargetException <<= e; + throw WrappedTargetException( aExceptionWrapper ); + } + } + else + { + ::rtl::OUString aName = impl_getPseudoAggregatePropertyName( nHandle ); + m_xDelegator->setPropertyValue( aName, rValue ); + } + } + + //-------------------------------------------------------------------- + void ParameterWrapper::getFastPropertyValue( Any& rValue, sal_Int32 nHandle ) const + { + if ( nHandle == PROPERTY_ID_VALUE ) + { + rValue = m_aValue.makeAny(); + } + else + { + ::rtl::OUString aName = impl_getPseudoAggregatePropertyName( nHandle ); + rValue = m_xDelegator->getPropertyValue( aName ); + } + } + + //-------------------------------------------------------------------- + void SAL_CALL ParameterWrapper::dispose() + { + ::osl::MutexGuard aGuard( m_aMutex ); + + m_aValue.setNull(); + m_aIndexes.resize(0); + m_xDelegator.clear(); + m_xDelegatorPSI.clear(); + m_xValueDestination.clear(); + + m_aBHelper.bDisposed = sal_True; + } + + //==================================================================== + //= ParameterWrapperContainer + //==================================================================== + //-------------------------------------------------------------------- + ParameterWrapperContainer::ParameterWrapperContainer() + :ParameterWrapperContainer_Base( m_aMutex ) + { + } + + //-------------------------------------------------------------------- + ParameterWrapperContainer::ParameterWrapperContainer( const Reference< XSingleSelectQueryAnalyzer >& _rxComposer ) + :ParameterWrapperContainer_Base( m_aMutex ) + { + Reference< XParametersSupplier > xSuppParams( _rxComposer, UNO_QUERY_THROW ); + Reference< XIndexAccess > xParameters( xSuppParams->getParameters(), UNO_QUERY_THROW ); + sal_Int32 nParamCount( xParameters->getCount() ); + m_aParameters.reserve( nParamCount ); + for ( sal_Int32 i=0; i<nParamCount; ++i ) + { + m_aParameters.push_back( new ParameterWrapper( Reference< XPropertySet >( xParameters->getByIndex( i ), UNO_QUERY_THROW ) ) ); + } + } + + //-------------------------------------------------------------------- + ParameterWrapperContainer::~ParameterWrapperContainer() + { + } + + //-------------------------------------------------------------------- + Type SAL_CALL ParameterWrapperContainer::getElementType() throw( RuntimeException ) + { + ::osl::MutexGuard aGuard( m_aMutex ); + impl_checkDisposed_throw(); + return ::getCppuType( static_cast< Reference< XPropertySet >* >( NULL ) ); + } + + //-------------------------------------------------------------------- + sal_Bool SAL_CALL ParameterWrapperContainer::hasElements() throw( RuntimeException ) + { + ::osl::MutexGuard aGuard( m_aMutex ); + impl_checkDisposed_throw(); + return !m_aParameters.empty(); + } + + //-------------------------------------------------------------------- + sal_Int32 SAL_CALL ParameterWrapperContainer::getCount() throw( RuntimeException ) + { + ::osl::MutexGuard aGuard( m_aMutex ); + impl_checkDisposed_throw(); + return m_aParameters.size(); + } + + //-------------------------------------------------------------------- + Any SAL_CALL ParameterWrapperContainer::getByIndex( sal_Int32 _nIndex ) throw( IndexOutOfBoundsException, WrappedTargetException, RuntimeException ) + { + ::osl::MutexGuard aGuard( m_aMutex ); + impl_checkDisposed_throw(); + + if ( ( _nIndex < 0 ) || ( _nIndex >= (sal_Int32)m_aParameters.size() ) ) + throw IndexOutOfBoundsException(); + + return makeAny( Reference< XPropertySet >( m_aParameters[ _nIndex ].get() ) ); + } + + //-------------------------------------------------------------------- + Reference< XEnumeration > ParameterWrapperContainer::createEnumeration() throw( RuntimeException ) + { + ::osl::MutexGuard aGuard( m_aMutex ); + impl_checkDisposed_throw(); + + return new ::comphelper::OEnumerationByIndex( static_cast< XIndexAccess* >( this ) ); + } + + //-------------------------------------------------------------------- + void ParameterWrapperContainer::impl_checkDisposed_throw() + { + if ( rBHelper.bDisposed ) + throw DisposedException( ::rtl::OUString(), *this ); + } + + //-------------------------------------------------------------------- + void SAL_CALL ParameterWrapperContainer::disposing() + { + ::osl::MutexGuard aGuard( m_aMutex ); + impl_checkDisposed_throw(); + + for ( Parameters::const_iterator param = m_aParameters.begin(); + param != m_aParameters.end(); + ++param + ) + { + (*param)->dispose(); + } + + Parameters aEmpty; + m_aParameters.swap( aEmpty ); + } + +//........................................................................ +} } // namespace dbtools::param +//........................................................................ + diff --git a/connectivity/source/commontools/predicateinput.cxx b/connectivity/source/commontools/predicateinput.cxx new file mode 100644 index 000000000000..8ffebb0cfbda --- /dev/null +++ b/connectivity/source/commontools/predicateinput.cxx @@ -0,0 +1,391 @@ +/************************************************************************* + * + * 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 <connectivity/predicateinput.hxx> +#include <comphelper/types.hxx> +#include <connectivity/dbtools.hxx> +#include <com/sun/star/sdbc/DataType.hpp> +#include <osl/diagnose.h> +#include <connectivity/sqlnode.hxx> +#include <comphelper/numbers.hxx> + +//......................................................................... +namespace dbtools +{ +//......................................................................... + + using ::com::sun::star::sdbc::XConnection; + using ::com::sun::star::lang::XMultiServiceFactory; + using ::com::sun::star::util::XNumberFormatsSupplier; + using ::com::sun::star::util::XNumberFormatter; + using ::com::sun::star::uno::UNO_QUERY; + using ::com::sun::star::beans::XPropertySet; + using ::com::sun::star::beans::XPropertySetInfo; + using ::com::sun::star::lang::Locale; + using ::com::sun::star::uno::Exception; + using ::com::sun::star::i18n::XLocaleData; + using ::com::sun::star::i18n::LocaleDataItem; + + using namespace ::com::sun::star::sdbc; + using namespace ::connectivity; + + using ::connectivity::OSQLParseNode; + + #define Reference ::com::sun::star::uno::Reference + + //===================================================================== + //--------------------------------------------------------------------- + static sal_Unicode lcl_getSeparatorChar( const ::rtl::OUString& _rSeparator, sal_Unicode _nFallback ) + { + OSL_ENSURE( 0 < _rSeparator.getLength(), "::lcl_getSeparatorChar: invalid separator string!" ); + + sal_Unicode nReturn( _nFallback ); + if ( _rSeparator.getLength() ) + nReturn = static_cast< sal_Char >( _rSeparator.getStr()[0] ); + return nReturn; + } + + //===================================================================== + //= OPredicateInputController + //===================================================================== + //--------------------------------------------------------------------- + sal_Bool OPredicateInputController::getSeparatorChars( const Locale& _rLocale, sal_Unicode& _rDecSep, sal_Unicode& _rThdSep ) const + { + _rDecSep = '.'; + _rThdSep = ','; + try + { + LocaleDataItem aLocaleData; + if ( m_xLocaleData.is() ) + { + aLocaleData = m_xLocaleData->getLocaleItem( _rLocale ); + _rDecSep = lcl_getSeparatorChar( aLocaleData.decimalSeparator, _rDecSep ); + _rThdSep = lcl_getSeparatorChar( aLocaleData.decimalSeparator, _rThdSep ); + return sal_True; + } + } + catch( const Exception& ) + { + OSL_ENSURE( sal_False, "OPredicateInputController::getSeparatorChars: caught an exception!" ); + } + return sal_False; + } + + //--------------------------------------------------------------------- + OPredicateInputController::OPredicateInputController( + const Reference< XMultiServiceFactory >& _rxORB, const Reference< XConnection >& _rxConnection, const IParseContext* _pParseContext ) + :m_xORB( _rxORB ) + ,m_xConnection( _rxConnection ) + ,m_aParser( m_xORB, _pParseContext ) + { + try + { + // create a number formatter / number formats supplier pair + OSL_ENSURE( m_xORB.is(), "OPredicateInputController::OPredicateInputController: need a service factory!" ); + if ( m_xORB.is() ) + { + m_xFormatter = Reference< XNumberFormatter >( m_xORB->createInstance( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.util.NumberFormatter" ) ) ), + UNO_QUERY + ); + } + + Reference< XNumberFormatsSupplier > xNumberFormats = ::dbtools::getNumberFormats( m_xConnection, sal_True ); + if ( !xNumberFormats.is() ) + ::comphelper::disposeComponent( m_xFormatter ); + else if ( m_xFormatter.is() ) + m_xFormatter->attachNumberFormatsSupplier( xNumberFormats ); + + // create the locale data + if ( m_xORB.is() ) + { + m_xLocaleData = m_xLocaleData.query( m_xORB->createInstance( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.i18n.LocaleData" ) ) ) + ); + } + } + catch( const Exception& ) + { + OSL_ENSURE( sal_False, "OPredicateInputController::OPredicateInputController: caught an exception!" ); + } + } + + //--------------------------------------------------------------------- + OSQLParseNode* OPredicateInputController::implPredicateTree(::rtl::OUString& _rErrorMessage, const ::rtl::OUString& _rStatement, const Reference< XPropertySet > & _rxField) const + { + OSQLParseNode* pReturn = const_cast< OSQLParser& >( m_aParser ).predicateTree( _rErrorMessage, _rStatement, m_xFormatter, _rxField ); + if ( !pReturn ) + { // is it a text field ? + sal_Int32 nType = DataType::OTHER; + _rxField->getPropertyValue( ::rtl::OUString::createFromAscii( "Type" ) ) >>= nType; + + if ( ( DataType::CHAR == nType ) + || ( DataType::VARCHAR == nType ) + || ( DataType::LONGVARCHAR == nType ) + || ( DataType::CLOB == nType ) + ) + { // yes -> force a quoted text and try again + ::rtl::OUString sQuoted( _rStatement ); + if ( sQuoted.getLength() + && ( (sQuoted.getStr()[0] != '\'') + || (sQuoted.getStr()[ sQuoted.getLength() - 1 ] != '\'' ) + ) + ) + { + static const ::rtl::OUString sSingleQuote( RTL_CONSTASCII_USTRINGPARAM( "'" ) ); + static const ::rtl::OUString sDoubleQuote( RTL_CONSTASCII_USTRINGPARAM( "''" ) ); + + sal_Int32 nIndex = -1; + sal_Int32 nTemp = 0; + while ( -1 != ( nIndex = sQuoted.indexOf( '\'',nTemp ) ) ) + { + sQuoted = sQuoted.replaceAt( nIndex, 1, sDoubleQuote ); + nTemp = nIndex+2; + } + + ::rtl::OUString sTemp( sSingleQuote ); + ( sTemp += sQuoted ) += sSingleQuote; + sQuoted = sTemp; + } + pReturn = const_cast< OSQLParser& >( m_aParser ).predicateTree( _rErrorMessage, sQuoted, m_xFormatter, _rxField ); + } + + // one more fallback: for numeric fields, and value strings containing a decimal/thousands separator + // problem which is to be solved with this: + // * a system locale "german" + // * a column formatted with an english number format + // => the output is german (as we use the system locale for this), i.e. "3,4" + // => the input does not recognize the german text, as predicateTree uses the number format + // of the column to determine the main locale - the locale on the context is only a fallback + if ( ( DataType::FLOAT == nType ) + || ( DataType::REAL == nType ) + || ( DataType::DOUBLE == nType ) + || ( DataType::NUMERIC == nType ) + || ( DataType::DECIMAL == nType ) + ) + { + const IParseContext& rParseContext = m_aParser.getContext(); + // get the separators for the locale of our parse context + sal_Unicode nCtxDecSep; + sal_Unicode nCtxThdSep; + getSeparatorChars( rParseContext.getPreferredLocale(), nCtxDecSep, nCtxThdSep ); + + // determine the locale of the column we're building a predicate string for + sal_Unicode nFmtDecSep( nCtxDecSep ); + sal_Unicode nFmtThdSep( nCtxThdSep ); + try + { + Reference< XPropertySetInfo > xPSI( _rxField->getPropertySetInfo() ); + if ( xPSI.is() && xPSI->hasPropertyByName( ::rtl::OUString::createFromAscii( "FormatKey" ) ) ) + { + sal_Int32 nFormatKey = 0; + _rxField->getPropertyValue( ::rtl::OUString::createFromAscii( "FormatKey" ) ) >>= nFormatKey; + if ( nFormatKey && m_xFormatter.is() ) + { + Locale aFormatLocale; + ::comphelper::getNumberFormatProperty( + m_xFormatter, + nFormatKey, + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Locale" ) ) + ) >>= aFormatLocale; + + // valid locale + if ( aFormatLocale.Language.getLength() ) + { + getSeparatorChars( aFormatLocale, nFmtDecSep, nCtxThdSep ); + } + } + } + } + catch( const Exception& ) + { + OSL_ENSURE( sal_False, "OPredicateInputController::implPredicateTree: caught an exception while dealing with the formats!" ); + } + + sal_Bool bDecDiffers = ( nCtxDecSep != nFmtDecSep ); + sal_Bool bFmtDiffers = ( nCtxThdSep != nFmtThdSep ); + if ( bDecDiffers || bFmtDiffers ) + { // okay, at least one differs + // "translate" the value into the "format locale" + ::rtl::OUString sTranslated( _rStatement ); + const sal_Unicode nIntermediate( '_' ); + sTranslated = sTranslated.replace( nCtxDecSep, nIntermediate ); + sTranslated = sTranslated.replace( nCtxThdSep, nFmtThdSep ); + sTranslated = sTranslated.replace( nIntermediate, nFmtDecSep ); + + pReturn = const_cast< OSQLParser& >( m_aParser ).predicateTree( _rErrorMessage, sTranslated, m_xFormatter, _rxField ); + } + } + } + return pReturn; + } + + //--------------------------------------------------------------------- + sal_Bool OPredicateInputController::normalizePredicateString( + ::rtl::OUString& _rPredicateValue, const Reference< XPropertySet > & _rxField, ::rtl::OUString* _pErrorMessage ) const + { + OSL_ENSURE( m_xConnection.is() && m_xFormatter.is() && _rxField.is(), + "OPredicateInputController::normalizePredicateString: invalid state or params!" ); + + sal_Bool bSuccess = sal_False; + if ( m_xConnection.is() && m_xFormatter.is() && _rxField.is() ) + { + // parse the string + ::rtl::OUString sError; + ::rtl::OUString sTransformedText( _rPredicateValue ); + OSQLParseNode* pParseNode = implPredicateTree( sError, sTransformedText, _rxField ); + if ( _pErrorMessage ) *_pErrorMessage = sError; + + if ( pParseNode ) + { + const IParseContext& rParseContext = m_aParser.getContext(); + sal_Unicode nDecSeparator, nThousandSeparator; + getSeparatorChars( rParseContext.getPreferredLocale(), nDecSeparator, nThousandSeparator ); + + // translate it back into a string + sTransformedText = ::rtl::OUString(); + pParseNode->parseNodeToPredicateStr( + sTransformedText, m_xConnection, m_xFormatter, _rxField, + rParseContext.getPreferredLocale(), (sal_Char)nDecSeparator, &rParseContext + ); + _rPredicateValue = sTransformedText; + delete pParseNode; + + bSuccess = sal_True; + } + } + + return bSuccess; + } + + //--------------------------------------------------------------------- + ::rtl::OUString OPredicateInputController::getPredicateValue( + const ::rtl::OUString& _rPredicateValue, const Reference< XPropertySet > & _rxField, + sal_Bool _bForStatementUse, ::rtl::OUString* _pErrorMessage ) const + { + OSL_ENSURE( _rxField.is(), "OPredicateInputController::getPredicateValue: invalid params!" ); + ::rtl::OUString sReturn; + if ( _rxField.is() ) + { + ::rtl::OUString sValue( _rPredicateValue ); + + // a little problem : if the field is a text field, the normalizePredicateString added two + // '-characters to the text. If we would give this to predicateTree this would add + // two additional '-characters which we don't want. So check the field format. + // FS - 06.01.00 - 71532 + sal_Bool bValidQuotedText = ( sValue.getLength() >= 2 ) + && ( sValue.getStr()[0] == '\'' ) + && ( sValue.getStr()[ sValue.getLength() - 1 ] == '\'' ); + // again : as normalizePredicateString always did a conversion on the value text, + // bValidQuotedText == sal_True implies that we have a text field, as no other field + // values will be formatted with the quote characters + if ( bValidQuotedText ) + { + sValue = sValue.copy( 1, sValue.getLength() - 2 ); + static const ::rtl::OUString sSingleQuote( RTL_CONSTASCII_USTRINGPARAM( "'" ) ); + static const ::rtl::OUString sDoubleQuote( RTL_CONSTASCII_USTRINGPARAM( "''" ) ); + + sal_Int32 nIndex = -1; + sal_Int32 nTemp = 0; + while ( -1 != ( nIndex = sValue.indexOf( sDoubleQuote,nTemp ) ) ) + { + sValue = sValue.replaceAt( nIndex, 2, sSingleQuote ); + nTemp = nIndex+2; + } + } + + // The following is mostly stolen from the former implementation in the parameter dialog + // (dbaccess/source/ui/dlg/paramdialog.cxx). I do not fully understand this ..... + + ::rtl::OUString sError; + OSQLParseNode* pParseNode = implPredicateTree( sError, sValue, _rxField ); + if ( _pErrorMessage ) *_pErrorMessage = sError; + + if ( pParseNode ) + { + OSQLParseNode* pOdbcSpec = pParseNode->getByRule( OSQLParseNode::odbc_fct_spec ); + if ( pOdbcSpec ) + { + if ( !_bForStatementUse ) + { + if ( ( pOdbcSpec->count() >= 2 ) + && ( SQL_NODE_STRING == pOdbcSpec->getChild(1)->getNodeType() ) + ) + { + + sReturn = pOdbcSpec->getChild(1)->getTokenValue(); + } + else + OSL_ENSURE( sal_False, "OPredicateInputController::getPredicateValue: unknown/invalid structure (odbc + param use)!" ); + } + else + { + OSQLParseNode* pFuncSpecParent = pOdbcSpec->getParent(); + OSL_ENSURE( pFuncSpecParent, "OPredicateInputController::getPredicateValue: an ODBC func spec node without parent?" ); + if ( pFuncSpecParent ) + pFuncSpecParent->parseNodeToStr( + sReturn, m_xConnection, &m_aParser.getContext(), sal_False, sal_True + ); + } + } + else + { + if ( pParseNode->count() >= 3 ) + { + OSQLParseNode* pValueNode = pParseNode->getChild(2); + OSL_ENSURE( pValueNode, "OPredicateInputController::getPredicateValue: invalid node child!" ); + if ( !_bForStatementUse ) + { + if ( SQL_NODE_STRING == pValueNode->getNodeType() ) + sReturn = pValueNode->getTokenValue(); + else + pValueNode->parseNodeToStr( + sReturn, m_xConnection, &m_aParser.getContext(), sal_False, sal_True + ); + } + else + pValueNode->parseNodeToStr( + sReturn, m_xConnection, &m_aParser.getContext(), sal_False, sal_True + ); + } + else + OSL_ENSURE( sal_False, "OPredicateInputController::getPredicateValue: unknown/invalid structure (noodbc)!" ); + } + + delete pParseNode; + } + } + + return sReturn; + } +//......................................................................... +} // namespace dbtools +//......................................................................... + + diff --git a/connectivity/source/commontools/propertyids.cxx b/connectivity/source/commontools/propertyids.cxx new file mode 100644 index 000000000000..b6bae373a7db --- /dev/null +++ b/connectivity/source/commontools/propertyids.cxx @@ -0,0 +1,198 @@ +/************************************************************************* + * + * 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 "propertyids.hxx" + +namespace dbtools +{ + const sal_Char* getPROPERTY_QUERYTIMEOUT() { return "QueryTimeOut"; } + const sal_Char* getPROPERTY_MAXFIELDSIZE() { return "MaxFieldSize"; } + const sal_Char* getPROPERTY_MAXROWS() { return "MaxRows"; } + const sal_Char* getPROPERTY_CURSORNAME() { return "CursorName"; } + const sal_Char* getPROPERTY_RESULTSETCONCURRENCY() { return "ResultSetConcurrency"; } + const sal_Char* getPROPERTY_RESULTSETTYPE() { return "ResultSetType"; } + const sal_Char* getPROPERTY_FETCHDIRECTION() { return "FetchDirection"; } + const sal_Char* getPROPERTY_FETCHSIZE() { return "FetchSize"; } + const sal_Char* getPROPERTY_ESCAPEPROCESSING() { return "EscapeProcessing"; } + const sal_Char* getPROPERTY_USEBOOKMARKS() { return "UseBookmarks"; } + + const sal_Char* getPROPERTY_NAME() { return "Name"; } + const sal_Char* getPROPERTY_TYPE() { return "Type"; } + const sal_Char* getPROPERTY_TYPENAME() { return "TypeName"; } + const sal_Char* getPROPERTY_PRECISION() { return "Precision"; } + const sal_Char* getPROPERTY_SCALE() { return "Scale"; } + const sal_Char* getPROPERTY_ISNULLABLE() { return "IsNullable"; } + const sal_Char* getPROPERTY_ISAUTOINCREMENT() { return "IsAutoIncrement"; } + const sal_Char* getPROPERTY_ISROWVERSION() { return "IsRowVersion"; } + const sal_Char* getPROPERTY_DESCRIPTION() { return "Description"; } + const sal_Char* getPROPERTY_DEFAULTVALUE() { return "DefaultValue"; } + + const sal_Char* getPROPERTY_REFERENCEDTABLE() { return "ReferencedTable"; } + const sal_Char* getPROPERTY_UPDATERULE() { return "UpdateRule"; } + const sal_Char* getPROPERTY_DELETERULE() { return "DeleteRule"; } + const sal_Char* getPROPERTY_CATALOG() { return "Catalog"; } + const sal_Char* getPROPERTY_ISUNIQUE() { return "IsUnique"; } + const sal_Char* getPROPERTY_ISPRIMARYKEYINDEX() { return "IsPrimaryKeyIndex"; } + const sal_Char* getPROPERTY_ISCLUSTERED() { return "IsClustered"; } + const sal_Char* getPROPERTY_ISASCENDING() { return "IsAscending"; } + const sal_Char* getPROPERTY_SCHEMANAME() { return "SchemaName"; } + const sal_Char* getPROPERTY_CATALOGNAME() { return "CatalogName"; } + const sal_Char* getPROPERTY_COMMAND() { return "Command"; } + const sal_Char* getPROPERTY_CHECKOPTION() { return "CheckOption"; } + const sal_Char* getPROPERTY_PASSWORD() { return "Password"; } + const sal_Char* getPROPERTY_RELATEDCOLUMN() { return "RelatedColumn"; } + + const sal_Char* getPROPERTY_FUNCTION() { return "Function"; } + const sal_Char* getPROPERTY_AGGREGATEFUNCTION() { return "AggregateFunction"; } + const sal_Char* getPROPERTY_TABLENAME() { return "TableName"; } + const sal_Char* getPROPERTY_REALNAME() { return "RealName"; } + const sal_Char* getPROPERTY_DBASEPRECISIONCHANGED() { return "DbasePrecisionChanged"; } + const sal_Char* getPROPERTY_ISCURRENCY() { return "IsCurrency"; } + const sal_Char* getPROPERTY_ISBOOKMARKABLE() { return "IsBookmarkable"; } + + const sal_Char* getPROPERTY_FORMATKEY() { return "FormatKey"; } + const sal_Char* getPROPERTY_LOCALE() { return "Locale"; } + + const sal_Char* getPROPERTY_AUTOINCREMENTCREATION() { return "AutoIncrementCreation"; } + const sal_Char* getPROPERTY_PRIVILEGES() { return "Privileges"; } + const sal_Char* getPROPERTY_ID_HAVINGCLAUSE() { return "HavingClause"; } + const sal_Char* getPROPERTY_ID_ISSIGNED() { return "IsSigned"; } + const sal_Char* getPROPERTY_ID_ISSEARCHABLE() { return "IsSearchable"; } + + const sal_Char* getPROPERTY_ID_APPLYFILTER() { return "ApplyFilter"; } + const sal_Char* getPROPERTY_ID_FILTER() { return "Filter"; } + const sal_Char* getPROPERTY_ID_MASTERFIELDS() { return "MasterFields"; } + const sal_Char* getPROPERTY_ID_DETAILFIELDS() { return "DetailFields"; } + const sal_Char* getPROPERTY_ID_FIELDTYPE() { return "FieldType"; } + const sal_Char* getPROPERTY_ID_VALUE() { return "Value"; } + const sal_Char* getPROPERTY_ID_ACTIVE_CONNECTION() { return "ActiveConnection"; } + const sal_Char* getPROPERTY_ID_LABEL() { return "Label"; } + + //============================================================ + //= error messages + //============================================================ + const sal_Char* getSQLSTATE_SEQUENCE() { return "HY010"; } + const sal_Char* getSTR_DELIMITER() { return "/"; } + + + + OPropertyMap::~OPropertyMap() + { + ::std::map<sal_Int32 , rtl_uString*>::iterator aIter = m_aPropertyMap.begin(); + for(;aIter != m_aPropertyMap.end();++aIter) + if(aIter->second) + rtl_uString_release(aIter->second); + } + // ------------------------------------------------------------------------------ + ::rtl::OUString OPropertyMap::getNameByIndex(sal_Int32 _nIndex) const + { + ::rtl::OUString sRet; + ::std::map<sal_Int32 , rtl_uString*>::const_iterator aIter = m_aPropertyMap.find(_nIndex); + if(aIter == m_aPropertyMap.end()) + sRet = const_cast<OPropertyMap*>(this)->fillValue(_nIndex); + else + sRet = aIter->second; + return sRet; + } + // ------------------------------------------------------------------------------ + ::rtl::OUString OPropertyMap::fillValue(sal_Int32 _nIndex) + { + rtl_uString* pStr = NULL; + switch(_nIndex) + { + case PROPERTY_ID_QUERYTIMEOUT: { rtl_uString_newFromAscii(&pStr,getPROPERTY_QUERYTIMEOUT() ); break; } + case PROPERTY_ID_MAXFIELDSIZE: { rtl_uString_newFromAscii(&pStr,getPROPERTY_MAXFIELDSIZE() ); break; } + case PROPERTY_ID_MAXROWS: { rtl_uString_newFromAscii(&pStr,getPROPERTY_MAXROWS() ); break; } + case PROPERTY_ID_CURSORNAME: { rtl_uString_newFromAscii(&pStr,getPROPERTY_CURSORNAME() ); break; } + case PROPERTY_ID_RESULTSETCONCURRENCY: { rtl_uString_newFromAscii(&pStr,getPROPERTY_RESULTSETCONCURRENCY() ); break; } + case PROPERTY_ID_RESULTSETTYPE: { rtl_uString_newFromAscii(&pStr,getPROPERTY_RESULTSETTYPE() ); break; } + case PROPERTY_ID_FETCHDIRECTION: { rtl_uString_newFromAscii(&pStr,getPROPERTY_FETCHDIRECTION() ); break; } + case PROPERTY_ID_FETCHSIZE: { rtl_uString_newFromAscii(&pStr,getPROPERTY_FETCHSIZE() ); break; } + case PROPERTY_ID_ESCAPEPROCESSING: { rtl_uString_newFromAscii(&pStr,getPROPERTY_ESCAPEPROCESSING() ); break; } + case PROPERTY_ID_USEBOOKMARKS: { rtl_uString_newFromAscii(&pStr,getPROPERTY_USEBOOKMARKS() ); break; } + // Column + case PROPERTY_ID_NAME: { rtl_uString_newFromAscii(&pStr,getPROPERTY_NAME() ); break; } + case PROPERTY_ID_TYPE: { rtl_uString_newFromAscii(&pStr,getPROPERTY_TYPE() ); break; } + case PROPERTY_ID_TYPENAME: { rtl_uString_newFromAscii(&pStr,getPROPERTY_TYPENAME() ); break; } + case PROPERTY_ID_PRECISION: { rtl_uString_newFromAscii(&pStr,getPROPERTY_PRECISION() ); break; } + case PROPERTY_ID_SCALE: { rtl_uString_newFromAscii(&pStr,getPROPERTY_SCALE() ); break; } + case PROPERTY_ID_ISNULLABLE: { rtl_uString_newFromAscii(&pStr,getPROPERTY_ISNULLABLE() ); break; } + case PROPERTY_ID_ISAUTOINCREMENT: { rtl_uString_newFromAscii(&pStr,getPROPERTY_ISAUTOINCREMENT() ); break; } + case PROPERTY_ID_ISROWVERSION: { rtl_uString_newFromAscii(&pStr,getPROPERTY_ISROWVERSION() ); break; } + case PROPERTY_ID_DESCRIPTION: { rtl_uString_newFromAscii(&pStr,getPROPERTY_DESCRIPTION() ); break; } + case PROPERTY_ID_DEFAULTVALUE: { rtl_uString_newFromAscii(&pStr,getPROPERTY_DEFAULTVALUE() ); break; } + + case PROPERTY_ID_REFERENCEDTABLE: { rtl_uString_newFromAscii(&pStr,getPROPERTY_REFERENCEDTABLE() ); break; } + case PROPERTY_ID_UPDATERULE: { rtl_uString_newFromAscii(&pStr,getPROPERTY_UPDATERULE() ); break; } + case PROPERTY_ID_DELETERULE: { rtl_uString_newFromAscii(&pStr,getPROPERTY_DELETERULE() ); break; } + case PROPERTY_ID_CATALOG: { rtl_uString_newFromAscii(&pStr,getPROPERTY_CATALOG() ); break; } + case PROPERTY_ID_ISUNIQUE: { rtl_uString_newFromAscii(&pStr,getPROPERTY_ISUNIQUE() ); break; } + case PROPERTY_ID_ISPRIMARYKEYINDEX: { rtl_uString_newFromAscii(&pStr,getPROPERTY_ISPRIMARYKEYINDEX() ); break; } + case PROPERTY_ID_ISCLUSTERED: { rtl_uString_newFromAscii(&pStr,getPROPERTY_ISCLUSTERED() ); break; } + case PROPERTY_ID_ISASCENDING: { rtl_uString_newFromAscii(&pStr,getPROPERTY_ISASCENDING() ); break; } + case PROPERTY_ID_SCHEMANAME: { rtl_uString_newFromAscii(&pStr,getPROPERTY_SCHEMANAME() ); break; } + case PROPERTY_ID_CATALOGNAME: { rtl_uString_newFromAscii(&pStr,getPROPERTY_CATALOGNAME() ); break; } + + case PROPERTY_ID_COMMAND: { rtl_uString_newFromAscii(&pStr,getPROPERTY_COMMAND() ); break; } + case PROPERTY_ID_CHECKOPTION: { rtl_uString_newFromAscii(&pStr,getPROPERTY_CHECKOPTION() ); break; } + case PROPERTY_ID_PASSWORD: { rtl_uString_newFromAscii(&pStr,getPROPERTY_PASSWORD() ); break; } + case PROPERTY_ID_RELATEDCOLUMN: { rtl_uString_newFromAscii(&pStr,getPROPERTY_RELATEDCOLUMN() ); break; } + + case PROPERTY_ID_FUNCTION: { rtl_uString_newFromAscii(&pStr,getPROPERTY_FUNCTION() ); break; } + case PROPERTY_ID_AGGREGATEFUNCTION: { rtl_uString_newFromAscii(&pStr,getPROPERTY_AGGREGATEFUNCTION() ); break; } + case PROPERTY_ID_TABLENAME: { rtl_uString_newFromAscii(&pStr,getPROPERTY_TABLENAME() ); break; } + case PROPERTY_ID_REALNAME: { rtl_uString_newFromAscii(&pStr,getPROPERTY_REALNAME() ); break; } + case PROPERTY_ID_DBASEPRECISIONCHANGED: { rtl_uString_newFromAscii(&pStr,getPROPERTY_DBASEPRECISIONCHANGED()); break; } + case PROPERTY_ID_ISCURRENCY: { rtl_uString_newFromAscii(&pStr,getPROPERTY_ISCURRENCY() ); break; } + case PROPERTY_ID_ISBOOKMARKABLE: { rtl_uString_newFromAscii(&pStr,getPROPERTY_ISBOOKMARKABLE() ); break; } + case PROPERTY_ID_HY010: { rtl_uString_newFromAscii(&pStr,getSQLSTATE_SEQUENCE() ); break; } + case PROPERTY_ID_DELIMITER: { rtl_uString_newFromAscii(&pStr,getSTR_DELIMITER() ); break; } + case PROPERTY_ID_FORMATKEY: { rtl_uString_newFromAscii(&pStr,getPROPERTY_FORMATKEY() ); break; } + case PROPERTY_ID_LOCALE: { rtl_uString_newFromAscii(&pStr,getPROPERTY_LOCALE() ); break; } + case PROPERTY_ID_AUTOINCREMENTCREATION: { rtl_uString_newFromAscii(&pStr,getPROPERTY_AUTOINCREMENTCREATION()); break; } + case PROPERTY_ID_PRIVILEGES: { rtl_uString_newFromAscii(&pStr,getPROPERTY_PRIVILEGES() ); break; } + case PROPERTY_ID_HAVINGCLAUSE: { rtl_uString_newFromAscii(&pStr,getPROPERTY_ID_HAVINGCLAUSE() ); break; } + case PROPERTY_ID_ISSIGNED: { rtl_uString_newFromAscii(&pStr,getPROPERTY_ID_ISSIGNED() ); break; } + case PROPERTY_ID_ISSEARCHABLE: { rtl_uString_newFromAscii(&pStr,getPROPERTY_ID_ISSEARCHABLE() ); break; } + case PROPERTY_ID_LABEL: { rtl_uString_newFromAscii(&pStr,getPROPERTY_ID_LABEL() ); break; } + case PROPERTY_ID_APPLYFILTER: { rtl_uString_newFromAscii(&pStr,getPROPERTY_ID_APPLYFILTER() ); break; } + case PROPERTY_ID_FILTER: { rtl_uString_newFromAscii(&pStr,getPROPERTY_ID_FILTER() ); break; } + case PROPERTY_ID_MASTERFIELDS: { rtl_uString_newFromAscii(&pStr,getPROPERTY_ID_MASTERFIELDS() ); break; } + case PROPERTY_ID_DETAILFIELDS: { rtl_uString_newFromAscii(&pStr,getPROPERTY_ID_DETAILFIELDS() ); break; } + case PROPERTY_ID_FIELDTYPE: { rtl_uString_newFromAscii(&pStr,getPROPERTY_ID_FIELDTYPE() ); break; } + case PROPERTY_ID_VALUE: { rtl_uString_newFromAscii(&pStr,getPROPERTY_ID_VALUE() ); break; } + case PROPERTY_ID_ACTIVE_CONNECTION: { rtl_uString_newFromAscii(&pStr,getPROPERTY_ID_ACTIVE_CONNECTION() ); break; } + } + m_aPropertyMap[_nIndex] = pStr; + return pStr; + } +} + + diff --git a/connectivity/source/commontools/sqlerror.cxx b/connectivity/source/commontools/sqlerror.cxx new file mode 100644 index 000000000000..a04284799894 --- /dev/null +++ b/connectivity/source/commontools/sqlerror.cxx @@ -0,0 +1,363 @@ +/************************************************************************* + * + * 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 "connectivity/sqlerror.hxx" + +/** === begin UNO includes === **/ +#include <com/sun/star/sdbc/SQLException.hpp> +/** === end UNO includes === **/ + +#include <comphelper/officeresourcebundle.hxx> +#include <cppuhelper/exc_hlp.hxx> +#include <rtl/ustrbuf.hxx> + +#include <string.h> + +//........................................................................ +namespace connectivity +{ +//........................................................................ + + /** === begin UNO using === **/ + using ::com::sun::star::uno::Reference; + using ::com::sun::star::uno::UNO_QUERY; + using ::com::sun::star::uno::UNO_QUERY_THROW; + using ::com::sun::star::uno::Exception; + using ::com::sun::star::uno::RuntimeException; + using ::com::sun::star::uno::Any; + using ::com::sun::star::uno::makeAny; + using ::com::sun::star::uno::XInterface; + using ::com::sun::star::sdbc::SQLException; + using ::com::sun::star::uno::Type; + /** === end UNO using === **/ + + //using SQLError::ParamValue; // GCC (unxlngi6) does not like this + namespace + { + typedef SQLError::ParamValue ParamValue; + } + + //==================================================================== + //= SQLError_Impl - declaration + //==================================================================== + class SQLError_Impl + { + public: + SQLError_Impl( const ::comphelper::ComponentContext& _rContext ); + ~SQLError_Impl(); + + // versions of the public SQLError methods which are just delegated to this impl-class + static const ::rtl::OUString& getMessagePrefix(); + ::rtl::OUString getErrorMessage( const ErrorCondition _eCondition, const ParamValue& _rParamValue1, const ParamValue& _rParamValue2, const ParamValue& _rParamValue3 ); + ::rtl::OUString getSQLState( const ErrorCondition _eCondition ); + static ErrorCode getErrorCode( const ErrorCondition _eCondition ); + void raiseException( const ErrorCondition _eCondition, const Reference< XInterface >& _rxContext, const ParamValue& _rParamValue1, const ParamValue& _rParamValue2, const ParamValue& _rParamValue3 ); + void raiseException( const ErrorCondition _eCondition, const ParamValue& _rParamValue1, const ParamValue& _rParamValue2, const ParamValue& _rParamValue3 ); + void raiseTypedException( const ErrorCondition _eCondition, const Reference< XInterface >& _rxContext, const Type& _rExceptionType, const ParamValue& _rParamValue1, const ParamValue& _rParamValue2, const ParamValue& _rParamValue3 ); + SQLException getSQLException( const ErrorCondition _eCondition, const Reference< XInterface >& _rxContext, const ParamValue& _rParamValue1, const ParamValue& _rParamValue2, const ParamValue& _rParamValue3 ); + + private: + /// returns the basic error message associated with the given error condition, without any parameter replacements + ::rtl::OUString + impl_getErrorMessage( const ErrorCondition& _eCondition ); + + /// returns the SQLState associated with the given error condition + ::rtl::OUString + impl_getSQLState( const ErrorCondition& _eCondition ); + + /// returns an SQLException describing the given error condition + SQLException + impl_buildSQLException( const ErrorCondition _eCondition, const Reference< XInterface >& _rxContext, + const ParamValue& _rParamValue1, const ParamValue& _rParamValue2, const ParamValue& _rParamValue3 ); + + /// initializes our resource bundle + bool impl_initResources(); + + private: + ::osl::Mutex m_aMutex; + ::comphelper::ComponentContext m_aContext; + ::std::auto_ptr< ::comphelper::OfficeResourceBundle > m_pResources; + bool m_bAttemptedInit; + }; + + //==================================================================== + //= SQLError_Impl - implementation + //==================================================================== + //-------------------------------------------------------------------- + SQLError_Impl::SQLError_Impl( const ::comphelper::ComponentContext& _rContext ) + :m_aContext( _rContext ) + ,m_pResources( ) + ,m_bAttemptedInit( false ) + { + } + + //-------------------------------------------------------------------- + SQLError_Impl::~SQLError_Impl() + { + } + + //-------------------------------------------------------------------- + const ::rtl::OUString& SQLError_Impl::getMessagePrefix() + { + static ::rtl::OUString s_sMessagePrefix( RTL_CONSTASCII_USTRINGPARAM( "[OOoBase]" ) ); + return s_sMessagePrefix; + } + + //-------------------------------------------------------------------- + namespace + { + //................................................................ + /** substitutes a given placeholder in the given message with the given value + */ + void lcl_substitutePlaceholder( ::rtl::OUString& _rMessage, const sal_Char* _pPlaceholder, ParamValue _rParamValue ) + { + size_t nPlaceholderLen( strlen( _pPlaceholder ) ); + sal_Int32 nIndex = _rMessage.indexOfAsciiL( _pPlaceholder, nPlaceholderLen ); + + bool bHasPlaceholder = ( nIndex != -1 ); + bool bWantsPlaceholder = _rParamValue.is(); + OSL_ENSURE( bHasPlaceholder == bWantsPlaceholder, "lcl_substitutePlaceholder: placeholder where none is expected, or no placeholder where one is needed!" ); + + if ( bHasPlaceholder && bWantsPlaceholder ) + _rMessage = _rMessage.replaceAt( nIndex, nPlaceholderLen, *_rParamValue ); + } + + //................................................................ + sal_Int32 lcl_getResourceID( const ErrorCondition _eCondition, bool _bSQLState ) + { + return 256 + + 2 * ::sal::static_int_cast< sal_Int32, ErrorCondition >( _eCondition ) + + ( _bSQLState ? 1 : 0 ); + } + } + + //-------------------------------------------------------------------- + ::rtl::OUString SQLError_Impl::getErrorMessage( const ErrorCondition _eCondition, const ParamValue& _rParamValue1, const ParamValue& _rParamValue2, const ParamValue& _rParamValue3 ) + { + ::rtl::OUString sErrorMessage( impl_getErrorMessage( _eCondition ) ); + + lcl_substitutePlaceholder( sErrorMessage, "$1$", _rParamValue1 ); + lcl_substitutePlaceholder( sErrorMessage, "$2$", _rParamValue2 ); + lcl_substitutePlaceholder( sErrorMessage, "$3$", _rParamValue3 ); + + return sErrorMessage; + } + + //-------------------------------------------------------------------- + ::rtl::OUString SQLError_Impl::getSQLState( const ErrorCondition _eCondition ) + { + return impl_getSQLState( _eCondition ); + } + + //-------------------------------------------------------------------- + ErrorCode SQLError_Impl::getErrorCode( const ErrorCondition _eCondition ) + { + return 0 - ::sal::static_int_cast< ErrorCode, ErrorCondition >( _eCondition ); + } + + //-------------------------------------------------------------------- + void SQLError_Impl::raiseException( const ErrorCondition _eCondition, const Reference< XInterface >& _rxContext, const ParamValue& _rParamValue1, const ParamValue& _rParamValue2, const ParamValue& _rParamValue3 ) + { + raiseTypedException( + _eCondition, + _rxContext, + ::cppu::UnoType< SQLException >::get(), + _rParamValue1, + _rParamValue2, + _rParamValue3 + ); + } + + //-------------------------------------------------------------------- + void SQLError_Impl::raiseException( const ErrorCondition _eCondition, const ParamValue& _rParamValue1, const ParamValue& _rParamValue2, const ParamValue& _rParamValue3 ) + { + raiseTypedException( + _eCondition, + NULL, + ::cppu::UnoType< SQLException >::get(), + _rParamValue1, + _rParamValue2, + _rParamValue3 + ); + } + + //-------------------------------------------------------------------- + void SQLError_Impl::raiseTypedException( const ErrorCondition _eCondition, const Reference< XInterface >& _rxContext, + const Type& _rExceptionType, const ParamValue& _rParamValue1, const ParamValue& _rParamValue2, const ParamValue& _rParamValue3 ) + { + if ( !::cppu::UnoType< SQLException >::get().isAssignableFrom( _rExceptionType ) ) + throw ::std::bad_cast(); + + // default-construct an exception of the desired type + Any aException( NULL, _rExceptionType ); + + // fill it + SQLException* pException = static_cast< SQLException* >( aException.pData ); + *pException = impl_buildSQLException( _eCondition, _rxContext, _rParamValue1, _rParamValue2, _rParamValue3 ); + + // throw it + ::cppu::throwException( aException ); + } + + //-------------------------------------------------------------------- + SQLException SQLError_Impl::getSQLException( const ErrorCondition _eCondition, const Reference< XInterface >& _rxContext, + const ParamValue& _rParamValue1, const ParamValue& _rParamValue2, const ParamValue& _rParamValue3 ) + { + return impl_buildSQLException( _eCondition, _rxContext, _rParamValue1, _rParamValue2, _rParamValue3 ); + } + + //-------------------------------------------------------------------- + SQLException SQLError_Impl::impl_buildSQLException( const ErrorCondition _eCondition, const Reference< XInterface >& _rxContext, + const ParamValue& _rParamValue1, const ParamValue& _rParamValue2, const ParamValue& _rParamValue3 ) + { + return SQLException( + getErrorMessage( _eCondition, _rParamValue1, _rParamValue2, _rParamValue3 ), + _rxContext, + getSQLState( _eCondition ), + getErrorCode( _eCondition ), + Any() + ); + } + + //-------------------------------------------------------------------- + ::rtl::OUString SQLError_Impl::impl_getErrorMessage( const ErrorCondition& _eCondition ) + { + ::rtl::OUStringBuffer aMessage; + + if ( impl_initResources() ) + { + ::rtl::OUString sResMessage( m_pResources->loadString( lcl_getResourceID( _eCondition, false ) ) ); + OSL_ENSURE( sResMessage.getLength(), "SQLError_Impl::impl_getErrorMessage: illegal error condition, or invalid resource!" ); + aMessage.append( getMessagePrefix() ).appendAscii( " " ).append( sResMessage ); + } + + return aMessage.makeStringAndClear(); + } + + //-------------------------------------------------------------------- + ::rtl::OUString SQLError_Impl::impl_getSQLState( const ErrorCondition& _eCondition ) + { + ::rtl::OUString sState; + + if ( impl_initResources() ) + { + sal_Int32 nResourceId( lcl_getResourceID( _eCondition, true ) ); + if ( m_pResources->hasString( nResourceId ) ) + sState = m_pResources->loadString( nResourceId ); + } + + if ( !sState.getLength() ) + sState = ::rtl::OUString::intern( RTL_CONSTASCII_USTRINGPARAM( "S1000" ) ); + + return sState; + } + + //-------------------------------------------------------------------- + bool SQLError_Impl::impl_initResources() + { + if ( m_pResources.get() ) + return true; + if ( m_bAttemptedInit ) + return false; + + ::osl::MutexGuard aGuard( m_aMutex ); + m_bAttemptedInit = true; + + m_pResources.reset( new ::comphelper::OfficeResourceBundle( m_aContext.getUNOContext(), "sdberr" ) ); + return m_pResources.get() != NULL; + } + + //==================================================================== + //= SQLError + //==================================================================== + //-------------------------------------------------------------------- + SQLError::SQLError( const ::comphelper::ComponentContext& _rContext ) + :m_pImpl( new SQLError_Impl( _rContext ) ) + { + } + + //-------------------------------------------------------------------- + SQLError::~SQLError() + { + } + + //-------------------------------------------------------------------- + const ::rtl::OUString& SQLError::getMessagePrefix() + { + return SQLError_Impl::getMessagePrefix(); + } + + //-------------------------------------------------------------------- + ::rtl::OUString SQLError::getErrorMessage( const ErrorCondition _eCondition, const ParamValue& _rParamValue1, const ParamValue& _rParamValue2, const ParamValue& _rParamValue3 ) const + { + return m_pImpl->getErrorMessage( _eCondition, _rParamValue1, _rParamValue2, _rParamValue3 ); + } + + //-------------------------------------------------------------------- + ::rtl::OUString SQLError::getSQLState( const ErrorCondition _eCondition ) const + { + return m_pImpl->getSQLState( _eCondition ); + } + + //-------------------------------------------------------------------- + ErrorCode SQLError::getErrorCode( const ErrorCondition _eCondition ) + { + return SQLError_Impl::getErrorCode( _eCondition ); + } + + //-------------------------------------------------------------------- + void SQLError::raiseException( const ErrorCondition _eCondition, const Reference< XInterface >& _rxContext, const ParamValue& _rParamValue1, const ParamValue& _rParamValue2, const ParamValue& _rParamValue3 ) const + { + m_pImpl->raiseException( _eCondition, _rxContext, _rParamValue1, _rParamValue2, _rParamValue3 ); + } + + //-------------------------------------------------------------------- + void SQLError::raiseException( const ErrorCondition _eCondition, const ParamValue& _rParamValue1, const ParamValue& _rParamValue2, const ParamValue& _rParamValue3 ) const + { + m_pImpl->raiseException( _eCondition, _rParamValue1, _rParamValue2, _rParamValue3 ); + } + + //-------------------------------------------------------------------- + void SQLError::raiseTypedException( const ErrorCondition _eCondition, const Reference< XInterface >& _rxContext, + const Type& _rExceptionType, const ParamValue& _rParamValue1, const ParamValue& _rParamValue2, const ParamValue& _rParamValue3 ) const + { + m_pImpl->raiseTypedException( _eCondition, _rxContext, _rExceptionType, _rParamValue1, _rParamValue2, _rParamValue3 ); + } + + //-------------------------------------------------------------------- + SQLException SQLError::getSQLException( const ErrorCondition _eCondition, const Reference< XInterface >& _rxContext, + const ParamValue& _rParamValue1, const ParamValue& _rParamValue2, const ParamValue& _rParamValue3 ) const + { + return m_pImpl->getSQLException( _eCondition, _rxContext, _rParamValue1, _rParamValue2, _rParamValue3 ); + } + +//........................................................................ +} // namespace connectivity +//........................................................................ diff --git a/connectivity/source/commontools/statementcomposer.cxx b/connectivity/source/commontools/statementcomposer.cxx new file mode 100644 index 000000000000..0996eaaaaf86 --- /dev/null +++ b/connectivity/source/commontools/statementcomposer.cxx @@ -0,0 +1,315 @@ +/************************************************************************* + * + * 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 <connectivity/statementcomposer.hxx> + +#include <connectivity/dbtools.hxx> + +/** === begin UNO includes === **/ +#include <com/sun/star/sdb/CommandType.hpp> +#include <com/sun/star/lang/NullPointerException.hpp> +#include <com/sun/star/lang/XComponent.hpp> +#include <com/sun/star/sdb/XQueriesSupplier.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +/** === end UNO includes === **/ + +#include <unotools/sharedunocomponent.hxx> +#include <tools/diagnose_ex.h> +#include <comphelper/property.hxx> + +//........................................................................ +namespace dbtools +{ +//........................................................................ + + /** === begin UNO using === **/ + using ::com::sun::star::uno::Reference; + using ::com::sun::star::sdbc::XConnection; + using ::com::sun::star::sdb::XSingleSelectQueryComposer; + using ::com::sun::star::lang::NullPointerException; + using ::com::sun::star::uno::Exception; + using ::com::sun::star::lang::XComponent; + using ::com::sun::star::uno::UNO_QUERY_THROW; + using ::com::sun::star::sdb::XQueriesSupplier; + using ::com::sun::star::container::XNameAccess; + using ::com::sun::star::uno::UNO_QUERY; + using ::com::sun::star::beans::XPropertySet; + using ::com::sun::star::lang::XMultiServiceFactory; + using ::com::sun::star::sdbc::SQLException; + /** === end UNO using === **/ + namespace CommandType = ::com::sun::star::sdb::CommandType; + + //==================================================================== + //= StatementComposer_Data + //==================================================================== + struct StatementComposer_Data + { + const Reference< XConnection > xConnection; + Reference< XSingleSelectQueryComposer > xComposer; + ::rtl::OUString sCommand; + ::rtl::OUString sFilter; + ::rtl::OUString sOrder; + sal_Int32 nCommandType; + sal_Bool bEscapeProcessing; + bool bComposerDirty; + bool bDisposeComposer; + + StatementComposer_Data( const Reference< XConnection >& _rxConnection ) + :xConnection( _rxConnection ) + ,sCommand() + ,sFilter() + ,sOrder() + ,nCommandType( CommandType::COMMAND ) + ,bEscapeProcessing( sal_True ) + ,bComposerDirty( true ) + ,bDisposeComposer( true ) + { + if ( !_rxConnection.is() ) + throw NullPointerException(); + } + }; + + //-------------------------------------------------------------------- + namespace + { + //---------------------------------------------------------------- + void lcl_resetComposer( StatementComposer_Data& _rData ) + { + if ( _rData.bDisposeComposer && _rData.xComposer.is() ) + { + try + { + Reference< XComponent > xComposerComponent( _rData.xComposer, UNO_QUERY_THROW ); + xComposerComponent->dispose(); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + } + _rData.xComposer.clear(); + } + + //---------------------------------------------------------------- + bool lcl_ensureUpToDateComposer_nothrow( StatementComposer_Data& _rData ) + { + if ( !_rData.bComposerDirty ) + return _rData.xComposer.is(); + lcl_resetComposer( _rData ); + + try + { + ::rtl::OUString sStatement; + switch ( _rData.nCommandType ) + { + case CommandType::COMMAND: + if ( _rData.bEscapeProcessing ) + sStatement = _rData.sCommand; + // (in case of no escape processing we assume a not parseable statement) + break; + + case CommandType::TABLE: + { + if ( !_rData.sCommand.getLength() ) + break; + + sStatement = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "SELECT * FROM " ) ); + + ::rtl::OUString sCatalog, sSchema, sTable; + qualifiedNameComponents( _rData.xConnection->getMetaData(), _rData.sCommand, sCatalog, sSchema, sTable, eInDataManipulation ); + + sStatement += composeTableNameForSelect( _rData.xConnection, sCatalog, sSchema, sTable ); + } + break; + + case CommandType::QUERY: + { + // ask the connection for the query + Reference< XQueriesSupplier > xSupplyQueries( _rData.xConnection, UNO_QUERY_THROW ); + Reference< XNameAccess > xQueries( xSupplyQueries->getQueries(), UNO_QUERY_THROW ); + + if ( !xQueries->hasByName( _rData.sCommand ) ) + break; + + Reference< XPropertySet > xQuery( xQueries->getByName( _rData.sCommand ), UNO_QUERY_THROW ); + + // a native query ? + sal_Bool bQueryEscapeProcessing = sal_False; + xQuery->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "EscapeProcessing" ) ) ) >>= bQueryEscapeProcessing; + if ( !bQueryEscapeProcessing ) + break; + + // the command used by the query + xQuery->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Command" ) ) ) >>= sStatement; + if ( !sStatement.getLength() ) + break; + + // use a composer to build a statement from the query filter/order props + Reference< XMultiServiceFactory > xFactory( _rData.xConnection, UNO_QUERY_THROW ); + ::utl::SharedUNOComponent< XSingleSelectQueryComposer > xComposer; + xComposer.set( + xFactory->createInstance( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.sdb.SingleSelectQueryComposer" ) ) ), + UNO_QUERY_THROW + ); + + // the "basic" statement + xComposer->setElementaryQuery( sStatement ); + + // the sort order + const ::rtl::OUString sPropOrder( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Order" ) ) ); + if ( ::comphelper::hasProperty( sPropOrder, xQuery ) ) + { + ::rtl::OUString sOrder; + OSL_VERIFY( xQuery->getPropertyValue( sPropOrder ) >>= sOrder ); + xComposer->setOrder( sOrder ); + } + + // the filter + sal_Bool bApplyFilter = sal_True; + const ::rtl::OUString sPropApply = ::rtl::OUString::createFromAscii( "ApplyFilter" ); + if ( ::comphelper::hasProperty( sPropApply, xQuery ) ) + { + OSL_VERIFY( xQuery->getPropertyValue( sPropApply ) >>= bApplyFilter ); + } + + if ( bApplyFilter ) + { + ::rtl::OUString sFilter; + OSL_VERIFY( xQuery->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Filter" ) ) ) >>= sFilter ); + xComposer->setFilter( sFilter ); + } + + // the composed statement + sStatement = xComposer->getQuery(); + } + break; + + default: + OSL_ENSURE(sal_False, "lcl_ensureUpToDateComposer_nothrow: no table, no query, no statement - what else ?!"); + break; + } + + if ( sStatement.getLength() ) + { + // create an composer + Reference< XMultiServiceFactory > xFactory( _rData.xConnection, UNO_QUERY_THROW ); + Reference< XSingleSelectQueryComposer > xComposer( xFactory->createInstance( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.sdb.SingleSelectQueryComposer" ) ) ), + UNO_QUERY_THROW ); + xComposer->setElementaryQuery( sStatement ); + + // append sort/filter + xComposer->setOrder( _rData.sOrder ); + xComposer->setFilter( _rData.sFilter ); + + sStatement = xComposer->getQuery(); + + _rData.xComposer = xComposer; + _rData.bComposerDirty = false; + } + } + catch( const SQLException& ) + { + // allowed to leave here + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + + return _rData.xComposer.is(); + } + } + + //==================================================================== + //= StatementComposer + //==================================================================== + //-------------------------------------------------------------------- + StatementComposer::StatementComposer( const Reference< XConnection >& _rxConnection, + const ::rtl::OUString& _rCommand, const sal_Int32 _nCommandType, const sal_Bool _bEscapeProcessing ) + :m_pData( new StatementComposer_Data( _rxConnection ) ) + { + OSL_PRECOND( _rxConnection.is(), "StatementComposer::StatementComposer: illegal connection!" ); + m_pData->sCommand = _rCommand; + m_pData->nCommandType = _nCommandType; + m_pData->bEscapeProcessing = _bEscapeProcessing; + } + + //-------------------------------------------------------------------- + StatementComposer::~StatementComposer() + { + lcl_resetComposer( *m_pData ); + } + + //-------------------------------------------------------------------- + void StatementComposer::setDisposeComposer( bool _bDoDispose ) + { + m_pData->bDisposeComposer = _bDoDispose; + } + + //-------------------------------------------------------------------- + bool StatementComposer::getDisposeComposer() const + { + return m_pData->bDisposeComposer; + } + + //-------------------------------------------------------------------- + void StatementComposer::setFilter( const ::rtl::OUString& _rFilter ) + { + m_pData->sFilter = _rFilter; + m_pData->bComposerDirty = true; + } + + //-------------------------------------------------------------------- + void StatementComposer::setOrder( const ::rtl::OUString& _rOrder ) + { + m_pData->sOrder = _rOrder; + m_pData->bComposerDirty = true; + } + + //-------------------------------------------------------------------- + Reference< XSingleSelectQueryComposer > StatementComposer::getComposer() + { + lcl_ensureUpToDateComposer_nothrow( *m_pData ); + return m_pData->xComposer; + } + + //-------------------------------------------------------------------- + ::rtl::OUString StatementComposer::getQuery() + { + if ( lcl_ensureUpToDateComposer_nothrow( *m_pData ) ) + { + return m_pData->xComposer->getQuery(); + } + + return ::rtl::OUString(); + } + +//........................................................................ +} // namespace dbtools +//........................................................................ diff --git a/connectivity/source/commontools/warningscontainer.cxx b/connectivity/source/commontools/warningscontainer.cxx new file mode 100644 index 000000000000..91890e8149df --- /dev/null +++ b/connectivity/source/commontools/warningscontainer.cxx @@ -0,0 +1,123 @@ +/************************************************************************* + * + * 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 "connectivity/warningscontainer.hxx" +#include "connectivity/dbexception.hxx" + +#include <osl/diagnose.h> + +//........................................................................ +namespace dbtools +{ +//........................................................................ + + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::sdbc; + using namespace ::com::sun::star::sdb; + + //==================================================================== + //= WarningsContainer + //==================================================================== + //-------------------------------------------------------------------- + static void lcl_concatWarnings( Any& _rChainLeft, const Any& _rChainRight ) + { + if ( !_rChainLeft.hasValue() ) + _rChainLeft = _rChainRight; + else + { + // to travel the chain by reference (and not by value), we need the getValue ... + // looks like a hack, but the meaning of getValue is documented, and it's the only chance for reference-traveling .... + + OSL_ENSURE( SQLExceptionInfo( _rChainLeft ).isValid(), + "lcl_concatWarnings: invalid warnings chain (this will crash)!" ); + + const SQLException* pChainTravel = static_cast< const SQLException* >( _rChainLeft.getValue() ); + SQLExceptionIteratorHelper aReferenceIterHelper( *pChainTravel ); + while ( aReferenceIterHelper.hasMoreElements() ) + pChainTravel = aReferenceIterHelper.next(); + + // reached the end of the chain, and pChainTravel points to the last element + const_cast< SQLException* >( pChainTravel )->NextException = _rChainRight; + } + } + + //-------------------------------------------------------------------- + WarningsContainer::~WarningsContainer() + { + } + + //-------------------------------------------------------------------- + void WarningsContainer::appendWarning(const SQLException& _rWarning) + { + lcl_concatWarnings( m_aOwnWarnings, makeAny( _rWarning ) ); + } + + //-------------------------------------------------------------------- + void WarningsContainer::appendWarning( const SQLContext& _rContext ) + { + lcl_concatWarnings( m_aOwnWarnings, makeAny( _rContext )); + } + + //-------------------------------------------------------------------- + void WarningsContainer::appendWarning(const SQLWarning& _rWarning) + { + lcl_concatWarnings( m_aOwnWarnings, makeAny( _rWarning ) ); + } + + //-------------------------------------------------------------------- + Any SAL_CALL WarningsContainer::getWarnings( ) const + { + Any aAllWarnings; + if ( m_xExternalWarnings.is() ) + aAllWarnings = m_xExternalWarnings->getWarnings(); + + if ( m_aOwnWarnings.hasValue() ) + lcl_concatWarnings( aAllWarnings, m_aOwnWarnings ); + + return aAllWarnings; + } + + //-------------------------------------------------------------------- + void SAL_CALL WarningsContainer::clearWarnings( ) + { + if ( m_xExternalWarnings.is() ) + m_xExternalWarnings->clearWarnings(); + m_aOwnWarnings.clear(); + } + + //-------------------------------------------------------------------- + void WarningsContainer::appendWarning( const ::rtl::OUString& _rWarning, const sal_Char* _pAsciiSQLState, const Reference< XInterface >& _rxContext ) + { + appendWarning( SQLWarning( _rWarning, _rxContext, ::rtl::OUString::createFromAscii( _pAsciiSQLState ), 0, Any() ) ); + } + +//........................................................................ +} // namespace dbtools +//........................................................................ |