diff options
Diffstat (limited to 'dbaccess/source/core/api')
59 files changed, 26411 insertions, 0 deletions
diff --git a/dbaccess/source/core/api/BookmarkSet.cxx b/dbaccess/source/core/api/BookmarkSet.cxx new file mode 100644 index 000000000000..b5b9ec0ec787 --- /dev/null +++ b/dbaccess/source/core/api/BookmarkSet.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_dbaccess.hxx" +#ifndef DBACCESS_CORE_API_BOOKMARKSET_HXX +#include "BookmarkSet.hxx" +#endif +#ifndef _DBA_CORE_RESOURCE_HXX_ +#include "core_resource.hxx" +#endif +#ifndef _DBA_CORE_RESOURCE_HRC_ +#include "core_resource.hrc" +#endif +#ifndef _COM_SUN_STAR_SDBC_XRESULTSETUPDATE_HPP_ +#include <com/sun/star/sdbc/XResultSetUpdate.hpp> +#endif +#ifndef _DBHELPER_DBEXCEPTION_HXX_ +#include <connectivity/dbexception.hxx> +#endif +#include <rtl/logfile.hxx> + +#include <limits> + +using namespace dbaccess; +using namespace ::connectivity; +using 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::sdb; +using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::lang; +// using namespace ::cppu; +using namespace ::osl; + +void OBookmarkSet::construct(const Reference< XResultSet>& _xDriverSet,const ::rtl::OUString& i_sRowSetFilter) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OBookmarkSet::construct" ); + OCacheSet::construct(_xDriverSet,i_sRowSetFilter); + m_xRowLocate.set(_xDriverSet,UNO_QUERY); +} +// ----------------------------------------------------------------------------- +Any SAL_CALL OBookmarkSet::getBookmark() throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OBookmarkSet::getBookmark" ); + return m_xRowLocate->getBookmark(); +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL OBookmarkSet::moveToBookmark( const Any& bookmark ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OBookmarkSet::moveToBookmark" ); + return m_xRowLocate->moveToBookmark(bookmark); +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL OBookmarkSet::moveRelativeToBookmark( const Any& bookmark, sal_Int32 rows ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OBookmarkSet::moveRelativeToBookmark" ); + return m_xRowLocate->moveRelativeToBookmark(bookmark,rows); +} +// ------------------------------------------------------------------------- +sal_Int32 SAL_CALL OBookmarkSet::compareBookmarks( const Any& _first, const Any& _second ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OBookmarkSet::compareBookmarks" ); + return m_xRowLocate->compareBookmarks(_first,_second); +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL OBookmarkSet::hasOrderedBookmarks( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OBookmarkSet::hasOrderedBookmarks" ); + return m_xRowLocate->hasOrderedBookmarks(); +} +// ------------------------------------------------------------------------- +sal_Int32 SAL_CALL OBookmarkSet::hashBookmark( const Any& bookmark ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OBookmarkSet::hashBookmark" ); + return m_xRowLocate->hashBookmark(bookmark); +} +// ------------------------------------------------------------------------- +// ::com::sun::star::sdbcx::XDeleteRows +Sequence< sal_Int32 > SAL_CALL OBookmarkSet::deleteRows( const Sequence< Any >& rows ,const connectivity::OSQLTable& /*_xTable*/) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OBookmarkSet::deleteRows" ); + Reference< ::com::sun::star::sdbcx::XDeleteRows> xDeleteRow(m_xRowLocate,UNO_QUERY); + if(xDeleteRow.is()) + { + return xDeleteRow->deleteRows(rows); + } + return Sequence< sal_Int32 >(); +} +// ------------------------------------------------------------------------- +void SAL_CALL OBookmarkSet::insertRow( const ORowSetRow& _rInsertRow,const connectivity::OSQLTable& /*_xTable*/ ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OBookmarkSet::insertRow" ); + Reference<XRowUpdate> xUpdRow(m_xRowLocate,UNO_QUERY); + if(!xUpdRow.is()) + ::dbtools::throwSQLException( DBACORE_RESSTRING( RID_STR_NO_XROWUPDATE ), SQL_GENERAL_ERROR, *this ); + + Reference<XResultSetUpdate> xUpd(m_xRowLocate,UNO_QUERY); + if(xUpd.is()) + { + xUpd->moveToInsertRow(); + sal_Int32 i = 1; + connectivity::ORowVector< ORowSetValue > ::Vector::iterator aEnd = _rInsertRow->get().end(); + for(connectivity::ORowVector< ORowSetValue > ::Vector::iterator aIter = _rInsertRow->get().begin()+1;aIter != aEnd;++aIter,++i) + { + aIter->setSigned(m_aSignedFlags[i-1]); + updateColumn(i,xUpdRow,*aIter); + } + xUpd->insertRow(); + (*_rInsertRow->get().begin()) = m_xRowLocate->getBookmark(); + } + else + ::dbtools::throwSQLException( DBACORE_RESSTRING( RID_STR_NO_XRESULTSETUPDATE ), SQL_GENERAL_ERROR, *this ); +} +// ------------------------------------------------------------------------- +void SAL_CALL OBookmarkSet::updateRow(const ORowSetRow& _rInsertRow ,const ORowSetRow& _rOrginalRow,const connectivity::OSQLTable& /*_xTable*/ ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OBookmarkSet::updateRow" ); + // OCacheSet::updateRow( _rInsertRow,_rOrginalRow,_xTable); + Reference<XRowUpdate> xUpdRow(m_xRowLocate,UNO_QUERY); + if(!xUpdRow.is()) + ::dbtools::throwSQLException( DBACORE_RESSTRING( RID_STR_NO_XROWUPDATE ), SQL_GENERAL_ERROR, *this ); + + sal_Int32 i = 1; + connectivity::ORowVector< ORowSetValue > ::Vector::const_iterator aOrgIter = _rOrginalRow->get().begin()+1; + connectivity::ORowVector< ORowSetValue > ::Vector::iterator aEnd = _rInsertRow->get().end(); + for(connectivity::ORowVector< ORowSetValue > ::Vector::iterator aIter = _rInsertRow->get().begin()+1;aIter != aEnd;++aIter,++i,++aOrgIter) + { + aIter->setSigned(aOrgIter->isSigned()); + updateColumn(i,xUpdRow,*aIter); + } + + + Reference<XResultSetUpdate> xUpd(m_xRowLocate,UNO_QUERY); + if(xUpd.is()) + xUpd->updateRow(); + else + ::dbtools::throwSQLException( DBACORE_RESSTRING( RID_STR_NO_XRESULTSETUPDATE ), SQL_GENERAL_ERROR, *this ); +} +// ------------------------------------------------------------------------- +void SAL_CALL OBookmarkSet::deleteRow(const ORowSetRow& /*_rDeleteRow*/ ,const connectivity::OSQLTable& /*_xTable*/ ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OBookmarkSet::deleteRow" ); + Reference<XResultSetUpdate> xUpd(m_xRowLocate,UNO_QUERY); + + xUpd->deleteRow(); +} +// ------------------------------------------------------------------------- +void SAL_CALL OBookmarkSet::cancelRowUpdates( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OBookmarkSet::cancelRowUpdates" ); +} +// ------------------------------------------------------------------------- +void SAL_CALL OBookmarkSet::moveToInsertRow( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OBookmarkSet::moveToInsertRow" ); + Reference<XResultSetUpdate> xUpd(m_xRowLocate,UNO_QUERY); + if(xUpd.is()) + xUpd->moveToInsertRow(); +} +// ------------------------------------------------------------------------- +void SAL_CALL OBookmarkSet::moveToCurrentRow( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OBookmarkSet::moveToCurrentRow" ); +} +// ------------------------------------------------------------------------- +void OBookmarkSet::fillValueRow(ORowSetRow& _rRow,sal_Int32 _nPosition) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OBookmarkSet::fillValueRow" ); + OCacheSet::fillValueRow(_rRow,_nPosition); +} +// ------------------------------------------------------------------------- +void OBookmarkSet::updateColumn(sal_Int32 nPos,Reference< XRowUpdate > _xParameter,const ORowSetValue& _rValue) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OBookmarkSet::updateColumn" ); + if(_rValue.isBound() && _rValue.isModified()) + { + if(_rValue.isNull()) + _xParameter->updateNull(nPos); + else + { + + switch(_rValue.getTypeKind()) + { + case DataType::DECIMAL: + case DataType::NUMERIC: + _xParameter->updateNumericObject(nPos,_rValue.makeAny(),m_xSetMetaData->getScale(nPos)); + break; + case DataType::CHAR: + case DataType::VARCHAR: + //case DataType::DECIMAL: + //case DataType::NUMERIC: + _xParameter->updateString(nPos,_rValue); + break; + case DataType::BIGINT: + if ( _rValue.isSigned() ) + _xParameter->updateLong(nPos,_rValue); + else + _xParameter->updateString(nPos,_rValue); + break; + case DataType::BIT: + case DataType::BOOLEAN: + _xParameter->updateBoolean(nPos,_rValue); + break; + case DataType::TINYINT: + if ( _rValue.isSigned() ) + _xParameter->updateByte(nPos,_rValue); + else + _xParameter->updateShort(nPos,_rValue); + break; + case DataType::SMALLINT: + if ( _rValue.isSigned() ) + _xParameter->updateShort(nPos,_rValue); + else + _xParameter->updateInt(nPos,_rValue); + break; + case DataType::INTEGER: + if ( _rValue.isSigned() ) + _xParameter->updateInt(nPos,_rValue); + else + _xParameter->updateLong(nPos,_rValue); + break; + case DataType::FLOAT: + _xParameter->updateFloat(nPos,_rValue); + break; + case DataType::DOUBLE: + case DataType::REAL: + _xParameter->updateDouble(nPos,_rValue); + break; + case DataType::DATE: + _xParameter->updateDate(nPos,_rValue); + break; + case DataType::TIME: + _xParameter->updateTime(nPos,_rValue); + break; + case DataType::TIMESTAMP: + _xParameter->updateTimestamp(nPos,_rValue); + break; + case DataType::BINARY: + case DataType::VARBINARY: + case DataType::LONGVARBINARY: + _xParameter->updateBytes(nPos,_rValue); + break; + case DataType::BLOB: + case DataType::CLOB: + _xParameter->updateObject(nPos,_rValue.getAny()); + break; + } + } + } +} + diff --git a/dbaccess/source/core/api/BookmarkSet.hxx b/dbaccess/source/core/api/BookmarkSet.hxx new file mode 100644 index 000000000000..36d3c90c7969 --- /dev/null +++ b/dbaccess/source/core/api/BookmarkSet.hxx @@ -0,0 +1,75 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +#ifndef DBACCESS_CORE_API_BOOKMARKSET_HXX +#define DBACCESS_CORE_API_BOOKMARKSET_HXX + +#ifndef DBACCESS_CORE_API_CACHESET_HXX +#include "CacheSet.hxx" +#endif +#ifndef _COM_SUN_STAR_SDBC_XROWUPDATE_HPP_ +#include <com/sun/star/sdbc/XRowUpdate.hpp> +#endif + +namespace dbaccess +{ + // this set is used when we have a bookmarkable set from the driver + class OBookmarkSet : public OCacheSet + { + ::com::sun::star::uno::Reference< ::com::sun::star::sdbcx::XRowLocate> m_xRowLocate; + + void updateColumn(sal_Int32 nPos,::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRowUpdate > _xParameter,const connectivity::ORowSetValue& _rValue); + public: + OBookmarkSet() + {} + ~OBookmarkSet() + { + m_xRowLocate = NULL; + } + + virtual void construct(const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XResultSet>& _xDriverSet,const ::rtl::OUString& i_sRowSetFilter); + virtual void fillValueRow(ORowSetRow& _rRow,sal_Int32 _nPosition); + // ::com::sun::star::sdbcx::XRowLocate + virtual ::com::sun::star::uno::Any SAL_CALL getBookmark() throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL moveToBookmark( const ::com::sun::star::uno::Any& bookmark ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL moveRelativeToBookmark( const ::com::sun::star::uno::Any& bookmark, sal_Int32 rows ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Int32 SAL_CALL compareBookmarks( const ::com::sun::star::uno::Any& first, const ::com::sun::star::uno::Any& second ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL hasOrderedBookmarks( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Int32 SAL_CALL hashBookmark( const ::com::sun::star::uno::Any& bookmark ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + // ::com::sun::star::sdbcx::XDeleteRows + virtual ::com::sun::star::uno::Sequence< sal_Int32 > SAL_CALL deleteRows( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& rows ,const connectivity::OSQLTable& _xTable) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + // ::com::sun::star::sdbc::XResultSetUpdate + virtual void SAL_CALL insertRow( const ORowSetRow& _rInsertRow,const connectivity::OSQLTable& _xTable ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL updateRow(const ORowSetRow& _rInsertRow,const ORowSetRow& _rOrginalRow,const connectivity::OSQLTable& _xTable ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL deleteRow(const ORowSetRow& _rInsertRow,const connectivity::OSQLTable& _xTable ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL cancelRowUpdates( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL moveToInsertRow( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL moveToCurrentRow( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + }; +} +#endif // DBACCESS_CORE_API_BOOKMARKSET_HXX + diff --git a/dbaccess/source/core/api/CIndexColumn.hxx b/dbaccess/source/core/api/CIndexColumn.hxx new file mode 100644 index 000000000000..948d472ef88c --- /dev/null +++ b/dbaccess/source/core/api/CIndexColumn.hxx @@ -0,0 +1,59 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +#ifndef DBACCESS_INDEXCOLUMN_HXX_ +#define DBACCESS_INDEXCOLUMN_HXX_ + +#ifndef _CONNECTIVITY_ADABAS_COLUMN_HXX_ +#include "adabas/BColumn.hxx" +#endif + +namespace connectivity +{ + namespace adabas + { + class OIndexColumn : public OAdabasColumn + { + protected: + sal_Bool m_IsAscending; + public: + OIndexColumn(); + OIndexColumn( sal_Bool _IsAscending, + const ::rtl::OUString& _Name, + const ::rtl::OUString& _TypeName, + const ::rtl::OUString& _DefaultValue, + sal_Int32 _IsNullable, + sal_Int32 _Precision, + sal_Int32 _Scale, + sal_Int32 _Type, + sal_Bool _IsAutoIncrement); + + virtual void construct(); + }; + } +} +#endif // DBACCESS_INDEXCOLUMN_HXX_ diff --git a/dbaccess/source/core/api/CIndexes.cxx b/dbaccess/source/core/api/CIndexes.cxx new file mode 100644 index 000000000000..3fdd9cc4de1a --- /dev/null +++ b/dbaccess/source/core/api/CIndexes.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_dbaccess.hxx" +#ifndef DBACCESS_INDEXES_HXX_ +#include "CIndexes.hxx" +#endif +#ifndef _COM_SUN_STAR_SDBC_XROW_HPP_ +#include <com/sun/star/sdbc/XRow.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_XRESULTSET_HPP_ +#include <com/sun/star/sdbc/XResultSet.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_INDEXTYPE_HPP_ +#include <com/sun/star/sdbc/IndexType.hpp> +#endif +#ifndef DBACCESS_SHARED_DBASTRINGS_HRC +#include "dbastrings.hrc" +#endif +#ifndef _CONNECTIVITY_DBTOOLS_HXX_ +#include <connectivity/dbtools.hxx> +#endif +#ifndef _COMPHELPER_EXTRACT_HXX_ +#include <comphelper/extract.hxx> +#endif +#ifndef _TOOLS_DEBUG_HXX +#include <tools/debug.hxx> +#endif + + +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 dbaccess; +using namespace cppu; + + +ObjectType OIndexes::createObject(const ::rtl::OUString& _rName) +{ + ObjectType xRet; + if ( m_xIndexes.is() && m_xIndexes->hasByName(_rName) ) + xRet.set(m_xIndexes->getByName(_rName),UNO_QUERY); + else + xRet = OIndexesHelper::createObject(_rName); + + return xRet; +} +// ------------------------------------------------------------------------- +Reference< XPropertySet > OIndexes::createDescriptor() +{ + Reference<XDataDescriptorFactory> xData( m_xIndexes,UNO_QUERY); + if(xData.is()) + return xData->createDataDescriptor(); + else + return OIndexesHelper::createDescriptor(); +} +// ------------------------------------------------------------------------- +// XAppend +ObjectType OIndexes::appendObject( const ::rtl::OUString& _rForName, const Reference< XPropertySet >& descriptor ) +{ + Reference<XAppend> xData( m_xIndexes,UNO_QUERY); + if ( !xData.is() ) + return OIndexesHelper::appendObject( _rForName, descriptor ); + + xData->appendByDescriptor(descriptor); + return createObject( _rForName ); +} +// ------------------------------------------------------------------------- +// XDrop +void OIndexes::dropObject(sal_Int32 _nPos,const ::rtl::OUString _sElementName) +{ + if ( m_xIndexes.is() ) + { + Reference<XDrop> xData( m_xIndexes,UNO_QUERY); + if ( xData.is() ) + xData->dropByName(_sElementName); + } + else + OIndexesHelper::dropObject(_nPos,_sElementName); +} +// ------------------------------------------------------------------------- +void SAL_CALL OIndexes::disposing(void) +{ + if ( m_xIndexes.is() ) + clear_NoDispose(); + else + OIndexesHelper::disposing(); +} +// ----------------------------------------------------------------------------- + + + + diff --git a/dbaccess/source/core/api/CIndexes.hxx b/dbaccess/source/core/api/CIndexes.hxx new file mode 100644 index 000000000000..c461204754be --- /dev/null +++ b/dbaccess/source/core/api/CIndexes.hxx @@ -0,0 +1,58 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +#ifndef DBACCESS_INDEXES_HXX_ +#define DBACCESS_INDEXES_HXX_ + +#ifndef CONNECTIVITY_INDEXESHELPER_HXX +#include "connectivity/TIndexes.hxx" +#endif + +namespace dbaccess +{ + class OIndexes : public connectivity::OIndexesHelper + { + ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess > m_xIndexes; + protected: + virtual connectivity::sdbcx::ObjectType createObject(const ::rtl::OUString& _rName); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > createDescriptor(); + virtual connectivity::sdbcx::ObjectType appendObject( const ::rtl::OUString& _rForName, const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& descriptor ); + virtual void dropObject(sal_Int32 _nPos,const ::rtl::OUString _sElementName); + public: + OIndexes(connectivity::OTableHelper* _pTable, + ::osl::Mutex& _rMutex, + const ::std::vector< ::rtl::OUString> &_rVector, + const ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess >& _rxIndexes + ) : connectivity::OIndexesHelper(_pTable,_rMutex,_rVector) + ,m_xIndexes(_rxIndexes) + {} + + virtual void SAL_CALL disposing(void); + }; +} + +#endif // DBACCESS_INDEXES_HXX_ diff --git a/dbaccess/source/core/api/CRowSetColumn.cxx b/dbaccess/source/core/api/CRowSetColumn.cxx new file mode 100644 index 000000000000..12a7d16e8716 --- /dev/null +++ b/dbaccess/source/core/api/CRowSetColumn.cxx @@ -0,0 +1,111 @@ +/************************************************************************* + * + * 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_dbaccess.hxx" + +#include "dbastrings.hrc" +#include "apitools.hxx" +#include "CRowSetColumn.hxx" + +#include <com/sun/star/sdb/XColumn.hpp> +#include <com/sun/star/beans/PropertyAttribute.hpp> + +#include <comphelper/types.hxx> +#include <cppuhelper/typeprovider.hxx> + +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::sdb; +using namespace ::com::sun::star::beans; + +//.............................................................................. +namespace dbaccess +{ +//.............................................................................. + +//------------------------------------------------------------------------------ +ORowSetColumn::ORowSetColumn( const Reference < XResultSetMetaData >& _xMetaData, const Reference < XRow >& _xRow, sal_Int32 _nPos, + const Reference< XDatabaseMetaData >& _rxDBMeta, const ::rtl::OUString& _rDescription, const ::rtl::OUString& i_sLabel,ORowSetCacheIterator& _rColumnValue ) + :ORowSetDataColumn( _xMetaData, _xRow, NULL, _nPos, _rxDBMeta, _rDescription, i_sLabel,_rColumnValue ) +{ +} + +//------------------------------------------------------------------------------ +::cppu::IPropertyArrayHelper* ORowSetColumn::createArrayHelper( ) const +{ + const sal_Int32 nDerivedProperties = 21; + Sequence< Property> aDerivedProperties( nDerivedProperties ); + Property* pDesc = aDerivedProperties.getArray(); + sal_Int32 nPos = 0; + + DECL_PROP1( CATALOGNAME, ::rtl::OUString, READONLY ); + DECL_PROP1( DISPLAYSIZE, sal_Int32, READONLY ); + DECL_PROP1_BOOL( ISAUTOINCREMENT, READONLY ); + DECL_PROP1_BOOL( ISCASESENSITIVE, READONLY ); + DECL_PROP1_BOOL( ISCURRENCY, READONLY ); + DECL_PROP1_BOOL( ISDEFINITELYWRITABLE, READONLY ); + DECL_PROP1( ISNULLABLE, sal_Int32, READONLY ); + DECL_PROP1_BOOL( ISREADONLY, BOUND ); + DECL_PROP1_BOOL( ISROWVERSION, READONLY ); + DECL_PROP1_BOOL( ISSEARCHABLE, READONLY ); + DECL_PROP1_BOOL( ISSIGNED, READONLY ); + DECL_PROP1_BOOL( ISWRITABLE, READONLY ); + DECL_PROP1( LABEL, ::rtl::OUString, READONLY ); + DECL_PROP1( PRECISION, sal_Int32, READONLY ); + DECL_PROP1( SCALE, sal_Int32, READONLY ); + DECL_PROP1( SCHEMANAME, ::rtl::OUString, READONLY ); + DECL_PROP1( SERVICENAME, ::rtl::OUString, READONLY ); + DECL_PROP1( TABLENAME, ::rtl::OUString, READONLY ); + DECL_PROP1( TYPE, sal_Int32, READONLY ); + DECL_PROP1( TYPENAME, ::rtl::OUString, READONLY ); + DECL_PROP2( VALUE, Any, READONLY, BOUND ); + OSL_ENSURE( nPos == nDerivedProperties, "ORowSetColumn::createArrayHelper: inconsistency!" ); + + Sequence< Property > aRegisteredProperties; + describeProperties( aRegisteredProperties ); + + return new ::cppu::OPropertyArrayHelper( ::comphelper::concatSequences( aDerivedProperties, aRegisteredProperties ), sal_False ); +} + +//------------------------------------------------------------------------------ +::cppu::IPropertyArrayHelper& ORowSetColumn::getInfoHelper() +{ + return *static_cast< ::comphelper::OPropertyArrayUsageHelper< ORowSetColumn >* >(this)->getArrayHelper(); +} + +//------------------------------------------------------------------------------ +void SAL_CALL ORowSetColumn::setFastPropertyValue_NoBroadcast(sal_Int32 nHandle,const Any& rValue )throw (Exception) +{ + OSL_ENSURE( nHandle != PROPERTY_ID_VALUE, "ORowSetColumn::setFastPropertyValue_NoBroadcast: hmm? This property is marked as READONLY!" ); + if ( nHandle != PROPERTY_ID_VALUE ) + ORowSetDataColumn::setFastPropertyValue_NoBroadcast( nHandle, rValue ); +} + +//.............................................................................. +} // namespace dbaccess +//.............................................................................. diff --git a/dbaccess/source/core/api/CRowSetColumn.hxx b/dbaccess/source/core/api/CRowSetColumn.hxx new file mode 100644 index 000000000000..043837f44589 --- /dev/null +++ b/dbaccess/source/core/api/CRowSetColumn.hxx @@ -0,0 +1,66 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ +#ifndef DBACCESS_CORE_API_CROWSETCOLUMN_HXX +#define DBACCESS_CORE_API_CROWSETCOLUMN_HXX + +#ifndef DBACCESS_CORE_API_ROWSETROW_HXX +#include "RowSetRow.hxx" +#endif +#ifndef _CONNECTIVITY_COMMONTOOLS_HXX_ +#include <connectivity/CommonTools.hxx> +#endif +#ifndef _COMPHELPER_PROPERTY_ARRAY_HELPER_HXX_ +#include <comphelper/proparrhlp.hxx> +#endif +#ifndef DBACCESS_CORE_API_CROWSETDATACOLUMN_HXX +#include "CRowSetDataColumn.hxx" +#endif + +namespace dbaccess +{ + class ORowSetColumn; + class ORowSetColumn :public ORowSetDataColumn + ,public ::comphelper::OPropertyArrayUsageHelper< ORowSetColumn > + + { + public: + ORowSetColumn( const ::com::sun::star::uno::Reference < ::com::sun::star::sdbc::XResultSetMetaData >& _xMetaData, + const ::com::sun::star::uno::Reference < ::com::sun::star::sdbc::XRow >& _xRow, + sal_Int32 _nPos, + const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XDatabaseMetaData >& _rxDBMeta, + const ::rtl::OUString& _rDescription, + const ::rtl::OUString& i_sLabel, + ORowSetCacheIterator& _rColumnValue); + + virtual ::cppu::IPropertyArrayHelper* createArrayHelper( ) const; + virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper(); + virtual void SAL_CALL setFastPropertyValue_NoBroadcast( sal_Int32 nHandle,const ::com::sun::star::uno::Any& rValue )throw (::com::sun::star::uno::Exception ); + }; + +} + +#endif // DBACCESS_CORE_API_CROWSETCOLUMN_HXX diff --git a/dbaccess/source/core/api/CRowSetDataColumn.cxx b/dbaccess/source/core/api/CRowSetDataColumn.cxx new file mode 100644 index 000000000000..9bdcda88c93d --- /dev/null +++ b/dbaccess/source/core/api/CRowSetDataColumn.cxx @@ -0,0 +1,292 @@ +/************************************************************************* + * + * 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_dbaccess.hxx" + +#ifndef _DBACORE_DATACOLUMN_HXX_ +#include "CRowSetDataColumn.hxx" +#endif +#ifndef DBACCESS_SHARED_DBASTRINGS_HRC +#include "dbastrings.hrc" +#endif +#ifndef _DBASHARED_APITOOLS_HXX_ +#include "apitools.hxx" +#endif +#ifndef _COMPHELPER_TYPES_HXX_ +#include <comphelper/types.hxx> +#endif +#ifndef _CPPUHELPER_TYPEPROVIDER_HXX_ +#include <cppuhelper/typeprovider.hxx> +#endif +#ifndef _COM_SUN_STAR_BEANS_PROPERTYATTRIBUTE_HPP_ +#include <com/sun/star/beans/PropertyAttribute.hpp> +#endif +#ifndef _TOOLS_DEBUG_HXX +#include <tools/debug.hxx> +#endif + +using namespace dbaccess; +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; +using namespace ::com::sun::star::util; +using namespace cppu; +using namespace osl; + +DBG_NAME(ORowSetDataColumn) +// ------------------------------------------------------------------------- +ORowSetDataColumn::ORowSetDataColumn( const Reference < XResultSetMetaData >& _xMetaData, + const Reference < XRow >& _xRow, + const Reference < XRowUpdate >& _xRowUpdate, + sal_Int32 _nPos, + const Reference< XDatabaseMetaData >& _rxDBMeta, + const ::rtl::OUString& _rDescription, + const ::rtl::OUString& i_sLabel, + const ORowSetCacheIterator& _rColumnValue) + :ODataColumn(_xMetaData,_xRow,_xRowUpdate,_nPos,_rxDBMeta) + ,m_aColumnValue(_rColumnValue) + ,m_sLabel(i_sLabel) + ,m_aDescription(_rDescription) +{ + DBG_CTOR(ORowSetDataColumn,NULL); + OColumnSettings::registerProperties( *this ); + registerProperty( PROPERTY_DESCRIPTION, PROPERTY_ID_DESCRIPTION, PropertyAttribute::READONLY, &m_aDescription, ::getCppuType( &m_aDescription ) ); +} +// ------------------------------------------------------------------------- +ORowSetDataColumn::~ORowSetDataColumn() +{ + DBG_DTOR(ORowSetDataColumn,NULL); +} +// ------------------------------------------------------------------------- +// comphelper::OPropertyArrayUsageHelper +//------------------------------------------------------------------------------ +::cppu::IPropertyArrayHelper* ORowSetDataColumn::createArrayHelper( ) const +{ + const sal_Int32 nDerivedProperties = 21; + Sequence< Property> aDerivedProperties( nDerivedProperties ); + Property* pDesc = aDerivedProperties.getArray(); + sal_Int32 nPos = 0; + + DECL_PROP1( CATALOGNAME, ::rtl::OUString, READONLY ); + DECL_PROP1( DISPLAYSIZE, sal_Int32, READONLY ); + DECL_PROP1_BOOL( ISAUTOINCREMENT, READONLY ); + DECL_PROP1_BOOL( ISCASESENSITIVE, READONLY ); + DECL_PROP1_BOOL( ISCURRENCY, READONLY ); + DECL_PROP1_BOOL( ISDEFINITELYWRITABLE, READONLY ); + DECL_PROP1( ISNULLABLE, sal_Int32, READONLY ); + DECL_PROP1_BOOL( ISREADONLY, BOUND ); + DECL_PROP1_BOOL( ISROWVERSION, READONLY ); + DECL_PROP1_BOOL( ISSEARCHABLE, READONLY ); + DECL_PROP1_BOOL( ISSIGNED, READONLY ); + DECL_PROP1_BOOL( ISWRITABLE, READONLY ); + DECL_PROP1( LABEL, ::rtl::OUString, READONLY ); + DECL_PROP1( PRECISION, sal_Int32, READONLY ); + DECL_PROP1( SCALE, sal_Int32, READONLY ); + DECL_PROP1( SCHEMANAME, ::rtl::OUString, READONLY ); + DECL_PROP1( SERVICENAME, ::rtl::OUString, READONLY ); + DECL_PROP1( TABLENAME, ::rtl::OUString, READONLY ); + DECL_PROP1( TYPE, sal_Int32, READONLY ); + DECL_PROP1( TYPENAME, ::rtl::OUString, READONLY ); + DECL_PROP1( VALUE, Any, BOUND ); + OSL_ENSURE( nPos == nDerivedProperties, "ORowSetDataColumn::createArrayHelper: inconsistency!" ); + + Sequence< Property > aRegisteredProperties; + describeProperties( aRegisteredProperties ); + + return new ::cppu::OPropertyArrayHelper( ::comphelper::concatSequences( aDerivedProperties, aRegisteredProperties ), sal_False ); +} + +// cppu::OPropertySetHelper +//------------------------------------------------------------------------------ +::cppu::IPropertyArrayHelper& ORowSetDataColumn::getInfoHelper() +{ + return *static_cast< ::comphelper::OPropertyArrayUsageHelper< ORowSetDataColumn >* >(this)->getArrayHelper(); +} +// ------------------------------------------------------------------------- +void SAL_CALL ORowSetDataColumn::getFastPropertyValue( Any& rValue, sal_Int32 nHandle ) const +{ + if ( PROPERTY_ID_VALUE == nHandle ) + { + if ( !m_aColumnValue.isNull() && m_aColumnValue->isValid() ) + { + ::osl::Mutex* pMutex = m_aColumnValue.getMutex(); + ::osl::MutexGuard aGuard( *pMutex ); +#if OSL_DEBUG_LEVEL > 0 + ORowSetRow aRow = *m_aColumnValue; +#endif + OSL_ENSURE((sal_Int32)aRow->get().size() > m_nPos,"Pos is greater than size of vector"); + rValue = ((*m_aColumnValue)->get())[m_nPos].makeAny(); + } + } + else if ( PROPERTY_ID_LABEL == nHandle && m_sLabel.getLength() ) + rValue <<= m_sLabel; + else + ODataColumn::getFastPropertyValue( rValue, nHandle ); +} + +// ------------------------------------------------------------------------- +void SAL_CALL ORowSetDataColumn::setFastPropertyValue_NoBroadcast(sal_Int32 nHandle,const Any& rValue )throw (Exception) +{ + switch( nHandle ) + { + case PROPERTY_ID_VALUE: + updateObject(rValue); + break; + case PROPERTY_ID_ISREADONLY: + { + sal_Bool bVal = sal_False; + rValue >>= bVal; + m_isReadOnly.reset(bVal); + } + break; + default: + ODataColumn::setFastPropertyValue_NoBroadcast( nHandle,rValue ); + break; + } +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL ORowSetDataColumn::convertFastPropertyValue( Any & rConvertedValue, + Any & rOldValue, + sal_Int32 nHandle, + const Any& rValue ) throw (IllegalArgumentException) +{ + sal_Bool bModified = sal_False; + switch( nHandle ) + { + case PROPERTY_ID_VALUE: + { + rConvertedValue = rValue; + getFastPropertyValue(rOldValue, PROPERTY_ID_VALUE); + bModified = rConvertedValue != rOldValue; + } + break; + case PROPERTY_ID_ISREADONLY: + { + rConvertedValue = rValue; + getFastPropertyValue(rOldValue, PROPERTY_ID_ISREADONLY); + bModified = rConvertedValue != rOldValue; + } + break; + default: + bModified = ODataColumn::convertFastPropertyValue(rConvertedValue, rOldValue, nHandle, rValue); + break; + } + + return bModified; +} +//-------------------------------------------------------------------------- +Sequence< sal_Int8 > ORowSetDataColumn::getImplementationId() throw (RuntimeException) +{ + static OImplementationId * pId = 0; + if (! pId) + { + MutexGuard aGuard( Mutex::getGlobalMutex() ); + if (! pId) + { + static OImplementationId aId; + pId = &aId; + } + } + return pId->getImplementationId(); +} +// ------------------------------------------------------------------------- +void ORowSetDataColumn::fireValueChange(const ORowSetValue& _rOldValue) +{ + if ( !m_aColumnValue.isNull() && m_aColumnValue->isValid() && (!(((*m_aColumnValue)->get())[m_nPos] == _rOldValue)) ) + { + sal_Int32 nHandle = PROPERTY_ID_VALUE; + m_aOldValue = _rOldValue.makeAny(); + Any aNew = ((*m_aColumnValue)->get())[m_nPos].makeAny(); + + fire(&nHandle, &aNew, &m_aOldValue, 1, sal_False ); + } + else if ( !m_aColumnValue.isNull() && !_rOldValue.isNull() ) + { + sal_Int32 nHandle = PROPERTY_ID_VALUE; + m_aOldValue = _rOldValue.makeAny(); + Any aNew; + + fire(&nHandle, &aNew, &m_aOldValue, 1, sal_False ); + } +} +// ----------------------------------------------------------------------------- +DBG_NAME(ORowSetDataColumns ) +ORowSetDataColumns::ORowSetDataColumns( + sal_Bool _bCase, + const ::vos::ORef< ::connectivity::OSQLColumns>& _rColumns, + ::cppu::OWeakObject& _rParent, + ::osl::Mutex& _rMutex, + const ::std::vector< ::rtl::OUString> &_rVector + ) : connectivity::sdbcx::OCollection(_rParent,_bCase,_rMutex,_rVector) + ,m_aColumns(_rColumns) +{ + DBG_CTOR(ORowSetDataColumns ,NULL); +} +// ----------------------------------------------------------------------------- +ORowSetDataColumns::~ORowSetDataColumns() +{ + DBG_DTOR(ORowSetDataColumns ,NULL); +} +// ----------------------------------------------------------------------------- +sdbcx::ObjectType ORowSetDataColumns::createObject(const ::rtl::OUString& _rName) +{ + connectivity::sdbcx::ObjectType xNamed; + + ::comphelper::UStringMixEqual aCase(isCaseSensitive()); + ::connectivity::OSQLColumns::Vector::const_iterator first = ::connectivity::find(m_aColumns->get().begin(),m_aColumns->get().end(),_rName,aCase); + if(first != m_aColumns->get().end()) + xNamed.set(*first,UNO_QUERY); + + return xNamed; +} +// ----------------------------------------------------------------------------- +void SAL_CALL ORowSetDataColumns::disposing(void) +{ + // clear_NoDispose(); + ORowSetDataColumns_BASE::disposing(); + m_aColumns = NULL; + // m_aColumns.clear(); +} +// ----------------------------------------------------------------------------- +void ORowSetDataColumns::assign(const ::vos::ORef< ::connectivity::OSQLColumns>& _rColumns,const ::std::vector< ::rtl::OUString> &_rVector) +{ + m_aColumns = _rColumns; + reFill(_rVector); +} +// ----------------------------------------------------------------------------- +void ORowSetDataColumns::impl_refresh() throw(::com::sun::star::uno::RuntimeException) +{ +} +// ----------------------------------------------------------------------------- + + diff --git a/dbaccess/source/core/api/CRowSetDataColumn.hxx b/dbaccess/source/core/api/CRowSetDataColumn.hxx new file mode 100644 index 000000000000..e5009d4d6f7c --- /dev/null +++ b/dbaccess/source/core/api/CRowSetDataColumn.hxx @@ -0,0 +1,113 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ +#ifndef DBACCESS_CORE_API_CROWSETDATACOLUMN_HXX +#define DBACCESS_CORE_API_CROWSETDATACOLUMN_HXX + +#include "datacolumn.hxx" +#include "RowSetRow.hxx" +#include "RowSetCacheIterator.hxx" +#include "columnsettings.hxx" + +#include <connectivity/CommonTools.hxx> +#include <comphelper/proparrhlp.hxx> + +namespace dbaccess +{ + class ORowSetDataColumn; + typedef ::comphelper::OPropertyArrayUsageHelper<ORowSetDataColumn> ORowSetDataColumn_PROP; + + class ORowSetDataColumn : public ODataColumn, + public OColumnSettings, + public ORowSetDataColumn_PROP + { + protected: + ORowSetCacheIterator m_aColumnValue; + ::com::sun::star::uno::Any m_aOldValue; + + ::rtl::OUString m_sLabel; + ::rtl::OUString m_aDescription; // description + ORowSetBase* m_pRowSet; + + virtual ~ORowSetDataColumn(); + public: + ORowSetDataColumn(const ::com::sun::star::uno::Reference < ::com::sun::star::sdbc::XResultSetMetaData >& _xMetaData, + const ::com::sun::star::uno::Reference < ::com::sun::star::sdbc::XRow >& _xRow, + const ::com::sun::star::uno::Reference < ::com::sun::star::sdbc::XRowUpdate >& _xRowUpdate, + sal_Int32 _nPos, + const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XDatabaseMetaData >& _rxDBMeta, + const ::rtl::OUString& _rDescription, + const ::rtl::OUString& i_sLabel, + const ORowSetCacheIterator& _rColumnValue); + + + // com::sun::star::lang::XTypeProvider + virtual ::com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId() throw (::com::sun::star::uno::RuntimeException); + // comphelper::OPropertyArrayUsageHelper + virtual ::cppu::IPropertyArrayHelper* createArrayHelper( ) const; + + // cppu::OPropertySetHelper + virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper(); + + virtual sal_Bool SAL_CALL convertFastPropertyValue( ::com::sun::star::uno::Any & rConvertedValue, + ::com::sun::star::uno::Any & rOldValue, + sal_Int32 nHandle, + const ::com::sun::star::uno::Any& rValue ) throw (::com::sun::star::lang::IllegalArgumentException); + virtual void SAL_CALL getFastPropertyValue( ::com::sun::star::uno::Any& rValue, sal_Int32 nHandle ) const; + virtual void SAL_CALL setFastPropertyValue_NoBroadcast(sal_Int32 nHandle,const ::com::sun::star::uno::Any& rValue )throw (::com::sun::star::uno::Exception); + + virtual void fireValueChange(const ::connectivity::ORowSetValue& _rOldValue); + protected: + using ODataColumn::getFastPropertyValue; + }; + // ------------------------------------------------------------------------- +// typedef connectivity::ORefVector< ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet> > +// ORowSetDataColumns_COLLECTION; + + typedef connectivity::sdbcx::OCollection ORowSetDataColumns_BASE; + class ORowSetDataColumns : public ORowSetDataColumns_BASE + { + ::vos::ORef< ::connectivity::OSQLColumns> m_aColumns; + protected: + virtual connectivity::sdbcx::ObjectType createObject(const ::rtl::OUString& _rName); + virtual void impl_refresh() throw(::com::sun::star::uno::RuntimeException); + public: + ORowSetDataColumns( + sal_Bool _bCase, + const ::vos::ORef< ::connectivity::OSQLColumns>& _rColumns, + ::cppu::OWeakObject& _rParent, + ::osl::Mutex& _rMutex, + const ::std::vector< ::rtl::OUString> &_rVector + ); + virtual ~ORowSetDataColumns(); + // only the name is identical to ::cppu::OComponentHelper + virtual void SAL_CALL disposing(void); + void assign(const ::vos::ORef< ::connectivity::OSQLColumns>& _rColumns,const ::std::vector< ::rtl::OUString> &_rVector); + }; +} + +#endif + diff --git a/dbaccess/source/core/api/CacheSet.cxx b/dbaccess/source/core/api/CacheSet.cxx new file mode 100644 index 000000000000..dd64e835adb4 --- /dev/null +++ b/dbaccess/source/core/api/CacheSet.cxx @@ -0,0 +1,753 @@ +/************************************************************************* + * + * 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_dbaccess.hxx" +#ifndef DBACCESS_CORE_API_CACHESET_HXX +#include "CacheSet.hxx" +#endif +#ifndef _DBA_CORE_RESOURCE_HXX_ +#include "core_resource.hxx" +#endif +#ifndef _DBA_CORE_RESOURCE_HRC_ +#include "core_resource.hrc" +#endif +#ifndef _COM_SUN_STAR_SDBCX_COMPAREBOOKMARK_HPP_ +#include <com/sun/star/sdbcx/CompareBookmark.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_XRESULTSETMETADATASUPPLIER_HPP_ +#include <com/sun/star/sdbc/XResultSetMetaDataSupplier.hpp> +#endif +#ifndef _COM_SUN_STAR_BEANS_XPROPERTYSET_HPP_ +#include <com/sun/star/beans/XPropertySet.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_XDATABASEMETADATA_HPP_ +#include <com/sun/star/sdbc/XDatabaseMetaData.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_XPREPAREDSTATEMENT_HPP_ +#include <com/sun/star/sdbc/XPreparedStatement.hpp> +#endif +#include <com/sun/star/sdbc/ColumnValue.hpp> +#ifndef _COM_SUN_STAR_SDBC_XPARAMETERS_HPP_ +#include <com/sun/star/sdbc/XParameters.hpp> +#endif +#ifndef DBACCESS_SHARED_DBASTRINGS_HRC +#include "dbastrings.hrc" +#endif +#ifndef _COM_SUN_STAR_SDBCX_XKEYSSUPPLIER_HPP_ +#include <com/sun/star/sdbcx/XKeysSupplier.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBCX_XINDEXESSUPPLIER_HPP_ +#include <com/sun/star/sdbcx/XIndexesSupplier.hpp> +#endif + +#include <limits> + +#ifndef _CONNECTIVITY_DBTOOLS_HXX_ +#include <connectivity/dbtools.hxx> +#endif +#ifndef _COM_SUN_STAR_SDBCX_KEYTYPE_HPP_ +#include <com/sun/star/sdbcx/KeyType.hpp> +#endif +#ifndef _COMPHELPER_EXTRACT_HXX_ +#include <comphelper/extract.hxx> +#endif +#ifndef _COM_SUN_STAR_IO_XINPUTSTREAM_HPP_ +#include <com/sun/star/io/XInputStream.hpp> +#endif +#ifndef _COMPHELPER_TYPES_HXX_ +#include <comphelper/types.hxx> +#endif +#ifndef _TOOLS_DEBUG_HXX +#include <tools/debug.hxx> +#endif +#include <rtl/ustrbuf.hxx> +#include <rtl/logfile.hxx> + +using namespace comphelper; + +using namespace dbaccess; +using namespace dbtools; +using namespace connectivity; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::sdbc; +// using namespace ::com::sun::star::sdb; +using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::io; +// using namespace ::cppu; +using namespace ::osl; + +DBG_NAME(OCacheSet) +// ------------------------------------------------------------------------- +OCacheSet::OCacheSet() + :m_bInserted(sal_False) + ,m_bUpdated(sal_False) + ,m_bDeleted(sal_False) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCacheSet::OCacheSet" ); + DBG_CTOR(OCacheSet,NULL); + +} +// ------------------------------------------------------------------------- +::rtl::OUString OCacheSet::getIdentifierQuoteString() const +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCacheSet::getIdentifierQuoteString" ); + ::rtl::OUString sQuote; + Reference<XDatabaseMetaData> xMeta; + if ( m_xConnection.is() && (xMeta = m_xConnection->getMetaData()).is() ) + sQuote = xMeta->getIdentifierQuoteString(); + return sQuote; +} +// ------------------------------------------------------------------------- +void OCacheSet::construct( const Reference< XResultSet>& _xDriverSet,const ::rtl::OUString& /*i_sRowSetFilter*/) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCacheSet::construct" ); + OSL_ENSURE(_xDriverSet.is(),"Invalid resultSet"); + if(_xDriverSet.is()) + { + m_xDriverSet = _xDriverSet; + m_xDriverRow.set(_xDriverSet,UNO_QUERY); + m_xSetMetaData = Reference<XResultSetMetaDataSupplier>(_xDriverSet,UNO_QUERY)->getMetaData(); + if ( m_xSetMetaData.is() ) + { + const sal_Int32 nCount = m_xSetMetaData->getColumnCount(); + m_aNullable.realloc(nCount); + m_aSignedFlags.realloc(nCount); + m_aColumnTypes.realloc(nCount); + sal_Bool* pNullableIter = m_aNullable.getArray(); + sal_Bool* pSignedIter = m_aSignedFlags.getArray(); + sal_Int32* pColumnIter = m_aColumnTypes.getArray(); + for (sal_Int32 i=1; i <= nCount; ++i,++pSignedIter,++pColumnIter,++pNullableIter) + { + *pNullableIter = m_xSetMetaData->isNullable(i) != ColumnValue::NO_NULLS; + *pSignedIter = m_xSetMetaData->isSigned(i); + *pColumnIter = m_xSetMetaData->getColumnType(i); + } + } + Reference< XStatement> xStmt(m_xDriverSet->getStatement(),UNO_QUERY); + if(xStmt.is()) + m_xConnection = xStmt->getConnection(); + else + { + Reference< XPreparedStatement> xPrepStmt(m_xDriverSet->getStatement(),UNO_QUERY); + if ( xPrepStmt.is() ) + m_xConnection = xPrepStmt->getConnection(); + } + } +} +// ------------------------------------------------------------------------- +OCacheSet::~OCacheSet() +{ + try + { + m_xDriverSet = NULL; + m_xDriverRow = NULL; + m_xSetMetaData = NULL; + m_xConnection = NULL; + } + catch(Exception&) + { + OSL_ENSURE(0,"Exception occured"); + } + catch(...) + { + OSL_ENSURE(0,"Unknown Exception occured"); + } + + DBG_DTOR(OCacheSet,NULL); +} +// ----------------------------------------------------------------------------- +void OCacheSet::fillTableName(const Reference<XPropertySet>& _xTable) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCacheSet::fillTableName" ); + OSL_ENSURE(_xTable.is(),"OCacheSet::fillTableName: PropertySet is empty!"); + if(!m_aComposedTableName.getLength() && _xTable.is() ) + { + Reference<XDatabaseMetaData> xMeta(m_xConnection->getMetaData()); + m_aComposedTableName = composeTableName(xMeta + ,comphelper::getString(_xTable->getPropertyValue(PROPERTY_CATALOGNAME)) + ,comphelper::getString(_xTable->getPropertyValue(PROPERTY_SCHEMANAME)) + ,comphelper::getString(_xTable->getPropertyValue(PROPERTY_NAME)) + ,sal_True + ,::dbtools::eInDataManipulation); + } +} +// ------------------------------------------------------------------------- +void SAL_CALL OCacheSet::insertRow( const ORowSetRow& _rInsertRow,const connectivity::OSQLTable& _xTable ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCacheSet::insertRow" ); + ::rtl::OUStringBuffer aSql(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("INSERT INTO "))); + Reference<XPropertySet> xSet(_xTable,UNO_QUERY); + fillTableName(xSet); + + aSql.append(m_aComposedTableName); + aSql.append(::rtl::OUString::createFromAscii(" ( ")); + // set values and column names + ::rtl::OUStringBuffer aValues = ::rtl::OUString::createFromAscii(" VALUES ( "); + static ::rtl::OUString aPara(RTL_CONSTASCII_USTRINGPARAM("?,")); + ::rtl::OUString aQuote = getIdentifierQuoteString(); + static ::rtl::OUString aComma(RTL_CONSTASCII_USTRINGPARAM(",")); + sal_Int32 i = 1; + ORowVector< ORowSetValue >::Vector::const_iterator aIter = _rInsertRow->get().begin()+1; + connectivity::ORowVector< ORowSetValue > ::Vector::iterator aEnd = _rInsertRow->get().end(); + for(; aIter != aEnd;++aIter) + { + aSql.append(::dbtools::quoteName( aQuote,m_xSetMetaData->getColumnName(i++))); + aSql.append(aComma); + aValues.append(aPara); + } + + aSql.setCharAt(aSql.getLength()-1,')'); + aValues.setCharAt(aValues.getLength()-1,')'); + + aSql.append(aValues.makeStringAndClear()); + // now create end execute the prepared statement + { + Reference< XPreparedStatement > xPrep(m_xConnection->prepareStatement(aSql.makeStringAndClear())); + Reference< XParameters > xParameter(xPrep,UNO_QUERY); + i = 1; + for(aIter = _rInsertRow->get().begin()+1; aIter != aEnd;++aIter,++i) + { + if(aIter->isNull()) + xParameter->setNull(i,aIter->getTypeKind()); + else + setParameter(i,xParameter,*aIter,m_xSetMetaData->getColumnType(i),m_xSetMetaData->getScale(i)); + } + + m_bInserted = xPrep->executeUpdate() > 0; + } + +// ::rtl::OUString aCountSql = ::rtl::OUString::createFromAscii("SELECT COUNT(*) FROM "); +// aCountSql += m_aComposedTableName; +// try +// { +// Reference< XStatement > xStmt(m_xConnection->createStatement()); +// Reference<XResultSet> xRes(xStmt->executeQuery(aCountSql)); +// if(xRes.is() && xRes->next()) +// { +// Reference<XRow> xRow(xRes,UNO_QUERY); +// } +// } +// catch(SQLException&) +// { +// } + + // TODO set the bookmark in the insert row +} +// ------------------------------------------------------------------------- +void OCacheSet::fillParameters( const ORowSetRow& _rRow + ,const connectivity::OSQLTable& _xTable + ,::rtl::OUStringBuffer& _sCondition + ,::rtl::OUStringBuffer& _sParameter + ,::std::list< sal_Int32>& _rOrgValues) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCacheSet::fillParameters" ); + // use keys and indexes for excat postioning + // first the keys + Reference<XPropertySet> xSet(_xTable,UNO_QUERY); + const Reference<XNameAccess> xPrimaryKeyColumns = getPrimaryKeyColumns_throw(xSet); + // second the indexes + Reference<XIndexesSupplier> xIndexSup(_xTable,UNO_QUERY); + Reference<XIndexAccess> xIndexes; + if(xIndexSup.is()) + xIndexes.set(xIndexSup->getIndexes(),UNO_QUERY); + + // Reference<XColumnsSupplier> + Reference<XPropertySet> xIndexColsSup; + Reference<XNameAccess> xIndexColumns; + ::std::vector< Reference<XNameAccess> > aAllIndexColumns; + if(xIndexes.is()) + { + for(sal_Int32 j=0;j<xIndexes->getCount();++j) + { + xIndexColsSup.set(xIndexes->getByIndex(j),UNO_QUERY); + if( xIndexColsSup.is() + && comphelper::getBOOL(xIndexColsSup->getPropertyValue(PROPERTY_ISUNIQUE)) + && !comphelper::getBOOL(xIndexColsSup->getPropertyValue(PROPERTY_ISPRIMARYKEYINDEX)) + ) + aAllIndexColumns.push_back(Reference<XColumnsSupplier>(xIndexColsSup,UNO_QUERY)->getColumns()); + } + } + + ::rtl::OUString aColumnName; + + static ::rtl::OUString aPara = ::rtl::OUString::createFromAscii("?,"); + static ::rtl::OUString aAnd = ::rtl::OUString::createFromAscii(" AND "); + + ::rtl::OUString aQuote = getIdentifierQuoteString(); + + sal_Int32 nCheckCount = 1; // index for the orginal values + sal_Int32 i = 1; + + ::rtl::OUString sIsNull(RTL_CONSTASCII_USTRINGPARAM(" IS NULL")); + ::rtl::OUString sParam(RTL_CONSTASCII_USTRINGPARAM(" = ?")); + ORowVector< ORowSetValue >::Vector::const_iterator aIter = _rRow->get().begin()+1; + ORowVector< ORowSetValue >::Vector::const_iterator aEnd = _rRow->get().end()+1; + for(; aIter != aEnd;++aIter,++nCheckCount,++i) + { + aColumnName = m_xSetMetaData->getColumnName(i); + if(xPrimaryKeyColumns.is() && xPrimaryKeyColumns->hasByName(aColumnName)) + { + _sCondition.append(::dbtools::quoteName( aQuote,aColumnName)); + if(aIter->isNull()) + _sCondition.append(sIsNull); + else + _sCondition.append(sParam); + _sCondition.append(aAnd); + _rOrgValues.push_back(nCheckCount); + + } // if(xPrimaryKeyColumns.is() && xPrimaryKeyColumns->hasByName(aColumnName)) + ::std::vector< Reference<XNameAccess> >::const_iterator aIndexEnd = aAllIndexColumns.end(); + for( ::std::vector< Reference<XNameAccess> >::const_iterator aIndexIter = aAllIndexColumns.begin(); + aIndexIter != aIndexEnd;++aIndexIter) + { + if((*aIndexIter)->hasByName(aColumnName)) + { + _sCondition.append(::dbtools::quoteName( aQuote,aColumnName)); + if(aIter->isNull()) + _sCondition.append(sIsNull); + else + _sCondition.append(sParam); + _sCondition.append(aAnd); + _rOrgValues.push_back(nCheckCount); + break; + } + } + if(aIter->isModified()) + { + _sParameter.append(::dbtools::quoteName( aQuote,aColumnName)); + _sParameter.append(aPara); + } + } +} +// ------------------------------------------------------------------------- +void SAL_CALL OCacheSet::updateRow(const ORowSetRow& _rInsertRow ,const ORowSetRow& _rOrginalRow,const connectivity::OSQLTable& _xTable ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCacheSet::updateRow" ); + Reference<XPropertySet> xSet(_xTable,UNO_QUERY); + fillTableName(xSet); + + ::rtl::OUStringBuffer aSql = ::rtl::OUString::createFromAscii("UPDATE "); + aSql.append(m_aComposedTableName); + aSql.append(::rtl::OUString::createFromAscii(" SET ")); + // list all cloumns that should be set + + ::rtl::OUStringBuffer aCondition; + ::std::list< sal_Int32> aOrgValues; + fillParameters(_rInsertRow,_xTable,aCondition,aSql,aOrgValues); + aSql.setCharAt(aSql.getLength()-1,' '); + if ( aCondition.getLength() ) + { + aCondition.setLength(aCondition.getLength()-5); + + aSql.append(::rtl::OUString::createFromAscii(" WHERE ")); + aSql.append(aCondition.makeStringAndClear()); + } + else + ::dbtools::throwSQLException( + DBACORE_RESSTRING( RID_STR_NO_UPDATE_MISSING_CONDITION ), SQL_GENERAL_ERROR, *this ); + + // now create end execute the prepared statement + Reference< XPreparedStatement > xPrep(m_xConnection->prepareStatement(aSql.makeStringAndClear())); + Reference< XParameters > xParameter(xPrep,UNO_QUERY); + sal_Int32 i = 1; + connectivity::ORowVector< ORowSetValue > ::Vector::iterator aEnd = _rInsertRow->get().end(); + for(ORowVector< ORowSetValue >::Vector::const_iterator aIter = _rInsertRow->get().begin()+1; aIter != aEnd;++aIter) + { + if(aIter->isModified()) + { + setParameter(i,xParameter,*aIter,m_xSetMetaData->getColumnType(i),m_xSetMetaData->getScale(i)); + ++i; + } + } // for(ORowVector< ORowSetValue >::Vector::const_iterator aIter = _rInsertRow->get().begin()+1; aIter != aEnd;++aIter) + ::std::list< sal_Int32>::const_iterator aOrgValueEnd = aOrgValues.end(); + for(::std::list< sal_Int32>::const_iterator aOrgValue = aOrgValues.begin(); aOrgValue != aOrgValueEnd;++aOrgValue,++i) + { + setParameter(i,xParameter,(_rOrginalRow->get())[*aOrgValue],m_xSetMetaData->getColumnType(i),m_xSetMetaData->getScale(i)); + } + + m_bUpdated = xPrep->executeUpdate() > 0; +} +// ------------------------------------------------------------------------- +void SAL_CALL OCacheSet::deleteRow(const ORowSetRow& _rDeleteRow ,const connectivity::OSQLTable& _xTable ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCacheSet::deleteRow" ); + Reference<XPropertySet> xSet(_xTable,UNO_QUERY); + fillTableName(xSet); + + ::rtl::OUStringBuffer aSql = ::rtl::OUString::createFromAscii("DELETE FROM "); + aSql.append(m_aComposedTableName); + aSql.append(::rtl::OUString::createFromAscii(" WHERE ")); + + // list all cloumns that should be set + ::rtl::OUString aQuote = getIdentifierQuoteString(); + static ::rtl::OUString aAnd = ::rtl::OUString::createFromAscii(" AND "); + + // use keys and indexes for excat postioning + // first the keys + const Reference<XNameAccess> xPrimaryKeyColumns = getPrimaryKeyColumns_throw(xSet); + // second the indexes + Reference<XIndexesSupplier> xIndexSup(_xTable,UNO_QUERY); + Reference<XIndexAccess> xIndexes; + if(xIndexSup.is()) + xIndexes.set(xIndexSup->getIndexes(),UNO_QUERY); + + // Reference<XColumnsSupplier> + Reference<XPropertySet> xIndexColsSup; + Reference<XNameAccess> xIndexColumns; + ::std::vector< Reference<XNameAccess> > aAllIndexColumns; + if(xIndexes.is()) + { + for(sal_Int32 j=0;j<xIndexes->getCount();++j) + { + xIndexColsSup.set(xIndexes->getByIndex(j),UNO_QUERY); + if( xIndexColsSup.is() + && comphelper::getBOOL(xIndexColsSup->getPropertyValue(PROPERTY_ISUNIQUE)) + && !comphelper::getBOOL(xIndexColsSup->getPropertyValue(PROPERTY_ISPRIMARYKEYINDEX)) + ) + aAllIndexColumns.push_back(Reference<XColumnsSupplier>(xIndexColsSup,UNO_QUERY)->getColumns()); + } + } + + ::rtl::OUStringBuffer aColumnName; + ::std::list< sal_Int32> aOrgValues; + fillParameters(_rDeleteRow,_xTable,aSql,aColumnName,aOrgValues); + + aSql.setLength(aSql.getLength()-5); + + // now create end execute the prepared statement + Reference< XPreparedStatement > xPrep(m_xConnection->prepareStatement(aSql.makeStringAndClear())); + Reference< XParameters > xParameter(xPrep,UNO_QUERY); + sal_Int32 i = 1; + ::std::list< sal_Int32>::const_iterator aOrgValueEnd = aOrgValues.end(); + for(::std::list< sal_Int32>::const_iterator j = aOrgValues.begin(); j != aOrgValueEnd;++j,++i) + { + setParameter(i,xParameter,(_rDeleteRow->get())[*j],m_xSetMetaData->getColumnType(i),m_xSetMetaData->getScale(i)); + } + + m_bDeleted = xPrep->executeUpdate() > 0; +} +// ------------------------------------------------------------------------- +void OCacheSet::setParameter(sal_Int32 nPos + ,const Reference< XParameters >& _xParameter + ,const ORowSetValue& _rValue + ,sal_Int32 _nType + ,sal_Int32 _nScale) const +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCacheSet::setParameter" ); + sal_Int32 nType = ( _nType != DataType::OTHER ) ? _nType : _rValue.getTypeKind(); + ::dbtools::setObjectWithInfo(_xParameter,nPos,_rValue,nType,_nScale); +} +// ------------------------------------------------------------------------- +void OCacheSet::fillValueRow(ORowSetRow& _rRow,sal_Int32 _nPosition) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCacheSet::fillValueRow" ); + Any aBookmark = getBookmark(); + if(!aBookmark.hasValue()) + aBookmark = makeAny(_nPosition); + + connectivity::ORowVector< ORowSetValue >::Vector::iterator aIter = _rRow->get().begin(); + connectivity::ORowVector< ORowSetValue >::Vector::iterator aEnd = _rRow->get().end(); + (*aIter) = aBookmark; + ++aIter; + for(sal_Int32 i=1;aIter != aEnd;++aIter,++i) + { + aIter->setSigned(m_aSignedFlags[i-1]); + aIter->fill(i,m_aColumnTypes[i-1],m_aNullable[i-1],this); + } +} +// ----------------------------------------------------------------------------- +sal_Bool SAL_CALL OCacheSet::wasNull( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCacheSet::wasNull" ); + return m_xDriverRow->wasNull(); +} +// ------------------------------------------------------------------------- +::rtl::OUString SAL_CALL OCacheSet::getString( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCacheSet::getString" ); + return m_xDriverRow->getString(columnIndex); +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL OCacheSet::getBoolean( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCacheSet::getBoolean" ); + return m_xDriverRow->getBoolean(columnIndex); +} +// ------------------------------------------------------------------------- +sal_Int8 SAL_CALL OCacheSet::getByte( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCacheSet::getByte" ); + return m_xDriverRow->getByte(columnIndex); +} +// ------------------------------------------------------------------------- +sal_Int16 SAL_CALL OCacheSet::getShort( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCacheSet::getShort" ); + return m_xDriverRow->getShort(columnIndex); +} +// ------------------------------------------------------------------------- +sal_Int32 SAL_CALL OCacheSet::getInt( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCacheSet::getInt" ); + return m_xDriverRow->getInt(columnIndex); +} +// ------------------------------------------------------------------------- +sal_Int64 SAL_CALL OCacheSet::getLong( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCacheSet::getLong" ); + return m_xDriverRow->getLong(columnIndex); +} +// ------------------------------------------------------------------------- +float SAL_CALL OCacheSet::getFloat( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCacheSet::getFloat" ); + return m_xDriverRow->getFloat(columnIndex); +} +// ------------------------------------------------------------------------- +double SAL_CALL OCacheSet::getDouble( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCacheSet::getDouble" ); + return m_xDriverRow->getDouble(columnIndex); +} +// ------------------------------------------------------------------------- +Sequence< sal_Int8 > SAL_CALL OCacheSet::getBytes( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCacheSet::getBytes" ); + return m_xDriverRow->getBytes(columnIndex); +} +// ------------------------------------------------------------------------- +::com::sun::star::util::Date SAL_CALL OCacheSet::getDate( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCacheSet::getDate" ); + return m_xDriverRow->getDate(columnIndex); +} +// ------------------------------------------------------------------------- +::com::sun::star::util::Time SAL_CALL OCacheSet::getTime( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCacheSet::getTime" ); + return m_xDriverRow->getTime(columnIndex); +} +// ------------------------------------------------------------------------- +::com::sun::star::util::DateTime SAL_CALL OCacheSet::getTimestamp( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCacheSet::getTimestamp" ); + return m_xDriverRow->getTimestamp(columnIndex); +} +// ------------------------------------------------------------------------- +Reference< ::com::sun::star::io::XInputStream > SAL_CALL OCacheSet::getBinaryStream( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCacheSet::getBinaryStream" ); + return m_xDriverRow->getBinaryStream(columnIndex); +} +// ------------------------------------------------------------------------- +Reference< ::com::sun::star::io::XInputStream > SAL_CALL OCacheSet::getCharacterStream( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCacheSet::getCharacterStream" ); + return m_xDriverRow->getCharacterStream(columnIndex); +} +// ------------------------------------------------------------------------- +Any SAL_CALL OCacheSet::getObject( sal_Int32 columnIndex, const Reference< ::com::sun::star::container::XNameAccess >& typeMap ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCacheSet::getObject" ); + return m_xDriverRow->getObject(columnIndex,typeMap); +} +// ------------------------------------------------------------------------- +Reference< XRef > SAL_CALL OCacheSet::getRef( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCacheSet::getRef" ); + return m_xDriverRow->getRef(columnIndex); +} +// ------------------------------------------------------------------------- +Reference< XBlob > SAL_CALL OCacheSet::getBlob( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCacheSet::getBlob" ); + return m_xDriverRow->getBlob(columnIndex); +} +// ------------------------------------------------------------------------- +Reference< XClob > SAL_CALL OCacheSet::getClob( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCacheSet::getClob" ); + return m_xDriverRow->getClob(columnIndex); +} +// ------------------------------------------------------------------------- +Reference< XArray > SAL_CALL OCacheSet::getArray( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCacheSet::getArray" ); + return m_xDriverRow->getArray(columnIndex); +} +// ------------------------------------------------------------------------- +// XResultSet +sal_Bool SAL_CALL OCacheSet::next( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCacheSet::next" ); + m_bInserted = m_bUpdated = m_bDeleted = sal_False; + return m_xDriverSet->next(); +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL OCacheSet::isBeforeFirst( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCacheSet::isBeforeFirst" ); + return m_xDriverSet->isBeforeFirst(); +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL OCacheSet::isAfterLast( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCacheSet::isAfterLast" ); + return m_xDriverSet->isAfterLast(); +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL OCacheSet::isFirst( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCacheSet::isFirst" ); + return m_xDriverSet->isFirst(); +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL OCacheSet::isLast( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCacheSet::isLast" ); + return m_xDriverSet->isLast(); +} +// ------------------------------------------------------------------------- +void SAL_CALL OCacheSet::beforeFirst( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCacheSet::beforeFirst" ); + m_bInserted = m_bUpdated = m_bDeleted = sal_False; + m_xDriverSet->beforeFirst(); +} +// ------------------------------------------------------------------------- +void SAL_CALL OCacheSet::afterLast( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCacheSet::afterLast" ); + m_bInserted = m_bUpdated = m_bDeleted = sal_False; + m_xDriverSet->afterLast(); +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL OCacheSet::first( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCacheSet::first" ); + m_bInserted = m_bUpdated = m_bDeleted = sal_False; + return m_xDriverSet->first(); +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL OCacheSet::last( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCacheSet::last" ); + m_bInserted = m_bUpdated = m_bDeleted = sal_False; + return m_xDriverSet->last(); +} +// ------------------------------------------------------------------------- +sal_Int32 SAL_CALL OCacheSet::getRow( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCacheSet::getRow" ); + return m_xDriverSet->getRow(); +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL OCacheSet::absolute( sal_Int32 row ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCacheSet::absolute" ); + m_bInserted = m_bUpdated = m_bDeleted = sal_False; + return m_xDriverSet->absolute(row); +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL OCacheSet::relative( sal_Int32 rows ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCacheSet::relative" ); + m_bInserted = m_bUpdated = m_bDeleted = sal_False; + return m_xDriverSet->relative(rows); +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL OCacheSet::previous( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCacheSet::previous" ); + m_bInserted = m_bUpdated = m_bDeleted = sal_False; + return m_xDriverSet->previous(); +} +// ------------------------------------------------------------------------- +void SAL_CALL OCacheSet::refreshRow( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCacheSet::refreshRow" ); + m_xDriverSet->refreshRow(); +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL OCacheSet::rowUpdated( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCacheSet::rowUpdated" ); + return m_xDriverSet->rowUpdated(); +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL OCacheSet::rowInserted( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCacheSet::rowInserted" ); + return m_xDriverSet->rowInserted(); +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL OCacheSet::rowDeleted( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCacheSet::rowDeleted" ); + return m_xDriverSet->rowDeleted(); +} +// ------------------------------------------------------------------------- +Reference< XInterface > SAL_CALL OCacheSet::getStatement( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCacheSet::getStatement" ); + return m_xDriverSet->getStatement(); +} +// ----------------------------------------------------------------------------- +bool OCacheSet::isResultSetChanged() const +{ + return false; +} +// ----------------------------------------------------------------------------- +void OCacheSet::reset(const Reference< XResultSet>& /*_xDriverSet*/) +{ + OSL_ENSURE(0,"Illegal call!"); +} +// ----------------------------------------------------------------------------- +void OCacheSet::mergeColumnValues(sal_Int32 i_nColumnIndex,ORowSetValueVector::Vector& /*io_aInsertRow*/,ORowSetValueVector::Vector& /*io_aRow*/,::std::vector<sal_Int32>& o_aChangedColumns) +{ + o_aChangedColumns.push_back(i_nColumnIndex); +} +// ----------------------------------------------------------------------------- +bool OCacheSet::columnValuesUpdated(ORowSetValueVector::Vector& /*io_aCachedRow*/,const ORowSetValueVector::Vector& /*io_aRow*/) +{ + return false; +} +// ----------------------------------------------------------------------------- +bool OCacheSet::updateColumnValues(const ORowSetValueVector::Vector& /*io_aCachedRow*/,ORowSetValueVector::Vector& /*io_aRow*/,const ::std::vector<sal_Int32>& /*i_aChangedColumns*/) +{ + return true; +} +// ----------------------------------------------------------------------------- +void OCacheSet::fillMissingValues(ORowSetValueVector::Vector& /*io_aRow*/) const +{ +} +// ----------------------------------------------------------------------------- + diff --git a/dbaccess/source/core/api/CacheSet.hxx b/dbaccess/source/core/api/CacheSet.hxx new file mode 100644 index 000000000000..ef3503fa5e4e --- /dev/null +++ b/dbaccess/source/core/api/CacheSet.hxx @@ -0,0 +1,179 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ +#ifndef DBACCESS_CORE_API_CACHESET_HXX +#define DBACCESS_CORE_API_CACHESET_HXX + +#ifndef _COM_SUN_STAR_SDBC_XROW_HPP_ +#include <com/sun/star/sdbc/XRow.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_XRESULTSETMETADATA_HPP_ +#include <com/sun/star/sdbc/XResultSetMetaData.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_XRESULTSETMETADATASUPPLIER_HPP_ +#include <com/sun/star/sdbc/XResultSetMetaDataSupplier.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_XRESULTSET_HPP_ +#include <com/sun/star/sdbc/XResultSet.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_XCONNECTION_HPP_ +#include <com/sun/star/sdbc/XConnection.hpp> +#endif +#ifndef _COM_SUN_STAR_BEANS_XPROPERTYSET_HPP_ +#include <com/sun/star/beans/XPropertySet.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBCX_XROWLOCATE_HPP_ +#include <com/sun/star/sdbcx/XRowLocate.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBCX_XDELETEROWS_HPP_ +#include <com/sun/star/sdbcx/XDeleteRows.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBCX_COMPAREBOOKMARK_HPP_ +#include <com/sun/star/sdbcx/CompareBookmark.hpp> +#endif +#ifndef DBACCESS_CORE_API_ROWSETROW_HXX +#include "RowSetRow.hxx" +#endif +#ifndef _CPPUHELPER_IMPLBASE1_HXX_ +#include <cppuhelper/implbase1.hxx> +#endif + +#include <list> +namespace rtl +{ + class OUStringBuffer; +} +namespace com{ namespace sun { namespace star{namespace sdbc{ class XParameters; } } } } + +namespace dbaccess +{ + class OCacheSet : public ::cppu::WeakImplHelper1< ::com::sun::star::sdbc::XRow> + { + protected: + ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XResultSet> m_xDriverSet; + ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRow> m_xDriverRow; + ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XResultSetMetaData> m_xSetMetaData; + ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection> m_xConnection; + + ::com::sun::star::uno::Sequence<sal_Bool> m_aNullable; + ::com::sun::star::uno::Sequence<sal_Bool> m_aSignedFlags; + ::com::sun::star::uno::Sequence<sal_Int32> m_aColumnTypes; + ORowSetRow m_aInsertRow; + ::rtl::OUString m_aComposedTableName; + sal_Bool m_bInserted; + sal_Bool m_bUpdated; + sal_Bool m_bDeleted; + + OCacheSet(); + virtual ~OCacheSet(); + + void setParameter(sal_Int32 nPos + ,const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XParameters >& _xParameter + ,const connectivity::ORowSetValue& _rValue + ,sal_Int32 _nType + ,sal_Int32 _nScale + ) const; + void fillParameters( const ORowSetRow& _rRow + ,const connectivity::OSQLTable& _xTable + ,::rtl::OUStringBuffer& _sCondition + ,::rtl::OUStringBuffer& _sParameter + ,::std::list< sal_Int32>& _rOrgValues); + void fillTableName(const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet>& _xTable) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + + ::rtl::OUString getIdentifierQuoteString() const; + public: + + // late constructor + virtual void construct(const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XResultSet>& _xDriverSet,const ::rtl::OUString& i_sRowSetFilter); + virtual void fillValueRow(ORowSetRow& _rRow,sal_Int32 _nPosition); + + // ::com::sun::star::sdbc::XRow + virtual sal_Bool SAL_CALL wasNull( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getString( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL getBoolean( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Int8 SAL_CALL getByte( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Int16 SAL_CALL getShort( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Int32 SAL_CALL getInt( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Int64 SAL_CALL getLong( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual float SAL_CALL getFloat( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual double SAL_CALL getDouble( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL getBytes( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::util::Date SAL_CALL getDate( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::util::Time SAL_CALL getTime( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::util::DateTime SAL_CALL getTimestamp( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > SAL_CALL getBinaryStream( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > SAL_CALL getCharacterStream( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Any SAL_CALL getObject( sal_Int32 columnIndex, const ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess >& typeMap ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRef > SAL_CALL getRef( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XBlob > SAL_CALL getBlob( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XClob > SAL_CALL getClob( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XArray > SAL_CALL getArray( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + // ::com::sun::star::sdbc::XResultSet + virtual sal_Bool SAL_CALL next( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL isBeforeFirst( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL isAfterLast( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL isFirst( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL isLast( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL beforeFirst( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL afterLast( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL first( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL last( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Int32 SAL_CALL getRow( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL absolute( sal_Int32 row ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL relative( sal_Int32 rows ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL previous( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL refreshRow( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL rowUpdated( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL rowInserted( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL rowDeleted( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL getStatement( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + // ::com::sun::star::sdbcx::XRowLocate + virtual ::com::sun::star::uno::Any SAL_CALL getBookmark() throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException) = 0; + virtual sal_Bool SAL_CALL moveToBookmark( const ::com::sun::star::uno::Any& bookmark ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException) = 0; + virtual sal_Bool SAL_CALL moveRelativeToBookmark( const ::com::sun::star::uno::Any& bookmark, sal_Int32 rows ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException) = 0; + virtual sal_Int32 SAL_CALL compareBookmarks( const ::com::sun::star::uno::Any& first, const ::com::sun::star::uno::Any& second ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException) = 0; + virtual sal_Bool SAL_CALL hasOrderedBookmarks( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException) = 0; + virtual sal_Int32 SAL_CALL hashBookmark( const ::com::sun::star::uno::Any& bookmark ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException) = 0; + // ::com::sun::star::sdbcx::XDeleteRows + virtual ::com::sun::star::uno::Sequence< sal_Int32 > SAL_CALL deleteRows( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& rows,const connectivity::OSQLTable& _xTable ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException) = 0; + // ::com::sun::star::sdbc::XResultSetUpdate + virtual void SAL_CALL insertRow( const ORowSetRow& _rInsertRow,const connectivity::OSQLTable& _xTable ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL updateRow( const ORowSetRow& _rInsertRow,const ORowSetRow& _rOrginalRow,const connectivity::OSQLTable& _xTable ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException) = 0; + virtual void SAL_CALL deleteRow( const ORowSetRow& _rDeleteRow,const connectivity::OSQLTable& _xTable ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException) = 0; + virtual void SAL_CALL cancelRowUpdates( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException) = 0; + virtual void SAL_CALL moveToInsertRow( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException) = 0; + virtual void SAL_CALL moveToCurrentRow( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException) = 0; + + virtual bool isResultSetChanged() const; + virtual void reset(const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XResultSet>& _xDriverSet); + virtual void mergeColumnValues(sal_Int32 i_nColumnIndex,ORowSetValueVector::Vector& io_aInsertRow,ORowSetValueVector::Vector& io_aRow,::std::vector<sal_Int32>& o_aChangedColumns); + virtual bool columnValuesUpdated(ORowSetValueVector::Vector& o_aCachedRow,const ORowSetValueVector::Vector& i_aRow); + virtual bool updateColumnValues(const ORowSetValueVector::Vector& io_aCachedRow,ORowSetValueVector::Vector& io_aRow,const ::std::vector<sal_Int32>& i_aChangedColumns); + virtual void fillMissingValues(ORowSetValueVector::Vector& io_aRow) const; + }; +} +#endif //DBACCESS_CORE_API_CACHESET_HXX + diff --git a/dbaccess/source/core/api/FilteredContainer.cxx b/dbaccess/source/core/api/FilteredContainer.cxx new file mode 100644 index 000000000000..aa20bf080e4d --- /dev/null +++ b/dbaccess/source/core/api/FilteredContainer.cxx @@ -0,0 +1,498 @@ +/************************************************************************* + * + * 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_dbaccess.hxx" + +#include "dbastrings.hrc" +#include "FilteredContainer.hxx" +#include "RefreshListener.hxx" +#include "sdbcoretools.hxx" +#include <com/sun/star/sdbc/XRow.hpp> +#include <connectivity/dbtools.hxx> +#include <tools/wldcrd.hxx> +#include <tools/diagnose_ex.h> +#include <rtl/logfile.hxx> +#include <boost/optional.hpp> + +namespace dbaccess +{ + using namespace dbtools; + 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::sdb; + using namespace ::com::sun::star::sdbcx; + using namespace ::com::sun::star::util; + using namespace ::com::sun::star::container; + using namespace ::osl; + using namespace ::comphelper; + using namespace ::cppu; + using namespace ::connectivity::sdbcx; + +//------------------------------------------------------------------------------ +/** creates a vector of WildCards and reduce the _rTableFilter of the length of WildsCards +*/ +sal_Int32 createWildCardVector(Sequence< ::rtl::OUString >& _rTableFilter, ::std::vector< WildCard >& _rOut) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "api", "Ocke.Janssen@sun.com", "OFilteredContainer::createWildCardVector" ); + // for wildcard search : remove all table filters which are a wildcard expression and build a WilCard + // for them + ::rtl::OUString* pTableFilters = _rTableFilter.getArray(); + ::rtl::OUString* pEnd = pTableFilters + _rTableFilter.getLength(); + sal_Int32 nShiftPos = 0; + for (sal_Int32 i=0; pEnd != pTableFilters; ++pTableFilters,++i) + { + if (pTableFilters->indexOf('%') != -1) + { + _rOut.push_back(WildCard(pTableFilters->replace('%', '*'))); + } + else + { + if (nShiftPos != i) + { + _rTableFilter.getArray()[nShiftPos] = _rTableFilter.getArray()[i]; + } + ++nShiftPos; + } + } + // now aTableFilter contains nShiftPos non-wc-strings and aWCSearch all wc-strings + _rTableFilter.realloc(nShiftPos); + return nShiftPos; +} + + // ------------------------------------------------------------------------- + bool lcl_isElementAllowed( const ::rtl::OUString& _rName, + const Sequence< ::rtl::OUString >& _rTableFilter, + const ::std::vector< WildCard >& _rWCSearch ) + { + sal_Int32 nTableFilterLen = _rTableFilter.getLength(); + + const ::rtl::OUString* tableFilter = _rTableFilter.getConstArray(); + const ::rtl::OUString* tableFilterEnd = _rTableFilter.getConstArray() + nTableFilterLen; + bool bFilterMatch = ::std::find( tableFilter, tableFilterEnd, _rName ) != tableFilterEnd; + // the table is allowed to "pass" if we had no filters at all or any of the non-wildcard filters matches + if (!bFilterMatch && !_rWCSearch.empty()) + { // or if one of the wildcrad expression matches + for ( ::std::vector< WildCard >::const_iterator aLoop = _rWCSearch.begin(); + aLoop != _rWCSearch.end() && !bFilterMatch; + ++aLoop + ) + bFilterMatch = aLoop->Matches( _rName ); + } + + return bFilterMatch; + } + + //-------------------------------------------------------------------------- + typedef ::boost::optional< ::rtl::OUString > OptionalString; + struct TableInfo + { + OptionalString sComposedName; + OptionalString sType; + OptionalString sCatalog; + OptionalString sSchema; + OptionalString sName; + + TableInfo( const ::rtl::OUString& _composedName ) + :sComposedName( _composedName ) + { + } + + TableInfo( const ::rtl::OUString& _catalog, const ::rtl::OUString& _schema, const ::rtl::OUString& _name, + const ::rtl::OUString& _type ) + :sComposedName() + ,sType( _type ) + ,sCatalog( _catalog ) + ,sSchema( _schema ) + ,sName( _name ) + { + } + }; + typedef ::std::vector< TableInfo > TableInfos; + + //-------------------------------------------------------------------------- + void lcl_ensureComposedName( TableInfo& _io_tableInfo, const Reference< XDatabaseMetaData >& _metaData ) + { + if ( !_metaData.is() ) + throw RuntimeException(); + + if ( !_io_tableInfo.sComposedName ) + { + OSL_ENSURE( !!_io_tableInfo.sCatalog && !!_io_tableInfo.sSchema && !!_io_tableInfo.sName, "lcl_ensureComposedName: How should I composed the name from nothing!?" ); + + _io_tableInfo.sComposedName = OptionalString( + composeTableName( _metaData, *_io_tableInfo.sCatalog, *_io_tableInfo.sSchema, *_io_tableInfo.sName, + sal_False, ::dbtools::eInDataManipulation ) + ); + } + } + + //-------------------------------------------------------------------------- + void lcl_ensureType( TableInfo& _io_tableInfo, const Reference< XDatabaseMetaData >& _metaData, const Reference< XNameAccess >& _masterContainer ) + { + if ( !!_io_tableInfo.sType ) + return; + + lcl_ensureComposedName( _io_tableInfo, _metaData ); + + if ( !_masterContainer.is() ) + throw RuntimeException(); + + ::rtl::OUString sTypeName; + try + { + Reference< XPropertySet > xTable( _masterContainer->getByName( *_io_tableInfo.sComposedName ), UNO_QUERY_THROW ); + OSL_VERIFY( xTable->getPropertyValue( PROPERTY_TYPE ) >>= sTypeName ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + _io_tableInfo.sType = OptionalString( sTypeName ); + } + + //-------------------------------------------------------------------------- + connectivity::TStringVector lcl_filter( const TableInfos& _unfilteredTables, + const Sequence< ::rtl::OUString >& _tableFilter, const Sequence< ::rtl::OUString >& _tableTypeFilter, + const Reference< XDatabaseMetaData >& _metaData, const Reference< XNameAccess >& _masterContainer ) + { + TableInfos aFilteredTables; + + // first, filter for the table names + sal_Int32 nTableFilterCount = _tableFilter.getLength(); + sal_Bool dontFilterTableNames = ( ( nTableFilterCount == 1 ) && _tableFilter[0].equalsAsciiL( "%", 1 ) ); + if( dontFilterTableNames ) + { + aFilteredTables = _unfilteredTables; + } + else + { + // for wildcard search : remove all table filters which are a wildcard expression and build a WilCard + // for them + ::std::vector< WildCard > aWildCardTableFilter; + Sequence< ::rtl::OUString > aNonWildCardTableFilter = _tableFilter; + nTableFilterCount = createWildCardVector( aNonWildCardTableFilter, aWildCardTableFilter ); + + TableInfos aUnfilteredTables( _unfilteredTables ); + aUnfilteredTables.reserve( nTableFilterCount + ( aWildCardTableFilter.size() * 10 ) ); + + for ( TableInfos::iterator table = aUnfilteredTables.begin(); + table != aUnfilteredTables.end(); + ++table + ) + { + lcl_ensureComposedName( *table, _metaData ); + + if ( lcl_isElementAllowed( *table->sComposedName, aNonWildCardTableFilter, aWildCardTableFilter ) ) + aFilteredTables.push_back( *table ); + } + } + + // second, filter for the table types + sal_Int32 nTableTypeFilterCount = _tableTypeFilter.getLength(); + sal_Bool dontFilterTableTypes = ( ( nTableTypeFilterCount == 1 ) && _tableTypeFilter[0].equalsAsciiL( "%", 1 ) ); + dontFilterTableTypes = dontFilterTableTypes || ( nTableTypeFilterCount == 0 ); + // (for TableTypeFilter, unlike TableFilter, "empty" means "do not filter at all") + if ( !dontFilterTableTypes ) + { + TableInfos aUnfilteredTables; + aUnfilteredTables.swap( aFilteredTables ); + + const ::rtl::OUString* pTableTypeFilterBegin = _tableTypeFilter.getConstArray(); + const ::rtl::OUString* pTableTypeFilterEnd = pTableTypeFilterBegin + _tableTypeFilter.getLength(); + + for ( TableInfos::iterator table = aUnfilteredTables.begin(); + table != aUnfilteredTables.end(); + ++table + ) + { + // ensure that we know the table type + lcl_ensureType( *table, _metaData, _masterContainer ); + + if ( ::std::find( pTableTypeFilterBegin, pTableTypeFilterEnd, *table->sType ) != pTableTypeFilterEnd ) + aFilteredTables.push_back( *table ); + } + } + + connectivity::TStringVector aReturn; + for ( TableInfos::iterator table = aFilteredTables.begin(); + table != aFilteredTables.end(); + ++table + ) + { + lcl_ensureComposedName( *table, _metaData ); + aReturn.push_back( *table->sComposedName ); + } + return aReturn; + } + + //========================================================================== + //= OViewContainer + //========================================================================== + OFilteredContainer::OFilteredContainer(::cppu::OWeakObject& _rParent, + ::osl::Mutex& _rMutex, + const Reference< XConnection >& _xCon, + sal_Bool _bCase, + IRefreshListener* _pRefreshListener, + ::dbtools::IWarningsContainer* _pWarningsContainer + ,oslInterlockedCount& _nInAppend) + :OCollection(_rParent,_bCase,_rMutex,::std::vector< ::rtl::OUString>()) + ,m_bConstructed(sal_False) + ,m_pWarningsContainer(_pWarningsContainer) + ,m_pRefreshListener(_pRefreshListener) + ,m_nInAppend(_nInAppend) + ,m_xConnection(_xCon) + { + } + // ------------------------------------------------------------------------- + void OFilteredContainer::construct(const Reference< XNameAccess >& _rxMasterContainer, + const Sequence< ::rtl::OUString >& _rTableFilter, + const Sequence< ::rtl::OUString >& _rTableTypeFilter) + { + try + { + Reference<XConnection> xCon = m_xConnection; + if ( xCon.is() ) + m_xMetaData = xCon->getMetaData(); + } + catch(SQLException&) + { + DBG_UNHANDLED_EXCEPTION(); + } + + m_xMasterContainer = _rxMasterContainer; + + if ( m_xMasterContainer.is() ) + { + addMasterContainerListener(); + + TableInfos aUnfilteredTables; + + Sequence< ::rtl::OUString > aNames = m_xMasterContainer->getElementNames(); + const ::rtl::OUString* name = aNames.getConstArray(); + const ::rtl::OUString* nameEnd = name + aNames.getLength(); + for ( ; name != nameEnd; ++name ) + aUnfilteredTables.push_back( TableInfo( *name ) ); + + reFill( lcl_filter( aUnfilteredTables, + _rTableFilter, _rTableTypeFilter, m_xMetaData, m_xMasterContainer ) ); + + m_bConstructed = sal_True; + } + else + { + construct( _rTableFilter, _rTableTypeFilter ); + } + } + //------------------------------------------------------------------------------ + void OFilteredContainer::construct(const Sequence< ::rtl::OUString >& _rTableFilter, const Sequence< ::rtl::OUString >& _rTableTypeFilter) + { + // build sorted versions of the filter sequences, so the visibility decision is faster + Sequence< ::rtl::OUString > aTableFilter(_rTableFilter); + sal_Int32 nTableFilterLen = aTableFilter.getLength(); + + // for wildcard search : remove all table filters which are a wildcard expression and build a WilCard + // for them + ::std::vector< WildCard > aWCSearch; + nTableFilterLen = createWildCardVector(aTableFilter,aWCSearch); + + try + { + Reference< XConnection > xCon( m_xConnection, UNO_SET_THROW ); + m_xMetaData.set( xCon->getMetaData(), UNO_SET_THROW ); + + // create a table table filter suitable for the XDatabaseMetaData::getTables call, + // taking into account both the externally-provided table type filter, and any + // table type restriction which is inherent to the container + Sequence< ::rtl::OUString > aTableTypeFilter; + ::rtl::OUString sInherentTableTypeRestriction( getTableTypeRestriction() ); + if ( sInherentTableTypeRestriction.getLength() ) + { + if ( _rTableTypeFilter.getLength() != 0 ) + { + const ::rtl::OUString* tableType = _rTableTypeFilter.getConstArray(); + const ::rtl::OUString* tableTypeEnd = tableType + _rTableTypeFilter.getLength(); + for ( ; tableType != tableTypeEnd; ++tableType ) + { + if ( *tableType == sInherentTableTypeRestriction ) + break; + } + if ( tableType == tableTypeEnd ) + { // the only table type which can be part of this container is not allowed + // by the externally provided table type filter. + m_bConstructed = sal_True; + return; + } + } + aTableTypeFilter.realloc( 1 ); + aTableTypeFilter[0] = sInherentTableTypeRestriction; + } + else + { + // no container-inherent restriction for the table types + if ( _rTableTypeFilter.getLength() == 0 ) + { // no externally-provided table type filter => use the default filter + getAllTableTypeFilter( aTableTypeFilter ); + } + else + { + aTableTypeFilter = _rTableTypeFilter; + } + } + + static const ::rtl::OUString sAll = ::rtl::OUString::createFromAscii("%"); + Reference< XResultSet > xTables = m_xMetaData->getTables( Any(), sAll, sAll, aTableTypeFilter ); + Reference< XRow > xCurrentRow( xTables, UNO_QUERY_THROW ); + + TableInfos aUnfilteredTables; + + ::rtl::OUString sCatalog, sSchema, sName, sType; + while ( xTables->next() ) + { + sCatalog = xCurrentRow->getString(1); + sSchema = xCurrentRow->getString(2); + sName = xCurrentRow->getString(3); + sType = xCurrentRow->getString(4); + + aUnfilteredTables.push_back( TableInfo( sCatalog, sSchema, sName, sType ) ); + } + + reFill( lcl_filter( aUnfilteredTables, + _rTableFilter, aTableTypeFilter, m_xMetaData, NULL ) ); + + disposeComponent( xTables ); + } + catch (const Exception&) + { + DBG_UNHANDLED_EXCEPTION(); + disposing(); + return; + } + + m_bConstructed = sal_True; + } + + //------------------------------------------------------------------------------ + void OFilteredContainer::disposing() + { + OCollection::disposing(); + + if ( m_xMasterContainer.is() ) + removeMasterContainerListener(); + + m_xMasterContainer = NULL; + m_xMetaData = NULL; + m_pWarningsContainer = NULL; + m_pRefreshListener = NULL; + m_bConstructed = sal_False; + } + + // ------------------------------------------------------------------------- + void OFilteredContainer::impl_refresh() throw(RuntimeException) + { + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "api", "Ocke.Janssen@sun.com", "OFilteredContainer::impl_refresh" ); + if ( m_pRefreshListener ) + { + m_bConstructed = sal_False; + Reference<XRefreshable> xRefresh(m_xMasterContainer,UNO_QUERY); + if ( xRefresh.is() ) + xRefresh->refresh(); + m_pRefreshListener->refresh(this); + } + } + + // ----------------------------------------------------------------------------- + ::rtl::OUString OFilteredContainer::getNameForObject(const ObjectType& _xObject) + { + OSL_ENSURE( _xObject.is(), "OFilteredContainer::getNameForObject: Object is NULL!" ); + return ::dbtools::composeTableName( m_xMetaData, _xObject, ::dbtools::eInDataManipulation, false, false, false ); + } + + // ----------------------------------------------------------------------------- + // multiple to obtain all tables from XDatabaseMetaData::getTables, via passing a particular + // table type filter: + // adhere to the standard, which requests to pass a NULL table type filter, if + // you want to retrieve all tables + #define FILTER_MODE_STANDARD 0 + // only pass %, which is not allowed by the standard, but understood by some drivers + #define FILTER_MODE_WILDCARD 1 + // only pass TABLE and VIEW + #define FILTER_MODE_FIXED 2 + // do the thing which showed to be the safest way, understood by nearly all + // drivers, even the ones which do not understand the standard + #define FILTER_MODE_MIX_ALL 3 + + void OFilteredContainer::getAllTableTypeFilter( Sequence< ::rtl::OUString >& /* [out] */ _rFilter ) const + { + sal_Int32 nFilterMode = FILTER_MODE_MIX_ALL; + // for compatibility reasons, this is the default: we used this way before we + // introduced the TableTypeFilterMode setting + + // obtain the data source we belong to, and the TableTypeFilterMode setting + Any aFilterModeSetting; + if ( getDataSourceSetting( getDataSource( (Reference< XInterface >)m_rParent ), "TableTypeFilterMode", aFilterModeSetting ) ) + { + OSL_VERIFY( aFilterModeSetting >>= nFilterMode ); + } + + const ::rtl::OUString sAll( RTL_CONSTASCII_USTRINGPARAM( "%" ) ); + const ::rtl::OUString sView( RTL_CONSTASCII_USTRINGPARAM( "VIEW" ) ); + const ::rtl::OUString sTable( RTL_CONSTASCII_USTRINGPARAM( "TABLE" ) ); + + switch ( nFilterMode ) + { + default: + OSL_ENSURE( sal_False, "OTableContainer::getAllTableTypeFilter: unknown TableTypeFilterMode!" ); + case FILTER_MODE_MIX_ALL: + _rFilter.realloc( 3 ); + _rFilter[0] = sView; + _rFilter[1] = sTable; + _rFilter[2] = sAll; + break; + case FILTER_MODE_FIXED: + _rFilter.realloc( 2 ); + _rFilter[0] = sView; + _rFilter[1] = sTable; + break; + case FILTER_MODE_WILDCARD: + _rFilter.realloc( 1 ); + _rFilter[0] = sAll; + break; + case FILTER_MODE_STANDARD: + _rFilter.realloc( 0 ); + break; + } + } + +// .............................................................................. +} // namespace +// .............................................................................. + + diff --git a/dbaccess/source/core/api/HelperCollections.cxx b/dbaccess/source/core/api/HelperCollections.cxx new file mode 100644 index 000000000000..2e536b5c2e26 --- /dev/null +++ b/dbaccess/source/core/api/HelperCollections.cxx @@ -0,0 +1,122 @@ +/************************************************************************* + * + * 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_dbaccess.hxx" +#ifndef DBA_HELPERCOLLECTIONS_HXX +#include "HelperCollections.hxx" +#endif + +#ifndef DBACCESS_SHARED_DBASTRINGS_HRC +#include "dbastrings.hrc" +#endif + +namespace dbaccess +{ + using namespace dbtools; + using namespace comphelper; + using namespace connectivity; + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::beans; + using namespace ::com::sun::star::sdbc; + using namespace ::com::sun::star::sdb; + using namespace ::com::sun::star::sdbcx; + using namespace ::com::sun::star::container; + using namespace ::com::sun::star::lang; + using namespace ::com::sun::star::script; + using namespace ::cppu; + using namespace ::osl; + // ----------------------------------------------------------------------------- + OPrivateColumns::OPrivateColumns(const ::vos::ORef< ::connectivity::OSQLColumns>& _rColumns, + sal_Bool _bCase, + ::cppu::OWeakObject& _rParent, + ::osl::Mutex& _rMutex, + const ::std::vector< ::rtl::OUString> &_rVector, + sal_Bool _bUseAsIndex + ) : sdbcx::OCollection(_rParent,_bCase,_rMutex,_rVector,_bUseAsIndex) + ,m_aColumns(_rColumns) + { + } + + // ------------------------------------------------------------------------- + OPrivateColumns* OPrivateColumns::createWithIntrinsicNames( const ::vos::ORef< ::connectivity::OSQLColumns >& _rColumns, + sal_Bool _bCase, ::cppu::OWeakObject& _rParent, ::osl::Mutex& _rMutex ) + { + ::std::vector< ::rtl::OUString > aNames; aNames.reserve( _rColumns->get().size() ); + + ::rtl::OUString sColumName; + for ( ::connectivity::OSQLColumns::Vector::const_iterator column = _rColumns->get().begin(); + column != _rColumns->get().end(); + ++column + ) + { + Reference< XPropertySet > xColumn( *column, UNO_QUERY_THROW ); + xColumn->getPropertyValue( PROPERTY_NAME ) >>= sColumName; + aNames.push_back( sColumName ); + } + return new OPrivateColumns( _rColumns, _bCase, _rParent, _rMutex, aNames, sal_False ); + } + + // ------------------------------------------------------------------------- + void SAL_CALL OPrivateColumns::disposing(void) + { + m_aColumns = NULL; + clear_NoDispose(); + // we're not owner of the objects we're holding, instead the object we got in our ctor is + // So we're not allowed to dispose our elements. + OPrivateColumns_Base::disposing(); + } + // ------------------------------------------------------------------------- + connectivity::sdbcx::ObjectType OPrivateColumns::createObject(const ::rtl::OUString& _rName) + { + if ( m_aColumns.isValid() ) + { + ::connectivity::OSQLColumns::Vector::const_iterator aIter = find(m_aColumns->get().begin(),m_aColumns->get().end(),_rName,isCaseSensitive()); + if(aIter == m_aColumns->get().end()) + aIter = findRealName(m_aColumns->get().begin(),m_aColumns->get().end(),_rName,isCaseSensitive()); + + if(aIter != m_aColumns->get().end()) + return connectivity::sdbcx::ObjectType(*aIter,UNO_QUERY); + + OSL_ENSURE(0,"Column not found in collection!"); + } + return NULL; + } + // ------------------------------------------------------------------------- + connectivity::sdbcx::ObjectType OPrivateTables::createObject(const ::rtl::OUString& _rName) + { + if ( !m_aTables.empty() ) + { + OSQLTables::iterator aIter = m_aTables.find(_rName); + OSL_ENSURE(aIter != m_aTables.end(),"Table not found!"); + OSL_ENSURE(aIter->second.is(),"Table is null!"); + return connectivity::sdbcx::ObjectType(m_aTables.find(_rName)->second,UNO_QUERY); + } + return NULL; + } + // ----------------------------------------------------------------------------- +} diff --git a/dbaccess/source/core/api/HelperCollections.hxx b/dbaccess/source/core/api/HelperCollections.hxx new file mode 100644 index 000000000000..1169a20b0750 --- /dev/null +++ b/dbaccess/source/core/api/HelperCollections.hxx @@ -0,0 +1,128 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ +#ifndef DBA_HELPERCOLLECTIONS_HXX +#define DBA_HELPERCOLLECTIONS_HXX + +#ifndef _CONNECTIVITY_SDBCX_COLLECTION_HXX_ +#include "connectivity/sdbcx/VCollection.hxx" +#endif +#ifndef _CONNECTIVITY_DBTOOLS_HXX_ +#include <connectivity/dbtools.hxx> +#endif +#ifndef _DBHELPER_DBCONVERSION_HXX_ +#include <connectivity/dbconversion.hxx> +#endif +#ifndef _CONNECTIVITY_SDBCX_COLUMN_HXX_ +#include <connectivity/PColumn.hxx> +#endif +#ifndef _VOS_REF_HXX_ +#include <vos/ref.hxx> +#endif + +namespace dbaccess +{ + using namespace dbtools; + using namespace comphelper; + using namespace connectivity; + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::beans; + using namespace ::com::sun::star::sdbc; + using namespace ::com::sun::star::sdb; + using namespace ::com::sun::star::sdbcx; + using namespace ::com::sun::star::container; + using namespace ::com::sun::star::lang; + using namespace ::com::sun::star::script; + using namespace ::cppu; + using namespace ::osl; + // ----------------------------------------------------------------------------- + typedef connectivity::sdbcx::OCollection OPrivateColumns_Base; + class OPrivateColumns : public OPrivateColumns_Base + { + ::vos::ORef< ::connectivity::OSQLColumns> m_aColumns; + protected: + virtual connectivity::sdbcx::ObjectType createObject(const ::rtl::OUString& _rName); + virtual void impl_refresh() throw(RuntimeException) {} + virtual Reference< XPropertySet > createDescriptor() + { + return NULL; + } + public: + OPrivateColumns(const ::vos::ORef< ::connectivity::OSQLColumns>& _rColumns, + sal_Bool _bCase, + ::cppu::OWeakObject& _rParent, + ::osl::Mutex& _rMutex, + const ::std::vector< ::rtl::OUString> &_rVector, + sal_Bool _bUseAsIndex = sal_False + ); + + /** creates a columns instance as above, but taking the names from the columns itself + */ + static OPrivateColumns* createWithIntrinsicNames( + const ::vos::ORef< ::connectivity::OSQLColumns >& _rColumns, + sal_Bool _bCase, + ::cppu::OWeakObject& _rParent, + ::osl::Mutex& _rMutex + ); + + virtual void SAL_CALL disposing(void); + }; + typedef connectivity::sdbcx::OCollection OPrivateTables_BASE; + + //========================================================================== + //= OPrivateTables + //========================================================================== + class OPrivateTables : public OPrivateTables_BASE + { + OSQLTables m_aTables; + protected: + virtual connectivity::sdbcx::ObjectType createObject(const ::rtl::OUString& _rName); + virtual void impl_refresh() throw(RuntimeException) {} + virtual Reference< XPropertySet > createDescriptor() + { + return NULL; + } + public: + OPrivateTables( const OSQLTables& _rTables, + sal_Bool _bCase, + ::cppu::OWeakObject& _rParent, + ::osl::Mutex& _rMutex, + const ::std::vector< ::rtl::OUString> &_rVector + ) : sdbcx::OCollection(_rParent,_bCase,_rMutex,_rVector) + ,m_aTables(_rTables) + { + } + virtual void SAL_CALL disposing(void) + { + clear_NoDispose(); + // we're not owner of the objects we're holding, instead the object we got in our ctor is + // So we're not allowed to dispose our elements. + m_aTables.clear(); + OPrivateTables_BASE::disposing(); + } + }; +} +#endif // DBA_HELPERCOLLECTIONS_HXX diff --git a/dbaccess/source/core/api/KeySet.cxx b/dbaccess/source/core/api/KeySet.cxx new file mode 100644 index 000000000000..a2a324f11469 --- /dev/null +++ b/dbaccess/source/core/api/KeySet.cxx @@ -0,0 +1,1704 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle andor 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_dbaccess.hxx" + +#ifndef DBACCESS_CORE_API_KEYSET_HXX +#include "KeySet.hxx" +#endif +#ifndef _DBA_CORE_RESOURCE_HXX_ +#include "core_resource.hxx" +#endif +#ifndef _DBA_CORE_RESOURCE_HRC_ +#include "core_resource.hrc" +#endif +#ifndef _COM_SUN_STAR_BEANS_XPROPERTYSET_HPP_ +#include <com/sun/star/beans/XPropertySet.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_XDATABASEMETADATA_HPP_ +#include <com/sun/star/sdbc/XDatabaseMetaData.hpp> +#endif +#include <com/sun/star/sdbc/ColumnValue.hpp> +#ifndef _COM_SUN_STAR_SDBC_XPREPAREDSTATEMENT_HPP_ +#include <com/sun/star/sdbc/XPreparedStatement.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBCxParameterS_HPP_ +#include <com/sun/star/sdbc/XParameters.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_XGENERATEDRESULTSET_HPP_ +#include <com/sun/star/sdbc/XGeneratedResultSet.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_XCOLUMNLOCATE_HPP_ +#include <com/sun/star/sdbc/XColumnLocate.hpp> +#endif +#ifndef _COM_SUN_STAR_CONTAINER_XINDEXACCESS_HPP_ +#include <com/sun/star/container/XIndexAccess.hpp> +#endif +#ifndef DBACCESS_SHARED_DBASTRINGS_HRC +#include "dbastrings.hrc" +#endif +#ifndef _DBASHARED_APITOOLS_HXX_ +#include "apitools.hxx" +#endif +#ifndef _COM_SUN_STAR_SDBCX_XKEYSSUPPLIER_HPP_ +#include <com/sun/star/sdbcx/XKeysSupplier.hpp> +#endif +#ifndef _COM_SUN_STAR_SDB_XSINGLESELECTQUERYCOMPOSER_HPP_ +#include <com/sun/star/sdb/XSingleSelectQueryComposer.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBCX_XINDEXESSUPPLIER_HPP_ +#include <com/sun/star/sdbcx/XIndexesSupplier.hpp> +#endif +#ifndef _CPPUHELPER_TYPEPROVIDER_HXX_ +#include <cppuhelper/typeprovider.hxx> +#endif +#ifndef _COMPHELPER_TYPES_HXX_ +#include <comphelper/types.hxx> +#endif +#ifndef _COM_SUN_STAR_SDBCX_KEYTYPE_HPP_ +#include <com/sun/star/sdbcx/KeyType.hpp> +#endif +#ifndef _CONNECTIVITY_DBTOOLS_HXX_ +#include <connectivity/dbtools.hxx> +#endif +#ifndef _DBHELPER_DBEXCEPTION_HXX_ +#include <connectivity/dbexception.hxx> +#endif +#include <list> +#include <algorithm> +#include <string.h> +#ifndef _COM_SUN_STAR_IO_XINPUTSTREAM_HPP_ +#include <com/sun/star/io/XInputStream.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBCX_XTABLESSUPPLIER_HPP_ +#include <com/sun/star/sdbcx/XTablesSupplier.hpp> +#endif +#ifndef DBACCESS_CORE_API_QUERYCOMPOSER_HXX +#include "querycomposer.hxx" +#endif +#ifndef DBACCESS_SOURCE_CORE_INC_COMPOSERTOOLS_HXX +#include "composertools.hxx" +#endif +#ifndef _TOOLS_DEBUG_HXX +#include <tools/debug.hxx> +#endif +#include <string.h> +#include <rtl/logfile.hxx> +#include "PrivateRow.hxx" + +using namespace dbaccess; +using namespace ::connectivity; +using 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::sdb; +using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::util; +using namespace ::com::sun::star::io; +using namespace ::com::sun::star; +using namespace ::cppu; +using namespace ::osl; + +namespace +{ + void lcl_fillIndexColumns(const Reference<XIndexAccess>& _xIndexes, ::std::vector< Reference<XNameAccess> >& _rAllIndexColumns) + { + if ( _xIndexes.is() ) + { + Reference<XPropertySet> xIndexColsSup; + sal_Int32 nCount = _xIndexes->getCount(); + for(sal_Int32 j = 0 ; j < nCount ; ++j) + { + xIndexColsSup.set(_xIndexes->getByIndex(j),UNO_QUERY); + if( xIndexColsSup.is() + && comphelper::getBOOL(xIndexColsSup->getPropertyValue(PROPERTY_ISUNIQUE)) + && !comphelper::getBOOL(xIndexColsSup->getPropertyValue(PROPERTY_ISPRIMARYKEYINDEX)) + ) + _rAllIndexColumns.push_back(Reference<XColumnsSupplier>(xIndexColsSup,UNO_QUERY)->getColumns()); + } + } + } +} +DBG_NAME(OKeySet) +// ------------------------------------------------------------------------- +OKeySet::OKeySet(const connectivity::OSQLTable& _xTable, + const Reference< XIndexAccess>& _xTableKeys, + const ::rtl::OUString& _rUpdateTableName, // this can be the alias or the full qualified name + const Reference< XSingleSelectQueryAnalyzer >& _xComposer, + const ORowSetValueVector& _aParameterValueForCache) + :m_aParameterValueForCache(_aParameterValueForCache) + ,m_pKeyColumnNames(NULL) + ,m_pColumnNames(NULL) + ,m_pParameterNames(NULL) + ,m_pForeignColumnNames(NULL) + ,m_xTable(_xTable) + ,m_xTableKeys(_xTableKeys) + ,m_xComposer(_xComposer) + ,m_sUpdateTableName(_rUpdateTableName) + ,m_bRowCountFinal(sal_False) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::OKeySet" ); + DBG_CTOR(OKeySet,NULL); + +} +// ----------------------------------------------------------------------------- +OKeySet::~OKeySet() +{ + try + { + ::comphelper::disposeComponent(m_xStatement); + } + catch(Exception&) + { + m_xStatement = NULL; + } + catch(...) + { + OSL_ENSURE(0,"Unknown Exception occured"); + } + m_xComposer = NULL; + + DBG_DTOR(OKeySet,NULL); +} +void OKeySet::initColumns() +{ + Reference<XDatabaseMetaData> xMeta = m_xConnection->getMetaData(); + bool bCase = (xMeta.is() && xMeta->storesMixedCaseQuotedIdentifiers()) ? true : false; + m_pKeyColumnNames.reset( new SelectColumnsMetaData(bCase) ); + m_pColumnNames.reset( new SelectColumnsMetaData(bCase) ); + m_pParameterNames.reset( new SelectColumnsMetaData(bCase) ); + m_pForeignColumnNames.reset( new SelectColumnsMetaData(bCase) ); +} +void OKeySet::findTableColumnsMatching_throw( const Any& i_aTable, + const ::rtl::OUString& i_rUpdateTableName, + const Reference<XDatabaseMetaData>& i_xMeta, + const Reference<XNameAccess>& i_xQueryColumns, + ::std::auto_ptr<SelectColumnsMetaData>& o_pKeyColumnNames) +{ + // first ask the database itself for the best columns which can be used + Sequence< ::rtl::OUString> aBestColumnNames; + Reference<XNameAccess> xKeyColumns = getPrimaryKeyColumns_throw(i_aTable); + if ( xKeyColumns.is() ) + aBestColumnNames = xKeyColumns->getElementNames(); + + const Reference<XColumnsSupplier> xTblColSup(i_aTable,UNO_QUERY_THROW); + const Reference<XNameAccess> xTblColumns = xTblColSup->getColumns(); + // locate parameter in select columns + Reference<XParametersSupplier> xParaSup(m_xComposer,UNO_QUERY); + Reference<XIndexAccess> xQueryParameters = xParaSup->getParameters(); + const sal_Int32 nParaCount = xQueryParameters->getCount(); + Sequence< ::rtl::OUString> aParameterColumns(nParaCount); + for(sal_Int32 i = 0; i< nParaCount;++i) + { + Reference<XPropertySet> xPara(xQueryParameters->getByIndex(i),UNO_QUERY_THROW); + xPara->getPropertyValue(PROPERTY_REALNAME) >>= aParameterColumns[i]; + } + + ::rtl::OUString sUpdateTableName( i_rUpdateTableName ); + if ( sUpdateTableName.getLength() == 0 ) + { + OSL_ENSURE( false, "OKeySet::findTableColumnsMatching_throw: This is a fallback only - it won't work when the table has an alias name." ); + // If i_aTable originates from a query composer, and is a table which appears with an alias in the SELECT statement, + // then the below code will not produce correct results. + // For instance, imagine a "SELECT alias.col FROM table AS alias". Now i_aTable would be the table named + // "table", so our sUpdateTableName would be "table" as well - not the information about the "alias" is + // already lost here. + // now getColumnPositions would travers the columns, and check which of them belong to the table denoted + // by sUpdateTableName. Since the latter is "table", but the columns only know that they belong to a table + // named "alias", there will be no matching - so getColumnPositions wouldn't find anything. + + ::rtl::OUString sCatalog, sSchema, sTable; + Reference<XPropertySet> xTableProp( i_aTable, UNO_QUERY_THROW ); + xTableProp->getPropertyValue( PROPERTY_CATALOGNAME )>>= sCatalog; + xTableProp->getPropertyValue( PROPERTY_SCHEMANAME ) >>= sSchema; + xTableProp->getPropertyValue( PROPERTY_NAME ) >>= sTable; + sUpdateTableName = dbtools::composeTableName( i_xMeta, sCatalog, sSchema, sTable, sal_False, ::dbtools::eInDataManipulation ); + } + + ::dbaccess::getColumnPositions(i_xQueryColumns,aBestColumnNames,sUpdateTableName,(*o_pKeyColumnNames),true); + ::dbaccess::getColumnPositions(i_xQueryColumns,xTblColumns->getElementNames(),sUpdateTableName,(*m_pColumnNames),true); + ::dbaccess::getColumnPositions(i_xQueryColumns,aParameterColumns,sUpdateTableName,(*m_pParameterNames),true); + + if ( o_pKeyColumnNames->empty() ) + { + ::dbtools::throwGenericSQLException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Could not find any key column." ) ), *this ); + } + + for ( SelectColumnsMetaData::const_iterator keyColumn = o_pKeyColumnNames->begin(); + keyColumn != o_pKeyColumnNames->end(); + ++keyColumn + ) + { + if ( !xTblColumns->hasByName( keyColumn->second.sRealName ) ) + continue; + + Reference<XPropertySet> xProp( xTblColumns->getByName( keyColumn->second.sRealName ), UNO_QUERY ); + sal_Bool bAuto = sal_False; + if ( ( xProp->getPropertyValue( PROPERTY_ISAUTOINCREMENT ) >>= bAuto ) && bAuto ) + m_aAutoColumns.push_back( keyColumn->first ); + } +} +::rtl::OUStringBuffer OKeySet::createKeyFilter() +{ + static ::rtl::OUString aAnd = ::rtl::OUString::createFromAscii(" AND "); + const ::rtl::OUString aQuote = getIdentifierQuoteString(); + ::rtl::OUStringBuffer aFilter; + static ::rtl::OUString s_sDot(RTL_CONSTASCII_USTRINGPARAM(".")); + static ::rtl::OUString s_sParam(RTL_CONSTASCII_USTRINGPARAM(" = ?")); + // create the where clause + Reference<XDatabaseMetaData> xMeta = m_xConnection->getMetaData(); + SelectColumnsMetaData::iterator aPosEnd = m_pKeyColumnNames->end(); + for(SelectColumnsMetaData::iterator aPosIter = m_pKeyColumnNames->begin();aPosIter != aPosEnd;) + { + aFilter.append(::dbtools::quoteTableName( xMeta,aPosIter->second.sTableName,::dbtools::eInDataManipulation)); + aFilter.append(s_sDot); + aFilter.append(::dbtools::quoteName( aQuote,aPosIter->second.sRealName)); + aFilter.append(s_sParam); + ++aPosIter; + if(aPosIter != aPosEnd) + aFilter.append(aAnd); + } + return aFilter; +} +// ----------------------------------------------------------------------------- +void OKeySet::construct(const Reference< XResultSet>& _xDriverSet,const ::rtl::OUString& i_sRowSetFilter) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::construct" ); + OCacheSet::construct(_xDriverSet,i_sRowSetFilter); + initColumns(); + + Reference<XNameAccess> xKeyColumns = getKeyColumns(); + Reference<XDatabaseMetaData> xMeta = m_xConnection->getMetaData(); + Reference<XColumnsSupplier> xQueryColSup(m_xComposer,UNO_QUERY); + const Reference<XNameAccess> xQueryColumns = xQueryColSup->getColumns(); + findTableColumnsMatching_throw(makeAny(m_xTable),m_sUpdateTableName,xMeta,xQueryColumns,m_pKeyColumnNames); + + // the first row is empty because it's now easier for us to distinguish when we are beforefirst or first + // without extra varaible to be set + m_aKeyMap.insert(OKeySetMatrix::value_type(0,OKeySetValue(NULL,::std::pair<sal_Int32,Reference<XRow> >(0,NULL)))); + m_aKeyIter = m_aKeyMap.begin(); + + ::rtl::OUStringBuffer aFilter = createKeyFilter(); + + Reference< XSingleSelectQueryComposer> xSourceComposer(m_xComposer,UNO_QUERY); + Reference< XMultiServiceFactory > xFactory(m_xConnection, UNO_QUERY_THROW); + Reference<XSingleSelectQueryComposer> xAnalyzer(xFactory->createInstance(SERVICE_NAME_SINGLESELECTQUERYCOMPOSER),UNO_QUERY); + xAnalyzer->setElementaryQuery(xSourceComposer->getElementaryQuery()); + Reference<XTablesSupplier> xTabSup(xAnalyzer,uno::UNO_QUERY); + Reference<XNameAccess> xSelectTables(xTabSup->getTables(),uno::UNO_QUERY); + const Sequence< ::rtl::OUString> aSeq = xSelectTables->getElementNames(); + if ( aSeq.getLength() > 1 ) // special handling for join + { + static ::rtl::OUString aAnd = ::rtl::OUString::createFromAscii(" AND "); + const ::rtl::OUString aQuote = getIdentifierQuoteString(); + static ::rtl::OUString s_sDot(RTL_CONSTASCII_USTRINGPARAM(".")); + static ::rtl::OUString s_sParam(RTL_CONSTASCII_USTRINGPARAM(" = ?")); + const ::rtl::OUString* pIter = aSeq.getConstArray(); + const ::rtl::OUString* pEnd = pIter + aSeq.getLength(); + for(;pIter != pEnd;++pIter) + { + if ( *pIter != m_sUpdateTableName ) + { + connectivity::OSQLTable xSelColSup(xSelectTables->getByName(*pIter),uno::UNO_QUERY); + Reference<XPropertySet> xProp(xSelColSup,uno::UNO_QUERY); + ::rtl::OUString sSelectTableName = ::dbtools::composeTableName( xMeta, xProp, ::dbtools::eInDataManipulation, false, false, false ); + + ::dbaccess::getColumnPositions(xQueryColumns,xSelColSup->getColumns()->getElementNames(),sSelectTableName,(*m_pForeignColumnNames)); + + SelectColumnsMetaData::iterator aPosEnd = (*m_pForeignColumnNames).end(); + for(SelectColumnsMetaData::iterator aPosIter = (*m_pForeignColumnNames).begin();aPosIter != aPosEnd;++aPosIter) + { + // look for columns not in the source columns to use them as filter as well + // if ( !xSourceColumns->hasByName(aPosIter->first) ) + { + if ( aFilter.getLength() ) + aFilter.append(aAnd); + aFilter.append(::dbtools::quoteName( aQuote,sSelectTableName)); + aFilter.append(s_sDot); + aFilter.append(::dbtools::quoteName( aQuote,aPosIter->second.sRealName)); + aFilter.append(s_sParam); + } + } + break; + } + } + } // if ( aSeq.getLength() > 1 ) // special handling for join + executeStatement(aFilter,i_sRowSetFilter,xAnalyzer); +} +void OKeySet::executeStatement(::rtl::OUStringBuffer& io_aFilter,const ::rtl::OUString& i_sRowSetFilter,Reference<XSingleSelectQueryComposer>& io_xAnalyzer) +{ + bool bFilterSet = i_sRowSetFilter.getLength() != 0; + if ( bFilterSet ) + { + FilterCreator aFilterCreator; + aFilterCreator.append( i_sRowSetFilter ); + aFilterCreator.append( io_aFilter.makeStringAndClear() ); + io_aFilter = aFilterCreator.getComposedAndClear(); + } + io_xAnalyzer->setFilter(io_aFilter.makeStringAndClear()); + if ( bFilterSet ) + { + Sequence< Sequence< PropertyValue > > aFilter2 = io_xAnalyzer->getStructuredFilter(); + const Sequence< PropertyValue >* pOr = aFilter2.getConstArray(); + const Sequence< PropertyValue >* pOrEnd = pOr + aFilter2.getLength(); + for(;pOr != pOrEnd;++pOr) + { + const PropertyValue* pAnd = pOr->getConstArray(); + const PropertyValue* pAndEnd = pAnd + pOr->getLength(); + for(;pAnd != pAndEnd;++pAnd) + { + ::rtl::OUString sValue; + if ( !(pAnd->Value >>= sValue) || !(sValue.equalsAscii("?") || sValue.matchAsciiL(":",1,0)) ) + { // we have a criteria which has to be taken into account for updates + m_aFilterColumns.push_back(pAnd->Name); + } + } + } + } + m_xStatement = m_xConnection->prepareStatement(io_xAnalyzer->getQueryWithSubstitution()); + ::comphelper::disposeComponent(io_xAnalyzer); +} +// ------------------------------------------------------------------------- +Any SAL_CALL OKeySet::getBookmark() throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::getBookmark" ); + OSL_ENSURE(m_aKeyIter != m_aKeyMap.end() && m_aKeyIter != m_aKeyMap.begin(), + "getBookmark is only possible when we stand on a valid row!"); + return makeAny(m_aKeyIter->first); +} + +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL OKeySet::moveToBookmark( const Any& bookmark ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::moveToBookmark" ); + m_bInserted = m_bUpdated = m_bDeleted = sal_False; + m_aKeyIter = m_aKeyMap.find(::comphelper::getINT32(bookmark)); + return m_aKeyIter != m_aKeyMap.end(); +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL OKeySet::moveRelativeToBookmark( const Any& bookmark, sal_Int32 rows ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::moveRelativeToBookmark" ); + m_bInserted = m_bUpdated = m_bDeleted = sal_False; + m_aKeyIter = m_aKeyMap.find(::comphelper::getINT32(bookmark)); + if(m_aKeyIter != m_aKeyMap.end()) + { + relative(rows); + } + + return !isBeforeFirst() && !isAfterLast(); +} +// ------------------------------------------------------------------------- +sal_Int32 SAL_CALL OKeySet::compareBookmarks( const Any& _first, const Any& _second ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::compareBookmarks" ); + sal_Int32 nFirst = 0, nSecond = 0; + _first >>= nFirst; + _second >>= nSecond; + + return (nFirst != nSecond) ? CompareBookmark::NOT_EQUAL : CompareBookmark::EQUAL; +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL OKeySet::hasOrderedBookmarks( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::hasOrderedBookmarks" ); + return sal_True; +} +// ------------------------------------------------------------------------- +sal_Int32 SAL_CALL OKeySet::hashBookmark( const Any& bookmark ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::hashBookmark" ); + return ::comphelper::getINT32(bookmark); +} +// ------------------------------------------------------------------------- +// ::com::sun::star::sdbcx::XDeleteRows +Sequence< sal_Int32 > SAL_CALL OKeySet::deleteRows( const Sequence< Any >& rows ,const connectivity::OSQLTable& _xTable) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::deleteRows" ); + Reference<XPropertySet> xSet(_xTable,UNO_QUERY); + fillTableName(xSet); + + ::rtl::OUStringBuffer aSql = ::rtl::OUString::createFromAscii("DELETE FROM "); + aSql.append(m_aComposedTableName); + aSql.append(::rtl::OUString::createFromAscii(" WHERE ")); + + // list all cloumns that should be set + const ::rtl::OUString aQuote = getIdentifierQuoteString(); + static ::rtl::OUString aAnd = ::rtl::OUString::createFromAscii(" AND "); + static ::rtl::OUString aOr = ::rtl::OUString::createFromAscii(" OR "); + static ::rtl::OUString aEqual = ::rtl::OUString::createFromAscii(" = ?"); + + + // use keys and indexes for excat postioning + // first the keys + Reference<XNameAccess> xKeyColumns = getKeyColumns(); + + ::rtl::OUStringBuffer aCondition = ::rtl::OUString::createFromAscii("( "); + + SelectColumnsMetaData::const_iterator aIter = (*m_pKeyColumnNames).begin(); + SelectColumnsMetaData::const_iterator aPosEnd = (*m_pKeyColumnNames).end(); + for(;aIter != aPosEnd;++aIter) + { + aCondition.append(::dbtools::quoteName( aQuote,aIter->second.sRealName)); + aCondition.append(aEqual); + aCondition.append(aAnd); + } + aCondition.setLength(aCondition.getLength()-5); + const ::rtl::OUString sCon( aCondition.makeStringAndClear() ); + + const Any* pBegin = rows.getConstArray(); + const Any* pEnd = pBegin + rows.getLength(); + + Sequence< Any > aKeys; + for(;pBegin != pEnd;++pBegin) + { + aSql.append(sCon); + aSql.append(aOr); + } + aSql.setLength(aSql.getLength()-3); + + // now create end execute the prepared statement + + Reference< XPreparedStatement > xPrep(m_xConnection->prepareStatement(aSql.makeStringAndClear())); + Reference< XParameters > xParameter(xPrep,UNO_QUERY); + + pBegin = rows.getConstArray(); + sal_Int32 i=1; + for(;pBegin != pEnd;++pBegin) + { + m_aKeyIter = m_aKeyMap.find(::comphelper::getINT32(*pBegin)); + if(m_aKeyIter != m_aKeyMap.end()) + { + connectivity::ORowVector< ORowSetValue >::Vector::iterator aKeyIter = m_aKeyIter->second.first->get().begin(); + connectivity::ORowVector< ORowSetValue >::Vector::iterator aKeyEnd = m_aKeyIter->second.first->get().end(); + SelectColumnsMetaData::const_iterator aPosIter = (*m_pKeyColumnNames).begin(); + for(sal_uInt16 j = 0;aKeyIter != aKeyEnd;++aKeyIter,++j,++aPosIter) + { + setParameter(i++,xParameter,*aKeyIter,aPosIter->second.nType,aPosIter->second.nScale); + } + } + } + + sal_Bool bOk = xPrep->executeUpdate() > 0; + Sequence< sal_Int32 > aRet(rows.getLength()); + memset(aRet.getArray(),bOk,sizeof(sal_Int32)*aRet.getLength()); + if(bOk) + { + pBegin = rows.getConstArray(); + pEnd = pBegin + rows.getLength(); + + for(;pBegin != pEnd;++pBegin) + { + sal_Int32 nPos = 0; + *pBegin >>= nPos; + if(m_aKeyIter == m_aKeyMap.find(nPos) && m_aKeyIter != m_aKeyMap.end()) + ++m_aKeyIter; + m_aKeyMap.erase(nPos); + m_bDeleted = sal_True; + } + } + return aRet; +} +// ------------------------------------------------------------------------- +void SAL_CALL OKeySet::updateRow(const ORowSetRow& _rInsertRow ,const ORowSetRow& _rOrginalRow,const connectivity::OSQLTable& _xTable ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::updateRow" ); + Reference<XPropertySet> xSet(_xTable,UNO_QUERY); + fillTableName(xSet); + + ::rtl::OUStringBuffer aSql = ::rtl::OUString::createFromAscii("UPDATE "); + aSql.append(m_aComposedTableName); + aSql.append(::rtl::OUString::createFromAscii(" SET ")); + // list all cloumns that should be set + static ::rtl::OUString aPara = ::rtl::OUString::createFromAscii(" = ?,"); + ::rtl::OUString aQuote = getIdentifierQuoteString(); + static ::rtl::OUString aAnd = ::rtl::OUString::createFromAscii(" AND "); + ::rtl::OUString sIsNull(RTL_CONSTASCII_USTRINGPARAM(" IS NULL")); + ::rtl::OUString sParam(RTL_CONSTASCII_USTRINGPARAM(" = ?")); + + // use keys and indexes for excat postioning + // first the keys + Reference<XNameAccess> xKeyColumns = getKeyColumns(); + + // second the indexes + Reference<XIndexesSupplier> xIndexSup(_xTable,UNO_QUERY); + Reference<XIndexAccess> xIndexes; + if ( xIndexSup.is() ) + xIndexes.set(xIndexSup->getIndexes(),UNO_QUERY); + + + ::std::vector< Reference<XNameAccess> > aAllIndexColumns; + lcl_fillIndexColumns(xIndexes,aAllIndexColumns); + + ::rtl::OUString aColumnName; + ::rtl::OUStringBuffer sKeyCondition,sIndexCondition; + ::std::vector<sal_Int32> aIndexColumnPositions; + + const sal_Int32 nOldLength = aSql.getLength(); + sal_Int32 i = 1; + // here we build the condition part for the update statement + SelectColumnsMetaData::const_iterator aIter = m_pColumnNames->begin(); + SelectColumnsMetaData::const_iterator aEnd = m_pColumnNames->end(); + for(;aIter != aEnd;++aIter,++i) + { + //if(xKeyColumns.is() && xKeyColumns->hasByName(aIter->first)) + if ( m_pKeyColumnNames->find(aIter->first) != m_pKeyColumnNames->end() ) + { + sKeyCondition.append(::dbtools::quoteName( aQuote,aIter->second.sRealName)); + if((_rOrginalRow->get())[aIter->second.nPosition].isNull()) + sKeyCondition.append(sIsNull); + else + sKeyCondition.append(sParam); + sKeyCondition.append(aAnd); + } + else + { + ::std::vector< Reference<XNameAccess> >::const_iterator aIndexEnd = aAllIndexColumns.end(); + for( ::std::vector< Reference<XNameAccess> >::const_iterator aIndexIter = aAllIndexColumns.begin(); + aIndexIter != aIndexEnd;++aIndexIter) + { + if((*aIndexIter)->hasByName(aIter->first)) + { + sIndexCondition.append(::dbtools::quoteName( aQuote,aIter->second.sRealName)); + if((_rOrginalRow->get())[aIter->second.nPosition].isNull()) + sIndexCondition.append(sIsNull); + else + { + sIndexCondition.append(sParam); + aIndexColumnPositions.push_back(aIter->second.nPosition); + } + sIndexCondition.append(aAnd); + break; + } + } + } + if((_rInsertRow->get())[aIter->second.nPosition].isModified()) + { + aSql.append(::dbtools::quoteName( aQuote,aIter->second.sRealName)); + aSql.append(aPara); + } + } + + if( aSql.getLength() != nOldLength ) + { + aSql.setLength(aSql.getLength()-1); + } + else + ::dbtools::throwSQLException( DBACORE_RESSTRING( RID_STR_NO_VALUE_CHANGED ), SQL_GENERAL_ERROR, m_xConnection ); + + if(sKeyCondition.getLength() || sIndexCondition.getLength()) + { + aSql.append(::rtl::OUString::createFromAscii(" WHERE ")); + if(sKeyCondition.getLength() && sIndexCondition.getLength()) + { + aSql.append(sKeyCondition.makeStringAndClear()); + aSql.append(sIndexCondition.makeStringAndClear()); + } + else if(sKeyCondition.getLength()) + { + aSql.append(sKeyCondition.makeStringAndClear()); + } + else if(sIndexCondition.getLength()) + { + aSql.append(sIndexCondition.makeStringAndClear()); + } + aSql.setLength(aSql.getLength()-5); // remove the last AND + } + else + ::dbtools::throwSQLException( DBACORE_RESSTRING( RID_STR_NO_CONDITION_FOR_PK ), SQL_GENERAL_ERROR, m_xConnection ); + + // now create end execute the prepared statement + + ::rtl::OUString sEmpty; + executeUpdate(_rInsertRow ,_rOrginalRow,aSql.makeStringAndClear(),sEmpty,aIndexColumnPositions); +} +// ----------------------------------------------------------------------------- +void OKeySet::executeUpdate(const ORowSetRow& _rInsertRow ,const ORowSetRow& _rOrginalRow,const ::rtl::OUString& i_sSQL,const ::rtl::OUString& i_sTableName,const ::std::vector<sal_Int32>& _aIndexColumnPositions) +{ + // now create end execute the prepared statement + Reference< XPreparedStatement > xPrep(m_xConnection->prepareStatement(i_sSQL)); + Reference< XParameters > xParameter(xPrep,UNO_QUERY); + + bool bRefetch = true; + Reference<XRow> xRow; + sal_Int32 i = 1; + // first the set values + SelectColumnsMetaData::const_iterator aIter = m_pColumnNames->begin(); + SelectColumnsMetaData::const_iterator aEnd = m_pColumnNames->end(); + sal_uInt16 j = 0; + for(;aIter != aEnd;++aIter,++j) + { + if ( !i_sTableName.getLength() || aIter->second.sTableName == i_sTableName ) + { + sal_Int32 nPos = aIter->second.nPosition; + if((_rInsertRow->get())[nPos].isModified()) + { + if ( bRefetch ) + { + bRefetch = ::std::find(m_aFilterColumns.begin(),m_aFilterColumns.end(),aIter->second.sRealName) == m_aFilterColumns.end(); + } + impl_convertValue_throw(_rInsertRow,aIter->second); + (_rInsertRow->get())[nPos].setSigned((_rOrginalRow->get())[nPos].isSigned()); + setParameter(i++,xParameter,(_rInsertRow->get())[nPos],aIter->second.nType,aIter->second.nScale); + } + } + } + // and then the values of the where condition + aIter = m_pKeyColumnNames->begin(); + aEnd = m_pKeyColumnNames->end(); + j = 0; + for(;aIter != aEnd;++aIter,++j) + { + if ( !i_sTableName.getLength() || aIter->second.sTableName == i_sTableName ) + { + setParameter(i++,xParameter,(_rOrginalRow->get())[aIter->second.nPosition],aIter->second.nType,aIter->second.nScale); + } + } + if ( !_aIndexColumnPositions.empty() ) + { + // now we have to set the index values + ::std::vector<sal_Int32>::const_iterator aIdxColIter = _aIndexColumnPositions.begin(); + ::std::vector<sal_Int32>::const_iterator aIdxColEnd = _aIndexColumnPositions.end(); + j = 0; + aIter = m_pColumnNames->begin(); + for(;aIdxColIter != aIdxColEnd;++aIdxColIter,++i,++j,++aIter) + { + setParameter(i,xParameter,(_rOrginalRow->get())[*aIdxColIter],(_rOrginalRow->get())[*aIdxColIter].getTypeKind(),aIter->second.nScale); + } + } + const sal_Int32 nRowsUpdated = xPrep->executeUpdate(); + m_bUpdated = nRowsUpdated > 0; + if(m_bUpdated) + { + const sal_Int32 nBookmark = ::comphelper::getINT32((_rInsertRow->get())[0].getAny()); + m_aKeyIter = m_aKeyMap.find(nBookmark); + m_aKeyIter->second.second.first = 2; + m_aKeyIter->second.second.second = xRow; + copyRowValue(_rInsertRow,m_aKeyIter->second.first,nBookmark); + tryRefetch(_rInsertRow,bRefetch); + } +} +// ------------------------------------------------------------------------- +void SAL_CALL OKeySet::insertRow( const ORowSetRow& _rInsertRow,const connectivity::OSQLTable& _xTable ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::insertRow" ); + ::rtl::OUStringBuffer aSql(::rtl::OUString::createFromAscii("INSERT INTO ")); + Reference<XPropertySet> xSet(_xTable,UNO_QUERY); + fillTableName(xSet); + + aSql.append(m_aComposedTableName); + aSql.append(::rtl::OUString::createFromAscii(" ( ")); + // set values and column names + ::rtl::OUStringBuffer aValues(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" VALUES ( "))); + static ::rtl::OUString aPara(RTL_CONSTASCII_USTRINGPARAM("?,")); + ::rtl::OUString aQuote = getIdentifierQuoteString(); + static ::rtl::OUString aComma(RTL_CONSTASCII_USTRINGPARAM(",")); + + SelectColumnsMetaData::const_iterator aIter = m_pColumnNames->begin(); + SelectColumnsMetaData::const_iterator aEnd = m_pColumnNames->end(); + sal_Int32 j = 1; + bool bRefetch = true; + sal_Bool bModified = sal_False; + for(;aIter != aEnd;++aIter,++j) + { + if((_rInsertRow->get())[aIter->second.nPosition].isModified()) + { + if ( bRefetch ) + { + bRefetch = ::std::find(m_aFilterColumns.begin(),m_aFilterColumns.end(),aIter->second.sRealName) == m_aFilterColumns.end(); + } + aSql.append(::dbtools::quoteName( aQuote,aIter->second.sRealName)); + aSql.append(aComma); + aValues.append(aPara); + bModified = sal_True; + } + } + if ( !bModified ) + ::dbtools::throwSQLException( DBACORE_RESSTRING( RID_STR_NO_VALUE_CHANGED ), SQL_GENERAL_ERROR, m_xConnection ); + + aSql.setCharAt(aSql.getLength()-1,')'); + aValues.setCharAt(aValues.getLength()-1,')'); + aSql.append(aValues.makeStringAndClear()); + // now create,fill and execute the prepared statement + ::rtl::OUString sEmpty; + executeInsert(_rInsertRow,aSql.makeStringAndClear(),sEmpty,bRefetch); +} +// ------------------------------------------------------------------------- +void OKeySet::executeInsert( const ORowSetRow& _rInsertRow,const ::rtl::OUString& i_sSQL,const ::rtl::OUString& i_sTableName,bool bRefetch ) +{ + // now create,fill and execute the prepared statement + Reference< XPreparedStatement > xPrep(m_xConnection->prepareStatement(i_sSQL)); + Reference< XParameters > xParameter(xPrep,UNO_QUERY); + + SelectColumnsMetaData::const_iterator aIter = m_pColumnNames->begin(); + SelectColumnsMetaData::const_iterator aEnd = m_pColumnNames->end(); + for(sal_Int32 i = 1;aIter != aEnd;++aIter) + { + if ( !i_sTableName.getLength() || aIter->second.sTableName == i_sTableName ) + { + const sal_Int32 nPos = aIter->second.nPosition; + if((_rInsertRow->get())[nPos].isModified()) + { + if((_rInsertRow->get())[nPos].isNull()) + xParameter->setNull(i++,(_rInsertRow->get())[nPos].getTypeKind()); + else + { + impl_convertValue_throw(_rInsertRow,aIter->second); + (_rInsertRow->get())[nPos].setSigned(m_aSignedFlags[nPos-1]); + setParameter(i++,xParameter,(_rInsertRow->get())[nPos],aIter->second.nType,aIter->second.nScale); + } + } + } + } + + m_bInserted = xPrep->executeUpdate() > 0; + sal_Bool bAutoValuesFetched = sal_False; + if ( m_bInserted ) + { + // first insert the default values into the insertrow + aIter = m_pColumnNames->begin(); + for(;aIter != aEnd;++aIter) + { + if ( !(_rInsertRow->get())[aIter->second.nPosition].isModified() ) + (_rInsertRow->get())[aIter->second.nPosition] = aIter->second.sDefaultValue; + } + try + { + Reference< XGeneratedResultSet > xGRes(xPrep, UNO_QUERY); + if ( xGRes.is() ) + { + Reference< XResultSet > xRes = xGRes->getGeneratedValues(); + Reference< XRow > xRow(xRes,UNO_QUERY); + if ( xRow.is() && xRes->next() ) + { + Reference< XResultSetMetaDataSupplier > xMdSup(xRes,UNO_QUERY); + Reference< XResultSetMetaData > xMd = xMdSup->getMetaData(); + sal_Int32 nColumnCount = xMd->getColumnCount(); + ::std::vector< ::rtl::OUString >::iterator aAutoIter = m_aAutoColumns.begin(); + ::std::vector< ::rtl::OUString >::iterator aAutoEnd = m_aAutoColumns.end(); + for (sal_Int32 i = 1;aAutoIter != aAutoEnd && i <= nColumnCount; ++aAutoIter,++i) + { +#if OSL_DEBUG_LEVEL > 1 + ::rtl::OUString sColumnName( xMd->getColumnName(i) ); +#endif + SelectColumnsMetaData::iterator aFind = m_pKeyColumnNames->find(*aAutoIter); + if ( aFind != m_pKeyColumnNames->end() ) + (_rInsertRow->get())[aFind->second.nPosition].fill(i,aFind->second.nType,aFind->second.bNullable,xRow); + } + bAutoValuesFetched = sal_True; + } + } + } + catch(Exception&) + { + OSL_ENSURE(0,"Could not execute GeneratedKeys() stmt"); + } + } + + ::comphelper::disposeComponent(xPrep); + + if ( !i_sTableName.getLength() && !bAutoValuesFetched && m_bInserted ) + { + // first check if all key column values were set + const ::rtl::OUString sMax(RTL_CONSTASCII_USTRINGPARAM(" MAX(")); + const ::rtl::OUString sMaxEnd(RTL_CONSTASCII_USTRINGPARAM("),")); + const ::rtl::OUString sQuote = getIdentifierQuoteString(); + ::rtl::OUString sMaxStmt; + aEnd = m_pKeyColumnNames->end(); + ::std::vector< ::rtl::OUString >::iterator aAutoIter = m_aAutoColumns.begin(); + ::std::vector< ::rtl::OUString >::iterator aAutoEnd = m_aAutoColumns.end(); + for (;aAutoIter != aAutoEnd; ++aAutoIter) + { + // we will only fetch values which are keycolumns + SelectColumnsMetaData::iterator aFind = m_pKeyColumnNames->find(*aAutoIter); + if ( aFind != aEnd ) + { + sMaxStmt += sMax; + sMaxStmt += ::dbtools::quoteName( sQuote,aFind->second.sRealName +); + sMaxStmt += sMaxEnd; + } + } + + if(sMaxStmt.getLength()) + { + sMaxStmt = sMaxStmt.replaceAt(sMaxStmt.getLength()-1,1,::rtl::OUString::createFromAscii(" ")); + ::rtl::OUString sStmt = ::rtl::OUString::createFromAscii("SELECT "); + sStmt += sMaxStmt; + sStmt += ::rtl::OUString::createFromAscii("FROM "); + ::rtl::OUString sCatalog,sSchema,sTable; + ::dbtools::qualifiedNameComponents(m_xConnection->getMetaData(),m_sUpdateTableName,sCatalog,sSchema,sTable,::dbtools::eInDataManipulation); + sStmt += ::dbtools::composeTableNameForSelect( m_xConnection, sCatalog, sSchema, sTable ); + try + { + // now fetch the autoincrement values + Reference<XStatement> xStatement = m_xConnection->createStatement(); + Reference<XResultSet> xRes = xStatement->executeQuery(sStmt); + Reference<XRow> xRow(xRes,UNO_QUERY); + if(xRow.is() && xRes->next()) + { + aAutoIter = m_aAutoColumns.begin(); + for (sal_Int32 i=1;aAutoIter != aAutoEnd; ++aAutoIter,++i) + { + // we will only fetch values which are keycolumns + SelectColumnsMetaData::iterator aFind = m_pKeyColumnNames->find(*aAutoIter); + if ( aFind != aEnd ) + (_rInsertRow->get())[aFind->second.nPosition].fill(i,aFind->second.nType,aFind->second.bNullable,xRow); + } + } + ::comphelper::disposeComponent(xStatement); + } + catch(SQLException&) + { + OSL_ENSURE(0,"Could not fetch with MAX() "); + } + } + } + if ( m_bInserted ) + { + OKeySetMatrix::iterator aKeyIter = m_aKeyMap.end(); + --aKeyIter; + ORowSetRow aKeyRow = new connectivity::ORowVector< ORowSetValue >(m_pKeyColumnNames->size()); + copyRowValue(_rInsertRow,aKeyRow,aKeyIter->first + 1); + + m_aKeyIter = m_aKeyMap.insert(OKeySetMatrix::value_type(aKeyIter->first + 1,OKeySetValue(aKeyRow,::std::pair<sal_Int32,Reference<XRow> >(1,NULL)))).first; + // now we set the bookmark for this row + (_rInsertRow->get())[0] = makeAny((sal_Int32)m_aKeyIter->first); + tryRefetch(_rInsertRow,bRefetch); + } +} +void OKeySet::tryRefetch(const ORowSetRow& _rInsertRow,bool bRefetch) +{ + if ( bRefetch ) + { + // we just areassign the base members + try + { + Reference< XParameters > xParameter(m_xStatement,UNO_QUERY); + OSL_ENSURE(xParameter.is(),"No Parameter interface!"); + xParameter->clearParameters(); + + sal_Int32 nPos=1; + connectivity::ORowVector< ORowSetValue >::Vector::const_iterator aParaIter; + connectivity::ORowVector< ORowSetValue >::Vector::const_iterator aParaEnd; + OUpdatedParameter::iterator aUpdateFind = m_aUpdatedParameter.find(m_aKeyIter->first); + if ( aUpdateFind == m_aUpdatedParameter.end() ) + { + aParaIter = m_aParameterValueForCache.get().begin(); + aParaEnd = m_aParameterValueForCache.get().end(); + } + else + { + aParaIter = aUpdateFind->second.get().begin(); + aParaEnd = aUpdateFind->second.get().end(); + } + + for(++aParaIter;aParaIter != aParaEnd;++aParaIter,++nPos) + { + ::dbtools::setObjectWithInfo( xParameter, nPos, aParaIter->makeAny(), aParaIter->getTypeKind() ); + } + connectivity::ORowVector< ORowSetValue >::Vector::const_iterator aIter2 = m_aKeyIter->second.first->get().begin(); + SelectColumnsMetaData::const_iterator aPosIter = (*m_pKeyColumnNames).begin(); + SelectColumnsMetaData::const_iterator aPosEnd = (*m_pKeyColumnNames).end(); + for(;aPosIter != aPosEnd;++aPosIter,++aIter2,++nPos) + setParameter(nPos,xParameter,*aIter2,aPosIter->second.nType,aPosIter->second.nScale); + aPosIter = (*m_pForeignColumnNames).begin(); + aPosEnd = (*m_pForeignColumnNames).end(); + for(;aPosIter != aPosEnd;++aPosIter,++aIter2,++nPos) + setParameter(nPos,xParameter,*aIter2,aPosIter->second.nType,aPosIter->second.nScale); + + m_xSet = m_xStatement->executeQuery(); + OSL_ENSURE(m_xSet.is(),"No resultset form statement!"); + bRefetch = m_xSet->next(); + } + catch(Exception) + { + bRefetch = false; + } + } + if ( !bRefetch ) + { + m_aKeyIter->second.second.second = new OPrivateRow(_rInsertRow->get()); + } +} +// ----------------------------------------------------------------------------- +void OKeySet::copyRowValue(const ORowSetRow& _rInsertRow,ORowSetRow& _rKeyRow,sal_Int32 i_nBookmark) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::copyRowValue" ); + connectivity::ORowVector< ORowSetValue >::Vector::iterator aIter = _rKeyRow->get().begin(); + + // check the if the parameter values have been changed + OSL_ENSURE((m_aParameterValueForCache.get().size()-1) == m_pParameterNames->size(),"OKeySet::copyRowValue: Parameter values and names differ!"); + connectivity::ORowVector< ORowSetValue >::Vector::const_iterator aParaValuesIter = m_aParameterValueForCache.get().begin() +1; + + bool bChanged = false; + SelectColumnsMetaData::const_iterator aParaIter = (*m_pParameterNames).begin(); + SelectColumnsMetaData::const_iterator aParaEnd = (*m_pParameterNames).end(); + for(sal_Int32 i = 1;aParaIter != aParaEnd;++aParaIter,++aParaValuesIter,++i) + { + ORowSetValue aValue(*aParaValuesIter); + aValue.setSigned(m_aSignedFlags[aParaIter->second.nPosition]); + if ( (_rInsertRow->get())[aParaIter->second.nPosition] != aValue ) + { + ORowSetValueVector aCopy(m_aParameterValueForCache); + (aCopy.get())[i] = (_rInsertRow->get())[aParaIter->second.nPosition]; + m_aUpdatedParameter[i_nBookmark] = aCopy; + bChanged = true; + } + } + if ( !bChanged ) + { + m_aUpdatedParameter.erase(i_nBookmark); + } + + // update the key values + SelectColumnsMetaData::const_iterator aPosIter = (*m_pKeyColumnNames).begin(); + SelectColumnsMetaData::const_iterator aPosEnd = (*m_pKeyColumnNames).end(); + for(;aPosIter != aPosEnd;++aPosIter,++aIter) + { + *aIter = (_rInsertRow->get())[aPosIter->second.nPosition]; + impl_convertValue_throw(_rKeyRow,aPosIter->second); + aIter->setTypeKind(aPosIter->second.nType); + } +} +// ------------------------------------------------------------------------- +void SAL_CALL OKeySet::deleteRow(const ORowSetRow& _rDeleteRow,const connectivity::OSQLTable& _xTable ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::deleteRow" ); + Reference<XPropertySet> xSet(_xTable,UNO_QUERY); + fillTableName(xSet); + + ::rtl::OUStringBuffer aSql = ::rtl::OUString::createFromAscii("DELETE FROM "); + aSql.append(m_aComposedTableName); + aSql.append(::rtl::OUString::createFromAscii(" WHERE ")); + + // list all cloumns that should be set + ::rtl::OUString aQuote = getIdentifierQuoteString(); + static ::rtl::OUString aAnd = ::rtl::OUString::createFromAscii(" AND "); + + // use keys and indexes for excat postioning + Reference<XNameAccess> xKeyColumns = getKeyColumns(); + // second the indexes + Reference<XIndexesSupplier> xIndexSup(_xTable,UNO_QUERY); + Reference<XIndexAccess> xIndexes; + if ( xIndexSup.is() ) + xIndexes.set(xIndexSup->getIndexes(),UNO_QUERY); + + // Reference<XColumnsSupplier> + ::std::vector< Reference<XNameAccess> > aAllIndexColumns; + lcl_fillIndexColumns(xIndexes,aAllIndexColumns); + + ::rtl::OUString aColumnName; + ::rtl::OUStringBuffer sIndexCondition; + ::std::vector<sal_Int32> aIndexColumnPositions; + SelectColumnsMetaData::const_iterator aIter = m_pColumnNames->begin(); + SelectColumnsMetaData::const_iterator aEnd = m_pColumnNames->end(); + + sal_Int32 i = 1; + for(i = 1;aIter != aEnd;++aIter,++i) + { + if ( m_pKeyColumnNames->find(aIter->first) != m_pKeyColumnNames->end() ) + { + aSql.append(::dbtools::quoteName( aQuote,aIter->second.sRealName)); + if((_rDeleteRow->get())[aIter->second.nPosition].isNull()) + { + OSL_ENSURE(0,"can a primary key be null"); + aSql.append(::rtl::OUString::createFromAscii(" IS NULL")); + } + else + aSql.append(::rtl::OUString::createFromAscii(" = ?")); + aSql.append(aAnd); + } + else + { + ::std::vector< Reference<XNameAccess> >::const_iterator aIndexEnd = aAllIndexColumns.end(); + for( ::std::vector< Reference<XNameAccess> >::const_iterator aIndexIter = aAllIndexColumns.begin(); + aIndexIter != aIndexEnd;++aIndexIter) + { + if((*aIndexIter)->hasByName(aIter->first)) + { + sIndexCondition.append(::dbtools::quoteName( aQuote,aIter->second.sRealName)); + if((_rDeleteRow->get())[aIter->second.nPosition].isNull()) + sIndexCondition.append(::rtl::OUString::createFromAscii(" IS NULL")); + else + { + sIndexCondition.append(::rtl::OUString::createFromAscii(" = ?")); + aIndexColumnPositions.push_back(aIter->second.nPosition); + } + sIndexCondition.append(aAnd); + + break; + } + } + } + } + aSql.append(sIndexCondition.makeStringAndClear()); + aSql.setLength(aSql.getLength()-5); + + // now create end execute the prepared statement + Reference< XPreparedStatement > xPrep(m_xConnection->prepareStatement(aSql.makeStringAndClear())); + Reference< XParameters > xParameter(xPrep,UNO_QUERY); + + aIter = (*m_pKeyColumnNames).begin(); + aEnd = (*m_pKeyColumnNames).end(); + i = 1; + for(;aIter != aEnd;++aIter,++i) + { + setParameter(i,xParameter,(_rDeleteRow->get())[aIter->second.nPosition],aIter->second.nType,aIter->second.nScale); + } + + // now we have to set the index values + ::std::vector<sal_Int32>::iterator aIdxColIter = aIndexColumnPositions.begin(); + ::std::vector<sal_Int32>::iterator aIdxColEnd = aIndexColumnPositions.end(); + aIter = m_pColumnNames->begin(); + for(;aIdxColIter != aIdxColEnd;++aIdxColIter,++i,++aIter) + { + setParameter(i,xParameter,(_rDeleteRow->get())[*aIdxColIter],(_rDeleteRow->get())[*aIdxColIter].getTypeKind(),aIter->second.nScale); + } + + m_bDeleted = xPrep->executeUpdate() > 0; + + if(m_bDeleted) + { + sal_Int32 nBookmark = ::comphelper::getINT32((_rDeleteRow->get())[0].getAny()); + if(m_aKeyIter == m_aKeyMap.find(nBookmark) && m_aKeyIter != m_aKeyMap.end()) + ++m_aKeyIter; + m_aKeyMap.erase(nBookmark); + m_bDeleted = sal_True; + } +} +// ------------------------------------------------------------------------- +void SAL_CALL OKeySet::cancelRowUpdates( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::cancelRowUpdates" ); + m_bInserted = m_bUpdated = m_bDeleted = sal_False; +} +// ------------------------------------------------------------------------- +void SAL_CALL OKeySet::moveToInsertRow( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::moveToInsertRow" ); +} +// ------------------------------------------------------------------------- +void SAL_CALL OKeySet::moveToCurrentRow( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::moveToCurrentRow" ); +} +// ------------------------------------------------------------------------- +Reference<XNameAccess> OKeySet::getKeyColumns() const +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::getKeyColumns" ); + // use keys and indexes for excat postioning + // first the keys + + Reference<XIndexAccess> xKeys = m_xTableKeys; + if ( !xKeys.is() ) + { + Reference<XPropertySet> xSet(m_xTable,UNO_QUERY); + const Reference<XNameAccess> xPrimaryKeyColumns = getPrimaryKeyColumns_throw(xSet); + return xPrimaryKeyColumns; + } + + Reference<XColumnsSupplier> xKeyColsSup; + Reference<XNameAccess> xKeyColumns; + if(xKeys.is()) + { + Reference<XPropertySet> xProp; + sal_Int32 nCount = xKeys->getCount(); + for(sal_Int32 i = 0;i< nCount;++i) + { + xProp.set(xKeys->getByIndex(i),UNO_QUERY); + if ( xProp.is() ) + { + sal_Int32 nKeyType = 0; + xProp->getPropertyValue(PROPERTY_TYPE) >>= nKeyType; + if(KeyType::PRIMARY == nKeyType) + { + xKeyColsSup.set(xProp,UNO_QUERY); + OSL_ENSURE(xKeyColsSup.is(),"Columnsupplier is null!"); + xKeyColumns = xKeyColsSup->getColumns(); + break; + } + } + } + } + + return xKeyColumns; +} +// ----------------------------------------------------------------------------- +sal_Bool SAL_CALL OKeySet::next( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::next" ); + m_bInserted = m_bUpdated = m_bDeleted = sal_False; + + if(isAfterLast()) + return sal_False; + if(!m_bRowCountFinal) // not yet all records fetched + { + ++m_aKeyIter; // this is possible because we stand on begin() and this is the "beforefirst" row + if(m_aKeyIter == m_aKeyMap.end() && !fetchRow()) + m_aKeyIter = m_aKeyMap.end(); + } + else if(!isAfterLast()) + ++m_aKeyIter; + + refreshRow(); + return !isAfterLast(); +} +// ----------------------------------------------------------------------------- +sal_Bool SAL_CALL OKeySet::isBeforeFirst( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::isBeforeFirst" ); + return m_aKeyIter == m_aKeyMap.begin(); +} +// ----------------------------------------------------------------------------- +sal_Bool SAL_CALL OKeySet::isAfterLast( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::isAfterLast" ); + return m_bRowCountFinal && m_aKeyIter == m_aKeyMap.end(); +} +// ----------------------------------------------------------------------------- +sal_Bool SAL_CALL OKeySet::isFirst( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::isFirst" ); + OKeySetMatrix::iterator aTemp = m_aKeyMap.begin(); + ++aTemp; + return m_aKeyIter == aTemp && m_aKeyIter != m_aKeyMap.end(); +} +// ----------------------------------------------------------------------------- +sal_Bool SAL_CALL OKeySet::isLast( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::isLast" ); + if(!m_bRowCountFinal) + return sal_False; + + OKeySetMatrix::iterator aTemp = m_aKeyMap.end(); + --aTemp; + return m_aKeyIter == aTemp; +} +// ----------------------------------------------------------------------------- +void SAL_CALL OKeySet::beforeFirst( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::beforeFirst" ); + m_bInserted = m_bUpdated = m_bDeleted = sal_False; + m_aKeyIter = m_aKeyMap.begin(); + m_xRow = NULL; + ::comphelper::disposeComponent(m_xSet); +} +// ----------------------------------------------------------------------------- +void SAL_CALL OKeySet::afterLast( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::afterLast" ); + m_bInserted = m_bUpdated = m_bDeleted = sal_False; + fillAllRows(); + m_aKeyIter = m_aKeyMap.end(); + m_xRow = NULL; + ::comphelper::disposeComponent(m_xSet); +} +// ----------------------------------------------------------------------------- +sal_Bool SAL_CALL OKeySet::first( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::first" ); + m_bInserted = m_bUpdated = m_bDeleted = sal_False; + m_aKeyIter = m_aKeyMap.begin(); + ++m_aKeyIter; + if(m_aKeyIter == m_aKeyMap.end() && !fetchRow()) + m_aKeyIter = m_aKeyMap.end(); + + refreshRow(); + return m_aKeyIter != m_aKeyMap.end() && m_aKeyIter != m_aKeyMap.begin(); +} +// ----------------------------------------------------------------------------- +sal_Bool SAL_CALL OKeySet::last( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::last" ); + m_bInserted = m_bUpdated = m_bDeleted = sal_False; + fillAllRows(); + + m_aKeyIter = m_aKeyMap.end(); + --m_aKeyIter; + refreshRow(); + return m_aKeyIter != m_aKeyMap.end() && m_aKeyIter != m_aKeyMap.begin(); +} +// ----------------------------------------------------------------------------- +sal_Int32 SAL_CALL OKeySet::getRow( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::getRow" ); + OSL_ENSURE(!isAfterLast(),"getRow is not allowed when afterlast record!"); + OSL_ENSURE(!isBeforeFirst(),"getRow is not allowed when beforefirst record!"); + + return ::std::distance(m_aKeyMap.begin(),m_aKeyIter); +} +// ----------------------------------------------------------------------------- +sal_Bool SAL_CALL OKeySet::absolute( sal_Int32 row ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::absolute" ); + m_bInserted = m_bUpdated = m_bDeleted = sal_False; + OSL_ENSURE(row,"absolute(0) isn't allowed!"); + if(row < 0) + { + if(!m_bRowCountFinal) + fillAllRows(); + + for(;row < 0 && m_aKeyIter != m_aKeyMap.begin();++row) + m_aKeyIter--; + } + else + { + if(row >= (sal_Int32)m_aKeyMap.size()) + { + if(!m_bRowCountFinal) + { + sal_Bool bNext = sal_True; + for(sal_Int32 i=m_aKeyMap.size()-1;i < row && bNext;++i) + bNext = fetchRow(); + } + else + m_aKeyIter = m_aKeyMap.end(); + } + else + { + m_aKeyIter = m_aKeyMap.begin(); + for(;row > 0 && m_aKeyIter != m_aKeyMap.end();--row) + ++m_aKeyIter; + } + } + refreshRow(); + + return m_aKeyIter != m_aKeyMap.end() && m_aKeyIter != m_aKeyMap.begin(); +} +// ----------------------------------------------------------------------------- +sal_Bool SAL_CALL OKeySet::relative( sal_Int32 rows ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::relative" ); + if(!rows) + { + refreshRow(); + return sal_True; + } + return absolute(getRow()+rows); +} +// ----------------------------------------------------------------------------- +sal_Bool SAL_CALL OKeySet::previous( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::previous" ); + m_bInserted = m_bUpdated = m_bDeleted = sal_False; + if(m_aKeyIter != m_aKeyMap.begin()) + { + --m_aKeyIter; + refreshRow(); + } + return m_aKeyIter != m_aKeyMap.begin(); +} +// ----------------------------------------------------------------------------- +void SAL_CALL OKeySet::refreshRow() throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::refreshRow" ); + if(isBeforeFirst() || isAfterLast() || !m_xStatement.is()) + return; + + m_xRow = NULL; + ::comphelper::disposeComponent(m_xSet); + + if ( m_aKeyIter->second.second.second.is() ) + { + m_xRow = m_aKeyIter->second.second.second; + return; + } + // we just areassign the base members + Reference< XParameters > xParameter(m_xStatement,UNO_QUERY); + OSL_ENSURE(xParameter.is(),"No Parameter interface!"); + xParameter->clearParameters(); + + sal_Int32 nPos=1; + connectivity::ORowVector< ORowSetValue >::Vector::const_iterator aParaIter; + connectivity::ORowVector< ORowSetValue >::Vector::const_iterator aParaEnd; + OUpdatedParameter::iterator aUpdateFind = m_aUpdatedParameter.find(m_aKeyIter->first); + if ( aUpdateFind == m_aUpdatedParameter.end() ) + { + aParaIter = m_aParameterValueForCache.get().begin(); + aParaEnd = m_aParameterValueForCache.get().end(); + } + else + { + aParaIter = aUpdateFind->second.get().begin(); + aParaEnd = aUpdateFind->second.get().end(); + } + + for(++aParaIter;aParaIter != aParaEnd;++aParaIter,++nPos) + { + ::dbtools::setObjectWithInfo( xParameter, nPos, aParaIter->makeAny(), aParaIter->getTypeKind() ); + } + + // now set the primary key column values + connectivity::ORowVector< ORowSetValue >::Vector::const_iterator aIter = m_aKeyIter->second.first->get().begin(); + SelectColumnsMetaData::const_iterator aPosIter = (*m_pKeyColumnNames).begin(); + SelectColumnsMetaData::const_iterator aPosEnd = (*m_pKeyColumnNames).end(); + for(;aPosIter != aPosEnd;++aPosIter,++aIter,++nPos) + setParameter(nPos,xParameter,*aIter,aPosIter->second.nType,aPosIter->second.nScale); + aPosIter = (*m_pForeignColumnNames).begin(); + aPosEnd = (*m_pForeignColumnNames).end(); + for(;aPosIter != aPosEnd;++aPosIter,++aIter,++nPos) + setParameter(nPos,xParameter,*aIter,aPosIter->second.nType,aPosIter->second.nScale); + + m_xSet = m_xStatement->executeQuery(); + OSL_ENSURE(m_xSet.is(),"No resultset form statement!"); + sal_Bool bOK = m_xSet->next(); + if ( !bOK ) + m_aKeyIter = m_aKeyMap.end(); + m_xRow.set(m_xSet,UNO_QUERY); + OSL_ENSURE(m_xRow.is(),"No row form statement!"); +} +// ----------------------------------------------------------------------------- +sal_Bool OKeySet::fetchRow() +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::fetchRow" ); + // fetch the next row and append on the keyset + sal_Bool bRet = sal_False; + if ( !m_bRowCountFinal ) + bRet = m_xDriverSet->next(); + if ( bRet ) + { + ORowSetRow aKeyRow = new connectivity::ORowVector< ORowSetValue >((*m_pKeyColumnNames).size() + m_pForeignColumnNames->size()); + connectivity::ORowVector< ORowSetValue >::Vector::iterator aIter = aKeyRow->get().begin(); + // first fetch the values needed for the key column + SelectColumnsMetaData::const_iterator aPosIter = (*m_pKeyColumnNames).begin(); + SelectColumnsMetaData::const_iterator aPosEnd = (*m_pKeyColumnNames).end(); + for(;aPosIter != aPosEnd;++aPosIter,++aIter) + { + const SelectColumnDescription& rColDesc = aPosIter->second; + aIter->fill(rColDesc.nPosition,rColDesc.nType,rColDesc.bNullable,m_xDriverRow); + } + // now fetch the values from the missing columns from other tables + aPosIter = (*m_pForeignColumnNames).begin(); + aPosEnd = (*m_pForeignColumnNames).end(); + for(;aPosIter != aPosEnd;++aPosIter,++aIter) + { + const SelectColumnDescription& rColDesc = aPosIter->second; + aIter->fill(rColDesc.nPosition,rColDesc.nType,rColDesc.bNullable,m_xDriverRow); + } + m_aKeyIter = m_aKeyMap.insert(OKeySetMatrix::value_type(m_aKeyMap.rbegin()->first+1,OKeySetValue(aKeyRow,::std::pair<sal_Int32,Reference<XRow> >(0,NULL)))).first; + } + else + m_bRowCountFinal = sal_True; + return bRet; +} +// ------------------------------------------------------------------------- +void OKeySet::fillAllRows() +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::fillAllRows" ); + if(!m_bRowCountFinal) + { + while(fetchRow()) + ; + } +} +// XRow +sal_Bool SAL_CALL OKeySet::wasNull( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::wasNull" ); + return m_xRow->wasNull(); +} +// ------------------------------------------------------------------------- +::rtl::OUString SAL_CALL OKeySet::getString( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::getString" ); + OSL_ENSURE(m_xRow.is(),"m_xRow is null!"); + return m_xRow->getString(columnIndex); +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL OKeySet::getBoolean( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::getBoolean" ); + OSL_ENSURE(m_xRow.is(),"m_xRow is null!"); + return m_xRow->getBoolean(columnIndex); +} +// ------------------------------------------------------------------------- +sal_Int8 SAL_CALL OKeySet::getByte( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::getByte" ); + OSL_ENSURE(m_xRow.is(),"m_xRow is null!"); + return m_xRow->getByte(columnIndex); +} +// ------------------------------------------------------------------------- +sal_Int16 SAL_CALL OKeySet::getShort( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::getShort" ); + OSL_ENSURE(m_xRow.is(),"m_xRow is null!"); + return m_xRow->getShort(columnIndex); +} +// ------------------------------------------------------------------------- +sal_Int32 SAL_CALL OKeySet::getInt( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::getInt" ); + OSL_ENSURE(m_xRow.is(),"m_xRow is null!"); + return m_xRow->getInt(columnIndex); +} +// ------------------------------------------------------------------------- +sal_Int64 SAL_CALL OKeySet::getLong( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::getLong" ); + OSL_ENSURE(m_xRow.is(),"m_xRow is null!"); + return m_xRow->getLong(columnIndex); +} +// ------------------------------------------------------------------------- +float SAL_CALL OKeySet::getFloat( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::getFloat" ); + OSL_ENSURE(m_xRow.is(),"m_xRow is null!"); + return m_xRow->getFloat(columnIndex); +} +// ------------------------------------------------------------------------- +double SAL_CALL OKeySet::getDouble( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::getDouble" ); + OSL_ENSURE(m_xRow.is(),"m_xRow is null!"); + return m_xRow->getDouble(columnIndex); +} +// ------------------------------------------------------------------------- +Sequence< sal_Int8 > SAL_CALL OKeySet::getBytes( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::getBytes" ); + OSL_ENSURE(m_xRow.is(),"m_xRow is null!"); + return m_xRow->getBytes(columnIndex); +} +// ------------------------------------------------------------------------- +::com::sun::star::util::Date SAL_CALL OKeySet::getDate( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::getDate" ); + OSL_ENSURE(m_xRow.is(),"m_xRow is null!"); + return m_xRow->getDate(columnIndex); +} +// ------------------------------------------------------------------------- +::com::sun::star::util::Time SAL_CALL OKeySet::getTime( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::getTime" ); + OSL_ENSURE(m_xRow.is(),"m_xRow is null!"); + return m_xRow->getTime(columnIndex); +} +// ------------------------------------------------------------------------- +::com::sun::star::util::DateTime SAL_CALL OKeySet::getTimestamp( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::getTimestamp" ); + OSL_ENSURE(m_xRow.is(),"m_xRow is null!"); + return m_xRow->getTimestamp(columnIndex); +} +// ------------------------------------------------------------------------- +Reference< ::com::sun::star::io::XInputStream > SAL_CALL OKeySet::getBinaryStream( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::getBinaryStream" ); + OSL_ENSURE(m_xRow.is(),"m_xRow is null!"); + return m_xRow->getBinaryStream(columnIndex); +} +// ------------------------------------------------------------------------- +Reference< ::com::sun::star::io::XInputStream > SAL_CALL OKeySet::getCharacterStream( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::getCharacterStream" ); + OSL_ENSURE(m_xRow.is(),"m_xRow is null!"); + return m_xRow->getCharacterStream(columnIndex); +} +// ------------------------------------------------------------------------- +Any SAL_CALL OKeySet::getObject( sal_Int32 columnIndex, const Reference< ::com::sun::star::container::XNameAccess >& typeMap ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::getObject" ); + OSL_ENSURE(m_xRow.is(),"m_xRow is null!"); + return m_xRow->getObject(columnIndex,typeMap); +} +// ------------------------------------------------------------------------- +Reference< XRef > SAL_CALL OKeySet::getRef( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::getRef" ); + OSL_ENSURE(m_xRow.is(),"m_xRow is null!"); + return m_xRow->getRef(columnIndex); +} +// ------------------------------------------------------------------------- +Reference< XBlob > SAL_CALL OKeySet::getBlob( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::getBlob" ); + OSL_ENSURE(m_xRow.is(),"m_xRow is null!"); + return m_xRow->getBlob(columnIndex); +} +// ------------------------------------------------------------------------- +Reference< XClob > SAL_CALL OKeySet::getClob( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::getClob" ); + OSL_ENSURE(m_xRow.is(),"m_xRow is null!"); + return m_xRow->getClob(columnIndex); +} +// ------------------------------------------------------------------------- +Reference< XArray > SAL_CALL OKeySet::getArray( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::getArray" ); + OSL_ENSURE(m_xRow.is(),"m_xRow is null!"); + return m_xRow->getArray(columnIndex); +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL OKeySet::rowUpdated( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::rowUpdated" ); + return m_aKeyIter != m_aKeyMap.begin() && m_aKeyIter != m_aKeyMap.end() && m_aKeyIter->second.second.first == 2; +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL OKeySet::rowInserted( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::rowInserted" ); + return m_aKeyIter != m_aKeyMap.begin() && m_aKeyIter != m_aKeyMap.end() && m_aKeyIter->second.second.first == 1; +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL OKeySet::rowDeleted( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::rowDeleted" ); + sal_Bool bDeleted = m_bDeleted; + m_bDeleted = sal_False; + return bDeleted; +} +// ----------------------------------------------------------------------------- +::rtl::OUString OKeySet::getComposedTableName(const ::rtl::OUString& _sCatalog, + const ::rtl::OUString& _sSchema, + const ::rtl::OUString& _sTable) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::getComposedTableName" ); + ::rtl::OUString aComposedName; + Reference<XDatabaseMetaData> xMetaData = m_xConnection->getMetaData(); + + if( xMetaData.is() && xMetaData->supportsTableCorrelationNames() ) + { + aComposedName = ::dbtools::composeTableName( xMetaData, _sCatalog, _sSchema, _sTable, sal_False, ::dbtools::eInDataManipulation ); + // first we have to check if the composed tablename is in the select clause or if an alias is used + Reference<XTablesSupplier> xTabSup(m_xComposer,UNO_QUERY); + Reference<XNameAccess> xSelectTables = xTabSup->getTables(); + OSL_ENSURE(xSelectTables.is(),"No Select tables!"); + if(xSelectTables.is()) + { + if(!xSelectTables->hasByName(aComposedName)) + { // the composed name isn't used in the select clause so we have to find out which name is used instead + ::rtl::OUString sCatalog,sSchema,sTable; + ::dbtools::qualifiedNameComponents(xMetaData,m_sUpdateTableName,sCatalog,sSchema,sTable,::dbtools::eInDataManipulation); + aComposedName = ::dbtools::composeTableNameForSelect( m_xConnection, sCatalog, sSchema, sTable ); + } + else + aComposedName = ::dbtools::composeTableNameForSelect( m_xConnection, _sCatalog, _sSchema, _sTable ); + } + } + else + aComposedName = ::dbtools::composeTableNameForSelect( m_xConnection, _sCatalog, _sSchema, _sTable ); + + return aComposedName; +} +// ----------------------------------------------------------------------------- +namespace dbaccess +{ + +void getColumnPositions(const Reference<XNameAccess>& _rxQueryColumns, + const ::com::sun::star::uno::Sequence< ::rtl::OUString >& _aColumnNames, + const ::rtl::OUString& _rsUpdateTableName, + SelectColumnsMetaData& o_rColumnNames, + bool i_bAppendTableName) + { + // get the real name of the columns + Sequence< ::rtl::OUString> aSelNames(_rxQueryColumns->getElementNames()); + const ::rtl::OUString* pSelIter = aSelNames.getConstArray(); + const ::rtl::OUString* pSelEnd = pSelIter + aSelNames.getLength(); + + const ::rtl::OUString* pTblColumnIter = _aColumnNames.getConstArray(); + const ::rtl::OUString* pTblColumnEnd = pTblColumnIter + _aColumnNames.getLength(); + + + ::comphelper::UStringMixLess aTmp(o_rColumnNames.key_comp()); + ::comphelper::UStringMixEqual bCase(static_cast< ::comphelper::UStringMixLess*>(&aTmp)->isCaseSensitive()); + + for(sal_Int32 nPos = 1;pSelIter != pSelEnd;++pSelIter,++nPos) + { + Reference<XPropertySet> xQueryColumnProp(_rxQueryColumns->getByName(*pSelIter),UNO_QUERY_THROW); + ::rtl::OUString sRealName,sTableName; + OSL_ENSURE(xQueryColumnProp->getPropertySetInfo()->hasPropertyByName(PROPERTY_REALNAME),"Property REALNAME not available!"); + OSL_ENSURE(xQueryColumnProp->getPropertySetInfo()->hasPropertyByName(PROPERTY_TABLENAME),"Property TABLENAME not available!"); + xQueryColumnProp->getPropertyValue(PROPERTY_REALNAME) >>= sRealName; + xQueryColumnProp->getPropertyValue(PROPERTY_TABLENAME) >>= sTableName; + + for(;pTblColumnIter != pTblColumnEnd;++pTblColumnIter) + { + if(bCase(sRealName,*pTblColumnIter) && bCase(_rsUpdateTableName,sTableName) && o_rColumnNames.find(*pTblColumnIter) == o_rColumnNames.end()) + { + sal_Int32 nType = 0; + xQueryColumnProp->getPropertyValue(PROPERTY_TYPE) >>= nType; + sal_Int32 nScale = 0; + xQueryColumnProp->getPropertyValue(PROPERTY_SCALE) >>= nScale; + ::rtl::OUString sColumnDefault; + if ( xQueryColumnProp->getPropertySetInfo()->hasPropertyByName(PROPERTY_DEFAULTVALUE) ) + xQueryColumnProp->getPropertyValue(PROPERTY_DEFAULTVALUE) >>= sColumnDefault; + + sal_Int32 nNullable = ColumnValue::NULLABLE_UNKNOWN; + OSL_VERIFY( xQueryColumnProp->getPropertyValue( PROPERTY_ISNULLABLE ) >>= nNullable ); + + if ( i_bAppendTableName ) + { + ::rtl::OUStringBuffer sName; + sName.append(sTableName); + sName.appendAscii("."); + sName.append(sRealName); + SelectColumnDescription aColDesc( nPos, nType,nScale,nNullable != sdbc::ColumnValue::NO_NULLS, sColumnDefault ); + aColDesc.sRealName = sRealName; + aColDesc.sTableName = sTableName; + o_rColumnNames[sName.makeStringAndClear()] = aColDesc; + } + else + o_rColumnNames[sRealName] = SelectColumnDescription( nPos, nType,nScale,nNullable != sdbc::ColumnValue::NO_NULLS, sColumnDefault ); + + break; + } + } + pTblColumnIter = _aColumnNames.getConstArray(); + } + } +} +// ----------------------------------------------------------------------------- +void OKeySet::impl_convertValue_throw(const ORowSetRow& _rInsertRow,const SelectColumnDescription& i_aMetaData) +{ + ORowSetValue& aValue((_rInsertRow->get())[i_aMetaData.nPosition]); + switch(i_aMetaData.nType) + { + case DataType::DECIMAL: + case DataType::NUMERIC: + { + ::rtl::OUString sValue = aValue.getString(); + sal_Int32 nIndex = sValue.indexOf('.'); + if ( nIndex != -1 ) + { + aValue = sValue.copy(0,::std::min(sValue.getLength(),nIndex + (i_aMetaData.nScale > 0 ? i_aMetaData.nScale + 1 : 0))); + } + } + break; + default: + break; + } +} +// ----------------------------------------------------------------------------- + diff --git a/dbaccess/source/core/api/KeySet.hxx b/dbaccess/source/core/api/KeySet.hxx new file mode 100644 index 000000000000..ecb56d7c88b4 --- /dev/null +++ b/dbaccess/source/core/api/KeySet.hxx @@ -0,0 +1,233 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +#ifndef DBACCESS_CORE_API_KEYSET_HXX +#define DBACCESS_CORE_API_KEYSET_HXX + +#ifndef DBACCESS_CORE_API_CACHESET_HXX +#include "CacheSet.hxx" +#endif + +#ifndef _CPPUHELPER_IMPLBASE1_HXX_ +#include <cppuhelper/implbase1.hxx> +#endif +#include <memory> +#include <map> + +#ifndef _COM_SUN_STAR_LANG_XUNOTUNNEL_HPP_ +#include <com/sun/star/lang/XUnoTunnel.hpp> +#endif +#include <com/sun/star/sdb/XSingleSelectQueryAnalyzer.hpp> +#include <com/sun/star/sdb/XSingleSelectQueryComposer.hpp> +#ifndef _COMPHELPER_STLTYPES_HXX_ +#include <comphelper/stl_types.hxx> +#endif + +namespace dbaccess +{ + struct SelectColumnDescription + { + ::rtl::OUString sRealName; // may be empty + ::rtl::OUString sTableName; // may be empty + ::rtl::OUString sDefaultValue; + sal_Int32 nPosition; + sal_Int32 nType; + sal_Int32 nScale; + sal_Bool bNullable; + + + + SelectColumnDescription() + :nPosition( 0 ) + ,nType( 0 ) + ,nScale( 0 ) + ,bNullable(sal_False) + { + } + + SelectColumnDescription( sal_Int32 _nPosition, sal_Int32 _nType, sal_Int32 _nScale,sal_Bool _bNullable, const ::rtl::OUString& _rDefaultValue ) + :sDefaultValue( _rDefaultValue ) + ,nPosition( _nPosition ) + ,nType( _nType ) + ,nScale( _nScale ) + ,bNullable(_bNullable) + { + } + }; + typedef ::std::map< ::rtl::OUString, SelectColumnDescription, ::comphelper::UStringMixLess > SelectColumnsMetaData; + + // the elements of _rxQueryColumns must have the properties PROPERTY_REALNAME and PROPERTY_TABLENAME + void getColumnPositions(const ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess >& _rxQueryColumns, + const ::com::sun::star::uno::Sequence< ::rtl::OUString >& _rColumnNames, + const ::rtl::OUString& _rsUpdateTableName, + SelectColumnsMetaData& o_rColumnNames /* out */, + bool i_bAppendTableName = false); + + typedef ::std::pair<ORowSetRow,::std::pair<sal_Int32,::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRow> > > OKeySetValue; + typedef ::std::map<sal_Int32,OKeySetValue > OKeySetMatrix; + typedef ::std::map<sal_Int32,ORowSetValueVector > OUpdatedParameter; + // is used when the source supports keys + class OKeySet : public OCacheSet + { + protected: + OKeySetMatrix m_aKeyMap; + OKeySetMatrix::iterator m_aKeyIter; + + ::std::vector< ::rtl::OUString > m_aAutoColumns; // contains all columns which are autoincrement ones + + OUpdatedParameter m_aUpdatedParameter; // contains all parameter which have been updated and are needed for refetching + ORowSetValueVector m_aParameterValueForCache; + ::std::auto_ptr<SelectColumnsMetaData> m_pKeyColumnNames; // contains all key column names + ::std::auto_ptr<SelectColumnsMetaData> m_pColumnNames; // contains all column names + ::std::auto_ptr<SelectColumnsMetaData> m_pParameterNames; // contains all parameter names + ::std::auto_ptr<SelectColumnsMetaData> m_pForeignColumnNames; // contains all column names of the rest + connectivity::OSQLTable m_xTable; // reference to our table + ::com::sun::star::uno::Reference< ::com::sun::star::container::XIndexAccess> m_xTableKeys; + ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XPreparedStatement> m_xStatement; + ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XResultSet> m_xSet; + ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRow> m_xRow; + ::com::sun::star::uno::Reference< ::com::sun::star::sdb::XSingleSelectQueryAnalyzer > m_xComposer; + ::rtl::OUString m_sUpdateTableName; + ::std::vector< ::rtl::OUString > m_aFilterColumns; + + sal_Bool m_bRowCountFinal; + + /** + getComposedTableName return the composed table name for the query + @param _sCatalog the catalogname may be empty + @param _sSchema the schemaname may be empty + @param _sTable the tablename + + @return the composed name + */ + ::rtl::OUString getComposedTableName( const ::rtl::OUString& _sCatalog, + const ::rtl::OUString& _sSchema, + const ::rtl::OUString& _sTable); + + /** copies the values from the insert row into the key row + * + * \param _rInsertRow the row which was inserted + * \param _rKeyRow The current key row of the row set. + + \param i_nBookmark The bookmark is used to update the parameter + */ + void copyRowValue(const ORowSetRow& _rInsertRow,ORowSetRow& _rKeyRow,sal_Int32 i_nBookmark); + + ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess > getKeyColumns() const; + void fillAllRows(); + sal_Bool fetchRow(); + + void impl_convertValue_throw(const ORowSetRow& _rInsertRow,const SelectColumnDescription& i_aMetaData); + void initColumns(); + void findTableColumnsMatching_throw( const ::com::sun::star::uno::Any& i_aTable, + const ::rtl::OUString& i_rUpdateTableName, + const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XDatabaseMetaData>& i_xMeta, + const ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess>& i_xQueryColumns, + ::std::auto_ptr<SelectColumnsMetaData>& o_pKeyColumnNames); + ::rtl::OUStringBuffer createKeyFilter(); + void tryRefetch(const ORowSetRow& _rInsertRow,bool bRefetch); + void executeUpdate(const ORowSetRow& _rInsertRow ,const ORowSetRow& _rOrginalRow,const ::rtl::OUString& i_sSQL,const ::rtl::OUString& i_sTableName,const ::std::vector<sal_Int32>& _aIndexColumnPositions = ::std::vector<sal_Int32>()); + void executeInsert( const ORowSetRow& _rInsertRow,const ::rtl::OUString& i_sSQL,const ::rtl::OUString& i_sTableName = ::rtl::OUString(),bool bRefetch = false); + void executeStatement(::rtl::OUStringBuffer& io_aFilter,const ::rtl::OUString& i_sRowSetFilter,::com::sun::star::uno::Reference< ::com::sun::star::sdb::XSingleSelectQueryComposer>& io_xAnalyzer); + + virtual ~OKeySet(); + public: + OKeySet(const connectivity::OSQLTable& _xTable, + const ::com::sun::star::uno::Reference< ::com::sun::star::container::XIndexAccess>& _xTableKeys, + const ::rtl::OUString& _rUpdateTableName, + const ::com::sun::star::uno::Reference< ::com::sun::star::sdb::XSingleSelectQueryAnalyzer >& _xComposer, + const ORowSetValueVector& _aParameterValueForCache); + + // late ctor which can throw exceptions + virtual void construct(const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XResultSet>& _xDriverSet,const ::rtl::OUString& i_sRowSetFilter); + + // ::com::sun::star::sdbc::XRow + virtual sal_Bool SAL_CALL wasNull( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getString( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL getBoolean( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Int8 SAL_CALL getByte( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Int16 SAL_CALL getShort( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Int32 SAL_CALL getInt( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Int64 SAL_CALL getLong( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual float SAL_CALL getFloat( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual double SAL_CALL getDouble( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL getBytes( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::util::Date SAL_CALL getDate( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::util::Time SAL_CALL getTime( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::util::DateTime SAL_CALL getTimestamp( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > SAL_CALL getBinaryStream( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > SAL_CALL getCharacterStream( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Any SAL_CALL getObject( sal_Int32 columnIndex, const ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess >& typeMap ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRef > SAL_CALL getRef( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XBlob > SAL_CALL getBlob( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XClob > SAL_CALL getClob( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XArray > SAL_CALL getArray( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + + + virtual sal_Bool SAL_CALL rowUpdated( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL rowInserted( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL rowDeleted( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + // ::com::sun::star::sdbc::XResultSet + virtual sal_Bool SAL_CALL next( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL isBeforeFirst( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL isAfterLast( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL isFirst( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL isLast( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL beforeFirst( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL afterLast( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL first( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL last( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Int32 SAL_CALL getRow( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL absolute( sal_Int32 row ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL relative( sal_Int32 rows ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL previous( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL refreshRow( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + // ::com::sun::star::sdbcx::XRowLocate + virtual ::com::sun::star::uno::Any SAL_CALL getBookmark() throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + // ------------------------------------------------------------------------- + virtual sal_Bool SAL_CALL moveToBookmark( const ::com::sun::star::uno::Any& bookmark ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + // ------------------------------------------------------------------------- + virtual sal_Bool SAL_CALL moveRelativeToBookmark( const ::com::sun::star::uno::Any& bookmark, sal_Int32 rows ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + // ------------------------------------------------------------------------- + virtual sal_Int32 SAL_CALL compareBookmarks( const ::com::sun::star::uno::Any& first, const ::com::sun::star::uno::Any& second ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + // ------------------------------------------------------------------------- + virtual sal_Bool SAL_CALL hasOrderedBookmarks( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + // ------------------------------------------------------------------------- + virtual sal_Int32 SAL_CALL hashBookmark( const ::com::sun::star::uno::Any& bookmark ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + // ------------------------------------------------------------------------- + // ::com::sun::star::sdbcx::XDeleteRows + virtual ::com::sun::star::uno::Sequence< sal_Int32 > SAL_CALL deleteRows( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& rows ,const connectivity::OSQLTable& _xTable) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + // ::com::sun::star::sdbc::XResultSetUpdate + virtual void SAL_CALL updateRow(const ORowSetRow& _rInsertRow,const ORowSetRow& _rOrginalRow,const connectivity::OSQLTable& _xTable ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL deleteRow(const ORowSetRow& _rInsertRow,const connectivity::OSQLTable& _xTable ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL insertRow( const ORowSetRow& _rInsertRow,const connectivity::OSQLTable& _xTable ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL cancelRowUpdates( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL moveToInsertRow( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL moveToCurrentRow( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + }; +} +#endif // DBACCESS_CORE_API_KEYSET_HXX + diff --git a/dbaccess/source/core/api/OptimisticSet.cxx b/dbaccess/source/core/api/OptimisticSet.cxx new file mode 100644 index 000000000000..837824751f0f --- /dev/null +++ b/dbaccess/source/core/api/OptimisticSet.cxx @@ -0,0 +1,767 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: OptimisticSet.cxx,v $ + * $Revision: 1.73 $ + * + * 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_dbaccess.hxx" + +#include "OptimisticSet.hxx" +#include "core_resource.hxx" +#include "core_resource.hrc" +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/sdbc/XDatabaseMetaData.hpp> +#include <com/sun/star/sdbc/ColumnValue.hpp> +#include <com/sun/star/sdbc/XPreparedStatement.hpp> +#include <com/sun/star/sdbc/XParameters.hpp> +#include <com/sun/star/sdbc/XGeneratedResultSet.hpp> +#include <com/sun/star/sdb/XSingleSelectQueryComposer.hpp> +#include <com/sun/star/sdb/SQLFilterOperator.hpp> +#include <com/sun/star/sdbc/XColumnLocate.hpp> +#include <com/sun/star/container/XIndexAccess.hpp> +#include "dbastrings.hrc" +#include "apitools.hxx" +#include <com/sun/star/sdbcx/XKeysSupplier.hpp> +#include <com/sun/star/sdb/XSingleSelectQueryComposer.hpp> +#include <com/sun/star/sdbcx/XIndexesSupplier.hpp> +#include <cppuhelper/typeprovider.hxx> +#include <comphelper/types.hxx> +#include <com/sun/star/sdbcx/KeyType.hpp> +#include <connectivity/dbtools.hxx> +#include <connectivity/dbexception.hxx> +#include <list> +#include <algorithm> +#include <string.h> +#include <com/sun/star/io/XInputStream.hpp> +#include <com/sun/star/sdbcx/XTablesSupplier.hpp> +#include "querycomposer.hxx" +#include "composertools.hxx" +#include <tools/debug.hxx> +#include <string.h> +#include <rtl/logfile.hxx> + +using namespace dbaccess; +using namespace ::connectivity; +using 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::sdb; +using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::util; +using namespace ::com::sun::star::io; +using namespace ::com::sun::star; +using namespace ::cppu; +using namespace ::osl; + +DECLARE_STL_USTRINGACCESS_MAP(::rtl::OUStringBuffer,TSQLStatements); +namespace +{ + void lcl_fillKeyCondition(const ::rtl::OUString& i_sTableName,const ::rtl::OUString& i_sQuotedColumnName,const ORowSetValue& i_aValue,TSQLStatements& io_aKeyConditions) + { + ::rtl::OUStringBuffer& rKeyCondition = io_aKeyConditions[i_sTableName]; + if ( rKeyCondition.getLength() ) + rKeyCondition.appendAscii(" AND "); + rKeyCondition.append(i_sQuotedColumnName); + if ( i_aValue.isNull() ) + rKeyCondition.appendAscii(" IS NULL"); + else + rKeyCondition.appendAscii(" = ?"); + } +} + +DBG_NAME(OptimisticSet) +// ------------------------------------------------------------------------- +OptimisticSet::OptimisticSet(const ::comphelper::ComponentContext& _rContext, + const Reference< XConnection>& i_xConnection, + const Reference< XSingleSelectQueryAnalyzer >& _xComposer, + const ORowSetValueVector& _aParameterValueForCache) + :OKeySet(NULL,NULL,::rtl::OUString(),_xComposer,_aParameterValueForCache) + ,m_aSqlParser( _rContext.getLegacyServiceFactory() ) + ,m_aSqlIterator( i_xConnection, Reference<XTablesSupplier>(_xComposer,UNO_QUERY)->getTables(), m_aSqlParser, NULL ) + ,m_bResultSetChanged(false) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OptimisticSet::OptimisticSet" ); + DBG_CTOR(OptimisticSet,NULL); +} +// ----------------------------------------------------------------------------- +OptimisticSet::~OptimisticSet() +{ + DBG_DTOR(OptimisticSet,NULL); +} +// ----------------------------------------------------------------------------- +void OptimisticSet::construct(const Reference< XResultSet>& _xDriverSet,const ::rtl::OUString& i_sRowSetFilter) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OptimisticSet::construct" ); + OCacheSet::construct(_xDriverSet,i_sRowSetFilter); + initColumns(); + + Reference<XDatabaseMetaData> xMeta = m_xConnection->getMetaData(); + bool bCase = (xMeta.is() && xMeta->storesMixedCaseQuotedIdentifiers()) ? true : false; + Reference<XColumnsSupplier> xQueryColSup(m_xComposer,UNO_QUERY); + const Reference<XNameAccess> xQueryColumns = xQueryColSup->getColumns(); + const Reference<XTablesSupplier> xTabSup(m_xComposer,UNO_QUERY); + const Reference<XNameAccess> xTables = xTabSup->getTables(); + const Sequence< ::rtl::OUString> aTableNames = xTables->getElementNames(); + const ::rtl::OUString* pTableNameIter = aTableNames.getConstArray(); + const ::rtl::OUString* pTableNameEnd = pTableNameIter + aTableNames.getLength(); + for( ; pTableNameIter != pTableNameEnd ; ++pTableNameIter) + { + ::std::auto_ptr<SelectColumnsMetaData> pKeyColumNames(new SelectColumnsMetaData(bCase)); + findTableColumnsMatching_throw(xTables->getByName(*pTableNameIter),*pTableNameIter,xMeta,xQueryColumns,pKeyColumNames); + m_pKeyColumnNames->insert(pKeyColumNames->begin(),pKeyColumNames->end()); + } + + // the first row is empty because it's now easier for us to distinguish when we are beforefirst or first + // without extra variable to be set + m_aKeyMap.insert(OKeySetMatrix::value_type(0,OKeySetValue(NULL,::std::pair<sal_Int32,Reference<XRow> >(0,NULL)))); + m_aKeyIter = m_aKeyMap.begin(); + + ::rtl::OUStringBuffer aFilter = createKeyFilter(); + + Reference< XSingleSelectQueryComposer> xSourceComposer(m_xComposer,UNO_QUERY); + Reference< XMultiServiceFactory > xFactory(m_xConnection, UNO_QUERY_THROW); + Reference<XSingleSelectQueryComposer> xAnalyzer(xFactory->createInstance(SERVICE_NAME_SINGLESELECTQUERYCOMPOSER),UNO_QUERY); + ::rtl::OUString sQuery = xSourceComposer->getQuery(); + xAnalyzer->setElementaryQuery(xSourceComposer->getElementaryQuery()); + // check for joins + ::rtl::OUString aErrorMsg; + ::std::auto_ptr<OSQLParseNode> pStatementNode( m_aSqlParser.parseTree( aErrorMsg, sQuery ) ); + m_aSqlIterator.setParseTree( pStatementNode.get() ); + m_aSqlIterator.traverseAll(); + fillJoinedColumns_throw(m_aSqlIterator.getJoinConditions()); + + const ::rtl::OUString sComposerFilter = m_xComposer->getFilter(); + if ( i_sRowSetFilter.getLength() || (sComposerFilter.getLength() && sComposerFilter != i_sRowSetFilter) ) + { + FilterCreator aFilterCreator; + if ( sComposerFilter.getLength() && sComposerFilter != i_sRowSetFilter ) + aFilterCreator.append( sComposerFilter ); + aFilterCreator.append( i_sRowSetFilter ); + aFilterCreator.append( aFilter.makeStringAndClear() ); + aFilter = aFilterCreator.getComposedAndClear(); + } + xAnalyzer->setFilter(aFilter.makeStringAndClear()); + m_xStatement = m_xConnection->prepareStatement(xAnalyzer->getQueryWithSubstitution()); + ::comphelper::disposeComponent(xAnalyzer); +} +// ------------------------------------------------------------------------- +// ::com::sun::star::sdbcx::XDeleteRows +Sequence< sal_Int32 > SAL_CALL OptimisticSet::deleteRows( const Sequence< Any >& /*rows*/ ,const connectivity::OSQLTable& /*_xTable*/) throw(SQLException, RuntimeException) +{ + Sequence< sal_Int32 > aRet; + return aRet; +} +// ------------------------------------------------------------------------- +void SAL_CALL OptimisticSet::updateRow(const ORowSetRow& _rInsertRow ,const ORowSetRow& _rOrginalRow,const connectivity::OSQLTable& /*_xTable*/ ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OptimisticSet::updateRow" ); + if ( m_aJoinedKeyColumns.empty() ) + throw SQLException(); + // list all cloumns that should be set + static ::rtl::OUString s_sPara = ::rtl::OUString::createFromAscii(" = ?"); + ::rtl::OUString aQuote = getIdentifierQuoteString(); + static ::rtl::OUString aAnd = ::rtl::OUString::createFromAscii(" AND "); + ::rtl::OUString sIsNull(RTL_CONSTASCII_USTRINGPARAM(" IS NULL")); + ::rtl::OUString sParam(RTL_CONSTASCII_USTRINGPARAM(" = ?")); + + ::rtl::OUString aColumnName; + ::rtl::OUStringBuffer sKeyCondition; + ::std::map< ::rtl::OUString,bool > aResultSetChanged; + TSQLStatements aKeyConditions; + TSQLStatements aIndexConditions; + TSQLStatements aSql; + + // sal_Int32 i = 1; + // here we build the condition part for the update statement + SelectColumnsMetaData::const_iterator aIter = m_pColumnNames->begin(); + SelectColumnsMetaData::const_iterator aEnd = m_pColumnNames->end(); + for(;aIter != aEnd;++aIter) + { + if ( aResultSetChanged.find( aIter->second.sTableName ) == aResultSetChanged.end() ) + aResultSetChanged[aIter->second.sTableName] = false; + const ::rtl::OUString sQuotedColumnName = ::dbtools::quoteName( aQuote,aIter->second.sRealName); + if ( m_pKeyColumnNames->find(aIter->first) != m_pKeyColumnNames->end() ) + { + aResultSetChanged[aIter->second.sTableName] = m_aJoinedKeyColumns.find(aIter->second.nPosition) != m_aJoinedKeyColumns.end(); + lcl_fillKeyCondition(aIter->second.sTableName,sQuotedColumnName,(_rOrginalRow->get())[aIter->second.nPosition],aKeyConditions); + } + if((_rInsertRow->get())[aIter->second.nPosition].isModified()) + { + if ( m_aJoinedKeyColumns.find(aIter->second.nPosition) != m_aJoinedKeyColumns.end() ) + throw SQLException(); + + ::std::map<sal_Int32,sal_Int32>::const_iterator aJoinIter = m_aJoinedColumns.find(aIter->second.nPosition); + if ( aJoinIter != m_aJoinedColumns.end() ) + { + (_rInsertRow->get())[aJoinIter->second] = (_rInsertRow->get())[aIter->second.nPosition]; + } + ::rtl::OUStringBuffer& rPart = aSql[aIter->second.sTableName]; + if ( rPart.getLength() ) + rPart.appendAscii(", "); + rPart.append(sQuotedColumnName); + rPart.append(s_sPara); + } + } + + if( aSql.empty() ) + ::dbtools::throwSQLException( DBACORE_RESSTRING( RID_STR_NO_VALUE_CHANGED ), SQL_GENERAL_ERROR, m_xConnection ); + + if( aKeyConditions.empty() ) + ::dbtools::throwSQLException( DBACORE_RESSTRING( RID_STR_NO_CONDITION_FOR_PK ), SQL_GENERAL_ERROR, m_xConnection ); + + static const ::rtl::OUString s_sUPDATE(RTL_CONSTASCII_USTRINGPARAM("UPDATE ")); + static const ::rtl::OUString s_sSET(RTL_CONSTASCII_USTRINGPARAM(" SET ")); + + Reference<XDatabaseMetaData> xMetaData = m_xConnection->getMetaData(); + + TSQLStatements::iterator aSqlIter = aSql.begin(); + TSQLStatements::iterator aSqlEnd = aSql.end(); + for(;aSqlIter != aSqlEnd ; ++aSqlIter) + { + if ( aSqlIter->second.getLength() ) + { + m_bResultSetChanged = m_bResultSetChanged || aResultSetChanged[aSqlIter->first]; + ::rtl::OUStringBuffer sSql(s_sUPDATE); + ::rtl::OUString sCatalog,sSchema,sTable; + ::dbtools::qualifiedNameComponents(xMetaData,aSqlIter->first,sCatalog,sSchema,sTable,::dbtools::eInDataManipulation); + sSql.append( ::dbtools::composeTableNameForSelect( m_xConnection, sCatalog, sSchema, sTable ) ); + sSql.append(s_sSET); + sSql.append(aSqlIter->second); + ::rtl::OUStringBuffer& rCondition = aKeyConditions[aSqlIter->first]; + bool bAddWhere = true; + if ( rCondition.getLength() ) + { + bAddWhere = false; + sSql.appendAscii(" WHERE "); + sSql.append( rCondition ); + } + executeUpdate(_rInsertRow ,_rOrginalRow,sSql.makeStringAndClear(),aSqlIter->first); + } + } +} +// ------------------------------------------------------------------------- +void SAL_CALL OptimisticSet::insertRow( const ORowSetRow& _rInsertRow,const connectivity::OSQLTable& /*_xTable*/ ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OptimisticSet::insertRow" ); + TSQLStatements aSql; + TSQLStatements aParameter; + TSQLStatements aKeyConditions; + ::std::map< ::rtl::OUString,bool > aResultSetChanged; + ::rtl::OUString aQuote = getIdentifierQuoteString(); + static ::rtl::OUString aAnd = ::rtl::OUString::createFromAscii(" AND "); + ::rtl::OUString sIsNull(RTL_CONSTASCII_USTRINGPARAM(" IS NULL")); + ::rtl::OUString sParam(RTL_CONSTASCII_USTRINGPARAM(" = ?")); + + // here we build the condition part for the update statement + SelectColumnsMetaData::const_iterator aIter = m_pColumnNames->begin(); + SelectColumnsMetaData::const_iterator aEnd = m_pColumnNames->end(); + for(;aIter != aEnd;++aIter) + { + if ( aResultSetChanged.find( aIter->second.sTableName ) == aResultSetChanged.end() ) + aResultSetChanged[aIter->second.sTableName] = false; + + const ::rtl::OUString sQuotedColumnName = ::dbtools::quoteName( aQuote,aIter->second.sRealName); + if ( (_rInsertRow->get())[aIter->second.nPosition].isModified() ) + { + if ( m_aJoinedKeyColumns.find(aIter->second.nPosition) != m_aJoinedKeyColumns.end() ) + { + lcl_fillKeyCondition(aIter->second.sTableName,sQuotedColumnName,(_rInsertRow->get())[aIter->second.nPosition],aKeyConditions); + aResultSetChanged[aIter->second.sTableName] = true; + } + ::std::map<sal_Int32,sal_Int32>::const_iterator aJoinIter = m_aJoinedColumns.find(aIter->second.nPosition); + if ( aJoinIter != m_aJoinedColumns.end() ) + { + (_rInsertRow->get())[aJoinIter->second] = (_rInsertRow->get())[aIter->second.nPosition]; + } + ::rtl::OUStringBuffer& rPart = aSql[aIter->second.sTableName]; + if ( rPart.getLength() ) + rPart.appendAscii(", "); + rPart.append(sQuotedColumnName); + ::rtl::OUStringBuffer& rParam = aParameter[aIter->second.sTableName]; + if ( rParam.getLength() ) + rParam.appendAscii(", "); + rParam.appendAscii("?"); + } + } + if ( aParameter.empty() ) + ::dbtools::throwSQLException( DBACORE_RESSTRING( RID_STR_NO_VALUE_CHANGED ), SQL_GENERAL_ERROR, m_xConnection ); + + Reference<XDatabaseMetaData> xMetaData = m_xConnection->getMetaData(); + static const ::rtl::OUString s_sINSERT(RTL_CONSTASCII_USTRINGPARAM("INSERT INTO ")); + static const ::rtl::OUString s_sVALUES(RTL_CONSTASCII_USTRINGPARAM(") VALUES ( ")); + TSQLStatements::iterator aSqlIter = aSql.begin(); + TSQLStatements::iterator aSqlEnd = aSql.end(); + for(;aSqlIter != aSqlEnd ; ++aSqlIter) + { + if ( aSqlIter->second.getLength() ) + { + m_bResultSetChanged = m_bResultSetChanged || aResultSetChanged[aSqlIter->first]; + ::rtl::OUStringBuffer sSql(s_sINSERT); + ::rtl::OUString sCatalog,sSchema,sTable; + ::dbtools::qualifiedNameComponents(xMetaData,aSqlIter->first,sCatalog,sSchema,sTable,::dbtools::eInDataManipulation); + ::rtl::OUString sComposedTableName = ::dbtools::composeTableNameForSelect( m_xConnection, sCatalog, sSchema, sTable ); + sSql.append(sComposedTableName); + sSql.appendAscii(" ( "); + sSql.append(aSqlIter->second); + sSql.append(s_sVALUES); + sSql.append(aParameter[aSqlIter->first]); + sSql.appendAscii(" )"); + + ::rtl::OUStringBuffer& rCondition = aKeyConditions[aSqlIter->first]; + if ( rCondition.getLength() ) + { + ::rtl::OUStringBuffer sQuery; + sQuery.appendAscii("SELECT "); + sQuery.append(aSqlIter->second); + sQuery.appendAscii(" FROM "); + sQuery.append(sComposedTableName); + sQuery.appendAscii(" WHERE "); + sQuery.append(rCondition); + + try + { + Reference< XPreparedStatement > xPrep(m_xConnection->prepareStatement(sQuery.makeStringAndClear())); + Reference< XParameters > xParameter(xPrep,UNO_QUERY); + // and then the values of the where condition + SelectColumnsMetaData::iterator aKeyCol = m_pKeyColumnNames->begin(); + SelectColumnsMetaData::iterator aKeysEnd = m_pKeyColumnNames->end(); + sal_Int32 i = 1; + for(;aKeyCol != aKeysEnd;++aKeyCol) + { + if ( aKeyCol->second.sTableName == aSqlIter->first ) + { + setParameter(i++,xParameter,(_rInsertRow->get())[aKeyCol->second.nPosition],aKeyCol->second.nType,aKeyCol->second.nScale); + } + } + Reference<XResultSet> xRes = xPrep->executeQuery(); + Reference<XRow> xRow(xRes,UNO_QUERY); + if ( xRow.is() && xRes->next() ) + { + m_bResultSetChanged = true; + continue; + } + } + catch(const SQLException&) + { + } + } + + executeInsert(_rInsertRow,sSql.makeStringAndClear(),aSqlIter->first); + } + } +} +// ------------------------------------------------------------------------- +void SAL_CALL OptimisticSet::deleteRow(const ORowSetRow& _rDeleteRow,const connectivity::OSQLTable& /*_xTable*/ ) throw(SQLException, RuntimeException) +{ + ::rtl::OUString sParam(RTL_CONSTASCII_USTRINGPARAM(" = ?")); + ::rtl::OUString sIsNull(RTL_CONSTASCII_USTRINGPARAM(" IS NULL")); + static const ::rtl::OUString s_sAnd(RTL_CONSTASCII_USTRINGPARAM(" AND ")); + ::rtl::OUString aQuote = getIdentifierQuoteString(); + ::rtl::OUString aColumnName; + ::rtl::OUStringBuffer sKeyCondition,sIndexCondition; + ::std::vector<sal_Int32> aIndexColumnPositions; + TSQLStatements aKeyConditions; + TSQLStatements aIndexConditions; + TSQLStatements aSql; + + // sal_Int32 i = 1; + // here we build the condition part for the update statement + SelectColumnsMetaData::const_iterator aIter = m_pColumnNames->begin(); + SelectColumnsMetaData::const_iterator aEnd = m_pColumnNames->end(); + for(;aIter != aEnd;++aIter) + { + if ( m_aJoinedKeyColumns.find(aIter->second.nPosition) == m_aJoinedKeyColumns.end() && m_pKeyColumnNames->find(aIter->first) != m_pKeyColumnNames->end() ) + { + // only delete rows which aren't the key in the join + const ::rtl::OUString sQuotedColumnName = ::dbtools::quoteName( aQuote,aIter->second.sRealName); + lcl_fillKeyCondition(aIter->second.sTableName,sQuotedColumnName,(_rDeleteRow->get())[aIter->second.nPosition],aKeyConditions); + } + } + Reference<XDatabaseMetaData> xMetaData = m_xConnection->getMetaData(); + TSQLStatements::iterator aSqlIter = aKeyConditions.begin(); + TSQLStatements::iterator aSqlEnd = aKeyConditions.end(); + for(;aSqlIter != aSqlEnd ; ++aSqlIter) + { + ::rtl::OUStringBuffer& rCondition = aSqlIter->second; + if ( rCondition.getLength() ) + { + ::rtl::OUStringBuffer sSql; + sSql.appendAscii("DELETE FROM "); + ::rtl::OUString sCatalog,sSchema,sTable; + ::dbtools::qualifiedNameComponents(xMetaData,aSqlIter->first,sCatalog,sSchema,sTable,::dbtools::eInDataManipulation); + sSql.append( ::dbtools::composeTableNameForSelect( m_xConnection, sCatalog, sSchema, sTable ) ); + sSql.appendAscii(" WHERE "); + sSql.append( rCondition ); + executeDelete(_rDeleteRow,sSql.makeStringAndClear(),aSqlIter->first); + } + } +} +// ------------------------------------------------------------------------- +void OptimisticSet::executeDelete(const ORowSetRow& _rDeleteRow,const ::rtl::OUString& i_sSQL,const ::rtl::OUString& i_sTableName) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OptimisticSet::executeDelete" ); + + // now create end execute the prepared statement + Reference< XPreparedStatement > xPrep(m_xConnection->prepareStatement(i_sSQL)); + Reference< XParameters > xParameter(xPrep,UNO_QUERY); + + SelectColumnsMetaData::const_iterator aIter = m_pKeyColumnNames->begin(); + SelectColumnsMetaData::const_iterator aEnd = m_pKeyColumnNames->end(); + sal_Int32 i = 1; + for(;aIter != aEnd;++aIter) + { + if ( aIter->second.sTableName == i_sTableName ) + setParameter(i++,xParameter,(_rDeleteRow->get())[aIter->second.nPosition],aIter->second.nType,aIter->second.nScale); + } + m_bDeleted = xPrep->executeUpdate() > 0; + + if(m_bDeleted) + { + sal_Int32 nBookmark = ::comphelper::getINT32((_rDeleteRow->get())[0].getAny()); + if(m_aKeyIter == m_aKeyMap.find(nBookmark) && m_aKeyIter != m_aKeyMap.end()) + ++m_aKeyIter; + m_aKeyMap.erase(nBookmark); + m_bDeleted = sal_True; + } +} +// ----------------------------------------------------------------------------- +::rtl::OUString OptimisticSet::getComposedTableName(const ::rtl::OUString& /*_sCatalog*/, + const ::rtl::OUString& /*_sSchema*/, + const ::rtl::OUString& /*_sTable*/) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OptimisticSet::getComposedTableName" ); + ::rtl::OUString aComposedName; +/* + Reference<XDatabaseMetaData> xMetaData = m_xConnection->getMetaData(); + + if( xMetaData.is() && xMetaData->supportsTableCorrelationNames() ) + { + aComposedName = ::dbtools::composeTableName( xMetaData, _sCatalog, _sSchema, _sTable, sal_False, ::dbtools::eInDataManipulation ); + // first we have to check if the composed tablename is in the select clause or if an alias is used + Reference<XTablesSupplier> xTabSup(m_xComposer,UNO_QUERY); + Reference<XNameAccess> xSelectTables = xTabSup->getTables(); + OSL_ENSURE(xSelectTables.is(),"No Select tables!"); + if(xSelectTables.is()) + { + if(!xSelectTables->hasByName(aComposedName)) + { // the composed name isn't used in the select clause so we have to find out which name is used instead + ::rtl::OUString sCatalog,sSchema,sTable; + ::dbtools::qualifiedNameComponents(xMetaData,m_sUpdateTableName,sCatalog,sSchema,sTable,::dbtools::eInDataManipulation); + aComposedName = ::dbtools::composeTableNameForSelect( m_xConnection, sCatalog, sSchema, sTable ); + } + else + aComposedName = ::dbtools::composeTableNameForSelect( m_xConnection, _sCatalog, _sSchema, _sTable ); + } + } + else + aComposedName = ::dbtools::composeTableNameForSelect( m_xConnection, _sCatalog, _sSchema, _sTable ); +*/ + return aComposedName; +} +// ----------------------------------------------------------------------------- +void OptimisticSet::fillJoinedColumns_throw(const ::std::vector< TNodePair >& i_aJoinColumns) +{ + ::std::vector< TNodePair >::const_iterator aIter = i_aJoinColumns.begin(); + for(;aIter != i_aJoinColumns.end();++aIter) + { + ::rtl::OUString sColumnName,sTableName; + m_aSqlIterator.getColumnRange(aIter->first,sColumnName,sTableName); + ::rtl::OUStringBuffer sLeft,sRight; + sLeft.append(sTableName); + sLeft.appendAscii("."); + sLeft.append(sColumnName); + m_aSqlIterator.getColumnRange(aIter->second,sColumnName,sTableName); + sRight.append(sTableName); + sRight.appendAscii("."); + sRight.append(sColumnName); + fillJoinedColumns_throw(sLeft.makeStringAndClear(),sRight.makeStringAndClear()); + } +} +// ----------------------------------------------------------------------------- +void OptimisticSet::fillJoinedColumns_throw(const ::rtl::OUString& i_sLeftColumn,const ::rtl::OUString& i_sRightColumn) +{ + sal_Int32 nLeft = 0,nRight = 0; + SelectColumnsMetaData::const_iterator aLeftIter = m_pKeyColumnNames->find(i_sLeftColumn); + SelectColumnsMetaData::const_iterator aRightIter = m_pKeyColumnNames->find(i_sRightColumn); + + bool bLeftKey = aLeftIter != m_pKeyColumnNames->end(); + if ( bLeftKey ) + { + nLeft = aLeftIter->second.nPosition; + } + else + { + aLeftIter = m_pColumnNames->find(i_sLeftColumn); + if ( aLeftIter != m_pColumnNames->end() ) + nLeft = aLeftIter->second.nPosition; + } + + bool bRightKey = aRightIter != m_pKeyColumnNames->end(); + if ( bRightKey ) + { + nRight = aRightIter->second.nPosition; + } + else + { + aRightIter = m_pColumnNames->find(i_sRightColumn); + if ( aRightIter != m_pColumnNames->end() ) + nRight = aRightIter->second.nPosition; + } + + if (bLeftKey) + m_aJoinedKeyColumns[nLeft] = nRight; + else + m_aJoinedColumns[nLeft] = nRight; + if (bRightKey) + m_aJoinedKeyColumns[nRight] = nLeft; + else + m_aJoinedColumns[nRight] = nLeft; +} +// ----------------------------------------------------------------------------- +bool OptimisticSet::isResultSetChanged() const +{ + bool bOld = m_bResultSetChanged; + m_bResultSetChanged = false; + return bOld; +} +// ----------------------------------------------------------------------------- +void OptimisticSet::reset(const Reference< XResultSet>& _xDriverSet) +{ + OCacheSet::construct(_xDriverSet,::rtl::OUString()); + m_bRowCountFinal = sal_False; + m_aKeyMap.clear(); + m_aKeyMap.insert(OKeySetMatrix::value_type(0,OKeySetValue(NULL,::std::pair<sal_Int32,Reference<XRow> >(0,NULL)))); + m_aKeyIter = m_aKeyMap.begin(); +} +// ----------------------------------------------------------------------------- +void OptimisticSet::mergeColumnValues(sal_Int32 i_nColumnIndex,ORowSetValueVector::Vector& io_aInsertRow,ORowSetValueVector::Vector& io_aRow,::std::vector<sal_Int32>& o_aChangedColumns) +{ + o_aChangedColumns.push_back(i_nColumnIndex); + ::std::map<sal_Int32,sal_Int32>::const_iterator aJoinIter = m_aJoinedColumns.find(i_nColumnIndex); + if ( aJoinIter != m_aJoinedColumns.end() ) + { + io_aRow[aJoinIter->second] = io_aRow[i_nColumnIndex]; + io_aInsertRow[aJoinIter->second] = io_aInsertRow[i_nColumnIndex]; + io_aRow[aJoinIter->second].setModified(); + o_aChangedColumns.push_back(aJoinIter->second); + } +} +namespace +{ + struct PositionFunctor : ::std::unary_function<SelectColumnsMetaData::value_type,bool> + { + sal_Int32 m_nPos; + PositionFunctor(sal_Int32 i_nPos) + : m_nPos(i_nPos) + { + } + + inline bool operator()(const SelectColumnsMetaData::value_type& _aType) + { + return m_nPos == _aType.second.nPosition; + } + }; + struct TableNameFunctor : ::std::unary_function<SelectColumnsMetaData::value_type,bool> + { + ::rtl::OUString m_sTableName; + TableNameFunctor(const ::rtl::OUString& i_sTableName) + : m_sTableName(i_sTableName) + { + } + + inline bool operator()(const SelectColumnsMetaData::value_type& _aType) + { + return m_sTableName == _aType.second.sTableName; + } + }; +} +// ----------------------------------------------------------------------------- +bool OptimisticSet::updateColumnValues(const ORowSetValueVector::Vector& io_aCachedRow,ORowSetValueVector::Vector& io_aRow,const ::std::vector<sal_Int32>& i_aChangedColumns) +{ + bool bRet = false; + ::std::vector<sal_Int32>::const_iterator aColIdxIter = i_aChangedColumns.begin(); + for(;aColIdxIter != i_aChangedColumns.end();++aColIdxIter) + { + SelectColumnsMetaData::const_iterator aFind = ::std::find_if(m_pKeyColumnNames->begin(),m_pKeyColumnNames->end(),PositionFunctor(*aColIdxIter)); + if ( aFind != m_pKeyColumnNames->end() ) + { + const ::rtl::OUString sTableName = aFind->second.sTableName; + aFind = ::std::find_if(m_pKeyColumnNames->begin(),m_pKeyColumnNames->end(),TableNameFunctor(sTableName)); + while( aFind != m_pKeyColumnNames->end() ) + { + io_aRow[aFind->second.nPosition].setSigned(io_aCachedRow[aFind->second.nPosition].isSigned()); + if ( io_aCachedRow[aFind->second.nPosition] != io_aRow[aFind->second.nPosition] ) + break; + ++aFind; + } + if ( aFind == m_pKeyColumnNames->end() ) + { + bRet = true; + SelectColumnsMetaData::const_iterator aIter = m_pColumnNames->begin(); + SelectColumnsMetaData::const_iterator aEnd = m_pColumnNames->end(); + for ( ;aIter != aEnd;++aIter ) + { + if ( aIter->second.sTableName == sTableName ) + { + io_aRow[aIter->second.nPosition] = io_aCachedRow[aIter->second.nPosition]; + io_aRow[aIter->second.nPosition].setModified(); + } + } + } + } + } + return bRet; +} +// ----------------------------------------------------------------------------- +bool OptimisticSet::columnValuesUpdated(ORowSetValueVector::Vector& o_aCachedRow,const ORowSetValueVector::Vector& i_aRow) +{ + bool bRet = false; + SelectColumnsMetaData::const_iterator aIter = m_pColumnNames->begin(); + SelectColumnsMetaData::const_iterator aEnd = m_pColumnNames->end(); + for(;aIter != aEnd;++aIter) + { + SelectColumnsMetaData::const_iterator aFind = ::std::find_if(m_pKeyColumnNames->begin(),m_pKeyColumnNames->end(),PositionFunctor(aIter->second.nPosition)); + if ( aFind != m_pKeyColumnNames->end() ) + { + const ::rtl::OUString sTableName = aFind->second.sTableName; + aFind = ::std::find_if(m_pKeyColumnNames->begin(),m_pKeyColumnNames->end(),TableNameFunctor(sTableName)); + while( aFind != m_pKeyColumnNames->end() ) + { + o_aCachedRow[aFind->second.nPosition].setSigned(i_aRow[aFind->second.nPosition].isSigned()); + if ( o_aCachedRow[aFind->second.nPosition] != i_aRow[aFind->second.nPosition] ) + break; + ++aFind; + } + if ( aFind == m_pKeyColumnNames->end() ) + { + bRet = true; + SelectColumnsMetaData::const_iterator aIter2 = m_pColumnNames->begin(); + SelectColumnsMetaData::const_iterator aEnd2 = m_pColumnNames->end(); + for ( ;aIter2 != aEnd2;++aIter2 ) + { + if ( aIter2->second.sTableName == sTableName ) + { + o_aCachedRow[aIter2->second.nPosition] = i_aRow[aIter2->second.nPosition]; + o_aCachedRow[aIter2->second.nPosition].setModified(); + } + } + fillMissingValues(o_aCachedRow); + } + } + } + return bRet; +} +// ----------------------------------------------------------------------------- +void OptimisticSet::fillMissingValues(ORowSetValueVector::Vector& io_aRow) const +{ + TSQLStatements aSql; + TSQLStatements aKeyConditions; + ::std::map< ::rtl::OUString,bool > aResultSetChanged; + ::rtl::OUString aQuote = getIdentifierQuoteString(); + static ::rtl::OUString aAnd = ::rtl::OUString::createFromAscii(" AND "); + ::rtl::OUString sIsNull(RTL_CONSTASCII_USTRINGPARAM(" IS NULL")); + ::rtl::OUString sParam(RTL_CONSTASCII_USTRINGPARAM(" = ?")); + // here we build the condition part for the update statement + SelectColumnsMetaData::const_iterator aColIter = m_pColumnNames->begin(); + SelectColumnsMetaData::const_iterator aColEnd = m_pColumnNames->end(); + for(;aColIter != aColEnd;++aColIter) + { + const ::rtl::OUString sQuotedColumnName = ::dbtools::quoteName( aQuote,aColIter->second.sRealName); + if ( m_aJoinedKeyColumns.find(aColIter->second.nPosition) != m_aJoinedKeyColumns.end() ) + { + lcl_fillKeyCondition(aColIter->second.sTableName,sQuotedColumnName,io_aRow[aColIter->second.nPosition],aKeyConditions); + } + ::rtl::OUStringBuffer& rPart = aSql[aColIter->second.sTableName]; + if ( rPart.getLength() ) + rPart.appendAscii(", "); + rPart.append(sQuotedColumnName); + } + Reference<XDatabaseMetaData> xMetaData = m_xConnection->getMetaData(); + TSQLStatements::iterator aSqlIter = aSql.begin(); + TSQLStatements::iterator aSqlEnd = aSql.end(); + for(;aSqlIter != aSqlEnd ; ++aSqlIter) + { + if ( aSqlIter->second.getLength() ) + { + ::rtl::OUStringBuffer& rCondition = aKeyConditions[aSqlIter->first]; + if ( rCondition.getLength() ) + { + ::rtl::OUString sCatalog,sSchema,sTable; + ::dbtools::qualifiedNameComponents(xMetaData,aSqlIter->first,sCatalog,sSchema,sTable,::dbtools::eInDataManipulation); + ::rtl::OUString sComposedTableName = ::dbtools::composeTableNameForSelect( m_xConnection, sCatalog, sSchema, sTable ); + ::rtl::OUStringBuffer sQuery; + sQuery.appendAscii("SELECT "); + sQuery.append(aSqlIter->second); + sQuery.appendAscii(" FROM "); + sQuery.append(sComposedTableName); + sQuery.appendAscii(" WHERE "); + sQuery.append(rCondition.makeStringAndClear()); + + try + { + Reference< XPreparedStatement > xPrep(m_xConnection->prepareStatement(sQuery.makeStringAndClear())); + Reference< XParameters > xParameter(xPrep,UNO_QUERY); + // and then the values of the where condition + SelectColumnsMetaData::iterator aKeyIter = m_pKeyColumnNames->begin(); + SelectColumnsMetaData::iterator aKeyEnd = m_pKeyColumnNames->end(); + sal_Int32 i = 1; + for(;aKeyIter != aKeyEnd;++aKeyIter) + { + if ( aKeyIter->second.sTableName == aSqlIter->first ) + { + setParameter(i++,xParameter,io_aRow[aKeyIter->second.nPosition],aKeyIter->second.nType,aKeyIter->second.nScale); + } + } + Reference<XResultSet> xRes = xPrep->executeQuery(); + Reference<XRow> xRow(xRes,UNO_QUERY); + if ( xRow.is() && xRes->next() ) + { + i = 1; + aColIter = m_pColumnNames->begin(); + for(;aColIter != aColEnd;++aColIter) + { + if ( aColIter->second.sTableName == aSqlIter->first ) + { + io_aRow[aColIter->second.nPosition].fill(i++,aColIter->second.nType,aColIter->second.bNullable,xRow); + io_aRow[aColIter->second.nPosition].setModified(); + } + } + } + } + catch(const SQLException&) + { + } + } + } + } +} +// ----------------------------------------------------------------------------- + diff --git a/dbaccess/source/core/api/OptimisticSet.hxx b/dbaccess/source/core/api/OptimisticSet.hxx new file mode 100644 index 000000000000..ba0a04c8b773 --- /dev/null +++ b/dbaccess/source/core/api/OptimisticSet.hxx @@ -0,0 +1,109 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: KeySet.hxx,v $ + * $Revision: 1.30 $ + * + * 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. + * + ************************************************************************/ + +#ifndef DBACCESS_CORE_API_OPTIMISTICSET_HXX +#define DBACCESS_CORE_API_OPTIMISTICSET_HXX + +#include "KeySet.hxx" +#include <cppuhelper/implbase1.hxx> + +#include <connectivity/sqlparse.hxx> +#include <connectivity/sqliterator.hxx> + +#include <com/sun/star/lang/XUnoTunnel.hpp> +#include <com/sun/star/sdb/XSingleSelectQueryAnalyzer.hpp> +#include <comphelper/stl_types.hxx> +#include <comphelper/componentcontext.hxx> + +namespace dbaccess +{ + // is used when the source supports keys + class OptimisticSet : public OKeySet + { + ::connectivity::OSQLParser m_aSqlParser; + ::connectivity::OSQLParseTreeIterator m_aSqlIterator; + + ::std::map<sal_Int32,sal_Int32> m_aJoinedColumns; + ::std::map<sal_Int32,sal_Int32> m_aJoinedKeyColumns; + + + mutable bool m_bResultSetChanged; + + /** + getComposedTableName return the composed table name for the query + @param _sCatalog the catalogname may be empty + @param _sSchema the schemaname may be empty + @param _sTable the tablename + + @return the composed name + */ + ::rtl::OUString getComposedTableName( const ::rtl::OUString& _sCatalog, + const ::rtl::OUString& _sSchema, + const ::rtl::OUString& _sTable); + + void impl_convertValue_throw(const ORowSetRow& _rInsertRow,const SelectColumnDescription& i_aMetaData); + + void executeDelete(const ORowSetRow& _rDeleteRow,const ::rtl::OUString& i_sSQL,const ::rtl::OUString& i_sTableName); + void fillJoinedColumns_throw(const ::std::vector< ::connectivity::TNodePair>& i_aJoinColumns); + void fillJoinedColumns_throw(const ::rtl::OUString& i_sLeftColumn,const ::rtl::OUString& i_sRightColumn); + protected: + virtual ~OptimisticSet(); + public: + OptimisticSet(const ::comphelper::ComponentContext& _rContext, + const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection>& i_xConnection, + const ::com::sun::star::uno::Reference< ::com::sun::star::sdb::XSingleSelectQueryAnalyzer >& _xComposer, + const ORowSetValueVector& _aParameterValueForCache); + + // late ctor which can throw exceptions + virtual void construct(const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XResultSet>& _xDriverSet,const ::rtl::OUString& i_sRowSetFilter); + + // ------------------------------------------------------------------------- + // ::com::sun::star::sdbcx::XDeleteRows + virtual ::com::sun::star::uno::Sequence< sal_Int32 > SAL_CALL deleteRows( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& rows ,const connectivity::OSQLTable& _xTable) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + // ::com::sun::star::sdbc::XResultSetUpdate + virtual void SAL_CALL updateRow(const ORowSetRow& _rInsertRow,const ORowSetRow& _rOrginalRow,const connectivity::OSQLTable& _xTable ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL deleteRow(const ORowSetRow& _rInsertRow,const connectivity::OSQLTable& _xTable ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL insertRow( const ORowSetRow& _rInsertRow,const connectivity::OSQLTable& _xTable ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + + // CacheSet + virtual bool isResultSetChanged() const; + virtual void reset(const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XResultSet>& _xDriverSet); + virtual void mergeColumnValues(sal_Int32 i_nColumnIndex,ORowSetValueVector::Vector& io_aInsertRow,ORowSetValueVector::Vector& io_aRow,::std::vector<sal_Int32>& o_aChangedColumns); + virtual bool columnValuesUpdated(ORowSetValueVector::Vector& o_aCachedRow,const ORowSetValueVector::Vector& i_aRow); + virtual bool updateColumnValues(const ORowSetValueVector::Vector& io_aCachedRow,ORowSetValueVector::Vector& io_aRow,const ::std::vector<sal_Int32>& i_aChangedColumns); + virtual void fillMissingValues(ORowSetValueVector::Vector& io_aRow) const; + + bool isReadOnly() const { return m_aJoinedKeyColumns.empty(); } + const ::std::map<sal_Int32,sal_Int32>& getJoinedColumns() const { return m_aJoinedColumns; } + const ::std::map<sal_Int32,sal_Int32>& getJoinedKeyColumns() const { return m_aJoinedKeyColumns; } + }; +} +#endif // DBACCESS_CORE_API_OPTIMISTICSET_HXX + diff --git a/dbaccess/source/core/api/PrivateRow.cxx b/dbaccess/source/core/api/PrivateRow.cxx new file mode 100644 index 000000000000..939e335b4cb3 --- /dev/null +++ b/dbaccess/source/core/api/PrivateRow.cxx @@ -0,0 +1,142 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle andor 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_dbaccess.hxx" +#include "PrivateRow.hxx" + +using namespace dbaccess; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::sdb; +using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::util; +using namespace ::com::sun::star; + +::sal_Bool SAL_CALL OPrivateRow::wasNull( ) throw (SQLException, RuntimeException) + { + return m_aRow[m_nPos].isNull(); + } + ::rtl::OUString SAL_CALL OPrivateRow::getString( ::sal_Int32 columnIndex ) throw (SQLException, RuntimeException) + { + m_nPos = columnIndex; + return m_aRow[m_nPos]; + } + ::sal_Bool SAL_CALL OPrivateRow::getBoolean( ::sal_Int32 columnIndex ) throw (SQLException, RuntimeException) + { + m_nPos = columnIndex; + return m_aRow[m_nPos]; + } + ::sal_Int8 SAL_CALL OPrivateRow::getByte( ::sal_Int32 columnIndex ) throw (SQLException, RuntimeException) + { + m_nPos = columnIndex; + return m_aRow[m_nPos]; + } + ::sal_Int16 SAL_CALL OPrivateRow::getShort( ::sal_Int32 columnIndex ) throw (SQLException, RuntimeException) + { + m_nPos = columnIndex; + return m_aRow[m_nPos]; + } + ::sal_Int32 SAL_CALL OPrivateRow::getInt( ::sal_Int32 columnIndex ) throw (SQLException, RuntimeException) + { + m_nPos = columnIndex; + return m_aRow[m_nPos]; + } + ::sal_Int64 SAL_CALL OPrivateRow::getLong( ::sal_Int32 columnIndex ) throw (SQLException, RuntimeException) + { + m_nPos = columnIndex; + return m_aRow[m_nPos]; + } + float SAL_CALL OPrivateRow::getFloat( ::sal_Int32 columnIndex ) throw (SQLException, RuntimeException) + { + m_nPos = columnIndex; + return m_aRow[m_nPos]; + } + double SAL_CALL OPrivateRow::getDouble( ::sal_Int32 columnIndex ) throw (SQLException, RuntimeException) + { + m_nPos = columnIndex; + return m_aRow[m_nPos]; + } + Sequence< ::sal_Int8 > SAL_CALL OPrivateRow::getBytes( ::sal_Int32 columnIndex ) throw (SQLException, RuntimeException) + { + m_nPos = columnIndex; + return m_aRow[m_nPos]; + } + ::com::sun::star::util::Date SAL_CALL OPrivateRow::getDate( ::sal_Int32 columnIndex ) throw (SQLException, RuntimeException) + { + m_nPos = columnIndex; + return m_aRow[m_nPos]; + } + ::com::sun::star::util::Time SAL_CALL OPrivateRow::getTime( ::sal_Int32 columnIndex ) throw (SQLException, RuntimeException) + { + m_nPos = columnIndex; + return m_aRow[m_nPos]; + } + ::com::sun::star::util::DateTime SAL_CALL OPrivateRow::getTimestamp( ::sal_Int32 columnIndex ) throw (SQLException, RuntimeException) + { + m_nPos = columnIndex; + return m_aRow[m_nPos]; + } + Reference< ::com::sun::star::io::XInputStream > SAL_CALL OPrivateRow::getBinaryStream( ::sal_Int32 columnIndex ) throw (SQLException, RuntimeException) + { + m_nPos = columnIndex; + return Reference< ::com::sun::star::io::XInputStream >(m_aRow[m_nPos].makeAny(),UNO_QUERY); + } + Reference< ::com::sun::star::io::XInputStream > SAL_CALL OPrivateRow::getCharacterStream( ::sal_Int32 columnIndex ) throw (SQLException, RuntimeException) + { + m_nPos = columnIndex; + return Reference< ::com::sun::star::io::XInputStream >(m_aRow[m_nPos].makeAny(),UNO_QUERY); + } + Any SAL_CALL OPrivateRow::getObject( ::sal_Int32 columnIndex, const Reference< ::com::sun::star::container::XNameAccess >& ) throw (SQLException, RuntimeException) + { + m_nPos = columnIndex; + return m_aRow[m_nPos].makeAny(); + } + Reference< XRef > SAL_CALL OPrivateRow::getRef( ::sal_Int32 columnIndex ) throw (SQLException, RuntimeException) + { + m_nPos = columnIndex; + return Reference< XRef >(m_aRow[m_nPos].makeAny(),UNO_QUERY); + } + Reference< XBlob > SAL_CALL OPrivateRow::getBlob( ::sal_Int32 columnIndex ) throw (SQLException, RuntimeException) + { + m_nPos = columnIndex; + return Reference< XBlob >(m_aRow[m_nPos].makeAny(),UNO_QUERY); + } + Reference< XClob > SAL_CALL OPrivateRow::getClob( ::sal_Int32 columnIndex ) throw (SQLException, RuntimeException) + { + m_nPos = columnIndex; + return Reference< XClob >(m_aRow[m_nPos].makeAny(),UNO_QUERY); + } + Reference< XArray > SAL_CALL OPrivateRow::getArray( ::sal_Int32 columnIndex ) throw (SQLException, RuntimeException) + { + m_nPos = columnIndex; + return Reference< XArray >(m_aRow[m_nPos].makeAny(),UNO_QUERY); + } + diff --git a/dbaccess/source/core/api/PrivateRow.hxx b/dbaccess/source/core/api/PrivateRow.hxx new file mode 100644 index 000000000000..82dd97232c92 --- /dev/null +++ b/dbaccess/source/core/api/PrivateRow.hxx @@ -0,0 +1,69 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: OptimisticSet.cxx,v $ + * $Revision: 1.73 $ + * + * 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. + * + ************************************************************************/ +#ifndef PRIVATE_ROW_HXX +#define PRIVATE_ROW_HXX + +#include <cppuhelper/implbase1.hxx> +#include <com/sun/star/sdbc/XRow.hpp> +#include "RowSetRow.hxx" + +namespace dbaccess +{ + class OPrivateRow : public ::cppu::WeakImplHelper1< ::com::sun::star::sdbc::XRow> + { + ORowSetValueVector::Vector m_aRow; + sal_Int32 m_nPos; + public: + OPrivateRow(const ORowSetValueVector::Vector& i_aRow) : m_aRow(i_aRow),m_nPos(0) + { + } + virtual ::sal_Bool SAL_CALL wasNull( ) throw (::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getString( ::sal_Int32 columnIndex ) throw (::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::sal_Bool SAL_CALL getBoolean( ::sal_Int32 columnIndex ) throw (::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::sal_Int8 SAL_CALL getByte( ::sal_Int32 columnIndex ) throw (::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::sal_Int16 SAL_CALL getShort( ::sal_Int32 columnIndex ) throw (::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::sal_Int32 SAL_CALL getInt( ::sal_Int32 columnIndex ) throw (::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::sal_Int64 SAL_CALL getLong( ::sal_Int32 columnIndex ) throw (::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual float SAL_CALL getFloat( ::sal_Int32 columnIndex ) throw (::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual double SAL_CALL getDouble( ::sal_Int32 columnIndex ) throw (::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::sal_Int8 > SAL_CALL getBytes( ::sal_Int32 columnIndex ) throw (::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::util::Date SAL_CALL getDate( ::sal_Int32 columnIndex ) throw (::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::util::Time SAL_CALL getTime( ::sal_Int32 columnIndex ) throw (::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::util::DateTime SAL_CALL getTimestamp( ::sal_Int32 columnIndex ) throw (::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > SAL_CALL getBinaryStream( ::sal_Int32 columnIndex ) throw (::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > SAL_CALL getCharacterStream( ::sal_Int32 columnIndex ) throw (::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Any SAL_CALL getObject( ::sal_Int32 columnIndex, const ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess >& typeMap ) throw (::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRef > SAL_CALL getRef( ::sal_Int32 columnIndex ) throw (::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XBlob > SAL_CALL getBlob( ::sal_Int32 columnIndex ) throw (::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XClob > SAL_CALL getClob( ::sal_Int32 columnIndex ) throw (::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XArray > SAL_CALL getArray( ::sal_Int32 columnIndex ) throw (::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + }; +} // dbaccess +#endif // PRIVATE_ROW_HXX diff --git a/dbaccess/source/core/api/RowSet.cxx b/dbaccess/source/core/api/RowSet.cxx new file mode 100644 index 000000000000..829155709119 --- /dev/null +++ b/dbaccess/source/core/api/RowSet.cxx @@ -0,0 +1,3057 @@ +/************************************************************************* + * + * 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_dbaccess.hxx" + +#include "RowSet.hxx" +#include "dbastrings.hrc" +#include "sdbcoretools.hxx" +#include "SingleSelectQueryComposer.hxx" +#include "module_dba.hxx" +#include "sdbcoretools.hxx" +#include "CRowSetColumn.hxx" +#include "CRowSetDataColumn.hxx" +#include "RowSetCache.hxx" +#include "core_resource.hrc" +#include "core_resource.hxx" +#include "tablecontainer.hxx" + +/** === begin UNO includes === **/ +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/container/XChild.hpp> +#include <com/sun/star/lang/DisposedException.hpp> +#include <com/sun/star/sdb/CommandType.hpp> +#include <com/sun/star/sdb/ErrorCondition.hpp> +#include <com/sun/star/sdb/RowChangeAction.hpp> +#include <com/sun/star/sdb/RowSetVetoException.hpp> +#include <com/sun/star/sdb/XCompletedConnection.hpp> +#include <com/sun/star/sdb/XParametersSupplier.hpp> +#include <com/sun/star/sdb/XQueriesSupplier.hpp> +#include <com/sun/star/sdbc/FetchDirection.hpp> +#include <com/sun/star/sdbc/ResultSetConcurrency.hpp> +#include <com/sun/star/sdbc/XDataSource.hpp> +#include <com/sun/star/sdbc/XDriverAccess.hpp> +#include <com/sun/star/sdbcx/CompareBookmark.hpp> +#include <com/sun/star/sdbcx/Privilege.hpp> +#include <com/sun/star/sdbcx/XDataDefinitionSupplier.hpp> +#include <com/sun/star/uno/XNamingService.hpp> +#include <com/sun/star/util/XNumberFormatsSupplier.hpp> +/** === end UNO includes === **/ + +#include <comphelper/componentcontext.hxx> +#include <comphelper/extract.hxx> +#include <comphelper/interaction.hxx> +#include <comphelper/property.hxx> +#include <comphelper/seqstream.hxx> +#include <comphelper/sequence.hxx> +#include <comphelper/types.hxx> +#include <comphelper/uno3.hxx> +#include <connectivity/BlobHelper.hxx> +#include <connectivity/dbconversion.hxx> +#include <connectivity/dbexception.hxx> +#include <connectivity/dbtools.hxx> +#include <cppuhelper/exc_hlp.hxx> +#include <cppuhelper/interfacecontainer.h> +#include <cppuhelper/typeprovider.hxx> +#include <rtl/logfile.hxx> +#include <unotools/syslocale.hxx> +#include <tools/debug.hxx> +#include <tools/diagnose_ex.h> +#include <unotools/configmgr.hxx> + +using namespace utl; +using namespace dbaccess; +using namespace connectivity; +using namespace comphelper; +using namespace dbtools; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::sdb; +using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::task; +using namespace ::com::sun::star::util; +using namespace ::cppu; +using namespace ::osl; + +//-------------------------------------------------------------------------- +extern "C" void SAL_CALL createRegistryInfo_ORowSet() +{ + static ::dba::OAutoRegistration< ORowSet > aAutoRegistration; +} +// ----------------------------------------------------------------------------- + +#define NOTIFY_LISTERNERS_CHECK(_rListeners,T,method) \ + Sequence< Reference< XInterface > > aListenerSeq = _rListeners.getElements(); \ + \ + const Reference< XInterface >* pxIntBegin = aListenerSeq.getConstArray(); \ + const Reference< XInterface >* pxInt = pxIntBegin + aListenerSeq.getLength(); \ + \ + _rGuard.clear(); \ + sal_Bool bCheck = sal_True; \ + while( pxInt > pxIntBegin && bCheck ) \ + { \ + try \ + { \ + while( pxInt > pxIntBegin && bCheck ) \ + { \ + --pxInt; \ + bCheck = static_cast< T* >( pxInt->get() )->method(aEvt); \ + } \ + } \ + catch( RuntimeException& ) \ + { \ + } \ + } \ + _rGuard.reset(); + + +//.................................................................. +namespace dbaccess +{ +//.................................................................. +//-------------------------------------------------------------------------- +Reference< XInterface > ORowSet_CreateInstance(const Reference< XMultiServiceFactory >& _rxFactory) +{ + return *(new ORowSet(_rxFactory)); +} +//-------------------------------------------------------------------------- +ORowSet::ORowSet( const Reference< ::com::sun::star::lang::XMultiServiceFactory >& _rxORB ) + :ORowSet_BASE1(m_aMutex) + ,ORowSetBase( _rxORB, ORowSet_BASE1::rBHelper, &m_aMutex ) + ,m_pParameters( NULL ) + ,m_aRowsetListeners(*m_pMutex) + ,m_aApproveListeners(*m_pMutex) + ,m_aRowsChangeListener(*m_pMutex) + ,m_pTables(NULL) + ,m_nFetchDirection(FetchDirection::FORWARD) + ,m_nFetchSize(50) + ,m_nMaxFieldSize(0) + ,m_nMaxRows(0) + ,m_nQueryTimeOut(0) + ,m_nCommandType(CommandType::COMMAND) + ,m_nTransactionIsolation(0) + ,m_nPrivileges(0) + ,m_nInAppend(0) + ,m_bUseEscapeProcessing(sal_True) + ,m_bApplyFilter(sal_False) + ,m_bCommandFacetsDirty( sal_True ) + ,m_bModified(sal_False) + ,m_bRebuildConnOnExecute(sal_False) + ,m_bIsBookmarable(sal_True) + ,m_bNew(sal_False) + ,m_bCanUpdateInsertedRows(sal_True) + ,m_bOwnConnection(sal_False) +{ + m_nResultSetType = ResultSetType::SCROLL_SENSITIVE; + m_nResultSetConcurrency = ResultSetConcurrency::UPDATABLE; + m_pMySelf = this; + m_aActiveConnection <<= m_xActiveConnection; + + sal_Int32 nRBT = PropertyAttribute::READONLY | PropertyAttribute::BOUND | PropertyAttribute::TRANSIENT; + sal_Int32 nRT = PropertyAttribute::READONLY | PropertyAttribute::TRANSIENT; + sal_Int32 nBT = PropertyAttribute::BOUND | PropertyAttribute::TRANSIENT; + + m_aPrematureParamValues.get().resize( 0 ); + + // sdb.RowSet Properties + registerMayBeVoidProperty(PROPERTY_ACTIVE_CONNECTION,PROPERTY_ID_ACTIVE_CONNECTION, PropertyAttribute::MAYBEVOID|PropertyAttribute::TRANSIENT|PropertyAttribute::BOUND, &m_aActiveConnection, ::getCppuType(reinterpret_cast< Reference< XConnection >* >(NULL))); + registerProperty(PROPERTY_DATASOURCENAME, PROPERTY_ID_DATASOURCENAME, PropertyAttribute::BOUND, &m_aDataSourceName, ::getCppuType(reinterpret_cast< ::rtl::OUString*>(NULL))); + registerProperty(PROPERTY_COMMAND, PROPERTY_ID_COMMAND, PropertyAttribute::BOUND, &m_aCommand, ::getCppuType(reinterpret_cast< ::rtl::OUString*>(NULL))); + registerProperty(PROPERTY_COMMAND_TYPE, PROPERTY_ID_COMMAND_TYPE, PropertyAttribute::BOUND, &m_nCommandType, ::getCppuType(reinterpret_cast< sal_Int32*>(NULL))); + registerProperty(PROPERTY_ACTIVECOMMAND, PROPERTY_ID_ACTIVECOMMAND, nRBT, &m_aActiveCommand, ::getCppuType(reinterpret_cast< ::rtl::OUString*>(NULL))); + registerProperty(PROPERTY_IGNORERESULT, PROPERTY_ID_IGNORERESULT, PropertyAttribute::BOUND, &m_bIgnoreResult, ::getBooleanCppuType()); + registerProperty(PROPERTY_FILTER, PROPERTY_ID_FILTER, PropertyAttribute::BOUND, &m_aFilter, ::getCppuType(reinterpret_cast< ::rtl::OUString*>(NULL))); + registerProperty(PROPERTY_HAVING_CLAUSE, PROPERTY_ID_HAVING_CLAUSE, PropertyAttribute::BOUND, &m_aHavingClause, ::getCppuType(reinterpret_cast< ::rtl::OUString*>(NULL))); + registerProperty(PROPERTY_GROUP_BY, PROPERTY_ID_GROUP_BY, PropertyAttribute::BOUND, &m_aGroupBy, ::getCppuType(reinterpret_cast< ::rtl::OUString*>(NULL))); + registerProperty(PROPERTY_APPLYFILTER, PROPERTY_ID_APPLYFILTER, PropertyAttribute::BOUND, &m_bApplyFilter, ::getBooleanCppuType()); + registerProperty(PROPERTY_ORDER, PROPERTY_ID_ORDER, PropertyAttribute::BOUND, &m_aOrder, ::getCppuType(reinterpret_cast< ::rtl::OUString*>(NULL))); + registerProperty(PROPERTY_PRIVILEGES, PROPERTY_ID_PRIVILEGES, nRT, &m_nPrivileges, ::getCppuType(reinterpret_cast< sal_Int32*>(NULL))); + registerProperty(PROPERTY_ISMODIFIED, PROPERTY_ID_ISMODIFIED, nBT, &m_bModified, ::getBooleanCppuType()); + registerProperty(PROPERTY_ISNEW, PROPERTY_ID_ISNEW, nRBT, &m_bNew, ::getBooleanCppuType()); + registerProperty(PROPERTY_SINGLESELECTQUERYCOMPOSER,PROPERTY_ID_SINGLESELECTQUERYCOMPOSER, nRT, &m_xComposer, ::getCppuType(reinterpret_cast< Reference< XSingleSelectQueryComposer >* >(NULL))); + + // sdbcx.ResultSet Properties + registerProperty(PROPERTY_ISBOOKMARKABLE, PROPERTY_ID_ISBOOKMARKABLE, nRT, &m_bIsBookmarable, ::getBooleanCppuType()); + registerProperty(PROPERTY_CANUPDATEINSERTEDROWS,PROPERTY_ID_CANUPDATEINSERTEDROWS, nRT, &m_bCanUpdateInsertedRows, ::getBooleanCppuType()); + // sdbc.ResultSet Properties + registerProperty(PROPERTY_RESULTSETCONCURRENCY, PROPERTY_ID_RESULTSETCONCURRENCY, PropertyAttribute::TRANSIENT, &m_nResultSetConcurrency,::getCppuType(reinterpret_cast< sal_Int32*>(NULL))); + registerProperty(PROPERTY_RESULTSETTYPE, PROPERTY_ID_RESULTSETTYPE, PropertyAttribute::TRANSIENT, &m_nResultSetType, ::getCppuType(reinterpret_cast< sal_Int32*>(NULL))); + registerProperty(PROPERTY_FETCHDIRECTION, PROPERTY_ID_FETCHDIRECTION, PropertyAttribute::TRANSIENT, &m_nFetchDirection, ::getCppuType(reinterpret_cast< sal_Int32*>(NULL))); + registerProperty(PROPERTY_FETCHSIZE, PROPERTY_ID_FETCHSIZE, PropertyAttribute::TRANSIENT, &m_nFetchSize, ::getCppuType(reinterpret_cast< sal_Int32*>(NULL))); + + // sdbc.RowSet Properties + registerProperty(PROPERTY_URL, PROPERTY_ID_URL, 0, &m_aURL, ::getCppuType(reinterpret_cast< ::rtl::OUString*>(NULL))); + registerProperty(PROPERTY_TRANSACTIONISOLATION, PROPERTY_ID_TRANSACTIONISOLATION, PropertyAttribute::TRANSIENT, &m_nTransactionIsolation,::getCppuType(reinterpret_cast< sal_Int32*>(NULL))); + registerMayBeVoidProperty(PROPERTY_TYPEMAP, PROPERTY_ID_TYPEMAP, PropertyAttribute::MAYBEVOID|PropertyAttribute::TRANSIENT, &m_aTypeMap, ::getCppuType(reinterpret_cast< Reference< XNameAccess >* >(NULL))); + registerProperty(PROPERTY_ESCAPE_PROCESSING,PROPERTY_ID_ESCAPE_PROCESSING, PropertyAttribute::BOUND, &m_bUseEscapeProcessing,::getBooleanCppuType() ); + registerProperty(PROPERTY_QUERYTIMEOUT, PROPERTY_ID_QUERYTIMEOUT, PropertyAttribute::TRANSIENT, &m_nQueryTimeOut, ::getCppuType(reinterpret_cast< sal_Int32*>(NULL))); + registerProperty(PROPERTY_MAXFIELDSIZE, PROPERTY_ID_MAXFIELDSIZE, PropertyAttribute::TRANSIENT, &m_nMaxFieldSize, ::getCppuType(reinterpret_cast< sal_Int32*>(NULL))); + registerProperty(PROPERTY_MAXROWS, PROPERTY_ID_MAXROWS, 0, &m_nMaxRows, ::getCppuType(reinterpret_cast< sal_Int32*>(NULL)) ); + registerProperty(PROPERTY_USER, PROPERTY_ID_USER, PropertyAttribute::TRANSIENT, &m_aUser, ::getCppuType(reinterpret_cast< ::rtl::OUString*>(NULL))); + registerProperty(PROPERTY_PASSWORD, PROPERTY_ID_PASSWORD, PropertyAttribute::TRANSIENT, &m_aPassword, ::getCppuType(reinterpret_cast< ::rtl::OUString*>(NULL))); + + registerProperty(PROPERTY_UPDATE_CATALOGNAME, PROPERTY_ID_UPDATE_CATALOGNAME, PropertyAttribute::BOUND, &m_aUpdateCatalogName, ::getCppuType(reinterpret_cast< ::rtl::OUString*>(NULL))); + registerProperty(PROPERTY_UPDATE_SCHEMANAME, PROPERTY_ID_UPDATE_SCHEMANAME, PropertyAttribute::BOUND, &m_aUpdateSchemaName, ::getCppuType(reinterpret_cast< ::rtl::OUString*>(NULL))); + registerProperty(PROPERTY_UPDATE_TABLENAME, PROPERTY_ID_UPDATE_TABLENAME, PropertyAttribute::BOUND, &m_aUpdateTableName, ::getCppuType(reinterpret_cast< ::rtl::OUString*>(NULL))); +} + +ORowSet::~ORowSet() +{ + if ( !m_rBHelper.bDisposed && !m_rBHelper.bInDispose ) + { + OSL_ENSURE(0, "Please check who doesn't dispose this component!"); + osl_incrementInterlockedCount( &m_refCount ); + dispose(); + } +} + +// ----------------------------------------------------------------------------- +void ORowSet::getPropertyDefaultByHandle( sal_Int32 _nHandle, Any& _rDefault ) const +{ + switch( _nHandle ) + { + case PROPERTY_ID_COMMAND_TYPE: + _rDefault <<= static_cast<sal_Int32>(CommandType::COMMAND); + break; + case PROPERTY_ID_IGNORERESULT: + _rDefault <<= sal_False; + break; + case PROPERTY_ID_APPLYFILTER: + _rDefault <<= sal_False; + break; + case PROPERTY_ID_ISMODIFIED: + _rDefault <<= sal_False; + break; + case PROPERTY_ID_ISBOOKMARKABLE: + _rDefault <<= sal_True; + break; + case PROPERTY_ID_CANUPDATEINSERTEDROWS: + _rDefault <<= sal_True; + break; + case PROPERTY_ID_RESULTSETTYPE: + _rDefault <<= ResultSetType::SCROLL_INSENSITIVE; + break; + case PROPERTY_ID_RESULTSETCONCURRENCY: + _rDefault <<= ResultSetConcurrency::UPDATABLE; + break; + case PROPERTY_ID_FETCHDIRECTION: + _rDefault <<= FetchDirection::FORWARD; + break; + case PROPERTY_ID_FETCHSIZE: + _rDefault <<= static_cast<sal_Int32>(1); + break; + case PROPERTY_ID_ESCAPE_PROCESSING: + _rDefault <<= sal_True; + break; + case PROPERTY_ID_MAXROWS: + _rDefault <<= sal_Int32( 0 ); + break; + case PROPERTY_ID_FILTER: + case PROPERTY_ID_HAVING_CLAUSE: + case PROPERTY_ID_GROUP_BY: + case PROPERTY_ID_ORDER: + case PROPERTY_ID_UPDATE_CATALOGNAME: + case PROPERTY_ID_UPDATE_SCHEMANAME: + case PROPERTY_ID_UPDATE_TABLENAME: + _rDefault <<= ::rtl::OUString(); + break; + } +} +// ------------------------------------------------------------------------- +// typedef ::comphelper::OPropertyArrayUsageHelper<ORowSet> ORowSet_Prop; + +void SAL_CALL ORowSet::setFastPropertyValue_NoBroadcast(sal_Int32 nHandle,const Any& rValue) throw (Exception) +{ + switch(nHandle) + { + case PROPERTY_ID_ISMODIFIED: + m_bModified = cppu::any2bool(rValue); + break; + case PROPERTY_ID_FETCHDIRECTION: + if( m_nResultSetType == ResultSetType::FORWARD_ONLY) + throw Exception(); // else run through + default: + OPropertyStateContainer::setFastPropertyValue_NoBroadcast(nHandle,rValue); + } + + if ( ( nHandle == PROPERTY_ID_ACTIVE_CONNECTION ) + || ( nHandle == PROPERTY_ID_DATASOURCENAME ) + || ( nHandle == PROPERTY_ID_COMMAND ) + || ( nHandle == PROPERTY_ID_COMMAND_TYPE ) + || ( nHandle == PROPERTY_ID_IGNORERESULT ) + || ( nHandle == PROPERTY_ID_FILTER ) + || ( nHandle == PROPERTY_ID_HAVING_CLAUSE ) + || ( nHandle == PROPERTY_ID_GROUP_BY ) + || ( nHandle == PROPERTY_ID_APPLYFILTER ) + || ( nHandle == PROPERTY_ID_ORDER ) + || ( nHandle == PROPERTY_ID_URL ) + || ( nHandle == PROPERTY_ID_USER ) + ) + { + m_bCommandFacetsDirty = sal_True; + } + + + switch(nHandle) + { + case PROPERTY_ID_ACTIVE_CONNECTION: + // the new connection + { + Reference< XConnection > xNewConnection(m_aActiveConnection,UNO_QUERY); + setActiveConnection(xNewConnection, sal_False); + } + + m_bOwnConnection = sal_False; + m_bRebuildConnOnExecute = sal_False; + break; + + case PROPERTY_ID_DATASOURCENAME: + if(!m_xStatement.is()) + { + Reference< XConnection > xNewConn; + Any aNewConn; + aNewConn <<= xNewConn; + setFastPropertyValue(PROPERTY_ID_ACTIVE_CONNECTION, aNewConn); + } + else + m_bRebuildConnOnExecute = sal_True; + break; + case PROPERTY_ID_FETCHSIZE: + if(m_pCache) + { + m_pCache->setMaxRowSize(m_nFetchSize); + fireRowcount(); + } + break; + case PROPERTY_ID_URL: + // is the connection-to-be-built determined by the url (which is the case if m_aDataSourceName is empty) ? + if (!m_aDataSourceName.getLength()) + { + // are we active at the moment ? + if (m_xStatement.is()) + // yes -> the next execute needs to rebuild our connection because of this new property + m_bRebuildConnOnExecute = sal_True; + else + { // no -> drop our active connection (if we have one) as it doesn't correspond to this new property value anymore + Reference< XConnection > xNewConn; + Any aNewConn; + aNewConn <<= xNewConn; + setFastPropertyValue(PROPERTY_ID_ACTIVE_CONNECTION, aNewConn); + } + } + m_bOwnConnection = sal_True; + break; + case PROPERTY_ID_TYPEMAP: + ::cppu::extractInterface(m_xTypeMap,m_aTypeMap); + break; + default: + break; + }; +} +// ------------------------------------------------------------------------- +void SAL_CALL ORowSet::getFastPropertyValue(Any& rValue,sal_Int32 nHandle) const +{ + if(m_pCache) + { + switch(nHandle) + { + case PROPERTY_ID_ISMODIFIED: + rValue.setValue(&m_bModified,::getCppuBooleanType()); + break; + case PROPERTY_ID_ISNEW: + rValue.setValue(&m_bNew,::getCppuBooleanType()); + break; + case PROPERTY_ID_PRIVILEGES: + rValue <<= m_pCache->m_nPrivileges; + break; + case PROPERTY_ID_ACTIVE_CONNECTION: + rValue <<= m_xActiveConnection; + break; + case PROPERTY_ID_TYPEMAP: + rValue <<= m_xTypeMap; + break; + default: + ORowSetBase::getFastPropertyValue(rValue,nHandle); + }; + } + else + { + switch(nHandle) + { + case PROPERTY_ID_ACTIVE_CONNECTION: + rValue <<= m_xActiveConnection; + break; + case PROPERTY_ID_TYPEMAP: + rValue <<= m_xTypeMap; + break; + default: + ORowSetBase::getFastPropertyValue(rValue,nHandle); + } + } +} +// ------------------------------------------------------------------------- +// com::sun::star::XTypeProvider +Sequence< Type > SAL_CALL ORowSet::getTypes() throw (RuntimeException) +{ + OTypeCollection aTypes(::getCppuType( (const Reference< XPropertySet > *)0 ), + ::getCppuType( (const Reference< XFastPropertySet > *)0 ), + ::getCppuType( (const Reference< XMultiPropertySet > *)0 ), + ::comphelper::concatSequences(ORowSet_BASE1::getTypes(),ORowSetBase::getTypes())); + return aTypes.getTypes(); +} +// ------------------------------------------------------------------------- +Sequence< sal_Int8 > SAL_CALL ORowSet::getImplementationId() throw (RuntimeException) +{ + static OImplementationId * pId = 0; + if (! pId) + { + MutexGuard aGuard( Mutex::getGlobalMutex() ); + if (! pId) + { + static OImplementationId aId; + pId = &aId; + } + } + return pId->getImplementationId(); +} +// ------------------------------------------------------------------------- + +// com::sun::star::XInterface +Any SAL_CALL ORowSet::queryInterface( const Type & rType ) throw (RuntimeException) +{ + return ORowSet_BASE1::queryInterface( rType); +} +// ------------------------------------------------------------------------- +void SAL_CALL ORowSet::acquire() throw() +{ + ORowSet_BASE1::acquire(); +} +// ------------------------------------------------------------------------- +void SAL_CALL ORowSet::release() throw() +{ + ORowSet_BASE1::release(); +} +// ------------------------------------------------------------------------- + +// com::sun::star::XUnoTunnel +sal_Int64 SAL_CALL ORowSet::getSomething( const Sequence< sal_Int8 >& rId ) throw(RuntimeException) +{ + if (rId.getLength() == 16 && 0 == rtl_compareMemory(getImplementationId().getConstArray(), rId.getConstArray(), 16 ) ) + return reinterpret_cast<sal_Int64>(this); + + return 0; +} +// ------------------------------------------------------------------------- +// com::sun::star::XAggregation +Any SAL_CALL ORowSet::queryAggregation( const Type& rType ) throw(RuntimeException) +{ + Any aRet(ORowSetBase::queryInterface(rType)); + if (!aRet.hasValue()) + aRet = ORowSet_BASE1::queryAggregation(rType); + return aRet; +} +//------------------------------------------------------------------------------ +rtl::OUString ORowSet::getImplementationName_static( ) throw(RuntimeException) +{ + return rtl::OUString::createFromAscii("com.sun.star.comp.dba.ORowSet"); +} +// ------------------------------------------------------------------------- +// ::com::sun::star::XServiceInfo +::rtl::OUString SAL_CALL ORowSet::getImplementationName( ) throw(RuntimeException) +{ + return getImplementationName_static(); +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL ORowSet::supportsService( const ::rtl::OUString& _rServiceName ) throw(RuntimeException) +{ + return ::comphelper::findValue(getSupportedServiceNames(), _rServiceName, sal_True).getLength() != 0; +} +//------------------------------------------------------------------------------ +Sequence< ::rtl::OUString > ORowSet::getSupportedServiceNames_static( ) throw (RuntimeException) +{ + Sequence< rtl::OUString > aSNS( 5 ); + aSNS[0] = SERVICE_SDBC_RESULTSET; + aSNS[1] = SERVICE_SDBC_ROWSET; + aSNS[2] = SERVICE_SDBCX_RESULTSET; + aSNS[3] = SERVICE_SDB_RESULTSET; + aSNS[4] = SERVICE_SDB_ROWSET; + return aSNS; +} +// ------------------------------------------------------------------------- +Sequence< ::rtl::OUString > SAL_CALL ORowSet::getSupportedServiceNames( ) throw(RuntimeException) +{ + return getSupportedServiceNames_static(); +} +//------------------------------------------------------------------------------ +Reference< XInterface > ORowSet::Create(const Reference< XComponentContext >& _rxContext) +{ + ::comphelper::ComponentContext aContext( _rxContext ); + return ORowSet_CreateInstance( aContext.getLegacyServiceFactory() ); +} +// ------------------------------------------------------------------------- +// OComponentHelper +void SAL_CALL ORowSet::disposing() +{ + OPropertyStateContainer::disposing(); + + MutexGuard aGuard(m_aMutex); + EventObject aDisposeEvent; + aDisposeEvent.Source = static_cast< XComponent* >(this); + m_aRowsetListeners.disposeAndClear( aDisposeEvent ); + m_aApproveListeners.disposeAndClear( aDisposeEvent ); + m_aRowsChangeListener.disposeAndClear( aDisposeEvent ); + + freeResources( true ); + + // remove myself as dispose listener + Reference< XComponent > xComponent(m_xActiveConnection, UNO_QUERY); + if (xComponent.is()) + { + Reference<XEventListener> xEvt; + query_aggregation(this,xEvt); + xComponent->removeEventListener(xEvt); + } + + m_aActiveConnection = Any(); // the any conatains a reference too + if(m_bOwnConnection) + ::comphelper::disposeComponent(m_xActiveConnection); + m_xActiveConnection = NULL; + + + ORowSetBase::disposing(); +} +// ------------------------------------------------------------------------- +void ORowSet::freeResources( bool _bComplete ) +{ + MutexGuard aGuard(m_aMutex); + + // free all clones + connectivity::OWeakRefArray::iterator aEnd = m_aClones.end(); + for (connectivity::OWeakRefArray::iterator i = m_aClones.begin(); aEnd != i; i++) + { + Reference< XComponent > xComp(i->get(), UNO_QUERY); + if (xComp.is()) + xComp->dispose(); + } + m_aClones.clear(); + + if ( _bComplete ) + { + // the columns must be disposed before the querycomposer is disposed because + // their owner can be the composer + TDataColumns().swap(m_aDataColumns);// clear and resize capacity + m_xColumns = NULL; + if ( m_pColumns ) + m_pColumns->disposing(); + // dispose the composer to avoid that everbody knows that the querycomposer is eol + try { ::comphelper::disposeComponent( m_xComposer ); } + catch(Exception&) + { + DBG_UNHANDLED_EXCEPTION(); + m_xComposer = NULL; + } + + // let our warnings container forget the reference to the (possibly disposed) old result set + m_aWarnings.setExternalWarnings( NULL ); + + DELETEZ(m_pCache); + + impl_resetTables_nothrow(); + + m_xStatement = NULL; + m_xTypeMap = NULL; + + m_aBookmark = Any(); + m_bBeforeFirst = sal_True; + m_bAfterLast = sal_False; + m_bNew = sal_False; + m_bModified = sal_False; + m_bLastKnownRowCountFinal = sal_False; + m_nLastKnownRowCount = 0; + if ( m_aOldRow.isValid() ) + m_aOldRow->clearRow(); + + impl_disposeParametersContainer_nothrow(); + + m_bCommandFacetsDirty = sal_True; + } +} + +// ------------------------------------------------------------------------- +void ORowSet::setActiveConnection( Reference< XConnection >& _rxNewConn, sal_Bool _bFireEvent ) +{ + if (_rxNewConn.get() == m_xActiveConnection.get()) + // nothing to do + return; + + // remove the event listener for the old connection + Reference< XComponent > xComponent(m_xActiveConnection, UNO_QUERY); + if (xComponent.is()) + { + Reference<XEventListener> xListener; + query_aggregation(this, xListener); + xComponent->removeEventListener(xListener); + } + + // if we owned the connection, remember it for later disposing + if(m_bOwnConnection) + m_xOldConnection = m_xActiveConnection; + + // for firing the PropertyChangeEvent + sal_Int32 nHandle = PROPERTY_ID_ACTIVE_CONNECTION; + Any aOldConnection; aOldConnection <<= m_xActiveConnection; + Any aNewConnection; aNewConnection <<= _rxNewConn; + + // set the new connection + m_xActiveConnection = _rxNewConn; + if (m_xActiveConnection.is()) + m_aActiveConnection <<= m_xActiveConnection; + else + m_aActiveConnection.clear(); + + // fire the event + if (_bFireEvent) + fire(&nHandle, &aNewConnection, &aOldConnection, 1, sal_False); + + // register as event listener for the new connection + xComponent.set(m_xActiveConnection,UNO_QUERY); + if (xComponent.is()) + { + Reference<XEventListener> xListener; + query_aggregation(this, xListener); + xComponent->addEventListener(xListener); + } +} + +// ------------------------------------------------------------------------- +// ::com::sun::star::XEventListener +void SAL_CALL ORowSet::disposing( const ::com::sun::star::lang::EventObject& Source ) throw(RuntimeException) +{ + // close rowset because the connection is going to be deleted (someone told me :-) + Reference<XConnection> xCon(Source.Source,UNO_QUERY); + if(m_xActiveConnection == xCon) + { + close(); + { + MutexGuard aGuard( m_aMutex ); + Reference< XConnection > xXConnection; + setActiveConnection( xXConnection ); + } + } +} +// ------------------------------------------------------------------------- + +// XCloseable +void SAL_CALL ORowSet::close( ) throw(SQLException, RuntimeException) +{ + { + MutexGuard aGuard( m_aMutex ); + ::connectivity::checkDisposed(ORowSet_BASE1::rBHelper.bDisposed); + } + // additionals things to set + freeResources( true ); +} +// ------------------------------------------------------------------------- +// comphelper::OPropertyArrayUsageHelper +::cppu::IPropertyArrayHelper* ORowSet::createArrayHelper( ) const +{ + Sequence< Property > aProps; + describeProperties(aProps); + return new ::cppu::OPropertyArrayHelper(aProps); +} +// ------------------------------------------------------------------------- +// cppu::OPropertySetHelper +::cppu::IPropertyArrayHelper& SAL_CALL ORowSet::getInfoHelper() +{ + typedef ::comphelper::OPropertyArrayUsageHelper<ORowSet> ORowSet_PROP; + return *ORowSet_PROP::getArrayHelper(); +} +// ----------------------------------------------------------------------------- +void ORowSet::updateValue(sal_Int32 columnIndex,const ORowSetValue& x) +{ + ::connectivity::checkDisposed(ORowSet_BASE1::rBHelper.bDisposed); + + ::osl::MutexGuard aGuard( *m_pMutex ); + checkUpdateConditions(columnIndex); + checkUpdateIterator(); + + ORowSetValueVector::Vector& rRow = ((*m_aCurrentRow)->get()); + ORowSetNotifier aNotify(this,rRow); + m_pCache->updateValue(columnIndex,x,rRow,aNotify.getChangedColumns()); + aNotify.firePropertyChange(); +} +// ------------------------------------------------------------------------- +// XRowUpdate +void SAL_CALL ORowSet::updateNull( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + ::connectivity::checkDisposed(ORowSet_BASE1::rBHelper.bDisposed); + + ::osl::MutexGuard aGuard( *m_pMutex ); + checkUpdateConditions(columnIndex); + checkUpdateIterator(); + + ORowSetValueVector::Vector& rRow = ((*m_aCurrentRow)->get()); + ORowSetNotifier aNotify(this,rRow); + m_pCache->updateNull(columnIndex,rRow,aNotify.getChangedColumns()); + aNotify.firePropertyChange(); +} +// ------------------------------------------------------------------------- +void SAL_CALL ORowSet::updateBoolean( sal_Int32 columnIndex, sal_Bool x ) throw(SQLException, RuntimeException) +{ + updateValue(columnIndex,x); +} +// ------------------------------------------------------------------------- +void SAL_CALL ORowSet::updateByte( sal_Int32 columnIndex, sal_Int8 x ) throw(SQLException, RuntimeException) +{ + updateValue(columnIndex,x); +} +// ------------------------------------------------------------------------- +void SAL_CALL ORowSet::updateShort( sal_Int32 columnIndex, sal_Int16 x ) throw(SQLException, RuntimeException) +{ + updateValue(columnIndex,x); +} +// ------------------------------------------------------------------------- +void SAL_CALL ORowSet::updateInt( sal_Int32 columnIndex, sal_Int32 x ) throw(SQLException, RuntimeException) +{ + updateValue(columnIndex,x); +} +// ------------------------------------------------------------------------- +void SAL_CALL ORowSet::updateLong( sal_Int32 columnIndex, sal_Int64 x ) throw(SQLException, RuntimeException) +{ + updateValue(columnIndex,x); +} +// ------------------------------------------------------------------------- +void SAL_CALL ORowSet::updateFloat( sal_Int32 columnIndex, float x ) throw(SQLException, RuntimeException) +{ + updateValue(columnIndex,x); +} +// ------------------------------------------------------------------------- +void SAL_CALL ORowSet::updateDouble( sal_Int32 columnIndex, double x ) throw(SQLException, RuntimeException) +{ + updateValue(columnIndex,x); +} +// ------------------------------------------------------------------------- +void SAL_CALL ORowSet::updateString( sal_Int32 columnIndex, const ::rtl::OUString& x ) throw(SQLException, RuntimeException) +{ + updateValue(columnIndex,x); +} +// ------------------------------------------------------------------------- +void SAL_CALL ORowSet::updateBytes( sal_Int32 columnIndex, const Sequence< sal_Int8 >& x ) throw(SQLException, RuntimeException) +{ + updateValue(columnIndex,x); +} +// ------------------------------------------------------------------------- +void SAL_CALL ORowSet::updateDate( sal_Int32 columnIndex, const ::com::sun::star::util::Date& x ) throw(SQLException, RuntimeException) +{ + updateValue(columnIndex,x); +} +// ------------------------------------------------------------------------- +void SAL_CALL ORowSet::updateTime( sal_Int32 columnIndex, const ::com::sun::star::util::Time& x ) throw(SQLException, RuntimeException) +{ + updateValue(columnIndex,x); +} +// ------------------------------------------------------------------------- +void SAL_CALL ORowSet::updateTimestamp( sal_Int32 columnIndex, const ::com::sun::star::util::DateTime& x ) throw(SQLException, RuntimeException) +{ + updateValue(columnIndex,x); +} +// ------------------------------------------------------------------------- +void SAL_CALL ORowSet::updateBinaryStream( sal_Int32 columnIndex, const Reference< ::com::sun::star::io::XInputStream >& x, sal_Int32 length ) throw(SQLException, RuntimeException) +{ + ::connectivity::checkDisposed(ORowSet_BASE1::rBHelper.bDisposed); + ::osl::MutexGuard aGuard( *m_pMutex ); + checkUpdateConditions(columnIndex); + checkUpdateIterator(); + + //if(((*m_aCurrentRow)->get())[columnIndex].getTypeKind() == DataType::BLOB) + //{ + // ::connectivity::ORowSetValue aOldValue = ((*m_aCurrentRow)->get())[columnIndex]; + // m_pCache->updateBinaryStream(columnIndex,x,length); + // ((*m_aCurrentRow)->get())[columnIndex] = makeAny(x); + // ((*m_aCurrentRow)->get())[columnIndex].setTypeKind(DataType::BLOB); + // firePropertyChange(columnIndex-1 ,aOldValue); + // fireProperty(PROPERTY_ID_ISMODIFIED,sal_True,sal_False); + //} + //else + { + Sequence<sal_Int8> aSeq; + if(x.is()) + x->readBytes(aSeq,length); + updateValue(columnIndex,aSeq); + } +} +// ------------------------------------------------------------------------- +void SAL_CALL ORowSet::updateCharacterStream( sal_Int32 columnIndex, const Reference< ::com::sun::star::io::XInputStream >& x, sal_Int32 length ) throw(SQLException, RuntimeException) +{ + ::connectivity::checkDisposed(ORowSet_BASE1::rBHelper.bDisposed); + ::osl::MutexGuard aGuard( *m_pMutex ); + checkUpdateConditions(columnIndex); + checkUpdateIterator(); + ORowSetValueVector::Vector& rRow = ((*m_aCurrentRow)->get()); + ORowSetNotifier aNotify(this,rRow); + m_pCache->updateCharacterStream(columnIndex,x,length,rRow,aNotify.getChangedColumns()); + aNotify.firePropertyChange(); +} +// ------------------------------------------------------------------------- +void SAL_CALL ORowSet::updateObject( sal_Int32 columnIndex, const Any& x ) throw(SQLException, RuntimeException) +{ + ::connectivity::checkDisposed(ORowSet_BASE1::rBHelper.bDisposed); + ::osl::MutexGuard aGuard( *m_pMutex ); + checkUpdateConditions(columnIndex); + checkUpdateIterator(); + + Any aNewValue = x; + + if ( m_pColumns ) + { + Reference<XPropertySet> xColumn(m_pColumns->getByIndex(columnIndex-1),UNO_QUERY); + sal_Int32 nColType = 0; + xColumn->getPropertyValue(PROPERTY_TYPE) >>= nColType; + switch( nColType ) + { + case DataType::DATE: + case DataType::TIME: + case DataType::TIMESTAMP: + { + double nValue = 0; + if ( x >>= nValue ) + { + if ( DataType::TIMESTAMP == nColType ) + aNewValue <<= dbtools::DBTypeConversion::toDateTime( nValue ); + else if ( DataType::DATE == nColType ) + aNewValue <<= dbtools::DBTypeConversion::toDate( nValue ); + else + aNewValue <<= dbtools::DBTypeConversion::toTime( nValue ); + } + break; + } + } + } + + if (!::dbtools::implUpdateObject(this, columnIndex, aNewValue)) + { // there is no other updateXXX call which can handle the value in x + ORowSetValueVector::Vector& rRow = ((*m_aCurrentRow)->get()); + ORowSetNotifier aNotify(this,rRow); + m_pCache->updateObject(columnIndex,aNewValue,rRow,aNotify.getChangedColumns()); + aNotify.firePropertyChange(); + } +} +// ------------------------------------------------------------------------- +void SAL_CALL ORowSet::updateNumericObject( sal_Int32 columnIndex, const Any& x, sal_Int32 scale ) throw(SQLException, RuntimeException) +{ + ::connectivity::checkDisposed(ORowSet_BASE1::rBHelper.bDisposed); + ::osl::MutexGuard aGuard( *m_pMutex ); + checkUpdateConditions(columnIndex); + checkUpdateIterator(); + ORowSetValueVector::Vector& rRow = ((*m_aCurrentRow)->get()); + ORowSetNotifier aNotify(this,rRow); + m_pCache->updateNumericObject(columnIndex,x,scale,rRow,aNotify.getChangedColumns()); + aNotify.firePropertyChange(); +} +// ------------------------------------------------------------------------- + +// XResultSetUpdate +void SAL_CALL ORowSet::insertRow( ) throw(SQLException, RuntimeException) +{ + ::connectivity::checkDisposed(ORowSet_BASE1::rBHelper.bDisposed); + // insertRow is not allowd when + // standing not on the insert row nor + // when the row isn't modified + // or the concurency is read only + ::osl::ResettableMutexGuard aGuard( *m_pMutex ); + + if(!m_pCache || !m_bNew || !m_bModified || m_nResultSetConcurrency == ResultSetConcurrency::READ_ONLY) + throwFunctionSequenceException(*this); + + if(m_bModified) + { + // remember old value for fire + sal_Bool bOld = m_bNew; + + ORowSetRow aOldValues; + if ( !m_aCurrentRow.isNull() ) + aOldValues = new ORowSetValueVector( m_aCurrentRow->getBody() ); + Sequence<Any> aChangedBookmarks; + RowsChangeEvent aEvt(*this,RowChangeAction::INSERT,1,aChangedBookmarks); + notifyAllListenersRowBeforeChange(aGuard,aEvt); + + ::std::vector< Any > aBookmarks; + sal_Bool bInserted = m_pCache->insertRow(aBookmarks); + + // make sure that our row is set to the new inserted row before clearing the insert flags in the cache + m_pCache->resetInsertRow(bInserted); + + // notification order + // - column values + setCurrentRow( sal_False, sal_True, aOldValues, aGuard ); // we don't move here + + // read-only flag restored + impl_restoreDataColumnsWriteable_throw(); + + // - rowChanged + notifyAllListenersRowChanged(aGuard,aEvt); + + if ( !aBookmarks.empty() ) + { + RowsChangeEvent aUpEvt(*this,RowChangeAction::UPDATE,aBookmarks.size(),Sequence<Any>(&(*aBookmarks.begin()),aBookmarks.size())); + notifyAllListenersRowChanged(aGuard,aUpEvt); + } + + // - IsModified + if(!m_bModified) + fireProperty(PROPERTY_ID_ISMODIFIED,sal_False,sal_True); + OSL_ENSURE( !m_bModified, "ORowSet::insertRow: just updated, but _still_ modified?" ); + + // - IsNew + if(m_bNew != bOld) + fireProperty(PROPERTY_ID_ISNEW,m_bNew,bOld); + + // - RowCount/IsRowCountFinal + fireRowcount(); + } +} +// ------------------------------------------------------------------------- +sal_Int32 SAL_CALL ORowSet::getRow( ) throw(SQLException, RuntimeException) +{ + ::osl::MutexGuard aGuard( *m_pMutex ); + checkCache(); + + // check if we are inserting a row + return (m_pCache && ( m_pCache->m_bNew || m_bModified )) ? 0 : ORowSetBase::getRow(); +} +// ------------------------------------------------------------------------- +void SAL_CALL ORowSet::updateRow( ) throw(SQLException, RuntimeException) +{ + ::connectivity::checkDisposed(ORowSet_BASE1::rBHelper.bDisposed); + // not allowed when standing on insert row + ::osl::ResettableMutexGuard aGuard( *m_pMutex ); + if ( !m_pCache || m_nResultSetConcurrency == ResultSetConcurrency::READ_ONLY || m_bNew || ((m_pCache->m_nPrivileges & Privilege::UPDATE ) != Privilege::UPDATE) ) + throwFunctionSequenceException(*this); + + + if(m_bModified) + { + ORowSetRow aOldValues; + if ( !m_aCurrentRow.isNull() ) + aOldValues = new ORowSetValueVector( m_aCurrentRow->getBody() ); + + Sequence<Any> aChangedBookmarks; + RowsChangeEvent aEvt(*this,RowChangeAction::UPDATE,1,aChangedBookmarks); + notifyAllListenersRowBeforeChange(aGuard,aEvt); + + ::std::vector< Any > aBookmarks; + m_pCache->updateRow(m_aCurrentRow.operator ->(),aBookmarks); + if ( !aBookmarks.empty() ) + aEvt.Bookmarks = Sequence<Any>(&(*aBookmarks.begin()),aBookmarks.size()); + aEvt.Rows += aBookmarks.size(); + m_aBookmark = m_pCache->getBookmark(); + m_aCurrentRow = m_pCache->m_aMatrixIter; + if ( m_pCache->m_aMatrixIter != m_pCache->getEnd() && (*m_pCache->m_aMatrixIter).isValid() ) + { + if ( m_pCache->isResultSetChanged() ) + { + impl_rebuild_throw(aGuard); + } + else + { + m_aOldRow->setRow(new ORowSetValueVector(m_aCurrentRow->getBody())); + + // notification order + // - column values + ORowSetBase::firePropertyChange(aOldValues); + } + // - rowChanged + notifyAllListenersRowChanged(aGuard,aEvt); + + // - IsModified + if(!m_bModified) + fireProperty(PROPERTY_ID_ISMODIFIED,sal_False,sal_True); + OSL_ENSURE( !m_bModified, "ORowSet::updateRow: just updated, but _still_ modified?" ); + + // - RowCount/IsRowCountFinal + fireRowcount(); + } + else if ( !m_bAfterLast ) // the update went rong + { + ::dbtools::throwSQLException( DBACORE_RESSTRING( RID_STR_UPDATE_FAILED ), SQL_INVALID_CURSOR_POSITION, *this ); + } + } +} +// ------------------------------------------------------------------------- +void SAL_CALL ORowSet::deleteRow( ) throw(SQLException, RuntimeException) +{ + ::connectivity::checkDisposed(ORowSet_BASE1::rBHelper.bDisposed); + + ::osl::ResettableMutexGuard aGuard( *m_pMutex ); + checkCache(); + + if ( m_bBeforeFirst || m_bAfterLast ) + ::dbtools::throwSQLException( DBACORE_RESSTRING( RID_STR_NO_DELETE_BEFORE_AFTER ), SQL_INVALID_CURSOR_POSITION, *this ); + if ( m_bNew ) + ::dbtools::throwSQLException( DBACORE_RESSTRING( RID_STR_NO_DELETE_INSERT_ROW ), SQL_INVALID_CURSOR_POSITION, *this ); + if ( m_nResultSetConcurrency == ResultSetConcurrency::READ_ONLY ) + ::dbtools::throwSQLException( DBACORE_RESSTRING( RID_STR_RESULT_IS_READONLY ), SQL_FUNCTION_SEQUENCE_ERROR, *this ); + if ( ( m_pCache->m_nPrivileges & Privilege::DELETE ) != Privilege::DELETE ) + ::dbtools::throwSQLException( DBACORE_RESSTRING( RID_STR_NO_DELETE_PRIVILEGE ), SQL_FUNCTION_SEQUENCE_ERROR, *this ); + if ( rowDeleted() ) + ::dbtools::throwSQLException( DBACORE_RESSTRING( RID_STR_ROW_ALREADY_DELETED ), SQL_FUNCTION_SEQUENCE_ERROR, *this ); + + // this call position the cache indirect + Any aBookmarkToDelete( m_aBookmark ); + positionCache( MOVE_NONE_REFRESH_ONLY ); + sal_Int32 nDeletePosition = m_pCache->getRow(); + + notifyRowSetAndClonesRowDelete( aBookmarkToDelete ); + + ORowSetRow aOldValues; + if ( m_pCache->m_aMatrixIter != m_pCache->getEnd() && m_pCache->m_aMatrixIter->isValid() ) + aOldValues = new ORowSetValueVector( m_pCache->m_aMatrixIter->getBody() ); + + Sequence<Any> aChangedBookmarks; + RowsChangeEvent aEvt(*this,RowChangeAction::DELETE,1,aChangedBookmarks); + notifyAllListenersRowBeforeChange(aGuard,aEvt); + + m_pCache->deleteRow(); + notifyRowSetAndClonesRowDeleted( aBookmarkToDelete, nDeletePosition ); + + ORowSetNotifier aNotifier( this ); + // this will call cancelRowModification on the cache if necessary + + // notification order + // - rowChanged + notifyAllListenersRowChanged(aGuard,aEvt); + + // - IsModified + // - IsNew + aNotifier.fire( ); + + // - RowCount/IsRowCountFinal + fireRowcount(); +} + +// ------------------------------------------------------------------------- +void ORowSet::implCancelRowUpdates( sal_Bool _bNotifyModified ) SAL_THROW( ( SQLException, RuntimeException ) ) +{ + ::connectivity::checkDisposed(ORowSet_BASE1::rBHelper.bDisposed); + + ::osl::MutexGuard aGuard( *m_pMutex ); + if ( m_bBeforeFirst || m_bAfterLast || rowDeleted() ) + return; // nothing to do so return + + checkCache(); + // cancelRowUpdates is not allowed when: + // - standing on the insert row + // - the concurrency is read only + // - the current row is deleted + if ( m_bNew || m_nResultSetConcurrency == ResultSetConcurrency::READ_ONLY ) + throwFunctionSequenceException(*this); + + positionCache( MOVE_NONE_REFRESH_ONLY ); + + ORowSetRow aOldValues; + if ( !m_aCurrentRow.isNull() ) + aOldValues = new ORowSetValueVector( m_aCurrentRow->getBody() ); + + m_pCache->cancelRowUpdates(); + + m_aBookmark = m_pCache->getBookmark(); + m_aCurrentRow = m_pCache->m_aMatrixIter; + m_aCurrentRow.setBookmark(m_aBookmark); + + // notification order + // - column values + ORowSetBase::firePropertyChange(aOldValues); + // IsModified + if( !m_bModified && _bNotifyModified ) + fireProperty(PROPERTY_ID_ISMODIFIED,sal_False,sal_True); +} + +// ------------------------------------------------------------------------- +void SAL_CALL ORowSet::cancelRowUpdates( ) throw(SQLException, RuntimeException) +{ + implCancelRowUpdates( sal_True ); +} + +// ------------------------------------------------------------------------- +void SAL_CALL ORowSet::addRowSetListener( const Reference< XRowSetListener >& listener ) throw(RuntimeException) +{ + ::connectivity::checkDisposed(ORowSet_BASE1::rBHelper.bDisposed); + + ::osl::MutexGuard aGuard( m_aColumnsMutex ); + if(listener.is()) + m_aRowsetListeners.addInterface(listener); +} +// ------------------------------------------------------------------------- +void SAL_CALL ORowSet::removeRowSetListener( const Reference< XRowSetListener >& listener ) throw(RuntimeException) +{ + ::connectivity::checkDisposed(ORowSet_BASE1::rBHelper.bDisposed); + + ::osl::MutexGuard aGuard( m_aColumnsMutex ); + if(listener.is()) + m_aRowsetListeners.removeInterface(listener); +} +// ----------------------------------------------------------------------------- +void ORowSet::notifyAllListeners(::osl::ResettableMutexGuard& _rGuard) +{ + EventObject aEvt(*m_pMySelf); + _rGuard.clear(); + m_aRowsetListeners.notifyEach( &XRowSetListener::rowSetChanged, aEvt ); + _rGuard.reset(); +} +// ------------------------------------------------------------------------- +void ORowSet::notifyAllListenersCursorMoved(::osl::ResettableMutexGuard& _rGuard) +{ + EventObject aEvt(*m_pMySelf); + _rGuard.clear(); + m_aRowsetListeners.notifyEach( &XRowSetListener::cursorMoved, aEvt ); + _rGuard.reset(); +} +// ------------------------------------------------------------------------- +void ORowSet::notifyAllListenersRowChanged(::osl::ResettableMutexGuard& _rGuard, const RowsChangeEvent& aEvt) +{ + _rGuard.clear(); + m_aRowsetListeners.notifyEach( &XRowSetListener::rowChanged, (EventObject)aEvt ); + m_aRowsChangeListener.notifyEach( &XRowsChangeListener::rowsChanged, aEvt ); + _rGuard.reset(); +} +// ------------------------------------------------------------------------- +sal_Bool ORowSet::notifyAllListenersCursorBeforeMove(::osl::ResettableMutexGuard& _rGuard) +{ + EventObject aEvt(*m_pMySelf); + NOTIFY_LISTERNERS_CHECK(m_aApproveListeners,XRowSetApproveListener,approveCursorMove); + return bCheck; +} +// ------------------------------------------------------------------------- +void ORowSet::notifyAllListenersRowBeforeChange(::osl::ResettableMutexGuard& _rGuard,const RowChangeEvent &aEvt) +{ + NOTIFY_LISTERNERS_CHECK(m_aApproveListeners,XRowSetApproveListener,approveRowChange); + if ( !bCheck ) + m_aErrors.raiseTypedException( sdb::ErrorCondition::ROW_SET_OPERATION_VETOED, *this, ::cppu::UnoType< RowSetVetoException >::get() ); +} +// ------------------------------------------------------------------------- +void ORowSet::fireRowcount() +{ + sal_Int32 nCurrentRowCount( impl_getRowCount() ); + sal_Bool bCurrentRowCountFinal( m_pCache->m_bRowCountFinal ); + + if ( m_nLastKnownRowCount != nCurrentRowCount ) + { + sal_Int32 nHandle = PROPERTY_ID_ROWCOUNT; + Any aNew,aOld; + aNew <<= nCurrentRowCount; aOld <<= m_nLastKnownRowCount; + fire(&nHandle,&aNew,&aOld,1,sal_False); + m_nLastKnownRowCount = nCurrentRowCount; + } + if ( !m_bLastKnownRowCountFinal && ( m_bLastKnownRowCountFinal != bCurrentRowCountFinal ) ) + { + sal_Int32 nHandle = PROPERTY_ID_ISROWCOUNTFINAL; + Any aNew,aOld; + aNew <<= bCurrentRowCountFinal; + aOld <<= m_bLastKnownRowCountFinal; + fire(&nHandle,&aNew,&aOld,1,sal_False); + m_bLastKnownRowCountFinal = bCurrentRowCountFinal; + } +} +// ------------------------------------------------------------------------- +void SAL_CALL ORowSet::moveToInsertRow( ) throw(SQLException, RuntimeException) +{ + ::connectivity::checkDisposed(ORowSet_BASE1::rBHelper.bDisposed); + + ::osl::ResettableMutexGuard aGuard( *m_pMutex ); + checkPositioningAllowed(); + if ( ( m_pCache->m_nPrivileges & Privilege::INSERT ) != Privilege::INSERT ) + ::dbtools::throwSQLException( DBACORE_RESSTRING( RID_STR_NO_INSERT_PRIVILEGE ), SQL_GENERAL_ERROR, *this ); + + if ( notifyAllListenersCursorBeforeMove( aGuard ) ) + { + // remember old value for fire + ORowSetRow aOldValues; + if ( rowDeleted() ) + { + positionCache( MOVE_FORWARD ); + m_pCache->next(); + setCurrentRow( sal_True, sal_False, aOldValues, aGuard); + } + else + positionCache( MOVE_NONE_REFRESH_ONLY ); + + // check before because the resultset could be empty + if ( !m_bBeforeFirst + && !m_bAfterLast + && m_pCache->m_aMatrixIter != m_pCache->getEnd() + && m_pCache->m_aMatrixIter->isValid() + ) + aOldValues = new ORowSetValueVector( m_pCache->m_aMatrixIter->getBody() ); + + const sal_Bool bNewState = m_bNew; + const sal_Bool bModState = m_bModified; + + m_pCache->moveToInsertRow(); + m_aCurrentRow = m_pCache->m_aInsertRow; + + // set read-only flag to false + impl_setDataColumnsWriteable_throw(); + + // notification order + // - column values + ORowSetBase::firePropertyChange(aOldValues); + + // - cursorMoved + notifyAllListenersCursorMoved(aGuard); + + // - IsModified + if ( bModState != m_bModified ) + fireProperty( PROPERTY_ID_ISMODIFIED, m_bModified, bModState ); + + // - IsNew + if ( bNewState != m_bNew ) + fireProperty( PROPERTY_ID_ISNEW, m_bNew, bNewState ); + + // - RowCount/IsRowCountFinal + fireRowcount(); + } +} +// ------------------------------------------------------------------------- +void ORowSet::impl_setDataColumnsWriteable_throw() +{ + impl_restoreDataColumnsWriteable_throw(); + TDataColumns::iterator aIter = m_aDataColumns.begin(); + m_aReadOnlyDataColumns.resize(m_aDataColumns.size(),false); + ::std::bit_vector::iterator aReadIter = m_aReadOnlyDataColumns.begin(); + for(;aIter != m_aDataColumns.end();++aIter,++aReadIter) + { + sal_Bool bReadOnly = sal_False; + (*aIter)->getPropertyValue(PROPERTY_ISREADONLY) >>= bReadOnly; + *aReadIter = bReadOnly; + + (*aIter)->setPropertyValue(PROPERTY_ISREADONLY,makeAny(sal_False)); + } +} +// ------------------------------------------------------------------------- +void ORowSet::impl_restoreDataColumnsWriteable_throw() +{ + TDataColumns::iterator aIter = m_aDataColumns.begin(); + ::std::bit_vector::iterator aReadIter = m_aReadOnlyDataColumns.begin(); + for(;aReadIter != m_aReadOnlyDataColumns.end();++aIter,++aReadIter) + { + (*aIter)->setPropertyValue(PROPERTY_ISREADONLY,makeAny((sal_Bool)*aReadIter )); + } + m_aReadOnlyDataColumns.clear(); +} +// ------------------------------------------------------------------------- +void SAL_CALL ORowSet::moveToCurrentRow( ) throw(SQLException, RuntimeException) +{ + ::connectivity::checkDisposed(ORowSet_BASE1::rBHelper.bDisposed); + + ::osl::ResettableMutexGuard aGuard( *m_pMutex ); + checkPositioningAllowed(); + + if ( !m_pCache->m_bNew && !m_bModified ) + // nothing to do if we're not on the insertion row, and not modified otherwise + return; + + if ( rowDeleted() ) + // this would perhaps even justify a RuntimeException .... + // if the current row is deleted, then no write access to this row should be possible. So, + // m_bModified should be true. Also, as soon as somebody calls moveToInsertRow, + // our current row should not be deleted anymore. So, we should not have survived the above + // check "if ( !m_pCache->m_bNew && !m_bModified )" + ::dbtools::throwSQLException( DBACORE_RESSTRING( RID_STR_ROW_ALREADY_DELETED ), SQL_FUNCTION_SEQUENCE_ERROR, *this ); + + if ( notifyAllListenersCursorBeforeMove( aGuard ) ) + { + positionCache( MOVE_NONE_REFRESH_ONLY ); + + ORowSetNotifier aNotifier( this ); + + // notification order + // - cursorMoved + notifyAllListenersCursorMoved(aGuard); + + // - IsModified + // - IsNew + aNotifier.fire(); + } +} +// ------------------------------------------------------------------------- +// XRow +sal_Bool SAL_CALL ORowSet::wasNull( ) throw(SQLException, RuntimeException) +{ + ::osl::MutexGuard aGuard( *m_pMutex ); + checkCache(); + + return ( m_pCache && isInsertRow() ) ? ((*m_pCache->m_aInsertRow)->get())[m_nLastColumnIndex].isNull() : ORowSetBase::wasNull(); +} +// ----------------------------------------------------------------------------- +const ORowSetValue& ORowSet::getInsertValue(sal_Int32 columnIndex) +{ + checkCache(); + + if ( m_pCache && isInsertRow() ) + return ((*m_pCache->m_aInsertRow)->get())[m_nLastColumnIndex = columnIndex]; + + return getValue(columnIndex); +} +// ------------------------------------------------------------------------- +::rtl::OUString SAL_CALL ORowSet::getString( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + ::osl::MutexGuard aGuard( *m_pMutex ); + return getInsertValue(columnIndex); +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL ORowSet::getBoolean( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + ::osl::MutexGuard aGuard( *m_pMutex ); + return getInsertValue(columnIndex); +} +// ------------------------------------------------------------------------- +sal_Int8 SAL_CALL ORowSet::getByte( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + ::osl::MutexGuard aGuard( *m_pMutex ); + return getInsertValue(columnIndex); +} +// ------------------------------------------------------------------------- +sal_Int16 SAL_CALL ORowSet::getShort( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + ::osl::MutexGuard aGuard( *m_pMutex ); + return getInsertValue(columnIndex); +} +// ------------------------------------------------------------------------- +sal_Int32 SAL_CALL ORowSet::getInt( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + ::osl::MutexGuard aGuard( *m_pMutex ); + return getInsertValue(columnIndex); +} +// ------------------------------------------------------------------------- +sal_Int64 SAL_CALL ORowSet::getLong( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + ::osl::MutexGuard aGuard( *m_pMutex ); + return getInsertValue(columnIndex); +} +// ------------------------------------------------------------------------- +float SAL_CALL ORowSet::getFloat( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + ::osl::MutexGuard aGuard( *m_pMutex ); + return getInsertValue(columnIndex); +} +// ------------------------------------------------------------------------- +double SAL_CALL ORowSet::getDouble( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + ::osl::MutexGuard aGuard( *m_pMutex ); + return getInsertValue(columnIndex); +} +// ------------------------------------------------------------------------- +Sequence< sal_Int8 > SAL_CALL ORowSet::getBytes( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + ::osl::MutexGuard aGuard( *m_pMutex ); + return getInsertValue(columnIndex); +} +// ------------------------------------------------------------------------- +::com::sun::star::util::Date SAL_CALL ORowSet::getDate( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + ::osl::MutexGuard aGuard( *m_pMutex ); + return getInsertValue(columnIndex); +} +// ------------------------------------------------------------------------- +::com::sun::star::util::Time SAL_CALL ORowSet::getTime( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + ::osl::MutexGuard aGuard( *m_pMutex ); + return getInsertValue(columnIndex); +} +// ------------------------------------------------------------------------- +::com::sun::star::util::DateTime SAL_CALL ORowSet::getTimestamp( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + ::osl::MutexGuard aGuard( *m_pMutex ); + return getInsertValue(columnIndex); +} +// ------------------------------------------------------------------------- +Reference< ::com::sun::star::io::XInputStream > SAL_CALL ORowSet::getBinaryStream( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + ::osl::MutexGuard aGuard( *m_pMutex ); + if ( m_pCache && isInsertRow() ) + { + checkCache(); + return new ::comphelper::SequenceInputStream(((*m_pCache->m_aInsertRow)->get())[m_nLastColumnIndex = columnIndex].getSequence()); + } + + return ORowSetBase::getBinaryStream(columnIndex); +} +// ------------------------------------------------------------------------- +Reference< ::com::sun::star::io::XInputStream > SAL_CALL ORowSet::getCharacterStream( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + ::osl::MutexGuard aGuard( *m_pMutex ); + if(m_pCache && isInsertRow() ) + { + checkCache(); + return new ::comphelper::SequenceInputStream(((*m_pCache->m_aInsertRow)->get())[m_nLastColumnIndex = columnIndex].getSequence()); + } + + return ORowSetBase::getCharacterStream(columnIndex); +} +// ------------------------------------------------------------------------- +Any SAL_CALL ORowSet::getObject( sal_Int32 columnIndex, const Reference< XNameAccess >& /*typeMap*/ ) throw(SQLException, RuntimeException) +{ + ::osl::MutexGuard aGuard( *m_pMutex ); + return getInsertValue(columnIndex).makeAny(); +} +// ------------------------------------------------------------------------- +Reference< XRef > SAL_CALL ORowSet::getRef( sal_Int32 /*columnIndex*/ ) throw(SQLException, RuntimeException) +{ + return Reference< XRef >(); +} +// ------------------------------------------------------------------------- +Reference< XBlob > SAL_CALL ORowSet::getBlob( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + if ( m_pCache && isInsertRow() ) + { + checkCache(); + return new ::connectivity::BlobHelper(((*m_pCache->m_aInsertRow)->get())[m_nLastColumnIndex = columnIndex].getSequence()); + } + return ORowSetBase::getBlob(columnIndex); +} +// ------------------------------------------------------------------------- +Reference< XClob > SAL_CALL ORowSet::getClob( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + return Reference< XClob >(getInsertValue(columnIndex).makeAny(),UNO_QUERY); +} +// ------------------------------------------------------------------------- +Reference< XArray > SAL_CALL ORowSet::getArray( sal_Int32 /*columnIndex*/ ) throw(SQLException, RuntimeException) +{ + return Reference< XArray >(); +} +// ------------------------------------------------------------------------- +void SAL_CALL ORowSet::executeWithCompletion( const Reference< XInteractionHandler >& _rxHandler ) throw(SQLException, RuntimeException) +{ + if (!_rxHandler.is()) + execute(); + + ::connectivity::checkDisposed(ORowSet_BASE1::rBHelper.bDisposed); + + // tell everybody that we will change the result set + approveExecution(); + + ResettableMutexGuard aGuard( m_aMutex ); + + try + { + freeResources( m_bCommandFacetsDirty ); + + // calc the connection to be used + if (m_xActiveConnection.is() && m_bRebuildConnOnExecute) + { + // there was a setProperty(ActiveConnection), but a setProperty(DataSource) _after_ that, too + Reference< XConnection > xXConnection; + setActiveConnection( xXConnection ); + } + calcConnection( _rxHandler ); + m_bRebuildConnOnExecute = sal_False; + + Reference< XSingleSelectQueryComposer > xComposer = getCurrentSettingsComposer( this, m_aContext.getLegacyServiceFactory() ); + Reference<XParametersSupplier> xParameters(xComposer, UNO_QUERY); + + Reference<XIndexAccess> xParamsAsIndicies = xParameters.is() ? xParameters->getParameters() : Reference<XIndexAccess>(); + const sal_Int32 nParamCount = xParamsAsIndicies.is() ? xParamsAsIndicies->getCount() : 0; + if ( m_aParametersSet.size() < (size_t)nParamCount ) + m_aParametersSet.resize( nParamCount ,false); + + ::dbtools::askForParameters( xComposer, this, m_xActiveConnection, _rxHandler,m_aParametersSet ); + } + // ensure that only the allowed exceptions leave this block + catch(SQLException&) + { + throw; + } + catch(RuntimeException&) + { + throw; + } + catch(Exception&) + { + DBG_ERROR("ORowSet::executeWithCompletion: caught an unexpected exception type while filling in the parameters!"); + } + + // we're done with the parameters, now for the real execution + + // do the real execute + execute_NoApprove_NoNewConn(aGuard); +} + +// ------------------------------------------------------------------------- +Reference< XIndexAccess > SAL_CALL ORowSet::getParameters( ) throw (RuntimeException) +{ + ::osl::MutexGuard aGuard( *m_pMutex ); + ::connectivity::checkDisposed(ORowSet_BASE1::rBHelper.bDisposed); + + if ( m_bCommandFacetsDirty ) + // need to rebuild the parameters, since some property which contributes to the + // complete command, and thus the parameters, changed + impl_disposeParametersContainer_nothrow(); + + if ( !m_pParameters.get() && m_aCommand.getLength() ) + { + try + { + ::rtl::OUString sNotInterestedIn; + impl_initComposer_throw( sNotInterestedIn ); + } + catch( const Exception& ) + { + // silence it + } + } + + return m_pParameters.get(); +} + +// ------------------------------------------------------------------------- +void ORowSet::approveExecution() throw (RowSetVetoException, RuntimeException) +{ + ::osl::MutexGuard aGuard( m_aColumnsMutex ); + EventObject aEvt(*this); + + OInterfaceIteratorHelper aApproveIter( m_aApproveListeners ); + while ( aApproveIter.hasMoreElements() ) + { + Reference< XRowSetApproveListener > xListener( static_cast< XRowSetApproveListener* >( aApproveIter.next() ) ); + try + { + if ( xListener.is() && !xListener->approveRowSetChange( aEvt ) ) + throw RowSetVetoException(); + } + catch ( const DisposedException& e ) + { + if ( e.Context == xListener ) + aApproveIter.remove(); + } + catch ( const RuntimeException& ) { throw; } + catch ( const RowSetVetoException& ) { throw; } + catch ( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + } +} +// ------------------------------------------------------------------------- +// XRowSet +// ------------------------------------------------------------------------- +void SAL_CALL ORowSet::execute( ) throw(SQLException, RuntimeException) +{ + ::connectivity::checkDisposed(ORowSet_BASE1::rBHelper.bDisposed); + + // tell everybody that we will change the result set + approveExecution(); + + ResettableMutexGuard aGuard( m_aMutex ); + freeResources( m_bCommandFacetsDirty ); + + // calc the connection to be used + if (m_xActiveConnection.is() && m_bRebuildConnOnExecute) { + // there was a setProperty(ActiveConnection), but a setProperty(DataSource) _after_ that, too + Reference< XConnection> xXConnection; + setActiveConnection( xXConnection ); + } + + calcConnection(NULL); + m_bRebuildConnOnExecute = sal_False; + + // do the real execute + execute_NoApprove_NoNewConn(aGuard); +} + +//------------------------------------------------------------------------------ +void ORowSet::setStatementResultSetType( const Reference< XPropertySet >& _rxStatement, sal_Int32 _nDesiredResultSetType, sal_Int32 _nDesiredResultSetConcurrency ) +{ + OSL_ENSURE( _rxStatement.is(), "ORowSet::setStatementResultSetType: invalid statement - this will crash!" ); + + sal_Int32 nResultSetType( _nDesiredResultSetType ); + sal_Int32 nResultSetConcurrency( _nDesiredResultSetConcurrency ); + + // there *might* be a data source setting which tells use to be more defensive with those settings + // #i15113# / 2005-02-10 / frank.schoenheit@sun.com + sal_Bool bRespectDriverRST = sal_False; + Any aSetting; + if ( getDataSourceSetting( ::dbaccess::getDataSource( m_xActiveConnection ), "RespectDriverResultSetType", aSetting ) ) + { + OSL_VERIFY( aSetting >>= bRespectDriverRST ); + } + + if ( bRespectDriverRST ) + { + // try type/concurrency settings with decreasing usefullness, and rely on what the connection claims + // to support + Reference< XDatabaseMetaData > xMeta( m_xActiveConnection->getMetaData() ); + + sal_Int32 nCharacteristics[5][2] = + { { ResultSetType::SCROLL_SENSITIVE, ResultSetConcurrency::UPDATABLE }, + { ResultSetType::SCROLL_INSENSITIVE, ResultSetConcurrency::UPDATABLE }, + { ResultSetType::SCROLL_SENSITIVE, ResultSetConcurrency::READ_ONLY }, + { ResultSetType::SCROLL_INSENSITIVE, ResultSetConcurrency::READ_ONLY }, + { ResultSetType::FORWARD_ONLY, ResultSetConcurrency::READ_ONLY } + }; + sal_Int32 i=0; + if ( m_xActiveConnection->getMetaData()->isReadOnly() ) + i = 2; // if the database is read-only we only should use read-only concurrency + + for ( ; i<5; ++i ) + { + nResultSetType = nCharacteristics[i][0]; + nResultSetConcurrency = nCharacteristics[i][1]; + + // don't try type/concurrency pairs which are more featured than what our caller requested + if ( nResultSetType > _nDesiredResultSetType ) + continue; + if ( nResultSetConcurrency > _nDesiredResultSetConcurrency ) + continue; + + if ( xMeta.is() && xMeta->supportsResultSetConcurrency( nResultSetType, nResultSetConcurrency ) ) + break; + } + } + + _rxStatement->setPropertyValue( PROPERTY_RESULTSETTYPE, makeAny( nResultSetType ) ); + _rxStatement->setPropertyValue( PROPERTY_RESULTSETCONCURRENCY, makeAny( nResultSetConcurrency ) ); +} + +// ----------------------------------------------------------------------------- +Reference< XResultSet > ORowSet::impl_prepareAndExecute_throw() +{ + ::rtl::OUString sCommandToExecute; + sal_Bool bUseEscapeProcessing = impl_initComposer_throw( sCommandToExecute ); + + Reference< XResultSet> xResultSet; + try + { + m_xStatement = m_xActiveConnection->prepareStatement( sCommandToExecute ); + if ( !m_xStatement.is() ) + { + ::dbtools::throwSQLException( DBACORE_RESSTRING( RID_STR_INTERNAL_ERROR ), SQL_GENERAL_ERROR, *this ); + } + + Reference< XPropertySet > xStatementProps( m_xStatement, UNO_QUERY_THROW ); + // set the result set type and concurrency + try + { + xStatementProps->setPropertyValue( PROPERTY_USEBOOKMARKS, makeAny( sal_True ) ); + setStatementResultSetType( xStatementProps, m_nResultSetType, m_nResultSetConcurrency ); + } + catch ( const Exception& ) + { + // this exception doesn't matter here because when we catch an exception + // then the driver doesn't support this feature + } + m_aParameterValueForCache.get().resize(1); + Reference< XParameters > xParam( m_xStatement, UNO_QUERY_THROW ); + size_t nParamCount( m_pParameters.is() ? m_pParameters->size() : m_aPrematureParamValues.get().size() ); + for ( size_t i=1; i<=nParamCount; ++i ) + { + ORowSetValue& rParamValue( getParameterStorage( (sal_Int32)i ) ); + ::dbtools::setObjectWithInfo( xParam, i, rParamValue.makeAny(), rParamValue.getTypeKind() ); + m_aParameterValueForCache.get().push_back(rParamValue); + } + + xResultSet = m_xStatement->executeQuery(); + } + catch( const SQLException& ) + { + SQLExceptionInfo aError( ::cppu::getCaughtException() ); + OSL_ENSURE( aError.isValid(), "ORowSet::impl_prepareAndExecute_throw: caught an SQLException which we cannot analyze!" ); + + // append information about what we were actually going to execute + try + { + String sQuery = bUseEscapeProcessing && m_xComposer.is() ? m_xComposer->getQuery() : m_aActiveCommand; + String sInfo( DBA_RES_PARAM( RID_STR_COMMAND_LEADING_TO_ERROR, "$command$", sQuery ) ); + aError.append( SQLExceptionInfo::SQL_CONTEXT, sInfo ); + } + catch( const Exception& ) { DBG_UNHANDLED_EXCEPTION(); } + + // propagate + aError.doThrow(); + } + + return xResultSet; +} + +// ----------------------------------------------------------------------------- +void ORowSet::impl_initializeColumnSettings_nothrow( const Reference< XPropertySet >& _rxTemplateColumn, const Reference< XPropertySet >& _rxRowSetColumn ) +{ + OSL_ENSURE( _rxTemplateColumn.is() && _rxRowSetColumn.is(), + "ORowSet::impl_initializeColumnSettings_nothrow: this will crash!" ); + + bool bHaveAnyColumnSetting = false; + try + { + Reference< XPropertySetInfo > xInfo( _rxTemplateColumn->getPropertySetInfo(), UNO_QUERY_THROW ); + + // a number of properties is plain copied + const ::rtl::OUString aPropertyNames[] = { + PROPERTY_ALIGN, PROPERTY_RELATIVEPOSITION, PROPERTY_WIDTH, PROPERTY_HIDDEN, PROPERTY_CONTROLMODEL, + PROPERTY_HELPTEXT, PROPERTY_CONTROLDEFAULT + }; + for ( size_t i=0; i<sizeof( aPropertyNames ) / sizeof( aPropertyNames[0] ); ++i ) + { + if ( xInfo->hasPropertyByName( aPropertyNames[i] ) ) + { + _rxRowSetColumn->setPropertyValue( aPropertyNames[i], _rxTemplateColumn->getPropertyValue( aPropertyNames[i] ) ); + bHaveAnyColumnSetting = true; + } + } + + // the format key is slightly more complex + sal_Int32 nFormatKey = 0; + if( xInfo->hasPropertyByName( PROPERTY_NUMBERFORMAT ) ) + { + _rxTemplateColumn->getPropertyValue( PROPERTY_NUMBERFORMAT ) >>= nFormatKey; + bHaveAnyColumnSetting = true; + } + if ( !nFormatKey && m_xNumberFormatTypes.is() ) + nFormatKey = ::dbtools::getDefaultNumberFormat( _rxTemplateColumn, m_xNumberFormatTypes, SvtSysLocale().GetLocaleData().getLocale() ); + _rxRowSetColumn->setPropertyValue( PROPERTY_NUMBERFORMAT, makeAny( nFormatKey ) ); + } + catch(Exception&) + { + DBG_UNHANDLED_EXCEPTION(); + return; + } + + if ( bHaveAnyColumnSetting ) + return; + + // the template column could not provide *any* setting. Okay, probably it's a parser column, which + // does not offer those. However, perhaps the template column referes to a table column, which we + // can use as new template column + try + { + Reference< XPropertySetInfo > xInfo( _rxTemplateColumn->getPropertySetInfo(), UNO_QUERY_THROW ); + if ( !xInfo->hasPropertyByName( PROPERTY_TABLENAME ) ) + // no chance + return; + + ::rtl::OUString sTableName; + OSL_VERIFY( _rxTemplateColumn->getPropertyValue( PROPERTY_TABLENAME ) >>= sTableName ); + + Reference< XNameAccess > xTables( impl_getTables_throw(), UNO_QUERY_THROW ); + if ( !xTables->hasByName( sTableName ) ) + // no chance + return; + + Reference< XColumnsSupplier > xTableColSup( xTables->getByName( sTableName ), UNO_QUERY_THROW ); + Reference< XNameAccess > xTableCols( xTableColSup->getColumns(), UNO_QUERY_THROW ); + + ::rtl::OUString sTableColumnName; + + // get the "Name" or (preferred) "RealName" property of the column + ::rtl::OUString sNamePropertyName( PROPERTY_NAME ); + if ( xInfo->hasPropertyByName( PROPERTY_REALNAME ) ) + sNamePropertyName = PROPERTY_REALNAME; + OSL_VERIFY( _rxTemplateColumn->getPropertyValue( sNamePropertyName ) >>= sTableColumnName ); + + if ( !xTableCols->hasByName( sTableColumnName ) ) + return; + + Reference< XPropertySet > xTableColumn( xTableCols->getByName( sTableColumnName ), UNO_QUERY_THROW ); + impl_initializeColumnSettings_nothrow( xTableColumn, _rxRowSetColumn ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } +} + +// ----------------------------------------------------------------------------- +void ORowSet::execute_NoApprove_NoNewConn(ResettableMutexGuard& _rClearForNotification) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "frank.schoenheit@sun.com", "ORowSet::execute_NoApprove_NoNewConn" ); + + // now we can dispose our old connection + ::comphelper::disposeComponent(m_xOldConnection); + m_xOldConnection = NULL; + + // do we need a new statement + if ( m_bCommandFacetsDirty ) + { + m_xStatement = NULL; + m_xComposer = NULL; + + Reference< XResultSet > xResultSet( impl_prepareAndExecute_throw() ); + + // let our warnings container forget the reference to the (possibly disposed) old result set + m_aWarnings.setExternalWarnings( NULL ); + // clear all current warnings + m_aWarnings.clearWarnings(); + // let the warnings container know about the new "external warnings" + m_aWarnings.setExternalWarnings( Reference< XWarningsSupplier >( xResultSet, UNO_QUERY ) ); + + ::rtl::OUString aComposedUpdateTableName; + if ( m_aUpdateTableName.getLength() ) + aComposedUpdateTableName = composeTableName( m_xActiveConnection->getMetaData(), m_aUpdateCatalogName, m_aUpdateSchemaName, m_aUpdateTableName, sal_False, ::dbtools::eInDataManipulation ); + + { + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "frank.schoenheit@sun.com", "ORowSet::execute_NoApprove_NoNewConn: creating cache" ); + m_pCache = new ORowSetCache( xResultSet, m_xComposer.get(), m_aContext, aComposedUpdateTableName, m_bModified, m_bNew,m_aParameterValueForCache,m_aFilter ); + if ( m_nResultSetConcurrency == ResultSetConcurrency::READ_ONLY ) + { + m_nPrivileges = Privilege::SELECT; + m_pCache->m_nPrivileges = Privilege::SELECT; + } + m_pCache->setMaxRowSize(m_nFetchSize); + m_aCurrentRow = m_pCache->createIterator(this); + m_aOldRow = m_pCache->registerOldRow(); + } + + // get the locale + // ConfigManager* pConfigMgr = ConfigManager::GetConfigManager(); + Locale aLocale = SvtSysLocale().GetLocaleData().getLocale(); + // pConfigMgr->GetDirectConfigProperty(ConfigManager::LOCALE) >>= aLocale; + + // get the numberformatTypes + OSL_ENSURE(m_xActiveConnection.is(),"No ActiveConnection"); + Reference< XNumberFormatTypes> xNumberFormatTypes; + Reference< XNumberFormatsSupplier> xNumberFormat = ::dbtools::getNumberFormats(m_xActiveConnection); + if ( xNumberFormat.is() ) + m_xNumberFormatTypes.set(xNumberFormat->getNumberFormats(),UNO_QUERY); + + ::vos::ORef< ::connectivity::OSQLColumns> aColumns = new ::connectivity::OSQLColumns(); + ::std::vector< ::rtl::OUString> aNames; + ::rtl::OUString aDescription; + sal_Int32 nFormatKey = 0; + + const ::std::map<sal_Int32,sal_Int32>& rKeyColumns = m_pCache->getKeyColumns(); + if(!m_xColumns.is()) + { + RTL_LOGFILE_CONTEXT_AUTHOR( aColumnCreateLog, "dbaccess", "frank.schoenheit@sun.com", "ORowSet::execute_NoApprove_NoNewConn::creating columns" ); + // use the meta data + Reference<XResultSetMetaDataSupplier> xMetaSup(m_xStatement,UNO_QUERY); + try + { + Reference<XResultSetMetaData> xMetaData = xMetaSup->getMetaData(); + if ( xMetaData.is() ) + { + sal_Int32 nCount = xMetaData->getColumnCount(); + m_aDataColumns.reserve(nCount+1); + aColumns->get().reserve(nCount+1); + DECLARE_STL_USTRINGACCESS_MAP(int,StringMap); + StringMap aColumnMap; + for (sal_Int32 i = 0 ; i < nCount; ++i) + { + // retrieve the name of the column + ::rtl::OUString sName = xMetaData->getColumnName(i + 1); + // check for duplicate entries + if(aColumnMap.find(sName) != aColumnMap.end()) + { + ::rtl::OUString sAlias(sName); + sal_Int32 searchIndex=1; + while(aColumnMap.find(sAlias) != aColumnMap.end()) + { + (sAlias = sName) += ::rtl::OUString::valueOf(searchIndex++); + } + sName = sAlias; + } + ORowSetDataColumn* pColumn = new ORowSetDataColumn( getMetaData(), + this, + this, + i+1, + m_xActiveConnection->getMetaData(), + aDescription, + ::rtl::OUString(), + m_aCurrentRow); + aColumnMap.insert(StringMap::value_type(sName,0)); + aColumns->get().push_back(pColumn); + pColumn->setName(sName); + aNames.push_back(sName); + m_aDataColumns.push_back(pColumn); + + pColumn->setFastPropertyValue_NoBroadcast(PROPERTY_ID_ISREADONLY,makeAny(rKeyColumns.find(i+1) != rKeyColumns.end())); + + try + { + nFormatKey = 0; + if(m_xNumberFormatTypes.is()) + nFormatKey = ::dbtools::getDefaultNumberFormat(pColumn,m_xNumberFormatTypes,aLocale); + + + pColumn->setFastPropertyValue_NoBroadcast(PROPERTY_ID_NUMBERFORMAT,makeAny(nFormatKey)); + pColumn->setFastPropertyValue_NoBroadcast(PROPERTY_ID_RELATIVEPOSITION,makeAny(sal_Int32(i+1))); + pColumn->setFastPropertyValue_NoBroadcast(PROPERTY_ID_WIDTH,makeAny(sal_Int32(227))); + pColumn->setFastPropertyValue_NoBroadcast(PROPERTY_ID_ALIGN,makeAny((sal_Int32)0)); + pColumn->setFastPropertyValue_NoBroadcast(PROPERTY_ID_HIDDEN,::cppu::bool2any(sal_False)); + } + catch(Exception&) + { + } + } + } + } + catch (SQLException&) + { + } + } + else + { + // create the rowset columns + Reference< XResultSetMetaData > xMeta( getMetaData(), UNO_QUERY_THROW ); + sal_Int32 nCount = xMeta->getColumnCount(); + m_aDataColumns.reserve(nCount+1); + aColumns->get().reserve(nCount+1); + ::std::set< Reference< XPropertySet > > aAllColumns; + + for(sal_Int32 i=1; i <= nCount ;++i) + { + ::rtl::OUString sName = xMeta->getColumnName(i); + ::rtl::OUString sColumnLabel = xMeta->getColumnLabel(i); + + // retrieve the column number |i| + Reference<XPropertySet> xColumn; + { + sal_Bool bReFetchName = sal_False; + if (m_xColumns->hasByName(sColumnLabel)) + m_xColumns->getByName(sColumnLabel) >>= xColumn; + if (!xColumn.is() && m_xColumns->hasByName(sName)) + m_xColumns->getByName(sName) >>= xColumn; + + // check if column already in the list we need another + if ( aAllColumns.find( xColumn ) != aAllColumns.end() ) + { + xColumn = NULL; + bReFetchName = sal_True; + sColumnLabel = ::rtl::OUString(); + } + if(!xColumn.is()) + { + // no column found so we could look at the position i + //bReFetchName = sal_True; + //sColumnLabel = ::rtl::OUString(); + Reference<XIndexAccess> xIndexAccess(m_xColumns,UNO_QUERY); + if(xIndexAccess.is() && i <= xIndexAccess->getCount()) + { + xIndexAccess->getByIndex(i-1) >>= xColumn; + } + else + { + Sequence< ::rtl::OUString> aSeq = m_xColumns->getElementNames(); + if( i <= aSeq.getLength()) + { + m_xColumns->getByName(aSeq.getConstArray()[i-1]) >>= xColumn; + } + } + } + if(bReFetchName && xColumn.is()) + xColumn->getPropertyValue(PROPERTY_NAME) >>= sName; + aAllColumns.insert( xColumn ); + } + + // create a RowSetDataColumn + { + Reference<XPropertySetInfo> xInfo = xColumn.is() ? xColumn->getPropertySetInfo() : Reference<XPropertySetInfo>(); + if(xInfo.is() && xInfo->hasPropertyByName(PROPERTY_DESCRIPTION)) + aDescription = comphelper::getString(xColumn->getPropertyValue(PROPERTY_DESCRIPTION)); + + ::rtl::OUString sParseLabel; + if ( xColumn.is() ) + { + xColumn->getPropertyValue(PROPERTY_LABEL) >>= sParseLabel; + } + ORowSetDataColumn* pColumn = new ORowSetDataColumn( getMetaData(), + this, + this, + i, + m_xActiveConnection->getMetaData(), + aDescription, + sParseLabel, + m_aCurrentRow); + aColumns->get().push_back(pColumn); + + pColumn->setFastPropertyValue_NoBroadcast(PROPERTY_ID_ISREADONLY,makeAny(rKeyColumns.find(i) != rKeyColumns.end())); + + if(!sColumnLabel.getLength()) + { + if(xColumn.is()) + xColumn->getPropertyValue(PROPERTY_NAME) >>= sColumnLabel; + else + sColumnLabel = DBACORE_RESSTRING( RID_STR_EXPRESSION1 ); + } + pColumn->setName(sColumnLabel); + aNames.push_back(sColumnLabel); + m_aDataColumns.push_back(pColumn); + + if ( xColumn.is() ) + impl_initializeColumnSettings_nothrow( xColumn, pColumn ); + } + } + } + // now create the columns we need + if(m_pColumns) + m_pColumns->assign(aColumns,aNames); + else + { + Reference<XDatabaseMetaData> xMeta = m_xActiveConnection->getMetaData(); + m_pColumns = new ORowSetDataColumns(xMeta.is() && xMeta->supportsMixedCaseQuotedIdentifiers(), + aColumns,*this,m_aColumnsMutex,aNames); + } + } + checkCache(); + // notify the rowset listeners + notifyAllListeners(_rClearForNotification); +} +// ------------------------------------------------------------------------- +// XRowSetApproveBroadcaster +void SAL_CALL ORowSet::addRowSetApproveListener( const Reference< XRowSetApproveListener >& listener ) throw(RuntimeException) +{ + ::connectivity::checkDisposed(ORowSet_BASE1::rBHelper.bDisposed); + + ::osl::MutexGuard aGuard( m_aColumnsMutex ); + + m_aApproveListeners.addInterface(listener); +} +// ------------------------------------------------------------------------- +void SAL_CALL ORowSet::removeRowSetApproveListener( const Reference< XRowSetApproveListener >& listener ) throw(RuntimeException) +{ + ::connectivity::checkDisposed(ORowSet_BASE1::rBHelper.bDisposed); + + ::osl::MutexGuard aGuard( m_aColumnsMutex ); + + m_aApproveListeners.removeInterface(listener); +} +// XRowsChangeBroadcaster +void SAL_CALL ORowSet::addRowsChangeListener( const Reference< XRowsChangeListener >& listener ) throw(RuntimeException) +{ + ::connectivity::checkDisposed(ORowSet_BASE1::rBHelper.bDisposed); + + ::osl::MutexGuard aGuard( m_aColumnsMutex ); + + m_aRowsChangeListener.addInterface(listener); +} +// ------------------------------------------------------------------------- +void SAL_CALL ORowSet::removeRowsChangeListener( const Reference< XRowsChangeListener >& listener ) throw(RuntimeException) +{ + ::connectivity::checkDisposed(ORowSet_BASE1::rBHelper.bDisposed); + + ::osl::MutexGuard aGuard( m_aColumnsMutex ); + + m_aRowsChangeListener.removeInterface(listener); +} +// ------------------------------------------------------------------------- + +// XResultSetAccess +Reference< XResultSet > SAL_CALL ORowSet::createResultSet( ) throw(SQLException, RuntimeException) +{ + ::osl::MutexGuard aGuard( m_aColumnsMutex ); + + if(m_xStatement.is()) + { + ORowSetClone* pClone = new ORowSetClone( m_aContext, *this, m_pMutex ); + Reference< XResultSet > xRet(pClone); + m_aClones.push_back(WeakReferenceHelper(xRet)); + return xRet; + } + return Reference< XResultSet >(); +} +// ------------------------------------------------------------------------- + +// ::com::sun::star::util::XCancellable +void SAL_CALL ORowSet::cancel( ) throw(RuntimeException) +{ + ::connectivity::checkDisposed(ORowSet_BASE1::rBHelper.bDisposed); +} +// ------------------------------------------------------------------------- + +// ::com::sun::star::sdbcx::XDeleteRows +Sequence< sal_Int32 > SAL_CALL ORowSet::deleteRows( const Sequence< Any >& rows ) throw(SQLException, RuntimeException) +{ + ::connectivity::checkDisposed(ORowSet_BASE1::rBHelper.bDisposed); + + if(!m_pCache || m_nResultSetConcurrency == ResultSetConcurrency::READ_ONLY) + throwFunctionSequenceException(*this); + + ::osl::ResettableMutexGuard aGuard( *m_pMutex ); + + Sequence<Any> aChangedBookmarks; + RowsChangeEvent aEvt(*this,RowChangeAction::DELETE,rows.getLength(),aChangedBookmarks); + // notify the rowset listeners + notifyAllListenersRowBeforeChange(aGuard,aEvt); + + Sequence< sal_Int32 > aResults( rows.getLength() ); + const Any* row = rows.getConstArray(); + const Any* rowEnd = rows.getConstArray() + rows.getLength(); + sal_Int32* result = aResults.getArray(); + for ( ; row != rowEnd; ++row, ++result ) + { + *result = 0; + if ( !m_pCache->moveToBookmark( *row ) ) + continue; + sal_Int32 nDeletePosition = m_pCache->getRow(); + + // first notify the clones so that they can save their position + notifyRowSetAndClonesRowDelete( *row ); + + // now delete the row + if ( !m_pCache->deleteRow() ) + continue; + *result = 1; + // now notify that we have deleted + notifyRowSetAndClonesRowDeleted( *row, nDeletePosition ); + } + aEvt.Rows = aResults.getLength(); + + // we have to check if we stand on the insert row and if so we have to reset it + ORowSetNotifier aNotifier( this ); + // this will call cancelRowModification on the cache if necessary + // notification order + // - rowChanged + notifyAllListenersRowChanged(aGuard,aEvt); + + // - IsModified + // - IsNew + aNotifier.fire(); + + // - RowCount/IsRowCountFinal + fireRowcount(); + + return aResults; +} +// ----------------------------------------------------------------------------- +void ORowSet::notifyRowSetAndClonesRowDelete( const Any& _rBookmark ) +{ + // notify ourself + onDeleteRow( _rBookmark ); + // notify the clones + connectivity::OWeakRefArray::iterator aEnd = m_aClones.end(); + for (connectivity::OWeakRefArray::iterator i = m_aClones.begin(); aEnd != i; i++) + { + Reference< XUnoTunnel > xTunnel(i->get(),UNO_QUERY); + if(xTunnel.is()) + { + ORowSetClone* pClone = reinterpret_cast<ORowSetClone*>(xTunnel->getSomething(ORowSetClone::getUnoTunnelImplementationId())); + if(pClone) + pClone->onDeleteRow( _rBookmark ); + } + } +} +//------------------------------------------------------------------------------ +void ORowSet::notifyRowSetAndClonesRowDeleted( const Any& _rBookmark, sal_Int32 _nPos ) +{ + // notify ourself + onDeletedRow( _rBookmark, _nPos ); + // notify the clones + connectivity::OWeakRefArray::iterator aEnd = m_aClones.end(); + for (connectivity::OWeakRefArray::iterator i = m_aClones.begin(); aEnd != i; i++) + { + Reference< XUnoTunnel > xTunnel(i->get(),UNO_QUERY); + if(xTunnel.is()) + { + ORowSetClone* pClone = reinterpret_cast<ORowSetClone*>(xTunnel->getSomething(ORowSetClone::getUnoTunnelImplementationId())); + if(pClone) + pClone->onDeletedRow( _rBookmark, _nPos ); + } + } +} +//------------------------------------------------------------------------------ +Reference< XConnection > ORowSet::calcConnection(const Reference< XInteractionHandler >& _rxHandler) throw( SQLException, RuntimeException ) +{ + MutexGuard aGuard(m_aMutex); + if (!m_xActiveConnection.is()) + { + Reference< XConnection > xNewConn; + if ( m_aDataSourceName.getLength() ) + { + Reference< XNameAccess > xDatabaseContext( + m_aContext.createComponent( (::rtl::OUString)SERVICE_SDB_DATABASECONTEXT ), + UNO_QUERY_THROW ); + try + { + Reference< XDataSource > xDataSource( xDatabaseContext->getByName( m_aDataSourceName ), UNO_QUERY_THROW ); + + // try connecting with the interaction handler + Reference< XCompletedConnection > xComplConn( xDataSource, UNO_QUERY ); + if ( _rxHandler.is() && xComplConn.is() ) + { + xNewConn = xComplConn->connectWithCompletion( _rxHandler ); + } + else + { + xNewConn = xDataSource->getConnection( m_aUser, m_aPassword ); + } + } + catch ( const SQLException& e ) + { + throw; + } + catch ( const Exception& e ) + { + Any aError = ::cppu::getCaughtException(); + ::rtl::OUString sMessage = ResourceManager::loadString( RID_NO_SUCH_DATA_SOURCE, + "$name$", m_aDataSourceName, "$error$", extractExceptionMessage( m_aContext, aError ) ); + ::dbtools::throwGenericSQLException( sMessage, *this ); + } + } + setActiveConnection(xNewConn); + m_bOwnConnection = sal_True; + } + return m_xActiveConnection; +} +//------------------------------------------------------------------------------ +Reference< XNameAccess > ORowSet::impl_getTables_throw() +{ + Reference< XNameAccess > xTables; + + Reference< XTablesSupplier > xTablesAccess( m_xActiveConnection, UNO_QUERY ); + if ( xTablesAccess.is() ) + { + xTables.set( xTablesAccess->getTables(), UNO_QUERY_THROW ); + } + else if ( m_pTables ) + { + xTables = m_pTables; + } + else + { + if ( !m_xActiveConnection.is() ) + throw SQLException(DBA_RES(RID_STR_CONNECTION_INVALID),*this,SQLSTATE_GENERAL,1000,Any() ); + + sal_Bool bCase = sal_True; + try + { + Reference<XDatabaseMetaData> xMeta = m_xActiveConnection->getMetaData(); + bCase = xMeta.is() && xMeta->storesMixedCaseQuotedIdentifiers(); + } + catch(SQLException&) + { + DBG_UNHANDLED_EXCEPTION(); + } + + m_pTables = new OTableContainer(*this,m_aMutex,m_xActiveConnection,bCase,NULL,NULL,NULL,m_nInAppend); + xTables = m_pTables; + Sequence< ::rtl::OUString> aTableFilter(1); + aTableFilter[0] = ::rtl::OUString::createFromAscii("%"); + m_pTables->construct(aTableFilter,Sequence< ::rtl::OUString>()); + } + + return xTables; +} + +//------------------------------------------------------------------------------ +void ORowSet::impl_resetTables_nothrow() +{ + if ( !m_pTables ) + return; + + try + { + m_pTables->dispose(); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + + DELETEZ( m_pTables ); +} + +//------------------------------------------------------------------------------ +sal_Bool ORowSet::impl_initComposer_throw( ::rtl::OUString& _out_rCommandToExecute ) +{ + sal_Bool bUseEscapeProcessing = impl_buildActiveCommand_throw( ); + _out_rCommandToExecute = m_aActiveCommand; + if ( !bUseEscapeProcessing ) + return bUseEscapeProcessing; + + Reference< XMultiServiceFactory > xFactory( m_xActiveConnection, UNO_QUERY ); + if ( xFactory.is() ) + { + try + { + ::comphelper::disposeComponent( m_xComposer ); + m_xComposer.set( xFactory->createInstance( SERVICE_NAME_SINGLESELECTQUERYCOMPOSER ), UNO_QUERY_THROW ); + } + catch (const Exception& ) { m_xComposer = NULL; } + } + if ( !m_xComposer.is() ) + m_xComposer = new OSingleSelectQueryComposer( impl_getTables_throw(), m_xActiveConnection, m_aContext ); + + m_xComposer->setCommand( m_aCommand,m_nCommandType ); + m_aActiveCommand = m_xComposer->getQuery(); + + m_xComposer->setFilter( m_bApplyFilter ? m_aFilter : ::rtl::OUString() ); + m_xComposer->setHavingClause( m_bApplyFilter ? m_aHavingClause : ::rtl::OUString() ); + + if ( m_bIgnoreResult ) + { // append a "0=1" filter + // don't simply overwrite an existent filter, this would lead to problems if this existent + // filter contains paramters (since a keyset may add parameters itself) + // 2003-12-12 - #23418# - fs@openoffice.org + m_xComposer->setElementaryQuery( m_xComposer->getQuery( ) ); + m_xComposer->setFilter( ::rtl::OUString::createFromAscii( "0 = 1" ) ); + } + + m_xComposer->setOrder( m_aOrder ); + m_xComposer->setGroup( m_aGroupBy ); + + if ( !m_xColumns.is() ) + { + Reference< XColumnsSupplier > xCols( m_xComposer, UNO_QUERY_THROW ); + m_xColumns = xCols->getColumns(); + } + + impl_initParametersContainer_nothrow(); + + _out_rCommandToExecute = m_xComposer->getQueryWithSubstitution(); + + return bUseEscapeProcessing; +} + +//------------------------------------------------------------------------------ +sal_Bool ORowSet::impl_buildActiveCommand_throw() +{ + // create the sql command + // from a table name or get the command out of a query (not a view) + // the last use the command as it is + sal_Bool bDoEscapeProcessing = m_bUseEscapeProcessing; + + m_aActiveCommand = ::rtl::OUString(); + ::rtl::OUString sCommand; + + if ( !m_aCommand.getLength() ) + return bDoEscapeProcessing; + + switch (m_nCommandType) + { + case CommandType::TABLE: + { + impl_resetTables_nothrow(); + if ( bDoEscapeProcessing ) + { + Reference< XNameAccess > xTables( impl_getTables_throw() ); + if ( xTables->hasByName(m_aCommand) ) + { +/* + Reference< XPropertySet > xTable; + try + { + xTables->getByName( m_aCommand ) >>= xTable; + } + catch(const WrappedTargetException& e) + { + SQLException e2; + if ( e.TargetException >>= e2 ) + throw e2; + } + catch(Exception&) + { + DBG_UNHANDLED_EXCEPTION(); + } + + Reference<XColumnsSupplier> xSup(xTable,UNO_QUERY); + if ( xSup.is() ) + m_xColumns = xSup->getColumns(); + + sCommand = rtl::OUString::createFromAscii("SELECT * FROM "); + ::rtl::OUString sCatalog, sSchema, sTable; + ::dbtools::qualifiedNameComponents( m_xActiveConnection->getMetaData(), m_aCommand, sCatalog, sSchema, sTable, ::dbtools::eInDataManipulation ); + sCommand += ::dbtools::composeTableNameForSelect( m_xActiveConnection, sCatalog, sSchema, sTable ); +*/ + } + else + { + String sMessage( DBACORE_RESSTRING( RID_STR_TABLE_DOES_NOT_EXIST ) ); + sMessage.SearchAndReplaceAscii( "$table$", m_aCommand ); + throwGenericSQLException(sMessage,*this); + } + } + else + { + sCommand = rtl::OUString::createFromAscii("SELECT * FROM "); + ::rtl::OUString sCatalog, sSchema, sTable; + ::dbtools::qualifiedNameComponents( m_xActiveConnection->getMetaData(), m_aCommand, sCatalog, sSchema, sTable, ::dbtools::eInDataManipulation ); + sCommand += ::dbtools::composeTableNameForSelect( m_xActiveConnection, sCatalog, sSchema, sTable ); + } + } + break; + + case CommandType::QUERY: + { + Reference< XQueriesSupplier > xQueriesAccess(m_xActiveConnection, UNO_QUERY); + if (xQueriesAccess.is()) + { + Reference< ::com::sun::star::container::XNameAccess > xQueries(xQueriesAccess->getQueries()); + if (xQueries->hasByName(m_aCommand)) + { + Reference< XPropertySet > xQuery(xQueries->getByName(m_aCommand),UNO_QUERY); + OSL_ENSURE(xQuery.is(),"ORowSet::impl_buildActiveCommand_throw: Query is NULL!"); + if ( xQuery.is() ) + { + xQuery->getPropertyValue(PROPERTY_COMMAND) >>= sCommand; + xQuery->getPropertyValue(PROPERTY_ESCAPE_PROCESSING) >>= bDoEscapeProcessing; + if ( bDoEscapeProcessing != m_bUseEscapeProcessing ) + { + sal_Bool bOldValue = m_bUseEscapeProcessing; + m_bUseEscapeProcessing = bDoEscapeProcessing; + fireProperty(PROPERTY_ID_ESCAPE_PROCESSING,bOldValue,bDoEscapeProcessing); + } + + ::rtl::OUString aCatalog,aSchema,aTable; + xQuery->getPropertyValue(PROPERTY_UPDATE_CATALOGNAME) >>= aCatalog; + xQuery->getPropertyValue(PROPERTY_UPDATE_SCHEMANAME) >>= aSchema; + xQuery->getPropertyValue(PROPERTY_UPDATE_TABLENAME) >>= aTable; + if(aTable.getLength()) + m_aUpdateTableName = composeTableName( m_xActiveConnection->getMetaData(), aCatalog, aSchema, aTable, sal_False, ::dbtools::eInDataManipulation ); +/* + Reference<XColumnsSupplier> xSup(xQuery,UNO_QUERY); + if(xSup.is()) + m_xColumns = xSup->getColumns(); +*/ + } + } + else + { + String sMessage( DBACORE_RESSTRING( RID_STR_QUERY_DOES_NOT_EXIST ) ); + sMessage.SearchAndReplaceAscii( "$table$", m_aCommand ); + throwGenericSQLException(sMessage,*this); + } + } + else + throw SQLException(DBA_RES(RID_STR_NO_XQUERIESSUPPLIER),*this,::rtl::OUString(),0,Any()); + } + break; + + default: + sCommand = m_aCommand; + break; + } + + m_aActiveCommand = sCommand; + + if ( !m_aActiveCommand.getLength() && !bDoEscapeProcessing ) + ::dbtools::throwSQLException( DBACORE_RESSTRING( RID_STR_NO_SQL_COMMAND ), SQL_FUNCTION_SEQUENCE_ERROR, *this ); + + return bDoEscapeProcessing; +} + +//------------------------------------------------------------------------------ +void ORowSet::impl_initParametersContainer_nothrow() +{ + OSL_PRECOND( !m_pParameters.is(), "ORowSet::impl_initParametersContainer_nothrow: already initialized the parameters!" ); + + m_pParameters = new param::ParameterWrapperContainer( m_xComposer.get() ); + // copy the premature parameters into the final ones + size_t nParamCount( ::std::min( m_pParameters->size(), m_aPrematureParamValues.get().size() ) ); + for ( size_t i=0; i<nParamCount; ++i ) + { + (*m_pParameters)[i] = m_aPrematureParamValues.get()[i]; + } +} + +//------------------------------------------------------------------------------ +void ORowSet::impl_disposeParametersContainer_nothrow() +{ + if ( !m_pParameters.is() ) + return; + + // copy the actual values to our "premature" ones, to preserve them for later use + size_t nParamCount( m_pParameters->size() ); + m_aPrematureParamValues.get().resize( nParamCount ); + for ( size_t i=0; i<nParamCount; ++i ) + { + m_aPrematureParamValues.get()[i] = (*m_pParameters)[i]; + } + + m_pParameters->dispose(); + m_pParameters = NULL; +} + +// ----------------------------------------------------------------------------- +ORowSetValue& ORowSet::getParameterStorage(sal_Int32 parameterIndex) +{ + ::connectivity::checkDisposed( ORowSet_BASE1::rBHelper.bDisposed ); + if ( parameterIndex < 1 ) + throwInvalidIndexException( *this ); + + if ( m_aParametersSet.size() < (size_t)parameterIndex ) + m_aParametersSet.resize( parameterIndex ,false); + m_aParametersSet[parameterIndex - 1] = true; + + if ( m_aParametersSet.size() < (size_t)parameterIndex ) + m_aParametersSet.resize( parameterIndex ,false); + m_aParametersSet[parameterIndex - 1] = true; + + if ( m_pParameters.is() ) + { + if ( m_bCommandFacetsDirty ) + // need to rebuild the parameters, since some property which contributes to the + // complete command, and thus the parameters, changed + impl_disposeParametersContainer_nothrow(); + if ( m_pParameters.is() ) + { + if ( (size_t)parameterIndex > m_pParameters->size() ) + throwInvalidIndexException( *this ); + return (*m_pParameters)[ parameterIndex - 1 ]; + } + } + + if ( m_aPrematureParamValues.get().size() < (size_t)parameterIndex ) + m_aPrematureParamValues.get().resize( parameterIndex ); + return m_aPrematureParamValues.get()[ parameterIndex - 1 ]; +} +// ------------------------------------------------------------------------- +// XParameters +void SAL_CALL ORowSet::setNull( sal_Int32 parameterIndex, sal_Int32 /*sqlType*/ ) throw(SQLException, RuntimeException) +{ + ::osl::MutexGuard aGuard( m_aColumnsMutex ); + + getParameterStorage( parameterIndex ).setNull(); +} +// ------------------------------------------------------------------------- +void SAL_CALL ORowSet::setObjectNull( sal_Int32 parameterIndex, sal_Int32 sqlType, const ::rtl::OUString& /*typeName*/ ) throw(SQLException, RuntimeException) +{ + setNull( parameterIndex, sqlType ); +} +// ----------------------------------------------------------------------------- +void ORowSet::setParameter(sal_Int32 parameterIndex, const ORowSetValue& x) +{ + ::osl::MutexGuard aGuard( m_aColumnsMutex ); + + getParameterStorage( parameterIndex ) = x; +} + +// ------------------------------------------------------------------------- +void SAL_CALL ORowSet::setBoolean( sal_Int32 parameterIndex, sal_Bool x ) throw(SQLException, RuntimeException) +{ + setParameter(parameterIndex,x); +} +// ------------------------------------------------------------------------- +void SAL_CALL ORowSet::setByte( sal_Int32 parameterIndex, sal_Int8 x ) throw(SQLException, RuntimeException) +{ + setParameter(parameterIndex,x); +} +// ------------------------------------------------------------------------- +void SAL_CALL ORowSet::setShort( sal_Int32 parameterIndex, sal_Int16 x ) throw(SQLException, RuntimeException) +{ + setParameter(parameterIndex,x); +} +// ------------------------------------------------------------------------- +void SAL_CALL ORowSet::setInt( sal_Int32 parameterIndex, sal_Int32 x ) throw(SQLException, RuntimeException) +{ + setParameter(parameterIndex,x); +} +// ------------------------------------------------------------------------- +void SAL_CALL ORowSet::setLong( sal_Int32 parameterIndex, sal_Int64 x ) throw(SQLException, RuntimeException) +{ + setParameter(parameterIndex,x); +} +// ------------------------------------------------------------------------- +void SAL_CALL ORowSet::setFloat( sal_Int32 parameterIndex, float x ) throw(SQLException, RuntimeException) +{ + setParameter(parameterIndex,x); +} +// ------------------------------------------------------------------------- +void SAL_CALL ORowSet::setDouble( sal_Int32 parameterIndex, double x ) throw(SQLException, RuntimeException) +{ + setParameter(parameterIndex,x); +} +// ------------------------------------------------------------------------- +void SAL_CALL ORowSet::setString( sal_Int32 parameterIndex, const ::rtl::OUString& x ) throw(SQLException, RuntimeException) +{ + setParameter(parameterIndex,x); +} +// ------------------------------------------------------------------------- +void SAL_CALL ORowSet::setBytes( sal_Int32 parameterIndex, const Sequence< sal_Int8 >& x ) throw(SQLException, RuntimeException) +{ + setParameter(parameterIndex,x); +} +// ------------------------------------------------------------------------- +void SAL_CALL ORowSet::setDate( sal_Int32 parameterIndex, const ::com::sun::star::util::Date& x ) throw(SQLException, RuntimeException) +{ + setParameter(parameterIndex,x); +} +// ------------------------------------------------------------------------- +void SAL_CALL ORowSet::setTime( sal_Int32 parameterIndex, const ::com::sun::star::util::Time& x ) throw(SQLException, RuntimeException) +{ + setParameter(parameterIndex,x); +} +// ------------------------------------------------------------------------- +void SAL_CALL ORowSet::setTimestamp( sal_Int32 parameterIndex, const ::com::sun::star::util::DateTime& x ) throw(SQLException, RuntimeException) +{ + setParameter(parameterIndex,x); +} +// ------------------------------------------------------------------------- +void SAL_CALL ORowSet::setBinaryStream( sal_Int32 parameterIndex, const Reference< ::com::sun::star::io::XInputStream >& x, sal_Int32 length ) throw(SQLException, RuntimeException) +{ + ::osl::MutexGuard aGuard( m_aColumnsMutex ); + ORowSetValue& rParamValue( getParameterStorage( parameterIndex ) ); + + try + { + Sequence <sal_Int8> aData; + x->readBytes(aData, length); + rParamValue = aData; + x->closeInput(); + } + catch( Exception& ) + { + throw SQLException(); + } +} +// ------------------------------------------------------------------------- +void SAL_CALL ORowSet::setCharacterStream( sal_Int32 parameterIndex, const Reference< ::com::sun::star::io::XInputStream >& x, sal_Int32 length ) throw(SQLException, RuntimeException) +{ + ::osl::MutexGuard aGuard( m_aColumnsMutex ); + ORowSetValue& rParamValue( getParameterStorage( parameterIndex ) ); + try + { + Sequence <sal_Int8> aData; + rtl::OUString aDataStr; + // the data is given as character data and the length defines the character length + sal_Int32 nSize = x->readBytes(aData, length * sizeof(sal_Unicode)); + if (nSize / sizeof(sal_Unicode)) + aDataStr = rtl::OUString((sal_Unicode*)aData.getConstArray(), nSize / sizeof(sal_Unicode)); + rParamValue = aDataStr; + rParamValue.setTypeKind( DataType::LONGVARCHAR ); + x->closeInput(); + } + catch( Exception& ) + { + throw SQLException(); + } +} +// ------------------------------------------------------------------------- +void SAL_CALL ORowSet::setObject( sal_Int32 parameterIndex, const Any& x ) throw(SQLException, RuntimeException) +{ + if ( !::dbtools::implSetObject( this, parameterIndex, x ) ) + { // there is no other setXXX call which can handle the value in x + throw SQLException(); + } +} +// ------------------------------------------------------------------------- +void SAL_CALL ORowSet::setObjectWithInfo( sal_Int32 parameterIndex, const Any& x, sal_Int32 targetSqlType, sal_Int32 /*scale*/ ) throw(SQLException, RuntimeException) +{ + ::osl::MutexGuard aGuard( m_aColumnsMutex ); + ORowSetValue& rParamValue( getParameterStorage( parameterIndex ) ); + setObject( parameterIndex, x ); + rParamValue.setTypeKind( targetSqlType ); +} +// ------------------------------------------------------------------------- +void SAL_CALL ORowSet::setRef( sal_Int32 /*parameterIndex*/, const Reference< XRef >& /*x*/ ) throw(SQLException, RuntimeException) +{ + ::dbtools::throwFeatureNotImplementedException( "XParameters::setRef", *this ); +} +// ------------------------------------------------------------------------- +void SAL_CALL ORowSet::setBlob( sal_Int32 /*parameterIndex*/, const Reference< XBlob >& /*x*/ ) throw(SQLException, RuntimeException) +{ + ::dbtools::throwFeatureNotImplementedException( "XParameters::setBlob", *this ); +} +// ------------------------------------------------------------------------- +void SAL_CALL ORowSet::setClob( sal_Int32 /*parameterIndex*/, const Reference< XClob >& /*x*/ ) throw(SQLException, RuntimeException) +{ + ::dbtools::throwFeatureNotImplementedException( "XParameters::setClob", *this ); +} +// ------------------------------------------------------------------------- +void SAL_CALL ORowSet::setArray( sal_Int32 /*parameterIndex*/, const Reference< XArray >& /*x*/ ) throw(SQLException, RuntimeException) +{ + ::dbtools::throwFeatureNotImplementedException( "XParameters::setArray", *this ); +} +// ------------------------------------------------------------------------- +void SAL_CALL ORowSet::clearParameters( ) throw(SQLException, RuntimeException) +{ + ::connectivity::checkDisposed(ORowSet_BASE1::rBHelper.bDisposed); + + ::osl::MutexGuard aGuard( m_aColumnsMutex ); + + size_t nParamCount( m_pParameters.is() ? m_pParameters->size() : m_aPrematureParamValues.get().size() ); + for ( size_t i=1; i<=nParamCount; ++i ) + getParameterStorage( (sal_Int32)i ).setNull(); + m_aParametersSet.clear(); +} + +// ------------------------------------------------------------------------- +Any SAL_CALL ORowSet::getWarnings( ) throw (SQLException, RuntimeException) +{ + return m_aWarnings.getWarnings(); +} + +// ------------------------------------------------------------------------- +void SAL_CALL ORowSet::clearWarnings( ) throw (SQLException, RuntimeException) +{ + m_aWarnings.clearWarnings(); +} +// ----------------------------------------------------------------------------- +void ORowSet::doCancelModification( ) +{ + //OSL_ENSURE( isModification(), "ORowSet::doCancelModification: invalid call (no cache!)!" ); + if ( isModification() ) + { + // read-only flag restored + impl_restoreDataColumnsWriteable_throw(); + m_pCache->cancelRowModification(); + } + m_bModified = sal_False; +} + +// ----------------------------------------------------------------------------- +sal_Bool ORowSet::isModification( ) +{ + return isNew(); +} + +// ----------------------------------------------------------------------------- +sal_Bool ORowSet::isModified( ) +{ + return m_bModified; +} + +// ----------------------------------------------------------------------------- +sal_Bool ORowSet::isNew( ) +{ + return m_bNew; +} + +// ----------------------------------------------------------------------------- +void ORowSet::checkUpdateIterator() +{ + if(!m_bModified && !m_bNew) + { + m_pCache->setUpdateIterator(m_aCurrentRow); + m_aCurrentRow = m_pCache->m_aInsertRow; + m_bModified = sal_True; + } // if(!m_bModified && !m_bNew) + else if ( m_bNew ) // here we are modifing a value + m_bModified = sal_True; +} +// ----------------------------------------------------------------------------- +void ORowSet::checkUpdateConditions(sal_Int32 columnIndex) +{ + checkCache(); + if ( m_nResultSetConcurrency == ResultSetConcurrency::READ_ONLY) + ::dbtools::throwSQLException( DBACORE_RESSTRING( RID_STR_RESULT_IS_READONLY ), SQL_GENERAL_ERROR, *this ); + + if ( rowDeleted() ) + ::dbtools::throwSQLException( DBACORE_RESSTRING( RID_STR_ROW_ALREADY_DELETED ), SQL_INVALID_CURSOR_POSITION, *this ); + + if ( m_aCurrentRow.isNull() ) + ::dbtools::throwSQLException( DBACORE_RESSTRING( RID_STR_INVALID_CURSOR_STATE ), SQL_INVALID_CURSOR_STATE, *this ); + + if ( columnIndex <= 0 || sal_Int32((*m_aCurrentRow)->get().size()) <= columnIndex ) + ::dbtools::throwSQLException( DBACORE_RESSTRING( RID_STR_INVALID_INDEX ), SQL_INVALID_DESCRIPTOR_INDEX, *this ); +} +// ----------------------------------------------------------------------------- +void SAL_CALL ORowSet::refreshRow( ) throw(SQLException, RuntimeException) +{ + + ORowSetNotifier aNotifier( this ); + // this will call cancelRowModification on the cache if necessary + + // notification order: + if ( m_bModified && m_pCache ) + // - column values + implCancelRowUpdates( sal_False ); // do _not_ notify the IsModify - will do this ourself below + + ORowSetBase::refreshRow(); + + // - IsModified + // - IsNew + aNotifier.fire( ); +} +// ----------------------------------------------------------------------------- +void ORowSet::impl_rebuild_throw(::osl::ResettableMutexGuard& _rGuard) +{ + Reference< XResultSet > xResultSet( m_xStatement->executeQuery() ); + m_aWarnings.setExternalWarnings( Reference< XWarningsSupplier >( xResultSet, UNO_QUERY ) ); + m_pCache->reset(xResultSet); + notifyAllListeners(_rGuard); +} +// *********************************************************** +// ORowSetClone +// *********************************************************** +DBG_NAME(ORowSetClone); +//-------------------------------------------------------------------------- +ORowSetClone::ORowSetClone( const ::comphelper::ComponentContext& _rContext, ORowSet& rParent, ::osl::Mutex* _pMutex ) + :OSubComponent(m_aMutex, rParent) + ,ORowSetBase( _rContext, OComponentHelper::rBHelper, _pMutex ) + ,m_pParent(&rParent) + ,m_nFetchDirection(rParent.m_nFetchDirection) + ,m_nFetchSize(rParent.m_nFetchSize) + ,m_bIsBookmarable(sal_True) +{ + DBG_CTOR(ORowSetClone, NULL); + + m_nResultSetType = rParent.m_nResultSetType; + m_nResultSetConcurrency = ResultSetConcurrency::READ_ONLY; + m_pMySelf = this; + m_bClone = sal_True; + m_bBeforeFirst = rParent.m_bBeforeFirst; + m_bAfterLast = rParent.m_bAfterLast; + m_pCache = rParent.m_pCache; + m_aBookmark = rParent.m_aBookmark; + m_aCurrentRow = m_pCache->createIterator(this); + m_xNumberFormatTypes = rParent.m_xNumberFormatTypes; + + m_aOldRow = m_pCache->registerOldRow(); + + ::vos::ORef< ::connectivity::OSQLColumns> aColumns = new ::connectivity::OSQLColumns(); + ::std::vector< ::rtl::OUString> aNames; + + ::rtl::OUString aDescription; + // ConfigManager* pConfigMgr = ConfigManager::GetConfigManager(); + // Locale aLocale; + // pConfigMgr->GetDirectConfigProperty(ConfigManager::LOCALE) >>= aLocale; + Locale aLocale = SvtSysLocale().GetLocaleData().getLocale(); + + if ( rParent.m_pColumns ) + { + Sequence< ::rtl::OUString> aSeq = rParent.m_pColumns->getElementNames(); + const ::rtl::OUString* pIter = aSeq.getConstArray(); + const ::rtl::OUString* pEnd = pIter + aSeq.getLength(); + aColumns->get().reserve(aSeq.getLength()+1); + for(sal_Int32 i=1;pIter != pEnd ;++pIter,++i) + { + Reference<XPropertySet> xColumn; + rParent.m_pColumns->getByName(*pIter) >>= xColumn; + if(xColumn->getPropertySetInfo()->hasPropertyByName(PROPERTY_DESCRIPTION)) + aDescription = comphelper::getString(xColumn->getPropertyValue(PROPERTY_DESCRIPTION)); + + ::rtl::OUString sParseLabel; + xColumn->getPropertyValue(PROPERTY_LABEL) >>= sParseLabel; + ORowSetColumn* pColumn = new ORowSetColumn( rParent.getMetaData(), + this, + i, + rParent.m_xActiveConnection->getMetaData(), + aDescription, + sParseLabel, + m_aCurrentRow); + aColumns->get().push_back(pColumn); + pColumn->setName(*pIter); + aNames.push_back(*pIter); + m_aDataColumns.push_back(pColumn); + + pColumn->setFastPropertyValue_NoBroadcast(PROPERTY_ID_ALIGN,xColumn->getPropertyValue(PROPERTY_ALIGN)); + sal_Int32 nFormatKey = 0; + xColumn->getPropertyValue(PROPERTY_NUMBERFORMAT) >>= nFormatKey; + if(!nFormatKey && xColumn.is() && m_xNumberFormatTypes.is()) + nFormatKey = ::dbtools::getDefaultNumberFormat(xColumn,m_xNumberFormatTypes,aLocale); + pColumn->setFastPropertyValue_NoBroadcast(PROPERTY_ID_NUMBERFORMAT,makeAny(nFormatKey)); + pColumn->setFastPropertyValue_NoBroadcast(PROPERTY_ID_RELATIVEPOSITION,xColumn->getPropertyValue(PROPERTY_RELATIVEPOSITION)); + pColumn->setFastPropertyValue_NoBroadcast(PROPERTY_ID_WIDTH,xColumn->getPropertyValue(PROPERTY_WIDTH)); + pColumn->setFastPropertyValue_NoBroadcast(PROPERTY_ID_HIDDEN,xColumn->getPropertyValue(PROPERTY_HIDDEN)); + pColumn->setFastPropertyValue_NoBroadcast(PROPERTY_ID_CONTROLMODEL,xColumn->getPropertyValue(PROPERTY_CONTROLMODEL)); + pColumn->setFastPropertyValue_NoBroadcast(PROPERTY_ID_HELPTEXT,xColumn->getPropertyValue(PROPERTY_HELPTEXT)); + pColumn->setFastPropertyValue_NoBroadcast(PROPERTY_ID_CONTROLDEFAULT,xColumn->getPropertyValue(PROPERTY_CONTROLDEFAULT)); + + } // for(sal_Int32 i=1;pIter != pEnd ;++pIter,++i) + } + Reference<XDatabaseMetaData> xMeta = rParent.m_xActiveConnection->getMetaData(); + m_pColumns = new ORowSetDataColumns(xMeta.is() && xMeta->supportsMixedCaseQuotedIdentifiers(), + aColumns,*this,m_aMutex,aNames); + + sal_Int32 nRT = PropertyAttribute::READONLY | PropertyAttribute::TRANSIENT; + + // sdb.RowSet Properties + // registerProperty(PROPERTY_CURSORNAME, PROPERTY_ID_CURSORNAME, PropertyAttribute::READONLY, &m_aDataSourceName, ::getCppuType(reinterpret_cast< ::rtl::OUString*>(NULL))); + registerMayBeVoidProperty(PROPERTY_ACTIVE_CONNECTION,PROPERTY_ID_ACTIVE_CONNECTION, PropertyAttribute::MAYBEVOID|PropertyAttribute::READONLY, &rParent.m_aActiveConnection, ::getCppuType(reinterpret_cast< Reference< XConnection >* >(NULL))); + registerProperty(PROPERTY_RESULTSETCONCURRENCY, PROPERTY_ID_RESULTSETCONCURRENCY, PropertyAttribute::READONLY, &m_nResultSetConcurrency,::getCppuType(reinterpret_cast< sal_Int32*>(NULL))); + registerProperty(PROPERTY_RESULTSETTYPE, PROPERTY_ID_RESULTSETTYPE, PropertyAttribute::READONLY, &m_nResultSetType, ::getCppuType(reinterpret_cast< sal_Int32*>(NULL))); + registerProperty(PROPERTY_FETCHDIRECTION, PROPERTY_ID_FETCHDIRECTION, PropertyAttribute::TRANSIENT, &m_nFetchDirection, ::getCppuType(reinterpret_cast< sal_Int32*>(NULL))); + registerProperty(PROPERTY_FETCHSIZE, PROPERTY_ID_FETCHSIZE, PropertyAttribute::TRANSIENT, &m_nFetchSize, ::getCppuType(reinterpret_cast< sal_Int32*>(NULL))); + registerProperty(PROPERTY_ISBOOKMARKABLE, PROPERTY_ID_ISBOOKMARKABLE, nRT, &m_bIsBookmarable, ::getBooleanCppuType()); +} + +//-------------------------------------------------------------------------- +ORowSetClone::~ORowSetClone() +{ + DBG_DTOR(ORowSetClone, NULL); +} +// com::sun::star::XTypeProvider +//-------------------------------------------------------------------------- +Sequence< Type > ORowSetClone::getTypes() throw (RuntimeException) +{ + return ::comphelper::concatSequences(OSubComponent::getTypes(),ORowSetBase::getTypes()); +} +// com::sun::star::XInterface +//-------------------------------------------------------------------------- +Any ORowSetClone::queryInterface( const Type & rType ) throw (RuntimeException) +{ + Any aRet = ORowSetBase::queryInterface(rType); + if(!aRet.hasValue()) + aRet = OSubComponent::queryInterface(rType); + return aRet; +} +//------------------------------------------------------------------------------ +void ORowSetClone::acquire() throw() +{ + OSubComponent::acquire(); +} + +//------------------------------------------------------------------------------ +void ORowSetClone::release() throw() +{ + OSubComponent::release(); +} + +// XServiceInfo +//------------------------------------------------------------------------------ +rtl::OUString ORowSetClone::getImplementationName( ) throw(RuntimeException) +{ + return rtl::OUString::createFromAscii("com.sun.star.sdb.ORowSetClone"); +} + +//------------------------------------------------------------------------------ +sal_Bool ORowSetClone::supportsService( const ::rtl::OUString& _rServiceName ) throw (RuntimeException) +{ + return ::comphelper::findValue(getSupportedServiceNames(), _rServiceName, sal_True).getLength() != 0; +} + +//------------------------------------------------------------------------------ +Sequence< ::rtl::OUString > ORowSetClone::getSupportedServiceNames( ) throw (RuntimeException) +{ + Sequence< ::rtl::OUString > aSNS( 2 ); + aSNS[0] = SERVICE_SDBC_RESULTSET; + aSNS[1] = SERVICE_SDB_RESULTSET; + return aSNS; +} + +// OComponentHelper +//------------------------------------------------------------------------------ +void ORowSetClone::disposing() +{ + MutexGuard aGuard( m_aMutex ); + ORowSetBase::disposing(); + + m_pParent = NULL; + m_pMutex = &m_aMutex; // this must be done here because someone could hold a ref to us and try to do something + OSubComponent::disposing(); +} + +// XCloseable +//------------------------------------------------------------------------------ +void ORowSetClone::close(void) throw( SQLException, RuntimeException ) +{ + { + MutexGuard aGuard( m_aMutex ); + if (OComponentHelper::rBHelper.bDisposed) + throw DisposedException(); + } + dispose(); +} +// ------------------------------------------------------------------------- + +// comphelper::OPropertyArrayUsageHelper +::cppu::IPropertyArrayHelper* ORowSetClone::createArrayHelper( ) const +{ + Sequence< Property > aProps; + describeProperties(aProps); + return new ::cppu::OPropertyArrayHelper(aProps); +} +// ------------------------------------------------------------------------- + +// cppu::OPropertySetHelper +::cppu::IPropertyArrayHelper& SAL_CALL ORowSetClone::getInfoHelper() +{ + typedef ::comphelper::OPropertyArrayUsageHelper<ORowSetClone> ORowSetClone_PROP; + return *ORowSetClone_PROP::getArrayHelper(); +} +// ------------------------------------------------------------------------- +//-------------------------------------------------------------------------- +Sequence< sal_Int8 > ORowSetClone::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(); +} +// ----------------------------------------------------------------------------- +// com::sun::star::XUnoTunnel +sal_Int64 SAL_CALL ORowSetClone::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); + + return 0; +} +// ----------------------------------------------------------------------------- +void SAL_CALL ORowSetClone::setFastPropertyValue_NoBroadcast(sal_Int32 nHandle,const Any& rValue) throw (Exception) +{ + if ( nHandle == PROPERTY_ID_FETCHSIZE ) + { + if ( m_pParent ) + m_pParent->setFastPropertyValue_NoBroadcast( nHandle, rValue ); + } + + OPropertyStateContainer::setFastPropertyValue_NoBroadcast(nHandle,rValue); +} + +// ----------------------------------------------------------------------------- +void ORowSetClone::doCancelModification( ) +{ + //OSL_ENSURE( sal_False, "ORowSetClone::doCancelModification: invalid call!" ); +} + +// ----------------------------------------------------------------------------- +sal_Bool ORowSetClone::isModification( ) +{ + return sal_False; +} + +// ----------------------------------------------------------------------------- +sal_Bool ORowSetClone::isModified( ) +{ + return sal_False; +} + +// ----------------------------------------------------------------------------- +sal_Bool ORowSetClone::isNew( ) +{ + return sal_False; +} + +// ------------------------------------------------------------------------- +void SAL_CALL ORowSetClone::execute( ) throw(SQLException, RuntimeException) +{ + throwFunctionNotSupportedException( "RowSetClone::XRowSet::execute", *this ); +} + +// ------------------------------------------------------------------------- +void SAL_CALL ORowSetClone::addRowSetListener( const Reference< XRowSetListener >& ) throw(RuntimeException) +{ + throwFunctionNotSupportedException( "RowSetClone::XRowSet", *this ); +} + +// ------------------------------------------------------------------------- +void SAL_CALL ORowSetClone::removeRowSetListener( const Reference< XRowSetListener >& ) throw(RuntimeException) +{ + throwFunctionNotSupportedException( "RowSetClone::XRowSet", *this ); +} + +} // dbaccess diff --git a/dbaccess/source/core/api/RowSet.hxx b/dbaccess/source/core/api/RowSet.hxx new file mode 100644 index 000000000000..8a85237cb928 --- /dev/null +++ b/dbaccess/source/core/api/RowSet.hxx @@ -0,0 +1,544 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +#ifndef DBACCESS_CORE_API_ROWSET_HXX +#define DBACCESS_CORE_API_ROWSET_HXX + +#include "apitools.hxx" +#include "RowSetBase.hxx" + +/** === begin UNO includes === **/ +#include <com/sun/star/sdbc/XPreparedStatement.hpp> +#include <com/sun/star/sdbc/XConnection.hpp> +#include <com/sun/star/sdb/XSingleSelectQueryComposer.hpp> +#include <com/sun/star/sdb/XResultSetAccess.hpp> +#include <com/sun/star/sdbc/XRowSetListener.hpp> +#include <com/sun/star/sdbc/XRowUpdate.hpp> +#include <com/sun/star/sdbc/XResultSetUpdate.hpp> +#include <com/sun/star/sdbc/XParameters.hpp> +#include <com/sun/star/sdb/XRowSetApproveBroadcaster.hpp> +#include <com/sun/star/sdbc/ResultSetType.hpp> +#include <com/sun/star/util/XCancellable.hpp> +#include <com/sun/star/sdbcx/XDeleteRows.hpp> +#include <com/sun/star/sdb/XCompletedExecution.hpp> +#include <com/sun/star/sdb/RowSetVetoException.hpp> +#include <com/sun/star/sdb/XSingleSelectQueryAnalyzer.hpp> +#include <com/sun/star/sdb/XSingleSelectQueryComposer.hpp> +#include <com/sun/star/sdb/XParametersSupplier.hpp> +#include <com/sun/star/sdb/XRowsChangeBroadcaster.hpp> +/** === end UNO includes === **/ + +#include <cppuhelper/compbase12.hxx> +#include <connectivity/paramwrapper.hxx> +#include <connectivity/FValue.hxx> +#include <connectivity/warningscontainer.hxx> + +namespace dbaccess +{ + typedef ::cppu::WeakAggComponentImplHelper12 < ::com::sun::star::sdb::XResultSetAccess + , ::com::sun::star::sdb::XRowSetApproveBroadcaster + , ::com::sun::star::sdb::XRowsChangeBroadcaster + , ::com::sun::star::sdbcx::XDeleteRows + , ::com::sun::star::sdbc::XParameters + , ::com::sun::star::lang::XEventListener + , ::com::sun::star::sdbc::XResultSetUpdate + , ::com::sun::star::sdbc::XRowUpdate + , ::com::sun::star::util::XCancellable + , ::com::sun::star::sdb::XCompletedExecution + , ::com::sun::star::sdb::XParametersSupplier + , ::com::sun::star::sdbc::XWarningsSupplier + > ORowSet_BASE1; + + class OTableContainer; + class ORowSet : public comphelper::OBaseMutex + , public ORowSet_BASE1 + , public ORowSetBase + , public ::comphelper::OPropertyArrayUsageHelper<ORowSet> + { + friend class ORowSetClone; + + ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection > m_xOldConnection; + ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection > m_xActiveConnection; + ::com::sun::star::uno::Any m_aActiveConnection; + ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess > m_xTypeMap; + ::com::sun::star::uno::Any m_aTypeMap; + ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XPreparedStatement > m_xStatement; + ::com::sun::star::uno::Reference< ::com::sun::star::sdb::XSingleSelectQueryComposer > m_xComposer; + ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess > m_xColumns; // the columns from a table or query + + connectivity::OWeakRefArray m_aClones; + /** our parameters as XPropertySet instances and ORowSetValue instances + */ + ::dbtools::param::ParametersContainerRef m_pParameters; + /** our parameters values, used when we do not yet have a parameters container + (since we have not been executed, yet) + */ + ORowSetValueVector m_aPrematureParamValues; + ORowSetValueVector m_aParameterValueForCache; + ::std::bit_vector m_aParametersSet; + ::std::bit_vector m_aReadOnlyDataColumns; + + ::cppu::OInterfaceContainerHelper m_aRowsetListeners; + ::cppu::OInterfaceContainerHelper m_aApproveListeners; + ::cppu::OInterfaceContainerHelper m_aRowsChangeListener; + + ::dbtools::WarningsContainer m_aWarnings; + + OTableContainer* m_pTables; + + rtl::OUString m_aCommand; + rtl::OUString m_aDataSourceName; + rtl::OUString m_aURL; + rtl::OUString m_aUser; + rtl::OUString m_aPassword; + rtl::OUString m_aFilter; + rtl::OUString m_aHavingClause; + rtl::OUString m_aGroupBy; + rtl::OUString m_aOrder; + rtl::OUString m_aActiveCommand; + rtl::OUString m_aCursorName; + rtl::OUString m_aUpdateCatalogName; // is set by a query + rtl::OUString m_aUpdateSchemaName; // is set by a query + rtl::OUString m_aUpdateTableName; // is set by a query + + sal_Int32 m_nFetchDirection; + sal_Int32 m_nFetchSize; + sal_Int32 m_nMaxFieldSize; + sal_Int32 m_nMaxRows; + sal_Int32 m_nQueryTimeOut; + sal_Int32 m_nCommandType; + sal_Int32 m_nTransactionIsolation; + sal_Int32 m_nPrivileges; + sal_Int32 m_nLastKnownRowCount; + oslInterlockedCount m_nInAppend; + sal_Bool m_bLastKnownRowCountFinal; + sal_Bool m_bUseEscapeProcessing ; + sal_Bool m_bApplyFilter ; + sal_Bool m_bCommandFacetsDirty; // any of the facets which define the active command is dirty + sal_Bool m_bModified ; + sal_Bool m_bRebuildConnOnExecute ; + sal_Bool m_bIsBookmarable ; + sal_Bool m_bNew ; + sal_Bool m_bCanUpdateInsertedRows; + sal_Bool m_bOwnConnection; + + private: + /** builds m_aActiveCommand from our settings + + @return + whether we should use escape processing before executing the actual command. This is determined + from our own EscapeProcessing property, and possibly overruled by the respective property + of a query we're based on. + */ + sal_Bool impl_buildActiveCommand_throw(); + + /** initializes our query composer, and everything which has to do with it + + If we don't use escape processing, then we don't have a composer, and everything + related to it. Nonetheless, _out_rCommandToExecute and the return value are properly + initialized. + + @param _out_rCommandToExecute + The command which is to be executed, according to the current settings - + it is built from our active command plus our current filter/order criterions. + + @return + whether we should use escape processing before executing the actual command. This is determined + from our own EscapeProcessing property, and possibly overruled by the respective property + of a query we're based on. + Effectively, this value determines whether or not we actually have an composer (m_xComposer) + and dependent information (such as the parameters container). + + @precond + m_xActiveConnection points to a valid SDB-level connection + + @throws com::sun::star::sdb::SQLException + if an database-related error occured + + @throws com::sun::star::uno::RuntimeException + if any of the components involved throws a com::sun::star::uno::RuntimeException + */ + sal_Bool impl_initComposer_throw( ::rtl::OUString& _out_rCommandToExecute ); + + /** returns the table container of our active connection + + If our connection is able to provide a tables container, this one is returned. + Else, if m_pTables is not <NULL/>, this one will returned. + Else, m_pTables will be constructed and returned. + + @precond m_xActiveConnection is not <NULL/> + @throws ::com::sun::star::sdbc::SQLException + if retrieving or constructing the tables container goes wrong + + @see impl_resetTables_nothrow + */ + ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess > + impl_getTables_throw(); + + /** cleans up m_pTables, and resets it to <NULL/> + */ + void impl_resetTables_nothrow(); + + /** prepares and executes our command + */ + ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XResultSet > + impl_prepareAndExecute_throw(); + + ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection > calcConnection(const ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler >& _rxHandler) throw( ::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException ); + // free clones and ParseTree. Plus, if _bComplete is <TRUE/>, *all* other associated resources + void freeResources( bool _bComplete ); + + /// informs the clones (and ourself) that we are going to delete a record with a given bookmark + void notifyRowSetAndClonesRowDelete( const ::com::sun::star::uno::Any& _rBookmark ); + + /// inform the clones (and ourself) that we have deleted a record with a given bookmark + void notifyRowSetAndClonesRowDeleted( const ::com::sun::star::uno::Any& _rBookmark, sal_Int32 _nPos ); + + void checkUpdateIterator(); + const connectivity::ORowSetValue& getInsertValue(sal_Int32 columnIndex); + void setParameter(sal_Int32 parameterIndex, const connectivity::ORowSetValue& x); + // resizes the parameter vector if nescessary + ::connectivity::ORowSetValue& getParameterStorage( sal_Int32 parameterIndex ); + + void updateValue(sal_Int32 columnIndex,const connectivity::ORowSetValue& x); + void checkUpdateConditions(sal_Int32 columnIndex); + void impl_rebuild_throw(::osl::ResettableMutexGuard& _rGuard); + // set all data columns to writeable + void impl_setDataColumnsWriteable_throw(); + // restore the old state of the data column read-only state + void impl_restoreDataColumnsWriteable_throw(); + + protected: + virtual void SAL_CALL setFastPropertyValue_NoBroadcast(sal_Int32 nHandle,const ::com::sun::star::uno::Any& rValue) throw (::com::sun::star::uno::Exception); + virtual void SAL_CALL getFastPropertyValue(::com::sun::star::uno::Any& rValue,sal_Int32 nHandle) const; + virtual void getPropertyDefaultByHandle( sal_Int32 _nHandle, ::com::sun::star::uno::Any& _rDefault ) const; + + virtual void fireRowcount(); + void notifyAllListenersRowBeforeChange(::osl::ResettableMutexGuard& _rGuard,const ::com::sun::star::sdb::RowChangeEvent &rEvt); + void notifyAllListenersRowChanged(::osl::ResettableMutexGuard& _rGuard,const ::com::sun::star::sdb::RowsChangeEvent& rEvt); + virtual sal_Bool notifyAllListenersCursorBeforeMove(::osl::ResettableMutexGuard& _rGuard); + virtual void notifyAllListenersCursorMoved(::osl::ResettableMutexGuard& _rGuard); + virtual void notifyAllListeners(::osl::ResettableMutexGuard& _rGuard); + + virtual void doCancelModification( ); + virtual sal_Bool isModification( ); + virtual sal_Bool isModified( ); + virtual sal_Bool isNew( ); + + virtual ~ORowSet(); + + public: + ORowSet(const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >&); + + // com::sun::star::lang::XTypeProvider + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type > SAL_CALL getTypes() throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId() throw (::com::sun::star::uno::RuntimeException); + + // com::sun::star::uno::XInterface + virtual ::com::sun::star::uno::Any SAL_CALL queryInterface( const ::com::sun::star::uno::Type & rType ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL acquire() throw(); + virtual void SAL_CALL release() throw(); + + // com::sun::star::lang::XUnoTunnel + virtual sal_Int64 SAL_CALL getSomething( const ::com::sun::star::uno::Sequence< sal_Int8 >& aIdentifier ) throw(::com::sun::star::uno::RuntimeException); + + // com::sun::star::uno::XAggregation + virtual ::com::sun::star::uno::Any SAL_CALL queryAggregation( const ::com::sun::star::uno::Type& aType ) throw(::com::sun::star::uno::RuntimeException); + + // ::com::sun::star::lang::XServiceInfo + virtual ::rtl::OUString SAL_CALL getImplementationName( ) throw(::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) throw(::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames( ) throw(::com::sun::star::uno::RuntimeException); + + // ::com::sun::star::lang::XServiceInfo - static methods + static ::com::sun::star::uno::Sequence< ::rtl::OUString > getSupportedServiceNames_static(void) throw( ::com::sun::star::uno::RuntimeException ); + static ::rtl::OUString getImplementationName_static(void) throw( ::com::sun::star::uno::RuntimeException ); + static ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > + SAL_CALL Create(const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext >&); + + // OComponentHelper + virtual void SAL_CALL disposing(void); + + // ::com::sun::star::lang::XEventListener + virtual void SAL_CALL disposing( const ::com::sun::star::lang::EventObject& Source ) throw(::com::sun::star::uno::RuntimeException); + + // ::com::sun::star::sdbc::XCloseable + virtual void SAL_CALL close( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + + // comphelper::OPropertyArrayUsageHelper + virtual ::cppu::IPropertyArrayHelper* createArrayHelper( ) const; + + // cppu::OPropertySetHelper + virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper(); + + // ::com::sun::star::sdbc::XResultSet + virtual sal_Int32 SAL_CALL getRow( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL refreshRow( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + + // XCompletedExecution + virtual void SAL_CALL executeWithCompletion( const ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler >& handler ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + + // XParametersSupplier + virtual ::com::sun::star::uno::Reference< ::com::sun::star::container::XIndexAccess > SAL_CALL getParameters( ) throw (::com::sun::star::uno::RuntimeException); + + // ::com::sun::star::sdbc::XRow + virtual sal_Bool SAL_CALL wasNull( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getString( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL getBoolean( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Int8 SAL_CALL getByte( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Int16 SAL_CALL getShort( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Int32 SAL_CALL getInt( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Int64 SAL_CALL getLong( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual float SAL_CALL getFloat( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual double SAL_CALL getDouble( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL getBytes( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::util::Date SAL_CALL getDate( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::util::Time SAL_CALL getTime( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::util::DateTime SAL_CALL getTimestamp( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > SAL_CALL getBinaryStream( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > SAL_CALL getCharacterStream( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Any SAL_CALL getObject( sal_Int32 columnIndex, const ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess >& typeMap ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRef > SAL_CALL getRef( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XBlob > SAL_CALL getBlob( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XClob > SAL_CALL getClob( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XArray > SAL_CALL getArray( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + + // ::com::sun::star::sdbc::XRowUpdate + virtual void SAL_CALL updateNull( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL updateBoolean( sal_Int32 columnIndex, sal_Bool x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL updateByte( sal_Int32 columnIndex, sal_Int8 x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL updateShort( sal_Int32 columnIndex, sal_Int16 x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL updateInt( sal_Int32 columnIndex, sal_Int32 x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL updateLong( sal_Int32 columnIndex, sal_Int64 x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL updateFloat( sal_Int32 columnIndex, float x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL updateDouble( sal_Int32 columnIndex, double x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL updateString( sal_Int32 columnIndex, const ::rtl::OUString& x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL updateBytes( sal_Int32 columnIndex, const ::com::sun::star::uno::Sequence< sal_Int8 >& x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL updateDate( sal_Int32 columnIndex, const ::com::sun::star::util::Date& x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL updateTime( sal_Int32 columnIndex, const ::com::sun::star::util::Time& x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL updateTimestamp( sal_Int32 columnIndex, const ::com::sun::star::util::DateTime& x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL updateBinaryStream( sal_Int32 columnIndex, const ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream >& x, sal_Int32 length ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL updateCharacterStream( sal_Int32 columnIndex, const ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream >& x, sal_Int32 length ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL updateObject( sal_Int32 columnIndex, const ::com::sun::star::uno::Any& x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL updateNumericObject( sal_Int32 columnIndex, const ::com::sun::star::uno::Any& x, sal_Int32 scale ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + + // ::com::sun::star::sdbc::XResultSetUpdate + virtual void SAL_CALL insertRow( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL updateRow( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL deleteRow( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL cancelRowUpdates( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL moveToInsertRow( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL moveToCurrentRow( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + + // ::com::sun::star::sdbc::XRowSet + virtual void SAL_CALL execute( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL addRowSetListener( const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRowSetListener >& listener ) throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeRowSetListener( const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRowSetListener >& listener ) throw(::com::sun::star::uno::RuntimeException); + + // ::com::sun::star::sdb::XRowSetApproveBroadcaster + virtual void SAL_CALL addRowSetApproveListener( const ::com::sun::star::uno::Reference< ::com::sun::star::sdb::XRowSetApproveListener >& listener ) throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeRowSetApproveListener( const ::com::sun::star::uno::Reference< ::com::sun::star::sdb::XRowSetApproveListener >& listener ) throw(::com::sun::star::uno::RuntimeException); + + // ::com::sun::star::sdb::XRowsChangeBroadcaster + virtual void SAL_CALL addRowsChangeListener( const ::com::sun::star::uno::Reference< ::com::sun::star::sdb::XRowsChangeListener >& listener ) throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeRowsChangeListener( const ::com::sun::star::uno::Reference< ::com::sun::star::sdb::XRowsChangeListener >& listener ) throw(::com::sun::star::uno::RuntimeException); + + // ::com::sun::star::sdb::XResultSetAccess + virtual ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XResultSet > SAL_CALL createResultSet( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + + // ::com::sun::star::util::XCancellable + virtual void SAL_CALL cancel( ) throw(::com::sun::star::uno::RuntimeException); + + // ::com::sun::star::sdbcx::XDeleteRows + virtual ::com::sun::star::uno::Sequence< sal_Int32 > SAL_CALL deleteRows( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& rows ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + + // XParameters + virtual void SAL_CALL setNull( sal_Int32 parameterIndex, sal_Int32 sqlType ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setObjectNull( sal_Int32 parameterIndex, sal_Int32 sqlType, const ::rtl::OUString& typeName ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setBoolean( sal_Int32 parameterIndex, sal_Bool x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setByte( sal_Int32 parameterIndex, sal_Int8 x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setShort( sal_Int32 parameterIndex, sal_Int16 x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setInt( sal_Int32 parameterIndex, sal_Int32 x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setLong( sal_Int32 parameterIndex, sal_Int64 x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setFloat( sal_Int32 parameterIndex, float x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setDouble( sal_Int32 parameterIndex, double x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setString( sal_Int32 parameterIndex, const ::rtl::OUString& x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setBytes( sal_Int32 parameterIndex, const ::com::sun::star::uno::Sequence< sal_Int8 >& x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setDate( sal_Int32 parameterIndex, const ::com::sun::star::util::Date& x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setTime( sal_Int32 parameterIndex, const ::com::sun::star::util::Time& x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setTimestamp( sal_Int32 parameterIndex, const ::com::sun::star::util::DateTime& x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setBinaryStream( sal_Int32 parameterIndex, const ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream >& x, sal_Int32 length ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setCharacterStream( sal_Int32 parameterIndex, const ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream >& x, sal_Int32 length ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setObject( sal_Int32 parameterIndex, const ::com::sun::star::uno::Any& x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setObjectWithInfo( sal_Int32 parameterIndex, const ::com::sun::star::uno::Any& x, sal_Int32 targetSqlType, sal_Int32 scale ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setRef( sal_Int32 parameterIndex, const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRef >& x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setBlob( sal_Int32 parameterIndex, const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XBlob >& x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setClob( sal_Int32 parameterIndex, const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XClob >& x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setArray( sal_Int32 parameterIndex, const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XArray >& x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL clearParameters( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + + // XWarningsSupplier + virtual ::com::sun::star::uno::Any SAL_CALL getWarnings( ) throw (::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL clearWarnings( ) throw (::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + + protected: + /** implement the <method>execute</method>, without calling the approve listeners and without building a new + connection + @param _rClearForNotification mutex to clear before doing the final notifications + */ + void execute_NoApprove_NoNewConn(::osl::ResettableMutexGuard& _rClearForNotification); + + /** call the RowSetApproveListeners<p/> + throws an RowSetVetoException if one of the listeners vetoed + */ + void approveExecution() throw (::com::sun::star::sdb::RowSetVetoException, ::com::sun::star::uno::RuntimeException); + + /// set m_xActiveConnection, fire a PropertyChangeEvent if necessary, do the event listener handling etc + void setActiveConnection( ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection >& _rxNewConn, sal_Bool _bFireEvent = sal_True ); + + void implCancelRowUpdates( sal_Bool _bNotifyModified ) SAL_THROW( ( ::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException ) ); + + /** sets the given result set type/concurrency at the given statement, while respecting + possibly related data source settings + */ + void setStatementResultSetType( + const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& _rxStatement, + sal_Int32 _nDesiredResultSetType, + sal_Int32 _nDesiredResultSetConcurrency + ); + + /** initializes a given RowSet column with the ColumnSettings (width, format, hidden, etc.) from a + template column. + + If the template column supports any of the known column settings, they're plain copied. If not, + the template column is examined for a TableName and Name property, and the table column described + by those is used to find and copy the column settings. + */ + void impl_initializeColumnSettings_nothrow( + const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& _rxTemplateColumn, + const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& _rxRowSetColumn + ); + + /** initializes our parameters container (m_pParameters) according to the parameter columns as + obtained from our composer + */ + void impl_initParametersContainer_nothrow(); + /** disposes our parameters container + */ + void impl_disposeParametersContainer_nothrow(); + + protected: + using ORowSetBase::getFastPropertyValue; + using ORowSetBase::firePropertyChange; + using ORowSetBase::doCancelModification; + using ORowSetBase::isModification; + using ORowSetBase::isModified; + using ORowSetBase::isNew; + }; + + + //************************************************************ + // ORowSetClone + //************************************************************ + class ORowSetClone : public comphelper::OBaseMutex + ,public OSubComponent + ,public ORowSetBase + ,public ::comphelper::OPropertyArrayUsageHelper < ORowSetClone > + { + protected: + ORowSet* m_pParent; + sal_Int32 m_nFetchDirection; + sal_Int32 m_nFetchSize; + sal_Bool m_bIsBookmarable; + + protected: + // the clone can not insert anything + virtual void doCancelModification( ); + virtual sal_Bool isModification( ); + virtual sal_Bool isModified( ); + virtual sal_Bool isNew( ); + + virtual void SAL_CALL setFastPropertyValue_NoBroadcast(sal_Int32 nHandle,const ::com::sun::star::uno::Any& rValue) throw (::com::sun::star::uno::Exception); + public: + ORowSetClone( const ::comphelper::ComponentContext& _rContext, ORowSet& rParent, ::osl::Mutex* _pMutex ); + virtual ~ORowSetClone(); + + // com::sun::star::lang::XTypeProvider + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type > SAL_CALL getTypes() throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId() throw (::com::sun::star::uno::RuntimeException) + { + return getUnoTunnelImplementationId(); + } + + // com::sun::star::uno::XInterface + virtual ::com::sun::star::uno::Any SAL_CALL queryInterface( const ::com::sun::star::uno::Type & rType ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL acquire() throw(); + virtual void SAL_CALL release() throw(); + + // ::com::sun::star::lang::XServiceInfo + virtual ::rtl::OUString SAL_CALL getImplementationName( ) throw(::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) throw(::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames( ) throw(::com::sun::star::uno::RuntimeException); + + // com::sun::star::lang::XUnoTunnel + virtual sal_Int64 SAL_CALL getSomething( const ::com::sun::star::uno::Sequence< sal_Int8 >& aIdentifier ) throw(::com::sun::star::uno::RuntimeException); + static ::com::sun::star::uno::Sequence< sal_Int8 > getUnoTunnelImplementationId(); + + // OComponentHelper + virtual void SAL_CALL disposing(void); + + // ::com::sun::star::sdbc::XCloseable + virtual void SAL_CALL close( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + + // com::sun::star::beans::XPropertySet + virtual ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo( ) throw(::com::sun::star::uno::RuntimeException) + { + return ::cppu::OPropertySetHelper::createPropertySetInfo(getInfoHelper()); + } + + // ::com::sun::star::sdbc::XRowSet + virtual void SAL_CALL execute( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL addRowSetListener( const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRowSetListener >& listener ) throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeRowSetListener( const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRowSetListener >& listener ) throw(::com::sun::star::uno::RuntimeException); + + // comphelper::OPropertyArrayUsageHelper + virtual ::cppu::IPropertyArrayHelper* createArrayHelper( ) const; + + // cppu::OPropertySetHelper + virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper(); + + protected: + using ORowSetBase::doCancelModification; + using ORowSetBase::isModification; + using ORowSetBase::isModified; + using ORowSetBase::isNew; + using ORowSetBase::rowDeleted; + }; + +} +#endif // DBACCESS_CORE_API_ROWSET_HXX + diff --git a/dbaccess/source/core/api/RowSetBase.cxx b/dbaccess/source/core/api/RowSetBase.cxx new file mode 100644 index 000000000000..57157cf4f998 --- /dev/null +++ b/dbaccess/source/core/api/RowSetBase.cxx @@ -0,0 +1,1577 @@ +/************************************************************************* + * + * 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_dbaccess.hxx" + +#include "RowSetBase.hxx" +#include "CRowSetDataColumn.hxx" +#include <connectivity/sdbcx/VCollection.hxx> +#include "RowSetCache.hxx" +#include "dbastrings.hrc" +#include "core_resource.hrc" +#include <com/sun/star/lang/DisposedException.hpp> +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/sdbcx/CompareBookmark.hpp> +#include <com/sun/star/sdbc/ResultSetConcurrency.hpp> +#include <com/sun/star/lang/Locale.hpp> +#include <com/sun/star/util/NumberFormat.hpp> +#include <comphelper/sequence.hxx> +#include <comphelper/extract.hxx> +#include <comphelper/seqstream.hxx> +#include <connectivity/dbexception.hxx> +#include <osl/thread.h> +#include <tools/debug.hxx> +#include <rtl/logfile.hxx> + +using namespace dbaccess; +using namespace connectivity; +using namespace connectivity::sdbcx; +using namespace comphelper; +using 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::sdb; +using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::util; +using namespace ::cppu; +using namespace ::osl; + +namespace dbaccess +{ + +// ========================================================================= +// = OEmptyCollection +// ========================================================================= +// ------------------------------------------------------------------------- +class OEmptyCollection : public sdbcx::OCollection +{ +protected: + virtual void impl_refresh() throw(RuntimeException); + virtual connectivity::sdbcx::ObjectType createObject(const ::rtl::OUString& _rName); +public: + OEmptyCollection(::cppu::OWeakObject& _rParent,::osl::Mutex& _rMutex) : OCollection(_rParent,sal_True,_rMutex,::std::vector< ::rtl::OUString>()){} +}; +// ----------------------------------------------------------------------------- +void OEmptyCollection::impl_refresh() throw(RuntimeException) +{ +} +// ----------------------------------------------------------------------------- +connectivity::sdbcx::ObjectType OEmptyCollection::createObject(const ::rtl::OUString& /*_rName*/) +{ + return connectivity::sdbcx::ObjectType(); +} +// ----------------------------------------------------------------------------- + +// ========================================================================= +// = ORowSetBase +// ========================================================================= +DBG_NAME(ORowSetBase) +// ------------------------------------------------------------------------- +ORowSetBase::ORowSetBase( const ::comphelper::ComponentContext& _rContext, ::cppu::OBroadcastHelper& _rBHelper, ::osl::Mutex* _pMutex ) + :OPropertyStateContainer(_rBHelper) + ,m_pMutex(_pMutex) + ,m_pCache(NULL) + ,m_pColumns(NULL) + ,m_rBHelper(_rBHelper) + ,m_pEmptyCollection( NULL ) + ,m_aContext( _rContext ) + ,m_aErrors( _rContext ) + ,m_nLastColumnIndex(-1) + ,m_nDeletedPosition(-1) + ,m_nResultSetType( ResultSetType::FORWARD_ONLY ) + ,m_nResultSetConcurrency( ResultSetConcurrency::READ_ONLY ) + ,m_bClone(sal_False) + ,m_bIgnoreResult(sal_False) + ,m_bBeforeFirst(sal_True) // changed from sal_False + ,m_bAfterLast(sal_False) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::ORowSetBase" ); + DBG_CTOR(ORowSetBase,NULL); + + sal_Int32 nRBT = PropertyAttribute::READONLY | PropertyAttribute::BOUND | PropertyAttribute::TRANSIENT; + + sal_Int32 nInitialRowCountValue = 0; + sal_Bool bInitialRowCountFinalValue( sal_False ); + registerPropertyNoMember( PROPERTY_ROWCOUNT, PROPERTY_ID_ROWCOUNT, nRBT, ::getCppuType( &nInitialRowCountValue ), &nInitialRowCountValue ); + registerPropertyNoMember( PROPERTY_ISROWCOUNTFINAL, PROPERTY_ID_ISROWCOUNTFINAL, nRBT, ::getBooleanCppuType(), &bInitialRowCountFinalValue ); +} +// ----------------------------------------------------------------------------- +ORowSetBase::~ORowSetBase() +{ + if(m_pColumns) + { + TDataColumns().swap(m_aDataColumns); + m_pColumns->acquire(); + m_pColumns->disposing(); + delete m_pColumns; + m_pColumns = NULL; + } + + if ( m_pEmptyCollection ) + delete m_pEmptyCollection; + + DBG_DTOR(ORowSetBase,NULL); +} +// com::sun::star::lang::XTypeProvider +//-------------------------------------------------------------------------- +Sequence< Type > ORowSetBase::getTypes() throw (RuntimeException) +{ + //RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::getTypes" ); + return ::comphelper::concatSequences(ORowSetBase_BASE::getTypes(),OPropertyStateContainer::getTypes()); +} +// com::sun::star::uno::XInterface +//-------------------------------------------------------------------------- +Any ORowSetBase::queryInterface( const Type & rType ) throw (RuntimeException) +{ + //RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::queryInterface" ); + Any aRet = ORowSetBase_BASE::queryInterface(rType); + if(!aRet.hasValue()) + aRet = OPropertyStateContainer::queryInterface(rType); + return aRet; +} +// ------------------------------------------------------------------------- +void SAL_CALL ORowSetBase::getFastPropertyValue(Any& rValue,sal_Int32 nHandle) const +{ + //RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::getFastPropertyValue" ); + if(m_pCache) + { + switch(nHandle) + { + case PROPERTY_ID_ROWCOUNT: + rValue <<= impl_getRowCount(); + break; + case PROPERTY_ID_ISROWCOUNTFINAL: + rValue.setValue(&m_pCache->m_bRowCountFinal,::getCppuBooleanType()); + break; + default: + OPropertyStateContainer::getFastPropertyValue(rValue,nHandle); + }; + } + else + OPropertyStateContainer::getFastPropertyValue(rValue,nHandle); +} +// ------------------------------------------------------------------------- +// OComponentHelper +void SAL_CALL ORowSetBase::disposing(void) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::disposing" ); + MutexGuard aGuard(*m_pMutex); + + if ( m_pColumns ) + { + TDataColumns().swap(m_aDataColumns); + m_pColumns->disposing(); + } + if ( m_pCache ) + { + m_pCache->deregisterOldRow(m_aOldRow); + m_pCache->deleteIterator(this); + } + m_pCache = NULL; +} +// ------------------------------------------------------------------------- +// comphelper::OPropertyArrayUsageHelper +::cppu::IPropertyArrayHelper* ORowSetBase::createArrayHelper( ) const +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::createArrayHelper" ); + Sequence< Property > aProps; + describeProperties(aProps); + return new ::cppu::OPropertyArrayHelper(aProps); +} +// ------------------------------------------------------------------------- +// cppu::OPropertySetHelper +::cppu::IPropertyArrayHelper& SAL_CALL ORowSetBase::getInfoHelper() +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::getInfoHelper" ); + return *const_cast<ORowSetBase*>(this)->getArrayHelper(); +} +// ------------------------------------------------------------------------- +// XRow +sal_Bool SAL_CALL ORowSetBase::wasNull( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::wasNull" ); + ::osl::MutexGuard aGuard( *m_pMutex ); + checkCache(); + return impl_wasNull(); +} +// ----------------------------------------------------------------------------- +sal_Bool ORowSetBase::impl_wasNull() +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::impl_wasNull" ); + return ((m_nLastColumnIndex != -1) && !m_aCurrentRow.isNull() && m_aCurrentRow != m_pCache->getEnd() && m_aCurrentRow->isValid()) ? ((*m_aCurrentRow)->get())[m_nLastColumnIndex].isNull() : sal_True; +} + +// ----------------------------------------------------------------------------- +const ORowSetValue& ORowSetBase::getValue(sal_Int32 columnIndex) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::getValue" ); + checkCache(); + return impl_getValue(columnIndex); +} +// ----------------------------------------------------------------------------- +const ORowSetValue& ORowSetBase::impl_getValue(sal_Int32 columnIndex) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::impl_getValue" ); + if ( m_bBeforeFirst || m_bAfterLast ) + { + OSL_ENSURE(0,"ORowSetBase::getValue: Illegal call here (we're before first or after last)!"); + ::dbtools::throwSQLException( DBACORE_RESSTRING( RID_STR_CURSOR_BEFORE_OR_AFTER ), SQL_INVALID_CURSOR_POSITION, *m_pMySelf ); + } + + if ( impl_rowDeleted() ) + { + return m_aEmptyValue; + } + + bool bValidCurrentRow = ( !m_aCurrentRow.isNull() && m_aCurrentRow != m_pCache->getEnd() && m_aCurrentRow->isValid() ); + if ( !bValidCurrentRow ) + { + // currentrow is null when the clone moves the window + positionCache( MOVE_NONE_REFRESH_ONLY ); + m_aCurrentRow = m_pCache->m_aMatrixIter; + OSL_ENSURE(!m_aCurrentRow.isNull(),"ORowSetBase::getValue: we don't stand on a valid row! Row is null."); + + bValidCurrentRow = ( !m_aCurrentRow.isNull() && m_aCurrentRow != m_pCache->getEnd() && m_aCurrentRow->isValid() ); + } + + if ( bValidCurrentRow ) + { +#if OSL_DEBUG_LEVEL > 0 + ORowSetMatrix::iterator aCacheEnd; + ORowSetMatrix::iterator aCurrentRow; + aCacheEnd = m_pCache->getEnd(); + aCurrentRow = m_aCurrentRow; + ORowSetCacheMap::iterator aCacheIter = m_aCurrentRow.getIter(); + sal_Int32 n = aCacheIter->first; + n = n; + ORowSetCacheIterator_Helper aHelper = aCacheIter->second; + ORowSetMatrix::iterator k = aHelper.aIterator; + for (; k != m_pCache->getEnd(); ++k) + { + ORowSetValueVector* pTemp = k->getBodyPtr(); + OSL_ENSURE( pTemp != (void*)0xfeeefeee,"HALT!" ); + } +#endif + OSL_ENSURE(!m_aCurrentRow.isNull() && m_aCurrentRow < m_pCache->getEnd() && aCacheIter != m_pCache->m_aCacheIterators.end(),"Invalid iterator set for currentrow!"); +#if OSL_DEBUG_LEVEL > 0 + ORowSetRow rRow = (*m_aCurrentRow); + OSL_ENSURE(rRow.isValid() && static_cast<sal_uInt16>(columnIndex) < (rRow->get()).size(),"Invalid size of vector!"); +#endif + return ((*m_aCurrentRow)->get())[m_nLastColumnIndex = columnIndex]; + } + + // we should normally never reach this + return m_aEmptyValue; +} +// ------------------------------------------------------------------------- +::rtl::OUString SAL_CALL ORowSetBase::getString( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::getString" ); + ::osl::MutexGuard aGuard( *m_pMutex ); + return getValue(columnIndex); +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL ORowSetBase::getBoolean( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::getBoolean" ); + ::osl::MutexGuard aGuard( *m_pMutex ); + return getValue(columnIndex); +} +// ------------------------------------------------------------------------- +sal_Int8 SAL_CALL ORowSetBase::getByte( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::getByte" ); + ::osl::MutexGuard aGuard( *m_pMutex ); + return getValue(columnIndex); +} +// ------------------------------------------------------------------------- +sal_Int16 SAL_CALL ORowSetBase::getShort( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::getShort" ); + ::osl::MutexGuard aGuard( *m_pMutex ); + return getValue(columnIndex); +} +// ------------------------------------------------------------------------- +sal_Int32 SAL_CALL ORowSetBase::getInt( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::getInt" ); + ::osl::MutexGuard aGuard( *m_pMutex ); + return getValue(columnIndex); +} +// ------------------------------------------------------------------------- +sal_Int64 SAL_CALL ORowSetBase::getLong( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::getLong" ); + ::osl::MutexGuard aGuard( *m_pMutex ); + return getValue(columnIndex); +} +// ------------------------------------------------------------------------- +float SAL_CALL ORowSetBase::getFloat( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::getFloat" ); + ::osl::MutexGuard aGuard( *m_pMutex ); + return getValue(columnIndex); +} +// ------------------------------------------------------------------------- +double SAL_CALL ORowSetBase::getDouble( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::getDouble" ); + ::osl::MutexGuard aGuard( *m_pMutex ); + return getValue(columnIndex); +} +// ------------------------------------------------------------------------- +Sequence< sal_Int8 > SAL_CALL ORowSetBase::getBytes( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::getBytes" ); + ::osl::MutexGuard aGuard( *m_pMutex ); + return getValue(columnIndex); +} +// ------------------------------------------------------------------------- +::com::sun::star::util::Date SAL_CALL ORowSetBase::getDate( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::getDate" ); + ::osl::MutexGuard aGuard( *m_pMutex ); + return getValue(columnIndex); +} +// ------------------------------------------------------------------------- +::com::sun::star::util::Time SAL_CALL ORowSetBase::getTime( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::getTime" ); + ::osl::MutexGuard aGuard( *m_pMutex ); + return getValue(columnIndex); +} +// ------------------------------------------------------------------------- +::com::sun::star::util::DateTime SAL_CALL ORowSetBase::getTimestamp( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::getTimestamp" ); + ::osl::MutexGuard aGuard( *m_pMutex ); + return getValue(columnIndex); +} +// ------------------------------------------------------------------------- +Reference< ::com::sun::star::io::XInputStream > SAL_CALL ORowSetBase::getBinaryStream( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::getBinaryStream" ); + ::osl::MutexGuard aGuard( *m_pMutex ); + checkCache(); + + if ( m_bBeforeFirst || m_bAfterLast ) + { + OSL_ENSURE(0,"ORowSetBase::getBinaryStream: Illegal call here (we're before first or after last)!"); + ::dbtools::throwSQLException( DBACORE_RESSTRING( RID_STR_CURSOR_BEFORE_OR_AFTER ), SQL_INVALID_CURSOR_POSITION, *m_pMySelf ); + } + + if ( impl_rowDeleted() ) + { + return NULL; + } + + bool bValidCurrentRow = ( !m_aCurrentRow.isNull() && m_aCurrentRow != m_pCache->getEnd() && m_aCurrentRow->isValid() ); + if ( !bValidCurrentRow ) + { + positionCache( MOVE_NONE_REFRESH_ONLY ); + m_aCurrentRow = m_pCache->m_aMatrixIter; + OSL_ENSURE(!m_aCurrentRow.isNull(),"ORowSetBase::getBinaryStream: we don't stand on a valid row! Row is null."); + + bValidCurrentRow = ( !m_aCurrentRow.isNull() && m_aCurrentRow != m_pCache->getEnd() && m_aCurrentRow->isValid() ); + } + + if ( bValidCurrentRow ) + return new ::comphelper::SequenceInputStream(((*m_aCurrentRow)->get())[m_nLastColumnIndex = columnIndex].getSequence()); + + // we should normally never reach this + return Reference< ::com::sun::star::io::XInputStream >(); +} +// ------------------------------------------------------------------------- +Reference< ::com::sun::star::io::XInputStream > SAL_CALL ORowSetBase::getCharacterStream( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::getCharacterStream" ); + return getBinaryStream(columnIndex); +} +// ------------------------------------------------------------------------- +Any SAL_CALL ORowSetBase::getObject( sal_Int32 columnIndex, const Reference< XNameAccess >& /*typeMap*/ ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::getObject" ); + ::osl::MutexGuard aGuard( *m_pMutex ); + checkCache(); + + return getValue(columnIndex).makeAny(); +} +// ------------------------------------------------------------------------- +Reference< XRef > SAL_CALL ORowSetBase::getRef( sal_Int32 /*columnIndex*/ ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::getRef" ); + ::dbtools::throwFeatureNotImplementedException( "XRow::getRef", *m_pMySelf ); + return NULL; +} +// ------------------------------------------------------------------------- +Reference< XBlob > SAL_CALL ORowSetBase::getBlob( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::getBlob" ); + return Reference< XBlob >(getValue(columnIndex).makeAny(),UNO_QUERY); +} +// ------------------------------------------------------------------------- +Reference< XClob > SAL_CALL ORowSetBase::getClob( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::getClob" ); + return Reference< XClob >(getValue(columnIndex).makeAny(),UNO_QUERY); +} +// ------------------------------------------------------------------------- +Reference< XArray > SAL_CALL ORowSetBase::getArray( sal_Int32 /*columnIndex*/ ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::getArray" ); + ::dbtools::throwFeatureNotImplementedException( "XRow::getArray", *m_pMySelf ); + return NULL; +} +// ------------------------------------------------------------------------- +// ::com::sun::star::sdbcx::XRowLocate +Any SAL_CALL ORowSetBase::getBookmark( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::getBookmark" ); + DBG_TRACE2("DBACCESS ORowSetBase::getBookmark() Clone = %i ID = %i\n",m_bClone,osl_getThreadIdentifier(NULL)); + ::connectivity::checkDisposed(m_rBHelper.bDisposed); + ::osl::MutexGuard aGuard( *m_pMutex ); + checkCache(); + + if ( m_bBeforeFirst || m_bAfterLast ) + ::dbtools::throwSQLException( DBACORE_RESSTRING( RID_STR_NO_BOOKMARK_BEFORE_OR_AFTER ), SQL_INVALID_CURSOR_POSITION, *m_pMySelf ); + + if ( impl_rowDeleted() ) + ::dbtools::throwSQLException( DBACORE_RESSTRING( RID_STR_NO_BOOKMARK_DELETED ), SQL_INVALID_CURSOR_POSITION, *m_pMySelf ); + + OSL_ENSURE( m_aBookmark.hasValue(), "ORowSetBase::getBookmark: bookmark has no value!" ); + return m_aBookmark; +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL ORowSetBase::moveToBookmark( const Any& bookmark ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::moveToBookmark" ); + DBG_TRACE2("DBACCESS ORowSetBase::moveToBookmark(Any) Clone = %i ID = %i\n",m_bClone,osl_getThreadIdentifier(NULL)); + OSL_ENSURE(bookmark.hasValue(),"ORowSetBase::moveToBookmark bookmark has no value!"); + ::osl::ResettableMutexGuard aGuard( *m_pMutex ); + + if(!bookmark.hasValue() || m_nResultSetType == ResultSetType::FORWARD_ONLY) + { + if(bookmark.hasValue()) + OSL_ENSURE(0,"MoveToBookmark is not possible when we are only forward"); + else + OSL_ENSURE(0,"Bookmark is not valid"); + throwFunctionSequenceException(*m_pMySelf); + } + + + checkCache(); + + sal_Bool bRet( notifyAllListenersCursorBeforeMove( aGuard ) ); + if ( bRet ) + { + // check if we are inserting a row + sal_Bool bWasNew = m_pCache->m_bNew || impl_rowDeleted(); + + ORowSetNotifier aNotifier( this ); + // this will call cancelRowModification on the cache if necessary + + ORowSetRow aOldValues = getOldRow(bWasNew); + + bRet = m_pCache->moveToBookmark(bookmark); + doCancelModification( ); + if(bRet) + { + // notification order + // - column values + // - cursorMoved + setCurrentRow( sal_True, sal_True, aOldValues, aGuard ); + } + else + { + movementFailed(); + } + + // - IsModified + // - IsNew + aNotifier.fire( ); + } + DBG_TRACE2("DBACCESS ORowSetBase::moveToBookmark(Any) = %i Clone = %i\n",bRet,m_bClone); + return bRet; +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL ORowSetBase::moveRelativeToBookmark( const Any& bookmark, sal_Int32 rows ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::moveRelativeToBookmark" ); + DBG_TRACE2("DBACCESS ORowSetBase::moveRelativeToBookmark(Any,%i) Clone = %i\n",rows,m_bClone); + ::connectivity::checkDisposed(m_rBHelper.bDisposed); + + ::osl::ResettableMutexGuard aGuard( *m_pMutex ); + + checkPositioningAllowed(); + + sal_Bool bRet( notifyAllListenersCursorBeforeMove( aGuard ) ); + if ( bRet ) + { + // check if we are inserting a row + sal_Bool bWasNew = m_pCache->m_bNew || rowDeleted(); + + ORowSetNotifier aNotifier( this ); + // this will call cancelRowModification on the cache if necessary + + ORowSetRow aOldValues = getOldRow(bWasNew); + + bRet = m_pCache->moveRelativeToBookmark(bookmark,rows); + doCancelModification( ); + if(bRet) + { + // notification order + // - column values + // - cursorMoved + setCurrentRow( sal_True, sal_True, aOldValues, aGuard ); + } + else + movementFailed(); + + // - IsModified + // - IsNew + aNotifier.fire( ); + + // RowCount/IsRowCountFinal + fireRowcount(); + } + DBG_TRACE3("DBACCESS ORowSetBase::moveRelativeToBookmark(Any,%i) = %i Clone = %i\n",rows,bRet,m_bClone); + return bRet; +} +// ------------------------------------------------------------------------- +sal_Int32 SAL_CALL ORowSetBase::compareBookmarks( const Any& _first, const Any& _second ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::compareBookmarks" ); + ::osl::MutexGuard aGuard( *m_pMutex ); + checkCache(); + return m_pCache->compareBookmarks(_first,_second); +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL ORowSetBase::hasOrderedBookmarks( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::hasOrderedBookmarks" ); + ::osl::MutexGuard aGuard( *m_pMutex ); + checkCache(); + return m_pCache->hasOrderedBookmarks(); +} +// ------------------------------------------------------------------------- +sal_Int32 SAL_CALL ORowSetBase::hashBookmark( const Any& bookmark ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::hashBookmark" ); + ::osl::MutexGuard aGuard( *m_pMutex ); + checkCache(); + return m_pCache->hashBookmark(bookmark); +} +// ------------------------------------------------------------------------- +// ------------------------------------------------------------------------- +// XResultSetMetaDataSupplier +Reference< XResultSetMetaData > SAL_CALL ORowSetBase::getMetaData( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::getMetaData" ); + ::connectivity::checkDisposed(m_rBHelper.bDisposed); + + Reference< XResultSetMetaData > xMeta; + if(m_pCache) + xMeta = m_pCache->getMetaData(); + + return xMeta; +} +// ------------------------------------------------------------------------- + +// XColumnLocate +sal_Int32 SAL_CALL ORowSetBase::findColumn( const ::rtl::OUString& columnName ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::findColumn" ); + ::connectivity::checkDisposed(m_rBHelper.bDisposed); + + ::osl::MutexGuard aGuard( m_aColumnsMutex ); + // it is possible to save some time her when we remember the names - position relation in a map + return m_pColumns ? m_pColumns->findColumn(columnName) : sal_Int32(0); +} +// ------------------------------------------------------------------------- + +// ::com::sun::star::sdbcx::XColumnsSupplier +Reference< XNameAccess > SAL_CALL ORowSetBase::getColumns( ) throw(RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::getColumns" ); + ::connectivity::checkDisposed(m_rBHelper.bDisposed); + + ::osl::MutexGuard aGuard( m_aColumnsMutex ); + if(!m_pColumns) + { + if (!m_pEmptyCollection) + m_pEmptyCollection = new OEmptyCollection(*m_pMySelf,m_aColumnsMutex); + return m_pEmptyCollection; + } + + return m_pColumns; +} +// ------------------------------------------------------------------------- +// XResultSet +sal_Bool SAL_CALL ORowSetBase::next( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::next" ); + DBG_TRACE2("DBACCESS ORowSetBase::next() Clone = %i ID = %i\n",m_bClone,osl_getThreadIdentifier(NULL)); + ::osl::ResettableMutexGuard aGuard( *m_pMutex ); + checkCache(); + + sal_Bool bRet( notifyAllListenersCursorBeforeMove( aGuard ) ); + if ( bRet ) + { + // check if we are inserting a row + sal_Bool bWasNew = m_pCache->m_bNew || impl_rowDeleted(); + + ORowSetNotifier aNotifier( this ); + // this will call cancelRowModification on the cache if necessary + + ORowSetRow aOldValues = getOldRow(bWasNew); + + positionCache( MOVE_FORWARD ); + sal_Bool bAfterLast = m_pCache->isAfterLast(); + bRet = m_pCache->next(); + doCancelModification( ); + + + if ( bRet || bAfterLast != m_pCache->isAfterLast() ) + { + // notification order + // - column values + // - cursorMoved + setCurrentRow( bRet, sal_True, aOldValues, aGuard ); + OSL_ENSURE(!m_bBeforeFirst,"BeforeFirst is true. I don't know why?"); + } + else + { + // moved after the last row + movementFailed(); + OSL_ENSURE(m_bAfterLast,"AfterLast is false. I don't know why?"); + } + + // - IsModified + // - IsNew + aNotifier.fire(); + + // - RowCount/IsRowCountFinal + fireRowcount(); + } + DBG_TRACE3("DBACCESS ORowSetBase::next() = %i Clone = %i ID = %i\n",bRet,m_bClone,osl_getThreadIdentifier(NULL)); + return bRet; +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL ORowSetBase::isBeforeFirst( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::isBeforeFirst" ); + ::connectivity::checkDisposed(m_rBHelper.bDisposed); + ::osl::MutexGuard aGuard( *m_pMutex ); + checkCache(); + + DBG_TRACE2("DBACCESS ORowSetBase::isBeforeFirst() = %i Clone = %i\n",m_bBeforeFirst,m_bClone); + + return m_bBeforeFirst; +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL ORowSetBase::isAfterLast( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::isAfterLast" ); + ::connectivity::checkDisposed(m_rBHelper.bDisposed); + ::osl::MutexGuard aGuard( *m_pMutex ); + checkCache(); + DBG_TRACE2("DBACCESS ORowSetBase::isAfterLast() = %i Clone = %i\n",m_bAfterLast,m_bClone); + + return m_bAfterLast; +} +// ------------------------------------------------------------------------- +sal_Bool ORowSetBase::isOnFirst() +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::isOnFirst" ); + return isFirst(); +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL ORowSetBase::isFirst( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::isFirst" ); + DBG_TRACE2("DBACCESS ORowSetBase::isFirst() Clone = %i ID = %i\n",m_bClone,osl_getThreadIdentifier(NULL)); + + ::connectivity::checkDisposed(m_rBHelper.bDisposed); + ::osl::MutexGuard aGuard( *m_pMutex ); + checkCache(); + + if ( m_bBeforeFirst || m_bAfterLast ) + return sal_False; + + if ( impl_rowDeleted() ) + return ( m_nDeletedPosition == 1 ); + + positionCache( MOVE_NONE_REFRESH_ONLY ); + sal_Bool bIsFirst = m_pCache->isFirst(); + + DBG_TRACE2("DBACCESS ORowSetBase::isFirst() = %i Clone = %i\n",bIsFirst,m_bClone); + return bIsFirst; +} +// ------------------------------------------------------------------------- +sal_Bool ORowSetBase::isOnLast() +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::isOnLast" ); + return isLast(); +} +// ----------------------------------------------------------------------------- +sal_Bool SAL_CALL ORowSetBase::isLast( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::isLast" ); + DBG_TRACE2("DBACCESS ORowSetBase::isLast() Clone = %i ID = %i\n",m_bClone,osl_getThreadIdentifier(NULL)); + ::connectivity::checkDisposed(m_rBHelper.bDisposed); + ::osl::MutexGuard aGuard( *m_pMutex ); + checkCache(); + + if ( m_bBeforeFirst || m_bAfterLast ) + return sal_False; + + if ( impl_rowDeleted() ) + { + if ( !m_pCache->m_bRowCountFinal ) + return sal_False; + else + return ( m_nDeletedPosition == impl_getRowCount() ); + } + + positionCache( MOVE_NONE_REFRESH_ONLY ); + sal_Bool bIsLast = m_pCache->isLast(); + + DBG_TRACE2("DBACCESS ORowSetBase::isLast() = %i Clone = %i\n",bIsLast,m_bClone); + return bIsLast; +} +// ------------------------------------------------------------------------- +void SAL_CALL ORowSetBase::beforeFirst( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::beforeFirst" ); + DBG_TRACE2("DBACCESS ORowSetBase::beforeFirst() Clone = %i ID = %i\n",m_bClone,osl_getThreadIdentifier(NULL)); + ::connectivity::checkDisposed(m_rBHelper.bDisposed); + ::osl::ResettableMutexGuard aGuard( *m_pMutex ); + + checkPositioningAllowed(); + + // check if we are inserting a row + sal_Bool bWasNew = m_pCache->m_bNew || impl_rowDeleted(); + + if((bWasNew || !m_bBeforeFirst) && notifyAllListenersCursorBeforeMove(aGuard) ) + { + ORowSetNotifier aNotifier( this ); + // this will call cancelRowModification on the cache if necessary + + if ( !m_bBeforeFirst ) + { + ORowSetRow aOldValues = getOldRow(bWasNew); + m_pCache->beforeFirst(); + doCancelModification( ); + + // notification order + // - column values + // - cursorMoved + setCurrentRow( sal_True, sal_True, aOldValues, aGuard ); + + // - IsModified + // - Isnew + aNotifier.fire(); + + // - RowCount/IsRowCountFinal + fireRowcount(); + } + + // to be done _after_ the notifications! + m_aOldRow->clearRow(); + } + DBG_TRACE2("DBACCESS ORowSetBase::beforeFirst() Clone = %i ID = %i\n",m_bClone,osl_getThreadIdentifier(NULL)); +} +// ------------------------------------------------------------------------- +void SAL_CALL ORowSetBase::afterLast( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::afterLast" ); + DBG_TRACE2("DBACCESS ORowSetBase::afterLast() Clone = %i ID = %i\n",m_bClone,osl_getThreadIdentifier(NULL)); + ::connectivity::checkDisposed(m_rBHelper.bDisposed); + + ::osl::ResettableMutexGuard aGuard( *m_pMutex ); + checkPositioningAllowed(); + + sal_Bool bWasNew = m_pCache->m_bNew || impl_rowDeleted(); + + if((bWasNew || !m_bAfterLast) && notifyAllListenersCursorBeforeMove(aGuard) ) + { + // check if we are inserting a row + ORowSetNotifier aNotifier( this ); + // this will call cancelRowModification on the cache if necessary + + if(!m_bAfterLast) + { + ORowSetRow aOldValues = getOldRow(bWasNew); + + m_pCache->afterLast(); + doCancelModification( ); + + // notification order + // - column values + // - cursorMoved + setCurrentRow( sal_True, sal_True, aOldValues, aGuard ); + + // - IsModified + // - Isnew + aNotifier.fire(); + + // - RowCount/IsRowCountFinal + fireRowcount(); + } + } + DBG_TRACE2("DBACCESS ORowSetBase::afterLast() Clone = %i ID = %i\n",m_bClone,osl_getThreadIdentifier(NULL)); +} +// ----------------------------------------------------------------------------- +sal_Bool SAL_CALL ORowSetBase::move( ::std::mem_fun_t<sal_Bool,ORowSetBase>& _aCheckFunctor, + ::std::mem_fun_t<sal_Bool,ORowSetCache>& _aMovementFunctor) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::move" ); + DBG_TRACE2("DBACCESS ORowSetBase::move() Clone = %i ID = %i\n",m_bClone,osl_getThreadIdentifier(NULL)); + ::connectivity::checkDisposed(m_rBHelper.bDisposed); + ::osl::ResettableMutexGuard aGuard( *m_pMutex ); + checkPositioningAllowed(); + + sal_Bool bRet( notifyAllListenersCursorBeforeMove( aGuard ) ); + if( bRet ) + { + // check if we are inserting a row + sal_Bool bWasNew = m_pCache->m_bNew || rowDeleted(); + + ORowSetNotifier aNotifier( this ); + // this will call cancelRowModification on the cache if necessary + + ORowSetRow aOldValues = getOldRow(bWasNew); + + sal_Bool bMoved = ( bWasNew || !_aCheckFunctor(this) ); + + bRet = _aMovementFunctor(m_pCache); + doCancelModification( ); + + if ( bRet ) + { + // notification order + // - column values + // - cursorMoved + setCurrentRow( bMoved, sal_True, aOldValues, aGuard ); + } + else + { // first goes wrong so there is no row + movementFailed(); + } + + // - IsModified + // - IsNew + aNotifier.fire(); + + // - RowCount/IsRowCountFinal + fireRowcount(); + } + DBG_TRACE2("DBACCESS ORowSetBase::move() = %i Clone = %i\n",bRet,m_bClone); + return bRet; +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL ORowSetBase::first( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::first" ); + DBG_TRACE2("DBACCESS ORowSetBase::first() Clone = %i ID = %i\n",m_bClone,osl_getThreadIdentifier(NULL)); + ::std::mem_fun_t<sal_Bool,ORowSetBase> ioF_tmp(&ORowSetBase::isOnFirst); + ::std::mem_fun_t<sal_Bool,ORowSetCache> F_tmp(&ORowSetCache::first); + return move(ioF_tmp,F_tmp); +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL ORowSetBase::last( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::last" ); + DBG_TRACE2("DBACCESS ORowSetBase::last() Clone = %i ID = %i\n",m_bClone,osl_getThreadIdentifier(NULL)); + ::std::mem_fun_t<sal_Bool,ORowSetBase> ioL_tmp(&ORowSetBase::isOnLast); + ::std::mem_fun_t<sal_Bool,ORowSetCache> L_tmp(&ORowSetCache::last); + return move(ioL_tmp,L_tmp); +} +// ------------------------------------------------------------------------- +sal_Int32 SAL_CALL ORowSetBase::getRow( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::getRow" ); + DBG_TRACE2("DBACCESS ORowSetBase::getRow() Clone = %i ID = %i\n",m_bClone,osl_getThreadIdentifier(NULL)); + ::osl::MutexGuard aGuard( *m_pMutex ); + + checkCache(); + return impl_getRow(); +} +// ------------------------------------------------------------------------- +sal_Int32 ORowSetBase::impl_getRow() +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::impl_getRow" ); + sal_Int32 nPos = 0; + if ( m_bBeforeFirst ) + nPos = 0; + else if ( m_bAfterLast ) + nPos = impl_getRowCount() + 1; + else if ( impl_rowDeleted() ) + nPos = m_nDeletedPosition; + else if ( !m_bClone && m_pCache->m_bNew ) + nPos = 0; + else + { + if ( m_pCache->isAfterLast() + || m_pCache->isBeforeFirst() + || ( m_pCache->compareBookmarks( m_aBookmark, m_pCache->getBookmark() ) != CompareBookmark::EQUAL ) + ) + { + positionCache( MOVE_NONE_REFRESH_ONLY ); + } + nPos = m_pCache->getRow(); + } + DBG_TRACE3("DBACCESS ORowSetBase::impl_getRow() = %i Clone = %i ID = %i\n",nPos,m_bClone,osl_getThreadIdentifier(NULL)); + return nPos; +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL ORowSetBase::absolute( sal_Int32 row ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::absolute" ); + DBG_TRACE2("DBACCESS ORowSetBase::absolute(%i) Clone = %i\n",row,m_bClone); + ::connectivity::checkDisposed(m_rBHelper.bDisposed); + ::osl::ResettableMutexGuard aGuard( *m_pMutex ); + checkPositioningAllowed(); + + sal_Bool bRet = ( row > 0 ) + && notifyAllListenersCursorBeforeMove( aGuard ); + if ( bRet ) + { + // check if we are inserting a row + sal_Bool bWasNew = m_pCache->m_bNew || rowDeleted(); + + ORowSetNotifier aNotifier( this ); + // this will call cancelRowModification on the cache if necessary + + ORowSetRow aOldValues = getOldRow(bWasNew); + + bRet = m_pCache->absolute(row); + doCancelModification( ); + + if(bRet) + { + // notification order + // - column values + // - cursorMoved + setCurrentRow( sal_True, sal_True, aOldValues, aGuard ); + } + else + { // absolute movement goes wrong we stand left or right side of the rows + movementFailed(); + } + + // - IsModified + // - IsNew + aNotifier.fire(); + + // - RowCount/IsRowCountFinal + fireRowcount(); + } + DBG_TRACE3("DBACCESS ORowSetBase::absolute(%i) = %i Clone = %i\n",row,bRet,m_bClone); + return bRet; +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL ORowSetBase::relative( sal_Int32 rows ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::relative" ); + DBG_TRACE2("DBACCESS ORowSetBase::relative(%i) Clone = %i\n",rows,m_bClone); + ::connectivity::checkDisposed(m_rBHelper.bDisposed); + + ::osl::ResettableMutexGuard aGuard( *m_pMutex ); + + if(!rows) + return sal_True; // in this case do nothing + + checkPositioningAllowed(); + + sal_Bool bRet = + ( ( !m_bAfterLast || rows <= 0 ) + && ( !m_bBeforeFirst || rows >= 0 ) + && notifyAllListenersCursorBeforeMove( aGuard ) + ); + + if ( bRet ) + { + // check if we are inserting a row + sal_Bool bWasNew = m_pCache->m_bNew || rowDeleted(); + + ORowSetNotifier aNotifier( this ); + // this will call cancelRowModification on the cache if necessary + + ORowSetRow aOldValues = getOldRow(bWasNew); + + positionCache( rows > 0 ? MOVE_FORWARD : MOVE_BACKWARD ); + bRet = m_pCache->relative(rows); + doCancelModification( ); + + if(bRet) + { + // notification order + // - column values + // - cursorMoved + setCurrentRow( sal_True, sal_True, aOldValues, aGuard ); + } + else + { + movementFailed(); + } + + // - IsModified + // - IsNew + aNotifier.fire(); + + // - RowCount/IsRowCountFinal + fireRowcount(); + } + DBG_TRACE3("DBACCESS ORowSetBase::relative(%i) = %i Clone = %i\n",rows,bRet,m_bClone); + return bRet; +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL ORowSetBase::previous( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::previous" ); + DBG_TRACE2("DBACCESS ORowSetBase::previous() Clone = %i ID = %i\n",m_bClone,osl_getThreadIdentifier(NULL)); + ::connectivity::checkDisposed(m_rBHelper.bDisposed); + ::osl::ResettableMutexGuard aGuard( *m_pMutex ); + + checkPositioningAllowed(); + + sal_Bool bRet = !m_bBeforeFirst + && notifyAllListenersCursorBeforeMove(aGuard); + + if ( bRet ) + { + // check if we are inserting a row + sal_Bool bWasNew = m_pCache->m_bNew || rowDeleted(); + + ORowSetNotifier aNotifier( this ); + // this will call cancelRowModification on the cache if necessary + + ORowSetRow aOldValues = getOldRow(bWasNew); + + positionCache( MOVE_BACKWARD ); + bRet = m_pCache->previous(); + doCancelModification( ); + + // if m_bBeforeFirst is false and bRet is false than we stood on the first row + if(!m_bBeforeFirst || bRet) + { + // notification order + // - column values + // - cursorMoved + setCurrentRow( sal_True, sal_True, aOldValues, aGuard ); + } + else + { + DBG_ERROR( "ORowSetBase::previous: inconsistency!" ); + // we should never reach this place, as we should not get into this whole branch if m_bBeforeFirst + // was |true| from the beginning + movementFailed(); + } + + // - IsModified + // - IsNew + aNotifier.fire(); + + // - RowCount/IsRowCountFinal + fireRowcount(); + } + DBG_TRACE2("DBACCESS ORowSetBase::previous() = %i Clone = %i\n",bRet,m_bClone); + return bRet; +} +// ----------------------------------------------------------------------------- +void ORowSetBase::setCurrentRow( sal_Bool _bMoved, sal_Bool _bDoNotify, const ORowSetRow& _rOldValues, ::osl::ResettableMutexGuard& _rGuard ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::setCurrentRow" ); + DBG_TRACE2("DBACCESS ORowSetBase::setCurrentRow() Clone = %i ID = %i\n",m_bClone,osl_getThreadIdentifier(NULL)); + m_bBeforeFirst = m_pCache->isBeforeFirst(); + m_bAfterLast = m_pCache->isAfterLast(); + //m_pCache->resetInsertRow(sal_True); + + if(!(m_bBeforeFirst || m_bAfterLast)) + { + m_aBookmark = m_pCache->getBookmark(); + OSL_ENSURE(m_aBookmark.hasValue(),"Bookmark has no value!"); + m_aCurrentRow = m_pCache->m_aMatrixIter; + OSL_ENSURE(!m_aCurrentRow.isNull(),"CurrentRow is null!"); + m_aCurrentRow.setBookmark(m_aBookmark); + OSL_ENSURE(!m_aCurrentRow.isNull() && m_aCurrentRow != m_pCache->getEnd(),"Position of matrix iterator isn't valid!"); + OSL_ENSURE(m_aCurrentRow->isValid(),"Currentrow isn't valid"); + OSL_ENSURE(m_aBookmark.hasValue(),"Bookmark has no value!"); + +#if OSL_DEBUG_LEVEL > 0 + sal_Int32 nOldRow = m_pCache->getRow(); +#endif + positionCache( MOVE_NONE_REFRESH_ONLY ); +#if OSL_DEBUG_LEVEL > 0 + sal_Int32 nNewRow = m_pCache->getRow(); +#endif + OSL_ENSURE(nOldRow == nNewRow,"Old position is not equal to new postion"); + m_aCurrentRow = m_pCache->m_aMatrixIter; + OSL_ENSURE(!m_aCurrentRow.isNull(),"CurrentRow is nul after positionCache!"); +#if OSL_DEBUG_LEVEL > 0 + ORowSetRow rRow = (*m_aCurrentRow); + OSL_ENSURE(rRow.isValid() ,"Invalid size of vector!"); +#endif + // the cache could repositioned so we need to adjust the cache + // #104144# OJ + if ( _bMoved && m_aCurrentRow.isNull() ) + { + positionCache( MOVE_NONE_REFRESH_ONLY ); + m_aCurrentRow = m_pCache->m_aMatrixIter; + OSL_ENSURE(!m_aCurrentRow.isNull(),"CurrentRow is nul after positionCache!"); + } + } + else + { + m_aOldRow->clearRow(); + m_aCurrentRow = m_pCache->getEnd(); + m_aBookmark = Any(); + m_aCurrentRow.setBookmark(m_aBookmark); + } + + // notification order + // - column values + if ( _bDoNotify ) + firePropertyChange(_rOldValues); + + // TODO: can this be done before the notifications? + if(!(m_bBeforeFirst || m_bAfterLast) && !m_aCurrentRow.isNull() && m_aCurrentRow->isValid() && m_aCurrentRow != m_pCache->getEnd()) + m_aOldRow->setRow(new ORowSetValueVector(m_aCurrentRow->getBody())); + + if ( _bMoved && _bDoNotify ) + // - cursorMoved + notifyAllListenersCursorMoved( _rGuard ); + + DBG_TRACE2("DBACCESS ORowSetBase::setCurrentRow() Clone = %i ID = %i\n",m_bClone,osl_getThreadIdentifier(NULL)); +} +// ----------------------------------------------------------------------------- +void ORowSetBase::checkPositioningAllowed() throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::checkPositioningAllowed" ); + if(!m_pCache || m_nResultSetType == ResultSetType::FORWARD_ONLY) + throwFunctionSequenceException(*m_pMySelf); +} +//------------------------------------------------------------------------------ +Reference< XInterface > ORowSetBase::getStatement(void) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::getStatement" ); + return NULL; +} +// ------------------------------------------------------------------------- +void SAL_CALL ORowSetBase::refreshRow( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::refreshRow" ); + ::connectivity::checkDisposed(m_rBHelper.bDisposed); + ::osl::MutexGuard aGuard( *m_pMutex ); + checkCache(); + if ( impl_rowDeleted() ) + throwSQLException( "The current row is deleted", SQL_INVALID_CURSOR_STATE, Reference< XRowSet >( this ) ); + + if(!(m_bBeforeFirst || m_bAfterLast)) + { + positionCache( MOVE_NONE_REFRESH_ONLY ); + m_pCache->refreshRow(); + } +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL ORowSetBase::rowUpdated( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::rowUpdated" ); + ::osl::MutexGuard aGuard( *m_pMutex ); + checkCache(); + + if ( impl_rowDeleted() ) + return sal_False; + + return m_pCache->rowUpdated(); +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL ORowSetBase::rowInserted( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::rowInserted" ); + ::osl::MutexGuard aGuard( *m_pMutex ); + + checkCache(); + + if ( impl_rowDeleted() ) + return sal_False; + + return m_pCache->rowInserted(); +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL ORowSetBase::rowDeleted( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::rowDeleted" ); + ::osl::MutexGuard aGuard( *m_pMutex ); + checkCache(); + return impl_rowDeleted(); +} +// ------------------------------------------------------------------------- +sal_Bool ORowSetBase::impl_rowDeleted( ) +{ + return !m_aBookmark.hasValue() && !m_bBeforeFirst && !m_bAfterLast; +} +// ------------------------------------------------------------------------- +// XWarningsSupplier +Any SAL_CALL ORowSetBase::getWarnings( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::getWarnings" ); + ::osl::MutexGuard aGuard( *m_pMutex ); + + if ( m_pCache ) + { + Reference< XWarningsSupplier > xWarnings( m_pCache->m_xSet.get(), UNO_QUERY ); + if ( xWarnings.is() ) + return xWarnings->getWarnings(); + } + + return Any(); +} +// ------------------------------------------------------------------------- +void SAL_CALL ORowSetBase::clearWarnings( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::clearWarnings" ); + ::osl::MutexGuard aGuard( *m_pMutex ); + + if ( m_pCache ) + { + Reference< XWarningsSupplier > xWarnings( m_pCache->m_xSet.get(), UNO_QUERY ); + if ( xWarnings.is() ) + xWarnings->clearWarnings(); + } +} +// ------------------------------------------------------------------------- +void ORowSetBase::firePropertyChange(const ORowSetRow& _rOldRow) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::firePropertyChange" ); + DBG_TRACE2("DBACCESS ORowSetBase::firePropertyChange() Clone = %i ID = %i\n",m_bClone,osl_getThreadIdentifier(NULL)); + OSL_ENSURE(m_pColumns,"Columns can not be NULL here!"); +#if OSL_DEBUG_LEVEL > 1 + sal_Bool bNull; + ORowSetMatrix::iterator atest; + bNull = m_aCurrentRow.isNull(); + atest = m_aCurrentRow; +#endif + sal_Int32 i=0; + try + { + TDataColumns::iterator aEnd = m_aDataColumns.end(); + for(TDataColumns::iterator aIter = m_aDataColumns.begin();aIter != aEnd;++aIter,++i) // #104278# OJ ++i inserted + (*aIter)->fireValueChange(_rOldRow.isValid() ? (_rOldRow->get())[i+1] : ::connectivity::ORowSetValue()); + } + catch(Exception&) + { + OSL_ENSURE(0,"firePropertyChange: Exception"); + } + DBG_TRACE2("DBACCESS ORowSetBase::firePropertyChange() Clone = %i ID = %i\n",m_bClone,osl_getThreadIdentifier(NULL)); +} +// ------------------------------------------------------------------------- +void ORowSetBase::firePropertyChange(sal_Int32 _nPos,const ::connectivity::ORowSetValue& _rOldValue) +{ + OSL_ENSURE(_nPos < (sal_Int32)m_aDataColumns.size(),"nPos is invalid!"); + m_aDataColumns[_nPos]->fireValueChange(_rOldValue); +} +// ----------------------------------------------------------------------------- +void ORowSetBase::fireRowcount() +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::fireRowcount" ); +} + +// ----------------------------------------------------------------------------- +sal_Bool ORowSetBase::notifyAllListenersCursorBeforeMove(::osl::ResettableMutexGuard& /*_rGuard*/) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::notifyAllListenersCursorBeforeMove" ); + return sal_True; +} + +// ----------------------------------------------------------------------------- +void ORowSetBase::notifyAllListenersCursorMoved(::osl::ResettableMutexGuard& /*_rGuard*/) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::notifyAllListenersCursorMoved" ); +} + +// ----------------------------------------------------------------------------- +void ORowSetBase::notifyAllListeners(::osl::ResettableMutexGuard& /*_rGuard*/) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::notifyAllListeners" ); +} + +// ----------------------------------------------------------------------------- +void ORowSetBase::fireProperty( sal_Int32 _nProperty, sal_Bool _bNew, sal_Bool _bOld ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::fireProperty" ); + Any aNew = bool2any( _bNew ); + Any aOld = bool2any( _bOld ); + fire( &_nProperty, &aNew, &aOld, 1, sal_False ); +} + +// ----------------------------------------------------------------------------- +void ORowSetBase::positionCache( CursorMoveDirection _ePrepareForDirection ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::positionCache" ); + DBG_TRACE2("DBACCESS ORowSetBase::positionCache() Clone = %i ID = %i\n",m_bClone,osl_getThreadIdentifier(NULL)); + + sal_Bool bSuccess = sal_False; + if ( m_aBookmark.hasValue() ) + { + bSuccess = m_pCache->moveToBookmark( m_aBookmark ); + } + else + { + if ( m_bBeforeFirst ) + { + bSuccess = m_pCache->beforeFirst(); + } + else if ( m_bAfterLast ) + { + bSuccess = m_pCache->afterLast(); + } + else + { + OSL_ENSURE( m_nDeletedPosition >= 1, "ORowSetBase::positionCache: no bookmark, and no valid 'deleted position'!" ); + switch ( _ePrepareForDirection ) + { + case MOVE_FORWARD: + if ( m_nDeletedPosition > 1 ) + bSuccess = m_pCache->absolute( m_nDeletedPosition - 1 ); + else + { + m_pCache->beforeFirst(); + bSuccess = sal_True; + } + break; + + case MOVE_BACKWARD: + if ( m_pCache->m_bRowCountFinal && ( m_nDeletedPosition == impl_getRowCount() ) ) + { + m_pCache->afterLast(); + bSuccess = sal_True; + } + else + bSuccess = m_pCache->absolute( m_nDeletedPosition ); + break; + + case MOVE_NONE_REFRESH_ONLY: + bSuccess = sal_False; // will be asserted below + break; + } + } + } + OSL_ENSURE( bSuccess, "ORowSetBase::positionCache: failed!" ); + + DBG_TRACE2("DBACCESS ORowSetBase::positionCache() Clone = %i ID = %i\n",m_bClone,osl_getThreadIdentifier(NULL)); +} +// ----------------------------------------------------------------------------- +void ORowSetBase::checkCache() +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::checkCache" ); + ::connectivity::checkDisposed(m_rBHelper.bDisposed); + if(!m_pCache) + throwFunctionSequenceException(*m_pMySelf); +} +// ----------------------------------------------------------------------------- +void ORowSetBase::movementFailed() +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::movementFailed" ); + DBG_TRACE2("DBACCESS ORowSetBase::movementFailed() Clone = %i ID = %i\n",m_bClone,osl_getThreadIdentifier(NULL)); + m_aOldRow->clearRow(); + m_aCurrentRow = m_pCache->getEnd(); + m_bBeforeFirst = m_pCache->isBeforeFirst(); + m_bAfterLast = m_pCache->isAfterLast(); + m_aBookmark = Any(); + m_aCurrentRow.setBookmark(m_aBookmark); + OSL_ENSURE(m_bBeforeFirst || m_bAfterLast,"BeforeFirst or AfterLast is wrong!"); + DBG_TRACE2("DBACCESS ORowSetBase::movementFailed() Clone = %i ID = %i\n",m_bClone,osl_getThreadIdentifier(NULL)); +} +// ----------------------------------------------------------------------------- +ORowSetRow ORowSetBase::getOldRow(sal_Bool _bWasNew) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::getOldRow" ); + OSL_ENSURE(m_aOldRow.isValid(),"RowSetRowHElper isn't valid!"); + ORowSetRow aOldValues; + if ( !_bWasNew && m_aOldRow->getRow().isValid() ) + aOldValues = new ORowSetValueVector( m_aOldRow->getRow().getBody()); // remember the old values + return aOldValues; +} +// ----------------------------------------------------------------------------- +void ORowSetBase::getPropertyDefaultByHandle( sal_Int32 /*_nHandle*/, Any& _rDefault ) const +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::getPropertyDefaultByHandle" ); + _rDefault.clear(); +} +// ----------------------------------------------------------------------------- +void ORowSetBase::onDeleteRow( const Any& _rBookmark ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::onDeleteRow" ); + if ( rowDeleted() ) + // not interested in + return; + + ::osl::MutexGuard aGuard( *m_pMutex ); + //OSL_ENSURE( m_aBookmark.hasValue(), "ORowSetBase::onDeleteRow: Bookmark isn't valid!" ); + if ( compareBookmarks( _rBookmark, m_aBookmark ) == 0 ) + { + positionCache( MOVE_NONE_REFRESH_ONLY ); + m_nDeletedPosition = m_pCache->getRow(); + } +} +// ----------------------------------------------------------------------------- +void ORowSetBase::onDeletedRow( const Any& _rBookmark, sal_Int32 _nPos ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::onDeletedRow" ); + if ( rowDeleted() ) + { + // if we're a clone, and on a deleted row, and the main RowSet deleted another + // row (only the main RowSet can, clones can't), which is *before* our + // deleted position, then we have to adjust this position + if ( m_bClone && ( _nPos < m_nDeletedPosition ) ) + --m_nDeletedPosition; + return; + } + + ::osl::MutexGuard aGuard( *m_pMutex ); + if ( compareBookmarks( _rBookmark, m_aBookmark ) == 0 ) + { + m_aOldRow->clearRow(); + m_aCurrentRow = m_pCache->getEnd(); + m_aBookmark = Any(); + m_aCurrentRow.setBookmark( m_aBookmark ); + } +} +// ----------------------------------------------------------------------------- +sal_Int32 ORowSetBase::impl_getRowCount() const +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetBase::impl_getRowCount" ); + sal_Int32 nRowCount( m_pCache->m_nRowCount ); + if ( const_cast< ORowSetBase* >( this )->rowDeleted() && !m_pCache->m_bNew ) + ++nRowCount; + return nRowCount; +} +// ============================================================================= +struct ORowSetNotifierImpl +{ + ::std::vector<sal_Int32> aChangedColumns; + ::std::vector<Any> aChangedBookmarks; + ORowSetValueVector::Vector aRow; + +}; +DBG_NAME(ORowSetNotifier) +// ----------------------------------------------------------------------------- +ORowSetNotifier::ORowSetNotifier( ORowSetBase* _pRowSet ) + :m_pRowSet( _pRowSet ) + ,m_bWasNew( sal_False ) + ,m_bWasModified( sal_False ) +#ifdef DBG_UTIL + ,m_bNotifyCalled( sal_False ) +#endif +{ + DBG_CTOR(ORowSetNotifier,NULL); + + OSL_ENSURE( m_pRowSet, "ORowSetNotifier::ORowSetNotifier: invalid row set. This wil crash." ); + + // remember the "inserted" and "modified" state for later firing + m_bWasNew = m_pRowSet->isNew( ORowSetBase::GrantNotifierAccess() ); + m_bWasModified = m_pRowSet->isModified( ORowSetBase::GrantNotifierAccess() ); + + // if the row set is on the insert row, then we need to cancel this + if ( m_pRowSet->isModification( ORowSetBase::GrantNotifierAccess() ) ) + m_pRowSet->doCancelModification( ORowSetBase::GrantNotifierAccess() ); +} +// ----------------------------------------------------------------------------- +ORowSetNotifier::ORowSetNotifier( ORowSetBase* _pRowSet,const ORowSetValueVector::Vector& i_aRow ) + :m_pImpl(new ORowSetNotifierImpl) + ,m_pRowSet( _pRowSet ) + ,m_bWasNew( sal_False ) + ,m_bWasModified( sal_False ) +#ifdef DBG_UTIL + ,m_bNotifyCalled( sal_False ) +#endif +{ + DBG_CTOR(ORowSetNotifier,NULL); + + OSL_ENSURE( m_pRowSet, "ORowSetNotifier::ORowSetNotifier: invalid row set. This wil crash." ); + m_pImpl->aRow = i_aRow; // yes, create a copy to store the old values +} +// ----------------------------------------------------------------------------- +ORowSetNotifier::~ORowSetNotifier( ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetNotifier::~ORowSetNotifier" ); + DBG_DTOR(ORowSetNotifier,NULL); +} + +// ----------------------------------------------------------------------------- +void ORowSetNotifier::fire() +{ + // we're not interested in firing changes FALSE->TRUE, only TRUE->FALSE. + // (the former would be quite pathological, e.g. after a failed movement) + + if ( m_bWasModified + && ( m_bWasModified != m_pRowSet->isModified( ORowSetBase::GrantNotifierAccess() ) ) + ) + m_pRowSet->fireProperty( PROPERTY_ID_ISMODIFIED, sal_False, sal_True, ORowSetBase::GrantNotifierAccess() ); + + if ( m_bWasNew + && ( m_bWasNew != m_pRowSet->isNew( ORowSetBase::GrantNotifierAccess() ) ) + ) + m_pRowSet->fireProperty( PROPERTY_ID_ISNEW, sal_False, sal_True, ORowSetBase::GrantNotifierAccess() ); + +#ifdef DBG_UTIL + m_bNotifyCalled = sal_True; +#endif +} +// ----------------------------------------------------------------------------- +::std::vector<sal_Int32>& ORowSetNotifier::getChangedColumns() const +{ + OSL_ENSURE(m_pImpl.get(),"Illegal CTor call, use the other one!"); + return m_pImpl->aChangedColumns; +} +// ----------------------------------------------------------------------------- +::std::vector<Any>& ORowSetNotifier::getChangedBookmarks() const +{ + OSL_ENSURE(m_pImpl.get(),"Illegal CTor call, use the other one!"); + return m_pImpl->aChangedBookmarks; +} +// ----------------------------------------------------------------------------- +void ORowSetNotifier::firePropertyChange() +{ + OSL_ENSURE(m_pImpl.get(),"Illegal CTor call, use the other one!"); + if( m_pImpl.get() ) + { + ::std::vector<sal_Int32>::iterator aIter = m_pImpl->aChangedColumns.begin(); + for(;aIter != m_pImpl->aChangedColumns.end();++aIter) + { + m_pRowSet->firePropertyChange((*aIter)-1 ,m_pImpl->aRow[(*aIter)-1], ORowSetBase::GrantNotifierAccess()); + } + m_pRowSet->fireProperty(PROPERTY_ID_ISMODIFIED,sal_True,sal_False, ORowSetBase::GrantNotifierAccess()); + } +} +} // namespace dbaccess diff --git a/dbaccess/source/core/api/RowSetBase.hxx b/dbaccess/source/core/api/RowSetBase.hxx new file mode 100644 index 000000000000..9a7e9182e1d0 --- /dev/null +++ b/dbaccess/source/core/api/RowSetBase.hxx @@ -0,0 +1,463 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ +#ifndef DBACCESS_CORE_API_ROWSETBASE_HXX +#define DBACCESS_CORE_API_ROWSETBASE_HXX + +#ifndef _CPPUHELPER_IMPLBASE10_HXX_ +#include <cppuhelper/implbase10.hxx> +#endif +#ifndef _COM_SUN_STAR_SDBCX_XCOLUMNSSUPPLIER_HPP_ +#include <com/sun/star/sdbcx/XColumnsSupplier.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_XROW_HPP_ +#include <com/sun/star/sdbc/XRow.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_XCOLUMNLOCATE_HPP_ +#include <com/sun/star/sdbc/XColumnLocate.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_XCLOSEABLE_HPP_ +#include <com/sun/star/sdbc/XCloseable.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBCX_XROWLOCATE_HPP_ +#include <com/sun/star/sdbcx/XRowLocate.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_XRESULTSETMETADATASUPPLIER_HPP_ +#include <com/sun/star/sdbc/XResultSetMetaDataSupplier.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_XWARNINGSSUPPLIER_HPP_ +#include <com/sun/star/sdbc/XWarningsSupplier.hpp> +#endif +#ifndef _COM_SUN_STAR_LANG_XSERVICEINFO_HPP_ +#include <com/sun/star/lang/XServiceInfo.hpp> +#endif +#ifndef _COM_SUN_STAR_LANG_XUNOTUNNEL_HPP_ +#include <com/sun/star/lang/XUnoTunnel.hpp> +#endif +#ifndef _CPPUHELPER_INTERFACECONTAINER_H_ +#include <cppuhelper/interfacecontainer.h> +#endif +#ifndef CONNECTIVITY_SQLERROR_HXX +#include <connectivity/sqlerror.hxx> +#endif +#ifndef _CONNECTIVITY_COMMONTOOLS_HXX_ +#include <connectivity/CommonTools.hxx> +#endif +#ifndef COMPHELPER_PROPERTYSTATECONTAINER_HXX +#include <comphelper/propertystatecontainer.hxx> +#endif +#ifndef _COMPHELPER_PROPERTY_ARRAY_HELPER_HXX_ +#include <comphelper/proparrhlp.hxx> +#endif +#ifndef _COM_SUN_STAR_SDBC_XROWSET_HPP_ +#include <com/sun/star/sdbc/XRowSet.hpp> +#endif +#ifndef _COM_SUN_STAR_UTIL_XNUMBERFORMATTYPES_HPP_ +#include <com/sun/star/util/XNumberFormatTypes.hpp> +#endif +#ifndef _COM_SUN_STAR_CONTAINER_XNAMEACCESS_HPP_ +#include <com/sun/star/container/XNameAccess.hpp> +#endif +#ifndef DBACCESS_CORE_API_ROWSETROW_HXX +#include "RowSetRow.hxx" +#endif +#ifndef _COMPHELPER_BROADCASTHELPER_HXX_ +#include <comphelper/broadcasthelper.hxx> +#endif +#ifndef DBACCESS_ROWSETCACHEITERATOR_HXX +#include "RowSetCacheIterator.hxx" +#endif +#include "core_resource.hxx" +#include <comphelper/componentcontext.hxx> + +#include <functional> + + +namespace com { namespace sun { namespace star { + namespace sdb { struct RowChangeEvent; } + namespace lang { struct Locale; } +} } } + +namespace dbaccess +{ + class OEmptyCollection; + + typedef ::cppu::ImplHelper10< ::com::sun::star::sdbcx::XRowLocate, + ::com::sun::star::sdbc::XRow, + ::com::sun::star::sdbc::XResultSetMetaDataSupplier, + ::com::sun::star::sdbc::XWarningsSupplier, + ::com::sun::star::sdbc::XColumnLocate, + ::com::sun::star::sdbcx::XColumnsSupplier, + ::com::sun::star::lang::XServiceInfo, + ::com::sun::star::sdbc::XRowSet, + ::com::sun::star::sdbc::XCloseable, + ::com::sun::star::lang::XUnoTunnel> ORowSetBase_BASE; + + class ORowSetCache; + class ORowSetDataColumns; + class ORowSetCacheIterator; + class ORowSetDataColumn; + class ORowSetBase : public ORowSetBase_BASE, + public ::comphelper::OPropertyStateContainer, + public ::comphelper::OPropertyArrayUsageHelper<ORowSetBase> // this class hold the static property info + { + OModuleClient m_aModuleClient; + protected: + typedef ::std::vector<ORowSetDataColumn*> TDataColumns; + ::osl::Mutex* m_pMutex; // this the mutex form the rowset itself + ::osl::Mutex m_aRowCountMutex, // mutex for rowcount changes + // we need a extra mutex for columns to prevend deadlock when setting new values + // for a row + m_aColumnsMutex; + + ::com::sun::star::uno::Any m_aBookmark; + ORowSetCacheIterator m_aCurrentRow; // contains the actual fetched row + TORowSetOldRowHelperRef m_aOldRow; + TDataColumns m_aDataColumns; // holds the columns as m_pColumns but know the implementation class + connectivity::ORowSetValue m_aEmptyValue; // only for error case + + ::cppu::OWeakObject* m_pMySelf; // set by derived classes + ORowSetCache* m_pCache; // the cache is used by the rowset and his clone (shared) + ORowSetDataColumns* m_pColumns; // represent the select columns + ::cppu::OBroadcastHelper& m_rBHelper; // must be set from the derived classes + // is used when the formatkey for database types is set + ::com::sun::star::uno::Reference< ::com::sun::star::util::XNumberFormatTypes> m_xNumberFormatTypes; + OEmptyCollection* m_pEmptyCollection; + + ::comphelper::ComponentContext m_aContext; + ::connectivity::SQLError m_aErrors; + + sal_Int32 m_nLastColumnIndex; // the last column ask for, used for wasNull() + sal_Int32 m_nDeletedPosition; // is set only when a row was deleted + sal_Int32 m_nResultSetType; // fetch property + sal_Int32 m_nResultSetConcurrency; + sal_Bool m_bClone; // I'm clone or not + sal_Bool m_bIgnoreResult ; + sal_Bool m_bBeforeFirst : 1; + sal_Bool m_bAfterLast : 1; + + protected: + ORowSetBase( + const ::comphelper::ComponentContext& _rContext, + ::cppu::OBroadcastHelper& _rBHelper, + ::osl::Mutex* _pMutex + ); + + // fire a notification for all that are listening on column::VALUE property + void firePropertyChange(const ORowSetRow& _rOldRow); + // fire a change for one column + // _nPos starts at zero + void firePropertyChange(sal_Int32 _nPos,const ::connectivity::ORowSetValue& _rNewValue); + + // fire if rowcount changed + virtual void fireRowcount(); + // notify row changed + virtual sal_Bool notifyAllListenersCursorBeforeMove(::osl::ResettableMutexGuard& _rGuard); + // notify cursor moved + virtual void notifyAllListenersCursorMoved(::osl::ResettableMutexGuard& _rGuard); + // notify all that rowset changed + virtual void notifyAllListeners(::osl::ResettableMutexGuard& _rGuard); + + // cancel the insertion, if necessary (means if we're on the insert row) + virtual void doCancelModification( ) = 0; + // return <TRUE/> if and only if we're using the insert row (means: we're updating _or_ inserting) + virtual sal_Bool isModification( ) = 0; + // return <TRUE/> if and only if the current row is modified + // TODO: isn't this the same as isModification? + virtual sal_Bool isModified( ) = 0; + // return <TRUE/> if and only if the current row is the insert row + virtual sal_Bool isNew( ) = 0; + // notify the change of a boolean property + void fireProperty( sal_Int32 _nProperty, sal_Bool _bNew, sal_Bool _bOld ); + + // OPropertyStateContainer + virtual void getPropertyDefaultByHandle( sal_Int32 _nHandle, ::com::sun::star::uno::Any& _rDefault ) const; + virtual void SAL_CALL getFastPropertyValue(::com::sun::star::uno::Any& rValue,sal_Int32 nHandle) const; + + enum CursorMoveDirection + { + /// denotes a cursor move forward + MOVE_FORWARD, + /// denotes a cursor move backwards + MOVE_BACKWARD, + /// denotes no cursor move at all, used when the current row is to be refreshed only + MOVE_NONE_REFRESH_ONLY + }; + /** positions the cache in preparation of a cursor move + + Normally, the cache is simply moved to our bookmark (m_aBookmark). If however the current + row is deleted, then the cache is properly positioned for a following cursor movement in the + given direction. + + @param _ePrepareForDirection + the direction into which the cursor should be moved after the call. If we're currently not on + a deleted row, this parameter is ignored, since in this case the cache is simply moved to + m_aBookmark.</br> + If, however, we're currently on a deleted row, this is used to properly position the cache + using <member>m_nDeletedPosition</member>.<br/> + In this case, MOVE_NONE_REFRESH_ONLY is not supported. This is because the deleted row + (to which the RowSet currently points to) is not present in the cache. So, you cannot move the + cache to this row. + */ + void positionCache( CursorMoveDirection _ePrepareForDirection ); + + // returns a value of a column of the current row + const connectivity::ORowSetValue& getValue(sal_Int32 columnIndex); + // the cache has to be checked before calling this method + const connectivity::ORowSetValue& impl_getValue(sal_Int32 columnIndex); + // sets the current and the bookmark + void setCurrentRow( sal_Bool _bMoved, sal_Bool _bDoNotify, const ORowSetRow& _rOldValues, ::osl::ResettableMutexGuard& _rGuard); + void checkPositioningAllowed() throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + // checks if the cache is null + void checkCache(); + // sets the bookmark to Any() + // m_aCurrentRow to end of matrix + // m_aOldRow to NULL + void movementFailed(); + + ORowSetRow getOldRow(sal_Bool _bWasNew); + /** move the cache the postion defined by the member functor + @param _aCheckFunctor + Return <TRUE/> when we already stand on the row we want to. + @param _aMovementFunctor + The mehtod used to move. + @return + <TRUE/> if movement was successful. + */ + sal_Bool SAL_CALL move( ::std::mem_fun_t<sal_Bool,ORowSetBase>& _aCheckFunctor, + ::std::mem_fun_t<sal_Bool,ORowSetCache>& _aMovementFunctor); + + /** same meaning as isFirst. Only need by mem_fun + @return + <TRUE/> if so. + */ + sal_Bool isOnFirst(); + /** same meaning as isLast. Only need by mem_fun + @return + <TRUE/> if so. + */ + sal_Bool isOnLast(); + + /** returns the current row count + + This function takes into account that we might actually be positioned on a + deleted row, so that m_pCache->m_nRowCount does not really reflect the actual + count. + + @precond + Our mutext is locked. + */ + sal_Int32 impl_getRowCount() const; + + // the checkCache has to be called before calling this methods + sal_Bool impl_wasNull(); + sal_Int32 impl_getRow(); + sal_Bool impl_rowDeleted(); + + public: + virtual ~ORowSetBase(); + + // OComponentHelper + virtual void SAL_CALL disposing(void); + + // com::sun::star::beans::XPropertySet + virtual ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo( ) throw(::com::sun::star::uno::RuntimeException) + { + return ::cppu::OPropertySetHelper::createPropertySetInfo(getInfoHelper()); + } + + // comphelper::OPropertyArrayUsageHelper + virtual ::cppu::IPropertyArrayHelper* createArrayHelper( ) const; + + // cppu::OPropertySetHelper + virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper(); + + // com::sun::star::lang::XTypeProvider + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type > SAL_CALL getTypes() throw (::com::sun::star::uno::RuntimeException); + + // com::sun::star::uno::XInterface + virtual ::com::sun::star::uno::Any SAL_CALL queryInterface( const ::com::sun::star::uno::Type & rType ) throw (::com::sun::star::uno::RuntimeException); + + // ::com::sun::star::sdbc::XWarningsSupplier + virtual ::com::sun::star::uno::Any SAL_CALL getWarnings( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL clearWarnings( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + + // ::com::sun::star::sdbc::XResultSetMetaDataSupplier + virtual ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XResultSetMetaData > SAL_CALL getMetaData( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + + // ::com::sun::star::sdbc::XColumnLocate + virtual sal_Int32 SAL_CALL findColumn( const ::rtl::OUString& columnName ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + + // ::com::sun::star::sdbcx::XColumnsSupplier + virtual ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess > SAL_CALL getColumns( ) throw(::com::sun::star::uno::RuntimeException); + + // ::com::sun::star::sdbc::XRow + virtual sal_Bool SAL_CALL wasNull( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getString( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL getBoolean( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Int8 SAL_CALL getByte( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Int16 SAL_CALL getShort( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Int32 SAL_CALL getInt( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Int64 SAL_CALL getLong( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual float SAL_CALL getFloat( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual double SAL_CALL getDouble( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL getBytes( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::util::Date SAL_CALL getDate( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::util::Time SAL_CALL getTime( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::util::DateTime SAL_CALL getTimestamp( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > SAL_CALL getBinaryStream( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > SAL_CALL getCharacterStream( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Any SAL_CALL getObject( sal_Int32 columnIndex, const ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess >& typeMap ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRef > SAL_CALL getRef( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XBlob > SAL_CALL getBlob( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XClob > SAL_CALL getClob( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XArray > SAL_CALL getArray( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + + // ::com::sun::star::sdbcx::XRowLocate + virtual ::com::sun::star::uno::Any SAL_CALL getBookmark( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL moveToBookmark( const ::com::sun::star::uno::Any& bookmark ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL moveRelativeToBookmark( const ::com::sun::star::uno::Any& bookmark, sal_Int32 rows ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Int32 SAL_CALL compareBookmarks( const ::com::sun::star::uno::Any& first, const ::com::sun::star::uno::Any& second ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL hasOrderedBookmarks( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Int32 SAL_CALL hashBookmark( const ::com::sun::star::uno::Any& bookmark ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + + // ::com::sun::star::sdbc::XResultSet + virtual sal_Bool SAL_CALL next( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL isBeforeFirst( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL isAfterLast( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL isFirst( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL isLast( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL beforeFirst( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL afterLast( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL first( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL last( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Int32 SAL_CALL getRow( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL absolute( sal_Int32 row ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL relative( sal_Int32 rows ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL previous( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL refreshRow( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL rowUpdated( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL rowInserted( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL rowDeleted( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL getStatement( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + + // ::com::sun::star::sdbc::XRowSet + virtual void SAL_CALL execute( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException) = 0; + virtual void SAL_CALL addRowSetListener( const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRowSetListener >& listener ) throw(::com::sun::star::uno::RuntimeException) = 0; + virtual void SAL_CALL removeRowSetListener( const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRowSetListener >& listener ) throw(::com::sun::star::uno::RuntimeException) = 0; + + // is called when the rowset is going to delete this bookmark _rBookmark + void onDeleteRow( const ::com::sun::star::uno::Any& _rBookmark ); + // is called when the rowset has deleted this bookmark _rBookmark + void onDeletedRow( const ::com::sun::star::uno::Any& _rBookmark, sal_Int32 _nPos ); + + // ========================================================== + // granular access control + struct GrantNotifierAccess { friend class ORowSetNotifier; private: GrantNotifierAccess () { } }; + + // cancel the insertion, if necessary (means if we're on the insert row) + inline void doCancelModification( const GrantNotifierAccess& ) { doCancelModification(); } + inline sal_Bool isModification( const GrantNotifierAccess& ) { return isModification(); } + inline sal_Bool isModified( const GrantNotifierAccess& ) { return isModified(); } + inline sal_Bool isNew( const GrantNotifierAccess& ) { return isNew(); } + inline sal_Bool isInsertRow() { return isNew() || isModified(); } + inline void fireProperty( sal_Int32 _nProperty, sal_Bool _bNew, sal_Bool _bOld, const GrantNotifierAccess& ) + { + fireProperty( _nProperty, _bNew, _bOld ); + } + inline void firePropertyChange(sal_Int32 _nPos,const ::connectivity::ORowSetValue& _rNewValue, const GrantNotifierAccess& ) + { + firePropertyChange(_nPos,_rNewValue); + } + using ::comphelper::OPropertyStateContainer::getFastPropertyValue; + + ::osl::Mutex* getMutex() const { return m_pMutex; } + }; + + // ======================================================================== + /** eases the handling of the doCancelModification and notifyCancelInsert methods + + <p>The class can only be used on the stack, within a method of ORowSetBase (or derivees)</p> + */ + struct ORowSetNotifierImpl; + class ORowSetNotifier + { + private: + ::std::auto_ptr<ORowSetNotifierImpl> m_pImpl; + ORowSetBase* m_pRowSet; + // not aquired! This is not necessary because this class here is to be used on the stack within + // a method of ORowSetBase (or derivees) + sal_Bool m_bWasNew; + sal_Bool m_bWasModified; + +#ifdef DBG_UTIL + sal_Bool m_bNotifyCalled; +#endif + + public: + /** constructs the object, and cancels the insertion + + @see ORowSetBase::doCancelModification + */ + ORowSetNotifier( ORowSetBase* m_pRowSet ); + + /** use this one to consturct an vector for change value notification + */ + ORowSetNotifier( ORowSetBase* m_pRowSet,const ORowSetValueVector::Vector& i_aRow ); + + // destructs the object. <member>fire</member> has to be called before. + ~ORowSetNotifier( ); + + /** notifies the insertion + + <p>This has <em>not</em> been put into the destructor by intention!<br/> + + The destructor is called during stack unwinding in case of an exception, so if we would do + listener notification there, this would have the potential of another exception during stack + unwinding, which would terminate the application.</p> + + @see ORowSetBase::notifyCancelInsert + */ + void fire(); + + /** notifies value change events and notifies IsModified + @param i_aChangedColumns the index of the changed value columns + @param i_aRow the old values + @see ORowSetBase::notifyCancelInsert + */ + void firePropertyChange(); + + /** use this one to store the inde of the changed column values + */ + ::std::vector<sal_Int32>& getChangedColumns() const; + ::std::vector<com::sun::star::uno::Any>& getChangedBookmarks() const; + + }; + +} // end of namespace + +#endif // DBACCESS_CORE_API_ROWSETBASE_HXX + diff --git a/dbaccess/source/core/api/RowSetCache.cxx b/dbaccess/source/core/api/RowSetCache.cxx new file mode 100644 index 000000000000..e4e468b13779 --- /dev/null +++ b/dbaccess/source/core/api/RowSetCache.cxx @@ -0,0 +1,1685 @@ +/************************************************************************* + * + * 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_dbaccess.hxx" + + +#include "BookmarkSet.hxx" +#include "CRowSetColumn.hxx" +#include "CRowSetDataColumn.hxx" +#include "KeySet.hxx" +#include "OptimisticSet.hxx" +#include "RowSetBase.hxx" +#include "RowSetCache.hxx" +#include "StaticSet.hxx" +#include "WrappedResultSet.hxx" +#include "core_resource.hrc" +#include "core_resource.hxx" +#include "dbastrings.hrc" + +/** === begin UNO includes === **/ +#include <com/sun/star/sdbc/ColumnValue.hpp> +#include <com/sun/star/sdbc/ResultSetConcurrency.hpp> +#include <com/sun/star/sdbcx/CompareBookmark.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> +/** === end UNO includes === **/ + +#include <comphelper/extract.hxx> +#include <comphelper/property.hxx> +#include <comphelper/seqstream.hxx> +#include <comphelper/uno3.hxx> +#include <connectivity/dbexception.hxx> +#include <connectivity/dbtools.hxx> +#include <connectivity/sqliterator.hxx> +#include <connectivity/sqlnode.hxx> +#include <connectivity/sqlparse.hxx> +#include <tools/debug.hxx> +#include <tools/diagnose_ex.h> + +#include <algorithm> + +using namespace dbaccess; +using namespace dbtools; +using namespace connectivity; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::sdb; +using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::lang; +using namespace ::cppu; +using namespace ::osl; + +#define CHECK_MATRIX_POS(M) OSL_ENSURE(((M) >= static_cast<ORowSetMatrix::difference_type>(0)) && ((M) < static_cast<sal_Int32>(m_pMatrix->size())),"Position is invalid!") + +DBG_NAME(ORowSetCache) +// ------------------------------------------------------------------------- +ORowSetCache::ORowSetCache(const Reference< XResultSet >& _xRs, + const Reference< XSingleSelectQueryAnalyzer >& _xAnalyzer, + const ::comphelper::ComponentContext& _rContext, + const ::rtl::OUString& _rUpdateTableName, + sal_Bool& _bModified, + sal_Bool& _bNew, + const ORowSetValueVector& _aParameterValueForCache, + const ::rtl::OUString& i_sRowSetFilter) + :m_xSet(_xRs) + ,m_xMetaData(Reference< XResultSetMetaDataSupplier >(_xRs,UNO_QUERY)->getMetaData()) + ,m_aContext( _rContext ) + ,m_pCacheSet(NULL) + ,m_pMatrix(NULL) + ,m_pInsertMatrix(NULL) + ,m_nLastColumnIndex(0) + ,m_nFetchSize(0) + ,m_nRowCount(0) + ,m_nPrivileges( Privilege::SELECT ) + ,m_nPosition(0) + ,m_nStartPos(0) + ,m_nEndPos(0) + ,m_bRowCountFinal(sal_False) + ,m_bBeforeFirst(sal_True) + ,m_bAfterLast( sal_False ) + ,m_bUpdated(sal_False) + ,m_bModified(_bModified) + ,m_bNew(_bNew) +{ + DBG_CTOR(ORowSetCache,NULL); + + // first try if the result can be used to do inserts and updates + try + { + Reference< XResultSetUpdate> xUp(_xRs,UNO_QUERY_THROW); + Reference< XPropertySet> xProp(_xRs,UNO_QUERY); + Reference< XPropertySetInfo > xPropInfo = xProp->getPropertySetInfo(); + sal_Bool bBookmarkable = xPropInfo->hasPropertyByName(PROPERTY_ISBOOKMARKABLE) && + any2bool(xProp->getPropertyValue(PROPERTY_ISBOOKMARKABLE)) && Reference< XRowLocate >(_xRs, UNO_QUERY).is(); + if ( bBookmarkable ) + { + xUp->moveToInsertRow(); + xUp->cancelRowUpdates(); + _xRs->beforeFirst(); + m_nPrivileges = Privilege::SELECT|Privilege::DELETE|Privilege::INSERT|Privilege::UPDATE; + m_pCacheSet = new WrappedResultSet(); + m_xCacheSet = m_pCacheSet; + m_pCacheSet->construct(_xRs,i_sRowSetFilter); + return; + } + } + catch(const Exception& ex) + { + (void)ex; + } + _xRs->beforeFirst(); + + // check if all keys of the updateable table are fetched + sal_Bool bAllKeysFound = sal_False; + sal_Int32 nTablesCount = 0; + + Reference< XPropertySet> xProp(_xRs,UNO_QUERY); + Reference< XPropertySetInfo > xPropInfo = xProp->getPropertySetInfo(); + sal_Bool bNeedKeySet = !(xPropInfo->hasPropertyByName(PROPERTY_ISBOOKMARKABLE) && + any2bool(xProp->getPropertyValue(PROPERTY_ISBOOKMARKABLE)) && Reference< XRowLocate >(_xRs, UNO_QUERY).is() ); + bNeedKeySet = bNeedKeySet || (xPropInfo->hasPropertyByName(PROPERTY_RESULTSETCONCURRENCY) && + ::comphelper::getINT32(xProp->getPropertyValue(PROPERTY_RESULTSETCONCURRENCY)) == ResultSetConcurrency::READ_ONLY); + + Reference< XIndexAccess> xUpdateTableKeys; + ::rtl::OUString aUpdateTableName = _rUpdateTableName; + Reference< XConnection> xConnection; + // first we need a connection + Reference< XStatement> xStmt(_xRs->getStatement(),UNO_QUERY); + if(xStmt.is()) + xConnection = xStmt->getConnection(); + else + { + Reference< XPreparedStatement> xPrepStmt(_xRs->getStatement(),UNO_QUERY); + xConnection = xPrepStmt->getConnection(); + } + OSL_ENSURE(xConnection.is(),"No connection!"); + if(_xAnalyzer.is()) + { + try + { + Reference<XTablesSupplier> xTabSup(_xAnalyzer,UNO_QUERY); + OSL_ENSURE(xTabSup.is(),"ORowSet::execute composer isn't a tablesupplier!"); + Reference<XNameAccess> xTables = xTabSup->getTables(); + Sequence< ::rtl::OUString> aTableNames = xTables->getElementNames(); + if ( aTableNames.getLength() > 1 && !_rUpdateTableName.getLength() && bNeedKeySet ) + {// here we have a join or union and nobody told us which table to update, so we update them all + m_nPrivileges = Privilege::SELECT|Privilege::DELETE|Privilege::INSERT|Privilege::UPDATE; + OptimisticSet* pCursor = new OptimisticSet(m_aContext,xConnection,_xAnalyzer,_aParameterValueForCache); + m_pCacheSet = pCursor; + m_xCacheSet = m_pCacheSet; + try + { + m_pCacheSet->construct(_xRs,i_sRowSetFilter); + if ( pCursor->isReadOnly() ) + m_nPrivileges = Privilege::SELECT; + m_aKeyColumns = pCursor->getJoinedKeyColumns(); + return; + } + catch(const Exception&) + { + // DBG_UNHANDLED_EXCEPTION(); + } + m_pCacheSet = NULL; + m_xCacheSet.clear(); + } + else + { + if(_rUpdateTableName.getLength() && xTables->hasByName(_rUpdateTableName)) + xTables->getByName(_rUpdateTableName) >>= m_aUpdateTable; + else if(xTables->getElementNames().getLength()) + { + aUpdateTableName = xTables->getElementNames()[0]; + xTables->getByName(aUpdateTableName) >>= m_aUpdateTable; + } + Reference<XIndexAccess> xIndexAccess(xTables,UNO_QUERY); + if(xIndexAccess.is()) + nTablesCount = xIndexAccess->getCount(); + else + nTablesCount = xTables->getElementNames().getLength(); + + if(m_aUpdateTable.is() && nTablesCount < 3) // for we can't handle more than 2 tables in our keyset + { + Reference<XPropertySet> xSet(m_aUpdateTable,UNO_QUERY); + const Reference<XNameAccess> xPrimaryKeyColumns = dbtools::getPrimaryKeyColumns_throw(xSet); + if ( xPrimaryKeyColumns.is() ) + { + Reference<XColumnsSupplier> xColSup(_xAnalyzer,UNO_QUERY); + if ( xColSup.is() ) + { + Reference<XNameAccess> xSelColumns = xColSup->getColumns(); + Reference<XDatabaseMetaData> xMeta = xConnection->getMetaData(); + SelectColumnsMetaData aColumnNames(xMeta.is() && xMeta->supportsMixedCaseQuotedIdentifiers() ? true : false); + ::dbaccess::getColumnPositions(xSelColumns,xPrimaryKeyColumns->getElementNames(),aUpdateTableName,aColumnNames); + bAllKeysFound = !aColumnNames.empty() && sal_Int32(aColumnNames.size()) == xPrimaryKeyColumns->getElementNames().getLength(); + } + } + } + } + } + catch(Exception&) + { + } + } + + // first check if resultset is bookmarkable + if(!bNeedKeySet) + { + try + { + m_pCacheSet = new OBookmarkSet(); + m_xCacheSet = m_pCacheSet; + m_pCacheSet->construct(_xRs,i_sRowSetFilter); + + // check privileges + m_nPrivileges = Privilege::SELECT; + if(Reference<XResultSetUpdate>(_xRs,UNO_QUERY).is()) // this interface is optional so we have to check it + { + Reference<XPropertySet> xTable(m_aUpdateTable,UNO_QUERY); + if(xTable.is() && xTable->getPropertySetInfo()->hasPropertyByName(PROPERTY_PRIVILEGES)) + { + m_nPrivileges = 0; + xTable->getPropertyValue(PROPERTY_PRIVILEGES) >>= m_nPrivileges; + if(!m_nPrivileges) + m_nPrivileges = Privilege::SELECT; + } + } + } + catch(const SQLException&) + { + bNeedKeySet = sal_True; + } + + } + if(bNeedKeySet) + { + // need to check if we could handle this select clause + bAllKeysFound = bAllKeysFound && (nTablesCount == 1 || checkJoin(xConnection,_xAnalyzer,aUpdateTableName)); + + // || !(comphelper::hasProperty(PROPERTY_CANUPDATEINSERTEDROWS,xProp) && any2bool(xProp->getPropertyValue(PROPERTY_CANUPDATEINSERTEDROWS))) + + // oj removed because keyset uses only the next// || (xProp->getPropertySetInfo()->hasPropertyByName(PROPERTY_RESULTSETTYPE) && comphelper::getINT32(xProp->getPropertyValue(PROPERTY_RESULTSETTYPE)) == ResultSetType::FORWARD_ONLY) + if(!bAllKeysFound ) + { + m_pCacheSet = new OStaticSet(); + m_xCacheSet = m_pCacheSet; + m_pCacheSet->construct(_xRs,i_sRowSetFilter); + m_nPrivileges = Privilege::SELECT; + } + else + { + Reference<XDatabaseMetaData> xMeta = xConnection->getMetaData(); + SelectColumnsMetaData aColumnNames(xMeta.is() && xMeta->supportsMixedCaseQuotedIdentifiers() ? true : false); + Reference<XColumnsSupplier> xColSup(_xAnalyzer,UNO_QUERY); + Reference<XNameAccess> xSelColumns = xColSup->getColumns(); + Reference<XNameAccess> xColumns = m_aUpdateTable->getColumns(); + ::dbaccess::getColumnPositions(xSelColumns,xColumns->getElementNames(),aUpdateTableName,aColumnNames); + + // check privileges + m_nPrivileges = Privilege::SELECT; + sal_Bool bNoInsert = sal_False; + + Sequence< ::rtl::OUString> aNames(xColumns->getElementNames()); + const ::rtl::OUString* pIter = aNames.getConstArray(); + const ::rtl::OUString* pEnd = pIter + aNames.getLength(); + for(;pIter != pEnd;++pIter) + { + Reference<XPropertySet> xColumn(xColumns->getByName(*pIter),UNO_QUERY); + OSL_ENSURE(xColumn.is(),"Column in table is null!"); + if(xColumn.is()) + { + sal_Int32 nNullable = 0; + xColumn->getPropertyValue(PROPERTY_ISNULLABLE) >>= nNullable; + if(nNullable == ColumnValue::NO_NULLS && aColumnNames.find(*pIter) == aColumnNames.end()) + { // we found a column where null is not allowed so we can't insert new values + bNoInsert = sal_True; + break; // one column is enough + } + } + } + + OKeySet* pKeySet = new OKeySet(m_aUpdateTable,xUpdateTableKeys,aUpdateTableName ,_xAnalyzer,_aParameterValueForCache); + try + { + m_pCacheSet = pKeySet; + m_xCacheSet = m_pCacheSet; + pKeySet->construct(_xRs,i_sRowSetFilter); + + if(Reference<XResultSetUpdate>(_xRs,UNO_QUERY).is()) // this interface is optional so we have to check it + { + Reference<XPropertySet> xTable(m_aUpdateTable,UNO_QUERY); + if(xTable.is() && xTable->getPropertySetInfo()->hasPropertyByName(PROPERTY_PRIVILEGES)) + { + m_nPrivileges = 0; + xTable->getPropertyValue(PROPERTY_PRIVILEGES) >>= m_nPrivileges; + if(!m_nPrivileges) + m_nPrivileges = Privilege::SELECT; + } + } + if(bNoInsert) + m_nPrivileges |= ~Privilege::INSERT; // remove the insert privilege + } + catch(const SQLException&) + { + // we couldn't create a keyset here so we have to create a static cache + if ( m_pCacheSet ) + m_pCacheSet = NULL; + m_xCacheSet = NULL; + m_pCacheSet = new OStaticSet(); + m_xCacheSet = m_pCacheSet; + m_pCacheSet->construct(_xRs,i_sRowSetFilter); + m_nPrivileges = Privilege::SELECT; + } + } + + } + // last check + if(!bAllKeysFound && xProp->getPropertySetInfo()->hasPropertyByName(PROPERTY_RESULTSETCONCURRENCY) && + ::comphelper::getINT32(xProp->getPropertyValue(PROPERTY_RESULTSETCONCURRENCY)) == ResultSetConcurrency::READ_ONLY) + m_nPrivileges = Privilege::SELECT; +} + +// ------------------------------------------------------------------------- +ORowSetCache::~ORowSetCache() +{ + m_pCacheSet = NULL; + m_xCacheSet = NULL; + if(m_pMatrix) + { + m_pMatrix->clear(); + delete m_pMatrix; + } + + if(m_pInsertMatrix) + { + m_pInsertMatrix->clear(); + delete m_pInsertMatrix; + } + m_xSet = WeakReference< XResultSet>(); + m_xMetaData = NULL; + m_aUpdateTable = NULL; + + DBG_DTOR(ORowSetCache,NULL); +} + +// ------------------------------------------------------------------------- +void ORowSetCache::setMaxRowSize(sal_Int32 _nSize) +{ + + if(_nSize == m_nFetchSize) + return; + + m_nFetchSize = _nSize; + if(!m_pMatrix) + { + m_pMatrix = new ORowSetMatrix(_nSize); + m_aMatrixIter = m_pMatrix->end(); + m_aMatrixEnd = m_pMatrix->end(); + + m_pInsertMatrix = new ORowSetMatrix(1); // a little bit overkill but ??? :-) + m_aInsertRow = m_pInsertMatrix->end(); + } + else + { + // now correct the iterator in our iterator vector + ::std::vector<sal_Int32> aPositions; + ::std::map<sal_Int32,sal_Bool> aCacheIterToChange; + // first get the positions where they stand now + ORowSetCacheMap::iterator aCacheIter = m_aCacheIterators.begin(); + ORowSetCacheMap::iterator aCacheEnd = m_aCacheIterators.end(); + for(;aCacheIter != aCacheEnd;++aCacheIter) + { + aCacheIterToChange[aCacheIter->first] = sal_False; + if ( !aCacheIter->second.pRowSet->isInsertRow() + /*&& aCacheIter->second.aIterator != m_pMatrix->end()*/ && !m_bModified ) + { + ptrdiff_t nDist = (aCacheIter->second.aIterator - m_pMatrix->begin()); + aPositions.push_back(nDist); + aCacheIterToChange[aCacheIter->first] = sal_True; + } + } + sal_Int32 nKeyPos = (m_aMatrixIter - m_pMatrix->begin()); + m_pMatrix->resize(_nSize); + + if ( nKeyPos < _nSize ) + m_aMatrixIter = m_pMatrix->begin() + nKeyPos; + else + m_aMatrixIter = m_pMatrix->end(); + m_aMatrixEnd = m_pMatrix->end(); + + // now adjust their positions because a resize invalid all iterators + ::std::vector<sal_Int32>::const_iterator aIter = aPositions.begin(); + ::std::map<sal_Int32,sal_Bool>::const_iterator aPosChangeIter = aCacheIterToChange.begin(); + for( aCacheIter = m_aCacheIterators.begin(); + aPosChangeIter != aCacheIterToChange.end(); + ++aPosChangeIter,++aCacheIter) + { + if ( aPosChangeIter->second ) + { + CHECK_MATRIX_POS(*aIter); + if ( *aIter < _nSize ) + aCacheIter->second.aIterator = m_pMatrix->begin() + *aIter++; + else + aCacheIter->second.aIterator = m_pMatrix->end(); + } + } + } + if(!m_nPosition) + { + sal_Int32 nNewSt = 1; + fillMatrix(nNewSt,_nSize+1); + m_nStartPos = 0; + m_nEndPos = _nSize; + } +} +// ------------------------------------------------------------------------- + +// XResultSetMetaDataSupplier +Reference< XResultSetMetaData > ORowSetCache::getMetaData( ) +{ + return m_xMetaData; +} +// ------------------------------------------------------------------------- +Any lcl_getBookmark(ORowSetValue& i_aValue,OCacheSet* i_pCacheSet) +{ + switch ( i_aValue.getTypeKind() ) + { + case DataType::TINYINT: + case DataType::SMALLINT: + case DataType::INTEGER: + return makeAny((sal_Int32)i_aValue); + default: + if ( i_pCacheSet && i_aValue.isNull()) + i_aValue = i_pCacheSet->getBookmark(); + return i_aValue.getAny(); + } +} +// ------------------------------------------------------------------------- +// ::com::sun::star::sdbcx::XRowLocate +Any ORowSetCache::getBookmark( ) +{ + + if(m_bAfterLast) + throwFunctionSequenceException(m_xSet.get()); + + if ( m_aMatrixIter >= m_pMatrix->end() || m_aMatrixIter < m_pMatrix->begin() || !(*m_aMatrixIter).isValid()) + { + return Any(); // this is allowed here because the rowset knowns what it is doing + } + + return lcl_getBookmark(((*m_aMatrixIter)->get())[0],m_pCacheSet); +} +// ------------------------------------------------------------------------- +sal_Bool ORowSetCache::moveToBookmark( const Any& bookmark ) +{ + if ( m_pCacheSet->moveToBookmark(bookmark) ) + { + m_bBeforeFirst = sal_False; + m_nPosition = m_pCacheSet->getRow(); + + checkPositionFlags(); + + if(!m_bAfterLast) + { + moveWindow(); + checkPositionFlags(); + if ( !m_bAfterLast ) + { + m_aMatrixIter = calcPosition(); + OSL_ENSURE(m_aMatrixIter->isValid(),"Iterator after moveToBookmark not valid"); + } + else + m_aMatrixIter = m_pMatrix->end(); + } + else + m_aMatrixIter = m_pMatrix->end(); + } + else + return sal_False; + + return m_aMatrixIter != m_pMatrix->end() && (*m_aMatrixIter).isValid(); +} +// ------------------------------------------------------------------------- +sal_Bool ORowSetCache::moveRelativeToBookmark( const Any& bookmark, sal_Int32 rows ) +{ + sal_Bool bRet( moveToBookmark( bookmark ) ); + if ( bRet ) + { + m_nPosition = m_pCacheSet->getRow() + rows; + absolute(m_nPosition); + // for(sal_Int32 i=0;i<rows && m_aMatrixIter != m_pMatrix->end();++i,++m_aMatrixIter) ; + + bRet = m_aMatrixIter != m_pMatrix->end() && (*m_aMatrixIter).isValid(); + } + + return bRet; +} +// ------------------------------------------------------------------------- +sal_Int32 ORowSetCache::compareBookmarks( const Any& _first, const Any& _second ) +{ + return (!_first.hasValue() || !_second.hasValue()) ? CompareBookmark::NOT_COMPARABLE : m_pCacheSet->compareBookmarks(_first,_second); +} +// ------------------------------------------------------------------------- +sal_Bool ORowSetCache::hasOrderedBookmarks( ) +{ + return m_pCacheSet->hasOrderedBookmarks(); +} +// ------------------------------------------------------------------------- +sal_Int32 ORowSetCache::hashBookmark( const Any& bookmark ) +{ + return m_pCacheSet->hashBookmark(bookmark); +} +// XRowUpdate +// ----------------------------------------------------------------------------- +void ORowSetCache::updateNull(sal_Int32 columnIndex,ORowSetValueVector::Vector& io_aRow + ,::std::vector<sal_Int32>& o_ChangedColumns + ) +{ + checkUpdateConditions(columnIndex); + + ORowSetValueVector::Vector& rInsert = ((*m_aInsertRow)->get()); + rInsert[columnIndex].setBound(sal_True); + rInsert[columnIndex].setNull(); + rInsert[columnIndex].setModified(); + io_aRow[columnIndex].setNull(); + + m_pCacheSet->mergeColumnValues(columnIndex,rInsert,io_aRow,o_ChangedColumns); + impl_updateRowFromCache_throw(io_aRow,o_ChangedColumns); +} +// ----------------------------------------------------------------------------- +void ORowSetCache::updateValue(sal_Int32 columnIndex,const ORowSetValue& x + ,ORowSetValueVector::Vector& io_aRow + ,::std::vector<sal_Int32>& o_ChangedColumns + ) +{ + checkUpdateConditions(columnIndex); + + ORowSetValueVector::Vector& rInsert = ((*m_aInsertRow)->get()); + rInsert[columnIndex].setBound(sal_True); + rInsert[columnIndex] = x; + rInsert[columnIndex].setModified(); + io_aRow[columnIndex] = rInsert[columnIndex]; + + m_pCacheSet->mergeColumnValues(columnIndex,rInsert,io_aRow,o_ChangedColumns); + impl_updateRowFromCache_throw(io_aRow,o_ChangedColumns); +} +// ------------------------------------------------------------------------- +void ORowSetCache::updateCharacterStream( sal_Int32 columnIndex, const Reference< ::com::sun::star::io::XInputStream >& x + , sal_Int32 length,ORowSetValueVector::Vector& io_aRow + ,::std::vector<sal_Int32>& o_ChangedColumns + ) +{ + checkUpdateConditions(columnIndex); + + Sequence<sal_Int8> aSeq; + if(x.is()) + x->readBytes(aSeq,length); + + ORowSetValueVector::Vector& rInsert = ((*m_aInsertRow)->get()); + rInsert[columnIndex].setBound(sal_True); + rInsert[columnIndex] = aSeq; + rInsert[columnIndex].setModified(); + io_aRow[columnIndex] = makeAny(x); + + m_pCacheSet->mergeColumnValues(columnIndex,rInsert,io_aRow,o_ChangedColumns); + impl_updateRowFromCache_throw(io_aRow,o_ChangedColumns); +} +// ------------------------------------------------------------------------- +void ORowSetCache::updateObject( sal_Int32 columnIndex, const Any& x + ,ORowSetValueVector::Vector& io_aRow + ,::std::vector<sal_Int32>& o_ChangedColumns + ) +{ + checkUpdateConditions(columnIndex); + + ORowSetValueVector::Vector& rInsert = ((*m_aInsertRow)->get()); + rInsert[columnIndex].setBound(sal_True); + rInsert[columnIndex] = x; + rInsert[columnIndex].setModified(); + io_aRow[columnIndex] = rInsert[columnIndex]; + + m_pCacheSet->mergeColumnValues(columnIndex,rInsert,io_aRow,o_ChangedColumns); + impl_updateRowFromCache_throw(io_aRow,o_ChangedColumns); +} +// ------------------------------------------------------------------------- +void ORowSetCache::updateNumericObject( sal_Int32 columnIndex, const Any& x, sal_Int32 /*scale*/ + ,ORowSetValueVector::Vector& io_aRow + ,::std::vector<sal_Int32>& o_ChangedColumns + ) +{ + checkUpdateConditions(columnIndex); + + ORowSetValueVector::Vector& rInsert = ((*m_aInsertRow)->get()); + rInsert[columnIndex].setBound(sal_True); + rInsert[columnIndex] = x; + rInsert[columnIndex].setModified(); + io_aRow[columnIndex] = rInsert[columnIndex]; + + m_pCacheSet->mergeColumnValues(columnIndex,rInsert,io_aRow,o_ChangedColumns); + impl_updateRowFromCache_throw(io_aRow,o_ChangedColumns); +} +// ------------------------------------------------------------------------- +// XResultSet +sal_Bool ORowSetCache::next( ) +{ + if(!isAfterLast()) + { + m_bBeforeFirst = sal_False; + ++m_nPosition; + + // after we increment the position we have to check if we are already after the last row + checkPositionFlags(); + if(!m_bAfterLast) + { + moveWindow(); + + OSL_ENSURE(((m_nPosition - m_nStartPos) - 1) < (sal_Int32)m_pMatrix->size(),"Position is behind end()!"); + m_aMatrixIter = calcPosition(); + checkPositionFlags(); + } + } + + return !m_bAfterLast; +} +// ------------------------------------------------------------------------- +sal_Bool ORowSetCache::isBeforeFirst( ) +{ + // return !m_nPosition; + + return m_bBeforeFirst; +} +// ------------------------------------------------------------------------- +sal_Bool ORowSetCache::isAfterLast( ) +{ + + return m_bAfterLast; +} +// ------------------------------------------------------------------------- +sal_Bool ORowSetCache::isFirst( ) +{ + + return m_nPosition == 1; // ask resultset for +} +// ------------------------------------------------------------------------- +sal_Bool ORowSetCache::isLast( ) +{ + // return m_bRowCountFinal ? (m_nPosition==m_nRowCount) : m_pCacheSet->isLast(); + + return m_nPosition == m_nRowCount; +} +// ------------------------------------------------------------------------- +sal_Bool ORowSetCache::beforeFirst( ) +{ + + + if(!m_bBeforeFirst) + { + m_bAfterLast = sal_False; + m_nPosition = 0; + m_bBeforeFirst = sal_True; + m_pCacheSet->beforeFirst(); + moveWindow(); + m_aMatrixIter = m_pMatrix->end(); + } + return sal_True; +} +// ------------------------------------------------------------------------- +sal_Bool ORowSetCache::afterLast( ) +{ + + + if(!m_bAfterLast) + { + m_bBeforeFirst = sal_False; + m_bAfterLast = sal_True; + + if(!m_bRowCountFinal) + { + m_pCacheSet->last(); + m_bRowCountFinal = sal_True; + m_nRowCount = m_pCacheSet->getRow();// + 1 removed + } + m_pCacheSet->afterLast(); + + m_nPosition = 0; + m_aMatrixIter = m_pMatrix->end(); + } + return sal_True; +} +// ------------------------------------------------------------------------- +sal_Bool ORowSetCache::fillMatrix(sal_Int32& _nNewStartPos,sal_Int32 _nNewEndPos) +{ + OSL_ENSURE(_nNewStartPos != _nNewEndPos,"ORowSetCache::fillMatrix: StartPos and EndPos can not be equal!"); + // fill the whole window with new data + ORowSetMatrix::iterator aIter = m_pMatrix->begin(); + sal_Bool bCheck = m_pCacheSet->absolute(_nNewStartPos); // -1 no need to + + sal_Int32 i=_nNewStartPos; + for(;i<_nNewEndPos;++i,++aIter) + { + if(bCheck) + { + if(!aIter->isValid()) + *aIter = new ORowSetValueVector(m_xMetaData->getColumnCount()); + m_pCacheSet->fillValueRow(*aIter,i); + } + else + { // there are no more rows found so we can fetch some before start + + if(!m_bRowCountFinal) + { + if(m_pCacheSet->previous()) // because we stand after the last row + m_nRowCount = m_pCacheSet->getRow(); // here we have the row count + if(!m_nRowCount) + m_nRowCount = i-1; // it can be that getRow return zero + m_bRowCountFinal = sal_True; + } + if(m_nRowCount > m_nFetchSize) + { + ORowSetMatrix::iterator aEnd = aIter; + ORowSetMatrix::iterator aRealEnd = m_pMatrix->end(); + sal_Int32 nPos = m_nRowCount - m_nFetchSize + 1; + _nNewStartPos = nPos; + bCheck = m_pCacheSet->absolute(_nNewStartPos); + + for(;bCheck && aIter != aRealEnd;++aIter) + { + if(bCheck) + { + if(!aIter->isValid()) + *aIter = new ORowSetValueVector(m_xMetaData->getColumnCount()); + m_pCacheSet->fillValueRow(*aIter,nPos++); + } + bCheck = m_pCacheSet->next(); + } + if(aIter != aEnd) + ::std::rotate(m_pMatrix->begin(),aEnd,aRealEnd); + } + break; + } + bCheck = m_pCacheSet->next(); + } + // m_nStartPos = _nNewStartPos; + // we have to read one row forward to enshure that we know when we are on last row + // but only when we don't know it already + if(!m_bRowCountFinal) + { + if(!m_pCacheSet->next()) + { + if(m_pCacheSet->previous()) // because we stand after the last row + m_nRowCount = m_pCacheSet->getRow(); // here we have the row count + m_bRowCountFinal = sal_True; + } + else + m_nRowCount = std::max(i,m_nRowCount); + + } + return bCheck; +} +// ------------------------------------------------------------------------- +sal_Bool ORowSetCache::moveWindow() +{ + + sal_Bool bRet = sal_True; + + sal_Int32 nDiff = (sal_Int32)(m_nFetchSize*0.5 -0.5); + sal_Int32 nNewStartPos = (m_nPosition - nDiff); + // sal_Int32 nNewEndPos = (m_nPosition+m_nFetchSize*0.5); + sal_Int32 nNewEndPos = nNewStartPos + m_nFetchSize; + + if ( m_nPosition <= m_nStartPos ) + { // the window is behind the new start pos + if(!m_nStartPos) + return sal_False; + // the new position should be the nPos - nFetchSize/2 + if ( nNewEndPos > m_nStartPos ) + { // but the two regions are overlapping + // fill the rows behind the new end + + ORowSetMatrix::iterator aEnd; // the iterator we need for rotate + ORowSetMatrix::iterator aIter; // the iterator we fill with new values + + sal_Bool bCheck = sal_True; + if ( nNewStartPos < 1 ) + { + bCheck = m_pCacheSet->first(); + // aEnd = m_pMatrix->begin() + (sal_Int32)(m_nFetchSize*0.5); + OSL_ENSURE((nNewEndPos - m_nStartPos - nNewStartPos) < (sal_Int32)m_pMatrix->size(),"Position is behind end()!"); + aEnd = m_pMatrix->begin() + (nNewEndPos - m_nStartPos - nNewStartPos); + aIter = aEnd; + m_nStartPos = 0; + } + else + { + OSL_ENSURE((nNewEndPos - m_nStartPos -1) < (sal_Int32)m_pMatrix->size(),"Position is behind end()!"); + aEnd = m_pMatrix->begin() + ((nNewEndPos - m_nStartPos)-1); + aIter = m_pMatrix->begin() + ((nNewEndPos - m_nStartPos)-1); + bCheck = m_pCacheSet->absolute(nNewStartPos); + m_nStartPos = nNewStartPos -1; + } + + if ( bCheck ) + { + sal_Int32 nPos = m_nStartPos; + bCheck = fill(aIter,m_pMatrix->end(),nPos,bCheck); + + ::std::rotate(m_pMatrix->begin(),aEnd,m_pMatrix->end()); + // now correct the iterator in our iterator vector + // rotateCacheIterator(aEnd-m_pMatrix->begin()); //can't be used because they decrement and here we need to increment + ptrdiff_t nNewDist = aEnd - m_pMatrix->begin(); + ptrdiff_t nOffSet = m_pMatrix->end() - aEnd; + ORowSetCacheMap::iterator aCacheIter = m_aCacheIterators.begin(); + ORowSetCacheMap::iterator aCacheEnd = m_aCacheIterators.end(); + for(;aCacheIter != aCacheEnd;++aCacheIter) + { + if ( !aCacheIter->second.pRowSet->isInsertRow() + && aCacheIter->second.aIterator != m_pMatrix->end() && !m_bModified ) + { + ptrdiff_t nDist = (aCacheIter->second.aIterator - m_pMatrix->begin()); + if ( nDist >= nNewDist ) + { + aCacheIter->second.aIterator = m_pMatrix->end(); + } + else + { +#if OSL_DEBUG_LEVEL > 0 + ORowSetMatrix::iterator aOldPos; + aOldPos = aCacheIter->second.aIterator; +#endif + CHECK_MATRIX_POS( ((aOldPos - m_pMatrix->begin()) + nOffSet) ); + aCacheIter->second.aIterator += nOffSet; +#if OSL_DEBUG_LEVEL > 0 + ORowSetMatrix::iterator aCurrentPos; + aCurrentPos = aCacheIter->second.aIterator; +#endif + OSL_ENSURE(aCacheIter->second.aIterator >= m_pMatrix->begin() + && aCacheIter->second.aIterator < m_pMatrix->end(),"Iterator out of area!"); + } + } + } + } + else + { // normaly this should never happen + OSL_ENSURE(0,"What the hell is happen here!"); + return sal_False; + } + } + else + {// no rows can be reused so fill again + if(nNewStartPos < 1) // special case + { + m_nStartPos = 0; + + rotateCacheIterator(static_cast<sal_Int16>(m_nFetchSize+1)); // static_cast<sal_Int16>(m_nFetchSize+1) + + m_pCacheSet->beforeFirst(); + + sal_Bool bCheck; + ORowSetMatrix::iterator aIter = m_pMatrix->begin(); + for(sal_Int32 i=0;i<m_nFetchSize;++i,++aIter) + { + bCheck = m_pCacheSet->next(); + if ( bCheck ) + { + if(!aIter->isValid()) + *aIter = new ORowSetValueVector(m_xMetaData->getColumnCount()); + m_pCacheSet->fillValueRow(*aIter,i+1); + } + else + *aIter = NULL; + } + } + else + bRet = reFillMatrix(nNewStartPos,nNewEndPos); + } + } + else if(m_nPosition > m_nStartPos) + { // the new start pos is above the startpos of the window + + if(m_nPosition <= (m_nStartPos+m_nFetchSize)) + { // position in window + OSL_ENSURE((m_nPosition - m_nStartPos -1) < (sal_Int32)m_pMatrix->size(),"Position is behind end()!"); + m_aMatrixIter = calcPosition(); + if(!m_aMatrixIter->isValid()) + { + sal_Bool bOk( m_pCacheSet->absolute( m_nPosition ) ); + if ( bOk ) + { + *m_aMatrixIter = new ORowSetValueVector(m_xMetaData->getColumnCount()); + m_pCacheSet->fillValueRow(*m_aMatrixIter,m_nPosition); + // we have to read one row forward to ensure that we know when we are on last row + // but only when we don't know it already + if ( !m_bRowCountFinal ) + { + bOk = m_pCacheSet->absolute( m_nPosition + 1 ); + if ( bOk ) + m_nRowCount = std::max(sal_Int32(m_nPosition+1),m_nRowCount); + } + } + if(!bOk) + { + if(!m_bRowCountFinal) + { + // because we stand after the last row + m_nRowCount = m_pCacheSet->previous() ? m_pCacheSet->getRow() : 0;// + 1 removed + m_bRowCountFinal = sal_True; + } + } + } + } + else if(nNewStartPos < (m_nStartPos+m_nFetchSize)) + { // position behind window but the region is overlapping + // the rows from begin() to (begin + nNewStartPos - m_nStartPos) can be refilled with the new rows + // the rows behind this can be reused + ORowSetMatrix::iterator aIter = m_pMatrix->begin(); + CHECK_MATRIX_POS(nNewStartPos - m_nStartPos - 1); + ORowSetMatrix::iterator aEnd = m_pMatrix->begin() + (nNewStartPos - m_nStartPos - 1); + + sal_Int32 nPos = m_nStartPos + m_nFetchSize + 1; + sal_Bool bCheck = m_pCacheSet->absolute(nPos); + bCheck = fill(aIter,aEnd,nPos,bCheck); // refill the region wew don't need anymore + +// // we know that this is the current maximal rowcount here +// if ( !m_bRowCountFinal && bCheck ) +// m_nRowCount = std::max(nPos,m_nRowCount); + // we have to read one row forward to enshure that we know when we are on last row + // but only when we don't know it already + sal_Bool bOk = sal_True; + if(bCheck && !m_bRowCountFinal) + bOk = m_pCacheSet->next(); + // bind end to front + if(bCheck) + { // rotate the end to the front + ::std::rotate(m_pMatrix->begin(),aIter,m_pMatrix->end()); + // now correct the iterator in our iterator vector + rotateCacheIterator( (sal_Int16)( aIter - m_pMatrix->begin() ) ); + m_nStartPos = nNewStartPos - 1; // must be -1 + // now I can say how many rows we have + if(!bOk) + { + m_pCacheSet->previous(); // because we stand after the last row + m_nRowCount = nPos; // here we have the row count + m_bRowCountFinal = sal_True; + } + else if(!m_bRowCountFinal) + m_nRowCount = std::max(++nPos,m_nRowCount); + } + else + { // the end was reached before end() so we can set the start before nNewStartPos + + m_nStartPos += (aIter - m_pMatrix->begin()); + // m_nStartPos = (aIter - m_pMatrix->begin()); + ::std::rotate(m_pMatrix->begin(),aIter,m_pMatrix->end()); + // now correct the iterator in our iterator vector + rotateCacheIterator( (sal_Int16)( aIter - m_pMatrix->begin() ) ); + + if ( !m_bRowCountFinal ) + { + m_pCacheSet->previous(); // because we stand after the last row + m_nRowCount = std::max(m_nRowCount,--nPos); // here we have the row count + OSL_ENSURE(nPos == m_pCacheSet->getRow(),"nPos isn't valid!"); + m_bRowCountFinal = sal_True; + } + // TODO check + // m_nStartPos = (nNewStartPos+m_nRowCount) - m_nFetchSize ; + if(m_nStartPos < 0) + m_nStartPos = 0; + } + // here we need only to check if the begining row is valid. If not we have to fetch it. + if(!m_pMatrix->begin()->isValid()) + { + aIter = m_pMatrix->begin(); + + nPos = m_nStartPos; + bCheck = m_pCacheSet->absolute(m_nStartPos); + for(; !aIter->isValid() && bCheck;++aIter) + { + OSL_ENSURE(aIter != m_pMatrix->end(),"Invalid iterator"); + bCheck = m_pCacheSet->next(); + if ( bCheck ) // resultset stands on right position + { + *aIter = new ORowSetValueVector(m_xMetaData->getColumnCount()); + m_pCacheSet->fillValueRow(*aIter,++nPos); + } + } + } + } + else // no rows can be reused so fill again + bRet = reFillMatrix(nNewStartPos,nNewEndPos); + } + + if(!m_bRowCountFinal) + m_nRowCount = std::max(m_nPosition,m_nRowCount); + OSL_ENSURE(m_nStartPos >= 0,"ORowSetCache::moveWindow: m_nStartPos is less than 0!"); + + return bRet; +} +// ------------------------------------------------------------------------- +sal_Bool ORowSetCache::first( ) +{ + // first move to the first row + // then check if the cache window is at the begining + // when not postionize the window and fill it with data + // smart moving of the window -> clear only the rows whom are out of range + sal_Bool bRet = m_pCacheSet->first(); + if(bRet) + { + m_bBeforeFirst = m_bAfterLast = sal_False; + m_nPosition = 1; + moveWindow(); + m_aMatrixIter = m_pMatrix->begin(); + } + else + { + m_bRowCountFinal = m_bBeforeFirst = m_bAfterLast = sal_True; + m_nRowCount = m_nPosition = 0; + + OSL_ENSURE(m_bBeforeFirst || m_bNew,"ORowSetCache::first return false and BeforeFirst isn't true"); + m_aMatrixIter = m_pMatrix->end(); + } + return bRet; +} +// ------------------------------------------------------------------------- +sal_Bool ORowSetCache::last( ) +{ + sal_Bool bRet = m_pCacheSet->last(); + if(bRet) + { + m_bBeforeFirst = m_bAfterLast = sal_False; + if(!m_bRowCountFinal) + { + m_bRowCountFinal = sal_True; + m_nRowCount = m_nPosition = m_pCacheSet->getRow(); // not + 1 + } + m_nPosition = m_pCacheSet->getRow(); + moveWindow(); + // we have to repositioning because moveWindow can modify the cache + m_pCacheSet->last(); +// if(m_nPosition > m_nFetchSize) +// m_aMatrixIter = m_pMatrix->end() -1; +// else +// m_aMatrixIter = m_pMatrix->begin() + m_nPosition - 1; + OSL_ENSURE(((m_nPosition - m_nStartPos) - 1) < (sal_Int32)m_pMatrix->size(),"Position is behind end()!"); + m_aMatrixIter = calcPosition(); + } + else + { + m_bRowCountFinal = m_bBeforeFirst = m_bAfterLast = sal_True; + m_nRowCount = m_nPosition = 0; + OSL_ENSURE(m_bBeforeFirst,"ORowSetCache::last return false and BeforeFirst isn't true"); + m_aMatrixIter = m_pMatrix->end(); + } +#if OSL_DEBUG_LEVEL > 1 + if(bRet) + { + OSL_ENSURE((*m_aMatrixIter).isValid(),"ORowSetCache::last: Row not valid!"); + } +#endif + + return bRet; +} +// ------------------------------------------------------------------------- +sal_Int32 ORowSetCache::getRow( ) +{ + return (isBeforeFirst() || isAfterLast()) ? 0 : m_nPosition; +} +// ------------------------------------------------------------------------- +sal_Bool ORowSetCache::absolute( sal_Int32 row ) +{ + if(!row ) + throw SQLException(DBACORE_RESSTRING(RID_STR_NO_ABS_ZERO),NULL,SQLSTATE_GENERAL,1000,Any() ); + + if(row < 0) + { + // here we have to scroll from the last row to backward so we have to go to last row and + // and two the previous + if(m_bRowCountFinal || last()) + { + m_nPosition = m_nRowCount + row + 1; // + row because row is negative and +1 because row==-1 means last row + if(m_nPosition < 1) + { + m_bBeforeFirst = sal_True; + m_bAfterLast = sal_False; + m_aMatrixIter = m_pMatrix->end(); + } + else + { + m_bBeforeFirst = sal_False; + m_bAfterLast = m_nPosition > m_nRowCount; + moveWindow(); + OSL_ENSURE(((m_nPosition - m_nStartPos) - 1) < (sal_Int32)m_pMatrix->size(),"Position is behind end()!"); + m_aMatrixIter = calcPosition(); + } + } + else + m_aMatrixIter = m_pMatrix->end(); + } + else + { + m_nPosition = row; + // the position flags + m_bBeforeFirst = sal_False; + checkPositionFlags(); + + if(!m_bAfterLast) + { + moveWindow(); + checkPositionFlags(); + if(!m_bAfterLast) + m_aMatrixIter = calcPosition(); + else + m_aMatrixIter = m_pMatrix->end(); + } + else + m_aMatrixIter = m_pMatrix->end(); + } + + return !(m_bAfterLast || m_bBeforeFirst); +} +// ------------------------------------------------------------------------- +sal_Bool ORowSetCache::relative( sal_Int32 rows ) +{ + sal_Bool bErg = sal_True; + if(rows) + { + sal_Int32 nNewPosition = m_nPosition + rows; + + if ( m_bBeforeFirst && rows > 0 ) + nNewPosition = rows; + else if ( m_bRowCountFinal && m_bAfterLast && rows < 0 ) + nNewPosition = m_nRowCount + 1 + rows; + else + if ( m_bBeforeFirst || ( m_bRowCountFinal && m_bAfterLast ) ) + throw SQLException( DBACORE_RESSTRING( RID_STR_NO_RELATIVE ), NULL, SQLSTATE_GENERAL, 1000, Any() ); + if ( nNewPosition ) + { + bErg = absolute( nNewPosition ); + bErg = bErg && !isAfterLast() && !isBeforeFirst(); + } + else + { + m_bBeforeFirst = sal_True; + bErg = sal_False; + } + } + return bErg; +} +// ------------------------------------------------------------------------- +sal_Bool ORowSetCache::previous( ) +{ + sal_Bool bRet = sal_False; + if(!isBeforeFirst()) + { + if(m_bAfterLast) // we stand after the last row so one before is the last row + bRet = last(); + else + { + m_bAfterLast = sal_False; + --m_nPosition; + moveWindow(); + OSL_ENSURE(((m_nPosition - m_nStartPos) - 1) < (sal_Int32)m_pMatrix->size(),"Position is behind end()!"); + + checkPositionFlags(); + + if(!m_nPosition) + { + m_bBeforeFirst = sal_True; + m_aMatrixIter = m_pMatrix->end(); + } + else + { + m_aMatrixIter = calcPosition(); + bRet = (*m_aMatrixIter).isValid(); + } + } + } + return bRet; +} +// ------------------------------------------------------------------------- +void ORowSetCache::refreshRow( ) +{ + if(isAfterLast()) + throw SQLException(DBACORE_RESSTRING(RID_STR_NO_REFESH_AFTERLAST),NULL,SQLSTATE_GENERAL,1000,Any() ); + OSL_ENSURE(m_aMatrixIter != m_pMatrix->end(),"refreshRow() called for invalid row!"); + m_pCacheSet->refreshRow(); + m_pCacheSet->fillValueRow(*m_aMatrixIter,m_nPosition); + if ( m_bNew ) + { + cancelRowModification(); + } +} +// ------------------------------------------------------------------------- +sal_Bool ORowSetCache::rowUpdated( ) +{ + return m_pCacheSet->rowUpdated(); +} +// ------------------------------------------------------------------------- +sal_Bool ORowSetCache::rowInserted( ) +{ + return m_pCacheSet->rowInserted(); +} +// ------------------------------------------------------------------------- +// XResultSetUpdate +sal_Bool ORowSetCache::insertRow(::std::vector< Any >& o_aBookmarks) +{ + if ( !m_bNew || !m_aInsertRow->isValid() ) + throw SQLException(DBACORE_RESSTRING(RID_STR_NO_MOVETOINSERTROW_CALLED),NULL,SQLSTATE_GENERAL,1000,Any() ); + + m_pCacheSet->insertRow(*m_aInsertRow,m_aUpdateTable); + + sal_Bool bRet( rowInserted() ); + if ( bRet ) + { + ++m_nRowCount; + Any aBookmark = ((*m_aInsertRow)->get())[0].makeAny(); + m_bAfterLast = m_bBeforeFirst = sal_False; + if(aBookmark.hasValue()) + { + moveToBookmark(aBookmark); + // update the cached values + ORowSetValueVector::Vector& rCurrentRow = ((*m_aMatrixIter))->get(); + ORowSetMatrix::iterator aIter = m_pMatrix->begin(); + for(;aIter != m_pMatrix->end();++aIter) + { + if ( m_aMatrixIter != aIter && aIter->isValid() && m_pCacheSet->columnValuesUpdated((*aIter)->get(),rCurrentRow) ) + { + o_aBookmarks.push_back(lcl_getBookmark((*aIter)->get()[0],m_pCacheSet)); + } + } + } + else + { + OSL_ENSURE(0,"There must be a bookmark after the row was inserted!"); + } + } + return bRet; +} +// ------------------------------------------------------------------------- +void ORowSetCache::resetInsertRow(sal_Bool _bClearInsertRow) +{ + if ( _bClearInsertRow ) + clearInsertRow(); + m_bNew = sal_False; + m_bModified = sal_False; +} +// ------------------------------------------------------------------------- +void ORowSetCache::cancelRowModification() +{ + // clear the insertrow references -> implies that the current row of the rowset changes as well + ORowSetCacheMap::iterator aCacheIter = m_aCacheIterators.begin(); + ORowSetCacheMap::iterator aCacheEnd = m_aCacheIterators.end(); + for(;aCacheIter != aCacheEnd;++aCacheIter) + { + if ( aCacheIter->second.pRowSet->isInsertRow() && aCacheIter->second.aIterator == m_aInsertRow ) + aCacheIter->second.aIterator = m_pMatrix->end(); + } // for(;aCacheIter != aCacheEnd;++aCacheIter) + resetInsertRow(sal_False); +} +// ------------------------------------------------------------------------- +void ORowSetCache::updateRow( ORowSetMatrix::iterator& _rUpdateRow,::std::vector< Any >& o_aBookmarks ) +{ + if(isAfterLast() || isBeforeFirst()) + throw SQLException(DBACORE_RESSTRING(RID_STR_NO_UPDATEROW),NULL,SQLSTATE_GENERAL,1000,Any() ); + + Any aBookmark = ((*_rUpdateRow)->get())[0].makeAny(); + OSL_ENSURE(aBookmark.hasValue(),"Bookmark must have a value!"); + // here we don't have to reposition our CacheSet, when we try to update a row, + // the row was already fetched + moveToBookmark(aBookmark); + m_pCacheSet->updateRow(*_rUpdateRow,*m_aMatrixIter,m_aUpdateTable); + // refetch the whole row + (*m_aMatrixIter) = NULL; + + if ( moveToBookmark(aBookmark) ) + { + // update the cached values + ORowSetValueVector::Vector& rCurrentRow = ((*m_aMatrixIter))->get(); + ORowSetMatrix::iterator aIter = m_pMatrix->begin(); + for(;aIter != m_pMatrix->end();++aIter) + { + if ( m_aMatrixIter != aIter && aIter->isValid() && m_pCacheSet->columnValuesUpdated((*aIter)->get(),rCurrentRow) ) + { + o_aBookmarks.push_back(lcl_getBookmark((*aIter)->get()[0],m_pCacheSet)); + } + } + } + + m_bModified = sal_False; +} +// ------------------------------------------------------------------------- +bool ORowSetCache::deleteRow( ) +{ + if(isAfterLast() || isBeforeFirst()) + throw SQLException(DBACORE_RESSTRING(RID_STR_NO_DELETEROW),NULL,SQLSTATE_GENERAL,1000,Any() ); + + // m_pCacheSet->absolute(m_nPosition); + m_pCacheSet->deleteRow(*m_aMatrixIter,m_aUpdateTable); + if ( !m_pCacheSet->rowDeleted() ) + return false; + + --m_nRowCount; + OSL_ENSURE(((m_nPosition - m_nStartPos) - 1) < (sal_Int32)m_pMatrix->size(),"Position is behind end()!"); + ORowSetMatrix::iterator aPos = calcPosition(); + (*aPos) = NULL; + + ORowSetMatrix::iterator aEnd = m_pMatrix->end(); + for(++aPos;aPos != aEnd && aPos->isValid();++aPos) + { + *(aPos-1) = *aPos; + (*aPos) = NULL; + } + m_aMatrixIter = m_pMatrix->end(); + + --m_nPosition; + return true; +} +// ------------------------------------------------------------------------- +void ORowSetCache::cancelRowUpdates( ) +{ + m_bNew = m_bModified = sal_False; + if(!m_nPosition) + { + OSL_ENSURE(0,"cancelRowUpdates:Invalid positions pos == 0"); + ::dbtools::throwFunctionSequenceException(NULL); + } + + if(m_pCacheSet->absolute(m_nPosition)) + m_pCacheSet->fillValueRow(*m_aMatrixIter,m_nPosition); + else + { + OSL_ENSURE(0,"cancelRowUpdates couldn't position right with absolute"); + ::dbtools::throwFunctionSequenceException(NULL); + } +} +// ------------------------------------------------------------------------- +void ORowSetCache::moveToInsertRow( ) +{ + m_bNew = sal_True; + m_bUpdated = m_bAfterLast = sal_False; + + m_aInsertRow = m_pInsertMatrix->begin(); + if(!m_aInsertRow->isValid()) + *m_aInsertRow = new ORowSetValueVector(m_xMetaData->getColumnCount()); + + // we don't unbound the bookmark column + ORowSetValueVector::Vector::iterator aIter = (*m_aInsertRow)->get().begin()+1; + ORowSetValueVector::Vector::iterator aEnd = (*m_aInsertRow)->get().end(); + for(sal_Int32 i = 1;aIter != aEnd;++aIter,++i) + { + aIter->setBound(sal_False); + aIter->setModified(sal_False); + aIter->setNull(); + aIter->setTypeKind(m_xMetaData->getColumnType(i)); + } +} +// ------------------------------------------------------------------------- +ORowSetCacheIterator ORowSetCache::createIterator(ORowSetBase* _pRowSet) +{ + + ORowSetCacheIterator_Helper aHelper; + aHelper.aIterator = m_pMatrix->end(); + aHelper.pRowSet = _pRowSet; + return ORowSetCacheIterator(m_aCacheIterators.insert(m_aCacheIterators.begin(),ORowSetCacheMap::value_type(m_aCacheIterators.size()+1,aHelper)),this,_pRowSet); +} +// ----------------------------------------------------------------------------- +void ORowSetCache::deleteIterator(const ORowSetBase* _pRowSet) +{ + ORowSetCacheMap::iterator aCacheIter = m_aCacheIterators.begin(); + for(;aCacheIter != m_aCacheIterators.end();) + { + if ( aCacheIter->second.pRowSet == _pRowSet ) + { + m_aCacheIterators.erase(aCacheIter); + aCacheIter = m_aCacheIterators.begin(); + } // if ( aCacheIter->second.pRowSet == _pRowSet ) + else + ++aCacheIter; + } +} +// ----------------------------------------------------------------------------- +void ORowSetCache::rotateCacheIterator(ORowSetMatrix::difference_type _nDist) +{ + if(_nDist) + { + // now correct the iterator in our iterator vector + ORowSetCacheMap::iterator aCacheIter = m_aCacheIterators.begin(); + ORowSetCacheMap::iterator aCacheEnd = m_aCacheIterators.end(); + for(;aCacheIter != aCacheEnd;++aCacheIter) + { + if ( !aCacheIter->second.pRowSet->isInsertRow() + && aCacheIter->second.aIterator != m_pMatrix->end() && !m_bModified ) + { + ptrdiff_t nDist = (aCacheIter->second.aIterator - m_pMatrix->begin()); + if(nDist < _nDist) + { + aCacheIter->second.aIterator = m_pMatrix->end(); + } + else + { + OSL_ENSURE((aCacheIter->second.aIterator - m_pMatrix->begin()) >= _nDist,"Invalid Dist value!"); + aCacheIter->second.aIterator -= _nDist; + OSL_ENSURE(aCacheIter->second.aIterator >= m_pMatrix->begin() + && aCacheIter->second.aIterator < m_pMatrix->end(),"Iterator out of area!"); + } + } + } + } +} +// ------------------------------------------------------------------------- +void ORowSetCache::setUpdateIterator(const ORowSetMatrix::iterator& _rOriginalRow) +{ + m_aInsertRow = m_pInsertMatrix->begin(); + if(!m_aInsertRow->isValid()) + *m_aInsertRow = new ORowSetValueVector(m_xMetaData->getColumnCount()); + + (*(*m_aInsertRow)) = (*(*_rOriginalRow)); + // we don't unbound the bookmark column + ORowSetValueVector::Vector::iterator aIter = (*m_aInsertRow)->get().begin(); + ORowSetValueVector::Vector::iterator aEnd = (*m_aInsertRow)->get().end(); + for(;aIter != aEnd;++aIter) + aIter->setModified(sal_False); +} +// ----------------------------------------------------------------------------- +void ORowSetCache::checkPositionFlags() +{ + if(m_bRowCountFinal) + { + m_bAfterLast = m_nPosition > m_nRowCount; + if(m_bAfterLast) + m_nPosition = 0;//m_nRowCount; + } +} +// ----------------------------------------------------------------------------- +void ORowSetCache::checkUpdateConditions(sal_Int32 columnIndex) +{ + if(m_bAfterLast || columnIndex >= (sal_Int32)(*m_aInsertRow)->get().size()) + throwFunctionSequenceException(m_xSet.get()); +} +//------------------------------------------------------------------------------ +sal_Bool ORowSetCache::checkInnerJoin(const ::connectivity::OSQLParseNode *pNode,const Reference< XConnection>& _xConnection,const ::rtl::OUString& _sUpdateTableName) +{ + sal_Bool bOk = sal_False; + if (pNode->count() == 3 && // Ausdruck is geklammert + SQL_ISPUNCTUATION(pNode->getChild(0),"(") && + SQL_ISPUNCTUATION(pNode->getChild(2),")")) + { + bOk = checkInnerJoin(pNode->getChild(1),_xConnection,_sUpdateTableName); + } + else if ((SQL_ISRULE(pNode,search_condition) || SQL_ISRULE(pNode,boolean_term)) && // AND/OR-Verknuepfung: + pNode->count() == 3) + { + // nur AND Verknüpfung zulassen + if ( SQL_ISTOKEN(pNode->getChild(1),AND) ) + bOk = checkInnerJoin(pNode->getChild(0),_xConnection,_sUpdateTableName) + && checkInnerJoin(pNode->getChild(2),_xConnection,_sUpdateTableName); + } + else if (SQL_ISRULE(pNode,comparison_predicate)) + { + // only the comparison of columns is allowed + DBG_ASSERT(pNode->count() == 3,"checkInnerJoin: Fehler im Parse Tree"); + if (!(SQL_ISRULE(pNode->getChild(0),column_ref) && + SQL_ISRULE(pNode->getChild(2),column_ref) && + pNode->getChild(1)->getNodeType() == SQL_NODE_EQUAL)) + { + bOk = sal_False; + } + ::rtl::OUString sColumnName,sTableRange; + OSQLParseTreeIterator::getColumnRange( pNode->getChild(0), _xConnection, sColumnName, sTableRange ); + bOk = sTableRange == _sUpdateTableName; + if ( !bOk ) + { + OSQLParseTreeIterator::getColumnRange( pNode->getChild(2), _xConnection, sColumnName, sTableRange ); + bOk = sTableRange == _sUpdateTableName; + } + } + return bOk; +} +// ----------------------------------------------------------------------------- +sal_Bool ORowSetCache::checkJoin(const Reference< XConnection>& _xConnection, + const Reference< XSingleSelectQueryAnalyzer >& _xAnalyzer, + const ::rtl::OUString& _sUpdateTableName ) +{ + sal_Bool bOk = sal_False; + ::rtl::OUString sSql = _xAnalyzer->getQuery(); + ::rtl::OUString sErrorMsg; + ::connectivity::OSQLParser aSqlParser( m_aContext.getLegacyServiceFactory() ); + ::std::auto_ptr< ::connectivity::OSQLParseNode> pSqlParseNode( aSqlParser.parseTree(sErrorMsg,sSql)); + if ( pSqlParseNode.get() && SQL_ISRULE(pSqlParseNode, select_statement) ) + { + OSQLParseNode* pTableRefCommalist = pSqlParseNode->getByRule(::connectivity::OSQLParseNode::table_ref_commalist); + OSL_ENSURE(pTableRefCommalist,"NO tables why!?"); + if(pTableRefCommalist && pTableRefCommalist->count() == 1) + { + // we found only one element so it must some kind of join here + OSQLParseNode* pJoin = pTableRefCommalist->getByRule(::connectivity::OSQLParseNode::qualified_join); + if(pJoin) + { // we are only intereseted in qualified joins like RIGHT or LEFT + OSQLParseNode* pJoinType = pJoin->getChild(1); + OSQLParseNode* pOuterType = NULL; + if(SQL_ISRULE(pJoinType,join_type) && pJoinType->count() == 2) + pOuterType = pJoinType->getChild(0); + else if(SQL_ISRULE(pJoinType,outer_join_type)) + pOuterType = pJoinType; + + sal_Bool bCheck = sal_False; + sal_Bool bLeftSide = sal_False; + if(pOuterType) + { // found outer join + bLeftSide = SQL_ISTOKEN(pOuterType->getChild(0),LEFT); + bCheck = bLeftSide || SQL_ISTOKEN(pOuterType->getChild(0),RIGHT); + } + + if(bCheck) + { // here we know that we have to check on which side our table resides + const OSQLParseNode* pTableRef = pJoin->getByRule(::connectivity::OSQLParseNode::qualified_join); + if(bLeftSide) + pTableRef = pJoin->getChild(0); + else + pTableRef = pJoin->getChild(3); + OSL_ENSURE(SQL_ISRULE(pTableRef,table_ref),"Must be a tableref here!"); + + ::rtl::OUString sTableRange = OSQLParseNode::getTableRange(pTableRef); + if(!sTableRange.getLength()) + pTableRef->getChild(0)->parseNodeToStr( sTableRange, _xConnection, NULL, sal_False, sal_False ); + bOk = sTableRange == _sUpdateTableName; + } + } + } + else + { + OSQLParseNode* pWhereOpt = pSqlParseNode->getChild(3)->getChild(1); + if ( pWhereOpt && !pWhereOpt->isLeaf() ) + bOk = checkInnerJoin(pWhereOpt->getChild(1),_xConnection,_sUpdateTableName); + } + } + return bOk; +} +// ----------------------------------------------------------------------------- +void ORowSetCache::clearInsertRow() +{ + // we don't unbound the bookmark column + if ( m_aInsertRow != m_pInsertMatrix->end() && m_aInsertRow->isValid() ) + { + ORowSetValueVector::Vector::iterator aIter = (*m_aInsertRow)->get().begin()+1; + ORowSetValueVector::Vector::iterator aEnd = (*m_aInsertRow)->get().end(); + for(;aIter != aEnd;++aIter) + { + aIter->setBound(sal_False); + aIter->setModified(sal_False); + aIter->setNull(); + } // for(;aIter != (*m_aInsertRow)->end();++aIter) + } +} +// ----------------------------------------------------------------------------- +ORowSetMatrix::iterator ORowSetCache::calcPosition() const +{ + sal_Int32 nValue = (m_nPosition - m_nStartPos) - 1; + CHECK_MATRIX_POS(nValue); + return ( nValue < 0 || nValue >= static_cast<sal_Int32>(m_pMatrix->size()) ) ? m_pMatrix->end() : (m_pMatrix->begin() + nValue); +} +// ----------------------------------------------------------------------------- + +TORowSetOldRowHelperRef ORowSetCache::registerOldRow() +{ + TORowSetOldRowHelperRef pRef = new ORowSetOldRowHelper(ORowSetRow()); + m_aOldRows.push_back(pRef); + return pRef; +} +// ----------------------------------------------------------------------------- +void ORowSetCache::deregisterOldRow(const TORowSetOldRowHelperRef& _rRow) +{ + TOldRowSetRows::iterator aOldRowEnd = m_aOldRows.end(); + for (TOldRowSetRows::iterator aOldRowIter = m_aOldRows.begin(); aOldRowIter != aOldRowEnd; ++aOldRowIter) + { + if ( aOldRowIter->getBodyPtr() == _rRow.getBodyPtr() ) + { + m_aOldRows.erase(aOldRowIter); + break; + } + + } +} +// ----------------------------------------------------------------------------- +sal_Bool ORowSetCache::reFillMatrix(sal_Int32 _nNewStartPos,sal_Int32 _nNewEndPos) +{ + TOldRowSetRows::iterator aOldRowEnd = m_aOldRows.end(); + for (TOldRowSetRows::iterator aOldRowIter = m_aOldRows.begin(); aOldRowIter != aOldRowEnd; ++aOldRowIter) + { + if ( aOldRowIter->isValid() && aOldRowIter->getBody().getRow().isValid() ) + aOldRowIter->getBody().setRow(new ORowSetValueVector(aOldRowIter->getBody().getRow().getBody()) ); + } + sal_Int32 nNewSt = _nNewStartPos; + sal_Bool bRet = fillMatrix(nNewSt,_nNewEndPos); + m_nStartPos = nNewSt - 1; + rotateCacheIterator(static_cast<sal_Int16>(m_nFetchSize+1)); // forces that every iterator will be set to null + return bRet; +} +// ----------------------------------------------------------------------------- +sal_Bool ORowSetCache::fill(ORowSetMatrix::iterator& _aIter,const ORowSetMatrix::iterator& _aEnd,sal_Int32& _nPos,sal_Bool _bCheck) +{ + sal_Int32 nColumnCount = m_xMetaData->getColumnCount(); + for(; _bCheck && _aIter != _aEnd;) + { + if ( !_aIter->isValid() ) + *_aIter = new ORowSetValueVector(nColumnCount); + else + { + TOldRowSetRows::iterator aOldRowEnd = m_aOldRows.end(); + for (TOldRowSetRows::iterator aOldRowIter = m_aOldRows.begin(); aOldRowIter != aOldRowEnd; ++aOldRowIter) + { + if ( aOldRowIter->getBody().getRow().isEqualBody(*_aIter) ) + *_aIter = new ORowSetValueVector(nColumnCount); + } + } + m_pCacheSet->fillValueRow(*_aIter++,++_nPos); + _bCheck = m_pCacheSet->next(); + } + return _bCheck; +} +// ----------------------------------------------------------------------------- +bool ORowSetCache::isResultSetChanged() const +{ + return m_pCacheSet->isResultSetChanged(); +} +// ----------------------------------------------------------------------------- +void ORowSetCache::reset(const Reference< XResultSet>& _xDriverSet) +{ + m_xMetaData.set(Reference< XResultSetMetaDataSupplier >(_xDriverSet,UNO_QUERY)->getMetaData()); + m_pCacheSet->reset(_xDriverSet); + + m_bRowCountFinal = sal_False; + m_nRowCount = 0; + reFillMatrix(m_nStartPos+1,m_nEndPos+1); +} +// ----------------------------------------------------------------------------- +void ORowSetCache::impl_updateRowFromCache_throw(ORowSetValueVector::Vector& io_aRow + ,::std::vector<sal_Int32>& o_ChangedColumns) +{ + if ( o_ChangedColumns.size() > 1 ) + { + ORowSetMatrix::iterator aIter = m_pMatrix->begin(); + for(;aIter != m_pMatrix->end();++aIter) + { + if ( aIter->isValid() && m_pCacheSet->updateColumnValues((*aIter)->get(),io_aRow,o_ChangedColumns)) + { + break; + } + } + + if ( aIter == m_pMatrix->end() ) + { + m_pCacheSet->fillMissingValues(io_aRow); + } + } +} +// ----------------------------------------------------------------------------- diff --git a/dbaccess/source/core/api/RowSetCache.hxx b/dbaccess/source/core/api/RowSetCache.hxx new file mode 100644 index 000000000000..76e1d7145752 --- /dev/null +++ b/dbaccess/source/core/api/RowSetCache.hxx @@ -0,0 +1,273 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ +#ifndef DBACCESS_CORE_API_ROWSETCACHE_HXX +#define DBACCESS_CORE_API_ROWSETCACHE_HXX + +#ifndef _CONNECTIVITY_COMMONTOOLS_HXX_ +#include <connectivity/CommonTools.hxx> +#endif +#ifndef _COM_SUN_STAR_LANG_XSERVICEINFO_HPP_ +#include <com/sun/star/lang/XServiceInfo.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_XPREPAREDSTATEMENT_HPP_ +#include <com/sun/star/sdbc/XPreparedStatement.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_XCONNECTION_HPP_ +#include <com/sun/star/sdbc/XConnection.hpp> +#endif +#ifndef _COM_SUN_STAR_SDB_XSINGLESELECTQUERYANALYZER_HPP_ +#include <com/sun/star/sdb/XSingleSelectQueryAnalyzer.hpp> +#endif +#ifndef _COM_SUN_STAR_SDB_XSINGLESELECTQUERYANALYZER_HPP_ +#include <com/sun/star/sdb/XSingleSelectQueryAnalyzer.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_XRESULTSETMETADATASUPPLIER_HPP_ +#include <com/sun/star/sdbc/XResultSetMetaDataSupplier.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_XWARNINGSSUPPLIER_HPP_ +#include <com/sun/star/sdbc/XWarningsSupplier.hpp> +#endif +#ifndef _COM_SUN_STAR_SDB_XRESULTSETACCESS_HPP_ +#include <com/sun/star/sdb/XResultSetAccess.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_XROW_HPP_ +#include <com/sun/star/sdbc/XRow.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_XCOLUMNLOCATE_HPP_ +#include <com/sun/star/sdbc/XColumnLocate.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBCX_XROWLOCATE_HPP_ +#include <com/sun/star/sdbcx/XRowLocate.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_XROWUPDATE_HPP_ +#include <com/sun/star/sdbc/XRowUpdate.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_XRESULTSETUPDATE_HPP_ +#include <com/sun/star/sdbc/XResultSetUpdate.hpp> +#endif +#ifndef _COM_SUN_STAR_SDB_XROWSETAPPROVEBROADCASTER_HPP_ +#include <com/sun/star/sdb/XRowSetApproveBroadcaster.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_RESULTSETTYPE_HPP_ +#include <com/sun/star/sdbc/ResultSetType.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBCX_XDELETEROWS_HPP_ +#include <com/sun/star/sdbcx/XDeleteRows.hpp> +#endif +#ifndef _CPPUHELPER_COMPBASE11_HXX_ +#include <cppuhelper/compbase11.hxx> +#endif +#ifndef _COMPHELPER_PROPERTYCONTAINER_HXX_ +#include <comphelper/propertycontainer.hxx> +#endif +#ifndef COMPHELPER_COMPONENTCONTEXT_HXX +#include <comphelper/componentcontext.hxx> +#endif +#ifndef _CPPUHELPER_IMPLBASE5_HXX_ +#include <cppuhelper/implbase5.hxx> +#endif +#ifndef _COMPHELPER_PROPERTY_ARRAY_HELPER_HXX_ +#include <comphelper/proparrhlp.hxx> +#endif +#ifndef DBACCESS_CORE_API_ROWSETROW_HXX +#include "RowSetRow.hxx" +#endif +#ifndef DBACCESS_ROWSETCACHEITERATOR_HXX +#include "RowSetCacheIterator.hxx" +#endif + +namespace connectivity +{ + class OSQLParseNode; +} +namespace dbaccess +{ + class OCacheSet; + class ORowSetDataColumns; + class ORowSetCacheClone; + + class ORowSetCache + { + friend class ORowSetBase; + friend class ORowSet; + friend class ORowSetClone; + friend class ORowSetCacheIterator; + + typedef ::std::vector< TORowSetOldRowHelperRef > TOldRowSetRows; + + ::std::map<sal_Int32,sal_Int32> m_aKeyColumns; + //the set can be static, bookmarkable or keyset + ::com::sun::star::uno::WeakReference< ::com::sun::star::sdbc::XResultSet> m_xSet; + ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XResultSetMetaData > m_xMetaData; // must be before m_aInsertRow + ::comphelper::ComponentContext m_aContext; + + ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRow> m_xCacheSet; + + OCacheSet* m_pCacheSet; // is a bookmarkable, keyset or static resultset + ORowSetMatrix* m_pMatrix; // represent the table struct + ORowSetMatrix::iterator m_aMatrixIter; // represent a row of the table + ORowSetMatrix::iterator m_aMatrixEnd; // present the row behind the last row of the table + ORowSetCacheMap m_aCacheIterators; + TOldRowSetRows m_aOldRows; + + ORowSetMatrix* m_pInsertMatrix; // represent the rows which should be inserted normally this is only one + ORowSetMatrix::iterator m_aInsertRow; // represent a insert row + + // ORowSetRow m_aInsertRow; // present the row that should be inserted + sal_Int32 m_nLastColumnIndex; // the last column ask for, used for wasNull() + + connectivity::OSQLTable m_aUpdateTable; // used for updates/deletes and inserts + + sal_Int32 m_nFetchSize; + sal_Int32 m_nRowCount; + sal_Int32 m_nPrivileges; + sal_Int32 m_nPosition; // 0 means beforefirst + + sal_Int32 m_nStartPos; // start pos of the window zero based + sal_Int32 m_nEndPos; // end pos of the window zero based + + sal_Bool m_bRowCountFinal ; + sal_Bool m_bBeforeFirst ; + sal_Bool m_bAfterLast ; + sal_Bool m_bUpdated ; + sal_Bool& m_bModified ; // points to the rowset member m_bModified + sal_Bool& m_bNew ; // points to the rowset member m_bNew + + sal_Bool fill(ORowSetMatrix::iterator& _aIter,const ORowSetMatrix::iterator& _aEnd,sal_Int32& _nPos,sal_Bool _bCheck); + sal_Bool reFillMatrix(sal_Int32 _nNewStartPos,sal_Int32 nNewEndPos); + sal_Bool fillMatrix(sal_Int32 &_nNewStartPos,sal_Int32 _nNewEndPos); + sal_Bool moveWindow(); + // returns true when a keyset needs to be created. + sal_Bool impl_createBookmarkSet_nothrow(const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XResultSet >& _xRs); + + void firePropertyChange(sal_Int32 _nColumnIndex,const ::connectivity::ORowSetValue& _rOldValue); + + void rotateCacheIterator(ORowSetMatrix::difference_type _nDist); + void updateValue(sal_Int32 columnIndex + ,const connectivity::ORowSetValue& x + ,ORowSetValueVector::Vector& io_aRow + ,::std::vector<sal_Int32>& o_ChangedColumns + ); + + void impl_updateRowFromCache_throw(ORowSetValueVector::Vector& io_aRow + ,::std::vector<sal_Int32>& o_ChangedColumns + ); + // checks and set the flags isAfterLast isLast and position when afterlast is true + void checkPositionFlags(); + void checkUpdateConditions(sal_Int32 columnIndex); + sal_Bool checkJoin( const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection>& _xConnection, + const ::com::sun::star::uno::Reference< ::com::sun::star::sdb::XSingleSelectQueryAnalyzer >& _xComposer, + const ::rtl::OUString& _sUpdateTableName); + sal_Bool checkInnerJoin(const ::connectivity::OSQLParseNode *pNode + ,const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection>& _xConnection + ,const ::rtl::OUString& _sUpdateTableName); + + // clears the insert row + void clearInsertRow(); + ORowSetMatrix::iterator calcPosition() const; + + protected: + ORowSetMatrix::iterator& getEnd() { return m_aMatrixEnd;} + // is called when after a moveToInsertRow a movement (next, etc) was called + void cancelRowModification(); + public: + ORowSetCache(const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XResultSet >& _xRs, + const ::com::sun::star::uno::Reference< ::com::sun::star::sdb::XSingleSelectQueryAnalyzer >& _xAnalyzer, + const ::comphelper::ComponentContext& _rContext, + const ::rtl::OUString& _rUpdateTableName, + sal_Bool& _bModified, + sal_Bool& _bNew, + const ORowSetValueVector& _aParameterValueForCache, + const ::rtl::OUString& i_sRowSetFilter); + ~ORowSetCache(); + + + // called from the rowset when a updateXXX was called for the first time + void setUpdateIterator(const ORowSetMatrix::iterator& _rOriginalRow); + ORowSetCacheIterator createIterator(ORowSetBase* _pRowSet); + void deleteIterator(const ORowSetBase* _pRowSet); + // sets the size of the matrix + void setMaxRowSize(sal_Int32 _nSize); + + TORowSetOldRowHelperRef registerOldRow(); + void deregisterOldRow(const TORowSetOldRowHelperRef& _rRow); + + // ::com::sun::star::sdbc::XResultSetMetaDataSupplier + ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XResultSetMetaData > getMetaData( ); + + // ::com::sun::star::sdbcx::XRowLocate + ::com::sun::star::uno::Any getBookmark( ); + sal_Bool moveToBookmark( const ::com::sun::star::uno::Any& bookmark ); + sal_Bool moveRelativeToBookmark( const ::com::sun::star::uno::Any& bookmark, sal_Int32 rows ); + sal_Int32 compareBookmarks( const ::com::sun::star::uno::Any& first, const ::com::sun::star::uno::Any& second ); + sal_Bool hasOrderedBookmarks( ); + sal_Int32 hashBookmark( const ::com::sun::star::uno::Any& bookmark ); + + // ::com::sun::star::sdbc::XRowUpdate + void updateCharacterStream( sal_Int32 columnIndex, const ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream >& x, sal_Int32 length,ORowSetValueVector::Vector& io_aRow,::std::vector<sal_Int32>& o_ChangedColumns + ); + void updateObject( sal_Int32 columnIndex, const ::com::sun::star::uno::Any& x,ORowSetValueVector::Vector& io_aRow ,::std::vector<sal_Int32>& o_ChangedColumns); + void updateNumericObject( sal_Int32 columnIndex, const ::com::sun::star::uno::Any& x, sal_Int32 scale,ORowSetValueVector::Vector& io_aRow ,::std::vector<sal_Int32>& o_ChangedColumns); + void updateNull(sal_Int32 columnIndex + ,ORowSetValueVector::Vector& io_aRow + ,::std::vector<sal_Int32>& o_ChangedColumns + ); + + // ::com::sun::star::sdbc::XResultSet + sal_Bool next( ); + sal_Bool isBeforeFirst( ); + sal_Bool isAfterLast( ); + sal_Bool isFirst( ); + sal_Bool isLast( ); + sal_Bool beforeFirst( ); + sal_Bool afterLast( ); + sal_Bool first( ); + sal_Bool last( ); + sal_Int32 getRow( ); + sal_Bool absolute( sal_Int32 row ); + sal_Bool relative( sal_Int32 rows ); + sal_Bool previous( ); + void refreshRow( ); + sal_Bool rowUpdated( ); + sal_Bool rowInserted( ); + + // ::com::sun::star::sdbc::XResultSetUpdate + sal_Bool insertRow(::std::vector< ::com::sun::star::uno::Any >& o_aBookmarks); + void resetInsertRow(sal_Bool _bClearInsertRow); + + void updateRow( ORowSetMatrix::iterator& _rUpdateRow,::std::vector< ::com::sun::star::uno::Any >& o_aBookmarks ); + bool deleteRow(); + void cancelRowUpdates( ); + void moveToInsertRow( ); + + const ::std::map<sal_Int32,sal_Int32>& getKeyColumns() const { return m_aKeyColumns; } + bool isResultSetChanged() const; + void reset(const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XResultSet>& _xDriverSet); + }; +} +#endif + diff --git a/dbaccess/source/core/api/RowSetCacheIterator.cxx b/dbaccess/source/core/api/RowSetCacheIterator.cxx new file mode 100644 index 000000000000..29d3f38278f4 --- /dev/null +++ b/dbaccess/source/core/api/RowSetCacheIterator.cxx @@ -0,0 +1,152 @@ +/************************************************************************* + * + * 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_dbaccess.hxx" +#ifndef DBACCESS_ROWSETCACHEITERATOR_HXX +#include "RowSetCacheIterator.hxx" +#endif +#ifndef DBACCESS_CORE_API_ROWSETCACHE_HXX +#include "RowSetCache.hxx" +#endif +#ifndef DBACCESS_CORE_API_ROWSETBASE_HXX +#include "RowSetBase.hxx" +#endif +#include <rtl/logfile.hxx> + +using namespace dbaccess; +ORowSetCacheIterator::ORowSetCacheIterator(const ORowSetCacheIterator& _rRH) +: m_aIter(_rRH.m_aIter) +, m_pCache(_rRH.m_pCache) +,m_pRowSet(_rRH.m_pRowSet) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetCacheIterator::ORowSetCacheIterator" ); +} +// ----------------------------------------------------------------------------- +ORowSetCacheIterator::operator ORowSetMatrix::iterator() +{ + return m_aIter->second.aIterator; +} +// ----------------------------------------------------------------------------- +ORowSetCacheIterator& ORowSetCacheIterator::operator =(const ORowSetCacheIterator& _rRH) +{ + if(this == &_rRH) + return *this; + + m_pCache = _rRH.m_pCache; + m_aIter = _rRH.m_aIter; + m_pRowSet = _rRH.m_pRowSet; + + return *this; +} +// ----------------------------------------------------------------------------- +ORowSetCacheIterator& ORowSetCacheIterator::operator =(const ORowSetMatrix::iterator& _rIter) +{ + m_aIter->second.aIterator = _rIter; + return *this; +} +// ----------------------------------------------------------------------------- +ORowSetRow& ORowSetCacheIterator::operator *() +{ + return *m_aIter->second.aIterator; +} +// ----------------------------------------------------------------------------- +const ORowSetRow& ORowSetCacheIterator::operator *() const +{ + if ( !m_pRowSet->isInsertRow() && m_aIter->second.aIterator == m_pCache->m_pMatrix->end() ) + { + OSL_ENSURE(m_aIter->second.aBookmark.hasValue(),"bookmark has no value!"); + OSL_VERIFY(m_pCache->moveToBookmark(m_aIter->second.aBookmark)); + m_aIter->second.aIterator = m_pCache->m_aMatrixIter; + } + return *m_aIter->second.aIterator; +} +// ----------------------------------------------------------------------------- +ORowSetMatrix::iterator& ORowSetCacheIterator::operator ->() +{ + return m_aIter->second.aIterator; +} +// ----------------------------------------------------------------------------- +const ORowSetMatrix::iterator& ORowSetCacheIterator::operator ->() const +{ + if ( !m_pRowSet->isInsertRow() && m_aIter->second.aIterator == m_pCache->m_pMatrix->end() ) + { + OSL_ENSURE(m_aIter->second.aBookmark.hasValue(),"bookmark has no value!"); + OSL_VERIFY(m_pCache->moveToBookmark(m_aIter->second.aBookmark)); + m_aIter->second.aIterator = m_pCache->m_aMatrixIter; + } + return m_aIter->second.aIterator; +} +// ----------------------------------------------------------------------------- +bool ORowSetCacheIterator::operator <=(const ORowSetMatrix::iterator& _rRH) const +{ + return m_aIter->second.aIterator <= _rRH; +} +// ----------------------------------------------------------------------------- +bool ORowSetCacheIterator::operator <(const ORowSetMatrix::iterator& _rRH) const +{ + return m_aIter->second.aIterator < _rRH; +} +// ----------------------------------------------------------------------------- +bool ORowSetCacheIterator::operator !=(const ORowSetMatrix::iterator& _rRH) const +{ + return m_aIter->second.aIterator != _rRH; +} +// ----------------------------------------------------------------------------- +bool ORowSetCacheIterator::operator ==(const ORowSetMatrix::iterator& _rRH) const +{ + return m_aIter->second.aIterator == _rRH; +} +// ----------------------------------------------------------------------------- +void ORowSetCacheIterator::setBookmark(const ::com::sun::star::uno::Any& _rBookmark) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetCacheIterator::setBookmark" ); + m_aIter->second.aBookmark = _rBookmark; +} +// ----------------------------------------------------------------------------- +sal_Bool ORowSetCacheIterator::isNull() const +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetCacheIterator::isNull" ); + sal_Bool bRet = !m_pCache || !m_pRowSet || m_aIter == m_pCache->m_aCacheIterators.end(); + if ( !bRet ) + { + ORowSetCacheIterator_Helper aHelper = m_aIter->second; + bRet = ( m_pRowSet->isInsertRow() + ? + m_aIter->second.aIterator == m_pCache->m_pInsertMatrix->end() + : + m_aIter->second.aIterator == m_pCache->m_pMatrix->end() + ); + } + return bRet; +} +// ----------------------------------------------------------------------------- +::osl::Mutex* ORowSetCacheIterator::getMutex() const +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ORowSetCacheIterator::getMutex" ); + return m_pRowSet ? m_pRowSet->getMutex() : NULL; +} diff --git a/dbaccess/source/core/api/RowSetCacheIterator.hxx b/dbaccess/source/core/api/RowSetCacheIterator.hxx new file mode 100644 index 000000000000..6c4c1a8576ce --- /dev/null +++ b/dbaccess/source/core/api/RowSetCacheIterator.hxx @@ -0,0 +1,92 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ +#ifndef DBACCESS_ROWSETCACHEITERATOR_HXX +#define DBACCESS_ROWSETCACHEITERATOR_HXX + +#ifndef DBACCESS_CORE_API_ROWSETROW_HXX +#include "RowSetRow.hxx" +#endif +#ifndef _COMPHELPER_STLTYPES_HXX_ +#include <comphelper/stl_types.hxx> +#endif + +namespace dbaccess +{ + class ORowSetBase; + typedef struct + { + ORowSetMatrix::iterator aIterator; + ::com::sun::star::uno::Any aBookmark; + ORowSetBase* pRowSet; + } ORowSetCacheIterator_Helper; + + DECLARE_STL_STDKEY_MAP(sal_Int32,ORowSetCacheIterator_Helper,ORowSetCacheMap); + + class ORowSetCache; + class ORowSetCacheIterator + { + friend class ORowSetCache; + ORowSetCacheMap::iterator m_aIter; + ORowSetCache* m_pCache; + ORowSetBase* m_pRowSet; + protected: + ORowSetCacheIterator(const ORowSetCacheMap::iterator& _rIter,ORowSetCache* _pCache,ORowSetBase* _pRowSet) + : m_aIter(_rIter) + ,m_pCache(_pCache) + ,m_pRowSet(_pRowSet) + { + } + public: + ORowSetCacheIterator() :m_aIter(),m_pCache(NULL),m_pRowSet(NULL){} + ORowSetCacheIterator(const ORowSetCacheIterator& _rRH); + ORowSetCacheIterator& operator =(const ORowSetCacheIterator&); + + sal_Bool isNull() const; + ORowSetCacheIterator& operator =(const ORowSetMatrix::iterator&); + operator ORowSetMatrix::iterator(); + + ORowSetRow& operator *(); + const ORowSetRow& operator *() const; + + ORowSetMatrix::iterator& operator ->(); + const ORowSetMatrix::iterator& operator ->() const; + + bool operator <=(const ORowSetMatrix::iterator& _rRH) const; + bool operator <(const ORowSetMatrix::iterator& _rRH) const; + bool operator !=(const ORowSetMatrix::iterator& _rRH) const; + bool operator ==(const ORowSetMatrix::iterator& _rRH) const; + + void setBookmark(const ::com::sun::star::uno::Any& _rBookmark); + ::com::sun::star::uno::Any getBookmark() const { return m_aIter->second.aBookmark; } + ::osl::Mutex* getMutex() const; + + ORowSetCacheMap::iterator getIter() const { return m_aIter; } + }; +} +#endif // DBACCESS_ROWSETCACHEITERATOR_HXX + + diff --git a/dbaccess/source/core/api/RowSetRow.hxx b/dbaccess/source/core/api/RowSetRow.hxx new file mode 100644 index 000000000000..1178c2990b83 --- /dev/null +++ b/dbaccess/source/core/api/RowSetRow.hxx @@ -0,0 +1,108 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ +#ifndef DBACCESS_CORE_API_ROWSETROW_HXX +#define DBACCESS_CORE_API_ROWSETROW_HXX + +#ifndef _VOS_REF_HXX_ +#include <vos/ref.hxx> +#endif +#ifndef _CONNECTIVITY_COMMONTOOLS_HXX_ +#include <connectivity/CommonTools.hxx> +#endif +#ifndef _CONNECTIVITY_FILE_VALUE_HXX_ +#include "connectivity/FValue.hxx" +#endif +#ifndef _COMPHELPER_TYPES_HXX_ +#include <comphelper/types.hxx> +#endif + +namespace dbaccess +{ + typedef connectivity::ORowVector< connectivity::ORowSetValue > ORowSetValueVector; + typedef ::vos::ORef< ORowSetValueVector > ORowSetRow; + typedef ::std::vector< ORowSetRow > ORowSetMatrix; + + class ORowSetOldRowHelper + { + oslInterlockedCount m_refCount; + ORowSetRow m_aRow; + + ORowSetOldRowHelper& operator=(const ORowSetOldRowHelper& _rRH); + ORowSetOldRowHelper(const ORowSetOldRowHelper& _rRh); + public: + ORowSetOldRowHelper() : m_refCount(0){} + ORowSetOldRowHelper(const ORowSetRow& _rRow) + : m_refCount(0) + , m_aRow(_rRow) + {} +// ORowSetOldRowHelper(const ORowSetOldRowHelper& _rRh) +// : m_refCount(0) +// , m_aRow(_rRh.m_aRow) +// {} + + void acquire() + { + osl_incrementInterlockedCount( &m_refCount ); + } + void release() + { + if (! osl_decrementInterlockedCount( &m_refCount )) + delete this; + } + inline ORowSetRow getRow() const { return m_aRow; } + inline void clearRow() { m_aRow = NULL; } + inline void setRow(const ORowSetRow& _rRow) { m_aRow = _rRow; } + }; + + typedef ::vos::ORef< ORowSetOldRowHelper > TORowSetOldRowHelperRef; + + class ORowSetValueCompare + { + const ::com::sun::star::uno::Any& m_rAny; + public: + ORowSetValueCompare(const ::com::sun::star::uno::Any& _rAny) : m_rAny(_rAny){} + + sal_Bool operator ()(const ORowSetRow& _rRH) + { + switch((_rRH->get())[0].getTypeKind()) + { + case ::com::sun::star::sdbc::DataType::TINYINT: + case ::com::sun::star::sdbc::DataType::SMALLINT: + case ::com::sun::star::sdbc::DataType::INTEGER: + return comphelper::getINT32(m_rAny) == (sal_Int32)(_rRH->get())[0]; + default: + { + ::com::sun::star::uno::Sequence<sal_Int8> aSeq; + m_rAny >>= aSeq; + return aSeq == (_rRH->get())[0]; + } + } + } + }; +} +#endif // DBACCESS_CORE_API_ROWSETROW_HXX + diff --git a/dbaccess/source/core/api/SingleSelectQueryComposer.cxx b/dbaccess/source/core/api/SingleSelectQueryComposer.cxx new file mode 100644 index 000000000000..2f9a58c975b7 --- /dev/null +++ b/dbaccess/source/core/api/SingleSelectQueryComposer.cxx @@ -0,0 +1,1875 @@ +/************************************************************************* + * + * 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_dbaccess.hxx" + +#include "composertools.hxx" +#include "core_resource.hrc" +#include "core_resource.hxx" +#include "dbastrings.hrc" +#include "HelperCollections.hxx" +#include "SingleSelectQueryComposer.hxx" +#include "sdbcoretools.hxx" + +/** === begin UNO includes === **/ +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/container/XChild.hpp> +#include <com/sun/star/i18n/XLocaleData.hpp> +#include <com/sun/star/lang/DisposedException.hpp> +#include <com/sun/star/sdb/BooleanComparisonMode.hpp> +#include <com/sun/star/sdb/SQLFilterOperator.hpp> +#include <com/sun/star/sdb/XQueriesSupplier.hpp> +#include <com/sun/star/sdb/CommandType.hpp> +#include <com/sun/star/sdbc/ColumnSearch.hpp> +#include <com/sun/star/sdbc/DataType.hpp> +#include <com/sun/star/sdbc/XResultSetMetaData.hpp> +#include <com/sun/star/sdbc/XResultSetMetaDataSupplier.hpp> +#include <com/sun/star/sdbc/XParameters.hpp> +#include <com/sun/star/uno/XAggregation.hpp> +#include <com/sun/star/util/XNumberFormatter.hpp> +/** === end UNO includes === **/ + +#include <comphelper/processfactory.hxx> +#include <comphelper/sequence.hxx> +#include <comphelper/types.hxx> +#include <cppuhelper/typeprovider.hxx> +#include <rtl/logfile.hxx> +#include <unotools/syslocale.hxx> +#include <tools/debug.hxx> +#include <tools/diagnose_ex.h> +#include <unotools/configmgr.hxx> +#include <unotools/sharedunocomponent.hxx> + +#include <memory> + +using namespace ::dbaccess; +using namespace ::dbtools; +using namespace ::comphelper; +using namespace ::connectivity; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::sdb; +using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::i18n; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::script; +using namespace ::com::sun::star::util; +using namespace ::cppu; +using namespace ::osl; +using namespace ::utl; + +namespace dbaccess { +namespace BooleanComparisonMode = ::com::sun::star::sdb::BooleanComparisonMode; +} + +#define STR_SELECT ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("SELECT ")) +#define STR_FROM ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" FROM ")) +#define STR_WHERE ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" WHERE ")) +#define STR_GROUP_BY ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" GROUP BY ")) +#define STR_HAVING ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" HAVING ")) +#define STR_ORDER_BY ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" ORDER BY ")) +#define STR_AND ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" AND ")) +#define STR_OR ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" OR ")) +#define STR_LIKE ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" LIKE ")) +#define STR_EQUAL ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" = ")) +#define L_BRACKET ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("(")) +#define R_BRACKET ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(")")) +#define COMMA ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(",")) + +// ------------------------------------------------------------------------- +namespace +{ + // ..................................................................... + /** parses the given statement, using the given parser, returns a parse node representing + the statement + + If the statement cannot be parsed, an error is thrown. + */ + const OSQLParseNode* parseStatement_throwError( OSQLParser& _rParser, const ::rtl::OUString& _rStatement, const Reference< XInterface >& _rxContext ) + { + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "frank.schoenheit@sun.com", "SingleSelectQueryComposer.cxx::parseStatement_throwError" ); + ::rtl::OUString aErrorMsg; + const OSQLParseNode* pNewSqlParseNode = _rParser.parseTree( aErrorMsg, _rStatement ); + if ( !pNewSqlParseNode ) + { + ::rtl::OUString sSQLStateGeneralError( getStandardSQLState( SQL_GENERAL_ERROR ) ); + SQLException aError2( aErrorMsg, _rxContext, sSQLStateGeneralError, 1000, Any() ); + SQLException aError1( _rStatement, _rxContext, sSQLStateGeneralError, 1000, makeAny( aError2 ) ); + throw SQLException(_rParser.getContext().getErrorMessage(OParseContext::ERROR_GENERAL),_rxContext,sSQLStateGeneralError,1000,makeAny(aError1)); + } + return pNewSqlParseNode; + } + + // ..................................................................... + /** checks whether the given parse node describes a valid single select statement, throws + an error if not + */ + void checkForSingleSelect_throwError( const OSQLParseNode* pStatementNode, OSQLParseTreeIterator& _rIterator, + const Reference< XInterface >& _rxContext, const ::rtl::OUString& _rOriginatingCommand ) + { + const OSQLParseNode* pOldNode = _rIterator.getParseTree(); + + // determine the statement type + _rIterator.setParseTree( pStatementNode ); + _rIterator.traverseAll(); + bool bIsSingleSelect = ( _rIterator.getStatementType() == SQL_STATEMENT_SELECT ); + + // throw the error, if necessary + if ( !bIsSingleSelect || SQL_ISRULE( pStatementNode, union_statement ) ) // #i4229# OJ + { + // restore the old node before throwing the exception + _rIterator.setParseTree( pOldNode ); + // and now really ... + SQLException aError1( _rOriginatingCommand, _rxContext, getStandardSQLState( SQL_GENERAL_ERROR ), 1000, Any() ); + throw SQLException( DBACORE_RESSTRING( RID_STR_ONLY_QUERY ), _rxContext, + getStandardSQLState( SQL_GENERAL_ERROR ), 1000, makeAny( aError1 ) ); + } + + delete pOldNode; + } + + // ..................................................................... + /** combines parseStatement_throwError and checkForSingleSelect_throwError + */ + void parseAndCheck_throwError( OSQLParser& _rParser, const ::rtl::OUString& _rStatement, + OSQLParseTreeIterator& _rIterator, const Reference< XInterface >& _rxContext ) + { + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "frank.schoenheit@sun.com", "SingleSelectQueryComposer.cxx::parseAndCheck_throwError" ); + const OSQLParseNode* pNode = parseStatement_throwError( _rParser, _rStatement, _rxContext ); + checkForSingleSelect_throwError( pNode, _rIterator, _rxContext, _rStatement ); + } + + // ..................................................................... + /** transforms a parse node describing a complete statement into a pure select + statement, without any filter/order/groupby/having clauses + */ + ::rtl::OUString getPureSelectStatement( const OSQLParseNode* _pRootNode, Reference< XConnection > _rxConnection ) + { + ::rtl::OUString sSQL = STR_SELECT; + _pRootNode->getChild(1)->parseNodeToStr( sSQL, _rxConnection ); + _pRootNode->getChild(2)->parseNodeToStr( sSQL, _rxConnection ); + sSQL += STR_FROM; + _pRootNode->getChild(3)->getChild(0)->getChild(1)->parseNodeToStr( sSQL, _rxConnection ); + return sSQL; + } + + /** resets an SQL iterator, including deletion of the parse tree, and disposal if desired + */ + void resetIterator( OSQLParseTreeIterator& _rIterator, bool _bDispose ) + { + const OSQLParseNode* pSqlParseNode = _rIterator.getParseTree(); + _rIterator.setParseTree(NULL); + delete pSqlParseNode; + if ( _bDispose ) + _rIterator.dispose(); + } + void lcl_addFilterCriteria_throw(sal_Int32 i_nFilterOperator,const ::rtl::OUString& i_sValue,::rtl::OUStringBuffer& o_sRet) + { + switch( i_nFilterOperator ) + { + case SQLFilterOperator::EQUAL: + o_sRet.append(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" = "))); + o_sRet.append(i_sValue); + break; + case SQLFilterOperator::NOT_EQUAL: + o_sRet.append(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" <> "))); + o_sRet.append(i_sValue); + break; + case SQLFilterOperator::LESS: + o_sRet.append(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" < "))); + o_sRet.append(i_sValue); + break; + case SQLFilterOperator::GREATER: + o_sRet.append(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" > "))); + o_sRet.append(i_sValue); + break; + case SQLFilterOperator::LESS_EQUAL: + o_sRet.append(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" <= "))); + o_sRet.append(i_sValue); + break; + case SQLFilterOperator::GREATER_EQUAL: + o_sRet.append(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" >= "))); + o_sRet.append(i_sValue); + break; + case SQLFilterOperator::LIKE: + o_sRet.append(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" LIKE "))); + o_sRet.append(i_sValue); + break; + case SQLFilterOperator::NOT_LIKE: + o_sRet.append(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" NOT LIKE "))); + o_sRet.append(i_sValue); + break; + case SQLFilterOperator::SQLNULL: + o_sRet.append(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" IS NULL")) ); + break; + case SQLFilterOperator::NOT_SQLNULL: + o_sRet.append(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" IS NOT NULL")) ); + break; + default: + throw SQLException(); + } + } + +} + +DBG_NAME(OSingleSelectQueryComposer) +// ------------------------------------------------------------------------- +OSingleSelectQueryComposer::OSingleSelectQueryComposer(const Reference< XNameAccess>& _rxTables, + const Reference< XConnection>& _xConnection, + const ::comphelper::ComponentContext& _rContext ) + :OSubComponent(m_aMutex,_xConnection) + ,OPropertyContainer(m_aBHelper) + ,m_aSqlParser( _rContext.getLegacyServiceFactory() ) + ,m_aSqlIterator( _xConnection, _rxTables, m_aSqlParser, NULL ) + ,m_aAdditiveIterator( _xConnection, _rxTables, m_aSqlParser, NULL ) + ,m_aElementaryParts( (size_t)SQLPartCount ) + ,m_xConnection(_xConnection) + ,m_xMetaData(_xConnection->getMetaData()) + ,m_xConnectionTables( _rxTables ) + ,m_aContext( _rContext ) + ,m_pTables(NULL) + ,m_nBoolCompareMode( BooleanComparisonMode::EQUAL_INTEGER ) + ,m_nCommandType(CommandType::COMMAND) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::OSingleSelectQueryComposer" ); + DBG_CTOR(OSingleSelectQueryComposer,NULL); + + if ( !m_aContext.is() || !m_xConnection.is() || !m_xConnectionTables.is() ) + throw IllegalArgumentException(); + + registerProperty(PROPERTY_ORIGINAL,PROPERTY_ID_ORIGINAL,PropertyAttribute::BOUND|PropertyAttribute::READONLY,&m_sOrignal,::getCppuType(&m_sOrignal)); + + m_aCurrentColumns.resize(4); + + m_aLocale = SvtSysLocale().GetLocaleData().getLocale(); + m_xNumberFormatsSupplier = dbtools::getNumberFormats( m_xConnection, sal_True, m_aContext.getLegacyServiceFactory() ); + Reference< XLocaleData > xLocaleData; + m_aContext.createComponent( "com.sun.star.i18n.LocaleData", xLocaleData ); + LocaleDataItem aData = xLocaleData->getLocaleItem(m_aLocale); + m_sDecimalSep = aData.decimalSeparator; + OSL_ENSURE(m_sDecimalSep.getLength() == 1,"OSingleSelectQueryComposer::OSingleSelectQueryComposer decimal separator is not 1 length"); + try + { + Any aValue; + Reference<XInterface> xDs = dbaccess::getDataSource(_xConnection); + if ( dbtools::getDataSourceSetting(xDs,static_cast <rtl::OUString> (PROPERTY_BOOLEANCOMPARISONMODE),aValue) ) + { + OSL_VERIFY( aValue >>= m_nBoolCompareMode ); + } + Reference< XQueriesSupplier > xQueriesAccess(m_xConnection, UNO_QUERY); + if (xQueriesAccess.is()) + m_xConnectionQueries = xQueriesAccess->getQueries(); + } + catch(Exception&) + { + } +} +// ------------------------------------------------------------------------- +OSingleSelectQueryComposer::~OSingleSelectQueryComposer() +{ + DBG_DTOR(OSingleSelectQueryComposer,NULL); + ::std::vector<OPrivateColumns*>::iterator aColIter = m_aColumnsCollection.begin(); + ::std::vector<OPrivateColumns*>::iterator aEnd = m_aColumnsCollection.end(); + for(;aColIter != aEnd;++aColIter) + delete *aColIter; + + ::std::vector<OPrivateTables*>::iterator aTabIter = m_aTablesCollection.begin(); + ::std::vector<OPrivateTables*>::iterator aTabEnd = m_aTablesCollection.end(); + for(;aTabIter != aTabEnd;++aTabIter) + delete *aTabIter; +} +// ------------------------------------------------------------------------- +// OComponentHelper +void SAL_CALL OSingleSelectQueryComposer::disposing(void) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::disposing" ); + OSubComponent::disposing(); + + MutexGuard aGuard(m_aMutex); + + resetIterator( m_aSqlIterator, true ); + resetIterator( m_aAdditiveIterator, true ); + + m_xConnectionTables = NULL; + m_xConnection = NULL; + + clearCurrentCollections(); +} +IMPLEMENT_FORWARD_XINTERFACE3(OSingleSelectQueryComposer,OSubComponent,OSingleSelectQueryComposer_BASE,OPropertyContainer) +IMPLEMENT_SERVICE_INFO1(OSingleSelectQueryComposer,"org.openoffice.comp.dba.OSingleSelectQueryComposer",SERVICE_NAME_SINGLESELECTQUERYCOMPOSER) +IMPLEMENT_TYPEPROVIDER3(OSingleSelectQueryComposer,OSubComponent,OSingleSelectQueryComposer_BASE,OPropertyContainer) +IMPLEMENT_PROPERTYCONTAINER_DEFAULTS(OSingleSelectQueryComposer) + +// ------------------------------------------------------------------------- +// com::sun::star::lang::XUnoTunnel +sal_Int64 SAL_CALL OSingleSelectQueryComposer::getSomething( const Sequence< sal_Int8 >& rId ) throw(RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getSomething" ); + if (rId.getLength() == 16 && 0 == rtl_compareMemory(getImplementationId().getConstArray(), rId.getConstArray(), 16 ) ) + return reinterpret_cast<sal_Int64>(this); + + return sal_Int64(0); +} + +// ------------------------------------------------------------------------- +// XSingleSelectQueryAnalyzer +::rtl::OUString SAL_CALL OSingleSelectQueryComposer::getQuery( ) throw(RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getQuery" ); + ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed); + ::osl::MutexGuard aGuard( m_aMutex ); + + TGetParseNode F_tmp(&OSQLParseTreeIterator::getParseTree); + return getStatementPart(F_tmp,m_aSqlIterator); +} + +// ------------------------------------------------------------------------- +void SAL_CALL OSingleSelectQueryComposer::setQuery( const ::rtl::OUString& command ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "frank.schoenheit@sun.com", "OSingleSelectQueryComposer::setQuery" ); + ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed); + + ::osl::MutexGuard aGuard( m_aMutex ); + m_nCommandType = CommandType::COMMAND; + // first clear the tables and columns + clearCurrentCollections(); + // now set the new one + setQuery_Impl(command); + m_sOrignal = command; + + // reset the additive iterator to the same statement + parseAndCheck_throwError( m_aSqlParser, m_sOrignal, m_aAdditiveIterator, *this ); + + // we have no "elementary" parts anymore (means filter/groupby/having/order clauses) + for ( SQLPart eLoopParts = Where; eLoopParts != SQLPartCount; incSQLPart( eLoopParts ) ) + m_aElementaryParts[ eLoopParts ] = ::rtl::OUString(); +} +// ------------------------------------------------------------------------- +void SAL_CALL OSingleSelectQueryComposer::setCommand( const ::rtl::OUString& Command,sal_Int32 _nCommandType ) throw(SQLException, RuntimeException) +{ + ::rtl::OUStringBuffer sSQL; + switch(_nCommandType) + { + case CommandType::COMMAND: + setElementaryQuery(Command); + return; + case CommandType::TABLE: + if ( m_xConnectionTables->hasByName(Command) ) + { + sSQL.appendAscii("SELECT * FROM "); + Reference< XPropertySet > xTable; + try + { + m_xConnectionTables->getByName( Command ) >>= xTable; + } + catch(const WrappedTargetException& e) + { + SQLException e2; + if ( e.TargetException >>= e2 ) + throw e2; + } + catch(Exception&) + { + DBG_UNHANDLED_EXCEPTION(); + } + + sSQL.append(dbtools::composeTableNameForSelect(m_xConnection,xTable)); + } + else + { + String sMessage( DBACORE_RESSTRING( RID_STR_TABLE_DOES_NOT_EXIST ) ); + sMessage.SearchAndReplaceAscii( "$table$", Command ); + throwGenericSQLException(sMessage,*this); + } + break; + case CommandType::QUERY: + if ( m_xConnectionQueries->hasByName(Command) ) + { + + Reference<XPropertySet> xQuery(m_xConnectionQueries->getByName(Command),UNO_QUERY); + ::rtl::OUString sCommand; + xQuery->getPropertyValue(PROPERTY_COMMAND) >>= sCommand; + sSQL.append(sCommand); + } + else + { + String sMessage( DBACORE_RESSTRING( RID_STR_QUERY_DOES_NOT_EXIST ) ); + sMessage.SearchAndReplaceAscii( "$table$", Command ); + throwGenericSQLException(sMessage,*this); + } + + break; + default: + break; + } + ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed); + + ::osl::MutexGuard aGuard( m_aMutex ); + m_nCommandType = _nCommandType; + m_sCommand = Command; + // first clear the tables and columns + clearCurrentCollections(); + // now set the new one + ::rtl::OUString sCommand = sSQL.makeStringAndClear(); + setElementaryQuery(sCommand); + m_sOrignal = sCommand; +/* + // reset the additive iterator to the same statement + parseAndCheck_throwError( m_aSqlParser, m_sOrignal, m_aAdditiveIterator, *this ); + + // we have no "elementary" parts anymore (means filter/groupby/having/order clauses) + for ( SQLPart eLoopParts = Where; eLoopParts != SQLPartCount; incSQLPart( eLoopParts ) ) + m_aElementaryParts[ eLoopParts ] = ::rtl::OUString(); +*/ +} +// ----------------------------------------------------------------------------- +void OSingleSelectQueryComposer::setQuery_Impl( const ::rtl::OUString& command ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "frank.schoenheit@sun.com", "OSingleSelectQueryComposer::setQuery_Impl" ); + // parse this + parseAndCheck_throwError( m_aSqlParser, command, m_aSqlIterator, *this ); + + // strip it from all clauses, to have the pure SELECT statement + m_aPureSelectSQL = getPureSelectStatement( m_aSqlIterator.getParseTree(), m_xConnection ); + + // update columns and tables + // why? Shouldn't this be done on request only? + // otherwise nothing is working anymore :-) +// getColumns(); + getTables(); +} +// ----------------------------------------------------------------------------- +Sequence< Sequence< PropertyValue > > SAL_CALL OSingleSelectQueryComposer::getStructuredHavingClause( ) throw (RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getStructuredHavingClause" ); + TGetParseNode F_tmp(&OSQLParseTreeIterator::getSimpleHavingTree); + return getStructuredCondition(F_tmp); +} +// ------------------------------------------------------------------------- +Sequence< Sequence< PropertyValue > > SAL_CALL OSingleSelectQueryComposer::getStructuredFilter( ) throw(RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getStructuredFilter" ); + TGetParseNode F_tmp(&OSQLParseTreeIterator::getSimpleWhereTree); + return getStructuredCondition(F_tmp); +} +// ----------------------------------------------------------------------------- +void SAL_CALL OSingleSelectQueryComposer::appendHavingClauseByColumn( const Reference< XPropertySet >& column, sal_Bool andCriteria,sal_Int32 filterOperator ) throw (SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::appendHavingClauseByColumn" ); + ::std::mem_fun1_t<bool,OSingleSelectQueryComposer,::rtl::OUString> F_tmp(&OSingleSelectQueryComposer::implSetHavingClause); + setConditionByColumn(column,andCriteria,F_tmp,filterOperator); +} +// ----------------------------------------------------------------------------- +void SAL_CALL OSingleSelectQueryComposer::appendFilterByColumn( const Reference< XPropertySet >& column, sal_Bool andCriteria,sal_Int32 filterOperator ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::appendFilterByColumn" ); + ::std::mem_fun1_t<bool,OSingleSelectQueryComposer,::rtl::OUString> F_tmp(&OSingleSelectQueryComposer::implSetFilter); + setConditionByColumn(column,andCriteria,F_tmp,filterOperator); +} +// ----------------------------------------------------------------------------- +::rtl::OUString OSingleSelectQueryComposer::impl_getColumnName_throw(const Reference< XPropertySet >& column) +{ + ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed); + + getColumns(); + if ( !column.is() + || !m_aCurrentColumns[SelectColumns] + || !column->getPropertySetInfo()->hasPropertyByName(PROPERTY_NAME) + ) + { + String sError(DBACORE_RESSTRING(RID_STR_COLUMN_UNKNOWN_PROP)); + sError.SearchAndReplaceAscii("%value", ::rtl::OUString(PROPERTY_NAME)); + SQLException aErr(sError,*this,SQLSTATE_GENERAL,1000,Any() ); + throw SQLException(DBACORE_RESSTRING(RID_STR_COLUMN_NOT_VALID),*this,SQLSTATE_GENERAL,1000,makeAny(aErr) ); + } + + ::rtl::OUString aName,aNewName; + column->getPropertyValue(PROPERTY_NAME) >>= aName; + + if ( !m_xMetaData->supportsOrderByUnrelated() && m_aCurrentColumns[SelectColumns] && !m_aCurrentColumns[SelectColumns]->hasByName(aName)) + { + String sError(DBACORE_RESSTRING(RID_STR_COLUMN_MUST_VISIBLE)); + sError.SearchAndReplaceAscii("%name", aName); + throw SQLException(sError,*this,SQLSTATE_GENERAL,1000,Any() ); + } + + // filter anhaengen + // select ohne where und order by aufbauen + ::rtl::OUString aQuote = m_xMetaData->getIdentifierQuoteString(); + if ( m_aCurrentColumns[SelectColumns]->hasByName(aName) ) + { + Reference<XPropertySet> xColumn; + m_aCurrentColumns[SelectColumns]->getByName(aName) >>= xColumn; + OSL_ENSURE(xColumn->getPropertySetInfo()->hasPropertyByName(PROPERTY_REALNAME),"Property REALNAME not available!"); + OSL_ENSURE(xColumn->getPropertySetInfo()->hasPropertyByName(PROPERTY_TABLENAME),"Property TABLENAME not available!"); + OSL_ENSURE(xColumn->getPropertySetInfo()->hasPropertyByName(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Function"))),"Property FUNCTION not available!"); + + ::rtl::OUString sRealName,sTableName; + xColumn->getPropertyValue(PROPERTY_REALNAME) >>= sRealName; + xColumn->getPropertyValue(PROPERTY_TABLENAME) >>= sTableName; + sal_Bool bFunction = sal_False; + xColumn->getPropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Function"))) >>= bFunction; + if ( sRealName == aName ) + { + if ( bFunction ) + aNewName = aName; + else + { + if(sTableName.indexOf('.',0) != -1) + { + ::rtl::OUString aCatlog,aSchema,aTable; + ::dbtools::qualifiedNameComponents(m_xMetaData,sTableName,aCatlog,aSchema,aTable,::dbtools::eInDataManipulation); + sTableName = ::dbtools::composeTableName( m_xMetaData, aCatlog, aSchema, aTable, sal_True, ::dbtools::eInDataManipulation ); + } + else + sTableName = ::dbtools::quoteName(aQuote,sTableName); + + aNewName = sTableName; + aNewName += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(".")); + aNewName += ::dbtools::quoteName(aQuote,sRealName); + } + } + else + aNewName = ::dbtools::quoteName(aQuote,aName); + } + else + aNewName = getTableAlias(column) + ::dbtools::quoteName(aQuote,aName); + return aNewName; +} +// ------------------------------------------------------------------------- +void SAL_CALL OSingleSelectQueryComposer::appendOrderByColumn( const Reference< XPropertySet >& column, sal_Bool ascending ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::appendOrderByColumn" ); + ::osl::MutexGuard aGuard( m_aMutex ); + ::rtl::OUString sColumnName( impl_getColumnName_throw(column) ); + ::rtl::OUString sOrder = getOrder(); + if ( (sOrder.getLength() != 0) && sColumnName.getLength() ) + sOrder += COMMA; + sOrder += sColumnName; + if ( !ascending && sColumnName.getLength() ) + sOrder += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" DESC ")); + + setOrder(sOrder); +} + +// ------------------------------------------------------------------------- +void SAL_CALL OSingleSelectQueryComposer::appendGroupByColumn( const Reference< XPropertySet >& column) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::appendGroupByColumn" ); + ::osl::MutexGuard aGuard( m_aMutex ); + ::rtl::OUString sColumnName( impl_getColumnName_throw(column) ); + OrderCreator aComposer; + aComposer.append( getGroup() ); + aComposer.append( sColumnName ); + setGroup( aComposer.getComposedAndClear() ); +} +// ------------------------------------------------------------------------- +::rtl::OUString OSingleSelectQueryComposer::composeStatementFromParts( const ::std::vector< ::rtl::OUString >& _rParts ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::composeStatementFromParts" ); + DBG_ASSERT( _rParts.size() == (size_t)SQLPartCount, "OSingleSelectQueryComposer::composeStatementFromParts: invalid parts array!" ); + + ::rtl::OUStringBuffer aSql( m_aPureSelectSQL ); + for ( SQLPart eLoopParts = Where; eLoopParts != SQLPartCount; incSQLPart( eLoopParts ) ) + if ( _rParts[ eLoopParts ].getLength() ) + { + aSql.append( getKeyword( eLoopParts ) ); + aSql.append( _rParts[ eLoopParts ] ); + } + + return aSql.makeStringAndClear(); +} + +// ------------------------------------------------------------------------- +::rtl::OUString SAL_CALL OSingleSelectQueryComposer::getElementaryQuery() throw (::com::sun::star::uno::RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getElementaryQuery" ); + return composeStatementFromParts( m_aElementaryParts ); +} + +// ------------------------------------------------------------------------- +void SAL_CALL OSingleSelectQueryComposer::setElementaryQuery( const ::rtl::OUString& _rElementary ) throw (::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "frank.schoenheit@sun.com", "OSingleSelectQueryComposer::setElementaryQuery" ); + ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed); + ::osl::MutexGuard aGuard( m_aMutex ); + + // remember the 4 current "additive" clauses + ::std::vector< ::rtl::OUString > aAdditiveClauses( SQLPartCount ); + for ( SQLPart eLoopParts = Where; eLoopParts != SQLPartCount; incSQLPart( eLoopParts ) ) + aAdditiveClauses[ eLoopParts ] = getSQLPart( eLoopParts, m_aAdditiveIterator, sal_False ); + + // clear the tables and columns + clearCurrentCollections(); + // set and parse the new query + setQuery_Impl( _rElementary ); + + // get the 4 elementary parts of the statement + for ( SQLPart eLoopParts = Where; eLoopParts != SQLPartCount; incSQLPart( eLoopParts ) ) + m_aElementaryParts[ eLoopParts ] = getSQLPart( eLoopParts, m_aSqlIterator, sal_False ); + + // reset the the AdditiveIterator: m_aPureSelectSQL may have changed + try + { + parseAndCheck_throwError( m_aSqlParser, composeStatementFromParts( aAdditiveClauses ), m_aAdditiveIterator, *this ); + } + catch( const Exception& e ) + { + (void)e; + DBG_ERROR( "OSingleSelectQueryComposer::setElementaryQuery: there should be no error anymore for the additive statement!" ); + // every part of the additive statement should have passed other tests already, and should not + // be able to cause any errors ... me thinks + } +} + +// ------------------------------------------------------------------------- +namespace +{ + ::rtl::OUString getComposedClause( const ::rtl::OUString _rElementaryClause, const ::rtl::OUString _rAdditionalClause, + TokenComposer& _rComposer, const ::rtl::OUString _rKeyword ) + { + _rComposer.clear(); + _rComposer.append( _rElementaryClause ); + _rComposer.append( _rAdditionalClause ); + ::rtl::OUString sComposed = _rComposer.getComposedAndClear(); + if ( sComposed.getLength() ) + sComposed = _rKeyword + sComposed; + return sComposed; + } +} + +// ------------------------------------------------------------------------- +void OSingleSelectQueryComposer::setSingleAdditiveClause( SQLPart _ePart, const ::rtl::OUString& _rClause ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::setSingleAdditiveClause" ); + ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed); + ::osl::MutexGuard aGuard( m_aMutex ); + + // if nothing is changed, do nothing + if ( getSQLPart( _ePart, m_aAdditiveIterator, sal_False ) == _rClause ) + return; + + // collect the 4 single parts as they're currently set + ::std::vector< ::rtl::OUString > aClauses; + aClauses.reserve( (size_t)SQLPartCount ); + for ( SQLPart eLoopParts = Where; eLoopParts != SQLPartCount; incSQLPart( eLoopParts ) ) + aClauses.push_back( getSQLPart( eLoopParts, m_aSqlIterator, sal_True ) ); + + // overwrite the one part in question here + ::std::auto_ptr< TokenComposer > pComposer; + if ( ( _ePart == Where ) || ( _ePart == Having ) ) + pComposer.reset( new FilterCreator ); + else + pComposer.reset( new OrderCreator ); + aClauses[ _ePart ] = getComposedClause( m_aElementaryParts[ _ePart ], _rClause, + *pComposer, getKeyword( _ePart ) ); + + // construct the complete statement + ::rtl::OUStringBuffer aSql(m_aPureSelectSQL); + for ( SQLPart eLoopParts = Where; eLoopParts != SQLPartCount; incSQLPart( eLoopParts ) ) + aSql.append(aClauses[ eLoopParts ]); + + // set the query + setQuery_Impl(aSql.makeStringAndClear()); + + // clear column collections which (might) have changed + clearColumns( ParameterColumns ); + if ( _ePart == Order ) + clearColumns( OrderColumns ); + if ( _ePart == Group ) + clearColumns( GroupByColumns ); + + // also, since the "additive filter" change, we need to rebuild our "additive" statement + aSql = m_aPureSelectSQL; + // again, first get all the old additive parts + for ( SQLPart eLoopParts = Where; eLoopParts != SQLPartCount; incSQLPart( eLoopParts ) ) + aClauses[ eLoopParts ] = getSQLPart( eLoopParts, m_aAdditiveIterator, sal_True ); + // then overwrite the one in question + aClauses[ _ePart ] = getComposedClause( ::rtl::OUString(), _rClause, *pComposer, getKeyword( _ePart ) ); + // and parse it, so that m_aAdditiveIterator is up to date + for ( SQLPart eLoopParts = Where; eLoopParts != SQLPartCount; incSQLPart( eLoopParts ) ) + aSql.append(aClauses[ eLoopParts ]); + try + { + parseAndCheck_throwError( m_aSqlParser, aSql.makeStringAndClear(), m_aAdditiveIterator, *this ); + } + catch( const Exception& e ) + { + (void)e; + DBG_ERROR( "OSingleSelectQueryComposer::setSingleAdditiveClause: there should be no error anymore for the additive statement!" ); + // every part of the additive statement should have passed other tests already, and should not + // be able to cause any errors ... me thinks + } +} + +// ------------------------------------------------------------------------- +void SAL_CALL OSingleSelectQueryComposer::setFilter( const ::rtl::OUString& filter ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::setFilter" ); + setSingleAdditiveClause( Where, filter ); +} + +// ------------------------------------------------------------------------- +void SAL_CALL OSingleSelectQueryComposer::setOrder( const ::rtl::OUString& order ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::setOrder" ); + setSingleAdditiveClause( Order, order ); +} +// ----------------------------------------------------------------------------- +void SAL_CALL OSingleSelectQueryComposer::setGroup( const ::rtl::OUString& group ) throw (SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::setGroup" ); + setSingleAdditiveClause( Group, group ); +} +// ------------------------------------------------------------------------- +void SAL_CALL OSingleSelectQueryComposer::setHavingClause( const ::rtl::OUString& filter ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::setHavingClause" ); + setSingleAdditiveClause( Having, filter ); +} + +// ------------------------------------------------------------------------- +// XTablesSupplier +Reference< XNameAccess > SAL_CALL OSingleSelectQueryComposer::getTables( ) throw(RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getTables" ); + ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed); + + ::osl::MutexGuard aGuard( m_aMutex ); + if ( !m_pTables ) + { + const OSQLTables& aTables = m_aSqlIterator.getTables(); + ::std::vector< ::rtl::OUString> aNames; + OSQLTables::const_iterator aEnd = aTables.end(); + for(OSQLTables::const_iterator aIter = aTables.begin(); aIter != aEnd;++aIter) + aNames.push_back(aIter->first); + + m_pTables = new OPrivateTables(aTables,m_xMetaData->supportsMixedCaseQuotedIdentifiers(),*this,m_aMutex,aNames); + } + + return m_pTables; +} +// ------------------------------------------------------------------------- +// XColumnsSupplier +Reference< XNameAccess > SAL_CALL OSingleSelectQueryComposer::getColumns( ) throw(RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getColumns" ); + ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed); + ::osl::MutexGuard aGuard( m_aMutex ); + if ( !!m_aCurrentColumns[SelectColumns] ) + return m_aCurrentColumns[SelectColumns]; + + ::std::vector< ::rtl::OUString> aNames; + ::vos::ORef< OSQLColumns> aSelectColumns; + sal_Bool bCase = sal_True; + Reference< XNameAccess> xQueryColumns; + if ( m_nCommandType == CommandType::QUERY ) + { + Reference<XColumnsSupplier> xSup(m_xConnectionQueries->getByName(m_sCommand),UNO_QUERY); + if(xSup.is()) + xQueryColumns = xSup->getColumns(); + } + + do { + + try + { + SharedUNOComponent< XStatement, DisposableComponent > xStatement; + SharedUNOComponent< XPreparedStatement, DisposableComponent > xPreparedStatement; + + bCase = m_xMetaData->supportsMixedCaseQuotedIdentifiers(); + aSelectColumns = m_aSqlIterator.getSelectColumns(); + + ::rtl::OUStringBuffer aSQL; + aSQL.append( m_aPureSelectSQL ); + aSQL.append( STR_WHERE ); + + // preserve the original WHERE clause + // #i102234# / 2009-06-02 / frank.schoenheit@sun.com + ::rtl::OUString sOriginalWhereClause = getSQLPart( Where, m_aSqlIterator, sal_False ); + if ( sOriginalWhereClause.getLength() ) + { + aSQL.appendAscii( " ( 0 = 1 ) AND ( " ); + aSQL.append( sOriginalWhereClause ); + aSQL.appendAscii( " ) " ); + } + else + { + aSQL.appendAscii( " ( 0 = 1 ) " ); + } + + ::rtl::OUString sGroupBy = getSQLPart( Group, m_aSqlIterator, sal_True ); + if ( sGroupBy.getLength() ) + aSQL.append( sGroupBy ); + + ::rtl::OUString sSQL( aSQL.makeStringAndClear() ); + // normalize the statement so that it doesn't contain any application-level features anymore + ::rtl::OUString sError; + const ::std::auto_ptr< OSQLParseNode > pStatementTree( m_aSqlParser.parseTree( sError, sSQL, false ) ); + DBG_ASSERT( pStatementTree.get(), "OSingleSelectQueryComposer::getColumns: could not parse the column retrieval statement!" ); + if ( pStatementTree.get() ) + if ( !pStatementTree->parseNodeToExecutableStatement( sSQL, m_xConnection, m_aSqlParser, NULL ) ) + break; + + Reference< XResultSetMetaData > xResultSetMeta; + Reference< XResultSetMetaDataSupplier > xResMetaDataSup; + try + { + xPreparedStatement.set( m_xConnection->prepareStatement( sSQL ), UNO_QUERY_THROW ); + xResMetaDataSup.set( xPreparedStatement, UNO_QUERY_THROW ); + xResultSetMeta.set( xResMetaDataSup->getMetaData(), UNO_QUERY_THROW ); + } + catch( const Exception& ) { } + + try + { + if ( !xResultSetMeta.is() ) + { + xStatement.reset( Reference< XStatement >( m_xConnection->createStatement(), UNO_QUERY_THROW ) ); + Reference< XPropertySet > xStatementProps( xStatement, UNO_QUERY_THROW ); + try { xStatementProps->setPropertyValue( PROPERTY_ESCAPE_PROCESSING, makeAny( sal_False ) ); } + catch ( const Exception& ) { DBG_UNHANDLED_EXCEPTION(); } + xResMetaDataSup.set( xStatement->executeQuery( sSQL ), UNO_QUERY_THROW ); + xResultSetMeta.set( xResMetaDataSup->getMetaData(), UNO_QUERY_THROW ); + } + } + catch( const Exception& ) + { + //@see issue http://qa.openoffice.org/issues/show_bug.cgi?id=110111 + // access returns a different order of column names when executing select * from + // and asking the columns from the metadata. + Reference< XParameters > xParameters( xPreparedStatement, UNO_QUERY_THROW ); + Reference< XIndexAccess > xPara = getParameters(); + for(sal_Int32 i = 1;i <= xPara->getCount();++i) + xParameters->setNull(i,DataType::VARCHAR); + xResMetaDataSup.set(xPreparedStatement->executeQuery(), UNO_QUERY_THROW ); + xResultSetMeta.set( xResMetaDataSup->getMetaData(), UNO_QUERY_THROW ); + } + + if ( aSelectColumns->get().empty() ) + { + // This is a valid case. If we can syntactically parse the query, but not semantically + // (e.g. because it is based on a table we do not know), then there will be no SelectColumns + aSelectColumns = ::connectivity::parse::OParseColumn::createColumnsForResultSet( xResultSetMeta, m_xMetaData ,xQueryColumns); + break; + } + + const ::comphelper::UStringMixEqual aCaseCompare( bCase ); + const ::comphelper::TStringMixEqualFunctor aCaseCompareFunctor( bCase ); + typedef ::std::set< size_t > SizeTSet; + SizeTSet aUsedSelectColumns; + ::connectivity::parse::OParseColumn::StringMap aColumnNames; + + sal_Int32 nCount = xResultSetMeta->getColumnCount(); + OSL_ENSURE( (size_t) nCount == aSelectColumns->get().size(), "OSingleSelectQueryComposer::getColumns: inconsistent column counts, this might result in wrong columns!" ); + for(sal_Int32 i=1;i<=nCount;++i) + { + ::rtl::OUString sColumnName = xResultSetMeta->getColumnName(i); + ::rtl::OUString sColumnLabel; + if ( xQueryColumns.is() && xQueryColumns->hasByName(sColumnName) ) + { + Reference<XPropertySet> xQueryColumn(xQueryColumns->getByName(sColumnName),UNO_QUERY_THROW); + xQueryColumn->getPropertyValue(PROPERTY_LABEL) >>= sColumnLabel; + } + else + sColumnLabel = xResultSetMeta->getColumnLabel(i); + sal_Bool bFound = sal_False; + OSQLColumns::Vector::const_iterator aFind = ::connectivity::find(aSelectColumns->get().begin(),aSelectColumns->get().end(),sColumnLabel,aCaseCompare); + size_t nFoundSelectColumnPos = aFind - aSelectColumns->get().begin(); + if ( aFind != aSelectColumns->get().end() ) + { + if ( aUsedSelectColumns.find( nFoundSelectColumnPos ) != aUsedSelectColumns.end() ) + { // we found a column name which exists twice + // so we start after the first found + do + { + aFind = ::connectivity::findRealName(++aFind,aSelectColumns->get().end(),sColumnName,aCaseCompare); + nFoundSelectColumnPos = aFind - aSelectColumns->get().begin(); + } + while ( ( aUsedSelectColumns.find( nFoundSelectColumnPos ) != aUsedSelectColumns.end() ) + && ( aFind != aSelectColumns->get().end() ) + ); + } + if ( aFind != aSelectColumns->get().end() ) + { + (*aFind)->getPropertyValue(PROPERTY_NAME) >>= sColumnName; + aUsedSelectColumns.insert( nFoundSelectColumnPos ); + aNames.push_back(sColumnName); + bFound = sal_True; + } + } + + if ( bFound ) + continue; + + OSQLColumns::Vector::const_iterator aRealFind = ::connectivity::findRealName( + aSelectColumns->get().begin(), aSelectColumns->get().end(), sColumnName, aCaseCompare ); + + if ( i > static_cast< sal_Int32>( aSelectColumns->get().size() ) ) + { + aSelectColumns->get().push_back( + ::connectivity::parse::OParseColumn::createColumnForResultSet( xResultSetMeta, m_xMetaData, i ,aColumnNames) + ); + OSL_ENSURE( aSelectColumns->get().size() == (size_t)i, "OSingleSelectQueryComposer::getColumns: inconsistency!" ); + } + else if ( aRealFind == aSelectColumns->get().end() ) + { + // we can now only look if we found it under the realname propertery + // here we have to make the assumption that the position is correct + OSQLColumns::Vector::iterator aFind2 = aSelectColumns->get().begin() + i-1; + Reference<XPropertySet> xProp(*aFind2,UNO_QUERY); + if ( !xProp.is() || !xProp->getPropertySetInfo()->hasPropertyByName( PROPERTY_REALNAME ) ) + continue; + + ::connectivity::parse::OParseColumn* pColumn = new ::connectivity::parse::OParseColumn(xProp,bCase); + pColumn->setFunction(::comphelper::getBOOL(xProp->getPropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Function"))))); + pColumn->setAggregateFunction(::comphelper::getBOOL(xProp->getPropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("AggregateFunction"))))); + + ::rtl::OUString sRealName; + xProp->getPropertyValue(PROPERTY_REALNAME) >>= sRealName; + ::std::vector< ::rtl::OUString>::iterator aFindName; + if ( !sColumnName.getLength() ) + xProp->getPropertyValue(PROPERTY_NAME) >>= sColumnName; + + + aFindName = ::std::find_if(aNames.begin(),aNames.end(),::std::bind2nd(aCaseCompareFunctor,sColumnName)); + sal_Int32 j = 0; + while ( aFindName != aNames.end() ) + { + sColumnName += ::rtl::OUString::valueOf(++j); + aFindName = ::std::find_if(aNames.begin(),aNames.end(),::std::bind2nd(aCaseCompareFunctor,sColumnName)); + } + + pColumn->setName(sColumnName); + pColumn->setRealName(sRealName); + pColumn->setTableName(::comphelper::getString(xProp->getPropertyValue(PROPERTY_TABLENAME))); + + (aSelectColumns->get())[i-1] = pColumn; + } + else + continue; + + aUsedSelectColumns.insert( (size_t)(i - 1) ); + aNames.push_back( sColumnName ); + } + } + catch(const Exception&) + { + } + + } while ( false ); + + if ( aNames.empty() ) + m_aCurrentColumns[ SelectColumns ] = OPrivateColumns::createWithIntrinsicNames( aSelectColumns, bCase, *this, m_aMutex ); + else + m_aCurrentColumns[ SelectColumns ] = new OPrivateColumns( aSelectColumns, bCase, *this, m_aMutex, aNames ); + + return m_aCurrentColumns[SelectColumns]; +} +// ------------------------------------------------------------------------- +sal_Bool OSingleSelectQueryComposer::setORCriteria(OSQLParseNode* pCondition, OSQLParseTreeIterator& _rIterator, + ::std::vector< ::std::vector < PropertyValue > >& rFilters, const Reference< ::com::sun::star::util::XNumberFormatter > & xFormatter) const +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::setORCriteria" ); + // Runde Klammern um den Ausdruck + if (pCondition->count() == 3 && + SQL_ISPUNCTUATION(pCondition->getChild(0),"(") && + SQL_ISPUNCTUATION(pCondition->getChild(2),")")) + { + return setORCriteria(pCondition->getChild(1), _rIterator, rFilters, xFormatter); + } + // oder Verknuepfung + // a searchcondition can only look like this: search_condition SQL_TOKEN_OR boolean_term + else if (SQL_ISRULE(pCondition,search_condition)) + { + sal_Bool bResult = sal_True; + for (int i = 0; bResult && i < 3; i+=2) + { + // Ist das erste Element wieder eine OR-Verknuepfung? + // Dann rekursiv absteigen ... + //if (!i && SQL_ISRULE(pCondition->getChild(i),search_condition)) + if (SQL_ISRULE(pCondition->getChild(i),search_condition)) + bResult = setORCriteria(pCondition->getChild(i), _rIterator, rFilters, xFormatter); + else + { + rFilters.push_back( ::std::vector < PropertyValue >()); + bResult = setANDCriteria(pCondition->getChild(i), _rIterator, rFilters[rFilters.size() - 1], xFormatter); + } + } + return bResult; + } + else + { + rFilters.push_back(::std::vector < PropertyValue >()); + return setANDCriteria(pCondition, _rIterator, rFilters[rFilters.size() - 1], xFormatter); + } +} + +//-------------------------------------------------------------------------------------------------- +sal_Bool OSingleSelectQueryComposer::setANDCriteria( OSQLParseNode * pCondition, + OSQLParseTreeIterator& _rIterator, ::std::vector < PropertyValue >& rFilter, const Reference< XNumberFormatter > & xFormatter) const +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::setANDCriteria" ); + // Runde Klammern + if (SQL_ISRULE(pCondition,boolean_primary)) + { + // this should not occur + DBG_ERROR("boolean_primary in And-Criteria"); + return sal_False; + } + // Das erste Element ist (wieder) eine AND-Verknuepfung + else if ( SQL_ISRULE(pCondition,boolean_term) && pCondition->count() == 3 ) + { + return setANDCriteria(pCondition->getChild(0), _rIterator, rFilter, xFormatter) && + setANDCriteria(pCondition->getChild(2), _rIterator, rFilter, xFormatter); + } + else if (SQL_ISRULE(pCondition, comparison_predicate)) + { + return setComparsionPredicate(pCondition,_rIterator,rFilter,xFormatter); + } + else if (SQL_ISRULE(pCondition,like_predicate) || + SQL_ISRULE(pCondition,test_for_null) || + SQL_ISRULE(pCondition,in_predicate) || + SQL_ISRULE(pCondition,all_or_any_predicate) || + SQL_ISRULE(pCondition,between_predicate)) + { + if (SQL_ISRULE(pCondition->getChild(0), column_ref)) + { + PropertyValue aItem; + ::rtl::OUString aValue; + ::rtl::OUString aColumnName; + + + // pCondition->parseNodeToStr(aValue,m_xMetaData, xFormatter, m_aLocale,static_cast<sal_Char>(m_sDecimalSep.toChar())); + pCondition->parseNodeToStr( aValue, m_xConnection, NULL ); + // pCondition->getChild(0)->parseNodeToStr(aColumnName,m_xMetaData, xFormatter, m_aLocale,static_cast<sal_Char>(m_sDecimalSep.toChar())); + pCondition->getChild(0)->parseNodeToStr( aColumnName, m_xConnection, NULL ); + + // don't display the column name + aValue = aValue.copy(aColumnName.getLength()); + aValue = aValue.trim(); + + aItem.Name = getColumnName(pCondition->getChild(0),_rIterator); + aItem.Value <<= aValue; + aItem.Handle = 0; // just to know that this is not one the known ones + if ( SQL_ISRULE(pCondition,like_predicate) ) + { + if ( SQL_ISTOKEN(pCondition->getChild(1)->getChild(0),NOT) ) + aItem.Handle = SQLFilterOperator::NOT_LIKE; + else + aItem.Handle = SQLFilterOperator::LIKE; + } + else if (SQL_ISRULE(pCondition,test_for_null)) + { + if (SQL_ISTOKEN(pCondition->getChild(1)->getChild(2),NOT) ) + aItem.Handle = SQLFilterOperator::NOT_SQLNULL; + else + aItem.Handle = SQLFilterOperator::SQLNULL; + } + else if (SQL_ISRULE(pCondition,in_predicate)) + { + OSL_ENSURE( false, "OSingleSelectQueryComposer::setANDCriteria: in_predicate not implemented!" ); + } + else if (SQL_ISRULE(pCondition,all_or_any_predicate)) + { + OSL_ENSURE( false, "OSingleSelectQueryComposer::setANDCriteria: all_or_any_predicate not implemented!" ); + } + else if (SQL_ISRULE(pCondition,between_predicate)) + { + OSL_ENSURE( false, "OSingleSelectQueryComposer::setANDCriteria: between_predicate not implemented!" ); + } + + rFilter.push_back(aItem); + } + else + return sal_False; + } + else if (SQL_ISRULE(pCondition,existence_test) || + SQL_ISRULE(pCondition,unique_test)) + { + // this couldn't be handled here, too complex + // as we need a field name + return sal_False; + } + else + return sal_False; + + return sal_True; +} +// ----------------------------------------------------------------------------- +sal_Int32 OSingleSelectQueryComposer::getPredicateType(OSQLParseNode * _pPredicate) const +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getPredicateType" ); + sal_Int32 nPredicate = SQLFilterOperator::EQUAL; + switch (_pPredicate->getNodeType()) + { + case SQL_NODE_EQUAL: + nPredicate = SQLFilterOperator::EQUAL; + break; + case SQL_NODE_NOTEQUAL: + nPredicate = SQLFilterOperator::NOT_EQUAL; + break; + case SQL_NODE_LESS: + nPredicate = SQLFilterOperator::LESS; + break; + case SQL_NODE_LESSEQ: + nPredicate = SQLFilterOperator::LESS_EQUAL; + break; + case SQL_NODE_GREAT: + nPredicate = SQLFilterOperator::GREATER; + break; + case SQL_NODE_GREATEQ: + nPredicate = SQLFilterOperator::GREATER_EQUAL; + break; + default: + OSL_ENSURE(0,"Wrong NodeType!"); + } + return nPredicate; +} +//------------------------------------------------------------------------------ +sal_Bool OSingleSelectQueryComposer::setComparsionPredicate(OSQLParseNode * pCondition, OSQLParseTreeIterator& _rIterator, + ::std::vector < PropertyValue >& rFilter, const Reference< ::com::sun::star::util::XNumberFormatter > & xFormatter) const +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::setComparsionPredicate" ); + DBG_ASSERT(SQL_ISRULE(pCondition, comparison_predicate),"setComparsionPredicate: pCondition ist kein ComparsionPredicate"); + if (SQL_ISRULE(pCondition->getChild(0), column_ref) || + SQL_ISRULE(pCondition->getChild(pCondition->count()-1), column_ref)) + { + PropertyValue aItem; + ::rtl::OUString aValue; + sal_uInt32 nPos; + if (SQL_ISRULE(pCondition->getChild(0), column_ref)) + { + nPos = 0; + sal_uInt32 i=1; + + aItem.Handle = getPredicateType(pCondition->getChild(i)); + // don't display the equal + if (pCondition->getChild(i)->getNodeType() == SQL_NODE_EQUAL) + i++; + + // go forward + for (;i < pCondition->count();i++) + pCondition->getChild(i)->parseNodeToPredicateStr( + aValue, m_xConnection, xFormatter, m_aLocale, static_cast<sal_Char>(m_sDecimalSep.toChar() ) ); + } + else if (SQL_ISRULE(pCondition->getChild(pCondition->count()-1), column_ref)) + { + nPos = pCondition->count()-1; + + sal_Int32 i = pCondition->count() - 2; + switch (pCondition->getChild(i)->getNodeType()) + { + case SQL_NODE_EQUAL: + // don't display the equal + i--; + aItem.Handle = SQLFilterOperator::EQUAL; + break; + case SQL_NODE_NOTEQUAL: + i--; + aItem.Handle = SQLFilterOperator::NOT_EQUAL; + break; + case SQL_NODE_LESS: + // take the opposite as we change the order + i--; + aValue = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(">=")); + aItem.Handle = SQLFilterOperator::GREATER_EQUAL; + break; + case SQL_NODE_LESSEQ: + // take the opposite as we change the order + i--; + aValue = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(">")); + aItem.Handle = SQLFilterOperator::GREATER; + break; + case SQL_NODE_GREAT: + // take the opposite as we change the order + i--; + aValue = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("<=")); + aItem.Handle = SQLFilterOperator::LESS_EQUAL; + break; + case SQL_NODE_GREATEQ: + // take the opposite as we change the order + i--; + aValue = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("<")); + aItem.Handle = SQLFilterOperator::LESS; + break; + default: + break; + } + + // go backward + for (; i >= 0; i--) + pCondition->getChild(i)->parseNodeToPredicateStr( + aValue, m_xConnection, xFormatter, m_aLocale, static_cast<sal_Char>( m_sDecimalSep.toChar() ) ); + } + else + return sal_False; + + aItem.Name = getColumnName(pCondition->getChild(nPos),_rIterator); + aItem.Value <<= aValue; + rFilter.push_back(aItem); + } + else if (SQL_ISRULE(pCondition->getChild(0), set_fct_spec ) || + SQL_ISRULE(pCondition->getChild(0), general_set_fct)) + { + PropertyValue aItem; + ::rtl::OUString aValue; + ::rtl::OUString aColumnName; + + pCondition->parseNodeToPredicateStr(aValue, m_xConnection, xFormatter, m_aLocale, static_cast<sal_Char>( m_sDecimalSep.toChar() ) ); + pCondition->getChild(0)->parseNodeToPredicateStr( aColumnName, m_xConnection, xFormatter, m_aLocale, static_cast<sal_Char>( m_sDecimalSep .toChar() ) ); + + // don't display the column name + aValue = aValue.copy(aColumnName.getLength()); + aValue.trim(); + + aItem.Name = getColumnName(pCondition->getChild(0),_rIterator); + aItem.Value <<= aValue; + aItem.Handle = pCondition->getNodeType(); + rFilter.push_back(aItem); + } + else // kann sich nur um einen Expr. Ausdruck handeln + { + PropertyValue aItem; + ::rtl::OUString aName, aValue; + + OSQLParseNode *pLhs = pCondition->getChild(0); + OSQLParseNode *pRhs = pCondition->getChild(2); + + // Feldnamen + sal_uInt16 i; + for (i=0;i< pLhs->count();i++) + pLhs->getChild(i)->parseNodeToPredicateStr( aName, m_xConnection, xFormatter, m_aLocale, static_cast<sal_Char>( m_sDecimalSep.toChar() ) ); + + // Kriterium + aItem.Handle = pCondition->getChild(1)->getNodeType(); + aValue = pCondition->getChild(1)->getTokenValue(); + for(i=0;i< pRhs->count();i++) + pRhs->getChild(i)->parseNodeToPredicateStr(aValue, m_xConnection, xFormatter, m_aLocale, static_cast<sal_Char>( m_sDecimalSep.toChar() ) ); + + aItem.Name = aName; + aItem.Value <<= aValue; + rFilter.push_back(aItem); + } + return sal_True; +} +// functions for analysing SQL +//-------------------------------------------------------------------------------------------------- +::rtl::OUString OSingleSelectQueryComposer::getColumnName( ::connectivity::OSQLParseNode* pColumnRef, OSQLParseTreeIterator& _rIterator ) const +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getColumnName" ); + ::rtl::OUString aTableRange, aColumnName; + _rIterator.getColumnRange(pColumnRef,aColumnName,aTableRange); + return aColumnName; +} +//------------------------------------------------------------------------------ +::rtl::OUString SAL_CALL OSingleSelectQueryComposer::getFilter( ) throw(RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getFilter" ); + ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed); + ::osl::MutexGuard aGuard( m_aMutex ); + return getSQLPart(Where,m_aAdditiveIterator,sal_False); +} +// ------------------------------------------------------------------------- +::rtl::OUString SAL_CALL OSingleSelectQueryComposer::getOrder( ) throw(RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getOrder" ); + ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed); + ::osl::MutexGuard aGuard( m_aMutex ); + return getSQLPart(Order,m_aAdditiveIterator,sal_False); +} +// ------------------------------------------------------------------------- +::rtl::OUString SAL_CALL OSingleSelectQueryComposer::getGroup( ) throw (RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getGroup" ); + ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed); + ::osl::MutexGuard aGuard( m_aMutex ); + return getSQLPart(Group,m_aAdditiveIterator,sal_False); +} +// ----------------------------------------------------------------------------- +::rtl::OUString OSingleSelectQueryComposer::getHavingClause() throw (RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getHavingClause" ); + ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed); + ::osl::MutexGuard aGuard( m_aMutex ); + return getSQLPart(Having,m_aAdditiveIterator,sal_False); +} +// ----------------------------------------------------------------------------- +::rtl::OUString OSingleSelectQueryComposer::getTableAlias(const Reference< XPropertySet >& column) const +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getTableAlias" ); + ::rtl::OUString sReturn; + if(m_pTables && m_pTables->getCount() > 1) + { + ::rtl::OUString aCatalog,aSchema,aTable,aComposedName,aColumnName; + column->getPropertyValue(PROPERTY_CATALOGNAME) >>= aCatalog; + column->getPropertyValue(PROPERTY_SCHEMANAME) >>= aSchema; + column->getPropertyValue(PROPERTY_TABLENAME) >>= aTable; + column->getPropertyValue(PROPERTY_NAME) >>= aColumnName; + + Sequence< ::rtl::OUString> aNames(m_pTables->getElementNames()); + const ::rtl::OUString* pBegin = aNames.getConstArray(); + const ::rtl::OUString* pEnd = pBegin + aNames.getLength(); + + if(!aTable.getLength()) + { // we don't found a table name, now we must search every table for this column + for(;pBegin != pEnd;++pBegin) + { + Reference<XColumnsSupplier> xColumnsSupp; + m_pTables->getByName(*pBegin) >>= xColumnsSupp; + + if(xColumnsSupp.is() && xColumnsSupp->getColumns()->hasByName(aColumnName)) + { +// Reference<XPropertySet> xTableProp(xColumnsSupp,UNO_QUERY); +// xTableProp->getPropertyValue(PROPERTY_CATALOGNAME) >>= aCatalog; +// xTableProp->getPropertyValue(PROPERTY_SCHEMANAME) >>= aSchema; +// xTableProp->getPropertyValue(PROPERTY_NAME) >>= aTable; + aTable = *pBegin; + break; + } + } + } + else + { + aComposedName = ::dbtools::composeTableName( m_xMetaData, aCatalog, aSchema, aTable, sal_False, ::dbtools::eInDataManipulation ); + + // first check if this is the table we want to or has it a tablealias + + if(!m_pTables->hasByName(aComposedName)) + { + ::comphelper::UStringMixLess aTmp(m_aAdditiveIterator.getTables().key_comp()); + ::comphelper::UStringMixEqual aComp(static_cast< ::comphelper::UStringMixLess*>(&aTmp)->isCaseSensitive()); + for(;pBegin != pEnd;++pBegin) + { + Reference<XPropertySet> xTableProp; + m_pTables->getByName(*pBegin) >>= xTableProp; + OSL_ENSURE(xTableProp.is(),"Table isn't a propertyset!"); + if(xTableProp.is()) + { + ::rtl::OUString aCatalog2,aSchema2,aTable2; + xTableProp->getPropertyValue(PROPERTY_CATALOGNAME) >>= aCatalog2; + xTableProp->getPropertyValue(PROPERTY_SCHEMANAME) >>= aSchema2; + xTableProp->getPropertyValue(PROPERTY_NAME) >>= aTable2; + if(aComp(aCatalog,aCatalog2) && aComp(aSchema,aSchema2) && aComp(aTable,aTable2)) + { + aCatalog = aCatalog2; + aSchema = aSchema2; + aTable = aTable2; + break; + } + } + } + } + } + if(pBegin != pEnd) + { + sReturn = ::dbtools::composeTableName( m_xMetaData, aCatalog, aSchema, aTable, sal_True, ::dbtools::eInDataManipulation ); + sReturn += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(".")); + } + } + return sReturn; +} +// ----------------------------------------------------------------------------- +Reference< XIndexAccess > SAL_CALL OSingleSelectQueryComposer::getParameters( ) throw(RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getParameters" ); + // now set the Parameters + if ( !m_aCurrentColumns[ParameterColumns] ) + { + ::vos::ORef< OSQLColumns> aCols = m_aSqlIterator.getParameters(); + ::std::vector< ::rtl::OUString> aNames; + OSQLColumns::Vector::const_iterator aEnd = aCols->get().end(); + for(OSQLColumns::Vector::const_iterator aIter = aCols->get().begin(); aIter != aEnd;++aIter) + aNames.push_back(getString((*aIter)->getPropertyValue(PROPERTY_NAME))); + m_aCurrentColumns[ParameterColumns] = new OPrivateColumns(aCols,m_xMetaData->supportsMixedCaseQuotedIdentifiers(),*this,m_aMutex,aNames,sal_True); + } + + return m_aCurrentColumns[ParameterColumns]; +} +// ----------------------------------------------------------------------------- +void OSingleSelectQueryComposer::clearColumns( const EColumnType _eType ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::clearColumns" ); + OPrivateColumns* pColumns = m_aCurrentColumns[ _eType ]; + if ( pColumns != NULL ) + { + pColumns->disposing(); + m_aColumnsCollection.push_back( pColumns ); + m_aCurrentColumns[ _eType ] = NULL; + } +} +// ----------------------------------------------------------------------------- +void OSingleSelectQueryComposer::clearCurrentCollections() +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::clearCurrentCollections" ); + ::std::vector<OPrivateColumns*>::iterator aIter = m_aCurrentColumns.begin(); + ::std::vector<OPrivateColumns*>::iterator aEnd = m_aCurrentColumns.end(); + for (;aIter != aEnd;++aIter) + { + if ( *aIter ) + { + (*aIter)->disposing(); + m_aColumnsCollection.push_back(*aIter); + *aIter = NULL; + } + } + + if(m_pTables) + { + m_pTables->disposing(); + m_aTablesCollection.push_back(m_pTables); + m_pTables = NULL; + } +} +// ----------------------------------------------------------------------------- +Reference< XIndexAccess > OSingleSelectQueryComposer::setCurrentColumns( EColumnType _eType, + const ::vos::ORef< OSQLColumns >& _rCols ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::setCurrentColumns" ); + ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed); + + ::osl::MutexGuard aGuard( m_aMutex ); + // now set the group columns + if ( !m_aCurrentColumns[_eType] ) + { + ::std::vector< ::rtl::OUString> aNames; + OSQLColumns::Vector::const_iterator aEnd = _rCols->get().end(); + for(OSQLColumns::Vector::const_iterator aIter = _rCols->get().begin(); aIter != aEnd;++aIter) + aNames.push_back(getString((*aIter)->getPropertyValue(PROPERTY_NAME))); + m_aCurrentColumns[_eType] = new OPrivateColumns(_rCols,m_xMetaData->supportsMixedCaseQuotedIdentifiers(),*this,m_aMutex,aNames,sal_True); + } + + return m_aCurrentColumns[_eType]; +} +// ----------------------------------------------------------------------------- +Reference< XIndexAccess > SAL_CALL OSingleSelectQueryComposer::getGroupColumns( ) throw(RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getGroupColumns" ); + return setCurrentColumns( GroupByColumns, m_aAdditiveIterator.getGroupColumns() ); +} +// ------------------------------------------------------------------------- +Reference< XIndexAccess > SAL_CALL OSingleSelectQueryComposer::getOrderColumns( ) throw(RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getOrderColumns" ); + return setCurrentColumns( OrderColumns, m_aAdditiveIterator.getOrderColumns() ); +} +// ----------------------------------------------------------------------------- +::rtl::OUString SAL_CALL OSingleSelectQueryComposer::getQueryWithSubstitution( ) throw (SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getQueryWithSubstitution" ); + ::osl::MutexGuard aGuard( m_aMutex ); + ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed); + + ::rtl::OUString sSqlStatement( getQuery() ); + + const OSQLParseNode* pStatementNode = m_aSqlIterator.getParseTree(); + if ( pStatementNode ) + { + SQLException aError; + if ( !pStatementNode->parseNodeToExecutableStatement( sSqlStatement, m_xConnection, m_aSqlParser, &aError ) ) + throw SQLException( aError ); + } + + return sSqlStatement; +} +// ----------------------------------------------------------------------------- +::rtl::OUString OSingleSelectQueryComposer::getStatementPart( TGetParseNode& _aGetFunctor, OSQLParseTreeIterator& _rIterator ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getStatementPart" ); + ::rtl::OUString sResult; + + const OSQLParseNode* pNode = _aGetFunctor( &_rIterator ); + if ( pNode ) + pNode->parseNodeToStr( sResult, m_xConnection ); + + return sResult; +} +// ----------------------------------------------------------------------------- +namespace +{ + ::rtl::OUString lcl_getCondition(const Sequence< Sequence< PropertyValue > >& filter ) + { + ::rtl::OUStringBuffer sRet; + const Sequence< PropertyValue >* pOrIter = filter.getConstArray(); + const Sequence< PropertyValue >* pOrEnd = pOrIter + filter.getLength(); + while ( pOrIter != pOrEnd ) + { + if ( pOrIter->getLength() ) + { + sRet.append(L_BRACKET); + const PropertyValue* pAndIter = pOrIter->getConstArray(); + const PropertyValue* pAndEnd = pAndIter + pOrIter->getLength(); + while ( pAndIter != pAndEnd ) + { + sRet.append(pAndIter->Name); + ::rtl::OUString sValue; + pAndIter->Value >>= sValue; + lcl_addFilterCriteria_throw(pAndIter->Handle,sValue,sRet); + ++pAndIter; + if ( pAndIter != pAndEnd ) + sRet.append(STR_AND); + } + sRet.append(R_BRACKET); + } + ++pOrIter; + if ( pOrIter != pOrEnd && sRet.getLength() ) + sRet.append(STR_OR); + } + return sRet.makeStringAndClear(); + } +} +// ----------------------------------------------------------------------------- +void SAL_CALL OSingleSelectQueryComposer::setStructuredFilter( const Sequence< Sequence< PropertyValue > >& filter ) throw (SQLException, ::com::sun::star::lang::IllegalArgumentException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::setStructuredFilter" ); + setFilter(lcl_getCondition(filter)); +} +// ----------------------------------------------------------------------------- +void SAL_CALL OSingleSelectQueryComposer::setStructuredHavingClause( const Sequence< Sequence< PropertyValue > >& filter ) throw (SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::setStructuredHavingClause" ); + setHavingClause(lcl_getCondition(filter)); +} +// ----------------------------------------------------------------------------- +void OSingleSelectQueryComposer::setConditionByColumn( const Reference< XPropertySet >& column, sal_Bool andCriteria ,::std::mem_fun1_t<bool,OSingleSelectQueryComposer,::rtl::OUString>& _aSetFunctor,sal_Int32 filterOperator) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::setConditionByColumn" ); + ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed); + + if ( !column.is() + || !column->getPropertySetInfo()->hasPropertyByName(PROPERTY_VALUE) + || !column->getPropertySetInfo()->hasPropertyByName(PROPERTY_NAME) + || !column->getPropertySetInfo()->hasPropertyByName(PROPERTY_TYPE)) + throw SQLException(DBACORE_RESSTRING(RID_STR_COLUMN_NOT_VALID),*this,SQLSTATE_GENERAL,1000,Any() ); + + sal_Int32 nType = 0; + column->getPropertyValue(PROPERTY_TYPE) >>= nType; + sal_Int32 nSearchable = dbtools::getSearchColumnFlag(m_xConnection,nType); + if(nSearchable == ColumnSearch::NONE) + throw SQLException(DBACORE_RESSTRING(RID_STR_COLUMN_NOT_SEARCHABLE),*this,SQLSTATE_GENERAL,1000,Any() ); + + ::osl::MutexGuard aGuard( m_aMutex ); + + ::rtl::OUString aName; + column->getPropertyValue(PROPERTY_NAME) >>= aName; + + Any aValue; + column->getPropertyValue(PROPERTY_VALUE) >>= aValue; + + ::rtl::OUStringBuffer aSQL; + const ::rtl::OUString aQuote = m_xMetaData->getIdentifierQuoteString(); + getColumns(); + + if ( m_aCurrentColumns[SelectColumns] && m_aCurrentColumns[SelectColumns]->hasByName(aName) ) + { + Reference<XPropertySet> xColumn; + m_aCurrentColumns[SelectColumns]->getByName(aName) >>= xColumn; + OSL_ENSURE(xColumn->getPropertySetInfo()->hasPropertyByName(PROPERTY_REALNAME),"Property REALNAME not available!"); + OSL_ENSURE(xColumn->getPropertySetInfo()->hasPropertyByName(PROPERTY_TABLENAME),"Property TABLENAME not available!"); + OSL_ENSURE(xColumn->getPropertySetInfo()->hasPropertyByName(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("AggregateFunction"))),"Property AggregateFunctionnot available!"); + + ::rtl::OUString sRealName,sTableName; + xColumn->getPropertyValue(PROPERTY_REALNAME) >>= sRealName; + xColumn->getPropertyValue(PROPERTY_TABLENAME) >>= sTableName; + if(sTableName.indexOf('.',0) != -1) + { + ::rtl::OUString aCatlog,aSchema,aTable; + ::dbtools::qualifiedNameComponents(m_xMetaData,sTableName,aCatlog,aSchema,aTable,::dbtools::eInDataManipulation); + sTableName = ::dbtools::composeTableName( m_xMetaData, aCatlog, aSchema, aTable, sal_True, ::dbtools::eInDataManipulation ); + } + else + sTableName = ::dbtools::quoteName(aQuote,sTableName); + + if ( !::comphelper::getBOOL(xColumn->getPropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Function")))) ) + { + aSQL = sTableName; + aSQL.appendAscii( "." ); + aSQL.append( ::dbtools::quoteName( aQuote, sRealName ) ); + } + else + aSQL = sRealName; + + } + else + { + aSQL = getTableAlias( column ); + aSQL.append( ::dbtools::quoteName( aQuote, aName ) ); + } + + + if ( aValue.hasValue() ) + { + if( !m_xTypeConverter.is() ) + m_aContext.createComponent( "com.sun.star.script.Converter", m_xTypeConverter ); + OSL_ENSURE(m_xTypeConverter.is(),"NO typeconverter!"); + + if ( nType != DataType::BOOLEAN && DataType::BIT != nType ) + { + ::rtl::OUString sEmpty; + lcl_addFilterCriteria_throw(filterOperator,sEmpty,aSQL); + } + + switch(nType) + { + case DataType::VARCHAR: + case DataType::CHAR: + case DataType::LONGVARCHAR: + aSQL.append( DBTypeConversion::toSQLString( nType, aValue, sal_True, m_xTypeConverter ) ); + break; + case DataType::CLOB: + { + Reference< XClob > xClob(aValue,UNO_QUERY); + if ( xClob.is() ) + { + const ::sal_Int64 nLength = xClob->length(); + if ( sal_Int64(nLength + aSQL.getLength() + STR_LIKE.getLength() ) < sal_Int64(SAL_MAX_INT32) ) + { + aSQL.appendAscii("'"); + aSQL.append( xClob->getSubString(1,(sal_Int32)nLength) ); + aSQL.appendAscii("'"); + } + } + else + { + aSQL.append( DBTypeConversion::toSQLString( nType, aValue, sal_True, m_xTypeConverter ) ); + } + } + break; + case DataType::VARBINARY: + case DataType::BINARY: + case DataType::LONGVARBINARY: + { + Sequence<sal_Int8> aSeq; + if(aValue >>= aSeq) + { + if(nSearchable == ColumnSearch::CHAR) + { + aSQL.appendAscii( "\'" ); + } + aSQL.appendAscii( "0x" ); + const sal_Int8* pBegin = aSeq.getConstArray(); + const sal_Int8* pEnd = pBegin + aSeq.getLength(); + for(;pBegin != pEnd;++pBegin) + { + aSQL.append( (sal_Int32)*pBegin, 16 ).getStr(); + } + if(nSearchable == ColumnSearch::CHAR) + aSQL.appendAscii( "\'" ); + } + else + throw SQLException(DBACORE_RESSTRING(RID_STR_NOT_SEQUENCE_INT8),*this,SQLSTATE_GENERAL,1000,Any() ); + } + break; + case DataType::BIT: + case DataType::BOOLEAN: + { + sal_Bool bValue = sal_False; + m_xTypeConverter->convertToSimpleType(aValue, TypeClass_BOOLEAN) >>= bValue; + + ::rtl::OUString sColumnExp = aSQL.makeStringAndClear(); + getBoleanComparisonPredicate( sColumnExp, bValue, m_nBoolCompareMode, aSQL ); + } + break; + default: + aSQL.append( DBTypeConversion::toSQLString( nType, aValue, sal_True, m_xTypeConverter ) ); + break; + } + } + else + { + sal_Int32 nFilterOp = filterOperator; + if ( filterOperator != SQLFilterOperator::SQLNULL && filterOperator != SQLFilterOperator::NOT_SQLNULL ) + nFilterOp = SQLFilterOperator::SQLNULL; + ::rtl::OUString sEmpty; + lcl_addFilterCriteria_throw(nFilterOp,sEmpty,aSQL); + } + + // filter anhaengen + // select ohne where und order by aufbauen + ::rtl::OUString sFilter = getFilter(); + + if ( sFilter.getLength() && aSQL.getLength() ) + { + ::rtl::OUString sTemp(L_BRACKET); + sTemp += sFilter; + sTemp += R_BRACKET; + sTemp += andCriteria ? STR_AND : STR_OR; + sFilter = sTemp; + } + sFilter += aSQL.makeStringAndClear(); + + // add the filter and the sort order + _aSetFunctor(this,sFilter); +} +// ----------------------------------------------------------------------------- +Sequence< Sequence< PropertyValue > > OSingleSelectQueryComposer::getStructuredCondition( TGetParseNode& _aGetFunctor ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getStructuredCondition" ); + ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed); + + MutexGuard aGuard(m_aMutex); + + Sequence< Sequence< PropertyValue > > aFilterSeq; + ::rtl::OUString sFilter = getStatementPart( _aGetFunctor, m_aAdditiveIterator ); + + if ( sFilter.getLength() != 0 ) + { + ::rtl::OUString aSql(m_aPureSelectSQL); + // build a temporary parse node + const OSQLParseNode* pTempNode = m_aAdditiveIterator.getParseTree(); + + aSql += STR_WHERE; + aSql += sFilter; + + ::rtl::OUString aErrorMsg; + ::std::auto_ptr<OSQLParseNode> pSqlParseNode( m_aSqlParser.parseTree(aErrorMsg,aSql)); + if ( pSqlParseNode.get() ) + { + m_aAdditiveIterator.setParseTree(pSqlParseNode.get()); + // normalize the filter + OSQLParseNode* pWhereNode = const_cast<OSQLParseNode*>(m_aAdditiveIterator.getWhereTree()); + + OSQLParseNode* pCondition = pWhereNode->getChild(1); + #if OSL_DEBUG_LEVEL > 0 + ::rtl::OUString sCondition; + pCondition->parseNodeToStr( sCondition, m_xConnection ); + #endif + OSQLParseNode::negateSearchCondition(pCondition); + + pCondition = pWhereNode->getChild(1); + #if OSL_DEBUG_LEVEL > 0 + sCondition = ::rtl::OUString(); + pCondition->parseNodeToStr( sCondition, m_xConnection ); + #endif + OSQLParseNode::disjunctiveNormalForm(pCondition); + + pCondition = pWhereNode->getChild(1); + #if OSL_DEBUG_LEVEL > 0 + sCondition = ::rtl::OUString(); + pCondition->parseNodeToStr( sCondition, m_xConnection ); + #endif + OSQLParseNode::absorptions(pCondition); + + pCondition = pWhereNode->getChild(1); + #if OSL_DEBUG_LEVEL > 0 + sCondition = ::rtl::OUString(); + pCondition->parseNodeToStr( sCondition, m_xConnection ); + #endif + if ( pCondition ) + { + ::std::vector< ::std::vector < PropertyValue > > aFilters; + Reference< XNumberFormatter > xFormatter; + m_aContext.createComponent( "com.sun.star.util.NumberFormatter", xFormatter ); + xFormatter->attachNumberFormatsSupplier( m_xNumberFormatsSupplier ); + + if (setORCriteria(pCondition, m_aAdditiveIterator, aFilters, xFormatter)) + { + aFilterSeq.realloc(aFilters.size()); + Sequence<PropertyValue>* pFilters = aFilterSeq.getArray(); + ::std::vector< ::std::vector < PropertyValue > >::const_iterator aEnd = aFilters.end(); + ::std::vector< ::std::vector < PropertyValue > >::const_iterator i = aFilters.begin(); + for ( ; i != aEnd ; ++i) + { + const ::std::vector < PropertyValue >& rProperties = *i; + pFilters->realloc(rProperties.size()); + PropertyValue* pFilter = pFilters->getArray(); + ::std::vector < PropertyValue >::const_iterator j = rProperties.begin(); + ::std::vector < PropertyValue >::const_iterator aEnd2 = rProperties.end(); + for ( ; j != aEnd2 ; ++j) + { + *pFilter = *j; + ++pFilter; + } + ++pFilters; + } + } + } + // restore + m_aAdditiveIterator.setParseTree(pTempNode); + } + } + return aFilterSeq; +} +// ----------------------------------------------------------------------------- +::rtl::OUString OSingleSelectQueryComposer::getKeyword( SQLPart _ePart ) const +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getKeyword" ); + ::rtl::OUString sKeyword; + switch(_ePart) + { + default: + OSL_ENSURE( 0, "OSingleSelectQueryComposer::getKeyWord: Invalid enum value!" ); + // no break, fallback to WHERE + case Where: + sKeyword = STR_WHERE; + break; + case Group: + sKeyword = STR_GROUP_BY; + break; + case Having: + sKeyword = STR_HAVING; + break; + case Order: + sKeyword = STR_ORDER_BY; + break; + } + return sKeyword; +} + +// ----------------------------------------------------------------------------- +::rtl::OUString OSingleSelectQueryComposer::getSQLPart( SQLPart _ePart, OSQLParseTreeIterator& _rIterator, sal_Bool _bWithKeyword ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getSQLPart" ); + TGetParseNode F_tmp(&OSQLParseTreeIterator::getSimpleWhereTree); + ::rtl::OUString sKeyword( getKeyword( _ePart ) ); + switch(_ePart) + { + case Where: + F_tmp = TGetParseNode(&OSQLParseTreeIterator::getSimpleWhereTree); + break; + case Group: + F_tmp = TGetParseNode (&OSQLParseTreeIterator::getSimpleGroupByTree); + break; + case Having: + F_tmp = TGetParseNode(&OSQLParseTreeIterator::getSimpleHavingTree); + break; + case Order: + F_tmp = TGetParseNode(&OSQLParseTreeIterator::getSimpleOrderTree); + break; + default: + OSL_ENSURE(0,"Invalid enum value!"); + } + + ::rtl::OUString sRet = getStatementPart( F_tmp, _rIterator ); + if ( _bWithKeyword && sRet.getLength() ) + sRet = sKeyword + sRet; + return sRet; +} +// ----------------------------------------------------------------------------- diff --git a/dbaccess/source/core/api/StaticSet.cxx b/dbaccess/source/core/api/StaticSet.cxx new file mode 100644 index 000000000000..de768b6ceb8e --- /dev/null +++ b/dbaccess/source/core/api/StaticSet.cxx @@ -0,0 +1,392 @@ +/************************************************************************* + * + * 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_dbaccess.hxx" + +#ifndef DBACCESS_CORE_API_STATICSET_HXX +#include "StaticSet.hxx" +#endif +#ifndef _COM_SUN_STAR_SDBCX_COMPAREBOOKMARK_HPP_ +#include <com/sun/star/sdbcx/CompareBookmark.hpp> +#endif +#ifndef _COM_SUN_STAR_BEANS_XPROPERTYSET_HPP_ +#include <com/sun/star/beans/XPropertySet.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_XDATABASEMETADATA_HPP_ +#include <com/sun/star/sdbc/XDatabaseMetaData.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_XPREPAREDSTATEMENT_HPP_ +#include <com/sun/star/sdbc/XPreparedStatement.hpp> +#endif +#ifndef DBACCESS_SHARED_DBASTRINGS_HRC +#include "dbastrings.hrc" +#endif +#ifndef _DBASHARED_APITOOLS_HXX_ +#include "apitools.hxx" +#endif +#ifndef _CONNECTIVITY_COMMONTOOLS_HXX_ +#include <connectivity/CommonTools.hxx> +#endif +#ifndef _COMPHELPER_TYPES_HXX_ +#include <comphelper/types.hxx> +#endif +#include <rtl/logfile.hxx> + +using namespace dbaccess; +using namespace connectivity; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::sdbc; +// using namespace ::com::sun::star::sdb; +using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::lang; +// using namespace ::cppu; +using namespace ::osl; + +// ------------------------------------------------------------------------- +void OStaticSet::fillValueRow(ORowSetRow& _rRow,sal_Int32 /*_nPosition*/) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStaticSet::fillValueRow" ); + _rRow = *m_aSetIter; +} +// ------------------------------------------------------------------------- +// ::com::sun::star::sdbcx::XRowLocate +Any SAL_CALL OStaticSet::getBookmark() throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStaticSet::getBookmark" ); + return makeAny(getRow()); +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL OStaticSet::moveToBookmark( const Any& bookmark ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStaticSet::moveToBookmark" ); + m_bInserted = m_bUpdated = m_bDeleted = sal_False; + return absolute(::comphelper::getINT32(bookmark)); +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL OStaticSet::moveRelativeToBookmark( const Any& bookmark, sal_Int32 rows ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStaticSet::moveRelativeToBookmark" ); + m_bInserted = m_bUpdated = m_bDeleted = sal_False; + return absolute(::comphelper::getINT32(bookmark)+rows); +} +// ------------------------------------------------------------------------- +sal_Int32 SAL_CALL OStaticSet::compareBookmarks( const Any& _first, const Any& _second ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStaticSet::compareBookmarks" ); + sal_Int32 nFirst = 0, nSecond = 0; + _first >>= nFirst; + _second >>= nSecond; + return (nFirst < nSecond) ? CompareBookmark::LESS : ((nFirst > nSecond) ? CompareBookmark::GREATER : CompareBookmark::EQUAL); +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL OStaticSet::hasOrderedBookmarks( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStaticSet::hasOrderedBookmarks" ); + return sal_True; +} +// ------------------------------------------------------------------------- +sal_Int32 SAL_CALL OStaticSet::hashBookmark( const Any& bookmark ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStaticSet::hashBookmark" ); + return ::comphelper::getINT32(bookmark); +} +// ------------------------------------------------------------------------- +sal_Bool OStaticSet::fetchRow() +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStaticSet::fetchRow" ); + sal_Bool bRet = sal_False; + if ( !m_bEnd ) + bRet = m_xDriverSet->next(); + if ( bRet ) + { + m_aSet.push_back(new connectivity::ORowVector< connectivity::ORowSetValue >(m_xSetMetaData->getColumnCount())); + m_aSetIter = m_aSet.end() - 1; + ((*m_aSetIter)->get())[0] = getRow(); + OCacheSet::fillValueRow(*m_aSetIter,((*m_aSetIter)->get())[0]); + } + else + m_bEnd = sal_True; + return bRet; +} +// ------------------------------------------------------------------------- +void OStaticSet::fillAllRows() +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStaticSet::fillAllRows" ); + if(!m_bEnd) + { + while(m_xDriverSet->next()) + { + ORowSetRow pRow = new connectivity::ORowVector< connectivity::ORowSetValue >(m_xSetMetaData->getColumnCount()); + m_aSet.push_back(pRow); + m_aSetIter = m_aSet.end() - 1; + (pRow->get())[0] = getRow(); + OCacheSet::fillValueRow(pRow,(pRow->get())[0]); + } + m_bEnd = sal_True; + } +} +// ------------------------------------------------------------------------- +// XResultSet +sal_Bool SAL_CALL OStaticSet::next( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStaticSet::next" ); + m_bInserted = m_bUpdated = m_bDeleted = sal_False; + + if(isAfterLast()) + return sal_False; + if(!m_bEnd) // not yet all records fetched + { + ++m_aSetIter; + if(m_aSetIter == m_aSet.end() && !fetchRow()) + m_aSetIter = m_aSet.end(); + } + else if(!isAfterLast()) + ++m_aSetIter; + return !isAfterLast(); +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL OStaticSet::isBeforeFirst( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStaticSet::isBeforeFirst" ); + return m_aSetIter == m_aSet.begin(); +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL OStaticSet::isAfterLast( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStaticSet::isAfterLast" ); + return m_aSetIter == m_aSet.end() && m_bEnd; +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL OStaticSet::isFirst( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStaticSet::isFirst" ); + return m_aSetIter == m_aSet.begin()+1; +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL OStaticSet::isLast( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStaticSet::isLast" ); + return m_aSetIter == m_aSet.end()-1 && m_bEnd; +} +// ------------------------------------------------------------------------- +void SAL_CALL OStaticSet::beforeFirst( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStaticSet::beforeFirst" ); + m_bInserted = m_bUpdated = m_bDeleted = sal_False; + m_aSetIter = m_aSet.begin(); +} +// ------------------------------------------------------------------------- +void SAL_CALL OStaticSet::afterLast( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStaticSet::afterLast" ); + m_bInserted = m_bUpdated = m_bDeleted = sal_False; + fillAllRows(); + m_aSetIter = m_aSet.end(); +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL OStaticSet::first( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStaticSet::first" ); + m_bInserted = m_bUpdated = m_bDeleted = sal_False; + m_aSetIter = m_aSet.begin()+1; + if(m_aSetIter == m_aSet.end() && !fetchRow()) + m_aSetIter = m_aSet.end(); + + return m_aSetIter != m_aSet.end(); +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL OStaticSet::last( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStaticSet::last" ); + m_bInserted = m_bUpdated = m_bDeleted = sal_False; + fillAllRows(); + m_aSetIter = m_aSet.end()-1; + + return !isBeforeFirst() && !isAfterLast(); +} +// ------------------------------------------------------------------------- +sal_Int32 SAL_CALL OStaticSet::getRow( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStaticSet::getRow" ); + OSL_ENSURE(!isAfterLast(),"getRow is not allowed when afterlast record!"); + OSL_ENSURE(!isBeforeFirst(),"getRow is not allowed when beforefirst record!"); + + sal_Int32 nPos = m_aSet.size() - (m_aSet.end() - m_aSetIter); + OSL_ENSURE(nPos > 0,"RowPos is < 0"); + return nPos; +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL OStaticSet::absolute( sal_Int32 row ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStaticSet::absolute" ); + m_bInserted = m_bUpdated = m_bDeleted = sal_False; + OSL_ENSURE(row,"OStaticSet::absolute: INVALID row number!"); + // if row greater 0 than count from end - row means last + if(row < 0) + { + if(!m_bEnd) + fillAllRows(); + + sal_Int32 nRow = getRow(); + nRow += row; + if(nRow <= (sal_Int32)m_aSet.size()) + m_aSetIter = m_aSet.begin() + nRow; + else + m_aSetIter = m_aSet.begin(); + } + else if(row > 0) + { + if(row >= (sal_Int32)m_aSet.size()) + { + if(!m_bEnd) + { + sal_Bool bNext = sal_True; + for(sal_Int32 i=m_aSet.size()-1;i < row && bNext;++i) + bNext = fetchRow(); + } + + if(row > (sal_Int32)m_aSet.size()) + m_aSetIter = m_aSet.end(); // check again + else + m_aSetIter = m_aSet.begin() + row; + } + else + m_aSetIter = m_aSet.begin() + row; + } + + return m_aSetIter != m_aSet.end() && m_aSetIter != m_aSet.begin(); +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL OStaticSet::relative( sal_Int32 rows ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStaticSet::relative" ); + if(!rows) + return sal_True; + + sal_Int32 nCurPos = getRow(); + return absolute(nCurPos+rows); +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL OStaticSet::previous( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStaticSet::previous" ); + m_bInserted = m_bUpdated = m_bDeleted = sal_False; + + if(m_aSetIter != m_aSet.begin()) + --m_aSetIter; + + return m_aSetIter != m_aSet.begin(); +} +// ------------------------------------------------------------------------- +void SAL_CALL OStaticSet::refreshRow( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStaticSet::refreshRow" ); +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL OStaticSet::rowUpdated( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStaticSet::rowUpdated" ); + return m_bUpdated; +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL OStaticSet::rowInserted( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStaticSet::rowInserted" ); + return m_bInserted; +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL OStaticSet::rowDeleted( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStaticSet::rowDeleted" ); + return m_bDeleted; +} +// ------------------------------------------------------------------------- +Sequence< sal_Int32 > SAL_CALL OStaticSet::deleteRows( const Sequence< Any >& rows,const connectivity::OSQLTable& _xTable ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStaticSet::deleteRows" ); + Sequence< sal_Int32 > aRet(rows.getLength()); + const Any* pBegin = rows.getConstArray(); + const Any* pEnd = pBegin + rows.getLength(); + for(sal_Int32 i=0;pBegin != pEnd; ++pBegin,++i) + { + deleteRow(*(m_aSet.begin() + comphelper::getINT32(*pBegin)),_xTable); + aRet.getArray()[i] = m_bDeleted; + } + return aRet; +} +// ------------------------------------------------------------------------- +void SAL_CALL OStaticSet::insertRow( const ORowSetRow& _rInsertRow,const connectivity::OSQLTable& _xTable ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStaticSet::insertRow" ); + OCacheSet::insertRow( _rInsertRow,_xTable); + if(m_bInserted) + { + m_aSet.push_back(new ORowVector< ORowSetValue >(*_rInsertRow)); // we don't know where the new row is so we append it to the current rows + m_aSetIter = m_aSet.end() - 1; + ((*m_aSetIter)->get())[0] = (_rInsertRow->get())[0] = getBookmark(); + m_bEnd = sal_False; + } +} +// ------------------------------------------------------------------------- +void SAL_CALL OStaticSet::updateRow(const ORowSetRow& _rInsertRow ,const ORowSetRow& _rOrginalRow,const connectivity::OSQLTable& _xTable ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStaticSet::updateRow" ); + OCacheSet::updateRow( _rInsertRow,_rOrginalRow,_xTable); +} +// ------------------------------------------------------------------------- +void SAL_CALL OStaticSet::deleteRow(const ORowSetRow& _rDeleteRow ,const connectivity::OSQLTable& _xTable ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStaticSet::deleteRow" ); + OCacheSet::deleteRow(_rDeleteRow,_xTable); + if(m_bDeleted) + { + ORowSetMatrix::iterator aPos = m_aSet.begin()+(_rDeleteRow->get())[0].getInt32(); + if(aPos == (m_aSet.end()-1)) + m_aSetIter = m_aSet.end(); + m_aSet.erase(aPos); + } +} +// ------------------------------------------------------------------------- +void SAL_CALL OStaticSet::cancelRowUpdates( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStaticSet::cancelRowUpdates" ); +} +// ------------------------------------------------------------------------- +void SAL_CALL OStaticSet::moveToInsertRow( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStaticSet::moveToInsertRow" ); +} +// ------------------------------------------------------------------------- +void SAL_CALL OStaticSet::moveToCurrentRow( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStaticSet::moveToCurrentRow" ); +} +// ------------------------------------------------------------------------- + diff --git a/dbaccess/source/core/api/StaticSet.hxx b/dbaccess/source/core/api/StaticSet.hxx new file mode 100644 index 000000000000..676044cb61f9 --- /dev/null +++ b/dbaccess/source/core/api/StaticSet.hxx @@ -0,0 +1,93 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +#ifndef DBACCESS_CORE_API_STATICSET_HXX +#define DBACCESS_CORE_API_STATICSET_HXX + +#ifndef DBACCESS_CORE_API_CACHESET_HXX +#include "CacheSet.hxx" +#endif + +namespace dbaccess +{ + // is used when nothing is supported by the driver + // we use a snapshot + class OStaticSet : public OCacheSet + { + ORowSetMatrix m_aSet; + ORowSetMatrix::iterator m_aSetIter; + sal_Bool m_bEnd; + sal_Bool fetchRow(); + void fillAllRows(); + public: + OStaticSet() + : m_aSetIter(m_aSet.end()) + , m_bEnd(sal_False) + { + m_aSet.push_back(NULL); // this is the beforefirst record + } + + virtual void fillValueRow(ORowSetRow& _rRow,sal_Int32 _nPosition); + // ::com::sun::star::sdbcx::XRowLocate + virtual ::com::sun::star::uno::Any SAL_CALL getBookmark() throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL moveToBookmark( const ::com::sun::star::uno::Any& bookmark ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL moveRelativeToBookmark( const ::com::sun::star::uno::Any& bookmark, sal_Int32 rows ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Int32 SAL_CALL compareBookmarks( const ::com::sun::star::uno::Any& first, const ::com::sun::star::uno::Any& second ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL hasOrderedBookmarks( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Int32 SAL_CALL hashBookmark( const ::com::sun::star::uno::Any& bookmark ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + + // ::com::sun::star::sdbc::XResultSet + virtual sal_Bool SAL_CALL next( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL isBeforeFirst( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL isAfterLast( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL isFirst( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL isLast( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL beforeFirst( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL afterLast( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL first( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL last( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Int32 SAL_CALL getRow( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL absolute( sal_Int32 row ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL relative( sal_Int32 rows ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL previous( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL refreshRow( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL rowUpdated( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL rowInserted( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL rowDeleted( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + // ::com::sun::star::sdbcx::XDeleteRows + virtual ::com::sun::star::uno::Sequence< sal_Int32 > SAL_CALL deleteRows( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& rows,const connectivity::OSQLTable& _xTable ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + // ::com::sun::star::sdbc::XResultSetUpdate + virtual void SAL_CALL insertRow( const ORowSetRow& _rInsertRow,const connectivity::OSQLTable& _xTable ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL updateRow(const ORowSetRow& _rInsertRow,const ORowSetRow& _rOrginalRow,const connectivity::OSQLTable& _xTable ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL deleteRow(const ORowSetRow& _rInsertRow,const connectivity::OSQLTable& _xTable ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL cancelRowUpdates( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL moveToInsertRow( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL moveToCurrentRow( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + }; +} +#endif //DBACCESS_CORE_API_STATICSET_HXX + diff --git a/dbaccess/source/core/api/TableDeco.cxx b/dbaccess/source/core/api/TableDeco.cxx new file mode 100644 index 000000000000..a296833ab6ef --- /dev/null +++ b/dbaccess/source/core/api/TableDeco.cxx @@ -0,0 +1,758 @@ +/************************************************************************* + * + * 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_dbaccess.hxx" + +#ifndef _DBA_CORE_TABLEDECORATOR_HXX_ +#include "TableDeco.hxx" +#endif +#ifndef _DBACORE_DEFINITIONCOLUMN_HXX_ +#include <definitioncolumn.hxx> +#endif +#ifndef DBACCESS_SHARED_DBASTRINGS_HRC +#include "dbastrings.hrc" +#endif +#ifndef _DBA_CORE_RESOURCE_HXX_ +#include "core_resource.hxx" +#endif +#ifndef _DBA_CORE_RESOURCE_HRC_ +#include "core_resource.hrc" +#endif +#ifndef _TOOLS_DEBUG_HXX +#include <tools/debug.hxx> +#endif + +#ifndef _CPPUHELPER_TYPEPROVIDER_HXX_ +#include <cppuhelper/typeprovider.hxx> +#endif +#ifndef _COMPHELPER_ENUMHELPER_HXX_ +#include <comphelper/enumhelper.hxx> +#endif +#ifndef _COMPHELPER_CONTAINER_HXX_ +#include <comphelper/container.hxx> +#endif +#ifndef _COMPHELPER_SEQUENCE_HXX_ +#include <comphelper/sequence.hxx> +#endif +#ifndef _COMPHELPER_PROPERTY_HXX_ +#include <comphelper/property.hxx> +#endif +#ifndef _COMPHELPER_TYPES_HXX_ +#include <comphelper/types.hxx> +#endif +#ifndef _COM_SUN_STAR_UTIL_XREFRESHLISTENER_HPP_ +#include <com/sun/star/util/XRefreshListener.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_XCONNECTION_HPP_ +#include <com/sun/star/sdbc/XConnection.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_XROW_HPP_ +#include <com/sun/star/sdbc/XRow.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBCX_PRIVILEGE_HPP_ +#include <com/sun/star/sdbcx/Privilege.hpp> +#endif +#ifndef _COM_SUN_STAR_BEANS_PROPERTYATTRIBUTE_HPP_ +#include <com/sun/star/beans/PropertyAttribute.hpp> +#endif +#ifndef _CONNECTIVITY_DBTOOLS_HXX_ +#include <connectivity/dbtools.hxx> +#endif +#ifndef _DBHELPER_DBEXCEPTION_HXX_ +#include <connectivity/dbexception.hxx> +#endif +#ifndef _CONNECTIVITY_DBTOOLS_HXX_ +#include <connectivity/dbtools.hxx> +#endif +#ifndef _COMPHELPER_EXTRACT_HXX_ +#include <comphelper/extract.hxx> +#endif +#ifndef DBA_CONTAINERMEDIATOR_HXX +#include "ContainerMediator.hxx" +#endif +#include <rtl/logfile.hxx> + +using namespace dbaccess; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::util; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::container; +using namespace ::osl; +using namespace ::comphelper; +using namespace ::dbtools; +using namespace ::cppu; + +//========================================================================== +//= ODBTableDecorator +//========================================================================== +DBG_NAME(ODBTableDecorator) +// ----------------------------------------------------------------------------- +ODBTableDecorator::ODBTableDecorator( const Reference< XConnection >& _rxConnection, const Reference< XColumnsSupplier >& _rxNewTable, + const Reference< XNumberFormatsSupplier >& _rxNumberFormats, const Reference< XNameAccess >& _xColumnDefinitions ) throw(SQLException) + :OTableDescriptor_BASE(m_aMutex) + ,ODataSettings(OTableDescriptor_BASE::rBHelper) + ,m_xTable(_rxNewTable) + ,m_xColumnDefinitions(_xColumnDefinitions) + ,m_xConnection( _rxConnection ) + ,m_xMetaData( _rxConnection.is() ? _rxConnection->getMetaData() : Reference< XDatabaseMetaData >() ) + ,m_xNumberFormats( _rxNumberFormats ) + ,m_nPrivileges(-1) + ,m_pColumns(NULL) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ODBTableDecorator::ODBTableDecorator" ); + DBG_CTOR(ODBTableDecorator, NULL); + ODataSettings::registerPropertiesFor(this); +} +// ------------------------------------------------------------------------- +ODBTableDecorator::~ODBTableDecorator() +{ + DBG_DTOR(ODBTableDecorator, NULL); + if ( m_pColumns ) + delete m_pColumns; +} + +//-------------------------------------------------------------------------- +Sequence< sal_Int8 > ODBTableDecorator::getImplementationId() throw (RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ODBTableDecorator::getImplementationId" ); + static OImplementationId * pId = 0; + if (! pId) + { + MutexGuard aGuard( Mutex::getGlobalMutex() ); + if (! pId) + { + static OImplementationId aId; + pId = &aId; + } + } + return pId->getImplementationId(); +} + +// OComponentHelper +//------------------------------------------------------------------------------ +void SAL_CALL ODBTableDecorator::disposing() +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ODBTableDecorator::disposing" ); + OPropertySetHelper::disposing(); + OTableDescriptor_BASE::disposing(); + + MutexGuard aGuard(m_aMutex); + m_xTable = NULL; + m_xMetaData = NULL; + m_pTables = NULL; + m_xColumnDefinitions = NULL; + m_xNumberFormats = NULL; + if ( m_pColumns ) + m_pColumns->disposing(); + m_xColumnMediator = NULL; +} +// ----------------------------------------------------------------------------- +sal_Bool SAL_CALL ODBTableDecorator::convertFastPropertyValue( + Any & rConvertedValue, + Any & rOldValue, + sal_Int32 nHandle, + const Any& rValue ) + throw (::com::sun::star::lang::IllegalArgumentException) +{ + //RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ODBTableDecorator::convertFastPropertyValue" ); + sal_Bool bRet = sal_True; + switch(nHandle) + { + case PROPERTY_ID_PRIVILEGES: + case PROPERTY_ID_FILTER: + case PROPERTY_ID_ORDER: + case PROPERTY_ID_APPLYFILTER: + case PROPERTY_ID_FONT: + case PROPERTY_ID_ROW_HEIGHT: + case PROPERTY_ID_TEXTCOLOR: + case PROPERTY_ID_TEXTLINECOLOR: + case PROPERTY_ID_TEXTEMPHASIS: + case PROPERTY_ID_TEXTRELIEF: + case PROPERTY_ID_FONTCHARWIDTH: + case PROPERTY_ID_FONTCHARSET: + case PROPERTY_ID_FONTFAMILY: + case PROPERTY_ID_FONTHEIGHT: + case PROPERTY_ID_FONTKERNING: + case PROPERTY_ID_FONTNAME: + case PROPERTY_ID_FONTORIENTATION: + case PROPERTY_ID_FONTPITCH: + case PROPERTY_ID_FONTSLANT: + case PROPERTY_ID_FONTSTRIKEOUT: + case PROPERTY_ID_FONTSTYLENAME: + case PROPERTY_ID_FONTUNDERLINE: + case PROPERTY_ID_FONTWEIGHT: + case PROPERTY_ID_FONTWIDTH: + case PROPERTY_ID_FONTWORDLINEMODE: + case PROPERTY_ID_FONTTYPE: + bRet = ODataSettings::convertFastPropertyValue(rConvertedValue, rOldValue,nHandle,rValue); + break; + + default: + { + Any aValue; + getFastPropertyValue(aValue,nHandle); + bRet = ::comphelper::tryPropertyValue(rConvertedValue,rOldValue,rValue,aValue,::getCppuType(reinterpret_cast< ::rtl::OUString*>(NULL))); + } + break; // we assume that it works + } + return bRet; +} +// ----------------------------------------------------------------------------- +void ODBTableDecorator::setFastPropertyValue_NoBroadcast(sal_Int32 _nHandle, const Any& _rValue) throw (Exception) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ODBTableDecorator::setFastPropertyValue_NoBroadcast" ); + switch(_nHandle) + { + case PROPERTY_ID_PRIVILEGES: + OSL_ENSURE(0,"Property is readonly!"); + case PROPERTY_ID_FILTER: + case PROPERTY_ID_ORDER: + case PROPERTY_ID_APPLYFILTER: + case PROPERTY_ID_FONT: + case PROPERTY_ID_ROW_HEIGHT: + case PROPERTY_ID_TEXTCOLOR: + case PROPERTY_ID_TEXTLINECOLOR: + case PROPERTY_ID_TEXTEMPHASIS: + case PROPERTY_ID_TEXTRELIEF: + case PROPERTY_ID_FONTCHARWIDTH: + case PROPERTY_ID_FONTCHARSET: + case PROPERTY_ID_FONTFAMILY: + case PROPERTY_ID_FONTHEIGHT: + case PROPERTY_ID_FONTKERNING: + case PROPERTY_ID_FONTNAME: + case PROPERTY_ID_FONTORIENTATION: + case PROPERTY_ID_FONTPITCH: + case PROPERTY_ID_FONTSLANT: + case PROPERTY_ID_FONTSTRIKEOUT: + case PROPERTY_ID_FONTSTYLENAME: + case PROPERTY_ID_FONTUNDERLINE: + case PROPERTY_ID_FONTWEIGHT: + case PROPERTY_ID_FONTWIDTH: + case PROPERTY_ID_FONTWORDLINEMODE: + case PROPERTY_ID_FONTTYPE: + + ODataSettings::setFastPropertyValue_NoBroadcast(_nHandle, _rValue); + break; + case PROPERTY_ID_CATALOGNAME: + { + Reference<XPropertySet> xProp(m_xTable,UNO_QUERY); + xProp->setPropertyValue(PROPERTY_CATALOGNAME,_rValue); + } + break; + case PROPERTY_ID_SCHEMANAME: + { + Reference<XPropertySet> xProp(m_xTable,UNO_QUERY); + xProp->setPropertyValue(PROPERTY_SCHEMANAME,_rValue); + } + break; + case PROPERTY_ID_NAME: + { + Reference<XPropertySet> xProp(m_xTable,UNO_QUERY); + xProp->setPropertyValue(PROPERTY_NAME,_rValue); + } + break; + case PROPERTY_ID_DESCRIPTION: + { + Reference<XPropertySet> xProp(m_xTable,UNO_QUERY); + xProp->setPropertyValue(PROPERTY_DESCRIPTION,_rValue); + } + break; + case PROPERTY_ID_TYPE: + { + Reference<XPropertySet> xProp(m_xTable,UNO_QUERY); + xProp->setPropertyValue(PROPERTY_TYPE,_rValue); + } + break; + } +} +//------------------------------------------------------------------------------ +void ODBTableDecorator::getFastPropertyValue(Any& _rValue, sal_Int32 _nHandle) const +{ + //RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ODBTableDecorator::getFastPropertyValue" ); + switch(_nHandle) + { + case PROPERTY_ID_PRIVILEGES: + { + if ( -1 == m_nPrivileges ) + fillPrivileges(); + Reference<XPropertySet> xProp(m_xTable,UNO_QUERY); + Reference<XPropertySetInfo> xInfo = xProp->getPropertySetInfo(); + if ( xInfo->hasPropertyByName(PROPERTY_PRIVILEGES) ) + { + _rValue <<= m_nPrivileges; + break; + } + } + // run through + + case PROPERTY_ID_FILTER: + case PROPERTY_ID_ORDER: + case PROPERTY_ID_APPLYFILTER: + case PROPERTY_ID_FONT: + case PROPERTY_ID_ROW_HEIGHT: + case PROPERTY_ID_TEXTCOLOR: + case PROPERTY_ID_TEXTLINECOLOR: + case PROPERTY_ID_TEXTEMPHASIS: + case PROPERTY_ID_TEXTRELIEF: + case PROPERTY_ID_FONTCHARWIDTH: + case PROPERTY_ID_FONTCHARSET: + case PROPERTY_ID_FONTFAMILY: + case PROPERTY_ID_FONTHEIGHT: + case PROPERTY_ID_FONTKERNING: + case PROPERTY_ID_FONTNAME: + case PROPERTY_ID_FONTORIENTATION: + case PROPERTY_ID_FONTPITCH: + case PROPERTY_ID_FONTSLANT: + case PROPERTY_ID_FONTSTRIKEOUT: + case PROPERTY_ID_FONTSTYLENAME: + case PROPERTY_ID_FONTUNDERLINE: + case PROPERTY_ID_FONTWEIGHT: + case PROPERTY_ID_FONTWIDTH: + case PROPERTY_ID_FONTWORDLINEMODE: + case PROPERTY_ID_FONTTYPE: + ODataSettings::getFastPropertyValue(_rValue, _nHandle); + break; + case PROPERTY_ID_CATALOGNAME: + { + Reference<XPropertySet> xProp(m_xTable,UNO_QUERY); + _rValue = xProp->getPropertyValue(PROPERTY_CATALOGNAME); + } + break; + case PROPERTY_ID_SCHEMANAME: + { + Reference<XPropertySet> xProp(m_xTable,UNO_QUERY); + _rValue = xProp->getPropertyValue(PROPERTY_SCHEMANAME); + } + break; + case PROPERTY_ID_NAME: + { + Reference<XPropertySet> xProp(m_xTable,UNO_QUERY); + _rValue = xProp->getPropertyValue(PROPERTY_NAME); + } + break; + case PROPERTY_ID_DESCRIPTION: + { + Reference<XPropertySet> xProp(m_xTable,UNO_QUERY); + _rValue = xProp->getPropertyValue(PROPERTY_DESCRIPTION); + } + break; + case PROPERTY_ID_TYPE: + { + Reference<XPropertySet> xProp(m_xTable,UNO_QUERY); + _rValue = xProp->getPropertyValue(PROPERTY_TYPE); + } + break; + default: + OSL_ENSURE(0,"Invalid Handle for table"); + } +} +// ------------------------------------------------------------------------- +void ODBTableDecorator::construct() +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ODBTableDecorator::construct" ); + sal_Bool bNotFound = sal_True; + Reference<XPropertySet> xProp(m_xTable,UNO_QUERY); + if ( xProp.is() ) + { + Reference<XPropertySetInfo> xInfo = xProp->getPropertySetInfo(); + bNotFound = !xInfo->hasPropertyByName(PROPERTY_PRIVILEGES); + } + if ( bNotFound ) + registerProperty(PROPERTY_PRIVILEGES, PROPERTY_ID_PRIVILEGES, PropertyAttribute::BOUND | PropertyAttribute::READONLY, + &m_nPrivileges, ::getCppuType(static_cast<sal_Int32*>(NULL))); +} +// ----------------------------------------------------------------------------- +::cppu::IPropertyArrayHelper* ODBTableDecorator::createArrayHelper(sal_Int32 /*_nId*/) const +{ + //RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ODBTableDecorator::createArrayHelper" ); + Reference<XPropertySet> xProp(m_xTable,UNO_QUERY); + Reference<XPropertySetInfo> xInfo = xProp->getPropertySetInfo(); + + Sequence< Property > aTableProps = xInfo->getProperties(); + Property* pIter = aTableProps.getArray(); + Property* pEnd = pIter + aTableProps.getLength(); + for (;pIter != pEnd ; ++pIter) + { + if (0 == pIter->Name.compareToAscii(PROPERTY_CATALOGNAME)) + pIter->Handle = PROPERTY_ID_CATALOGNAME; + else if (0 ==pIter->Name.compareToAscii(PROPERTY_SCHEMANAME)) + pIter->Handle = PROPERTY_ID_SCHEMANAME; + else if (0 ==pIter->Name.compareToAscii(PROPERTY_NAME)) + pIter->Handle = PROPERTY_ID_NAME; + else if (0 ==pIter->Name.compareToAscii(PROPERTY_DESCRIPTION)) + pIter->Handle = PROPERTY_ID_DESCRIPTION; + else if (0 ==pIter->Name.compareToAscii(PROPERTY_TYPE)) + pIter->Handle = PROPERTY_ID_TYPE; + else if (0 ==pIter->Name.compareToAscii(PROPERTY_PRIVILEGES)) + pIter->Handle = PROPERTY_ID_PRIVILEGES; + } + + describeProperties(aTableProps); + + return new ::cppu::OPropertyArrayHelper(aTableProps); +} +// ----------------------------------------------------------------------------- +::cppu::IPropertyArrayHelper & SAL_CALL ODBTableDecorator::getInfoHelper() +{ + //RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ODBTableDecorator::getInfoHelper" ); + Reference<XPropertySet> xProp(m_xTable,UNO_QUERY); + + Reference<XPropertySetInfo> xInfo = xProp->getPropertySetInfo(); + bool bIsDescriptor = (xInfo->getPropertyByName(PROPERTY_NAME).Attributes & PropertyAttribute::READONLY) == 0; + + return *ODBTableDecorator_PROP::getArrayHelper( bIsDescriptor ? 0 : 1 ); + + // TODO: this is a HACK, and prone to errors + // The OIdPropertyArrayUsageHelper is intended for classes where there exists a known, limited + // number of different property set infos (distinguished by the ID), all implemented by this very + // same class. + // However, in this case here we have an unknown, potentially unlimited number of different + // property set infos: Depending on the table for which we act as decorator, different property + // sets might exist. +} +// ------------------------------------------------------------------------- +// XServiceInfo +IMPLEMENT_SERVICE_INFO1(ODBTableDecorator, "com.sun.star.sdb.dbaccess.ODBTableDecorator", SERVICE_SDBCX_TABLE) +// ------------------------------------------------------------------------- +Any SAL_CALL ODBTableDecorator::queryInterface( const Type & rType ) throw(RuntimeException) +{ + //RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ODBTableDecorator::queryInterface" ); + Any aRet; + if(m_xTable.is()) + { + aRet = m_xTable->queryInterface(rType); + if(aRet.hasValue()) + { // now we know that our table supports this type so we return ourself + aRet = OTableDescriptor_BASE::queryInterface(rType); + if(!aRet.hasValue()) + aRet = ODataSettings::queryInterface(rType); + } + } + + return aRet; +} +// ------------------------------------------------------------------------- +Sequence< Type > SAL_CALL ODBTableDecorator::getTypes( ) throw(RuntimeException) +{ + //RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ODBTableDecorator::getTypes" ); + Reference<XTypeProvider> xTypes(m_xTable,UNO_QUERY); + OSL_ENSURE(xTypes.is(),"Table must be a TypePropvider!"); + return xTypes->getTypes(); +} + +// ----------------------------------------------------------------------------- +// XRename, +//------------------------------------------------------------------------------ +void SAL_CALL ODBTableDecorator::rename( const ::rtl::OUString& _rNewName ) throw(SQLException, ElementExistException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ODBTableDecorator::rename" ); + ::osl::MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OTableDescriptor_BASE::rBHelper.bDisposed); + Reference<XRename> xRename(m_xTable,UNO_QUERY); + if(xRename.is()) + { +// ::rtl::OUString sOldName; +// Reference<XPropertySet> xProp(m_xTable,UNO_QUERY); +// xProp->getPropertyValue(PROPERTY_NAME) >>= sOldName; + xRename->rename(_rNewName); + } + else // not supported + throw SQLException(DBACORE_RESSTRING(RID_STR_NO_TABLE_RENAME),*this,SQLSTATE_GENERAL,1000,Any() ); +} + +// XAlterTable, +//------------------------------------------------------------------------------ +void SAL_CALL ODBTableDecorator::alterColumnByName( const ::rtl::OUString& _rName, const Reference< XPropertySet >& _rxDescriptor ) throw(SQLException, NoSuchElementException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ODBTableDecorator::alterColumnByName" ); + ::osl::MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OTableDescriptor_BASE::rBHelper.bDisposed); + Reference<XAlterTable> xAlter(m_xTable,UNO_QUERY); + if(xAlter.is()) + { + xAlter->alterColumnByName(_rName,_rxDescriptor); + } + else + throw SQLException(DBACORE_RESSTRING(RID_STR_COLUMN_ALTER_BY_NAME),*this,SQLSTATE_GENERAL,1000,Any() ); + if(m_pColumns) + m_pColumns->refresh(); +} + +//------------------------------------------------------------------------------ +void SAL_CALL ODBTableDecorator::alterColumnByIndex( sal_Int32 _nIndex, const Reference< XPropertySet >& _rxDescriptor ) throw(SQLException, IndexOutOfBoundsException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ODBTableDecorator::alterColumnByIndex" ); + ::osl::MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OTableDescriptor_BASE::rBHelper.bDisposed); + Reference<XAlterTable> xAlter(m_xTable,UNO_QUERY); + if(xAlter.is()) + { + xAlter->alterColumnByIndex(_nIndex,_rxDescriptor); + if(m_pColumns) + m_pColumns->refresh(); + } + else // not supported + throw SQLException(DBACORE_RESSTRING(RID_STR_COLUMN_ALTER_BY_INDEX),*this,SQLSTATE_GENERAL,1000,Any() ); +} +// ----------------------------------------------------------------------------- +Reference< XNameAccess> ODBTableDecorator::getIndexes() throw (RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ODBTableDecorator::getIndexes" ); + ::osl::MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OTableDescriptor_BASE::rBHelper.bDisposed); + return Reference< XIndexesSupplier>(m_xTable,UNO_QUERY)->getIndexes(); +} +// ------------------------------------------------------------------------- +Reference< XIndexAccess> ODBTableDecorator::getKeys() throw (RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ODBTableDecorator::getKeys" ); + ::osl::MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OTableDescriptor_BASE::rBHelper.bDisposed); + return Reference< XKeysSupplier>(m_xTable,UNO_QUERY)->getKeys(); +} +// ------------------------------------------------------------------------- +Reference< XNameAccess> ODBTableDecorator::getColumns() throw (RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ODBTableDecorator::getColumns" ); + ::osl::MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OTableDescriptor_BASE::rBHelper.bDisposed); + + if(!m_pColumns) + refreshColumns(); + + return m_pColumns; +} +// ----------------------------------------------------------------------------- +::rtl::OUString SAL_CALL ODBTableDecorator::getName() throw(RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ODBTableDecorator::getName" ); + ::osl::MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OTableDescriptor_BASE::rBHelper.bDisposed); + Reference<XNamed> xName(m_xTable,UNO_QUERY); + OSL_ENSURE(xName.is(),"Table should support the XNamed interface"); + return xName->getName(); +} +// ----------------------------------------------------------------------------- +sal_Int64 SAL_CALL ODBTableDecorator::getSomething( const Sequence< sal_Int8 >& rId ) throw(RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ODBTableDecorator::getSomething" ); + if (rId.getLength() == 16 && 0 == rtl_compareMemory(getUnoTunnelImplementationId().getConstArray(), rId.getConstArray(), 16 ) ) + return reinterpret_cast<sal_Int64>(this); + + sal_Int64 nRet = 0; + Reference<XUnoTunnel> xTunnel(m_xTable,UNO_QUERY); + if(xTunnel.is()) + nRet = xTunnel->getSomething(rId); + return nRet; +} +// ----------------------------------------------------------------------------- +Sequence< sal_Int8 > ODBTableDecorator::getUnoTunnelImplementationId() +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ODBTableDecorator::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(); +} +// ----------------------------------------------------------------------------- +void ODBTableDecorator::fillPrivileges() const +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ODBTableDecorator::fillPrivileges" ); + // somebody is asking for the privileges an we do not know them, yet + m_nPrivileges = 0; + try + { + Reference<XPropertySet> xProp(m_xTable,UNO_QUERY); + if ( xProp.is() ) + { + if ( xProp->getPropertySetInfo()->hasPropertyByName(PROPERTY_PRIVILEGES) ) + { + xProp->getPropertyValue(PROPERTY_PRIVILEGES) >>= m_nPrivileges; + } + if ( m_nPrivileges == 0 ) // second chance + { + ::rtl::OUString sCatalog,sSchema,sName; + xProp->getPropertyValue(PROPERTY_CATALOGNAME) >>= sCatalog; + xProp->getPropertyValue(PROPERTY_SCHEMANAME) >>= sSchema; + xProp->getPropertyValue(PROPERTY_NAME) >>= sName; + m_nPrivileges = ::dbtools::getTablePrivileges(getMetaData(),sCatalog,sSchema, sName); + } + } + } + catch(const SQLException& e) + { + (void)e; + DBG_ERROR("ODBTableDecorator::ODBTableDecorator : could not collect the privileges !"); + } +} +// ----------------------------------------------------------------------------- +Reference< XPropertySet > SAL_CALL ODBTableDecorator::createDataDescriptor( ) throw (RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ODBTableDecorator::createDataDescriptor" ); + ::osl::MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OTableDescriptor_BASE::rBHelper.bDisposed); + + Reference< XDataDescriptorFactory > xFactory( m_xTable, UNO_QUERY ); + DBG_ASSERT( xFactory.is(), "ODBTableDecorator::createDataDescriptor: invalid table!" ); + Reference< XColumnsSupplier > xColsSupp; + if ( xFactory.is() ) + xColsSupp = xColsSupp.query( xFactory->createDataDescriptor() ); + + return new ODBTableDecorator( + m_xConnection, + xColsSupp, + m_xNumberFormats, + NULL + ); +} +// ----------------------------------------------------------------------------- +Reference< ::com::sun::star::beans::XPropertySetInfo > SAL_CALL ODBTableDecorator::getPropertySetInfo( ) throw(RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ODBTableDecorator::getPropertySetInfo" ); + return ::cppu::OPropertySetHelper::createPropertySetInfo(getInfoHelper()); +} +// ----------------------------------------------------------------------------- +void ODBTableDecorator::refreshColumns() +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ODBTableDecorator::refreshColumns" ); + ::osl::MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OTableDescriptor_BASE::rBHelper.bDisposed); + + ::std::vector< ::rtl::OUString> aVector; + + Reference<XNameAccess> xNames; + if(m_xTable.is()) + { + xNames = m_xTable->getColumns(); + if(xNames.is()) + { + Sequence< ::rtl::OUString> aNames = xNames->getElementNames(); + const ::rtl::OUString* pIter = aNames.getConstArray(); + const ::rtl::OUString* pEnd = pIter + aNames.getLength(); + for(;pIter != pEnd;++pIter) + aVector.push_back(*pIter); + } + } + if(!m_pColumns) + { + OColumns* pCol = new OColumns(*this,m_aMutex,xNames,m_xMetaData.is() && m_xMetaData->supportsMixedCaseQuotedIdentifiers(),aVector, + this,this, + m_xMetaData.is() && m_xMetaData->supportsAlterTableWithAddColumn(), + m_xMetaData.is() && m_xMetaData->supportsAlterTableWithDropColumn()); + + pCol->setParent(*this); + OContainerMediator* pMediator = new OContainerMediator( pCol, m_xColumnDefinitions, m_xConnection, OContainerMediator::eColumns ); + m_xColumnMediator = pMediator; + pCol->setMediator( pMediator ); + m_pColumns = pCol; + } + else + m_pColumns->reFill(aVector); +} +// ----------------------------------------------------------------------------- +OColumn* ODBTableDecorator::createColumn(const ::rtl::OUString& _rName) const +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ODBTableDecorator::createColumn" ); + OColumn* pReturn = NULL; + + Reference<XNameAccess> xNames; + if ( m_xTable.is() ) + { + xNames = m_xTable->getColumns(); + + if ( xNames.is() && xNames->hasByName(_rName) ) + { + Reference<XPropertySet> xProp(xNames->getByName(_rName),UNO_QUERY); + + Reference<XPropertySet> xColumnDefintion; + if ( m_xColumnDefinitions.is() && m_xColumnDefinitions->hasByName(_rName)) + xColumnDefintion.set(m_xColumnDefinitions->getByName(_rName),UNO_QUERY); + + pReturn = new OTableColumnWrapper( xProp, xColumnDefintion, false ); + } + } + return pReturn; +} +// ----------------------------------------------------------------------------- +void ODBTableDecorator::columnAppended( const Reference< XPropertySet >& /*_rxSourceDescriptor*/ ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ODBTableDecorator::columnAppended" ); + // not interested in +} +// ----------------------------------------------------------------------------- +void ODBTableDecorator::columnDropped(const ::rtl::OUString& _sName) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ODBTableDecorator::columnDropped" ); + Reference<XDrop> xDrop(m_xColumnDefinitions,UNO_QUERY); + if ( xDrop.is() && m_xColumnDefinitions->hasByName(_sName) ) + xDrop->dropByName(_sName); +} + +// ----------------------------------------------------------------------------- +Reference< XPropertySet > ODBTableDecorator::createColumnDescriptor() +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ODBTableDecorator::createColumnDescriptor" ); + Reference<XDataDescriptorFactory> xNames; + if(m_xTable.is()) + xNames.set(m_xTable->getColumns(),UNO_QUERY); + Reference< XPropertySet > xRet; + if ( xNames.is() ) + xRet = new OTableColumnDescriptorWrapper( xNames->createDataDescriptor(), false, true ); + return xRet; +} +// ----------------------------------------------------------------------------- +void SAL_CALL ODBTableDecorator::acquire() throw() +{ + OTableDescriptor_BASE::acquire(); +} +// ----------------------------------------------------------------------------- +void SAL_CALL ODBTableDecorator::release() throw() +{ + OTableDescriptor_BASE::release(); +} + +// ----------------------------------------------------------------------------- +void SAL_CALL ODBTableDecorator::setName( const ::rtl::OUString& /*aName*/ ) throw (::com::sun::star::uno::RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ODBTableDecorator::setName" ); + throwFunctionNotSupportedException( "XNamed::setName", *this ); +} + +// ----------------------------------------------------------------------------- + + diff --git a/dbaccess/source/core/api/View.cxx b/dbaccess/source/core/api/View.cxx new file mode 100644 index 000000000000..fa528d203466 --- /dev/null +++ b/dbaccess/source/core/api/View.cxx @@ -0,0 +1,161 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: View.cxx,v $ + * $Revision: 1.3 $ + * + * 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_dbaccess.hxx" + +#include "View.hxx" +#include "dbastrings.hrc" + +#include "connectivity/dbexception.hxx" +#include "connectivity/dbtools.hxx" + +/** === begin UNO includes === **/ +#include <com/sun/star/lang/WrappedTargetException.hpp> +#include <com/sun/star/lang/DisposedException.hpp> +#include <com/sun/star/sdbc/XRow.hpp> +/** === end UNO includes === **/ + +#include <cppuhelper/exc_hlp.hxx> +#include <tools/diagnose_ex.h> +#include <unotools/sharedunocomponent.hxx> + +//........................................................................ +namespace dbaccess +{ +//........................................................................ + + /** === begin UNO using === **/ + using namespace ::com::sun::star::uno; + using ::com::sun::star::sdbc::XDatabaseMetaData; + using ::com::sun::star::sdbc::SQLException; + using ::com::sun::star::sdbc::XConnection; + using ::com::sun::star::lang::WrappedTargetException; + using ::com::sun::star::lang::XMultiServiceFactory; + using ::com::sun::star::sdbc::XResultSet; + using ::com::sun::star::sdbc::XStatement; + using ::com::sun::star::lang::DisposedException; + using ::com::sun::star::sdbc::XRow; + /** === end UNO using === **/ + + ::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; + } + //==================================================================== + //= View + //==================================================================== + //-------------------------------------------------------------------- + View::View( const Reference< XConnection >& _rxConnection, sal_Bool _bCaseSensitive, + const ::rtl::OUString& _rCatalogName,const ::rtl::OUString& _rSchemaName, const ::rtl::OUString& _rName ) + :View_Base( _bCaseSensitive, _rName, _rxConnection->getMetaData(), 0, ::rtl::OUString(), _rSchemaName, _rCatalogName ) + { + m_nCommandHandle = getProperty(PROPERTY_COMMAND).Handle; + try + { + Reference<XMultiServiceFactory> xFac(_rxConnection,UNO_QUERY_THROW); + static const ::rtl::OUString s_sViewAccess(RTL_CONSTASCII_USTRINGPARAM("ViewAccessServiceName")); + m_xViewAccess.set(xFac->createInstance(lcl_getServiceNameForSetting(_rxConnection,s_sViewAccess)),UNO_QUERY); + } + catch(const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + } + + //-------------------------------------------------------------------- + View::~View() + { + } + + //-------------------------------------------------------------------- + IMPLEMENT_FORWARD_REFCOUNT( View, View_Base ) + IMPLEMENT_GET_IMPLEMENTATION_ID( View ) + // ------------------------------------------------------------------------- + Any SAL_CALL View::queryInterface( const Type & _rType ) throw(RuntimeException) + { + if(_rType == getCppuType( (Reference<XAlterView>*)0) && !m_xViewAccess.is() ) + return Any(); + Any aReturn = View_Base::queryInterface( _rType ); + if ( !aReturn.hasValue() ) + aReturn = View_IBASE::queryInterface( _rType ); + return aReturn; + } + // ------------------------------------------------------------------------- + Sequence< Type > SAL_CALL View::getTypes( ) throw(RuntimeException) + { + Type aAlterType = getCppuType( (Reference<XAlterView>*)0); + + Sequence< Type > aTypes( ::comphelper::concatSequences(View_Base::getTypes(),View_IBASE::getTypes()) ); + ::std::vector<Type> aOwnTypes; + aOwnTypes.reserve(aTypes.getLength()); + + const Type* pIter = aTypes.getConstArray(); + const Type* pEnd = pIter + aTypes.getLength(); + for(;pIter != pEnd ;++pIter) + { + if( (*pIter != aAlterType || m_xViewAccess.is()) ) + aOwnTypes.push_back(*pIter); + } + + Type* pTypes = aOwnTypes.empty() ? 0 : &aOwnTypes[0]; + return Sequence< Type >(pTypes, aOwnTypes.size()); + } + + //-------------------------------------------------------------------- + void SAL_CALL View::alterCommand( const ::rtl::OUString& _rNewCommand ) throw (SQLException, RuntimeException) + { + OSL_ENSURE(m_xViewAccess.is(),"Illegal call to AlterView!"); + m_xViewAccess->alterCommand(this,_rNewCommand); + } + + //-------------------------------------------------------------------- + void SAL_CALL View::getFastPropertyValue( Any& _rValue, sal_Int32 _nHandle ) const + { + if ( _nHandle == m_nCommandHandle && m_xViewAccess.is() ) + { + // retrieve the very current command, don't rely on the base classes cached value + // (which we initialized empty, anyway) + _rValue <<= m_xViewAccess->getCommand(const_cast<View*>(this)); + return; + } + + View_Base::getFastPropertyValue( _rValue, _nHandle ); + } + // ----------------------------------------------------------------------------- +//........................................................................ +} // namespace dbaccess +//........................................................................ diff --git a/dbaccess/source/core/api/WrappedResultSet.cxx b/dbaccess/source/core/api/WrappedResultSet.cxx new file mode 100644 index 000000000000..22e8f61383ac --- /dev/null +++ b/dbaccess/source/core/api/WrappedResultSet.cxx @@ -0,0 +1,255 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: BookmarkSet.cxx,v $ + * $Revision: 1.21 $ + * + * 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_dbaccess.hxx" +#include "WrappedResultSet.hxx" +#include "core_resource.hxx" +#include "core_resource.hrc" +#include <com/sun/star/sdbc/XResultSetUpdate.hpp> +#include <connectivity/dbexception.hxx> +#include <rtl/logfile.hxx> + +#include <limits> + +using namespace dbaccess; +using namespace ::connectivity; +using 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::sdb; +using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::lang; +// using namespace ::cppu; +using namespace ::osl; + +void WrappedResultSet::construct(const Reference< XResultSet>& _xDriverSet,const ::rtl::OUString& i_sRowSetFilter) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "WrappedResultSet::construct" ); + OCacheSet::construct(_xDriverSet,i_sRowSetFilter); + m_xUpd.set(_xDriverSet,UNO_QUERY_THROW); + m_xRowLocate.set(_xDriverSet,UNO_QUERY_THROW); + m_xUpdRow.set(_xDriverSet,UNO_QUERY_THROW); +} +// ----------------------------------------------------------------------------- +Any SAL_CALL WrappedResultSet::getBookmark() throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "WrappedResultSet::getBookmark" ); + if ( m_xRowLocate.is() ) + { + return m_xRowLocate->getBookmark( ); + } + return makeAny(m_xDriverSet->getRow()); +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL WrappedResultSet::moveToBookmark( const Any& bookmark ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "WrappedResultSet::moveToBookmark" ); + return m_xRowLocate->moveToBookmark( bookmark ); +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL WrappedResultSet::moveRelativeToBookmark( const Any& bookmark, sal_Int32 rows ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "WrappedResultSet::moveRelativeToBookmark" ); + return m_xRowLocate->moveRelativeToBookmark( bookmark,rows ); +} +// ------------------------------------------------------------------------- +sal_Int32 SAL_CALL WrappedResultSet::compareBookmarks( const Any& _first, const Any& _second ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "WrappedResultSet::compareBookmarks" ); + return m_xRowLocate->compareBookmarks( _first,_second ); +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL WrappedResultSet::hasOrderedBookmarks( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "WrappedResultSet::hasOrderedBookmarks" ); + return m_xRowLocate->hasOrderedBookmarks(); +} +// ------------------------------------------------------------------------- +sal_Int32 SAL_CALL WrappedResultSet::hashBookmark( const Any& bookmark ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "WrappedResultSet::hashBookmark" ); + return m_xRowLocate->hashBookmark(bookmark); +} +// ------------------------------------------------------------------------- +// ::com::sun::star::sdbcx::XDeleteRows +Sequence< sal_Int32 > SAL_CALL WrappedResultSet::deleteRows( const Sequence< Any >& rows ,const connectivity::OSQLTable& /*_xTable*/) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "WrappedResultSet::deleteRows" ); + Reference< ::com::sun::star::sdbcx::XDeleteRows> xDeleteRow(m_xRowLocate,UNO_QUERY); + if(xDeleteRow.is()) + { + return xDeleteRow->deleteRows(rows); + } + return Sequence< sal_Int32 >(); +} +// ------------------------------------------------------------------------- +void SAL_CALL WrappedResultSet::insertRow( const ORowSetRow& _rInsertRow,const connectivity::OSQLTable& /*_xTable*/ ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "WrappedResultSet::insertRow" ); + + m_xUpd->moveToInsertRow(); + sal_Int32 i = 1; + connectivity::ORowVector< ORowSetValue > ::Vector::iterator aEnd = _rInsertRow->get().end(); + for(connectivity::ORowVector< ORowSetValue > ::Vector::iterator aIter = _rInsertRow->get().begin()+1;aIter != aEnd;++aIter,++i) + { + aIter->setSigned(m_aSignedFlags[i-1]); + updateColumn(i,m_xUpdRow,*aIter); + } + m_xUpd->insertRow(); + (*_rInsertRow->get().begin()) = getBookmark(); +} +// ------------------------------------------------------------------------- +void SAL_CALL WrappedResultSet::updateRow(const ORowSetRow& _rInsertRow ,const ORowSetRow& _rOrginalRow,const connectivity::OSQLTable& /*_xTable*/ ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "WrappedResultSet::updateRow" ); + sal_Int32 i = 1; + connectivity::ORowVector< ORowSetValue > ::Vector::const_iterator aOrgIter = _rOrginalRow->get().begin()+1; + connectivity::ORowVector< ORowSetValue > ::Vector::iterator aEnd = _rInsertRow->get().end(); + for(connectivity::ORowVector< ORowSetValue > ::Vector::iterator aIter = _rInsertRow->get().begin()+1;aIter != aEnd;++aIter,++i,++aOrgIter) + { + aIter->setSigned(aOrgIter->isSigned()); + updateColumn(i,m_xUpdRow,*aIter); + } + m_xUpd->updateRow(); +} +// ------------------------------------------------------------------------- +void SAL_CALL WrappedResultSet::deleteRow(const ORowSetRow& /*_rDeleteRow*/ ,const connectivity::OSQLTable& /*_xTable*/ ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "WrappedResultSet::deleteRow" ); + m_xUpd->deleteRow(); +} +// ------------------------------------------------------------------------- +void SAL_CALL WrappedResultSet::cancelRowUpdates( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "WrappedResultSet::cancelRowUpdates" ); + m_xUpd->cancelRowUpdates(); +} +// ------------------------------------------------------------------------- +void SAL_CALL WrappedResultSet::moveToInsertRow( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "WrappedResultSet::moveToInsertRow" ); + m_xUpd->moveToInsertRow(); +} +// ------------------------------------------------------------------------- +void SAL_CALL WrappedResultSet::moveToCurrentRow( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "WrappedResultSet::moveToCurrentRow" ); + m_xUpd->moveToCurrentRow(); +} +// ------------------------------------------------------------------------- +void WrappedResultSet::fillValueRow(ORowSetRow& _rRow,sal_Int32 _nPosition) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "WrappedResultSet::fillValueRow" ); + OCacheSet::fillValueRow(_rRow,_nPosition); +} +// ------------------------------------------------------------------------- +void WrappedResultSet::updateColumn(sal_Int32 nPos,Reference< XRowUpdate > _xParameter,const ORowSetValue& _rValue) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "WrappedResultSet::updateColumn" ); + if(_rValue.isBound() && _rValue.isModified()) + { + if(_rValue.isNull()) + _xParameter->updateNull(nPos); + else + { + + switch(_rValue.getTypeKind()) + { + case DataType::DECIMAL: + case DataType::NUMERIC: + _xParameter->updateNumericObject(nPos,_rValue.makeAny(),m_xSetMetaData->getScale(nPos)); + break; + case DataType::CHAR: + case DataType::VARCHAR: + //case DataType::DECIMAL: + //case DataType::NUMERIC: + _xParameter->updateString(nPos,_rValue); + break; + case DataType::BIGINT: + if ( _rValue.isSigned() ) + _xParameter->updateLong(nPos,_rValue); + else + _xParameter->updateString(nPos,_rValue); + break; + case DataType::BIT: + case DataType::BOOLEAN: + _xParameter->updateBoolean(nPos,_rValue); + break; + case DataType::TINYINT: + if ( _rValue.isSigned() ) + _xParameter->updateByte(nPos,_rValue); + else + _xParameter->updateShort(nPos,_rValue); + break; + case DataType::SMALLINT: + if ( _rValue.isSigned() ) + _xParameter->updateShort(nPos,_rValue); + else + _xParameter->updateInt(nPos,_rValue); + break; + case DataType::INTEGER: + if ( _rValue.isSigned() ) + _xParameter->updateInt(nPos,_rValue); + else + _xParameter->updateLong(nPos,_rValue); + break; + case DataType::FLOAT: + _xParameter->updateFloat(nPos,_rValue); + break; + case DataType::DOUBLE: + case DataType::REAL: + _xParameter->updateDouble(nPos,_rValue); + break; + case DataType::DATE: + _xParameter->updateDate(nPos,_rValue); + break; + case DataType::TIME: + _xParameter->updateTime(nPos,_rValue); + break; + case DataType::TIMESTAMP: + _xParameter->updateTimestamp(nPos,_rValue); + break; + case DataType::BINARY: + case DataType::VARBINARY: + case DataType::LONGVARBINARY: + _xParameter->updateBytes(nPos,_rValue); + break; + case DataType::BLOB: + case DataType::CLOB: + _xParameter->updateObject(nPos,_rValue.getAny()); + break; + } + } + } +} + diff --git a/dbaccess/source/core/api/WrappedResultSet.hxx b/dbaccess/source/core/api/WrappedResultSet.hxx new file mode 100644 index 000000000000..082811748e6a --- /dev/null +++ b/dbaccess/source/core/api/WrappedResultSet.hxx @@ -0,0 +1,79 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: BookmarkSet.hxx,v $ + * $Revision: 1.11 $ + * + * 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. + * + ************************************************************************/ + +#ifndef DBACCESS_CORE_API_WRAPPEDRESULTSET_HXX +#define DBACCESS_CORE_API_WRAPPEDRESULTSET_HXX + +#ifndef DBACCESS_CORE_API_CACHESET_HXX +#include "CacheSet.hxx" +#endif +#include <com/sun/star/sdbc/XRowUpdate.hpp> +#include <com/sun/star/sdbc/XResultSetUpdate.hpp> + +namespace dbaccess +{ + // this set is used when we have a bookmarkable set from the driver + class WrappedResultSet : public OCacheSet + { + ::com::sun::star::uno::Reference< ::com::sun::star::sdbcx::XRowLocate> m_xRowLocate; + ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XResultSetUpdate> m_xUpd; + ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRowUpdate> m_xUpdRow; + + void updateColumn(sal_Int32 nPos,::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRowUpdate > _xParameter,const connectivity::ORowSetValue& _rValue); + public: + WrappedResultSet() + {} + ~WrappedResultSet() + { + m_xRowLocate = NULL; + } + + virtual void construct(const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XResultSet>& _xDriverSet,const ::rtl::OUString& i_sRowSetFilter); + virtual void fillValueRow(ORowSetRow& _rRow,sal_Int32 _nPosition); + // ::com::sun::star::sdbcx::XRowLocate + virtual ::com::sun::star::uno::Any SAL_CALL getBookmark() throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL moveToBookmark( const ::com::sun::star::uno::Any& bookmark ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL moveRelativeToBookmark( const ::com::sun::star::uno::Any& bookmark, sal_Int32 rows ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Int32 SAL_CALL compareBookmarks( const ::com::sun::star::uno::Any& first, const ::com::sun::star::uno::Any& second ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL hasOrderedBookmarks( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Int32 SAL_CALL hashBookmark( const ::com::sun::star::uno::Any& bookmark ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + // ::com::sun::star::sdbcx::XDeleteRows + virtual ::com::sun::star::uno::Sequence< sal_Int32 > SAL_CALL deleteRows( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& rows ,const connectivity::OSQLTable& _xTable) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + // ::com::sun::star::sdbc::XResultSetUpdate + virtual void SAL_CALL insertRow( const ORowSetRow& _rInsertRow,const connectivity::OSQLTable& _xTable ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL updateRow(const ORowSetRow& _rInsertRow,const ORowSetRow& _rOrginalRow,const connectivity::OSQLTable& _xTable ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL deleteRow(const ORowSetRow& _rInsertRow,const connectivity::OSQLTable& _xTable ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL cancelRowUpdates( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL moveToInsertRow( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL moveToCurrentRow( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + }; +} +#endif // DBACCESS_CORE_API_WRAPPEDRESULTSET_HXX + diff --git a/dbaccess/source/core/api/callablestatement.cxx b/dbaccess/source/core/api/callablestatement.cxx new file mode 100644 index 000000000000..22057ff7a9f6 --- /dev/null +++ b/dbaccess/source/core/api/callablestatement.cxx @@ -0,0 +1,344 @@ +/************************************************************************* + * + * 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_dbaccess.hxx" +#ifndef _DBA_COREAPI_CALLABLESTATEMENT_HXX_ +#include <callablestatement.hxx> +#endif +#ifndef _COM_SUN_STAR_LANG_DISPOSEDEXCEPTION_HPP_ +#include <com/sun/star/lang/DisposedException.hpp> +#endif +#ifndef _CPPUHELPER_TYPEPROVIDER_HXX_ +#include <cppuhelper/typeprovider.hxx> +#endif +#ifndef _COMPHELPER_PROPERTY_HXX_ +#include <comphelper/property.hxx> +#endif +#ifndef _TOOLS_DEBUG_HXX //autogen +#include <tools/debug.hxx> +#endif +#ifndef DBACCESS_SHARED_DBASTRINGS_HRC +#include "dbastrings.hrc" +#endif +#include <rtl/logfile.hxx> + +using namespace dbaccess; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::cppu; +using namespace ::osl; + +// com::sun::star::lang::XTypeProvider +//-------------------------------------------------------------------------- +Sequence< Type > OCallableStatement::getTypes() throw (RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCallableStatement::getTypes" ); + OTypeCollection aTypes(::getCppuType( (const Reference< XRow > *)0 ), + ::getCppuType( (const Reference< XOutParameters > *)0 ), + OPreparedStatement::getTypes() ); + + return aTypes.getTypes(); +} + +//-------------------------------------------------------------------------- +Sequence< sal_Int8 > OCallableStatement::getImplementationId() throw (RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCallableStatement::getImplementationId" ); + static OImplementationId * pId = 0; + if (! pId) + { + MutexGuard aGuard( Mutex::getGlobalMutex() ); + if (! pId) + { + static OImplementationId aId; + pId = &aId; + } + } + return pId->getImplementationId(); +} + +// com::sun::star::uno::XInterface +//-------------------------------------------------------------------------- +Any OCallableStatement::queryInterface( const Type & rType ) throw (RuntimeException) +{ + //RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCallableStatement::queryInterface" ); + Any aIface = OPreparedStatement::queryInterface( rType ); + if (!aIface.hasValue()) + aIface = ::cppu::queryInterface( + rType, + static_cast< XRow * >( this ), + static_cast< XOutParameters * >( this )); + return aIface; +} + +//-------------------------------------------------------------------------- +void OCallableStatement::acquire() throw () +{ + OPreparedStatement::acquire(); +} + +//-------------------------------------------------------------------------- +void OCallableStatement::release() throw () +{ + OPreparedStatement::release(); +} + +// XServiceInfo +//------------------------------------------------------------------------------ +rtl::OUString OCallableStatement::getImplementationName( ) throw(RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCallableStatement::getImplementationName" ); + return rtl::OUString::createFromAscii("com.sun.star.sdb.OCallableStatement"); +} + +//------------------------------------------------------------------------------ +Sequence< ::rtl::OUString > OCallableStatement::getSupportedServiceNames( ) throw (RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCallableStatement::getSupportedServiceNames" ); + Sequence< ::rtl::OUString > aSNS( 2 ); + aSNS.getArray()[0] = SERVICE_SDBC_CALLABLESTATEMENT; + aSNS.getArray()[1] = SERVICE_SDB_CALLABLESTATEMENT; + return aSNS; +} + +// XOutParameters +//------------------------------------------------------------------------------ +void SAL_CALL OCallableStatement::registerOutParameter( sal_Int32 parameterIndex, sal_Int32 sqlType, const ::rtl::OUString& typeName ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCallableStatement::registerOutParameter" ); + MutexGuard aGuard(m_aMutex); + + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + + + Reference< XOutParameters >(m_xAggregateAsSet, UNO_QUERY)->registerOutParameter( parameterIndex, sqlType, typeName ); +} + +//------------------------------------------------------------------------------ +void SAL_CALL OCallableStatement::registerNumericOutParameter( sal_Int32 parameterIndex, sal_Int32 sqlType, sal_Int32 scale ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCallableStatement::registerNumericOutParameter" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + + Reference< XOutParameters >(m_xAggregateAsSet, UNO_QUERY)->registerNumericOutParameter( parameterIndex, sqlType, scale ); +} + +// XRow +//------------------------------------------------------------------------------ +sal_Bool SAL_CALL OCallableStatement::wasNull( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCallableStatement::wasNull" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + + return Reference< XRow >(m_xAggregateAsSet, UNO_QUERY)->wasNull(); +} + +//------------------------------------------------------------------------------ +::rtl::OUString SAL_CALL OCallableStatement::getString( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCallableStatement::getString" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + + return Reference< XRow >(m_xAggregateAsSet, UNO_QUERY)->getString( columnIndex ); +} + +//------------------------------------------------------------------------------ +sal_Bool SAL_CALL OCallableStatement::getBoolean( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCallableStatement::getBoolean" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + + return Reference< XRow >(m_xAggregateAsSet, UNO_QUERY)->getBoolean( columnIndex ); +} + +//------------------------------------------------------------------------------ +sal_Int8 SAL_CALL OCallableStatement::getByte( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCallableStatement::getByte" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + + return Reference< XRow >(m_xAggregateAsSet, UNO_QUERY)->getByte( columnIndex ); +} + +//------------------------------------------------------------------------------ +sal_Int16 SAL_CALL OCallableStatement::getShort( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCallableStatement::getShort" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + return Reference< XRow >(m_xAggregateAsSet, UNO_QUERY)->getShort( columnIndex ); +} + +//------------------------------------------------------------------------------ +sal_Int32 SAL_CALL OCallableStatement::getInt( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCallableStatement::getInt" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + return Reference< XRow >(m_xAggregateAsSet, UNO_QUERY)->getInt( columnIndex ); +} + +//------------------------------------------------------------------------------ +sal_Int64 SAL_CALL OCallableStatement::getLong( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCallableStatement::getLong" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + return Reference< XRow >(m_xAggregateAsSet, UNO_QUERY)->getLong( columnIndex ); +} + +//------------------------------------------------------------------------------ +float SAL_CALL OCallableStatement::getFloat( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCallableStatement::getFloat" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + return Reference< XRow >(m_xAggregateAsSet, UNO_QUERY)->getFloat( columnIndex ); +} + +//------------------------------------------------------------------------------ +double SAL_CALL OCallableStatement::getDouble( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCallableStatement::getDouble" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + return Reference< XRow >(m_xAggregateAsSet, UNO_QUERY)->getDouble( columnIndex ); +} + +//------------------------------------------------------------------------------ +Sequence< sal_Int8 > SAL_CALL OCallableStatement::getBytes( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCallableStatement::getBytes" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + return Reference< XRow >(m_xAggregateAsSet, UNO_QUERY)->getBytes( columnIndex ); +} + +//------------------------------------------------------------------------------ +::com::sun::star::util::Date SAL_CALL OCallableStatement::getDate( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCallableStatement::getDate" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + return Reference< XRow >(m_xAggregateAsSet, UNO_QUERY)->getDate( columnIndex ); +} + +//------------------------------------------------------------------------------ +::com::sun::star::util::Time SAL_CALL OCallableStatement::getTime( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCallableStatement::getTime" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + return Reference< XRow >(m_xAggregateAsSet, UNO_QUERY)->getTime( columnIndex ); +} + +//------------------------------------------------------------------------------ +::com::sun::star::util::DateTime SAL_CALL OCallableStatement::getTimestamp( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCallableStatement::getTimestamp" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + + return Reference< XRow >(m_xAggregateAsSet, UNO_QUERY)->getTimestamp( columnIndex ); +} + +//------------------------------------------------------------------------------ +Reference< ::com::sun::star::io::XInputStream > SAL_CALL OCallableStatement::getBinaryStream( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCallableStatement::getBinaryStream" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + + return Reference< XRow >(m_xAggregateAsSet, UNO_QUERY)->getBinaryStream( columnIndex ); +} + +//------------------------------------------------------------------------------ +Reference< ::com::sun::star::io::XInputStream > SAL_CALL OCallableStatement::getCharacterStream( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCallableStatement::getCharacterStream" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + + return Reference< XRow >(m_xAggregateAsSet, UNO_QUERY)->getCharacterStream( columnIndex ); +} + +//------------------------------------------------------------------------------ +Any SAL_CALL OCallableStatement::getObject( sal_Int32 columnIndex, const Reference< ::com::sun::star::container::XNameAccess >& typeMap ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCallableStatement::getObject" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + + return Reference< XRow >(m_xAggregateAsSet, UNO_QUERY)->getObject( columnIndex, typeMap ); +} + +//------------------------------------------------------------------------------ +Reference< XRef > SAL_CALL OCallableStatement::getRef( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCallableStatement::getRef" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + return Reference< XRow >(m_xAggregateAsSet, UNO_QUERY)->getRef( columnIndex ); +} + +//------------------------------------------------------------------------------ +Reference< XBlob > SAL_CALL OCallableStatement::getBlob( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCallableStatement::getBlob" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + return Reference< XRow >(m_xAggregateAsSet, UNO_QUERY)->getBlob( columnIndex ); +} + +//------------------------------------------------------------------------------ +Reference< XClob > SAL_CALL OCallableStatement::getClob( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCallableStatement::getClob" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + return Reference< XRow >(m_xAggregateAsSet, UNO_QUERY)->getClob( columnIndex ); +} + +//------------------------------------------------------------------------------ +Reference< XArray > SAL_CALL OCallableStatement::getArray( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OCallableStatement::getArray" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + return Reference< XRow >(m_xAggregateAsSet, UNO_QUERY)->getArray( columnIndex ); +} + + diff --git a/dbaccess/source/core/api/column.cxx b/dbaccess/source/core/api/column.cxx new file mode 100644 index 000000000000..292bf5694793 --- /dev/null +++ b/dbaccess/source/core/api/column.cxx @@ -0,0 +1,481 @@ +/************************************************************************* + * + * 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_dbaccess.hxx" + +#include "ContainerMediator.hxx" +#include "apitools.hxx" +#include "column.hxx" +#include "core_resource.hrc" +#include "core_resource.hxx" +#include "dbastrings.hrc" +#include "sdbcoretools.hxx" + +#include <com/sun/star/lang/DisposedException.hpp> +#include <com/sun/star/sdbc/ColumnValue.hpp> +#include <com/sun/star/sdbc/DataType.hpp> + +#include <comphelper/basicio.hxx> +#include <comphelper/enumhelper.hxx> +#include <comphelper/extract.hxx> +#include <comphelper/property.hxx> +#include <comphelper/seqstream.hxx> +#include <comphelper/sequence.hxx> +#include <comphelper/types.hxx> +#include <connectivity/TTableHelper.hxx> +#include <connectivity/dbexception.hxx> +#include <connectivity/dbtools.hxx> +#include <cppuhelper/typeprovider.hxx> +#include <osl/diagnose.h> +#include <tools/debug.hxx> + +#include <algorithm> + +using namespace dbaccess; +using namespace connectivity; +using namespace connectivity; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::awt; +using namespace ::com::sun::star::io; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::util; +using namespace ::osl; +using namespace ::comphelper; +using namespace ::cppu; + +DBG_NAME(OColumn) + +//============================================================ +//= OColumn +//============================================================ +//-------------------------------------------------------------------------- +OColumn::OColumn( const bool _bNameIsReadOnly ) + :OColumnBase( m_aMutex ) + ,::comphelper::OPropertyContainer( OColumnBase::rBHelper ) +{ + DBG_CTOR(OColumn, NULL); + + registerProperty( PROPERTY_NAME, PROPERTY_ID_NAME, _bNameIsReadOnly ? PropertyAttribute::READONLY : 0, + &m_sName, ::getCppuType( &m_sName ) ); +} + +//-------------------------------------------------------------------------- +OColumn::~OColumn() +{ + DBG_DTOR(OColumn, NULL); +} + +// com::sun::star::lang::XTypeProvider +//-------------------------------------------------------------------------- +Sequence< Type > OColumn::getTypes() throw (RuntimeException) +{ + return ::comphelper::concatSequences( + OColumnBase::getTypes(), + ::comphelper::OPropertyContainer::getTypes() + ); +} + +// com::sun::star::uno::XInterface +IMPLEMENT_FORWARD_XINTERFACE2( OColumn, OColumnBase, ::comphelper::OPropertyContainer ) + +// ::com::sun::star::lang::XServiceInfo +//------------------------------------------------------------------------------ +rtl::OUString OColumn::getImplementationName( ) throw(RuntimeException) +{ + return rtl::OUString::createFromAscii("com.sun.star.sdb.OColumn"); +} + +//------------------------------------------------------------------------------ +sal_Bool OColumn::supportsService( const ::rtl::OUString& _rServiceName ) throw (RuntimeException) +{ + return ::comphelper::findValue(getSupportedServiceNames(), _rServiceName, sal_True).getLength() != 0; +} + +//------------------------------------------------------------------------------ +Sequence< ::rtl::OUString > OColumn::getSupportedServiceNames( ) throw (RuntimeException) +{ + Sequence< ::rtl::OUString > aSNS( 1 ); + aSNS[0] = SERVICE_SDBCX_COLUMN; + return aSNS; +} + +// OComponentHelper +//------------------------------------------------------------------------------ +void OColumn::disposing() +{ + OPropertyContainer::disposing(); +} + +// com::sun::star::beans::XPropertySet +//------------------------------------------------------------------------------ +Reference< XPropertySetInfo > OColumn::getPropertySetInfo() throw (RuntimeException) +{ + return createPropertySetInfo( getInfoHelper() ) ; +} + +// ----------------------------------------------------------------------------- +::rtl::OUString SAL_CALL OColumn::getName( ) throw(::com::sun::star::uno::RuntimeException) +{ + return m_sName; +} +// ----------------------------------------------------------------------------- +void SAL_CALL OColumn::setName( const ::rtl::OUString& _rName ) throw(::com::sun::star::uno::RuntimeException) +{ + m_sName = _rName; +} + +// ----------------------------------------------------------------------------- +void OColumn::fireValueChange(const ::connectivity::ORowSetValue& /*_rOldValue*/) +{ + DBG_ERROR( "OColumn::fireValueChange: not implemented!" ); +} + +//------------------------------------------------------------------------------ +void OColumn::registerProperty( const ::rtl::OUString& _rName, sal_Int32 _nHandle, sal_Int32 _nAttributes, void* _pPointerToMember, const Type& _rMemberType ) +{ + ::comphelper::OPropertyContainer::registerProperty( _rName, _nHandle, _nAttributes, _pPointerToMember, _rMemberType ); +} + +//------------------------------------------------------------------------------ +void OColumn::registerMayBeVoidProperty( const ::rtl::OUString& _rName, sal_Int32 _nHandle, sal_Int32 _nAttributes, Any* _pPointerToMember, const Type& _rExpectedType ) +{ + ::comphelper::OPropertyContainer::registerMayBeVoidProperty( _rName, _nHandle, _nAttributes, _pPointerToMember, _rExpectedType ); +} + +//------------------------------------------------------------------------------ +void OColumn::registerPropertyNoMember( const ::rtl::OUString& _rName, sal_Int32 _nHandle, sal_Int32 _nAttributes, const Type& _rType, const void* _pInitialValue ) +{ + ::comphelper::OPropertyContainer::registerPropertyNoMember( _rName, _nHandle, _nAttributes, _rType, _pInitialValue ); +} + +//============================================================ +//= OColumns +//============================================================ +DBG_NAME(OColumns); + +//-------------------------------------------------------------------------- +OColumns::OColumns(::cppu::OWeakObject& _rParent, + ::osl::Mutex& _rMutex, + sal_Bool _bCaseSensitive,const ::std::vector< ::rtl::OUString> &_rVector, + IColumnFactory* _pColFactory, + ::connectivity::sdbcx::IRefreshableColumns* _pRefresh, + sal_Bool _bAddColumn, + sal_Bool _bDropColumn, + sal_Bool _bUseHardRef) + : OColumns_BASE(_rParent,_bCaseSensitive,_rMutex,_rVector,_bUseHardRef) + ,m_pMediator(NULL) + ,m_xDrvColumns(NULL) + ,m_pColFactoryImpl(_pColFactory) + ,m_pRefreshColumns(_pRefresh) + ,m_bInitialized(sal_False) + ,m_bAddColumn(_bAddColumn) + ,m_bDropColumn(_bDropColumn) +{ + DBG_CTOR(OColumns, NULL); +} + +// ------------------------------------------------------------------------- +OColumns::OColumns(::cppu::OWeakObject& _rParent, ::osl::Mutex& _rMutex, + const ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess >& _rxDrvColumns, + sal_Bool _bCaseSensitive,const ::std::vector< ::rtl::OUString> &_rVector, + IColumnFactory* _pColFactory, + ::connectivity::sdbcx::IRefreshableColumns* _pRefresh, + sal_Bool _bAddColumn, + sal_Bool _bDropColumn, + sal_Bool _bUseHardRef) + : OColumns_BASE(_rParent,_bCaseSensitive,_rMutex,_rVector,_bUseHardRef) + ,m_pMediator(NULL) + ,m_xDrvColumns(_rxDrvColumns) + ,m_pColFactoryImpl(_pColFactory) + ,m_pRefreshColumns(_pRefresh) + ,m_bInitialized(sal_False) + ,m_bAddColumn(_bAddColumn) + ,m_bDropColumn(_bDropColumn) +{ + DBG_CTOR(OColumns, NULL); +} +//-------------------------------------------------------------------------- +OColumns::~OColumns() +{ + DBG_DTOR(OColumns, NULL); +} + +// XServiceInfo +//------------------------------------------------------------------------------ +rtl::OUString OColumns::getImplementationName( ) throw(RuntimeException) +{ + return rtl::OUString::createFromAscii("com.sun.star.sdb.OColumns"); +} + +//------------------------------------------------------------------------------ +sal_Bool OColumns::supportsService( const ::rtl::OUString& _rServiceName ) throw (RuntimeException) +{ + return ::comphelper::findValue(getSupportedServiceNames(), _rServiceName, sal_True).getLength() != 0; +} + +//------------------------------------------------------------------------------ +Sequence< ::rtl::OUString > OColumns::getSupportedServiceNames( ) throw (RuntimeException) +{ + Sequence< ::rtl::OUString > aSNS( 1 ); + aSNS[0] = SERVICE_SDBCX_CONTAINER; + return aSNS; +} + +//------------------------------------------------------------------ +void OColumns::append( const ::rtl::OUString& _rName, OColumn* _pColumn ) +{ + MutexGuard aGuard(m_rMutex); + + OSL_ENSURE( _pColumn, "OColumns::append: invalid column!" ); + OSL_ENSURE( !m_pElements->exists( _rName ),"OColumns::append: Column already exists"); + + _pColumn->m_sName = _rName; + + // now really insert the column + insertElement( _rName, _pColumn ); +} + +//------------------------------------------------------------------ +void OColumns::clearColumns() +{ + MutexGuard aGuard(m_rMutex); + disposing(); +} + +// ----------------------------------------------------------------------------- +void SAL_CALL OColumns::disposing(void) +{ + MutexGuard aGuard(m_rMutex); + m_xDrvColumns = NULL; + m_pMediator = NULL; + m_pColFactoryImpl = NULL; + OColumns_BASE::disposing(); +} + +// ------------------------------------------------------------------------- +void OColumns::impl_refresh() throw(::com::sun::star::uno::RuntimeException) +{ + if (m_pRefreshColumns) + m_pRefreshColumns->refreshColumns(); +} + +// ------------------------------------------------------------------------- +connectivity::sdbcx::ObjectType OColumns::createObject(const ::rtl::OUString& _rName) +{ + OSL_ENSURE(m_pColFactoryImpl, "OColumns::createObject: no column factory!"); + + connectivity::sdbcx::ObjectType xRet; + if ( m_pColFactoryImpl ) + { + xRet = m_pColFactoryImpl->createColumn(_rName); + Reference<XChild> xChild(xRet,UNO_QUERY); + if ( xChild.is() ) + xChild->setParent(static_cast<XChild*>(static_cast<TXChild*>(this))); + } + + Reference<XPropertySet> xDest(xRet,UNO_QUERY); + if ( m_pMediator && xDest.is() ) + m_pMediator->notifyElementCreated(_rName,xDest); + + return xRet; +} +// ------------------------------------------------------------------------- +Reference< XPropertySet > OColumns::createDescriptor() +{ + if ( m_pColFactoryImpl ) + { + Reference<XPropertySet> xRet = m_pColFactoryImpl->createColumnDescriptor(); + Reference<XChild> xChild(xRet,UNO_QUERY); + if ( xChild.is() ) + xChild->setParent(static_cast<XChild*>(static_cast<TXChild*>(this))); + return xRet; + } + else + return Reference< XPropertySet >(); +} +// ------------------------------------------------------------------------- +Any SAL_CALL OColumns::queryInterface( const Type & rType ) throw(RuntimeException) +{ + Any aRet; + if(m_xDrvColumns.is()) + { + aRet = m_xDrvColumns->queryInterface(rType); + if ( aRet.hasValue() ) + aRet = OColumns_BASE::queryInterface( rType); + if ( !aRet.hasValue() ) + aRet = TXChild::queryInterface( rType); + return aRet; + } + else if(!m_pTable || (m_pTable && !m_pTable->isNew())) + { + if(!m_bAddColumn && rType == getCppuType( (Reference<XAppend>*)0)) + return Any(); + if(!m_bDropColumn && rType == getCppuType( (Reference<XDrop>*)0)) + return Any(); + } + + aRet = OColumns_BASE::queryInterface( rType); + if ( !aRet.hasValue() ) + aRet = TXChild::queryInterface( rType); + return aRet; +} +// ------------------------------------------------------------------------- +Sequence< Type > SAL_CALL OColumns::getTypes( ) throw(RuntimeException) +{ + sal_Bool bAppendFound = sal_False,bDropFound = sal_False; + + sal_Int32 nSize = 0; + Type aAppendType = getCppuType( (Reference<XAppend>*)0); + Type aDropType = getCppuType( (Reference<XDrop>*)0); + if(m_xDrvColumns.is()) + { + Reference<XTypeProvider> xTypes(m_xDrvColumns,UNO_QUERY); + Sequence< Type > aTypes(xTypes->getTypes()); + + Sequence< Type > aSecTypes(OColumns_BASE::getTypes()); + + + const Type* pBegin = aTypes.getConstArray(); + const Type* pEnd = pBegin + aTypes.getLength(); + for (;pBegin != pEnd ; ++pBegin) + { + if(aAppendType == *pBegin) + bAppendFound = sal_True; + else if(aDropType == *pBegin) + bDropFound = sal_True; + } + nSize = (bDropFound ? (bAppendFound ? 0 : 1) : (bAppendFound ? 1 : 2)); + } + else + { + nSize = ((m_pTable && m_pTable->isNew()) ? 0 : + ((m_bDropColumn ? + (m_bAddColumn ? 0 : 1) : (m_bAddColumn ? 1 : 2)))); + bDropFound = (m_pTable && m_pTable->isNew()) || m_bDropColumn; + bAppendFound = (m_pTable && m_pTable->isNew()) || m_bAddColumn; + } + Sequence< Type > aTypes(::comphelper::concatSequences(OColumns_BASE::getTypes(),TXChild::getTypes())); + Sequence< Type > aRet(aTypes.getLength() - nSize); + + const Type* pBegin = aTypes.getConstArray(); + const Type* pEnd = pBegin + aTypes.getLength(); + for(sal_Int32 i=0;pBegin != pEnd ;++pBegin) + { + if(*pBegin != aAppendType && *pBegin != aDropType) + aRet.getArray()[i++] = *pBegin; + else if(bDropFound && *pBegin == aDropType) + aRet.getArray()[i++] = *pBegin; + else if(bAppendFound && *pBegin == aAppendType) + aRet.getArray()[i++] = *pBegin; + } + return aRet; +} +// ------------------------------------------------------------------------- +// XAppend +sdbcx::ObjectType OColumns::appendObject( const ::rtl::OUString& _rForName, const Reference< XPropertySet >& descriptor ) +{ + sdbcx::ObjectType xReturn; + + Reference< XAppend > xAppend( m_xDrvColumns, UNO_QUERY ); + if ( xAppend.is() ) + { + xAppend->appendByDescriptor(descriptor); + xReturn = createObject( _rForName ); + } + else if ( m_pTable && !m_pTable->isNew() ) + { + if ( m_bAddColumn ) + { + Reference< ::com::sun::star::sdb::tools::XTableAlteration> xAlterService = m_pTable->getAlterService(); + if ( xAlterService.is() ) + { + xAlterService->addColumn(m_pTable,descriptor); + xReturn = createObject( _rForName ); + } + else + xReturn = OColumns_BASE::appendObject( _rForName, descriptor ); + } + else + ::dbtools::throwGenericSQLException( DBA_RES( RID_STR_NO_COLUMN_ADD ), static_cast<XChild*>(static_cast<TXChild*>(this)) ); + } + else + xReturn = cloneDescriptor( descriptor ); + + if ( m_pColFactoryImpl ) + m_pColFactoryImpl->columnAppended( descriptor ); + + ::dbaccess::notifyDataSourceModified(m_xParent,sal_True); + + return xReturn; +} +// ------------------------------------------------------------------------- +// XDrop +void OColumns::dropObject(sal_Int32 _nPos,const ::rtl::OUString _sElementName) +{ + Reference< XDrop > xDrop( m_xDrvColumns, UNO_QUERY ); + if ( xDrop.is() ) + { + xDrop->dropByName( _sElementName ); + } + else if ( m_pTable && !m_pTable->isNew() ) + { + if ( m_bDropColumn ) + { + Reference< ::com::sun::star::sdb::tools::XTableAlteration> xAlterService = m_pTable->getAlterService(); + if ( xAlterService.is() ) + xAlterService->dropColumn(m_pTable,_sElementName); + else + OColumns_BASE::dropObject(_nPos,_sElementName); + } + else + ::dbtools::throwGenericSQLException( DBA_RES( RID_STR_NO_COLUMN_DROP ), static_cast<XChild*>(static_cast<TXChild*>(this)) ); + } + + if ( m_pColFactoryImpl ) + m_pColFactoryImpl->columnDropped(_sElementName); + + ::dbaccess::notifyDataSourceModified(m_xParent,sal_True); +} +// ----------------------------------------------------------------------------- + +Reference< XInterface > SAL_CALL OColumns::getParent( ) throw (RuntimeException) +{ + ::osl::MutexGuard aGuard(m_rMutex); + return m_xParent; +} +// ----------------------------------------------------------------------------- +void SAL_CALL OColumns::setParent( const Reference< XInterface >& _xParent ) throw (NoSupportException, RuntimeException) +{ + ::osl::MutexGuard aGuard(m_rMutex); + m_xParent = _xParent; +} +// ----------------------------------------------------------------------------- diff --git a/dbaccess/source/core/api/columnsettings.cxx b/dbaccess/source/core/api/columnsettings.cxx new file mode 100644 index 000000000000..a88879ca5eb8 --- /dev/null +++ b/dbaccess/source/core/api/columnsettings.cxx @@ -0,0 +1,182 @@ +/************************************************************************* + * 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_dbaccess.hxx" + +#include "columnsettings.hxx" +#include "dbastrings.hrc" + +/** === begin UNO includes === **/ +#include <com/sun/star/beans/PropertyAttribute.hpp> +/** === end UNO includes === **/ + +#include <cppuhelper/typeprovider.hxx> +#include <comphelper/property.hxx> +#include <tools/debug.hxx> +#include <tools/diagnose_ex.h> + +//........................................................................ +namespace dbaccess +{ +//........................................................................ + + /** === begin UNO using === **/ + using ::com::sun::star::uno::Reference; + using ::com::sun::star::uno::XInterface; + 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::uno::Sequence; + using ::com::sun::star::uno::Type; + using ::com::sun::star::lang::IllegalArgumentException; + using ::com::sun::star::beans::XPropertySet; + using ::com::sun::star::beans::XPropertySetInfo; + /** === end UNO using === **/ + namespace PropertyAttribute = ::com::sun::star::beans::PropertyAttribute; + + //============================================================================== + //= OColumnSettings + //============================================================================== + DBG_NAME( OColumnSettings ) + //------------------------------------------------------------------------------ + OColumnSettings::OColumnSettings() + :m_bHidden(sal_False) + { + DBG_CTOR( OColumnSettings, NULL ); + } + + //------------------------------------------------------------------------------ + OColumnSettings::~OColumnSettings() + { + DBG_DTOR( OColumnSettings, NULL ); + } + + //------------------------------------------------------------------------------ + void OColumnSettings::registerProperties( IPropertyContainer& _rPropertyContainer ) + { + const sal_Int32 nBoundAttr = PropertyAttribute::BOUND; + const sal_Int32 nMayBeVoidAttr = PropertyAttribute::MAYBEVOID | nBoundAttr; + + const Type& rSalInt32Type = ::getCppuType( static_cast< sal_Int32* >( NULL ) ); + const Type& rStringType = ::getCppuType( static_cast< ::rtl::OUString* >( NULL ) ); + + _rPropertyContainer.registerMayBeVoidProperty( PROPERTY_ALIGN, PROPERTY_ID_ALIGN, nMayBeVoidAttr, &m_aAlignment, rSalInt32Type ); + _rPropertyContainer.registerMayBeVoidProperty( PROPERTY_NUMBERFORMAT, PROPERTY_ID_NUMBERFORMAT, nMayBeVoidAttr, &m_aFormatKey, rSalInt32Type ); + _rPropertyContainer.registerMayBeVoidProperty( PROPERTY_RELATIVEPOSITION, PROPERTY_ID_RELATIVEPOSITION, nMayBeVoidAttr, &m_aRelativePosition, rSalInt32Type ); + _rPropertyContainer.registerMayBeVoidProperty( PROPERTY_WIDTH, PROPERTY_ID_WIDTH, nMayBeVoidAttr, &m_aWidth, rSalInt32Type ); + _rPropertyContainer.registerMayBeVoidProperty( PROPERTY_HELPTEXT, PROPERTY_ID_HELPTEXT, nMayBeVoidAttr, &m_aHelpText, rStringType ); + _rPropertyContainer.registerMayBeVoidProperty( PROPERTY_CONTROLDEFAULT, PROPERTY_ID_CONTROLDEFAULT, nMayBeVoidAttr, &m_aControlDefault, rStringType ); + _rPropertyContainer.registerProperty( PROPERTY_CONTROLMODEL, PROPERTY_ID_CONTROLMODEL, nBoundAttr, &m_xControlModel, ::getCppuType( &m_xControlModel ) ); + _rPropertyContainer.registerProperty( PROPERTY_HIDDEN, PROPERTY_ID_HIDDEN, nBoundAttr, &m_bHidden, ::getCppuType( &m_bHidden ) ); + } + + //------------------------------------------------------------------------------ + bool OColumnSettings::isColumnSettingProperty( const sal_Int32 _nPropertyHandle ) + { + return ( _nPropertyHandle == PROPERTY_ID_ALIGN ) + || ( _nPropertyHandle == PROPERTY_ID_NUMBERFORMAT ) + || ( _nPropertyHandle == PROPERTY_ID_RELATIVEPOSITION ) + || ( _nPropertyHandle == PROPERTY_ID_WIDTH ) + || ( _nPropertyHandle == PROPERTY_ID_HELPTEXT ) + || ( _nPropertyHandle == PROPERTY_ID_CONTROLDEFAULT ) + || ( _nPropertyHandle == PROPERTY_ID_CONTROLMODEL ) + || ( _nPropertyHandle == PROPERTY_ID_HIDDEN ); + } + + //------------------------------------------------------------------------------ + bool OColumnSettings::isDefaulted( const sal_Int32 _nPropertyHandle, const Any& _rPropertyValue ) + { + switch ( _nPropertyHandle ) + { + case PROPERTY_ID_ALIGN: + case PROPERTY_ID_NUMBERFORMAT: + case PROPERTY_ID_RELATIVEPOSITION: + case PROPERTY_ID_WIDTH: + case PROPERTY_ID_HELPTEXT: + case PROPERTY_ID_CONTROLDEFAULT: + return !_rPropertyValue.hasValue(); + + case PROPERTY_ID_CONTROLMODEL: + return !Reference< XPropertySet >( _rPropertyValue, UNO_QUERY ).is(); + + case PROPERTY_ID_HIDDEN: + { + sal_Bool bHidden = sal_False; + OSL_VERIFY( _rPropertyValue >>= bHidden ); + return !bHidden; + } + } + OSL_ENSURE( false, "OColumnSettings::isDefaulted: illegal property handle!" ); + return sal_False; + } + + //------------------------------------------------------------------------------ + bool OColumnSettings::hasDefaultSettings( const Reference< XPropertySet >& _rxColumn ) + { + ENSURE_OR_THROW( _rxColumn.is(), "illegal column" ); + try + { + Reference< XPropertySetInfo > xPSI( _rxColumn->getPropertySetInfo(), UNO_SET_THROW ); + + struct PropertyDescriptor + { + ::rtl::OUString sName; + sal_Int32 nHandle; + }; + PropertyDescriptor aProps[] = + { + { PROPERTY_ALIGN, PROPERTY_ID_ALIGN }, + { PROPERTY_NUMBERFORMAT, PROPERTY_ID_NUMBERFORMAT }, + { PROPERTY_RELATIVEPOSITION, PROPERTY_ID_RELATIVEPOSITION }, + { PROPERTY_WIDTH, PROPERTY_ID_WIDTH }, + { PROPERTY_HELPTEXT, PROPERTY_ID_HELPTEXT }, + { PROPERTY_CONTROLDEFAULT, PROPERTY_ID_CONTROLDEFAULT }, + { PROPERTY_CONTROLMODEL, PROPERTY_ID_CONTROLMODEL }, + { PROPERTY_HIDDEN, PROPERTY_ID_HIDDEN } + }; + + for ( size_t i=0; i < sizeof( aProps ) / sizeof( aProps[0] ); ++i ) + { + if ( xPSI->hasPropertyByName( aProps[i].sName ) ) + if ( !isDefaulted( aProps[i].nHandle, _rxColumn->getPropertyValue( aProps[i].sName ) ) ) + return false; + } + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + return true; + } + +//........................................................................ +} // namespace dbaccess +//........................................................................ diff --git a/dbaccess/source/core/api/datacolumn.cxx b/dbaccess/source/core/api/datacolumn.cxx new file mode 100644 index 000000000000..cb1be701cb99 --- /dev/null +++ b/dbaccess/source/core/api/datacolumn.cxx @@ -0,0 +1,485 @@ +/************************************************************************* + * + * 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_dbaccess.hxx" +#ifndef _DBACORE_DATACOLUMN_HXX_ +#include "datacolumn.hxx" +#endif +#ifndef _COM_SUN_STAR_LANG_DISPOSEDEXCEPTION_HPP_ +#include <com/sun/star/lang/DisposedException.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_XRESULTSETMETADATASUPPLIER_HPP_ +#include <com/sun/star/sdbc/XResultSetMetaDataSupplier.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_DATATYPE_HPP_ +#include <com/sun/star/sdbc/DataType.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_COLUMNVALUE_HPP_ +#include <com/sun/star/sdbc/ColumnValue.hpp> +#endif +#ifndef _CPPUHELPER_TYPEPROVIDER_HXX_ +#include <cppuhelper/typeprovider.hxx> +#endif +#ifndef _TOOLS_DEBUG_HXX +#include <tools/debug.hxx> +#endif +#ifndef DBACCESS_SHARED_DBASTRINGS_HRC +#include "dbastrings.hrc" +#endif +#ifndef _DBASHARED_APITOOLS_HXX_ +#include "apitools.hxx" +#endif + +using namespace dbaccess; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::sdb; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::container; +using namespace ::osl; +using namespace ::comphelper; +using namespace ::cppu; + +DBG_NAME(ODataColumn) +//-------------------------------------------------------------------------- +ODataColumn::ODataColumn( + const Reference < XResultSetMetaData >& _xMetaData, + const Reference < XRow >& _xRow, + const Reference < XRowUpdate >& _xRowUpdate, + sal_Int32 _nPos, + const Reference< XDatabaseMetaData >& _rxDBMeta) + :OResultColumn(_xMetaData, _nPos, _rxDBMeta) + ,m_xRow(_xRow) + ,m_xRowUpdate(_xRowUpdate) +{ + DBG_CTOR(ODataColumn,NULL); +} +// ----------------------------------------------------------------------------- +ODataColumn::~ODataColumn() +{ + DBG_DTOR(ODataColumn,NULL); +} + +// com::sun::star::lang::XTypeProvider +//-------------------------------------------------------------------------- +Sequence< Type > ODataColumn::getTypes() throw (RuntimeException) +{ + OTypeCollection aTypes(::getCppuType( (const Reference< XColumn > *)0 ), + ::getCppuType( (const Reference< XColumnUpdate > *)0 ), + OColumn::getTypes()); + return aTypes.getTypes(); +} + +//-------------------------------------------------------------------------- +Sequence< sal_Int8 > ODataColumn::getImplementationId() throw (RuntimeException) +{ + static OImplementationId * pId = 0; + if (! pId) + { + MutexGuard aGuard( Mutex::getGlobalMutex() ); + if (! pId) + { + static OImplementationId aId; + pId = &aId; + } + } + return pId->getImplementationId(); +} + +//------------------------------------------------------------------------------ +Any SAL_CALL ODataColumn::queryInterface( const Type & _rType ) throw (RuntimeException) +{ + Any aReturn = OResultColumn::queryInterface(_rType); + if (!aReturn.hasValue()) + aReturn = ::cppu::queryInterface(_rType, + static_cast< XColumn* >(this), + static_cast< XColumnUpdate* >(this) + ); + return aReturn; +} + +// XServiceInfo +//------------------------------------------------------------------------------ +rtl::OUString ODataColumn::getImplementationName( ) throw(RuntimeException) +{ + return rtl::OUString::createFromAscii("com.sun.star.sdb.ODataColumn"); +} + +//------------------------------------------------------------------------------ +Sequence< ::rtl::OUString > ODataColumn::getSupportedServiceNames( ) throw (RuntimeException) +{ + Sequence< ::rtl::OUString > aSNS( 3 ); + aSNS[0] = SERVICE_SDBCX_COLUMN; + aSNS[1] = SERVICE_SDB_RESULTCOLUMN; + aSNS[2] = SERVICE_SDB_DATACOLUMN; + return aSNS; +} + +// OComponentHelper +//------------------------------------------------------------------------------ +void ODataColumn::disposing() +{ + OResultColumn::disposing(); + + m_xRow = NULL; + m_xRowUpdate = NULL; +} + +// ::com::sun::star::sdb::XColumn +//------------------------------------------------------------------------------ +sal_Bool ODataColumn::wasNull(void) throw( SQLException, RuntimeException ) +{ + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(!m_xRow.is()); + + return m_xRow->wasNull(); +} + +//------------------------------------------------------------------------------ +rtl::OUString ODataColumn::getString(void) throw( SQLException, RuntimeException ) +{ + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(!m_xRow.is()); + + return m_xRow->getString(m_nPos); +} + +//------------------------------------------------------------------------------ +sal_Bool ODataColumn::getBoolean(void) throw( SQLException, RuntimeException ) +{ + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(!m_xRow.is()); + + return m_xRow->getBoolean(m_nPos); +} + +//------------------------------------------------------------------------------ +sal_Int8 ODataColumn::getByte(void) throw( SQLException, RuntimeException ) +{ + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(!m_xRow.is()); + + return m_xRow->getByte(m_nPos); +} + +//------------------------------------------------------------------------------ +sal_Int16 ODataColumn::getShort(void) throw( SQLException, RuntimeException ) +{ + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(!m_xRow.is()); + + return m_xRow->getShort(m_nPos); +} + +//------------------------------------------------------------------------------ +sal_Int32 ODataColumn::getInt(void) throw( SQLException, RuntimeException ) +{ + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(!m_xRow.is()); + + return m_xRow->getInt(m_nPos); +} + +//------------------------------------------------------------------------------ +sal_Int64 ODataColumn::getLong(void) throw( SQLException, RuntimeException ) +{ + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(!m_xRow.is()); + + return m_xRow->getLong(m_nPos); +} + +//------------------------------------------------------------------------------ +float ODataColumn::getFloat(void) throw( SQLException, RuntimeException ) +{ + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(!m_xRow.is()); + + return m_xRow->getFloat(m_nPos); +} +//------------------------------------------------------------------------------ +double ODataColumn::getDouble(void) throw( SQLException, RuntimeException ) +{ + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(!m_xRow.is()); + + return m_xRow->getDouble(m_nPos); +} + +//------------------------------------------------------------------------------ +Sequence< sal_Int8 > ODataColumn::getBytes(void) throw( SQLException, RuntimeException ) +{ + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(!m_xRow.is()); + + return m_xRow->getBytes(m_nPos); +} +//------------------------------------------------------------------------------ +com::sun::star::util::Date ODataColumn::getDate(void) throw( SQLException, RuntimeException ) +{ + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(!m_xRow.is()); + + return m_xRow->getDate(m_nPos); +} + +//------------------------------------------------------------------------------ +com::sun::star::util::Time ODataColumn::getTime(void) throw( SQLException, RuntimeException ) +{ + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(!m_xRow.is()); + + return m_xRow->getTime(m_nPos); +} +//------------------------------------------------------------------------------ +com::sun::star::util::DateTime ODataColumn::getTimestamp(void) throw( SQLException, RuntimeException ) +{ + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(!m_xRow.is()); + + return m_xRow->getTimestamp(m_nPos); +} + +//------------------------------------------------------------------------------ +Reference< ::com::sun::star::io::XInputStream > ODataColumn::getBinaryStream(void) throw( SQLException, RuntimeException ) +{ + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(!m_xRow.is()); + + return m_xRow->getBinaryStream(m_nPos); +} + +//------------------------------------------------------------------------------ +Reference< ::com::sun::star::io::XInputStream > ODataColumn::getCharacterStream(void) throw( SQLException, RuntimeException ) +{ + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(!m_xRow.is()); + + return m_xRow->getCharacterStream(m_nPos); +} + +//------------------------------------------------------------------------------ +Any ODataColumn::getObject(const Reference< ::com::sun::star::container::XNameAccess > & typeMap) throw( SQLException, RuntimeException ) +{ + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(!m_xRow.is()); + + return m_xRow->getObject(m_nPos, typeMap); +} + +//------------------------------------------------------------------------------ +Reference< XRef > ODataColumn::getRef(void) throw( SQLException, RuntimeException ) +{ + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(!m_xRow.is()); + + return m_xRow->getRef(m_nPos); +} + +//------------------------------------------------------------------------------ +Reference< XBlob > ODataColumn::getBlob(void) throw( SQLException, RuntimeException ) +{ + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(!m_xRow.is()); + + return m_xRow->getBlob(m_nPos); +} + +//------------------------------------------------------------------------------ +Reference< XClob > ODataColumn::getClob(void) throw( SQLException, RuntimeException ) +{ + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(!m_xRow.is()); + + return m_xRow->getClob(m_nPos); +} + +//------------------------------------------------------------------------------ +Reference< XArray > ODataColumn::getArray(void) throw( SQLException, RuntimeException ) +{ + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(!m_xRow.is()); + + return m_xRow->getArray(m_nPos); +} + +// ::com::sun::star::sdb::XColumnUpdate +//------------------------------------------------------------------------------ +void ODataColumn::updateNull(void) throw( SQLException, RuntimeException ) +{ + MutexGuard aGuard( m_aMutex ); + ::connectivity::checkDisposed(!m_xRowUpdate.is()); + + m_xRowUpdate->updateNull(m_nPos); +} + +//------------------------------------------------------------------------------ +void ODataColumn::updateBoolean(sal_Bool x) throw( SQLException, RuntimeException ) +{ + MutexGuard aGuard( m_aMutex ); + ::connectivity::checkDisposed(!m_xRowUpdate.is()); + + m_xRowUpdate->updateBoolean(m_nPos, x); +} + +//------------------------------------------------------------------------------ +void ODataColumn::updateByte(sal_Int8 x) throw( SQLException, RuntimeException ) +{ + MutexGuard aGuard( m_aMutex ); + ::connectivity::checkDisposed(!m_xRowUpdate.is()); + + m_xRowUpdate->updateByte(m_nPos, x); +} + +//------------------------------------------------------------------------------ +void ODataColumn::updateShort(sal_Int16 x) throw( SQLException, RuntimeException ) +{ + MutexGuard aGuard( m_aMutex ); + ::connectivity::checkDisposed(!m_xRowUpdate.is()); + + m_xRowUpdate->updateShort(m_nPos, x); +} + +//------------------------------------------------------------------------------ +void ODataColumn::updateInt(sal_Int32 x) throw( SQLException, RuntimeException ) +{ + MutexGuard aGuard( m_aMutex ); + ::connectivity::checkDisposed(!m_xRowUpdate.is()); + + m_xRowUpdate->updateInt(m_nPos, x); +} + +//------------------------------------------------------------------------------ +void ODataColumn::updateLong(sal_Int64 x) throw( SQLException, RuntimeException ) +{ + MutexGuard aGuard( m_aMutex ); + ::connectivity::checkDisposed(!m_xRowUpdate.is()); + + m_xRowUpdate->updateLong(m_nPos, x); +} + +//------------------------------------------------------------------------------ +void ODataColumn::updateFloat(float x) throw( SQLException, RuntimeException ) +{ + MutexGuard aGuard( m_aMutex ); + ::connectivity::checkDisposed(!m_xRowUpdate.is()); + + m_xRowUpdate->updateFloat(m_nPos, x); +} + +//------------------------------------------------------------------------------ +void ODataColumn::updateDouble(double x) throw( SQLException, RuntimeException ) +{ + MutexGuard aGuard( m_aMutex ); + ::connectivity::checkDisposed(!m_xRowUpdate.is()); + + m_xRowUpdate->updateDouble(m_nPos, x); +} + +//------------------------------------------------------------------------------ +void ODataColumn::updateString(const rtl::OUString& x) throw( SQLException, RuntimeException ) +{ + MutexGuard aGuard( m_aMutex ); + ::connectivity::checkDisposed(!m_xRowUpdate.is()); + + m_xRowUpdate->updateString(m_nPos, x); +} + +//------------------------------------------------------------------------------ +void ODataColumn::updateBytes(const Sequence< sal_Int8 >& x) throw( SQLException, RuntimeException ) +{ + MutexGuard aGuard( m_aMutex ); + ::connectivity::checkDisposed(!m_xRowUpdate.is()); + + m_xRowUpdate->updateBytes(m_nPos, x); +} + +//------------------------------------------------------------------------------ +void ODataColumn::updateDate(const com::sun::star::util::Date& x) throw( SQLException, RuntimeException ) +{ + MutexGuard aGuard( m_aMutex ); + ::connectivity::checkDisposed(!m_xRowUpdate.is()); + + m_xRowUpdate->updateDate(m_nPos, x); +} + +//------------------------------------------------------------------------------ +void ODataColumn::updateTime(const ::com::sun::star::util::Time& x) throw( SQLException, RuntimeException ) +{ + MutexGuard aGuard( m_aMutex ); + ::connectivity::checkDisposed(!m_xRowUpdate.is()); + + m_xRowUpdate->updateTime(m_nPos, x); +} + +//------------------------------------------------------------------------------ +void ODataColumn::updateTimestamp(const ::com::sun::star::util::DateTime& x) throw( SQLException, RuntimeException ) +{ + MutexGuard aGuard( m_aMutex ); + ::connectivity::checkDisposed(!m_xRowUpdate.is()); + + m_xRowUpdate->updateTimestamp(m_nPos, x); +} + +//------------------------------------------------------------------------------ +void ODataColumn::updateCharacterStream(const Reference< ::com::sun::star::io::XInputStream > & x, sal_Int32 length) throw( SQLException, RuntimeException ) +{ + MutexGuard aGuard( m_aMutex ); + ::connectivity::checkDisposed(!m_xRowUpdate.is()); + + m_xRowUpdate->updateCharacterStream(m_nPos, x, length); +} + +//------------------------------------------------------------------------------ +void ODataColumn::updateBinaryStream(const Reference< ::com::sun::star::io::XInputStream > & x, sal_Int32 length) throw( SQLException, RuntimeException ) +{ + MutexGuard aGuard( m_aMutex ); + ::connectivity::checkDisposed(!m_xRowUpdate.is()); + + m_xRowUpdate->updateBinaryStream(m_nPos, x, length); +} + +//------------------------------------------------------------------------------ +void ODataColumn::updateNumericObject(const Any& x, sal_Int32 scale) throw( SQLException, RuntimeException ) +{ + MutexGuard aGuard( m_aMutex ); + ::connectivity::checkDisposed(!m_xRowUpdate.is()); + + m_xRowUpdate->updateNumericObject(m_nPos, x, scale); +} + +//------------------------------------------------------------------------------ +void ODataColumn::updateObject(const Any& x) throw( SQLException, RuntimeException ) +{ + MutexGuard aGuard( m_aMutex ); + ::connectivity::checkDisposed(!m_xRowUpdate.is()); + + m_xRowUpdate->updateObject(m_nPos, x); +} + diff --git a/dbaccess/source/core/api/datacolumn.hxx b/dbaccess/source/core/api/datacolumn.hxx new file mode 100644 index 000000000000..3c18fd4d830d --- /dev/null +++ b/dbaccess/source/core/api/datacolumn.hxx @@ -0,0 +1,129 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +#ifndef _DBACORE_DATACOLUMN_HXX_ +#define _DBACORE_DATACOLUMN_HXX_ + +#ifndef _COM_SUN_STAR_SDBC_XROWUPDATE_HPP_ +#include <com/sun/star/sdbc/XRowUpdate.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_XROW_HPP_ +#include <com/sun/star/sdbc/XRow.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_XRESULTSETMETADATA_HDL_ +#include <com/sun/star/sdbc/XResultSetMetaData.hdl> +#endif +#ifndef _COM_SUN_STAR_SDB_XCOLUMN_HPP_ +#include <com/sun/star/sdb/XColumn.hpp> +#endif +#ifndef _COM_SUN_STAR_SDB_XCOLUMNUPDATE_HPP_ +#include <com/sun/star/sdb/XColumnUpdate.hpp> +#endif +#ifndef _DBA_COREAPI_RESULTCOLUMN_HXX_ +#include <resultcolumn.hxx> +#endif +namespace dbaccess +{ + //************************************************************ + // ODataColumn + //************************************************************ + class ODataColumn : public OResultColumn, + public ::com::sun::star::sdb::XColumn, + public ::com::sun::star::sdb::XColumnUpdate + { + protected: + ::com::sun::star::uno::Reference < ::com::sun::star::sdbc::XRow > m_xRow; + ::com::sun::star::uno::Reference < ::com::sun::star::sdbc::XRowUpdate > m_xRowUpdate; + + virtual ~ODataColumn(); + public: + ODataColumn (const ::com::sun::star::uno::Reference < ::com::sun::star::sdbc::XResultSetMetaData >& _xMetaData, + const ::com::sun::star::uno::Reference < ::com::sun::star::sdbc::XRow >& _xRow, + const ::com::sun::star::uno::Reference < ::com::sun::star::sdbc::XRowUpdate >& _xRowUpdate, + sal_Int32 _nPos, + const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XDatabaseMetaData >& _rxDBMeta); + + // com::sun::star::lang::XTypeProvider + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type > SAL_CALL getTypes() throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId() throw (::com::sun::star::uno::RuntimeException); + + // com::sun::star::uno::XInterface + virtual ::com::sun::star::uno::Any SAL_CALL queryInterface( const ::com::sun::star::uno::Type & rType ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL acquire() throw() { OResultColumn::acquire(); } + virtual void SAL_CALL release() throw() { OResultColumn::release(); } + + // ::com::sun::star::lang::XServiceInfo + virtual ::rtl::OUString SAL_CALL getImplementationName( ) throw(::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames( ) throw(::com::sun::star::uno::RuntimeException); + + // cppu::OComponentHelper + virtual void SAL_CALL disposing(void); + + // ::com::sun::star::sdb::XColumn + virtual sal_Bool SAL_CALL wasNull( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getString( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL getBoolean( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Int8 SAL_CALL getByte( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Int16 SAL_CALL getShort( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Int32 SAL_CALL getInt( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Int64 SAL_CALL getLong( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual float SAL_CALL getFloat( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual double SAL_CALL getDouble( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL getBytes( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::util::Date SAL_CALL getDate( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::util::Time SAL_CALL getTime( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::util::DateTime SAL_CALL getTimestamp( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > SAL_CALL getBinaryStream( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > SAL_CALL getCharacterStream( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Any SAL_CALL getObject( const ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess >& typeMap ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRef > SAL_CALL getRef( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XBlob > SAL_CALL getBlob( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XClob > SAL_CALL getClob( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XArray > SAL_CALL getArray( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + + // ::com::sun::star::sdb::XColumnUpdate + virtual void SAL_CALL updateNull( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL updateBoolean( sal_Bool x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL updateByte( sal_Int8 x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL updateShort( sal_Int16 x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL updateInt( sal_Int32 x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL updateLong( sal_Int64 x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL updateFloat( float x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL updateDouble( double x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL updateString( const ::rtl::OUString& x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL updateBytes( const ::com::sun::star::uno::Sequence< sal_Int8 >& x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL updateDate( const ::com::sun::star::util::Date& x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL updateTime( const ::com::sun::star::util::Time& x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL updateTimestamp( const ::com::sun::star::util::DateTime& x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL updateBinaryStream( const ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream >& x, sal_Int32 length ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL updateCharacterStream( const ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream >& x, sal_Int32 length ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL updateObject( const ::com::sun::star::uno::Any& x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL updateNumericObject( const ::com::sun::star::uno::Any& x, sal_Int32 scale ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + }; +} +#endif // _DBACORE_RESULTCOLUMN_HXX_ + diff --git a/dbaccess/source/core/api/datasettings.cxx b/dbaccess/source/core/api/datasettings.cxx new file mode 100644 index 000000000000..2f5a01fd7004 --- /dev/null +++ b/dbaccess/source/core/api/datasettings.cxx @@ -0,0 +1,254 @@ +/************************************************************************* + * + * 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_dbaccess.hxx" + +#ifndef _DBA_CORE_DATASETTINGS_HXX_ +#include "datasettings.hxx" +#endif +#ifndef _DBASHARED_APITOOLS_HXX_ +#include "apitools.hxx" +#endif +#ifndef DBACCESS_SHARED_DBASTRINGS_HRC +#include "dbastrings.hrc" +#endif +#ifndef _OSL_DIAGNOSE_H_ +#include <osl/diagnose.h> +#endif +#ifndef _COMPHELPER_PROPERTY_HXX_ +#include <comphelper/property.hxx> +#endif +#ifndef _COMPHELPER_TYPES_HXX_ +#include <comphelper/types.hxx> +#endif +#ifndef _COM_SUN_STAR_BEANS_PROPERTYATTRIBUTE_HPP_ +#include <com/sun/star/beans/PropertyAttribute.hpp> +#endif +#ifndef _SV_SVAPP_HXX +#include <vcl/svapp.hxx> +#endif +#ifndef _COM_SUN_STAR_AWT_FONTWEIGHT_HPP_ +#include <com/sun/star/awt/FontWeight.hpp> +#endif +#ifndef _COM_SUN_STAR_AWT_FONTEMPHASISMARK_HPP_ +#include <com/sun/star/awt/FontEmphasisMark.hpp> +#endif +#ifndef _COM_SUN_STAR_AWT_FONTRELIEF_HPP_ +#include <com/sun/star/awt/FontRelief.hpp> +#endif + +#ifndef _COM_SUN_STAR_AWT_FONTWIDTH_HPP_ +#include <com/sun/star/awt/FontWidth.hpp> +#endif + + +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::awt; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::beans; +using namespace ::comphelper; +using namespace ::cppu; + +//........................................................................ +namespace dbaccess +{ +//========================================================================== +//= ODataSettings +//========================================================================== +//-------------------------------------------------------------------------- +void ODataSettings::registerPropertiesFor(ODataSettings_Base* _pItem) +{ + if ( m_bQuery ) + { + registerProperty(PROPERTY_HAVING_CLAUSE, PROPERTY_ID_HAVING_CLAUSE, PropertyAttribute::BOUND, + &_pItem->m_sHavingClause, ::getCppuType(&_pItem->m_sHavingClause)); + + registerProperty(PROPERTY_GROUP_BY, PROPERTY_ID_GROUP_BY, PropertyAttribute::BOUND, + &_pItem->m_sGroupBy, ::getCppuType(&_pItem->m_sGroupBy)); + } + + registerProperty(PROPERTY_FILTER, PROPERTY_ID_FILTER, PropertyAttribute::BOUND, + &_pItem->m_sFilter, ::getCppuType(&_pItem->m_sFilter)); + + registerProperty(PROPERTY_ORDER, PROPERTY_ID_ORDER, PropertyAttribute::BOUND, + &_pItem->m_sOrder, ::getCppuType(&_pItem->m_sOrder)); + + registerProperty(PROPERTY_APPLYFILTER, PROPERTY_ID_APPLYFILTER, PropertyAttribute::BOUND, + &_pItem->m_bApplyFilter, ::getBooleanCppuType()); + + registerProperty(PROPERTY_FONT, PROPERTY_ID_FONT, PropertyAttribute::BOUND, + &_pItem->m_aFont, ::getCppuType(&_pItem->m_aFont)); + + registerMayBeVoidProperty(PROPERTY_ROW_HEIGHT, PROPERTY_ID_ROW_HEIGHT, PropertyAttribute::BOUND | PropertyAttribute::MAYBEVOID, + &_pItem->m_aRowHeight, ::getCppuType(static_cast<sal_Int32*>(NULL))); + + registerMayBeVoidProperty(PROPERTY_TEXTCOLOR, PROPERTY_ID_TEXTCOLOR, PropertyAttribute::BOUND | PropertyAttribute::MAYBEVOID, + &_pItem->m_aTextColor, ::getCppuType(static_cast<sal_Int32*>(NULL))); + + registerMayBeVoidProperty(PROPERTY_TEXTLINECOLOR, PROPERTY_ID_TEXTLINECOLOR, PropertyAttribute::BOUND | PropertyAttribute::MAYBEVOID, + &_pItem->m_aTextLineColor, ::getCppuType(static_cast<sal_Int32*>(NULL))); + + registerProperty(PROPERTY_TEXTEMPHASIS, PROPERTY_ID_TEXTEMPHASIS, PropertyAttribute::BOUND, + &_pItem->m_nFontEmphasis, ::getCppuType(&_pItem->m_nFontEmphasis)); + + registerProperty(PROPERTY_TEXTRELIEF, PROPERTY_ID_TEXTRELIEF, PropertyAttribute::BOUND,&_pItem->m_nFontRelief, ::getCppuType(&_pItem->m_nFontRelief)); + + registerProperty(PROPERTY_FONTNAME, PROPERTY_ID_FONTNAME, PropertyAttribute::BOUND,&_pItem->m_aFont.Name, ::getCppuType(&_pItem->m_aFont.Name)); + registerProperty(PROPERTY_FONTHEIGHT, PROPERTY_ID_FONTHEIGHT, PropertyAttribute::BOUND,&_pItem->m_aFont.Height, ::getCppuType(&_pItem->m_aFont.Height)); + registerProperty(PROPERTY_FONTWIDTH, PROPERTY_ID_FONTWIDTH, PropertyAttribute::BOUND,&_pItem->m_aFont.Width, ::getCppuType(&_pItem->m_aFont.Width)); + registerProperty(PROPERTY_FONTSTYLENAME, PROPERTY_ID_FONTSTYLENAME, PropertyAttribute::BOUND,&_pItem->m_aFont.StyleName, ::getCppuType(&_pItem->m_aFont.StyleName)); + registerProperty(PROPERTY_FONTFAMILY, PROPERTY_ID_FONTFAMILY, PropertyAttribute::BOUND,&_pItem->m_aFont.Family, ::getCppuType(&_pItem->m_aFont.Family)); + registerProperty(PROPERTY_FONTCHARSET, PROPERTY_ID_FONTCHARSET, PropertyAttribute::BOUND,&_pItem->m_aFont.CharSet, ::getCppuType(&_pItem->m_aFont.CharSet)); + registerProperty(PROPERTY_FONTPITCH, PROPERTY_ID_FONTPITCH, PropertyAttribute::BOUND,&_pItem->m_aFont.Pitch, ::getCppuType(&_pItem->m_aFont.Pitch)); + registerProperty(PROPERTY_FONTCHARWIDTH, PROPERTY_ID_FONTCHARWIDTH, PropertyAttribute::BOUND,&_pItem->m_aFont.CharacterWidth, ::getCppuType(&_pItem->m_aFont.CharacterWidth)); + registerProperty(PROPERTY_FONTWEIGHT, PROPERTY_ID_FONTWEIGHT, PropertyAttribute::BOUND,&_pItem->m_aFont.Weight, ::getCppuType(&_pItem->m_aFont.Weight)); + registerProperty(PROPERTY_FONTSLANT, PROPERTY_ID_FONTSLANT, PropertyAttribute::BOUND,&_pItem->m_aFont.Slant, ::getCppuType(&_pItem->m_aFont.Slant)); + registerProperty(PROPERTY_FONTUNDERLINE, PROPERTY_ID_FONTUNDERLINE, PropertyAttribute::BOUND,&_pItem->m_aFont.Underline, ::getCppuType(&_pItem->m_aFont.Underline)); + registerProperty(PROPERTY_FONTSTRIKEOUT, PROPERTY_ID_FONTSTRIKEOUT, PropertyAttribute::BOUND,&_pItem->m_aFont.Strikeout, ::getCppuType(&_pItem->m_aFont.Strikeout)); + registerProperty(PROPERTY_FONTORIENTATION, PROPERTY_ID_FONTORIENTATION, PropertyAttribute::BOUND,&_pItem->m_aFont.Orientation, ::getCppuType(&_pItem->m_aFont.Orientation)); + registerProperty(PROPERTY_FONTKERNING, PROPERTY_ID_FONTKERNING, PropertyAttribute::BOUND,&_pItem->m_aFont.Kerning, ::getCppuType(&_pItem->m_aFont.Kerning)); + registerProperty(PROPERTY_FONTWORDLINEMODE, PROPERTY_ID_FONTWORDLINEMODE,PropertyAttribute::BOUND,&_pItem->m_aFont.WordLineMode, ::getCppuType(&_pItem->m_aFont.WordLineMode)); + registerProperty(PROPERTY_FONTTYPE, PROPERTY_ID_FONTTYPE, PropertyAttribute::BOUND,&_pItem->m_aFont.Type, ::getCppuType(&_pItem->m_aFont.Type)); +} + +//-------------------------------------------------------------------------- +ODataSettings::ODataSettings(OBroadcastHelper& _rBHelper,sal_Bool _bQuery) + :OPropertyStateContainer(_rBHelper) + ,ODataSettings_Base() + ,m_bQuery(_bQuery) +{ +} + +//-------------------------------------------------------------------------- +ODataSettings_Base::ODataSettings_Base() + :m_bApplyFilter(sal_False) + ,m_aFont(::comphelper::getDefaultFont()) + ,m_nFontEmphasis(::com::sun::star::awt::FontEmphasisMark::NONE) + ,m_nFontRelief(::com::sun::star::awt::FontRelief::NONE) +{ +} + +//-------------------------------------------------------------------------- +ODataSettings_Base::ODataSettings_Base(const ODataSettings_Base& _rSource) + :m_sFilter( _rSource.m_sFilter ) + ,m_sHavingClause( _rSource.m_sHavingClause ) + ,m_sGroupBy( _rSource.m_sGroupBy ) + ,m_sOrder( _rSource.m_sOrder ) + ,m_bApplyFilter( _rSource.m_bApplyFilter ) + ,m_aFont( _rSource.m_aFont ) + ,m_aRowHeight( _rSource.m_aRowHeight ) + ,m_aTextColor( _rSource.m_aTextColor ) + ,m_aTextLineColor( _rSource.m_aTextLineColor ) + ,m_nFontEmphasis( _rSource.m_nFontEmphasis ) + ,m_nFontRelief( _rSource.m_nFontRelief ) +{ +} + +// ----------------------------------------------------------------------------- +ODataSettings_Base::~ODataSettings_Base() +{ +} + +// ----------------------------------------------------------------------------- +void ODataSettings::getPropertyDefaultByHandle( sal_Int32 _nHandle, Any& _rDefault ) const +{ + static ::com::sun::star::awt::FontDescriptor aFD = ::comphelper::getDefaultFont(); + switch( _nHandle ) + { + case PROPERTY_ID_HAVING_CLAUSE: + case PROPERTY_ID_GROUP_BY: + case PROPERTY_ID_FILTER: + case PROPERTY_ID_ORDER: + _rDefault <<= ::rtl::OUString(); + break; + case PROPERTY_ID_FONT: + _rDefault <<= ::comphelper::getDefaultFont(); + break; + case PROPERTY_ID_APPLYFILTER: + _rDefault <<= sal_False; + break; + case PROPERTY_ID_TEXTRELIEF: + _rDefault <<= ::com::sun::star::awt::FontRelief::NONE; + break; + case PROPERTY_ID_TEXTEMPHASIS: + _rDefault <<= ::com::sun::star::awt::FontEmphasisMark::NONE; + break; + case PROPERTY_ID_FONTNAME: + _rDefault <<= aFD.Name; + break; + case PROPERTY_ID_FONTHEIGHT: + _rDefault <<= aFD.Height; + break; + case PROPERTY_ID_FONTWIDTH: + _rDefault <<= aFD.Width; + break; + case PROPERTY_ID_FONTSTYLENAME: + _rDefault <<= aFD.StyleName; + break; + case PROPERTY_ID_FONTFAMILY: + _rDefault <<= aFD.Family; + break; + case PROPERTY_ID_FONTCHARSET: + _rDefault <<= aFD.CharSet; + break; + case PROPERTY_ID_FONTPITCH: + _rDefault <<= aFD.Pitch; + break; + case PROPERTY_ID_FONTCHARWIDTH: + _rDefault <<= aFD.CharacterWidth; + break; + case PROPERTY_ID_FONTWEIGHT: + _rDefault <<= aFD.Weight; + break; + case PROPERTY_ID_FONTSLANT: + _rDefault <<= aFD.Slant; + break; + case PROPERTY_ID_FONTUNDERLINE: + _rDefault <<= aFD.Underline; + break; + case PROPERTY_ID_FONTSTRIKEOUT: + _rDefault <<= aFD.Strikeout; + break; + case PROPERTY_ID_FONTORIENTATION: + _rDefault <<= aFD.Orientation; + break; + case PROPERTY_ID_FONTKERNING: + _rDefault <<= aFD.Kerning; + break; + case PROPERTY_ID_FONTWORDLINEMODE: + _rDefault <<= aFD.WordLineMode; + break; + case PROPERTY_ID_FONTTYPE: + _rDefault <<= aFD.Type; + break; + } +} +//........................................................................ +} // namespace dbaccess +//........................................................................ + diff --git a/dbaccess/source/core/api/definitioncolumn.cxx b/dbaccess/source/core/api/definitioncolumn.cxx new file mode 100644 index 000000000000..4620abd661f3 --- /dev/null +++ b/dbaccess/source/core/api/definitioncolumn.cxx @@ -0,0 +1,673 @@ +/************************************************************************* + * + * 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_dbaccess.hxx" + +#include "apitools.hxx" +#include "dbastrings.hrc" +#include "definitioncolumn.hxx" +#include "sdbcoretools.hxx" + +/** === begin UNO includes === **/ +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/sdbcx/XTablesSupplier.hpp> +/** === end UNO includes === **/ + +#include <comphelper/property.hxx> +#include <comphelper/types.hxx> +#include <connectivity/dbtools.hxx> +#include <cppuhelper/typeprovider.hxx> +#include <tools/debug.hxx> +#include <tools/diagnose_ex.h> + +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::container; +using namespace ::cppu; +using namespace ::comphelper; +using namespace ::osl; +using namespace dbaccess; + +#define HAS_DESCRIPTION 0x00000001 +#define HAS_DEFAULTVALUE 0x00000002 +#define HAS_ROWVERSION 0x00000004 +#define HAS_AUTOINCREMENT_CREATION 0x00000008 + +//============================================================ +//= OTableColumnDescriptor +//============================================================ +IMPLEMENT_FORWARD_XINTERFACE2(OTableColumnDescriptor,OColumn,TXChild) + +//------------------------------------------------------------------------------ +void OTableColumnDescriptor::impl_registerProperties() +{ + sal_Int32 nDefaultAttr = m_bActAsDescriptor ? 0 : PropertyAttribute::READONLY; + + registerProperty( PROPERTY_TYPENAME, PROPERTY_ID_TYPENAME, nDefaultAttr, &m_aTypeName, ::getCppuType( &m_aTypeName ) ); + registerProperty( PROPERTY_DESCRIPTION, PROPERTY_ID_DESCRIPTION, nDefaultAttr, &m_aDescription, ::getCppuType( &m_aDescription ) ); + registerProperty( PROPERTY_DEFAULTVALUE, PROPERTY_ID_DEFAULTVALUE, nDefaultAttr, &m_aDefaultValue, ::getCppuType( &m_aDefaultValue ) ); + + if ( m_bActAsDescriptor ) + registerProperty( PROPERTY_AUTOINCREMENTCREATION, PROPERTY_ID_AUTOINCREMENTCREATION, nDefaultAttr, &m_aAutoIncrementValue, ::getCppuType( &m_aAutoIncrementValue ) ); + + registerProperty( PROPERTY_TYPE, PROPERTY_ID_TYPE, nDefaultAttr, &m_nType, ::getCppuType( &m_nType ) ); + registerProperty( PROPERTY_PRECISION, PROPERTY_ID_PRECISION, nDefaultAttr, &m_nPrecision, ::getCppuType( &m_nPrecision ) ); + registerProperty( PROPERTY_SCALE, PROPERTY_ID_SCALE, nDefaultAttr, &m_nScale, ::getCppuType( &m_nScale ) ); + registerProperty( PROPERTY_ISNULLABLE, PROPERTY_ID_ISNULLABLE, nDefaultAttr, &m_nIsNullable, ::getCppuType( &m_nIsNullable ) ); + registerProperty( PROPERTY_ISAUTOINCREMENT, PROPERTY_ID_ISAUTOINCREMENT, nDefaultAttr, &m_bAutoIncrement, ::getCppuType( &m_bAutoIncrement ) ); + registerProperty( PROPERTY_ISROWVERSION, PROPERTY_ID_ISROWVERSION, nDefaultAttr, &m_bRowVersion, ::getCppuType( &m_bRowVersion ) ); + registerProperty( PROPERTY_ISCURRENCY, PROPERTY_ID_ISCURRENCY, nDefaultAttr, &m_bCurrency, ::getCppuType( &m_bCurrency ) ); + + OColumnSettings::registerProperties( *this ); +} + +//-------------------------------------------------------------------------- +IMPLEMENT_GET_IMPLEMENTATION_ID( OTableColumnDescriptor ) + +// ::com::sun::star::lang::XServiceInfo +//------------------------------------------------------------------------------ +rtl::OUString OTableColumnDescriptor::getImplementationName( ) throw (RuntimeException) +{ + return rtl::OUString::createFromAscii("com.sun.star.sdb.OTableColumnDescriptor"); +} + +//------------------------------------------------------------------------------ +Sequence< ::rtl::OUString > OTableColumnDescriptor::getSupportedServiceNames( ) throw (RuntimeException) +{ + Sequence< ::rtl::OUString > aSNS( 2 ); + aSNS[0] = m_bActAsDescriptor ? SERVICE_SDBCX_COLUMNDESCRIPTOR : SERVICE_SDBCX_COLUMN; + aSNS[1] = SERVICE_SDB_COLUMNSETTINGS; + return aSNS; +} + +// comphelper::OPropertyArrayUsageHelper +//------------------------------------------------------------------------------ +::cppu::IPropertyArrayHelper* OTableColumnDescriptor::createArrayHelper( ) const +{ + Sequence< Property > aProps; + describeProperties( aProps ); + return new ::cppu::OPropertyArrayHelper( aProps ); +} + +// cppu::OPropertySetHelper +//------------------------------------------------------------------------------ +::cppu::IPropertyArrayHelper& OTableColumnDescriptor::getInfoHelper() +{ + return *static_cast< ::comphelper::OPropertyArrayUsageHelper< OTableColumnDescriptor >* >(this)->getArrayHelper(); +} + +//------------------------------------------------------------------------------ +void OTableColumnDescriptor::setFastPropertyValue_NoBroadcast( sal_Int32 nHandle, const Any& rValue ) throw (Exception) +{ + OColumn::setFastPropertyValue_NoBroadcast( nHandle, rValue ); + ::dbaccess::notifyDataSourceModified( m_xParent, sal_True ); +} + +// ----------------------------------------------------------------------------- +Reference< XInterface > SAL_CALL OTableColumnDescriptor::getParent( ) throw (RuntimeException) +{ + ::osl::MutexGuard aGuard(m_aMutex); + return m_xParent; +} +// ----------------------------------------------------------------------------- +void SAL_CALL OTableColumnDescriptor::setParent( const Reference< XInterface >& _xParent ) throw (NoSupportException, RuntimeException) +{ + ::osl::MutexGuard aGuard(m_aMutex); + m_xParent = _xParent; +} +//============================================================ +//= OTableColumn +//============================================================ +DBG_NAME(OTableColumn); + +// ------------------------------------------------------------------------- +OTableColumn::OTableColumn( const ::rtl::OUString& _rName ) + :OTableColumnDescriptor( false /* do not act as descriptor */ ) +{ + DBG_CTOR(OTableColumn,NULL); + m_sName = _rName; +} + +// ----------------------------------------------------------------------------- +OTableColumn::~OTableColumn() +{ + DBG_DTOR(OTableColumn,NULL); +} + +//-------------------------------------------------------------------------- +IMPLEMENT_GET_IMPLEMENTATION_ID( OTableColumn ) + +//------------------------------------------------------------------------------ +rtl::OUString OTableColumn::getImplementationName( ) throw (RuntimeException) +{ + return rtl::OUString::createFromAscii("com.sun.star.sdb.OTableColumn"); +} + +//------------------------------------------------------------------------------ +::cppu::IPropertyArrayHelper& SAL_CALL OTableColumn::getInfoHelper() +{ + return *OTableColumn_PBase::getArrayHelper(); +} + +//------------------------------------------------------------------------------ +::cppu::IPropertyArrayHelper* OTableColumn::createArrayHelper( ) const +{ + return OTableColumnDescriptor::createArrayHelper(); +} + +// ========================================================================= +//= OQueryColumn +// ========================================================================= +DBG_NAME( OQueryColumn ); + +// ------------------------------------------------------------------------- +OQueryColumn::OQueryColumn( const Reference< XPropertySet >& _rxParserColumn, const Reference< XConnection >& _rxConnection,const ::rtl::OUString i_sLabel ) + :OTableColumnDescriptor( false /* do not act as descriptor */ ) + ,m_sLabel(i_sLabel) +{ + const sal_Int32 nPropAttr = PropertyAttribute::READONLY; + registerProperty( PROPERTY_CATALOGNAME, PROPERTY_ID_CATALOGNAME, nPropAttr, &m_sCatalogName, ::getCppuType( &m_sCatalogName ) ); + registerProperty( PROPERTY_SCHEMANAME, PROPERTY_ID_SCHEMANAME, nPropAttr, &m_sSchemaName, ::getCppuType( &m_sSchemaName ) ); + registerProperty( PROPERTY_TABLENAME, PROPERTY_ID_TABLENAME, nPropAttr, &m_sTableName, ::getCppuType( &m_sTableName ) ); + registerProperty( PROPERTY_REALNAME, PROPERTY_ID_REALNAME, nPropAttr, &m_sRealName, ::getCppuType( &m_sRealName ) ); + registerProperty( PROPERTY_LABEL, PROPERTY_ID_LABEL, nPropAttr, &m_sLabel, ::getCppuType( &m_sLabel ) ); + + DBG_CTOR( OQueryColumn, NULL ); + + OSL_VERIFY( _rxParserColumn->getPropertyValue( PROPERTY_TYPENAME ) >>= m_aTypeName ); + OSL_VERIFY( _rxParserColumn->getPropertyValue( PROPERTY_ISNULLABLE ) >>= m_nIsNullable ); + OSL_VERIFY( _rxParserColumn->getPropertyValue( PROPERTY_PRECISION ) >>= m_nPrecision ); + OSL_VERIFY( _rxParserColumn->getPropertyValue( PROPERTY_SCALE ) >>= m_nScale ); + OSL_VERIFY( _rxParserColumn->getPropertyValue( PROPERTY_TYPE ) >>= m_nType ); + OSL_VERIFY( _rxParserColumn->getPropertyValue( PROPERTY_ISAUTOINCREMENT ) >>= m_bAutoIncrement ); + OSL_VERIFY( _rxParserColumn->getPropertyValue( PROPERTY_ISCURRENCY ) >>= m_bCurrency ); + OSL_VERIFY( _rxParserColumn->getPropertyValue( PROPERTY_NAME ) >>= m_sName ); + + m_bRowVersion = sal_False; + + Reference< XPropertySetInfo > xPSI( _rxParserColumn->getPropertySetInfo(), UNO_SET_THROW ); + if ( xPSI->hasPropertyByName( PROPERTY_DEFAULTVALUE ) ) + OSL_VERIFY( _rxParserColumn->getPropertyValue( PROPERTY_DEFAULTVALUE ) >>= m_aDefaultValue ); + + // copy some optional properties from the parser column + struct PropertyDescriptor + { + ::rtl::OUString sName; + sal_Int32 nHandle; + }; + PropertyDescriptor aProps[] = + { + { PROPERTY_CATALOGNAME, PROPERTY_ID_CATALOGNAME }, + { PROPERTY_SCHEMANAME, PROPERTY_ID_SCHEMANAME }, + { PROPERTY_TABLENAME, PROPERTY_ID_TABLENAME }, + { PROPERTY_REALNAME, PROPERTY_ID_REALNAME } + }; + for ( size_t i=0; i < sizeof( aProps ) / sizeof( aProps[0] ); ++i ) + { + if ( xPSI->hasPropertyByName( aProps[i].sName ) ) + setFastPropertyValue_NoBroadcast( aProps[i].nHandle, _rxParserColumn->getPropertyValue( aProps[i].sName ) ); + } + + // determine the table column we're based on + osl_incrementInterlockedCount( &m_refCount ); + { + m_xOriginalTableColumn = impl_determineOriginalTableColumn( _rxConnection ); + } + osl_decrementInterlockedCount( &m_refCount ); +} + +//-------------------------------------------------------------------------- +OQueryColumn::~OQueryColumn() +{ + DBG_DTOR( OQueryColumn, NULL ); +} + +//-------------------------------------------------------------------------- +Reference< XPropertySet > OQueryColumn::impl_determineOriginalTableColumn( const Reference< XConnection >& _rxConnection ) +{ + OSL_PRECOND( _rxConnection.is(), "OQueryColumn::impl_determineOriginalTableColumn: illegal connection!" ); + if ( !_rxConnection.is() ) + return NULL; + + Reference< XPropertySet > xOriginalTableColumn; + try + { + // determine the composed table name, plus the column name, as indicated by the + // respective properties + ::rtl::OUString sCatalog, sSchema, sTable; + OSL_VERIFY( getPropertyValue( PROPERTY_CATALOGNAME ) >>= sCatalog ); + OSL_VERIFY( getPropertyValue( PROPERTY_SCHEMANAME ) >>= sSchema ); + OSL_VERIFY( getPropertyValue( PROPERTY_TABLENAME ) >>= sTable ); + if ( !sCatalog.getLength() && !sSchema.getLength() && !sTable.getLength() ) + return NULL; + + ::rtl::OUString sComposedTableName = ::dbtools::composeTableName( + _rxConnection->getMetaData(), sCatalog, sSchema, sTable, sal_False, ::dbtools::eComplete ); + + // retrieve the table in question + Reference< XTablesSupplier > xSuppTables( _rxConnection, UNO_QUERY_THROW ); + Reference< XNameAccess > xTables( xSuppTables->getTables(), UNO_QUERY_THROW ); + if ( !xTables->hasByName( sComposedTableName ) ) + return NULL; + + Reference< XColumnsSupplier > xSuppCols( xTables->getByName( sComposedTableName ), UNO_QUERY_THROW ); + Reference< XNameAccess > xColumns( xSuppCols->getColumns(), UNO_QUERY_THROW ); + + ::rtl::OUString sColumn; + OSL_VERIFY( getPropertyValue( PROPERTY_REALNAME ) >>= sColumn ); + if ( !xColumns->hasByName( sColumn ) ) + return NULL; + + xOriginalTableColumn.set( xColumns->getByName( sColumn ), UNO_QUERY ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + return xOriginalTableColumn; +} + +//-------------------------------------------------------------------------- +IMPLEMENT_GET_IMPLEMENTATION_ID( OQueryColumn ) + +//-------------------------------------------------------------------------- +::rtl::OUString SAL_CALL OQueryColumn::getImplementationName( ) throw(RuntimeException) +{ + return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "org.openoffice.comp.dbaccess.OQueryColumn" ) ); +} + +//------------------------------------------------------------------------------ +::cppu::IPropertyArrayHelper& SAL_CALL OQueryColumn::getInfoHelper() +{ + return *OQueryColumn_PBase::getArrayHelper(); +} + +//-------------------------------------------------------------------------- +::cppu::IPropertyArrayHelper* OQueryColumn::createArrayHelper() const +{ + return OTableColumnDescriptor::createArrayHelper(); +} + +//-------------------------------------------------------------------------- +void SAL_CALL OQueryColumn::getFastPropertyValue( Any& _rValue, sal_Int32 _nHandle ) const +{ + OTableColumnDescriptor::getFastPropertyValue( _rValue, _nHandle ); + + // special treatment for column settings: + if ( !OColumnSettings::isColumnSettingProperty( _nHandle ) ) + return; + + // If the setting has its default value, then try to obtain the value from the table column which + // this query column is based on + if ( !OColumnSettings::isDefaulted( _nHandle, _rValue ) ) + return; + + if ( !m_xOriginalTableColumn.is() ) + return; + + try + { + // determine original property name + ::rtl::OUString sPropName; + sal_Int16 nAttributes( 0 ); + const_cast< OQueryColumn* >( this )->getInfoHelper().fillPropertyMembersByHandle( &sPropName, &nAttributes, _nHandle ); + OSL_ENSURE( sPropName.getLength(), "OColumnWrapper::impl_getPropertyNameFromHandle: property not found!" ); + + _rValue = m_xOriginalTableColumn->getPropertyValue( sPropName ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } +} + +//========================================================================== +//= OColumnWrapper +//========================================================================== +DBG_NAME(OColumnWrapper); +//-------------------------------------------------------------------------- +OColumnWrapper::OColumnWrapper( const Reference< XPropertySet > & rCol, const bool _bNameIsReadOnly ) + :OColumn( _bNameIsReadOnly ) + ,m_xAggregate(rCol) + ,m_nColTypeID(-1) +{ + DBG_CTOR(OColumnWrapper,NULL); + // which type of aggregate property do we have? + // we distingish the properties by the containment of optional properties + m_nColTypeID = 0; + if ( m_xAggregate.is() ) + { + Reference <XPropertySetInfo > xInfo(m_xAggregate->getPropertySetInfo()); + m_nColTypeID |= xInfo->hasPropertyByName(PROPERTY_DESCRIPTION) ? HAS_DESCRIPTION : 0; + m_nColTypeID |= xInfo->hasPropertyByName(PROPERTY_DEFAULTVALUE) ? HAS_DEFAULTVALUE : 0; + m_nColTypeID |= xInfo->hasPropertyByName(PROPERTY_ISROWVERSION) ? HAS_ROWVERSION : 0; + m_nColTypeID |= xInfo->hasPropertyByName(PROPERTY_AUTOINCREMENTCREATION) ? HAS_AUTOINCREMENT_CREATION : 0; + + m_xAggregate->getPropertyValue(PROPERTY_NAME) >>= m_sName; + } +} +// ----------------------------------------------------------------------------- +OColumnWrapper::~OColumnWrapper() +{ + DBG_DTOR(OColumnWrapper,NULL); +} + +//------------------------------------------------------------------------------ +::rtl::OUString OColumnWrapper::impl_getPropertyNameFromHandle( const sal_Int32 _nHandle ) const +{ + ::rtl::OUString sPropName; + sal_Int16 nAttributes( 0 ); + const_cast< OColumnWrapper* >( this )->getInfoHelper().fillPropertyMembersByHandle( &sPropName, &nAttributes, _nHandle ); + OSL_ENSURE( sPropName.getLength(), "OColumnWrapper::impl_getPropertyNameFromHandle: property not found!" ); + return sPropName; +} + +//------------------------------------------------------------------------------ +void OColumnWrapper::getFastPropertyValue( Any& rValue, sal_Int32 nHandle ) const +{ + // derived classes are free to either use the OPropertyContainer(Helper) mechanisms for properties, + // or to declare additional properties which are to be forwarded to the wrapped object. So we need + // to distinguish those cases. + if ( OColumn::isRegisteredProperty( nHandle ) ) + { + OColumn::getFastPropertyValue( rValue, nHandle ); + } + else + { + rValue = m_xAggregate->getPropertyValue( impl_getPropertyNameFromHandle( nHandle ) ); + } +} + +//------------------------------------------------------------------------------ +sal_Bool OColumnWrapper::convertFastPropertyValue( Any & rConvertedValue, Any & rOldValue, sal_Int32 nHandle, + const Any& rValue ) throw (IllegalArgumentException) +{ + sal_Bool bModified( sal_False ); + if ( OColumn::isRegisteredProperty( nHandle ) ) + { + bModified = OColumn::convertFastPropertyValue( rConvertedValue, rOldValue, nHandle, rValue ); + } + else + { + getFastPropertyValue( rOldValue, nHandle ); + if ( rOldValue != rValue ) + { + rConvertedValue = rValue; + bModified = sal_True; + } + } + return bModified; +} + +//------------------------------------------------------------------------------ +void OColumnWrapper::setFastPropertyValue_NoBroadcast( sal_Int32 nHandle, const Any& rValue ) throw (Exception) +{ + if ( OColumn::isRegisteredProperty( nHandle ) ) + { + OColumn::setFastPropertyValue_NoBroadcast( nHandle, rValue ); + } + else + { + m_xAggregate->setPropertyValue( impl_getPropertyNameFromHandle( nHandle ), rValue ); + } +} + +// ----------------------------------------------------------------------------- +sal_Int64 SAL_CALL OColumnWrapper::getSomething( const Sequence< sal_Int8 >& aIdentifier ) throw(RuntimeException) +{ + Reference< XUnoTunnel > xTunnel( m_xAggregate, UNO_QUERY); + if ( xTunnel.is() ) + return xTunnel->getSomething( aIdentifier ); + return 0; +} + +//============================================================ +//= OTableColumnDescriptorWrapper +//============================================================ +//-------------------------------------------------------------------------- +OTableColumnDescriptorWrapper::OTableColumnDescriptorWrapper( const Reference< XPropertySet >& _rCol, const bool _bPureWrap, const bool _bIsDescriptor ) + :OColumnWrapper( _rCol, !_bIsDescriptor ) + ,m_bPureWrap( _bPureWrap ) + ,m_bIsDescriptor( _bIsDescriptor ) +{ + // let the ColumnSettings register its properties + OColumnSettings::registerProperties( *this ); +} + +// com::sun::star::lang::XTypeProvider +//-------------------------------------------------------------------------- +IMPLEMENT_GET_IMPLEMENTATION_ID( OTableColumnDescriptorWrapper ) + +// ::com::sun::star::lang::XServiceInfo +//------------------------------------------------------------------------------ +rtl::OUString OTableColumnDescriptorWrapper::getImplementationName( ) throw (RuntimeException) +{ + return rtl::OUString::createFromAscii("com.sun.star.sdb.OTableColumnDescriptorWrapper"); +} + +//------------------------------------------------------------------------------ +Sequence< ::rtl::OUString > OTableColumnDescriptorWrapper::getSupportedServiceNames( ) throw (RuntimeException) +{ + Sequence< ::rtl::OUString > aSNS( 2 ); + aSNS[0] = SERVICE_SDBCX_COLUMNDESCRIPTOR; + aSNS[1] = SERVICE_SDB_COLUMNSETTINGS; + return aSNS; +} + +// comphelper::OPropertyArrayUsageHelper +//------------------------------------------------------------------------------ +::cppu::IPropertyArrayHelper* OTableColumnDescriptorWrapper::createArrayHelper( sal_Int32 nId ) const +{ + const sal_Int32 nHaveAlways = 7; + + // Which optional properties are contained? + sal_Int32 nHaveOptionally = 0; + if (nId & HAS_DESCRIPTION) + ++nHaveOptionally; + if (nId & HAS_DEFAULTVALUE) + ++nHaveOptionally; + if (nId & HAS_ROWVERSION) + ++nHaveOptionally; + if ( nId & HAS_AUTOINCREMENT_CREATION ) + ++nHaveOptionally; + + const sal_Int32 nPropertyCount( nHaveAlways + nHaveOptionally ); + Sequence< Property > aTableDescProperties( nPropertyCount ); + Property* pDesc = aTableDescProperties.getArray(); + sal_Int32 nPos = 0; + + DECL_PROP0_BOOL( ISAUTOINCREMENT ); + DECL_PROP0_BOOL( ISCURRENCY ); + DECL_PROP0( ISNULLABLE, sal_Int32 ); + DECL_PROP0( PRECISION, sal_Int32 ); + DECL_PROP0( SCALE, sal_Int32 ); + DECL_PROP0( TYPE, sal_Int32 ); + DECL_PROP0( TYPENAME, ::rtl::OUString ); + + if ( nId & HAS_AUTOINCREMENT_CREATION ) + { + DECL_PROP1( AUTOINCREMENTCREATION, ::rtl::OUString, MAYBEVOID ); + } + if ( nId & HAS_DEFAULTVALUE ) + { + DECL_PROP0( DEFAULTVALUE, ::rtl::OUString ); + } + if ( nId & HAS_DESCRIPTION ) + { + DECL_PROP0( DESCRIPTION, ::rtl::OUString ); + } + if ( nId & HAS_ROWVERSION ) + { + DECL_PROP0_BOOL( ISROWVERSION ); + } + + OSL_ENSURE( nPos == nPropertyCount, "OTableColumnDescriptorWrapper::createArrayHelper: something went wrong!" ); + + if ( !m_bIsDescriptor ) + { + for ( Property* prop = aTableDescProperties.getArray(); + prop != aTableDescProperties.getArray() + aTableDescProperties.getLength(); + ++prop + ) + { + prop->Attributes |= PropertyAttribute::READONLY; + } + } + + // finally also describe the properties which are maintained by our base class, in particular the OPropertyContainerHelper + Sequence< Property > aBaseProperties; + describeProperties( aBaseProperties ); + + Sequence< Property > aAllProperties( ::comphelper::concatSequences( aTableDescProperties, aBaseProperties ) ); + return new ::cppu::OPropertyArrayHelper( aAllProperties, sal_False ); +} + +// cppu::OPropertySetHelper +//------------------------------------------------------------------------------ +::cppu::IPropertyArrayHelper& OTableColumnDescriptorWrapper::getInfoHelper() +{ + return *static_cast< OIdPropertyArrayUsageHelper< OTableColumnDescriptorWrapper >* >(this)->getArrayHelper(m_nColTypeID); +} + +//------------------------------------------------------------------------------ +void OTableColumnDescriptorWrapper::getFastPropertyValue( Any& rValue, sal_Int32 nHandle ) const +{ + if ( m_bPureWrap ) + { + rValue = m_xAggregate->getPropertyValue( impl_getPropertyNameFromHandle( nHandle ) ); + } + else + { + OColumnWrapper::getFastPropertyValue( rValue, nHandle ); + } +} + +//------------------------------------------------------------------------------ +sal_Bool OTableColumnDescriptorWrapper::convertFastPropertyValue( Any & rConvertedValue, Any & rOldValue, sal_Int32 nHandle, const Any& rValue ) throw (IllegalArgumentException) +{ + sal_Bool bModified(sal_False); + if ( m_bPureWrap ) + { + // do not delegate to OColumnWrapper: It would, for the properties which were registered with registerProperty, + // ask the OPropertyContainer base class, which is not what we want here. + // TODO: the whole "m_bPureWrap"-thingie is strange. We should have a dedicated class doing this wrapping, + // not a class which normally serves other purposes, and only sometimes does a "pure wrap". It makes the + // code unnecessarily hard to maintain, and error prone. + rOldValue = m_xAggregate->getPropertyValue( impl_getPropertyNameFromHandle( nHandle ) ); + if ( rOldValue != rValue ) + { + rConvertedValue = rValue; + bModified = sal_True; + } + } + else + { + bModified = OColumnWrapper::convertFastPropertyValue( rConvertedValue, rOldValue, nHandle, rValue ); + } + return bModified; +} + +//------------------------------------------------------------------------------ +void OTableColumnDescriptorWrapper::setFastPropertyValue_NoBroadcast( + sal_Int32 nHandle, + const Any& rValue + ) + throw (Exception) +{ + if ( m_bPureWrap ) + { + m_xAggregate->setPropertyValue( impl_getPropertyNameFromHandle( nHandle ), rValue ); + } + else + { + OColumnWrapper::setFastPropertyValue_NoBroadcast( nHandle, rValue ); + } +} + +//============================================================ +//= OTableColumnWrapper +//============================================================ +//-------------------------------------------------------------------------- +OTableColumnWrapper::OTableColumnWrapper( const Reference< XPropertySet >& rCol, const Reference< XPropertySet >& _xColDefintion, + const bool _bPureWrap ) + :OTableColumnDescriptorWrapper( rCol, _bPureWrap, false ) +{ + osl_incrementInterlockedCount( &m_refCount ); + if ( _xColDefintion.is() ) + { + try + { + ::comphelper::copyProperties( _xColDefintion, this ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + } + osl_decrementInterlockedCount( &m_refCount ); +} + +//-------------------------------------------------------------------------- +OTableColumnWrapper::~OTableColumnWrapper() +{ +} + +//-------------------------------------------------------------------------- +IMPLEMENT_GET_IMPLEMENTATION_ID( OTableColumnWrapper ) + +//------------------------------------------------------------------------------ +rtl::OUString OTableColumnWrapper::getImplementationName( ) throw (RuntimeException) +{ + return rtl::OUString::createFromAscii( "com.sun.star.sdb.OTableColumnWrapper" ); +} + +//------------------------------------------------------------------------------ +Sequence< ::rtl::OUString > OTableColumnWrapper::getSupportedServiceNames( ) throw (RuntimeException) +{ + Sequence< ::rtl::OUString > aSNS( 2 ); + aSNS[0] = SERVICE_SDBCX_COLUMN; + aSNS[1] = SERVICE_SDB_COLUMNSETTINGS; + return aSNS; +} + +//------------------------------------------------------------------------------ +::cppu::IPropertyArrayHelper& OTableColumnWrapper::getInfoHelper() +{ + return *static_cast< OIdPropertyArrayUsageHelper< OTableColumnWrapper >* >(this)->getArrayHelper(m_nColTypeID); +} + +// comphelper::OPropertyArrayUsageHelper +//------------------------------------------------------------------------------ +::cppu::IPropertyArrayHelper* OTableColumnWrapper::createArrayHelper( sal_Int32 nId ) const +{ + return OTableColumnDescriptorWrapper::createArrayHelper( nId ); +} + diff --git a/dbaccess/source/core/api/makefile.mk b/dbaccess/source/core/api/makefile.mk new file mode 100644 index 000000000000..9a4dc9d8ec52 --- /dev/null +++ b/dbaccess/source/core/api/makefile.mk @@ -0,0 +1,82 @@ +#************************************************************************* +# +# 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=..$/..$/.. +PRJINC=$(PRJ)$/source +PRJNAME=dbaccess +TARGET=api + +ENABLE_EXCEPTIONS=TRUE + +# --- Settings ---------------------------------- + +.INCLUDE : settings.mk +.INCLUDE : $(PRJ)$/util$/dba.pmk + +# --- Files ------------------------------------- +SLOFILES= \ + $(SLO)$/querydescriptor.obj \ + $(SLO)$/FilteredContainer.obj \ + $(SLO)$/TableDeco.obj \ + $(SLO)$/RowSetCacheIterator.obj \ + $(SLO)$/RowSet.obj \ + $(SLO)$/column.obj \ + $(SLO)$/RowSetBase.obj \ + $(SLO)$/CRowSetDataColumn.obj \ + $(SLO)$/CRowSetColumn.obj \ + $(SLO)$/querycomposer.obj \ + $(SLO)$/CIndexes.obj \ + $(SLO)$/BookmarkSet.obj \ + $(SLO)$/KeySet.obj \ + $(SLO)$/StaticSet.obj \ + $(SLO)$/CacheSet.obj \ + $(SLO)$/RowSetCache.obj \ + $(SLO)$/definitioncolumn.obj \ + $(SLO)$/resultcolumn.obj \ + $(SLO)$/datacolumn.obj \ + $(SLO)$/resultset.obj \ + $(SLO)$/statement.obj \ + $(SLO)$/preparedstatement.obj \ + $(SLO)$/callablestatement.obj \ + $(SLO)$/query.obj \ + $(SLO)$/querycontainer.obj \ + $(SLO)$/table.obj \ + $(SLO)$/viewcontainer.obj \ + $(SLO)$/tablecontainer.obj \ + $(SLO)$/SingleSelectQueryComposer.obj \ + $(SLO)$/HelperCollections.obj \ + $(SLO)$/datasettings.obj \ + $(SLO)$/View.obj \ + $(SLO)$/WrappedResultSet.obj \ + $(SLO)$/OptimisticSet.obj \ + $(SLO)$/PrivateRow.obj \ + $(SLO)$/columnsettings.obj + +# --- Targets ---------------------------------- + +.INCLUDE : target.mk + diff --git a/dbaccess/source/core/api/preparedstatement.cxx b/dbaccess/source/core/api/preparedstatement.cxx new file mode 100644 index 000000000000..98c7c1c74b65 --- /dev/null +++ b/dbaccess/source/core/api/preparedstatement.cxx @@ -0,0 +1,473 @@ +/************************************************************************* + * + * 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_dbaccess.hxx" + +#include "dbastrings.hrc" + +#include <com/sun/star/lang/DisposedException.hpp> +#include <com/sun/star/sdbc/XConnection.hpp> +#include <com/sun/star/sdbc/XDatabaseMetaData.hpp> + +#include <comphelper/property.hxx> +#include <comphelper/sequence.hxx> +#include <cppuhelper/typeprovider.hxx> +#include <preparedstatement.hxx> +#include <resultcolumn.hxx> +#include <resultset.hxx> +#include <tools/debug.hxx> +#include <tools/diagnose_ex.h> + +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::cppu; +using namespace ::osl; +using namespace dbaccess; + +DBG_NAME(OPreparedStatement) + +//-------------------------------------------------------------------------- +OPreparedStatement::OPreparedStatement(const Reference< XConnection > & _xConn, + const Reference< XInterface > & _xStatement) + :OStatementBase(_xConn, _xStatement) +{ + DBG_CTOR(OPreparedStatement, NULL); + m_xAggregateAsParameters = Reference< XParameters >( m_xAggregateAsSet, UNO_QUERY_THROW ); + + Reference<XDatabaseMetaData> xMeta = _xConn->getMetaData(); + m_pColumns = new OColumns(*this, m_aMutex, xMeta.is() && xMeta->supportsMixedCaseQuotedIdentifiers(),::std::vector< ::rtl::OUString>(), NULL,NULL); +} + +//-------------------------------------------------------------------------- +OPreparedStatement::~OPreparedStatement() +{ + m_pColumns->acquire(); + m_pColumns->disposing(); + delete m_pColumns; + + DBG_DTOR(OPreparedStatement, NULL); +} + +// com::sun::star::lang::XTypeProvider +//-------------------------------------------------------------------------- +Sequence< Type > OPreparedStatement::getTypes() throw (RuntimeException) +{ + OTypeCollection aTypes(::getCppuType( (const Reference< XServiceInfo > *)0 ), + ::getCppuType( (const Reference< XPreparedStatement > *)0 ), + ::getCppuType( (const Reference< XParameters > *)0 ), + ::getCppuType( (const Reference< XResultSetMetaDataSupplier > *)0 ), + ::getCppuType( (const Reference< XColumnsSupplier > *)0 ), + OStatementBase::getTypes() ); + + return aTypes.getTypes(); +} + +//-------------------------------------------------------------------------- +Sequence< sal_Int8 > OPreparedStatement::getImplementationId() throw (RuntimeException) +{ + static OImplementationId * pId = 0; + if (! pId) + { + MutexGuard aGuard( Mutex::getGlobalMutex() ); + if (! pId) + { + static OImplementationId aId; + pId = &aId; + } + } + return pId->getImplementationId(); +} + +// com::sun::star::uno::XInterface +//-------------------------------------------------------------------------- +Any OPreparedStatement::queryInterface( const Type & rType ) throw (RuntimeException) +{ + Any aIface = OStatementBase::queryInterface( rType ); + if (!aIface.hasValue()) + aIface = ::cppu::queryInterface( + rType, + static_cast< XServiceInfo * >( this ), + static_cast< XParameters * >( this ), + static_cast< XColumnsSupplier * >( this ), + static_cast< XResultSetMetaDataSupplier * >( this ), + static_cast< XPreparedBatchExecution * >( this ), + static_cast< XMultipleResults * >( this ), + static_cast< XPreparedStatement * >( this )); + return aIface; +} + +//-------------------------------------------------------------------------- +void OPreparedStatement::acquire() throw () +{ + OStatementBase::acquire(); +} + +//-------------------------------------------------------------------------- +void OPreparedStatement::release() throw () +{ + OStatementBase::release(); +} + +// XServiceInfo +//------------------------------------------------------------------------------ +rtl::OUString OPreparedStatement::getImplementationName( ) throw(RuntimeException) +{ + return rtl::OUString::createFromAscii("com.sun.star.sdb.OPreparedStatement"); +} + +//------------------------------------------------------------------------------ +sal_Bool OPreparedStatement::supportsService( const ::rtl::OUString& _rServiceName ) throw (RuntimeException) +{ + return ::comphelper::findValue(getSupportedServiceNames(), _rServiceName, sal_True).getLength() != 0; +} + +//------------------------------------------------------------------------------ +Sequence< ::rtl::OUString > OPreparedStatement::getSupportedServiceNames( ) throw (RuntimeException) +{ + Sequence< ::rtl::OUString > aSNS( 2 ); + aSNS.getArray()[0] = SERVICE_SDBC_PREPAREDSTATEMENT; + aSNS.getArray()[1] = SERVICE_SDB_PREPAREDSTATMENT; + return aSNS; +} + +// OComponentHelper +//------------------------------------------------------------------------------ +void OPreparedStatement::disposing() +{ + { + MutexGuard aGuard(m_aMutex); + m_pColumns->disposing(); + m_xAggregateAsParameters = NULL; + } + OStatementBase::disposing(); +} + +// ::com::sun::star::sdbcx::XColumnsSupplier +//------------------------------------------------------------------------------ +Reference< ::com::sun::star::container::XNameAccess > OPreparedStatement::getColumns(void) throw( RuntimeException ) +{ + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + + // do we have to populate the columns + if (!m_pColumns->isInitialized()) + { + try + { + Reference< XResultSetMetaDataSupplier > xSuppMeta( m_xAggregateAsSet, UNO_QUERY_THROW ); + Reference< XResultSetMetaData > xMetaData( xSuppMeta->getMetaData(), UNO_SET_THROW ); + + Reference< XConnection > xConn( getConnection(), UNO_SET_THROW ); + Reference< XDatabaseMetaData > xDBMeta( xConn->getMetaData(), UNO_SET_THROW ); + + for (sal_Int32 i = 0, nCount = xMetaData->getColumnCount(); i < nCount; ++i) + { + // retrieve the name of the column + rtl::OUString aName = xMetaData->getColumnName(i + 1); + OResultColumn* pColumn = new OResultColumn(xMetaData, i + 1, xDBMeta); + m_pColumns->append(aName, pColumn); + } + } + catch (const SQLException& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + m_pColumns->setInitialized(); + } + return m_pColumns; +} + +// XResultSetMetaDataSupplier +//------------------------------------------------------------------------------ +Reference< XResultSetMetaData > OPreparedStatement::getMetaData(void) throw( SQLException, RuntimeException ) +{ + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + return Reference< XResultSetMetaDataSupplier >( m_xAggregateAsSet, UNO_QUERY_THROW )->getMetaData(); +} + +// XPreparedStatement +//------------------------------------------------------------------------------ +Reference< XResultSet > OPreparedStatement::executeQuery() throw( SQLException, RuntimeException ) +{ + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + + disposeResultSet(); + + Reference< XResultSet > xResultSet; + Reference< XResultSet > xDrvResultSet = Reference< XPreparedStatement >( m_xAggregateAsSet, UNO_QUERY_THROW )->executeQuery(); + if (xDrvResultSet.is()) + { + xResultSet = new OResultSet(xDrvResultSet, *this, m_pColumns->isCaseSensitive()); + + // keep the resultset weak + m_aResultSet = xResultSet; + } + return xResultSet; +} + +//------------------------------------------------------------------------------ +sal_Int32 OPreparedStatement::executeUpdate() throw( SQLException, RuntimeException ) +{ + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + + disposeResultSet(); + + return Reference< XPreparedStatement >( m_xAggregateAsSet, UNO_QUERY_THROW )->executeUpdate(); +} + +//------------------------------------------------------------------------------ +sal_Bool OPreparedStatement::execute() throw( SQLException, RuntimeException ) +{ + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + + disposeResultSet(); + + return Reference< XPreparedStatement >( m_xAggregateAsSet, UNO_QUERY_THROW )->execute(); +} + +//------------------------------------------------------------------------------ +Reference< XConnection > OPreparedStatement::getConnection(void) throw( SQLException, RuntimeException ) +{ + return Reference< XConnection > (m_xParent, UNO_QUERY); +} + +// XParameters +//------------------------------------------------------------------------------ +void SAL_CALL OPreparedStatement::setNull( sal_Int32 parameterIndex, sal_Int32 sqlType ) throw(SQLException, RuntimeException) +{ + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + + m_xAggregateAsParameters->setNull(parameterIndex, sqlType); +} + +//------------------------------------------------------------------------------ +void SAL_CALL OPreparedStatement::setObjectNull( sal_Int32 parameterIndex, sal_Int32 sqlType, const ::rtl::OUString& typeName ) throw(SQLException, RuntimeException) +{ + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + + m_xAggregateAsParameters->setObjectNull(parameterIndex, sqlType, typeName); +} + +//------------------------------------------------------------------------------ +void SAL_CALL OPreparedStatement::setBoolean( sal_Int32 parameterIndex, sal_Bool x ) throw(SQLException, RuntimeException) +{ + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + + m_xAggregateAsParameters->setBoolean(parameterIndex, x); +} + +//------------------------------------------------------------------------------ +void SAL_CALL OPreparedStatement::setByte( sal_Int32 parameterIndex, sal_Int8 x ) throw(SQLException, RuntimeException) +{ + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + + m_xAggregateAsParameters->setByte(parameterIndex, x); +} + +//------------------------------------------------------------------------------ +void SAL_CALL OPreparedStatement::setShort( sal_Int32 parameterIndex, sal_Int16 x ) throw(SQLException, RuntimeException) +{ + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + + m_xAggregateAsParameters->setShort(parameterIndex, x); +} + +//------------------------------------------------------------------------------ +void SAL_CALL OPreparedStatement::setInt( sal_Int32 parameterIndex, sal_Int32 x ) throw(SQLException, RuntimeException) +{ + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + + m_xAggregateAsParameters->setInt(parameterIndex, x); +} + +//------------------------------------------------------------------------------ +void SAL_CALL OPreparedStatement::setLong( sal_Int32 parameterIndex, sal_Int64 x ) throw(SQLException, RuntimeException) +{ + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + + m_xAggregateAsParameters->setLong(parameterIndex, x); +} + +//------------------------------------------------------------------------------ +void SAL_CALL OPreparedStatement::setFloat( sal_Int32 parameterIndex, float x ) throw(SQLException, RuntimeException) +{ + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + + m_xAggregateAsParameters->setFloat(parameterIndex, x); +} + +//------------------------------------------------------------------------------ +void SAL_CALL OPreparedStatement::setDouble( sal_Int32 parameterIndex, double x ) throw(SQLException, RuntimeException) +{ + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + + m_xAggregateAsParameters->setDouble(parameterIndex, x); +} + +//------------------------------------------------------------------------------ +void SAL_CALL OPreparedStatement::setString( sal_Int32 parameterIndex, const ::rtl::OUString& x ) throw(SQLException, RuntimeException) +{ + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + + m_xAggregateAsParameters->setString(parameterIndex, x); +} + +//------------------------------------------------------------------------------ +void SAL_CALL OPreparedStatement::setBytes( sal_Int32 parameterIndex, const Sequence< sal_Int8 >& x ) throw(SQLException, RuntimeException) +{ + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + + m_xAggregateAsParameters->setBytes(parameterIndex, x); +} + +//------------------------------------------------------------------------------ +void SAL_CALL OPreparedStatement::setDate( sal_Int32 parameterIndex, const ::com::sun::star::util::Date& x ) throw(SQLException, RuntimeException) +{ + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + + m_xAggregateAsParameters->setDate(parameterIndex, x); +} + +//------------------------------------------------------------------------------ +void SAL_CALL OPreparedStatement::setTime( sal_Int32 parameterIndex, const ::com::sun::star::util::Time& x ) throw(SQLException, RuntimeException) +{ + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + + m_xAggregateAsParameters->setTime(parameterIndex, x); +} + +//------------------------------------------------------------------------------ +void SAL_CALL OPreparedStatement::setTimestamp( sal_Int32 parameterIndex, const ::com::sun::star::util::DateTime& x ) throw(SQLException, RuntimeException) +{ + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + + m_xAggregateAsParameters->setTimestamp(parameterIndex, x); +} + +//------------------------------------------------------------------------------ +void SAL_CALL OPreparedStatement::setBinaryStream( sal_Int32 parameterIndex, const Reference< ::com::sun::star::io::XInputStream >& x, sal_Int32 length ) throw(SQLException, RuntimeException) +{ + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + + m_xAggregateAsParameters->setBinaryStream(parameterIndex, x, length); +} + +//------------------------------------------------------------------------------ +void SAL_CALL OPreparedStatement::setCharacterStream( sal_Int32 parameterIndex, const Reference< ::com::sun::star::io::XInputStream >& x, sal_Int32 length ) throw(SQLException, RuntimeException) +{ + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + + m_xAggregateAsParameters->setCharacterStream(parameterIndex, x, length); +} + +//------------------------------------------------------------------------------ +void SAL_CALL OPreparedStatement::setObject( sal_Int32 parameterIndex, const Any& x ) throw(SQLException, RuntimeException) +{ + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + + m_xAggregateAsParameters->setObject(parameterIndex, x); +} + +//------------------------------------------------------------------------------ +void SAL_CALL OPreparedStatement::setObjectWithInfo( sal_Int32 parameterIndex, const Any& x, sal_Int32 targetSqlType, sal_Int32 scale ) throw(SQLException, RuntimeException) +{ + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + + m_xAggregateAsParameters->setObjectWithInfo(parameterIndex, x, targetSqlType, scale); +} + +//------------------------------------------------------------------------------ +void SAL_CALL OPreparedStatement::setRef( sal_Int32 parameterIndex, const Reference< XRef >& x ) throw(SQLException, RuntimeException) +{ + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + + m_xAggregateAsParameters->setRef(parameterIndex, x); +} + +//------------------------------------------------------------------------------ +void SAL_CALL OPreparedStatement::setBlob( sal_Int32 parameterIndex, const Reference< XBlob >& x ) throw(SQLException, RuntimeException) +{ + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + + m_xAggregateAsParameters->setBlob(parameterIndex, x); +} + +//------------------------------------------------------------------------------ +void SAL_CALL OPreparedStatement::setClob( sal_Int32 parameterIndex, const Reference< XClob >& x ) throw(SQLException, RuntimeException) +{ + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + + m_xAggregateAsParameters->setClob(parameterIndex, x); +} + +//------------------------------------------------------------------------------ +void SAL_CALL OPreparedStatement::setArray( sal_Int32 parameterIndex, const Reference< XArray >& x ) throw(SQLException, RuntimeException) +{ + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + + m_xAggregateAsParameters->setArray(parameterIndex, x); +} + +//------------------------------------------------------------------------------ +void SAL_CALL OPreparedStatement::clearParameters( ) throw(SQLException, RuntimeException) +{ + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + + m_xAggregateAsParameters->clearParameters(); +} + diff --git a/dbaccess/source/core/api/query.cxx b/dbaccess/source/core/api/query.cxx new file mode 100644 index 000000000000..f4cc3cf34714 --- /dev/null +++ b/dbaccess/source/core/api/query.cxx @@ -0,0 +1,445 @@ +/************************************************************************* + * + * 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_dbaccess.hxx" + +#ifndef _DBA_COREAPI_QUERY_HXX_ +#include "query.hxx" +#endif +#ifndef DBACCESS_SHARED_DBASTRINGS_HRC +#include "dbastrings.hrc" +#endif +#ifndef DBTOOLS_WARNINGSCONTAINER_HXX +#include <connectivity/warningscontainer.hxx> +#endif +#ifndef DBA_HELPERCOLLECTIONS_HXX +#include "HelperCollections.hxx" +#endif +#ifndef _DBA_CORE_RESOURCE_HXX_ +#include "core_resource.hxx" +#endif +#ifndef _DBA_CORE_RESOURCE_HRC_ +#include "core_resource.hrc" +#endif + +#ifndef _CPPUHELPER_QUERYINTERFACE_HXX_ +#include <cppuhelper/queryinterface.hxx> +#endif +#ifndef _TOOLS_DEBUG_HXX +#include <tools/debug.hxx> +#endif +#ifndef TOOLS_DIAGNOSE_EX_H +#include <tools/diagnose_ex.h> +#endif +#ifndef _COMPHELPER_PROPERTY_AGGREGATION_HXX_ +#include <comphelper/propagg.hxx> +#endif +#ifndef _COMPHELPER_SEQUENCE_HXX_ +#include <comphelper/sequence.hxx> +#endif + +/** === begin UNO includes === **/ +#ifndef _COM_SUN_STAR_SDBC_XCONNECTION_HPP_ +#include <com/sun/star/sdbc/XConnection.hpp> +#endif +#ifndef _COM_SUN_STAR_LANG_DISPOSEDEXCEPTION_HPP_ +#include <com/sun/star/lang/DisposedException.hpp> +#endif +#ifndef _COM_SUN_STAR_SDB_XSINGLESELECTQUERYCOMPOSER_HPP_ +#include <com/sun/star/sdb/XSingleSelectQueryComposer.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_XRESULTSETMETADATASUPPLIER_HPP_ +#include <com/sun/star/sdbc/XResultSetMetaDataSupplier.hpp> +#endif +/** === end UNO includes === **/ + +#ifndef _COMPHELPER_TYPES_HXX_ +#include <comphelper/types.hxx> +#endif +#ifndef _COMPHELPER_PROPERTY_HXX_ +#include <comphelper/property.hxx> +#endif +#ifndef UNOTOOLS_INC_SHAREDUNOCOMPONENT_HXX +#include <unotools/sharedunocomponent.hxx> +#endif +#ifndef _DBACORE_DEFINITIONCOLUMN_HXX_ +#include "definitioncolumn.hxx" +#endif + +#include <functional> + +#ifndef DBACORE_SDBCORETOOLS_HXX +#include "sdbcoretools.hxx" +#endif +#ifndef DBACCESS_CORE_API_QUERYCOMPOSER_HXX +#include "querycomposer.hxx" +#endif +#ifndef _COM_SUN_STAR_BEANS_PROPERTYATTRIBUTE_HPP_ +#include <com/sun/star/beans/PropertyAttribute.hpp> +#endif +#ifndef DBA_CONTAINERMEDIATOR_HXX +#include "ContainerMediator.hxx" +#endif + +using namespace dbaccess; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::sdb; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::util; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::container; +using namespace ::comphelper; +using namespace ::osl; +using namespace ::cppu; +using namespace ::utl; + +//........................................................................ +namespace dbaccess +{ +//........................................................................ + +//========================================================================== +//= OQuery +//========================================================================== +DBG_NAME(OQuery) +//-------------------------------------------------------------------------- +OQuery::OQuery( const Reference< XPropertySet >& _rxCommandDefinition + ,const Reference< XConnection >& _rxConn + ,const Reference< XMultiServiceFactory >& _xORB) + :OContentHelper(_xORB,NULL,TContentPtr(new OContentHelper_Impl)) + ,OQueryDescriptor_Base(m_aMutex,*this) + ,ODataSettings(OContentHelper::rBHelper,sal_True) + ,m_xCommandDefinition(_rxCommandDefinition) + ,m_xConnection(_rxConn) + ,m_pColumnMediator( NULL ) + ,m_pWarnings( NULL ) + ,m_bCaseSensitiv(sal_True) + ,m_eDoingCurrently(NONE) +{ + DBG_CTOR(OQuery, NULL); + registerProperties(); + ODataSettings::registerPropertiesFor(this); + + osl_incrementInterlockedCount(&m_refCount); + DBG_ASSERT(m_xCommandDefinition.is(), "OQuery::OQuery : invalid CommandDefinition object !"); + if ( m_xCommandDefinition.is() ) + { + try + { + ::comphelper::copyProperties(_rxCommandDefinition,this); + } + catch(Exception&) + { + OSL_ENSURE(sal_False, "OQueryDescriptor_Base::OQueryDescriptor_Base: caught an exception!"); + } + + m_xCommandDefinition->addPropertyChangeListener(::rtl::OUString(), this); + // m_xCommandDefinition->addPropertyChangeListener(PROPERTY_NAME, this); + m_xCommandPropInfo = m_xCommandDefinition->getPropertySetInfo(); + } + DBG_ASSERT(m_xConnection.is(), "OQuery::OQuery : invalid connection !"); + osl_decrementInterlockedCount(&m_refCount); +} + +//-------------------------------------------------------------------------- +OQuery::~OQuery() +{ + DBG_DTOR(OQuery, NULL); +} +// ----------------------------------------------------------------------------- +IMPLEMENT_IMPLEMENTATION_ID(OQuery); +IMPLEMENT_GETTYPES3(OQuery,OQueryDescriptor_Base,ODataSettings,OContentHelper); +IMPLEMENT_FORWARD_XINTERFACE3( OQuery,OContentHelper,OQueryDescriptor_Base,ODataSettings) +//-------------------------------------------------------------------------- +void OQuery::rebuildColumns() +{ + OSL_PRECOND( getColumnCount() == 0, "OQuery::rebuildColumns: column container should be empty!" ); + // the base class' definition of rebuildColumns promised that clearColumns is called before rebuildColumns + + try + { + m_pColumnMediator = NULL; + + Reference<XColumnsSupplier> xColSup(m_xCommandDefinition,UNO_QUERY); + Reference< XNameAccess > xColumnDefinitions; + if ( xColSup.is() ) + { + xColumnDefinitions = xColSup->getColumns(); + if ( xColumnDefinitions.is() ) + m_pColumnMediator = new OContainerMediator( m_pColumns, xColumnDefinitions, m_xConnection, OContainerMediator::eColumns ); + } + + // fill the columns with columns from the statement + Reference< XMultiServiceFactory > xFactory( m_xConnection, UNO_QUERY_THROW ); + SharedUNOComponent< XSingleSelectQueryComposer, DisposableComponent > xComposer( + Reference< XSingleSelectQueryComposer >( xFactory->createInstance( SERVICE_NAME_SINGLESELECTQUERYCOMPOSER ), UNO_QUERY_THROW ) ); + + Reference< XNameAccess > xColumns; + Reference< XIndexAccess > xColumnsIndexed; + try + { + xComposer->setQuery( m_sCommand ); + Reference< XColumnsSupplier > xCols( xComposer, UNO_QUERY_THROW ); + xColumns.set( xCols->getColumns(), UNO_QUERY_THROW ); + xColumnsIndexed.set( xColumns, UNO_QUERY_THROW ); + } + catch( const SQLException& ) { } + + SharedUNOComponent< XPreparedStatement, DisposableComponent > xPreparedStatement; + if ( !xColumns.is() || ( xColumnsIndexed->getCount() == 0 ) ) + { // the QueryComposer could not parse it. Try a lean version. + xPreparedStatement.set( m_xConnection->prepareStatement( m_sCommand ), UNO_QUERY_THROW ); + Reference< XResultSetMetaDataSupplier > xResMetaDataSup( xPreparedStatement, UNO_QUERY_THROW ); + Reference< XResultSetMetaData > xResultSetMeta( xResMetaDataSup->getMetaData() ); + if ( !xResultSetMeta.is() ) + { + ::rtl::OUString sError( DBA_RES( RID_STR_STATEMENT_WITHOUT_RESULT_SET ) ); + ::dbtools::throwSQLException( sError, SQL_GENERAL_ERROR, *this ); + } + + Reference< XDatabaseMetaData > xDBMeta( m_xConnection->getMetaData(), UNO_QUERY_THROW ); + ::vos::ORef< OSQLColumns > aParseColumns( + ::connectivity::parse::OParseColumn::createColumnsForResultSet( xResultSetMeta, xDBMeta,xColumnDefinitions ) ); + xColumns = OPrivateColumns::createWithIntrinsicNames( + aParseColumns, xDBMeta->storesMixedCaseQuotedIdentifiers(), *this, m_aMutex ); + if ( !xColumns.is() ) + throw RuntimeException(); + } + + Sequence< ::rtl::OUString> aNames = xColumns->getElementNames(); + const ::rtl::OUString* pIter = aNames.getConstArray(); + const ::rtl::OUString* pEnd = pIter + aNames.getLength(); + for ( sal_Int32 i = 0;pIter != pEnd; ++pIter,++i) + { + Reference<XPropertySet> xSource(xColumns->getByName( *pIter ),UNO_QUERY); + ::rtl::OUString sLabel = *pIter; + if ( xColumnDefinitions.is() && xColumnDefinitions->hasByName(*pIter) ) + { + Reference<XPropertySet> xCommandColumn(xColumnDefinitions->getByName( *pIter ),UNO_QUERY); + xCommandColumn->getPropertyValue(PROPERTY_LABEL) >>= sLabel; + } + OQueryColumn* pColumn = new OQueryColumn( xSource, m_xConnection, sLabel); + Reference< XChild > xChild( *pColumn, UNO_QUERY_THROW ); + xChild->setParent( *this ); + + implAppendColumn( *pIter, pColumn ); + Reference< XPropertySet > xDest( *pColumn, UNO_QUERY_THROW ); + if ( m_pColumnMediator.is() ) + m_pColumnMediator->notifyElementCreated( *pIter, xDest ); + } + } + catch( const SQLContext& e ) + { + if ( m_pWarnings ) + m_pWarnings->appendWarning( e ); + } + catch( const SQLWarning& e ) + { + if ( m_pWarnings ) + m_pWarnings->appendWarning( e ); + } + catch( const SQLException& e ) + { + if ( m_pWarnings ) + m_pWarnings->appendWarning( e ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } +} + +// XServiceInfo +//-------------------------------------------------------------------------- +IMPLEMENT_SERVICE_INFO3(OQuery, "com.sun.star.sdb.dbaccess.OQuery", SERVICE_SDB_DATASETTINGS, SERVICE_SDB_QUERY, SERVICE_SDB_QUERYDEFINITION) + +// ::com::sun::star::beans::XPropertyChangeListener +//-------------------------------------------------------------------------- +void SAL_CALL OQuery::propertyChange( const PropertyChangeEvent& _rSource ) throw(RuntimeException) +{ + sal_Int32 nOwnHandle = -1; + { + MutexGuard aGuard(m_aMutex); + + DBG_ASSERT(_rSource.Source.get() == Reference< XInterface >(m_xCommandDefinition, UNO_QUERY).get(), + "OQuery::propertyChange : where did this call come from ?"); + + if (m_eDoingCurrently == SETTING_PROPERTIES) + // we're setting the property ourself, so we will do the neccessary notifications later + return; + + // forward this to our own member holding a copy of the property value + if (getArrayHelper()->hasPropertyByName(_rSource.PropertyName)) + { + Property aOwnProp = getArrayHelper()->getPropertyByName(_rSource.PropertyName); + nOwnHandle = aOwnProp.Handle; + ODataSettings::setFastPropertyValue_NoBroadcast(nOwnHandle, _rSource.NewValue); + // don't use our own setFastPropertyValue_NoBroadcast, this would forward it to the CommandSettings, + // again + // and don't use the "real" setPropertyValue, this is to expensive and not sure to succeed + } + else + { + DBG_ERROR("OQuery::propertyChange : my CommandDefinition has more properties than I do !"); + } + } + + fire(&nOwnHandle, &_rSource.NewValue, &_rSource.OldValue, 1, sal_False); +} + +//-------------------------------------------------------------------------- +void SAL_CALL OQuery::disposing( const EventObject& _rSource ) throw (RuntimeException) +{ + MutexGuard aGuard(m_aMutex); + + (void)_rSource; + DBG_ASSERT(_rSource.Source.get() == Reference< XInterface >(m_xCommandDefinition, UNO_QUERY).get(), + "OQuery::disposing : where did this call come from ?"); + + m_xCommandDefinition->removePropertyChangeListener(::rtl::OUString(), this); + m_xCommandDefinition = NULL; +} + +// XDataDescriptorFactory +//-------------------------------------------------------------------------- +Reference< XPropertySet > SAL_CALL OQuery::createDataDescriptor( ) throw(RuntimeException) +{ + return new OQueryDescriptor(*this); +} + +// pseudo-XComponent +//-------------------------------------------------------------------------- +void SAL_CALL OQuery::disposing() +{ + MutexGuard aGuard(m_aMutex); + if (m_xCommandDefinition.is()) + { + m_xCommandDefinition->removePropertyChangeListener(::rtl::OUString(), this); + m_xCommandDefinition = NULL; + } + disposeColumns(); + + m_pWarnings = NULL; +} + +//-------------------------------------------------------------------------- +void OQuery::setFastPropertyValue_NoBroadcast( sal_Int32 _nHandle, const Any& _rValue ) throw (Exception) +{ + ODataSettings::setFastPropertyValue_NoBroadcast(_nHandle, _rValue); + ::rtl::OUString sAggPropName; + sal_Int16 nAttr = 0; + if (getInfoHelper().fillPropertyMembersByHandle(&sAggPropName,&nAttr,_nHandle) && + m_xCommandPropInfo.is() && + m_xCommandPropInfo->hasPropertyByName(sAggPropName)) + { // the base class holds the property values itself, but we have to forward this to our CommandDefinition + + m_eDoingCurrently = SETTING_PROPERTIES; + OAutoActionReset(this); + m_xCommandDefinition->setPropertyValue(sAggPropName, _rValue); + + if ( PROPERTY_ID_COMMAND == _nHandle ) + // the columns are out of date if we are based on a new statement .... + // 90573 - 16.08.2001 - frank.schoenheit@sun.com + setColumnsOutOfDate(); + } +} + +//-------------------------------------------------------------------------- +Reference< XPropertySetInfo > SAL_CALL OQuery::getPropertySetInfo( ) throw(RuntimeException) +{ + return createPropertySetInfo( getInfoHelper() ) ; +} + +//------------------------------------------------------------------------------ +::cppu::IPropertyArrayHelper& OQuery::getInfoHelper() +{ + return *getArrayHelper(); +} + +//-------------------------------------------------------------------------- +::cppu::IPropertyArrayHelper* OQuery::createArrayHelper( ) const +{ + Sequence< Property > aProps; + // our own props + describeProperties(aProps); + return new ::cppu::OPropertyArrayHelper(aProps); +} +// ----------------------------------------------------------------------------- +OColumn* OQuery::createColumn(const ::rtl::OUString& /*_rName*/) const +{ + return NULL; +} +// ----------------------------------------------------------------------------- +void SAL_CALL OQuery::rename( const ::rtl::OUString& newName ) throw (SQLException, ElementExistException, RuntimeException) +{ + MutexGuard aGuard(m_aMutex); + Reference<XRename> xRename(m_xCommandDefinition,UNO_QUERY); + OSL_ENSURE(xRename.is(),"No XRename interface!"); + if(xRename.is()) + xRename->rename(newName); +} +// ----------------------------------------------------------------------------- +void OQuery::registerProperties() +{ + // the properties which OCommandBase supplies (it has no own registration, as it's not derived from + // a OPropertyStateContainer) + registerProperty(PROPERTY_NAME, PROPERTY_ID_NAME, PropertyAttribute::BOUND|PropertyAttribute::CONSTRAINED, + &m_sElementName, ::getCppuType(&m_sElementName)); + + registerProperty(PROPERTY_COMMAND, PROPERTY_ID_COMMAND, PropertyAttribute::BOUND, + &m_sCommand, ::getCppuType(&m_sCommand)); + + registerProperty(PROPERTY_ESCAPE_PROCESSING, PROPERTY_ID_ESCAPE_PROCESSING, PropertyAttribute::BOUND, + &m_bEscapeProcessing, ::getBooleanCppuType()); + + registerProperty(PROPERTY_UPDATE_TABLENAME, PROPERTY_ID_UPDATE_TABLENAME, PropertyAttribute::BOUND, + &m_sUpdateTableName, ::getCppuType(&m_sUpdateTableName)); + + registerProperty(PROPERTY_UPDATE_SCHEMANAME, PROPERTY_ID_UPDATE_SCHEMANAME, PropertyAttribute::BOUND, + &m_sUpdateSchemaName, ::getCppuType(&m_sUpdateSchemaName)); + + registerProperty(PROPERTY_UPDATE_CATALOGNAME, PROPERTY_ID_UPDATE_CATALOGNAME, PropertyAttribute::BOUND, + &m_sUpdateCatalogName, ::getCppuType(&m_sUpdateCatalogName)); + + registerProperty(PROPERTY_LAYOUTINFORMATION, PROPERTY_ID_LAYOUTINFORMATION, PropertyAttribute::BOUND, + &m_aLayoutInformation, ::getCppuType(&m_aLayoutInformation)); +} + +// ----------------------------------------------------------------------------- +::rtl::OUString OQuery::determineContentType() const +{ + return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "application/vnd.org.openoffice.DatabaseQuery" ) ); +} + +// ----------------------------------------------------------------------------- +//........................................................................ +} // namespace dbaccess +//........................................................................ + diff --git a/dbaccess/source/core/api/query.hxx b/dbaccess/source/core/api/query.hxx new file mode 100644 index 000000000000..81e3a38c7862 --- /dev/null +++ b/dbaccess/source/core/api/query.hxx @@ -0,0 +1,186 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +#ifndef _DBA_COREAPI_QUERY_HXX_ +#define _DBA_COREAPI_QUERY_HXX_ + +#ifndef _DBA_COREAPI_QUERYDESCRIPTOR_HXX_ +#include "querydescriptor.hxx" +#endif +#ifndef _CPPUHELPER_IMPLBASE3_HXX_ +#include <cppuhelper/implbase3.hxx> +#endif +#ifndef _COM_SUN_STAR_SDBCX_XDATADESCRIPTORFACTORY_HPP_ +#include <com/sun/star/sdbcx/XDataDescriptorFactory.hpp> +#endif +#ifndef _COM_SUN_STAR_BEANS_XPROPERTYCHANGELISTENER_HPP_ +#include <com/sun/star/beans/XPropertyChangeListener.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_XCONNECTION_HPP_ +#include <com/sun/star/sdbc/XConnection.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBCX_XRENAME_HPP_ +#include <com/sun/star/sdbcx/XRename.hpp> +#endif +#ifndef DBA_CONTENTHELPER_HXX +#include "ContentHelper.hxx" +#endif + +#include <map> + +namespace dbtools +{ + class IWarningsContainer; +} + +//........................................................................ +namespace dbaccess +{ +//........................................................................ + +//========================================================================== +//= OQuery - an object implementing the sdb.Query service +//========================================================================== +typedef ::cppu::ImplHelper3 < ::com::sun::star::sdbcx::XDataDescriptorFactory, + ::com::sun::star::beans::XPropertyChangeListener, + ::com::sun::star::sdbcx::XRename + > OQuery_Base; +class OQuery; +class OColumn; +typedef ::comphelper::OPropertyArrayUsageHelper< OQuery > OQuery_ArrayHelperBase; + + +class OQuery :public OContentHelper + ,public OQueryDescriptor_Base + ,public OQuery_Base + ,public OQuery_ArrayHelperBase + ,public ODataSettings +{ + friend struct TRelease; + +public: + typedef ::std::map< ::rtl::OUString,OColumn*,::comphelper::UStringMixLess> TNameColumnMap; + +protected: +// TNameColumnMap m_aColumnMap; // contains all columnnames to columns + ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > m_xCommandDefinition; + ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection > m_xConnection; + ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySetInfo > m_xCommandPropInfo; + ::rtl::Reference< OContainerMediator > m_pColumnMediator; + ::dbtools::IWarningsContainer* m_pWarnings; + sal_Bool m_bCaseSensitiv : 1; // assume case sensitivity of the column names ? + + // possible actions on our "aggregate" + enum AGGREGATE_ACTION { NONE, SETTING_PROPERTIES, FLUSHING }; + AGGREGATE_ACTION m_eDoingCurrently; + + // ------------------------------------------------------------------------ + /** a class which automatically resets m_eDoingCurrently in it's destructor + */ + class OAutoActionReset; // just for the following friend declaration + friend class OAutoActionReset; + class OAutoActionReset + { + OQuery* m_pActor; + public: + OAutoActionReset(OQuery* _pActor) : m_pActor(_pActor) { } + ~OAutoActionReset() { m_pActor->m_eDoingCurrently = NONE; } + }; + +protected: + virtual ~OQuery(); + +// OPropertyArrayUsageHelper + virtual ::cppu::IPropertyArrayHelper* createArrayHelper( ) const; + ::cppu::IPropertyArrayHelper* getArrayHelper() { return OQuery_ArrayHelperBase::getArrayHelper(); } + +public: + OQuery( + const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& _rxCommandDefinition, + const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection >& _rxConn, + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& _xORB + ); + +// com::sun::star::lang::XTypeProvider + DECLARE_TYPEPROVIDER( ); + +// ::com::sun::star::uno::XInterface + DECLARE_XINTERFACE( ) + +// ::com::sun::star::beans::XPropertySet + virtual ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo( ) throw(::com::sun::star::uno::RuntimeException); + +// OPropertySetHelper + virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper(); + +// ::com::sun::star::lang::XServiceInfo + DECLARE_SERVICE_INFO(); + +// ::com::sun::star::sdbcx::XDataDescriptorFactory + virtual ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > SAL_CALL createDataDescriptor( ) throw(::com::sun::star::uno::RuntimeException); + +// ::com::sun::star::beans::XPropertyChangeListener + virtual void SAL_CALL propertyChange( const ::com::sun::star::beans::PropertyChangeEvent& evt ) throw(::com::sun::star::uno::RuntimeException); + +// ::com::sun::star::lang::XEventListener + virtual void SAL_CALL disposing( const ::com::sun::star::lang::EventObject& _rSource ) throw (::com::sun::star::uno::RuntimeException); + +// OPropertySetHelper + virtual void SAL_CALL setFastPropertyValue_NoBroadcast( + sal_Int32 nHandle, + const ::com::sun::star::uno::Any& rValue ) + throw (::com::sun::star::uno::Exception); + +public: + // the caller is responsible for the lifetime! + void setWarningsContainer( ::dbtools::IWarningsContainer* _pWarnings ) { m_pWarnings = _pWarnings; } + ::dbtools::IWarningsContainer* getWarningsContainer( ) const { return m_pWarnings; } + + // XRename + virtual void SAL_CALL rename( const ::rtl::OUString& newName ) throw (::com::sun::star::sdbc::SQLException, ::com::sun::star::container::ElementExistException, ::com::sun::star::uno::RuntimeException); + +protected: + virtual void SAL_CALL disposing(); + + virtual OColumn* createColumn(const ::rtl::OUString& _rName) const; + + virtual void rebuildColumns( ); + + // OContentHelper overridables + virtual ::rtl::OUString determineContentType() const; + +private: + void registerProperties(); +}; + +//........................................................................ +} // namespace dbaccess +//........................................................................ + +#endif // _DBA_COREAPI_QUERY_HXX_ + + diff --git a/dbaccess/source/core/api/querycomposer.cxx b/dbaccess/source/core/api/querycomposer.cxx new file mode 100644 index 000000000000..ea0a3617e9ba --- /dev/null +++ b/dbaccess/source/core/api/querycomposer.cxx @@ -0,0 +1,406 @@ +/************************************************************************* + * + * 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_dbaccess.hxx" + +#ifndef _COM_SUN_STAR_LANG_DISPOSEDEXCEPTION_HPP_ +#include <com/sun/star/lang/DisposedException.hpp> +#endif +#ifndef _COM_SUN_STAR_UTIL_XNUMBERFORMATTER_HPP_ +#include <com/sun/star/util/XNumberFormatter.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_COLUMNSEARCH_HPP_ +#include <com/sun/star/sdbc/ColumnSearch.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_DATATYPE_HPP_ +#include <com/sun/star/sdbc/DataType.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_XRESULTSETMETADATASUPPLIER_HPP_ +#include <com/sun/star/sdbc/XResultSetMetaDataSupplier.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_XRESULTSETMETADATA_HPP_ +#include <com/sun/star/sdbc/XResultSetMetaData.hpp> +#endif +#ifndef _COM_SUN_STAR_LANG_SERVICENOTREGISTEREDEXCEPTION_HPP_ +#include <com/sun/star/lang/ServiceNotRegisteredException.hpp> +#endif +#ifndef _COMPHELPER_SEQUENCE_HXX_ +#include <comphelper/sequence.hxx> +#endif +#ifndef _COM_SUN_STAR_UNO_XAGGREGATION_HPP_ +#include <com/sun/star/uno/XAggregation.hpp> +#endif +#ifndef _COMPHELPER_SEQUENCE_HXX_ +#include <comphelper/sequence.hxx> +#endif +#ifndef _COMPHELPER_PROCESSFACTORY_HXX_ +#include <comphelper/processfactory.hxx> +#endif +#ifndef DBACCESS_SHARED_DBASTRINGS_HRC +#include "dbastrings.hrc" +#endif +#ifndef _CPPUHELPER_TYPEPROVIDER_HXX_ +#include <cppuhelper/typeprovider.hxx> +#endif +#ifndef _UTL_CONFIGMGR_HXX_ +#include <unotools/configmgr.hxx> +#endif +#ifndef _COMPHELPER_TYPES_HXX_ +#include <comphelper/types.hxx> +#endif +#ifndef _TOOLS_DEBUG_HXX +#include <tools/debug.hxx> +#endif +#ifndef _COM_SUN_STAR_BEANS_PROPERTYATTRIBUTE_HPP_ +#include <com/sun/star/beans/PropertyAttribute.hpp> +#endif +#ifndef _COM_SUN_STAR_I18N_XLOCALEDATA_HPP_ +#include <com/sun/star/i18n/XLocaleData.hpp> +#endif +#ifndef INCLUDED_SVTOOLS_SYSLOCALE_HXX +#include <unotools/syslocale.hxx> +#endif +#ifndef _COM_SUN_STAR_CONTAINER_XCHILD_HPP_ +#include <com/sun/star/container/XChild.hpp> +#endif +#include <com/sun/star/sdb/SQLFilterOperator.hpp> +#ifndef DBACCESS_CORE_API_QUERYCOMPOSER_HXX +#include "querycomposer.hxx" +#endif +#ifndef DBA_HELPERCOLLECTIONS_HXX +#include "HelperCollections.hxx" +#endif +#ifndef DBACCESS_SOURCE_CORE_INC_COMPOSERTOOLS_HXX +#include "composertools.hxx" +#endif +#include <algorithm> +#include <rtl/logfile.hxx> + +using namespace dbaccess; +using namespace dbtools; +using namespace comphelper; +using namespace connectivity; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::sdb; +using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::i18n; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::script; +using namespace ::cppu; +using namespace ::osl; +using namespace ::utl; + + +DBG_NAME(OQueryComposer) +// ------------------------------------------------------------------------- +OQueryComposer::OQueryComposer(const Reference< XConnection>& _xConnection) + : OSubComponent(m_aMutex,_xConnection) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OQueryComposer::OQueryComposer" ); + DBG_CTOR(OQueryComposer,NULL); + OSL_ENSURE(_xConnection.is()," Connection cant be null!"); + + Reference<XMultiServiceFactory> xFac( _xConnection, UNO_QUERY_THROW ); + m_xComposer.set( xFac->createInstance( SERVICE_NAME_SINGLESELECTQUERYCOMPOSER ), UNO_QUERY_THROW ); + m_xComposerHelper.set( xFac->createInstance( SERVICE_NAME_SINGLESELECTQUERYCOMPOSER ), UNO_QUERY_THROW ); +} +// ------------------------------------------------------------------------- +OQueryComposer::~OQueryComposer() +{ + DBG_DTOR(OQueryComposer,NULL); +} +// ----------------------------------------------------------------------------- +void SAL_CALL OQueryComposer::disposing() +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OQueryComposer::disposing" ); + ::comphelper::disposeComponent(m_xComposerHelper); + ::comphelper::disposeComponent(m_xComposer); +} +// ------------------------------------------------------------------------- +// ::com::sun::star::lang::XTypeProvider +Sequence< Type > SAL_CALL OQueryComposer::getTypes() throw (RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OQueryComposer::getTypes" ); + return ::comphelper::concatSequences(OSubComponent::getTypes(),OQueryComposer_BASE::getTypes()); +} +// ------------------------------------------------------------------------- +Sequence< sal_Int8 > SAL_CALL OQueryComposer::getImplementationId() throw (RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OQueryComposer::getImplementationId" ); + static OImplementationId * pId = 0; + if (! pId) + { + MutexGuard aGuard( Mutex::getGlobalMutex() ); + if (! pId) + { + static OImplementationId aId; + pId = &aId; + } + } + return pId->getImplementationId(); +} +// ------------------------------------------------------------------------- +// com::sun::star::lang::XUnoTunnel +sal_Int64 SAL_CALL OQueryComposer::getSomething( const Sequence< sal_Int8 >& rId ) throw(RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OQueryComposer::getSomething" ); + if (rId.getLength() == 16 && 0 == rtl_compareMemory(getImplementationId().getConstArray(), rId.getConstArray(), 16 ) ) + return reinterpret_cast<sal_Int64>(this); + + return 0; +} +// ------------------------------------------------------------------------- +Any SAL_CALL OQueryComposer::queryInterface( const Type & rType ) throw(RuntimeException) +{ + //RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OQueryComposer::queryInterface" ); + Any aRet = OSubComponent::queryInterface(rType); + if(!aRet.hasValue()) + aRet = OQueryComposer_BASE::queryInterface(rType); + return aRet; +} +// ------------------------------------------------------------------------- +// XServiceInfo +//------------------------------------------------------------------------------ +rtl::OUString OQueryComposer::getImplementationName( ) throw(RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OQueryComposer::getImplementationName" ); + return rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.sdb.dbaccess.OQueryComposer")); +} +//------------------------------------------------------------------------------ +sal_Bool OQueryComposer::supportsService( const ::rtl::OUString& _rServiceName ) throw (RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OQueryComposer::supportsService" ); + return ::comphelper::findValue(getSupportedServiceNames(), _rServiceName, sal_True).getLength() != 0; +} +//------------------------------------------------------------------------------ +Sequence< ::rtl::OUString > OQueryComposer::getSupportedServiceNames( ) throw (RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OQueryComposer::getSupportedServiceNames" ); + Sequence< rtl::OUString > aSNS( 1 ); + aSNS[0] = SERVICE_SDB_SQLQUERYCOMPOSER; + return aSNS; +} +// ------------------------------------------------------------------------- +// XSQLQueryComposer +::rtl::OUString SAL_CALL OQueryComposer::getQuery( ) throw(RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OQueryComposer::getQuery" ); + ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed); + + ::osl::MutexGuard aGuard( m_aMutex ); + Reference<XPropertySet> xProp(m_xComposer,UNO_QUERY); + ::rtl::OUString sQuery; + if ( xProp.is() ) + xProp->getPropertyValue(PROPERTY_ORIGINAL) >>= sQuery; + return sQuery; +} +// ------------------------------------------------------------------------- +void SAL_CALL OQueryComposer::setQuery( const ::rtl::OUString& command ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OQueryComposer::setQuery" ); + ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed); + + ::osl::MutexGuard aGuard( m_aMutex ); + m_aFilters.clear(); + m_xComposer->setQuery(command); + m_sOrgFilter = m_xComposer->getFilter(); + m_sOrgOrder = m_xComposer->getOrder(); +} +// ------------------------------------------------------------------------- +::rtl::OUString SAL_CALL OQueryComposer::getComposedQuery( ) throw(RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OQueryComposer::getComposedQuery" ); + ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed); + + MutexGuard aGuard(m_aMutex); + + return m_xComposer->getQuery(); +} +// ------------------------------------------------------------------------- +::rtl::OUString SAL_CALL OQueryComposer::getFilter( ) throw(RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OQueryComposer::getFilter" ); + ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed); + MutexGuard aGuard(m_aMutex); + FilterCreator aFilterCreator; + aFilterCreator = ::std::for_each(m_aFilters.begin(),m_aFilters.end(),aFilterCreator); + return aFilterCreator.getComposedAndClear(); +} +// ------------------------------------------------------------------------- +Sequence< Sequence< PropertyValue > > SAL_CALL OQueryComposer::getStructuredFilter( ) throw(RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OQueryComposer::getStructuredFilter" ); + ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed); + + MutexGuard aGuard(m_aMutex); + return m_xComposer->getStructuredFilter(); +} +// ------------------------------------------------------------------------- +::rtl::OUString SAL_CALL OQueryComposer::getOrder( ) throw(RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OQueryComposer::getOrder" ); + ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed); + + ::osl::MutexGuard aGuard( m_aMutex ); + OrderCreator aOrderCreator; + aOrderCreator = ::std::for_each(m_aOrders.begin(),m_aOrders.end(),aOrderCreator); + return aOrderCreator.getComposedAndClear(); +} +// ----------------------------------------------------------------------------- +void SAL_CALL OQueryComposer::appendFilterByColumn( const Reference< XPropertySet >& column ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OQueryComposer::appendFilterByColumn" ); + ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed); + ::osl::MutexGuard aGuard( m_aMutex ); + + m_xComposerHelper->setQuery(getQuery()); + m_xComposerHelper->setFilter(::rtl::OUString()); + sal_Int32 nOp = SQLFilterOperator::EQUAL; + if ( column.is() ) + { + sal_Int32 nType = 0; + column->getPropertyValue(PROPERTY_TYPE) >>= nType; + switch(nType) + { + case DataType::VARCHAR: + case DataType::CHAR: + case DataType::LONGVARCHAR: + nOp = SQLFilterOperator::LIKE; + break; + default: + nOp = SQLFilterOperator::EQUAL; + } + } + m_xComposerHelper->appendFilterByColumn(column,sal_True,nOp); + + FilterCreator aFilterCreator; + aFilterCreator.append(getFilter()); + aFilterCreator.append(m_xComposerHelper->getFilter()); + + setFilter( aFilterCreator.getComposedAndClear() ); +} +// ------------------------------------------------------------------------- +void SAL_CALL OQueryComposer::appendOrderByColumn( const Reference< XPropertySet >& column, sal_Bool ascending ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OQueryComposer::appendOrderByColumn" ); + ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed); + ::osl::MutexGuard aGuard( m_aMutex ); + + m_xComposerHelper->setQuery(getQuery()); + m_xComposerHelper->setOrder(::rtl::OUString()); + m_xComposerHelper->appendOrderByColumn(column,ascending); + + OrderCreator aOrderCreator; + aOrderCreator.append(getOrder()); + aOrderCreator.append(m_xComposerHelper->getOrder()); + + setOrder(aOrderCreator.getComposedAndClear()); +} +// ------------------------------------------------------------------------- +void SAL_CALL OQueryComposer::setFilter( const ::rtl::OUString& filter ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OQueryComposer::setFilter" ); + ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed); + + ::osl::MutexGuard aGuard( m_aMutex ); + FilterCreator aFilterCreator; + aFilterCreator.append(m_sOrgFilter); + aFilterCreator.append(filter); + + m_aFilters.clear(); + if ( filter.getLength() ) + m_aFilters.push_back(filter); + + m_xComposer->setFilter( aFilterCreator.getComposedAndClear() ); +} +// ------------------------------------------------------------------------- +void SAL_CALL OQueryComposer::setOrder( const ::rtl::OUString& order ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OQueryComposer::setOrder" ); + ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed); + + ::osl::MutexGuard aGuard( m_aMutex ); + + OrderCreator aOrderCreator; + aOrderCreator.append(m_sOrgOrder); + aOrderCreator.append(order); + + m_aOrders.clear(); + if ( order.getLength() ) + m_aOrders.push_back(order); + + m_xComposer->setOrder(aOrderCreator.getComposedAndClear()); +} +// ------------------------------------------------------------------------- +// XTablesSupplier +Reference< XNameAccess > SAL_CALL OQueryComposer::getTables( ) throw(RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OQueryComposer::getTables" ); + ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed); + + ::osl::MutexGuard aGuard( m_aMutex ); + return Reference<XTablesSupplier>(m_xComposer,UNO_QUERY)->getTables(); +} +// ------------------------------------------------------------------------- +// XColumnsSupplier +Reference< XNameAccess > SAL_CALL OQueryComposer::getColumns( ) throw(RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OQueryComposer::getColumns" ); + ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed); + + ::osl::MutexGuard aGuard( m_aMutex ); + return Reference<XColumnsSupplier>(m_xComposer,UNO_QUERY)->getColumns(); +} +// ------------------------------------------------------------------------- +Reference< XIndexAccess > SAL_CALL OQueryComposer::getParameters( ) throw(RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OQueryComposer::getParameters" ); + ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed); + + ::osl::MutexGuard aGuard( m_aMutex ); + return Reference<XParametersSupplier>(m_xComposer,UNO_QUERY)->getParameters(); +} +// ----------------------------------------------------------------------------- +void SAL_CALL OQueryComposer::acquire() throw() +{ + OSubComponent::acquire(); +} +// ----------------------------------------------------------------------------- +void SAL_CALL OQueryComposer::release() throw() +{ + OSubComponent::release(); +} +// ----------------------------------------------------------------------------- + + + + + diff --git a/dbaccess/source/core/api/querycontainer.cxx b/dbaccess/source/core/api/querycontainer.cxx new file mode 100644 index 000000000000..043912259aff --- /dev/null +++ b/dbaccess/source/core/api/querycontainer.cxx @@ -0,0 +1,475 @@ +/************************************************************************* + * + * 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_dbaccess.hxx" + +#ifndef _DBA_CORE_QUERYCONTAINER_HXX_ +#include "querycontainer.hxx" +#endif +#ifndef DBACCESS_SHARED_DBASTRINGS_HRC +#include "dbastrings.hrc" +#endif +#ifndef _DBA_COREAPI_QUERY_HXX_ +#include "query.hxx" +#endif +#ifndef DBACCESS_OBJECTNAMEAPPROVAL_HXX +#include "objectnameapproval.hxx" +#endif +#ifndef DBA_CONTAINERLISTENER_HXX +#include "ContainerListener.hxx" +#endif +#ifndef DBACCESS_VETO_HXX +#include "veto.hxx" +#endif + +/** === begin UNO includes === **/ +#ifndef _COM_SUN_STAR_BEANS_XPROPERTYSET_HPP_ +#include <com/sun/star/beans/XPropertySet.hpp> +#endif +#ifndef _COM_SUN_STAR_CONTAINER_XCONTAINER_HPP_ +#include <com/sun/star/container/XContainer.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_XCONNECTION_HPP_ +#include <com/sun/star/sdbc/XConnection.hpp> +#endif +#ifndef _COM_SUN_STAR_CONTAINER_XCONTAINERAPPROVEBROADCASTER_HPP_ +#include <com/sun/star/container/XContainerApproveBroadcaster.hpp> +#endif +/** === end UNO includes === **/ + +#ifndef _DBHELPER_DBEXCEPTION_HXX_ +#include <connectivity/dbexception.hxx> +#endif + +#ifndef _TOOLS_DEBUG_HXX +#include <tools/debug.hxx> +#endif +#ifndef _COMPHELPER_ENUMHELPER_HXX_ +#include <comphelper/enumhelper.hxx> +#endif +#ifndef _COMPHELPER_UNO3_HXX_ +#include <comphelper/uno3.hxx> +#endif +#ifndef _COMPHELPER_PROPERTY_HXX_ +#include <comphelper/property.hxx> +#endif +#ifndef _COMPHELPER_SEQUENCE_HXX_ +#include <comphelper/sequence.hxx> +#endif +#ifndef _COMPHELPER_EXTRACT_HXX_ +#include <comphelper/extract.hxx> +#endif +#ifndef _CPPUHELPER_EXC_HLP_HXX_ +#include <cppuhelper/exc_hlp.hxx> +#endif + +using namespace dbtools; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::ucb; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::sdb; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::util; +using namespace ::osl; +using namespace ::comphelper; +using namespace ::cppu; + +//........................................................................ +namespace dbaccess +{ +//........................................................................ + +//========================================================================== +//= OQueryContainer +//========================================================================== +DBG_NAME(OQueryContainer) +//------------------------------------------------------------------------------ +OQueryContainer::OQueryContainer( + const Reference< XNameContainer >& _rxCommandDefinitions + , const Reference< XConnection >& _rxConn + , const Reference< XMultiServiceFactory >& _rxORB, + ::dbtools::IWarningsContainer* _pWarnings) + :ODefinitionContainer(_rxORB,NULL,TContentPtr(new ODefinitionContainer_Impl)) + ,m_pWarnings( _pWarnings ) + ,m_xCommandDefinitions(_rxCommandDefinitions) + ,m_xConnection(_rxConn) +{ + DBG_CTOR(OQueryContainer, NULL); + + increment(m_refCount); + { + m_pCommandsListener = new OContainerListener( *this, m_aMutex ); + m_pCommandsListener->acquire(); + + Reference< XContainer > xContainer( m_xCommandDefinitions, UNO_QUERY_THROW ); + xContainer->addContainerListener( m_pCommandsListener ); + + Reference< XContainerApproveBroadcaster > xContainerApprove( m_xCommandDefinitions, UNO_QUERY_THROW ); + xContainerApprove->addContainerApproveListener( m_pCommandsListener ); + + // fill my structures + ODefinitionContainer_Impl& rDefinitions( getDefinitions() ); + Sequence< ::rtl::OUString > sDefinitionNames = m_xCommandDefinitions->getElementNames(); + const ::rtl::OUString* pDefinitionName = sDefinitionNames.getConstArray(); + const ::rtl::OUString* pEnd = pDefinitionName + sDefinitionNames.getLength(); + for ( ; pDefinitionName != pEnd; ++pDefinitionName ) + { + rDefinitions.insert( *pDefinitionName, TContentPtr() ); + m_aDocuments.push_back(m_aDocumentMap.insert(Documents::value_type(*pDefinitionName,Documents::mapped_type())).first); + } + } + decrement(m_refCount); + + setElementApproval( PContainerApprove( new ObjectNameApproval( _rxConn, ObjectNameApproval::TypeQuery ) ) ); +} + +//------------------------------------------------------------------------------ +OQueryContainer::~OQueryContainer() +{ + DBG_DTOR(OQueryContainer, NULL); + // dispose(); + // maybe we're already disposed, but this should be uncritical +} +// ----------------------------------------------------------------------------- +IMPLEMENT_FORWARD_XINTERFACE2( OQueryContainer,ODefinitionContainer,OQueryContainer_Base) + +//------------------------------------------------------------------------------ +IMPLEMENT_FORWARD_XTYPEPROVIDER2( OQueryContainer,ODefinitionContainer,OQueryContainer_Base) + +//------------------------------------------------------------------------------ +void OQueryContainer::disposing() +{ + ODefinitionContainer::disposing(); + MutexGuard aGuard(m_aMutex); + if ( !m_xCommandDefinitions.is() ) + // already disposed + return; + + if ( m_pCommandsListener ) + { + Reference< XContainer > xContainer( m_xCommandDefinitions, UNO_QUERY ); + xContainer->removeContainerListener( m_pCommandsListener ); + Reference< XContainerApproveBroadcaster > xContainerApprove( m_xCommandDefinitions, UNO_QUERY ); + xContainerApprove->removeContainerApproveListener( m_pCommandsListener ); + + m_pCommandsListener->dispose(); + m_pCommandsListener->release(); + m_pCommandsListener = NULL; + } + + m_xCommandDefinitions = NULL; + m_xConnection = NULL; +} + +// XServiceInfo +//------------------------------------------------------------------------------ +IMPLEMENT_SERVICE_INFO2(OQueryContainer, "com.sun.star.sdb.dbaccess.OQueryContainer", SERVICE_SDBCX_CONTAINER, SERVICE_SDB_QUERIES) + +// XDataDescriptorFactory +//-------------------------------------------------------------------------- +Reference< XPropertySet > SAL_CALL OQueryContainer::createDataDescriptor( ) throw(RuntimeException) +{ + return new OQueryDescriptor(); +} + +// XAppend +//------------------------------------------------------------------------------ +void SAL_CALL OQueryContainer::appendByDescriptor( const Reference< XPropertySet >& _rxDesc ) throw(SQLException, ElementExistException, RuntimeException) +{ + ResettableMutexGuard aGuard(m_aMutex); + if ( !m_xCommandDefinitions.is() ) + throw DisposedException( ::rtl::OUString(), *this ); + + // first clone this object's CommandDefinition part + Reference< XPropertySet > xCommandDefinitionPart( m_aContext.createComponent( (::rtl::OUString)SERVICE_SDB_QUERYDEFINITION ), UNO_QUERY_THROW ); + ::comphelper::copyProperties( _rxDesc, xCommandDefinitionPart ); + // TODO : the columns part of the descriptor has to be copied + + // create a wrapper for the object (*before* inserting into our command definition container) + Reference< XContent > xNewObject( implCreateWrapper( Reference< XContent>( xCommandDefinitionPart, UNO_QUERY_THROW ) ) ); + + ::rtl::OUString sNewObjectName; + _rxDesc->getPropertyValue(PROPERTY_NAME) >>= sNewObjectName; + + try + { + notifyByName( aGuard, sNewObjectName, xNewObject, NULL, E_INSERTED, ApproveListeners ); + } + catch( const Exception& ) + { + disposeComponent( xNewObject ); + disposeComponent( xCommandDefinitionPart ); + throw; + } + + // insert the basic object into the definition container + { + m_eDoingCurrently = INSERTING; + OAutoActionReset aAutoReset(this); + m_xCommandDefinitions->insertByName(sNewObjectName, makeAny(xCommandDefinitionPart)); + } + + implAppend( sNewObjectName, xNewObject ); + notifyByName( aGuard, sNewObjectName, xNewObject, NULL, E_INSERTED, ContainerListemers ); +} + +// XDrop +//------------------------------------------------------------------------------ +void SAL_CALL OQueryContainer::dropByName( const ::rtl::OUString& _rName ) throw(SQLException, NoSuchElementException, RuntimeException) +{ + MutexGuard aGuard(m_aMutex); + if ( !checkExistence(_rName) ) + throw NoSuchElementException(_rName,*this); + + if ( !m_xCommandDefinitions.is() ) + throw DisposedException( ::rtl::OUString(), *this ); + + // now simply forward the remove request to the CommandDefinition container, we're a listener for the removal + // and thus we do everything neccessary in ::elementRemoved + m_xCommandDefinitions->removeByName(_rName); +} + +//------------------------------------------------------------------------------ +void SAL_CALL OQueryContainer::dropByIndex( sal_Int32 _nIndex ) throw(SQLException, IndexOutOfBoundsException, RuntimeException) +{ + MutexGuard aGuard(m_aMutex); + if ((_nIndex<0) || (_nIndex>getCount())) + throw IndexOutOfBoundsException(); + + if ( !m_xCommandDefinitions.is() ) + throw DisposedException( ::rtl::OUString(), *this ); + + ::rtl::OUString sName; + Reference<XPropertySet> xProp(Reference<XIndexAccess>(m_xCommandDefinitions,UNO_QUERY)->getByIndex(_nIndex),UNO_QUERY); + if ( xProp.is() ) + xProp->getPropertyValue(PROPERTY_NAME) >>= sName; + + dropByName(sName); +} +//------------------------------------------------------------------------------ +void SAL_CALL OQueryContainer::elementInserted( const ::com::sun::star::container::ContainerEvent& _rEvent ) throw(::com::sun::star::uno::RuntimeException) +{ + Reference< XContent > xNewElement; + ::rtl::OUString sElementName; + _rEvent.Accessor >>= sElementName; + { + MutexGuard aGuard(m_aMutex); + if (INSERTING == m_eDoingCurrently) + // nothing to do, we're inserting via an "appendByDescriptor" + return; + + DBG_ASSERT(sElementName.getLength(), "OQueryContainer::elementInserted : invalid name !"); + DBG_ASSERT(m_aDocumentMap.find(sElementName) == m_aDocumentMap.end(), "OQueryContainer::elementInserted : oops .... we're inconsistent with our master container !"); + if (!sElementName.getLength() || hasByName(sElementName)) + return; + + // insert an own new element + xNewElement = implCreateWrapper(sElementName); + } + insertByName(sElementName,makeAny(xNewElement)); +} + +//------------------------------------------------------------------------------ +void SAL_CALL OQueryContainer::elementRemoved( const ::com::sun::star::container::ContainerEvent& _rEvent ) throw(::com::sun::star::uno::RuntimeException) +{ + ::rtl::OUString sAccessor; + _rEvent.Accessor >>= sAccessor; + { + DBG_ASSERT(sAccessor.getLength(), "OQueryContainer::elementRemoved : invalid name !"); + DBG_ASSERT(m_aDocumentMap.find(sAccessor) != m_aDocumentMap.end(), "OQueryContainer::elementRemoved : oops .... we're inconsistent with our master container !"); + if ( !sAccessor.getLength() || !hasByName(sAccessor) ) + return; + } + removeByName(sAccessor); +} + +//------------------------------------------------------------------------------ +void SAL_CALL OQueryContainer::elementReplaced( const ::com::sun::star::container::ContainerEvent& _rEvent ) throw(::com::sun::star::uno::RuntimeException) +{ + Reference< XPropertySet > xReplacedElement; + Reference< XContent > xNewElement; + ::rtl::OUString sAccessor; + _rEvent.Accessor >>= sAccessor; + + { + MutexGuard aGuard(m_aMutex); + DBG_ASSERT(sAccessor.getLength(), "OQueryContainer::elementReplaced : invalid name !"); + DBG_ASSERT(m_aDocumentMap.find(sAccessor) != m_aDocumentMap.end(), "OQueryContainer::elementReplaced : oops .... we're inconsistent with our master container !"); + if (!sAccessor.getLength() || !hasByName(sAccessor)) + return; + + xNewElement = implCreateWrapper(sAccessor); + } + + replaceByName(sAccessor,makeAny(xNewElement)); +} + +//------------------------------------------------------------------------------ +Reference< XVeto > SAL_CALL OQueryContainer::approveInsertElement( const ContainerEvent& Event ) throw (WrappedTargetException, RuntimeException) +{ + ::rtl::OUString sName; + OSL_VERIFY( Event.Accessor >>= sName ); + Reference< XContent > xElement( Event.Element, UNO_QUERY_THROW ); + + Reference< XVeto > xReturn; + try + { + getElementApproval()->approveElement( sName, xElement.get() ); + } + catch( const Exception& ) + { + xReturn = new Veto( ::rtl::OUString(), ::cppu::getCaughtException() ); + } + return xReturn; +} + +//------------------------------------------------------------------------------ +Reference< XVeto > SAL_CALL OQueryContainer::approveReplaceElement( const ContainerEvent& /*Event*/ ) throw (WrappedTargetException, RuntimeException) +{ + return NULL; +} + +//------------------------------------------------------------------------------ +Reference< XVeto > SAL_CALL OQueryContainer::approveRemoveElement( const ContainerEvent& /*Event*/ ) throw (WrappedTargetException, RuntimeException) +{ + return NULL; +} + +//------------------------------------------------------------------------------ +void SAL_CALL OQueryContainer::disposing( const ::com::sun::star::lang::EventObject& _rSource ) throw(::com::sun::star::uno::RuntimeException) +{ + if (_rSource.Source.get() == Reference< XInterface >(m_xCommandDefinitions, UNO_QUERY).get()) + { // our "master container" (with the command definitions) is beeing disposed + DBG_ERROR("OQueryContainer::disposing : nobody should dispose the CommandDefinition container before disposing my connection !"); + dispose(); + } + else + { + Reference< XContent > xSource(_rSource.Source, UNO_QUERY); + // it's one of our documents .... + Documents::iterator aIter = m_aDocumentMap.begin(); + Documents::iterator aEnd = m_aDocumentMap.end(); + for (;aIter != aEnd;++aIter ) + { + if ( xSource == aIter->second.get() ) + { + m_xCommandDefinitions->removeByName(aIter->first); + break; + } + } + ODefinitionContainer::disposing(_rSource); + } +} + +// ----------------------------------------------------------------------------- +::rtl::OUString OQueryContainer::determineContentType() const +{ + return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "application/vnd.org.openoffice.DatabaseQueryContainer" ) ); +} + +// ----------------------------------------------------------------------------- +Reference< XContent > OQueryContainer::implCreateWrapper(const ::rtl::OUString& _rName) +{ + Reference< XContent > xObject(m_xCommandDefinitions->getByName(_rName),UNO_QUERY); + return implCreateWrapper(xObject); +} + +//-------------------------------------------------------------------------- +Reference< XContent > OQueryContainer::implCreateWrapper(const Reference< XContent >& _rxCommandDesc) +{ + Reference<XNameContainer> xContainer(_rxCommandDesc,UNO_QUERY); + Reference< XContent > xReturn; + if ( xContainer .is() ) + { + xReturn = new OQueryContainer( xContainer, m_xConnection, m_aContext.getLegacyServiceFactory(), m_pWarnings ); + } + else + { + OQuery* pNewObject = new OQuery( Reference< XPropertySet >( _rxCommandDesc, UNO_QUERY ), m_xConnection, m_aContext.getLegacyServiceFactory() ); + xReturn = pNewObject; + + pNewObject->setWarningsContainer( m_pWarnings ); +// pNewObject->getColumns(); + // Why? This is expensive. If you comment this in 'cause you really need it, be sure to run the + // QueryInQuery test in dbaccess/qa/complex/dbaccess ... + } + + return xReturn; +} +//-------------------------------------------------------------------------- +Reference< XContent > OQueryContainer::createObject( const ::rtl::OUString& _rName) +{ + return implCreateWrapper(_rName); +} +// ----------------------------------------------------------------------------- +sal_Bool OQueryContainer::checkExistence(const ::rtl::OUString& _rName) +{ + sal_Bool bRet = sal_False; + if ( !m_bInPropertyChange ) + { + bRet = m_xCommandDefinitions->hasByName(_rName); + Documents::iterator aFind = m_aDocumentMap.find(_rName); + if ( !bRet && aFind != m_aDocumentMap.end() ) + { + m_aDocuments.erase( ::std::find(m_aDocuments.begin(),m_aDocuments.end(),aFind)); + m_aDocumentMap.erase(aFind); + } + else if ( bRet && aFind == m_aDocumentMap.end() ) + { + implAppend(_rName,NULL); + } + } + return bRet; +} +//-------------------------------------------------------------------------- +sal_Bool SAL_CALL OQueryContainer::hasElements( ) throw (RuntimeException) +{ + MutexGuard aGuard(m_aMutex); + return m_xCommandDefinitions->hasElements(); +} +// ----------------------------------------------------------------------------- +sal_Int32 SAL_CALL OQueryContainer::getCount( ) throw(RuntimeException) +{ + MutexGuard aGuard(m_aMutex); + return Reference<XIndexAccess>(m_xCommandDefinitions,UNO_QUERY)->getCount(); +} +// ----------------------------------------------------------------------------- +Sequence< ::rtl::OUString > SAL_CALL OQueryContainer::getElementNames( ) throw(RuntimeException) +{ + MutexGuard aGuard(m_aMutex); + + return m_xCommandDefinitions->getElementNames(); +} + +//........................................................................ +} // namespace dbaccess +//........................................................................ + diff --git a/dbaccess/source/core/api/querydescriptor.cxx b/dbaccess/source/core/api/querydescriptor.cxx new file mode 100644 index 000000000000..0fb61dbd1f64 --- /dev/null +++ b/dbaccess/source/core/api/querydescriptor.cxx @@ -0,0 +1,323 @@ +/************************************************************************* + * + * 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_dbaccess.hxx" + +#ifndef _DBA_COREAPI_QUERYDESCRIPTOR_HXX_ +#include "querydescriptor.hxx" +#endif +#ifndef _DBASHARED_APITOOLS_HXX_ +#include "apitools.hxx" +#endif +#ifndef DBACCESS_SHARED_DBASTRINGS_HRC +#include "dbastrings.hrc" +#endif +#ifndef _COMPHELPER_PROPERTY_HXX_ +#include <comphelper/property.hxx> +#endif +#ifndef _COMPHELPER_SEQUENCE_HXX_ +#include <comphelper/sequence.hxx> +#endif +#ifndef _CPPUHELPER_TYPEPROVIDER_HXX_ +#include <cppuhelper/typeprovider.hxx> +#endif +#ifndef _COM_SUN_STAR_BEANS_PROPERTYATTRIBUTE_HPP_ +#include <com/sun/star/beans/PropertyAttribute.hpp> +#endif +#ifndef _DBACORE_DEFINITIONCOLUMN_HXX_ +#include "definitioncolumn.hxx" +#endif +#ifndef _TOOLS_DEBUG_HXX +#include <tools/debug.hxx> +#endif + +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::awt; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::util; +using namespace ::comphelper; +using namespace ::osl; +using namespace ::cppu; + +//........................................................................ +namespace dbaccess +{ +//........................................................................ + +//========================================================================== +//= OQueryDescriptor +//========================================================================== +DBG_NAME(OQueryDescriptor) +//-------------------------------------------------------------------------- +OQueryDescriptor::OQueryDescriptor() + :OQueryDescriptor_Base(m_aMutex,*this) + ,ODataSettings(m_aBHelper,sal_True) +{ + DBG_CTOR(OQueryDescriptor,NULL); + registerProperties(); + ODataSettings::registerPropertiesFor(this); +} + +//-------------------------------------------------------------------------- +OQueryDescriptor::OQueryDescriptor(const OQueryDescriptor_Base& _rSource) + :OQueryDescriptor_Base(_rSource,*this) + ,ODataSettings(m_aBHelper,sal_True) +{ + DBG_CTOR(OQueryDescriptor,NULL); + registerProperties(); + ODataSettings::registerPropertiesFor(this); +} +// ----------------------------------------------------------------------------- +OQueryDescriptor::~OQueryDescriptor() +{ + DBG_DTOR(OQueryDescriptor,NULL); +} +// ----------------------------------------------------------------------------- +IMPLEMENT_TYPEPROVIDER2(OQueryDescriptor,OQueryDescriptor_Base,ODataSettings); +IMPLEMENT_FORWARD_XINTERFACE3( OQueryDescriptor,OWeakObject,OQueryDescriptor_Base,ODataSettings) +//-------------------------------------------------------------------------- +void OQueryDescriptor::registerProperties() +{ + // the properties which OCommandBase supplies (it has no own registration, as it's not derived from + // a OPropertyStateContainer) + registerProperty(PROPERTY_NAME, PROPERTY_ID_NAME, PropertyAttribute::BOUND|PropertyAttribute::CONSTRAINED, + &m_sElementName, ::getCppuType(&m_sElementName)); + + registerProperty(PROPERTY_COMMAND, PROPERTY_ID_COMMAND, PropertyAttribute::BOUND, + &m_sCommand, ::getCppuType(&m_sCommand)); + + registerProperty(PROPERTY_ESCAPE_PROCESSING, PROPERTY_ID_ESCAPE_PROCESSING, PropertyAttribute::BOUND, + &m_bEscapeProcessing, ::getBooleanCppuType()); + + registerProperty(PROPERTY_UPDATE_TABLENAME, PROPERTY_ID_UPDATE_TABLENAME, PropertyAttribute::BOUND, + &m_sUpdateTableName, ::getCppuType(&m_sUpdateTableName)); + + registerProperty(PROPERTY_UPDATE_SCHEMANAME, PROPERTY_ID_UPDATE_SCHEMANAME, PropertyAttribute::BOUND, + &m_sUpdateSchemaName, ::getCppuType(&m_sUpdateSchemaName)); + + registerProperty(PROPERTY_UPDATE_CATALOGNAME, PROPERTY_ID_UPDATE_CATALOGNAME, PropertyAttribute::BOUND, + &m_sUpdateCatalogName, ::getCppuType(&m_sUpdateCatalogName)); + + registerProperty(PROPERTY_LAYOUTINFORMATION, PROPERTY_ID_LAYOUTINFORMATION, PropertyAttribute::BOUND, + &m_aLayoutInformation, ::getCppuType(&m_aLayoutInformation)); +} +// ----------------------------------------------------------------------------- +//-------------------------------------------------------------------------- +Reference< XPropertySetInfo > SAL_CALL OQueryDescriptor::getPropertySetInfo( ) throw(RuntimeException) +{ + return createPropertySetInfo( getInfoHelper() ) ; +} + +//------------------------------------------------------------------------------ +::cppu::IPropertyArrayHelper& OQueryDescriptor::getInfoHelper() +{ + return *getArrayHelper(); +} +//-------------------------------------------------------------------------- +::cppu::IPropertyArrayHelper* OQueryDescriptor::createArrayHelper( ) const +{ + Sequence< Property > aProps; + describeProperties(aProps); + return new ::cppu::OPropertyArrayHelper(aProps); +} + +// ----------------------------------------------------------------------------- +DBG_NAME(OQueryDescriptor_Base); +//-------------------------------------------------------------------------- +OQueryDescriptor_Base::OQueryDescriptor_Base(::osl::Mutex& _rMutex,::cppu::OWeakObject& _rMySelf) + :m_bColumnsOutOfDate(sal_True) + ,m_rMutex(_rMutex) +{ + DBG_CTOR(OQueryDescriptor_Base,NULL); + m_pColumns = new OColumns(_rMySelf, m_rMutex, sal_True,::std::vector< ::rtl::OUString>(), this,this); +} +//-------------------------------------------------------------------------- +OQueryDescriptor_Base::OQueryDescriptor_Base(const OQueryDescriptor_Base& _rSource,::cppu::OWeakObject& _rMySelf) + :m_bColumnsOutOfDate(sal_True) + ,m_rMutex(_rSource.m_rMutex) +{ + DBG_CTOR(OQueryDescriptor_Base,NULL); + m_pColumns = new OColumns(_rMySelf, m_rMutex, sal_True,::std::vector< ::rtl::OUString>(), this,this); + + m_sCommand = _rSource.m_sCommand; + m_bEscapeProcessing = _rSource.m_bEscapeProcessing; + m_sUpdateTableName = _rSource.m_sUpdateTableName; + m_sUpdateSchemaName = _rSource.m_sUpdateSchemaName; + m_sUpdateCatalogName = _rSource.m_sUpdateCatalogName; + m_aLayoutInformation = _rSource.m_aLayoutInformation; +} + +//-------------------------------------------------------------------------- +OQueryDescriptor_Base::~OQueryDescriptor_Base() +{ + m_pColumns->acquire(); + m_pColumns->disposing(); + delete m_pColumns; + + DBG_DTOR(OQueryDescriptor_Base,NULL); +} +// ----------------------------------------------------------------------------- +sal_Int64 SAL_CALL OQueryDescriptor_Base::getSomething( const Sequence< sal_Int8 >& _rIdentifier ) throw(RuntimeException) +{ + if (_rIdentifier.getLength() != 16) + return 0; + + if (0 == rtl_compareMemory(getImplementationId().getConstArray(), _rIdentifier.getConstArray(), 16 ) ) + return reinterpret_cast<sal_Int64>(this); + + return 0; +} +//-------------------------------------------------------------------------- +IMPLEMENT_IMPLEMENTATION_ID(OQueryDescriptor_Base) +//-------------------------------------------------------------------------- +void OQueryDescriptor_Base::setColumnsOutOfDate( sal_Bool _bOutOfDate ) +{ + m_bColumnsOutOfDate = _bOutOfDate; + if ( !m_bColumnsOutOfDate ) + m_pColumns->setInitialized(); +} + +//-------------------------------------------------------------------------- +void OQueryDescriptor_Base::implAppendColumn( const ::rtl::OUString& _rName, OColumn* _pColumn ) +{ + m_pColumns->append( _rName, _pColumn ); +} + +//-------------------------------------------------------------------------- +void OQueryDescriptor_Base::clearColumns( ) +{ + m_pColumns->clearColumns(); + + setColumnsOutOfDate(); +} + +//-------------------------------------------------------------------------- +Reference< XNameAccess > SAL_CALL OQueryDescriptor_Base::getColumns( ) throw (RuntimeException) +{ + MutexGuard aGuard(m_rMutex); + + if ( isColumnsOutOfDate() ) + { + // clear the current columns + clearColumns(); + + // do this before rebuildColumns. This prevents recursion, e.g. in the case where we + // have queries with cyclic references: + // foo := SELECT * FROM bar + // bar := SELECT * FROM foo + setColumnsOutOfDate( sal_False ); + + // rebuild them + try + { + rebuildColumns(); + } + catch ( const Exception& ) + { + setColumnsOutOfDate( sal_True ); + throw; + } + } + + return m_pColumns; +} + +//-------------------------------------------------------------------------- +::rtl::OUString SAL_CALL OQueryDescriptor_Base::getImplementationName( ) throw(RuntimeException) +{ + return ::rtl::OUString::createFromAscii("com.sun.star.sdb.OQueryDescriptor"); +} + +//-------------------------------------------------------------------------- +sal_Bool SAL_CALL OQueryDescriptor_Base::supportsService( const ::rtl::OUString& _rServiceName ) throw(RuntimeException) +{ + return ::comphelper::findValue(getSupportedServiceNames(), _rServiceName, sal_True).getLength() != 0; +} + +//-------------------------------------------------------------------------- +Sequence< ::rtl::OUString > SAL_CALL OQueryDescriptor_Base::getSupportedServiceNames( ) throw(RuntimeException) +{ + Sequence< ::rtl::OUString > aSupported(2); + aSupported.getArray()[0] = SERVICE_SDB_DATASETTINGS; + aSupported.getArray()[1] = SERVICE_SDB_QUERYDESCRIPTOR; + return aSupported; +} +//-------------------------------------------------------------------------- +void OQueryDescriptor_Base::disposeColumns() +{ + m_pColumns->disposing(); +} + +// ----------------------------------------------------------------------------- +void OQueryDescriptor_Base::columnAppended( const Reference< XPropertySet >& /*_rxSourceDescriptor*/ ) +{ + // not interested in +} + +// ----------------------------------------------------------------------------- +void OQueryDescriptor_Base::columnDropped(const ::rtl::OUString& /*_sName*/) +{ + // not interested in +} + +// ----------------------------------------------------------------------------- +Reference< XPropertySet > OQueryDescriptor_Base::createColumnDescriptor() +{ + OSL_ENSURE( false, "OQueryDescriptor_Base::createColumnDescriptor: called why?" ); + return NULL; +} + +// ----------------------------------------------------------------------------- +void OQueryDescriptor_Base::rebuildColumns( ) +{ +} + +// ----------------------------------------------------------------------------- +// IRefreshableColumns +void OQueryDescriptor_Base::refreshColumns() +{ + MutexGuard aGuard( m_rMutex ); + + clearColumns(); + rebuildColumns(); +} + +//------------------------------------------------------------------------------ +OColumn* OQueryDescriptor_Base::createColumn( const ::rtl::OUString& /*_rName*/ ) const +{ + // creating a column/descriptor for a query/descriptor does not make sense at all + return NULL; +} +// ----------------------------------------------------------------------------- +//........................................................................ +} // namespace dbaccess +//........................................................................ + + diff --git a/dbaccess/source/core/api/querydescriptor.hxx b/dbaccess/source/core/api/querydescriptor.hxx new file mode 100644 index 000000000000..2f27b4b9c628 --- /dev/null +++ b/dbaccess/source/core/api/querydescriptor.hxx @@ -0,0 +1,183 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +#ifndef _DBA_COREAPI_QUERYDESCRIPTOR_HXX_ +#define _DBA_COREAPI_QUERYDESCRIPTOR_HXX_ + +#ifndef _CPPUHELPER_IMPLBASE3_HXX_ +#include <cppuhelper/implbase3.hxx> +#endif +#ifndef _COMPHELPER_PROPERTY_ARRAY_HELPER_HXX_ +#include <comphelper/proparrhlp.hxx> +#endif +#ifndef _OSL_MUTEX_HXX_ +#include <osl/mutex.hxx> +#endif + +#ifndef _COM_SUN_STAR_SDBCX_XCOLUMNSSUPPLIER_HPP_ +#include <com/sun/star/sdbcx/XColumnsSupplier.hpp> +#endif +#ifndef _COM_SUN_STAR_LANG_XSERVICEINFO_HPP_ +#include <com/sun/star/lang/XServiceInfo.hpp> +#endif +#ifndef _COM_SUN_STAR_LANG_XUNOTUNNEL_HPP_ +#include <com/sun/star/lang/XUnoTunnel.hpp> +#endif + +#ifndef _DBASHARED_APITOOLS_HXX_ +#include "apitools.hxx" +#endif +#ifndef _DBA_COREAPI_COLUMN_HXX_ +#include "column.hxx" +#endif +#ifndef _DBA_CORE_DATASETTINGS_HXX_ +#include "datasettings.hxx" +#endif +#ifndef _DBA_CORE_COMMANDBASE_HXX_ +#include "commandbase.hxx" +#endif +#ifndef _COMPHELPER_BROADCASTHELPER_HXX_ +#include <comphelper/broadcasthelper.hxx> +#endif +#ifndef _COMPHELPER_UNO3_HXX_ +#include <comphelper/uno3.hxx> +#endif + +//........................................................................ +namespace dbaccess +{ +//........................................................................ + +//========================================================================== +//= OQueryDescriptor_Base - a query descriptor (as the name suggests :) +//========================================================================== +typedef ::cppu::ImplHelper3< + ::com::sun::star::sdbcx::XColumnsSupplier, + ::com::sun::star::lang::XUnoTunnel, + ::com::sun::star::lang::XServiceInfo > OQueryDescriptor_BASE; + +class OQueryDescriptor_Base + :public OQueryDescriptor_BASE + ,public OCommandBase + ,public IColumnFactory + ,public ::connectivity::sdbcx::IRefreshableColumns +{ +private: + sal_Bool m_bColumnsOutOfDate : 1; // the columns have to be rebuild on the next getColumns ? + ::osl::Mutex& m_rMutex; + +protected: + OColumns* m_pColumns; // our column descriptions + ::rtl::OUString m_sElementName; + virtual ~OQueryDescriptor_Base(); + + void setColumnsOutOfDate( sal_Bool _bOutOfDate = sal_True ); + sal_Bool isColumnsOutOfDate() const { return m_bColumnsOutOfDate; } + + sal_Int32 getColumnCount() const { return m_pColumns ? m_pColumns->getCount() : 0; } + void clearColumns( ); + + void implAppendColumn( const ::rtl::OUString& _rName, OColumn* _pColumn ); + +public: + OQueryDescriptor_Base(::osl::Mutex& _rMutex,::cppu::OWeakObject& _rMySelf); + /** constructs the object with a UNO QueryDescriptor. If you use this ctor, the resulting object + won't have any column informations (the column container will be empty) + */ + OQueryDescriptor_Base(const OQueryDescriptor_Base& _rSource,::cppu::OWeakObject& _rMySelf); + +// ::com::sun::star::sdbcx::XColumnsSupplier + virtual ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess > SAL_CALL getColumns( ) throw(::com::sun::star::uno::RuntimeException); + +// ::com::sun::star::lang::XUnoTunnel + virtual sal_Int64 SAL_CALL getSomething( const ::com::sun::star::uno::Sequence< sal_Int8 >& aIdentifier ) throw(::com::sun::star::uno::RuntimeException); + DECLARE_IMPLEMENTATION_ID( ); + +// ::com::sun::star::lang::XServiceInfo + virtual ::rtl::OUString SAL_CALL getImplementationName( ) throw(::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) throw(::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames( ) throw(::com::sun::star::uno::RuntimeException); + +protected: + +// IColumnFactory + virtual OColumn* createColumn(const ::rtl::OUString& _rName) const; + virtual ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > createColumnDescriptor(); + virtual void columnAppended( const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& _rxSourceDescriptor ); + virtual void columnDropped(const ::rtl::OUString& _sName); + + /** rebuild our columns set + + clearColumns has already been called before, do <em>NOT</em> call it, again + */ + virtual void rebuildColumns( ); + + virtual void disposeColumns(); + + // IRefreshableColumns overridables + virtual void refreshColumns(); +}; + +class OQueryDescriptor : public comphelper::OMutexAndBroadcastHelper + ,public ::cppu::OWeakObject + ,public OQueryDescriptor_Base + ,public ::comphelper::OPropertyArrayUsageHelper< OQueryDescriptor_Base > + ,public ODataSettings +{ + OQueryDescriptor(const OQueryDescriptor&); + void operator =(const OQueryDescriptor&); + // helper + void registerProperties(); +protected: + // OPropertyArrayUsageHelper + virtual ::cppu::IPropertyArrayHelper* createArrayHelper( ) const; + + // OPropertySetHelper + virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper(); + + virtual ~OQueryDescriptor(); +public: + OQueryDescriptor(); + OQueryDescriptor(const OQueryDescriptor_Base& _rSource); + + // com::sun::star::lang::XTypeProvider + DECLARE_TYPEPROVIDER( ); + +// ::com::sun::star::uno::XInterface + DECLARE_XINTERFACE( ) + + // ::com::sun::star::beans::XPropertySet + virtual ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo( ) throw(::com::sun::star::uno::RuntimeException); + +}; +//........................................................................ +} // namespace dbaccess +//........................................................................ + +#endif // _DBA_COREAPI_QUERYDESCRIPTOR_HXX_ + + diff --git a/dbaccess/source/core/api/resultcolumn.cxx b/dbaccess/source/core/api/resultcolumn.cxx new file mode 100644 index 000000000000..02195693bba1 --- /dev/null +++ b/dbaccess/source/core/api/resultcolumn.cxx @@ -0,0 +1,357 @@ +/************************************************************************* + * + * 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_dbaccess.hxx" +#ifndef _DBACORE_RESULTCOLUMN_HXX_ +#include "resultcolumn.hxx" +#endif +#ifndef _COM_SUN_STAR_LANG_DISPOSEDEXCEPTION_HPP_ +#include <com/sun/star/lang/DisposedException.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_XRESULTSETMETADATASUPPLIER_HPP_ +#include <com/sun/star/sdbc/XResultSetMetaDataSupplier.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_DATATYPE_HPP_ +#include <com/sun/star/sdbc/DataType.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_COLUMNVALUE_HPP_ +#include <com/sun/star/sdbc/ColumnValue.hpp> +#endif +#ifndef _CPPUHELPER_TYPEPROVIDER_HXX_ +#include <cppuhelper/typeprovider.hxx> +#endif +#ifndef _TOOLS_DEBUG_HXX +#include <tools/debug.hxx> +#endif +#ifndef TOOLS_DIAGNOSE_EX_H +#include <tools/diagnose_ex.h> +#endif +#ifndef DBACCESS_SHARED_DBASTRINGS_HRC +#include "dbastrings.hrc" +#endif +#ifndef _DBASHARED_APITOOLS_HXX_ +#include "apitools.hxx" +#endif +#ifndef _COM_SUN_STAR_BEANS_PROPERTYATTRIBUTE_HPP_ +#include <com/sun/star/beans/PropertyAttribute.hpp> +#endif +#ifndef _CPPUHELPER_EXC_HLP_HXX_ +#include <cppuhelper/exc_hlp.hxx> +#endif +#ifndef _OSL_THREAD_H_ +#include <osl/thread.h> +#endif + +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::container; +using namespace ::osl; +using namespace ::comphelper; +using namespace ::cppu; +using namespace dbaccess; + +DBG_NAME(OResultColumn) +//-------------------------------------------------------------------------- +OResultColumn::OResultColumn( const Reference < XResultSetMetaData >& _xMetaData, sal_Int32 _nPos, + const Reference< XDatabaseMetaData >& _rxDBMeta ) + :OColumn( true ) + ,m_xMetaData( _xMetaData ) + ,m_xDBMetaData( _rxDBMeta ) + ,m_nPos( _nPos ) +{ + DBG_CTOR(OResultColumn,NULL); +} +// ----------------------------------------------------------------------------- +void OResultColumn::impl_determineIsRowVersion_nothrow() +{ + if ( m_aIsRowVersion.hasValue() ) + return; + m_aIsRowVersion <<= (sal_Bool)(sal_False); + + OSL_ENSURE( m_xDBMetaData.is(), "OResultColumn::impl_determineIsRowVersion_nothrow: no DBMetaData!" ); + if ( !m_xDBMetaData.is() ) + return; + + try + { + ::rtl::OUString sCatalog, sSchema, sTable, sColumnName; + getPropertyValue( PROPERTY_CATALOGNAME ) >>= sCatalog; + getPropertyValue( PROPERTY_SCHEMANAME ) >>= sSchema; + getPropertyValue( PROPERTY_TABLENAME ) >>= sTable; + getPropertyValue( PROPERTY_NAME ) >>= sColumnName; + + try + { + Reference< XResultSet > xVersionColumns = m_xDBMetaData->getVersionColumns( + makeAny( sCatalog ), sSchema, sTable ); + if ( xVersionColumns.is() ) // allowed to be NULL + { + Reference< XRow > xResultRow( xVersionColumns, UNO_QUERY_THROW ); + while ( xVersionColumns->next() ) + { + if ( xResultRow->getString( 2 ) == sColumnName ) + { + m_aIsRowVersion <<= (sal_Bool)(sal_True); + break; + } + } + } + } + catch(const SQLException&) + { + } + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } +} +// ----------------------------------------------------------------------------- +OResultColumn::~OResultColumn() +{ + DBG_DTOR(OResultColumn,NULL); +} +// com::sun::star::lang::XTypeProvider +//-------------------------------------------------------------------------- +Sequence< sal_Int8 > OResultColumn::getImplementationId() throw (RuntimeException) +{ + static OImplementationId * pId = 0; + if (! pId) + { + MutexGuard aGuard( Mutex::getGlobalMutex() ); + if (! pId) + { + static OImplementationId aId; + pId = &aId; + } + } + return pId->getImplementationId(); +} + +// XServiceInfo +//------------------------------------------------------------------------------ +rtl::OUString OResultColumn::getImplementationName( ) throw(RuntimeException) +{ + return rtl::OUString::createFromAscii("com.sun.star.sdb.OResultColumn"); +} + +//------------------------------------------------------------------------------ +Sequence< ::rtl::OUString > OResultColumn::getSupportedServiceNames( ) throw (RuntimeException) +{ + Sequence< ::rtl::OUString > aSNS( 2 ); + aSNS[0] = SERVICE_SDBCX_COLUMN; + aSNS[1] = SERVICE_SDB_RESULTCOLUMN; + return aSNS; +} + +// OComponentHelper +//------------------------------------------------------------------------------ +void OResultColumn::disposing() +{ + OColumn::disposing(); + + MutexGuard aGuard(m_aMutex); + m_xMetaData = NULL; +} + +// comphelper::OPropertyArrayUsageHelper +//------------------------------------------------------------------------------ +::cppu::IPropertyArrayHelper* OResultColumn::createArrayHelper( ) const +{ + BEGIN_PROPERTY_HELPER(21) + DECL_PROP1(CATALOGNAME, ::rtl::OUString, READONLY); + DECL_PROP1(DISPLAYSIZE, sal_Int32, READONLY); + DECL_PROP1_BOOL(ISAUTOINCREMENT, READONLY); + DECL_PROP1_BOOL(ISCASESENSITIVE, READONLY); + DECL_PROP1_BOOL(ISCURRENCY, READONLY); + DECL_PROP1_BOOL(ISDEFINITELYWRITABLE, READONLY); + DECL_PROP1(ISNULLABLE, sal_Int32, READONLY); + DECL_PROP1_BOOL(ISREADONLY, READONLY); + DECL_PROP1_BOOL(ISROWVERSION, READONLY); + DECL_PROP1_BOOL(ISSEARCHABLE, READONLY); + DECL_PROP1_BOOL(ISSIGNED, READONLY); + DECL_PROP1_BOOL(ISWRITABLE, READONLY); + DECL_PROP1(LABEL, ::rtl::OUString, READONLY); + DECL_PROP1(NAME, ::rtl::OUString, READONLY); + DECL_PROP1(PRECISION, sal_Int32, READONLY); + DECL_PROP1(SCALE, sal_Int32, READONLY); + DECL_PROP1(SCHEMANAME, ::rtl::OUString, READONLY); + DECL_PROP1(SERVICENAME, ::rtl::OUString, READONLY); + DECL_PROP1(TABLENAME, ::rtl::OUString, READONLY); + DECL_PROP1(TYPE, sal_Int32, READONLY); + DECL_PROP1(TYPENAME, ::rtl::OUString, READONLY); + END_PROPERTY_HELPER(); +} + +// cppu::OPropertySetHelper +//------------------------------------------------------------------------------ +::cppu::IPropertyArrayHelper& OResultColumn::getInfoHelper() +{ + return *static_cast< ::comphelper::OPropertyArrayUsageHelper< OResultColumn >* >(this)->getArrayHelper(); +} + +//------------------------------------------------------------------------------ +namespace +{ + template< typename TYPE > + void obtain( Any& _out_rValue, ::boost::optional< TYPE > _rCache, const sal_Int32 _nPos, const Reference < XResultSetMetaData >& _rxResultMeta, TYPE (SAL_CALL XResultSetMetaData::*Getter)( sal_Int32 ) ) + { + if ( !_rCache ) + _rCache.reset( (_rxResultMeta.get()->*Getter)( _nPos ) ); + _out_rValue <<= *_rCache; + } +} + +//------------------------------------------------------------------------------ +void OResultColumn::getFastPropertyValue( Any& rValue, sal_Int32 nHandle ) const +{ + try + { + if ( OColumn::isRegisteredProperty( nHandle ) ) + { + OColumn::getFastPropertyValue( rValue, nHandle ); + } + else + { + switch (nHandle) + { + case PROPERTY_ID_ISROWVERSION: + const_cast< OResultColumn* >( this )->impl_determineIsRowVersion_nothrow(); + rValue = m_aIsRowVersion; + break; + case PROPERTY_ID_TABLENAME: + rValue <<= m_xMetaData->getTableName(m_nPos); + break; + case PROPERTY_ID_SCHEMANAME: + rValue <<= m_xMetaData->getSchemaName(m_nPos); + break; + case PROPERTY_ID_CATALOGNAME: + rValue <<= m_xMetaData->getCatalogName(m_nPos); + break; + case PROPERTY_ID_ISSIGNED: + obtain( rValue, m_isSigned, m_nPos, m_xMetaData, &XResultSetMetaData::isSigned ); + break; + case PROPERTY_ID_ISCURRENCY: + obtain( rValue, m_isCurrency, m_nPos, m_xMetaData, &XResultSetMetaData::isCurrency ); + break; + case PROPERTY_ID_ISSEARCHABLE: + obtain( rValue, m_bSearchable, m_nPos, m_xMetaData, &XResultSetMetaData::isSearchable ); + break; + case PROPERTY_ID_ISCASESENSITIVE: + obtain( rValue, m_isCaseSensitive, m_nPos, m_xMetaData, &XResultSetMetaData::isCaseSensitive ); + break; + case PROPERTY_ID_ISREADONLY: + obtain( rValue, m_isReadOnly, m_nPos, m_xMetaData, &XResultSetMetaData::isReadOnly ); + break; + case PROPERTY_ID_ISWRITABLE: + obtain( rValue, m_isWritable, m_nPos, m_xMetaData, &XResultSetMetaData::isWritable ); + break; + case PROPERTY_ID_ISDEFINITELYWRITABLE: + obtain( rValue, m_isDefinitelyWritable, m_nPos, m_xMetaData, &XResultSetMetaData::isDefinitelyWritable ); + break; + case PROPERTY_ID_ISAUTOINCREMENT: + obtain( rValue, m_isAutoIncrement, m_nPos, m_xMetaData, &XResultSetMetaData::isAutoIncrement ); + break; + case PROPERTY_ID_SERVICENAME: + rValue <<= m_xMetaData->getColumnServiceName(m_nPos); + break; + case PROPERTY_ID_LABEL: + obtain( rValue, m_sColumnLabel, m_nPos, m_xMetaData, &XResultSetMetaData::getColumnLabel ); + break; + case PROPERTY_ID_DISPLAYSIZE: + obtain( rValue, m_nColumnDisplaySize, m_nPos, m_xMetaData, &XResultSetMetaData::getColumnDisplaySize ); + break; + case PROPERTY_ID_TYPE: + obtain( rValue, m_nColumnType, m_nPos, m_xMetaData, &XResultSetMetaData::getColumnType ); + break; + case PROPERTY_ID_PRECISION: + obtain( rValue, m_nPrecision, m_nPos, m_xMetaData, &XResultSetMetaData::getPrecision ); + break; + case PROPERTY_ID_SCALE: + obtain( rValue, m_nScale, m_nPos, m_xMetaData, &XResultSetMetaData::getScale ); + break; + case PROPERTY_ID_ISNULLABLE: + obtain( rValue, m_isNullable, m_nPos, m_xMetaData, &XResultSetMetaData::isNullable ); + break; + case PROPERTY_ID_TYPENAME: + rValue <<= m_xMetaData->getColumnTypeName(m_nPos); + break; + default: + OSL_ENSURE( false, "OResultColumn::getFastPropertyValue: unknown property handle!" ); + break; + } + } + } + catch (SQLException& ) + { + // default handling if we caught an exception + switch (nHandle) + { + case PROPERTY_ID_LABEL: + case PROPERTY_ID_TYPENAME: + case PROPERTY_ID_SERVICENAME: + case PROPERTY_ID_TABLENAME: + case PROPERTY_ID_SCHEMANAME: + case PROPERTY_ID_CATALOGNAME: + // empty string'S + rValue <<= rtl::OUString(); + break; + case PROPERTY_ID_ISROWVERSION: + case PROPERTY_ID_ISAUTOINCREMENT: + case PROPERTY_ID_ISWRITABLE: + case PROPERTY_ID_ISDEFINITELYWRITABLE: + case PROPERTY_ID_ISCASESENSITIVE: + case PROPERTY_ID_ISSEARCHABLE: + case PROPERTY_ID_ISCURRENCY: + case PROPERTY_ID_ISSIGNED: + { + sal_Bool bVal = sal_False; + rValue.setValue(&bVal, getBooleanCppuType()); + } break; + case PROPERTY_ID_ISREADONLY: + { + sal_Bool bVal = sal_True; + rValue.setValue(&bVal, getBooleanCppuType()); + } break; + case PROPERTY_ID_SCALE: + case PROPERTY_ID_PRECISION: + case PROPERTY_ID_DISPLAYSIZE: + rValue <<= sal_Int32(0); + break; + case PROPERTY_ID_TYPE: + rValue <<= sal_Int32(DataType::SQLNULL); + break; + case PROPERTY_ID_ISNULLABLE: + rValue <<= ColumnValue::NULLABLE_UNKNOWN; + break; + } + } +} + diff --git a/dbaccess/source/core/api/resultcolumn.hxx b/dbaccess/source/core/api/resultcolumn.hxx new file mode 100644 index 000000000000..7e1842241cf6 --- /dev/null +++ b/dbaccess/source/core/api/resultcolumn.hxx @@ -0,0 +1,101 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +#ifndef _DBACORE_RESULTCOLUMN_HXX_ +#define _DBACORE_RESULTCOLUMN_HXX_ + +#ifndef _COM_SUN_STAR_SDBC_XRESULTSETMETADATA_HDL_ +#include <com/sun/star/sdbc/XResultSetMetaData.hdl> +#endif +#ifndef _DBA_COREAPI_COLUMN_HXX_ +#include <column.hxx> +#endif +#include <boost/optional.hpp> +namespace dbaccess +{ + //************************************************************ + // OResultColumn + //************************************************************ + class OResultColumn : public OColumn, + public ::comphelper::OPropertyArrayUsageHelper < OResultColumn > + { + protected: + ::com::sun::star::uno::Reference < ::com::sun::star::sdbc::XResultSetMetaData > m_xMetaData; + ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XDatabaseMetaData > m_xDBMetaData; + sal_Int32 m_nPos; + ::com::sun::star::uno::Any m_aIsRowVersion; + mutable ::boost::optional< sal_Bool > m_isSigned; + mutable ::boost::optional< sal_Bool > m_isCurrency; + mutable ::boost::optional< sal_Bool > m_bSearchable; + mutable ::boost::optional< sal_Bool > m_isCaseSensitive; + mutable ::boost::optional< sal_Bool > m_isReadOnly; + mutable ::boost::optional< sal_Bool > m_isWritable; + mutable ::boost::optional< sal_Bool > m_isDefinitelyWritable; + mutable ::boost::optional< sal_Bool > m_isAutoIncrement; + mutable ::boost::optional< sal_Int32 > m_isNullable; + mutable ::boost::optional< ::rtl::OUString > m_sColumnLabel; + mutable ::boost::optional< sal_Int32 > m_nColumnDisplaySize; + mutable ::boost::optional< sal_Int32 > m_nColumnType; + mutable ::boost::optional< sal_Int32 > m_nPrecision; + mutable ::boost::optional< sal_Int32 > m_nScale; + + virtual ~OResultColumn(); + public: + OResultColumn( + const ::com::sun::star::uno::Reference < ::com::sun::star::sdbc::XResultSetMetaData >& _xMetaData, + sal_Int32 _nPos, + const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XDatabaseMetaData >& _rxDBMeta ); + + // com::sun::star::lang::XTypeProvider + virtual ::com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId() throw (::com::sun::star::uno::RuntimeException); + + // com::sun::star::lang::XServiceInfo + virtual ::rtl::OUString SAL_CALL getImplementationName( ) throw(::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames( ) throw(::com::sun::star::uno::RuntimeException); + + // cppu::OComponentHelper + virtual void SAL_CALL disposing(void); + + // comphelper::OPropertyArrayUsageHelper + virtual ::cppu::IPropertyArrayHelper* createArrayHelper( ) const; + + // cppu::OPropertySetHelper + virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper(); + virtual void SAL_CALL getFastPropertyValue( + ::com::sun::star::uno::Any& rValue, + sal_Int32 nHandle + ) const; + + private: + void impl_determineIsRowVersion_nothrow(); + + protected: + using ::cppu::OPropertySetHelper::getFastPropertyValue; + }; +} +#endif // _DBACORE_RESULTCOLUMN_HXX_ + diff --git a/dbaccess/source/core/api/resultset.cxx b/dbaccess/source/core/api/resultset.cxx new file mode 100644 index 000000000000..0f1be7553ad6 --- /dev/null +++ b/dbaccess/source/core/api/resultset.cxx @@ -0,0 +1,1208 @@ +/************************************************************************* + * + * 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_dbaccess.hxx" +#ifndef _DBA_COREAPI_RESULTSET_HXX_ +#include <resultset.hxx> +#endif +#ifndef DBACCESS_SHARED_DBASTRINGS_HRC +#include "dbastrings.hrc" +#endif +#ifndef _DBASHARED_APITOOLS_HXX_ +#include "apitools.hxx" +#endif +#ifndef _COM_SUN_STAR_LANG_DISPOSEDEXCEPTION_HPP_ +#include <com/sun/star/lang/DisposedException.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_RESULTSETTYPE_HPP_ +#include <com/sun/star/sdbc/ResultSetType.hpp> +#endif +#ifndef _CPPUHELPER_TYPEPROVIDER_HXX_ +#include <cppuhelper/typeprovider.hxx> +#endif +#ifndef _COMPHELPER_PROPERTY_HXX_ +#include <comphelper/property.hxx> +#endif +#ifndef _COMPHELPER_SEQUENCE_HXX_ +#include <comphelper/sequence.hxx> +#endif +#ifndef _COMPHELPER_TYPES_HXX_ +#include <comphelper/types.hxx> +#endif +#ifndef _TOOLS_DEBUG_HXX //autogen +#include <tools/debug.hxx> +#endif +#ifndef TOOLS_DIAGNOSE_EX_H +#include <tools/diagnose_ex.h> +#endif +#ifndef _DBA_COREAPI_DATACOLUMN_HXX_ +#include <datacolumn.hxx> +#endif +#ifndef _COM_SUN_STAR_BEANS_PROPERTYATTRIBUTE_HPP_ +#include <com/sun/star/beans/PropertyAttribute.hpp> +#endif +#ifndef _DBHELPER_DBEXCEPTION_HXX_ +#include <connectivity/dbexception.hxx> +#endif +#ifndef _CONNECTIVITY_DBTOOLS_HXX_ +#include <connectivity/dbtools.hxx> +#endif +#ifndef _CPPUHELPER_EXC_HLP_HXX_ +#include <cppuhelper/exc_hlp.hxx> +#endif +#ifndef _OSL_THREAD_H_ +#include <osl/thread.h> +#endif +#include <rtl/logfile.hxx> + + +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::sdbcx; +//using namespace ::com::sun::star::sdb; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::container; +using namespace ::cppu; +using namespace ::osl; +using namespace dbaccess; +using namespace dbtools; + +DBG_NAME(OResultSet) + +//-------------------------------------------------------------------------- +OResultSet::OResultSet(const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XResultSet >& _xResultSet, + const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& _xStatement, + sal_Bool _bCaseSensitive) + :OResultSetBase(m_aMutex) + ,OPropertySetHelper(OResultSetBase::rBHelper) + ,m_xDelegatorResultSet(_xResultSet) + ,m_aWarnings( Reference< XWarningsSupplier >( _xResultSet, UNO_QUERY ) ) + ,m_bIsBookmarkable(sal_False) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::OResultSet" ); + DBG_CTOR(OResultSet, NULL); + + m_pColumns = new OColumns(*this, m_aMutex, _bCaseSensitive, ::std::vector< ::rtl::OUString>(), NULL,NULL); + + try + { + m_aStatement = _xStatement; + m_xDelegatorResultSetUpdate = m_xDelegatorResultSetUpdate.query( m_xDelegatorResultSet ); + m_xDelegatorRow = m_xDelegatorRow.query( m_xDelegatorResultSet ); + m_xDelegatorRowUpdate = m_xDelegatorRowUpdate.query( m_xDelegatorResultSet ); + + Reference< XPropertySet > xSet(m_xDelegatorResultSet, UNO_QUERY); + xSet->getPropertyValue(PROPERTY_RESULTSETTYPE) >>= m_nResultSetType; + xSet->getPropertyValue(PROPERTY_RESULTSETCONCURRENCY) >>= m_nResultSetConcurrency; + + // test for Bookmarks + if (ResultSetType::FORWARD_ONLY != m_nResultSetType) + { + Reference <XPropertySetInfo > xInfo(xSet->getPropertySetInfo()); + if (xInfo->hasPropertyByName(PROPERTY_ISBOOKMARKABLE)) + { + m_bIsBookmarkable = ::comphelper::getBOOL(xSet->getPropertyValue(PROPERTY_ISBOOKMARKABLE)); + OSL_ENSURE( !m_bIsBookmarkable || Reference< XRowLocate >(m_xDelegatorResultSet, UNO_QUERY).is(), + "OResultSet::OResultSet: aggregate is inconsistent in it's bookmarkable attribute!" ); + m_bIsBookmarkable = m_bIsBookmarkable && Reference< XRowLocate >(m_xDelegatorResultSet, UNO_QUERY).is(); + } + } + } + catch(Exception&) + { + } +} + +//-------------------------------------------------------------------------- +OResultSet::~OResultSet() +{ + m_pColumns->acquire(); + m_pColumns->disposing(); + delete m_pColumns; + + DBG_DTOR(OResultSet, NULL); +} + +// com::sun::star::lang::XTypeProvider +//-------------------------------------------------------------------------- +Sequence< Type > OResultSet::getTypes() throw (RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::getTypes" ); + OTypeCollection aTypes(::getCppuType( (const Reference< XPropertySet > *)0 ), + OResultSetBase::getTypes()); + + return aTypes.getTypes(); +} + +//-------------------------------------------------------------------------- +Sequence< sal_Int8 > OResultSet::getImplementationId() throw (RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::getImplementationId" ); + static OImplementationId * pId = 0; + if (! pId) + { + MutexGuard aGuard( Mutex::getGlobalMutex() ); + if (! pId) + { + static OImplementationId aId; + pId = &aId; + } + } + return pId->getImplementationId(); +} + +// com::sun::star::uno::XInterface +//-------------------------------------------------------------------------- +Any OResultSet::queryInterface( const Type & rType ) throw (RuntimeException) +{ + //RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::queryInterface" ); + Any aIface = OResultSetBase::queryInterface( rType ); + if (!aIface.hasValue()) + aIface = ::cppu::queryInterface( + rType, + static_cast< XPropertySet * >( this )); + + return aIface; +} + +//-------------------------------------------------------------------------- +void OResultSet::acquire() throw () +{ + OResultSetBase::acquire(); +} + +//-------------------------------------------------------------------------- +void OResultSet::release() throw () +{ + OResultSetBase::release(); +} + + +// OResultSetBase +//------------------------------------------------------------------------------ +void OResultSet::disposing() +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::disposing" ); + OPropertySetHelper::disposing(); + + MutexGuard aGuard(m_aMutex); + + // free the columns + m_pColumns->disposing(); + + // close the pending result set + Reference< XCloseable > (m_xDelegatorResultSet, UNO_QUERY)->close(); + + m_xDelegatorResultSet = NULL; + m_xDelegatorRow = NULL; + m_xDelegatorRowUpdate = NULL; + + m_aStatement = Reference< XInterface >(); +} + +// XCloseable +//------------------------------------------------------------------------------ +void OResultSet::close(void) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::close" ); + { + MutexGuard aGuard( m_aMutex ); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + } + dispose(); +} + +// XServiceInfo +//------------------------------------------------------------------------------ +rtl::OUString OResultSet::getImplementationName( ) throw(RuntimeException) +{ + //RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::getImplementationName" ); + return rtl::OUString::createFromAscii("com.sun.star.sdb.OResultSet"); +} + +//------------------------------------------------------------------------------ +sal_Bool OResultSet::supportsService( const ::rtl::OUString& _rServiceName ) throw (RuntimeException) +{ + //RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::supportsService" ); + return ::comphelper::findValue(getSupportedServiceNames(), _rServiceName, sal_True).getLength() != 0; +} + +//------------------------------------------------------------------------------ +Sequence< ::rtl::OUString > OResultSet::getSupportedServiceNames( ) throw (RuntimeException) +{ + //RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::getSupportedServiceNames" ); + Sequence< ::rtl::OUString > aSNS( 2 ); + aSNS[0] = SERVICE_SDBC_RESULTSET; + aSNS[1] = SERVICE_SDB_RESULTSET; + return aSNS; +} + +// com::sun::star::beans::XPropertySet +//------------------------------------------------------------------------------ +Reference< XPropertySetInfo > OResultSet::getPropertySetInfo() throw (RuntimeException) +{ + //RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::getPropertySetInfo" ); + return createPropertySetInfo( getInfoHelper() ) ; +} + +// comphelper::OPropertyArrayUsageHelper +//------------------------------------------------------------------------------ +::cppu::IPropertyArrayHelper* OResultSet::createArrayHelper( ) const +{ + //RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::createArrayHelper" ); + BEGIN_PROPERTY_HELPER(6) + DECL_PROP1(CURSORNAME, ::rtl::OUString, READONLY); + DECL_PROP0(FETCHDIRECTION, sal_Int32); + DECL_PROP0(FETCHSIZE, sal_Int32); + DECL_PROP1_BOOL(ISBOOKMARKABLE, READONLY); + DECL_PROP1(RESULTSETCONCURRENCY, sal_Int32, READONLY); + DECL_PROP1(RESULTSETTYPE, sal_Int32, READONLY); + END_PROPERTY_HELPER(); +} + +// cppu::OPropertySetHelper +//------------------------------------------------------------------------------ +::cppu::IPropertyArrayHelper& OResultSet::getInfoHelper() +{ + //RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::getInfoHelper" ); + return *getArrayHelper(); +} + +//------------------------------------------------------------------------------ +sal_Bool OResultSet::convertFastPropertyValue(Any & rConvertedValue, Any & rOldValue, sal_Int32 nHandle, const Any& rValue ) throw( IllegalArgumentException ) +{ + //RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::convertFastPropertyValue" ); + // be lazy ... + rConvertedValue = rValue; + getFastPropertyValue( rOldValue, nHandle ); + return sal_True; +} + +//------------------------------------------------------------------------------ +void OResultSet::setFastPropertyValue_NoBroadcast( sal_Int32 nHandle, const Any& rValue ) throw (Exception) +{ + //RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::setFastPropertyValue_NoBroadcast" ); + // set it for the driver result set + Reference< XPropertySet > xSet(m_xDelegatorResultSet, UNO_QUERY); + switch (nHandle) + { + case PROPERTY_ID_FETCHDIRECTION: + xSet->setPropertyValue(PROPERTY_FETCHDIRECTION, rValue); + break; + case PROPERTY_ID_FETCHSIZE: + xSet->setPropertyValue(PROPERTY_FETCHSIZE, rValue); + break; + default: + DBG_ERROR("unknown Property"); + } +} + +//------------------------------------------------------------------------------ +void OResultSet::getFastPropertyValue( Any& rValue, sal_Int32 nHandle ) const +{ + //RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::getFastPropertyValue" ); + switch (nHandle) + { + case PROPERTY_ID_ISBOOKMARKABLE: + { + sal_Bool bVal = m_bIsBookmarkable; + rValue.setValue(&bVal, getBooleanCppuType()); + } break; + default: + { + // get the property name + ::rtl::OUString aPropName; + sal_Int16 nAttributes; + const_cast<OResultSet*>(this)->getInfoHelper(). + fillPropertyMembersByHandle(&aPropName, &nAttributes, nHandle); + OSL_ENSURE(aPropName.getLength(), "property not found?"); + + // now read the value + rValue = Reference< XPropertySet >(m_xDelegatorResultSet, UNO_QUERY)->getPropertyValue(aPropName); + } + } +} + +// XWarningsSupplier +//------------------------------------------------------------------------------ +Any OResultSet::getWarnings(void) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::getWarnings" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + return m_aWarnings.getWarnings(); +} + +//------------------------------------------------------------------------------ +void OResultSet::clearWarnings(void) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::clearWarnings" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + m_aWarnings.clearWarnings(); +} + +// ::com::sun::star::sdbc::XResultSetMetaDataSupplier +//------------------------------------------------------------------------------ +Reference< XResultSetMetaData > OResultSet::getMetaData(void) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::getMetaData" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + return Reference< XResultSetMetaDataSupplier >(m_xDelegatorResultSet, UNO_QUERY)->getMetaData(); +} + +// ::com::sun::star::sdbc::XColumnLocate +//------------------------------------------------------------------------------ +sal_Int32 OResultSet::findColumn(const rtl::OUString& columnName) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::findColumn" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + return Reference< XColumnLocate >(m_xDelegatorResultSet, UNO_QUERY)->findColumn(columnName); +} + +//------------------------------------------------------------------------------ +namespace +{ + static Reference< XDatabaseMetaData > lcl_getDBMetaDataFromStatement_nothrow( const Reference< XInterface >& _rxStatement ) + { + Reference< XDatabaseMetaData > xDBMetaData; + try + { + Reference< XStatement > xStatement( _rxStatement, UNO_QUERY ); + Reference< XPreparedStatement > xPreparedStatement( _rxStatement, UNO_QUERY ); + Reference< XConnection > xConn; + if ( xStatement.is() ) + xConn = xStatement->getConnection(); + else if ( xPreparedStatement.is() ) + xConn = xPreparedStatement->getConnection(); + if ( xConn.is() ) + xDBMetaData = xConn->getMetaData(); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + return xDBMetaData; + } +} +// ::com::sun::star::sdbcx::XColumnsSupplier +//------------------------------------------------------------------------------ +Reference< ::com::sun::star::container::XNameAccess > OResultSet::getColumns(void) throw( RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::getColumns" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + // do we have to populate the columns + if (!m_pColumns->isInitialized()) + { + // get the metadata + Reference< XResultSetMetaData > xMetaData = Reference< XResultSetMetaDataSupplier >(m_xDelegatorResultSet, UNO_QUERY)->getMetaData(); + + sal_Int32 nColCount = 0; + // do we have columns + try + { + Reference< XDatabaseMetaData > xDBMetaData( lcl_getDBMetaDataFromStatement_nothrow( getStatement() ) ); + nColCount = xMetaData->getColumnCount(); + + for ( sal_Int32 i = 0; i < nColCount; ++i) + { + // retrieve the name of the column + rtl::OUString sName = xMetaData->getColumnName(i + 1); + ODataColumn* pColumn = new ODataColumn(xMetaData, m_xDelegatorRow, m_xDelegatorRowUpdate, i + 1, xDBMetaData); + + // don't silently assume that the name is unique - result set implementations + // are allowed to return duplicate names, but we are required to have + // unique column names + if ( m_pColumns->hasByName( sName ) ) + sName = ::dbtools::createUniqueName( m_pColumns, sName ); + + m_pColumns->append( sName, pColumn ); + } + } + catch ( const SQLException& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + m_pColumns->setInitialized(); + + #if OSL_DEBUG_LEVEL > 0 + // some sanity checks. Especially in case we auto-adjusted the column names above, + // this might be reasonable + try + { + const Reference< XNameAccess > xColNames( static_cast< XNameAccess* >( m_pColumns ), UNO_SET_THROW ); + const Sequence< ::rtl::OUString > aNames( xColNames->getElementNames() ); + OSL_POSTCOND( aNames.getLength() == nColCount, + "OResultSet::getColumns: invalid column count!" ); + for ( const ::rtl::OUString* pName = aNames.getConstArray(); + pName != aNames.getConstArray() + aNames.getLength(); + ++pName + ) + { + Reference< XPropertySet > xColProps( xColNames->getByName( *pName ), UNO_QUERY_THROW ); + ::rtl::OUString sName; + OSL_VERIFY( xColProps->getPropertyValue( PROPERTY_NAME ) >>= sName ); + OSL_POSTCOND( sName == *pName, "OResultSet::getColumns: invalid column name!" ); + } + + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + #endif + } + return m_pColumns; +} + +// ::com::sun::star::sdbc::XRow +//------------------------------------------------------------------------------ +sal_Bool OResultSet::wasNull(void) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::wasNull" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + return m_xDelegatorRow->wasNull(); +} +//------------------------------------------------------------------------------ +rtl::OUString OResultSet::getString(sal_Int32 columnIndex) throw( SQLException, RuntimeException ) +{ + //RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::getString" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + return m_xDelegatorRow->getString(columnIndex); +} +//------------------------------------------------------------------------------ +sal_Bool OResultSet::getBoolean(sal_Int32 columnIndex) throw( SQLException, RuntimeException ) +{ + //RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::getBoolean" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + return m_xDelegatorRow->getBoolean(columnIndex); +} +//------------------------------------------------------------------------------ +sal_Int8 OResultSet::getByte(sal_Int32 columnIndex) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::getByte" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + return m_xDelegatorRow->getByte(columnIndex); +} +//------------------------------------------------------------------------------ +sal_Int16 OResultSet::getShort(sal_Int32 columnIndex) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::getShort" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + return m_xDelegatorRow->getShort(columnIndex); +} +//------------------------------------------------------------------------------ +sal_Int32 OResultSet::getInt(sal_Int32 columnIndex) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::getInt" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + return m_xDelegatorRow->getInt(columnIndex); +} +//------------------------------------------------------------------------------ +sal_Int64 OResultSet::getLong(sal_Int32 columnIndex) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::getLong" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + return m_xDelegatorRow->getLong(columnIndex); +} +//------------------------------------------------------------------------------ +float OResultSet::getFloat(sal_Int32 columnIndex) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::getFloat" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + return m_xDelegatorRow->getFloat(columnIndex); +} +//------------------------------------------------------------------------------ +double OResultSet::getDouble(sal_Int32 columnIndex) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::getDouble" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + return m_xDelegatorRow->getDouble(columnIndex); +} +//------------------------------------------------------------------------------ +Sequence< sal_Int8 > OResultSet::getBytes(sal_Int32 columnIndex) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::getBytes" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + return m_xDelegatorRow->getBytes(columnIndex); +} +//------------------------------------------------------------------------------ +::com::sun::star::util::Date OResultSet::getDate(sal_Int32 columnIndex) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::getDate" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + return m_xDelegatorRow->getDate(columnIndex); +} +//------------------------------------------------------------------------------ +::com::sun::star::util::Time OResultSet::getTime(sal_Int32 columnIndex) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::getTime" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + return m_xDelegatorRow->getTime(columnIndex); +} +//------------------------------------------------------------------------------ +::com::sun::star::util::DateTime OResultSet::getTimestamp(sal_Int32 columnIndex) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::getTimestamp" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + return m_xDelegatorRow->getTimestamp(columnIndex); +} +//------------------------------------------------------------------------------ +Reference< ::com::sun::star::io::XInputStream > OResultSet::getBinaryStream(sal_Int32 columnIndex) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::getBinaryStream" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + return m_xDelegatorRow->getBinaryStream(columnIndex); +} +//------------------------------------------------------------------------------ +Reference< ::com::sun::star::io::XInputStream > OResultSet::getCharacterStream(sal_Int32 columnIndex) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::getCharacterStream" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + return m_xDelegatorRow->getCharacterStream(columnIndex); +} +//------------------------------------------------------------------------------ +Any OResultSet::getObject(sal_Int32 columnIndex, const Reference< ::com::sun::star::container::XNameAccess > & typeMap) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::getObject" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + return m_xDelegatorRow->getObject(columnIndex, typeMap); +} +//------------------------------------------------------------------------------ +Reference< XRef > OResultSet::getRef(sal_Int32 columnIndex) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::getRef" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + return m_xDelegatorRow->getRef(columnIndex); +} +//------------------------------------------------------------------------------ +Reference< XBlob > OResultSet::getBlob(sal_Int32 columnIndex) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::getBlob" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + return m_xDelegatorRow->getBlob(columnIndex); +} +//------------------------------------------------------------------------------ +Reference< XClob > OResultSet::getClob(sal_Int32 columnIndex) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::getClob" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + return m_xDelegatorRow->getClob(columnIndex); +} +//------------------------------------------------------------------------------ +Reference< XArray > OResultSet::getArray(sal_Int32 columnIndex) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::getArray" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + return m_xDelegatorRow->getArray(columnIndex); +} + +// ::com::sun::star::sdbc::XRowUpdate +//------------------------------------------------------------------------------ +void OResultSet::updateNull(sal_Int32 columnIndex) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::updateNull" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + checkReadOnly(); + + m_xDelegatorRowUpdate->updateNull(columnIndex); +} + +//------------------------------------------------------------------------------ +void OResultSet::updateBoolean(sal_Int32 columnIndex, sal_Bool x) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::updateBoolean" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + checkReadOnly(); + + m_xDelegatorRowUpdate->updateBoolean(columnIndex, x); +} +//------------------------------------------------------------------------------ +void OResultSet::updateByte(sal_Int32 columnIndex, sal_Int8 x) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::updateByte" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + checkReadOnly(); + + m_xDelegatorRowUpdate->updateByte(columnIndex, x); +} +//------------------------------------------------------------------------------ +void OResultSet::updateShort(sal_Int32 columnIndex, sal_Int16 x) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::updateShort" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + checkReadOnly(); + + m_xDelegatorRowUpdate->updateShort(columnIndex, x); +} +//------------------------------------------------------------------------------ +void OResultSet::updateInt(sal_Int32 columnIndex, sal_Int32 x) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::updateInt" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + checkReadOnly(); + + m_xDelegatorRowUpdate->updateInt(columnIndex, x); +} +//------------------------------------------------------------------------------ +void OResultSet::updateLong(sal_Int32 columnIndex, sal_Int64 x) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::updateLong" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + checkReadOnly(); + + m_xDelegatorRowUpdate->updateLong(columnIndex, x); +} +//------------------------------------------------------------------------------ +void OResultSet::updateFloat(sal_Int32 columnIndex, float x) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::updateFloat" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + checkReadOnly(); + + m_xDelegatorRowUpdate->updateFloat(columnIndex, x); +} +//------------------------------------------------------------------------------ +void OResultSet::updateDouble(sal_Int32 columnIndex, double x) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::updateDouble" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + checkReadOnly(); + + m_xDelegatorRowUpdate->updateDouble(columnIndex, x); +} +//------------------------------------------------------------------------------ +void OResultSet::updateString(sal_Int32 columnIndex, const rtl::OUString& x) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::updateString" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + checkReadOnly(); + + m_xDelegatorRowUpdate->updateString(columnIndex, x); +} +//------------------------------------------------------------------------------ +void OResultSet::updateBytes(sal_Int32 columnIndex, const Sequence< sal_Int8 >& x) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::updateBytes" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + checkReadOnly(); + + m_xDelegatorRowUpdate->updateBytes(columnIndex, x); +} +//------------------------------------------------------------------------------ +void OResultSet::updateDate(sal_Int32 columnIndex, const ::com::sun::star::util::Date& x) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::updateDate" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + checkReadOnly(); + + m_xDelegatorRowUpdate->updateDate(columnIndex, x); +} +//------------------------------------------------------------------------------ +void OResultSet::updateTime(sal_Int32 columnIndex, const ::com::sun::star::util::Time& x) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::updateTime" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + checkReadOnly(); + + m_xDelegatorRowUpdate->updateTime(columnIndex, x); +} +//------------------------------------------------------------------------------ +void OResultSet::updateTimestamp(sal_Int32 columnIndex, const ::com::sun::star::util::DateTime& x) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::updateTimestamp" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + checkReadOnly(); + + m_xDelegatorRowUpdate->updateTimestamp(columnIndex, x); +} +//------------------------------------------------------------------------------ +void OResultSet::updateBinaryStream(sal_Int32 columnIndex, const Reference< ::com::sun::star::io::XInputStream > & x, sal_Int32 length) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::updateBinaryStream" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + checkReadOnly(); + + m_xDelegatorRowUpdate->updateBinaryStream(columnIndex, x, length); +} +//------------------------------------------------------------------------------ +void OResultSet::updateCharacterStream(sal_Int32 columnIndex, const Reference< ::com::sun::star::io::XInputStream > & x, sal_Int32 length) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::updateCharacterStream" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + checkReadOnly(); + + m_xDelegatorRowUpdate->updateCharacterStream(columnIndex, x, length); +} +//------------------------------------------------------------------------------ +void OResultSet::updateNumericObject(sal_Int32 columnIndex, const Any& x, sal_Int32 scale) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::updateNumericObject" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + checkReadOnly(); + + m_xDelegatorRowUpdate->updateNumericObject(columnIndex, x, scale); +} + +//------------------------------------------------------------------------------ +void OResultSet::updateObject(sal_Int32 columnIndex, const Any& x) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::updateObject" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + checkReadOnly(); + + m_xDelegatorRowUpdate->updateObject(columnIndex, x); +} + +// ::com::sun::star::sdbc::XResultSet +//------------------------------------------------------------------------------ +sal_Bool OResultSet::next(void) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::next" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + return m_xDelegatorResultSet->next(); +} + +//------------------------------------------------------------------------------ +sal_Bool OResultSet::isBeforeFirst(void) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::isBeforeFirst" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + return m_xDelegatorResultSet->isBeforeFirst(); +} + +//------------------------------------------------------------------------------ +sal_Bool OResultSet::isAfterLast(void) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::isAfterLast" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + return m_xDelegatorResultSet->isAfterLast(); +} + +//------------------------------------------------------------------------------ +sal_Bool OResultSet::isFirst(void) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::isFirst" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + return m_xDelegatorResultSet->isFirst(); +} + +//------------------------------------------------------------------------------ +sal_Bool OResultSet::isLast(void) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::isLast" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + return m_xDelegatorResultSet->isLast(); +} + +//------------------------------------------------------------------------------ +void OResultSet::beforeFirst(void) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::beforeFirst" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + m_xDelegatorResultSet->beforeFirst(); +} + +//------------------------------------------------------------------------------ +void OResultSet::afterLast(void) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::afterLast" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + m_xDelegatorResultSet->afterLast(); +} + +//------------------------------------------------------------------------------ +sal_Bool OResultSet::first(void) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::first" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + return m_xDelegatorResultSet->first(); +} + +//------------------------------------------------------------------------------ +sal_Bool OResultSet::last(void) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::last" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + return m_xDelegatorResultSet->last(); +} + +//------------------------------------------------------------------------------ +sal_Int32 OResultSet::getRow(void) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::getRow" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + return m_xDelegatorResultSet->getRow(); +} + +//------------------------------------------------------------------------------ +sal_Bool OResultSet::absolute(sal_Int32 row) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::absolute" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + return m_xDelegatorResultSet->absolute(row); +} + +//------------------------------------------------------------------------------ +sal_Bool OResultSet::relative(sal_Int32 rows) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::relative" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + return m_xDelegatorResultSet->relative(rows); +} + +//------------------------------------------------------------------------------ +sal_Bool OResultSet::previous(void) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::previous" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + return m_xDelegatorResultSet->previous(); +} + +//------------------------------------------------------------------------------ +void OResultSet::refreshRow(void) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::refreshRow" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + m_xDelegatorResultSet->refreshRow(); +} + +//------------------------------------------------------------------------------ +sal_Bool OResultSet::rowUpdated(void) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::rowUpdated" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + return m_xDelegatorResultSet->rowUpdated(); +} + +//------------------------------------------------------------------------------ +sal_Bool OResultSet::rowInserted(void) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::rowInserted" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + return m_xDelegatorResultSet->rowInserted(); +} + +//------------------------------------------------------------------------------ +sal_Bool OResultSet::rowDeleted(void) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::rowDeleted" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + return m_xDelegatorResultSet->rowDeleted(); +} + +//------------------------------------------------------------------------------ +Reference< XInterface > OResultSet::getStatement(void) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::getStatement" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + return m_aStatement; +} + +// ::com::sun::star::sdbcx::XRowLocate +//------------------------------------------------------------------------------ +Any OResultSet::getBookmark(void) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::getBookmark" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + checkBookmarkable(); + + return Reference< XRowLocate >(m_xDelegatorResultSet, UNO_QUERY)->getBookmark(); +} + +//------------------------------------------------------------------------------ +sal_Bool OResultSet::moveToBookmark(const Any& bookmark) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::moveToBookmark" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + checkBookmarkable(); + + return Reference< XRowLocate >(m_xDelegatorResultSet, UNO_QUERY)->moveToBookmark(bookmark); +} + +//------------------------------------------------------------------------------ +sal_Bool OResultSet::moveRelativeToBookmark(const Any& bookmark, sal_Int32 rows) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::moveRelativeToBookmark" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + checkBookmarkable(); + + return Reference< XRowLocate >(m_xDelegatorResultSet, UNO_QUERY)->moveRelativeToBookmark(bookmark, rows); +} + +//------------------------------------------------------------------------------ +sal_Int32 OResultSet::compareBookmarks(const Any& _first, const Any& _second) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::compareBookmarks" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + checkBookmarkable(); + + return Reference< XRowLocate >(m_xDelegatorResultSet, UNO_QUERY)->compareBookmarks(_first, _second); +} + +//------------------------------------------------------------------------------ +sal_Bool OResultSet::hasOrderedBookmarks(void) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::hasOrderedBookmarks" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + checkBookmarkable(); + + return Reference< XRowLocate >(m_xDelegatorResultSet, UNO_QUERY)->hasOrderedBookmarks(); +} + +//------------------------------------------------------------------------------ +sal_Int32 OResultSet::hashBookmark(const Any& bookmark) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::hashBookmark" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + checkBookmarkable(); + + return Reference< XRowLocate >(m_xDelegatorResultSet, UNO_QUERY)->hashBookmark(bookmark); +} + +// ::com::sun::star::sdbc::XResultSetUpdate +//------------------------------------------------------------------------------ +void OResultSet::insertRow(void) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::insertRow" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + checkReadOnly(); + + m_xDelegatorResultSetUpdate->insertRow(); +} + +//------------------------------------------------------------------------------ +void OResultSet::updateRow(void) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::updateRow" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + checkReadOnly(); + + m_xDelegatorResultSetUpdate->updateRow(); +} + +//------------------------------------------------------------------------------ +void OResultSet::deleteRow(void) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::deleteRow" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + checkReadOnly(); + + m_xDelegatorResultSetUpdate->deleteRow(); +} + +//------------------------------------------------------------------------------ +void OResultSet::cancelRowUpdates(void) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::cancelRowUpdates" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + checkReadOnly(); + + m_xDelegatorResultSetUpdate->cancelRowUpdates(); +} + +//------------------------------------------------------------------------------ +void OResultSet::moveToInsertRow(void) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::moveToInsertRow" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + checkReadOnly(); + + m_xDelegatorResultSetUpdate->moveToInsertRow(); +} + +//------------------------------------------------------------------------------ +void OResultSet::moveToCurrentRow(void) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::moveToCurrentRow" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OResultSetBase::rBHelper.bDisposed); + + checkReadOnly(); + + m_xDelegatorResultSetUpdate->moveToCurrentRow(); +} + +// ----------------------------------------------------------------------------- +void OResultSet::checkReadOnly() const +{ + //RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::checkReadOnly" ); + if ( ( m_nResultSetConcurrency == ResultSetConcurrency::READ_ONLY ) + || !m_xDelegatorResultSetUpdate.is() + ) + throwSQLException( "The result set is read-only.", SQL_GENERAL_ERROR, *const_cast< OResultSet* >( this ) ); +} + +// ----------------------------------------------------------------------------- +void OResultSet::checkBookmarkable() const +{ + //RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OResultSet::checkBookmarkable" ); + if ( !m_bIsBookmarkable ) + throwSQLException( "The result set does not have bookmark support.", SQL_GENERAL_ERROR, *const_cast< OResultSet* >( this ) ); +} +// ----------------------------------------------------------------------------- + diff --git a/dbaccess/source/core/api/resultset.hxx b/dbaccess/source/core/api/resultset.hxx new file mode 100644 index 000000000000..cc765919c313 --- /dev/null +++ b/dbaccess/source/core/api/resultset.hxx @@ -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. + * + ************************************************************************/ +#ifndef _DBA_COREAPI_RESULTSET_HXX_ +#define _DBA_COREAPI_RESULTSET_HXX_ + +#ifndef _DBA_COREAPI_COLUMN_HXX_ +#include "column.hxx" +#endif +#ifndef DBTOOLS_WARNINGSCONTAINER_HXX +#include <connectivity/warningscontainer.hxx> +#endif + +#ifndef _COM_SUN_STAR_LANG_XSERVICEINFO_HPP_ +#include <com/sun/star/lang/XServiceInfo.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_XSTATEMENT_HPP_ +#include <com/sun/star/sdbc/XStatement.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_XCLOSEABLE_HPP_ +#include <com/sun/star/sdbc/XCloseable.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_XRESULTSETMETADATASUPPLIER_HPP_ +#include <com/sun/star/sdbc/XResultSetMetaDataSupplier.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_XWARNINGSSUPPLIER_HPP_ +#include <com/sun/star/sdbc/XWarningsSupplier.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBCX_XCOLUMNSSUPPLIER_HPP_ +#include <com/sun/star/sdbcx/XColumnsSupplier.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_XRESULTSET_HPP_ +#include <com/sun/star/sdbc/XResultSet.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_XROW_HPP_ +#include <com/sun/star/sdbc/XRow.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_XCOLUMNLOCATE_HPP_ +#include <com/sun/star/sdbc/XColumnLocate.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBCX_XROWLOCATE_HPP_ +#include <com/sun/star/sdbcx/XRowLocate.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_XROWUPDATE_HPP_ +#include <com/sun/star/sdbc/XRowUpdate.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_XRESULTSETUPDATE_HPP_ +#include <com/sun/star/sdbc/XResultSetUpdate.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_RESULTSETCONCURRENCY_HPP_ +#include <com/sun/star/sdbc/ResultSetConcurrency.hpp> +#endif + +#ifndef _CPPUHELPER_PROPSHLP_HXX +#include <cppuhelper/propshlp.hxx> +#endif +#ifndef _COMPHELPER_PROPERTY_ARRAY_HELPER_HXX_ +#include <comphelper/proparrhlp.hxx> +#endif +#ifndef _OSL_DIAGNOSE_H_ +#include <osl/diagnose.h> +#endif +#ifndef _CPPUHELPER_COMPBASE11_HXX_ +#include <cppuhelper/compbase11.hxx> +#endif +#ifndef _COMPHELPER_BROADCASTHELPER_HXX_ +#include <comphelper/broadcasthelper.hxx> +#endif + +namespace dbaccess +{ + typedef ::cppu::WeakComponentImplHelper11< ::com::sun::star::sdbc::XWarningsSupplier, + ::com::sun::star::sdbc::XResultSet, + ::com::sun::star::sdbc::XResultSetMetaDataSupplier, + ::com::sun::star::sdbc::XRow, + ::com::sun::star::sdbc::XCloseable, + ::com::sun::star::sdbc::XColumnLocate, + ::com::sun::star::sdbcx::XRowLocate, + ::com::sun::star::sdbcx::XColumnsSupplier, + ::com::sun::star::sdbc::XResultSetUpdate, + ::com::sun::star::sdbc::XRowUpdate, + ::com::sun::star::lang::XServiceInfo > OResultSetBase; + + typedef ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface> ONoWeakStatement; + + //************************************************************ + // OResultSet + //************************************************************ + class OResultSet : public comphelper::OBaseMutex, + public OResultSetBase, + public ::cppu::OPropertySetHelper, + public ::comphelper::OPropertyArrayUsageHelper < OResultSet > + { + protected: + ONoWeakStatement m_aStatement; + + ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XResultSet > m_xDelegatorResultSet; + ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XResultSetUpdate > m_xDelegatorResultSetUpdate; + ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRow > m_xDelegatorRow; + ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRowUpdate > m_xDelegatorRowUpdate; + + ::dbtools::WarningsContainer m_aWarnings; + OColumns* m_pColumns; + sal_Int32 m_nResultSetType; + sal_Int32 m_nResultSetConcurrency; + sal_Bool m_bIsBookmarkable : 1; + + public: + OResultSet(const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XResultSet >& _xResultSet, + const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& _xStatement, + sal_Bool _bCaseSensitive); + virtual ~OResultSet(); + + // ::com::sun::star::lang::XTypeProvider + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type > SAL_CALL getTypes() throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId() throw (::com::sun::star::uno::RuntimeException); + + // ::com::sun::star::uno::XInterface + virtual ::com::sun::star::uno::Any SAL_CALL queryInterface( const ::com::sun::star::uno::Type & rType ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL acquire() throw(); + virtual void SAL_CALL release() throw(); + + // ::com::sun::star::lang::XServiceInfo + virtual ::rtl::OUString SAL_CALL getImplementationName( ) throw(::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) throw(::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames( ) throw(::com::sun::star::uno::RuntimeException); + + // ::cppu::OComponentHelper + virtual void SAL_CALL disposing(void); + + // ::com::sun::star::sdbc::XCloseable + virtual void SAL_CALL close( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + + // com::sun::star::beans::XPropertySet + virtual ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo( ) throw(::com::sun::star::uno::RuntimeException); + + // comphelper::OPropertyArrayUsageHelper + virtual ::cppu::IPropertyArrayHelper* createArrayHelper( ) const; + + // cppu::OPropertySetHelper + virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper(); + + virtual sal_Bool SAL_CALL convertFastPropertyValue( + ::com::sun::star::uno::Any & rConvertedValue, + ::com::sun::star::uno::Any & rOldValue, + sal_Int32 nHandle, + const ::com::sun::star::uno::Any& rValue ) + throw (::com::sun::star::lang::IllegalArgumentException); + virtual void SAL_CALL setFastPropertyValue_NoBroadcast( + sal_Int32 nHandle, + const ::com::sun::star::uno::Any& rValue + ) + throw (::com::sun::star::uno::Exception); + virtual void SAL_CALL getFastPropertyValue( ::com::sun::star::uno::Any& rValue, sal_Int32 nHandle ) const; + + // ::com::sun::star::sdbc::XWarningsSupplier + virtual ::com::sun::star::uno::Any SAL_CALL getWarnings( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL clearWarnings( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + + // ::com::sun::star::sdbc::XResultSetMetaDataSupplier + virtual ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XResultSetMetaData > SAL_CALL getMetaData( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + + // ::com::sun::star::sdbc::XColumnLocate + virtual sal_Int32 SAL_CALL findColumn( const ::rtl::OUString& columnName ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + + // ::com::sun::star::sdbcx::XColumnsSupplier + virtual ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess > SAL_CALL getColumns( ) throw(::com::sun::star::uno::RuntimeException); + + // ::com::sun::star::sdbc::XRow + virtual sal_Bool SAL_CALL wasNull( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getString( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL getBoolean( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Int8 SAL_CALL getByte( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Int16 SAL_CALL getShort( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Int32 SAL_CALL getInt( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Int64 SAL_CALL getLong( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual float SAL_CALL getFloat( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual double SAL_CALL getDouble( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL getBytes( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::util::Date SAL_CALL getDate( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::util::Time SAL_CALL getTime( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::util::DateTime SAL_CALL getTimestamp( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > SAL_CALL getBinaryStream( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > SAL_CALL getCharacterStream( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Any SAL_CALL getObject( sal_Int32 columnIndex, const ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess >& typeMap ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRef > SAL_CALL getRef( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XBlob > SAL_CALL getBlob( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XClob > SAL_CALL getClob( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XArray > SAL_CALL getArray( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + + // ::com::sun::star::sdbc::XResultSet + virtual sal_Bool SAL_CALL next( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL isBeforeFirst( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL isAfterLast( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL isFirst( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL isLast( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL beforeFirst( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL afterLast( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL first( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL last( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Int32 SAL_CALL getRow( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL absolute( sal_Int32 row ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL relative( sal_Int32 rows ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL previous( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL refreshRow( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL rowUpdated( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL rowInserted( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL rowDeleted( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL getStatement( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + + // ::com::sun::star::sdbcx::XRowLocate + virtual ::com::sun::star::uno::Any SAL_CALL getBookmark( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL moveToBookmark( const ::com::sun::star::uno::Any& bookmark ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL moveRelativeToBookmark( const ::com::sun::star::uno::Any& bookmark, sal_Int32 rows ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Int32 SAL_CALL compareBookmarks( const ::com::sun::star::uno::Any& first, const ::com::sun::star::uno::Any& second ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL hasOrderedBookmarks( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual sal_Int32 SAL_CALL hashBookmark( const ::com::sun::star::uno::Any& bookmark ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + + // ::com::sun::star::sdbc::XResultSetUpdate + virtual void SAL_CALL insertRow( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL updateRow( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL deleteRow( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL cancelRowUpdates( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL moveToInsertRow( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL moveToCurrentRow( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + + // ::com::sun::star::sdbc::XRowUpdate + virtual void SAL_CALL updateNull( sal_Int32 columnIndex ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL updateBoolean( sal_Int32 columnIndex, sal_Bool x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL updateByte( sal_Int32 columnIndex, sal_Int8 x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL updateShort( sal_Int32 columnIndex, sal_Int16 x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL updateInt( sal_Int32 columnIndex, sal_Int32 x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL updateLong( sal_Int32 columnIndex, sal_Int64 x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL updateFloat( sal_Int32 columnIndex, float x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL updateDouble( sal_Int32 columnIndex, double x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL updateString( sal_Int32 columnIndex, const ::rtl::OUString& x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL updateBytes( sal_Int32 columnIndex, const ::com::sun::star::uno::Sequence< sal_Int8 >& x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL updateDate( sal_Int32 columnIndex, const ::com::sun::star::util::Date& x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL updateTime( sal_Int32 columnIndex, const ::com::sun::star::util::Time& x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL updateTimestamp( sal_Int32 columnIndex, const ::com::sun::star::util::DateTime& x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL updateBinaryStream( sal_Int32 columnIndex, const ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream >& x, sal_Int32 length ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL updateCharacterStream( sal_Int32 columnIndex, const ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream >& x, sal_Int32 length ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL updateObject( sal_Int32 columnIndex, const ::com::sun::star::uno::Any& x ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL updateNumericObject( sal_Int32 columnIndex, const ::com::sun::star::uno::Any& x, sal_Int32 scale ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + + protected: + void checkReadOnly() const; + void checkBookmarkable() const; + + private: + using ::cppu::OPropertySetHelper::getFastPropertyValue; + }; +} +#endif // _DBA_COREAPI_RESULTSET_HXX_ + diff --git a/dbaccess/source/core/api/statement.cxx b/dbaccess/source/core/api/statement.cxx new file mode 100644 index 000000000000..05ef557f2582 --- /dev/null +++ b/dbaccess/source/core/api/statement.cxx @@ -0,0 +1,696 @@ +/************************************************************************* + * + * 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_dbaccess.hxx" +#ifndef _DBA_COREAPI_STATEMENT_HXX_ +#include <statement.hxx> +#endif +#ifndef _DBA_COREAPI_RESULTSET_HXX_ +#include <resultset.hxx> +#endif +#ifndef DBACCESS_SHARED_DBASTRINGS_HRC +#include "dbastrings.hrc" +#endif +#ifndef _COM_SUN_STAR_LANG_DISPOSEDEXCEPTION_HPP_ +#include <com/sun/star/lang/DisposedException.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_XDATABASEMETADATA_HPP_ +#include <com/sun/star/sdbc/XDatabaseMetaData.hpp> +#endif +#ifndef _COMPHELPER_SEQUENCE_HXX_ +#include <comphelper/sequence.hxx> +#endif +#ifndef _CPPUHELPER_TYPEPROVIDER_HXX_ +#include <cppuhelper/typeprovider.hxx> +#endif +#ifndef _COMPHELPER_PROPERTY_HXX_ +#include <comphelper/property.hxx> +#endif +#ifndef _COMPHELPER_TYPES_HXX_ +#include <comphelper/types.hxx> +#endif +#ifndef _TOOLS_DEBUG_HXX //autogen +#include <tools/debug.hxx> +#endif +#ifndef TOOLS_DIAGNOSE_EX_H +#include <tools/diagnose_ex.h> +#endif +#ifndef _DBHELPER_DBEXCEPTION_HXX_ +#include <connectivity/dbexception.hxx> +#endif +#include <rtl/logfile.hxx> + +using namespace ::com::sun::star::sdb; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::cppu; +using namespace ::osl; +using namespace dbaccess; +using namespace dbtools; + +DBG_NAME(OStatementBase) + +//-------------------------------------------------------------------------- +OStatementBase::OStatementBase(const Reference< XConnection > & _xConn, + const Reference< XInterface > & _xStatement) + :OSubComponent(m_aMutex, _xConn) + ,OPropertySetHelper(OComponentHelper::rBHelper) + ,m_bUseBookmarks( sal_False ) + ,m_bEscapeProcessing( sal_True ) + +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStatementBase::OStatementBase" ); + DBG_CTOR(OStatementBase, NULL); + OSL_ENSURE(_xStatement.is() ,"Statement is NULL!"); + m_xAggregateAsSet.set(_xStatement,UNO_QUERY); + m_xAggregateAsCancellable = Reference< ::com::sun::star::util::XCancellable > (m_xAggregateAsSet, UNO_QUERY); +} + +//-------------------------------------------------------------------------- +OStatementBase::~OStatementBase() +{ + DBG_DTOR(OStatementBase, NULL); +} + +// com::sun::star::lang::XTypeProvider +//-------------------------------------------------------------------------- +Sequence< Type > OStatementBase::getTypes() throw (RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStatementBase::getTypes" ); + OTypeCollection aTypes(::getCppuType( (const Reference< XPropertySet > *)0 ), + ::getCppuType( (const Reference< XWarningsSupplier > *)0 ), + ::getCppuType( (const Reference< XCloseable > *)0 ), + ::getCppuType( (const Reference< XMultipleResults > *)0 ), + ::getCppuType( (const Reference< ::com::sun::star::util::XCancellable > *)0 ), + OSubComponent::getTypes() ); + Reference< XGeneratedResultSet > xGRes(m_xAggregateAsSet, UNO_QUERY); + if ( xGRes.is() ) + aTypes = OTypeCollection(::getCppuType( (const Reference< XGeneratedResultSet > *)0 ),aTypes.getTypes()); + Reference< XPreparedBatchExecution > xPreparedBatchExecution(m_xAggregateAsSet, UNO_QUERY); + if ( xPreparedBatchExecution.is() ) + aTypes = OTypeCollection(::getCppuType( (const Reference< XPreparedBatchExecution > *)0 ),aTypes.getTypes()); + + return aTypes.getTypes(); +} + +// com::sun::star::uno::XInterface +//-------------------------------------------------------------------------- +Any OStatementBase::queryInterface( const Type & rType ) throw (RuntimeException) +{ + //RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStatementBase::queryInterface" ); + Any aIface = OSubComponent::queryInterface( rType ); + if (!aIface.hasValue()) + { + aIface = ::cppu::queryInterface( + rType, + static_cast< XPropertySet * >( this ), + static_cast< XWarningsSupplier * >( this ), + static_cast< XCloseable * >( this ), + static_cast< XMultipleResults * >( this ), + static_cast< ::com::sun::star::util::XCancellable * >( this )); + if ( !aIface.hasValue() ) + { + Reference< XGeneratedResultSet > xGRes(m_xAggregateAsSet, UNO_QUERY); + if ( ::getCppuType( (const Reference< XGeneratedResultSet > *)0 ) == rType && xGRes.is() ) + aIface = ::cppu::queryInterface(rType,static_cast< XGeneratedResultSet * >( this )); + } // if ( !aIface.hasValue() ) + if ( !aIface.hasValue() ) + { + Reference< XPreparedBatchExecution > xGRes(m_xAggregateAsSet, UNO_QUERY); + if ( ::getCppuType( (const Reference< XPreparedBatchExecution > *)0 ) == rType && xGRes.is() ) + aIface = ::cppu::queryInterface(rType,static_cast< XPreparedBatchExecution * >( this )); + } + } + return aIface; +} + +//-------------------------------------------------------------------------- +void OStatementBase::acquire() throw () +{ + OSubComponent::acquire(); +} + +//-------------------------------------------------------------------------- +void OStatementBase::release() throw () +{ + OSubComponent::release(); +} + +//------------------------------------------------------------------------------ +void OStatementBase::disposeResultSet() +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStatementBase::disposeResultSet" ); + // free the cursor if alive + Reference< XComponent > xComp(m_aResultSet.get(), UNO_QUERY); + if (xComp.is()) + xComp->dispose(); + m_aResultSet = NULL; +} + +// OComponentHelper +//------------------------------------------------------------------------------ +void OStatementBase::disposing() +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStatementBase::disposing" ); + OPropertySetHelper::disposing(); + + MutexGuard aGuard(m_aMutex); + + // free pending results + disposeResultSet(); + + // free the original statement + { + MutexGuard aCancelGuard(m_aCancelMutex); + m_xAggregateAsCancellable = NULL; + } + + if ( m_xAggregateAsSet.is() ) + { + try + { + Reference< XCloseable > (m_xAggregateAsSet, UNO_QUERY)->close(); + } + catch(RuntimeException& ) + {// don't care for anymore + } + } + m_xAggregateAsSet = NULL; + + // free the parent at last + OSubComponent::disposing(); +} + +// XCloseable +//------------------------------------------------------------------------------ +void OStatementBase::close(void) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStatementBase::close" ); + { + MutexGuard aGuard( m_aMutex ); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + } + dispose(); +} + +// OPropertySetHelper +//------------------------------------------------------------------------------ +Reference< XPropertySetInfo > OStatementBase::getPropertySetInfo() throw (RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStatementBase::getPropertySetInfo" ); + return createPropertySetInfo( getInfoHelper() ) ; +} + +// comphelper::OPropertyArrayUsageHelper +//------------------------------------------------------------------------------ +::cppu::IPropertyArrayHelper* OStatementBase::createArrayHelper( ) const +{ + //RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStatementBase::createArrayHelper" ); + BEGIN_PROPERTY_HELPER(10) + DECL_PROP0(CURSORNAME, ::rtl::OUString); + DECL_PROP0_BOOL(ESCAPE_PROCESSING); + DECL_PROP0(FETCHDIRECTION, sal_Int32); + DECL_PROP0(FETCHSIZE, sal_Int32); + DECL_PROP0(MAXFIELDSIZE, sal_Int32); + DECL_PROP0(MAXROWS, sal_Int32); + DECL_PROP0(QUERYTIMEOUT, sal_Int32); + DECL_PROP0(RESULTSETCONCURRENCY, sal_Int32); + DECL_PROP0(RESULTSETTYPE, sal_Int32); + DECL_PROP0_BOOL(USEBOOKMARKS); + END_PROPERTY_HELPER(); +} + +// cppu::OPropertySetHelper +//------------------------------------------------------------------------------ +::cppu::IPropertyArrayHelper& OStatementBase::getInfoHelper() +{ + //RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStatementBase::getInfoHelper" ); + return *getArrayHelper(); +} + +//------------------------------------------------------------------------------ +sal_Bool OStatementBase::convertFastPropertyValue( Any & rConvertedValue, Any & rOldValue, sal_Int32 nHandle, const Any& rValue ) throw( IllegalArgumentException ) +{ + //RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStatementBase::convertFastPropertyValue" ); + sal_Bool bModified(sal_False); + switch (nHandle) + { + case PROPERTY_ID_USEBOOKMARKS: + bModified = ::comphelper::tryPropertyValue( rConvertedValue, rOldValue, rValue, m_bUseBookmarks ); + break; + + case PROPERTY_ID_ESCAPE_PROCESSING: + bModified = ::comphelper::tryPropertyValue( rConvertedValue, rOldValue, rValue, m_bEscapeProcessing ); + break; + + default: + if ( m_xAggregateAsSet.is() ) + { + // get the property name + ::rtl::OUString sPropName; + getInfoHelper().fillPropertyMembersByHandle( &sPropName, NULL, nHandle ); + + // now set the value + Any aCurrentValue = m_xAggregateAsSet->getPropertyValue( sPropName ); + if ( aCurrentValue != rValue ) + { + rOldValue = aCurrentValue; + rConvertedValue = rValue; + bModified = sal_True; + } + } + break; + } + return bModified; +} + +//------------------------------------------------------------------------------ +void OStatementBase::setFastPropertyValue_NoBroadcast( sal_Int32 nHandle, const Any& rValue ) throw (Exception) +{ + //RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStatementBase::setFastPropertyValue_NoBroadcast" ); + switch ( nHandle ) + { + case PROPERTY_ID_USEBOOKMARKS: + { + m_bUseBookmarks = ::comphelper::getBOOL( rValue ); + if ( m_xAggregateAsSet.is() && m_xAggregateAsSet->getPropertySetInfo()->hasPropertyByName( PROPERTY_USEBOOKMARKS ) ) + m_xAggregateAsSet->setPropertyValue( PROPERTY_USEBOOKMARKS, rValue ); + } + break; + + case PROPERTY_ID_ESCAPE_PROCESSING: + m_bEscapeProcessing = ::comphelper::getBOOL( rValue ); + if ( m_xAggregateAsSet.is() ) + m_xAggregateAsSet->setPropertyValue( PROPERTY_ESCAPE_PROCESSING, rValue ); + break; + + default: + if ( m_xAggregateAsSet.is() ) + { + ::rtl::OUString sPropName; + getInfoHelper().fillPropertyMembersByHandle( &sPropName, NULL, nHandle ); + m_xAggregateAsSet->setPropertyValue( sPropName, rValue ); + } + break; + } +} + +//------------------------------------------------------------------------------ +void OStatementBase::getFastPropertyValue( Any& rValue, sal_Int32 nHandle ) const +{ + //RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStatementBase::getFastPropertyValue" ); + switch (nHandle) + { + case PROPERTY_ID_USEBOOKMARKS: + rValue <<= m_bUseBookmarks; + break; + + case PROPERTY_ID_ESCAPE_PROCESSING: + // don't rely on our aggregate - if it implements this wrong, and always returns + // TRUE here, then we would loop in impl_doEscapeProcessing_nothrow + rValue <<= m_bEscapeProcessing; + break; + + default: + if ( m_xAggregateAsSet.is() ) + { + ::rtl::OUString sPropName; + const_cast< OStatementBase* >( this )->getInfoHelper().fillPropertyMembersByHandle( &sPropName, NULL, nHandle ); + rValue = m_xAggregateAsSet->getPropertyValue( sPropName ); + } + break; + } +} + +// XWarningsSupplier +//------------------------------------------------------------------------------ +Any OStatementBase::getWarnings(void) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStatementBase::getWarnings" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + + return Reference< XWarningsSupplier >(m_xAggregateAsSet, UNO_QUERY)->getWarnings(); +} + +//------------------------------------------------------------------------------ +void OStatementBase::clearWarnings(void) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStatementBase::clearWarnings" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + + Reference< XWarningsSupplier >(m_xAggregateAsSet, UNO_QUERY)->clearWarnings(); +} + +// ::com::sun::star::util::XCancellable +//------------------------------------------------------------------------------ +void OStatementBase::cancel(void) throw( RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStatementBase::cancel" ); + // no blocking as cancel is typically called from a different thread + ClearableMutexGuard aCancelGuard(m_aCancelMutex); + if (m_xAggregateAsCancellable.is()) + m_xAggregateAsCancellable->cancel(); + // else do nothing +} + +// XMultipleResults +//------------------------------------------------------------------------------ +Reference< XResultSet > SAL_CALL OStatementBase::getResultSet( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStatementBase::getResultSet" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + + // first check the meta data + Reference<XDatabaseMetaData> xMeta = Reference< XConnection > (m_xParent, UNO_QUERY)->getMetaData(); + if (!xMeta.is() && !xMeta->supportsMultipleResultSets()) + throwFunctionSequenceException(*this); + + return Reference< XMultipleResults >(m_xAggregateAsSet, UNO_QUERY)->getResultSet(); +} + +//------------------------------------------------------------------------------ +sal_Int32 SAL_CALL OStatementBase::getUpdateCount( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStatementBase::getUpdateCount" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + + // first check the meta data + Reference<XDatabaseMetaData> xMeta = Reference< XConnection > (m_xParent, UNO_QUERY)->getMetaData(); + if (!xMeta.is() && !xMeta->supportsMultipleResultSets()) + throwFunctionSequenceException(*this); + + return Reference< XMultipleResults >(m_xAggregateAsSet, UNO_QUERY)->getUpdateCount(); +} + +//------------------------------------------------------------------------------ +sal_Bool SAL_CALL OStatementBase::getMoreResults( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStatementBase::getMoreResults" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + + // first check the meta data + Reference<XDatabaseMetaData> xMeta = Reference< XConnection > (m_xParent, UNO_QUERY)->getMetaData(); + if (!xMeta.is() && !xMeta->supportsMultipleResultSets()) + throwFunctionSequenceException(*this); + throwFunctionSequenceException(*this); + + // free the previous results + disposeResultSet(); + + return Reference< XMultipleResults >(m_xAggregateAsSet, UNO_QUERY)->getMoreResults(); +} + +// XPreparedBatchExecution +//------------------------------------------------------------------------------ +void SAL_CALL OStatementBase::addBatch( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStatementBase::addBatch" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + + // first check the meta data + Reference<XDatabaseMetaData> xMeta = Reference< XConnection > (m_xParent, UNO_QUERY)->getMetaData(); + if (!xMeta.is() && !xMeta->supportsBatchUpdates()) + throwFunctionSequenceException(*this); + + Reference< XPreparedBatchExecution >(m_xAggregateAsSet, UNO_QUERY)->addBatch(); +} + +//------------------------------------------------------------------------------ +void SAL_CALL OStatementBase::clearBatch( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStatementBase::clearBatch" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + + // first check the meta data + Reference<XDatabaseMetaData> xMeta = Reference< XConnection > (m_xParent, UNO_QUERY)->getMetaData(); + if (!xMeta.is() && !xMeta->supportsBatchUpdates()) + throwFunctionSequenceException(*this); + + Reference< XPreparedBatchExecution >(m_xAggregateAsSet, UNO_QUERY)->clearBatch(); +} + +//------------------------------------------------------------------------------ +Sequence< sal_Int32 > SAL_CALL OStatementBase::executeBatch( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStatementBase::executeBatch" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + + // first check the meta data + Reference<XDatabaseMetaData> xMeta = Reference< XConnection > (m_xParent, UNO_QUERY)->getMetaData(); + if (!xMeta.is() && !xMeta->supportsBatchUpdates()) + throwFunctionSequenceException(*this); + + // free the previous results + disposeResultSet(); + + return Reference< XPreparedBatchExecution >(m_xAggregateAsSet, UNO_QUERY)->executeBatch(); +} +// ----------------------------------------------------------------------------- +Reference< XResultSet > SAL_CALL OStatementBase::getGeneratedValues( ) throw (SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStatementBase::getGeneratedValues" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + Reference< XGeneratedResultSet > xGRes(m_xAggregateAsSet, UNO_QUERY); + + if ( xGRes.is() ) + return xGRes->getGeneratedValues( ); + return Reference< XResultSet >(); +} + +//************************************************************ +// OStatement +//************************************************************ +//------------------------------------------------------------------------------ +OStatement::OStatement( const Reference< XConnection >& _xConn, const Reference< XInterface > & _xStatement ) + :OStatementBase( _xConn, _xStatement ) + ,m_bAttemptedComposerCreation( false ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStatement::OStatement" ); + m_xAggregateStatement.set( _xStatement, UNO_QUERY_THROW ); +} + +//------------------------------------------------------------------------------ +IMPLEMENT_FORWARD_XINTERFACE2( OStatement, OStatementBase, OStatement_IFACE ); +IMPLEMENT_FORWARD_XTYPEPROVIDER2( OStatement, OStatementBase, OStatement_IFACE ); + +// XServiceInfo +//------------------------------------------------------------------------------ +rtl::OUString OStatement::getImplementationName( ) throw(RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStatement::getImplementationName" ); + return rtl::OUString::createFromAscii("com.sun.star.sdb.OStatement"); +} + +//------------------------------------------------------------------------------ +sal_Bool OStatement::supportsService( const ::rtl::OUString& _rServiceName ) throw (RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStatement::supportsService" ); + return ::comphelper::findValue(getSupportedServiceNames(), _rServiceName, sal_True).getLength() != 0; +} + +//------------------------------------------------------------------------------ +Sequence< ::rtl::OUString > OStatement::getSupportedServiceNames( ) throw (RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStatement::getSupportedServiceNames" ); + Sequence< ::rtl::OUString > aSNS( 1 ); + aSNS.getArray()[0] = SERVICE_SDBC_STATEMENT; + return aSNS; +} + +// XStatement +//------------------------------------------------------------------------------ +Reference< XResultSet > OStatement::executeQuery( const rtl::OUString& _rSQL ) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStatement::executeQuery" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + + disposeResultSet(); + Reference< XResultSet > xResultSet; + + ::rtl::OUString sSQL( impl_doEscapeProcessing_nothrow( _rSQL ) ); + + Reference< XResultSet > xInnerResultSet = m_xAggregateStatement->executeQuery( sSQL ); + Reference< XConnection > xConnection( m_xParent, UNO_QUERY_THROW ); + + if ( xInnerResultSet.is() ) + { + Reference< XDatabaseMetaData > xMeta = xConnection->getMetaData(); + sal_Bool bCaseSensitive = xMeta.is() && xMeta->supportsMixedCaseQuotedIdentifiers(); + xResultSet = new OResultSet( xInnerResultSet, *this, bCaseSensitive ); + + // keep the resultset weak + m_aResultSet = xResultSet; + } + + return xResultSet; +} + +//------------------------------------------------------------------------------ +sal_Int32 OStatement::executeUpdate( const rtl::OUString& _rSQL ) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStatement::executeUpdate" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + + disposeResultSet(); + + ::rtl::OUString sSQL( impl_doEscapeProcessing_nothrow( _rSQL ) ); + return m_xAggregateStatement->executeUpdate( sSQL ); +} + +//------------------------------------------------------------------------------ +sal_Bool OStatement::execute( const rtl::OUString& _rSQL ) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStatement::execute" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + + disposeResultSet(); + + ::rtl::OUString sSQL( impl_doEscapeProcessing_nothrow( _rSQL ) ); + return m_xAggregateStatement->execute( sSQL ); +} +//------------------------------------------------------------------------------ +void OStatement::addBatch( const rtl::OUString& _rSQL ) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStatement::execute" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + + // first check the meta data + Reference<XDatabaseMetaData> xMeta = Reference< XConnection > (m_xParent, UNO_QUERY)->getMetaData(); + if (!xMeta.is() && !xMeta->supportsBatchUpdates()) + throwFunctionSequenceException(*this); + + ::rtl::OUString sSQL( impl_doEscapeProcessing_nothrow( _rSQL ) ); + Reference< XBatchExecution >(m_xAggregateAsSet, UNO_QUERY)->addBatch( sSQL ); +} +//------------------------------------------------------------------------------ +void OStatement::clearBatch( ) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStatement::execute" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + // first check the meta data + Reference<XDatabaseMetaData> xMeta = Reference< XConnection > (m_xParent, UNO_QUERY)->getMetaData(); + if (!xMeta.is() && !xMeta->supportsBatchUpdates()) + throwFunctionSequenceException(*this); + + Reference< XBatchExecution >(m_xAggregateAsSet, UNO_QUERY)->clearBatch(); +} +//------------------------------------------------------------------------------ +Sequence< sal_Int32 > OStatement::executeBatch( ) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStatement::execute" ); + MutexGuard aGuard(m_aMutex); + ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed); + // first check the meta data + Reference<XDatabaseMetaData> xMeta = Reference< XConnection > (m_xParent, UNO_QUERY)->getMetaData(); + if (!xMeta.is() && !xMeta->supportsBatchUpdates()) + throwFunctionSequenceException(*this); + return Reference< XBatchExecution >(m_xAggregateAsSet, UNO_QUERY)->executeBatch( ); +} + +//------------------------------------------------------------------------------ +Reference< XConnection > OStatement::getConnection(void) throw( SQLException, RuntimeException ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStatement::getConnection" ); + return Reference< XConnection >( m_xParent, UNO_QUERY ); +} + +// ----------------------------------------------------------------------------- +void SAL_CALL OStatement::disposing() +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStatement::disposing" ); + OStatementBase::disposing(); + m_xComposer.clear(); + m_xAggregateStatement.clear(); +} + +// ----------------------------------------------------------------------------- +::rtl::OUString OStatement::impl_doEscapeProcessing_nothrow( const ::rtl::OUString& _rSQL ) const +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStatement::impl_doEscapeProcessing_nothrow" ); + if ( !m_bEscapeProcessing ) + return _rSQL; + try + { + if ( !impl_ensureComposer_nothrow() ) + return _rSQL; + + bool bParseable = false; + try { m_xComposer->setQuery( _rSQL ); bParseable = true; } + catch( const SQLException& ) { } + + if ( !bParseable ) + // if we cannot parse it, silently accept this. The driver is probably able to cope with it then + return _rSQL; + + ::rtl::OUString sLowLevelSQL = m_xComposer->getQueryWithSubstitution(); + return sLowLevelSQL; + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + + return _rSQL; +} + +// ----------------------------------------------------------------------------- +bool OStatement::impl_ensureComposer_nothrow() const +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStatement::impl_ensureComposer_nothrow" ); + if ( m_bAttemptedComposerCreation ) + return m_xComposer.is(); + + const_cast< OStatement* >( this )->m_bAttemptedComposerCreation = true; + try + { + Reference< XMultiServiceFactory > xFactory( m_xParent, UNO_QUERY_THROW ); + const_cast< OStatement* >( this )->m_xComposer.set( xFactory->createInstance( SERVICE_NAME_SINGLESELECTQUERYCOMPOSER ), UNO_QUERY_THROW ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + + return m_xComposer.is(); +} diff --git a/dbaccess/source/core/api/table.cxx b/dbaccess/source/core/api/table.cxx new file mode 100644 index 000000000000..e33098f74f4c --- /dev/null +++ b/dbaccess/source/core/api/table.cxx @@ -0,0 +1,417 @@ +/************************************************************************* + * + * 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_dbaccess.hxx" + +#include "table.hxx" +#include <definitioncolumn.hxx> +#include "dbastrings.hrc" +#include "core_resource.hxx" +#include "core_resource.hrc" +#include "CIndexes.hxx" + +#include <tools/debug.hxx> +#include <cppuhelper/typeprovider.hxx> +#include <comphelper/enumhelper.hxx> +#include <comphelper/container.hxx> +#include <comphelper/sequence.hxx> +#include <comphelper/types.hxx> +//#include <comphelper/extract.hxx> +#include <com/sun/star/util/XRefreshListener.hpp> +#include <com/sun/star/sdbc/XConnection.hpp> +#include <com/sun/star/sdbc/XRow.hpp> +#include <com/sun/star/sdbcx/Privilege.hpp> +#include <com/sun/star/sdbc/XResultSetMetaData.hpp> +#include <com/sun/star/sdbc/XResultSetMetaDataSupplier.hpp> + +#include <connectivity/TKeys.hxx> +#include <connectivity/dbtools.hxx> +#include <connectivity/dbexception.hxx> + +#include "sdbcoretools.hxx" +#include "ContainerMediator.hxx" +#include <rtl/logfile.hxx> + +using namespace dbaccess; +using namespace connectivity; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::util; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::container; +using namespace ::osl; +using namespace ::comphelper; +using namespace ::cppu; + +typedef ::std::map <sal_Int32, OTableColumn*, std::less <sal_Int32> > OColMap; + +//========================================================================== +//= ODBTable +//========================================================================== +DBG_NAME(ODBTable) +//-------------------------------------------------------------------------- +ODBTable::ODBTable(connectivity::sdbcx::OCollection* _pTables + ,const Reference< XConnection >& _rxConn + ,const ::rtl::OUString& _rCatalog + ,const ::rtl::OUString& _rSchema + ,const ::rtl::OUString& _rName + ,const ::rtl::OUString& _rType + ,const ::rtl::OUString& _rDesc + ,const Reference< XNameAccess >& _xColumnDefinitions) throw(SQLException) + :OTable_Base(_pTables,_rxConn,_rxConn->getMetaData().is() && _rxConn->getMetaData()->supportsMixedCaseQuotedIdentifiers(), _rName, _rType, _rDesc, _rSchema, _rCatalog ) + ,m_xColumnDefinitions(_xColumnDefinitions) + ,m_nPrivileges(0) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ODBTable::ODBTable" ); + DBG_CTOR(ODBTable, NULL); + DBG_ASSERT(getMetaData().is(), "ODBTable::ODBTable : invalid conn !"); + DBG_ASSERT(_rName.getLength(), "ODBTable::ODBTable : name !"); + // TODO : think about collecting the privileges here, as we can't ensure that in getFastPropertyValue, where + // we do this at the moment, the statement needed can be supplied by the connection (for example the SQL-Server + // ODBC driver does not allow more than one statement per connection, and in getFastPropertyValue it's more + // likely that it's already used up than it's here.) +} +// ----------------------------------------------------------------------------- +ODBTable::ODBTable(connectivity::sdbcx::OCollection* _pTables + ,const Reference< XConnection >& _rxConn) + throw(SQLException) + :OTable_Base(_pTables,_rxConn, _rxConn->getMetaData().is() && _rxConn->getMetaData()->supportsMixedCaseQuotedIdentifiers()) + ,m_nPrivileges(-1) +{ + DBG_CTOR(ODBTable, NULL); + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ODBTable::ODBTable" ); +} +// ------------------------------------------------------------------------- +ODBTable::~ODBTable() +{ + DBG_DTOR(ODBTable, NULL); +} +// ----------------------------------------------------------------------------- +IMPLEMENT_FORWARD_REFCOUNT(ODBTable,OTable_Base) + +//-------------------------------------------------------------------------- +OColumn* ODBTable::createColumn(const ::rtl::OUString& _rName) const +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ODBTable::createColumn" ); + OColumn* pReturn = NULL; + + Reference<XPropertySet> xProp; + if ( m_xDriverColumns.is() && m_xDriverColumns->hasByName(_rName) ) + { + xProp.set(m_xDriverColumns->getByName(_rName),UNO_QUERY); + } + else + { + OColumns* pColumns = static_cast<OColumns*>(m_pColumns); + xProp.set(pColumns->createBaseObject(_rName),UNO_QUERY); + } + + Reference<XPropertySet> xColumnDefintion; + if ( m_xColumnDefinitions.is() && m_xColumnDefinitions->hasByName(_rName) ) + xColumnDefintion.set(m_xColumnDefinitions->getByName(_rName),UNO_QUERY); + pReturn = new OTableColumnWrapper( xProp, xColumnDefintion, false ); + + return pReturn; +} +// ----------------------------------------------------------------------------- +void ODBTable::columnAppended( const Reference< XPropertySet >& /*_rxSourceDescriptor*/ ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ODBTable::columnAppended" ); + // not interested in +} +// ----------------------------------------------------------------------------- +void ODBTable::columnDropped(const ::rtl::OUString& _sName) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ODBTable::columnDropped" ); + Reference<XDrop> xDrop(m_xColumnDefinitions,UNO_QUERY); + if ( xDrop.is() && m_xColumnDefinitions->hasByName(_sName) ) + { + xDrop->dropByName(_sName); + } +} +//-------------------------------------------------------------------------- +Sequence< sal_Int8 > ODBTable::getImplementationId() throw (RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ODBTable::getImplementationId" ); + static OImplementationId * pId = 0; + if (! pId) + { + MutexGuard aGuard( Mutex::getGlobalMutex() ); + if (! pId) + { + static OImplementationId aId; + pId = &aId; + } + } + return pId->getImplementationId(); +} + +// OComponentHelper +//------------------------------------------------------------------------------ +void SAL_CALL ODBTable::disposing() +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ODBTable::disposing" ); + OPropertySetHelper::disposing(); + OTable_Base::disposing(); + m_xColumnDefinitions = NULL; + m_xDriverColumns = NULL; + m_pColumnMediator = NULL; +} + +//------------------------------------------------------------------------------ +void ODBTable::getFastPropertyValue(Any& _rValue, sal_Int32 _nHandle) const +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ODBTable::getFastPropertyValue" ); + if ((PROPERTY_ID_PRIVILEGES == _nHandle) && (-1 == m_nPrivileges)) + { // somebody is asking for the privileges an we do not know them, yet + const_cast<ODBTable*>(this)->m_nPrivileges = ::dbtools::getTablePrivileges(getMetaData(),m_CatalogName,m_SchemaName, m_Name); + } + + OTable_Base::getFastPropertyValue(_rValue, _nHandle); +} +// ------------------------------------------------------------------------- +void ODBTable::construct() +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ODBTable::construct" ); + ::osl::MutexGuard aGuard(m_aMutex); + + // we don't collect the privileges here, this is potentially expensive. Instead we determine them on request. + // (see getFastPropertyValue) + m_nPrivileges = -1; + + OTable_Base::construct(); + + registerProperty(PROPERTY_FILTER, PROPERTY_ID_FILTER, PropertyAttribute::BOUND, + &m_sFilter, ::getCppuType(&m_sFilter)); + + registerProperty(PROPERTY_ORDER, PROPERTY_ID_ORDER, PropertyAttribute::BOUND, + &m_sOrder, ::getCppuType(&m_sOrder)); + + registerProperty(PROPERTY_APPLYFILTER, PROPERTY_ID_APPLYFILTER, PropertyAttribute::BOUND, + &m_bApplyFilter, ::getBooleanCppuType()); + + registerProperty(PROPERTY_FONT, PROPERTY_ID_FONT, PropertyAttribute::BOUND, + &m_aFont, ::getCppuType(&m_aFont)); + + registerMayBeVoidProperty(PROPERTY_ROW_HEIGHT, PROPERTY_ID_ROW_HEIGHT, PropertyAttribute::BOUND | PropertyAttribute::MAYBEVOID, + &m_aRowHeight, ::getCppuType(static_cast<sal_Int32*>(NULL))); + + registerMayBeVoidProperty(PROPERTY_TEXTCOLOR, PROPERTY_ID_TEXTCOLOR, PropertyAttribute::BOUND | PropertyAttribute::MAYBEVOID, + &m_aTextColor, ::getCppuType(static_cast<sal_Int32*>(NULL))); + + registerProperty(PROPERTY_PRIVILEGES, PROPERTY_ID_PRIVILEGES, PropertyAttribute::BOUND | PropertyAttribute::READONLY, + &m_nPrivileges, ::getCppuType(static_cast<sal_Int32*>(NULL))); + + registerMayBeVoidProperty(PROPERTY_TEXTLINECOLOR, PROPERTY_ID_TEXTLINECOLOR, PropertyAttribute::BOUND | PropertyAttribute::MAYBEVOID, + &m_aTextLineColor, ::getCppuType(static_cast<sal_Int32*>(NULL))); + + registerProperty(PROPERTY_TEXTEMPHASIS, PROPERTY_ID_TEXTEMPHASIS, PropertyAttribute::BOUND, + &m_nFontEmphasis, ::getCppuType(&m_nFontEmphasis)); + + registerProperty(PROPERTY_TEXTRELIEF, PROPERTY_ID_TEXTRELIEF, PropertyAttribute::BOUND, + &m_nFontRelief, ::getCppuType(&m_nFontRelief)); + + registerProperty(PROPERTY_FONTNAME, PROPERTY_ID_FONTNAME, PropertyAttribute::BOUND,&m_aFont.Name, ::getCppuType(&m_aFont.Name)); + registerProperty(PROPERTY_FONTHEIGHT, PROPERTY_ID_FONTHEIGHT, PropertyAttribute::BOUND,&m_aFont.Height, ::getCppuType(&m_aFont.Height)); + registerProperty(PROPERTY_FONTWIDTH, PROPERTY_ID_FONTWIDTH, PropertyAttribute::BOUND,&m_aFont.Width, ::getCppuType(&m_aFont.Width)); + registerProperty(PROPERTY_FONTSTYLENAME, PROPERTY_ID_FONTSTYLENAME, PropertyAttribute::BOUND,&m_aFont.StyleName, ::getCppuType(&m_aFont.StyleName)); + registerProperty(PROPERTY_FONTFAMILY, PROPERTY_ID_FONTFAMILY, PropertyAttribute::BOUND,&m_aFont.Family, ::getCppuType(&m_aFont.Family)); + registerProperty(PROPERTY_FONTCHARSET, PROPERTY_ID_FONTCHARSET, PropertyAttribute::BOUND,&m_aFont.CharSet, ::getCppuType(&m_aFont.CharSet)); + registerProperty(PROPERTY_FONTPITCH, PROPERTY_ID_FONTPITCH, PropertyAttribute::BOUND,&m_aFont.Pitch, ::getCppuType(&m_aFont.Pitch)); + registerProperty(PROPERTY_FONTCHARWIDTH, PROPERTY_ID_FONTCHARWIDTH, PropertyAttribute::BOUND,&m_aFont.CharacterWidth, ::getCppuType(&m_aFont.CharacterWidth)); + registerProperty(PROPERTY_FONTWEIGHT, PROPERTY_ID_FONTWEIGHT, PropertyAttribute::BOUND,&m_aFont.Weight, ::getCppuType(&m_aFont.Weight)); + registerProperty(PROPERTY_FONTSLANT, PROPERTY_ID_FONTSLANT, PropertyAttribute::BOUND,&m_aFont.Slant, ::getCppuType(&m_aFont.Slant)); + registerProperty(PROPERTY_FONTUNDERLINE, PROPERTY_ID_FONTUNDERLINE, PropertyAttribute::BOUND,&m_aFont.Underline, ::getCppuType(&m_aFont.Underline)); + registerProperty(PROPERTY_FONTSTRIKEOUT, PROPERTY_ID_FONTSTRIKEOUT, PropertyAttribute::BOUND,&m_aFont.Strikeout, ::getCppuType(&m_aFont.Strikeout)); + registerProperty(PROPERTY_FONTORIENTATION, PROPERTY_ID_FONTORIENTATION, PropertyAttribute::BOUND,&m_aFont.Orientation, ::getCppuType(&m_aFont.Orientation)); + registerProperty(PROPERTY_FONTKERNING, PROPERTY_ID_FONTKERNING, PropertyAttribute::BOUND,&m_aFont.Kerning, ::getCppuType(&m_aFont.Kerning)); + registerProperty(PROPERTY_FONTWORDLINEMODE, PROPERTY_ID_FONTWORDLINEMODE,PropertyAttribute::BOUND,&m_aFont.WordLineMode, ::getCppuType(&m_aFont.WordLineMode)); + registerProperty(PROPERTY_FONTTYPE, PROPERTY_ID_FONTTYPE, PropertyAttribute::BOUND,&m_aFont.Type, ::getCppuType(&m_aFont.Type)); + + refreshColumns(); +} +// ----------------------------------------------------------------------------- +::cppu::IPropertyArrayHelper* ODBTable::createArrayHelper( sal_Int32 _nId) const +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ODBTable::createArrayHelper" ); + Sequence< Property > aProps; + describeProperties(aProps); + if(!_nId) + { + Property* pIter = aProps.getArray(); + Property* pEnd = pIter + aProps.getLength(); + for(;pIter != pEnd;++pIter) + { + if (0 == pIter->Name.compareToAscii(PROPERTY_CATALOGNAME)) + pIter->Attributes = PropertyAttribute::READONLY; + else if (0 == pIter->Name.compareToAscii(PROPERTY_SCHEMANAME)) + pIter->Attributes = PropertyAttribute::READONLY; + else if (0 == pIter->Name.compareToAscii(PROPERTY_DESCRIPTION)) + pIter->Attributes = PropertyAttribute::READONLY; + else if (0 == pIter->Name.compareToAscii(PROPERTY_NAME)) + pIter->Attributes = PropertyAttribute::READONLY; + } + } + + return new ::cppu::OPropertyArrayHelper(aProps); +} +// ----------------------------------------------------------------------------- +::cppu::IPropertyArrayHelper & SAL_CALL ODBTable::getInfoHelper() +{ + return *ODBTable_PROP::getArrayHelper(isNew() ? 1 : 0); +} +// ------------------------------------------------------------------------- +// XServiceInfo +IMPLEMENT_SERVICE_INFO1(ODBTable, "com.sun.star.sdb.dbaccess.ODBTable", SERVICE_SDBCX_TABLE) +// ------------------------------------------------------------------------- +Any SAL_CALL ODBTable::queryInterface( const Type & rType ) throw(RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ODBTable::getInfoHelper" ); + if(rType == getCppuType( (Reference<XRename>*)0) && !getRenameService().is() ) + return Any(); + if(rType == getCppuType( (Reference<XAlterTable>*)0) && !getAlterService().is() ) + return Any(); + return OTable_Base::queryInterface( rType); +} +// ------------------------------------------------------------------------- +Sequence< Type > SAL_CALL ODBTable::getTypes( ) throw(RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ODBTable::getTypes" ); + Type aRenameType = getCppuType( (Reference<XRename>*)0); + Type aAlterType = getCppuType( (Reference<XAlterTable>*)0); + + Sequence< Type > aTypes(OTable_Base::getTypes()); + ::std::vector<Type> aOwnTypes; + aOwnTypes.reserve(aTypes.getLength()); + + const Type* pIter = aTypes.getConstArray(); + const Type* pEnd = pIter + aTypes.getLength(); + for(;pIter != pEnd ;++pIter) + { + if( (*pIter != aRenameType || getRenameService().is()) && (*pIter != aAlterType || getAlterService().is())) + aOwnTypes.push_back(*pIter); + } + + Type* pTypes = aOwnTypes.empty() ? 0 : &aOwnTypes[0]; + return Sequence< Type >(pTypes, aOwnTypes.size()); +} +// XRename, +//------------------------------------------------------------------------------ +void SAL_CALL ODBTable::rename( const ::rtl::OUString& _rNewName ) throw(SQLException, ElementExistException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ODBTable::rename" ); + ::osl::MutexGuard aGuard(m_aMutex); + checkDisposed(connectivity::sdbcx::OTableDescriptor_BASE::rBHelper.bDisposed); + if ( !getRenameService().is() ) + throw SQLException(DBACORE_RESSTRING(RID_STR_NO_TABLE_RENAME),*this,SQLSTATE_GENERAL,1000,Any() ); + + Reference<XPropertySet> xTable(this); + getRenameService()->rename(xTable,_rNewName); + ::connectivity::OTable_TYPEDEF::rename(_rNewName); +} + +// XAlterTable, +//------------------------------------------------------------------------------ +void SAL_CALL ODBTable::alterColumnByName( const ::rtl::OUString& _rName, const Reference< XPropertySet >& _rxDescriptor ) throw(SQLException, NoSuchElementException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ODBTable::alterColumnByName" ); + ::osl::MutexGuard aGuard(m_aMutex); + checkDisposed(connectivity::sdbcx::OTableDescriptor_BASE::rBHelper.bDisposed); + if ( !getAlterService().is() ) + throw SQLException(DBACORE_RESSTRING(RID_STR_NO_TABLE_RENAME),*this,SQLSTATE_GENERAL,1000,Any() ); + + if ( !m_pColumns->hasByName(_rName) ) + throw SQLException(DBACORE_RESSTRING(RID_STR_COLUMN_NOT_VALID),*this,SQLSTATE_GENERAL,1000,Any() ); + + Reference<XPropertySet> xTable(this); + getAlterService()->alterColumnByName(xTable,_rName,_rxDescriptor); + m_pColumns->refresh(); +} +// ----------------------------------------------------------------------------- +sal_Int64 SAL_CALL ODBTable::getSomething( const Sequence< sal_Int8 >& rId ) throw(RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ODBTable::getSomething" ); + sal_Int64 nRet(0); + if (rId.getLength() == 16 && 0 == rtl_compareMemory(getUnoTunnelImplementationId().getConstArray(), rId.getConstArray(), 16 ) ) + nRet = reinterpret_cast<sal_Int64>(this); + else + nRet = OTable_Base::getSomething(rId); + + return nRet; +} +// ----------------------------------------------------------------------------- +Sequence< sal_Int8 > ODBTable::getUnoTunnelImplementationId() +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ODBTable::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(); +} +// ----------------------------------------------------------------------------- +Reference< XPropertySet > ODBTable::createColumnDescriptor() +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ODBTable::createColumnDescriptor" ); + return new OTableColumnDescriptor( true ); +} +// ----------------------------------------------------------------------------- +sdbcx::OCollection* ODBTable::createColumns(const TStringVector& _rNames) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ODBTable::createColumns" ); + Reference<XDatabaseMetaData> xMeta = getMetaData(); + OColumns* pCol = new OColumns(*this, m_aMutex, NULL, isCaseSensitive(), _rNames, this,this, + getAlterService().is() || (xMeta.is() && xMeta->supportsAlterTableWithAddColumn()), + getAlterService().is() || (xMeta.is() && xMeta->supportsAlterTableWithDropColumn())); + static_cast<OColumnsHelper*>(pCol)->setParent(this); + pCol->setParent(*this); + m_pColumnMediator = new OContainerMediator( pCol, m_xColumnDefinitions, getConnection(), OContainerMediator::eColumns ); + pCol->setMediator( m_pColumnMediator.get() ); + return pCol; +} +// ----------------------------------------------------------------------------- +sdbcx::OCollection* ODBTable::createKeys(const TStringVector& _rNames) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ODBTable::createKeys" ); + return new connectivity::OKeysHelper(this,m_aMutex,_rNames); +} +// ----------------------------------------------------------------------------- +sdbcx::OCollection* ODBTable::createIndexes(const TStringVector& _rNames) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "ODBTable::createIndexes" ); + return new OIndexes(this,m_aMutex,_rNames,NULL); +} +// ----------------------------------------------------------------------------- diff --git a/dbaccess/source/core/api/tablecontainer.cxx b/dbaccess/source/core/api/tablecontainer.cxx new file mode 100644 index 000000000000..76d6ac063441 --- /dev/null +++ b/dbaccess/source/core/api/tablecontainer.cxx @@ -0,0 +1,516 @@ +/************************************************************************* + * + * 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_dbaccess.hxx" + +#include "tablecontainer.hxx" +#include "dbastrings.hrc" +#include "table.hxx" +#include <comphelper/property.hxx> +#include <comphelper/processfactory.hxx> +#include <tools/debug.hxx> +#include <comphelper/enumhelper.hxx> +#include "core_resource.hxx" +#include "core_resource.hrc" +#include <com/sun/star/sdb/CommandType.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/beans/PropertyState.hpp> +#include <com/sun/star/beans/XPropertyState.hpp> +#include <com/sun/star/sdbc/XConnection.hpp> +#include <com/sun/star/sdbc/XDatabaseMetaData.hpp> +#include <com/sun/star/sdbcx/XColumnsSupplier.hpp> +#include <com/sun/star/sdbcx/XTablesSupplier.hpp> +#include <com/sun/star/sdbc/KeyRule.hpp> +#include <com/sun/star/sdbcx/KeyType.hpp> +#include <com/sun/star/sdbc/ColumnValue.hpp> +#include <com/sun/star/sdbc/XRow.hpp> +#include <comphelper/types.hxx> +#include <connectivity/dbtools.hxx> +#include <comphelper/extract.hxx> +#include <connectivity/dbexception.hxx> +#include "TableDeco.hxx" +#include "sdbcoretools.hxx" +#include "ContainerMediator.hxx" +#include "definitioncolumn.hxx" +#include "objectnameapproval.hxx" +#include <tools/string.hxx> +#include <rtl/logfile.hxx> +#ifndef TOOLS_DIAGNOSE_EX_H +#include <tools/diagnose_ex.h> +#endif +#ifndef TOOLS_DIAGNOSE_EX_H +#include <tools/diagnose_ex.h> +#endif + +using namespace dbaccess; +using namespace dbtools; +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::sdb; +using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::util; +using namespace ::osl; +using namespace ::comphelper; +using namespace ::cppu; +using namespace ::connectivity::sdbcx; + +namespace +{ + sal_Bool lcl_isPropertySetDefaulted(const Sequence< ::rtl::OUString>& _aNames,const Reference<XPropertySet>& _xProp) + { + Reference<XPropertyState> xState(_xProp,UNO_QUERY); + if ( xState.is() ) + { + const ::rtl::OUString* pIter = _aNames.getConstArray(); + const ::rtl::OUString* pEnd = pIter + _aNames.getLength(); + for(;pIter != pEnd;++pIter) + { + try + { + PropertyState aState = xState->getPropertyState(*pIter); + if ( aState != PropertyState_DEFAULT_VALUE ) + break; + } + catch(Exception) + { + OSL_ENSURE( 0, "lcl_isPropertySetDefaulted: Exception caught!" ); + } + } + return ( pIter == pEnd ); + } + return sal_False; + } +} +//========================================================================== +//= OTableContainer +//========================================================================== +DBG_NAME(OTableContainer) +//------------------------------------------------------------------------------ +OTableContainer::OTableContainer(::cppu::OWeakObject& _rParent, + ::osl::Mutex& _rMutex, + const Reference< XConnection >& _xCon, + sal_Bool _bCase, + const Reference< XNameContainer >& _xTableDefinitions, + IRefreshListener* _pRefreshListener, + ::dbtools::IWarningsContainer* _pWarningsContainer + ,oslInterlockedCount& _nInAppend) + :OFilteredContainer(_rParent,_rMutex,_xCon,_bCase,_pRefreshListener,_pWarningsContainer,_nInAppend) + ,m_xTableDefinitions(_xTableDefinitions) + ,m_pTableMediator( NULL ) + ,m_bInDrop(sal_False) +{ + DBG_CTOR(OTableContainer, NULL); +} + +//------------------------------------------------------------------------------ +OTableContainer::~OTableContainer() +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "api", "Ocke.Janssen@sun.com", "OTableContainer::OTableContainer" ); + // dispose(); + DBG_DTOR(OTableContainer, NULL); +} + +// ----------------------------------------------------------------------------- +void OTableContainer::removeMasterContainerListener() +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "api", "Ocke.Janssen@sun.com", "OTableContainer::removeMasterContainerListener" ); + try + { + Reference<XContainer> xCont( m_xMasterContainer, UNO_QUERY_THROW ); + xCont->removeContainerListener( this ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } +} + +// ----------------------------------------------------------------------------- +::rtl::OUString OTableContainer::getTableTypeRestriction() const +{ + // no restriction at all (other than the ones provided externally) + return ::rtl::OUString(); +} + +// ----------------------------------------------------------------------------- +// XServiceInfo +//------------------------------------------------------------------------------ +IMPLEMENT_SERVICE_INFO2(OTableContainer, "com.sun.star.sdb.dbaccess.OTableContainer", SERVICE_SDBCX_CONTAINER, SERVICE_SDBCX_TABLES) + +// ----------------------------------------------------------------------------- +namespace +{ +void lcl_createDefintionObject(const ::rtl::OUString& _rName + ,const Reference< XNameContainer >& _xTableDefinitions + ,Reference<XPropertySet>& _xTableDefinition + ,Reference<XNameAccess>& _xColumnDefinitions + ,sal_Bool _bModified) +{ + if ( _xTableDefinitions.is() ) + { + if ( _xTableDefinitions->hasByName(_rName) ) + _xTableDefinition.set(_xTableDefinitions->getByName(_rName),UNO_QUERY); + else + { + Sequence< Any > aArguments(1); + PropertyValue aValue; + // set as folder + aValue.Name = PROPERTY_NAME; + aValue.Value <<= _rName; + aArguments[0] <<= aValue; + _xTableDefinition.set(::comphelper::getProcessServiceFactory()->createInstanceWithArguments(SERVICE_SDB_TABLEDEFINITION,aArguments),UNO_QUERY); + _xTableDefinitions->insertByName(_rName,makeAny(_xTableDefinition)); + ::dbaccess::notifyDataSourceModified(_xTableDefinitions,_bModified); + } + Reference<XColumnsSupplier> xColumnsSupplier(_xTableDefinition,UNO_QUERY); + if ( xColumnsSupplier.is() ) + _xColumnDefinitions = xColumnsSupplier->getColumns(); + } +} +// ------------------------------------------------------------------------- +} +// ------------------------------------------------------------------------- +connectivity::sdbcx::ObjectType OTableContainer::createObject(const ::rtl::OUString& _rName) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "api", "Ocke.Janssen@sun.com", "OTableContainer::createObject" ); + Reference<XColumnsSupplier > xSup; + if(m_xMasterContainer.is() && m_xMasterContainer->hasByName(_rName)) + xSup.set(m_xMasterContainer->getByName(_rName),UNO_QUERY); + + connectivity::sdbcx::ObjectType xRet; + if ( m_xMetaData.is() ) + { + Reference<XPropertySet> xTableDefinition; + Reference<XNameAccess> xColumnDefinitions; + lcl_createDefintionObject(_rName,m_xTableDefinitions,xTableDefinition,xColumnDefinitions,sal_False); + + if ( xSup.is() ) + { + ODBTableDecorator* pTable = new ODBTableDecorator( m_xConnection, xSup, ::dbtools::getNumberFormats( m_xConnection ) ,xColumnDefinitions); + xRet = pTable; + pTable->construct(); + } + else + { + ::rtl::OUString sCatalog,sSchema,sTable; + ::dbtools::qualifiedNameComponents(m_xMetaData, + _rName, + sCatalog, + sSchema, + sTable, + ::dbtools::eInDataManipulation); + Any aCatalog; + if(sCatalog.getLength()) + aCatalog <<= sCatalog; + ::rtl::OUString sType,sDescription; + Sequence< ::rtl::OUString> aTypeFilter; + getAllTableTypeFilter( aTypeFilter ); + + Reference< XResultSet > xRes = m_xMetaData.is() ? m_xMetaData->getTables(aCatalog,sSchema,sTable,aTypeFilter) : Reference< XResultSet >(); + if(xRes.is() && xRes->next()) + { + Reference< XRow > xRow(xRes,UNO_QUERY); + if(xRow.is()) + { + sType = xRow->getString(4); + sDescription = xRow->getString(5); + } + } + ::comphelper::disposeComponent(xRes); + ODBTable* pTable = new ODBTable(this + ,m_xConnection + ,sCatalog + ,sSchema + ,sTable + ,sType + ,sDescription + ,xColumnDefinitions); + xRet = pTable; + pTable->construct(); + } + Reference<XPropertySet> xDest(xRet,UNO_QUERY); + if ( xTableDefinition.is() ) + ::comphelper::copyProperties(xTableDefinition,xDest); + + if ( !m_pTableMediator.is() ) + m_pTableMediator = new OContainerMediator( + this, m_xTableDefinitions.get(), m_xConnection, OContainerMediator::eTables ); + if ( m_pTableMediator.is() ) + m_pTableMediator->notifyElementCreated(_rName,xDest); + } + + return xRet; +} +// ----------------------------------------------------------------------------- +Reference< XPropertySet > OTableContainer::createDescriptor() +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "api", "Ocke.Janssen@sun.com", "OTableContainer::createDescriptor" ); + Reference< XPropertySet > xRet; + + // frist we have to look if the master tables does support this + // and if then create a table object as well with the master tables + Reference<XColumnsSupplier > xMasterColumnsSup; + Reference<XDataDescriptorFactory> xDataFactory(m_xMasterContainer,UNO_QUERY); + if ( xDataFactory.is() && m_xMetaData.is() ) + { + xMasterColumnsSup = Reference< XColumnsSupplier >( xDataFactory->createDataDescriptor(), UNO_QUERY ); + ODBTableDecorator* pTable = new ODBTableDecorator( m_xConnection, xMasterColumnsSup, ::dbtools::getNumberFormats( m_xConnection ) ,NULL); + xRet = pTable; + pTable->construct(); + } + else + { + ODBTable* pTable = new ODBTable(this, m_xConnection); + xRet = pTable; + pTable->construct(); + } + return xRet; +} +// ----------------------------------------------------------------------------- +// XAppend +ObjectType OTableContainer::appendObject( const ::rtl::OUString& _rForName, const Reference< XPropertySet >& descriptor ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "api", "Ocke.Janssen@sun.com", "OTableContainer::appendObject" ); + // append the new table with a create stmt + ::rtl::OUString aName = getString(descriptor->getPropertyValue(PROPERTY_NAME)); + if(m_xMasterContainer.is() && m_xMasterContainer->hasByName(aName)) + { + String sMessage(DBACORE_RESSTRING(RID_STR_TABLE_IS_FILTERED)); + sMessage.SearchAndReplaceAscii("$name$", aName); + throw SQLException(sMessage,static_cast<XTypeProvider*>(static_cast<OFilteredContainer*>(this)),SQLSTATE_GENERAL,1000,Any()); + } + + Reference< XConnection > xConnection( m_xConnection.get(), UNO_QUERY ); + PContainerApprove pApprove( new ObjectNameApproval( xConnection, ObjectNameApproval::TypeTable ) ); + pApprove->approveElement( aName, descriptor ); + + try + { + EnsureReset aReset(m_nInAppend); + Reference<XAppend> xAppend(m_xMasterContainer,UNO_QUERY); + if(xAppend.is()) + { + xAppend->appendByDescriptor(descriptor); + } + else + { + ::rtl::OUString aSql = ::dbtools::createSqlCreateTableStatement(descriptor,m_xConnection); + + Reference<XConnection> xCon = m_xConnection; + OSL_ENSURE(xCon.is(),"Connection is null!"); + if ( xCon.is() ) + { + Reference< XStatement > xStmt = xCon->createStatement( ); + if ( xStmt.is() ) + xStmt->execute(aSql); + ::comphelper::disposeComponent(xStmt); + } + } + } + catch(Exception&) + { + throw; + } + + Reference<XPropertySet> xTableDefinition; + Reference<XNameAccess> xColumnDefinitions; + lcl_createDefintionObject(getNameForObject(descriptor),m_xTableDefinitions,xTableDefinition,xColumnDefinitions,sal_False); + Reference<XColumnsSupplier> xSup(descriptor,UNO_QUERY); + Reference<XDataDescriptorFactory> xFac(xColumnDefinitions,UNO_QUERY); + Reference<XAppend> xAppend(xColumnDefinitions,UNO_QUERY); + sal_Bool bModified = sal_False; + if ( xSup.is() && xColumnDefinitions.is() && xFac.is() && xAppend.is() ) + { + Reference<XNameAccess> xNames = xSup->getColumns(); + if ( xNames.is() ) + { + Reference<XPropertySet> xProp = xFac->createDataDescriptor(); + Sequence< ::rtl::OUString> aSeq = xNames->getElementNames(); + const ::rtl::OUString* pIter = aSeq.getConstArray(); + const ::rtl::OUString* pEnd = pIter + aSeq.getLength(); + for(;pIter != pEnd;++pIter) + { + if ( !xColumnDefinitions->hasByName(*pIter) ) + { + Reference<XPropertySet> xColumn(xNames->getByName(*pIter),UNO_QUERY); + if ( !OColumnSettings::hasDefaultSettings( xColumn ) ) + { + ::comphelper::copyProperties( xColumn, xProp ); + xAppend->appendByDescriptor( xProp ); + bModified = sal_True; + } + } + } + } + } + const static ::rtl::OUString s_pTableProps[] = { ::rtl::OUString(PROPERTY_FILTER), ::rtl::OUString(PROPERTY_ORDER) + , ::rtl::OUString(PROPERTY_APPLYFILTER), ::rtl::OUString(PROPERTY_FONT) + , ::rtl::OUString(PROPERTY_ROW_HEIGHT), ::rtl::OUString(PROPERTY_TEXTCOLOR) + , ::rtl::OUString(PROPERTY_TEXTLINECOLOR), ::rtl::OUString(PROPERTY_TEXTEMPHASIS) + , ::rtl::OUString(PROPERTY_TEXTRELIEF) }; + Sequence< ::rtl::OUString> aNames(s_pTableProps,sizeof(s_pTableProps)/sizeof(s_pTableProps[0])); + if ( bModified || !lcl_isPropertySetDefaulted(aNames,xTableDefinition) ) + ::dbaccess::notifyDataSourceModified(m_xTableDefinitions,sal_True); + + return createObject( _rForName ); +} +// ------------------------------------------------------------------------- +// XDrop +void OTableContainer::dropObject(sal_Int32 _nPos,const ::rtl::OUString _sElementName) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "api", "Ocke.Janssen@sun.com", "OTableContainer::dropObject" ); + m_bInDrop = sal_True; + try + { + Reference< XDrop > xDrop(m_xMasterContainer,UNO_QUERY); + if(xDrop.is()) + xDrop->dropByName(_sElementName); + else + { + ::rtl::OUString sCatalog,sSchema,sTable,sComposedName; + + sal_Bool bIsView = sal_False; + Reference<XPropertySet> xTable(getObject(_nPos),UNO_QUERY); + if ( xTable.is() && m_xMetaData.is() ) + { + if( m_xMetaData.is() && m_xMetaData->supportsCatalogsInTableDefinitions() ) + xTable->getPropertyValue(PROPERTY_CATALOGNAME) >>= sCatalog; + if( m_xMetaData.is() && m_xMetaData->supportsSchemasInTableDefinitions() ) + xTable->getPropertyValue(PROPERTY_SCHEMANAME) >>= sSchema; + xTable->getPropertyValue(PROPERTY_NAME) >>= sTable; + + sComposedName = ::dbtools::composeTableName( m_xMetaData, sCatalog, sSchema, sTable, sal_True, ::dbtools::eInTableDefinitions ); + + ::rtl::OUString sType; + xTable->getPropertyValue(PROPERTY_TYPE) >>= sType; + bIsView = sType.equalsIgnoreAsciiCase(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("VIEW"))); + } + + if(!sComposedName.getLength()) + ::dbtools::throwFunctionSequenceException(static_cast<XTypeProvider*>(static_cast<OFilteredContainer*>(this))); + + ::rtl::OUString aSql = ::rtl::OUString::createFromAscii("DROP "); + + // #104282# OJ + if ( bIsView ) // here we have a view + aSql += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("VIEW ")); + else + aSql += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("TABLE ")); + aSql += sComposedName; + Reference<XConnection> xCon = m_xConnection; + OSL_ENSURE(xCon.is(),"Connection is null!"); + if ( xCon.is() ) + { + Reference< XStatement > xStmt = xCon->createStatement( ); + if(xStmt.is()) + xStmt->execute(aSql); + ::comphelper::disposeComponent(xStmt); + } + } + + if ( m_xTableDefinitions.is() && m_xTableDefinitions->hasByName(_sElementName) ) + { + m_xTableDefinitions->removeByName(_sElementName); + } + } + catch(Exception&) + { + m_bInDrop = sal_False; + throw; + } + m_bInDrop = sal_False; +} +// ----------------------------------------------------------------------------- +void SAL_CALL OTableContainer::elementInserted( const ContainerEvent& Event ) throw (RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "api", "Ocke.Janssen@sun.com", "OTableContainer::elementInserted" ); + ::osl::MutexGuard aGuard(m_rMutex); + ::rtl::OUString sName; + Event.Accessor >>= sName; + if ( !m_nInAppend && !hasByName(sName) ) + { + if(!m_xMasterContainer.is() || m_xMasterContainer->hasByName(sName)) + { + ObjectType xName = createObject(sName); + insertElement(sName,xName); + // and notify our listeners + ContainerEvent aEvent(static_cast<XContainer*>(this), makeAny(sName), makeAny(xName), Any()); + m_aContainerListeners.notifyEach( &XContainerListener::elementInserted, aEvent ); + } + } +} +// ----------------------------------------------------------------------------- +void SAL_CALL OTableContainer::elementRemoved( const ContainerEvent& /*Event*/ ) throw (RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "api", "Ocke.Janssen@sun.com", "OTableContainer::elementRemoved" ); +} +// ----------------------------------------------------------------------------- +void SAL_CALL OTableContainer::elementReplaced( const ContainerEvent& Event ) throw (RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "api", "Ocke.Janssen@sun.com", "OTableContainer::elementReplaced" ); + // create a new config entry + { + ::rtl::OUString sOldComposedName,sNewComposedName; + Event.ReplacedElement >>= sOldComposedName; + Event.Accessor >>= sNewComposedName; + + renameObject(sOldComposedName,sNewComposedName); + } +} +// ----------------------------------------------------------------------------- +void SAL_CALL OTableContainer::disposing() +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "api", "Ocke.Janssen@sun.com", "OTableContainer::disposing" ); + OFilteredContainer::disposing(); + // say our listeners goobye + m_xTableDefinitions = NULL; + m_pTableMediator = NULL; +} +// ----------------------------------------------------------------------------- +void SAL_CALL OTableContainer::disposing( const ::com::sun::star::lang::EventObject& /*Source*/ ) throw (::com::sun::star::uno::RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "api", "Ocke.Janssen@sun.com", "OTableContainer::disposing" ); +} + +// ----------------------------------------------------------------------------- +void OTableContainer::addMasterContainerListener() +{ + try + { + Reference< XContainer > xCont( m_xMasterContainer, UNO_QUERY_THROW ); + xCont->addContainerListener( this ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } +} + diff --git a/dbaccess/source/core/api/viewcontainer.cxx b/dbaccess/source/core/api/viewcontainer.cxx new file mode 100644 index 000000000000..0fc2542bfa4a --- /dev/null +++ b/dbaccess/source/core/api/viewcontainer.cxx @@ -0,0 +1,274 @@ +/************************************************************************* + * + * 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_dbaccess.hxx" + +#include "viewcontainer.hxx" +#include "dbastrings.hrc" +#include "core_resource.hxx" +#include "core_resource.hrc" +#include "View.hxx" + +#include <tools/debug.hxx> +#include <tools/wldcrd.hxx> +#include <comphelper/enumhelper.hxx> +#include <comphelper/types.hxx> +#include <connectivity/dbtools.hxx> +#include <comphelper/extract.hxx> +#include <connectivity/dbexception.hxx> +#include <rtl/ustrbuf.hxx> + +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/sdbc/XConnection.hpp> +#include <com/sun/star/sdbc/XDatabaseMetaData.hpp> +#include <com/sun/star/sdbc/KeyRule.hpp> +#include <com/sun/star/sdbc/ColumnValue.hpp> +#include <com/sun/star/sdbc/XRow.hpp> +#include <com/sun/star/sdbcx/XColumnsSupplier.hpp> +#include <com/sun/star/sdbcx/XTablesSupplier.hpp> +#include <com/sun/star/sdbcx/KeyType.hpp> + +using namespace dbaccess; +using namespace dbtools; +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::sdb; +using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::util; +using namespace ::com::sun::star::container; +using namespace ::osl; +using namespace ::comphelper; +using namespace ::cppu; +using namespace ::connectivity::sdbcx; + +//========================================================================== +//= OViewContainer +//========================================================================== +DBG_NAME(OViewContainer) +//------------------------------------------------------------------------------ +OViewContainer::OViewContainer(::cppu::OWeakObject& _rParent + ,::osl::Mutex& _rMutex + ,const Reference< XConnection >& _xCon + ,sal_Bool _bCase + ,IRefreshListener* _pRefreshListener + ,::dbtools::IWarningsContainer* _pWarningsContainer + ,oslInterlockedCount& _nInAppend) + :OFilteredContainer(_rParent,_rMutex,_xCon,_bCase,_pRefreshListener,_pWarningsContainer,_nInAppend) + ,m_bInElementRemoved(false) +{ + DBG_CTOR(OViewContainer, NULL); +} + +//------------------------------------------------------------------------------ +OViewContainer::~OViewContainer() +{ + // dispose(); + DBG_DTOR(OViewContainer, NULL); +} +//------------------------------------------------------------------------------ +// XServiceInfo +//------------------------------------------------------------------------------ +IMPLEMENT_SERVICE_INFO2(OViewContainer, "com.sun.star.sdb.dbaccess.OViewContainer", SERVICE_SDBCX_CONTAINER, SERVICE_SDBCX_TABLES) +// ----------------------------------------------------------------------------- +ObjectType OViewContainer::createObject(const ::rtl::OUString& _rName) +{ + ObjectType xProp; + if ( m_xMasterContainer.is() && m_xMasterContainer->hasByName(_rName) ) + xProp.set(m_xMasterContainer->getByName(_rName),UNO_QUERY); + + if ( !xProp.is() ) + { + ::rtl::OUString sCatalog,sSchema,sTable; + ::dbtools::qualifiedNameComponents(m_xMetaData, + _rName, + sCatalog, + sSchema, + sTable, + ::dbtools::eInDataManipulation); + return new View(m_xConnection, + isCaseSensitive(), + sCatalog, + sSchema, + sTable + ); + } + + return xProp; +} +// ----------------------------------------------------------------------------- +Reference< XPropertySet > OViewContainer::createDescriptor() +{ + Reference< XPropertySet > xRet; + // frist we have to look if the master tables does support this + // and if then create a table object as well with the master tables + Reference<XColumnsSupplier > xMasterColumnsSup; + Reference<XDataDescriptorFactory> xDataFactory(m_xMasterContainer,UNO_QUERY); + if(xDataFactory.is()) + xRet = xDataFactory->createDataDescriptor(); + else + xRet = new ::connectivity::sdbcx::OView(isCaseSensitive(),m_xMetaData); + + return xRet; +} +// ----------------------------------------------------------------------------- +// XAppend +ObjectType OViewContainer::appendObject( const ::rtl::OUString& _rForName, const Reference< XPropertySet >& descriptor ) +{ + // append the new table with a create stmt + ::rtl::OUString aName = getString(descriptor->getPropertyValue(PROPERTY_NAME)); + + Reference<XAppend> xAppend(m_xMasterContainer,UNO_QUERY); + Reference< XPropertySet > xProp = descriptor; + if(xAppend.is()) + { + EnsureReset aReset(m_nInAppend); + + xAppend->appendByDescriptor(descriptor); + if(m_xMasterContainer->hasByName(aName)) + xProp.set(m_xMasterContainer->getByName(aName),UNO_QUERY); + } + else + { + ::rtl::OUString sComposedName = ::dbtools::composeTableName( m_xMetaData, descriptor, ::dbtools::eInTableDefinitions, false, false, true ); + if(!sComposedName.getLength()) + ::dbtools::throwFunctionSequenceException(static_cast<XTypeProvider*>(static_cast<OFilteredContainer*>(this))); + + ::rtl::OUString sCommand; + descriptor->getPropertyValue(PROPERTY_COMMAND) >>= sCommand; + + ::rtl::OUStringBuffer aSQL; + aSQL.appendAscii( "CREATE VIEW " ); + aSQL.append ( sComposedName ); + aSQL.appendAscii( " AS " ); + aSQL.append ( sCommand ); + + Reference<XConnection> xCon = m_xConnection; + OSL_ENSURE(xCon.is(),"Connection is null!"); + if ( xCon.is() ) + { + ::utl::SharedUNOComponent< XStatement > xStmt( xCon->createStatement() ); + if ( xStmt.is() ) + xStmt->execute( aSQL.makeStringAndClear() ); + } + } + + return createObject( _rForName ); +} +// ------------------------------------------------------------------------- +// XDrop +void OViewContainer::dropObject(sal_Int32 _nPos,const ::rtl::OUString _sElementName) +{ + if ( !m_bInElementRemoved ) + { + Reference< XDrop > xDrop(m_xMasterContainer,UNO_QUERY); + if(xDrop.is()) + xDrop->dropByName(_sElementName); + else + { + ::rtl::OUString sCatalog,sSchema,sTable,sComposedName; + + Reference<XPropertySet> xTable(getObject(_nPos),UNO_QUERY); + if ( xTable.is() ) + { + xTable->getPropertyValue(PROPERTY_CATALOGNAME) >>= sCatalog; + xTable->getPropertyValue(PROPERTY_SCHEMANAME) >>= sSchema; + xTable->getPropertyValue(PROPERTY_NAME) >>= sTable; + + sComposedName = ::dbtools::composeTableName( m_xMetaData, sCatalog, sSchema, sTable, sal_True, ::dbtools::eInTableDefinitions ); + } + + if(!sComposedName.getLength()) + ::dbtools::throwFunctionSequenceException(static_cast<XTypeProvider*>(static_cast<OFilteredContainer*>(this))); + + ::rtl::OUString aSql = ::rtl::OUString::createFromAscii("DROP VIEW "); + aSql += sComposedName; + Reference<XConnection> xCon = m_xConnection; + OSL_ENSURE(xCon.is(),"Connection is null!"); + if ( xCon.is() ) + { + Reference< XStatement > xStmt = xCon->createStatement( ); + if(xStmt.is()) + xStmt->execute(aSql); + ::comphelper::disposeComponent(xStmt); + } + } + } +} +// ----------------------------------------------------------------------------- +void SAL_CALL OViewContainer::elementInserted( const ContainerEvent& Event ) throw (RuntimeException) +{ + ::osl::MutexGuard aGuard(m_rMutex); + ::rtl::OUString sName; + if ( ( Event.Accessor >>= sName ) + && ( !m_nInAppend ) + && ( !hasByName( sName ) ) + ) + { + Reference<XPropertySet> xProp(Event.Element,UNO_QUERY); + ::rtl::OUString sType; + xProp->getPropertyValue(PROPERTY_TYPE) >>= sType; + if ( sType == ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("VIEW")) ) + insertElement(sName,createObject(sName)); + } +} +// ----------------------------------------------------------------------------- +void SAL_CALL OViewContainer::elementRemoved( const ContainerEvent& Event ) throw (RuntimeException) +{ + ::osl::MutexGuard aGuard(m_rMutex); + ::rtl::OUString sName; + if ( (Event.Accessor >>= sName) && hasByName(sName) ) + { + m_bInElementRemoved = true; + try + { + dropByName(sName); + } + catch(Exception&) + { + m_bInElementRemoved = sal_False; + throw; + } + m_bInElementRemoved = false; + } +} +// ----------------------------------------------------------------------------- +void SAL_CALL OViewContainer::disposing( const ::com::sun::star::lang::EventObject& /*Source*/ ) throw (RuntimeException) +{ +} +// ----------------------------------------------------------------------------- +void SAL_CALL OViewContainer::elementReplaced( const ContainerEvent& /*Event*/ ) throw (RuntimeException) +{ +} +// ----------------------------------------------------------------------------- +::rtl::OUString OViewContainer::getTableTypeRestriction() const +{ + // no restriction at all (other than the ones provided externally) + return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "VIEW" ) ); +} |