/**************************************************************
 * 
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 * 
 *************************************************************/



// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_connectivity.hxx"
#include "dbase/DIndex.hxx"
#include "dbase/DIndexColumns.hxx"
#include <com/sun/star/lang/DisposedException.hpp>
#include "connectivity/sdbcx/VColumn.hxx"
#include <comphelper/sequence.hxx>
#include "dbase/DTable.hxx"
#include "dbase/DIndexIter.hxx"
#include <tools/config.hxx>
#include "connectivity/CommonTools.hxx"
#include <com/sun/star/sdbc/XResultSetMetaData.hpp>
#include <com/sun/star/sdbc/XResultSet.hpp>
#include <com/sun/star/sdbcx/XRowLocate.hpp>
#include <com/sun/star/sdbc/XRow.hpp>
#include <comphelper/extract.hxx>
#include <unotools/localfilehelper.hxx>
#include <unotools/ucbhelper.hxx>
#include <comphelper/types.hxx>
#include <connectivity/dbexception.hxx>
#include "dbase/DResultSet.hxx"
#include "diagnose_ex.h"
#include <comphelper/types.hxx>
#include "resource/dbase_res.hrc"
#include <unotools/sharedunocomponent.hxx>

using namespace ::comphelper;
// -------------------------------------------------------------------------
using namespace connectivity;
using namespace utl;
using namespace ::cppu;
using namespace connectivity::file;
using namespace connectivity::sdbcx;
using namespace connectivity::dbase;
using namespace com::sun::star::sdbc;
using namespace com::sun::star::sdbcx;
using namespace com::sun::star::uno;
using namespace com::sun::star::beans;
using namespace com::sun::star::lang;

IMPLEMENT_SERVICE_INFO(ODbaseIndex,"com.sun.star.sdbcx.driver.dbase.Index","com.sun.star.sdbcx.Index");
// -------------------------------------------------------------------------
ODbaseIndex::ODbaseIndex(ODbaseTable* _pTable) : OIndex(sal_True/*_pTable->getConnection()->getMetaData()->supportsMixedCaseQuotedIdentifiers()*/)
	,m_pFileStream(NULL)
	,m_nCurNode(NODE_NOTFOUND)
    ,m_pTable(_pTable)
{
	m_aHeader.db_pagecount = m_aHeader.db_rootpage = m_aHeader.db_keytype = m_aHeader.db_maxkeys = m_aHeader.db_keylen = 0;
	m_aHeader.db_name[0] = '\0';
	construct();
}
// -------------------------------------------------------------------------
ODbaseIndex::ODbaseIndex(	ODbaseTable* _pTable,
							const NDXHeader& _rHeader,
							const ::rtl::OUString& _rName)
	:OIndex(_rName,::rtl::OUString(),_rHeader.db_unique,sal_False,sal_False,sal_True) // _pTable->getConnection()->getMetaData()->supportsMixedCaseQuotedIdentifiers()
	,m_pFileStream(NULL)
    ,m_aHeader(_rHeader)
	,m_nCurNode(NODE_NOTFOUND)
    ,m_pTable(_pTable)
{
	construct();
}
// -----------------------------------------------------------------------------
ODbaseIndex::~ODbaseIndex()
{
	closeImpl();
}
// -------------------------------------------------------------------------
void ODbaseIndex::refreshColumns()
{
	::osl::MutexGuard aGuard( m_aMutex );

	TStringVector aVector;
	if(!isNew())
	{
		OSL_ENSURE(m_pFileStream,"FileStream is not opened!");
		OSL_ENSURE(m_aHeader.db_name[0] != '\0',"Invalid name for the column!");
		aVector.push_back(::rtl::OUString::createFromAscii(m_aHeader.db_name));
	}

	if(m_pColumns)
		m_pColumns->reFill(aVector);
	else
		m_pColumns = new ODbaseIndexColumns(this,m_aMutex,aVector);
}
//--------------------------------------------------------------------------
Sequence< sal_Int8 > ODbaseIndex::getUnoTunnelImplementationId()
{
	static ::cppu::OImplementationId * pId = 0;
	if (! pId)
	{
		::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
		if (! pId)
		{
			static ::cppu::OImplementationId aId;
			pId = &aId;
		}
	}
	return pId->getImplementationId();
}

