Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*
3 : : * This file is part of the LibreOffice project.
4 : : *
5 : : * This Source Code Form is subject to the terms of the Mozilla Public
6 : : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : : *
9 : : * This file incorporates work covered by the following license notice:
10 : : *
11 : : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : : * contributor license agreements. See the NOTICE file distributed
13 : : * with this work for additional information regarding copyright
14 : : * ownership. The ASF licenses this file to you under the Apache
15 : : * License, Version 2.0 (the "License"); you may not use this file
16 : : * except in compliance with the License. You may obtain a copy of
17 : : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : : */
19 : :
20 : : #include "dbase/DIndex.hxx"
21 : : #include "dbase/DIndexColumns.hxx"
22 : : #include <com/sun/star/lang/DisposedException.hpp>
23 : : #include "connectivity/sdbcx/VColumn.hxx"
24 : : #include <comphelper/sequence.hxx>
25 : : #include "dbase/DTable.hxx"
26 : : #include "dbase/DIndexIter.hxx"
27 : : #include <tools/config.hxx>
28 : : #include "connectivity/CommonTools.hxx"
29 : : #include <com/sun/star/sdbc/XResultSetMetaData.hpp>
30 : : #include <com/sun/star/sdbc/XResultSet.hpp>
31 : : #include <com/sun/star/sdbcx/XRowLocate.hpp>
32 : : #include <com/sun/star/sdbc/XRow.hpp>
33 : : #include <comphelper/extract.hxx>
34 : : #include <unotools/localfilehelper.hxx>
35 : : #include <unotools/ucbhelper.hxx>
36 : : #include <comphelper/types.hxx>
37 : : #include <connectivity/dbexception.hxx>
38 : : #include "dbase/DResultSet.hxx"
39 : : #include "diagnose_ex.h"
40 : : #include "resource/dbase_res.hrc"
41 : : #include <unotools/sharedunocomponent.hxx>
42 : :
43 : : using namespace ::comphelper;
44 : : // -------------------------------------------------------------------------
45 : : using namespace connectivity;
46 : : using namespace utl;
47 : : using namespace ::cppu;
48 : : using namespace connectivity::file;
49 : : using namespace connectivity::sdbcx;
50 : : using namespace connectivity::dbase;
51 : : using namespace com::sun::star::sdbc;
52 : : using namespace com::sun::star::sdbcx;
53 : : using namespace com::sun::star::uno;
54 : : using namespace com::sun::star::beans;
55 : : using namespace com::sun::star::lang;
56 : :
57 [ # # ][ # # ]: 0 : IMPLEMENT_SERVICE_INFO(ODbaseIndex,"com.sun.star.sdbcx.driver.dbase.Index","com.sun.star.sdbcx.Index");
[ # # ][ # # ]
[ # # ][ # # ]
58 : : // -------------------------------------------------------------------------
59 : 0 : ODbaseIndex::ODbaseIndex(ODbaseTable* _pTable) : OIndex(sal_True/*_pTable->getConnection()->getMetaData()->supportsMixedCaseQuotedIdentifiers()*/)
60 : : ,m_pFileStream(NULL)
61 : : ,m_nCurNode(NODE_NOTFOUND)
62 [ # # ][ # # ]: 0 : ,m_pTable(_pTable)
[ # # ]
63 : : {
64 : 0 : m_aHeader.db_pagecount = m_aHeader.db_rootpage = m_aHeader.db_keytype = m_aHeader.db_maxkeys = m_aHeader.db_keylen = 0;
65 : 0 : m_aHeader.db_name[0] = '\0';
66 [ # # ]: 0 : construct();
67 : 0 : }
68 : : // -------------------------------------------------------------------------
69 : 0 : ODbaseIndex::ODbaseIndex( ODbaseTable* _pTable,
70 : : const NDXHeader& _rHeader,
71 : : const ::rtl::OUString& _rName)
72 : : :OIndex(_rName,::rtl::OUString(),_rHeader.db_unique,sal_False,sal_False,sal_True)
73 : : ,m_pFileStream(NULL)
74 : : ,m_aHeader(_rHeader)
75 : : ,m_nCurNode(NODE_NOTFOUND)
76 [ # # ][ # # ]: 0 : ,m_pTable(_pTable)
[ # # ][ # # ]
77 : : {
78 [ # # ]: 0 : construct();
79 : 0 : }
80 : : // -----------------------------------------------------------------------------
81 [ # # ][ # # ]: 0 : ODbaseIndex::~ODbaseIndex()
82 : : {
83 [ # # ]: 0 : closeImpl();
84 [ # # ]: 0 : }
85 : : // -------------------------------------------------------------------------
86 : 0 : void ODbaseIndex::refreshColumns()
87 : : {
88 [ # # ]: 0 : ::osl::MutexGuard aGuard( m_aMutex );
89 : :
90 [ # # ]: 0 : TStringVector aVector;
91 [ # # ]: 0 : if(!isNew())
92 : : {
93 : : OSL_ENSURE(m_pFileStream,"FileStream is not opened!");
94 : : OSL_ENSURE(m_aHeader.db_name[0] != '\0',"Invalid name for the column!");
95 [ # # ]: 0 : aVector.push_back(::rtl::OUString::createFromAscii(m_aHeader.db_name));
96 : : }
97 : :
98 [ # # ]: 0 : if(m_pColumns)
99 [ # # ]: 0 : m_pColumns->reFill(aVector);
100 : : else
101 [ # # ][ # # ]: 0 : m_pColumns = new ODbaseIndexColumns(this,m_aMutex,aVector);
[ # # ]
102 : 0 : }
103 : : //--------------------------------------------------------------------------
104 : 0 : Sequence< sal_Int8 > ODbaseIndex::getUnoTunnelImplementationId()
105 : : {
106 : : static ::cppu::OImplementationId * pId = 0;
107 [ # # ]: 0 : if (! pId)
108 : : {
109 [ # # ][ # # ]: 0 : ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
110 [ # # ]: 0 : if (! pId)
111 : : {
112 [ # # ][ # # ]: 0 : static ::cppu::OImplementationId aId;
113 : 0 : pId = &aId;
114 [ # # ]: 0 : }
115 : : }
116 : 0 : return pId->getImplementationId();
117 : : }
118 : :
119 : : // XUnoTunnel
120 : : //------------------------------------------------------------------
121 : 0 : sal_Int64 ODbaseIndex::getSomething( const Sequence< sal_Int8 > & rId ) throw (RuntimeException)
122 : : {
123 [ # # ][ # # ]: 0 : return (rId.getLength() == 16 && 0 == memcmp(getUnoTunnelImplementationId().getConstArray(), rId.getConstArray(), 16 ) )
[ # # ]
124 : : ? reinterpret_cast< sal_Int64 >( this )
125 [ # # ]: 0 : : ODbaseIndex_BASE::getSomething(rId);
[ # # # # ]
126 : : }
127 : : //------------------------------------------------------------------
128 : 0 : ONDXPagePtr ODbaseIndex::getRoot()
129 : : {
130 : 0 : openIndexFile();
131 [ # # ]: 0 : if (!m_aRoot.Is())
132 : : {
133 : 0 : m_nRootPage = m_aHeader.db_rootpage;
134 : 0 : m_nPageCount = m_aHeader.db_pagecount;
135 : 0 : m_aRoot = CreatePage(m_nRootPage,NULL,sal_True);
136 : : }
137 : 0 : return m_aRoot;
138 : : }
139 : : //------------------------------------------------------------------
140 : 0 : sal_Bool ODbaseIndex::openIndexFile()
141 : : {
142 [ # # ]: 0 : if(!m_pFileStream)
143 : : {
144 [ # # ]: 0 : ::rtl::OUString sFile = getCompletePath();
145 [ # # ][ # # ]: 0 : if(UCBContentHelper::Exists(sFile))
146 : : {
147 [ # # ][ # # ]: 0 : m_pFileStream = OFileTable::createStream_simpleError(sFile, STREAM_READWRITE | STREAM_NOCREATE | STREAM_SHARE_DENYWRITE);
[ # # ]
148 [ # # ]: 0 : if (!m_pFileStream)
149 [ # # ][ # # ]: 0 : m_pFileStream = OFileTable::createStream_simpleError(sFile,STREAM_READ | STREAM_NOCREATE | STREAM_SHARE_DENYNONE);
[ # # ]
150 [ # # ]: 0 : if(m_pFileStream)
151 : : {
152 [ # # ]: 0 : m_pFileStream->SetNumberFormatInt(NUMBERFORMAT_INT_LITTLEENDIAN);
153 [ # # ]: 0 : m_pFileStream->SetBufferSize(PAGE_SIZE);
154 [ # # ]: 0 : (*m_pFileStream) >> *this;
155 : : }
156 : : }
157 [ # # ]: 0 : if(!m_pFileStream)
158 : : {
159 : 0 : const ::rtl::OUString sError( m_pTable->getConnection()->getResources().getResourceStringWithSubstitution(
160 : : STR_COULD_NOT_LOAD_FILE,
161 : : "$filename$", sFile
162 [ # # ]: 0 : ) );
163 [ # # ][ # # ]: 0 : ::dbtools::throwGenericSQLException( sError, *this );
164 : 0 : }
165 : : }
166 : :
167 : 0 : return m_pFileStream != NULL;
168 : : }
169 : : //------------------------------------------------------------------
170 : 0 : OIndexIterator* ODbaseIndex::createIterator(OBoolOperator* pOp,
171 : : const OOperand* pOperand)
172 : : {
173 : 0 : openIndexFile();
174 [ # # ]: 0 : return new OIndexIterator(this, pOp, pOperand);
175 : : }
176 : : //------------------------------------------------------------------
177 : 0 : sal_Bool ODbaseIndex::ConvertToKey(ONDXKey* rKey, sal_uInt32 nRec, const ORowSetValue& rValue)
178 : : {
179 : : OSL_ENSURE(m_pFileStream,"FileStream is not opened!");
180 : : // Search a specific value in Index
181 : : // If the Index is unique, the key doesn't matter
182 : : try
183 : : {
184 [ # # ]: 0 : if (m_aHeader.db_keytype == 0)
185 : : {
186 [ # # ][ # # ]: 0 : *rKey = ONDXKey(rValue.getString(), nRec );
[ # # ][ # # ]
187 : : }
188 : : else
189 : : {
190 [ # # ]: 0 : if (rValue.isNull())
191 [ # # ][ # # ]: 0 : *rKey = ONDXKey(rValue.getDouble(), DataType::DOUBLE, nRec );
[ # # ][ # # ]
[ # # ][ # # ]
192 : : else
193 [ # # ][ # # ]: 0 : *rKey = ONDXKey(rValue.getDouble(), nRec );
[ # # ][ # # ]
[ # # ]
194 : : }
195 : : }
196 : 0 : catch (Exception&)
197 : : {
198 : : OSL_ASSERT(0);
199 : 0 : return sal_False;
200 : : }
201 : 0 : return sal_True;
202 : : }
203 : :
204 : : //------------------------------------------------------------------
205 : 0 : sal_Bool ODbaseIndex::Find(sal_uInt32 nRec, const ORowSetValue& rValue)
206 : : {
207 [ # # ]: 0 : openIndexFile();
208 : : OSL_ENSURE(m_pFileStream,"FileStream is not opened!");
209 : : // Search a specific value in Index
210 : : // If the Index is unique, the key doesn't matter
211 [ # # ]: 0 : ONDXKey aKey;
212 [ # # ][ # # ]: 0 : return ConvertToKey(&aKey, nRec, rValue) && getRoot()->Find(aKey);
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
213 : : }
214 : :
215 : : //------------------------------------------------------------------
216 : 0 : sal_Bool ODbaseIndex::Insert(sal_uInt32 nRec, const ORowSetValue& rValue)
217 : : {
218 [ # # ]: 0 : openIndexFile();
219 : : OSL_ENSURE(m_pFileStream,"FileStream is not opened!");
220 [ # # ]: 0 : ONDXKey aKey;
221 : :
222 : : // Does the value already exist
223 : : // Use Find() always to determine the actual leaf
224 [ # # ][ # # ]: 0 : if (!ConvertToKey(&aKey, nRec, rValue) || (getRoot()->Find(aKey) && isUnique()))
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # # # ]
225 : 0 : return sal_False;
226 : :
227 [ # # ][ # # ]: 0 : ONDXNode aNewNode(aKey);
[ # # ]
228 : :
229 : : // insert in the current leaf
230 [ # # ]: 0 : if (!m_aCurLeaf.Is())
231 : 0 : return sal_False;
232 : :
233 [ # # ]: 0 : sal_Bool bResult = m_aCurLeaf->Insert(aNewNode);
234 [ # # ]: 0 : Release(bResult);
235 : :
236 [ # # ][ # # ]: 0 : return bResult;
237 : : }
238 : :
239 : : //------------------------------------------------------------------
240 : 0 : sal_Bool ODbaseIndex::Update(sal_uInt32 nRec, const ORowSetValue& rOldValue,
241 : : const ORowSetValue& rNewValue)
242 : : {
243 [ # # ]: 0 : openIndexFile();
244 : : OSL_ENSURE(m_pFileStream,"FileStream is not opened!");
245 [ # # ]: 0 : ONDXKey aKey;
246 [ # # ][ # # ]: 0 : if (!ConvertToKey(&aKey, nRec, rNewValue) || (isUnique() && getRoot()->Find(aKey)))
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # # # ]
247 : 0 : return sal_False;
248 : : else
249 [ # # ][ # # ]: 0 : return Delete(nRec, rOldValue) && Insert(nRec,rNewValue);
[ # # ][ # # ]
[ # # ]
250 : : }
251 : :
252 : : //------------------------------------------------------------------
253 : 0 : sal_Bool ODbaseIndex::Delete(sal_uInt32 nRec, const ORowSetValue& rValue)
254 : : {
255 [ # # ]: 0 : openIndexFile();
256 : : OSL_ENSURE(m_pFileStream,"FileStream is not opened!");
257 : : // Does the value already exist
258 : : // Always use Find() to determine the actual leaf
259 [ # # ]: 0 : ONDXKey aKey;
260 [ # # ][ # # ]: 0 : if (!ConvertToKey(&aKey, nRec, rValue) || !getRoot()->Find(aKey))
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
[ # # # # ]
261 : 0 : return sal_False;
262 : :
263 [ # # ][ # # ]: 0 : ONDXNode aNewNode(aKey);
[ # # ]
264 : :
265 : : // insert in the current leaf
266 [ # # ]: 0 : if (!m_aCurLeaf.Is())
267 : 0 : return sal_False;
268 : : #if OSL_DEBUG_LEVEL > 1
269 : : m_aRoot->PrintPage();
270 : : #endif
271 : :
272 [ # # ][ # # ]: 0 : return m_aCurLeaf->Delete(m_nCurNode);
[ # # ]
273 : : }
274 : : //------------------------------------------------------------------
275 : 0 : void ODbaseIndex::Collect(ONDXPage* pPage)
276 : : {
277 [ # # ]: 0 : if (pPage)
278 : 0 : m_aCollector.push_back(pPage);
279 : 0 : }
280 : : //------------------------------------------------------------------
281 : 0 : void ODbaseIndex::Release(sal_Bool bSave)
282 : : {
283 : : // Release the Index-recources
284 : 0 : m_bUseCollector = sal_False;
285 : :
286 [ # # ]: 0 : if (m_aCurLeaf.Is())
287 : : {
288 : 0 : m_aCurLeaf->Release(bSave);
289 : 0 : m_aCurLeaf.Clear();
290 : : }
291 : :
292 : : // Release the root
293 [ # # ]: 0 : if (m_aRoot.Is())
294 : : {
295 : 0 : m_aRoot->Release(bSave);
296 : 0 : m_aRoot.Clear();
297 : : }
298 : : // Release all references, before the FileStream will be closed
299 [ # # ]: 0 : for (sal_uIntPtr i = 0; i < m_aCollector.size(); i++)
300 : 0 : m_aCollector[i]->QueryDelete();
301 : :
302 : 0 : m_aCollector.clear();
303 : :
304 : : // Header modified?
305 [ # # ][ # # ]: 0 : if (bSave && (m_aHeader.db_rootpage != m_nRootPage ||
[ # # ]
306 : : m_aHeader.db_pagecount != m_nPageCount))
307 : : {
308 : 0 : m_aHeader.db_rootpage = m_nRootPage;
309 : 0 : m_aHeader.db_pagecount = m_nPageCount;
310 : 0 : (*m_pFileStream) << *this;
311 : : }
312 : 0 : m_nRootPage = m_nPageCount = 0;
313 : 0 : m_nCurNode = NODE_NOTFOUND;
314 : :
315 : 0 : closeImpl();
316 : 0 : }
317 : : // -----------------------------------------------------------------------------
318 : 0 : void ODbaseIndex::closeImpl()
319 : : {
320 [ # # ]: 0 : if(m_pFileStream)
321 : : {
322 [ # # ]: 0 : delete m_pFileStream;
323 : 0 : m_pFileStream = NULL;
324 : : }
325 : 0 : }
326 : : //------------------------------------------------------------------
327 : 0 : ONDXPage* ODbaseIndex::CreatePage(sal_uInt32 nPagePos, ONDXPage* pParent, sal_Bool bLoad)
328 : : {
329 : : OSL_ENSURE(m_pFileStream,"FileStream is not opened!");
330 : :
331 : : ONDXPage* pPage;
332 [ # # ]: 0 : if ( !m_aCollector.empty() )
333 : : {
334 [ # # ]: 0 : pPage = *(m_aCollector.rbegin());
335 : 0 : m_aCollector.pop_back();
336 : 0 : pPage->SetPagePos(nPagePos);
337 [ # # ]: 0 : pPage->SetParent(pParent);
338 : : }
339 : : else
340 [ # # ]: 0 : pPage = new ONDXPage(*this, nPagePos, pParent);
341 : :
342 [ # # ]: 0 : if (bLoad)
343 : 0 : (*m_pFileStream) >> *pPage;
344 : :
345 : 0 : return pPage;
346 : : }
347 : :
348 : : //------------------------------------------------------------------
349 : 0 : SvStream& connectivity::dbase::operator >> (SvStream &rStream, ODbaseIndex& rIndex)
350 : : {
351 : 0 : rStream.Seek(0);
352 : 0 : rStream.Read(&rIndex.m_aHeader,PAGE_SIZE);
353 : :
354 : 0 : rIndex.m_nRootPage = rIndex.m_aHeader.db_rootpage;
355 : 0 : rIndex.m_nPageCount = rIndex.m_aHeader.db_pagecount;
356 : 0 : return rStream;
357 : : }
358 : : //------------------------------------------------------------------
359 : 0 : SvStream& connectivity::dbase::operator << (SvStream &rStream, ODbaseIndex& rIndex)
360 : : {
361 : 0 : rStream.Seek(0);
362 : 0 : OSL_VERIFY_EQUALS( rStream.Write(&rIndex.m_aHeader,PAGE_SIZE), PAGE_SIZE, "Write not successful: Wrong header size for dbase index!");
363 : 0 : return rStream;
364 : : }
365 : : // -------------------------------------------------------------------------
366 : 0 : ::rtl::OUString ODbaseIndex::getCompletePath()
367 : : {
368 : 0 : ::rtl::OUString sDir = m_pTable->getConnection()->getURL();
369 [ # # ][ # # ]: 0 : sDir += OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_DELIMITER);
370 : 0 : sDir += m_Name;
371 : 0 : sDir += ::rtl::OUString(".ndx");
372 : 0 : return sDir;
373 : : }
374 : : //------------------------------------------------------------------
375 : 0 : void ODbaseIndex::createINFEntry()
376 : : {
377 : : // synchronize inf-file
378 [ # # ]: 0 : String sEntry = m_Name;
379 [ # # ]: 0 : sEntry += rtl::OUString(".ndx");
380 : :
381 : 0 : ::rtl::OUString sCfgFile(m_pTable->getConnection()->getURL());
382 [ # # ][ # # ]: 0 : sCfgFile += OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_DELIMITER);
383 : 0 : sCfgFile += m_pTable->getName();
384 : 0 : sCfgFile += ::rtl::OUString(".inf");
385 : :
386 : 0 : rtl::OUString sPhysicalPath;
387 [ # # ]: 0 : LocalFileHelper::ConvertURLToPhysicalName(sCfgFile,sPhysicalPath);
388 : :
389 [ # # ]: 0 : Config aInfFile(sPhysicalPath);
390 [ # # ]: 0 : aInfFile.SetGroup(dBASE_III_GROUP);
391 : :
392 [ # # ]: 0 : sal_uInt16 nSuffix = aInfFile.GetKeyCount();
393 : 0 : rtl::OString aNewEntry,aKeyName;
394 : 0 : sal_Bool bCase = isCaseSensitive();
395 [ # # ]: 0 : while (aNewEntry.isEmpty())
396 : : {
397 : 0 : aNewEntry = rtl::OString(RTL_CONSTASCII_STRINGPARAM("NDX"));
398 : 0 : aNewEntry += rtl::OString::valueOf(static_cast<sal_Int32>(++nSuffix));
399 [ # # ][ # # ]: 0 : for (sal_uInt16 i = 0; i < aInfFile.GetKeyCount(); i++)
400 : : {
401 [ # # ]: 0 : aKeyName = aInfFile.GetKeyName(i);
402 [ # # ][ # # ]: 0 : if (bCase ? aKeyName.equals(aNewEntry) : aKeyName.equalsIgnoreAsciiCase(aNewEntry))
403 : : {
404 : 0 : aNewEntry = rtl::OString();
405 : 0 : break;
406 : : }
407 : : }
408 : : }
409 [ # # ][ # # ]: 0 : aInfFile.WriteKey(aNewEntry, rtl::OUStringToOString(sEntry, m_pTable->getConnection()->getTextEncoding()));
[ # # ][ # # ]
[ # # ]
410 : 0 : }
411 : : // -------------------------------------------------------------------------
412 : 0 : sal_Bool ODbaseIndex::DropImpl()
413 : : {
414 [ # # ]: 0 : closeImpl();
415 : :
416 [ # # ]: 0 : ::rtl::OUString sPath = getCompletePath();
417 [ # # ][ # # ]: 0 : if(UCBContentHelper::Exists(sPath))
418 : : {
419 [ # # ][ # # ]: 0 : if(!UCBContentHelper::Kill(sPath))
420 [ # # ][ # # ]: 0 : m_pTable->getConnection()->throwGenericSQLException(STR_COULD_NOT_DELETE_INDEX,*m_pTable);
421 : : }
422 : :
423 : : // synchronize inf-file
424 : 0 : ::rtl::OUString sCfgFile(m_pTable->getConnection()->getURL());
425 [ # # ][ # # ]: 0 : sCfgFile += OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_DELIMITER);
426 : 0 : sCfgFile += m_pTable->getName();
427 : 0 : sCfgFile += ::rtl::OUString(".inf");
428 : :
429 : 0 : rtl::OUString sPhysicalPath;
430 : : OSL_VERIFY_RES( LocalFileHelper::ConvertURLToPhysicalName(sCfgFile, sPhysicalPath),
431 [ # # ]: 0 : "Can not convert Config Filename into Physical Name!");
432 : :
433 [ # # ]: 0 : Config aInfFile(sPhysicalPath);
434 [ # # ]: 0 : aInfFile.SetGroup(dBASE_III_GROUP);
435 [ # # ]: 0 : sal_uInt16 nKeyCnt = aInfFile.GetKeyCount();
436 : 0 : rtl::OString aKeyName;
437 [ # # ]: 0 : String sEntry = m_Name;
438 [ # # ]: 0 : sEntry += rtl::OUString(".ndx");
439 : :
440 : : // delete entries from the inf file
441 [ # # ]: 0 : for (sal_uInt16 nKey = 0; nKey < nKeyCnt; nKey++)
442 : : {
443 : : // References the Key to an Index-file?
444 [ # # ]: 0 : aKeyName = aInfFile.GetKeyName( nKey );
445 [ # # ]: 0 : if (aKeyName.copy(0,3).equalsL(RTL_CONSTASCII_STRINGPARAM("NDX")))
446 : : {
447 [ # # ][ # # ]: 0 : if(sEntry == String(rtl::OStringToOUString(aInfFile.ReadKey(aKeyName),m_pTable->getConnection()->getTextEncoding())))
[ # # ][ # # ]
[ # # ][ # # ]
448 : : {
449 [ # # ]: 0 : aInfFile.DeleteKey(aKeyName);
450 : 0 : break;
451 : : }
452 : : }
453 : : }
454 [ # # ][ # # ]: 0 : return sal_True;
455 : : }
456 : : // -------------------------------------------------------------------------
457 : 0 : void ODbaseIndex::impl_killFileAndthrowError_throw(sal_uInt16 _nErrorId,const ::rtl::OUString& _sFile)
458 : : {
459 : 0 : closeImpl();
460 [ # # ]: 0 : if(UCBContentHelper::Exists(_sFile))
461 : 0 : UCBContentHelper::Kill(_sFile);
462 [ # # ]: 0 : m_pTable->getConnection()->throwGenericSQLException(_nErrorId,*this);
463 : 0 : }
464 : : //------------------------------------------------------------------
465 : 0 : sal_Bool ODbaseIndex::CreateImpl()
466 : : {
467 : : // Create the Index
468 [ # # ]: 0 : const ::rtl::OUString sFile = getCompletePath();
469 [ # # ][ # # ]: 0 : if(UCBContentHelper::Exists(sFile))
470 : : {
471 : 0 : const ::rtl::OUString sError( m_pTable->getConnection()->getResources().getResourceStringWithSubstitution(
472 : : STR_COULD_NOT_CREATE_INDEX_NAME,
473 : : "$filename$", sFile
474 [ # # ]: 0 : ) );
475 [ # # ][ # # ]: 0 : ::dbtools::throwGenericSQLException( sError, *this );
476 : : }
477 : : // Index comprises only one column
478 [ # # ][ # # ]: 0 : if (m_pColumns->getCount() > 1)
479 [ # # ][ # # ]: 0 : m_pTable->getConnection()->throwGenericSQLException(STR_ONL_ONE_COLUMN_PER_INDEX,*this);
480 : :
481 [ # # ][ # # ]: 0 : Reference<XFastPropertySet> xCol(m_pColumns->getByIndex(0),UNO_QUERY);
482 : :
483 : : // Is the column already indexed?
484 [ # # ]: 0 : if ( !xCol.is() )
485 [ # # ][ # # ]: 0 : ::dbtools::throwFunctionSequenceException(*this);
486 : :
487 : : // create the index file
488 [ # # ][ # # ]: 0 : m_pFileStream = OFileTable::createStream_simpleError(sFile,STREAM_READWRITE | STREAM_SHARE_DENYWRITE | STREAM_TRUNC);
[ # # ]
489 [ # # ]: 0 : if (!m_pFileStream)
490 : : {
491 : 0 : const ::rtl::OUString sError( m_pTable->getConnection()->getResources().getResourceStringWithSubstitution(
492 : : STR_COULD_NOT_LOAD_FILE,
493 : : "$filename$", sFile
494 [ # # ]: 0 : ) );
495 [ # # ][ # # ]: 0 : ::dbtools::throwGenericSQLException( sError, *this );
496 : : }
497 : :
498 [ # # ]: 0 : m_pFileStream->SetNumberFormatInt(NUMBERFORMAT_INT_LITTLEENDIAN);
499 [ # # ]: 0 : m_pFileStream->SetBufferSize(PAGE_SIZE);
500 : :
501 : : // firstly the result must be sorted
502 [ # # ]: 0 : utl::SharedUNOComponent<XStatement> xStmt;
503 [ # # ]: 0 : utl::SharedUNOComponent<XResultSet> xSet;
504 [ # # ]: 0 : String aName;
505 : : try
506 : : {
507 [ # # ][ # # ]: 0 : xStmt.set( m_pTable->getConnection()->createStatement(), UNO_SET_THROW);
508 : :
509 [ # # ][ # # ]: 0 : aName = getString(xCol->getFastPropertyValue(PROPERTY_ID_NAME));
[ # # ][ # # ]
510 : :
511 [ # # ][ # # ]: 0 : const String aQuote(m_pTable->getConnection()->getMetaData()->getIdentifierQuoteString());
[ # # ][ # # ]
512 [ # # ]: 0 : String aStatement;
513 [ # # ]: 0 : aStatement.AssignAscii("SELECT ");
514 [ # # ]: 0 : aStatement += aQuote;
515 [ # # ]: 0 : aStatement += aName;
516 [ # # ]: 0 : aStatement += aQuote;
517 [ # # ]: 0 : aStatement.AppendAscii(" FROM ");
518 [ # # ]: 0 : aStatement += aQuote;
519 [ # # ]: 0 : aStatement += m_pTable->getName().getStr();
520 [ # # ]: 0 : aStatement += aQuote;
521 [ # # ]: 0 : aStatement.AppendAscii(" ORDER BY ");
522 [ # # ]: 0 : aStatement += aQuote;
523 [ # # ]: 0 : aStatement += aName;
524 [ # # ]: 0 : aStatement += aQuote;
525 : :
526 [ # # ][ # # ]: 0 : xSet.set( xStmt->executeQuery(aStatement),UNO_SET_THROW );
[ # # ][ # # ]
[ # # ][ # # ]
527 : : }
528 [ # # # # ]: 0 : catch(const Exception& )
529 : : {
530 [ # # ]: 0 : impl_killFileAndthrowError_throw(STR_COULD_NOT_CREATE_INDEX,sFile);
531 : : }
532 [ # # ]: 0 : if (!xSet.is())
533 : : {
534 [ # # ]: 0 : impl_killFileAndthrowError_throw(STR_COULD_NOT_CREATE_INDEX,sFile);
535 : : }
536 : :
537 : : // Set the header info
538 : 0 : memset(&m_aHeader,0,sizeof(m_aHeader));
539 : 0 : sal_Int32 nType = 0;
540 [ # # ]: 0 : ::rtl::Reference<OSQLColumns> aCols = m_pTable->getTableColumns();
541 [ # # ][ # # ]: 0 : const Reference< XPropertySet > xTableCol(*find(aCols->get().begin(),aCols->get().end(),aName,::comphelper::UStringMixEqual(isCaseSensitive())));
[ # # ][ # # ]
542 : :
543 [ # # ][ # # ]: 0 : xTableCol->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_TYPE)) >>= nType;
[ # # ][ # # ]
544 : :
545 [ # # ][ # # ]: 0 : m_aHeader.db_keytype = (nType == DataType::VARCHAR || nType == DataType::CHAR) ? 0 : 1;
546 [ # # ][ # # ]: 0 : m_aHeader.db_keylen = (m_aHeader.db_keytype) ? 8 : (sal_uInt16)getINT32(xTableCol->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_PRECISION)));
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # # # ]
547 : 0 : m_aHeader.db_keylen = (( m_aHeader.db_keylen - 1) / 4 + 1) * 4;
548 : 0 : m_aHeader.db_maxkeys = (PAGE_SIZE - 4) / (8 + m_aHeader.db_keylen);
549 [ # # ]: 0 : if ( m_aHeader.db_maxkeys < 3 )
550 : : {
551 [ # # ]: 0 : impl_killFileAndthrowError_throw(STR_COULD_NOT_CREATE_INDEX_KEYSIZE,sFile);
552 : : }
553 : :
554 [ # # ]: 0 : m_pFileStream->SetStreamSize(PAGE_SIZE);
555 : :
556 [ # # ][ # # ]: 0 : rtl::OString aCol(rtl::OUStringToOString(aName, m_pTable->getConnection()->getTextEncoding()));
557 [ # # ]: 0 : strncpy(m_aHeader.db_name, aCol.getStr(), std::min<size_t>(sizeof(m_aHeader.db_name), aCol.getLength()));
558 [ # # ]: 0 : m_aHeader.db_unique = m_IsUnique ? 1: 0;
559 : 0 : m_aHeader.db_keyrec = m_aHeader.db_keylen + 8;
560 : :
561 : : // modifications of the header are detected by differences between
562 : : // the HeaderInfo and nRootPage or nPageCount respectively
563 : 0 : m_nRootPage = 1;
564 : 0 : m_nPageCount = 2;
565 : :
566 [ # # ][ # # ]: 0 : m_aCurLeaf = m_aRoot = CreatePage(m_nRootPage);
[ # # ]
567 : 0 : m_aRoot->SetModified(sal_True);
568 : :
569 : 0 : m_bUseCollector = sal_True;
570 : :
571 : 0 : sal_Int32 nRowsLeft = 0;
572 [ # # ]: 0 : Reference<XRow> xRow(xSet,UNO_QUERY);
573 : :
574 [ # # ][ # # ]: 0 : if(xSet->last())
[ # # ]
575 : : {
576 [ # # ]: 0 : Reference< XUnoTunnel> xTunnel(xSet,UNO_QUERY);
577 : 0 : ODbaseResultSet* pDbaseRes = NULL;
578 [ # # ]: 0 : if(xTunnel.is())
579 [ # # ][ # # ]: 0 : pDbaseRes = reinterpret_cast< ODbaseResultSet* >( xTunnel->getSomething(ODbaseResultSet::getUnoTunnelImplementationId()) );
[ # # ][ # # ]
580 : : OSL_ENSURE(pDbaseRes,"No dbase resultset found? What's going on here!");
581 [ # # ]: 0 : Reference<XRowLocate> xRowLocate(xSet,UNO_QUERY);
582 [ # # ][ # # ]: 0 : nRowsLeft = xSet->getRow();
583 : :
584 [ # # ][ # # ]: 0 : xSet->beforeFirst();
585 : 0 : ORowSetValue atmpValue=ORowSetValue();
586 [ # # ]: 0 : ONDXKey aKey(atmpValue, nType, 0);
587 [ # # ]: 0 : ONDXKey aInsertKey(atmpValue, nType, 0);
588 : : // Create the index structure
589 [ # # ][ # # ]: 0 : while (xSet->next())
[ # # ]
590 : : {
591 [ # # ][ # # ]: 0 : ORowSetValue aValue(m_aHeader.db_keytype ? ORowSetValue(xRow->getDouble(1)) : ORowSetValue(xRow->getString(1)));
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
[ # # # # ]
592 : : // checking for duplicate entries
593 [ # # ][ # # ]: 0 : if (m_IsUnique && m_nCurNode != NODE_NOTFOUND)
594 : : {
595 [ # # ]: 0 : aKey.setValue(aValue);
596 [ # # ][ # # ]: 0 : if (aKey == (*m_aCurLeaf)[m_nCurNode].GetKey())
[ # # ]
597 : : {
598 [ # # ]: 0 : impl_killFileAndthrowError_throw(STR_COULD_NOT_CREATE_INDEX_NOT_UNIQUE,sFile);
599 : : }
600 : : }
601 [ # # ]: 0 : aInsertKey.setValue(aValue);
602 [ # # ]: 0 : aInsertKey.setRecord(pDbaseRes->getCurrentFilePos());
603 : :
604 [ # # ][ # # ]: 0 : ONDXNode aNewNode(aInsertKey);
[ # # ]
605 [ # # ][ # # ]: 0 : if (!m_aCurLeaf->Insert(aNewNode, --nRowsLeft))
606 : : break;
607 [ # # ][ # # ]: 0 : }
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
608 : : }
609 : :
610 [ # # ]: 0 : if(nRowsLeft)
611 : : {
612 [ # # ]: 0 : impl_killFileAndthrowError_throw(STR_COULD_NOT_CREATE_INDEX,sFile);
613 : : }
614 [ # # ]: 0 : Release();
615 [ # # ]: 0 : createINFEntry();
616 [ # # ][ # # ]: 0 : return sal_True;
[ # # ][ # # ]
617 : : }
618 : : // -----------------------------------------------------------------------------
619 : : // -----------------------------------------------------------------------------
620 : 0 : void SAL_CALL ODbaseIndex::acquire() throw()
621 : : {
622 : 0 : ODbaseIndex_BASE::acquire();
623 : 0 : }
624 : : // -----------------------------------------------------------------------------
625 : 0 : void SAL_CALL ODbaseIndex::release() throw()
626 : : {
627 : 0 : ODbaseIndex_BASE::release();
628 : 0 : }
629 : : // -----------------------------------------------------------------------------
630 : :
631 : :
632 : :
633 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|