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