diff options
Diffstat (limited to 'connectivity/source/drivers/dbase')
23 files changed, 7848 insertions, 0 deletions
diff --git a/connectivity/source/drivers/dbase/DCatalog.cxx b/connectivity/source/drivers/dbase/DCatalog.cxx new file mode 100644 index 000000000000..0935e492ff02 --- /dev/null +++ b/connectivity/source/drivers/dbase/DCatalog.cxx @@ -0,0 +1,70 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_connectivity.hxx" + + +#include "dbase/DCatalog.hxx" +#include "dbase/DConnection.hxx" +#include "dbase/DTables.hxx" +#include <com/sun/star/sdbc/XRow.hpp> +#include <com/sun/star/sdbc/XResultSet.hpp> + +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 connectivity::dbase; +// ------------------------------------------------------------------------- +ODbaseCatalog::ODbaseCatalog(ODbaseConnection* _pCon) : file::OFileCatalog(_pCon) +{ +} +// ------------------------------------------------------------------------- +void ODbaseCatalog::refreshTables() +{ + TStringVector aVector; + Sequence< ::rtl::OUString > aTypes; + Reference< XResultSet > xResult = m_xMetaData->getTables(Any(), + ::rtl::OUString::createFromAscii("%"),::rtl::OUString::createFromAscii("%"),aTypes); + + if(xResult.is()) + { + Reference< XRow > xRow(xResult,UNO_QUERY); + while(xResult->next()) + aVector.push_back(xRow->getString(3)); + } + if(m_pTables) + m_pTables->reFill(aVector); + else + m_pTables = new ODbaseTables(m_xMetaData,*this,m_aMutex,aVector); +} + + diff --git a/connectivity/source/drivers/dbase/DCode.cxx b/connectivity/source/drivers/dbase/DCode.cxx new file mode 100644 index 000000000000..d292c7ab5291 --- /dev/null +++ b/connectivity/source/drivers/dbase/DCode.cxx @@ -0,0 +1,131 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_connectivity.hxx" +#include "dbase/DCode.hxx" +#include <com/sun/star/sdbcx/XColumnsSupplier.hpp> +#include "dbase/DIndex.hxx" +#include "dbase/DIndexIter.hxx" + + +using namespace connectivity::dbase; +using namespace connectivity::file; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::container; + +TYPEINIT1(OFILEOperandAttr, OOperandAttr); +// ----------------------------------------------------------------------------- +OOperandAttr* OFILEAnalyzer::createOperandAttr(sal_Int32 _nPos, + const Reference< XPropertySet>& _xCol, + const Reference< XNameAccess>& _xIndexes) +{ + return new OFILEOperandAttr((sal_uInt16)_nPos,_xCol,_xIndexes); +} + +//------------------------------------------------------------------ +OFILEOperandAttr::OFILEOperandAttr(sal_uInt16 _nPos, + const Reference< XPropertySet>& _xColumn, + const Reference< XNameAccess>& _xIndexes) + : OOperandAttr(_nPos,_xColumn) +{ + if(_xIndexes.is()) + { + ::rtl::OUString sName; + Reference<XPropertySetInfo> xColInfo = _xColumn->getPropertySetInfo(); + Reference<XPropertySet> xIndex; + + Sequence< ::rtl::OUString> aSeq = _xIndexes->getElementNames(); + const ::rtl::OUString* pBegin = aSeq.getConstArray(); + const ::rtl::OUString* pEnd = pBegin + aSeq.getLength(); + for(;pBegin != pEnd;++pBegin) + { + _xIndexes->getByName(*pBegin) >>= xIndex; + if(xIndex.is()) + { + Reference<XColumnsSupplier> xColsSup(xIndex,UNO_QUERY); + Reference<XNameAccess> xNameAccess = xColsSup->getColumns(); + _xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_NAME)) >>= sName; + if(xNameAccess->hasByName(sName)) + { + m_xIndex = xIndex; + break; + } + else if(xColInfo->hasPropertyByName(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_REALNAME))) + { + _xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_REALNAME)) >>= sName; + if(xNameAccess->hasByName(sName)) + { + m_xIndex = xIndex; + break; + } + } + } + } + } + +} +// ------------------------------------------------------------------------- +sal_Bool OFILEOperandAttr::isIndexed() const +{ + return m_xIndex.is(); +} +//------------------------------------------------------------------ +OEvaluateSet* OFILEOperandAttr::preProcess(OBoolOperator* pOp, OOperand* pRight) +{ + OEvaluateSet* pEvaluateSet = NULL; + if (isIndexed()) + { + Reference<XUnoTunnel> xTunnel(m_xIndex,UNO_QUERY); + if(xTunnel.is()) + { + ODbaseIndex* pIndex = reinterpret_cast< ODbaseIndex* >( xTunnel->getSomething(ODbaseIndex::getUnoTunnelImplementationId()) ); + if(pIndex) + { + OIndexIterator* pIter = pIndex->createIterator(pOp,pRight); + + if (pIter) + { + pEvaluateSet = new OEvaluateSet(); + ULONG nRec = pIter->First(); + while (nRec != NODE_NOTFOUND) + { + (*pEvaluateSet)[nRec] = nRec; + nRec = pIter->Next(); + } + } + delete pIter; + } + } + } + return pEvaluateSet; +} + + diff --git a/connectivity/source/drivers/dbase/DColumns.cxx b/connectivity/source/drivers/dbase/DColumns.cxx new file mode 100644 index 000000000000..2f6eee5aba98 --- /dev/null +++ b/connectivity/source/drivers/dbase/DColumns.cxx @@ -0,0 +1,91 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_connectivity.hxx" +#include "dbase/DColumns.hxx" +#include "dbase/DTable.hxx" +#include "connectivity/sdbcx/VColumn.hxx" +#include <com/sun/star/lang/IndexOutOfBoundsException.hpp> +#include <comphelper/property.hxx> + +using namespace connectivity::dbase; +using namespace connectivity; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::container; + +typedef file::OColumns ODbaseColumns_BASE; +sdbcx::ObjectType ODbaseColumns::createObject(const ::rtl::OUString& _rName) +{ + + ODbaseTable* pTable = (ODbaseTable*)m_pTable; + + // Reference< XFastPropertySet> xCol(pTable->getColumns()[_rName],UNO_QUERY); + ::vos::ORef<OSQLColumns> aCols = pTable->getTableColumns(); + OSQLColumns::Vector::const_iterator aIter = find(aCols->get().begin(),aCols->get().end(),_rName,::comphelper::UStringMixEqual(isCaseSensitive())); + + sdbcx::ObjectType xRet; + if(aIter != aCols->get().end()) + xRet = sdbcx::ObjectType(*aIter,UNO_QUERY); + return xRet; +} + +// ------------------------------------------------------------------------- +void ODbaseColumns::impl_refresh() throw(RuntimeException) +{ + m_pTable->refreshColumns(); +} +// ------------------------------------------------------------------------- +Reference< XPropertySet > ODbaseColumns::createDescriptor() +{ + return new sdbcx::OColumn(isCaseSensitive()); +} +// ----------------------------------------------------------------------------- +// ------------------------------------------------------------------------- +// XAppend +sdbcx::ObjectType ODbaseColumns::appendObject( const ::rtl::OUString& _rForName, const Reference< XPropertySet >& descriptor ) +{ + if ( m_pTable->isNew() ) + return cloneDescriptor( descriptor ); + + m_pTable->addColumn( descriptor ); + return createObject( _rForName ); +} +// ----------------------------------------------------------------------------- +// ------------------------------------------------------------------------- +// XDrop +void ODbaseColumns::dropObject(sal_Int32 _nPos,const ::rtl::OUString /*_sElementName*/) +{ + if(!m_pTable->isNew()) + m_pTable->dropColumn(_nPos); +} +// ----------------------------------------------------------------------------- + diff --git a/connectivity/source/drivers/dbase/DConnection.cxx b/connectivity/source/drivers/dbase/DConnection.cxx new file mode 100644 index 000000000000..530df50e1674 --- /dev/null +++ b/connectivity/source/drivers/dbase/DConnection.cxx @@ -0,0 +1,135 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_connectivity.hxx" + +#ifndef _CONNECTIVITY_DBASE_OCONNECTION_HXX_ +#include "dbase/DConnection.hxx" +#endif +#include "dbase/DDatabaseMetaData.hxx" +#include "dbase/DCatalog.hxx" +#ifndef _CONNECTIVITY_DBASE_ODRIVER_HXX_ +#include "dbase/DDriver.hxx" +#endif +#include <com/sun/star/lang/DisposedException.hpp> +#include <tools/urlobj.hxx> +#include "dbase/DPreparedStatement.hxx" +#include "dbase/DStatement.hxx" +#include <tools/debug.hxx> +#include <connectivity/dbexception.hxx> + +using namespace connectivity::dbase; +using namespace connectivity::file; + +typedef connectivity::file::OConnection OConnection_BASE; + +//------------------------------------------------------------------------------ +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::lang; + +DBG_NAME(ODbaseConnection) +// -------------------------------------------------------------------------------- +ODbaseConnection::ODbaseConnection(ODriver* _pDriver) : OConnection(_pDriver) +{ + DBG_CTOR(ODbaseConnection,NULL); + m_aFilenameExtension = String::CreateFromAscii("dbf"); +} +//----------------------------------------------------------------------------- +ODbaseConnection::~ODbaseConnection() +{ + DBG_DTOR(ODbaseConnection,NULL); +} + +// XServiceInfo +// -------------------------------------------------------------------------------- +IMPLEMENT_SERVICE_INFO(ODbaseConnection, "com.sun.star.sdbc.drivers.dbase.Connection", "com.sun.star.sdbc.Connection") + +// -------------------------------------------------------------------------------- +Reference< XDatabaseMetaData > SAL_CALL ODbaseConnection::getMetaData( ) throw(SQLException, RuntimeException) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(OConnection_BASE::rBHelper.bDisposed); + + + Reference< XDatabaseMetaData > xMetaData = m_xMetaData; + if(!xMetaData.is()) + { + xMetaData = new ODbaseDatabaseMetaData(this); + m_xMetaData = xMetaData; + } + + return xMetaData; +} +//------------------------------------------------------------------------------ +::com::sun::star::uno::Reference< XTablesSupplier > ODbaseConnection::createCatalog() +{ + ::osl::MutexGuard aGuard( m_aMutex ); + Reference< XTablesSupplier > xTab = m_xCatalog; + if(!xTab.is()) + { + ODbaseCatalog *pCat = new ODbaseCatalog(this); + xTab = pCat; + m_xCatalog = xTab; + } + return xTab; +} +// -------------------------------------------------------------------------------- +Reference< XStatement > SAL_CALL ODbaseConnection::createStatement( ) throw(SQLException, RuntimeException) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(OConnection_BASE::rBHelper.bDisposed); + + + Reference< XStatement > xReturn = new ODbaseStatement(this); + m_aStatements.push_back(WeakReferenceHelper(xReturn)); + return xReturn; +} +// -------------------------------------------------------------------------------- +Reference< XPreparedStatement > SAL_CALL ODbaseConnection::prepareStatement( const ::rtl::OUString& sql ) throw(SQLException, RuntimeException) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(OConnection_BASE::rBHelper.bDisposed); + + + ODbasePreparedStatement* pStmt = new ODbasePreparedStatement(this); + Reference< XPreparedStatement > xHoldAlive = pStmt; + pStmt->construct(sql); + m_aStatements.push_back(WeakReferenceHelper(*pStmt)); + return pStmt; +} +// -------------------------------------------------------------------------------- +Reference< XPreparedStatement > SAL_CALL ODbaseConnection::prepareCall( const ::rtl::OUString& /*sql*/ ) throw(SQLException, RuntimeException) +{ + ::dbtools::throwFeatureNotImplementedException( "XConnection::prepareCall", *this ); + return NULL; +} +// ----------------------------------------------------------------------------- + diff --git a/connectivity/source/drivers/dbase/DDatabaseMetaData.cxx b/connectivity/source/drivers/dbase/DDatabaseMetaData.cxx new file mode 100644 index 000000000000..1e9b565cc4d7 --- /dev/null +++ b/connectivity/source/drivers/dbase/DDatabaseMetaData.cxx @@ -0,0 +1,416 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_connectivity.hxx" + + +#ifndef _CONNECTIVITY_DBASE_ODbaseDatabaseMetaData_HXX_ +#include "dbase/DDatabaseMetaData.hxx" +#endif +#include <com/sun/star/sdbc/DataType.hpp> +#include <com/sun/star/sdbc/ResultSetType.hpp> +#include <com/sun/star/sdbc/ColumnValue.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/sdbc/ResultSetConcurrency.hpp> +#include <com/sun/star/sdbcx/XColumnsSupplier.hpp> +#include <com/sun/star/sdbcx/XIndexesSupplier.hpp> +#include <tools/urlobj.hxx> +#include "FDatabaseMetaDataResultSet.hxx" +#include <com/sun/star/lang/XUnoTunnel.hpp> +#include "dbase/DIndex.hxx" +#include "connectivity/FValue.hxx" +#include <comphelper/extract.hxx> +#include <comphelper/types.hxx> +#include <ucbhelper/content.hxx> +#include <rtl/logfile.hxx> + +using namespace ::comphelper; +using namespace connectivity::dbase; +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::ucb; +using namespace ::com::sun::star::lang; + +ODbaseDatabaseMetaData::ODbaseDatabaseMetaData(::connectivity::file::OConnection* _pCon) :ODatabaseMetaData(_pCon) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbase", "Ocke.Janssen@sun.com", "ODbaseDatabaseMetaData::ODbaseDatabaseMetaData" ); +} +// ------------------------------------------------------------------------- +ODbaseDatabaseMetaData::~ODbaseDatabaseMetaData() +{ +} +// ------------------------------------------------------------------------- +Reference< XResultSet > ODbaseDatabaseMetaData::impl_getTypeInfo_throw( ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbase", "Ocke.Janssen@sun.com", "ODbaseDatabaseMetaData::impl_getTypeInfo_throw" ); + ::osl::MutexGuard aGuard( m_aMutex ); + + ::connectivity::ODatabaseMetaDataResultSet* pResult = new ::connectivity::ODatabaseMetaDataResultSet(::connectivity::ODatabaseMetaDataResultSet::eTypeInfo); + Reference< XResultSet > xRef = pResult; + + static ODatabaseMetaDataResultSet::ORows aRows; + if(aRows.empty()) + { + ODatabaseMetaDataResultSet::ORow aRow; + aRow.reserve(18); + + aRow.push_back(ODatabaseMetaDataResultSet::getEmptyValue()); + aRow.push_back(new ORowSetValueDecorator(::rtl::OUString::createFromAscii("VARCHAR"))); + aRow.push_back(new ORowSetValueDecorator(DataType::VARCHAR)); + aRow.push_back(new ORowSetValueDecorator((sal_Int32)254)); + aRow.push_back(ODatabaseMetaDataResultSet::getQuoteValue()); + aRow.push_back(ODatabaseMetaDataResultSet::getQuoteValue()); + aRow.push_back(new ORowSetValueDecorator(::rtl::OUString::createFromAscii("length"))); + aRow.push_back(new ORowSetValueDecorator((sal_Int32)ColumnValue::NULLABLE)); + aRow.push_back(ODatabaseMetaDataResultSet::get1Value()); + aRow.push_back(new ORowSetValueDecorator((sal_Int32)ColumnSearch::FULL)); + aRow.push_back(ODatabaseMetaDataResultSet::get1Value()); + aRow.push_back(ODatabaseMetaDataResultSet::get0Value()); + aRow.push_back(ODatabaseMetaDataResultSet::get0Value()); + aRow.push_back(new ORowSetValueDecorator(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("C")))); + aRow.push_back(ODatabaseMetaDataResultSet::get0Value()); + aRow.push_back(ODatabaseMetaDataResultSet::get0Value()); + aRow.push_back(ODatabaseMetaDataResultSet::getEmptyValue()); + aRow.push_back(ODatabaseMetaDataResultSet::getEmptyValue()); + aRow.push_back(new ORowSetValueDecorator((sal_Int32)10)); + + aRows.push_back(aRow); + + aRow[1] = new ORowSetValueDecorator(::rtl::OUString::createFromAscii("LONGVARCHAR")); + aRow[2] = new ORowSetValueDecorator(DataType::LONGVARCHAR); + aRow[3] = new ORowSetValueDecorator((sal_Int32)2147483647); + aRow[6] = new ORowSetValueDecorator(); + aRow[13] = new ORowSetValueDecorator(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("M"))); + aRows.push_back(aRow); + + aRow[1] = new ORowSetValueDecorator(::rtl::OUString::createFromAscii("DATE")); + aRow[2] = new ORowSetValueDecorator(DataType::DATE); + aRow[3] = new ORowSetValueDecorator((sal_Int32)10); + aRow[13] = new ORowSetValueDecorator(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("D"))); + aRows.push_back(aRow); + + aRow[1] = new ORowSetValueDecorator(::rtl::OUString::createFromAscii("BOOLEAN")); + aRow[2] = new ORowSetValueDecorator(DataType::BIT); + aRow[3] = ODatabaseMetaDataResultSet::get1Value(); + aRow[4] = ODatabaseMetaDataResultSet::getEmptyValue(); + aRow[5] = ODatabaseMetaDataResultSet::getEmptyValue(); + aRow[6] = new ORowSetValueDecorator(::rtl::OUString()); + aRow[9] = ODatabaseMetaDataResultSet::getBasicValue(); + aRow[13] = new ORowSetValueDecorator(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("L"))); + aRows.push_back(aRow); + + aRow[1] = new ORowSetValueDecorator(::rtl::OUString::createFromAscii("DOUBLE")); + aRow[2] = new ORowSetValueDecorator(DataType::DOUBLE); + aRow[3] = new ORowSetValueDecorator((sal_Int32)8); + aRow[13] = new ORowSetValueDecorator(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("B"))); + aRows.push_back(aRow); + + aRow[11] = new ORowSetValueDecorator(sal_True); + aRow[13] = new ORowSetValueDecorator(::rtl::OUString::createFromAscii("Y")); + aRows.push_back(aRow); + + aRow[1] = new ORowSetValueDecorator(::rtl::OUString::createFromAscii("TIMESTAMP")); + aRow[2] = new ORowSetValueDecorator(DataType::TIMESTAMP); + aRow[11] = new ORowSetValueDecorator(sal_False); + aRow[13] = new ORowSetValueDecorator(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("T"))); + aRows.push_back(aRow); + + aRow[1] = new ORowSetValueDecorator(::rtl::OUString::createFromAscii("INTEGER")); + aRow[2] = new ORowSetValueDecorator(DataType::INTEGER); + aRow[3] = new ORowSetValueDecorator((sal_Int32)10); + aRow[13] = new ORowSetValueDecorator(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("I"))); + aRows.push_back(aRow); + + aRow[1] = new ORowSetValueDecorator(::rtl::OUString::createFromAscii("DECIMAL")); + aRow[2] = new ORowSetValueDecorator(DataType::DECIMAL); + aRow[3] = new ORowSetValueDecorator((sal_Int32)20); + aRow[6] = new ORowSetValueDecorator(::rtl::OUString::createFromAscii("length,scale")); + aRow[13] = new ORowSetValueDecorator(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("F"))); + aRows.push_back(aRow); + + aRow[1] = new ORowSetValueDecorator(::rtl::OUString::createFromAscii("NUMERIC")); + aRow[2] = new ORowSetValueDecorator(DataType::DECIMAL); + aRow[3] = new ORowSetValueDecorator((sal_Int32)16); + aRow[13] = new ORowSetValueDecorator(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("N"))); + aRow[15] = new ORowSetValueDecorator((sal_Int32)16); + aRows.push_back(aRow); + } + + pResult->setRows(aRows); + return xRef; +} +// ------------------------------------------------------------------------- +Reference< XResultSet > SAL_CALL ODbaseDatabaseMetaData::getColumns( + const Any& /*catalog*/, const ::rtl::OUString& /*schemaPattern*/, const ::rtl::OUString& tableNamePattern, + const ::rtl::OUString& columnNamePattern ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbase", "Ocke.Janssen@sun.com", "ODbaseDatabaseMetaData::getColumns" ); + ::osl::MutexGuard aGuard( m_aMutex ); + + + Reference< XTablesSupplier > xTables = m_pConnection->createCatalog(); + if(!xTables.is()) + throw SQLException(); + + Reference< XNameAccess> xNames = xTables->getTables(); + if(!xNames.is()) + throw SQLException(); + + ODatabaseMetaDataResultSet::ORows aRows; + ODatabaseMetaDataResultSet::ORow aRow(19); + + aRow[10] = new ORowSetValueDecorator((sal_Int32)10); + Sequence< ::rtl::OUString> aTabNames(xNames->getElementNames()); + const ::rtl::OUString* pTabBegin = aTabNames.getConstArray(); + const ::rtl::OUString* pTabEnd = pTabBegin + aTabNames.getLength(); + for(;pTabBegin != pTabEnd;++pTabBegin) + { + if(match(tableNamePattern,*pTabBegin,'\0')) + { + Reference< XColumnsSupplier> xTable; + ::cppu::extractInterface(xTable,xNames->getByName(*pTabBegin)); + OSL_ENSURE(xTable.is(),"Table not found! Normallya exception had to be thrown here!"); + aRow[3] = new ORowSetValueDecorator(*pTabBegin); + + Reference< XNameAccess> xColumns = xTable->getColumns(); + if(!xColumns.is()) + throw SQLException(); + + Sequence< ::rtl::OUString> aColNames(xColumns->getElementNames()); + + const ::rtl::OUString* pBegin = aColNames.getConstArray(); + const ::rtl::OUString* pEnd = pBegin + aColNames.getLength(); + Reference< XPropertySet> xColumn; + for(sal_Int32 i=1;pBegin != pEnd;++pBegin,++i) + { + if(match(columnNamePattern,*pBegin,'\0')) + { + aRow[4] = new ORowSetValueDecorator(*pBegin); + + ::cppu::extractInterface(xColumn,xColumns->getByName(*pBegin)); + OSL_ENSURE(xColumn.is(),"Columns contains a column who isn't a fastpropertyset!"); + aRow[5] = new ORowSetValueDecorator(getINT32(xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_TYPE)))); + aRow[6] = new ORowSetValueDecorator(getString(xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_TYPENAME)))); + aRow[7] = new ORowSetValueDecorator(getINT32(xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_PRECISION)))); + aRow[9] = new ORowSetValueDecorator(getINT32(xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_SCALE)))); + aRow[11] = new ORowSetValueDecorator(getINT32(xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_ISNULLABLE)))); + aRow[13] = new ORowSetValueDecorator(getString(xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_DEFAULTVALUE)))); + switch((sal_Int32)aRow[5]->getValue()) + { + case DataType::CHAR: + case DataType::VARCHAR: + aRow[16] = new ORowSetValueDecorator((sal_Int32)254); + break; + case DataType::LONGVARCHAR: + aRow[16] = new ORowSetValueDecorator((sal_Int32)65535); + break; + default: + aRow[16] = new ORowSetValueDecorator((sal_Int32)0); + } + aRow[17] = new ORowSetValueDecorator(i); + switch(sal_Int32(aRow[11]->getValue())) + { + case ColumnValue::NO_NULLS: + aRow[18] = new ORowSetValueDecorator(::rtl::OUString::createFromAscii("NO")); + break; + case ColumnValue::NULLABLE: + aRow[18] = new ORowSetValueDecorator(::rtl::OUString::createFromAscii("YES")); + break; + default: + aRow[18] = new ORowSetValueDecorator(::rtl::OUString()); + } + aRows.push_back(aRow); + } + } + } + } + ::connectivity::ODatabaseMetaDataResultSet* pResult = new ::connectivity::ODatabaseMetaDataResultSet(::connectivity::ODatabaseMetaDataResultSet::eColumns); + Reference< XResultSet > xRef = pResult; + pResult->setRows(aRows); + + return xRef; +} +// ------------------------------------------------------------------------- +Reference< XResultSet > SAL_CALL ODbaseDatabaseMetaData::getIndexInfo( + const Any& /*catalog*/, const ::rtl::OUString& /*schema*/, const ::rtl::OUString& table, + sal_Bool unique, sal_Bool /*approximate*/ ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbase", "Ocke.Janssen@sun.com", "ODbaseDatabaseMetaData::getIndexInfo" ); + ::osl::MutexGuard aGuard( m_aMutex ); + + Reference< XTablesSupplier > xTables = m_pConnection->createCatalog(); + if(!xTables.is()) + throw SQLException(); + + Reference< XNameAccess> xNames = xTables->getTables(); + if(!xNames.is()) + throw SQLException(); + + ODatabaseMetaDataResultSet::ORows aRows; + ODatabaseMetaDataResultSet::ORow aRow(14); + + aRow[5] = new ORowSetValueDecorator(::rtl::OUString()); + aRow[10] = new ORowSetValueDecorator(::rtl::OUString::createFromAscii("A")); + + Reference< XIndexesSupplier> xTable; + ::cppu::extractInterface(xTable,xNames->getByName(table)); + aRow[3] = new ORowSetValueDecorator(table); + aRow[7] = new ORowSetValueDecorator((sal_Int32)3); + + Reference< XNameAccess> xIndexes = xTable->getIndexes(); + if(!xIndexes.is()) + throw SQLException(); + + Sequence< ::rtl::OUString> aIdxNames(xIndexes->getElementNames()); + + const ::rtl::OUString* pBegin = aIdxNames.getConstArray(); + const ::rtl::OUString* pEnd = pBegin + aIdxNames.getLength(); + Reference< XPropertySet> xIndex; + for(;pBegin != pEnd;++pBegin) + { + ::cppu::extractInterface(xIndex,xIndexes->getByName(*pBegin)); + OSL_ENSURE(xIndex.is(),"Indexes contains a column who isn't a fastpropertyset!"); + + if(unique && !getBOOL(xIndex->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_ISUNIQUE)))) + continue; + aRow[4] = new ORowSetValueDecorator(getBOOL(xIndex->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_ISUNIQUE)))); + aRow[6] = new ORowSetValueDecorator(*pBegin); + + Reference< XUnoTunnel> xTunnel(xIndex,UNO_QUERY); + if(xTunnel.is()) + { + ODbaseIndex* pIndex = reinterpret_cast< ODbaseIndex* >( xTunnel->getSomething(ODbaseIndex::getUnoTunnelImplementationId()) ); + if(pIndex) + { + aRow[11] = new ORowSetValueDecorator((sal_Int32)pIndex->getHeader().db_maxkeys); + aRow[12] = new ORowSetValueDecorator((sal_Int32)pIndex->getHeader().db_pagecount); + } + } + + Reference<XColumnsSupplier> xColumnsSup(xIndex,UNO_QUERY); + Reference< XNameAccess> xColumns = xColumnsSup->getColumns(); + Sequence< ::rtl::OUString> aColNames(xColumns->getElementNames()); + + const ::rtl::OUString* pColBegin = aColNames.getConstArray(); + const ::rtl::OUString* pColEnd = pColBegin + aColNames.getLength(); + Reference< XPropertySet> xColumn; + for(sal_Int32 j=1;pColBegin != pColEnd;++pColBegin,++j) + { + // xColumns->getByName(*pColBegin) >>= xColumn; + aRow[8] = new ORowSetValueDecorator(j); + aRow[9] = new ORowSetValueDecorator(*pColBegin); + aRows.push_back(aRow); + } + } + + ::connectivity::ODatabaseMetaDataResultSet* pResult = new ::connectivity::ODatabaseMetaDataResultSet(::connectivity::ODatabaseMetaDataResultSet::eIndexInfo); + Reference< XResultSet > xRef = pResult; + pResult->setRows(aRows); + return xRef; +} +// ------------------------------------------------------------------------- +::rtl::OUString SAL_CALL ODbaseDatabaseMetaData::getURL( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbase", "Ocke.Janssen@sun.com", "ODbaseDatabaseMetaData::getURL" ); + ::osl::MutexGuard aGuard( m_aMutex ); + return ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("sdbc:dbase:")) + m_pConnection->getURL(); +} +// ------------------------------------------------------------------------- +sal_Int32 SAL_CALL ODbaseDatabaseMetaData::getMaxBinaryLiteralLength( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbase", "Ocke.Janssen@sun.com", "ODbaseDatabaseMetaData::getMaxBinaryLiteralLength" ); + return STRING_MAXLEN; +} +// ------------------------------------------------------------------------- +sal_Int32 SAL_CALL ODbaseDatabaseMetaData::getMaxCharLiteralLength( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbase", "Ocke.Janssen@sun.com", "ODbaseDatabaseMetaData::getMaxCharLiteralLength" ); + return 254; +} +// ------------------------------------------------------------------------- +sal_Int32 SAL_CALL ODbaseDatabaseMetaData::getMaxColumnNameLength( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbase", "Ocke.Janssen@sun.com", "ODbaseDatabaseMetaData::getMaxColumnNameLength" ); + return 10; +} +// ------------------------------------------------------------------------- +sal_Int32 SAL_CALL ODbaseDatabaseMetaData::getMaxColumnsInIndex( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbase", "Ocke.Janssen@sun.com", "ODbaseDatabaseMetaData::getMaxColumnsInIndex" ); + return 1; +} +// ------------------------------------------------------------------------- +sal_Int32 SAL_CALL ODbaseDatabaseMetaData::getMaxColumnsInTable( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbase", "Ocke.Janssen@sun.com", "ODbaseDatabaseMetaData::getMaxColumnsInTable" ); + return 128; +} +// ----------------------------------------------------------------------------- +sal_Bool SAL_CALL ODbaseDatabaseMetaData::supportsAlterTableWithAddColumn( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbase", "Ocke.Janssen@sun.com", "ODbaseDatabaseMetaData::supportsAlterTableWithAddColumn" ); + return sal_True; +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL ODbaseDatabaseMetaData::supportsAlterTableWithDropColumn( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbase", "Ocke.Janssen@sun.com", "ODbaseDatabaseMetaData::supportsAlterTableWithDropColumn" ); + return sal_False; +} +// ----------------------------------------------------------------------------- +sal_Bool SAL_CALL ODbaseDatabaseMetaData::isReadOnly( ) throw(SQLException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbase", "Ocke.Janssen@sun.com", "ODbaseDatabaseMetaData::isReadOnly" ); + ::osl::MutexGuard aGuard( m_aMutex ); + + sal_Bool bReadOnly = sal_False; + static ::rtl::OUString sReadOnly = ::rtl::OUString::createFromAscii("IsReadOnly"); + ::ucbhelper::Content aFile(m_pConnection->getContent(),Reference< XCommandEnvironment >()); + aFile.getPropertyValue(sReadOnly) >>= bReadOnly; + + return bReadOnly; +} +// ----------------------------------------------------------------------------- +sal_Bool ODbaseDatabaseMetaData::impl_storesMixedCaseQuotedIdentifiers_throw( ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbase", "Ocke.Janssen@sun.com", "ODbaseDatabaseMetaData::impl_storesMixedCaseQuotedIdentifiers_throw" ); + return sal_True; +} +// ----------------------------------------------------------------------------- +sal_Bool ODbaseDatabaseMetaData::impl_supportsMixedCaseQuotedIdentifiers_throw( ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbase", "Ocke.Janssen@sun.com", "ODbaseDatabaseMetaData::impl_supportsMixedCaseQuotedIdentifiers_throw" ); + return sal_True; +} +// ----------------------------------------------------------------------------- + + diff --git a/connectivity/source/drivers/dbase/DDriver.cxx b/connectivity/source/drivers/dbase/DDriver.cxx new file mode 100644 index 000000000000..7281ac4036c2 --- /dev/null +++ b/connectivity/source/drivers/dbase/DDriver.cxx @@ -0,0 +1,127 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_connectivity.hxx" +#include "dbase/DDriver.hxx" +#include "dbase/DConnection.hxx" +#include <com/sun/star/lang/DisposedException.hpp> +#include "connectivity/dbexception.hxx" +#include "resource/dbase_res.hrc" + +using namespace connectivity::dbase; +using namespace connectivity::file; +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::lang; + + +// static ServiceInfo +//------------------------------------------------------------------------------ +rtl::OUString ODriver::getImplementationName_Static( ) throw(RuntimeException) +{ + return rtl::OUString::createFromAscii("com.sun.star.comp.sdbc.dbase.ODriver"); +} + +//------------------------------------------------------------------ +::rtl::OUString SAL_CALL ODriver::getImplementationName( ) throw(RuntimeException) +{ + return getImplementationName_Static(); +} + +//------------------------------------------------------------------ +::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL connectivity::dbase::ODriver_CreateInstance(const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& _rxFactory) throw( ::com::sun::star::uno::Exception ) +{ + return *(new ODriver(_rxFactory)); +} +// -------------------------------------------------------------------------------- +Reference< XConnection > SAL_CALL ODriver::connect( const ::rtl::OUString& url, const Sequence< PropertyValue >& info ) throw(SQLException, RuntimeException) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + if (ODriver_BASE::rBHelper.bDisposed) + throw DisposedException(); + + if ( ! acceptsURL(url) ) + return NULL; + + ODbaseConnection* pCon = new ODbaseConnection(this); + pCon->construct(url,info); + Reference< XConnection > xCon = pCon; + m_xConnections.push_back(WeakReferenceHelper(*pCon)); + + return xCon; +} +// -------------------------------------------------------------------------------- +sal_Bool SAL_CALL ODriver::acceptsURL( const ::rtl::OUString& url ) throw(SQLException, RuntimeException) +{ + return !url.compareTo(::rtl::OUString::createFromAscii("sdbc:dbase:"),11); +} +// ----------------------------------------------------------------------------- +Sequence< DriverPropertyInfo > SAL_CALL ODriver::getPropertyInfo( const ::rtl::OUString& url, const Sequence< PropertyValue >& /*info*/ ) throw(SQLException, RuntimeException) +{ + if ( acceptsURL(url) ) + { + ::std::vector< DriverPropertyInfo > aDriverInfo; + + Sequence< ::rtl::OUString > aBoolean(2); + aBoolean[0] = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("0")); + aBoolean[1] = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("1")); + + aDriverInfo.push_back(DriverPropertyInfo( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("CharSet")) + ,::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("CharSet of the database.")) + ,sal_False + ,::rtl::OUString() + ,Sequence< ::rtl::OUString >()) + ); + aDriverInfo.push_back(DriverPropertyInfo( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ShowDeleted")) + ,::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Display inactive records.")) + ,sal_False + ,::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("0")) + ,aBoolean) + ); + aDriverInfo.push_back(DriverPropertyInfo( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("EnableSQL92Check")) + ,::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Use SQL92 naming constraints.")) + ,sal_False + ,::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("0")) + ,aBoolean) + ); + return Sequence< DriverPropertyInfo >(&(aDriverInfo[0]),aDriverInfo.size()); + } + + SharedResources aResources; + const ::rtl::OUString sMessage = aResources.getResourceString(STR_URI_SYNTAX_ERROR); + ::dbtools::throwGenericSQLException(sMessage ,*this); + return Sequence< DriverPropertyInfo >(); +} +// ----------------------------------------------------------------------------- + + diff --git a/connectivity/source/drivers/dbase/DIndex.cxx b/connectivity/source/drivers/dbase/DIndex.cxx new file mode 100644 index 000000000000..c7e64beeef1a --- /dev/null +++ b/connectivity/source/drivers/dbase/DIndex.cxx @@ -0,0 +1,679 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_connectivity.hxx" +#include "dbase/DIndex.hxx" +#include "dbase/DIndexColumns.hxx" +#include <com/sun/star/lang/DisposedException.hpp> +#include "connectivity/sdbcx/VColumn.hxx" +#include <comphelper/sequence.hxx> +#include "dbase/DTable.hxx" +#include "dbase/DIndexIter.hxx" +#include <tools/config.hxx> +#include "connectivity/CommonTools.hxx" +#include <com/sun/star/sdbc/XResultSetMetaData.hpp> +#include <com/sun/star/sdbc/XResultSet.hpp> +#include <com/sun/star/sdbcx/XRowLocate.hpp> +#include <com/sun/star/sdbc/XRow.hpp> +#include <comphelper/extract.hxx> +#include <unotools/localfilehelper.hxx> +#include <unotools/ucbhelper.hxx> +#include <comphelper/types.hxx> +#include <connectivity/dbexception.hxx> +#include "dbase/DResultSet.hxx" +#include "diagnose_ex.h" +#include <comphelper/types.hxx> +#include "resource/dbase_res.hrc" +#include <unotools/sharedunocomponent.hxx> + +using namespace ::comphelper; +// ------------------------------------------------------------------------- +using namespace connectivity; +using namespace utl; +using namespace ::cppu; +using namespace connectivity::file; +using namespace connectivity::sdbcx; +using namespace connectivity::dbase; +using namespace com::sun::star::sdbc; +using namespace com::sun::star::sdbcx; +using namespace com::sun::star::uno; +using namespace com::sun::star::beans; +using namespace com::sun::star::lang; + +IMPLEMENT_SERVICE_INFO(ODbaseIndex,"com.sun.star.sdbcx.driver.dbase.Index","com.sun.star.sdbcx.Index"); +// ------------------------------------------------------------------------- +ODbaseIndex::ODbaseIndex(ODbaseTable* _pTable) : OIndex(sal_True/*_pTable->getConnection()->getMetaData()->storesMixedCaseQuotedIdentifiers()*/) + ,m_pFileStream(NULL) + ,m_nCurNode(NODE_NOTFOUND) + ,m_pTable(_pTable) +{ + m_aHeader.db_pagecount = m_aHeader.db_rootpage = m_aHeader.db_keytype = m_aHeader.db_maxkeys = m_aHeader.db_keylen = 0; + m_aHeader.db_name[0] = '\0'; + construct(); +} +// ------------------------------------------------------------------------- +ODbaseIndex::ODbaseIndex( ODbaseTable* _pTable, + const NDXHeader& _rHeader, + const ::rtl::OUString& _rName) + :OIndex(_rName,::rtl::OUString(),_rHeader.db_unique,sal_False,sal_False,sal_True) // _pTable->getConnection()->getMetaData()->storesMixedCaseQuotedIdentifiers() + ,m_pFileStream(NULL) + ,m_aHeader(_rHeader) + ,m_nCurNode(NODE_NOTFOUND) + ,m_pTable(_pTable) +{ + construct(); +} +// ----------------------------------------------------------------------------- +ODbaseIndex::~ODbaseIndex() +{ + closeImpl(); +} +// ------------------------------------------------------------------------- +void ODbaseIndex::refreshColumns() +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + TStringVector aVector; + if(!isNew()) + { + OSL_ENSURE(m_pFileStream,"FileStream is not opened!"); + OSL_ENSURE(m_aHeader.db_name[0] != '\0',"Invalid name for the column!"); + aVector.push_back(::rtl::OUString::createFromAscii(m_aHeader.db_name)); + } + + if(m_pColumns) + m_pColumns->reFill(aVector); + else + m_pColumns = new ODbaseIndexColumns(this,m_aMutex,aVector); +} +//-------------------------------------------------------------------------- +Sequence< sal_Int8 > ODbaseIndex::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(); +} + +// XUnoTunnel +//------------------------------------------------------------------ +sal_Int64 ODbaseIndex::getSomething( const Sequence< sal_Int8 > & rId ) throw (RuntimeException) +{ + return (rId.getLength() == 16 && 0 == rtl_compareMemory(getUnoTunnelImplementationId().getConstArray(), rId.getConstArray(), 16 ) ) + ? reinterpret_cast< sal_Int64 >( this ) + : ODbaseIndex_BASE::getSomething(rId); +} +//------------------------------------------------------------------ +ONDXPagePtr ODbaseIndex::getRoot() +{ + openIndexFile(); + if (!m_aRoot.Is()) + { + m_nRootPage = m_aHeader.db_rootpage; + m_nPageCount = m_aHeader.db_pagecount; + m_aRoot = CreatePage(m_nRootPage,NULL,TRUE); + } + return m_aRoot; +} +//------------------------------------------------------------------ +sal_Bool ODbaseIndex::openIndexFile() +{ + if(!m_pFileStream) + { + ::rtl::OUString sFile = getCompletePath(); + if(UCBContentHelper::Exists(sFile)) + { + m_pFileStream = OFileTable::createStream_simpleError(sFile, STREAM_READWRITE | STREAM_NOCREATE | STREAM_SHARE_DENYWRITE); + if (!m_pFileStream) + m_pFileStream = OFileTable::createStream_simpleError(sFile,STREAM_READ | STREAM_NOCREATE | STREAM_SHARE_DENYNONE); + if(m_pFileStream) + { + m_pFileStream->SetNumberFormatInt(NUMBERFORMAT_INT_LITTLEENDIAN); + m_pFileStream->SetBufferSize(PAGE_SIZE); + (*m_pFileStream) >> *this; + } + } + if(!m_pFileStream) + { + const ::rtl::OUString sError( m_pTable->getConnection()->getResources().getResourceStringWithSubstitution( + STR_COULD_NOT_LOAD_FILE, + "$filename$", sFile + ) ); + ::dbtools::throwGenericSQLException( sError, *this ); + } + } + + return m_pFileStream != NULL; +} +//------------------------------------------------------------------ +OIndexIterator* ODbaseIndex::createIterator(OBoolOperator* pOp, + const OOperand* pOperand) +{ + openIndexFile(); + return new OIndexIterator(this, pOp, pOperand); +} +//------------------------------------------------------------------ +BOOL ODbaseIndex::ConvertToKey(ONDXKey* rKey, sal_uInt32 nRec, const ORowSetValue& rValue) +{ + OSL_ENSURE(m_pFileStream,"FileStream is not opened!"); + // Sucht ein bestimmten Wert im Index + // Wenn der Index Unique ist, interssiert der Key nicht, sonst ja + try + { + if (m_aHeader.db_keytype == 0) + { + *rKey = ONDXKey(rValue.getString(), nRec ); + } + else + { + if (rValue.isNull()) + *rKey = ONDXKey(rValue.getDouble(), DataType::DOUBLE, nRec ); + else + *rKey = ONDXKey(rValue.getDouble(), nRec ); + } + } + catch (Exception&) + { + OSL_ASSERT(0); + return FALSE; + } + return TRUE; +} + +//------------------------------------------------------------------ +BOOL ODbaseIndex::Find(sal_uInt32 nRec, const ORowSetValue& rValue) +{ + openIndexFile(); + OSL_ENSURE(m_pFileStream,"FileStream is not opened!"); + // Sucht ein bestimmten Wert im Index + // Wenn der Index Unique ist, interssiert der Key nicht, sonst ja + ONDXKey aKey; + return ConvertToKey(&aKey, nRec, rValue) && getRoot()->Find(aKey); +} + +//------------------------------------------------------------------ +BOOL ODbaseIndex::Insert(sal_uInt32 nRec, const ORowSetValue& rValue) +{ + openIndexFile(); + OSL_ENSURE(m_pFileStream,"FileStream is not opened!"); + ONDXKey aKey; + + // Existiert der Wert bereits + // Find immer verwenden um das aktuelle Blatt zu bestimmen + if (!ConvertToKey(&aKey, nRec, rValue) || (getRoot()->Find(aKey) && isUnique())) + return FALSE; + + ONDXNode aNewNode(aKey); + + // einfuegen in das aktuelle Blatt + if (!m_aCurLeaf.Is()) + return FALSE; + + BOOL bResult = m_aCurLeaf->Insert(aNewNode); + Release(bResult); + + return bResult; +} + +//------------------------------------------------------------------ +BOOL ODbaseIndex::Update(sal_uInt32 nRec, const ORowSetValue& rOldValue, + const ORowSetValue& rNewValue) +{ + openIndexFile(); + OSL_ENSURE(m_pFileStream,"FileStream is not opened!"); + ONDXKey aKey; + if (!ConvertToKey(&aKey, nRec, rNewValue) || (isUnique() && getRoot()->Find(aKey))) + return FALSE; + else + return Delete(nRec, rOldValue) && Insert(nRec,rNewValue); +} + +//------------------------------------------------------------------ +BOOL ODbaseIndex::Delete(sal_uInt32 nRec, const ORowSetValue& rValue) +{ + openIndexFile(); + OSL_ENSURE(m_pFileStream,"FileStream is not opened!"); + // Existiert der Wert bereits + // Find immer verwenden um das aktuelle Blatt zu bestimmen + ONDXKey aKey; + if (!ConvertToKey(&aKey, nRec, rValue) || !getRoot()->Find(aKey)) + return FALSE; + + ONDXNode aNewNode(aKey); + + // einfuegen in das aktuelle Blatt + if (!m_aCurLeaf.Is()) + return FALSE; +#if OSL_DEBUG_LEVEL > 1 + m_aRoot->PrintPage(); +#endif + + return m_aCurLeaf->Delete(m_nCurNode); +} +//------------------------------------------------------------------ +void ODbaseIndex::Collect(ONDXPage* pPage) +{ + if (pPage) + m_aCollector.push_back(pPage); +} +//------------------------------------------------------------------ +void ODbaseIndex::Release(BOOL bSave) +{ + // Freigeben der Indexressourcen + m_bUseCollector = FALSE; + + if (m_aCurLeaf.Is()) + { + m_aCurLeaf->Release(bSave); + m_aCurLeaf.Clear(); + } + + // Wurzel freigeben + if (m_aRoot.Is()) + { + m_aRoot->Release(bSave); + m_aRoot.Clear(); + } + // alle Referenzen freigeben, bevor der FileStream geschlossen wird + for (ULONG i = 0; i < m_aCollector.size(); i++) + m_aCollector[i]->QueryDelete(); + + m_aCollector.clear(); + + // Header modifiziert ? + if (bSave && (m_aHeader.db_rootpage != m_nRootPage || + m_aHeader.db_pagecount != m_nPageCount)) + { + m_aHeader.db_rootpage = m_nRootPage; + m_aHeader.db_pagecount = m_nPageCount; + (*m_pFileStream) << *this; + } + m_nRootPage = m_nPageCount = 0; + m_nCurNode = NODE_NOTFOUND; + + closeImpl(); +} +// ----------------------------------------------------------------------------- +void ODbaseIndex::closeImpl() +{ + if(m_pFileStream) + { + delete m_pFileStream; + m_pFileStream = NULL; + } +} +//------------------------------------------------------------------ +ONDXPage* ODbaseIndex::CreatePage(sal_uInt32 nPagePos, ONDXPage* pParent, BOOL bLoad) +{ + OSL_ENSURE(m_pFileStream,"FileStream is not opened!"); + + ONDXPage* pPage; + if ( !m_aCollector.empty() ) + { + pPage = *(m_aCollector.rbegin()); + m_aCollector.pop_back(); + pPage->SetPagePos(nPagePos); + pPage->SetParent(pParent); + } + else + pPage = new ONDXPage(*this, nPagePos, pParent); + + if (bLoad) + (*m_pFileStream) >> *pPage; + + return pPage; +} + +//------------------------------------------------------------------ +SvStream& connectivity::dbase::operator >> (SvStream &rStream, ODbaseIndex& rIndex) +{ + rStream.Seek(0); + rStream.Read(&rIndex.m_aHeader,PAGE_SIZE); + +/* OJ: no longer needed + // Text convertierung + ByteString aText(rIndex.m_aHeader.db_name); + // aText.Convert(rIndex.m_pTable->getConnection()->GetCharacterSet(), m_pTable->getConnection()->getTextEncoding()); + // aText.Convert(rIndex.m_pTable->getConnection()->GetCharacterSet(), m_pTable->getConnection()->getTextEncoding()); + strcpy(rIndex.m_aHeader.db_name,aText.GetBuffer()); +*/ + rIndex.m_nRootPage = rIndex.m_aHeader.db_rootpage; + rIndex.m_nPageCount = rIndex.m_aHeader.db_pagecount; + return rStream; +} +//------------------------------------------------------------------ +SvStream& connectivity::dbase::operator << (SvStream &rStream, ODbaseIndex& rIndex) +{ + rStream.Seek(0); +/* OJ: no longer needed + ByteString aText(rIndex.m_aHeader.db_name); + // aText.Convert(m_pTable->getConnection()->getTextEncoding(), rIndex.m_pTable->getConnection()->GetCharacterSet()); + strcpy(rIndex.m_aHeader.db_name,aText.GetBuffer()); +*/ + OSL_VERIFY_EQUALS( rStream.Write(&rIndex.m_aHeader,PAGE_SIZE), PAGE_SIZE, "Write not successful: Wrong header size for dbase index!"); + return rStream; +} +// ------------------------------------------------------------------------- +::rtl::OUString ODbaseIndex::getCompletePath() +{ + ::rtl::OUString sDir = m_pTable->getConnection()->getURL(); + sDir += OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_DELIMITER); + sDir += m_Name; + sDir += ::rtl::OUString::createFromAscii(".ndx"); + return sDir; +} +//------------------------------------------------------------------ +void ODbaseIndex::createINFEntry() +{ + // inf Datei abgleichen + String sEntry = m_Name; + sEntry += String::CreateFromAscii(".ndx"); + + ::rtl::OUString sCfgFile(m_pTable->getConnection()->getURL()); + sCfgFile += OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_DELIMITER); + sCfgFile += m_pTable->getName(); + sCfgFile += ::rtl::OUString::createFromAscii(".inf"); + + String sPhysicalPath; + LocalFileHelper::ConvertURLToPhysicalName(sCfgFile,sPhysicalPath); + + Config aInfFile(sPhysicalPath); + aInfFile.SetGroup(dBASE_III_GROUP); + + USHORT nSuffix = aInfFile.GetKeyCount(); + ByteString aNewEntry,aKeyName; + BOOL bCase = isCaseSensitive(); + while (!aNewEntry.Len()) + { + aNewEntry = "NDX"; + aNewEntry += ByteString::CreateFromInt32(++nSuffix); + for (USHORT i = 0; i < aInfFile.GetKeyCount(); i++) + { + aKeyName = aInfFile.GetKeyName(i); + if (bCase ? aKeyName == aNewEntry : aKeyName.EqualsIgnoreCaseAscii(aNewEntry)) + { + aNewEntry.Erase(); + break; + } + } + } + aInfFile.WriteKey(aNewEntry,ByteString(sEntry,m_pTable->getConnection()->getTextEncoding())); +} +// ------------------------------------------------------------------------- +BOOL ODbaseIndex::DropImpl() +{ + closeImpl(); + + ::rtl::OUString sPath = getCompletePath(); + if(UCBContentHelper::Exists(sPath)) + { + if(!UCBContentHelper::Kill(sPath)) + m_pTable->getConnection()->throwGenericSQLException(STR_COULD_NOT_DELETE_INDEX,*m_pTable); + } + + // InfDatei abgleichen + + ::rtl::OUString sCfgFile(m_pTable->getConnection()->getURL()); + sCfgFile += OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_DELIMITER); + sCfgFile += m_pTable->getName(); + sCfgFile += ::rtl::OUString::createFromAscii(".inf"); + + String sPhysicalPath; + String sNDX(sCfgFile); + OSL_VERIFY_RES( LocalFileHelper::ConvertURLToPhysicalName(sNDX,sPhysicalPath),"Can not convert Config Filename into Physical Name!"); + + Config aInfFile(sPhysicalPath); + aInfFile.SetGroup(dBASE_III_GROUP); + USHORT nKeyCnt = aInfFile.GetKeyCount(); + ByteString aKeyName; + String sEntry = m_Name; + sEntry += String::CreateFromAscii(".ndx"); + + // delete entries from the inf file + for (USHORT nKey = 0; nKey < nKeyCnt; nKey++) + { + // Verweist der Key auf ein Indexfile?... + aKeyName = aInfFile.GetKeyName( nKey ); + if (aKeyName.Copy(0,3) == "NDX") + { + if(sEntry == String(aInfFile.ReadKey(aKeyName),m_pTable->getConnection()->getTextEncoding())) + { + aInfFile.DeleteKey(aKeyName); + break; + } + } + } + return TRUE; +} +// ------------------------------------------------------------------------- +void ODbaseIndex::impl_killFileAndthrowError_throw(sal_uInt16 _nErrorId,const ::rtl::OUString& _sFile) +{ + closeImpl(); + if(UCBContentHelper::Exists(_sFile)) + UCBContentHelper::Kill(_sFile); + m_pTable->getConnection()->throwGenericSQLException(_nErrorId,*this); +} +//------------------------------------------------------------------ +BOOL ODbaseIndex::CreateImpl() +{ + // Anlegen des Index + const ::rtl::OUString sFile = getCompletePath(); + if(UCBContentHelper::Exists(sFile)) + { + const ::rtl::OUString sError( m_pTable->getConnection()->getResources().getResourceStringWithSubstitution( + STR_COULD_NOT_CREATE_INDEX_NAME, + "$filename$", sFile + ) ); + ::dbtools::throwGenericSQLException( sError, *this ); + } + // Index ist nur einstufig + if (m_pColumns->getCount() > 1) + m_pTable->getConnection()->throwGenericSQLException(STR_ONL_ONE_COLUMN_PER_INDEX,*this); + + Reference<XFastPropertySet> xCol(m_pColumns->getByIndex(0),UNO_QUERY); + + // ist die Spalte schon indiziert ? + if ( !xCol.is() ) + ::dbtools::throwFunctionSequenceException(*this); +// else if (pColumn && pColumn->IsIndexed()) +// { +// String aText = String(OResId(STR_STAT_INDEX_COLUMN_ALREADY_INDEXED)); +// aText.SearchAndReplace(String::CreateFromAscii("#"),pColumn->GetName()); +// aStatus.Set(SDB_STAT_ERROR, +// String::CreateFromAscii("01000"), +// aStatus.CreateErrorMessage(aText), +// 0, String() ); +// return FALSE; +// } + + // create the index file + m_pFileStream = OFileTable::createStream_simpleError(sFile,STREAM_READWRITE | STREAM_SHARE_DENYWRITE | STREAM_TRUNC); + if (!m_pFileStream) + { + const ::rtl::OUString sError( m_pTable->getConnection()->getResources().getResourceStringWithSubstitution( + STR_COULD_NOT_LOAD_FILE, + "$filename$", sFile + ) ); + ::dbtools::throwGenericSQLException( sError, *this ); + } + + m_pFileStream->SetNumberFormatInt(NUMBERFORMAT_INT_LITTLEENDIAN); + m_pFileStream->SetBufferSize(PAGE_SIZE); + m_pFileStream->SetFiller('\0'); + + // Zunaechst muss das Ergebnis sortiert sein + utl::SharedUNOComponent<XStatement> xStmt; + utl::SharedUNOComponent<XResultSet> xSet; + String aName; + try + { + xStmt.set( m_pTable->getConnection()->createStatement(), UNO_SET_THROW); + + aName = getString(xCol->getFastPropertyValue(PROPERTY_ID_NAME)); + + const String aQuote(m_pTable->getConnection()->getMetaData()->getIdentifierQuoteString()); + String aStatement; + aStatement.AssignAscii("SELECT "); + aStatement += aQuote; + aStatement += aName; + aStatement += aQuote; + aStatement.AppendAscii(" FROM "); + aStatement += aQuote; + aStatement += m_pTable->getName().getStr(); + aStatement += aQuote; + aStatement.AppendAscii(" ORDER BY "); + aStatement += aQuote; + aStatement += aName; + aStatement += aQuote; + +// if (!m_IsUnique) // zusaetzlich sortierung mit der bookmarkspalte +// { +// aStatement.AppendAscii(" ,"); +// aStatement += aQuote; +// aStatement.AppendAscii("[BOOKMARK]"); // this is a special column +// aStatement += aQuote; +// } + + xSet.set( xStmt->executeQuery(aStatement),UNO_SET_THROW ); + } + catch(const Exception& ) + { + impl_killFileAndthrowError_throw(STR_COULD_NOT_CREATE_INDEX,sFile); + } + if (!xSet.is()) + { + impl_killFileAndthrowError_throw(STR_COULD_NOT_CREATE_INDEX,sFile); + } + + // Setzen der Headerinfo + memset(&m_aHeader,0,sizeof(m_aHeader)); + sal_Int32 nType = 0; + ::vos::ORef<OSQLColumns> aCols = m_pTable->getTableColumns(); + const Reference< XPropertySet > xTableCol(*find(aCols->get().begin(),aCols->get().end(),aName,::comphelper::UStringMixEqual(isCaseSensitive()))); + + xTableCol->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_TYPE)) >>= nType; + + m_aHeader.db_keytype = (nType == DataType::VARCHAR || nType == DataType::CHAR) ? 0 : 1; + m_aHeader.db_keylen = (m_aHeader.db_keytype) ? 8 : (USHORT)getINT32(xTableCol->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_PRECISION))); + m_aHeader.db_keylen = (( m_aHeader.db_keylen - 1) / 4 + 1) * 4; + m_aHeader.db_maxkeys = (PAGE_SIZE - 4) / (8 + m_aHeader.db_keylen); + if ( m_aHeader.db_maxkeys < 3 ) + { + impl_killFileAndthrowError_throw(STR_COULD_NOT_CREATE_INDEX_KEYSIZE,sFile); + } + + m_pFileStream->SetStreamSize(PAGE_SIZE); + + ByteString aCol(aName,m_pTable->getConnection()->getTextEncoding()); + strncpy(m_aHeader.db_name,aCol.GetBuffer(),std::min((USHORT)sizeof(m_aHeader.db_name), aCol.Len())); + m_aHeader.db_unique = m_IsUnique ? 1: 0; + m_aHeader.db_keyrec = m_aHeader.db_keylen + 8; + + // modifizierung am Header werden ueber Unterschiede zw. HeaderInfo und nRootPage + // bzw. nPageCout erkannt + + m_nRootPage = 1; + m_nPageCount = 2; + + // ODatabaseType eType = m_aHeader.db_keytype == 0 ? DataType::VARCHAR : DataType::DOUBLE; + m_aCurLeaf = m_aRoot = CreatePage(m_nRootPage); + m_aRoot->SetModified(TRUE); + + m_bUseCollector = TRUE; + + // ULONG nRowsLeft = pCursor->RowCount(); + sal_Int32 nRowsLeft = 0; + Reference<XRow> xRow(xSet,UNO_QUERY); + + if(xSet->last()) + { + Reference< XUnoTunnel> xTunnel(xSet,UNO_QUERY); + ODbaseResultSet* pDbaseRes = NULL; + if(xTunnel.is()) + pDbaseRes = reinterpret_cast< ODbaseResultSet* >( xTunnel->getSomething(ODbaseResultSet::getUnoTunnelImplementationId()) ); + OSL_ENSURE(pDbaseRes,"No dbase resultset found? What's going on here!"); + Reference<XRowLocate> xRowLocate(xSet,UNO_QUERY); + nRowsLeft = xSet->getRow(); + + xSet->beforeFirst(); + ORowSetValue atmpValue=ORowSetValue(); + ONDXKey aKey(atmpValue, nType, 0); + ONDXKey aInsertKey(atmpValue, nType, 0); + // Erzeugen der Indexstruktur + while (xSet->next()) + { + // ODbRow& rRow = *pCursor->GetRow(); + ORowSetValue aValue(m_aHeader.db_keytype ? ORowSetValue(xRow->getDouble(1)) : ORowSetValue(xRow->getString(1))); + // ueberpruefen auf doppelten eintrag + if (m_IsUnique && m_nCurNode != NODE_NOTFOUND) + { + aKey.setValue(aValue); + if (aKey == (*m_aCurLeaf)[m_nCurNode].GetKey()) + { + impl_killFileAndthrowError_throw(STR_COULD_NOT_CREATE_INDEX_NOT_UNIQUE,sFile); + } + } + aInsertKey.setValue(aValue); + aInsertKey.setRecord(pDbaseRes->getCurrentFilePos()); + + ONDXNode aNewNode(aInsertKey); + if (!m_aCurLeaf->Insert(aNewNode, --nRowsLeft)) + break; + } + } + + if(nRowsLeft) + { + impl_killFileAndthrowError_throw(STR_COULD_NOT_CREATE_INDEX,sFile); + } + Release(); + createINFEntry(); + return sal_True; +} +// ----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- +void SAL_CALL ODbaseIndex::acquire() throw() +{ + ODbaseIndex_BASE::acquire(); +} +// ----------------------------------------------------------------------------- +void SAL_CALL ODbaseIndex::release() throw() +{ + ODbaseIndex_BASE::release(); +} +// ----------------------------------------------------------------------------- + + + diff --git a/connectivity/source/drivers/dbase/DIndexColumns.cxx b/connectivity/source/drivers/dbase/DIndexColumns.cxx new file mode 100644 index 000000000000..59682a38d8af --- /dev/null +++ b/connectivity/source/drivers/dbase/DIndexColumns.cxx @@ -0,0 +1,94 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_connectivity.hxx" +#include "dbase/DIndexColumns.hxx" +#include "dbase/DTable.hxx" +#include "connectivity/sdbcx/VIndexColumn.hxx" +#include <comphelper/types.hxx> +#include <comphelper/property.hxx> +#include <connectivity/dbexception.hxx> + +using namespace ::comphelper; + +using namespace connectivity::dbase; +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; + + +sdbcx::ObjectType ODbaseIndexColumns::createObject(const ::rtl::OUString& _rName) +{ + const ODbaseTable* pTable = m_pIndex->getTable(); + + ::vos::ORef<OSQLColumns> aCols = pTable->getTableColumns(); + OSQLColumns::Vector::const_iterator aIter = find(aCols->get().begin(),aCols->get().end(),_rName,::comphelper::UStringMixEqual(isCaseSensitive())); + + Reference< XPropertySet > xCol; + if(aIter != aCols->get().end()) + xCol = *aIter; + + if(!xCol.is()) + return sdbcx::ObjectType(); + + sdbcx::ObjectType xRet = new sdbcx::OIndexColumn(sal_True,_rName + ,getString(xCol->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_TYPENAME))) + ,::rtl::OUString() + ,getINT32(xCol->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_ISNULLABLE))) + ,getINT32(xCol->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_PRECISION))) + ,getINT32(xCol->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_SCALE))) + ,getINT32(xCol->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_TYPE))) + ,sal_False + ,sal_False + ,sal_False + ,pTable->getConnection()->getMetaData()->storesMixedCaseQuotedIdentifiers()); + + return xRet; +} + +// ------------------------------------------------------------------------- +void ODbaseIndexColumns::impl_refresh() throw(RuntimeException) +{ + m_pIndex->refreshColumns(); +} +// ------------------------------------------------------------------------- +Reference< XPropertySet > ODbaseIndexColumns::createDescriptor() +{ + return new sdbcx::OIndexColumn(m_pIndex->getTable()->getConnection()->getMetaData()->storesMixedCaseQuotedIdentifiers()); +} +// ------------------------------------------------------------------------- +sdbcx::ObjectType ODbaseIndexColumns::appendObject( const ::rtl::OUString& /*_rForName*/, const Reference< XPropertySet >& descriptor ) +{ + return cloneDescriptor( descriptor ); +} +// ----------------------------------------------------------------------------- + + diff --git a/connectivity/source/drivers/dbase/DIndexIter.cxx b/connectivity/source/drivers/dbase/DIndexIter.cxx new file mode 100644 index 000000000000..f32b1f2cffe0 --- /dev/null +++ b/connectivity/source/drivers/dbase/DIndexIter.cxx @@ -0,0 +1,315 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_connectivity.hxx" +#include "dbase/DIndexIter.hxx" +#include <com/sun/star/sdb/SQLFilterOperator.hpp> + +using namespace ::com::sun::star::sdb; +using namespace connectivity; +using namespace connectivity::dbase; +using namespace connectivity::file; +using namespace ::com::sun::star::sdb; +//================================================================== +// OIndexIterator +//================================================================== +//------------------------------------------------------------------ +OIndexIterator::~OIndexIterator() +{ + // m_pIndex->UnLock(); + m_pIndex->release(); +} + +//------------------------------------------------------------------ +ULONG OIndexIterator::First() +{ + return Find(TRUE); +} + +//------------------------------------------------------------------ +ULONG OIndexIterator::Next() +{ + return Find(FALSE); +} +//------------------------------------------------------------------ +ULONG OIndexIterator::Find(BOOL bFirst) +{ + // ONDXIndex* m_pIndex = GetNDXIndex(); + + ULONG nRes = STRING_NOTFOUND; +// if (!m_pIndex->IsOpen()) +// return nRes; + + if (bFirst) + { + m_aRoot = m_pIndex->getRoot(); + m_aCurLeaf = NULL; + } + + if (!m_pOperator) + { + // Vorbereitung , auf kleinstes Element positionieren + if (bFirst) + { + ONDXPage* pPage = m_aRoot; + while (pPage && !pPage->IsLeaf()) + pPage = pPage->GetChild(m_pIndex); + + m_aCurLeaf = pPage; + m_nCurNode = NODE_NOTFOUND; + } + ONDXKey* pKey = GetNextKey(); + nRes = pKey ? pKey->GetRecord() : STRING_NOTFOUND; + } + else if (m_pOperator->IsA(TYPE(OOp_ISNOTNULL))) + nRes = GetNotNull(bFirst); + else if (m_pOperator->IsA(TYPE(OOp_ISNULL))) + nRes = GetNull(bFirst); + else if (m_pOperator->IsA(TYPE(OOp_LIKE))) + nRes = GetLike(bFirst); + else if (m_pOperator->IsA(TYPE(OOp_COMPARE))) + nRes = GetCompare(bFirst); + + return nRes; +} + +//------------------------------------------------------------------ +ONDXKey* OIndexIterator::GetFirstKey(ONDXPage* pPage, const OOperand& rKey) +{ + // sucht den vorgegeben key + // Besonderheit: gelangt der Algorithmus ans Ende + // wird immer die aktuelle Seite und die Knotenposition vermerkt + // auf die die Bedingung <= zutrifft + // dieses findet beim Insert besondere Beachtung + // ONDXIndex* m_pIndex = GetNDXIndex(); + OOp_COMPARE aTempOp(SQLFilterOperator::GREATER); + USHORT i = 0; + + if (pPage->IsLeaf()) + { + // im blatt wird die eigentliche Operation ausgefuehrt, sonst die temp. (>) + while (i < pPage->Count() && !m_pOperator->operate(&((*pPage)[i]).GetKey(),&rKey)) + i++; + } + else + while (i < pPage->Count() && !aTempOp.operate(&((*pPage)[i]).GetKey(),&rKey)) + i++; + + + ONDXKey* pFoundKey = NULL; + if (!pPage->IsLeaf()) + { + // weiter absteigen + ONDXPagePtr aPage = (i==0) ? pPage->GetChild(m_pIndex) + : ((*pPage)[i-1]).GetChild(m_pIndex, pPage); + pFoundKey = aPage.Is() ? GetFirstKey(aPage, rKey) : NULL; + } + else if (i == pPage->Count()) + { + pFoundKey = NULL; + } + else + { + pFoundKey = &(*pPage)[i].GetKey(); + if (!m_pOperator->operate(pFoundKey,&rKey)) + pFoundKey = NULL; + + m_aCurLeaf = pPage; + m_nCurNode = pFoundKey ? i : i - 1; + } + return pFoundKey; +} + +//------------------------------------------------------------------ +ULONG OIndexIterator::GetCompare(BOOL bFirst) +{ + ONDXKey* pKey = NULL; + // ONDXIndex* m_pIndex = GetNDXIndex(); + sal_Int32 ePredicateType = PTR_CAST(file::OOp_COMPARE,m_pOperator)->getPredicateType(); + + if (bFirst) + { + // Vorbereitung , auf kleinstes Element positionieren + ONDXPage* pPage = m_aRoot; + switch (ePredicateType) + { + case SQLFilterOperator::NOT_EQUAL: + case SQLFilterOperator::LESS: + case SQLFilterOperator::LESS_EQUAL: + while (pPage && !pPage->IsLeaf()) + pPage = pPage->GetChild(m_pIndex); + + m_aCurLeaf = pPage; + m_nCurNode = NODE_NOTFOUND; + } + + + switch (ePredicateType) + { + case SQLFilterOperator::NOT_EQUAL: + while ( ( ( pKey = GetNextKey() ) != NULL ) && !m_pOperator->operate(pKey,m_pOperand)) ; + break; + case SQLFilterOperator::LESS: + while ( ( ( pKey = GetNextKey() ) != NULL ) && pKey->getValue().isNull()) ; + break; + case SQLFilterOperator::LESS_EQUAL: + while ( ( pKey = GetNextKey() ) != NULL ) ; + break; + case SQLFilterOperator::GREATER_EQUAL: + case SQLFilterOperator::EQUAL: + pKey = GetFirstKey(m_aRoot,*m_pOperand); + break; + case SQLFilterOperator::GREATER: + pKey = GetFirstKey(m_aRoot,*m_pOperand); + if ( !pKey ) + while ( ( ( pKey = GetNextKey() ) != NULL ) && !m_pOperator->operate(pKey,m_pOperand)) ; + } + } + else + { + switch (ePredicateType) + { + case SQLFilterOperator::NOT_EQUAL: + while ( ( ( pKey = GetNextKey() ) != NULL ) && !m_pOperator->operate(pKey,m_pOperand)) + ; + break; + case SQLFilterOperator::LESS: + case SQLFilterOperator::LESS_EQUAL: + case SQLFilterOperator::EQUAL: + if ( ( ( pKey = GetNextKey() ) == NULL ) || !m_pOperator->operate(pKey,m_pOperand)) + { + pKey = NULL; + m_aCurLeaf = NULL; + } + break; + case SQLFilterOperator::GREATER_EQUAL: + case SQLFilterOperator::GREATER: + pKey = GetNextKey(); + } + } + + return pKey ? pKey->GetRecord() : STRING_NOTFOUND; +} + +//------------------------------------------------------------------ +ULONG OIndexIterator::GetLike(BOOL bFirst) +{ + // ONDXIndex* m_pIndex = GetNDXIndex(); + if (bFirst) + { + ONDXPage* pPage = m_aRoot; + + while (pPage && !pPage->IsLeaf()) + pPage = pPage->GetChild(m_pIndex); + + m_aCurLeaf = pPage; + m_nCurNode = NODE_NOTFOUND; + } + + ONDXKey* pKey; + while ( ( ( pKey = GetNextKey() ) != NULL ) && !m_pOperator->operate(pKey,m_pOperand)) + ; + return pKey ? pKey->GetRecord() : STRING_NOTFOUND; +} + +//------------------------------------------------------------------ +ULONG OIndexIterator::GetNull(BOOL bFirst) +{ + // ONDXIndex* m_pIndex = GetNDXIndex(); + if (bFirst) + { + ONDXPage* pPage = m_aRoot; + while (pPage && !pPage->IsLeaf()) + pPage = pPage->GetChild(m_pIndex); + + m_aCurLeaf = pPage; + m_nCurNode = NODE_NOTFOUND; + } + + ONDXKey* pKey; + if ( ( ( pKey = GetNextKey() ) == NULL ) || !pKey->getValue().isNull()) + { + pKey = NULL; + m_aCurLeaf = NULL; + } + return pKey ? pKey->GetRecord() : STRING_NOTFOUND; +} + +//------------------------------------------------------------------ +ULONG OIndexIterator::GetNotNull(BOOL bFirst) +{ + ONDXKey* pKey; + // ONDXIndex* m_pIndex = GetNDXIndex(); + if (bFirst) + { + // erst alle NULL werte abklappern + for (ULONG nRec = GetNull(bFirst); + nRec != STRING_NOTFOUND; + nRec = GetNull(FALSE)) + ; + pKey = m_aCurLeaf.Is() ? &(*m_aCurLeaf)[m_nCurNode].GetKey() : NULL; + } + else + pKey = GetNextKey(); + + return pKey ? pKey->GetRecord() : STRING_NOTFOUND; +} + +//------------------------------------------------------------------ +ONDXKey* OIndexIterator::GetNextKey() +{ + // ONDXIndex* m_pIndex = GetNDXIndex(); + if (m_aCurLeaf.Is() && ((++m_nCurNode) >= m_aCurLeaf->Count())) + { + ONDXPage* pPage = m_aCurLeaf; + // naechste Seite suchen + while (pPage) + { + ONDXPage* pParentPage = pPage->GetParent(); + if (pParentPage) + { + USHORT nPos = pParentPage->Search(pPage); + if (nPos != pParentPage->Count() - 1) + { // Seite gefunden + pPage = (*pParentPage)[nPos+1].GetChild(m_pIndex,pParentPage); + break; + } + } + pPage = pParentPage; + } + + // jetzt wieder zum Blatt + while (pPage && !pPage->IsLeaf()) + pPage = pPage->GetChild(m_pIndex); + + m_aCurLeaf = pPage; + m_nCurNode = 0; + } + return m_aCurLeaf.Is() ? &(*m_aCurLeaf)[m_nCurNode].GetKey() : NULL; +} + diff --git a/connectivity/source/drivers/dbase/DIndexes.cxx b/connectivity/source/drivers/dbase/DIndexes.cxx new file mode 100644 index 000000000000..fda3efa9cc5e --- /dev/null +++ b/connectivity/source/drivers/dbase/DIndexes.cxx @@ -0,0 +1,137 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_connectivity.hxx" +#include "dbase/DIndexes.hxx" +#include "dbase/DIndex.hxx" +#include <connectivity/dbexception.hxx> +#include <unotools/ucbhelper.hxx> +#include <comphelper/types.hxx> +#include "resource/dbase_res.hrc" + +using namespace ::comphelper; + +using namespace utl; +using namespace ::connectivity; +using namespace ::dbtools; +using namespace ::connectivity::dbase; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::lang; + +namespace starutil = ::com::sun::star::util; + +sdbcx::ObjectType ODbaseIndexes::createObject(const ::rtl::OUString& _rName) +{ + // Dir* pDir = m_pTable->getConnection()->getDir(); + // String aPath = pDir->GetName(); + // aPath += _rName.getStr(); + ::rtl::OUString sFile = m_pTable->getConnection()->getURL(); + sFile += OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_DELIMITER); + sFile += _rName; + sFile += ::rtl::OUString::createFromAscii(".ndx"); + if ( !UCBContentHelper::Exists(sFile) ) + { + const ::rtl::OUString sError( m_pTable->getConnection()->getResources().getResourceStringWithSubstitution( + STR_COULD_NOT_LOAD_FILE, + "$filename$", sFile + ) ); + ::dbtools::throwGenericSQLException( sError, *m_pTable ); + } + + sdbcx::ObjectType xRet; + SvStream* pFileStream = ::connectivity::file::OFileTable::createStream_simpleError(sFile,STREAM_READ | STREAM_NOCREATE| STREAM_SHARE_DENYWRITE); + if(pFileStream) + { + pFileStream->SetNumberFormatInt(NUMBERFORMAT_INT_LITTLEENDIAN); + pFileStream->SetBufferSize(PAGE_SIZE); + ODbaseIndex::NDXHeader aHeader; + + pFileStream->Seek(0); + pFileStream->Read(&aHeader,PAGE_SIZE); + delete pFileStream; + + ODbaseIndex* pIndex = new ODbaseIndex(m_pTable,aHeader,_rName); + xRet = pIndex; + pIndex->openIndexFile(); + } + else + { + const ::rtl::OUString sError( m_pTable->getConnection()->getResources().getResourceStringWithSubstitution( + STR_COULD_NOT_LOAD_FILE, + "$filename$", sFile + ) ); + ::dbtools::throwGenericSQLException( sError, *m_pTable ); + } + return xRet; +} +// ------------------------------------------------------------------------- +void ODbaseIndexes::impl_refresh( ) throw(RuntimeException) +{ + if(m_pTable) + m_pTable->refreshIndexes(); +} +// ------------------------------------------------------------------------- +Reference< XPropertySet > ODbaseIndexes::createDescriptor() +{ + return new ODbaseIndex(m_pTable); +} +typedef connectivity::sdbcx::OCollection ODbaseTables_BASE_BASE; +// ------------------------------------------------------------------------- +// XAppend +sdbcx::ObjectType ODbaseIndexes::appendObject( const ::rtl::OUString& _rForName, const Reference< XPropertySet >& descriptor ) +{ + Reference<XUnoTunnel> xTunnel(descriptor,UNO_QUERY); + if(xTunnel.is()) + { + ODbaseIndex* pIndex = reinterpret_cast< ODbaseIndex* >( xTunnel->getSomething(ODbaseIndex::getUnoTunnelImplementationId()) ); + if(!pIndex || !pIndex->CreateImpl()) + throw SQLException(); + } + + return createObject( _rForName ); +} +// ------------------------------------------------------------------------- +// XDrop +void ODbaseIndexes::dropObject(sal_Int32 _nPos,const ::rtl::OUString /*_sElementName*/) +{ + Reference< XUnoTunnel> xTunnel(getObject(_nPos),UNO_QUERY); + if ( xTunnel.is() ) + { + ODbaseIndex* pIndex = reinterpret_cast< ODbaseIndex* >( xTunnel->getSomething(ODbaseIndex::getUnoTunnelImplementationId()) ); + if ( pIndex ) + pIndex->DropImpl(); + } + +} +// ------------------------------------------------------------------------- + + diff --git a/connectivity/source/drivers/dbase/DNoException.cxx b/connectivity/source/drivers/dbase/DNoException.cxx new file mode 100644 index 000000000000..b39581f1be15 --- /dev/null +++ b/connectivity/source/drivers/dbase/DNoException.cxx @@ -0,0 +1,650 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_connectivity.hxx" +#include "dbase/DTable.hxx" +#include "dbase/DIndex.hxx" +#include "dbase/dindexnode.hxx" +#include <tools/debug.hxx> +#include "diagnose_ex.h" + +#include <sal/types.h> +#include <algorithm> +#include <rtl/logfile.hxx> + +using namespace connectivity; +using namespace connectivity::dbase; +using namespace com::sun::star::uno; +using namespace com::sun::star::sdbc; +//------------------------------------------------------------------ +sal_Bool ODbaseTable::seekRow(IResultSetHelper::Movement eCursorPosition, sal_Int32 nOffset, sal_Int32& nCurPos) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbase", "Ocke.Janssen@sun.com", "ODbaseTable::seekRow" ); + // ---------------------------------------------------------- + // Positionierung vorbereiten: + OSL_ENSURE(m_pFileStream,"ODbaseTable::seekRow: FileStream is NULL!"); + + sal_uInt32 nNumberOfRecords = (sal_uInt32)m_aHeader.db_anz; + sal_uInt32 nTempPos = m_nFilePos; + m_nFilePos = nCurPos; + + switch(eCursorPosition) + { + case IResultSetHelper::NEXT: + ++m_nFilePos; + break; + case IResultSetHelper::PRIOR: + if (m_nFilePos > 0) + --m_nFilePos; + break; + case IResultSetHelper::FIRST: + m_nFilePos = 1; + break; + case IResultSetHelper::LAST: + m_nFilePos = nNumberOfRecords; + break; + case IResultSetHelper::RELATIVE: + m_nFilePos = (((sal_Int32)m_nFilePos) + nOffset < 0) ? 0L + : (sal_uInt32)(((sal_Int32)m_nFilePos) + nOffset); + break; + case IResultSetHelper::ABSOLUTE: + case IResultSetHelper::BOOKMARK: + m_nFilePos = (sal_uInt32)nOffset; + break; + } + + if (m_nFilePos > (sal_Int32)nNumberOfRecords) + m_nFilePos = (sal_Int32)nNumberOfRecords + 1; + + if (m_nFilePos == 0 || m_nFilePos == (sal_Int32)nNumberOfRecords + 1) + goto Error; + else + { + sal_uInt16 nEntryLen = m_aHeader.db_slng; + + OSL_ENSURE(m_nFilePos >= 1,"SdbDBFCursor::FileFetchRow: ungueltige Record-Position"); + sal_Int32 nPos = m_aHeader.db_kopf + (sal_Int32)(m_nFilePos-1) * nEntryLen; + + ULONG nLen = m_pFileStream->Seek(nPos); + if (m_pFileStream->GetError() != ERRCODE_NONE) + goto Error; + + nLen = m_pFileStream->Read((char*)m_pBuffer, nEntryLen); + if (m_pFileStream->GetError() != ERRCODE_NONE) + goto Error; + } + goto End; + +Error: + switch(eCursorPosition) + { + case IResultSetHelper::PRIOR: + case IResultSetHelper::FIRST: + m_nFilePos = 0; + break; + case IResultSetHelper::LAST: + case IResultSetHelper::NEXT: + case IResultSetHelper::ABSOLUTE: + case IResultSetHelper::RELATIVE: + if (nOffset > 0) + m_nFilePos = nNumberOfRecords + 1; + else if (nOffset < 0) + m_nFilePos = 0; + break; + case IResultSetHelper::BOOKMARK: + m_nFilePos = nTempPos; // vorherige Position + } + // aStatus.Set(SDB_STAT_NO_DATA_FOUND); + return sal_False; + +End: + nCurPos = m_nFilePos; + return sal_True; +} +// ----------------------------------------------------------------------------- +BOOL ODbaseTable::ReadMemo(ULONG nBlockNo, ORowSetValue& aVariable) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbase", "Ocke.Janssen@sun.com", "ODbaseTable::ReadMemo" ); + BOOL bIsText = TRUE; + // SdbConnection* pConnection = GetConnection(); + + m_pMemoStream->Seek(nBlockNo * m_aMemoHeader.db_size); + switch (m_aMemoHeader.db_typ) + { + case MemodBaseIII: // dBase III-Memofeld, endet mit Ctrl-Z + { + const char cEOF = (char) 0x1a; + ByteString aBStr; + static char aBuf[514]; + aBuf[512] = 0; // sonst kann der Zufall uebel mitspielen + BOOL bReady = sal_False; + + do + { + m_pMemoStream->Read(&aBuf,512); + + USHORT i = 0; + while (aBuf[i] != cEOF && ++i < 512) + ; + bReady = aBuf[i] == cEOF; + + aBuf[i] = 0; + aBStr += aBuf; + + } while (!bReady && !m_pMemoStream->IsEof() && aBStr.Len() < STRING_MAXLEN); + + ::rtl::OUString aStr(aBStr.GetBuffer(), aBStr.Len(),getConnection()->getTextEncoding()); + aVariable = aStr; + + } break; + case MemoFoxPro: + case MemodBaseIV: // dBase IV-Memofeld mit Laengenangabe + { + char sHeader[4]; + m_pMemoStream->Read(sHeader,4); + // Foxpro stores text and binary data + if (m_aMemoHeader.db_typ == MemoFoxPro) + { + if (((BYTE)sHeader[0]) != 0 || ((BYTE)sHeader[1]) != 0 || ((BYTE)sHeader[2]) != 0) + { +// String aText = String(SdbResId(STR_STAT_IResultSetHelper::INVALID)); +// aText.SearchAndReplace(String::CreateFromAscii("%%d"),m_pMemoStream->GetFileName()); +// aText.SearchAndReplace(String::CreateFromAscii("%%t"),aStatus.TypeToString(MEMO)); +// aStatus.Set(SDB_STAT_ERROR, +// String::CreateFromAscii("01000"), +// aStatus.CreateErrorMessage(aText), +// 0, String() ); + return sal_False; + } + + bIsText = sHeader[3] != 0; + } + else if (((BYTE)sHeader[0]) != 0xFF || ((BYTE)sHeader[1]) != 0xFF || ((BYTE)sHeader[2]) != 0x08) + { +// String aText = String(SdbResId(STR_STAT_IResultSetHelper::INVALID)); +// aText.SearchAndReplace(String::CreateFromAscii("%%d"),m_pMemoStream->GetFileName()); +// aText.SearchAndReplace(String::CreateFromAscii("%%t"),aStatus.TypeToString(MEMO)); +// aStatus.Set(SDB_STAT_ERROR, +// String::CreateFromAscii("01000"), +// aStatus.CreateErrorMessage(aText), +// 0, String() ); + return sal_False; + } + + sal_uInt32 nLength; + (*m_pMemoStream) >> nLength; + + if (m_aMemoHeader.db_typ == MemodBaseIV) + nLength -= 8; + + // char cChar; + ::rtl::OUString aStr; + while ( nLength > STRING_MAXLEN ) + { + ByteString aBStr; + aBStr.Expand(STRING_MAXLEN); + m_pMemoStream->Read(aBStr.AllocBuffer(STRING_MAXLEN),STRING_MAXLEN); + aStr += ::rtl::OUString(aBStr.GetBuffer(),aBStr.Len(), getConnection()->getTextEncoding()); + nLength -= STRING_MAXLEN; + } + if ( nLength > 0 ) + { + ByteString aBStr; + aBStr.Expand(static_cast<xub_StrLen>(nLength)); + m_pMemoStream->Read(aBStr.AllocBuffer(static_cast<xub_StrLen>(nLength)),nLength); + // aBStr.ReleaseBufferAccess(); + + aStr += ::rtl::OUString(aBStr.GetBuffer(),aBStr.Len(), getConnection()->getTextEncoding()); + + } + if ( aStr.getLength() ) + aVariable = aStr; + } + } + return sal_True; +} +// ----------------------------------------------------------------------------- +void ODbaseTable::AllocBuffer() +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbase", "Ocke.Janssen@sun.com", "ODbaseTable::AllocBuffer" ); + UINT16 nSize = m_aHeader.db_slng; + OSL_ENSURE(nSize > 0, "Size too small"); + + if (m_nBufferSize != nSize) + { + delete[] m_pBuffer; + m_pBuffer = NULL; + } + + // Falls noch kein Puffer vorhanden: allozieren: + if (m_pBuffer == NULL && nSize) + { + m_nBufferSize = nSize; + m_pBuffer = new BYTE[m_nBufferSize+1]; + } +} +// ----------------------------------------------------------------------------- +BOOL ODbaseTable::WriteBuffer() +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbase", "Ocke.Janssen@sun.com", "ODbaseTable::WriteBuffer" ); + OSL_ENSURE(m_nFilePos >= 1,"SdbDBFCursor::FileFetchRow: ungueltige Record-Position"); + + // Auf gewuenschten Record positionieren: + long nPos = m_aHeader.db_kopf + (long)(m_nFilePos-1) * m_aHeader.db_slng; + m_pFileStream->Seek(nPos); + return m_pFileStream->Write((char*) m_pBuffer, m_aHeader.db_slng) > 0; +} +// ----------------------------------------------------------------------------- +sal_Int32 ODbaseTable::getCurrentLastPos() const +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbase", "Ocke.Janssen@sun.com", "ODbaseTable::getCurrentLastPos" ); + return m_aHeader.db_anz; +} +// ----------------------------------------------------------------------------- +//================================================================== +// ONDXNode +//================================================================== + +//------------------------------------------------------------------ +void ONDXNode::Read(SvStream &rStream, ODbaseIndex& rIndex) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbase", "Ocke.Janssen@sun.com", "ONDXNode::Read" ); + rStream >> aKey.nRecord; // schluessel + + if (rIndex.getHeader().db_keytype) + { + double aDbl; + rStream >> aDbl; + aKey = ONDXKey(aDbl,aKey.nRecord); + } + else + { + ByteString aBuf; + USHORT nLen = rIndex.getHeader().db_keylen; + char* pStr = aBuf.AllocBuffer(nLen+1); + + rStream.Read(pStr,nLen); + pStr[nLen] = 0; + aBuf.ReleaseBufferAccess(); + aBuf.EraseTrailingChars(); + + // aKey = ONDXKey((aBuf,rIndex.GetDBFConnection()->GetCharacterSet()) ,aKey.nRecord); + aKey = ONDXKey(::rtl::OUString(aBuf.GetBuffer(),aBuf.Len(),rIndex.m_pTable->getConnection()->getTextEncoding()) ,aKey.nRecord); + } + rStream >> aChild; +} + +union +{ + double aDbl; + char aData[128]; +} aNodeData; +//------------------------------------------------------------------ +void ONDXNode::Write(SvStream &rStream, const ONDXPage& rPage) const +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbase", "Ocke.Janssen@sun.com", "ONDXNode::Write" ); + const ODbaseIndex& rIndex = rPage.GetIndex(); + if (!rIndex.isUnique() || rPage.IsLeaf()) + rStream << (sal_uInt32)aKey.nRecord; // schluessel + else + rStream << (sal_uInt32)0; // schluessel + + if (rIndex.getHeader().db_keytype) // double + { + if (aKey.getValue().isNull()) + { + memset(aNodeData.aData,0,rIndex.getHeader().db_keylen); + rStream.Write((BYTE*)aNodeData.aData,rIndex.getHeader().db_keylen); + } + else + rStream << (double) aKey.getValue(); + } + else + { + memset(aNodeData.aData,0x20,rIndex.getHeader().db_keylen); + if (!aKey.getValue().isNull()) + { + ::rtl::OUString sValue = aKey.getValue(); + ByteString aText(sValue.getStr(), rIndex.m_pTable->getConnection()->getTextEncoding()); + strncpy(aNodeData.aData,aText.GetBuffer(),std::min(rIndex.getHeader().db_keylen, aText.Len())); + } + rStream.Write((BYTE*)aNodeData.aData,rIndex.getHeader().db_keylen); + } + rStream << aChild; +} + + +//------------------------------------------------------------------ +ONDXPagePtr& ONDXNode::GetChild(ODbaseIndex* pIndex, ONDXPage* pParent) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbase", "Ocke.Janssen@sun.com", "ONDXNode::GetChild" ); + if (!aChild.Is() && pIndex) + { + aChild = pIndex->CreatePage(aChild.GetPagePos(),pParent,aChild.HasPage()); + } + return aChild; +} + +//================================================================== +// ONDXKey +//================================================================== +//------------------------------------------------------------------ +BOOL ONDXKey::IsText(sal_Int32 eType) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbase", "Ocke.Janssen@sun.com", "ONDXKey::IsText" ); + return eType == DataType::VARCHAR || eType == DataType::CHAR; +} + +//------------------------------------------------------------------ +StringCompare ONDXKey::Compare(const ONDXKey& rKey) const +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbase", "Ocke.Janssen@sun.com", "ONDXKey::Compare" ); + // DBG_ASSERT(is(), "Falscher Indexzugriff"); + StringCompare eResult; + + if (getValue().isNull()) + { + if (rKey.getValue().isNull() || (rKey.IsText(getDBType()) && !rKey.getValue().getString().getLength())) + eResult = COMPARE_EQUAL; + else + eResult = COMPARE_LESS; + } + else if (rKey.getValue().isNull()) + { + if (getValue().isNull() || (IsText(getDBType()) && !getValue().getString().getLength())) + eResult = COMPARE_EQUAL; + else + eResult = COMPARE_GREATER; + } + else if (IsText(getDBType())) + { + INT32 nRes = getValue().getString().compareTo(rKey.getValue()); + eResult = (nRes > 0) ? COMPARE_GREATER : (nRes == 0) ? COMPARE_EQUAL : COMPARE_LESS; + } + else + { + double m = getValue(),n = rKey.getValue(); + eResult = (m > n) ? COMPARE_GREATER : (n == m) ? COMPARE_EQUAL : COMPARE_LESS; + } + + // Record vergleich, wenn Index !Unique + if (eResult == COMPARE_EQUAL && nRecord && rKey.nRecord) + eResult = (nRecord > rKey.nRecord) ? COMPARE_GREATER : + (nRecord == rKey.nRecord) ? COMPARE_EQUAL : COMPARE_LESS; + + return eResult; +} +// ----------------------------------------------------------------------------- +void ONDXKey::setValue(const ORowSetValue& _rVal) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbase", "Ocke.Janssen@sun.com", "ONDXKey::setValue" ); + xValue = _rVal; +} +// ----------------------------------------------------------------------------- +const ORowSetValue& ONDXKey::getValue() const +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbase", "Ocke.Janssen@sun.com", "ONDXKey::getValue" ); + return xValue; +} +// ----------------------------------------------------------------------------- +SvStream& connectivity::dbase::operator >> (SvStream &rStream, ONDXPagePtr& rPage) +{ + rStream >> rPage.nPagePos; + return rStream; +} +// ----------------------------------------------------------------------------- +SvStream& connectivity::dbase::operator << (SvStream &rStream, const ONDXPagePtr& rPage) +{ + rStream << rPage.nPagePos; + return rStream; +} +// ----------------------------------------------------------------------------- +//================================================================== +// ONDXPagePtr +//================================================================== +//------------------------------------------------------------------ +ONDXPagePtr::ONDXPagePtr(const ONDXPagePtr& rRef) + :ONDXPageRef(rRef) + ,nPagePos(rRef.nPagePos) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbase", "Ocke.Janssen@sun.com", "ONDXPagePtr::ONDXPagePtr" ); +} + +//------------------------------------------------------------------ +ONDXPagePtr::ONDXPagePtr(ONDXPage* pRefPage) + :ONDXPageRef(pRefPage) + ,nPagePos(0) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbase", "Ocke.Janssen@sun.com", "ONDXPagePtr::ONDXPagePtr" ); + if (pRefPage) + nPagePos = pRefPage->GetPagePos(); +} +//------------------------------------------------------------------ +ONDXPagePtr& ONDXPagePtr::operator=(const ONDXPagePtr& rRef) +{ + ONDXPageRef::operator=(rRef); + nPagePos = rRef.nPagePos; + return *this; +} + +//------------------------------------------------------------------ +ONDXPagePtr& ONDXPagePtr::operator= (ONDXPage* pRef) +{ + ONDXPageRef::operator=(pRef); + nPagePos = (pRef) ? pRef->GetPagePos() : 0; + return *this; +} +// ----------------------------------------------------------------------------- +static UINT32 nValue; +//------------------------------------------------------------------ +SvStream& connectivity::dbase::operator >> (SvStream &rStream, ONDXPage& rPage) +{ + rStream.Seek(rPage.GetPagePos() * 512); + rStream >> nValue >> rPage.aChild; + rPage.nCount = USHORT(nValue); + +// DBG_ASSERT(rPage.nCount && rPage.nCount < rPage.GetIndex().GetMaxNodes(), "Falscher Count"); + for (USHORT i = 0; i < rPage.nCount; i++) + rPage[i].Read(rStream, rPage.GetIndex()); + return rStream; +} + +//------------------------------------------------------------------ +SvStream& connectivity::dbase::operator << (SvStream &rStream, const ONDXPage& rPage) +{ + // Seite existiert noch nicht + ULONG nSize = (rPage.GetPagePos() + 1) * 512; + if (nSize > rStream.Seek(STREAM_SEEK_TO_END)) + { + rStream.SetStreamSize(nSize); + rStream.Seek(rPage.GetPagePos() * 512); + + char aEmptyData[512]; + memset(aEmptyData,0x00,512); + rStream.Write((BYTE*)aEmptyData,512); + } + ULONG nCurrentPos = rStream.Seek(rPage.GetPagePos() * 512); + OSL_UNUSED( nCurrentPos ); + + nValue = rPage.nCount; + rStream << nValue << rPage.aChild; + + USHORT i = 0; + for (; i < rPage.nCount; i++) + rPage[i].Write(rStream, rPage); + + // check if we have to fill the stream with '\0' + if(i < rPage.rIndex.getHeader().db_maxkeys) + { + ULONG nTell = rStream.Tell() % 512; + USHORT nBufferSize = rStream.GetBufferSize(); + ULONG nSize = nBufferSize - nTell; + char* pEmptyData = new char[nSize]; + memset(pEmptyData,0x00,nSize); + rStream.Write((BYTE*)pEmptyData,nSize); + rStream.Seek(nTell); + delete [] pEmptyData; + } + return rStream; +} +// ----------------------------------------------------------------------------- +#if OSL_DEBUG_LEVEL > 1 +//------------------------------------------------------------------ +void ONDXPage::PrintPage() +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbase", "Ocke.Janssen@sun.com", "ONDXPage::PrintPage" ); + DBG_TRACE4("\nSDB: -----------Page: %d Parent: %d Count: %d Child: %d-----", + nPagePos, HasParent() ? aParent->GetPagePos() : 0 ,nCount, aChild.GetPagePos()); + + for (USHORT i = 0; i < nCount; i++) + { + ONDXNode rNode = (*this)[i]; + ONDXKey& rKey = rNode.GetKey(); + if (!IsLeaf()) + rNode.GetChild(&rIndex, this); + + if (rKey.getValue().isNull()) + { + DBG_TRACE2("SDB: [%d,NULL,%d]",rKey.GetRecord(), rNode.GetChild().GetPagePos()); + } + else if (rIndex.getHeader().db_keytype) + { + DBG_TRACE3("SDB: [%d,%f,%d]",rKey.GetRecord(), rKey.getValue().getDouble(),rNode.GetChild().GetPagePos()); + } + else + { + DBG_TRACE3("SDB: [%d,%s,%d]",rKey.GetRecord(), (const char* )ByteString(rKey.getValue().getString().getStr(), rIndex.m_pTable->getConnection()->getTextEncoding()).GetBuffer(),rNode.GetChild().GetPagePos()); + } + } + DBG_TRACE("SDB: -----------------------------------------------\n"); + if (!IsLeaf()) + { +#if OSL_DEBUG_LEVEL > 1 + GetChild(&rIndex)->PrintPage(); + for (USHORT i = 0; i < nCount; i++) + { + ONDXNode rNode = (*this)[i]; + rNode.GetChild(&rIndex,this)->PrintPage(); + } +#endif + } + DBG_TRACE("SDB: ===============================================\n"); +} +#endif +// ----------------------------------------------------------------------------- +BOOL ONDXPage::IsFull() const +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbase", "Ocke.Janssen@sun.com", "ONDXPage::IsFull" ); + return Count() == rIndex.getHeader().db_maxkeys; +} +// ----------------------------------------------------------------------------- +//------------------------------------------------------------------ +USHORT ONDXPage::Search(const ONDXKey& rSearch) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbase", "Ocke.Janssen@sun.com", "ONDXPage::Search" ); + // binare Suche spaeter + USHORT i = 0xFFFF; + while (++i < Count()) + if ((*this)[i].GetKey() == rSearch) + break; + + return (i < Count()) ? i : NODE_NOTFOUND; +} + +//------------------------------------------------------------------ +USHORT ONDXPage::Search(const ONDXPage* pPage) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbase", "Ocke.Janssen@sun.com", "ONDXPage::Search" ); + USHORT i = 0xFFFF; + while (++i < Count()) + if (((*this)[i]).GetChild() == pPage) + break; + + // wenn nicht gefunden, dann wird davon ausgegangen, dass die Seite selbst + // auf die Page zeigt + return (i < Count()) ? i : NODE_NOTFOUND; +} +// ----------------------------------------------------------------------------- +// laeuft rekursiv +void ONDXPage::SearchAndReplace(const ONDXKey& rSearch, + ONDXKey& rReplace) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbase", "Ocke.Janssen@sun.com", "ONDXPage::SearchAndReplace" ); + OSL_ENSURE(rSearch != rReplace,"Invalid here:rSearch == rReplace"); + if (rSearch != rReplace) + { + USHORT nPos = NODE_NOTFOUND; + ONDXPage* pPage = this; + + while (pPage && (nPos = pPage->Search(rSearch)) == NODE_NOTFOUND) + pPage = pPage->aParent; + + if (pPage) + { + (*pPage)[nPos].GetKey() = rReplace; + pPage->SetModified(TRUE); + } + } +} +// ----------------------------------------------------------------------------- +ONDXNode& ONDXPage::operator[] (USHORT nPos) +{ + DBG_ASSERT(nCount > nPos, "falscher Indexzugriff"); + return ppNodes[nPos]; +} + +//------------------------------------------------------------------ +const ONDXNode& ONDXPage::operator[] (USHORT nPos) const +{ + DBG_ASSERT(nCount > nPos, "falscher Indexzugriff"); + return ppNodes[nPos]; +} +// ----------------------------------------------------------------------------- +void ONDXPage::Remove(USHORT nPos) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbase", "Ocke.Janssen@sun.com", "ONDXPage::Remove" ); + DBG_ASSERT(nCount > nPos, "falscher Indexzugriff"); + + for (USHORT i = nPos; i < (nCount-1); i++) + (*this)[i] = (*this)[i+1]; + + nCount--; + bModified = TRUE; +} +// ----------------------------------------------------------------------------- + + + + + + + + + + + diff --git a/connectivity/source/drivers/dbase/DPreparedStatement.cxx b/connectivity/source/drivers/dbase/DPreparedStatement.cxx new file mode 100644 index 000000000000..42bfff750eca --- /dev/null +++ b/connectivity/source/drivers/dbase/DPreparedStatement.cxx @@ -0,0 +1,42 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_connectivity.hxx" +#include "dbase/DPreparedStatement.hxx" +#include "dbase/DResultSet.hxx" + +using namespace connectivity::dbase; +using namespace connectivity::file; +using namespace com::sun::star::uno; +// ------------------------------------------------------------------------- +OResultSet* ODbasePreparedStatement::createResultSet() +{ + return new ODbaseResultSet(this,m_aSQLIterator); +} +// ------------------------------------------------------------------------- +IMPLEMENT_SERVICE_INFO(ODbasePreparedStatement,"com.sun.star.sdbc.driver.dbase.PreparedStatement","com.sun.star.sdbc.PreparedStatement"); diff --git a/connectivity/source/drivers/dbase/DResultSet.cxx b/connectivity/source/drivers/dbase/DResultSet.cxx new file mode 100644 index 000000000000..ab19bc49ff9d --- /dev/null +++ b/connectivity/source/drivers/dbase/DResultSet.cxx @@ -0,0 +1,249 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_connectivity.hxx" +#include <com/sun/star/sdbcx/CompareBookmark.hpp> +#include "dbase/DResultSet.hxx" +#include <com/sun/star/lang/DisposedException.hpp> +#include <comphelper/sequence.hxx> +#include "dbase/DIndex.hxx" +#include "dbase/DIndexIter.hxx" +#include "dbase/DCode.hxx" +#include <comphelper/types.hxx> +#include <connectivity/dbexception.hxx> +#include "resource/dbase_res.hrc" + +using namespace ::comphelper; + +using namespace connectivity::dbase; +using namespace connectivity::file; +using namespace ::cppu; +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::sdbcx; +// using namespace com::sun::star::container; +// using namespace com::sun::star::util; +//------------------------------------------------------------------------------ +ODbaseResultSet::ODbaseResultSet( OStatement_Base* pStmt,connectivity::OSQLParseTreeIterator& _aSQLIterator) + : file::OResultSet(pStmt,_aSQLIterator) + ,m_bBookmarkable(sal_True) +{ + registerProperty(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_ISBOOKMARKABLE), PROPERTY_ID_ISBOOKMARKABLE, PropertyAttribute::READONLY,&m_bBookmarkable, ::getBooleanCppuType()); +} +// ------------------------------------------------------------------------- +::rtl::OUString SAL_CALL ODbaseResultSet::getImplementationName( ) throw ( RuntimeException) +{ + return ::rtl::OUString::createFromAscii("com.sun.star.sdbcx.dbase.ResultSet"); +} +// ------------------------------------------------------------------------- +Sequence< ::rtl::OUString > SAL_CALL ODbaseResultSet::getSupportedServiceNames( ) throw( RuntimeException) +{ + Sequence< ::rtl::OUString > aSupported(2); + aSupported[0] = ::rtl::OUString::createFromAscii("com.sun.star.sdbc.ResultSet"); + aSupported[1] = ::rtl::OUString::createFromAscii("com.sun.star.sdbcx.ResultSet"); + return aSupported; +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL ODbaseResultSet::supportsService( const ::rtl::OUString& _rServiceName ) throw( RuntimeException) +{ + Sequence< ::rtl::OUString > aSupported(getSupportedServiceNames()); + const ::rtl::OUString* pSupported = aSupported.getConstArray(); + const ::rtl::OUString* pEnd = pSupported + aSupported.getLength(); + for (;pSupported != pEnd && !pSupported->equals(_rServiceName); ++pSupported) + ; + + return pSupported != pEnd; +} +// ------------------------------------------------------------------------- +Any SAL_CALL ODbaseResultSet::queryInterface( const Type & rType ) throw(RuntimeException) +{ + Any aRet = ODbaseResultSet_BASE::queryInterface(rType); + return aRet.hasValue() ? aRet : OResultSet::queryInterface(rType); +} +// ------------------------------------------------------------------------- + Sequence< Type > SAL_CALL ODbaseResultSet::getTypes( ) throw( RuntimeException) +{ + return ::comphelper::concatSequences(OResultSet::getTypes(),ODbaseResultSet_BASE::getTypes()); +} + +// ------------------------------------------------------------------------- +// XRowLocate +Any SAL_CALL ODbaseResultSet::getBookmark( ) throw( SQLException, RuntimeException) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(OResultSet_BASE::rBHelper.bDisposed); + OSL_ENSURE((m_bShowDeleted || !m_aRow->isDeleted()),"getBookmark called for deleted row"); + + return makeAny((sal_Int32)(m_aRow->get())[0]->getValue()); +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL ODbaseResultSet::moveToBookmark( const Any& bookmark ) throw( SQLException, RuntimeException) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(OResultSet_BASE::rBHelper.bDisposed); + + + m_bRowDeleted = m_bRowInserted = m_bRowUpdated = sal_False; + + return m_pTable ? Move(IResultSetHelper::BOOKMARK,comphelper::getINT32(bookmark),sal_True) : sal_False; +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL ODbaseResultSet::moveRelativeToBookmark( const Any& bookmark, sal_Int32 rows ) throw( SQLException, RuntimeException) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(OResultSet_BASE::rBHelper.bDisposed); + if(!m_pTable) + return sal_False; + + + Move(IResultSetHelper::BOOKMARK,comphelper::getINT32(bookmark),sal_False); + + return relative(rows); +} + +// ------------------------------------------------------------------------- +sal_Int32 SAL_CALL ODbaseResultSet::compareBookmarks( const Any& lhs, const Any& rhs ) throw( SQLException, RuntimeException) +{ + sal_Int32 nFirst(0),nSecond(0),nResult(0); + if ( !( lhs >>= nFirst ) || !( rhs >>= nSecond ) ) + { + ::connectivity::SharedResources aResources; + const ::rtl::OUString sMessage = aResources.getResourceString(STR_INVALID_BOOKMARK); + ::dbtools::throwGenericSQLException(sMessage ,*this); + } // if ( !( lhs >>= nFirst ) || !( rhs >>= nSecond ) ) + + // have a look at CompareBookmark + // we can't use the names there because we already have defines with the same name from the parser + if(nFirst < nSecond) + nResult = -1; + else if(nFirst > nSecond) + nResult = 1; + else + nResult = 0; + + return nResult; +} +// ------------------------------------------------------------------------- +sal_Bool SAL_CALL ODbaseResultSet::hasOrderedBookmarks( ) throw( SQLException, RuntimeException) +{ + return sal_True; +} +// ------------------------------------------------------------------------- +sal_Int32 SAL_CALL ODbaseResultSet::hashBookmark( const Any& bookmark ) throw( SQLException, RuntimeException) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(OResultSet_BASE::rBHelper.bDisposed); + + + return comphelper::getINT32(bookmark); +} +// ------------------------------------------------------------------------- +// XDeleteRows +Sequence< sal_Int32 > SAL_CALL ODbaseResultSet::deleteRows( const Sequence< Any >& /*rows*/ ) throw( SQLException, RuntimeException) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(OResultSet_BASE::rBHelper.bDisposed); + + ::dbtools::throwFeatureNotImplementedException( "XDeleteRows::deleteRows", *this ); + return Sequence< sal_Int32 >(); +} +// ------------------------------------------------------------------------- +sal_Bool ODbaseResultSet::fillIndexValues(const Reference< XColumnsSupplier> &_xIndex) +{ + Reference<XUnoTunnel> xTunnel(_xIndex,UNO_QUERY); + if(xTunnel.is()) + { + dbase::ODbaseIndex* pIndex = reinterpret_cast< dbase::ODbaseIndex* >( xTunnel->getSomething(dbase::ODbaseIndex::getUnoTunnelImplementationId()) ); + if(pIndex) + { + dbase::OIndexIterator* pIter = pIndex->createIterator(NULL,NULL); + + if (pIter) + { + sal_uInt32 nRec = pIter->First(); + while (nRec != SQL_COLUMN_NOTFOUND) + { + if (m_aOrderbyAscending[0]) + m_pFileSet->get().push_back(nRec); + else + m_pFileSet->get().insert(m_pFileSet->get().begin(),nRec); + nRec = pIter->Next(); + } + m_pFileSet->setFrozen(); + // if(!bDistinct) + // SetRowCount(pFileSet->count()); + delete pIter; + return sal_True; + } + delete pIter; + } + } + return sal_False; +} +// ------------------------------------------------------------------------- +::cppu::IPropertyArrayHelper & ODbaseResultSet::getInfoHelper() +{ + return *ODbaseResultSet_BASE3::getArrayHelper(); +} +// ----------------------------------------------------------------------------- +::cppu::IPropertyArrayHelper* ODbaseResultSet::createArrayHelper() const +{ + Sequence< Property > aProps; + describeProperties(aProps); + return new ::cppu::OPropertyArrayHelper(aProps); +} +// ----------------------------------------------------------------------------- +void SAL_CALL ODbaseResultSet::acquire() throw() +{ + ODbaseResultSet_BASE2::acquire(); +} +// ----------------------------------------------------------------------------- +void SAL_CALL ODbaseResultSet::release() throw() +{ + ODbaseResultSet_BASE2::release(); +} +// ----------------------------------------------------------------------------- +::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySetInfo > SAL_CALL ODbaseResultSet::getPropertySetInfo( ) throw(::com::sun::star::uno::RuntimeException) +{ + return ::cppu::OPropertySetHelper::createPropertySetInfo(getInfoHelper()); +} +// ----------------------------------------------------------------------------- +OSQLAnalyzer* ODbaseResultSet::createAnalyzer() +{ + return new OFILEAnalyzer(m_pTable->getConnection()); +} +// ----------------------------------------------------------------------------- +sal_Int32 ODbaseResultSet::getCurrentFilePos() const +{ + return m_pTable->getFilePos(); +} +// ----------------------------------------------------------------------------- + + diff --git a/connectivity/source/drivers/dbase/DStatement.cxx b/connectivity/source/drivers/dbase/DStatement.cxx new file mode 100644 index 000000000000..f65cfabe0dda --- /dev/null +++ b/connectivity/source/drivers/dbase/DStatement.cxx @@ -0,0 +1,44 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_connectivity.hxx" +#include "dbase/DStatement.hxx" +#include "dbase/DResultSet.hxx" + +using namespace connectivity::dbase; +using namespace connectivity::file; +using namespace com::sun::star::uno; + +// ------------------------------------------------------------------------- +OResultSet* ODbaseStatement::createResultSet() +{ + return new ODbaseResultSet(this,m_aSQLIterator); +} +// ------------------------------------------------------------------------- +IMPLEMENT_SERVICE_INFO(ODbaseStatement,"com.sun.star.sdbc.driver.dbase.Statement","com.sun.star.sdbc.Statement"); + diff --git a/connectivity/source/drivers/dbase/DTable.cxx b/connectivity/source/drivers/dbase/DTable.cxx new file mode 100644 index 000000000000..157d1f7b68fa --- /dev/null +++ b/connectivity/source/drivers/dbase/DTable.cxx @@ -0,0 +1,2855 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_connectivity.hxx" +#include "dbase/DTable.hxx" +#include <com/sun/star/sdbc/ColumnValue.hpp> +#include <com/sun/star/sdbc/DataType.hpp> +#include <com/sun/star/ucb/XContentAccess.hpp> +#include <com/sun/star/sdbc/XRow.hpp> +#include <svl/converter.hxx> +#include "dbase/DConnection.hxx" +#include "dbase/DColumns.hxx" +#include <osl/thread.h> +#include <tools/config.hxx> +#include "dbase/DIndex.hxx" +#include "dbase/DIndexes.hxx" +//#include "file/FDriver.hxx" +#include <comphelper/sequence.hxx> +#include <svl/zforlist.hxx> +#include <unotools/syslocale.hxx> +#include <rtl/math.hxx> +#include <stdio.h> //sprintf +#include <ucbhelper/content.hxx> +#include <comphelper/extract.hxx> +#include <connectivity/dbexception.hxx> +#include <connectivity/dbconversion.hxx> +#include <com/sun/star/lang/DisposedException.hpp> +#include <comphelper/property.hxx> +//#include <unotools/calendarwrapper.hxx> +#include <unotools/tempfile.hxx> +#include <unotools/ucbhelper.hxx> +#include <comphelper/types.hxx> +#include <cppuhelper/exc_hlp.hxx> +#include "connectivity/PColumn.hxx" +#include "connectivity/dbtools.hxx" +#include "connectivity/FValue.hxx" +#include "connectivity/dbconversion.hxx" +#include "resource/dbase_res.hrc" +#include <rtl/logfile.hxx> + +#include <algorithm> + +using namespace ::comphelper; +using namespace connectivity; +using namespace connectivity::sdbcx; +using namespace connectivity::dbase; +using namespace connectivity::file; +using namespace ::ucbhelper; +using namespace ::utl; +using namespace ::cppu; +using namespace ::dbtools; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::ucb; +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::i18n; + +// stored as the Field Descriptor terminator +#define FIELD_DESCRIPTOR_TERMINATOR 0x0D +#define DBF_EOL 0x1A + +namespace +{ +sal_Int32 lcl_getFileSize(SvStream& _rStream) +{ + sal_Int32 nFileSize = 0; + _rStream.Seek(STREAM_SEEK_TO_END); + _rStream.SeekRel(-1); + char cEOL; + _rStream >> cEOL; + nFileSize = _rStream.Tell(); + if ( cEOL == DBF_EOL ) + nFileSize -= 1; + return nFileSize; +} +/** + calculates the Julian date +*/ +void lcl_CalcJulDate(sal_Int32& _nJulianDate,sal_Int32& _nJulianTime,const com::sun::star::util::DateTime _aDateTime) +{ + com::sun::star::util::DateTime aDateTime = _aDateTime; + // weird: months fix + if (aDateTime.Month > 12) + { + aDateTime.Month--; + sal_uInt16 delta = _aDateTime.Month / 12; + aDateTime.Year += delta; + aDateTime.Month -= delta * 12; + aDateTime.Month++; + } + + _nJulianTime = ((aDateTime.Hours*3600000)+(aDateTime.Minutes*60000)+(aDateTime.Seconds*1000)+(aDateTime.HundredthSeconds*10)); + /* conversion factors */ + sal_uInt16 iy0; + sal_uInt16 im0; + if ( aDateTime.Month <= 2 ) + { + iy0 = aDateTime.Year - 1; + im0 = aDateTime.Month + 12; + } + else + { + iy0 = aDateTime.Year; + im0 = aDateTime.Month; + } + sal_Int32 ia = iy0 / 100; + sal_Int32 ib = 2 - ia + (ia >> 2); + /* calculate julian date */ + if ( aDateTime.Year <= 0 ) + { + _nJulianDate = (sal_Int32) ((365.25 * iy0) - 0.75) + + (sal_Int32) (30.6001 * (im0 + 1) ) + + aDateTime.Day + 1720994; + } // if ( _aDateTime.Year <= 0 ) + else + { + _nJulianDate = static_cast<sal_Int32>( ((365.25 * iy0) + + (sal_Int32) (30.6001 * (im0 + 1)) + + aDateTime.Day + 1720994)); + } + double JD = _nJulianDate + 0.5; + _nJulianDate = (sal_Int32)( JD + 0.5); + const double gyr = aDateTime.Year + (0.01 * aDateTime.Month) + (0.0001 * aDateTime.Day); + if ( gyr >= 1582.1015 ) /* on or after 15 October 1582 */ + _nJulianDate += ib; +} + +/** + calculates date time from the Julian Date +*/ +void lcl_CalDate(sal_Int32 _nJulianDate,sal_Int32 _nJulianTime,com::sun::star::util::DateTime& _rDateTime) +{ + if ( _nJulianDate ) + { + sal_Int32 ialp; + sal_Int32 ka = _nJulianDate; + if ( _nJulianDate >= 2299161 ) + { + ialp = (sal_Int32)( ((double) _nJulianDate - 1867216.25 ) / ( 36524.25 )); + ka = _nJulianDate + 1 + ialp - ( ialp >> 2 ); + } + sal_Int32 kb = ka + 1524; + sal_Int32 kc = (sal_Int32) ( ((double) kb - 122.1 ) / 365.25 ); + sal_Int32 kd = (sal_Int32) ((double) kc * 365.25); + sal_Int32 ke = (sal_Int32) ((double) ( kb - kd ) / 30.6001 ); + _rDateTime.Day = static_cast<sal_uInt16>(kb - kd - ((sal_Int32) ( (double) ke * 30.6001 ))); + if ( ke > 13 ) + _rDateTime.Month = static_cast<sal_uInt16>(ke - 13); + else + _rDateTime.Month = static_cast<sal_uInt16>(ke - 1); + if ( (_rDateTime.Month == 2) && (_rDateTime.Day > 28) ) + _rDateTime.Day = 29; + if ( (_rDateTime.Month == 2) && (_rDateTime.Day == 29) && (ke == 3) ) + _rDateTime.Year = static_cast<sal_uInt16>(kc - 4716); + else if ( _rDateTime.Month > 2 ) + _rDateTime.Year = static_cast<sal_uInt16>(kc - 4716); + else + _rDateTime.Year = static_cast<sal_uInt16>(kc - 4715); + } // if ( _nJulianDate ) + + if ( _nJulianTime ) + { + double d_s = _nJulianTime / 1000; + double d_m = d_s / 60; + double d_h = d_m / 60; + _rDateTime.Hours = (sal_uInt16) (d_h); + _rDateTime.Minutes = (sal_uInt16) d_m; // integer _aDateTime.Minutes + //// weird: time fix + // int test = (_rDateTime.Hours % 3) * 100 + _rDateTime.Minutes; + //int test_tbl[] = {0, 1, 2, 11, 12, 13, 22, 23, 24, 25, 34, 35, 36, + // 45, 46, 47, 56, 57, 58, 107, 108, 109, 110, 119, 120, 121, + // 130, 131, 132, 141, 142, 143, 152, 153, 154, 155, 204, 205, + // 206, 215, 216, 217, 226, 227, 228, 237, 238, 239, 240, 249, + // 250, 251}; + // for (int i = 0; i < sizeof(test_tbl)/sizeof(test_tbl[0]); i++) + //{ + // if (test == test_tbl[i]) + // { + // // frac += 0.000012; + // //d_hour = frac * 24.0; + // _rDateTime.Hours = (sal_uInt16)d_hour; + // d_minute = (d_hour - (double)_rDateTime.Hours) * 60.0; + // _rDateTime.Minutes = (sal_uInt16)d_minute; + // break; + // } + // } + + _rDateTime.Seconds = static_cast<sal_uInt16>(( d_m - (double) _rDateTime.Minutes ) * 60.0); + } +} + +} + +// ------------------------------------------------------------------------- +void ODbaseTable::readHeader() +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbase", "Ocke.Janssen@sun.com", "ODbaseTable::readHeader" ); + OSL_ENSURE(m_pFileStream,"No Stream available!"); + if(!m_pFileStream) + return; + m_pFileStream->RefreshBuffer(); // sicherstellen, dass die Kopfinformationen tatsaechlich neu gelesen werden + m_pFileStream->Seek(STREAM_SEEK_TO_BEGIN); + + BYTE nType=0; + (*m_pFileStream) >> nType; + if(ERRCODE_NONE != m_pFileStream->GetErrorCode()) + throwInvalidDbaseFormat(); + + m_pFileStream->Read((char*)(&m_aHeader.db_aedat), 3*sizeof(BYTE)); + if(ERRCODE_NONE != m_pFileStream->GetErrorCode()) + throwInvalidDbaseFormat(); + (*m_pFileStream) >> m_aHeader.db_anz; + if(ERRCODE_NONE != m_pFileStream->GetErrorCode()) + throwInvalidDbaseFormat(); + (*m_pFileStream) >> m_aHeader.db_kopf; + if(ERRCODE_NONE != m_pFileStream->GetErrorCode()) + throwInvalidDbaseFormat(); + (*m_pFileStream) >> m_aHeader.db_slng; + if(ERRCODE_NONE != m_pFileStream->GetErrorCode()) + throwInvalidDbaseFormat(); + m_pFileStream->Read((char*)(&m_aHeader.db_frei), 20*sizeof(BYTE)); + if(ERRCODE_NONE != m_pFileStream->GetErrorCode()) + throwInvalidDbaseFormat(); + + if ( ( ( m_aHeader.db_kopf - 1 ) / 32 - 1 ) <= 0 ) // anzahl felder + { + // no dbase file + throwInvalidDbaseFormat(); + } + else + { + // Konsistenzpruefung des Header: + m_aHeader.db_typ = (DBFType)nType; + switch (m_aHeader.db_typ) + { + case dBaseIII: + case dBaseIV: + case dBaseV: + case VisualFoxPro: + case VisualFoxProAuto: + case dBaseFS: + case dBaseFSMemo: + case dBaseIVMemoSQL: + case dBaseIIIMemo: + case FoxProMemo: + m_pFileStream->SetNumberFormatInt(NUMBERFORMAT_INT_LITTLEENDIAN); + if ( m_aHeader.db_frei[17] != 0x00 + && !m_aHeader.db_frei[18] && !m_aHeader.db_frei[19] && getConnection()->isTextEncodingDefaulted() ) + { + switch(m_aHeader.db_frei[17]) + { + case 0x01: m_eEncoding = RTL_TEXTENCODING_IBM_437; break; // DOS USA code page 437 + case 0x02: m_eEncoding = RTL_TEXTENCODING_IBM_850; break; // DOS Multilingual code page 850 + case 0x03: m_eEncoding = RTL_TEXTENCODING_MS_1252; break; // Windows ANSI code page 1252 + case 0x04: m_eEncoding = RTL_TEXTENCODING_APPLE_ROMAN; break; // Standard Macintosh + case 0x64: m_eEncoding = RTL_TEXTENCODING_IBM_852; break; // EE MS-DOS code page 852 + case 0x65: m_eEncoding = RTL_TEXTENCODING_IBM_865; break; // Nordic MS-DOS code page 865 + case 0x66: m_eEncoding = RTL_TEXTENCODING_IBM_866; break; // Russian MS-DOS code page 866 + case 0x67: m_eEncoding = RTL_TEXTENCODING_IBM_861; break; // Icelandic MS-DOS + //case 0x68: m_eEncoding = ; break; // Kamenicky (Czech) MS-DOS + //case 0x69: m_eEncoding = ; break; // Mazovia (Polish) MS-DOS + case 0x6A: m_eEncoding = RTL_TEXTENCODING_IBM_737; break; // Greek MS-DOS (437G) + case 0x6B: m_eEncoding = RTL_TEXTENCODING_IBM_857; break; // Turkish MS-DOS + case 0x96: m_eEncoding = RTL_TEXTENCODING_APPLE_CYRILLIC; break; // Russian Macintosh + case 0x97: m_eEncoding = RTL_TEXTENCODING_APPLE_CENTEURO; break; // Eastern European Macintosh + case 0x98: m_eEncoding = RTL_TEXTENCODING_APPLE_GREEK; break; // Greek Macintosh + case 0xC8: m_eEncoding = RTL_TEXTENCODING_MS_1250; break; // Windows EE code page 1250 + case 0xC9: m_eEncoding = RTL_TEXTENCODING_MS_1251; break; // Russian Windows + case 0xCA: m_eEncoding = RTL_TEXTENCODING_MS_1254; break; // Turkish Windows + case 0xCB: m_eEncoding = RTL_TEXTENCODING_MS_1253; break; // Greek Windows + default: + break; + } + } + break; + case dBaseIVMemo: + m_pFileStream->SetNumberFormatInt(NUMBERFORMAT_INT_LITTLEENDIAN); + break; + default: + { + throwInvalidDbaseFormat(); + } + } + } +} +// ------------------------------------------------------------------------- +void ODbaseTable::fillColumns() +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbase", "Ocke.Janssen@sun.com", "ODbaseTable::fillColumns" ); + m_pFileStream->Seek(STREAM_SEEK_TO_BEGIN); + m_pFileStream->Seek(32L); + + if(!m_aColumns.isValid()) + m_aColumns = new OSQLColumns(); + else + m_aColumns->get().clear(); + + m_aTypes.clear(); + m_aPrecisions.clear(); + m_aScales.clear(); + + // Anzahl Felder: + const sal_Int32 nFieldCount = (m_aHeader.db_kopf - 1) / 32 - 1; + OSL_ENSURE(nFieldCount,"No columns in table!"); + + m_aColumns->get().reserve(nFieldCount); + m_aTypes.reserve(nFieldCount); + m_aPrecisions.reserve(nFieldCount); + m_aScales.reserve(nFieldCount); + + String aStrFieldName; + aStrFieldName.AssignAscii("Column"); + ::rtl::OUString aTypeName; + static const ::rtl::OUString sVARCHAR(RTL_CONSTASCII_USTRINGPARAM("VARCHAR")); + const sal_Bool bCase = getConnection()->getMetaData()->storesMixedCaseQuotedIdentifiers(); + const bool bFoxPro = m_aHeader.db_typ == VisualFoxPro || m_aHeader.db_typ == VisualFoxProAuto || m_aHeader.db_typ == FoxProMemo; + + sal_Int32 i = 0; + for (; i < nFieldCount; i++) + { + DBFColumn aDBFColumn; + m_pFileStream->Read((char*)&aDBFColumn, sizeof(aDBFColumn)); + if ( FIELD_DESCRIPTOR_TERMINATOR == aDBFColumn.db_fnm[0] ) // 0x0D stored as the Field Descriptor terminator. + break; + + sal_Bool bIsRowVersion = bFoxPro && ( aDBFColumn.db_frei2[0] & 0x01 ) == 0x01; + //if ( bFoxPro && ( aDBFColumn.db_frei2[0] & 0x01 ) == 0x01 ) // system column not visible to user + // continue; + const String aColumnName((const char *)aDBFColumn.db_fnm,m_eEncoding); + + m_aRealFieldLengths.push_back(aDBFColumn.db_flng); + sal_Int32 nPrecision = aDBFColumn.db_flng; + sal_Int32 eType; + sal_Bool bIsCurrency = sal_False; + + char cType[2]; + cType[0] = aDBFColumn.db_typ; + cType[1] = 0; + aTypeName = ::rtl::OUString::createFromAscii(cType); +OSL_TRACE("column type: %c",aDBFColumn.db_typ); + + switch (aDBFColumn.db_typ) + { + case 'C': + eType = DataType::VARCHAR; + aTypeName = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("VARCHAR")); + break; + case 'F': + aTypeName = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("DECIMAL")); + case 'N': + if ( aDBFColumn.db_typ == 'N' ) + aTypeName = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("NUMERIC")); + eType = DataType::DECIMAL; + + // Bei numerischen Feldern werden zwei Zeichen mehr geschrieben, als die Precision der Spaltenbeschreibung eigentlich + // angibt, um Platz fuer das eventuelle Vorzeichen und das Komma zu haben. Das muss ich jetzt aber wieder rausrechnen. + nPrecision = SvDbaseConverter::ConvertPrecisionToOdbc(nPrecision,aDBFColumn.db_dez); + // leider gilt das eben Gesagte nicht fuer aeltere Versionen .... + break; + case 'L': + eType = DataType::BIT; + aTypeName = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("BOOLEAN")); + break; + case 'Y': + bIsCurrency = sal_True; + eType = DataType::DOUBLE; + aTypeName = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("DOUBLE")); + break; + case 'D': + eType = DataType::DATE; + aTypeName = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("DATE")); + break; + case 'T': + eType = DataType::TIMESTAMP; + aTypeName = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("TIMESTAMP")); + break; + case 'I': + eType = DataType::INTEGER; + aTypeName = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("INTEGER")); + break; + case 'M': + if ( bFoxPro && ( aDBFColumn.db_frei2[0] & 0x04 ) == 0x04 ) + { + eType = DataType::LONGVARBINARY; + aTypeName = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("LONGVARBINARY")); + } + else + { + aTypeName = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("LONGVARCHAR")); + eType = DataType::LONGVARCHAR; + } + nPrecision = 2147483647; + break; + case 'P': + aTypeName = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("LONGVARBINARY")); + eType = DataType::LONGVARBINARY; + nPrecision = 2147483647; + break; + case '0': + case 'B': + if ( m_aHeader.db_typ == VisualFoxPro || m_aHeader.db_typ == VisualFoxProAuto ) + { + aTypeName = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("DOUBLE")); + eType = DataType::DOUBLE; + } + else + { + aTypeName = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("LONGVARBINARY")); + eType = DataType::LONGVARBINARY; + nPrecision = 2147483647; + } + break; + default: + eType = DataType::OTHER; + } + + m_aTypes.push_back(eType); + m_aPrecisions.push_back(nPrecision); + m_aScales.push_back(aDBFColumn.db_dez); + + Reference< XPropertySet> xCol = new sdbcx::OColumn(aColumnName, + aTypeName, + ::rtl::OUString(), + ::rtl::OUString(), + ColumnValue::NULLABLE, + nPrecision, + aDBFColumn.db_dez, + eType, + sal_False, + bIsRowVersion, + bIsCurrency, + bCase); + m_aColumns->get().push_back(xCol); + } // for (; i < nFieldCount; i++) + OSL_ENSURE(i,"No columns in table!"); +} +// ------------------------------------------------------------------------- +ODbaseTable::ODbaseTable(sdbcx::OCollection* _pTables,ODbaseConnection* _pConnection) + :ODbaseTable_BASE(_pTables,_pConnection) + ,m_pMemoStream(NULL) + ,m_bWriteableMemo(sal_False) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbase", "Ocke.Janssen@sun.com", "ODbaseTable::ODbaseTable" ); + // initialize the header + m_aHeader.db_typ = dBaseIII; + m_aHeader.db_anz = 0; + m_aHeader.db_kopf = 0; + m_aHeader.db_slng = 0; + m_eEncoding = getConnection()->getTextEncoding(); +} +// ------------------------------------------------------------------------- +ODbaseTable::ODbaseTable(sdbcx::OCollection* _pTables,ODbaseConnection* _pConnection, + const ::rtl::OUString& _Name, + const ::rtl::OUString& _Type, + const ::rtl::OUString& _Description , + const ::rtl::OUString& _SchemaName, + const ::rtl::OUString& _CatalogName + ) : ODbaseTable_BASE(_pTables,_pConnection,_Name, + _Type, + _Description, + _SchemaName, + _CatalogName) + ,m_pMemoStream(NULL) + ,m_bWriteableMemo(sal_False) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbase", "Ocke.Janssen@sun.com", "ODbaseTable::ODbaseTable" ); + m_eEncoding = getConnection()->getTextEncoding(); +} + +// ----------------------------------------------------------------------------- +void ODbaseTable::construct() +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbase", "Ocke.Janssen@sun.com", "ODbaseTable::construct" ); + // initialize the header + m_aHeader.db_typ = dBaseIII; + m_aHeader.db_anz = 0; + m_aHeader.db_kopf = 0; + m_aHeader.db_slng = 0; + m_aMemoHeader.db_size = 0; + + String sFileName(getEntry(m_pConnection,m_Name)); + + INetURLObject aURL; + aURL.SetURL(sFileName); + + OSL_ENSURE( m_pConnection->matchesExtension( aURL.getExtension() ), + "ODbaseTable::ODbaseTable: invalid extension!"); + // getEntry is expected to ensure the corect file name + + m_pFileStream = createStream_simpleError( sFileName, STREAM_READWRITE | STREAM_NOCREATE | STREAM_SHARE_DENYWRITE); + m_bWriteable = ( m_pFileStream != NULL ); + + if ( !m_pFileStream ) + { + m_bWriteable = sal_False; + m_pFileStream = createStream_simpleError( sFileName, STREAM_READ | STREAM_NOCREATE | STREAM_SHARE_DENYNONE); + } + + if(m_pFileStream) + { + readHeader(); + if (HasMemoFields()) + { + // Memo-Dateinamen bilden (.DBT): + // nyi: Unschoen fuer Unix und Mac! + + if ( m_aHeader.db_typ == FoxProMemo || VisualFoxPro == m_aHeader.db_typ || VisualFoxProAuto == m_aHeader.db_typ ) // foxpro uses another extension + aURL.SetExtension(String::CreateFromAscii("fpt")); + else + aURL.SetExtension(String::CreateFromAscii("dbt")); + + // Wenn die Memodatei nicht gefunden wird, werden die Daten trotzdem angezeigt + // allerdings koennen keine Updates durchgefuehrt werden + // jedoch die Operation wird ausgefuehrt + m_pMemoStream = createStream_simpleError( aURL.GetMainURL(INetURLObject::NO_DECODE), STREAM_READWRITE | STREAM_NOCREATE | STREAM_SHARE_DENYWRITE); + if ( !m_pMemoStream ) + { + m_bWriteableMemo = sal_False; + m_pMemoStream = createStream_simpleError( aURL.GetMainURL(INetURLObject::NO_DECODE), STREAM_READ | STREAM_NOCREATE | STREAM_SHARE_DENYNONE); + } + if (m_pMemoStream) + ReadMemoHeader(); + } + // if(!m_pColumns && (!m_aColumns.isValid() || !m_aColumns->size())) + fillColumns(); + + UINT32 nFileSize = lcl_getFileSize(*m_pFileStream); + m_pFileStream->Seek(STREAM_SEEK_TO_BEGIN); + if ( m_aHeader.db_anz == 0 && ((nFileSize-m_aHeader.db_kopf)/m_aHeader.db_slng) > 0) // seems to be empty or someone wrote bullshit into the dbase file + m_aHeader.db_anz = ((nFileSize-m_aHeader.db_kopf)/m_aHeader.db_slng); + + // Buffersize abhaengig von der Filegroesse + m_pFileStream->SetBufferSize(nFileSize > 1000000 ? 32768 : + nFileSize > 100000 ? 16384 : + nFileSize > 10000 ? 4096 : 1024); + + if (m_pMemoStream) + { + // Puffer genau auf Laenge eines Satzes stellen + m_pMemoStream->Seek(STREAM_SEEK_TO_END); + nFileSize = m_pMemoStream->Tell(); + m_pMemoStream->Seek(STREAM_SEEK_TO_BEGIN); + + // Buffersize abhaengig von der Filegroesse + m_pMemoStream->SetBufferSize(nFileSize > 1000000 ? 32768 : + nFileSize > 100000 ? 16384 : + nFileSize > 10000 ? 4096 : + m_aMemoHeader.db_size); + } + + AllocBuffer(); + } +} +//------------------------------------------------------------------ +BOOL ODbaseTable::ReadMemoHeader() +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbase", "Ocke.Janssen@sun.com", "ODbaseTable::ReadMemoHeader" ); + m_pMemoStream->SetNumberFormatInt(NUMBERFORMAT_INT_LITTLEENDIAN); + m_pMemoStream->RefreshBuffer(); // sicherstellen das die Kopfinformationen tatsaechlich neu gelesen werden + m_pMemoStream->Seek(0L); + + (*m_pMemoStream) >> m_aMemoHeader.db_next; + switch (m_aHeader.db_typ) + { + case dBaseIIIMemo: // dBase III: feste Blockgroesse + case dBaseIVMemo: + // manchmal wird aber auch dBase3 dBase4 Memo zugeordnet + m_pMemoStream->Seek(20L); + (*m_pMemoStream) >> m_aMemoHeader.db_size; + if (m_aMemoHeader.db_size > 1 && m_aMemoHeader.db_size != 512) // 1 steht auch fuer dBase 3 + m_aMemoHeader.db_typ = MemodBaseIV; + else if (m_aMemoHeader.db_size > 1 && m_aMemoHeader.db_size == 512) + { + // nun gibt es noch manche Dateien, die verwenden eine Groessenangabe, + // sind aber dennoch dBase Dateien + char sHeader[4]; + m_pMemoStream->Seek(m_aMemoHeader.db_size); + m_pMemoStream->Read(sHeader,4); + + if ((m_pMemoStream->GetErrorCode() != ERRCODE_NONE) || ((BYTE)sHeader[0]) != 0xFF || ((BYTE)sHeader[1]) != 0xFF || ((BYTE)sHeader[2]) != 0x08) + m_aMemoHeader.db_typ = MemodBaseIII; + else + m_aMemoHeader.db_typ = MemodBaseIV; + } + else + { + m_aMemoHeader.db_typ = MemodBaseIII; + m_aMemoHeader.db_size = 512; + } + break; + case VisualFoxPro: + case VisualFoxProAuto: + case FoxProMemo: + m_aMemoHeader.db_typ = MemoFoxPro; + m_pMemoStream->Seek(6L); + m_pMemoStream->SetNumberFormatInt(NUMBERFORMAT_INT_BIGENDIAN); + (*m_pMemoStream) >> m_aMemoHeader.db_size; + break; + default: + OSL_ENSURE( false, "ODbaseTable::ReadMemoHeader: unsupported memo type!" ); + break; + } + return TRUE; +} +// ------------------------------------------------------------------------- +String ODbaseTable::getEntry(OConnection* _pConnection,const ::rtl::OUString& _sName ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbase", "Ocke.Janssen@sun.com", "ODbaseTable::getEntry" ); + ::rtl::OUString sURL; + try + { + Reference< XResultSet > xDir = _pConnection->getDir()->getStaticResultSet(); + Reference< XRow> xRow(xDir,UNO_QUERY); + ::rtl::OUString sName; + ::rtl::OUString sExt; + INetURLObject aURL; + static const ::rtl::OUString s_sSeparator(RTL_CONSTASCII_USTRINGPARAM("/")); + xDir->beforeFirst(); + while(xDir->next()) + { + sName = xRow->getString(1); + aURL.SetSmartProtocol(INET_PROT_FILE); + String sUrl = _pConnection->getURL() + s_sSeparator + sName; + aURL.SetSmartURL( sUrl ); + + // cut the extension + sExt = aURL.getExtension(); + + // name and extension have to coincide + if ( _pConnection->matchesExtension( sExt ) ) + { + sName = sName.replaceAt(sName.getLength()-(sExt.getLength()+1),sExt.getLength()+1,::rtl::OUString()); + if ( sName == _sName ) + { + Reference< XContentAccess > xContentAccess( xDir, UNO_QUERY ); + sURL = xContentAccess->queryContentIdentifierString(); + break; + } + } + } + xDir->beforeFirst(); // move back to before first record + } + catch(Exception&) + { + OSL_ASSERT(0); + } + return sURL; +} +// ------------------------------------------------------------------------- +void ODbaseTable::refreshColumns() +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbase", "Ocke.Janssen@sun.com", "ODbaseTable::refreshColumns" ); + ::osl::MutexGuard aGuard( m_aMutex ); + + TStringVector aVector; + aVector.reserve(m_aColumns->get().size()); + + for(OSQLColumns::Vector::const_iterator aIter = m_aColumns->get().begin();aIter != m_aColumns->get().end();++aIter) + aVector.push_back(Reference< XNamed>(*aIter,UNO_QUERY)->getName()); + + if(m_pColumns) + m_pColumns->reFill(aVector); + else + m_pColumns = new ODbaseColumns(this,m_aMutex,aVector); +} +// ------------------------------------------------------------------------- +void ODbaseTable::refreshIndexes() +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbase", "Ocke.Janssen@sun.com", "ODbaseTable::refreshIndexes" ); + TStringVector aVector; + if(m_pFileStream && (!m_pIndexes || m_pIndexes->getCount() == 0)) + { + INetURLObject aURL; + aURL.SetURL(getEntry(m_pConnection,m_Name)); + + aURL.setExtension(String::CreateFromAscii("inf")); + Config aInfFile(aURL.getFSysPath(INetURLObject::FSYS_DETECT)); + aInfFile.SetGroup(dBASE_III_GROUP); + USHORT nKeyCnt = aInfFile.GetKeyCount(); + ByteString aKeyName; + ByteString aIndexName; + + for (USHORT nKey = 0; nKey < nKeyCnt; nKey++) + { + // Verweist der Key auf ein Indexfile?... + aKeyName = aInfFile.GetKeyName( nKey ); + //...wenn ja, Indexliste der Tabelle hinzufuegen + if (aKeyName.Copy(0,3) == ByteString("NDX") ) + { + aIndexName = aInfFile.ReadKey(aKeyName); + aURL.setName(String(aIndexName,m_eEncoding)); + try + { + Content aCnt(aURL.GetMainURL(INetURLObject::NO_DECODE),Reference<XCommandEnvironment>()); + if (aCnt.isDocument()) + { + aVector.push_back(aURL.getBase()); + } + } + catch(Exception&) // a execption is thrown when no file exists + { + } + } + } + } + if(m_pIndexes) + m_pIndexes->reFill(aVector); + else + m_pIndexes = new ODbaseIndexes(this,m_aMutex,aVector); +} + +// ------------------------------------------------------------------------- +void SAL_CALL ODbaseTable::disposing(void) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbase", "Ocke.Janssen@sun.com", "ODbaseTable::disposing" ); + OFileTable::disposing(); + ::osl::MutexGuard aGuard(m_aMutex); + m_aColumns = NULL; +} +// ------------------------------------------------------------------------- +Sequence< Type > SAL_CALL ODbaseTable::getTypes( ) throw(RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbase", "Ocke.Janssen@sun.com", "ODbaseTable::getTypes" ); + Sequence< Type > aTypes = OTable_TYPEDEF::getTypes(); + ::std::vector<Type> aOwnTypes; + aOwnTypes.reserve(aTypes.getLength()); + + const Type* pBegin = aTypes.getConstArray(); + const Type* pEnd = pBegin + aTypes.getLength(); + for(;pBegin != pEnd;++pBegin) + { + if(!(*pBegin == ::getCppuType((const Reference<XKeysSupplier>*)0) || + // *pBegin == ::getCppuType((const Reference<XAlterTable>*)0) || + *pBegin == ::getCppuType((const Reference<XDataDescriptorFactory>*)0))) + { + aOwnTypes.push_back(*pBegin); + } + } + aOwnTypes.push_back(::getCppuType( (const Reference< ::com::sun::star::lang::XUnoTunnel > *)0 )); + Type *pTypes = aOwnTypes.empty() ? 0 : &aOwnTypes[0]; + return Sequence< Type >(pTypes, aOwnTypes.size()); +} + +// ------------------------------------------------------------------------- +Any SAL_CALL ODbaseTable::queryInterface( const Type & rType ) throw(RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbase", "Ocke.Janssen@sun.com", "ODbaseTable::queryInterface" ); + if( rType == ::getCppuType((const Reference<XKeysSupplier>*)0) || + rType == ::getCppuType((const Reference<XDataDescriptorFactory>*)0)) + return Any(); + + Any aRet = OTable_TYPEDEF::queryInterface(rType); + return aRet.hasValue() ? aRet : ::cppu::queryInterface(rType,static_cast< ::com::sun::star::lang::XUnoTunnel*> (this)); +} + +//-------------------------------------------------------------------------- +Sequence< sal_Int8 > ODbaseTable::getUnoTunnelImplementationId() +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbase", "Ocke.Janssen@sun.com", "ODbaseTable::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::lang::XUnoTunnel +//------------------------------------------------------------------ +sal_Int64 ODbaseTable::getSomething( const Sequence< sal_Int8 > & rId ) throw (RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbase", "Ocke.Janssen@sun.com", "ODbaseTable::getSomething" ); + return (rId.getLength() == 16 && 0 == rtl_compareMemory(getUnoTunnelImplementationId().getConstArray(), rId.getConstArray(), 16 ) ) + ? reinterpret_cast< sal_Int64 >( this ) + : ODbaseTable_BASE::getSomething(rId); +} +//------------------------------------------------------------------ +sal_Bool ODbaseTable::fetchRow(OValueRefRow& _rRow,const OSQLColumns & _rCols, sal_Bool _bUseTableDefs,sal_Bool bRetrieveData) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbase", "Ocke.Janssen@sun.com", "ODbaseTable::fetchRow" ); + // Einlesen der Daten + BOOL bIsCurRecordDeleted = ((char)m_pBuffer[0] == '*') ? TRUE : sal_False; + + // only read the bookmark + + // Satz als geloescht markieren + // rRow.setState(bIsCurRecordDeleted ? ROW_DELETED : ROW_CLEAN ); + _rRow->setDeleted(bIsCurRecordDeleted); + *(_rRow->get())[0] = m_nFilePos; + + if (!bRetrieveData) + return TRUE; + + sal_Size nByteOffset = 1; + // Felder: + OSQLColumns::Vector::const_iterator aIter = _rCols.get().begin(); + OSQLColumns::Vector::const_iterator aEnd = _rCols.get().end(); + const sal_Size nCount = _rRow->get().size(); + for (sal_Size i = 1; aIter != aEnd && nByteOffset <= m_nBufferSize && i < nCount;++aIter, i++) + { + // Laengen je nach Datentyp: + sal_Int32 nLen = 0; + sal_Int32 nType = 0; + if(_bUseTableDefs) + { + nLen = m_aPrecisions[i-1]; + nType = m_aTypes[i-1]; + } + else + { + (*aIter)->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_PRECISION)) >>= nLen; + (*aIter)->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_TYPE)) >>= nType; + } + switch(nType) + { + case DataType::INTEGER: + case DataType::DOUBLE: + case DataType::TIMESTAMP: + case DataType::DATE: + case DataType::BIT: + case DataType::LONGVARCHAR: + case DataType::LONGVARBINARY: + nLen = m_aRealFieldLengths[i-1]; + break; + case DataType::DECIMAL: + if(_bUseTableDefs) + nLen = SvDbaseConverter::ConvertPrecisionToDbase(nLen,m_aScales[i-1]); + else + nLen = SvDbaseConverter::ConvertPrecisionToDbase(nLen,getINT32((*aIter)->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_SCALE)))); + break; // das Vorzeichen und das Komma + + case DataType::BINARY: + case DataType::OTHER: + nByteOffset += nLen; + continue; + } + + // Ist die Variable ueberhaupt gebunden? + if ( !(_rRow->get())[i]->isBound() ) + { + // Nein - naechstes Feld. + nByteOffset += nLen; + OSL_ENSURE( nByteOffset <= m_nBufferSize ,"ByteOffset > m_nBufferSize!"); + continue; + } // if ( !(_rRow->get())[i]->isBound() ) + if ( ( nByteOffset + nLen) > m_nBufferSize ) + break; // length doesn't match buffer size. + + char *pData = (char *) (m_pBuffer + nByteOffset); + + // (*_rRow)[i].setType(nType); + + if (nType == DataType::CHAR || nType == DataType::VARCHAR) + { + char cLast = pData[nLen]; + pData[nLen] = 0; + String aStr(pData,(xub_StrLen)nLen,m_eEncoding); + aStr.EraseTrailingChars(); + + if ( aStr.Len() ) + *(_rRow->get())[i] = ::rtl::OUString(aStr); + else// keine StringLaenge, dann NULL + (_rRow->get())[i]->setNull(); + + pData[nLen] = cLast; + } // if (nType == DataType::CHAR || nType == DataType::VARCHAR) + else if ( DataType::TIMESTAMP == nType ) + { + sal_Int32 nDate = 0,nTime = 0; + memcpy(&nDate, pData, 4); + memcpy(&nTime, pData+ 4, 4); + if ( !nDate && !nTime ) + { + (_rRow->get())[i]->setNull(); + } + else + { + ::com::sun::star::util::DateTime aDateTime; + lcl_CalDate(nDate,nTime,aDateTime); + *(_rRow->get())[i] = aDateTime; + } + } + else if ( DataType::INTEGER == nType ) + { + sal_Int32 nValue = 0; + memcpy(&nValue, pData, nLen); + *(_rRow->get())[i] = nValue; + } + else if ( DataType::DOUBLE == nType ) + { + double d = 0.0; + if (getBOOL((*aIter)->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_ISCURRENCY)))) // Currency wird gesondert behandelt + { + sal_Int64 nValue = 0; + memcpy(&nValue, pData, nLen); + + if ( m_aScales[i-1] ) + d = (double)(nValue / pow(10.0,(int)m_aScales[i-1])); + else + d = (double)(nValue); + } + else + { + memcpy(&d, pData, nLen); + } + + *(_rRow->get())[i] = d; + } + else + { + // Falls Nul-Zeichen im String enthalten sind, in Blanks umwandeln! + for (sal_Int32 k = 0; k < nLen; k++) + { + if (pData[k] == '\0') + pData[k] = ' '; + } + + String aStr(pData, (xub_StrLen)nLen,m_eEncoding); // Spaces am Anfang und am Ende entfernen: + aStr.EraseLeadingChars(); + aStr.EraseTrailingChars(); + + if (!aStr.Len()) + { + nByteOffset += nLen; + (_rRow->get())[i]->setNull(); // keine Werte -> fertig + continue; + } + + switch (nType) + { + case DataType::DATE: + { + if (aStr.Len() != nLen) + { + (_rRow->get())[i]->setNull(); + break; + } + const sal_uInt16 nYear = (sal_uInt16)aStr.Copy( 0, 4 ).ToInt32(); + const sal_uInt16 nMonth = (sal_uInt16)aStr.Copy( 4, 2 ).ToInt32(); + const sal_uInt16 nDay = (sal_uInt16)aStr.Copy( 6, 2 ).ToInt32(); + + const ::com::sun::star::util::Date aDate(nDay,nMonth,nYear); + *(_rRow->get())[i] = aDate; + } + break; + case DataType::DECIMAL: + *(_rRow->get())[i] = ORowSetValue(aStr); + // pVal->setDouble(SdbTools::ToDouble(aStr)); + break; + case DataType::BIT: + { + BOOL b; + switch (* ((const char *)pData)) + { + case 'T': + case 'Y': + case 'J': b = TRUE; break; + default: b = FALSE; break; + } + *(_rRow->get())[i] = b; + // pVal->setDouble(b); + } + break; + case DataType::LONGVARBINARY: + case DataType::BINARY: + case DataType::LONGVARCHAR: + { + const long nBlockNo = aStr.ToInt32(); // Blocknummer lesen + if (nBlockNo > 0 && m_pMemoStream) // Daten aus Memo-Datei lesen, nur wenn + { + if ( !ReadMemo(nBlockNo, (_rRow->get())[i]->get()) ) + break; + } + else + (_rRow->get())[i]->setNull(); + } break; + default: + OSL_ASSERT("Falscher Type"); + } + (_rRow->get())[i]->setTypeKind(nType); + } + + nByteOffset += nLen; + OSL_ENSURE( nByteOffset <= m_nBufferSize ,"ByteOffset > m_nBufferSize!"); + } + return sal_True; +} +//------------------------------------------------------------------ +// ------------------------------------------------------------------------- +void ODbaseTable::FileClose() +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbase", "Ocke.Janssen@sun.com", "ODbaseTable::FileClose" ); + ::osl::MutexGuard aGuard(m_aMutex); + // falls noch nicht alles geschrieben wurde + if (m_pMemoStream && m_pMemoStream->IsWritable()) + m_pMemoStream->Flush(); + + delete m_pMemoStream; + m_pMemoStream = NULL; + + ODbaseTable_BASE::FileClose(); +} +// ------------------------------------------------------------------------- +BOOL ODbaseTable::CreateImpl() +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbase", "Ocke.Janssen@sun.com", "ODbaseTable::CreateImpl" ); + OSL_ENSURE(!m_pFileStream, "SequenceError"); + + if ( m_pConnection->isCheckEnabled() && ::dbtools::convertName2SQLName(m_Name,::rtl::OUString()) != m_Name ) + { + const ::rtl::OUString sError( getConnection()->getResources().getResourceStringWithSubstitution( + STR_SQL_NAME_ERROR, + "$name$", m_Name + ) ); + ::dbtools::throwGenericSQLException( sError, *this ); + } + + INetURLObject aURL; + aURL.SetSmartProtocol(INET_PROT_FILE); + String aName = getEntry(m_pConnection,m_Name); + if(!aName.Len()) + { + ::rtl::OUString aIdent = m_pConnection->getContent()->getIdentifier()->getContentIdentifier(); + if ( aIdent.lastIndexOf('/') != (aIdent.getLength()-1) ) + aIdent += ::rtl::OUString::createFromAscii("/"); + aIdent += m_Name; + aName = aIdent.getStr(); + } + aURL.SetURL(aName); + + if ( !m_pConnection->matchesExtension( aURL.getExtension() ) ) + aURL.setExtension(m_pConnection->getExtension()); + + try + { + Content aContent(aURL.GetMainURL(INetURLObject::NO_DECODE),Reference<XCommandEnvironment>()); + if (aContent.isDocument()) + { + // Hack fuer Bug #30609 , nur wenn das File existiert und die Laenge > 0 gibt es einen Fehler + SvStream* pFileStream = createStream_simpleError( aURL.GetMainURL(INetURLObject::NO_DECODE),STREAM_READ); + + if (pFileStream && pFileStream->Seek(STREAM_SEEK_TO_END)) + { + // aStatus.SetError(ERRCODE_IO_ALREADYEXISTS,TABLE,aFile.GetFull()); + return sal_False; + } + delete pFileStream; + } + } + catch(Exception&) // a execption is thrown when no file exists + { + } + + BOOL bMemoFile = sal_False; + + sal_Bool bOk = CreateFile(aURL, bMemoFile); + + FileClose(); + + if (!bOk) + { + try + { + Content aContent(aURL.GetMainURL(INetURLObject::NO_DECODE),Reference<XCommandEnvironment>()); + aContent.executeCommand( rtl::OUString::createFromAscii( "delete" ),bool2any( sal_True ) ); + } + catch(Exception&) // a execption is thrown when no file exists + { + } + return sal_False; + } + + if (bMemoFile) + { + String aExt = aURL.getExtension(); + aURL.setExtension(String::CreateFromAscii("dbt")); // extension for memo file + Content aMemo1Content(aURL.GetMainURL(INetURLObject::NO_DECODE),Reference<XCommandEnvironment>()); + + sal_Bool bMemoAlreadyExists = sal_False; + try + { + bMemoAlreadyExists = aMemo1Content.isDocument(); + } + catch(Exception&) // a execption is thrown when no file exists + { + } + if (bMemoAlreadyExists) + { + // aStatus.SetError(ERRCODE_IO_ALREADYEXISTS,MEMO,aFile.GetFull()); + aURL.setExtension(aExt); // kill dbf file + try + { + Content aMemoContent(aURL.GetMainURL(INetURLObject::NO_DECODE),Reference<XCommandEnvironment>()); + aMemoContent.executeCommand( rtl::OUString::createFromAscii( "delete" ),bool2any( sal_True ) ); + } + catch(const Exception&) + { + + const ::rtl::OUString sError( getConnection()->getResources().getResourceStringWithSubstitution( + STR_COULD_NOT_DELETE_FILE, + "$name$", aName + ) ); + ::dbtools::throwGenericSQLException( sError, *this ); + } + } + if (!CreateMemoFile(aURL)) + { + aURL.setExtension(aExt); // kill dbf file + Content aMemoContent(aURL.GetMainURL(INetURLObject::NO_DECODE),Reference<XCommandEnvironment>()); + aMemoContent.executeCommand( rtl::OUString::createFromAscii( "delete" ),bool2any( sal_True ) ); + return sal_False; + } + m_aHeader.db_typ = dBaseIIIMemo; + } + else + m_aHeader.db_typ = dBaseIII; + + return TRUE; +} +// ----------------------------------------------------------------------------- +void ODbaseTable::throwInvalidColumnType(const sal_uInt16 _nErrorId,const ::rtl::OUString& _sColumnName) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbase", "Ocke.Janssen@sun.com", "ODbaseTable::throwInvalidColumnType" ); + try + { + // we have to drop the file because it is corrupted now + DropImpl(); + } + catch(const Exception&) + { + } + + const ::rtl::OUString sError( getConnection()->getResources().getResourceStringWithSubstitution( + _nErrorId, + "$columnname$", _sColumnName + ) ); + ::dbtools::throwGenericSQLException( sError, *this ); +} +//------------------------------------------------------------------ +// erzeugt grundsaetzlich dBase IV Datei Format +BOOL ODbaseTable::CreateFile(const INetURLObject& aFile, BOOL& bCreateMemo) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbase", "Ocke.Janssen@sun.com", "ODbaseTable::CreateFile" ); + bCreateMemo = sal_False; + Date aDate; // aktuelles Datum + + m_pFileStream = createStream_simpleError( aFile.GetMainURL(INetURLObject::NO_DECODE),STREAM_READWRITE | STREAM_SHARE_DENYWRITE | STREAM_TRUNC ); + + if (!m_pFileStream) + return sal_False; + + BYTE nDbaseType = dBaseIII; + Reference<XIndexAccess> xColumns(getColumns(),UNO_QUERY); + Reference<XPropertySet> xCol; + const ::rtl::OUString sPropType = OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_TYPE); + + try + { + const sal_Int32 nCount = xColumns->getCount(); + for(sal_Int32 i=0;i<nCount;++i) + { + xColumns->getByIndex(i) >>= xCol; + OSL_ENSURE(xCol.is(),"This should be a column!"); + + switch (getINT32(xCol->getPropertyValue(sPropType))) + { + case DataType::DOUBLE: + case DataType::INTEGER: + case DataType::TIMESTAMP: + case DataType::LONGVARBINARY: + nDbaseType = VisualFoxPro; + i = nCount; // no more columns need to be checked + break; + } // switch (getINT32(xCol->getPropertyValue(sPropType))) + } + } + catch ( const Exception& e ) + { + (void)e; + + try + { + // we have to drop the file because it is corrupted now + DropImpl(); + } + catch(const Exception&) { } + throw; + } + + char aBuffer[21]; // write buffer + memset(aBuffer,0,sizeof(aBuffer)); + + m_pFileStream->Seek(0L); + (*m_pFileStream) << (BYTE) nDbaseType; // dBase format + (*m_pFileStream) << (BYTE) (aDate.GetYear() % 100); // aktuelles Datum + + + (*m_pFileStream) << (BYTE) aDate.GetMonth(); + (*m_pFileStream) << (BYTE) aDate.GetDay(); + (*m_pFileStream) << 0L; // Anzahl der Datensaetze + (*m_pFileStream) << (USHORT)((m_pColumns->getCount()+1) * 32 + 1); // Kopfinformationen, + // pColumns erhaelt immer eine Spalte mehr + (*m_pFileStream) << (USHORT) 0; // Satzlaenge wird spaeter bestimmt + m_pFileStream->Write(aBuffer, 20); + + USHORT nRecLength = 1; // Laenge 1 fuer deleted flag + sal_Int32 nMaxFieldLength = m_pConnection->getMetaData()->getMaxColumnNameLength(); + ::rtl::OUString aName; + const ::rtl::OUString sPropName = OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_NAME); + const ::rtl::OUString sPropPrec = OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_PRECISION); + const ::rtl::OUString sPropScale = OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_SCALE); + + try + { + const sal_Int32 nCount = xColumns->getCount(); + for(sal_Int32 i=0;i<nCount;++i) + { + xColumns->getByIndex(i) >>= xCol; + OSL_ENSURE(xCol.is(),"This should be a column!"); + + char cTyp( 'C' ); + + xCol->getPropertyValue(sPropName) >>= aName; + + ::rtl::OString aCol; + if ( DBTypeConversion::convertUnicodeString( aName, aCol, m_eEncoding ) > nMaxFieldLength) + { + throwInvalidColumnType( STR_INVALID_COLUMN_NAME_LENGTH, aName ); + } + + (*m_pFileStream) << aCol.getStr(); + m_pFileStream->Write(aBuffer, 11 - aCol.getLength()); + + sal_Int32 nPrecision = 0; + xCol->getPropertyValue(sPropPrec) >>= nPrecision; + sal_Int32 nScale = 0; + xCol->getPropertyValue(sPropScale) >>= nScale; + + bool bBinary = false; + + switch (getINT32(xCol->getPropertyValue(sPropType))) + { + case DataType::CHAR: + case DataType::VARCHAR: + cTyp = 'C'; + break; + case DataType::DOUBLE: + if (getBOOL(xCol->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_ISCURRENCY)))) // Currency wird gesondert behandelt + cTyp = 'Y'; + else + cTyp = 'B'; + break; + case DataType::INTEGER: + cTyp = 'I'; + break; + case DataType::TINYINT: + case DataType::SMALLINT: + case DataType::BIGINT: + case DataType::DECIMAL: + case DataType::NUMERIC: + case DataType::REAL: + cTyp = 'N'; // nur dBase 3 format + break; + case DataType::TIMESTAMP: + cTyp = 'T'; + break; + case DataType::DATE: + cTyp = 'D'; + break; + case DataType::BIT: + cTyp = 'L'; + break; + case DataType::LONGVARBINARY: + bBinary = true; + // run through + case DataType::LONGVARCHAR: + cTyp = 'M'; + break; + default: + { + throwInvalidColumnType(STR_INVALID_COLUMN_TYPE, aName); + } + } + + (*m_pFileStream) << cTyp; + if ( nDbaseType == VisualFoxPro ) + (*m_pFileStream) << (nRecLength-1); + else + m_pFileStream->Write(aBuffer, 4); + + switch(cTyp) + { + case 'C': + OSL_ENSURE(nPrecision < 255, "ODbaseTable::Create: Column zu lang!"); + if (nPrecision > 254) + { + throwInvalidColumnType(STR_INVALID_COLUMN_PRECISION, aName); + } + (*m_pFileStream) << (BYTE) Min((ULONG)nPrecision, 255UL); //Feldlaenge + nRecLength = nRecLength + (USHORT)::std::min((USHORT)nPrecision, (USHORT)255UL); + (*m_pFileStream) << (BYTE)0; //Nachkommastellen + break; + case 'F': + case 'N': + OSL_ENSURE(nPrecision >= nScale, + "ODbaseTable::Create: Feldlaenge muss groesser Nachkommastellen sein!"); + if (nPrecision < nScale) + { + throwInvalidColumnType(STR_INVALID_PRECISION_SCALE, aName); + } + if (getBOOL(xCol->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_ISCURRENCY)))) // Currency wird gesondert behandelt + { + (*m_pFileStream) << (BYTE)10; // Standard Laenge + (*m_pFileStream) << (BYTE)4; + nRecLength += 10; + } + else + { + sal_Int32 nPrec = SvDbaseConverter::ConvertPrecisionToDbase(nPrecision,nScale); + + (*m_pFileStream) << (BYTE)( nPrec); + (*m_pFileStream) << (BYTE)nScale; + nRecLength += (USHORT)nPrec; + } + break; + case 'L': + (*m_pFileStream) << (BYTE)1; + (*m_pFileStream) << (BYTE)0; + ++nRecLength; + break; + case 'I': + (*m_pFileStream) << (BYTE)4; + (*m_pFileStream) << (BYTE)0; + nRecLength += 4; + break; + case 'Y': + case 'B': + case 'T': + case 'D': + (*m_pFileStream) << (BYTE)8; + (*m_pFileStream) << (BYTE)0; + nRecLength += 8; + break; + case 'M': + bCreateMemo = TRUE; + (*m_pFileStream) << (BYTE)10; + (*m_pFileStream) << (BYTE)0; + nRecLength += 10; + if ( bBinary ) + aBuffer[0] = 0x06; + break; + default: + throwInvalidColumnType(STR_INVALID_COLUMN_TYPE, aName); + } + m_pFileStream->Write(aBuffer, 14); + aBuffer[0] = 0x00; + } + + (*m_pFileStream) << (BYTE)FIELD_DESCRIPTOR_TERMINATOR; // kopf ende + (*m_pFileStream) << (char)DBF_EOL; + m_pFileStream->Seek(10L); + (*m_pFileStream) << nRecLength; // Satzlaenge nachtraeglich eintragen + + if (bCreateMemo) + { + m_pFileStream->Seek(0L); + if (nDbaseType == VisualFoxPro) + (*m_pFileStream) << (BYTE) FoxProMemo; + else + (*m_pFileStream) << (BYTE) dBaseIIIMemo; + } // if (bCreateMemo) + } + catch ( const Exception& e ) + { + (void)e; + + try + { + // we have to drop the file because it is corrupted now + DropImpl(); + } + catch(const Exception&) { } + throw; + } + return TRUE; +} + +//------------------------------------------------------------------ +// erzeugt grundsaetzlich dBase III Datei Format +BOOL ODbaseTable::CreateMemoFile(const INetURLObject& aFile) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbase", "Ocke.Janssen@sun.com", "ODbaseTable::CreateMemoFile" ); + // Makro zum Filehandling fuers Erzeugen von Tabellen + m_pMemoStream = createStream_simpleError( aFile.GetMainURL(INetURLObject::NO_DECODE),STREAM_READWRITE | STREAM_SHARE_DENYWRITE); + + if (!m_pMemoStream) + return sal_False; + + char aBuffer[512]; // write buffer + memset(aBuffer,0,sizeof(aBuffer)); + +#ifdef WIN + m_pMemoStream->Seek(0L); + for (UINT16 i = 0; i < 512; i++) + { + (*m_pMemoStream) << BYTE(0); + } +#else + m_pMemoStream->SetFiller('\0'); + m_pMemoStream->SetStreamSize(512); +#endif + + m_pMemoStream->Seek(0L); + (*m_pMemoStream) << long(1); // Zeiger auf ersten freien Block + + m_pMemoStream->Flush(); + delete m_pMemoStream; + m_pMemoStream = NULL; + return TRUE; +} +//------------------------------------------------------------------ +BOOL ODbaseTable::Drop_Static(const ::rtl::OUString& _sUrl,sal_Bool _bHasMemoFields,OCollection* _pIndexes ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbase", "Ocke.Janssen@sun.com", "ODbaseTable::Drop_Static" ); + INetURLObject aURL; + aURL.SetURL(_sUrl); + + BOOL bDropped = ::utl::UCBContentHelper::Kill(aURL.GetMainURL(INetURLObject::NO_DECODE)); + + if(bDropped) + { + if (_bHasMemoFields) + { // delete the memo fields + aURL.setExtension(String::CreateFromAscii("dbt")); + bDropped = ::utl::UCBContentHelper::Kill(aURL.GetMainURL(INetURLObject::NO_DECODE)); + } + + if(bDropped) + { + if(_pIndexes) + { + try + { + sal_Int32 i = _pIndexes->getCount(); + while (i) + { + _pIndexes->dropByIndex(--i); + } + } + catch(SQLException) + { + } + } + // aFile.SetBase(m_Name); + aURL.setExtension(String::CreateFromAscii("inf")); + + // as the inf file does not necessarily exist, we aren't allowed to use UCBContentHelper::Kill + // 89711 - 16.07.2001 - frank.schoenheit@sun.com + try + { + ::ucbhelper::Content aDeleteContent( aURL.GetMainURL( INetURLObject::NO_DECODE ), Reference< XCommandEnvironment > () ); + aDeleteContent.executeCommand( ::rtl::OUString::createFromAscii( "delete" ), makeAny( sal_Bool( sal_True ) ) ); + } + catch(Exception&) + { + // silently ignore this .... + } + } + } + return bDropped; +} +// ----------------------------------------------------------------------------- +BOOL ODbaseTable::DropImpl() +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbase", "Ocke.Janssen@sun.com", "ODbaseTable::DropImpl" ); + FileClose(); + + if(!m_pIndexes) + refreshIndexes(); // look for indexes which must be deleted as well + + BOOL bDropped = Drop_Static(getEntry(m_pConnection,m_Name),HasMemoFields(),m_pIndexes); + if(!bDropped) + {// we couldn't drop the table so we have to reopen it + construct(); + if(m_pColumns) + m_pColumns->refresh(); + } + return bDropped; +} + +//------------------------------------------------------------------ +BOOL ODbaseTable::InsertRow(OValueRefVector& rRow, BOOL bFlush,const Reference<XIndexAccess>& _xCols) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbase", "Ocke.Janssen@sun.com", "ODbaseTable::InsertRow" ); + // Buffer mit Leerzeichen fuellen + AllocBuffer(); + memset(m_pBuffer, 0, m_aHeader.db_slng); + m_pBuffer[0] = ' '; + + // Gesamte neue Row uebernehmen: + // ... und am Ende als neuen Record hinzufuegen: + UINT32 nTempPos = m_nFilePos, + nFileSize = 0, + nMemoFileSize = 0; + + m_nFilePos = (ULONG)m_aHeader.db_anz + 1; + BOOL bInsertRow = UpdateBuffer( rRow, NULL, _xCols ); + if ( bInsertRow ) + { + nFileSize = lcl_getFileSize(*m_pFileStream); + + if (HasMemoFields() && m_pMemoStream) + { + m_pMemoStream->Seek(STREAM_SEEK_TO_END); + nMemoFileSize = m_pMemoStream->Tell(); + } + + if (!WriteBuffer()) + { + m_pFileStream->SetStreamSize(nFileSize); // alte Groesse restaurieren + + if (HasMemoFields() && m_pMemoStream) + m_pMemoStream->SetStreamSize(nMemoFileSize); // alte Groesse restaurieren + m_nFilePos = nTempPos; // Fileposition restaurieren + } + else + { + (*m_pFileStream) << (char)DBF_EOL; // write EOL + // Anzahl Datensaetze im Header erhoehen: + m_pFileStream->Seek( 4L ); + (*m_pFileStream) << (m_aHeader.db_anz + 1); + + // beim AppendOnly kein Flush! + if (bFlush) + m_pFileStream->Flush(); + + // bei Erfolg # erhoehen + m_aHeader.db_anz++; + *rRow.get()[0] = m_nFilePos; // BOOKmark setzen + m_nFilePos = nTempPos; + } + } + else + m_nFilePos = nTempPos; + + return bInsertRow; +} + +//------------------------------------------------------------------ +BOOL ODbaseTable::UpdateRow(OValueRefVector& rRow, OValueRefRow& pOrgRow,const Reference<XIndexAccess>& _xCols) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbase", "Ocke.Janssen@sun.com", "ODbaseTable::UpdateRow" ); + // Buffer mit Leerzeichen fuellen + AllocBuffer(); + + // Auf gewuenschten Record positionieren: + long nPos = m_aHeader.db_kopf + (long)(m_nFilePos-1) * m_aHeader.db_slng; + m_pFileStream->Seek(nPos); + m_pFileStream->Read((char*)m_pBuffer, m_aHeader.db_slng); + + UINT32 nMemoFileSize( 0 ); + if (HasMemoFields() && m_pMemoStream) + { + m_pMemoStream->Seek(STREAM_SEEK_TO_END); + nMemoFileSize = m_pMemoStream->Tell(); + } + if (!UpdateBuffer(rRow, pOrgRow,_xCols) || !WriteBuffer()) + { + if (HasMemoFields() && m_pMemoStream) + m_pMemoStream->SetStreamSize(nMemoFileSize); // alte Groesse restaurieren + } + else + { + m_pFileStream->Flush(); + } + return sal_True; +} + +//------------------------------------------------------------------ +BOOL ODbaseTable::DeleteRow(const OSQLColumns& _rCols) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbase", "Ocke.Janssen@sun.com", "ODbaseTable::DeleteRow" ); + // Einfach das Loesch-Flag setzen (egal, ob es schon gesetzt war + // oder nicht): + // Auf gewuenschten Record positionieren: + long nFilePos = m_aHeader.db_kopf + (long)(m_nFilePos-1) * m_aHeader.db_slng; + m_pFileStream->Seek(nFilePos); + + OValueRefRow aRow = new OValueRefVector(_rCols.get().size()); + + if (!fetchRow(aRow,_rCols,TRUE,TRUE)) + return sal_False; + + Reference<XPropertySet> xCol; + ::rtl::OUString aColName; + ::comphelper::UStringMixEqual aCase(isCaseSensitive()); + for (USHORT i = 0; i < m_pColumns->getCount(); i++) + { + Reference<XPropertySet> xIndex = isUniqueByColumnName(i); + if (xIndex.is()) + { + ::cppu::extractInterface(xCol,m_pColumns->getByIndex(i)); + OSL_ENSURE(xCol.is(),"ODbaseTable::DeleteRow column is null!"); + if(xCol.is()) + { + xCol->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_NAME)) >>= aColName; + + Reference<XUnoTunnel> xTunnel(xIndex,UNO_QUERY); + OSL_ENSURE(xTunnel.is(),"No TunnelImplementation!"); + ODbaseIndex* pIndex = reinterpret_cast< ODbaseIndex* >( xTunnel->getSomething(ODbaseIndex::getUnoTunnelImplementationId()) ); + OSL_ENSURE(pIndex,"ODbaseTable::DeleteRow: No Index returned!"); + + OSQLColumns::Vector::const_iterator aIter = _rCols.get().begin(); + sal_Int32 nPos = 1; + for(;aIter != _rCols.get().end();++aIter,++nPos) + { + if(aCase(getString((*aIter)->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_REALNAME))),aColName)) + break; + } + if (aIter == _rCols.get().end()) + continue; + + pIndex->Delete(m_nFilePos,*(aRow->get())[nPos]); + } + } + } + + m_pFileStream->Seek(nFilePos); + (*m_pFileStream) << (BYTE)'*'; // mark the row in the table as deleted + m_pFileStream->Flush(); + return sal_True; +} +// ------------------------------------------------------------------------- +Reference<XPropertySet> ODbaseTable::isUniqueByColumnName(sal_Int32 _nColumnPos) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbase", "Ocke.Janssen@sun.com", "ODbaseTable::isUniqueByColumnName" ); + if(!m_pIndexes) + refreshIndexes(); + if(m_pIndexes->hasElements()) + { + Reference<XPropertySet> xCol; + m_pColumns->getByIndex(_nColumnPos) >>= xCol; + OSL_ENSURE(xCol.is(),"ODbaseTable::isUniqueByColumnName column is null!"); + ::rtl::OUString sColName; + xCol->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_NAME)) >>= sColName; + + Reference<XPropertySet> xIndex; + for(sal_Int32 i=0;i<m_pIndexes->getCount();++i) + { + ::cppu::extractInterface(xIndex,m_pIndexes->getByIndex(i)); + if(xIndex.is() && getBOOL(xIndex->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_ISUNIQUE)))) + { + Reference<XNameAccess> xCols(Reference<XColumnsSupplier>(xIndex,UNO_QUERY)->getColumns()); + if(xCols->hasByName(sColName)) + return xIndex; + + } + } + } + return Reference<XPropertySet>(); +} +//------------------------------------------------------------------ +double toDouble(const ByteString& rString) +{ + return ::rtl::math::stringToDouble( rString, '.', ',', NULL, NULL ); +} + +//------------------------------------------------------------------ +BOOL ODbaseTable::UpdateBuffer(OValueRefVector& rRow, OValueRefRow pOrgRow,const Reference<XIndexAccess>& _xCols) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbase", "Ocke.Janssen@sun.com", "ODbaseTable::UpdateBuffer" ); + OSL_ENSURE(m_pBuffer,"Buffer is NULL!"); + if ( !m_pBuffer ) + return FALSE; + sal_Int32 nByteOffset = 1; + + // Felder aktualisieren: + Reference<XPropertySet> xCol; + Reference<XPropertySet> xIndex; + USHORT i; + ::rtl::OUString aColName; + const sal_Int32 nColumnCount = m_pColumns->getCount(); + ::std::vector< Reference<XPropertySet> > aIndexedCols(nColumnCount); + + ::comphelper::UStringMixEqual aCase(isCaseSensitive()); + + Reference<XIndexAccess> xColumns = m_pColumns; + // first search a key that exist already in the table + for (i = 0; i < nColumnCount; ++i) + { + sal_Int32 nPos = i; + if(_xCols != xColumns) + { + m_pColumns->getByIndex(i) >>= xCol; + OSL_ENSURE(xCol.is(),"ODbaseTable::UpdateBuffer column is null!"); + xCol->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_NAME)) >>= aColName; + + for(nPos = 0;nPos<_xCols->getCount();++nPos) + { + Reference<XPropertySet> xFindCol; + ::cppu::extractInterface(xFindCol,_xCols->getByIndex(nPos)); + OSL_ENSURE(xFindCol.is(),"ODbaseTable::UpdateBuffer column is null!"); + if(aCase(getString(xFindCol->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_NAME))),aColName)) + break; + } + if (nPos >= _xCols->getCount()) + continue; + } + + ++nPos; + xIndex = isUniqueByColumnName(i); + aIndexedCols[i] = xIndex; + if (xIndex.is()) + { + // first check if the value is different to the old one and when if it conform to the index + if(pOrgRow.isValid() && (rRow.get()[nPos]->getValue().isNull() || rRow.get()[nPos] == (pOrgRow->get())[nPos])) + continue; + else + { + // ODbVariantRef xVar = (pVal == NULL) ? new ODbVariant() : pVal; + Reference<XUnoTunnel> xTunnel(xIndex,UNO_QUERY); + OSL_ENSURE(xTunnel.is(),"No TunnelImplementation!"); + ODbaseIndex* pIndex = reinterpret_cast< ODbaseIndex* >( xTunnel->getSomething(ODbaseIndex::getUnoTunnelImplementationId()) ); + OSL_ENSURE(pIndex,"ODbaseTable::UpdateBuffer: No Index returned!"); + + if (pIndex->Find(0,*rRow.get()[nPos])) + { + // es existiert kein eindeutiger Wert + if ( !aColName.getLength() ) + { + m_pColumns->getByIndex(i) >>= xCol; + OSL_ENSURE(xCol.is(),"ODbaseTable::UpdateBuffer column is null!"); + xCol->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_NAME)) >>= aColName; + xCol.clear(); + } // if ( !aColName.getLength() ) + const ::rtl::OUString sError( getConnection()->getResources().getResourceStringWithSubstitution( + STR_DUPLICATE_VALUE_IN_COLUMN + ,"$columnname$", aColName + ) ); + ::dbtools::throwGenericSQLException( sError, *this ); + } + } + } + } + + // when we are here there is no double key in the table + + for (i = 0; i < nColumnCount && nByteOffset <= m_nBufferSize ; ++i) + { + // Laengen je nach Datentyp: + OSL_ENSURE(i < m_aPrecisions.size(),"Illegal index!"); + sal_Int32 nLen = 0; + sal_Int32 nType = 0; + sal_Int32 nScale = 0; + if ( i < m_aPrecisions.size() ) + { + nLen = m_aPrecisions[i]; + nType = m_aTypes[i]; + nScale = m_aScales[i]; + } + else + { + m_pColumns->getByIndex(i) >>= xCol; + if ( xCol.is() ) + { + xCol->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_PRECISION)) >>= nLen; + xCol->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_TYPE)) >>= nType; + xCol->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_SCALE)) >>= nScale; + } + } + + bool bSetZero = false; + switch (nType) + { + case DataType::INTEGER: + case DataType::DOUBLE: + case DataType::TIMESTAMP: + bSetZero = true; + case DataType::LONGVARBINARY: + case DataType::DATE: + case DataType::BIT: + case DataType::LONGVARCHAR: + nLen = m_aRealFieldLengths[i]; + break; + case DataType::DECIMAL: + nLen = SvDbaseConverter::ConvertPrecisionToDbase(nLen,nScale); + break; // das Vorzeichen und das Komma + default: + break; + + } // switch (nType) + + sal_Int32 nPos = i; + if(_xCols != xColumns) + { + m_pColumns->getByIndex(i) >>= xCol; + OSL_ENSURE(xCol.is(),"ODbaseTable::UpdateBuffer column is null!"); + xCol->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_NAME)) >>= aColName; + for(nPos = 0;nPos<_xCols->getCount();++nPos) + { + Reference<XPropertySet> xFindCol; + ::cppu::extractInterface(xFindCol,_xCols->getByIndex(nPos)); + if(aCase(getString(xFindCol->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_NAME))),aColName)) + break; + } + if (nPos >= _xCols->getCount()) + { + nByteOffset += nLen; + continue; + } + } + + + + ++nPos; // the row values start at 1 + // Ist die Variable ueberhaupt gebunden? + if ( !rRow.get()[nPos]->isBound() ) + { + // Nein - naechstes Feld. + nByteOffset += nLen; + continue; + } + if (aIndexedCols[i].is()) + { + Reference<XUnoTunnel> xTunnel(aIndexedCols[i],UNO_QUERY); + OSL_ENSURE(xTunnel.is(),"No TunnelImplementation!"); + ODbaseIndex* pIndex = reinterpret_cast< ODbaseIndex* >( xTunnel->getSomething(ODbaseIndex::getUnoTunnelImplementationId()) ); + OSL_ENSURE(pIndex,"ODbaseTable::UpdateBuffer: No Index returned!"); + // Update !! + if (pOrgRow.isValid() && !rRow.get()[nPos]->getValue().isNull() )//&& pVal->isModified()) + pIndex->Update(m_nFilePos,*(pOrgRow->get())[nPos],*rRow.get()[nPos]); + else + pIndex->Insert(m_nFilePos,*rRow.get()[nPos]); + } + + char* pData = (char *)(m_pBuffer + nByteOffset); + if (rRow.get()[nPos]->getValue().isNull()) + { + if ( bSetZero ) + memset(pData,0,nLen); // Zuruecksetzen auf NULL + else + memset(pData,' ',nLen); // Zuruecksetzen auf NULL + nByteOffset += nLen; + OSL_ENSURE( nByteOffset <= m_nBufferSize ,"ByteOffset > m_nBufferSize!"); + continue; + } + + sal_Bool bHadError = sal_False; + try + { + switch (nType) + { + case DataType::TIMESTAMP: + { + sal_Int32 nJulianDate = 0, nJulianTime = 0; + lcl_CalcJulDate(nJulianDate,nJulianTime,rRow.get()[nPos]->getValue()); + // Genau 8 Byte kopieren: + memcpy(pData,&nJulianDate,4); + memcpy(pData+4,&nJulianTime,4); + } + break; + case DataType::DATE: + { + ::com::sun::star::util::Date aDate; + if(rRow.get()[nPos]->getValue().getTypeKind() == DataType::DOUBLE) + aDate = ::dbtools::DBTypeConversion::toDate(rRow.get()[nPos]->getValue().getDouble()); + else + aDate = rRow.get()[nPos]->getValue(); + char s[9]; + snprintf(s, + sizeof(s), + "%04d%02d%02d", + (int)aDate.Year, + (int)aDate.Month, + (int)aDate.Day); + + // Genau 8 Byte kopieren: + strncpy(pData,s,sizeof s - 1); + } break; + case DataType::INTEGER: + { + sal_Int32 nValue = rRow.get()[nPos]->getValue(); + memcpy(pData,&nValue,nLen); + } + break; + case DataType::DOUBLE: + { + const double d = rRow.get()[nPos]->getValue(); + m_pColumns->getByIndex(i) >>= xCol; + + if (getBOOL(xCol->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_ISCURRENCY)))) // Currency wird gesondert behandelt + { + sal_Int64 nValue = 0; + if ( m_aScales[i] ) + nValue = (sal_Int64)(d * pow(10.0,(int)m_aScales[i])); + else + nValue = (sal_Int64)(d); + memcpy(pData,&nValue,nLen); + } // if (getBOOL(xCol->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_ISCURRENCY)))) // Currency wird gesondert behandelt + else + memcpy(pData,&d,nLen); + } + break; + case DataType::DECIMAL: + { + memset(pData,' ',nLen); // Zuruecksetzen auf NULL + + const double n = rRow.get()[nPos]->getValue(); + + // ein const_cast, da GetFormatPrecision am SvNumberFormat nicht const ist, obwohl es das eigentlich + // sein koennte und muesste + + const ByteString aDefaultValue( ::rtl::math::doubleToString( n, rtl_math_StringFormat_F, nScale, '.', NULL, 0)); + BOOL bValidLength = aDefaultValue.Len() <= nLen; + if ( bValidLength ) + { + strncpy(pData,aDefaultValue.GetBuffer(),nLen); + // write the resulting double back + *rRow.get()[nPos] = toDouble(aDefaultValue); + } + else + { + m_pColumns->getByIndex(i) >>= xCol; + OSL_ENSURE(xCol.is(),"ODbaseTable::UpdateBuffer column is null!"); + xCol->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_NAME)) >>= aColName; + ::std::list< ::std::pair<const sal_Char* , ::rtl::OUString > > aStringToSubstitutes; + aStringToSubstitutes.push_back(::std::pair<const sal_Char* , ::rtl::OUString >("$columnname$", aColName)); + aStringToSubstitutes.push_back(::std::pair<const sal_Char* , ::rtl::OUString >("$precision$", String::CreateFromInt32(nLen))); + aStringToSubstitutes.push_back(::std::pair<const sal_Char* , ::rtl::OUString >("$scale$", String::CreateFromInt32(nScale))); + aStringToSubstitutes.push_back(::std::pair<const sal_Char* , ::rtl::OUString >("$value$", ::rtl::OStringToOUString(aDefaultValue,RTL_TEXTENCODING_UTF8))); + + const ::rtl::OUString sError( getConnection()->getResources().getResourceStringWithSubstitution( + STR_INVALID_COLUMN_DECIMAL_VALUE + ,aStringToSubstitutes + ) ); + ::dbtools::throwGenericSQLException( sError, *this ); + } + } break; + case DataType::BIT: + *pData = rRow.get()[nPos]->getValue().getBool() ? 'T' : 'F'; + break; + case DataType::LONGVARBINARY: + case DataType::LONGVARCHAR: + { + char cNext = pData[nLen]; // merken und temporaer durch 0 ersetzen + pData[nLen] = '\0'; // das geht, da der Puffer immer ein Zeichen groesser ist ... + + ULONG nBlockNo = strtol((const char *)pData,NULL,10); // Blocknummer lesen + + // Naechstes Anfangszeichen wieder restaurieren: + pData[nLen] = cNext; + if (!m_pMemoStream || !WriteMemo(rRow.get()[nPos]->get(), nBlockNo)) + break; + + ByteString aStr; + ByteString aBlock(ByteString::CreateFromInt32(nBlockNo)); + aStr.Expand(static_cast<sal_uInt16>(nLen - aBlock.Len()), '0' ); + aStr += aBlock; + // Zeichen kopieren: + memset(pData,' ',nLen); // Zuruecksetzen auf NULL + memcpy(pData, aStr.GetBuffer(), nLen); + } break; + default: + { + memset(pData,' ',nLen); // Zuruecksetzen auf NULL + + ::rtl::OUString sStringToWrite( rRow.get()[nPos]->getValue().getString() ); + + // convert the string, using the connection's encoding + ::rtl::OString sEncoded; + + DBTypeConversion::convertUnicodeStringToLength( sStringToWrite, sEncoded, nLen, m_eEncoding ); + memcpy( pData, sEncoded.getStr(), sEncoded.getLength() ); + + } + break; + } + } + catch( SQLException& ) + { + throw; + } + catch ( Exception& ) { bHadError = sal_True; } + + if ( bHadError ) + { + m_pColumns->getByIndex(i) >>= xCol; + OSL_ENSURE( xCol.is(), "ODbaseTable::UpdateBuffer column is null!" ); + if ( xCol.is() ) + xCol->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_NAME)) >>= aColName; + + const ::rtl::OUString sError( getConnection()->getResources().getResourceStringWithSubstitution( + STR_INVALID_COLUMN_VALUE, + "$columnname$", aColName + ) ); + ::dbtools::throwGenericSQLException( sError, *this ); + } + // Und weiter ... + nByteOffset += nLen; + OSL_ENSURE( nByteOffset <= m_nBufferSize ,"ByteOffset > m_nBufferSize!"); + } + return sal_True; +} + +// ----------------------------------------------------------------------------- +BOOL ODbaseTable::WriteMemo(ORowSetValue& aVariable, ULONG& rBlockNr) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbase", "Ocke.Janssen@sun.com", "ODbaseTable::WriteMemo" ); + // wird die BlockNr 0 vorgegeben, wird der block ans Ende gehaengt + ULONG nSize = 0; + ::rtl::OString aStr; + ::com::sun::star::uno::Sequence<sal_Int8> aValue; + BYTE nHeader[4]; + const bool bBinary = aVariable.getTypeKind() == DataType::LONGVARBINARY && m_aMemoHeader.db_typ == MemoFoxPro; + if ( bBinary ) + { + aValue = aVariable.getSequence(); + nSize = aValue.getLength(); + } + else + { + nSize = DBTypeConversion::convertUnicodeString( aVariable.getString(), aStr, m_eEncoding ); + } + + // Anhaengen oder ueberschreiben + BOOL bAppend = rBlockNr == 0; + + if (!bAppend) + { + switch (m_aMemoHeader.db_typ) + { + case MemodBaseIII: // dBase III-Memofeld, endet mit 2 * Ctrl-Z + bAppend = nSize > (512 - 2); + break; + case MemoFoxPro: + case MemodBaseIV: // dBase IV-Memofeld mit Laengenangabe + { + char sHeader[4]; + m_pMemoStream->Seek(rBlockNr * m_aMemoHeader.db_size); + m_pMemoStream->SeekRel(4L); + m_pMemoStream->Read(sHeader,4); + + ULONG nOldSize; + if (m_aMemoHeader.db_typ == MemoFoxPro) + nOldSize = ((((unsigned char)sHeader[0]) * 256 + + (unsigned char)sHeader[1]) * 256 + + (unsigned char)sHeader[2]) * 256 + + (unsigned char)sHeader[3]; + else + nOldSize = ((((unsigned char)sHeader[3]) * 256 + + (unsigned char)sHeader[2]) * 256 + + (unsigned char)sHeader[1]) * 256 + + (unsigned char)sHeader[0] - 8; + + // passt die neue Laenge in die belegten Bloecke + ULONG nUsedBlocks = ((nSize + 8) / m_aMemoHeader.db_size) + (((nSize + 8) % m_aMemoHeader.db_size > 0) ? 1 : 0), + nOldUsedBlocks = ((nOldSize + 8) / m_aMemoHeader.db_size) + (((nOldSize + 8) % m_aMemoHeader.db_size > 0) ? 1 : 0); + bAppend = nUsedBlocks > nOldUsedBlocks; + } + } + } + + if (bAppend) + { + ULONG nStreamSize = m_pMemoStream->Seek(STREAM_SEEK_TO_END); + // letzten block auffuellen + rBlockNr = (nStreamSize / m_aMemoHeader.db_size) + ((nStreamSize % m_aMemoHeader.db_size) > 0 ? 1 : 0); + + m_pMemoStream->SetStreamSize(rBlockNr * m_aMemoHeader.db_size); + m_pMemoStream->Seek(STREAM_SEEK_TO_END); + } + else + { + m_pMemoStream->Seek(rBlockNr * m_aMemoHeader.db_size); + } + + switch (m_aMemoHeader.db_typ) + { + case MemodBaseIII: // dBase III-Memofeld, endet mit Ctrl-Z + { + const char cEOF = (char) DBF_EOL; + nSize++; + m_pMemoStream->Write( aStr.getStr(), aStr.getLength() ); + (*m_pMemoStream) << cEOF << cEOF; + } break; + case MemoFoxPro: + case MemodBaseIV: // dBase IV-Memofeld mit Laengenangabe + { + if ( MemodBaseIV == m_aMemoHeader.db_typ ) + (*m_pMemoStream) << (BYTE)0xFF + << (BYTE)0xFF + << (BYTE)0x08; + else + (*m_pMemoStream) << (BYTE)0x00 + << (BYTE)0x00 + << (BYTE)0x00; + + UINT32 nWriteSize = nSize; + if (m_aMemoHeader.db_typ == MemoFoxPro) + { + if ( bBinary ) + (*m_pMemoStream) << (BYTE) 0x00; // Picture + else + (*m_pMemoStream) << (BYTE) 0x01; // Memo + for (int i = 4; i > 0; nWriteSize >>= 8) + nHeader[--i] = (BYTE) (nWriteSize % 256); + } + else + { + (*m_pMemoStream) << (BYTE) 0x00; + nWriteSize += 8; + for (int i = 0; i < 4; nWriteSize >>= 8) + nHeader[i++] = (BYTE) (nWriteSize % 256); + } + + m_pMemoStream->Write(nHeader,4); + if ( bBinary ) + m_pMemoStream->Write( aValue.getConstArray(), aValue.getLength() ); + else + m_pMemoStream->Write( aStr.getStr(), aStr.getLength() ); + m_pMemoStream->Flush(); + } + } + + + // Schreiben der neuen Blocknummer + if (bAppend) + { + ULONG nStreamSize = m_pMemoStream->Seek(STREAM_SEEK_TO_END); + m_aMemoHeader.db_next = (nStreamSize / m_aMemoHeader.db_size) + ((nStreamSize % m_aMemoHeader.db_size) > 0 ? 1 : 0); + + // Schreiben der neuen Blocknummer + m_pMemoStream->Seek(0L); + (*m_pMemoStream) << m_aMemoHeader.db_next; + m_pMemoStream->Flush(); + } + return sal_True; +} + +// ----------------------------------------------------------------------------- +// XAlterTable +void SAL_CALL ODbaseTable::alterColumnByName( const ::rtl::OUString& colName, const Reference< XPropertySet >& descriptor ) throw(SQLException, NoSuchElementException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbase", "Ocke.Janssen@sun.com", "ODbaseTable::alterColumnByName" ); + ::osl::MutexGuard aGuard(m_aMutex); + checkDisposed(OTableDescriptor_BASE::rBHelper.bDisposed); + + + Reference<XDataDescriptorFactory> xOldColumn; + m_pColumns->getByName(colName) >>= xOldColumn; + + alterColumn(m_pColumns->findColumn(colName)-1,descriptor,xOldColumn); +} +// ------------------------------------------------------------------------- +void SAL_CALL ODbaseTable::alterColumnByIndex( sal_Int32 index, const Reference< XPropertySet >& descriptor ) throw(SQLException, ::com::sun::star::lang::IndexOutOfBoundsException, RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbase", "Ocke.Janssen@sun.com", "ODbaseTable::alterColumnByIndex" ); + ::osl::MutexGuard aGuard(m_aMutex); + checkDisposed(OTableDescriptor_BASE::rBHelper.bDisposed); + + if(index < 0 || index >= m_pColumns->getCount()) + throw IndexOutOfBoundsException(::rtl::OUString::valueOf(index),*this); + + Reference<XDataDescriptorFactory> xOldColumn; + m_pColumns->getByIndex(index) >>= xOldColumn; + alterColumn(index,descriptor,xOldColumn); +} +// ----------------------------------------------------------------------------- +void ODbaseTable::alterColumn(sal_Int32 index, + const Reference< XPropertySet >& descriptor , + const Reference< XDataDescriptorFactory >& xOldColumn ) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbase", "Ocke.Janssen@sun.com", "ODbaseTable::alterColumn" ); + if(index < 0 || index >= m_pColumns->getCount()) + throw IndexOutOfBoundsException(::rtl::OUString::valueOf(index),*this); + + ODbaseTable* pNewTable = NULL; + try + { + OSL_ENSURE(descriptor.is(),"ODbaseTable::alterColumn: descriptor can not be null!"); + // creates a copy of the the original column and copy all properties from descriptor in xCopyColumn + Reference<XPropertySet> xCopyColumn; + if(xOldColumn.is()) + xCopyColumn = xOldColumn->createDataDescriptor(); + else + xCopyColumn = new OColumn(getConnection()->getMetaData()->storesMixedCaseQuotedIdentifiers()); + + ::comphelper::copyProperties(descriptor,xCopyColumn); + + // creates a temp file + + String sTempName = createTempFile(); + + pNewTable = new ODbaseTable(m_pTables,static_cast<ODbaseConnection*>(m_pConnection)); + Reference<XPropertySet> xHoldTable = pNewTable; + pNewTable->setPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_NAME),makeAny(::rtl::OUString(sTempName))); + Reference<XAppend> xAppend(pNewTable->getColumns(),UNO_QUERY); + OSL_ENSURE(xAppend.is(),"ODbaseTable::alterColumn: No XAppend interface!"); + + // copy the structure + sal_Int32 i=0; + for(;i < index;++i) + { + Reference<XPropertySet> xProp; + m_pColumns->getByIndex(i) >>= xProp; + Reference<XDataDescriptorFactory> xColumn(xProp,UNO_QUERY); + Reference<XPropertySet> xCpy; + if(xColumn.is()) + xCpy = xColumn->createDataDescriptor(); + else + xCpy = new OColumn(getConnection()->getMetaData()->storesMixedCaseQuotedIdentifiers()); + ::comphelper::copyProperties(xProp,xCpy); + xAppend->appendByDescriptor(xCpy); + } + ++i; // now insert our new column + xAppend->appendByDescriptor(xCopyColumn); + + for(;i < m_pColumns->getCount();++i) + { + Reference<XPropertySet> xProp; + m_pColumns->getByIndex(i) >>= xProp; + Reference<XDataDescriptorFactory> xColumn(xProp,UNO_QUERY); + Reference<XPropertySet> xCpy; + if(xColumn.is()) + xCpy = xColumn->createDataDescriptor(); + else + xCpy = new OColumn(getConnection()->getMetaData()->storesMixedCaseQuotedIdentifiers()); + ::comphelper::copyProperties(xProp,xCpy); + xAppend->appendByDescriptor(xCpy); + } + + // construct the new table + if(!pNewTable->CreateImpl()) + { + const ::rtl::OUString sError( getConnection()->getResources().getResourceStringWithSubstitution( + STR_COLUMN_NOT_ALTERABLE, + "$columnname$", ::comphelper::getString(descriptor->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_NAME))) + ) ); + ::dbtools::throwGenericSQLException( sError, *this ); + } + + pNewTable->construct(); + + // copy the data + copyData(pNewTable,0); + + // now drop the old one + if( DropImpl() ) // we don't want to delete the memo columns too + { + // rename the new one to the old one + pNewTable->renameImpl(m_Name); + // release the temp file + pNewTable = NULL; + ::comphelper::disposeComponent(xHoldTable); + } + else + { + pNewTable = NULL; + } + FileClose(); + construct(); + if(m_pColumns) + m_pColumns->refresh(); + + } + catch(const SQLException&) + { + throw; + } + catch(const Exception&) + { + OSL_ENSURE(0,"ODbaseTable::alterColumn: Exception occured!"); + throw; + } +} +// ----------------------------------------------------------------------------- +Reference< XDatabaseMetaData> ODbaseTable::getMetaData() const +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbase", "Ocke.Janssen@sun.com", "ODbaseTable::getMetaData" ); + return getConnection()->getMetaData(); +} +// ------------------------------------------------------------------------- +void SAL_CALL ODbaseTable::rename( const ::rtl::OUString& newName ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::container::ElementExistException, ::com::sun::star::uno::RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbase", "Ocke.Janssen@sun.com", "ODbaseTable::rename" ); + ::osl::MutexGuard aGuard(m_aMutex); + checkDisposed(OTableDescriptor_BASE::rBHelper.bDisposed); + if(m_pTables && m_pTables->hasByName(newName)) + throw ElementExistException(newName,*this); + + + renameImpl(newName); + + ODbaseTable_BASE::rename(newName); + + construct(); + if(m_pColumns) + m_pColumns->refresh(); +} +namespace +{ + void renameFile(OConnection* _pConenction,const ::rtl::OUString& oldName, + const ::rtl::OUString& newName,const String& _sExtension) + { + String aName = ODbaseTable::getEntry(_pConenction,oldName); + if(!aName.Len()) + { + ::rtl::OUString aIdent = _pConenction->getContent()->getIdentifier()->getContentIdentifier(); + if ( aIdent.lastIndexOf('/') != (aIdent.getLength()-1) ) + aIdent += ::rtl::OUString::createFromAscii("/"); + aIdent += oldName; + aName = aIdent; + } + INetURLObject aURL; + aURL.SetURL(aName); + + aURL.setExtension( _sExtension ); + String sNewName(newName); + sNewName.AppendAscii("."); + sNewName += _sExtension; + + try + { + Content aContent(aURL.GetMainURL(INetURLObject::NO_DECODE),Reference<XCommandEnvironment>()); + + Sequence< PropertyValue > aProps( 1 ); + aProps[0].Name = ::rtl::OUString::createFromAscii("Title"); + aProps[0].Handle = -1; // n/a + aProps[0].Value = makeAny( ::rtl::OUString(sNewName) ); + Sequence< Any > aValues; + aContent.executeCommand( rtl::OUString::createFromAscii( "setPropertyValues" ),makeAny(aProps) ) >>= aValues; + if(aValues.getLength() && aValues[0].hasValue()) + throw Exception(); + } + catch(Exception&) + { + throw ElementExistException(newName,NULL); + } + } +} +// ------------------------------------------------------------------------- +void SAL_CALL ODbaseTable::renameImpl( const ::rtl::OUString& newName ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::container::ElementExistException, ::com::sun::star::uno::RuntimeException) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbase", "Ocke.Janssen@sun.com", "ODbaseTable::getEntry" ); + ::osl::MutexGuard aGuard(m_aMutex); + + FileClose(); + + + renameFile(m_pConnection,m_Name,newName,m_pConnection->getExtension()); + if ( HasMemoFields() ) + { // delete the memo fields + String sExt = String::CreateFromAscii("dbt"); + renameFile(m_pConnection,m_Name,newName,sExt); + } +} +// ----------------------------------------------------------------------------- +void ODbaseTable::addColumn(const Reference< XPropertySet >& _xNewColumn) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbase", "Ocke.Janssen@sun.com", "ODbaseTable::addColumn" ); + String sTempName = createTempFile(); + + ODbaseTable* pNewTable = new ODbaseTable(m_pTables,static_cast<ODbaseConnection*>(m_pConnection)); + Reference< XPropertySet > xHold = pNewTable; + pNewTable->setPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_NAME),makeAny(::rtl::OUString(sTempName))); + { + Reference<XAppend> xAppend(pNewTable->getColumns(),UNO_QUERY); + sal_Bool bCase = getConnection()->getMetaData()->storesMixedCaseQuotedIdentifiers(); + // copy the structure + for(sal_Int32 i=0;i < m_pColumns->getCount();++i) + { + Reference<XPropertySet> xProp; + m_pColumns->getByIndex(i) >>= xProp; + Reference<XDataDescriptorFactory> xColumn(xProp,UNO_QUERY); + Reference<XPropertySet> xCpy; + if(xColumn.is()) + xCpy = xColumn->createDataDescriptor(); + else + { + xCpy = new OColumn(bCase); + ::comphelper::copyProperties(xProp,xCpy); + } + + xAppend->appendByDescriptor(xCpy); + } + Reference<XPropertySet> xCpy = new OColumn(bCase); + ::comphelper::copyProperties(_xNewColumn,xCpy); + xAppend->appendByDescriptor(xCpy); + } + + // construct the new table + if(!pNewTable->CreateImpl()) + { + const ::rtl::OUString sError( getConnection()->getResources().getResourceStringWithSubstitution( + STR_COLUMN_NOT_ADDABLE, + "$columnname$", ::comphelper::getString(_xNewColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_NAME))) + ) ); + ::dbtools::throwGenericSQLException( sError, *this ); + } + + BOOL bAlreadyDroped = FALSE; + try + { + pNewTable->construct(); + // copy the data + copyData(pNewTable,pNewTable->m_pColumns->getCount()); + // drop the old table + if(DropImpl()) + { + bAlreadyDroped = TRUE; + pNewTable->renameImpl(m_Name); + // release the temp file + } + xHold = pNewTable = NULL; + + FileClose(); + construct(); + if(m_pColumns) + m_pColumns->refresh(); + } + catch(const SQLException&) + { + // here we know that the old table wasn't droped before + if(!bAlreadyDroped) + xHold = pNewTable = NULL; + + throw; + } +} +// ----------------------------------------------------------------------------- +void ODbaseTable::dropColumn(sal_Int32 _nPos) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbase", "Ocke.Janssen@sun.com", "ODbaseTable::dropColumn" ); + String sTempName = createTempFile(); + + ODbaseTable* pNewTable = new ODbaseTable(m_pTables,static_cast<ODbaseConnection*>(m_pConnection)); + Reference< XPropertySet > xHold = pNewTable; + pNewTable->setPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_NAME),makeAny(::rtl::OUString(sTempName))); + { + Reference<XAppend> xAppend(pNewTable->getColumns(),UNO_QUERY); + sal_Bool bCase = getConnection()->getMetaData()->storesMixedCaseQuotedIdentifiers(); + // copy the structure + for(sal_Int32 i=0;i < m_pColumns->getCount();++i) + { + if(_nPos != i) + { + Reference<XPropertySet> xProp; + m_pColumns->getByIndex(i) >>= xProp; + Reference<XDataDescriptorFactory> xColumn(xProp,UNO_QUERY); + Reference<XPropertySet> xCpy; + if(xColumn.is()) + xCpy = xColumn->createDataDescriptor(); + else + { + xCpy = new OColumn(bCase); + ::comphelper::copyProperties(xProp,xCpy); + } + xAppend->appendByDescriptor(xCpy); + } + } + } + + // construct the new table + if(!pNewTable->CreateImpl()) + { + xHold = pNewTable = NULL; + const ::rtl::OUString sError( getConnection()->getResources().getResourceStringWithSubstitution( + STR_COLUMN_NOT_DROP, + "$position$", ::rtl::OUString::valueOf(_nPos) + ) ); + ::dbtools::throwGenericSQLException( sError, *this ); + } + pNewTable->construct(); + // copy the data + copyData(pNewTable,_nPos); + // drop the old table + if(DropImpl()) + pNewTable->renameImpl(m_Name); + // release the temp file + + xHold = pNewTable = NULL; + + FileClose(); + construct(); +} +// ----------------------------------------------------------------------------- +String ODbaseTable::createTempFile() +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbase", "Ocke.Janssen@sun.com", "ODbaseTable::createTempFile" ); + ::rtl::OUString aIdent = m_pConnection->getContent()->getIdentifier()->getContentIdentifier(); + if ( aIdent.lastIndexOf('/') != (aIdent.getLength()-1) ) + aIdent += ::rtl::OUString::createFromAscii("/"); + String sTempName(aIdent); + String sExt; + sExt.AssignAscii("."); + sExt += m_pConnection->getExtension(); + + String sName(m_Name); + TempFile aTempFile(sName,&sExt,&sTempName); + if(!aTempFile.IsValid()) + getConnection()->throwGenericSQLException(STR_COULD_NOT_ALTER_TABLE,*this); + + INetURLObject aURL; + aURL.SetSmartProtocol(INET_PROT_FILE); + aURL.SetURL(aTempFile.GetURL()); + + String sNewName(aURL.getName()); + sNewName.Erase(sNewName.Len() - sExt.Len()); + return sNewName; +} +// ----------------------------------------------------------------------------- +void ODbaseTable::copyData(ODbaseTable* _pNewTable,sal_Int32 _nPos) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbase", "Ocke.Janssen@sun.com", "ODbaseTable::copyData" ); + sal_Int32 nPos = _nPos + 1; // +1 because we always have the bookmark clumn as well + OValueRefRow aRow = new OValueRefVector(m_pColumns->getCount()); + OValueRefRow aInsertRow; + if(_nPos) + { + aInsertRow = new OValueRefVector(_pNewTable->m_pColumns->getCount()); + ::std::for_each(aInsertRow->get().begin(),aInsertRow->get().end(),TSetRefBound(sal_True)); + } + else + aInsertRow = aRow; + + // we only have to bind the values which we need to copy into the new table + ::std::for_each(aRow->get().begin(),aRow->get().end(),TSetRefBound(sal_True)); + if(_nPos && (_nPos < (sal_Int32)aRow->get().size())) + (aRow->get())[nPos]->setBound(sal_False); + + + sal_Bool bOk = sal_True; + sal_Int32 nCurPos; + OValueRefVector::Vector::iterator aIter; + for(sal_uInt32 nRowPos = 0; nRowPos < m_aHeader.db_anz;++nRowPos) + { + bOk = seekRow( IResultSetHelper::BOOKMARK, nRowPos+1, nCurPos ); + if ( bOk ) + { + bOk = fetchRow( aRow, m_aColumns.getBody(), sal_True, sal_True); + if ( bOk && !aRow->isDeleted() ) // copy only not deleted rows + { + // special handling when pos == 0 then we don't have to distinguish between the two rows + if(_nPos) + { + aIter = aRow->get().begin()+1; + sal_Int32 nCount = 1; + for(OValueRefVector::Vector::iterator aInsertIter = aInsertRow->get().begin()+1; aIter != aRow->get().end() && aInsertIter != aInsertRow->get().end();++aIter,++nCount) + { + if(nPos != nCount) + { + (*aInsertIter)->setValue( (*aIter)->getValue() ); + ++aInsertIter; + } + } + } + bOk = _pNewTable->InsertRow(*aInsertRow,sal_True,_pNewTable->m_pColumns); + OSL_ENSURE(bOk,"Row could not be inserted!"); + } + else + OSL_ENSURE(bOk,"Row could not be fetched!"); + } + else + { + OSL_ASSERT(0); + } + } // for(sal_uInt32 nRowPos = 0; nRowPos < m_aHeader.db_anz;++nRowPos) +} +// ----------------------------------------------------------------------------- +void ODbaseTable::throwInvalidDbaseFormat() +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbase", "Ocke.Janssen@sun.com", "ODbaseTable::throwInvalidDbaseFormat" ); + FileClose(); + // no dbase file + + const ::rtl::OUString sError( getConnection()->getResources().getResourceStringWithSubstitution( + STR_INVALID_DBASE_FILE, + "$filename$", getEntry(m_pConnection,m_Name) + ) ); + ::dbtools::throwGenericSQLException( sError, *this ); +} +// ----------------------------------------------------------------------------- +void ODbaseTable::refreshHeader() +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbase", "Ocke.Janssen@sun.com", "ODbaseTable::refreshHeader" ); + if ( m_aHeader.db_anz == 0 ) + readHeader(); +} +//------------------------------------------------------------------ +sal_Bool ODbaseTable::seekRow(IResultSetHelper::Movement eCursorPosition, sal_Int32 nOffset, sal_Int32& nCurPos) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbase", "Ocke.Janssen@sun.com", "ODbaseTable::seekRow" ); + // ---------------------------------------------------------- + // Positionierung vorbereiten: + OSL_ENSURE(m_pFileStream,"ODbaseTable::seekRow: FileStream is NULL!"); + + sal_uInt32 nNumberOfRecords = (sal_uInt32)m_aHeader.db_anz; + sal_uInt32 nTempPos = m_nFilePos; + m_nFilePos = nCurPos; + + switch(eCursorPosition) + { + case IResultSetHelper::NEXT: + ++m_nFilePos; + break; + case IResultSetHelper::PRIOR: + if (m_nFilePos > 0) + --m_nFilePos; + break; + case IResultSetHelper::FIRST: + m_nFilePos = 1; + break; + case IResultSetHelper::LAST: + m_nFilePos = nNumberOfRecords; + break; + case IResultSetHelper::RELATIVE: + m_nFilePos = (((sal_Int32)m_nFilePos) + nOffset < 0) ? 0L + : (sal_uInt32)(((sal_Int32)m_nFilePos) + nOffset); + break; + case IResultSetHelper::ABSOLUTE: + case IResultSetHelper::BOOKMARK: + m_nFilePos = (sal_uInt32)nOffset; + break; + } + + if (m_nFilePos > (sal_Int32)nNumberOfRecords) + m_nFilePos = (sal_Int32)nNumberOfRecords + 1; + + if (m_nFilePos == 0 || m_nFilePos == (sal_Int32)nNumberOfRecords + 1) + goto Error; + else + { + sal_uInt16 nEntryLen = m_aHeader.db_slng; + + OSL_ENSURE(m_nFilePos >= 1,"SdbDBFCursor::FileFetchRow: ungueltige Record-Position"); + sal_Int32 nPos = m_aHeader.db_kopf + (sal_Int32)(m_nFilePos-1) * nEntryLen; + + ULONG nLen = m_pFileStream->Seek(nPos); + if (m_pFileStream->GetError() != ERRCODE_NONE) + goto Error; + + nLen = m_pFileStream->Read((char*)m_pBuffer, nEntryLen); + if (m_pFileStream->GetError() != ERRCODE_NONE) + goto Error; + } + goto End; + +Error: + switch(eCursorPosition) + { + case IResultSetHelper::PRIOR: + case IResultSetHelper::FIRST: + m_nFilePos = 0; + break; + case IResultSetHelper::LAST: + case IResultSetHelper::NEXT: + case IResultSetHelper::ABSOLUTE: + case IResultSetHelper::RELATIVE: + if (nOffset > 0) + m_nFilePos = nNumberOfRecords + 1; + else if (nOffset < 0) + m_nFilePos = 0; + break; + case IResultSetHelper::BOOKMARK: + m_nFilePos = nTempPos; // vorherige Position + } + // aStatus.Set(SDB_STAT_NO_DATA_FOUND); + return sal_False; + +End: + nCurPos = m_nFilePos; + return sal_True; +} +// ----------------------------------------------------------------------------- +BOOL ODbaseTable::ReadMemo(ULONG nBlockNo, ORowSetValue& aVariable) +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbase", "Ocke.Janssen@sun.com", "ODbaseTable::ReadMemo" ); + BOOL bIsText = TRUE; + // SdbConnection* pConnection = GetConnection(); + + m_pMemoStream->Seek(nBlockNo * m_aMemoHeader.db_size); + switch (m_aMemoHeader.db_typ) + { + case MemodBaseIII: // dBase III-Memofeld, endet mit Ctrl-Z + { + const char cEOF = (char) DBF_EOL; + ByteString aBStr; + static char aBuf[514]; + aBuf[512] = 0; // sonst kann der Zufall uebel mitspielen + BOOL bReady = sal_False; + + do + { + m_pMemoStream->Read(&aBuf,512); + + USHORT i = 0; + while (aBuf[i] != cEOF && ++i < 512) + ; + bReady = aBuf[i] == cEOF; + + aBuf[i] = 0; + aBStr += aBuf; + + } while (!bReady && !m_pMemoStream->IsEof() && aBStr.Len() < STRING_MAXLEN); + + ::rtl::OUString aStr(aBStr.GetBuffer(), aBStr.Len(),m_eEncoding); + aVariable = aStr; + + } break; + case MemoFoxPro: + case MemodBaseIV: // dBase IV-Memofeld mit Laengenangabe + { + char sHeader[4]; + m_pMemoStream->Read(sHeader,4); + // Foxpro stores text and binary data + if (m_aMemoHeader.db_typ == MemoFoxPro) + { +// if (((BYTE)sHeader[0]) != 0 || ((BYTE)sHeader[1]) != 0 || ((BYTE)sHeader[2]) != 0) +// { +//// String aText = String(SdbResId(STR_STAT_IResultSetHelper::INVALID)); +//// aText.SearchAndReplace(String::CreateFromAscii("%%d"),m_pMemoStream->GetFileName()); +//// aText.SearchAndReplace(String::CreateFromAscii("%%t"),aStatus.TypeToString(MEMO)); +//// aStatus.Set(SDB_STAT_ERROR, +//// String::CreateFromAscii("01000"), +//// aStatus.CreateErrorMessage(aText), +//// 0, String() ); +// return sal_False; +// } +// + bIsText = sHeader[3] != 0; + } + else if (((BYTE)sHeader[0]) != 0xFF || ((BYTE)sHeader[1]) != 0xFF || ((BYTE)sHeader[2]) != 0x08) + { +// String aText = String(SdbResId(STR_STAT_IResultSetHelper::INVALID)); +// aText.SearchAndReplace(String::CreateFromAscii("%%d"),m_pMemoStream->GetFileName()); +// aText.SearchAndReplace(String::CreateFromAscii("%%t"),aStatus.TypeToString(MEMO)); +// aStatus.Set(SDB_STAT_ERROR, +// String::CreateFromAscii("01000"), +// aStatus.CreateErrorMessage(aText), +// 0, String() ); + return sal_False; + } + + sal_uInt32 nLength(0); + (*m_pMemoStream) >> nLength; + + if (m_aMemoHeader.db_typ == MemodBaseIV) + nLength -= 8; + + if ( nLength ) + { + if ( bIsText ) + { + // char cChar; + ::rtl::OUStringBuffer aStr; + while ( nLength > STRING_MAXLEN ) + { + ByteString aBStr; + aBStr.Expand(STRING_MAXLEN); + m_pMemoStream->Read(aBStr.AllocBuffer(STRING_MAXLEN),STRING_MAXLEN); + aStr.append(::rtl::OUString(aBStr.GetBuffer(),aBStr.Len(), m_eEncoding)); + nLength -= STRING_MAXLEN; + } + if ( nLength > 0 ) + { + ByteString aBStr; + aBStr.Expand(static_cast<xub_StrLen>(nLength)); + m_pMemoStream->Read(aBStr.AllocBuffer(static_cast<xub_StrLen>(nLength)),nLength); + // aBStr.ReleaseBufferAccess(); + aStr.append(::rtl::OUString(aBStr.GetBuffer(),aBStr.Len(), m_eEncoding)); + } + if ( aStr.getLength() ) + aVariable = aStr.makeStringAndClear(); + } // if ( bIsText ) + else + { + ::com::sun::star::uno::Sequence< sal_Int8 > aData(nLength); + m_pMemoStream->Read(aData.getArray(),nLength); + aVariable = aData; + } + } // if ( nLength ) + } + } + return sal_True; +} +// ----------------------------------------------------------------------------- +void ODbaseTable::AllocBuffer() +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbase", "Ocke.Janssen@sun.com", "ODbaseTable::AllocBuffer" ); + UINT16 nSize = m_aHeader.db_slng; + OSL_ENSURE(nSize > 0, "Size too small"); + + if (m_nBufferSize != nSize) + { + delete m_pBuffer; + m_pBuffer = NULL; + } + + // Falls noch kein Puffer vorhanden: allozieren: + if (m_pBuffer == NULL && nSize) + { + m_nBufferSize = nSize; + m_pBuffer = new BYTE[m_nBufferSize+1]; + } +} +// ----------------------------------------------------------------------------- +BOOL ODbaseTable::WriteBuffer() +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbase", "Ocke.Janssen@sun.com", "ODbaseTable::WriteBuffer" ); + OSL_ENSURE(m_nFilePos >= 1,"SdbDBFCursor::FileFetchRow: ungueltige Record-Position"); + + // Auf gewuenschten Record positionieren: + long nPos = m_aHeader.db_kopf + (long)(m_nFilePos-1) * m_aHeader.db_slng; + m_pFileStream->Seek(nPos); + return m_pFileStream->Write((char*) m_pBuffer, m_aHeader.db_slng) > 0; +} +// ----------------------------------------------------------------------------- +sal_Int32 ODbaseTable::getCurrentLastPos() const +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbase", "Ocke.Janssen@sun.com", "ODbaseTable::getCurrentLastPos" ); + return m_aHeader.db_anz; +} diff --git a/connectivity/source/drivers/dbase/DTables.cxx b/connectivity/source/drivers/dbase/DTables.cxx new file mode 100644 index 000000000000..ad89446c3916 --- /dev/null +++ b/connectivity/source/drivers/dbase/DTables.cxx @@ -0,0 +1,144 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_connectivity.hxx" +#include "dbase/DTables.hxx" +#include "dbase/DTable.hxx" +#include <com/sun/star/sdbc/XRow.hpp> +#include <com/sun/star/sdbc/XResultSet.hpp> +#include <com/sun/star/sdbc/ColumnValue.hpp> +#include <com/sun/star/sdbc/KeyRule.hpp> +#include <com/sun/star/sdbcx/KeyType.hpp> +#include "file/FCatalog.hxx" +#include "file/FConnection.hxx" +#include <com/sun/star/lang/XUnoTunnel.hpp> +#include "dbase/DCatalog.hxx" +#include <comphelper/types.hxx> +#include "resource/dbase_res.hrc" +#include "connectivity/dbexception.hxx" + +using namespace ::comphelper; +using namespace connectivity; +using namespace connectivity::dbase; +using namespace connectivity::file; +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::lang; +using namespace ::com::sun::star::container; +namespace starutil = ::com::sun::star::util; + +sdbcx::ObjectType ODbaseTables::createObject(const ::rtl::OUString& _rName) +{ + ::rtl::OUString aName,aSchema; + ODbaseTable* pRet = new ODbaseTable(this,(ODbaseConnection*)static_cast<OFileCatalog&>(m_rParent).getConnection(), + _rName,::rtl::OUString::createFromAscii("TABLE")); + + sdbcx::ObjectType xRet = pRet; + pRet->construct(); + return xRet; +} +// ------------------------------------------------------------------------- +void ODbaseTables::impl_refresh( ) throw(RuntimeException) +{ + static_cast<ODbaseCatalog*>(&m_rParent)->refreshTables(); +} +// ------------------------------------------------------------------------- +Reference< XPropertySet > ODbaseTables::createDescriptor() +{ + return new ODbaseTable(this,(ODbaseConnection*)static_cast<OFileCatalog&>(m_rParent).getConnection()); +} +typedef connectivity::sdbcx::OCollection ODbaseTables_BASE_BASE; +// ------------------------------------------------------------------------- +// XAppend +sdbcx::ObjectType ODbaseTables::appendObject( const ::rtl::OUString& _rForName, const Reference< XPropertySet >& descriptor ) +{ + Reference<XUnoTunnel> xTunnel(descriptor,UNO_QUERY); + if(xTunnel.is()) + { + ODbaseTable* pTable = reinterpret_cast< ODbaseTable* >( xTunnel->getSomething(ODbaseTable::getUnoTunnelImplementationId()) ); + if(pTable) + { + pTable->setPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_NAME),makeAny(_rForName)); + try + { + if(!pTable->CreateImpl()) + throw SQLException(); + } + catch(SQLException&) + { + throw; + } + catch(Exception&) + { + throw SQLException(); + } + } + } + return createObject( _rForName ); +} +// ------------------------------------------------------------------------- +// XDrop +void ODbaseTables::dropObject(sal_Int32 _nPos,const ::rtl::OUString _sElementName) +{ + Reference< XUnoTunnel> xTunnel; + try + { + xTunnel.set(getObject(_nPos),UNO_QUERY); + } + catch(const Exception&) + { + if(ODbaseTable::Drop_Static(ODbaseTable::getEntry(static_cast<OFileCatalog&>(m_rParent).getConnection(),_sElementName),sal_False,NULL)) + return; + } + + if ( xTunnel.is() ) + { + ODbaseTable* pTable = reinterpret_cast< ODbaseTable* >( xTunnel->getSomething(ODbaseTable::getUnoTunnelImplementationId()) ); + if(pTable) + pTable->DropImpl(); + } + else + { + const ::rtl::OUString sError( static_cast<OFileCatalog&>(m_rParent).getConnection()->getResources().getResourceStringWithSubstitution( + STR_TABLE_NOT_DROP, + "$tablename$", _sElementName + ) ); + ::dbtools::throwGenericSQLException( sError, NULL ); + } +} +// ------------------------------------------------------------------------- +Any SAL_CALL ODbaseTables::queryInterface( const Type & rType ) throw(RuntimeException) +{ + typedef sdbcx::OCollection OTables_BASE; + return OTables_BASE::queryInterface(rType); +} +// ----------------------------------------------------------------------------- + + diff --git a/connectivity/source/drivers/dbase/Dservices.cxx b/connectivity/source/drivers/dbase/Dservices.cxx new file mode 100644 index 000000000000..831329a1feba --- /dev/null +++ b/connectivity/source/drivers/dbase/Dservices.cxx @@ -0,0 +1,175 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_connectivity.hxx" +#include "dbase/DDriver.hxx" +#include <cppuhelper/factory.hxx> +#include <osl/diagnose.h> + +using namespace connectivity::dbase; +using ::rtl::OUString; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Sequence; +using ::com::sun::star::registry::XRegistryKey; +using ::com::sun::star::lang::XSingleServiceFactory; +using ::com::sun::star::lang::XMultiServiceFactory; + +typedef Reference< XSingleServiceFactory > (SAL_CALL *createFactoryFunc) + ( + const Reference< XMultiServiceFactory > & rServiceManager, + const OUString & rComponentName, + ::cppu::ComponentInstantiation pCreateFunction, + const Sequence< OUString > & rServiceNames, + rtl_ModuleCount* _pT + ); + +//*************************************************************************************** +// +// Die vorgeschriebene C-Api muss erfuellt werden! +// Sie besteht aus drei Funktionen, die von dem Modul exportiert werden muessen. +// + +//--------------------------------------------------------------------------------------- +void REGISTER_PROVIDER( + const OUString& aServiceImplName, + const Sequence< OUString>& Services, + const Reference< ::com::sun::star::registry::XRegistryKey > & xKey) +{ + OUString aMainKeyName; + aMainKeyName = OUString::createFromAscii("/"); + aMainKeyName += aServiceImplName; + aMainKeyName += OUString::createFromAscii("/UNO/SERVICES"); + + Reference< ::com::sun::star::registry::XRegistryKey > xNewKey( xKey->createKey(aMainKeyName) ); + OSL_ENSURE(xNewKey.is(), "FILE::component_writeInfo : could not create a registry key !"); + + for (sal_Int32 i=0; i<Services.getLength(); ++i) + xNewKey->createKey(Services[i]); +} + + +//--------------------------------------------------------------------------------------- +struct ProviderRequest +{ + Reference< XSingleServiceFactory > xRet; + Reference< XMultiServiceFactory > const xServiceManager; + OUString const sImplementationName; + + ProviderRequest( + void* pServiceManager, + sal_Char const* pImplementationName + ) + : xServiceManager(reinterpret_cast<XMultiServiceFactory*>(pServiceManager)) + , sImplementationName(OUString::createFromAscii(pImplementationName)) + { + } + + inline + sal_Bool CREATE_PROVIDER( + const OUString& Implname, + const Sequence< OUString > & Services, + ::cppu::ComponentInstantiation Factory, + createFactoryFunc creator + ) + { + if (!xRet.is() && (Implname == sImplementationName)) + try + { + xRet = creator( xServiceManager, sImplementationName,Factory, Services,0); + } + catch(...) + { + } + return xRet.is(); + } + + void* getProvider() const { return xRet.get(); } +}; + +//--------------------------------------------------------------------------------------- + +extern "C" SAL_DLLPUBLIC_EXPORT void SAL_CALL +component_getImplementationEnvironment( + const sal_Char **ppEnvTypeName, + uno_Environment ** /*ppEnv*/ + ) +{ + *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME; +} + +//--------------------------------------------------------------------------------------- +extern "C" SAL_DLLPUBLIC_EXPORT sal_Bool SAL_CALL component_writeInfo( + void* /*pServiceManager*/, + void* pRegistryKey + ) +{ + if (pRegistryKey) + try + { + Reference< ::com::sun::star::registry::XRegistryKey > xKey(reinterpret_cast< ::com::sun::star::registry::XRegistryKey*>(pRegistryKey)); + + REGISTER_PROVIDER( + ODriver::getImplementationName_Static(), + ODriver::getSupportedServiceNames_Static(), xKey); + + return sal_True; + } + catch (::com::sun::star::registry::InvalidRegistryException& ) + { + OSL_ENSURE(sal_False, "FILE::component_writeInfo : could not create a registry key ! ## InvalidRegistryException !"); + } + + return sal_False; +} + +//--------------------------------------------------------------------------------------- +extern "C" SAL_DLLPUBLIC_EXPORT void* SAL_CALL component_getFactory( + const sal_Char* pImplementationName, + void* pServiceManager, + void* /*pRegistryKey*/) +{ + void* pRet = 0; + if (pServiceManager) + { + ProviderRequest aReq(pServiceManager,pImplementationName); + + aReq.CREATE_PROVIDER( + ODriver::getImplementationName_Static(), + ODriver::getSupportedServiceNames_Static(), + ODriver_CreateInstance, ::cppu::createSingleFactory) + ; + + if(aReq.xRet.is()) + aReq.xRet->acquire(); + + pRet = aReq.getProvider(); + } + + return pRet; +}; + diff --git a/connectivity/source/drivers/dbase/dbase.mxp.map b/connectivity/source/drivers/dbase/dbase.mxp.map new file mode 100644 index 000000000000..c5b4377b04c3 --- /dev/null +++ b/connectivity/source/drivers/dbase/dbase.mxp.map @@ -0,0 +1,173 @@ +component_getImplementationEnvironment +component_writeInfo +component_getFactory +__mh_dylib_header +___builtin_delete +___builtin_vec_delete +___builtin_vec_new +___check_eh_spec +___cp_pop_exception +___cp_push_exception +___eh_alloc +___get_eh_context +___pure_virtual +___rtti_class +___rtti_si +___rtti_user +___sjthrow +___start_cp_handler +___terminate +_terminate__Fv +dyld_stub_binding_helper +rest_world +save_world +___builtin_new +___eh_rtime_match +___tf9bad_alloc +__._10bad_typeid +__._8bad_cast +___get_eh_info +___is_pointer__FPv +___throw_type_match_rtti +___vt_10bad_typeid +___vt_8bad_cast +__keymgr_get_per_thread_data +__keymgr_set_per_thread_data +___tf9exception +___ti9exception +___vt_9exception +_what__C9exception +__._9bad_alloc +___vt_9bad_alloc +__._9type_info +___eq__C9type_infoRCB0 +___tf16__user_type_info +___tf9type_info +___ti9type_info +___vt_9type_info +_getPropertySetInfo__Q312connectivity5dbase15ODbaseResultSet +_release__Q312connectivity5dbase15ODbaseResultSet +_acquire__Q312connectivity5dbase15ODbaseResultSet +__._Q312connectivity5dbase15ODbaseResultSet +__._Q312connectivity5dbase15ODbaseStatement +__._Q312connectivity5dbase23ODbasePreparedStatement +_IsText__Q312connectivity5dbase7ONDXKeyl +_Write__CQ312connectivity5dbase8ONDXNodeR8SvStreamRCQ312connectivity5dbase8ONDXPage +_Read__Q312connectivity5dbase8ONDXNodeR8SvStreamRQ312connectivity5dbase11ODbaseIndex +_Merge__Q312connectivity5dbase8ONDXPageUsGQ312connectivity5dbase11ONDXPagePtr +_Remove__Q312connectivity5dbase8ONDXPageUs +_SearchAndReplace__Q312connectivity5dbase8ONDXPageRCQ312connectivity5dbase7ONDXKeyRB1 +_Search__Q312connectivity5dbase8ONDXPageRCQ312connectivity5dbase7ONDXKey +_FindPos__CQ312connectivity5dbase8ONDXPageRCQ312connectivity5dbase7ONDXKey +_ReleaseFull__Q312connectivity5dbase8ONDXPageUc +_Append__Q312connectivity5dbase8ONDXPageRQ312connectivity5dbase8ONDXNode +_Split__Q312connectivity5dbase8ONDXPageRB0 +_Insert__Q312connectivity5dbase8ONDXPageUsRQ312connectivity5dbase8ONDXNode +_IsFull__CQ312connectivity5dbase8ONDXPage +___vc__CQ312connectivity5dbase8ONDXPageUs +___ls__Q212connectivity5dbaseR8SvStreamRCQ312connectivity5dbase8ONDXPage +__._Q312connectivity5dbase8ONDXPage +_GetFirstKey__Q312connectivity5dbase14OIndexIteratorPQ312connectivity5dbase8ONDXPageRCQ312connectivity4file8OOperand +_GetCompare__Q312connectivity5dbase14OIndexIteratorUc +_GetLike__Q312connectivity5dbase14OIndexIteratorUc +_GetNull__Q312connectivity5dbase14OIndexIteratorUc +_GetNotNull__Q312connectivity5dbase14OIndexIteratorUc +_GetNextKey__Q312connectivity5dbase14OIndexIterator +_Find__Q312connectivity5dbase14OIndexIteratorUc +_refreshTables__Q312connectivity5dbase13ODbaseCatalog +__._Q312connectivity5dbase18UStringDescription +___Q312connectivity5dbase18UStringDescriptionPFv_PCc +__._Q312connectivity5dbase11ODbaseIndex +_release__Q312connectivity5dbase11ODbaseIndex +_acquire__Q312connectivity5dbase11ODbaseIndex +_createINFEntry__Q312connectivity5dbase11ODbaseIndex +_getEntry__Q312connectivity5dbase11ODbaseIndex +___ls__Q212connectivity5dbaseR8SvStreamRQ312connectivity5dbase11ODbaseIndex +_Release__Q312connectivity5dbase11ODbaseIndexUc +_ConvertToKey__Q312connectivity5dbase11ODbaseIndexPQ312connectivity5dbase7ONDXKeyUlRCQ312connectivity4file12ORowSetValue +_openIndexFile__Q312connectivity5dbase11ODbaseIndex +__._Q312connectivity5dbase11ODbaseTable +_WriteMemo__Q312connectivity5dbase11ODbaseTableRQ312connectivity4file12ORowSetValueRUl +_isUniqueByColumnName__Q312connectivity5dbase11ODbaseTableRCQ23rtl8OUString +_WriteBuffer__Q312connectivity5dbase11ODbaseTable +_UpdateBuffer__Q312connectivity5dbase11ODbaseTableRQ312connectivity4file12OValueVectorGQ23vost4ORef1ZB1RCQ53com3sun4star3unot9Reference1ZQ53com3sun4star9container12XIndexAccess +_CreateMemoFile__Q312connectivity5dbase11ODbaseTableRC13INetURLObject +_CreateFile__Q312connectivity5dbase11ODbaseTableRC13INetURLObjectRUc +_ReadMemo__Q312connectivity5dbase11ODbaseTableUlRQ312connectivity4file12ORowSetValue +_refreshIndexes__Q312connectivity5dbase11ODbaseTable +_refreshColumns__Q312connectivity5dbase11ODbaseTable +_AllocBuffer__Q312connectivity5dbase11ODbaseTable +_fillColumns__Q312connectivity5dbase11ODbaseTable +_ReadMemoHeader__Q312connectivity5dbase11ODbaseTable +_readHeader__Q312connectivity5dbase11ODbaseTable +_getPropertySetInfo__Q312connectivity4file26ODatabaseMetaDataResultSet +_release__Q312connectivity4file26ODatabaseMetaDataResultSet +_acquire__Q312connectivity4file26ODatabaseMetaDataResultSet +_getPropertySetInfo__Q312connectivity4file10OResultSet +_release__Q312connectivity4file10OResultSet +_acquire__Q312connectivity4file10OResultSet +_scanParameter__Q312connectivity4file10OResultSetPQ212connectivity13OSQLParseNodeRQ24_STLt6vector2ZPB1ZQ24_STLt9allocator1ZPB1 +_AddParameter__Q312connectivity4file10OResultSetPQ212connectivity13OSQLParseNodeRCQ53com3sun4star3unot9Reference1ZQ53com3sun4star5beans12XPropertySet +_SetAssignValue__Q312connectivity4file10OResultSetRC6Stringn1UcUl +_ParseAssignValues__Q312connectivity4file10OResultSetRCQ24_STLt6vector2Z6StringZQ24_STLt9allocator1ZB2PQ212connectivity13OSQLParseNodeUs +_getUnoTunnelImplementationId__Q312connectivity4file10OResultSet +_setOrderbyColumn__Q312connectivity4file10OResultSetUsPQ212connectivity13OSQLParseNoden1 +_CreateKeySet__Q312connectivity4file14OFILESortIndex +___Q312connectivity4file14OFILESortIndexPCQ312connectivity4file8OKeyTypePCUclUs +_anylizeSQL__Q312connectivity4file10OResultSet +_GetAssignValues__Q312connectivity4file10OResultSet +_moveAbsolute__Q312connectivity4file10OResultSetlUc +_ExecuteRow__Q312connectivity4file10OResultSetQ412connectivity4file10OFileTable12FilePositionlUcn2 +_AddKeyValue__Q312connectivity4file14OFILESortIndexPQ312connectivity4file13OFILEKeyValue +_GetOrderbyKeyValue__Q312connectivity4file10OResultSetGQ23vost4ORef1ZQ312connectivity4file12OValueVector +_evaluate__Q312connectivity4file10OResultSet +_SkipDeleted__Q312connectivity4file10OResultSetQ412connectivity4file10OFileTable12FilePositionlUc +__._Q312connectivity4file14OFILESortIndex +_construct__Q312connectivity4file10OResultSet +_isCount__CQ312connectivity4file10OResultSet +__._Q312connectivity4file18UStringDescription +___Q312connectivity4file18UStringDescriptionPFv_PCc +_disposing__Q312connectivity4file15OStatement_Base +_acquire__Q312connectivity4file15OStatement_Base +__._Q312connectivity4file16OStatement_BASE2 +__._Q312connectivity4file10OStatement +_disposeResultSet__Q312connectivity4file15OStatement_Base +_getImplementationName_Static__Q312connectivity4file11OFileDriver +_operate__CQ312connectivity4file8OOp_LIKEPCQ312connectivity4file8OOperandn1 +_operate__CQ312connectivity4file10OOp_ISNULLPCQ312connectivity4file8OOperandn1 +_IsOf__Q312connectivity4file12ONumOperatorPFv_Pv +_StaticType__Q312connectivity4file12ONumOperator +_IsOf__Q312connectivity4file11OOp_COMPAREPFv_Pv +_IsOf__Q312connectivity4file11OOp_NOTLIKEPFv_Pv +_StaticType__Q312connectivity4file11OOp_NOTLIKE +_IsOf__Q312connectivity4file8OOp_LIKEPFv_Pv +_IsOf__Q312connectivity4file13OOp_ISNOTNULLPFv_Pv +_IsOf__Q312connectivity4file10OOp_ISNULLPFv_Pv +_IsOf__Q312connectivity4file6OOp_ORPFv_Pv +_StaticType__Q312connectivity4file6OOp_OR +_IsOf__Q312connectivity4file7OOp_ANDPFv_Pv +_StaticType__Q312connectivity4file7OOp_AND +_IsOf__Q312connectivity4file13OBoolOperatorPFv_Pv +_IsOf__Q312connectivity4file9OOperatorPFv_Pv +_IsOf__Q312connectivity4file14OOperandResultPFv_Pv +_IsOf__Q312connectivity4file13OOperandConstPFv_Pv +_IsOf__Q312connectivity4file13OOperandValuePFv_Pv +_StaticType__Q312connectivity4file13OOperandValue +_IsOf__Q312connectivity4file13OOperandParamPFv_Pv +_IsOf__Q312connectivity4file16OFILEOperandAttrPFv_Pv +_StaticType__Q312connectivity4file16OFILEOperandAttr +_IsOf__Q312connectivity4file12OOperandAttrPFv_Pv +_IsOf__Q312connectivity4file11OOperandRowPFv_Pv +_StaticType__Q312connectivity4file11OOperandRow +_IsOf__Q312connectivity4file8OOperandPFv_Pv +_IsOf__Q312connectivity4file5OCodePFv_Pv +_StaticType__Q312connectivity4file5OCode +_execute_Operand__Q312connectivity4file18OPredicateCompilerPQ212connectivity13OSQLParseNode +_execute_ISNULL__Q312connectivity4file18OPredicateCompilerPQ212connectivity13OSQLParseNode +_execute_LIKE__Q312connectivity4file18OPredicateCompilerPQ212connectivity13OSQLParseNode +_execute_COMPARE__Q312connectivity4file18OPredicateCompilerPQ212connectivity13OSQLParseNode +___tf13bad_exception +___uncatch_exception +___eh_free +___tfv +___dynamic_cast diff --git a/connectivity/source/drivers/dbase/dbase.xcu b/connectivity/source/drivers/dbase/dbase.xcu new file mode 100755 index 000000000000..f5de1d53ab0e --- /dev/null +++ b/connectivity/source/drivers/dbase/dbase.xcu @@ -0,0 +1,100 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!--*********************************************************************** + * + * 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. + * + ************************************************************************ --> +<oor:component-data oor:name="Drivers" oor:package="org.openoffice.Office.DataAccess" xmlns:oor="http://openoffice.org/2001/registry" xmlns:xs="http://www.w3.org/2001/XMLSchema"> + <node oor:name="Installed"> + <node oor:name="sdbc:dbase:*" oor:op="replace"> + <prop oor:name="Driver"> + <value>com.sun.star.comp.sdbc.dbase.ODriver</value> + </prop> + <prop oor:name="DriverTypeDisplayName" oor:type="xs:string"> + <value xml:lang="en-US">dBASE</value> + </prop> + <node oor:name="Properties"> + <node oor:name="CharSet" oor:op="replace"> + <prop oor:name="Value" oor:type="xs:string"> + <value></value> + </prop> + </node> + <node oor:name="ShowDeleted" oor:op="replace"> + <prop oor:name="Value" oor:type="xs:boolean"> + <value>false</value> + </prop> + </node> + <node oor:name="EnableSQL92Check" oor:op="replace"> + <prop oor:name="Value" oor:type="xs:boolean"> + <value>false</value> + </prop> + </node> + <node oor:name="AddIndexAppendix" oor:op="replace"> + <prop oor:name="Value" oor:type="xs:boolean"> + <value>false</value> + </prop> + </node> + </node> + <node oor:name="Features"> + <node oor:name="UseSQL92NamingConstraints" oor:op="replace"> + <prop oor:name="Value" oor:type="xs:boolean"> + <value>true</value> + </prop> + </node> + <node oor:name="UseDOSLineEnds" oor:op="replace"> + <prop oor:name="Value" oor:type="xs:boolean"> + <value>true</value> + </prop> + </node> + <node oor:name="EscapeDateTime" oor:op="replace"> + <prop oor:name="Value" oor:type="xs:boolean"> + <value>true</value> + </prop> + </node> + </node> + <node oor:name="MetaData"> + <node oor:name="SupportsTableCreation" oor:op="replace"> + <prop oor:name="Value" oor:type="xs:boolean"> + <value>true</value> + </prop> + </node> + <node oor:name="SupportsBrowsing" oor:op="replace"> + <prop oor:name="Value" oor:type="xs:boolean"> + <value>true</value> + </prop> + </node> + <node oor:name="FileSystemBased" oor:op="replace"> + <prop oor:name="Value" oor:type="xs:boolean"> + <value>true</value> + </prop> + </node> + <node oor:name="MediaType" oor:op="replace"> + <prop oor:name="Value" oor:type="xs:string"> + <value>application/dbase</value> + </prop> + </node> + </node> + </node> + </node> +</oor:component-data> diff --git a/connectivity/source/drivers/dbase/dbase.xml b/connectivity/source/drivers/dbase/dbase.xml new file mode 100644 index 000000000000..b2a1bc2b803c --- /dev/null +++ b/connectivity/source/drivers/dbase/dbase.xml @@ -0,0 +1,33 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE module-description PUBLIC "-//W3C//DTD HTML 3.2//EN" "module-description.dtd"> +<module-description> + <module-name>file</module-name> + <component-description> + <author>Ocke Jannsen</author> + <name>com.sun.star.comp.sdbc.dbase.ODriver</name> + <description>This library implements the database driver for dBase file format. +</description> + <loader-name>com.sun.star.loader.SharedLibrary</loader-name> + <language>c++</language> + <status value="final"/> + <supported-service>com.sun.star.sdbc.Driver</supported-service> + <supported-service>com.sun.star.sdbcx.Driver</supported-service> + <service-dependency> ... </service-dependency> + </component-description> + <project-build-dependency>cppuhelper</project-build-dependency> + <project-build-dependency>cppu</project-build-dependency> + <project-build-dependency>sal</project-build-dependency> + <project-build-dependency>vos</project-build-dependency> + <runtime-module-dependency>file</runtime-module-dependency> + <runtime-module-dependency>cppuhelper</runtime-module-dependency> + <runtime-module-dependency>cppu</runtime-module-dependency> + <runtime-module-dependency>sal</runtime-module-dependency> + <runtime-module-dependency>vos</runtime-module-dependency> + <runtime-module-dependency>osl</runtime-module-dependency> + <runtime-module-dependency>svtools-light1</runtime-module-dependency> + <runtime-module-dependency>svtools</runtime-module-dependency> + <runtime-module-dependency>ucbhelper</runtime-module-dependency> + <runtime-module-dependency>dbtools</runtime-module-dependency> + <runtime-module-dependency>unotools</runtime-module-dependency> + <runtime-module-dependency>comphelper</runtime-module-dependency> +</module-description> diff --git a/connectivity/source/drivers/dbase/dindexnode.cxx b/connectivity/source/drivers/dbase/dindexnode.cxx new file mode 100644 index 000000000000..9a8905b6a6ba --- /dev/null +++ b/connectivity/source/drivers/dbase/dindexnode.cxx @@ -0,0 +1,1056 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_connectivity.hxx" +#include "dbase/dindexnode.hxx" +#include "connectivity/CommonTools.hxx" +#include <osl/thread.h> +#include "dbase/DIndex.hxx" +#include <tools/debug.hxx> +#include "diagnose_ex.h" + +#include <algorithm> + + +using namespace connectivity; +using namespace connectivity::dbase; +using namespace connectivity::file; +using namespace com::sun::star::sdbc; +// ----------------------------------------------------------------------------- +ONDXKey::ONDXKey(UINT32 nRec) + :nRecord(nRec) +{ +} +// ----------------------------------------------------------------------------- +ONDXKey::ONDXKey(const ORowSetValue& rVal, sal_Int32 eType, UINT32 nRec) + : ONDXKey_BASE(eType) + , nRecord(nRec) + , xValue(rVal) +{ +} +// ----------------------------------------------------------------------------- +ONDXKey::ONDXKey(const rtl::OUString& aStr, UINT32 nRec) + : ONDXKey_BASE(::com::sun::star::sdbc::DataType::VARCHAR) + ,nRecord(nRec) +{ + if (aStr.getLength()) + { + xValue = aStr; + xValue.setBound(sal_True); + } +} +// ----------------------------------------------------------------------------- + +ONDXKey::ONDXKey(double aVal, UINT32 nRec) + : ONDXKey_BASE(::com::sun::star::sdbc::DataType::DOUBLE) + ,nRecord(nRec) + ,xValue(aVal) +{ +} +// ----------------------------------------------------------------------------- + +//================================================================== +// Index Seite +//================================================================== +ONDXPage::ONDXPage(ODbaseIndex& rInd, sal_uInt32 nPos, ONDXPage* pParent) + :nPagePos(nPos) + ,bModified(FALSE) + ,nCount(0) + ,aParent(pParent) + ,rIndex(rInd) + ,ppNodes(NULL) +{ + sal_uInt16 nT = rIndex.getHeader().db_maxkeys; + ppNodes = new ONDXNode[nT]; +} + +//------------------------------------------------------------------ +ONDXPage::~ONDXPage() +{ + delete[] ppNodes; + // delete aParent; + // delete aChild; +} +//------------------------------------------------------------------ +void ONDXPage::QueryDelete() +{ + // Ablegen im GarbageCollector + if (IsModified() && rIndex.m_pFileStream) + (*rIndex.m_pFileStream) << *this; + + bModified = FALSE; + if (rIndex.UseCollector()) + { + if (aChild.Is()) + aChild->Release(FALSE); + + for (USHORT i = 0; i < rIndex.getHeader().db_maxkeys;i++) + { + if (ppNodes[i].GetChild().Is()) + ppNodes[i].GetChild()->Release(FALSE); + + ppNodes[i] = ONDXNode(); + } + RestoreNoDelete(); + + nCount = 0; + aParent.Clear(); + rIndex.Collect(this); + } + else + SvRefBase::QueryDelete(); +} +//------------------------------------------------------------------ +ONDXPagePtr& ONDXPage::GetChild(ODbaseIndex* pIndex) +{ + if (!aChild.Is() && pIndex) + { + aChild = rIndex.CreatePage(aChild.GetPagePos(),this,aChild.HasPage()); + } + return aChild; +} + +//------------------------------------------------------------------ +USHORT ONDXPage::FindPos(const ONDXKey& rKey) const +{ + // sucht nach Platz fuer den vorgegeben key auf einer Seite + USHORT i = 0; + while (i < nCount && rKey > ((*this)[i]).GetKey()) + i++; + + return i; +} + +//------------------------------------------------------------------ +BOOL ONDXPage::Find(const ONDXKey& rKey) +{ + // sucht den vorgegeben key + // Besonderheit: gelangt der Algorithmus ans Ende + // wird immer die aktuelle Seite und die Knotenposition vermerkt + // auf die die Bedingung <= zutrifft + // dieses findet beim Insert besondere Beachtung + USHORT i = 0; + while (i < nCount && rKey > ((*this)[i]).GetKey()) + i++; + + BOOL bResult = FALSE; + + if (!IsLeaf()) + { + // weiter absteigen + ONDXPagePtr aPage = (i==0) ? GetChild(&rIndex) : ((*this)[i-1]).GetChild(&rIndex, this); + bResult = aPage.Is() && aPage->Find(rKey); + } + else if (i == nCount) + { + rIndex.m_aCurLeaf = this; + rIndex.m_nCurNode = i - 1; + bResult = FALSE; + } + else + { + bResult = rKey == ((*this)[i]).GetKey(); + rIndex.m_aCurLeaf = this; + rIndex.m_nCurNode = bResult ? i : i - 1; + } + return bResult; +} + +//------------------------------------------------------------------ +BOOL ONDXPage::Insert(ONDXNode& rNode, sal_uInt32 nRowsLeft) +{ + // beim Erzeugen eines Index koennen auch mehrere Knoten eingefuegt werden + // diese sin dann aufsteigend sortiert + BOOL bAppend = nRowsLeft > 0; + if (IsFull()) + { + BOOL bResult = TRUE; + ONDXNode aSplitNode; + if (bAppend) + aSplitNode = rNode; + else + { + // merken des letzten Knotens + aSplitNode = (*this)[nCount-1]; + if(rNode.GetKey() <= aSplitNode.GetKey()) + { + + // und damit habe ich im folgenden praktisch eine Node weniger + if (IsLeaf() && this == &rIndex.m_aCurLeaf) + { + // geht davon aus, dass der Knoten, auf dem die Bedingung (<=) + // zutrifft, als m_nCurNode gesetzt ist + --nCount; // (sonst bekomme ich u.U. Assertions und GPFs - 60593) + bResult = Insert(rIndex.m_nCurNode + 1, rNode); + } + else // Position unbekannt + { + USHORT nPos = NODE_NOTFOUND; + while (++nPos < nCount && rNode.GetKey() > ((*this)[nPos]).GetKey()) ; + + --nCount; // (sonst bekomme ich u.U. Assertions und GPFs - 60593) + bResult = Insert(nPos, rNode); + } + + // konnte der neue Knoten eingefuegt werden + if (!bResult) + { + nCount++; + aSplitNode = rNode; + } + } + else + aSplitNode = rNode; + } + + sal_uInt32 nNewPagePos = rIndex.GetPageCount(); + sal_uInt32 nNewPageCount = nNewPagePos + 1; + + // Herausgeloesten Knoten beim Vater einfuegen + if (!HasParent()) + { + // Kein Vater, dann neue Wurzel + ONDXPagePtr aNewRoot = rIndex.CreatePage(nNewPagePos + 1); + aNewRoot->SetChild(this); + + rIndex.m_aRoot = aNewRoot; + rIndex.SetRootPos(nNewPagePos + 1); + rIndex.SetPageCount(++nNewPageCount); + } + + // neues blatt erzeugen und Seite aufteilen + ONDXPagePtr aNewPage = rIndex.CreatePage(nNewPagePos,aParent); + rIndex.SetPageCount(nNewPageCount); + + // wieviele Knoten weren noch eingefuegt + // kommen noch ausreichend, dann koennen die Seiten bis zum Rand vollgestopft werden + + ONDXNode aInnerNode; + if (!IsLeaf() || nRowsLeft < (sal_uInt32)(rIndex.GetMaxNodes() / 2)) + aInnerNode = Split(*aNewPage); + else + { + aInnerNode = (*this)[nCount - 1]; + //aInnerNode = aSplitNode; + + // Knoten zeigt auf neue Seite + aInnerNode.SetChild(aNewPage); + + // innere Knoten haben keine Recordnummer + if (rIndex.isUnique()) + aInnerNode.GetKey().ResetRecord(); + + // neue Seite zeigt nun auf Seite des herausgeloesten Knoten + if (!IsLeaf()) + aNewPage->SetChild(aInnerNode.GetChild()); + } + + aNewPage->Append(aSplitNode); + ONDXPagePtr aTempParent = aParent; + if (IsLeaf()) + { + rIndex.m_aCurLeaf = aNewPage; + rIndex.m_nCurNode = rIndex.m_aCurLeaf->Count() - 1; + + // Freigeben nicht benoetigter Seiten, danach besteht keine Referenz + // mehr auf die Seite, danach kann 'this' nicht mehr gueltig sein!!! + ReleaseFull(); + } + + // Einfuegen des herausgeloesten Knotens + return aTempParent->Insert(aInnerNode); + } + else // Seite einfach weiter auffuellen + { + if (bAppend) + { + if (IsLeaf()) + rIndex.m_nCurNode = nCount - 1; + return Append(rNode); + } + else + { + USHORT nNodePos = FindPos(rNode.GetKey()); + if (IsLeaf()) + rIndex.m_nCurNode = nNodePos; + + return Insert(nNodePos, rNode); + } + } +} + +//------------------------------------------------------------------ +BOOL ONDXPage::Insert(USHORT nPos, ONDXNode& rNode) +{ + USHORT nMaxCount = rIndex.getHeader().db_maxkeys; + if (nPos >= nMaxCount) + return FALSE; + + if (nCount) + { + ++nCount; + // nach rechts verschieben + for (USHORT i = std::min((USHORT)(nMaxCount-1), (USHORT)(nCount-1)); nPos < i; --i) + (*this)[i] = (*this)[i-1]; + } + else + if (nCount < nMaxCount) + nCount++; + + // einfuegen an der Position + ONDXNode& rInsertNode = (*this)[nPos]; + rInsertNode = rNode; + if (rInsertNode.GetChild().Is()) + { + rInsertNode.GetChild()->SetParent(this); + rNode.GetChild()->SetParent(this); + } + + bModified = TRUE; + + return TRUE; +} + +//------------------------------------------------------------------ +BOOL ONDXPage::Append(ONDXNode& rNode) +{ + DBG_ASSERT(!IsFull(), "kein Append moeglich"); + return Insert(nCount, rNode); +} +//------------------------------------------------------------------ +void ONDXPage::Release(BOOL bSave) +{ + // freigeben der Pages + if (aChild.Is()) + aChild->Release(bSave); + + // Pointer freigeben + aChild.Clear(); + + for (USHORT i = 0; i < rIndex.getHeader().db_maxkeys;i++) + { + if (ppNodes[i].GetChild()) + ppNodes[i].GetChild()->Release(bSave); + + ppNodes[i].GetChild().Clear(); + } + aParent = NULL; +} +//------------------------------------------------------------------ +void ONDXPage::ReleaseFull(BOOL bSave) +{ + ONDXPagePtr aTempParent = aParent; + Release(bSave); + + if (aTempParent.Is()) + { + // Freigeben nicht benoetigter Seiten, danach besteht keine Referenz + // mehr auf die Seite, danach kann 'this' nicht mehr gueltig sein!!! + USHORT nParentPos = aTempParent->Search(this); + if (nParentPos != NODE_NOTFOUND) + (*aTempParent)[nParentPos].GetChild().Clear(); + else + aTempParent->GetChild().Clear(); + } +} +//------------------------------------------------------------------ +BOOL ONDXPage::Delete(USHORT nNodePos) +{ + if (IsLeaf()) + { + // Letztes Element wird geloescht + if (nNodePos == (nCount - 1)) + { + ONDXNode aNode = (*this)[nNodePos]; + + // beim Parent muss nun der KeyValue ausgetauscht werden + if (HasParent()) + aParent->SearchAndReplace(aNode.GetKey(), + (*this)[nNodePos-1].GetKey()); + } + } + + // Loeschen des Knoten + Remove(nNodePos); + + // Unterlauf + if (HasParent() && nCount < (rIndex.GetMaxNodes() / 2)) + { + // Feststellen, welcher Knoten auf die Seite zeigt + USHORT nParentNodePos = aParent->Search(this); + // letzte Element auf Vaterseite + // -> zusammenlegen mit vorletzter Seite + if (nParentNodePos == (aParent->Count() - 1)) + { + if (!nParentNodePos) + // zusammenlegen mit linken nachbarn + Merge(nParentNodePos,aParent->GetChild(&rIndex)); + else + Merge(nParentNodePos,(*aParent)[nParentNodePos-1].GetChild(&rIndex,aParent)); + } + // sonst Seite mit naechster Seite zusammenlegen + else + { + // zusammenlegen mit rechten nachbarn + Merge(nParentNodePos + 1,((*aParent)[nParentNodePos + 1].GetChild(&rIndex,aParent))); + nParentNodePos++; + } + if (HasParent() && !(*aParent)[nParentNodePos].HasChild()) + aParent->Delete(nParentNodePos); +/* + // letzte Element auf Vaterseite + // -> zusammenlegen mit vorletzter Seite + if (nParentNodePos == (aParent->Count() - 1)) + { + if (!nParentNodePos) + // zusammenlegen mit linken nachbarn + Merge(nParentNodePos,aParent->GetChild(&rIndex)); + else + Merge(nParentNodePos,(*aParent)[nParentNodePos-1].GetChild(&rIndex,aParent)); + } + // sonst Seite mit naechster Seite zusammenlegen + else if(nParentNodePos != NODE_NOTFOUND) + { + // zusammenlegen mit rechten nachbarn + Merge(nParentNodePos + 1,((*aParent)[nParentNodePos + 1].GetChild(&rIndex,aParent))); + nParentNodePos++; + } + else // Sonderbehandlung + { + // Page ist aChild Page vom Parent => erste Page aus ppNodes an aChild anhaengen + Merge(0,(*aParent)[0].GetChild(&rIndex,aParent)); + nParentNodePos = 0; + } + + if (HasParent() && !(*aParent)[nParentNodePos].HasChild()) + aParent->Delete(nParentNodePos); +*/ + + } + else if (IsRoot()) + // Sicherstellen das die Position der Wurzel festgehalten wird + rIndex.SetRootPos(nPagePos); + return TRUE; +} + + +//------------------------------------------------------------------ +ONDXNode ONDXPage::Split(ONDXPage& rPage) +{ + DBG_ASSERT(IsFull(), "Falsches Splitting"); + /* Aufteilen einer Seite auf zwei + Blatt: + Seite 1 behaelt (n - (n/2)) + Seite 2 erhaelt (n/2) + Knoten n/2 wird dupliziert + Innerer Knoten: + Seite 1 behaelt (n+1)/2 + Seite 2 erhaelt (n/2-1) + Knoten ((n+1)/2 + 1) : wird herausgenommen + */ + ONDXNode aResultNode; + if (IsLeaf()) + { + for (USHORT i = (nCount - (nCount / 2)), j = 0 ; i < nCount; i++) + rPage.Insert(j++,(*this)[i]); + + // dieser Knoten enthaelt einen Schluessel der noch einmal im Tree vorkommt + // und ersetzt werden muss + ONDXNode aLastNode = (*this)[nCount - 1]; + nCount = nCount - (nCount / 2); + aResultNode = (*this)[nCount - 1]; + + if (HasParent()) + aParent->SearchAndReplace(aLastNode.GetKey(), + aResultNode.GetKey()); + } + else + { + for (USHORT i = (nCount + 1) / 2 + 1, j = 0 ; i < nCount; i++) + rPage.Insert(j++,(*this)[i]); + + aResultNode = (*this)[(nCount + 1) / 2]; + nCount = (nCount + 1) / 2; + + // neue Seite zeigt nun auf Seite des herausgeloesten Knoten + rPage.SetChild(aResultNode.GetChild()); + } + // Knoten zeigt auf neue Seite + aResultNode.SetChild(&rPage); + + // innere Knoten haben keine Recordnummer + if (rIndex.isUnique()) + aResultNode.GetKey().ResetRecord(); + bModified = TRUE; + return aResultNode; +} + +//------------------------------------------------------------------ +void ONDXPage::Merge(USHORT nParentNodePos, ONDXPagePtr xPage) +{ + DBG_ASSERT(HasParent(), "kein Vater vorhanden"); + DBG_ASSERT(nParentNodePos != NODE_NOTFOUND, "Falscher Indexaufbau"); + + /* Zusammenlegen zweier Seiten */ + ONDXNode aResultNode; + USHORT nMaxNodes = rIndex.GetMaxNodes(), + nMaxNodes_2 = nMaxNodes / 2; + + // Feststellen ob Seite rechter oder linker Nachbar + BOOL bRight = ((*xPage)[0].GetKey() > (*this)[0].GetKey()); // TRUE, wenn xPage die rechte Seite ist + USHORT nNewCount = (*xPage).Count() + Count(); + + if (IsLeaf()) + { + // Bedingung fuers zusammenlegen + if (nNewCount < (nMaxNodes_2 * 2)) + { + USHORT nLastNode = bRight ? Count() - 1 : xPage->Count() - 1; + if (bRight) + { + DBG_ASSERT(&xPage != this,"xPage und THIS duerfen nicht gleich sein: Endlosschleife"); + // alle Knoten aus xPage auf den linken Knoten verschieben (anhaengen) + while (xPage->Count()) + { + Append((*xPage)[0]); + xPage->Remove(0); + } + } + else + { + DBG_ASSERT(&xPage != this,"xPage und THIS duerfen nicht gleich sein: Endlosschleife"); + // xPage ist die linke Page und THIS die rechte + while (xPage->Count()) + { + Insert(0,(*xPage)[xPage->Count()-1]); + xPage->Remove(xPage->Count()-1); + } + // alte Position von xPage beim Parent mit this ersetzen + if (nParentNodePos) + (*aParent)[nParentNodePos-1].SetChild(this,aParent); + else // oder als rechten Knoten setzen + aParent->SetChild(this); + aParent->SetModified(TRUE); + + } + + // Child beziehung beim Vaterknoten aufheben + (*aParent)[nParentNodePos].SetChild(); + // Austauschen des KnotenWertes, nur wenn geaenderte Page + // die linke ist, ansonsten werde + + if(aParent->IsRoot() && aParent->Count() == 1) + { + (*aParent)[0].SetChild(); + aParent->ReleaseFull(); + aParent = NULL; + rIndex.SetRootPos(nPagePos); + rIndex.m_aRoot = this; + SetModified(TRUE); + } + else + aParent->SearchAndReplace((*this)[nLastNode].GetKey(),(*this)[nCount-1].GetKey()); + + xPage->SetModified(FALSE); + xPage->ReleaseFull(); // wird nicht mehr benoetigt + } + // Ausgleichen der Elemente nNewCount >= (nMaxNodes_2 * 2) + else + { + if (bRight) + { + // alle Knoten aus xPage auf den linken Knoten verschieben (anhaengen) + ONDXNode aReplaceNode = (*this)[nCount - 1]; + while (nCount < nMaxNodes_2) + { + Append((*xPage)[0]); + xPage->Remove(0); + } + // Austauschen des KnotenWertes: Setzt alten letzten Wert durch den letzten von xPage + aParent->SearchAndReplace(aReplaceNode.GetKey(),(*this)[nCount-1].GetKey()); + } + else + { + // alle Knoten aus this vor die xPage Knoten einfuegen + ONDXNode aReplaceNode = (*this)[nCount - 1]; + while (xPage->Count() < nMaxNodes_2) + { + xPage->Insert(0,(*this)[nCount-1]); + Remove(nCount-1); + } + // Austauschen des KnotenWertes + aParent->SearchAndReplace(aReplaceNode.GetKey(),(*this)[Count()-1].GetKey()); + } + } + } + else // !IsLeaf() + { + // Bedingung fuers zusammenlegen + if (nNewCount < nMaxNodes_2 * 2) + { + if (bRight) + { + DBG_ASSERT(&xPage != this,"xPage und THIS duerfen nicht gleich sein: Endlosschleife"); + // Vaterknoten wird mit integriert + // erhaelt zunaechst Child von xPage + (*aParent)[nParentNodePos].SetChild(xPage->GetChild(),aParent); + Append((*aParent)[nParentNodePos]); + for (USHORT i = 0 ; i < xPage->Count(); i++) + Append((*xPage)[i]); + } + else + { + DBG_ASSERT(&xPage != this,"xPage und THIS duerfen nicht gleich sein: Endlosschleife"); + // Vaterknoten wird mit integriert + // erhaelt zunaechst Child + (*aParent)[nParentNodePos].SetChild(GetChild(),aParent); // Parent merkt sich mein Child + Insert(0,(*aParent)[nParentNodePos]); // Node vom Parent bei mir einfuegen + while (xPage->Count()) + { + Insert(0,(*xPage)[xPage->Count()-1]); + xPage->Remove(xPage->Count()-1); + } + SetChild(xPage->GetChild()); + + if (nParentNodePos) + (*aParent)[nParentNodePos-1].SetChild(this,aParent); + else + aParent->SetChild(this); + } + + // danach wird der Vaterknoten zurueckgesetzt + (*aParent)[nParentNodePos].SetChild(); + aParent->SetModified(TRUE); + + if(aParent->IsRoot() && aParent->Count() == 1) + { + (*aParent).SetChild(); + aParent->ReleaseFull(); + aParent = NULL; + rIndex.SetRootPos(nPagePos); + rIndex.m_aRoot = this; + SetModified(TRUE); + } + else if(nParentNodePos) + // Austauschen des KnotenWertes + // beim Append wird der Bereich erweitert, beim INsert verweist der alte Knoten von xPage auf this + // deshalb muss der Knoten auch hier aktualisiert werden + aParent->SearchAndReplace((*aParent)[nParentNodePos-1].GetKey(),(*aParent)[nParentNodePos].GetKey()); + + xPage->SetModified(FALSE); + xPage->ReleaseFull(); + } + // Ausgleichen der Elemente + else + { + if (bRight) + { + while (nCount < nMaxNodes_2) + { + (*aParent)[nParentNodePos].SetChild(xPage->GetChild(),aParent); + Append((*aParent)[nParentNodePos]); + (*aParent)[nParentNodePos] = (*xPage)[0]; + xPage->Remove(0); + } + xPage->SetChild((*aParent)[nParentNodePos].GetChild()); + (*aParent)[nParentNodePos].SetChild(xPage,aParent); + } + else + { + while (nCount < nMaxNodes_2) + { + (*aParent)[nParentNodePos].SetChild(GetChild(),aParent); + Insert(0,(*aParent)[nParentNodePos]); + (*aParent)[nParentNodePos] = (*xPage)[xPage->Count()-1]; + xPage->Remove(xPage->Count()-1); + } + SetChild((*aParent)[nParentNodePos].GetChild()); + (*aParent)[nParentNodePos].SetChild(this,aParent); + + } + aParent->SetModified(TRUE); + } + } +} +//================================================================== +// ONDXNode +//================================================================== + +//------------------------------------------------------------------ +void ONDXNode::Read(SvStream &rStream, ODbaseIndex& rIndex) +{ + rStream >> aKey.nRecord; // schluessel + + if (rIndex.getHeader().db_keytype) + { + double aDbl; + rStream >> aDbl; + aKey = ONDXKey(aDbl,aKey.nRecord); + } + else + { + ByteString aBuf; + USHORT nLen = rIndex.getHeader().db_keylen; + char* pStr = aBuf.AllocBuffer(nLen+1); + + rStream.Read(pStr,nLen); + pStr[nLen] = 0; + aBuf.ReleaseBufferAccess(); + aBuf.EraseTrailingChars(); + + // aKey = ONDXKey((aBuf,rIndex.GetDBFConnection()->GetCharacterSet()) ,aKey.nRecord); + aKey = ONDXKey(::rtl::OUString(aBuf.GetBuffer(),aBuf.Len(),rIndex.m_pTable->getConnection()->getTextEncoding()) ,aKey.nRecord); + } + rStream >> aChild; +} + +union NodeData +{ + double aDbl; + char aData[128]; +} aNodeData; +//------------------------------------------------------------------ +void ONDXNode::Write(SvStream &rStream, const ONDXPage& rPage) const +{ + const ODbaseIndex& rIndex = rPage.GetIndex(); + if (!rIndex.isUnique() || rPage.IsLeaf()) + rStream << (sal_uInt32)aKey.nRecord; // schluessel + else + rStream << (sal_uInt32)0; // schluessel + + if (rIndex.getHeader().db_keytype) // double + { + if (aKey.getValue().isNull()) + { + memset(aNodeData.aData,0,rIndex.getHeader().db_keylen); + rStream.Write((BYTE*)aNodeData.aData,rIndex.getHeader().db_keylen); + } + else + rStream << (double) aKey.getValue(); + } + else + { + memset(aNodeData.aData,0x20,rIndex.getHeader().db_keylen); + if (!aKey.getValue().isNull()) + { + ::rtl::OUString sValue = aKey.getValue(); + ByteString aText(sValue.getStr(), rIndex.m_pTable->getConnection()->getTextEncoding()); + strncpy(aNodeData.aData,aText.GetBuffer(),std::min(rIndex.getHeader().db_keylen, aText.Len())); + } + rStream.Write((BYTE*)aNodeData.aData,rIndex.getHeader().db_keylen); + } + rStream << aChild; +} + + +//------------------------------------------------------------------ +ONDXPagePtr& ONDXNode::GetChild(ODbaseIndex* pIndex, ONDXPage* pParent) +{ + if (!aChild.Is() && pIndex) + { + aChild = pIndex->CreatePage(aChild.GetPagePos(),pParent,aChild.HasPage()); + } + return aChild; +} + +//================================================================== +// ONDXKey +//================================================================== +//------------------------------------------------------------------ +BOOL ONDXKey::IsText(sal_Int32 eType) +{ + return eType == DataType::VARCHAR || eType == DataType::CHAR; +} + +//------------------------------------------------------------------ +StringCompare ONDXKey::Compare(const ONDXKey& rKey) const +{ + // DBG_ASSERT(is(), "Falscher Indexzugriff"); + StringCompare eResult; + + if (getValue().isNull()) + { + if (rKey.getValue().isNull() || (rKey.IsText(getDBType()) && !rKey.getValue().getString().getLength())) + eResult = COMPARE_EQUAL; + else + eResult = COMPARE_LESS; + } + else if (rKey.getValue().isNull()) + { + if (getValue().isNull() || (IsText(getDBType()) && !getValue().getString().getLength())) + eResult = COMPARE_EQUAL; + else + eResult = COMPARE_GREATER; + } + else if (IsText(getDBType())) + { + INT32 nRes = getValue().getString().compareTo(rKey.getValue()); + eResult = (nRes > 0) ? COMPARE_GREATER : (nRes == 0) ? COMPARE_EQUAL : COMPARE_LESS; + } + else + { + double m = getValue(),n = rKey.getValue(); + eResult = (m > n) ? COMPARE_GREATER : (n == m) ? COMPARE_EQUAL : COMPARE_LESS; + } + + // Record vergleich, wenn Index !Unique + if (eResult == COMPARE_EQUAL && nRecord && rKey.nRecord) + eResult = (nRecord > rKey.nRecord) ? COMPARE_GREATER : + (nRecord == rKey.nRecord) ? COMPARE_EQUAL : COMPARE_LESS; + + return eResult; +} +// ----------------------------------------------------------------------------- +void ONDXKey::setValue(const ORowSetValue& _rVal) +{ + xValue = _rVal; +} +// ----------------------------------------------------------------------------- +const ORowSetValue& ONDXKey::getValue() const +{ + return xValue; +} +// ----------------------------------------------------------------------------- +SvStream& connectivity::dbase::operator >> (SvStream &rStream, ONDXPagePtr& rPage) +{ + rStream >> rPage.nPagePos; + return rStream; +} +// ----------------------------------------------------------------------------- +SvStream& connectivity::dbase::operator << (SvStream &rStream, const ONDXPagePtr& rPage) +{ + rStream << rPage.nPagePos; + return rStream; +} +// ----------------------------------------------------------------------------- +//================================================================== +// ONDXPagePtr +//================================================================== +//------------------------------------------------------------------ +ONDXPagePtr::ONDXPagePtr(const ONDXPagePtr& rRef) + :ONDXPageRef(rRef) + ,nPagePos(rRef.nPagePos) +{ +} + +//------------------------------------------------------------------ +ONDXPagePtr::ONDXPagePtr(ONDXPage* pRefPage) + :ONDXPageRef(pRefPage) + ,nPagePos(0) +{ + if (pRefPage) + nPagePos = pRefPage->GetPagePos(); +} +//------------------------------------------------------------------ +ONDXPagePtr& ONDXPagePtr::operator=(const ONDXPagePtr& rRef) +{ + ONDXPageRef::operator=(rRef); + nPagePos = rRef.nPagePos; + return *this; +} + +//------------------------------------------------------------------ +ONDXPagePtr& ONDXPagePtr::operator= (ONDXPage* pRef) +{ + ONDXPageRef::operator=(pRef); + nPagePos = (pRef) ? pRef->GetPagePos() : 0; + return *this; +} +// ----------------------------------------------------------------------------- +static UINT32 nValue; +//------------------------------------------------------------------ +SvStream& connectivity::dbase::operator >> (SvStream &rStream, ONDXPage& rPage) +{ + rStream.Seek(rPage.GetPagePos() * PAGE_SIZE); + rStream >> nValue >> rPage.aChild; + rPage.nCount = USHORT(nValue); + +// DBG_ASSERT(rPage.nCount && rPage.nCount < rPage.GetIndex().GetMaxNodes(), "Falscher Count"); + for (USHORT i = 0; i < rPage.nCount; i++) + rPage[i].Read(rStream, rPage.GetIndex()); + return rStream; +} + +//------------------------------------------------------------------ +SvStream& connectivity::dbase::operator << (SvStream &rStream, const ONDXPage& rPage) +{ + // Seite existiert noch nicht + ULONG nSize = (rPage.GetPagePos() + 1) * PAGE_SIZE; + if (nSize > rStream.Seek(STREAM_SEEK_TO_END)) + { + rStream.SetStreamSize(nSize); + rStream.Seek(rPage.GetPagePos() * PAGE_SIZE); + + char aEmptyData[PAGE_SIZE]; + memset(aEmptyData,0x00,PAGE_SIZE); + rStream.Write((BYTE*)aEmptyData,PAGE_SIZE); + } + ULONG nCurrentPos = rStream.Seek(rPage.GetPagePos() * PAGE_SIZE); + OSL_UNUSED( nCurrentPos ); + + nValue = rPage.nCount; + rStream << nValue << rPage.aChild; + + USHORT i = 0; + for (; i < rPage.nCount; i++) + rPage[i].Write(rStream, rPage); + + // check if we have to fill the stream with '\0' + if(i < rPage.rIndex.getHeader().db_maxkeys) + { + ULONG nTell = rStream.Tell() % PAGE_SIZE; + USHORT nBufferSize = rStream.GetBufferSize(); + ULONG nRemainSize = nBufferSize - nTell; + char* pEmptyData = new char[nRemainSize]; + memset(pEmptyData,0x00,nRemainSize); + rStream.Write((BYTE*)pEmptyData,nRemainSize); + rStream.Seek(nTell); + delete [] pEmptyData; + } + return rStream; +} +// ----------------------------------------------------------------------------- +#if OSL_DEBUG_LEVEL > 1 +//------------------------------------------------------------------ +void ONDXPage::PrintPage() +{ + DBG_TRACE4("\nSDB: -----------Page: %d Parent: %d Count: %d Child: %d-----", + nPagePos, HasParent() ? aParent->GetPagePos() : 0 ,nCount, aChild.GetPagePos()); + + for (USHORT i = 0; i < nCount; i++) + { + ONDXNode rNode = (*this)[i]; + ONDXKey& rKey = rNode.GetKey(); + if (!IsLeaf()) + rNode.GetChild(&rIndex, this); + + if (rKey.getValue().isNull()) + { + DBG_TRACE2("SDB: [%d,NULL,%d]",rKey.GetRecord(), rNode.GetChild().GetPagePos()); + } + else if (rIndex.getHeader().db_keytype) + { + DBG_TRACE3("SDB: [%d,%f,%d]",rKey.GetRecord(), rKey.getValue().getDouble(),rNode.GetChild().GetPagePos()); + } + else + { + DBG_TRACE3("SDB: [%d,%s,%d]",rKey.GetRecord(), (const char* )ByteString(rKey.getValue().getString().getStr(), rIndex.m_pTable->getConnection()->getTextEncoding()).GetBuffer(),rNode.GetChild().GetPagePos()); + } + } + DBG_TRACE("SDB: -----------------------------------------------\n"); + if (!IsLeaf()) + { +#if OSL_DEBUG_LEVEL > 1 + GetChild(&rIndex)->PrintPage(); + for (USHORT i = 0; i < nCount; i++) + { + ONDXNode rNode = (*this)[i]; + rNode.GetChild(&rIndex,this)->PrintPage(); + } +#endif + } + DBG_TRACE("SDB: ===============================================\n"); +} +#endif +// ----------------------------------------------------------------------------- +BOOL ONDXPage::IsFull() const +{ + return Count() == rIndex.getHeader().db_maxkeys; +} +// ----------------------------------------------------------------------------- +//------------------------------------------------------------------ +USHORT ONDXPage::Search(const ONDXKey& rSearch) +{ + // binare Suche spaeter + USHORT i = NODE_NOTFOUND; + while (++i < Count()) + if ((*this)[i].GetKey() == rSearch) + break; + + return (i < Count()) ? i : NODE_NOTFOUND; +} + +//------------------------------------------------------------------ +USHORT ONDXPage::Search(const ONDXPage* pPage) +{ + USHORT i = NODE_NOTFOUND; + while (++i < Count()) + if (((*this)[i]).GetChild() == pPage) + break; + + // wenn nicht gefunden, dann wird davon ausgegangen, dass die Seite selbst + // auf die Page zeigt + return (i < Count()) ? i : NODE_NOTFOUND; +} +// ----------------------------------------------------------------------------- +// laeuft rekursiv +void ONDXPage::SearchAndReplace(const ONDXKey& rSearch, + ONDXKey& rReplace) +{ + OSL_ENSURE(rSearch != rReplace,"Invalid here:rSearch == rReplace"); + if (rSearch != rReplace) + { + USHORT nPos = NODE_NOTFOUND; + ONDXPage* pPage = this; + + while (pPage && (nPos = pPage->Search(rSearch)) == NODE_NOTFOUND) + pPage = pPage->aParent; + + if (pPage) + { + (*pPage)[nPos].GetKey() = rReplace; + pPage->SetModified(TRUE); + } + } +} +// ----------------------------------------------------------------------------- +ONDXNode& ONDXPage::operator[] (USHORT nPos) +{ + DBG_ASSERT(nCount > nPos, "falscher Indexzugriff"); + return ppNodes[nPos]; +} + +//------------------------------------------------------------------ +const ONDXNode& ONDXPage::operator[] (USHORT nPos) const +{ + DBG_ASSERT(nCount > nPos, "falscher Indexzugriff"); + return ppNodes[nPos]; +} +// ----------------------------------------------------------------------------- +void ONDXPage::Remove(USHORT nPos) +{ + DBG_ASSERT(nCount > nPos, "falscher Indexzugriff"); + + for (USHORT i = nPos; i < (nCount-1); i++) + (*this)[i] = (*this)[i+1]; + + nCount--; + bModified = TRUE; +} +// ----------------------------------------------------------------------------- + diff --git a/connectivity/source/drivers/dbase/exports.dxp b/connectivity/source/drivers/dbase/exports.dxp new file mode 100644 index 000000000000..9630d7e06768 --- /dev/null +++ b/connectivity/source/drivers/dbase/exports.dxp @@ -0,0 +1,3 @@ +component_getImplementationEnvironment +component_writeInfo +component_getFactory diff --git a/connectivity/source/drivers/dbase/makefile.mk b/connectivity/source/drivers/dbase/makefile.mk new file mode 100644 index 000000000000..f855cf1f4554 --- /dev/null +++ b/connectivity/source/drivers/dbase/makefile.mk @@ -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. +# +#************************************************************************* + +PRJ=..$/..$/.. +PRJINC=..$/.. +PRJNAME=connectivity +TARGET=dbase + +VISIBILITY_HIDDEN=TRUE + +# --- Settings ---------------------------------- +.IF "$(DBGUTIL_OJ)"!="" +ENVCFLAGS+=/FR$(SLO)$/ +.ENDIF + +.INCLUDE : $(PRJ)$/makefile.pmk +.INCLUDE : $(PRJ)$/version.mk + +# --- Files ------------------------------------- + +SLOFILES=\ + $(SLO)$/DCode.obj \ + $(SLO)$/DResultSet.obj \ + $(SLO)$/DStatement.obj \ + $(SLO)$/DPreparedStatement.obj \ + $(SLO)$/dindexnode.obj \ + $(SLO)$/DIndexIter.obj \ + $(SLO)$/DDatabaseMetaData.obj \ + $(SLO)$/DCatalog.obj \ + $(SLO)$/DColumns.obj \ + $(SLO)$/DIndexColumns.obj \ + $(SLO)$/DIndex.obj \ + $(SLO)$/DIndexes.obj \ + $(SLO)$/DTable.obj \ + $(SLO)$/DTables.obj \ + $(SLO)$/DConnection.obj \ + $(SLO)$/Dservices.obj \ + $(SLO)$/DDriver.obj + +EXCEPTIONSFILES=\ + $(SLO)$/DCode.obj \ + $(SLO)$/DResultSet.obj \ + $(SLO)$/DStatement.obj \ + $(SLO)$/DPreparedStatement.obj \ + $(SLO)$/dindexnode.obj \ + $(SLO)$/DIndexIter.obj \ + $(SLO)$/DDatabaseMetaData.obj \ + $(SLO)$/DCatalog.obj \ + $(SLO)$/DColumns.obj \ + $(SLO)$/DIndexColumns.obj \ + $(SLO)$/DIndex.obj \ + $(SLO)$/DIndexes.obj \ + $(SLO)$/DTables.obj \ + $(SLO)$/DConnection.obj \ + $(SLO)$/Dservices.obj \ + $(SLO)$/DDriver.obj + +# [kh] ppc linux gcc compiler problem +.IF "$(OS)$(COM)$(CPUNAME)"=="LINUXGCCPOWERPC" +EXCEPTIONSNOOPTFILES= \ + $(SLO)$/DTable.obj +.ELSE +EXCEPTIONSFILES +=\ + $(SLO)$/DTable.obj +.ENDIF + + +SHL1VERSIONMAP=$(SOLARENV)/src/component.map + +# --- Library ----------------------------------- + +SHL1TARGET=$(TARGET)$(DLLPOSTFIX) +SHL1OBJS=$(SLOFILES) +SHL1STDLIBS=\ + $(CPPULIB) \ + $(CPPUHELPERLIB) \ + $(VOSLIB) \ + $(SVLLIB) \ + $(TOOLSLIB) \ + $(UCBHELPERLIB) \ + $(SALLIB) \ + $(DBTOOLSLIB) \ + $(DBFILELIB) \ + $(UNOTOOLSLIB) \ + $(COMPHELPERLIB) + +.IF "$(DBFILELIB)" == "" +SHL1STDLIBS+= ifile.lib +.ENDIF + +SHL1DEPN= +SHL1IMPLIB= i$(DBASE_TARGET) + + +SHL1DEF= $(MISC)$/$(SHL1TARGET).def + +DEF1NAME= $(SHL1TARGET) +DEF1EXPORTFILE= exports.dxp + + +# --- Targets ---------------------------------- + +.INCLUDE : $(PRJ)$/target.pmk + + |