summaryrefslogtreecommitdiff
path: root/connectivity/source/drivers/dbase/DTable.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'connectivity/source/drivers/dbase/DTable.cxx')
-rw-r--r--connectivity/source/drivers/dbase/DTable.cxx1861
1 files changed, 1861 insertions, 0 deletions
diff --git a/connectivity/source/drivers/dbase/DTable.cxx b/connectivity/source/drivers/dbase/DTable.cxx
new file mode 100644
index 000000000000..268792404cd6
--- /dev/null
+++ b/connectivity/source/drivers/dbase/DTable.cxx
@@ -0,0 +1,1861 @@
+/*************************************************************************
+ *
+ * $RCSfile: DTable.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 16:14:21 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (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.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifndef _CONNECTIVITY_DBASE_TABLE_HXX_
+#include "dbase/DTable.hxx"
+#endif
+#ifndef _COM_SUN_STAR_SDBC_COLUMNVALUE_HPP_
+#include <com/sun/star/sdbc/ColumnValue.hpp>
+#endif
+#ifndef _COM_SUN_STAR_SDBC_DATATYPE_HPP_
+#include <com/sun/star/sdbc/DataType.hpp>
+#endif
+#ifndef _COM_SUN_STAR_UCB_XCONTENTACCESS_HPP_
+#include <com/sun/star/ucb/XContentAccess.hpp>
+#endif
+#ifndef _COM_SUN_STAR_SQLC_XROW_HPP_
+#include <com/sun/star/sdbc/XRow.hpp>
+#endif
+#ifndef _SV_CONVERTER_HXX_
+#include <svtools/converter.hxx>
+#endif
+#ifndef _CONNECTIVITY_DBASE_DCONNECTION_HXX_
+#include "dbase/DConnection.hxx"
+#endif
+#ifndef _CONNECTIVITY_DBASE_COLUMNS_HXX_
+#include "dbase/DColumns.hxx"
+#endif
+#ifndef _OSL_THREAD_H_
+#include <osl/thread.h>
+#endif
+#ifndef _CONFIG_HXX //autogen
+#include <vcl/config.hxx>
+#endif
+#ifndef _CONNECTIVITY_DBASE_INDEX_HXX_
+#include "dbase/DIndex.hxx"
+#endif
+#ifndef _CONNECTIVITY_DBASE_INDEXES_HXX_
+#include "dbase/DIndexes.hxx"
+#endif
+#ifndef _UTL_SEQUENCE_HXX_
+#include <unotools/sequence.hxx>
+#endif
+#ifndef _CONNECTIVITY_DATECONVERSION_HXX_
+#include "DateConversion.hxx"
+#endif
+#ifndef _INTN_HXX //autogen
+#include <tools/intn.hxx>
+#endif
+#ifndef _ZFORLIST_HXX //autogen
+#include <svtools/zforlist.hxx>
+#endif
+#ifndef _SOLMATH_HXX //autogen wg. SolarMath
+#include <tools/solmath.hxx>
+#endif
+#include <stdio.h> //sprintf
+#ifndef _UCBHELPER_CONTENT_HXX
+#include <ucbhelper/content.hxx>
+#endif
+#ifndef _CPPUHELPER_EXTRACT_HXX_
+#include <cppuhelper/extract.hxx>
+#endif
+
+using namespace connectivity;
+using namespace connectivity::dbase;
+using namespace connectivity::file;
+using namespace ucb;
+using namespace cppu;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::ucb;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::sdbcx;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::lang;
+
+// -------------------------------------------------------------------------
+void ODbaseTable::readHeader()
+{
+ m_aFileStream.RefreshBuffer(); // sicherstellen, dass die Kopfinformationen tatsaechlich neu gelesen werden
+ m_aFileStream.Seek(STREAM_SEEK_TO_BEGIN);
+
+ BYTE aTyp;
+ m_aFileStream >> aTyp;
+ m_aFileStream.Read((char*)m_aHeader.db_aedat, 3*sizeof(BYTE));
+ m_aFileStream >> m_aHeader.db_anz;
+ m_aFileStream >> m_aHeader.db_kopf;
+ m_aFileStream >> m_aHeader.db_slng;
+ m_aFileStream.Read((char*)m_aHeader.db_frei, 20*sizeof(BYTE));
+
+ if (m_aHeader.db_anz < 0 ||
+ m_aHeader.db_kopf <= 0 ||
+ m_aHeader.db_slng <= 0 ||
+ ((m_aHeader.db_kopf - 1) / 32 - 1) <= 0) // anzahl felder
+ {
+ // Dies ist keine DBase Datei
+ }
+ else
+ {
+ // Konsistenzpruefung des Header:
+ m_aHeader.db_typ = (DBFType)aTyp;
+ switch (m_aHeader.db_typ)
+ {
+ case dBaseIII:
+ case dBaseIV:
+ case dBaseV:
+ case dBaseFS:
+ case dBaseFSMemo:
+ case dBaseIVMemoSQL:
+ case dBaseIIIMemo:
+ case dBaseIVMemo:
+ case FoxProMemo:
+ m_aFileStream.SetNumberFormatInt(NUMBERFORMAT_INT_LITTLEENDIAN);
+ break;
+ default:
+ { // Dies ist keine DBase Datei
+ }
+ }
+ }
+}
+// -------------------------------------------------------------------------
+void ODbaseTable::fillColumns()
+{
+ m_aFileStream.Seek(STREAM_SEEK_TO_BEGIN);
+ m_aFileStream.Seek(32L);
+
+ // Anzahl Felder:
+ sal_uInt32 nFieldCount = (m_aHeader.db_kopf - 1) / 32 - 1;
+
+ String aStrFieldName;aStrFieldName.AssignAscii("Column");
+ sal_Int32 nFieldCnt = 0;
+ ::rtl::OUString aTypeName;
+
+ for (sal_uInt32 i = 0; i < nFieldCount; i++)
+ {
+ DBFColumn aDBFColumn;
+ m_aFileStream.Read((char*)&aDBFColumn, sizeof(aDBFColumn));
+
+ // Info auslesen und in SdbColumn packen:
+ String aColumnName((const char *)aDBFColumn.db_fnm,osl_getThreadTextEncoding());
+
+// while (aOriginalColumns->ColumnNumber(aColumnName) != SDB_COLUMN_NOTFOUND)
+// (aColumnName = aStrFieldName) += String::CreateFromsal_Int32(++nFieldCnt);
+
+ sal_Int32 nPrecision = aDBFColumn.db_flng;
+ sal_Int32 eType;
+
+ switch (aDBFColumn.db_typ)
+ {
+ case 'C':
+ eType = DataType::VARCHAR;
+ aTypeName = ::rtl::OUString::createFromAscii("VARCHAR");
+ break;
+ case 'F':
+ case 'N':
+ eType = DataType::DECIMAL;
+ aTypeName = ::rtl::OUString::createFromAscii("DECIMAL");
+
+ // Bei numerischen Feldern werden zwei Zeichen mehr geschrieben, als die Precision der Spaltenbeschreibung eigentlich
+ // angibt, um Platz fuer das eventuelle Vorzeichen und das Komma zu haben. Das muss ich jetzt aber wieder rausrechnen.
+ nPrecision = SvDbaseConverter::ConvertPrecisionToOdbc(nPrecision,aDBFColumn.db_dez);
+ // leider gilt das eben Gesagte nicht fuer aeltere Versionen ....
+ ;
+ break;
+ case 'L':
+ eType = DataType::BIT;
+ aTypeName = ::rtl::OUString::createFromAscii("BIT");
+ break;
+ case 'D':
+ eType = DataType::DATE;
+ aTypeName = ::rtl::OUString::createFromAscii("DATE");
+ break;
+ case 'M':
+ eType = DataType::LONGVARCHAR;
+ aTypeName = ::rtl::OUString::createFromAscii("LONGVARCHAR");
+ nPrecision = 0;
+ break;
+ default:
+ aTypeName = ::rtl::OUString::createFromAscii("OTHER");
+ eType = DataType::OTHER;
+
+ }
+
+ sal_Int32 nFlags = 0;
+ switch (aDBFColumn.db_typ)
+ {
+ case 'C':
+ case 'D':
+ case 'L': nFlags = ColumnSearch::FULL; break;
+ case 'F':
+ case 'N': nFlags = ColumnSearch::BASIC; break;
+ case 'M': nFlags = ColumnSearch::CHAR; break;
+ default:
+ nFlags = ColumnSearch::NONE;
+
+ }
+ sdbcx::OColumn* pColumn = new sdbcx::OColumn(aColumnName,aTypeName,::rtl::OUString(),
+ ColumnValue::NULLABLE,nPrecision,aDBFColumn.db_dez,eType,sal_False,sal_False,sal_False,
+ getConnection()->getMetaData()->storesMixedCaseQuotedIdentifiers());
+ Reference< XFastPropertySet> xCol = pColumn;
+ m_aColumns->push_back(xCol);
+ }
+}
+// -------------------------------------------------------------------------
+//void ODbaseTable::fillIndexes()
+//{
+// Dir* pDir = m_pConnection->getDir();
+// String aPath = pDir->GetName();
+// aPath += _Name.getStr();
+// DirEntry aEntry(aPath);
+// aEntry.SetExtension(String::CreateFromAscii("inf"));
+//
+// Config aInfFile(aEntry.GetFull());
+// aInfFile.SetGroup(dBASE_III_GROUP);
+// sal_Int32 nKeyCnt = aInfFile.GetKeyCount();
+// ByteString aKeyName;
+// ByteString aIndexName;
+//
+// for (sal_Int32 nKey = 0,nPos=0; nKey < nKeyCnt; nKey++)
+// {
+// // Verweist der Key auf ein Indexfile?...
+// aKeyName = aInfFile.GetKeyName( nKey );
+// //...wenn ja, Indexliste der Tabelle hinzufuegen
+// if (aKeyName.Copy(0,3) == ByteString("NDX") )
+// {
+// aIndexName = aInfFile.ReadKey(aKeyName);
+// aEntry.SetName(String(aIndexName,osl_getThreadTextEncoding()));
+// if (aEntry.Exists())
+// {
+// readIndex(aEntry.GetBase());
+// }
+// // _rList.Insert(new String(aEntry.GetBase()), nPos++);
+// }
+// }
+//}
+// -------------------------------------------------------------------------
+//void ODbaseTable::readIndex(const String& _rName)
+//{
+//}
+// -------------------------------------------------------------------------
+ODbaseTable::ODbaseTable(ODbaseConnection* _pConnection) : ODbaseTable_BASE(_pConnection)
+ // , m_aColumns(_pConnection->getMetaData()->storesMixedCaseQuotedIdentifiers())
+{
+
+}
+// -------------------------------------------------------------------------
+ODbaseTable::ODbaseTable(ODbaseConnection* _pConnection,
+ const ::rtl::OUString& _Name,
+ const ::rtl::OUString& _Type,
+ const ::rtl::OUString& _Description ,
+ const ::rtl::OUString& _SchemaName,
+ const ::rtl::OUString& _CatalogName
+ ) : ODbaseTable_BASE(_pConnection,_Name,
+ _Type,
+ _Description,
+ _SchemaName,
+ _CatalogName)
+ // , m_aColumns(_pConnection->getMetaData()->storesMixedCaseQuotedIdentifiers())
+{
+ INetURLObject aURL;
+ aURL.SetSmartProtocol(INET_PROT_FILE);
+ aURL.SetSmartURL(getEntry(), INetURLObject::ENCODE_ALL);
+
+ if(aURL.getExtension() != m_pConnection->getExtension())
+ aURL.setExtension(m_pConnection->getExtension());
+
+ // Content aContent(aURL.GetMainURL());
+
+ m_aFileStream.Open(aURL.GetMainURL(), STREAM_READWRITE | STREAM_NOCREATE | STREAM_SHARE_DENYWRITE);
+ if(!m_aFileStream.IsOpen())
+ m_aFileStream.Open(aURL.GetMainURL(), STREAM_READ | STREAM_NOCREATE | STREAM_SHARE_DENYNONE );
+
+ if(m_aFileStream.IsOpen())
+ {
+ readHeader();
+
+ if (HasMemoFields())
+ {
+ // Memo-Dateinamen bilden (.DBT):
+ // nyi: Unschoen fuer Unix und Mac!
+
+ if (m_aHeader.db_typ == FoxProMemo) // foxpro verwendet andere extension
+ aURL.SetExtension(String::CreateFromAscii("fpt")); // nyi: Gross-/Kleinschreibung bei Unix? Klein ist sicherlich schoener.
+ else
+ aURL.SetExtension(String::CreateFromAscii("dbt")); // nyi: Gross-/Kleinschreibung bei Unix? Klein ist sicherlich schoener.
+
+ // Wenn die Memodatei nicht gefunden wird, werden die Daten trotzdem angezeigt
+ // allerdings koennen keine Updates durchgefuehrt werden
+ // jedoch die Operation wird ausgefuehrt
+ m_aMemoStream.Open(aURL.GetMainURL(), STREAM_READWRITE | STREAM_NOCREATE | STREAM_SHARE_DENYWRITE);
+ if (m_aMemoStream.IsOpen())
+ ReadMemoHeader();
+
+ // if (aStatus.IsError())
+ // {
+ // String aText = String(SdbResId(STR_STAT_FILE_NOT_FOUND));
+ // aText.SearchAndReplace(String::CreateFromAscii("%%d"),aFileEntry.GetName());
+ // aText.SearchAndReplace(String::CreateFromAscii("%%t"),aStatus.TypeToString(MEMO));
+ // aStatus.Set(SDB_STAT_SUCCESS_WITH_INFO,
+ // String::CreateFromAscii("01000"),
+ // aStatus.CreateErrorMessage(aText),
+ // 0, String() );
+ // m_aMemoStream.Close();
+ // }
+ }
+ // if (aStatus.IsError())
+ // FileClose();
+ //
+ fillColumns();
+
+ m_aFileStream.Seek(STREAM_SEEK_TO_END);
+ UINT32 nFileSize = m_aFileStream.Tell();
+ m_aFileStream.Seek(STREAM_SEEK_TO_BEGIN);
+
+ // Buffersize abhaengig von der Filegroesse
+ m_aFileStream.SetBufferSize(nFileSize > 1000000 ? 32768 :
+ nFileSize > 100000 ? 16384 :
+ nFileSize > 10000 ? 4096 : 1024);
+
+ if (m_aMemoStream.IsOpen())
+ {
+ // Puffer genau auf Laenge eines Satzes stellen
+ m_aMemoStream.Seek(STREAM_SEEK_TO_END);
+ nFileSize = m_aMemoStream.Tell();
+ m_aMemoStream.Seek(STREAM_SEEK_TO_BEGIN);
+
+ // Buffersize abhaengig von der Filegroesse
+ m_aMemoStream.SetBufferSize(nFileSize > 1000000 ? 32768 :
+ nFileSize > 100000 ? 16384 :
+ nFileSize > 10000 ? 4096 :
+ m_aMemoHeader.db_size);
+ }
+
+ AllocBuffer();
+
+ refreshColumns();
+ refreshIndexes();
+ }
+}
+//------------------------------------------------------------------
+BOOL ODbaseTable::ReadMemoHeader()
+{
+ m_aMemoStream.SetNumberFormatInt(NUMBERFORMAT_INT_LITTLEENDIAN);
+ m_aMemoStream.RefreshBuffer(); // sicherstellen das die Kopfinformationen tatsaechlich neu gelesen werden
+ m_aMemoStream.Seek(0L);
+
+ m_aMemoStream >> m_aMemoHeader.db_next;
+ switch (m_aHeader.db_typ)
+ {
+ case dBaseIIIMemo: // dBase III: feste Blockgre
+ case dBaseIVMemo:
+ // manchmal wird aber auch dBase3 dBase4 Memo zugeordnet
+ m_aMemoStream.Seek(20L);
+ m_aMemoStream >> m_aMemoHeader.db_size;
+ if (m_aMemoHeader.db_size > 1 && m_aMemoHeader.db_size != 512) // 1 steht auch fuer dBase 3
+ m_aMemoHeader.db_typ = MemodBaseIV;
+ else if (m_aMemoHeader.db_size > 1 && m_aMemoHeader.db_size == 512)
+ {
+ // nun gibt es noch manche Dateien, die verwenden eine Genangabe,
+ // sind aber dennoch dBase Dateien
+ char sHeader[4];
+ m_aMemoStream.Seek(m_aMemoHeader.db_size);
+ m_aMemoStream.Read(sHeader,4);
+
+ if ((m_aMemoStream.GetErrorCode() != ERRCODE_NONE) || ((BYTE)sHeader[0]) != 0xFF || ((BYTE)sHeader[1]) != 0xFF || ((BYTE)sHeader[2]) != 0x08)
+ m_aMemoHeader.db_typ = MemodBaseIII;
+ else
+ m_aMemoHeader.db_typ = MemodBaseIV;
+ }
+ else
+ {
+ m_aMemoHeader.db_typ = MemodBaseIII;
+ m_aMemoHeader.db_size = 512;
+ }
+ break;
+ case FoxProMemo:
+ m_aMemoHeader.db_typ = MemoFoxPro;
+ m_aMemoStream.Seek(6L);
+ m_aMemoStream.SetNumberFormatInt(NUMBERFORMAT_INT_BIGENDIAN);
+ m_aMemoStream >> m_aMemoHeader.db_size;
+ }
+ return TRUE;
+}
+// -------------------------------------------------------------------------
+::rtl::OUString ODbaseTable::getEntry()
+{
+ ::rtl::OUString aURL;
+ Reference< XResultSet > xDir = m_pConnection->getDir();
+ Reference< XRow> xRow(xDir,UNO_QUERY);
+ while(xDir->next())
+ {
+ if(xRow->getString(1) == m_Name)
+ {
+ Reference< XContentAccess > xContentAccess( xDir, UNO_QUERY );
+ aURL = xContentAccess->queryContentIdentfierString();
+ break;
+ }
+ }
+ xDir->beforeFirst(); // move back to before first record
+ return aURL;
+}
+// -------------------------------------------------------------------------
+void ODbaseTable::refreshColumns()
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ ::std::vector< ::rtl::OUString> aVector;
+
+ for(OSQLColumns::const_iterator aIter = m_aColumns->begin();aIter != m_aColumns->end();++aIter)
+ aVector.push_back(Reference< XNamed>(*aIter,UNO_QUERY)->getName());
+
+ if(m_pColumns)
+ delete m_pColumns;
+ m_pColumns = new ODbaseColumns(this,m_aMutex,aVector);
+}
+// -------------------------------------------------------------------------
+void ODbaseTable::refreshIndexes()
+{
+// Dir* pDir = m_pConnection->getDir();
+// String aPath = pDir->GetName();
+// aPath += m_Name.getStr();
+ INetURLObject aURL;
+ aURL.SetSmartProtocol(INET_PROT_FILE);
+ aURL.SetSmartURL(getEntry(), INetURLObject::ENCODE_ALL);
+
+ aURL.setExtension(String::CreateFromAscii("inf"));
+
+ Config aInfFile(aURL.GetMainURL());
+ aInfFile.SetGroup(dBASE_III_GROUP);
+ sal_Int32 nKeyCnt = aInfFile.GetKeyCount();
+ ByteString aKeyName;
+ ByteString aIndexName;
+
+ ::std::vector< ::rtl::OUString> aVector;
+
+ for (sal_Int32 nKey = 0,nPos=0; nKey < nKeyCnt; nKey++)
+ {
+ // Verweist der Key auf ein Indexfile?...
+ aKeyName = aInfFile.GetKeyName( nKey );
+ //...wenn ja, Indexliste der Tabelle hinzufuegen
+ if (aKeyName.Copy(0,3) == ByteString("NDX") )
+ {
+ aIndexName = aInfFile.ReadKey(aKeyName);
+ aURL.setName(String(aIndexName,osl_getThreadTextEncoding()));
+ Content aCnt(aURL.GetMainURL(),Reference<XCommandEnvironment>());
+ if (aCnt.isDocument())
+ {
+ aVector.push_back(aURL.getBase());
+ }
+ }
+ }
+ if(m_pIndexes)
+ delete m_pIndexes;
+ m_pIndexes = new ODbaseIndexes(this,m_aMutex,aVector);
+}
+
+// -------------------------------------------------------------------------
+void SAL_CALL ODbaseTable::disposing(void)
+{
+ OFileTable::disposing();
+ ::osl::MutexGuard aGuard(m_aMutex);
+ m_aColumns->clear();
+}
+// -------------------------------------------------------------------------
+Sequence< Type > SAL_CALL ODbaseTable::getTypes( ) throw(RuntimeException)
+{
+ Sequence< Type > aTypes = OTable_TYPEDEF::getTypes();
+ Sequence< Type > aRet(aTypes.getLength()-3);
+ const Type* pBegin = aTypes.getConstArray();
+ const Type* pEnd = pBegin + aTypes.getLength();
+ sal_Int32 i=0;
+ for(;pBegin != pEnd;++pBegin,++i)
+ {
+ if(!(*pBegin == ::getCppuType((const Reference<XKeysSupplier>*)0) ||
+ *pBegin == ::getCppuType((const Reference<XRename>*)0) ||
+ *pBegin == ::getCppuType((const Reference<XAlterTable>*)0) ||
+ *pBegin == ::getCppuType((const Reference<XDataDescriptorFactory>*)0)))
+ {
+ aRet.getArray()[i] = *pBegin;
+ }
+ }
+ aRet.getArray()[i] = ::getCppuType( (const Reference< ::com::sun::star::lang::XUnoTunnel > *)0 );
+
+ return aRet;
+}
+
+// -------------------------------------------------------------------------
+Any SAL_CALL ODbaseTable::queryInterface( const Type & rType ) throw(RuntimeException)
+{
+ if( rType == ::getCppuType((const Reference<XKeysSupplier>*)0) ||
+ rType == ::getCppuType((const Reference<XRename>*)0) ||
+ rType == ::getCppuType((const Reference<XAlterTable>*)0) ||
+ rType == ::getCppuType((const Reference<XDataDescriptorFactory>*)0))
+ return Any();
+
+ Any aRet = ::cppu::queryInterface(rType,static_cast< ::com::sun::star::lang::XUnoTunnel*> (this));
+ if(aRet.hasValue())
+ return aRet;
+
+ return OTable_TYPEDEF::queryInterface(rType);
+}
+
+//--------------------------------------------------------------------------
+Sequence< sal_Int8 > ODbaseTable::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();
+}
+
+// com::sun::star::lang::XUnoTunnel
+//------------------------------------------------------------------
+sal_Int64 ODbaseTable::getSomething( const Sequence< sal_Int8 > & rId ) throw (RuntimeException)
+{
+ if (rId.getLength() == 16 && 0 == rtl_compareMemory(getUnoTunnelImplementationId().getConstArray(), rId.getConstArray(), 16 ) )
+ return (sal_Int64)this;
+
+ return ODbaseTable_BASE::getSomething(rId);
+}
+//------------------------------------------------------------------
+sal_Bool ODbaseTable::seekRow(FilePosition eCursorPosition, sal_Int32 nOffset, sal_Int32& nCurPos)
+{
+ // ----------------------------------------------------------
+ // Positionierung vorbereiten:
+
+ sal_uInt32 nNumberOfRecords = (sal_uInt32)m_aHeader.db_anz;
+ sal_uInt32 nTempPos = m_nFilePos;
+ m_nFilePos = nCurPos;
+
+ switch(eCursorPosition)
+ {
+ case FILE_NEXT:
+ m_nFilePos++;
+ break;
+ case FILE_PRIOR:
+ if (m_nFilePos > 0)
+ m_nFilePos--;
+ break;
+ case FILE_FIRST:
+ m_nFilePos = 1;
+ break;
+ case FILE_LAST:
+ m_nFilePos = nNumberOfRecords;
+ break;
+ case FILE_RELATIVE:
+ m_nFilePos = (((sal_Int32)m_nFilePos) + nOffset < 0) ? 0L
+ : (sal_uInt32)(((sal_Int32)m_nFilePos) + nOffset);
+ break;
+ case FILE_ABSOLUTE:
+ case FILE_BOOKMARK:
+ m_nFilePos = (sal_uInt32)nOffset;
+ break;
+ }
+
+ if (m_nFilePos > (sal_Int32)nNumberOfRecords)
+ m_nFilePos = (sal_Int32)nNumberOfRecords + 1;
+
+ if (m_nFilePos == 0 || m_nFilePos == (sal_Int32)nNumberOfRecords + 1)
+ goto Error;
+ else
+ {
+ sal_uInt16 nEntryLen = m_aHeader.db_slng;
+
+ OSL_ENSHURE(m_nFilePos >= 1,"SdbDBFCursor::FileFetchRow: ungueltige Record-Position");
+ sal_Int32 nPos = m_aHeader.db_kopf + (sal_Int32)(m_nFilePos-1) * nEntryLen;
+
+ m_aFileStream.Seek(nPos);
+// if (aStatus.SetError(m_aFileStream)
+// goto Error;
+
+ m_aFileStream.Read((char*)m_pBuffer, nEntryLen);
+// if (aStatus.SetError(m_aFileStream)
+// goto Error;
+ }
+ goto End;
+
+Error:
+ switch(eCursorPosition)
+ {
+ case FILE_PRIOR:
+ case FILE_FIRST:
+ m_nFilePos = 0;
+ break;
+ case FILE_LAST:
+ case FILE_NEXT:
+ case FILE_ABSOLUTE:
+ case FILE_RELATIVE:
+ if (nOffset > 0)
+ m_nFilePos = nNumberOfRecords + 1;
+ else if (nOffset < 0)
+ m_nFilePos = 0;
+ break;
+ case FILE_BOOKMARK:
+ m_nFilePos = nTempPos; // vorherige Position
+ }
+ // aStatus.Set(SDB_STAT_NO_DATA_FOUND);
+ return sal_False;
+
+End:
+ nCurPos = m_nFilePos;
+ return sal_True;
+}
+//------------------------------------------------------------------
+sal_Bool ODbaseTable::fetchRow(file::OValueRow _rRow,const OSQLColumns & _rCols, sal_Bool bRetrieveData)
+{
+ // Einlesen der Daten
+ BOOL bIsCurRecordDeleted = ((char)m_pBuffer[0] == '*') ? TRUE : FALSE;
+
+ // only read the bookmark
+
+ // Satz als geloescht markieren
+ // rRow.setState(bIsCurRecordDeleted ? ROW_DELETED : ROW_CLEAN );
+ _rRow->setDeleted(bIsCurRecordDeleted);
+ (*_rRow)[0] = m_nFilePos;
+
+ if (!bRetrieveData)
+ return TRUE;
+
+ sal_Int32 nByteOffset = 1;
+ // Felder:
+ OSQLColumns::const_iterator aIter = _rCols.begin();
+ for (sal_Int32 i = 1; aIter != _rCols.end();++aIter, i++)
+ {
+ // pVal = (*_rRow)[i].getBodyPtr();
+ Reference< XFastPropertySet> xColumn = *aIter;
+
+ // Laengen je nach Datentyp:
+ // nyi: eine zentrale Funktion, die die Laenge liefert!
+ sal_Int32 nLen;
+ xColumn->getFastPropertyValue(PROPERTY_ID_PRECISION) >>= nLen;
+ sal_Int32 nType = getINT32(xColumn->getFastPropertyValue(PROPERTY_ID_TYPE));
+ switch(nType)
+ {
+ case DataType::DATE: nLen = 8; break;
+ case DataType::DECIMAL:
+ nLen = SvDbaseConverter::ConvertPrecisionToDbase(nLen,getINT32(xColumn->getFastPropertyValue(PROPERTY_ID_SCALE)));
+ break; // das Vorzeichen und das Komma
+ case DataType::BIT: nLen = 1; break;
+ case DataType::LONGVARCHAR: nLen = 10; break;
+ case DataType::OTHER:
+ nByteOffset += nLen;
+ continue;
+ default: break;
+ }
+
+ // Ist die Variable ueberhaupt gebunden?
+ if (!(*_rRow)[i].isBound())
+ {
+ // Nein - naechstes Feld.
+ nByteOffset += nLen;
+ continue;
+ }
+
+ char *pData = (char *) (m_pBuffer + nByteOffset);
+
+ (*_rRow)[i].setType(nType);
+
+ if (nType == DataType::CHAR || nType == DataType::VARCHAR)
+ {
+ char cLast = pData[nLen];
+ pData[nLen] = 0;
+ String aStr(pData,osl_getThreadTextEncoding());
+ aStr.EraseTrailingChars();
+
+ if (!aStr.Len()) // keine StringLaenge, dann NULL
+ (*_rRow)[i].setNull();
+ else
+ {
+ ::rtl::OUString aStr2(aStr);
+ (*_rRow)[i] = aStr2;
+ }
+ pData[nLen] = cLast;
+ }
+ else
+ {
+ // Falls Nul-Zeichen im String enthalten sind, in Blanks umwandeln!
+ for (sal_Int32 k = 0; k < nLen; k++)
+ {
+ if (pData[k] == '\0')
+ pData[k] = ' ';
+ }
+
+ String aStr(pData, nLen); // Spaces am Anfang und am Ende entfernen:
+ aStr.EraseLeadingChars();
+ aStr.EraseTrailingChars();
+
+ if (!aStr.Len())
+ {
+ nByteOffset += nLen;
+ (*_rRow)[i].setNull(); // keine Werte -> fertig
+ continue;
+ }
+
+ switch (nType)
+ {
+ case DataType::DATE:
+ {
+ if (aStr.Len() != nLen)
+ {
+ (*_rRow)[i].setNull();
+ break;
+ }
+ sal_Int32 nYear = aStr.Copy( 0, 4 ).ToInt32();
+ sal_Int32 nMonth = aStr.Copy( 4, 2 ).ToInt32();
+ sal_Int32 nDay = aStr.Copy( 6, 2 ).ToInt32();
+
+ ::com::sun::star::util::Date aDate(nDay,nMonth,nYear);
+ (*_rRow)[i] = DateConversion::toDouble(aDate);
+ }
+ break;
+ case DataType::DECIMAL:
+ (*_rRow)[i] = aStr.ToDouble();
+ // pVal->setDouble(SdbTools::ToDouble(aStr));
+ break;
+ case DataType::BIT:
+ {
+ BOOL b;
+ switch (* ((const char *)pData))
+ {
+ case 'T':
+ case 'Y':
+ case 'J': b = TRUE; break;
+ default: b = FALSE; break;
+ }
+ (*_rRow)[i] = b;
+ // pVal->setDouble(b);
+ }
+ break;
+ case DataType::LONGVARCHAR:
+ {
+ long nBlockNo = aStr.ToInt32(); // Blocknummer lesen
+ if (nBlockNo > 0 && m_aMemoStream.IsOpen()) // Daten aus Memo-Datei lesen, nur wenn
+ {
+ if (!ReadMemo(nBlockNo, (*_rRow)[i]))
+ break;
+ }
+ else
+ (*_rRow)[i].setNull();
+ } break;
+ default:
+ OSL_ASSERT("Falscher Type");
+ }
+ }
+
+// if (aStatus.IsError())
+// break;
+ // Und weiter ...
+ nByteOffset += nLen;
+ }
+ return sal_True;
+}
+//------------------------------------------------------------------
+BOOL ODbaseTable::ReadMemo(ULONG nBlockNo, OFileValue& aVariable)
+{
+ BOOL bIsText = TRUE;
+ // SdbConnection* pConnection = GetConnection();
+
+ m_aMemoStream.Seek(nBlockNo * m_aMemoHeader.db_size);
+ switch (m_aMemoHeader.db_typ)
+ {
+ case MemodBaseIII: // dBase III-Memofeld, endet mit Ctrl-Z
+ {
+ const char cEOF = (char) 0x1a;
+ ByteString aStr;
+ static char aBuf[514];
+ aBuf[512] = 0; // sonst kann der Zufall uebel mitspielen
+ BOOL bReady = FALSE;
+
+ do
+ {
+ m_aMemoStream.Read(&aBuf,512);
+
+ USHORT i = 0;
+ while (aBuf[i] != cEOF && ++i < 512)
+ ;
+ bReady = aBuf[i] == cEOF;
+
+ aBuf[i] = 0;
+ aStr += aBuf;
+
+ } while (!bReady && !m_aMemoStream.IsEof() && aStr.Len() < STRING_MAXLEN);
+
+ aVariable = ::rtl::OUString(aStr.GetBuffer(), aStr.Len(),osl_getThreadTextEncoding());
+ } break;
+ case MemoFoxPro:
+ case MemodBaseIV: // dBase IV-Memofeld mit Laengenangabe
+ {
+ char sHeader[4];
+ m_aMemoStream.Read(sHeader,4);
+ // Foxpro stores text and binary data
+ if (m_aMemoHeader.db_typ == MemoFoxPro)
+ {
+ if (((BYTE)sHeader[0]) != 0 || ((BYTE)sHeader[1]) != 0 || ((BYTE)sHeader[2]) != 0)
+ {
+// String aText = String(SdbResId(STR_STAT_FILE_INVALID));
+// aText.SearchAndReplace(String::CreateFromAscii("%%d"),m_aMemoStream.GetFileName());
+// aText.SearchAndReplace(String::CreateFromAscii("%%t"),aStatus.TypeToString(MEMO));
+// aStatus.Set(SDB_STAT_ERROR,
+// String::CreateFromAscii("01000"),
+// aStatus.CreateErrorMessage(aText),
+// 0, String() );
+ return FALSE;
+ }
+
+ bIsText = sHeader[3] != 0;
+ }
+ else if (((BYTE)sHeader[0]) != 0xFF || ((BYTE)sHeader[1]) != 0xFF || ((BYTE)sHeader[2]) != 0x08)
+ {
+// String aText = String(SdbResId(STR_STAT_FILE_INVALID));
+// aText.SearchAndReplace(String::CreateFromAscii("%%d"),m_aMemoStream.GetFileName());
+// aText.SearchAndReplace(String::CreateFromAscii("%%t"),aStatus.TypeToString(MEMO));
+// aStatus.Set(SDB_STAT_ERROR,
+// String::CreateFromAscii("01000"),
+// aStatus.CreateErrorMessage(aText),
+// 0, String() );
+ return FALSE;
+ }
+
+ ULONG nLength;
+ m_aMemoStream >> nLength;
+
+ if (m_aMemoHeader.db_typ == MemodBaseIV)
+ nLength -= 8;
+
+ // char cChar;
+ if (nLength < STRING_MAXLEN && bIsText)
+ {
+ ByteString aStr;
+ aStr.Expand(USHORT (nLength));
+ m_aMemoStream.Read(aStr.AllocBuffer((USHORT)nLength),nLength);
+ aStr.ReleaseBufferAccess();
+ aVariable = ::rtl::OUString(aStr.GetBuffer(),aStr.Len(), osl_getThreadTextEncoding());
+ }
+ else
+ {
+// ::Sequence<sal_Int8> aText(nLength);
+// sal_Int8* pData = aText.getArray();
+// for (ULONG i = 0; i < nLength; i++)
+// {
+// m_aMemoStream.Read(&cChar,1);
+// (*pData++) = cChar;
+// }
+// aVariable.setBytes(aText);
+ return sal_False;
+ }
+ }
+ }
+ return sal_True;
+}
+// -------------------------------------------------------------------------
+void ODbaseTable::FileClose()
+{
+ // falls noch nicht alles geschrieben wurde
+ if (m_aMemoStream.IsOpen() && m_aMemoStream.IsWritable())
+ m_aMemoStream.Flush();
+
+ m_aMemoStream.Close();
+
+ if (m_aFileStream.IsOpen() && m_aFileStream.IsWritable())
+ m_aFileStream.Flush();
+
+ m_aFileStream.Close();
+
+ if (m_pBuffer != NULL)
+ {
+ delete m_pBuffer;
+ m_pBuffer = NULL;
+ }
+}
+// -------------------------------------------------------------------------
+BOOL ODbaseTable::CreateImpl()
+{
+ OSL_ENSHURE(!m_aFileStream.IsOpen(), "SequenceError");
+
+ INetURLObject aURL;
+ aURL.SetSmartProtocol(INET_PROT_FILE);
+ aURL.SetSmartURL(getEntry(), INetURLObject::ENCODE_ALL);
+
+ if(aURL.getExtension() != m_pConnection->getExtension())
+ aURL.setExtension(m_pConnection->getExtension());
+
+ Content aContent(aURL.GetMainURL(),Reference<XCommandEnvironment>());
+
+ if (aContent.isDocument())
+ {
+ // Hack fuer Bug #30609 , nur wenn das File existiert und die Laenge > 0 gibt es einen Fehler
+ SvFileStream m_aFileStream;
+ m_aFileStream.Open(aURL.GetMainURL(),STREAM_STD_READ);
+
+ if (m_aFileStream.IsOpen() && m_aFileStream.Seek(STREAM_SEEK_TO_END))
+ {
+ // aStatus.SetError(ERRCODE_IO_ALREADYEXISTS,TABLE,aFile.GetFull());
+ return FALSE;
+ }
+ m_aFileStream.Close();
+ }
+
+ BOOL bMemoFile = FALSE;
+
+ sal_Bool bOk = CreateFile(aURL, bMemoFile);
+
+ FileClose();
+
+ if (!bOk)
+ {
+ aContent.executeCommand( rtl::OUString::createFromAscii( "delete" ),bool2any( sal_True ) );
+ return FALSE;
+ }
+
+ if (bMemoFile)
+ {
+ String aExt = aURL.getExtension();
+ aURL.setExtension(String::CreateFromAscii("dbt")); // extension for memo file
+ Content aMemo1Content(aURL.GetMainURL(),Reference<XCommandEnvironment>());
+
+ if (aMemo1Content.isDocument())
+ {
+ // aStatus.SetError(ERRCODE_IO_ALREADYEXISTS,MEMO,aFile.GetFull());
+ aURL.setExtension(aExt); // kill dbf file
+ Content aMemoContent(aURL.GetMainURL(),Reference<XCommandEnvironment>());
+ aMemoContent.executeCommand( rtl::OUString::createFromAscii( "delete" ),bool2any( sal_True ) );
+ return FALSE;
+ }
+ if (!CreateMemoFile(aURL))
+ {
+ aURL.setExtension(aExt); // kill dbf file
+ Content aMemoContent(aURL.GetMainURL(),Reference<XCommandEnvironment>());
+ aMemoContent.executeCommand( rtl::OUString::createFromAscii( "delete" ),bool2any( sal_True ) );
+ return FALSE;
+ }
+ m_aHeader.db_typ = dBaseIIIMemo;
+ }
+ else
+ m_aHeader.db_typ = dBaseIII;
+
+// if (GetDBFConnection()->GetShowDeleted())
+// nPrivileges = SDB_PR_READ | SDB_PR_INSERT | SDB_PR_UPDATE |
+// SDB_PR_ALTER | SDB_PR_DROP;
+// else
+ // nPrivileges = SDB_PR_READ | SDB_PR_INSERT | SDB_PR_UPDATE |
+ // SDB_PR_DELETE | SDB_PR_ALTER | SDB_PR_DROP;
+
+ return TRUE;
+}
+
+//------------------------------------------------------------------
+// erzeugt grundstzlich dBase IV Datei Format
+BOOL ODbaseTable::CreateFile(const INetURLObject& aFile, BOOL& bCreateMemo)
+{
+ bCreateMemo = FALSE;
+ Date aDate; // aktuelles Datum
+
+ m_aFileStream.Open(aFile.GetMainURL(), STREAM_READWRITE | STREAM_SHARE_DENYWRITE | STREAM_TRUNC);
+ if (!m_aFileStream.IsOpen())
+ return FALSE;
+
+ char aBuffer[21]; // write buffer
+ memset(aBuffer,0,sizeof(aBuffer));
+
+ m_aFileStream.Seek(0L);
+ m_aFileStream << (BYTE) dBaseIII; // dBase format
+ m_aFileStream << (BYTE) (aDate.GetYear() % 100); // aktuelles Datum
+
+
+ m_aFileStream << (BYTE) aDate.GetMonth();
+ m_aFileStream << (BYTE) aDate.GetDay();
+ m_aFileStream << 0L; // Anzahl der Datenstze
+ m_aFileStream << (USHORT)(m_pColumns->getCount() * 32 + 1); // Kopfinformationen,
+ // pColumns erhlt immer eine Spalte mehr
+ m_aFileStream << (USHORT) 0; // Satzlnge wird spter bestimmt
+ m_aFileStream.Write(aBuffer, 20);
+
+ USHORT nRecLength = 1; // Lnge 1 fr deleted flag
+ ULONG nMaxFieldLength = m_pConnection->getMetaData()->getMaxColumnNameLength();
+ Reference<XIndexAccess> xColumns(getColumns(),UNO_QUERY);
+
+ ::rtl::OUString aName;
+ Reference<XFastPropertySet> xCol;
+ for(sal_Int32 i=0;i<xColumns->getCount();++i)
+ {
+ xColumns->getByIndex(i) >>= xCol;
+ OSL_ENSHURE(xCol.is(),"This should be a column!");
+
+ char cTyp;
+
+ xCol->getFastPropertyValue(PROPERTY_ID_NAME) >>= aName;
+
+ if (aName.getLength() > nMaxFieldLength)
+ {
+// String aText = String(SdbResId(STR_DBF_INVALIDFIELDNAMELENGTH));
+// aText.SearchAndReplace(String::CreateFromAscii("#"),rColumn.GetName());
+// aStatus.Set(SDB_STAT_ERROR,
+// String::CreateFromAscii("01000"),
+// aStatus.CreateErrorMessage(aText),
+// 0, String() );
+ break;
+ }
+
+ ByteString aCol(aName.getStr(),gsl_getSystemTextEncoding());
+ m_aFileStream << aCol.GetBuffer();
+ m_aFileStream.Write(aBuffer, 11 - aCol.Len());
+
+ switch (getINT32(xCol->getFastPropertyValue(PROPERTY_ID_TYPE)))
+ {
+ case DataType::CHAR:
+ case DataType::VARCHAR:
+ cTyp = 'C';
+ break;
+ case DataType::TINYINT:
+ case DataType::SMALLINT:
+ case DataType::INTEGER:
+ case DataType::BIGINT:
+ case DataType::DECIMAL:
+ case DataType::NUMERIC:
+ case DataType::REAL:
+ case DataType::DOUBLE:
+ cTyp = 'N'; // nur dBase 3 format
+ break;
+ case DataType::DATE:
+ cTyp = 'D';
+ break;
+ case DataType::BIT:
+ cTyp = 'L';
+ break;
+ case DataType::LONGVARBINARY:
+ case DataType::LONGVARCHAR:
+ cTyp = 'M';
+ break;
+ default:
+ {
+// aStatus.Set(SDB_STAT_ERROR,
+// String::CreateFromAscii("01000"),
+// aStatus.CreateErrorMessage(String(SdbResId(STR_DBF_INVALIDFORMAT))),
+// 0, String() );
+ break;
+ }
+ }
+
+ m_aFileStream << cTyp;
+ m_aFileStream.Write(aBuffer, 4);
+
+ sal_Int32 nPrecision = 0;
+ xCol->getFastPropertyValue(PROPERTY_ID_PRECISION) >>= nPrecision;
+ sal_Int32 nScale = 0;
+ xCol->getFastPropertyValue(PROPERTY_ID_SCALE) >>= nScale;
+
+ switch(cTyp)
+ {
+ case 'C':
+ OSL_ENSHURE(nPrecision < 255, "ODbaseTable::Create: Column zu lang!");
+ if (nPrecision > 254)
+ {
+// String aText = String(SdbResId(STR_DBF_INVALIDFIELDLENGTH));
+// aText.SearchAndReplace(String::CreateFromAscii("#"),rColumn.GetName());
+// aStatus.Set(SDB_STAT_ERROR,
+// String::CreateFromAscii("01000"),
+// aStatus.CreateErrorMessage(aText),
+// 0, String() );
+ // break;
+ }
+ m_aFileStream << (BYTE) min(nPrecision, 255UL); //Feldlnge
+ nRecLength += (USHORT)min(nPrecision, 255UL);
+ m_aFileStream << (BYTE)0; //Nachkommastellen
+ break;
+ case 'F':
+ case 'N':
+ OSL_ENSHURE(nPrecision >= nScale,
+ "ODbaseTable::Create: Feldlnge mu grer Nachkommastellen sein!");
+ if (nPrecision < nScale)
+ {
+// aStatus.Set(SDB_STAT_ERROR,
+// String::CreateFromAscii("01000"),
+// aStatus.CreateErrorMessage(String(SdbResId(STR_DBF_INVALIDFORMAT))),
+// 0, String() );
+ break;
+ }
+ if (getBOOL(xCol->getFastPropertyValue(PROPERTY_ID_ISCURRENCY))) // Currency wird gesondert behandelt
+ {
+ m_aFileStream << (BYTE)10; // Standard Laenge
+ m_aFileStream << (BYTE)4;
+ nRecLength += 10;
+ }
+ else
+ {
+ UINT16 nPrec = SvDbaseConverter::ConvertPrecisionToDbase(nPrecision,nScale);
+
+ m_aFileStream << (BYTE)( nPrec);
+ m_aFileStream << (BYTE)nScale;
+ nRecLength += (USHORT)nPrec;
+ }
+ break;
+ case 'L':
+ m_aFileStream << (BYTE)1;
+ m_aFileStream << (BYTE)0;
+ nRecLength++;
+ break;
+ case 'D':
+ m_aFileStream << (BYTE)8;
+ m_aFileStream << (BYTE)0;
+ nRecLength += 8;
+ break;
+ case 'M':
+ bCreateMemo = TRUE;
+ m_aFileStream << (BYTE)10;
+ m_aFileStream << (BYTE)0;
+ nRecLength += 10;
+ break;
+ default:
+// aStatus.Set(SDB_STAT_ERROR,
+// String::CreateFromAscii("01000"),
+// aStatus.CreateErrorMessage(String(SdbResId(STR_DBF_INVALIDFORMAT))),
+// 0, String() );
+ break;
+ }
+ m_aFileStream.Write(aBuffer, 14);
+ }
+
+// if (aStatus.IsError())
+// return FALSE;
+
+ m_aFileStream << (BYTE)0x0d; // kopf ende
+ m_aFileStream.Seek(10L);
+ m_aFileStream << nRecLength; // satzlnge nachtrglich eintragen
+
+ if (bCreateMemo)
+ {
+ m_aFileStream.Seek(0L);
+ m_aFileStream << (BYTE) dBaseIIIMemo;
+ }
+ return TRUE;
+}
+
+//------------------------------------------------------------------
+// erzeugt grundstzlich dBase III Datei Format
+BOOL ODbaseTable::CreateMemoFile(const INetURLObject& aFile)
+{
+ // Makro zum Filehandling frs Erzeugen von Tabellen
+ m_aMemoStream.Open(aFile.GetMainURL(), STREAM_READWRITE | STREAM_SHARE_DENYWRITE);
+ if (!m_aMemoStream.IsOpen())
+ return FALSE;
+
+ char aBuffer[512]; // write buffer
+ memset(aBuffer,0,sizeof(aBuffer));
+
+#ifdef WIN
+ m_aMemoStream.Seek(0L);
+ for (UINT16 i = 0; i < 512; i++)
+ {
+ m_aMemoStream << BYTE(0);
+ }
+#else
+ m_aMemoStream.SetFiller('\0');
+ m_aMemoStream.SetStreamSize(512);
+#endif
+
+ m_aMemoStream.Seek(0L);
+ m_aMemoStream << long(1); // Zeiger auf ersten freien Block
+
+ m_aMemoStream.Close();
+ return TRUE;
+}
+//------------------------------------------------------------------
+BOOL ODbaseTable::DropImpl()
+{
+// NAMESPACE_VOS(OGuard) aGuard(m_pLock);
+//
+// if (InUse())
+// {
+// aStatus.SetError(ERRCODE_IO_LOCKVIOLATION,TABLE,aName);
+// return FALSE;
+// }
+
+ FileClose();
+
+ INetURLObject aURL;
+ aURL.SetSmartProtocol(INET_PROT_FILE);
+ aURL.SetSmartURL(getEntry(), INetURLObject::ENCODE_ALL);
+
+ Content aContent(aURL.GetMainURL(),Reference<XCommandEnvironment>());
+ aContent.executeCommand( rtl::OUString::createFromAscii( "delete" ),
+ makeAny( sal_Bool( sal_True ) ) );
+
+ if (HasMemoFields())
+ {
+ aURL.setExtension(String::CreateFromAscii("dbt"));
+ Content aMemoContent(aURL.GetMainURL(),Reference<XCommandEnvironment>());
+ aMemoContent.executeCommand( rtl::OUString::createFromAscii( "delete" ),bool2any( sal_True ) );
+ }
+
+ // jetzt noch die Indices loeschen
+ String aIndexName;
+ // aFile.SetExtension(String::CreateFromAscii("ndx"));
+ USHORT nCount = m_pIndexes->getCount(),
+ i = 0;
+ while (i < nCount)
+ {
+ m_pIndexes->dropByIndex(i);
+ }
+ // aFile.SetBase(m_Name);
+ aURL.setExtension(String::CreateFromAscii("inf"));
+ Content aInfContent(aURL.GetMainURL(),Reference<XCommandEnvironment>());
+ aInfContent.executeCommand( rtl::OUString::createFromAscii( "delete" ),bool2any( sal_True ) );
+ return TRUE;
+}
+//------------------------------------------------------------------
+BOOL ODbaseTable::InsertRow(ORefAssignValues& rRow, BOOL bFlush,const Reference<XIndexAccess>& _xCols)
+{
+ // Buffer mit Leerzeichen fllen
+ AllocBuffer();
+ memset(m_pBuffer, ' ', m_aHeader.db_slng);
+
+ // Gesamte neue Row uebernehmen:
+ // ... und am Ende als neuen Record hinzufuegen:
+ UINT32 nTempPos = m_nFilePos,
+ nFileSize,
+ nMemoFileSize;
+
+ m_nFilePos = (ULONG)m_aHeader.db_anz + 1;
+ if (!UpdateBuffer(rRow.getBody(),NULL,_xCols))
+ {
+ m_nFilePos = nTempPos;
+ return FALSE;
+ }
+
+ String aName = m_aFileStream.GetFileName();
+
+ m_aFileStream.Seek(STREAM_SEEK_TO_END);
+ nFileSize = m_aFileStream.Tell();
+
+ if (HasMemoFields() && m_aMemoStream.IsOpen())
+ {
+ m_aMemoStream.Seek(STREAM_SEEK_TO_END);
+ nMemoFileSize = m_aMemoStream.Tell();
+ }
+
+ if (!WriteBuffer())
+ {
+ m_aFileStream.SetStreamSize(nFileSize); // alte Gre restaurieren
+
+ if (HasMemoFields() && m_aMemoStream.IsOpen())
+ m_aMemoStream.SetStreamSize(nMemoFileSize); // alte Gre restaurieren
+ m_nFilePos = nTempPos; // Fileposition restaurieren
+ }
+ else
+ {
+ // Anzahl Datensaetze im Header erhoehen:
+ m_aFileStream.Seek( 4L );
+ m_aFileStream << (m_aHeader.db_anz + 1);
+
+ // beim AppendOnly kein Flush!
+ if (bFlush)
+ m_aFileStream.Flush();
+
+ // bei Erfolg # erhhen
+ m_aHeader.db_anz++;
+ (*rRow)[0] = m_nFilePos; // BOOKmark setzen
+ m_nFilePos = nTempPos;
+ }
+
+ return sal_True;;
+}
+
+//------------------------------------------------------------------
+BOOL ODbaseTable::UpdateRow(file::OValueVector& rRow, OValueRow pOrgRow,const Reference<XIndexAccess>& _xCols)
+{
+ // Buffer mit Leerzeichen fllen
+ AllocBuffer();
+
+ // Auf gewuenschten Record positionieren:
+ long nPos = m_aHeader.db_kopf + (long)(m_nFilePos-1) * m_aHeader.db_slng;
+ m_aFileStream.Seek(nPos);
+ m_aFileStream.Read((char*)m_pBuffer, m_aHeader.db_slng);
+
+ UINT32 nMemoFileSize;
+ if (HasMemoFields() && m_aMemoStream.IsOpen())
+ {
+ m_aMemoStream.Seek(STREAM_SEEK_TO_END);
+ nMemoFileSize = m_aMemoStream.Tell();
+ }
+ if (!UpdateBuffer(rRow, pOrgRow,_xCols) || !WriteBuffer())
+ {
+ if (HasMemoFields() && m_aMemoStream.IsOpen())
+ m_aMemoStream.SetStreamSize(nMemoFileSize); // alte Gre restaurieren
+ }
+ else
+ {
+ m_aFileStream.Flush();
+ }
+ return sal_True;
+}
+
+//------------------------------------------------------------------
+BOOL ODbaseTable::DeleteRow(const OSQLColumns& _rCols)
+{
+ // Einfach das Loesch-Flag setzen (egal, ob es schon gesetzt war
+ // oder nicht):
+ // Auf gewuenschten Record positionieren:
+ long nPos = m_aHeader.db_kopf + (long)(m_nFilePos-1) * m_aHeader.db_slng;
+ m_aFileStream.Seek(nPos);
+
+ OValueRow aRow = new OValueVector(_rCols.size());
+
+ if (!fetchRow(aRow,_rCols,TRUE))
+ return FALSE;
+
+ Reference<XFastPropertySet> xCol;
+ ::rtl::OUString aColName;
+ ::utl::UStringMixEqual aCase(isCaseSensitive());
+ for (USHORT i = 0; i < m_pColumns->getCount(); i++)
+ {
+ m_pColumns->getByIndex(i) >>= xCol;
+ // const SdbFILEColumn *pColumn = (const SdbFILEColumn *)(*aOriginalColumns)[i];
+
+ xCol->getFastPropertyValue(PROPERTY_ID_NAME) >>= aColName;
+ Reference<XFastPropertySet> xIndex = isUniqueByColumnName(aColName);
+ if (xIndex.is())
+ {
+ Reference<XUnoTunnel> xTunnel(xIndex,UNO_QUERY);
+ OSL_ENSHURE(xTunnel.is(),"No TunnelImplementation!");
+ ODbaseIndex* pIndex = (ODbaseIndex*)xTunnel->getSomething(ODbaseIndex::getUnoTunnelImplementationId());
+ OSL_ENSHURE(pIndex,"ODbaseTable::UpdateBuffer: No Index returned!");
+
+ OSQLColumns::const_iterator aIter = _rCols.begin();
+ // sal_Int32 nPos = 0;
+ for(;aIter != _rCols.end();++aIter,++nPos)
+ {
+// Reference<XFastPropertySet> xFindCol;
+// _xCols->getByIndex(nPos) >>= xFindCol;
+ if(aCase(getString((*aIter)->getFastPropertyValue(PROPERTY_ID_REALNAME)),aColName))
+ break;
+ }
+ if (aIter == _rCols.end())
+ continue;
+
+ pIndex->Delete(m_nFilePos,(*aRow)[nPos]);
+ }
+ }
+
+ m_aFileStream.Seek(nPos);
+ m_aFileStream << (BYTE)'*';
+ m_aFileStream.Flush();
+ return sal_True;;
+}
+
+//------------------------------------------------------------------
+BOOL ODbaseTable::WriteMemo(OFileValue& aVariable, ULONG& rBlockNr)
+{
+ // wird die BlockNr 0 vorgegeben, wird der block ans Ende gehaengt
+ char cChar = 0;
+ BOOL bIsText = TRUE;
+ // SdbConnection* pConnection = GetConnection();
+
+ ULONG nSize = 0;
+ ULONG nStreamSize;
+ BYTE nHeader[4];
+
+ ByteString aStr;
+ // ::Sequence<sal_Int8>* pData = NULL;
+// if (aVariable.getValueType() == ::getCppuType((const ::com::sun::star::uno::Sequence< sal_Int8 > *)0))
+// {
+// pData = (::Sequence<sal_Int8>*)aVariable.get();
+// nSize = pData->getLength();
+// }
+// else
+// {
+ aStr = ByteString(aVariable.getString().getStr(), osl_getThreadTextEncoding());
+ nSize = aStr.Len();
+ // }
+
+ // Anhaengen oder ueberschreiben
+ BOOL bAppend = rBlockNr == 0;
+
+ if (!bAppend)
+ {
+ switch (m_aMemoHeader.db_typ)
+ {
+ case MemodBaseIII: // dBase III-Memofeld, endet mit 2 * Ctrl-Z
+ bAppend = nSize > (512 - 2);
+ break;
+ case MemoFoxPro:
+ case MemodBaseIV: // dBase IV-Memofeld mit Laengenangabe
+ {
+ char sHeader[4];
+ m_aMemoStream.Seek(rBlockNr * m_aMemoHeader.db_size);
+ m_aMemoStream.SeekRel(4L);
+ m_aMemoStream.Read(sHeader,4);
+
+ ULONG nOldSize;
+ if (m_aMemoHeader.db_typ == MemoFoxPro)
+ nOldSize = ((((unsigned char)sHeader[0]) * 256 +
+ (unsigned char)sHeader[1]) * 256 +
+ (unsigned char)sHeader[2]) * 256 +
+ (unsigned char)sHeader[3];
+ else
+ nOldSize = ((((unsigned char)sHeader[3]) * 256 +
+ (unsigned char)sHeader[2]) * 256 +
+ (unsigned char)sHeader[1]) * 256 +
+ (unsigned char)sHeader[0] - 8;
+
+ // passt die neue Laenge in die belegten Bloecke
+ ULONG nUsedBlocks = ((nSize + 8) / m_aMemoHeader.db_size) + (((nSize + 8) % m_aMemoHeader.db_size > 0) ? 1 : 0),
+ nOldUsedBlocks = ((nOldSize + 8) / m_aMemoHeader.db_size) + (((nOldSize + 8) % m_aMemoHeader.db_size > 0) ? 1 : 0);
+ bAppend = nUsedBlocks > nOldUsedBlocks;
+ }
+ }
+ }
+
+ if (bAppend)
+ {
+ ULONG nStreamSize;
+ nStreamSize = m_aMemoStream.Seek(STREAM_SEEK_TO_END);
+ // letzten block auffuellen
+ rBlockNr = (nStreamSize / m_aMemoHeader.db_size) + ((nStreamSize % m_aMemoHeader.db_size) > 0 ? 1 : 0);
+
+ m_aMemoStream.SetStreamSize(rBlockNr * m_aMemoHeader.db_size);
+ m_aMemoStream.Seek(STREAM_SEEK_TO_END);
+ }
+ else
+ {
+ m_aMemoStream.Seek(rBlockNr * m_aMemoHeader.db_size);
+ }
+
+ switch (m_aMemoHeader.db_typ)
+ {
+ case MemodBaseIII: // dBase III-Memofeld, endet mit Ctrl-Z
+ {
+ const char cEOF = (char) 0x1a;
+ nSize++;
+
+// if (pData)
+// {
+// m_aMemoStream.Write((const char*) pData->getConstArray(), pData->getLength());
+// }
+// else
+// {
+ m_aMemoStream.Write(aStr.GetBuffer(), aStr.Len());
+ // }
+
+ m_aMemoStream << cEOF << cEOF;
+ } break;
+ case MemoFoxPro:
+ case MemodBaseIV: // dBase IV-Memofeld mit Laengenangabe
+ {
+ m_aMemoStream << (BYTE)0xFF
+ << (BYTE)0xFF
+ << (BYTE)0x08;
+
+ UINT32 nWriteSize = nSize;
+ if (m_aMemoHeader.db_typ == MemoFoxPro)
+ {
+ m_aMemoStream << (BYTE) 0x01; // ((pData = NULL) ? 0x01 : 0x00);
+ for (int i = 4; i > 0; nWriteSize >>= 8)
+ nHeader[--i] = (BYTE) (nWriteSize % 256);
+ }
+ else
+ {
+ m_aMemoStream << (BYTE) 0x00;
+ nWriteSize += 8;
+ for (int i = 0; i < 4; nWriteSize >>= 8)
+ nHeader[i++] = (BYTE) (nWriteSize % 256);
+ }
+
+ m_aMemoStream.Write(nHeader,4);
+// if (pData)
+// {
+// m_aMemoStream.Write((const char*) pData->getConstArray(), pData->getLength());
+// }
+// else
+// {
+ m_aMemoStream.Write(aStr.GetBuffer(), aStr.Len());
+ // }
+ m_aMemoStream.Flush();
+ }
+ }
+
+
+ // Schreiben der neuen Blocknummer
+ if (bAppend)
+ {
+ nStreamSize = m_aMemoStream.Seek(STREAM_SEEK_TO_END);
+ m_aMemoHeader.db_next = (nStreamSize / m_aMemoHeader.db_size) + ((nStreamSize % m_aMemoHeader.db_size) > 0 ? 1 : 0);
+
+ // Schreiben der neuen Blocknummer
+ m_aMemoStream.Seek(0L);
+ m_aMemoStream << m_aMemoHeader.db_next;
+ m_aMemoStream.Flush();
+ }
+ return sal_True;
+}
+//------------------------------------------------------------------
+void ODbaseTable::AllocBuffer()
+{
+ UINT16 nSize = m_aHeader.db_slng;
+ OSL_ENSHURE(nSize > 0, "Size too small");
+
+ if (m_nBufferSize != nSize)
+ {
+ delete m_pBuffer;
+ m_pBuffer = NULL;
+ }
+
+ // Falls noch kein Puffer vorhanden: allozieren:
+ if (m_pBuffer == NULL && nSize)
+ {
+ m_nBufferSize = nSize;
+ m_pBuffer = new BYTE[m_nBufferSize+1];
+ }
+}
+// -------------------------------------------------------------------------
+Reference<XFastPropertySet> ODbaseTable::isUniqueByColumnName(const ::rtl::OUString& _rColName)
+{
+ if(!m_pIndexes)
+ refreshIndexes();
+ Reference<XFastPropertySet> xIndex;
+ for(sal_Int32 i=0;i<m_pIndexes->getCount();++i)
+ {
+ m_pIndexes->getByIndex(i) >>= xIndex;
+ if(getBOOL(xIndex->getFastPropertyValue(PROPERTY_ID_ISUNIQUE)))
+ {
+ Reference<XNameAccess> xCols(Reference<XColumnsSupplier>(xIndex,UNO_QUERY)->getColumns());
+ if(xCols->hasByName(_rColName))
+ return xIndex;
+
+ }
+ }
+ return Reference<XFastPropertySet>();
+}
+//------------------------------------------------------------------
+double toDouble(const ByteString& rString)
+{
+ static International aInter(LANGUAGE_ENGLISH);
+ static int nErrno=0;
+ BOOL bInitialized = FALSE;
+ if (!bInitialized)
+ { // ensure that the two members we're interested in are really set
+ // (if the system doesn't know the locale en_US aIntl would be initialized with the
+ // system language which may be anything - which we don't want ...)
+ // 74342 - 21.03.00 - FS
+ aInter.SetNumThousandSep(',');
+ aInter.SetNumDecimalSep('.');
+ bInitialized = TRUE;
+ }
+ return SolarMath::StringToDouble(UniString(rString,gsl_getSystemTextEncoding()).GetBuffer(),aInter,nErrno);
+}
+
+//------------------------------------------------------------------
+BOOL ODbaseTable::UpdateBuffer(OValueVector& rRow, OValueRow pOrgRow,const Reference<XIndexAccess>& _xCols)
+{
+ USHORT nByteOffset = 1;
+
+ // Felder aktualisieren:
+ Reference<XFastPropertySet> xCol;
+ Reference<XFastPropertySet> xIndex;
+ USHORT i;
+ ::rtl::OUString aColName;
+ ::std::vector< Reference<XFastPropertySet> > aIndexedCols(m_pColumns->getCount());
+
+ ::utl::UStringMixEqual aCase(isCaseSensitive());
+
+ // first search a key that exist already in the table
+ for (i = 0; i < m_pColumns->getCount(); i++)
+ {
+ m_pColumns->getByIndex(i) >>= xCol;
+ xCol->getFastPropertyValue(PROPERTY_ID_NAME) >>= aColName;
+
+ // const SdbFILEColumn *pColumn = (const SdbFILEColumn *)(*aOriginalColumns)[i];
+ sal_Int32 nPos = 0;
+ for(;nPos<_xCols->getCount();++nPos)
+ {
+ Reference<XFastPropertySet> xFindCol;
+ _xCols->getByIndex(nPos) >>= xFindCol;
+ if(aCase(getString(xFindCol->getFastPropertyValue(PROPERTY_ID_NAME)),aColName))
+ break;
+ }
+ if (nPos >= _xCols->getCount())
+ continue;
+
+ ++nPos;
+ // ODbVariant* pVal = (*rRow)[nPos].getBodyPtr();
+ xIndex = isUniqueByColumnName(aColName);
+ aIndexedCols[i] = xIndex;
+ if (xIndex.is())
+ {
+ // Update !!
+ if(pOrgRow.isValid() && (rRow[nPos].isNull() || rRow[nPos] == (*pOrgRow)[nPos]))
+//
+// if (pOrgRow && (pVal == NULL ||
+// !pVal->isModified() ||
+// *pVal == *(*pOrgRow)[nPos]))
+ continue;
+ else
+ {
+ // ODbVariantRef xVar = (pVal == NULL) ? new ODbVariant() : pVal;
+ Reference<XUnoTunnel> xTunnel(xIndex,UNO_QUERY);
+ OSL_ENSHURE(xTunnel.is(),"No TunnelImplementation!");
+ ODbaseIndex* pIndex = (ODbaseIndex*)xTunnel->getSomething(ODbaseIndex::getUnoTunnelImplementationId());
+ OSL_ENSHURE(pIndex,"ODbaseTable::UpdateBuffer: No Index returned!");
+
+ if (pIndex->Find(0,rRow[nPos]))
+ {
+ // es existiert kein eindeutiger Wert
+// String aText = String(SdbResId(STR_VALUE_NOTUNIQUE));
+// aText.SearchAndReplace(String::CreateFromAscii("#"),pColumn->GetName());
+// String strDetailed = String(SdbResId(STR_DBF_DUPL_VALUE_INFO));
+// strDetailed.SearchAndReplace(String::CreateFromAscii("$col$"),pColumn->GetName());
+// aStatus.Set(SDB_STAT_ERROR,
+// String::CreateFromAscii("01000"),
+// aStatus.CreateErrorMessage(aText),
+// 0, strDetailed );
+ return FALSE;
+ }
+ }
+ }
+ }
+
+ // when we are here there is no double key in the table
+
+ for (i = 0; i < m_pColumns->getCount(); i++)
+ {
+ m_pColumns->getByIndex(i) >>= xCol;
+ xCol->getFastPropertyValue(PROPERTY_ID_NAME) >>= aColName;
+
+ // Laengen je nach Datentyp:
+ // nyi: eine zentrale Funktion, die die Laenge liefert!
+ USHORT nLen = (USHORT)getINT32(xCol->getFastPropertyValue(PROPERTY_ID_PRECISION));
+ sal_Int32 nType = getINT32(xCol->getFastPropertyValue(PROPERTY_ID_TYPE));
+ switch (nType)
+ {
+ case DataType::DATE: nLen = 8; break;
+ case DataType::DECIMAL:
+ nLen = SvDbaseConverter::ConvertPrecisionToDbase(nLen,getINT32(xCol->getFastPropertyValue(PROPERTY_ID_SCALE)));
+ break; // das Vorzeichen und das Komma
+ case DataType::BIT: nLen = 1; break;
+ case DataType::LONGVARCHAR:nLen = 10; break;
+ default: break;
+
+ }
+
+ sal_Int32 nPos = 0;
+ for(;nPos<_xCols->getCount();++nPos)
+ {
+ Reference<XFastPropertySet> xFindCol;
+ _xCols->getByIndex(nPos) >>= xFindCol;
+ if(aCase(getString(xFindCol->getFastPropertyValue(PROPERTY_ID_NAME)),aColName))
+ break;
+ }
+
+ if (nPos >= _xCols->getCount())
+ {
+ nByteOffset += nLen;
+ continue;
+ }
+
+ ++nPos; // the row values start at 1
+ // ODbVariant* pVal = (*rRow)[nPos].getBodyPtr();
+ if (aIndexedCols[i].is())
+ {
+ Reference<XUnoTunnel> xTunnel(aIndexedCols[i],UNO_QUERY);
+ OSL_ENSHURE(xTunnel.is(),"No TunnelImplementation!");
+ ODbaseIndex* pIndex = (ODbaseIndex*)xTunnel->getSomething(ODbaseIndex::getUnoTunnelImplementationId());
+ OSL_ENSHURE(pIndex,"ODbaseTable::UpdateBuffer: No Index returned!");
+ // Update !!
+ if (pOrgRow.isValid() && !rRow[nPos].isNull() )//&& pVal->isModified())
+ pIndex->Update(m_nFilePos,(*pOrgRow)[nPos],rRow[nPos]);
+ else
+ {
+ // ODbVariantRef xVar = (pVal == NULL) ? new ODbVariant() : pVal;
+ pIndex->Insert(m_nFilePos,rRow[nPos]);
+ }
+ }
+
+ // Ist die Variable ueberhaupt gebunden?
+ if (!rRow[nPos].isBound() )//|| !pVal->isModified())
+ {
+ // Nein - naechstes Feld.
+ nByteOffset += nLen;
+ continue;
+ }
+
+ char* pData = (char *)(m_pBuffer + nByteOffset);
+ if (rRow[nPos].isNull())
+ {
+ memset(pData,' ',nLen); // Zuruecksetzen auf NULL
+ nByteOffset += nLen;
+ continue;
+ }
+ try
+ {
+ switch (nType)
+ {
+ case DataType::DATE:
+ {
+ ::com::sun::star::util::Date aDate = DateConversion::toDate(rRow[nPos]);
+ char s[9];
+ sprintf(s,"%04d%02d%02d",
+ (int)aDate.Year,
+ (int)aDate.Month,
+ (int)aDate.Day);
+
+ // Genau 8 Byte kopieren:
+ strncpy(pData,s,sizeof s - 1);
+ } break;
+ case DataType::DECIMAL:
+ {
+ memset(pData,' ',nLen); // Zuruecksetzen auf NULL
+
+ double n = rRow[nPos];
+
+ int nPrecision = (int)getINT32(xCol->getFastPropertyValue(PROPERTY_ID_PRECISION));
+ int nScale = (int)getINT32(xCol->getFastPropertyValue(PROPERTY_ID_SCALE));
+ // ein const_cast, da GetFormatPrecision am SvNumberFormat nicht const ist, obwohl es das eigentlich
+ // sein koennte und muesste
+
+ String aString;
+ SolarMath::DoubleToString(aString,n,'F',nScale,'.');
+ ByteString aDefaultValue(aString,gsl_getSystemTextEncoding());
+ BOOL bValidLength = FALSE;
+ if (aDefaultValue.Len() <= nLen)
+ {
+ strncpy(pData,aDefaultValue.GetBuffer(),nLen);
+ // write the resulting double back
+ rRow[nPos] = toDouble(aDefaultValue);
+ bValidLength = TRUE;
+ }
+ if (!bValidLength)
+ {
+// String strError(SdbResId(STR_DBF_INVALID_FIELD_VALUE));
+// strError.SearchAndReplace(String::CreateFromAscii("$name$"), pColumn->GetName());
+//
+// String strDetailedInformation(SdbResId(STR_DBF_INVALID_FIELD_VALUE_DECIMAL));
+// strDetailedInformation.SearchAndReplace(String::CreateFromAscii("$name$"), pColumn->GetName());
+// strDetailedInformation.SearchAndReplace(String::CreateFromAscii("#length#"), nPrecision);
+// strDetailedInformation.SearchAndReplace(String::CreateFromAscii("#scale#"), nScale);
+// aStatus.Set(SDB_STAT_ERROR, String::CreateFromAscii("S1000"), aStatus.CreateErrorMessage(strError), 0, strDetailedInformation);
+ }
+ } break;
+ case DataType::BIT:
+ *pData = rRow[nPos].getBool() ? 'T' : 'F';
+ break;
+ case DataType::LONGVARCHAR:
+ {
+ char cNext = pData[nLen]; // merken und temporaer durch 0 ersetzen
+ pData[nLen] = '\0'; // das geht, da der Puffer immer ein Zeichen groesser ist ...
+
+ ULONG nBlockNo = strtol((const char *)pData,NULL,10); // Blocknummer lesen
+
+ // Naechstes Anfangszeichen wieder restaurieren:
+ pData[nLen] = cNext;
+ if (!m_aMemoStream.IsOpen() || !WriteMemo(rRow[nPos], nBlockNo))
+ break;
+
+ ByteString aStr;
+ ByteString aBlock(ByteString::CreateFromInt32(nBlockNo));
+ aStr.Expand(nLen - aBlock.Len(), '0');
+ aStr += aBlock;
+ aStr.Convert(gsl_getSystemTextEncoding(),osl_getThreadTextEncoding());
+ // Zeichen kopieren:
+ memset(pData,' ',nLen); // Zuruecksetzen auf NULL
+ memcpy(pData, aStr.GetBuffer(), nLen);
+ } break;
+ default:
+ {
+ memset(pData,' ',nLen); // Zuruecksetzen auf NULL
+ ByteString aStr(rRow[nPos].getString().getStr(),osl_getThreadTextEncoding());
+ // Zeichen kopieren:
+ memcpy(pData, aStr.GetBuffer(), min(nLen,aStr.Len()));
+ } break;
+ }
+ }
+ catch ( ... )
+ {
+// String strError(SdbResId(STR_DBF_INVALID_FIELD_VALUE));
+// strError.SearchAndReplace(String::CreateFromAscii("$name$"), pColumn->GetName());
+// aStatus.Set(SDB_STAT_ERROR, String::CreateFromAscii("S1000"), aStatus.CreateErrorMessage(strError), 0, String());
+ }
+// if (aStatus.IsError())
+// break;
+ // Und weiter ...
+ nByteOffset += nLen;
+ }
+ return sal_True;
+}
+
+
+//------------------------------------------------------------------
+BOOL ODbaseTable::WriteBuffer()
+{
+ OSL_ENSHURE(m_nFilePos >= 1,"SdbDBFCursor::FileFetchRow: ungueltige Record-Position");
+
+ // Auf gewuenschten Record positionieren:
+ long nPos = m_aHeader.db_kopf + (long)(m_nFilePos-1) * m_aHeader.db_slng;
+ m_aFileStream.Seek(nPos);
+ return m_aFileStream.Write((char*) m_pBuffer, m_aHeader.db_slng) > 0;
+}
+
+