1*cdf0e10cSrcweir /************************************************************************* 2*cdf0e10cSrcweir * 3*cdf0e10cSrcweir * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4*cdf0e10cSrcweir * 5*cdf0e10cSrcweir * Copyright 2000, 2010 Oracle and/or its affiliates. 6*cdf0e10cSrcweir * 7*cdf0e10cSrcweir * OpenOffice.org - a multi-platform office productivity suite 8*cdf0e10cSrcweir * 9*cdf0e10cSrcweir * This file is part of OpenOffice.org. 10*cdf0e10cSrcweir * 11*cdf0e10cSrcweir * OpenOffice.org is free software: you can redistribute it and/or modify 12*cdf0e10cSrcweir * it under the terms of the GNU Lesser General Public License version 3 13*cdf0e10cSrcweir * only, as published by the Free Software Foundation. 14*cdf0e10cSrcweir * 15*cdf0e10cSrcweir * OpenOffice.org is distributed in the hope that it will be useful, 16*cdf0e10cSrcweir * but WITHOUT ANY WARRANTY; without even the implied warranty of 17*cdf0e10cSrcweir * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18*cdf0e10cSrcweir * GNU Lesser General Public License version 3 for more details 19*cdf0e10cSrcweir * (a copy is included in the LICENSE file that accompanied this code). 20*cdf0e10cSrcweir * 21*cdf0e10cSrcweir * You should have received a copy of the GNU Lesser General Public License 22*cdf0e10cSrcweir * version 3 along with OpenOffice.org. If not, see 23*cdf0e10cSrcweir * <http://www.openoffice.org/license.html> 24*cdf0e10cSrcweir * for a copy of the LGPLv3 License. 25*cdf0e10cSrcweir * 26*cdf0e10cSrcweir ************************************************************************/ 27*cdf0e10cSrcweir 28*cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove 29*cdf0e10cSrcweir #include "precompiled_connectivity.hxx" 30*cdf0e10cSrcweir #include "dbase/DIndex.hxx" 31*cdf0e10cSrcweir #include "dbase/DIndexColumns.hxx" 32*cdf0e10cSrcweir #include <com/sun/star/lang/DisposedException.hpp> 33*cdf0e10cSrcweir #include "connectivity/sdbcx/VColumn.hxx" 34*cdf0e10cSrcweir #include <comphelper/sequence.hxx> 35*cdf0e10cSrcweir #include "dbase/DTable.hxx" 36*cdf0e10cSrcweir #include "dbase/DIndexIter.hxx" 37*cdf0e10cSrcweir #include <tools/config.hxx> 38*cdf0e10cSrcweir #include "connectivity/CommonTools.hxx" 39*cdf0e10cSrcweir #include <com/sun/star/sdbc/XResultSetMetaData.hpp> 40*cdf0e10cSrcweir #include <com/sun/star/sdbc/XResultSet.hpp> 41*cdf0e10cSrcweir #include <com/sun/star/sdbcx/XRowLocate.hpp> 42*cdf0e10cSrcweir #include <com/sun/star/sdbc/XRow.hpp> 43*cdf0e10cSrcweir #include <comphelper/extract.hxx> 44*cdf0e10cSrcweir #include <unotools/localfilehelper.hxx> 45*cdf0e10cSrcweir #include <unotools/ucbhelper.hxx> 46*cdf0e10cSrcweir #include <comphelper/types.hxx> 47*cdf0e10cSrcweir #include <connectivity/dbexception.hxx> 48*cdf0e10cSrcweir #include "dbase/DResultSet.hxx" 49*cdf0e10cSrcweir #include "diagnose_ex.h" 50*cdf0e10cSrcweir #include <comphelper/types.hxx> 51*cdf0e10cSrcweir #include "resource/dbase_res.hrc" 52*cdf0e10cSrcweir #include <unotools/sharedunocomponent.hxx> 53*cdf0e10cSrcweir 54*cdf0e10cSrcweir using namespace ::comphelper; 55*cdf0e10cSrcweir // ------------------------------------------------------------------------- 56*cdf0e10cSrcweir using namespace connectivity; 57*cdf0e10cSrcweir using namespace utl; 58*cdf0e10cSrcweir using namespace ::cppu; 59*cdf0e10cSrcweir using namespace connectivity::file; 60*cdf0e10cSrcweir using namespace connectivity::sdbcx; 61*cdf0e10cSrcweir using namespace connectivity::dbase; 62*cdf0e10cSrcweir using namespace com::sun::star::sdbc; 63*cdf0e10cSrcweir using namespace com::sun::star::sdbcx; 64*cdf0e10cSrcweir using namespace com::sun::star::uno; 65*cdf0e10cSrcweir using namespace com::sun::star::beans; 66*cdf0e10cSrcweir using namespace com::sun::star::lang; 67*cdf0e10cSrcweir 68*cdf0e10cSrcweir IMPLEMENT_SERVICE_INFO(ODbaseIndex,"com.sun.star.sdbcx.driver.dbase.Index","com.sun.star.sdbcx.Index"); 69*cdf0e10cSrcweir // ------------------------------------------------------------------------- 70*cdf0e10cSrcweir ODbaseIndex::ODbaseIndex(ODbaseTable* _pTable) : OIndex(sal_True/*_pTable->getConnection()->getMetaData()->supportsMixedCaseQuotedIdentifiers()*/) 71*cdf0e10cSrcweir ,m_pFileStream(NULL) 72*cdf0e10cSrcweir ,m_nCurNode(NODE_NOTFOUND) 73*cdf0e10cSrcweir ,m_pTable(_pTable) 74*cdf0e10cSrcweir { 75*cdf0e10cSrcweir m_aHeader.db_pagecount = m_aHeader.db_rootpage = m_aHeader.db_keytype = m_aHeader.db_maxkeys = m_aHeader.db_keylen = 0; 76*cdf0e10cSrcweir m_aHeader.db_name[0] = '\0'; 77*cdf0e10cSrcweir construct(); 78*cdf0e10cSrcweir } 79*cdf0e10cSrcweir // ------------------------------------------------------------------------- 80*cdf0e10cSrcweir ODbaseIndex::ODbaseIndex( ODbaseTable* _pTable, 81*cdf0e10cSrcweir const NDXHeader& _rHeader, 82*cdf0e10cSrcweir const ::rtl::OUString& _rName) 83*cdf0e10cSrcweir :OIndex(_rName,::rtl::OUString(),_rHeader.db_unique,sal_False,sal_False,sal_True) // _pTable->getConnection()->getMetaData()->supportsMixedCaseQuotedIdentifiers() 84*cdf0e10cSrcweir ,m_pFileStream(NULL) 85*cdf0e10cSrcweir ,m_aHeader(_rHeader) 86*cdf0e10cSrcweir ,m_nCurNode(NODE_NOTFOUND) 87*cdf0e10cSrcweir ,m_pTable(_pTable) 88*cdf0e10cSrcweir { 89*cdf0e10cSrcweir construct(); 90*cdf0e10cSrcweir } 91*cdf0e10cSrcweir // ----------------------------------------------------------------------------- 92*cdf0e10cSrcweir ODbaseIndex::~ODbaseIndex() 93*cdf0e10cSrcweir { 94*cdf0e10cSrcweir closeImpl(); 95*cdf0e10cSrcweir } 96*cdf0e10cSrcweir // ------------------------------------------------------------------------- 97*cdf0e10cSrcweir void ODbaseIndex::refreshColumns() 98*cdf0e10cSrcweir { 99*cdf0e10cSrcweir ::osl::MutexGuard aGuard( m_aMutex ); 100*cdf0e10cSrcweir 101*cdf0e10cSrcweir TStringVector aVector; 102*cdf0e10cSrcweir if(!isNew()) 103*cdf0e10cSrcweir { 104*cdf0e10cSrcweir OSL_ENSURE(m_pFileStream,"FileStream is not opened!"); 105*cdf0e10cSrcweir OSL_ENSURE(m_aHeader.db_name[0] != '\0',"Invalid name for the column!"); 106*cdf0e10cSrcweir aVector.push_back(::rtl::OUString::createFromAscii(m_aHeader.db_name)); 107*cdf0e10cSrcweir } 108*cdf0e10cSrcweir 109*cdf0e10cSrcweir if(m_pColumns) 110*cdf0e10cSrcweir m_pColumns->reFill(aVector); 111*cdf0e10cSrcweir else 112*cdf0e10cSrcweir m_pColumns = new ODbaseIndexColumns(this,m_aMutex,aVector); 113*cdf0e10cSrcweir } 114*cdf0e10cSrcweir //-------------------------------------------------------------------------- 115*cdf0e10cSrcweir Sequence< sal_Int8 > ODbaseIndex::getUnoTunnelImplementationId() 116*cdf0e10cSrcweir { 117*cdf0e10cSrcweir static ::cppu::OImplementationId * pId = 0; 118*cdf0e10cSrcweir if (! pId) 119*cdf0e10cSrcweir { 120*cdf0e10cSrcweir ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ); 121*cdf0e10cSrcweir if (! pId) 122*cdf0e10cSrcweir { 123*cdf0e10cSrcweir static ::cppu::OImplementationId aId; 124*cdf0e10cSrcweir pId = &aId; 125*cdf0e10cSrcweir } 126*cdf0e10cSrcweir } 127*cdf0e10cSrcweir return pId->getImplementationId(); 128*cdf0e10cSrcweir } 129*cdf0e10cSrcweir 130*cdf0e10cSrcweir // XUnoTunnel 131*cdf0e10cSrcweir //------------------------------------------------------------------ 132*cdf0e10cSrcweir sal_Int64 ODbaseIndex::getSomething( const Sequence< sal_Int8 > & rId ) throw (RuntimeException) 133*cdf0e10cSrcweir { 134*cdf0e10cSrcweir return (rId.getLength() == 16 && 0 == rtl_compareMemory(getUnoTunnelImplementationId().getConstArray(), rId.getConstArray(), 16 ) ) 135*cdf0e10cSrcweir ? reinterpret_cast< sal_Int64 >( this ) 136*cdf0e10cSrcweir : ODbaseIndex_BASE::getSomething(rId); 137*cdf0e10cSrcweir } 138*cdf0e10cSrcweir //------------------------------------------------------------------ 139*cdf0e10cSrcweir ONDXPagePtr ODbaseIndex::getRoot() 140*cdf0e10cSrcweir { 141*cdf0e10cSrcweir openIndexFile(); 142*cdf0e10cSrcweir if (!m_aRoot.Is()) 143*cdf0e10cSrcweir { 144*cdf0e10cSrcweir m_nRootPage = m_aHeader.db_rootpage; 145*cdf0e10cSrcweir m_nPageCount = m_aHeader.db_pagecount; 146*cdf0e10cSrcweir m_aRoot = CreatePage(m_nRootPage,NULL,sal_True); 147*cdf0e10cSrcweir } 148*cdf0e10cSrcweir return m_aRoot; 149*cdf0e10cSrcweir } 150*cdf0e10cSrcweir //------------------------------------------------------------------ 151*cdf0e10cSrcweir sal_Bool ODbaseIndex::openIndexFile() 152*cdf0e10cSrcweir { 153*cdf0e10cSrcweir if(!m_pFileStream) 154*cdf0e10cSrcweir { 155*cdf0e10cSrcweir ::rtl::OUString sFile = getCompletePath(); 156*cdf0e10cSrcweir if(UCBContentHelper::Exists(sFile)) 157*cdf0e10cSrcweir { 158*cdf0e10cSrcweir m_pFileStream = OFileTable::createStream_simpleError(sFile, STREAM_READWRITE | STREAM_NOCREATE | STREAM_SHARE_DENYWRITE); 159*cdf0e10cSrcweir if (!m_pFileStream) 160*cdf0e10cSrcweir m_pFileStream = OFileTable::createStream_simpleError(sFile,STREAM_READ | STREAM_NOCREATE | STREAM_SHARE_DENYNONE); 161*cdf0e10cSrcweir if(m_pFileStream) 162*cdf0e10cSrcweir { 163*cdf0e10cSrcweir m_pFileStream->SetNumberFormatInt(NUMBERFORMAT_INT_LITTLEENDIAN); 164*cdf0e10cSrcweir m_pFileStream->SetBufferSize(PAGE_SIZE); 165*cdf0e10cSrcweir (*m_pFileStream) >> *this; 166*cdf0e10cSrcweir } 167*cdf0e10cSrcweir } 168*cdf0e10cSrcweir if(!m_pFileStream) 169*cdf0e10cSrcweir { 170*cdf0e10cSrcweir const ::rtl::OUString sError( m_pTable->getConnection()->getResources().getResourceStringWithSubstitution( 171*cdf0e10cSrcweir STR_COULD_NOT_LOAD_FILE, 172*cdf0e10cSrcweir "$filename$", sFile 173*cdf0e10cSrcweir ) ); 174*cdf0e10cSrcweir ::dbtools::throwGenericSQLException( sError, *this ); 175*cdf0e10cSrcweir } 176*cdf0e10cSrcweir } 177*cdf0e10cSrcweir 178*cdf0e10cSrcweir return m_pFileStream != NULL; 179*cdf0e10cSrcweir } 180*cdf0e10cSrcweir //------------------------------------------------------------------ 181*cdf0e10cSrcweir OIndexIterator* ODbaseIndex::createIterator(OBoolOperator* pOp, 182*cdf0e10cSrcweir const OOperand* pOperand) 183*cdf0e10cSrcweir { 184*cdf0e10cSrcweir openIndexFile(); 185*cdf0e10cSrcweir return new OIndexIterator(this, pOp, pOperand); 186*cdf0e10cSrcweir } 187*cdf0e10cSrcweir //------------------------------------------------------------------ 188*cdf0e10cSrcweir sal_Bool ODbaseIndex::ConvertToKey(ONDXKey* rKey, sal_uInt32 nRec, const ORowSetValue& rValue) 189*cdf0e10cSrcweir { 190*cdf0e10cSrcweir OSL_ENSURE(m_pFileStream,"FileStream is not opened!"); 191*cdf0e10cSrcweir // Sucht ein bestimmten Wert im Index 192*cdf0e10cSrcweir // Wenn der Index Unique ist, interssiert der Key nicht, sonst ja 193*cdf0e10cSrcweir try 194*cdf0e10cSrcweir { 195*cdf0e10cSrcweir if (m_aHeader.db_keytype == 0) 196*cdf0e10cSrcweir { 197*cdf0e10cSrcweir *rKey = ONDXKey(rValue.getString(), nRec ); 198*cdf0e10cSrcweir } 199*cdf0e10cSrcweir else 200*cdf0e10cSrcweir { 201*cdf0e10cSrcweir if (rValue.isNull()) 202*cdf0e10cSrcweir *rKey = ONDXKey(rValue.getDouble(), DataType::DOUBLE, nRec ); 203*cdf0e10cSrcweir else 204*cdf0e10cSrcweir *rKey = ONDXKey(rValue.getDouble(), nRec ); 205*cdf0e10cSrcweir } 206*cdf0e10cSrcweir } 207*cdf0e10cSrcweir catch (Exception&) 208*cdf0e10cSrcweir { 209*cdf0e10cSrcweir OSL_ASSERT(0); 210*cdf0e10cSrcweir return sal_False; 211*cdf0e10cSrcweir } 212*cdf0e10cSrcweir return sal_True; 213*cdf0e10cSrcweir } 214*cdf0e10cSrcweir 215*cdf0e10cSrcweir //------------------------------------------------------------------ 216*cdf0e10cSrcweir sal_Bool ODbaseIndex::Find(sal_uInt32 nRec, const ORowSetValue& rValue) 217*cdf0e10cSrcweir { 218*cdf0e10cSrcweir openIndexFile(); 219*cdf0e10cSrcweir OSL_ENSURE(m_pFileStream,"FileStream is not opened!"); 220*cdf0e10cSrcweir // Sucht ein bestimmten Wert im Index 221*cdf0e10cSrcweir // Wenn der Index Unique ist, interssiert der Key nicht, sonst ja 222*cdf0e10cSrcweir ONDXKey aKey; 223*cdf0e10cSrcweir return ConvertToKey(&aKey, nRec, rValue) && getRoot()->Find(aKey); 224*cdf0e10cSrcweir } 225*cdf0e10cSrcweir 226*cdf0e10cSrcweir //------------------------------------------------------------------ 227*cdf0e10cSrcweir sal_Bool ODbaseIndex::Insert(sal_uInt32 nRec, const ORowSetValue& rValue) 228*cdf0e10cSrcweir { 229*cdf0e10cSrcweir openIndexFile(); 230*cdf0e10cSrcweir OSL_ENSURE(m_pFileStream,"FileStream is not opened!"); 231*cdf0e10cSrcweir ONDXKey aKey; 232*cdf0e10cSrcweir 233*cdf0e10cSrcweir // Existiert der Wert bereits 234*cdf0e10cSrcweir // Find immer verwenden um das aktuelle Blatt zu bestimmen 235*cdf0e10cSrcweir if (!ConvertToKey(&aKey, nRec, rValue) || (getRoot()->Find(aKey) && isUnique())) 236*cdf0e10cSrcweir return sal_False; 237*cdf0e10cSrcweir 238*cdf0e10cSrcweir ONDXNode aNewNode(aKey); 239*cdf0e10cSrcweir 240*cdf0e10cSrcweir // einfuegen in das aktuelle Blatt 241*cdf0e10cSrcweir if (!m_aCurLeaf.Is()) 242*cdf0e10cSrcweir return sal_False; 243*cdf0e10cSrcweir 244*cdf0e10cSrcweir sal_Bool bResult = m_aCurLeaf->Insert(aNewNode); 245*cdf0e10cSrcweir Release(bResult); 246*cdf0e10cSrcweir 247*cdf0e10cSrcweir return bResult; 248*cdf0e10cSrcweir } 249*cdf0e10cSrcweir 250*cdf0e10cSrcweir //------------------------------------------------------------------ 251*cdf0e10cSrcweir sal_Bool ODbaseIndex::Update(sal_uInt32 nRec, const ORowSetValue& rOldValue, 252*cdf0e10cSrcweir const ORowSetValue& rNewValue) 253*cdf0e10cSrcweir { 254*cdf0e10cSrcweir openIndexFile(); 255*cdf0e10cSrcweir OSL_ENSURE(m_pFileStream,"FileStream is not opened!"); 256*cdf0e10cSrcweir ONDXKey aKey; 257*cdf0e10cSrcweir if (!ConvertToKey(&aKey, nRec, rNewValue) || (isUnique() && getRoot()->Find(aKey))) 258*cdf0e10cSrcweir return sal_False; 259*cdf0e10cSrcweir else 260*cdf0e10cSrcweir return Delete(nRec, rOldValue) && Insert(nRec,rNewValue); 261*cdf0e10cSrcweir } 262*cdf0e10cSrcweir 263*cdf0e10cSrcweir //------------------------------------------------------------------ 264*cdf0e10cSrcweir sal_Bool ODbaseIndex::Delete(sal_uInt32 nRec, const ORowSetValue& rValue) 265*cdf0e10cSrcweir { 266*cdf0e10cSrcweir openIndexFile(); 267*cdf0e10cSrcweir OSL_ENSURE(m_pFileStream,"FileStream is not opened!"); 268*cdf0e10cSrcweir // Existiert der Wert bereits 269*cdf0e10cSrcweir // Find immer verwenden um das aktuelle Blatt zu bestimmen 270*cdf0e10cSrcweir ONDXKey aKey; 271*cdf0e10cSrcweir if (!ConvertToKey(&aKey, nRec, rValue) || !getRoot()->Find(aKey)) 272*cdf0e10cSrcweir return sal_False; 273*cdf0e10cSrcweir 274*cdf0e10cSrcweir ONDXNode aNewNode(aKey); 275*cdf0e10cSrcweir 276*cdf0e10cSrcweir // einfuegen in das aktuelle Blatt 277*cdf0e10cSrcweir if (!m_aCurLeaf.Is()) 278*cdf0e10cSrcweir return sal_False; 279*cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1 280*cdf0e10cSrcweir m_aRoot->PrintPage(); 281*cdf0e10cSrcweir #endif 282*cdf0e10cSrcweir 283*cdf0e10cSrcweir return m_aCurLeaf->Delete(m_nCurNode); 284*cdf0e10cSrcweir } 285*cdf0e10cSrcweir //------------------------------------------------------------------ 286*cdf0e10cSrcweir void ODbaseIndex::Collect(ONDXPage* pPage) 287*cdf0e10cSrcweir { 288*cdf0e10cSrcweir if (pPage) 289*cdf0e10cSrcweir m_aCollector.push_back(pPage); 290*cdf0e10cSrcweir } 291*cdf0e10cSrcweir //------------------------------------------------------------------ 292*cdf0e10cSrcweir void ODbaseIndex::Release(sal_Bool bSave) 293*cdf0e10cSrcweir { 294*cdf0e10cSrcweir // Freigeben der Indexressourcen 295*cdf0e10cSrcweir m_bUseCollector = sal_False; 296*cdf0e10cSrcweir 297*cdf0e10cSrcweir if (m_aCurLeaf.Is()) 298*cdf0e10cSrcweir { 299*cdf0e10cSrcweir m_aCurLeaf->Release(bSave); 300*cdf0e10cSrcweir m_aCurLeaf.Clear(); 301*cdf0e10cSrcweir } 302*cdf0e10cSrcweir 303*cdf0e10cSrcweir // Wurzel freigeben 304*cdf0e10cSrcweir if (m_aRoot.Is()) 305*cdf0e10cSrcweir { 306*cdf0e10cSrcweir m_aRoot->Release(bSave); 307*cdf0e10cSrcweir m_aRoot.Clear(); 308*cdf0e10cSrcweir } 309*cdf0e10cSrcweir // alle Referenzen freigeben, bevor der FileStream geschlossen wird 310*cdf0e10cSrcweir for (sal_uIntPtr i = 0; i < m_aCollector.size(); i++) 311*cdf0e10cSrcweir m_aCollector[i]->QueryDelete(); 312*cdf0e10cSrcweir 313*cdf0e10cSrcweir m_aCollector.clear(); 314*cdf0e10cSrcweir 315*cdf0e10cSrcweir // Header modifiziert ? 316*cdf0e10cSrcweir if (bSave && (m_aHeader.db_rootpage != m_nRootPage || 317*cdf0e10cSrcweir m_aHeader.db_pagecount != m_nPageCount)) 318*cdf0e10cSrcweir { 319*cdf0e10cSrcweir m_aHeader.db_rootpage = m_nRootPage; 320*cdf0e10cSrcweir m_aHeader.db_pagecount = m_nPageCount; 321*cdf0e10cSrcweir (*m_pFileStream) << *this; 322*cdf0e10cSrcweir } 323*cdf0e10cSrcweir m_nRootPage = m_nPageCount = 0; 324*cdf0e10cSrcweir m_nCurNode = NODE_NOTFOUND; 325*cdf0e10cSrcweir 326*cdf0e10cSrcweir closeImpl(); 327*cdf0e10cSrcweir } 328*cdf0e10cSrcweir // ----------------------------------------------------------------------------- 329*cdf0e10cSrcweir void ODbaseIndex::closeImpl() 330*cdf0e10cSrcweir { 331*cdf0e10cSrcweir if(m_pFileStream) 332*cdf0e10cSrcweir { 333*cdf0e10cSrcweir delete m_pFileStream; 334*cdf0e10cSrcweir m_pFileStream = NULL; 335*cdf0e10cSrcweir } 336*cdf0e10cSrcweir } 337*cdf0e10cSrcweir //------------------------------------------------------------------ 338*cdf0e10cSrcweir ONDXPage* ODbaseIndex::CreatePage(sal_uInt32 nPagePos, ONDXPage* pParent, sal_Bool bLoad) 339*cdf0e10cSrcweir { 340*cdf0e10cSrcweir OSL_ENSURE(m_pFileStream,"FileStream is not opened!"); 341*cdf0e10cSrcweir 342*cdf0e10cSrcweir ONDXPage* pPage; 343*cdf0e10cSrcweir if ( !m_aCollector.empty() ) 344*cdf0e10cSrcweir { 345*cdf0e10cSrcweir pPage = *(m_aCollector.rbegin()); 346*cdf0e10cSrcweir m_aCollector.pop_back(); 347*cdf0e10cSrcweir pPage->SetPagePos(nPagePos); 348*cdf0e10cSrcweir pPage->SetParent(pParent); 349*cdf0e10cSrcweir } 350*cdf0e10cSrcweir else 351*cdf0e10cSrcweir pPage = new ONDXPage(*this, nPagePos, pParent); 352*cdf0e10cSrcweir 353*cdf0e10cSrcweir if (bLoad) 354*cdf0e10cSrcweir (*m_pFileStream) >> *pPage; 355*cdf0e10cSrcweir 356*cdf0e10cSrcweir return pPage; 357*cdf0e10cSrcweir } 358*cdf0e10cSrcweir 359*cdf0e10cSrcweir //------------------------------------------------------------------ 360*cdf0e10cSrcweir SvStream& connectivity::dbase::operator >> (SvStream &rStream, ODbaseIndex& rIndex) 361*cdf0e10cSrcweir { 362*cdf0e10cSrcweir rStream.Seek(0); 363*cdf0e10cSrcweir rStream.Read(&rIndex.m_aHeader,PAGE_SIZE); 364*cdf0e10cSrcweir 365*cdf0e10cSrcweir /* OJ: no longer needed 366*cdf0e10cSrcweir // Text convertierung 367*cdf0e10cSrcweir ByteString aText(rIndex.m_aHeader.db_name); 368*cdf0e10cSrcweir // aText.Convert(rIndex.m_pTable->getConnection()->GetCharacterSet(), m_pTable->getConnection()->getTextEncoding()); 369*cdf0e10cSrcweir // aText.Convert(rIndex.m_pTable->getConnection()->GetCharacterSet(), m_pTable->getConnection()->getTextEncoding()); 370*cdf0e10cSrcweir strcpy(rIndex.m_aHeader.db_name,aText.GetBuffer()); 371*cdf0e10cSrcweir */ 372*cdf0e10cSrcweir rIndex.m_nRootPage = rIndex.m_aHeader.db_rootpage; 373*cdf0e10cSrcweir rIndex.m_nPageCount = rIndex.m_aHeader.db_pagecount; 374*cdf0e10cSrcweir return rStream; 375*cdf0e10cSrcweir } 376*cdf0e10cSrcweir //------------------------------------------------------------------ 377*cdf0e10cSrcweir SvStream& connectivity::dbase::operator << (SvStream &rStream, ODbaseIndex& rIndex) 378*cdf0e10cSrcweir { 379*cdf0e10cSrcweir rStream.Seek(0); 380*cdf0e10cSrcweir /* OJ: no longer needed 381*cdf0e10cSrcweir ByteString aText(rIndex.m_aHeader.db_name); 382*cdf0e10cSrcweir // aText.Convert(m_pTable->getConnection()->getTextEncoding(), rIndex.m_pTable->getConnection()->GetCharacterSet()); 383*cdf0e10cSrcweir strcpy(rIndex.m_aHeader.db_name,aText.GetBuffer()); 384*cdf0e10cSrcweir */ 385*cdf0e10cSrcweir OSL_VERIFY_EQUALS( rStream.Write(&rIndex.m_aHeader,PAGE_SIZE), PAGE_SIZE, "Write not successful: Wrong header size for dbase index!"); 386*cdf0e10cSrcweir return rStream; 387*cdf0e10cSrcweir } 388*cdf0e10cSrcweir // ------------------------------------------------------------------------- 389*cdf0e10cSrcweir ::rtl::OUString ODbaseIndex::getCompletePath() 390*cdf0e10cSrcweir { 391*cdf0e10cSrcweir ::rtl::OUString sDir = m_pTable->getConnection()->getURL(); 392*cdf0e10cSrcweir sDir += OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_DELIMITER); 393*cdf0e10cSrcweir sDir += m_Name; 394*cdf0e10cSrcweir sDir += ::rtl::OUString::createFromAscii(".ndx"); 395*cdf0e10cSrcweir return sDir; 396*cdf0e10cSrcweir } 397*cdf0e10cSrcweir //------------------------------------------------------------------ 398*cdf0e10cSrcweir void ODbaseIndex::createINFEntry() 399*cdf0e10cSrcweir { 400*cdf0e10cSrcweir // inf Datei abgleichen 401*cdf0e10cSrcweir String sEntry = m_Name; 402*cdf0e10cSrcweir sEntry += String::CreateFromAscii(".ndx"); 403*cdf0e10cSrcweir 404*cdf0e10cSrcweir ::rtl::OUString sCfgFile(m_pTable->getConnection()->getURL()); 405*cdf0e10cSrcweir sCfgFile += OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_DELIMITER); 406*cdf0e10cSrcweir sCfgFile += m_pTable->getName(); 407*cdf0e10cSrcweir sCfgFile += ::rtl::OUString::createFromAscii(".inf"); 408*cdf0e10cSrcweir 409*cdf0e10cSrcweir String sPhysicalPath; 410*cdf0e10cSrcweir LocalFileHelper::ConvertURLToPhysicalName(sCfgFile,sPhysicalPath); 411*cdf0e10cSrcweir 412*cdf0e10cSrcweir Config aInfFile(sPhysicalPath); 413*cdf0e10cSrcweir aInfFile.SetGroup(dBASE_III_GROUP); 414*cdf0e10cSrcweir 415*cdf0e10cSrcweir sal_uInt16 nSuffix = aInfFile.GetKeyCount(); 416*cdf0e10cSrcweir ByteString aNewEntry,aKeyName; 417*cdf0e10cSrcweir sal_Bool bCase = isCaseSensitive(); 418*cdf0e10cSrcweir while (!aNewEntry.Len()) 419*cdf0e10cSrcweir { 420*cdf0e10cSrcweir aNewEntry = "NDX"; 421*cdf0e10cSrcweir aNewEntry += ByteString::CreateFromInt32(++nSuffix); 422*cdf0e10cSrcweir for (sal_uInt16 i = 0; i < aInfFile.GetKeyCount(); i++) 423*cdf0e10cSrcweir { 424*cdf0e10cSrcweir aKeyName = aInfFile.GetKeyName(i); 425*cdf0e10cSrcweir if (bCase ? aKeyName == aNewEntry : aKeyName.EqualsIgnoreCaseAscii(aNewEntry)) 426*cdf0e10cSrcweir { 427*cdf0e10cSrcweir aNewEntry.Erase(); 428*cdf0e10cSrcweir break; 429*cdf0e10cSrcweir } 430*cdf0e10cSrcweir } 431*cdf0e10cSrcweir } 432*cdf0e10cSrcweir aInfFile.WriteKey(aNewEntry,ByteString(sEntry,m_pTable->getConnection()->getTextEncoding())); 433*cdf0e10cSrcweir } 434*cdf0e10cSrcweir // ------------------------------------------------------------------------- 435*cdf0e10cSrcweir sal_Bool ODbaseIndex::DropImpl() 436*cdf0e10cSrcweir { 437*cdf0e10cSrcweir closeImpl(); 438*cdf0e10cSrcweir 439*cdf0e10cSrcweir ::rtl::OUString sPath = getCompletePath(); 440*cdf0e10cSrcweir if(UCBContentHelper::Exists(sPath)) 441*cdf0e10cSrcweir { 442*cdf0e10cSrcweir if(!UCBContentHelper::Kill(sPath)) 443*cdf0e10cSrcweir m_pTable->getConnection()->throwGenericSQLException(STR_COULD_NOT_DELETE_INDEX,*m_pTable); 444*cdf0e10cSrcweir } 445*cdf0e10cSrcweir 446*cdf0e10cSrcweir // InfDatei abgleichen 447*cdf0e10cSrcweir 448*cdf0e10cSrcweir ::rtl::OUString sCfgFile(m_pTable->getConnection()->getURL()); 449*cdf0e10cSrcweir sCfgFile += OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_DELIMITER); 450*cdf0e10cSrcweir sCfgFile += m_pTable->getName(); 451*cdf0e10cSrcweir sCfgFile += ::rtl::OUString::createFromAscii(".inf"); 452*cdf0e10cSrcweir 453*cdf0e10cSrcweir String sPhysicalPath; 454*cdf0e10cSrcweir String sNDX(sCfgFile); 455*cdf0e10cSrcweir OSL_VERIFY_RES( LocalFileHelper::ConvertURLToPhysicalName(sNDX,sPhysicalPath),"Can not convert Config Filename into Physical Name!"); 456*cdf0e10cSrcweir 457*cdf0e10cSrcweir Config aInfFile(sPhysicalPath); 458*cdf0e10cSrcweir aInfFile.SetGroup(dBASE_III_GROUP); 459*cdf0e10cSrcweir sal_uInt16 nKeyCnt = aInfFile.GetKeyCount(); 460*cdf0e10cSrcweir ByteString aKeyName; 461*cdf0e10cSrcweir String sEntry = m_Name; 462*cdf0e10cSrcweir sEntry += String::CreateFromAscii(".ndx"); 463*cdf0e10cSrcweir 464*cdf0e10cSrcweir // delete entries from the inf file 465*cdf0e10cSrcweir for (sal_uInt16 nKey = 0; nKey < nKeyCnt; nKey++) 466*cdf0e10cSrcweir { 467*cdf0e10cSrcweir // Verweist der Key auf ein Indexfile?... 468*cdf0e10cSrcweir aKeyName = aInfFile.GetKeyName( nKey ); 469*cdf0e10cSrcweir if (aKeyName.Copy(0,3) == "NDX") 470*cdf0e10cSrcweir { 471*cdf0e10cSrcweir if(sEntry == String(aInfFile.ReadKey(aKeyName),m_pTable->getConnection()->getTextEncoding())) 472*cdf0e10cSrcweir { 473*cdf0e10cSrcweir aInfFile.DeleteKey(aKeyName); 474*cdf0e10cSrcweir break; 475*cdf0e10cSrcweir } 476*cdf0e10cSrcweir } 477*cdf0e10cSrcweir } 478*cdf0e10cSrcweir return sal_True; 479*cdf0e10cSrcweir } 480*cdf0e10cSrcweir // ------------------------------------------------------------------------- 481*cdf0e10cSrcweir void ODbaseIndex::impl_killFileAndthrowError_throw(sal_uInt16 _nErrorId,const ::rtl::OUString& _sFile) 482*cdf0e10cSrcweir { 483*cdf0e10cSrcweir closeImpl(); 484*cdf0e10cSrcweir if(UCBContentHelper::Exists(_sFile)) 485*cdf0e10cSrcweir UCBContentHelper::Kill(_sFile); 486*cdf0e10cSrcweir m_pTable->getConnection()->throwGenericSQLException(_nErrorId,*this); 487*cdf0e10cSrcweir } 488*cdf0e10cSrcweir //------------------------------------------------------------------ 489*cdf0e10cSrcweir sal_Bool ODbaseIndex::CreateImpl() 490*cdf0e10cSrcweir { 491*cdf0e10cSrcweir // Anlegen des Index 492*cdf0e10cSrcweir const ::rtl::OUString sFile = getCompletePath(); 493*cdf0e10cSrcweir if(UCBContentHelper::Exists(sFile)) 494*cdf0e10cSrcweir { 495*cdf0e10cSrcweir const ::rtl::OUString sError( m_pTable->getConnection()->getResources().getResourceStringWithSubstitution( 496*cdf0e10cSrcweir STR_COULD_NOT_CREATE_INDEX_NAME, 497*cdf0e10cSrcweir "$filename$", sFile 498*cdf0e10cSrcweir ) ); 499*cdf0e10cSrcweir ::dbtools::throwGenericSQLException( sError, *this ); 500*cdf0e10cSrcweir } 501*cdf0e10cSrcweir // Index ist nur einstufig 502*cdf0e10cSrcweir if (m_pColumns->getCount() > 1) 503*cdf0e10cSrcweir m_pTable->getConnection()->throwGenericSQLException(STR_ONL_ONE_COLUMN_PER_INDEX,*this); 504*cdf0e10cSrcweir 505*cdf0e10cSrcweir Reference<XFastPropertySet> xCol(m_pColumns->getByIndex(0),UNO_QUERY); 506*cdf0e10cSrcweir 507*cdf0e10cSrcweir // ist die Spalte schon indiziert ? 508*cdf0e10cSrcweir if ( !xCol.is() ) 509*cdf0e10cSrcweir ::dbtools::throwFunctionSequenceException(*this); 510*cdf0e10cSrcweir // else if (pColumn && pColumn->IsIndexed()) 511*cdf0e10cSrcweir // { 512*cdf0e10cSrcweir // String aText = String(OResId(STR_STAT_INDEX_COLUMN_ALREADY_INDEXED)); 513*cdf0e10cSrcweir // aText.SearchAndReplace(String::CreateFromAscii("#"),pColumn->GetName()); 514*cdf0e10cSrcweir // aStatus.Set(SDB_STAT_ERROR, 515*cdf0e10cSrcweir // String::CreateFromAscii("01000"), 516*cdf0e10cSrcweir // aStatus.CreateErrorMessage(aText), 517*cdf0e10cSrcweir // 0, String() ); 518*cdf0e10cSrcweir // return sal_False; 519*cdf0e10cSrcweir // } 520*cdf0e10cSrcweir 521*cdf0e10cSrcweir // create the index file 522*cdf0e10cSrcweir m_pFileStream = OFileTable::createStream_simpleError(sFile,STREAM_READWRITE | STREAM_SHARE_DENYWRITE | STREAM_TRUNC); 523*cdf0e10cSrcweir if (!m_pFileStream) 524*cdf0e10cSrcweir { 525*cdf0e10cSrcweir const ::rtl::OUString sError( m_pTable->getConnection()->getResources().getResourceStringWithSubstitution( 526*cdf0e10cSrcweir STR_COULD_NOT_LOAD_FILE, 527*cdf0e10cSrcweir "$filename$", sFile 528*cdf0e10cSrcweir ) ); 529*cdf0e10cSrcweir ::dbtools::throwGenericSQLException( sError, *this ); 530*cdf0e10cSrcweir } 531*cdf0e10cSrcweir 532*cdf0e10cSrcweir m_pFileStream->SetNumberFormatInt(NUMBERFORMAT_INT_LITTLEENDIAN); 533*cdf0e10cSrcweir m_pFileStream->SetBufferSize(PAGE_SIZE); 534*cdf0e10cSrcweir m_pFileStream->SetFiller('\0'); 535*cdf0e10cSrcweir 536*cdf0e10cSrcweir // Zunaechst muss das Ergebnis sortiert sein 537*cdf0e10cSrcweir utl::SharedUNOComponent<XStatement> xStmt; 538*cdf0e10cSrcweir utl::SharedUNOComponent<XResultSet> xSet; 539*cdf0e10cSrcweir String aName; 540*cdf0e10cSrcweir try 541*cdf0e10cSrcweir { 542*cdf0e10cSrcweir xStmt.set( m_pTable->getConnection()->createStatement(), UNO_SET_THROW); 543*cdf0e10cSrcweir 544*cdf0e10cSrcweir aName = getString(xCol->getFastPropertyValue(PROPERTY_ID_NAME)); 545*cdf0e10cSrcweir 546*cdf0e10cSrcweir const String aQuote(m_pTable->getConnection()->getMetaData()->getIdentifierQuoteString()); 547*cdf0e10cSrcweir String aStatement; 548*cdf0e10cSrcweir aStatement.AssignAscii("SELECT "); 549*cdf0e10cSrcweir aStatement += aQuote; 550*cdf0e10cSrcweir aStatement += aName; 551*cdf0e10cSrcweir aStatement += aQuote; 552*cdf0e10cSrcweir aStatement.AppendAscii(" FROM "); 553*cdf0e10cSrcweir aStatement += aQuote; 554*cdf0e10cSrcweir aStatement += m_pTable->getName().getStr(); 555*cdf0e10cSrcweir aStatement += aQuote; 556*cdf0e10cSrcweir aStatement.AppendAscii(" ORDER BY "); 557*cdf0e10cSrcweir aStatement += aQuote; 558*cdf0e10cSrcweir aStatement += aName; 559*cdf0e10cSrcweir aStatement += aQuote; 560*cdf0e10cSrcweir 561*cdf0e10cSrcweir // if (!m_IsUnique) // zusaetzlich sortierung mit der bookmarkspalte 562*cdf0e10cSrcweir // { 563*cdf0e10cSrcweir // aStatement.AppendAscii(" ,"); 564*cdf0e10cSrcweir // aStatement += aQuote; 565*cdf0e10cSrcweir // aStatement.AppendAscii("[BOOKMARK]"); // this is a special column 566*cdf0e10cSrcweir // aStatement += aQuote; 567*cdf0e10cSrcweir // } 568*cdf0e10cSrcweir 569*cdf0e10cSrcweir xSet.set( xStmt->executeQuery(aStatement),UNO_SET_THROW ); 570*cdf0e10cSrcweir } 571*cdf0e10cSrcweir catch(const Exception& ) 572*cdf0e10cSrcweir { 573*cdf0e10cSrcweir impl_killFileAndthrowError_throw(STR_COULD_NOT_CREATE_INDEX,sFile); 574*cdf0e10cSrcweir } 575*cdf0e10cSrcweir if (!xSet.is()) 576*cdf0e10cSrcweir { 577*cdf0e10cSrcweir impl_killFileAndthrowError_throw(STR_COULD_NOT_CREATE_INDEX,sFile); 578*cdf0e10cSrcweir } 579*cdf0e10cSrcweir 580*cdf0e10cSrcweir // Setzen der Headerinfo 581*cdf0e10cSrcweir memset(&m_aHeader,0,sizeof(m_aHeader)); 582*cdf0e10cSrcweir sal_Int32 nType = 0; 583*cdf0e10cSrcweir ::vos::ORef<OSQLColumns> aCols = m_pTable->getTableColumns(); 584*cdf0e10cSrcweir const Reference< XPropertySet > xTableCol(*find(aCols->get().begin(),aCols->get().end(),aName,::comphelper::UStringMixEqual(isCaseSensitive()))); 585*cdf0e10cSrcweir 586*cdf0e10cSrcweir xTableCol->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_TYPE)) >>= nType; 587*cdf0e10cSrcweir 588*cdf0e10cSrcweir m_aHeader.db_keytype = (nType == DataType::VARCHAR || nType == DataType::CHAR) ? 0 : 1; 589*cdf0e10cSrcweir m_aHeader.db_keylen = (m_aHeader.db_keytype) ? 8 : (sal_uInt16)getINT32(xTableCol->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_PRECISION))); 590*cdf0e10cSrcweir m_aHeader.db_keylen = (( m_aHeader.db_keylen - 1) / 4 + 1) * 4; 591*cdf0e10cSrcweir m_aHeader.db_maxkeys = (PAGE_SIZE - 4) / (8 + m_aHeader.db_keylen); 592*cdf0e10cSrcweir if ( m_aHeader.db_maxkeys < 3 ) 593*cdf0e10cSrcweir { 594*cdf0e10cSrcweir impl_killFileAndthrowError_throw(STR_COULD_NOT_CREATE_INDEX_KEYSIZE,sFile); 595*cdf0e10cSrcweir } 596*cdf0e10cSrcweir 597*cdf0e10cSrcweir m_pFileStream->SetStreamSize(PAGE_SIZE); 598*cdf0e10cSrcweir 599*cdf0e10cSrcweir ByteString aCol(aName,m_pTable->getConnection()->getTextEncoding()); 600*cdf0e10cSrcweir strncpy(m_aHeader.db_name,aCol.GetBuffer(),std::min((sal_uInt16)sizeof(m_aHeader.db_name), aCol.Len())); 601*cdf0e10cSrcweir m_aHeader.db_unique = m_IsUnique ? 1: 0; 602*cdf0e10cSrcweir m_aHeader.db_keyrec = m_aHeader.db_keylen + 8; 603*cdf0e10cSrcweir 604*cdf0e10cSrcweir // modifizierung am Header werden ueber Unterschiede zw. HeaderInfo und nRootPage 605*cdf0e10cSrcweir // bzw. nPageCout erkannt 606*cdf0e10cSrcweir 607*cdf0e10cSrcweir m_nRootPage = 1; 608*cdf0e10cSrcweir m_nPageCount = 2; 609*cdf0e10cSrcweir 610*cdf0e10cSrcweir // ODatabaseType eType = m_aHeader.db_keytype == 0 ? DataType::VARCHAR : DataType::DOUBLE; 611*cdf0e10cSrcweir m_aCurLeaf = m_aRoot = CreatePage(m_nRootPage); 612*cdf0e10cSrcweir m_aRoot->SetModified(sal_True); 613*cdf0e10cSrcweir 614*cdf0e10cSrcweir m_bUseCollector = sal_True; 615*cdf0e10cSrcweir 616*cdf0e10cSrcweir // sal_uIntPtr nRowsLeft = pCursor->RowCount(); 617*cdf0e10cSrcweir sal_Int32 nRowsLeft = 0; 618*cdf0e10cSrcweir Reference<XRow> xRow(xSet,UNO_QUERY); 619*cdf0e10cSrcweir 620*cdf0e10cSrcweir if(xSet->last()) 621*cdf0e10cSrcweir { 622*cdf0e10cSrcweir Reference< XUnoTunnel> xTunnel(xSet,UNO_QUERY); 623*cdf0e10cSrcweir ODbaseResultSet* pDbaseRes = NULL; 624*cdf0e10cSrcweir if(xTunnel.is()) 625*cdf0e10cSrcweir pDbaseRes = reinterpret_cast< ODbaseResultSet* >( xTunnel->getSomething(ODbaseResultSet::getUnoTunnelImplementationId()) ); 626*cdf0e10cSrcweir OSL_ENSURE(pDbaseRes,"No dbase resultset found? What's going on here!"); 627*cdf0e10cSrcweir Reference<XRowLocate> xRowLocate(xSet,UNO_QUERY); 628*cdf0e10cSrcweir nRowsLeft = xSet->getRow(); 629*cdf0e10cSrcweir 630*cdf0e10cSrcweir xSet->beforeFirst(); 631*cdf0e10cSrcweir ORowSetValue atmpValue=ORowSetValue(); 632*cdf0e10cSrcweir ONDXKey aKey(atmpValue, nType, 0); 633*cdf0e10cSrcweir ONDXKey aInsertKey(atmpValue, nType, 0); 634*cdf0e10cSrcweir // Erzeugen der Indexstruktur 635*cdf0e10cSrcweir while (xSet->next()) 636*cdf0e10cSrcweir { 637*cdf0e10cSrcweir // ODbRow& rRow = *pCursor->GetRow(); 638*cdf0e10cSrcweir ORowSetValue aValue(m_aHeader.db_keytype ? ORowSetValue(xRow->getDouble(1)) : ORowSetValue(xRow->getString(1))); 639*cdf0e10cSrcweir // ueberpruefen auf doppelten eintrag 640*cdf0e10cSrcweir if (m_IsUnique && m_nCurNode != NODE_NOTFOUND) 641*cdf0e10cSrcweir { 642*cdf0e10cSrcweir aKey.setValue(aValue); 643*cdf0e10cSrcweir if (aKey == (*m_aCurLeaf)[m_nCurNode].GetKey()) 644*cdf0e10cSrcweir { 645*cdf0e10cSrcweir impl_killFileAndthrowError_throw(STR_COULD_NOT_CREATE_INDEX_NOT_UNIQUE,sFile); 646*cdf0e10cSrcweir } 647*cdf0e10cSrcweir } 648*cdf0e10cSrcweir aInsertKey.setValue(aValue); 649*cdf0e10cSrcweir aInsertKey.setRecord(pDbaseRes->getCurrentFilePos()); 650*cdf0e10cSrcweir 651*cdf0e10cSrcweir ONDXNode aNewNode(aInsertKey); 652*cdf0e10cSrcweir if (!m_aCurLeaf->Insert(aNewNode, --nRowsLeft)) 653*cdf0e10cSrcweir break; 654*cdf0e10cSrcweir } 655*cdf0e10cSrcweir } 656*cdf0e10cSrcweir 657*cdf0e10cSrcweir if(nRowsLeft) 658*cdf0e10cSrcweir { 659*cdf0e10cSrcweir impl_killFileAndthrowError_throw(STR_COULD_NOT_CREATE_INDEX,sFile); 660*cdf0e10cSrcweir } 661*cdf0e10cSrcweir Release(); 662*cdf0e10cSrcweir createINFEntry(); 663*cdf0e10cSrcweir return sal_True; 664*cdf0e10cSrcweir } 665*cdf0e10cSrcweir // ----------------------------------------------------------------------------- 666*cdf0e10cSrcweir // ----------------------------------------------------------------------------- 667*cdf0e10cSrcweir void SAL_CALL ODbaseIndex::acquire() throw() 668*cdf0e10cSrcweir { 669*cdf0e10cSrcweir ODbaseIndex_BASE::acquire(); 670*cdf0e10cSrcweir } 671*cdf0e10cSrcweir // ----------------------------------------------------------------------------- 672*cdf0e10cSrcweir void SAL_CALL ODbaseIndex::release() throw() 673*cdf0e10cSrcweir { 674*cdf0e10cSrcweir ODbaseIndex_BASE::release(); 675*cdf0e10cSrcweir } 676*cdf0e10cSrcweir // ----------------------------------------------------------------------------- 677*cdf0e10cSrcweir 678*cdf0e10cSrcweir 679*cdf0e10cSrcweir 680