// XUnoTunnel
//------------------------------------------------------------------
sal_Int64 ODbaseIndex::getSomething( const Sequence< sal_Int8 > & rId ) throw (RuntimeException)
{
	return (rId.getLength() == 16 && 0 == rtl_compareMemory(getUnoTunnelImplementationId().getConstArray(),  rId.getConstArray(), 16 ) )
				? reinterpret_cast< sal_Int64 >( this )
				: ODbaseIndex_BASE::getSomething(rId);
}
//------------------------------------------------------------------
ONDXPagePtr ODbaseIndex::getRoot()
{
	openIndexFile();
	if (!m_aRoot.Is())
	{
		m_nRootPage = m_aHeader.db_rootpage;
		m_nPageCount = m_aHeader.db_pagecount;
		m_aRoot = CreatePage(m_nRootPage,NULL,sal_True);
	}
	return m_aRoot;
}
//------------------------------------------------------------------
sal_Bool ODbaseIndex::openIndexFile()
{
	if(!m_pFileStream)
	{
		::rtl::OUString sFile = getCompletePath();
		if(UCBContentHelper::Exists(sFile))
		{
			m_pFileStream = OFileTable::createStream_simpleError(sFile, STREAM_READWRITE | STREAM_NOCREATE | STREAM_SHARE_DENYWRITE);
			if (!m_pFileStream)
				m_pFileStream = OFileTable::createStream_simpleError(sFile,STREAM_READ | STREAM_NOCREATE | STREAM_SHARE_DENYNONE);
			if(m_pFileStream)
			{
				m_pFileStream->SetNumberFormatInt(NUMBERFORMAT_INT_LITTLEENDIAN);
				m_pFileStream->SetBufferSize(PAGE_SIZE);
				(*m_pFileStream) >> *this;
			}
		}
		if(!m_pFileStream)
		{
            const ::rtl::OUString sError( m_pTable->getConnection()->getResources().getResourceStringWithSubstitution(
                STR_COULD_NOT_LOAD_FILE,
                "$filename$", sFile
             ) );
            ::dbtools::throwGenericSQLException( sError, *this );
		}
	}

	return m_pFileStream != NULL;
}
//------------------------------------------------------------------
OIndexIterator* ODbaseIndex::createIterator(OBoolOperator* pOp,
											const OOperand* pOperand)
{
	openIndexFile();
	return new OIndexIterator(this, pOp, pOperand);
}
//------------------------------------------------------------------
sal_Bool ODbaseIndex::ConvertToKey(ONDXKey* rKey, sal_uInt32 nRec, const ORowSetValue& rValue)
{
	OSL_ENSURE(m_pFileStream,"FileStream is not opened!");
	// Sucht ein bestimmten Wert im Index
	// Wenn der Index Unique ist, interssiert der Key nicht, sonst ja
	try
	{
		if (m_aHeader.db_keytype == 0)
		{
			*rKey = ONDXKey(rValue.getString(), nRec );
		}
		else
		{
			if (rValue.isNull())
				*rKey = ONDXKey(rValue.getDouble(), DataType::DOUBLE, nRec );
			else
				*rKey = ONDXKey(rValue.getDouble(), nRec );
		}
	}
	catch (Exception&)
	{
		OSL_ASSERT(0);
		return sal_False;
	}
	return sal_True;
}

//------------------------------------------------------------------
sal_Bool ODbaseIndex::Find(sal_uInt32 nRec, const ORowSetValue& rValue)
{
	openIndexFile();
	OSL_ENSURE(m_pFileStream,"FileStream is not opened!");
	// Sucht ein bestimmten Wert im Index
	// Wenn der Index Unique ist, interssiert der Key nicht, sonst ja
	ONDXKey aKey;
	return ConvertToKey(&aKey, nRec, rValue) && getRoot()->Find(aKey);
}

//------------------------------------------------------------------
sal_Bool ODbaseIndex::Insert(sal_uInt32 nRec, const ORowSetValue& rValue)
{
	openIndexFile();
	OSL_ENSURE(m_pFileStream,"FileStream is not opened!");
	ONDXKey aKey;

	// Existiert der Wert bereits
	// Find immer verwenden um das aktuelle Blatt zu bestimmen
	if (!ConvertToKey(&aKey, nRec, rValue) || (getRoot()->Find(aKey) && isUnique()))
		return sal_False;

	ONDXNode aNewNode(aKey);

	// einfuegen in das aktuelle Blatt
	if (!m_aCurLeaf.Is())
		return sal_False;

	sal_Bool bResult = m_aCurLeaf->Insert(aNewNode);
	Release(bResult);

	return bResult;
}

