Files
libreoffice/connectivity/source/drivers/dbase/DTable.cxx

2038 lines
75 KiB
C++
Raw Normal View History

2000-09-18 15:18:56 +00:00
/*************************************************************************
*
* $RCSfile: DTable.cxx,v $
*
* $Revision: 1.66 $
2000-09-18 15:18:56 +00:00
*
* last change: $Author: hr $ $Date: 2001-10-12 15:21:00 $
2000-09-18 15:18:56 +00:00
*
* 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,
2000-09-20 05:52:26 +00:00
* WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING,
2000-09-18 15:18:56 +00:00
* 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
2000-10-09 11:34:19 +00:00
#ifndef _COMPHELPER_SEQUENCE_HXX_
#include <comphelper/sequence.hxx>
2000-09-18 15:18:56 +00:00
#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 _COMPHELPER_EXTRACT_HXX_
#include <comphelper/extract.hxx>
2000-09-18 15:18:56 +00:00
#endif
#ifndef _DBHELPER_DBEXCEPTION_HXX_
#include <connectivity/dbexception.hxx>
#endif
2000-12-06 11:07:47 +00:00
#ifndef _DBHELPER_DBCONVERSION_HXX_
#include <connectivity/dbconversion.hxx>
2000-12-06 11:07:47 +00:00
#endif
2001-03-28 10:32:43 +00:00
#ifndef _COM_SUN_STAR_LANG_DISPOSEDEXCEPTION_HPP_
#include <com/sun/star/lang/DisposedException.hpp>
#endif
#ifndef _COMPHELPER_PROPERTY_HXX_
#include <comphelper/property.hxx>
#endif
#ifndef _UNOTOOLS_TEMPFILE_HXX
#include <unotools/tempfile.hxx>
#endif
2001-05-28 12:03:37 +00:00
#ifndef _UNOTOOLS_UCBHELPER_HXX
#include <unotools/ucbhelper.hxx>
#endif
2001-03-28 10:32:43 +00:00
#ifndef _COMPHELPER_TYPES_HXX_
#include <comphelper/types.hxx>
#endif
2001-05-28 12:03:37 +00:00
#ifndef _CONNECTIVITY_SDBCX_COLUMN_HXX_
#include "connectivity/PColumn.hxx"
#endif
2000-09-18 15:18:56 +00:00
#include <algorithm>
2001-05-18 07:51:34 +00:00
using namespace ::comphelper;
2000-09-18 15:18:56 +00:00
using namespace connectivity;
2001-03-30 11:46:36 +00:00
using namespace connectivity::sdbcx;
2000-09-18 15:18:56 +00:00
using namespace connectivity::dbase;
using namespace connectivity::file;
using namespace ::ucb;
2001-03-28 10:32:43 +00:00
using namespace ::utl;
using namespace ::cppu;
using namespace ::dbtools;
2000-09-18 15:18:56 +00:00
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()
{
OSL_ENSURE(m_pFileStream,"No Stream available!");
if(!m_pFileStream)
return;
2001-08-02 06:59:15 +00:00
sal_Bool bError = sal_False;
2000-11-16 09:47:23 +00:00
m_pFileStream->RefreshBuffer(); // sicherstellen, dass die Kopfinformationen tatsaechlich neu gelesen werden
m_pFileStream->Seek(STREAM_SEEK_TO_BEGIN);
2000-09-18 15:18:56 +00:00
2001-08-02 06:59:15 +00:00
BYTE nType=0;
(*m_pFileStream) >> nType;
2001-08-02 06:59:15 +00:00
if(ERRCODE_NONE != m_pFileStream->GetErrorCode())
throwInvalidDbaseFormat();
m_pFileStream->Read((char*)(&m_aHeader.db_aedat), 3*sizeof(BYTE));
2001-08-02 06:59:15 +00:00
if(ERRCODE_NONE != m_pFileStream->GetErrorCode())
throwInvalidDbaseFormat();
2000-11-16 09:47:23 +00:00
(*m_pFileStream) >> m_aHeader.db_anz;
2001-08-02 06:59:15 +00:00
if(ERRCODE_NONE != m_pFileStream->GetErrorCode())
throwInvalidDbaseFormat();
2000-11-16 09:47:23 +00:00
(*m_pFileStream) >> m_aHeader.db_kopf;
2001-08-02 06:59:15 +00:00
if(ERRCODE_NONE != m_pFileStream->GetErrorCode())
throwInvalidDbaseFormat();
2000-11-16 09:47:23 +00:00
(*m_pFileStream) >> m_aHeader.db_slng;
2001-08-02 06:59:15 +00:00
if(ERRCODE_NONE != m_pFileStream->GetErrorCode())
throwInvalidDbaseFormat();
m_pFileStream->Read((char*)(&m_aHeader.db_frei), 20*sizeof(BYTE));
2001-08-02 06:59:15 +00:00
if(ERRCODE_NONE != m_pFileStream->GetErrorCode())
throwInvalidDbaseFormat();
2000-09-18 15:18:56 +00:00
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
{
// no dbase file
2001-08-02 06:59:15 +00:00
throwInvalidDbaseFormat();
2000-09-18 15:18:56 +00:00
}
else
{
// Konsistenzpruefung des Header:
m_aHeader.db_typ = (DBFType)nType;
2000-09-18 15:18:56 +00:00
switch (m_aHeader.db_typ)
{
case dBaseIII:
case dBaseIV:
case dBaseV:
case dBaseFS:
case dBaseFSMemo:
case dBaseIVMemoSQL:
case dBaseIIIMemo:
case dBaseIVMemo:
case FoxProMemo:
2000-11-16 09:47:23 +00:00
m_pFileStream->SetNumberFormatInt(NUMBERFORMAT_INT_LITTLEENDIAN);
2000-09-18 15:18:56 +00:00
break;
default:
{
2001-08-02 06:59:15 +00:00
throwInvalidDbaseFormat();
2000-09-18 15:18:56 +00:00
}
}
}
}
// -------------------------------------------------------------------------
void ODbaseTable::fillColumns()
{
2000-11-16 09:47:23 +00:00
m_pFileStream->Seek(STREAM_SEEK_TO_BEGIN);
m_pFileStream->Seek(32L);
2000-09-18 15:18:56 +00:00
2001-05-30 09:44:16 +00:00
if(!m_aColumns.isValid())
m_aColumns = new OSQLColumns();
else
m_aColumns->clear();
2001-03-28 10:32:43 +00:00
m_aTypes.clear();
m_aPrecisions.clear();
m_aScales.clear();
2000-09-18 15:18:56 +00:00
// Anzahl Felder:
sal_Int32 nFieldCount = (m_aHeader.db_kopf - 1) / 32 - 1;
m_aColumns->reserve(nFieldCount);
m_aTypes.reserve(nFieldCount);
m_aPrecisions.reserve(nFieldCount);
m_aScales.reserve(nFieldCount);
2000-09-18 15:18:56 +00:00
String aStrFieldName;aStrFieldName.AssignAscii("Column");
sal_Int32 nFieldCnt = 0;
::rtl::OUString aTypeName;
static const ::rtl::OUString sVARCHAR = ::rtl::OUString::createFromAscii("VARCHAR");
sal_Bool bCase = getConnection()->getMetaData()->storesMixedCaseQuotedIdentifiers();
2000-09-18 15:18:56 +00:00
for (sal_Int32 i = 0; i < nFieldCount; i++)
2000-09-18 15:18:56 +00:00
{
DBFColumn aDBFColumn;
2000-11-16 09:47:23 +00:00
m_pFileStream->Read((char*)&aDBFColumn, sizeof(aDBFColumn));
2000-09-18 15:18:56 +00:00
2000-09-29 14:30:09 +00:00
String aColumnName((const char *)aDBFColumn.db_fnm,getConnection()->getTextEncoding());
2000-09-18 15:18:56 +00:00
sal_Int32 nPrecision = aDBFColumn.db_flng;
sal_Int32 eType;
switch (aDBFColumn.db_typ)
{
case 'C':
eType = DataType::VARCHAR;
aTypeName = sVARCHAR;
2000-09-18 15:18:56 +00:00
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,
bCase);
2000-10-30 07:07:33 +00:00
Reference< XPropertySet> xCol = pColumn;
2000-09-18 15:18:56 +00:00
m_aColumns->push_back(xCol);
2000-11-27 07:00:26 +00:00
m_aTypes.push_back(eType);
m_aPrecisions.push_back(nPrecision);
m_aScales.push_back(aDBFColumn.db_dez);
2000-09-18 15:18:56 +00:00
}
}
// -------------------------------------------------------------------------
ODbaseTable::ODbaseTable(sdbcx::OCollection* _pTables,ODbaseConnection* _pConnection)
:ODbaseTable_BASE(_pTables,_pConnection)
,m_pMemoStream(NULL)
,m_bWriteableMemo(sal_False)
2000-09-18 15:18:56 +00:00
{
2000-11-16 09:47:23 +00:00
// initialize the header
m_aHeader.db_typ = dBaseIII;
m_aHeader.db_anz = 0;
m_aHeader.db_kopf = 0;
m_aHeader.db_slng = 0;
2000-09-18 15:18:56 +00:00
}
// -------------------------------------------------------------------------
ODbaseTable::ODbaseTable(sdbcx::OCollection* _pTables,ODbaseConnection* _pConnection,
2000-09-18 15:18:56 +00:00
const ::rtl::OUString& _Name,
const ::rtl::OUString& _Type,
const ::rtl::OUString& _Description ,
const ::rtl::OUString& _SchemaName,
const ::rtl::OUString& _CatalogName
) : ODbaseTable_BASE(_pTables,_pConnection,_Name,
2000-09-18 15:18:56 +00:00
_Type,
_Description,
_SchemaName,
_CatalogName)
2000-11-17 06:37:01 +00:00
,m_pMemoStream(NULL)
,m_bWriteableMemo(sal_False)
2001-02-22 12:53:00 +00:00
{
}
2001-02-22 12:53:00 +00:00
// -----------------------------------------------------------------------------
void ODbaseTable::construct()
2000-09-18 15:18:56 +00:00
{
2000-11-16 09:47:23 +00:00
// initialize the header
m_aHeader.db_typ = dBaseIII;
m_aHeader.db_anz = 0;
m_aHeader.db_kopf = 0;
m_aHeader.db_slng = 0;
String sFileName(getEntry(m_pConnection,m_Name));
2000-09-18 15:18:56 +00:00
INetURLObject aURL;
aURL.SetURL(sFileName);
2000-09-18 15:18:56 +00:00
OSL_ENSURE(aURL.getExtension() == m_pConnection->getExtension(),
"ODbaseTable::ODbaseTable: invalid extension!");
// getEntry is expected to ensure the corect file name
2000-11-16 09:47:23 +00:00
m_pFileStream = createStream_simpleError( sFileName, STREAM_READWRITE | STREAM_NOCREATE | STREAM_SHARE_DENYWRITE);
2000-09-18 15:18:56 +00:00
if (!(m_bWriteable = (NULL != m_pFileStream)))
m_pFileStream = createStream_simpleError( sFileName, STREAM_READ | STREAM_NOCREATE | STREAM_SHARE_DENYNONE);
2000-09-18 15:18:56 +00:00
2000-11-16 09:47:23 +00:00
if(m_pFileStream)
2000-09-18 15:18:56 +00:00
{
readHeader();
2001-03-01 09:56:00 +00:00
if (HasMemoFields())
2000-09-18 15:18:56 +00:00
{
2001-03-01 09:56:00 +00:00
// Memo-Dateinamen bilden (.DBT):
// nyi: Unschoen fuer Unix und Mac!
2000-09-18 15:18:56 +00:00
2001-03-01 09:56:00 +00:00
if (m_aHeader.db_typ == FoxProMemo) // foxpro uses another extension
aURL.SetExtension(String::CreateFromAscii("fpt"));
else
aURL.SetExtension(String::CreateFromAscii("dbt"));
2001-03-01 09:56:00 +00:00
// Wenn die Memodatei nicht gefunden wird, werden die Daten trotzdem angezeigt
// allerdings koennen keine Updates durchgefuehrt werden
// jedoch die Operation wird ausgefuehrt
m_pMemoStream = createStream_simpleError( aURL.GetMainURL(INetURLObject::NO_DECODE), STREAM_READWRITE | STREAM_NOCREATE | STREAM_SHARE_DENYWRITE);
2001-03-01 09:56:00 +00:00
if (!(m_bWriteableMemo = (NULL != m_pMemoStream)))
m_pMemoStream = createStream_simpleError( aURL.GetMainURL(INetURLObject::NO_DECODE), STREAM_READ | STREAM_NOCREATE | STREAM_SHARE_DENYNONE);
2001-03-01 09:56:00 +00:00
if (m_pMemoStream)
ReadMemoHeader();
}
2001-05-30 09:44:16 +00:00
// if(!m_pColumns && (!m_aColumns.isValid() || !m_aColumns->size()))
fillColumns();
2000-09-18 15:18:56 +00:00
2001-03-01 09:56:00 +00:00
m_pFileStream->Seek(STREAM_SEEK_TO_END);
UINT32 nFileSize = m_pFileStream->Tell();
m_pFileStream->Seek(STREAM_SEEK_TO_BEGIN);
2000-09-18 15:18:56 +00:00
2001-03-01 09:56:00 +00:00
// Buffersize abhaengig von der Filegroesse
m_pFileStream->SetBufferSize(nFileSize > 1000000 ? 32768 :
nFileSize > 100000 ? 16384 :
nFileSize > 10000 ? 4096 : 1024);
2001-03-01 09:56:00 +00:00
if (m_pMemoStream)
{
// Puffer genau auf Laenge eines Satzes stellen
m_pMemoStream->Seek(STREAM_SEEK_TO_END);
nFileSize = m_pMemoStream->Tell();
m_pMemoStream->Seek(STREAM_SEEK_TO_BEGIN);
2001-03-01 09:56:00 +00:00
// Buffersize abhaengig von der Filegroesse
m_pMemoStream->SetBufferSize(nFileSize > 1000000 ? 32768 :
nFileSize > 100000 ? 16384 :
nFileSize > 10000 ? 4096 :
m_aMemoHeader.db_size);
}
2000-09-18 15:18:56 +00:00
2001-03-01 09:56:00 +00:00
AllocBuffer();
2000-09-18 15:18:56 +00:00
}
}
//------------------------------------------------------------------
BOOL ODbaseTable::ReadMemoHeader()
{
2000-11-16 09:47:23 +00:00
m_pMemoStream->SetNumberFormatInt(NUMBERFORMAT_INT_LITTLEENDIAN);
m_pMemoStream->RefreshBuffer(); // sicherstellen das die Kopfinformationen tatsaechlich neu gelesen werden
m_pMemoStream->Seek(0L);
2000-09-18 15:18:56 +00:00
2000-11-16 09:47:23 +00:00
(*m_pMemoStream) >> m_aMemoHeader.db_next;
2000-09-18 15:18:56 +00:00
switch (m_aHeader.db_typ)
{
case dBaseIIIMemo: // dBase III: feste Blockgr<67><72>e
case dBaseIVMemo:
// manchmal wird aber auch dBase3 dBase4 Memo zugeordnet
2000-11-16 09:47:23 +00:00
m_pMemoStream->Seek(20L);
(*m_pMemoStream) >> m_aMemoHeader.db_size;
2000-09-18 15:18:56 +00:00
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 G<><47>enangabe,
// sind aber dennoch dBase Dateien
char sHeader[4];
2000-11-16 09:47:23 +00:00
m_pMemoStream->Seek(m_aMemoHeader.db_size);
m_pMemoStream->Read(sHeader,4);
2000-09-18 15:18:56 +00:00
2000-11-16 09:47:23 +00:00
if ((m_pMemoStream->GetErrorCode() != ERRCODE_NONE) || ((BYTE)sHeader[0]) != 0xFF || ((BYTE)sHeader[1]) != 0xFF || ((BYTE)sHeader[2]) != 0x08)
2000-09-18 15:18:56 +00:00
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;
2000-11-16 09:47:23 +00:00
m_pMemoStream->Seek(6L);
m_pMemoStream->SetNumberFormatInt(NUMBERFORMAT_INT_BIGENDIAN);
(*m_pMemoStream) >> m_aMemoHeader.db_size;
2000-09-18 15:18:56 +00:00
}
return TRUE;
}
// -------------------------------------------------------------------------
String ODbaseTable::getEntry(OConnection* _pConnection,const ::rtl::OUString& _sName )
2000-09-18 15:18:56 +00:00
{
::rtl::OUString aURL;
2001-03-30 11:07:07 +00:00
try
2000-09-18 15:18:56 +00:00
{
Reference< XResultSet > xDir = _pConnection->getDir()->getStaticResultSet();
2001-03-30 11:07:07 +00:00
Reference< XRow> xRow(xDir,UNO_QUERY);
::rtl::OUString sName;
::rtl::OUString sExt;
::rtl::OUString sNeededExt(_pConnection->getExtension());
2001-03-30 11:07:07 +00:00
sal_Int32 nExtLen = sNeededExt.getLength();
sal_Int32 nExtLenWithSep = nExtLen + 1;
xDir->beforeFirst();
while(xDir->next())
{
sName = xRow->getString(1);
2001-03-30 11:07:07 +00:00
// cut the extension
sExt = sName.copy(sName.getLength() - nExtLen);
sName = sName.copy(0, sName.getLength() - nExtLenWithSep);
2001-03-30 11:07:07 +00:00
// name and extension have to coincide
if ((sName == _sName) && (sExt == sNeededExt))
2001-03-30 11:07:07 +00:00
{
Reference< XContentAccess > xContentAccess( xDir, UNO_QUERY );
aURL = xContentAccess->queryContentIdentifierString();
break;
}
2000-09-18 15:18:56 +00:00
}
2001-03-30 11:07:07 +00:00
xDir->beforeFirst(); // move back to before first record
}
catch(Exception&)
{
OSL_ASSERT(0);
2000-09-18 15:18:56 +00:00
}
2001-03-30 11:07:07 +00:00
return aURL;
2000-09-18 15:18:56 +00:00
}
// -------------------------------------------------------------------------
void ODbaseTable::refreshColumns()
{
::osl::MutexGuard aGuard( m_aMutex );
TStringVector aVector;
aVector.reserve(m_aColumns->size());
2000-09-18 15:18:56 +00:00
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)
m_pColumns->reFill(aVector);
else
m_pColumns = new ODbaseColumns(this,m_aMutex,aVector);
2000-09-18 15:18:56 +00:00
}
// -------------------------------------------------------------------------
void ODbaseTable::refreshIndexes()
{
TStringVector aVector;
2001-07-16 08:58:40 +00:00
if(m_pFileStream && (!m_pIndexes || m_pIndexes->getCount() == 0))
2000-09-18 15:18:56 +00:00
{
2000-11-16 09:47:23 +00:00
INetURLObject aURL;
aURL.SetURL(getEntry(m_pConnection,m_Name));
2000-11-16 09:47:23 +00:00
aURL.setExtension(String::CreateFromAscii("inf"));
Config aInfFile(aURL.getFSysPath(INetURLObject::FSYS_DETECT));
2000-11-16 09:47:23 +00:00
aInfFile.SetGroup(dBASE_III_GROUP);
2001-03-01 09:51:00 +00:00
USHORT nKeyCnt = aInfFile.GetKeyCount();
2000-11-16 09:47:23 +00:00
ByteString aKeyName;
ByteString aIndexName;
2001-03-01 09:51:00 +00:00
for (USHORT nKey = 0,nPos=0; nKey < nKeyCnt; nKey++)
2000-09-18 15:18:56 +00:00
{
2000-11-16 09:47:23 +00:00
// Verweist der Key auf ein Indexfile?...
aKeyName = aInfFile.GetKeyName( nKey );
//...wenn ja, Indexliste der Tabelle hinzufuegen
if (aKeyName.Copy(0,3) == ByteString("NDX") )
2000-09-18 15:18:56 +00:00
{
2000-11-16 09:47:23 +00:00
aIndexName = aInfFile.ReadKey(aKeyName);
aURL.setName(String(aIndexName,getConnection()->getTextEncoding()));
try
{
2001-07-16 08:58:40 +00:00
Content aCnt(aURL.GetMainURL(INetURLObject::NO_DECODE),Reference<XCommandEnvironment>());
if (aCnt.isDocument())
{
aVector.push_back(aURL.getBase());
}
}
catch(Exception&) // a execption is thrown when no file exists
2000-11-16 09:47:23 +00:00
{
}
2000-09-18 15:18:56 +00:00
}
}
}
if(m_pIndexes)
2001-05-30 09:44:16 +00:00
m_pIndexes->reFill(aVector);
else
m_pIndexes = new ODbaseIndexes(this,m_aMutex,aVector);
2000-09-18 15:18:56 +00:00
}
// -------------------------------------------------------------------------
void SAL_CALL ODbaseTable::disposing(void)
{
OFileTable::disposing();
::osl::MutexGuard aGuard(m_aMutex);
m_aColumns = NULL;
2000-09-18 15:18:56 +00:00
}
// -------------------------------------------------------------------------
Sequence< Type > SAL_CALL ODbaseTable::getTypes( ) throw(RuntimeException)
{
Sequence< Type > aTypes = OTable_TYPEDEF::getTypes();
2001-07-20 11:21:43 +00:00
Sequence< Type > aRet(aTypes.getLength());
2000-09-18 15:18:56 +00:00
const Type* pBegin = aTypes.getConstArray();
const Type* pEnd = pBegin + aTypes.getLength();
sal_Int32 i=0;
2001-05-31 05:11:58 +00:00
for(;pBegin != pEnd;++pBegin)
2000-09-18 15:18:56 +00:00
{
2001-03-28 10:32:43 +00:00
if(!(*pBegin == ::getCppuType((const Reference<XKeysSupplier>*)0) ||
2001-05-30 09:44:16 +00:00
// *pBegin == ::getCppuType((const Reference<XAlterTable>*)0) ||
2000-09-18 15:18:56 +00:00
*pBegin == ::getCppuType((const Reference<XDataDescriptorFactory>*)0)))
{
2001-05-31 05:11:58 +00:00
aRet.getArray()[i++] = *pBegin;
2000-09-18 15:18:56 +00:00
}
}
aRet.getArray()[i] = ::getCppuType( (const Reference< ::com::sun::star::lang::XUnoTunnel > *)0 );
return aRet;
}
// -------------------------------------------------------------------------
Any SAL_CALL ODbaseTable::queryInterface( const Type & rType ) throw(RuntimeException)
{
2001-03-28 10:32:43 +00:00
if( rType == ::getCppuType((const Reference<XKeysSupplier>*)0) ||
2000-09-18 15:18:56 +00:00
rType == ::getCppuType((const Reference<XDataDescriptorFactory>*)0))
return Any();
Any aRet = OTable_TYPEDEF::queryInterface(rType);
return aRet.hasValue() ? aRet : ::cppu::queryInterface(rType,static_cast< ::com::sun::star::lang::XUnoTunnel*> (this));
2000-09-18 15:18:56 +00:00
}
//--------------------------------------------------------------------------
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)
{
return (rId.getLength() == 16 && 0 == rtl_compareMemory(getUnoTunnelImplementationId().getConstArray(), rId.getConstArray(), 16 ) )
?
(sal_Int64)this
:
ODbaseTable_BASE::getSomething(rId);
2000-09-18 15:18:56 +00:00
}
//------------------------------------------------------------------
2001-03-28 10:32:43 +00:00
sal_Bool ODbaseTable::fetchRow(OValueRow _rRow,const OSQLColumns & _rCols, sal_Bool _bUseTableDefs,sal_Bool bRetrieveData)
2000-09-18 15:18:56 +00:00
{
// Einlesen der Daten
2000-09-29 14:30:09 +00:00
BOOL bIsCurRecordDeleted = ((char)m_pBuffer[0] == '*') ? TRUE : sal_False;
2000-09-18 15:18:56 +00:00
// 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++)
{
// Laengen je nach Datentyp:
sal_Int32 nLen;
2000-11-27 07:00:26 +00:00
sal_Int32 nType;
if(_bUseTableDefs)
{
2000-12-13 14:21:14 +00:00
nLen = m_aPrecisions[i-1];
nType = m_aTypes[i-1];
2000-11-27 07:00:26 +00:00
}
else
{
(*aIter)->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_PRECISION)) >>= nLen;
(*aIter)->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_TYPE)) >>= nType;
2000-11-27 07:00:26 +00:00
}
2000-09-18 15:18:56 +00:00
switch(nType)
{
case DataType::DATE: nLen = 8; break;
case DataType::DECIMAL:
2000-11-27 07:00:26 +00:00
if(_bUseTableDefs)
2000-12-13 14:21:14 +00:00
nLen = SvDbaseConverter::ConvertPrecisionToDbase(nLen,m_aScales[i-1]);
2000-11-27 07:00:26 +00:00
else
nLen = SvDbaseConverter::ConvertPrecisionToDbase(nLen,getINT32((*aIter)->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_SCALE))));
2000-09-18 15:18:56 +00:00
break; // das Vorzeichen und das Komma
case DataType::BIT: nLen = 1; break;
case DataType::LONGVARCHAR: nLen = 10; break;
case DataType::OTHER:
nByteOffset += nLen;
continue;
}
// Ist die Variable ueberhaupt gebunden?
if (!(*_rRow)[i].isBound())
{
// Nein - naechstes Feld.
nByteOffset += nLen;
continue;
}
char *pData = (char *) (m_pBuffer + nByteOffset);
2000-09-29 14:30:09 +00:00
// (*_rRow)[i].setType(nType);
2000-09-18 15:18:56 +00:00
if (nType == DataType::CHAR || nType == DataType::VARCHAR)
{
char cLast = pData[nLen];
pData[nLen] = 0;
2001-03-01 09:51:00 +00:00
String aStr(pData,(xub_StrLen)nLen,getConnection()->getTextEncoding());
2000-09-18 15:18:56 +00:00
aStr.EraseTrailingChars();
if (!aStr.Len()) // keine StringLaenge, dann NULL
(*_rRow)[i].setNull();
else
(*_rRow)[i] = aStr;
2000-09-18 15:18:56 +00:00
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] = ' ';
}
2001-03-01 09:51:00 +00:00
String aStr(pData, (xub_StrLen)nLen,getConnection()->getTextEncoding()); // Spaces am Anfang und am Ende entfernen:
2000-09-18 15:18:56 +00:00
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;
}
2001-03-01 09:51:00 +00:00
sal_uInt16 nYear = (sal_uInt16)aStr.Copy( 0, 4 ).ToInt32();
sal_uInt16 nMonth = (sal_uInt16)aStr.Copy( 4, 2 ).ToInt32();
sal_uInt16 nDay = (sal_uInt16)aStr.Copy( 6, 2 ).ToInt32();
2000-09-18 15:18:56 +00:00
::com::sun::star::util::Date aDate(nDay,nMonth,nYear);
2000-12-06 11:07:47 +00:00
(*_rRow)[i] = aDate;
2000-09-18 15:18:56 +00:00
}
break;
case DataType::DECIMAL:
(*_rRow)[i] = aStr;
2000-09-18 15:18:56 +00:00
// pVal->setDouble(SdbTools::ToDouble(aStr));
break;
case DataType::BIT:
{
BOOL b;
switch (* ((const char *)pData))
{
case 'T':
case 'Y':
case 'J': b = TRUE; break;
2000-09-29 14:30:09 +00:00
default: b = sal_False; break;
2000-09-18 15:18:56 +00:00
}
(*_rRow)[i] = b;
// pVal->setDouble(b);
}
break;
case DataType::LONGVARCHAR:
{
long nBlockNo = aStr.ToInt32(); // Blocknummer lesen
2000-11-16 09:47:23 +00:00
if (nBlockNo > 0 && m_pMemoStream) // Daten aus Memo-Datei lesen, nur wenn
2000-09-18 15:18:56 +00:00
{
if (!ReadMemo(nBlockNo, (*_rRow)[i]))
break;
}
else
(*_rRow)[i].setNull();
} break;
default:
OSL_ASSERT("Falscher Type");
}
2000-10-17 08:15:19 +00:00
(*_rRow)[i].setTypeKind(nType);
2000-09-18 15:18:56 +00:00
}
// if (aStatus.IsError())
// break;
// Und weiter ...
nByteOffset += nLen;
}
return sal_True;
}
//------------------------------------------------------------------
// -------------------------------------------------------------------------
void ODbaseTable::FileClose()
{
2000-11-03 13:21:22 +00:00
::osl::MutexGuard aGuard(m_aMutex);
2000-09-18 15:18:56 +00:00
// falls noch nicht alles geschrieben wurde
2000-11-16 09:47:23 +00:00
if (m_pMemoStream && m_pMemoStream->IsWritable())
m_pMemoStream->Flush();
2000-09-18 15:18:56 +00:00
2000-11-16 09:47:23 +00:00
delete m_pMemoStream;
m_pMemoStream = NULL;
2000-09-18 15:18:56 +00:00
2000-11-03 13:21:22 +00:00
ODbaseTable_BASE::FileClose();
2000-09-18 15:18:56 +00:00
}
// -------------------------------------------------------------------------
BOOL ODbaseTable::CreateImpl()
{
2001-02-14 06:22:50 +00:00
OSL_ENSURE(!m_pFileStream, "SequenceError");
2000-09-18 15:18:56 +00:00
INetURLObject aURL;
aURL.SetSmartProtocol(INET_PROT_FILE);
String aName = getEntry(m_pConnection,m_Name);
2000-10-25 12:31:00 +00:00
if(!aName.Len())
{
::rtl::OUString aIdent = m_pConnection->getContent()->getIdentifier()->getContentIdentifier();
2001-02-22 12:53:00 +00:00
aIdent += ::rtl::OUString::createFromAscii("/");
2000-10-25 12:31:00 +00:00
aIdent += m_Name;
aName = aIdent.getStr();
}
2000-11-16 09:47:23 +00:00
aURL.SetURL(aName);
2000-09-18 15:18:56 +00:00
if(aURL.getExtension() != m_pConnection->getExtension())
aURL.setExtension(m_pConnection->getExtension());
2001-07-16 08:58:40 +00:00
Content aContent(aURL.GetMainURL(INetURLObject::NO_DECODE),Reference<XCommandEnvironment>());
try
2000-09-18 15:18:56 +00:00
{
if (aContent.isDocument())
2000-09-18 15:18:56 +00:00
{
// Hack fuer Bug #30609 , nur wenn das File existiert und die Laenge > 0 gibt es einen Fehler
SvStream* pFileStream = createStream_simpleError( aURL.GetMainURL(INetURLObject::NO_DECODE),STREAM_READ);
if (pFileStream && pFileStream->Seek(STREAM_SEEK_TO_END))
{
// aStatus.SetError(ERRCODE_IO_ALREADYEXISTS,TABLE,aFile.GetFull());
return sal_False;
}
delete pFileStream;
2000-09-18 15:18:56 +00:00
}
}
catch(Exception&) // a execption is thrown when no file exists
{
2000-09-18 15:18:56 +00:00
}
2000-09-29 14:30:09 +00:00
BOOL bMemoFile = sal_False;
2000-09-18 15:18:56 +00:00
sal_Bool bOk = CreateFile(aURL, bMemoFile);
FileClose();
if (!bOk)
{
aContent.executeCommand( rtl::OUString::createFromAscii( "delete" ),bool2any( sal_True ) );
2000-09-29 14:30:09 +00:00
return sal_False;
2000-09-18 15:18:56 +00:00
}
if (bMemoFile)
{
String aExt = aURL.getExtension();
aURL.setExtension(String::CreateFromAscii("dbt")); // extension for memo file
2001-07-16 08:58:40 +00:00
Content aMemo1Content(aURL.GetMainURL(INetURLObject::NO_DECODE),Reference<XCommandEnvironment>());
2000-09-18 15:18:56 +00:00
2001-03-02 12:29:11 +00:00
sal_Bool bMemoAlreadyExists = sal_False;
try
{
bMemoAlreadyExists = aMemo1Content.isDocument();
}
catch(Exception&) // a execption is thrown when no file exists
{
}
if (bMemoAlreadyExists)
2000-09-18 15:18:56 +00:00
{
// aStatus.SetError(ERRCODE_IO_ALREADYEXISTS,MEMO,aFile.GetFull());
aURL.setExtension(aExt); // kill dbf file
2001-05-28 12:03:37 +00:00
try
{
2001-07-16 08:58:40 +00:00
Content aMemoContent(aURL.GetMainURL(INetURLObject::NO_DECODE),Reference<XCommandEnvironment>());
2001-05-28 12:03:37 +00:00
aMemoContent.executeCommand( rtl::OUString::createFromAscii( "delete" ),bool2any( sal_True ) );
}
catch(const Exception&)
{
::rtl::OUString sMessage = ::rtl::OUString::createFromAscii("[StarOffice Base dbase] The memo file '");
sMessage += aName;
sMessage += ::rtl::OUString::createFromAscii(" already exists.");
throwGenericSQLException(sMessage, static_cast<XNamed*>(this));
}
2000-09-18 15:18:56 +00:00
}
if (!CreateMemoFile(aURL))
{
aURL.setExtension(aExt); // kill dbf file
2001-07-16 08:58:40 +00:00
Content aMemoContent(aURL.GetMainURL(INetURLObject::NO_DECODE),Reference<XCommandEnvironment>());
2000-09-18 15:18:56 +00:00
aMemoContent.executeCommand( rtl::OUString::createFromAscii( "delete" ),bool2any( sal_True ) );
2000-09-29 14:30:09 +00:00
return sal_False;
2000-09-18 15:18:56 +00:00
}
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 grunds<64>tzlich dBase IV Datei Format
BOOL ODbaseTable::CreateFile(const INetURLObject& aFile, BOOL& bCreateMemo)
{
2000-09-29 14:30:09 +00:00
bCreateMemo = sal_False;
2000-09-18 15:18:56 +00:00
Date aDate; // aktuelles Datum
m_pFileStream = createStream_simpleError( aFile.GetMainURL(INetURLObject::NO_DECODE),STREAM_READWRITE | STREAM_SHARE_DENYWRITE | STREAM_TRUNC );
2000-11-16 09:47:23 +00:00
if (!m_pFileStream)
2000-09-29 14:30:09 +00:00
return sal_False;
2000-09-18 15:18:56 +00:00
char aBuffer[21]; // write buffer
memset(aBuffer,0,sizeof(aBuffer));
2000-11-16 09:47:23 +00:00
m_pFileStream->Seek(0L);
(*m_pFileStream) << (BYTE) dBaseIII; // dBase format
(*m_pFileStream) << (BYTE) (aDate.GetYear() % 100); // aktuelles Datum
2000-09-18 15:18:56 +00:00
2000-11-16 09:47:23 +00:00
(*m_pFileStream) << (BYTE) aDate.GetMonth();
(*m_pFileStream) << (BYTE) aDate.GetDay();
(*m_pFileStream) << 0L; // Anzahl der Datens<6E>tze
(*m_pFileStream) << (USHORT)((m_pColumns->getCount()+1) * 32 + 1); // Kopfinformationen,
2000-09-18 15:18:56 +00:00
// pColumns erh<72>lt immer eine Spalte mehr
2000-11-16 09:47:23 +00:00
(*m_pFileStream) << (USHORT) 0; // Satzl<7A>nge wird sp<73>ter bestimmt
m_pFileStream->Write(aBuffer, 20);
2000-09-18 15:18:56 +00:00
USHORT nRecLength = 1; // L<>nge 1 f<>r deleted flag
2001-03-01 09:51:00 +00:00
sal_Int32 nMaxFieldLength = m_pConnection->getMetaData()->getMaxColumnNameLength();
2000-09-18 15:18:56 +00:00
Reference<XIndexAccess> xColumns(getColumns(),UNO_QUERY);
::rtl::OUString aName;
2000-10-30 07:07:33 +00:00
Reference<XPropertySet> xCol;
2000-09-18 15:18:56 +00:00
for(sal_Int32 i=0;i<xColumns->getCount();++i)
{
2001-02-14 06:22:50 +00:00
::cppu::extractInterface(xCol,xColumns->getByIndex(i));
OSL_ENSURE(xCol.is(),"This should be a column!");
2000-09-18 15:18:56 +00:00
char cTyp;
2001-05-14 10:42:44 +00:00
xCol->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_NAME)) >>= aName;
2000-09-18 15:18:56 +00:00
if (aName.getLength() > nMaxFieldLength)
{
2001-02-22 12:53:00 +00:00
::rtl::OUString sMsg = ::rtl::OUString::createFromAscii("Invalid column name length for column: ");
sMsg += aName;
sMsg += ::rtl::OUString::createFromAscii("!");
2001-05-14 10:42:44 +00:00
throw SQLException(sMsg,*this,OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_HY0000),1000,Any());
2000-09-18 15:18:56 +00:00
}
ByteString aCol(aName.getStr(), getConnection()->getTextEncoding());
2000-11-16 09:47:23 +00:00
(*m_pFileStream) << aCol.GetBuffer();
m_pFileStream->Write(aBuffer, 11 - aCol.Len());
2000-09-18 15:18:56 +00:00
2001-05-14 10:42:44 +00:00
switch (getINT32(xCol->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_TYPE))))
2000-09-18 15:18:56 +00:00
{
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:
{
2001-02-22 12:53:00 +00:00
::rtl::OUString sMsg = ::rtl::OUString::createFromAscii("Invalid column type for column: ");
sMsg += aName;
sMsg += ::rtl::OUString::createFromAscii("!");
2001-05-14 10:42:44 +00:00
throw SQLException(sMsg,*this,OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_HY0000),1000,Any());
2000-09-18 15:18:56 +00:00
}
}
2000-11-16 09:47:23 +00:00
(*m_pFileStream) << cTyp;
m_pFileStream->Write(aBuffer, 4);
2000-09-18 15:18:56 +00:00
sal_Int32 nPrecision = 0;
2001-05-14 10:42:44 +00:00
xCol->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_PRECISION)) >>= nPrecision;
2000-09-18 15:18:56 +00:00
sal_Int32 nScale = 0;
2001-05-14 10:42:44 +00:00
xCol->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_SCALE)) >>= nScale;
2000-09-18 15:18:56 +00:00
switch(cTyp)
{
case 'C':
2001-02-14 06:22:50 +00:00
OSL_ENSURE(nPrecision < 255, "ODbaseTable::Create: Column zu lang!");
2000-09-18 15:18:56 +00:00
if (nPrecision > 254)
{
2001-02-22 12:53:00 +00:00
::rtl::OUString sMsg = ::rtl::OUString::createFromAscii("Invalid precision for column: ");
sMsg += aName;
sMsg += ::rtl::OUString::createFromAscii("!");
2001-05-14 10:42:44 +00:00
throw SQLException(sMsg,*this,OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_HY0000),1000,Any());
2000-09-18 15:18:56 +00:00
}
2000-11-16 11:35:13 +00:00
(*m_pFileStream) << (BYTE) Min((ULONG)nPrecision, 255UL); //Feldl<64>nge
2000-11-14 10:55:54 +00:00
nRecLength += (USHORT)Min((ULONG)nPrecision, 255UL);
2000-11-16 11:35:13 +00:00
(*m_pFileStream) << (BYTE)0; //Nachkommastellen
2000-09-18 15:18:56 +00:00
break;
case 'F':
case 'N':
2001-02-14 06:22:50 +00:00
OSL_ENSURE(nPrecision >= nScale,
2000-09-18 15:18:56 +00:00
"ODbaseTable::Create: Feldl<64>nge mu<6D> gr<67><72>er Nachkommastellen sein!");
if (nPrecision < nScale)
{
2001-02-22 12:53:00 +00:00
::rtl::OUString sMsg = ::rtl::OUString::createFromAscii("Precision is less than scale for column: ");
sMsg += aName;
sMsg += ::rtl::OUString::createFromAscii("!");
2001-05-14 10:42:44 +00:00
throw SQLException(sMsg,*this,OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_HY0000),1000,Any());
2000-09-18 15:18:56 +00:00
break;
}
2001-05-14 10:42:44 +00:00
if (getBOOL(xCol->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_ISCURRENCY)))) // Currency wird gesondert behandelt
2000-09-18 15:18:56 +00:00
{
2000-11-16 09:47:23 +00:00
(*m_pFileStream) << (BYTE)10; // Standard Laenge
(*m_pFileStream) << (BYTE)4;
2000-09-18 15:18:56 +00:00
nRecLength += 10;
}
else
{
2001-03-01 09:51:00 +00:00
sal_Int32 nPrec = SvDbaseConverter::ConvertPrecisionToDbase(nPrecision,nScale);
2000-09-18 15:18:56 +00:00
2000-11-16 09:47:23 +00:00
(*m_pFileStream) << (BYTE)( nPrec);
(*m_pFileStream) << (BYTE)nScale;
2000-09-18 15:18:56 +00:00
nRecLength += (USHORT)nPrec;
}
break;
case 'L':
2000-11-16 09:47:23 +00:00
(*m_pFileStream) << (BYTE)1;
(*m_pFileStream) << (BYTE)0;
2000-09-18 15:18:56 +00:00
nRecLength++;
break;
case 'D':
2000-11-16 09:47:23 +00:00
(*m_pFileStream) << (BYTE)8;
(*m_pFileStream) << (BYTE)0;
2000-09-18 15:18:56 +00:00
nRecLength += 8;
break;
case 'M':
bCreateMemo = TRUE;
2000-11-16 09:47:23 +00:00
(*m_pFileStream) << (BYTE)10;
(*m_pFileStream) << (BYTE)0;
2000-09-18 15:18:56 +00:00
nRecLength += 10;
break;
default:
2001-02-22 12:53:00 +00:00
{
::rtl::OUString sMsg = ::rtl::OUString::createFromAscii("Invalid column type for column: ");
sMsg += aName;
sMsg += ::rtl::OUString::createFromAscii("!");
2001-05-14 10:42:44 +00:00
throw SQLException(sMsg,*this,OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_HY0000),1000,Any());
2001-02-22 12:53:00 +00:00
}
2000-09-18 15:18:56 +00:00
}
2000-11-16 09:47:23 +00:00
m_pFileStream->Write(aBuffer, 14);
2000-09-18 15:18:56 +00:00
}
2000-11-16 09:47:23 +00:00
(*m_pFileStream) << (BYTE)0x0d; // kopf ende
m_pFileStream->Seek(10L);
(*m_pFileStream) << nRecLength; // satzl<7A>nge nachtr<74>glich eintragen
2000-09-18 15:18:56 +00:00
if (bCreateMemo)
{
2000-11-16 09:47:23 +00:00
m_pFileStream->Seek(0L);
(*m_pFileStream) << (BYTE) dBaseIIIMemo;
2000-09-18 15:18:56 +00:00
}
return TRUE;
}
//------------------------------------------------------------------
// erzeugt grunds<64>tzlich dBase III Datei Format
BOOL ODbaseTable::CreateMemoFile(const INetURLObject& aFile)
{
// Makro zum Filehandling f<>rs Erzeugen von Tabellen
m_pMemoStream = createStream_simpleError( aFile.GetMainURL(INetURLObject::NO_DECODE),STREAM_READWRITE | STREAM_SHARE_DENYWRITE);
2000-11-16 09:47:23 +00:00
if (!m_pMemoStream)
2000-09-29 14:30:09 +00:00
return sal_False;
2000-09-18 15:18:56 +00:00
char aBuffer[512]; // write buffer
memset(aBuffer,0,sizeof(aBuffer));
#ifdef WIN
2000-11-16 09:47:23 +00:00
m_pMemoStream->Seek(0L);
2000-09-18 15:18:56 +00:00
for (UINT16 i = 0; i < 512; i++)
{
2000-11-16 09:47:23 +00:00
(*m_pMemoStream) << BYTE(0);
2000-09-18 15:18:56 +00:00
}
#else
2000-11-16 09:47:23 +00:00
m_pMemoStream->SetFiller('\0');
m_pMemoStream->SetStreamSize(512);
2000-09-18 15:18:56 +00:00
#endif
2000-11-16 09:47:23 +00:00
m_pMemoStream->Seek(0L);
(*m_pMemoStream) << long(1); // Zeiger auf ersten freien Block
2000-09-18 15:18:56 +00:00
2000-11-16 09:47:23 +00:00
m_pMemoStream->Flush();
delete m_pMemoStream;
m_pMemoStream = NULL;
2000-09-18 15:18:56 +00:00
return TRUE;
}
//------------------------------------------------------------------
BOOL ODbaseTable::Drop_Static(const ::rtl::OUString& _sUrl,sal_Bool _bHasMemoFields,OCollection* _pIndexes )
2000-09-18 15:18:56 +00:00
{
INetURLObject aURL;
aURL.SetURL(_sUrl);
2000-09-18 15:18:56 +00:00
2001-06-29 07:29:14 +00:00
BOOL bDropped = FALSE;
2000-09-18 15:18:56 +00:00
2001-07-16 08:58:40 +00:00
if(bDropped = ::utl::UCBContentHelper::Kill(aURL.GetMainURL(INetURLObject::NO_DECODE)))
2000-09-18 15:18:56 +00:00
{
if (_bHasMemoFields)
2001-06-29 07:29:14 +00:00
{ // delete the memo fields
aURL.setExtension(String::CreateFromAscii("dbt"));
2001-07-16 08:58:40 +00:00
bDropped = ::utl::UCBContentHelper::Kill(aURL.GetMainURL(INetURLObject::NO_DECODE));
2001-06-29 07:29:14 +00:00
}
2000-09-18 15:18:56 +00:00
2001-06-29 07:29:14 +00:00
if(bDropped)
2001-03-28 10:32:43 +00:00
{
if(_pIndexes)
2001-06-29 07:29:14 +00:00
{
sal_Int32 nCount = _pIndexes->getCount(),
2001-06-29 07:29:14 +00:00
i = 0;
while (i < nCount)
{
_pIndexes->dropByIndex(i);
2001-06-29 07:29:14 +00:00
}
}
// aFile.SetBase(m_Name);
aURL.setExtension(String::CreateFromAscii("inf"));
// as the inf file does not necessarily exist, we aren't allowed to use UCBContentHelper::Kill
// 89711 - 16.07.2001 - frank.schoenheit@sun.com
try
{
::ucb::Content aDeleteContent( aURL.GetMainURL( INetURLObject::NO_DECODE ), Reference< ::com::sun::star::ucb::XCommandEnvironment > () );
aDeleteContent.executeCommand( ::rtl::OUString::createFromAscii( "delete" ), makeAny( sal_Bool( sal_True ) ) );
}
catch(Exception&)
{
// silently ignore this ....
}
2001-03-28 10:32:43 +00:00
}
2000-09-18 15:18:56 +00:00
}
return bDropped;
}
// -----------------------------------------------------------------------------
BOOL ODbaseTable::DropImpl()
{
FileClose();
refreshIndexes(); // look for indexes which must be deleted as well
BOOL bDropped = Drop_Static(getEntry(m_pConnection,m_Name),HasMemoFields(),m_pIndexes);
2001-06-29 07:29:14 +00:00
if(!bDropped)
{// we couldn't drop the table so we have to reopen it
construct();
if(m_pColumns)
m_pColumns->refresh();
}
return bDropped;
2000-09-18 15:18:56 +00:00
}
//------------------------------------------------------------------
2000-09-29 14:30:09 +00:00
BOOL ODbaseTable::InsertRow(OValueVector& rRow, BOOL bFlush,const Reference<XIndexAccess>& _xCols)
2000-09-18 15:18:56 +00:00
{
// Buffer mit Leerzeichen f<>llen
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;
2001-06-29 07:29:14 +00:00
BOOL bInsertRow;
2000-09-18 15:18:56 +00:00
m_nFilePos = (ULONG)m_aHeader.db_anz + 1;
2001-06-29 07:29:14 +00:00
if (bInsertRow = UpdateBuffer(rRow,NULL,_xCols))
2000-09-18 15:18:56 +00:00
{
2001-06-29 07:29:14 +00:00
m_pFileStream->Seek(STREAM_SEEK_TO_END);
nFileSize = m_pFileStream->Tell();
2000-09-18 15:18:56 +00:00
2001-06-29 07:29:14 +00:00
if (HasMemoFields() && m_pMemoStream)
{
m_pMemoStream->Seek(STREAM_SEEK_TO_END);
nMemoFileSize = m_pMemoStream->Tell();
}
2000-09-18 15:18:56 +00:00
2001-06-29 07:29:14 +00:00
if (!WriteBuffer())
{
m_pFileStream->SetStreamSize(nFileSize); // alte Gr<47><72>e restaurieren
2000-09-18 15:18:56 +00:00
2001-06-29 07:29:14 +00:00
if (HasMemoFields() && m_pMemoStream)
m_pMemoStream->SetStreamSize(nMemoFileSize); // alte Gr<47><72>e restaurieren
m_nFilePos = nTempPos; // Fileposition restaurieren
}
else
{
// Anzahl Datensaetze im Header erhoehen:
m_pFileStream->Seek( 4L );
(*m_pFileStream) << (m_aHeader.db_anz + 1);
// beim AppendOnly kein Flush!
if (bFlush)
m_pFileStream->Flush();
// bei Erfolg # erh<72>hen
m_aHeader.db_anz++;
rRow[0] = m_nFilePos; // BOOKmark setzen
m_nFilePos = nTempPos;
}
2000-09-18 15:18:56 +00:00
}
else
m_nFilePos = nTempPos;
2001-06-29 07:29:14 +00:00
return bInsertRow;;
2000-09-18 15:18:56 +00:00
}
//------------------------------------------------------------------
2001-03-28 10:32:43 +00:00
BOOL ODbaseTable::UpdateRow(OValueVector& rRow, OValueRow pOrgRow,const Reference<XIndexAccess>& _xCols)
2000-09-18 15:18:56 +00:00
{
// Buffer mit Leerzeichen f<>llen
AllocBuffer();
// Auf gewuenschten Record positionieren:
long nPos = m_aHeader.db_kopf + (long)(m_nFilePos-1) * m_aHeader.db_slng;
2000-11-16 09:47:23 +00:00
m_pFileStream->Seek(nPos);
m_pFileStream->Read((char*)m_pBuffer, m_aHeader.db_slng);
2000-09-18 15:18:56 +00:00
UINT32 nMemoFileSize;
2000-11-16 09:47:23 +00:00
if (HasMemoFields() && m_pMemoStream)
2000-09-18 15:18:56 +00:00
{
2000-11-16 09:47:23 +00:00
m_pMemoStream->Seek(STREAM_SEEK_TO_END);
nMemoFileSize = m_pMemoStream->Tell();
2000-09-18 15:18:56 +00:00
}
if (!UpdateBuffer(rRow, pOrgRow,_xCols) || !WriteBuffer())
{
2000-11-16 09:47:23 +00:00
if (HasMemoFields() && m_pMemoStream)
m_pMemoStream->SetStreamSize(nMemoFileSize); // alte Gr<47><72>e restaurieren
2000-09-18 15:18:56 +00:00
}
else
{
2000-11-16 09:47:23 +00:00
m_pFileStream->Flush();
2000-09-18 15:18:56 +00:00
}
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 nFilePos = m_aHeader.db_kopf + (long)(m_nFilePos-1) * m_aHeader.db_slng;
m_pFileStream->Seek(nFilePos);
2000-09-18 15:18:56 +00:00
OValueRow aRow = new OValueVector(_rCols.size());
2000-11-27 07:00:26 +00:00
if (!fetchRow(aRow,_rCols,TRUE,TRUE))
2000-09-29 14:30:09 +00:00
return sal_False;
2000-09-18 15:18:56 +00:00
2000-10-30 07:07:33 +00:00
Reference<XPropertySet> xCol;
2000-09-18 15:18:56 +00:00
::rtl::OUString aColName;
2000-10-11 09:48:50 +00:00
::comphelper::UStringMixEqual aCase(isCaseSensitive());
2000-09-18 15:18:56 +00:00
for (USHORT i = 0; i < m_pColumns->getCount(); i++)
{
Reference<XPropertySet> xIndex = isUniqueByColumnName(i);
if (xIndex.is())
2000-09-18 15:18:56 +00:00
{
::cppu::extractInterface(xCol,m_pColumns->getByIndex(i));
OSL_ENSURE(xCol.is(),"ODbaseTable::DeleteRow column is null!");
if(xCol.is())
2000-09-18 15:18:56 +00:00
{
xCol->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_NAME)) >>= aColName;
2001-06-29 07:29:14 +00:00
Reference<XUnoTunnel> xTunnel(xIndex,UNO_QUERY);
OSL_ENSURE(xTunnel.is(),"No TunnelImplementation!");
ODbaseIndex* pIndex = (ODbaseIndex*)xTunnel->getSomething(ODbaseIndex::getUnoTunnelImplementationId());
OSL_ENSURE(pIndex,"ODbaseTable::DeleteRow: No Index returned!");
OSQLColumns::const_iterator aIter = _rCols.begin();
sal_Int32 nPos = 1;
2001-06-29 07:29:14 +00:00
for(;aIter != _rCols.end();++aIter,++nPos)
{
if(aCase(getString((*aIter)->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_REALNAME))),aColName))
break;
}
if (aIter == _rCols.end())
continue;
2000-09-18 15:18:56 +00:00
2001-06-29 07:29:14 +00:00
pIndex->Delete(m_nFilePos,(*aRow)[nPos]);
}
2000-09-18 15:18:56 +00:00
}
}
m_pFileStream->Seek(nFilePos);
2001-06-29 07:29:14 +00:00
(*m_pFileStream) << (BYTE)'*'; // mark the row in the table as deleted
2000-11-16 09:47:23 +00:00
m_pFileStream->Flush();
return sal_True;
2000-09-18 15:18:56 +00:00
}
// -------------------------------------------------------------------------
Reference<XPropertySet> ODbaseTable::isUniqueByColumnName(sal_Int32 _nColumnPos)
2000-09-18 15:18:56 +00:00
{
if(!m_pIndexes)
refreshIndexes();
if(m_pIndexes->hasElements())
2000-09-18 15:18:56 +00:00
{
Reference<XPropertySet> xCol;
m_pColumns->getByIndex(_nColumnPos) >>= xCol;
OSL_ENSURE(xCol.is(),"ODbaseTable::UpdateBuffer column is null!");
::rtl::OUString sColName;
xCol->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_NAME)) >>= sColName;
Reference<XPropertySet> xIndex;
for(sal_Int32 i=0;i<m_pIndexes->getCount();++i)
2000-09-18 15:18:56 +00:00
{
::cppu::extractInterface(xIndex,m_pIndexes->getByIndex(i));
if(xIndex.is() && getBOOL(xIndex->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_ISUNIQUE))))
{
Reference<XNameAccess> xCols(Reference<XColumnsSupplier>(xIndex,UNO_QUERY)->getColumns());
if(xCols->hasByName(sColName))
return xIndex;
2000-09-18 15:18:56 +00:00
}
2000-09-18 15:18:56 +00:00
}
}
2000-10-30 07:07:33 +00:00
return Reference<XPropertySet>();
2000-09-18 15:18:56 +00:00
}
//------------------------------------------------------------------
double toDouble(const ByteString& rString)
{
2001-07-30 07:53:02 +00:00
int nErrno;
return SolarMath::StringToDouble(UniString(rString,gsl_getSystemTextEncoding()).GetBuffer(),',','.',nErrno);
2000-09-18 15:18:56 +00:00
}
//------------------------------------------------------------------
BOOL ODbaseTable::UpdateBuffer(OValueVector& rRow, OValueRow pOrgRow,const Reference<XIndexAccess>& _xCols)
{
2001-03-01 09:51:00 +00:00
sal_Int32 nByteOffset = 1;
2000-09-18 15:18:56 +00:00
// Felder aktualisieren:
2000-10-30 07:07:33 +00:00
Reference<XPropertySet> xCol;
Reference<XPropertySet> xIndex;
2000-09-18 15:18:56 +00:00
USHORT i;
::rtl::OUString aColName;
sal_Int32 nColumnCount = m_pColumns->getCount();
::std::vector< Reference<XPropertySet> > aIndexedCols(nColumnCount);
2000-09-18 15:18:56 +00:00
2000-10-11 09:48:50 +00:00
::comphelper::UStringMixEqual aCase(isCaseSensitive());
2000-09-18 15:18:56 +00:00
Reference<XIndexAccess> xColumns = m_pColumns;
2000-09-18 15:18:56 +00:00
// first search a key that exist already in the table
for (i = 0; i < nColumnCount; ++i)
2000-09-18 15:18:56 +00:00
{
sal_Int32 nPos = i;
if(_xCols != xColumns)
2000-09-18 15:18:56 +00:00
{
m_pColumns->getByIndex(i) >>= xCol;
OSL_ENSURE(xCol.is(),"ODbaseTable::UpdateBuffer column is null!");
xCol->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_NAME)) >>= aColName;
for(nPos = 0;nPos<_xCols->getCount();++nPos)
{
Reference<XPropertySet> xFindCol;
::cppu::extractInterface(xFindCol,_xCols->getByIndex(nPos));
OSL_ENSURE(xFindCol.is(),"ODbaseTable::UpdateBuffer column is null!");
if(aCase(getString(xFindCol->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_NAME))),aColName))
break;
}
if (nPos >= _xCols->getCount())
continue;
2000-09-18 15:18:56 +00:00
}
++nPos;
xIndex = isUniqueByColumnName(i);
2000-09-18 15:18:56 +00:00
aIndexedCols[i] = xIndex;
if (xIndex.is())
{
2000-09-29 14:30:09 +00:00
// first check if the value is different to the old one and when if it conform to the index
2000-09-18 15:18:56 +00:00
if(pOrgRow.isValid() && (rRow[nPos].isNull() || rRow[nPos] == (*pOrgRow)[nPos]))
continue;
else
{
// ODbVariantRef xVar = (pVal == NULL) ? new ODbVariant() : pVal;
Reference<XUnoTunnel> xTunnel(xIndex,UNO_QUERY);
2001-02-14 06:22:50 +00:00
OSL_ENSURE(xTunnel.is(),"No TunnelImplementation!");
2000-09-18 15:18:56 +00:00
ODbaseIndex* pIndex = (ODbaseIndex*)xTunnel->getSomething(ODbaseIndex::getUnoTunnelImplementationId());
2001-02-14 06:22:50 +00:00
OSL_ENSURE(pIndex,"ODbaseTable::UpdateBuffer: No Index returned!");
2000-09-18 15:18:56 +00:00
if (pIndex->Find(0,rRow[nPos]))
{
// es existiert kein eindeutiger Wert
::rtl::OUString sMessage = ::rtl::OUString::createFromAscii("Duplicate value found in column \"");
sMessage += aColName;
sMessage += ::rtl::OUString::createFromAscii( "\"!");
throw SQLException(sMessage,*this,OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_HY0000),1000,Any());
2000-09-18 15:18:56 +00:00
}
}
}
}
// when we are here there is no double key in the table
for (i = 0; i < nColumnCount; ++i)
2000-09-18 15:18:56 +00:00
{
// Laengen je nach Datentyp:
sal_Int32 nLen = m_aPrecisions[i];
sal_Int32 nType = m_aTypes[i];
2001-07-30 07:53:02 +00:00
2000-09-18 15:18:56 +00:00
switch (nType)
{
case DataType::DATE: nLen = 8; break;
case DataType::DECIMAL:
2001-07-30 07:53:02 +00:00
nLen = SvDbaseConverter::ConvertPrecisionToDbase(nLen,m_aScales[i]);
2000-09-18 15:18:56 +00:00
break; // das Vorzeichen und das Komma
2001-06-29 07:29:14 +00:00
case DataType::BIT: nLen = 1; break;
case DataType::LONGVARCHAR: nLen = 10; break;
2000-09-18 15:18:56 +00:00
default: break;
}
sal_Int32 nPos = i;
if(_xCols != xColumns)
2000-09-18 15:18:56 +00:00
{
m_pColumns->getByIndex(i) >>= xCol;
OSL_ENSURE(xCol.is(),"ODbaseTable::UpdateBuffer column is null!");
xCol->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_NAME)) >>= aColName;
for(nPos = 0;nPos<_xCols->getCount();++nPos)
{
Reference<XPropertySet> xFindCol;
::cppu::extractInterface(xFindCol,_xCols->getByIndex(nPos));
if(aCase(getString(xFindCol->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_NAME))),aColName))
break;
}
if (nPos >= _xCols->getCount())
{
nByteOffset += nLen;
continue;
}
2000-09-18 15:18:56 +00:00
}
2000-09-18 15:18:56 +00:00
++nPos; // the row values start at 1
2001-05-11 05:14:11 +00:00
// Ist die Variable ueberhaupt gebunden?
if (!rRow[nPos].isBound() )
{
// Nein - naechstes Feld.
nByteOffset += nLen;
continue;
}
2000-09-18 15:18:56 +00:00
if (aIndexedCols[i].is())
{
Reference<XUnoTunnel> xTunnel(aIndexedCols[i],UNO_QUERY);
2001-02-14 06:22:50 +00:00
OSL_ENSURE(xTunnel.is(),"No TunnelImplementation!");
2000-09-18 15:18:56 +00:00
ODbaseIndex* pIndex = (ODbaseIndex*)xTunnel->getSomething(ODbaseIndex::getUnoTunnelImplementationId());
2001-02-14 06:22:50 +00:00
OSL_ENSURE(pIndex,"ODbaseTable::UpdateBuffer: No Index returned!");
2000-09-18 15:18:56 +00:00
// Update !!
if (pOrgRow.isValid() && !rRow[nPos].isNull() )//&& pVal->isModified())
pIndex->Update(m_nFilePos,(*pOrgRow)[nPos],rRow[nPos]);
else
pIndex->Insert(m_nFilePos,rRow[nPos]);
}
2001-05-11 05:14:11 +00:00
2000-09-18 15:18:56 +00:00
char* pData = (char *)(m_pBuffer + nByteOffset);
if (rRow[nPos].isNull())
{
memset(pData,' ',nLen); // Zuruecksetzen auf NULL
nByteOffset += nLen;
continue;
}
sal_Bool bHadError = sal_False;
Any aSQLError;
2000-09-18 15:18:56 +00:00
try
{
switch (nType)
{
case DataType::DATE:
{
2000-12-06 11:07:47 +00:00
::com::sun::star::util::Date aDate;
if(rRow[nPos].getTypeKind() == DataType::DOUBLE)
aDate = ::dbtools::DBTypeConversion::toDate(rRow[nPos].getDouble());
else
aDate = rRow[nPos];
2000-09-18 15:18:56 +00:00
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];
m_pColumns->getByIndex(i) >>= xCol;
OSL_ENSURE(xCol.is(),"ODbaseTable::UpdateBuffer column is null!");
xCol->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_NAME)) >>= aColName;
2001-07-30 07:53:02 +00:00
int nPrecision = (int)m_aPrecisions[i];
2001-05-14 10:42:44 +00:00
int nScale = (int)getINT32(xCol->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_SCALE)));
2000-09-18 15:18:56 +00:00
// 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, getConnection()->getTextEncoding());
2000-09-29 14:30:09 +00:00
BOOL bValidLength = sal_False;
2000-09-18 15:18:56 +00:00
if (aDefaultValue.Len() <= nLen)
{
strncpy(pData,aDefaultValue.GetBuffer(),nLen);
// write the resulting double back
rRow[nPos] = toDouble(aDefaultValue);
bValidLength = TRUE;
}
if (!bValidLength)
{
String sError;
sError.AppendAscii("The ");
sError += aColName.getStr();
sError.AppendAscii(" column has been defined as a \"Decimal\" type, the max. length is ");
sError += String::CreateFromInt32(nPrecision);
sError.AppendAscii(" characters (with ");
sError += String::CreateFromInt32(nScale);
sError.AppendAscii(" decimal places).\n\nThe specified value is longer than the number of digits allowed.");
throwGenericSQLException(sError, static_cast<XNamed*>(this));
2000-09-18 15:18:56 +00:00
}
} 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;
2000-11-16 09:47:23 +00:00
if (!m_pMemoStream || !WriteMemo(rRow[nPos], nBlockNo))
2000-09-18 15:18:56 +00:00
break;
ByteString aStr;
ByteString aBlock(ByteString::CreateFromInt32(nBlockNo));
aStr.Expand(nLen - aBlock.Len(), '0');
aStr += aBlock;
2000-09-29 14:30:09 +00:00
aStr.Convert(gsl_getSystemTextEncoding(),getConnection()->getTextEncoding());
2000-09-18 15:18:56 +00:00
// Zeichen kopieren:
memset(pData,' ',nLen); // Zuruecksetzen auf NULL
memcpy(pData, aStr.GetBuffer(), nLen);
} break;
default:
{
memset(pData,' ',nLen); // Zuruecksetzen auf NULL
2000-09-29 14:30:09 +00:00
ByteString aStr(rRow[nPos].getString().getStr(),getConnection()->getTextEncoding());
2000-09-18 15:18:56 +00:00
// Zeichen kopieren:
memcpy(pData, aStr.GetBuffer(), std::min(nLen,(sal_Int32)aStr.Len()));
2000-09-18 15:18:56 +00:00
} break;
}
}
catch( SQLException& e ) { aSQLError <<= e; bHadError = sal_True; }
catch ( Exception& ) { bHadError = sal_True; }
if ( bHadError )
2000-09-18 15:18:56 +00:00
{
m_pColumns->getByIndex(i) >>= xCol;
OSL_ENSURE(xCol.is(),"ODbaseTable::UpdateBuffer column is null!");
xCol->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_NAME)) >>= aColName;
2001-02-22 12:53:00 +00:00
::rtl::OUString sMsg = ::rtl::OUString::createFromAscii("Invalid value for column: ");
sMsg += aColName;
sMsg += ::rtl::OUString::createFromAscii("!");
throw SQLException(
sMsg,
*this,
OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_HY0000),
1000,
aSQLError
);
2000-09-18 15:18:56 +00:00
}
// Und weiter ...
nByteOffset += nLen;
}
return sal_True;
}
2000-10-30 07:07:33 +00:00
// -----------------------------------------------------------------------------
2001-03-28 10:32:43 +00:00
// XAlterTable
void SAL_CALL ODbaseTable::alterColumnByName( const ::rtl::OUString& colName, const Reference< XPropertySet >& descriptor ) throw(SQLException, NoSuchElementException, RuntimeException)
{
::osl::MutexGuard aGuard(m_aMutex);
2001-05-17 05:46:55 +00:00
checkDisposed(OTableDescriptor_BASE::rBHelper.bDisposed);
2001-03-28 10:32:43 +00:00
Reference<XDataDescriptorFactory> xOldColumn;
m_pColumns->getByName(colName) >>= xOldColumn;
2001-05-30 09:44:16 +00:00
alterColumn(m_pColumns->findColumn(colName)-1,descriptor,xOldColumn);
2001-03-28 10:32:43 +00:00
}
// -------------------------------------------------------------------------
void SAL_CALL ODbaseTable::alterColumnByIndex( sal_Int32 index, const Reference< XPropertySet >& descriptor ) throw(SQLException, ::com::sun::star::lang::IndexOutOfBoundsException, RuntimeException)
{
::osl::MutexGuard aGuard(m_aMutex);
2001-05-17 05:46:55 +00:00
checkDisposed(OTableDescriptor_BASE::rBHelper.bDisposed);
2001-03-28 10:32:43 +00:00
if(index < 0 || index >= m_pColumns->getCount())
2001-03-30 11:07:07 +00:00
throw IndexOutOfBoundsException(::rtl::OUString::valueOf(index),*this);
2001-03-28 10:32:43 +00:00
Reference<XDataDescriptorFactory> xOldColumn;
m_pColumns->getByIndex(index) >>= xOldColumn;
alterColumn(index,descriptor,xOldColumn);
}
// -----------------------------------------------------------------------------
void ODbaseTable::alterColumn(sal_Int32 index,
const Reference< XPropertySet >& descriptor ,
const Reference< XDataDescriptorFactory >& xOldColumn )
{
if(index < 0 || index >= m_pColumns->getCount())
2001-03-30 11:07:07 +00:00
throw IndexOutOfBoundsException(::rtl::OUString::valueOf(index),*this);
2001-03-28 10:32:43 +00:00
2001-06-29 07:29:14 +00:00
ODbaseTable* pNewTable = NULL;
try
{
OSL_ENSURE(descriptor.is(),"ODbaseTable::alterColumn: descriptor can not be null!");
// creates a copy of the the original column and copy all properties from descriptor in xCopyColumn
Reference<XPropertySet> xCopyColumn;
if(xOldColumn.is())
xCopyColumn = xOldColumn->createDataDescriptor();
else
xCopyColumn = new OColumn(getConnection()->getMetaData()->storesMixedCaseQuotedIdentifiers());
2001-03-28 10:32:43 +00:00
2001-06-29 07:29:14 +00:00
::comphelper::copyProperties(descriptor,xCopyColumn);
2001-03-28 10:32:43 +00:00
2001-06-29 07:29:14 +00:00
// creates a temp file
2001-03-28 10:32:43 +00:00
2001-06-29 07:29:14 +00:00
String sTempName = createTempFile();
pNewTable = new ODbaseTable(m_pTables,static_cast<ODbaseConnection*>(m_pConnection));
2001-06-29 07:29:14 +00:00
Reference<XPropertySet> xHoldTable = pNewTable;
pNewTable->setPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_NAME),makeAny(::rtl::OUString(sTempName)));
Reference<XAppend> xAppend(pNewTable->getColumns(),UNO_QUERY);
OSL_ENSURE(xAppend.is(),"ODbaseTable::alterColumn: No XAppend interface!");
// copy the structure
sal_Int32 i=0;
for(;i < index;++i)
2001-05-28 12:03:37 +00:00
{
2001-06-29 07:29:14 +00:00
Reference<XPropertySet> xProp;
m_pColumns->getByIndex(i) >>= xProp;
Reference<XDataDescriptorFactory> xColumn(xProp,UNO_QUERY);
Reference<XPropertySet> xCpy;
if(xColumn.is())
xCpy = xColumn->createDataDescriptor();
else
{
xCpy = new OColumn(getConnection()->getMetaData()->storesMixedCaseQuotedIdentifiers());
::comphelper::copyProperties(xProp,xCpy);
}
xAppend->appendByDescriptor(xCpy);
2001-05-28 12:03:37 +00:00
}
2001-06-29 07:29:14 +00:00
++i; // now insert our new column
xAppend->appendByDescriptor(xCopyColumn);
2001-03-28 10:32:43 +00:00
2001-06-29 07:29:14 +00:00
for(;i < m_pColumns->getCount();++i)
2001-05-28 12:03:37 +00:00
{
2001-06-29 07:29:14 +00:00
Reference<XPropertySet> xProp;
m_pColumns->getByIndex(i) >>= xProp;
Reference<XDataDescriptorFactory> xColumn(xProp,UNO_QUERY);
Reference<XPropertySet> xCpy;
if(xColumn.is())
xCpy = xColumn->createDataDescriptor();
else
{
xCpy = new OColumn(getConnection()->getMetaData()->storesMixedCaseQuotedIdentifiers());
::comphelper::copyProperties(xProp,xCpy);
}
xAppend->appendByDescriptor(xCpy);
2001-05-28 12:03:37 +00:00
}
2001-03-28 10:32:43 +00:00
2001-06-29 07:29:14 +00:00
// construct the new table
if(!pNewTable->CreateImpl())
{
delete pNewTable;
return;
}
pNewTable->construct();
2001-03-28 10:32:43 +00:00
2001-06-29 07:29:14 +00:00
// copy the data
copyData(pNewTable,0);
2001-03-28 10:32:43 +00:00
2001-06-29 07:29:14 +00:00
// now drop the old one
if(DropImpl())
{
// rename the new one to the old one
2001-10-12 11:02:56 +00:00
pNewTable->renameImpl(m_Name);
2001-06-29 07:29:14 +00:00
// release the temp file
pNewTable = NULL;
::comphelper::disposeComponent(xHoldTable);
}
else
2001-10-12 11:02:56 +00:00
{
2001-06-29 07:29:14 +00:00
delete pNewTable;
2001-10-12 11:02:56 +00:00
pNewTable = NULL;
}
2001-06-29 07:29:14 +00:00
FileClose();
construct();
if(m_pColumns)
m_pColumns->refresh();
2001-03-28 10:32:43 +00:00
2001-06-29 07:29:14 +00:00
}
catch(const SQLException&)
{
delete pNewTable;
throw;
}
catch(const Exception&)
{
OSL_ENSURE(0,"ODbaseTable::alterColumn: Exception occured!");
delete pNewTable;
throw;
}
2001-03-28 10:32:43 +00:00
}
// -------------------------------------------------------------------------
void SAL_CALL ODbaseTable::rename( const ::rtl::OUString& newName ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::container::ElementExistException, ::com::sun::star::uno::RuntimeException)
{
::osl::MutexGuard aGuard(m_aMutex);
2001-05-17 05:46:55 +00:00
checkDisposed(OTableDescriptor_BASE::rBHelper.bDisposed);
if(m_pTables && m_pTables->hasByName(newName))
throw ElementExistException(newName,*this);
2001-05-17 05:46:55 +00:00
2001-03-28 10:32:43 +00:00
2001-10-12 11:02:56 +00:00
renameImpl(newName);
}
// -------------------------------------------------------------------------
void SAL_CALL ODbaseTable::renameImpl( const ::rtl::OUString& newName ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::container::ElementExistException, ::com::sun::star::uno::RuntimeException)
{
::osl::MutexGuard aGuard(m_aMutex);
2001-03-28 10:32:43 +00:00
FileClose();
String aName = getEntry(m_pConnection,m_Name);
2001-03-28 10:32:43 +00:00
if(!aName.Len())
{
::rtl::OUString aIdent = m_pConnection->getContent()->getIdentifier()->getContentIdentifier();
aIdent += ::rtl::OUString::createFromAscii("/");
aIdent += m_Name;
aName = aIdent;
}
INetURLObject aURL;
aURL.SetURL(aName);
if(aURL.getExtension() != m_pConnection->getExtension())
aURL.setExtension(m_pConnection->getExtension());
String sNewName(newName);
sNewName.AppendAscii(".");
sNewName += m_pConnection->getExtension();
try
{
2001-07-16 08:58:40 +00:00
String sOldName = aURL.GetMainURL(INetURLObject::NO_DECODE);
2001-05-28 12:03:37 +00:00
// ::utl::UCBContentHelper::MoveTo(sOldName,sNewName);
2001-07-16 08:58:40 +00:00
Content aContent(aURL.GetMainURL(INetURLObject::NO_DECODE),Reference<XCommandEnvironment>());
Sequence< PropertyValue > aProps( 1 );
aProps[0].Name = ::rtl::OUString::createFromAscii("Title");
aProps[0].Handle = -1; // n/a
aProps[0].Value = makeAny( ::rtl::OUString(sNewName) );
Sequence< Any > aValues;
aContent.executeCommand( rtl::OUString::createFromAscii( "setPropertyValues" ),makeAny(aProps) ) >>= aValues;
if(aValues.getLength() && aValues[0].hasValue())
throw Exception();
// aContent.setPropertyValue( rtl::OUString::createFromAscii( "Title" ),makeAny( ::rtl::OUString(sNewName) ) );
2001-03-28 10:32:43 +00:00
}
catch(Exception&)
{
throw ElementExistException(newName,*this);
2001-03-28 10:32:43 +00:00
}
ODbaseTable_BASE::rename(newName);
2001-03-28 10:32:43 +00:00
construct();
2001-05-30 09:44:16 +00:00
if(m_pColumns)
m_pColumns->refresh();
2001-03-28 10:32:43 +00:00
}
// -----------------------------------------------------------------------------
void ODbaseTable::addColumn(const Reference< XPropertySet >& _xNewColumn)
{
String sTempName = createTempFile();
ODbaseTable* pNewTable = new ODbaseTable(m_pTables,static_cast<ODbaseConnection*>(m_pConnection));
2001-05-28 12:03:37 +00:00
pNewTable->acquire();
2001-05-14 10:42:44 +00:00
pNewTable->setPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_NAME),makeAny(::rtl::OUString(sTempName)));
2001-03-28 10:32:43 +00:00
{
Reference<XAppend> xAppend(pNewTable->getColumns(),UNO_QUERY);
2001-05-30 09:44:16 +00:00
sal_Bool bCase = getConnection()->getMetaData()->storesMixedCaseQuotedIdentifiers();
2001-03-28 10:32:43 +00:00
// copy the structure
for(sal_Int32 i=0;i < m_pColumns->getCount();++i)
{
2001-05-28 12:03:37 +00:00
Reference<XPropertySet> xProp;
m_pColumns->getByIndex(i) >>= xProp;
Reference<XDataDescriptorFactory> xColumn(xProp,UNO_QUERY);
Reference<XPropertySet> xCpy;
if(xColumn.is())
xCpy = xColumn->createDataDescriptor();
else
{
2001-05-30 09:44:16 +00:00
xCpy = new OColumn(bCase);
2001-05-28 12:03:37 +00:00
::comphelper::copyProperties(xProp,xCpy);
}
2001-03-28 10:32:43 +00:00
xAppend->appendByDescriptor(xCpy);
}
2001-05-30 09:44:16 +00:00
Reference<XPropertySet> xCpy = new OColumn(bCase);
::comphelper::copyProperties(_xNewColumn,xCpy);
xAppend->appendByDescriptor(xCpy);
2001-03-28 10:32:43 +00:00
}
// construct the new table
if(!pNewTable->CreateImpl())
{
2001-06-29 07:29:14 +00:00
delete pNewTable;
throw SQLException();
2001-03-28 10:32:43 +00:00
}
2001-06-29 07:29:14 +00:00
BOOL bAlreadyDroped = FALSE;
try
{
pNewTable->construct();
// copy the data
copyData(pNewTable,pNewTable->m_pColumns->getCount());
// drop the old table
if(DropImpl())
{
bAlreadyDroped = TRUE;
2001-10-12 11:02:56 +00:00
pNewTable->renameImpl(m_Name);
2001-06-29 07:29:14 +00:00
// release the temp file
pNewTable->release();
}
else
delete pNewTable;
2001-05-28 12:03:37 +00:00
2001-06-29 07:29:14 +00:00
FileClose();
construct();
if(m_pColumns)
m_pColumns->refresh();
}
catch(const SQLException&)
{
// here we know that the old table wasn't droped before
if(!bAlreadyDroped)
delete pNewTable;
2001-05-28 12:03:37 +00:00
2001-06-29 07:29:14 +00:00
throw;
}
2001-05-30 09:44:16 +00:00
}
// -----------------------------------------------------------------------------
void ODbaseTable::dropColumn(sal_Int32 _nPos)
{
String sTempName = createTempFile();
ODbaseTable* pNewTable = new ODbaseTable(m_pTables,static_cast<ODbaseConnection*>(m_pConnection));
2001-05-30 09:44:16 +00:00
pNewTable->acquire();
pNewTable->setPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_NAME),makeAny(::rtl::OUString(sTempName)));
{
Reference<XAppend> xAppend(pNewTable->getColumns(),UNO_QUERY);
sal_Bool bCase = getConnection()->getMetaData()->storesMixedCaseQuotedIdentifiers();
// copy the structure
for(sal_Int32 i=0;i < m_pColumns->getCount();++i)
{
if(_nPos != i)
{
Reference<XPropertySet> xProp;
m_pColumns->getByIndex(i) >>= xProp;
Reference<XDataDescriptorFactory> xColumn(xProp,UNO_QUERY);
Reference<XPropertySet> xCpy;
if(xColumn.is())
xCpy = xColumn->createDataDescriptor();
else
{
xCpy = new OColumn(bCase);
::comphelper::copyProperties(xProp,xCpy);
}
xAppend->appendByDescriptor(xCpy);
}
}
}
// construct the new table
if(!pNewTable->CreateImpl())
{
2001-06-29 07:29:14 +00:00
delete pNewTable;
throw SQLException();
2001-05-30 09:44:16 +00:00
}
pNewTable->construct();
2001-05-30 09:44:16 +00:00
// copy the data
2001-06-29 07:29:14 +00:00
copyData(pNewTable,_nPos);
2001-05-30 09:44:16 +00:00
// drop the old table
2001-06-29 07:29:14 +00:00
if(DropImpl())
{
2001-10-12 11:02:56 +00:00
pNewTable->renameImpl(m_Name);
2001-06-29 07:29:14 +00:00
// release the temp file
pNewTable->release();
}
else
delete pNewTable;
2001-05-30 09:44:16 +00:00
FileClose();
construct();
if(m_pColumns)
m_pColumns->refresh();
2001-03-28 10:32:43 +00:00
}
// -----------------------------------------------------------------------------
String ODbaseTable::createTempFile()
{
::rtl::OUString aIdent = m_pConnection->getContent()->getIdentifier()->getContentIdentifier();
aIdent += ::rtl::OUString::createFromAscii("/");
String sTempName(aIdent);
String sExt;
sExt.AssignAscii(".");
sExt += m_pConnection->getExtension();
2001-03-30 09:16:42 +00:00
String sName(m_Name);
TempFile aTempFile(sName,&sExt,&sTempName);
2001-03-28 10:32:43 +00:00
if(!aTempFile.IsValid())
2001-05-14 10:42:44 +00:00
throw SQLException(::rtl::OUString::createFromAscii("Error while alter table!"),NULL,OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_HY0000),1000,Any());
2001-03-28 10:32:43 +00:00
INetURLObject aURL;
aURL.SetSmartProtocol(INET_PROT_FILE);
aURL.SetURL(aTempFile.GetURL());
2001-05-30 09:44:16 +00:00
2001-03-28 10:32:43 +00:00
String sNewName(aURL.getName());
sNewName.Erase(sNewName.Len() - sExt.Len());
return sNewName;
}
// -----------------------------------------------------------------------------
2001-06-29 07:29:14 +00:00
void ODbaseTable::copyData(ODbaseTable* _pNewTable,sal_Int32 _nPos)
2001-03-28 10:32:43 +00:00
{
2001-06-29 07:29:14 +00:00
sal_Int32 nPos = _nPos + 1; // +1 because we always have the bookmark clumn as well
2001-03-28 10:32:43 +00:00
OValueRow aRow = new OValueVector(m_pColumns->getCount());
2001-06-29 07:29:14 +00:00
OValueRow aInsertRow;
if(nPos)
{
aInsertRow = new OValueVector(_pNewTable->m_pColumns->getCount());
::std::for_each(aInsertRow->begin(),aInsertRow->end(),TSetBound(sal_True));
2001-06-29 07:29:14 +00:00
}
else
aInsertRow = aRow;
// we only have to bind the values which we need to copy into the new table
::std::for_each(aRow->begin(),aRow->end(),TSetBound(sal_True));
if(nPos && (nPos < (sal_Int32)aRow->size()))
2001-06-29 07:29:14 +00:00
(*aRow)[nPos].setBound(sal_False);
2001-03-28 10:32:43 +00:00
sal_Bool bOk = sal_True;
sal_Int32 nCurPos;
OValueVector::iterator aIter;
2001-03-28 10:32:43 +00:00
for(sal_uInt32 nRowPos = 0; nRowPos < m_aHeader.db_anz;++nRowPos)
{
if(bOk = seekRow(FILE_BOOKMARK,nRowPos+1,nCurPos))
2001-03-28 10:32:43 +00:00
{
if(bOk = fetchRow(aRow,m_aColumns.getBody(),sal_True,sal_True))
{
2001-06-29 07:29:14 +00:00
// special handling when pos == 0 then we don't have to distinguish between the two rows
if(nPos)
{
aIter = aRow->begin()+1;
sal_Int32 nCount = 1;
for(OValueVector::iterator aInsertIter = aInsertRow->begin()+1; aIter != aRow->end() && aInsertIter != aInsertRow->end();++aIter,++nCount)
{
if(nPos != nCount)
{
*aInsertIter = *aIter;
++aInsertIter;
}
}
}
bOk = _pNewTable->InsertRow(*aInsertRow,sal_True,_pNewTable->m_pColumns);
2001-03-28 10:32:43 +00:00
OSL_ENSURE(bOk,"Row could not be inserted!");
}
else
OSL_ENSURE(bOk,"Row could not be fetched!");
}
else
{
OSL_ASSERT(0);
}
}
}
// -----------------------------------------------------------------------------
2001-08-02 06:59:15 +00:00
void ODbaseTable::throwInvalidDbaseFormat()
{
FileClose();
2001-08-02 06:59:15 +00:00
// no dbase file
::rtl::OUString sMessage = ::rtl::OUString::createFromAscii("[StarOffice Base dbase] The file '");
sMessage += getEntry(m_pConnection,m_Name);
2001-08-02 06:59:15 +00:00
sMessage += ::rtl::OUString::createFromAscii(" is an invalid (or unrecognized) dBase file.");
throwGenericSQLException(sMessage, static_cast<XNamed*>(this));
}
// -----------------------------------------------------------------------------
void ODbaseTable::refreshHeader()
{
readHeader();
}
// -----------------------------------------------------------------------------