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