//------------------------------------------------------------------
sal_Bool ODbaseIndex::Update(sal_uInt32 nRec, const ORowSetValue& rOldValue,
						 const ORowSetValue& rNewValue)
{
	openIndexFile();
	OSL_ENSURE(m_pFileStream,"FileStream is not opened!");
	ONDXKey aKey;
	if (!ConvertToKey(&aKey, nRec, rNewValue) || (isUnique() && getRoot()->Find(aKey)))
		return sal_False;
	else
		return Delete(nRec, rOldValue) && Insert(nRec,rNewValue);
}

//------------------------------------------------------------------
sal_Bool ODbaseIndex::Delete(sal_uInt32 nRec, const ORowSetValue& rValue)
{
	openIndexFile();
	OSL_ENSURE(m_pFileStream,"FileStream is not opened!");
	// Existiert der Wert bereits
	// Find immer verwenden um das aktuelle Blatt zu bestimmen
	ONDXKey aKey;
	if (!ConvertToKey(&aKey, nRec, rValue) || !getRoot()->Find(aKey))
		return sal_False;

	ONDXNode aNewNode(aKey);

	// einfuegen in das aktuelle Blatt
	if (!m_aCurLeaf.Is())
		return sal_False;
#if OSL_DEBUG_LEVEL > 1
	m_aRoot->PrintPage();
#endif

	return m_aCurLeaf->Delete(m_nCurNode);
}
//------------------------------------------------------------------
void ODbaseIndex::Collect(ONDXPage* pPage)
{
	if (pPage)
		m_aCollector.push_back(pPage);
}
//------------------------------------------------------------------
void ODbaseIndex::Release(sal_Bool bSave)
{
	// Freigeben der Indexressourcen
	m_bUseCollector = sal_False;

	if (m_aCurLeaf.Is())
	{
		m_aCurLeaf->Release(bSave);
		m_aCurLeaf.Clear();
	}

	// Wurzel freigeben
	if (m_aRoot.Is())
	{
		m_aRoot->Release(bSave);
		m_aRoot.Clear();
	}
	// alle Referenzen freigeben, bevor der FileStream geschlossen wird
	for (sal_uIntPtr i = 0; i < m_aCollector.size(); i++)
		m_aCollector[i]->QueryDelete();

	m_aCollector.clear();

	// Header modifiziert ?
	if (bSave && (m_aHeader.db_rootpage != m_nRootPage ||
		m_aHeader.db_pagecount != m_nPageCount))
	{
		m_aHeader.db_rootpage = m_nRootPage;
		m_aHeader.db_pagecount = m_nPageCount;
		(*m_pFileStream) << *this;
	}
	m_nRootPage = m_nPageCount = 0;
	m_nCurNode = NODE_NOTFOUND;

	closeImpl();
}
// -----------------------------------------------------------------------------
void ODbaseIndex::closeImpl()
{
	if(m_pFileStream)
	{
		delete m_pFileStream;
		m_pFileStream = NULL;
	}
}
//------------------------------------------------------------------
ONDXPage* ODbaseIndex::CreatePage(sal_uInt32 nPagePos, ONDXPage* pParent, sal_Bool bLoad)
{
	OSL_ENSURE(m_pFileStream,"FileStream is not opened!");

	ONDXPage* pPage;
	if ( !m_aCollector.empty() )
	{
		pPage = *(m_aCollector.rbegin());
		m_aCollector.pop_back();
		pPage->SetPagePos(nPagePos);
		pPage->SetParent(pParent);
	}
	else
		pPage = new ONDXPage(*this, nPagePos, pParent);

	if (bLoad)
		(*m_pFileStream) >> *pPage;

	return pPage;
}

//------------------------------------------------------------------
SvStream& connectivity::dbase::operator >> (SvStream &rStream, ODbaseIndex& rIndex)
{
	rStream.Seek(0);
	rStream.Read(&rIndex.m_aHeader,PAGE_SIZE);

/* OJ: no longer needed
	// Text convertierung
	ByteString aText(rIndex.m_aHeader.db_name);
	//	aText.Convert(rIndex.m_pTable->getConnection()->GetCharacterSet(), m_pTable->getConnection()->getTextEncoding());
	//	aText.Convert(rIndex.m_pTable->getConnection()->GetCharacterSet(), m_pTable->getConnection()->getTextEncoding());
	strcpy(rIndex.m_aHeader.db_name,aText.GetBuffer());
*/
	rIndex.m_nRootPage = rIndex.m_aHeader.db_rootpage;
	rIndex.m_nPageCount = rIndex.m_aHeader.db_pagecount;
	return rStream;
}
//------------------------------------------------------------------
SvStream& connectivity::dbase::operator << (SvStream &rStream, ODbaseIndex& rIndex)
{
	rStream.Seek(0);
/* OJ: no longer needed
	ByteString aText(rIndex.m_aHeader.db_name);
	//	aText.Convert(m_pTable->getConnection()->getTextEncoding(), rIndex.m_pTable->getConnection()->GetCharacterSet());
	strcpy(rIndex.m_aHeader.db_name,aText.GetBuffer());
*/
    OSL_VERIFY_EQUALS( rStream.Write(&rIndex.m_aHeader,PAGE_SIZE), PAGE_SIZE, "Write not successful: Wrong header size for dbase index!");
	return rStream;
}
// -------------------------------------------------------------------------
::rtl::OUString ODbaseIndex::getCompletePath()
{
	::rtl::OUString sDir = m_pTable->getConnection()->getURL();
	sDir += OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_DELIMITER);
	sDir += m_Name;
	sDir += ::rtl::OUString::createFromAscii(".ndx");
	return sDir;
}
//------------------------------------------------------------------
void ODbaseIndex::createINFEntry()
{
	// inf Datei abgleichen
	String sEntry = m_Name;
	sEntry += String::CreateFromAscii(".ndx");

	::rtl::OUString sCfgFile(m_pTable->getConnection()->getURL());
	sCfgFile += OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_DELIMITER);
	sCfgFile += m_pTable->getName();
	sCfgFile += ::rtl::OUString::createFromAscii(".inf");

	String sPhysicalPath;
	LocalFileHelper::ConvertURLToPhysicalName(sCfgFile,sPhysicalPath);

	Config aInfFile(sPhysicalPath);
	aInfFile.SetGroup(dBASE_III_GROUP);

	sal_uInt16 nSuffix = aInfFile.GetKeyCount();
	ByteString aNewEntry,aKeyName;
	sal_Bool bCase = isCaseSensitive();
	while (!aNewEntry.Len())
	{
		aNewEntry = "NDX";
		aNewEntry += ByteString::CreateFromInt32(++nSuffix);
		for (sal_uInt16 i = 0; i < aInfFile.GetKeyCount(); i++)
		{
			aKeyName = aInfFile.GetKeyName(i);
			if (bCase ? aKeyName == aNewEntry : aKeyName.EqualsIgnoreCaseAscii(aNewEntry))
			{
				aNewEntry.Erase();
				break;
			}
		}
	}
	aInfFile.WriteKey(aNewEntry,ByteString(sEntry,m_pTable->getConnection()->getTextEncoding()));
}
// -------------------------------------------------------------------------
sal_Bool ODbaseIndex::DropImpl()
{
	closeImpl();

	::rtl::OUString sPath = getCompletePath();
	if(UCBContentHelper::Exists(sPath))
	{
		if(!UCBContentHelper::Kill(sPath))
            m_pTable->getConnection()->throwGenericSQLException(STR_COULD_NOT_DELETE_INDEX,*m_pTable);
	}

	// InfDatei abgleichen

	::rtl::OUString sCfgFile(m_pTable->getConnection()->getURL());
	sCfgFile += OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_DELIMITER);
	sCfgFile += m_pTable->getName();
	sCfgFile += ::rtl::OUString::createFromAscii(".inf");

	String sPhysicalPath;
	String sNDX(sCfgFile);
    OSL_VERIFY_RES( LocalFileHelper::ConvertURLToPhysicalName(sNDX,sPhysicalPath),"Can not convert Config Filename into Physical Name!");

	Config aInfFile(sPhysicalPath);
	aInfFile.SetGroup(dBASE_III_GROUP);
	sal_uInt16 nKeyCnt = aInfFile.GetKeyCount();
	ByteString aKeyName;
	String sEntry = m_Name;
	sEntry += String::CreateFromAscii(".ndx");

	// delete entries from the inf file
	for (sal_uInt16 nKey = 0; nKey < nKeyCnt; nKey++)
	{
		// Verweist der Key auf ein Indexfile?...
		aKeyName = aInfFile.GetKeyName( nKey );
		if (aKeyName.Copy(0,3) == "NDX")
		{
			if(sEntry == String(aInfFile.ReadKey(aKeyName),m_pTable->getConnection()->getTextEncoding()))
			{
				aInfFile.DeleteKey(aKeyName);
				break;
			}
		}
	}
	return sal_True;
}
// -------------------------------------------------------------------------
void ODbaseIndex::impl_killFileAndthrowError_throw(sal_uInt16 _nErrorId,const ::rtl::OUString& _sFile)
{
    closeImpl();
	if(UCBContentHelper::Exists(_sFile))
		UCBContentHelper::Kill(_sFile);
    m_pTable->getConnection()->throwGenericSQLException(_nErrorId,*this);
}
//------------------------------------------------------------------
sal_Bool ODbaseIndex::CreateImpl()
{
	// Anlegen des Index
	const ::rtl::OUString sFile = getCompletePath();
	if(UCBContentHelper::Exists(sFile))
    {
        const ::rtl::OUString sError( m_pTable->getConnection()->getResources().getResourceStringWithSubstitution(
            STR_COULD_NOT_CREATE_INDEX_NAME,
            "$filename$", sFile
         ) );
        ::dbtools::throwGenericSQLException( sError, *this );
    }
	// Index ist nur einstufig
	if (m_pColumns->getCount() > 1)
        m_pTable->getConnection()->throwGenericSQLException(STR_ONL_ONE_COLUMN_PER_INDEX,*this);

	Reference<XFastPropertySet> xCol(m_pColumns->getByIndex(0),UNO_QUERY);

	// ist die Spalte schon indiziert ?
	if ( !xCol.is() )
		::dbtools::throwFunctionSequenceException(*this);
//	else if (pColumn && pColumn->IsIndexed())
//	{
//		String aText = String(OResId(STR_STAT_INDEX_COLUMN_ALREADY_INDEXED));
//		aText.SearchAndReplace(String::CreateFromAscii("#"),pColumn->GetName());
//		aStatus.Set(SDB_STAT_ERROR,
//				String::CreateFromAscii("01000"),
//				aStatus.CreateErrorMessage(aText),
//				0, String() );
//		return sal_False;
//	}

	// create the index file
	m_pFileStream = OFileTable::createStream_simpleError(sFile,STREAM_READWRITE | STREAM_SHARE_DENYWRITE | STREAM_TRUNC);
	if (!m_pFileStream)
    {
        const ::rtl::OUString sError( m_pTable->getConnection()->getResources().getResourceStringWithSubstitution(
            STR_COULD_NOT_LOAD_FILE,
            "$filename$", sFile
         ) );
        ::dbtools::throwGenericSQLException( sError, *this );
    }

	m_pFileStream->SetNumberFormatInt(NUMBERFORMAT_INT_LITTLEENDIAN);
	m_pFileStream->SetBufferSize(PAGE_SIZE);
	m_pFileStream->SetFiller('\0');

    // Zunaechst muss das Ergebnis sortiert sein
    utl::SharedUNOComponent<XStatement> xStmt;
	utl::SharedUNOComponent<XResultSet> xSet;
	String aName;
	try
	{
		xStmt.set( m_pTable->getConnection()->createStatement(), UNO_SET_THROW);

		aName = getString(xCol->getFastPropertyValue(PROPERTY_ID_NAME));

		const String aQuote(m_pTable->getConnection()->getMetaData()->getIdentifierQuoteString());
		String aStatement;
		aStatement.AssignAscii("SELECT ");
		aStatement += aQuote;
		aStatement += aName;
		aStatement += aQuote;
		aStatement.AppendAscii(" FROM ");
		aStatement += aQuote;
		aStatement += m_pTable->getName().getStr();
		aStatement += aQuote;
		aStatement.AppendAscii(" ORDER BY ");
		aStatement += aQuote;
		aStatement += aName;
		aStatement += aQuote;

//		if (!m_IsUnique) // zusaetzlich sortierung mit der bookmarkspalte
//		{
//			aStatement.AppendAscii(" ,");
//			aStatement += aQuote;
//			aStatement.AppendAscii("[BOOKMARK]"); // this is a special column
//			aStatement += aQuote;
//		}

		xSet.set( xStmt->executeQuery(aStatement),UNO_SET_THROW );
	}
	catch(const Exception& )
	{
        impl_killFileAndthrowError_throw(STR_COULD_NOT_CREATE_INDEX,sFile);
	}
	if (!xSet.is())
	{
		impl_killFileAndthrowError_throw(STR_COULD_NOT_CREATE_INDEX,sFile);
	}

	// Setzen der Headerinfo
	memset(&m_aHeader,0,sizeof(m_aHeader));
    sal_Int32 nType = 0;
	::vos::ORef<OSQLColumns> aCols = m_pTable->getTableColumns();
	const Reference< XPropertySet > xTableCol(*find(aCols->get().begin(),aCols->get().end(),aName,::comphelper::UStringMixEqual(isCaseSensitive())));

	xTableCol->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_TYPE)) >>= nType;

	m_aHeader.db_keytype = (nType == DataType::VARCHAR || nType == DataType::CHAR) ? 0 : 1;
	m_aHeader.db_keylen  = (m_aHeader.db_keytype) ? 8 : (sal_uInt16)getINT32(xTableCol->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_PRECISION)));
    m_aHeader.db_keylen = (( m_aHeader.db_keylen - 1) / 4 + 1) * 4;
	m_aHeader.db_maxkeys = (PAGE_SIZE - 4) / (8 + m_aHeader.db_keylen);
    if ( m_aHeader.db_maxkeys < 3 )
    {
        impl_killFileAndthrowError_throw(STR_COULD_NOT_CREATE_INDEX_KEYSIZE,sFile);
    }

	m_pFileStream->SetStreamSize(PAGE_SIZE);

	ByteString aCol(aName,m_pTable->getConnection()->getTextEncoding());
	strncpy(m_aHeader.db_name,aCol.GetBuffer(),std::min((sal_uInt16)sizeof(m_aHeader.db_name), aCol.Len()));
	m_aHeader.db_unique  = m_IsUnique ? 1: 0;
	m_aHeader.db_keyrec  = m_aHeader.db_keylen + 8;

	// modifizierung am Header werden ueber Unterschiede zw. HeaderInfo und nRootPage
	// bzw. nPageCout erkannt

	m_nRootPage = 1;
	m_nPageCount = 2;

	//	ODatabaseType eType = m_aHeader.db_keytype == 0 ? DataType::VARCHAR : DataType::DOUBLE;
	m_aCurLeaf = m_aRoot = CreatePage(m_nRootPage);
	m_aRoot->SetModified(sal_True);

	m_bUseCollector = sal_True;

	//	sal_uIntPtr nRowsLeft = pCursor->RowCount();
	sal_Int32 nRowsLeft = 0;
	Reference<XRow> xRow(xSet,UNO_QUERY);

	if(xSet->last())
	{
		Reference< XUnoTunnel> xTunnel(xSet,UNO_QUERY);
		ODbaseResultSet* pDbaseRes = NULL;
		if(xTunnel.is())
			pDbaseRes = reinterpret_cast< ODbaseResultSet* >( xTunnel->getSomething(ODbaseResultSet::getUnoTunnelImplementationId()) );
		OSL_ENSURE(pDbaseRes,"No dbase resultset found? What's going on here!");
		Reference<XRowLocate> xRowLocate(xSet,UNO_QUERY);
		nRowsLeft = xSet->getRow();

		xSet->beforeFirst();
		ORowSetValue	atmpValue=ORowSetValue();
		ONDXKey aKey(atmpValue, nType, 0);
		ONDXKey aInsertKey(atmpValue, nType, 0);
		// Erzeugen der Indexstruktur
		while (xSet->next())
		{
			//	ODbRow& rRow = *pCursor->GetRow();
			ORowSetValue aValue(m_aHeader.db_keytype ? ORowSetValue(xRow->getDouble(1)) : ORowSetValue(xRow->getString(1)));
			// ueberpruefen auf doppelten eintrag
			if (m_IsUnique && m_nCurNode != NODE_NOTFOUND)
			{
				aKey.setValue(aValue);
				if (aKey == (*m_aCurLeaf)[m_nCurNode].GetKey())
				{
                    impl_killFileAndthrowError_throw(STR_COULD_NOT_CREATE_INDEX_NOT_UNIQUE,sFile);
				}
			}
			aInsertKey.setValue(aValue);
			aInsertKey.setRecord(pDbaseRes->getCurrentFilePos());

			ONDXNode aNewNode(aInsertKey);
			if (!m_aCurLeaf->Insert(aNewNode, --nRowsLeft))
				break;
		}
	}

    if(nRowsLeft)
	{
        impl_killFileAndthrowError_throw(STR_COULD_NOT_CREATE_INDEX,sFile);
	}
	Release();
	createINFEntry();
	return sal_True;
}
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
void SAL_CALL ODbaseIndex::acquire() throw()
{
	ODbaseIndex_BASE::acquire();
}
// -----------------------------------------------------------------------------
void SAL_CALL ODbaseIndex::release() throw()
{
	ODbaseIndex_BASE::release();
}
// -----------------------------------------------------------------------------



