/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
void ODbaseTable::readHeader()
{
OSL_ENSURE(m_pFileStream,"No Stream available!"); if(!m_pFileStream) return;
m_pFileStream->RefreshBuffer(); // Make sure, that the header information actually is read again
m_pFileStream->Seek(STREAM_SEEK_TO_BEGIN);
if ( ( ( m_aHeader.headerLength - 1 ) / 32 - 1 ) <= 0 ) // number of fields
{ // no dBASE file
throwInvalidDbaseFormat();
} else
{ // Consistency check of the header:
m_aHeader.type = static_cast<DBFType>(nType); switch (m_aHeader.type)
{ case dBaseIII: case dBaseIV: case dBaseV: case VisualFoxPro: case VisualFoxProAuto: case dBaseFS: case dBaseFSMemo: case dBaseIVMemoSQL: case dBaseIIIMemo: case FoxProMemo:
m_pFileStream->SetEndian(SvStreamEndian::LITTLE); if( getConnection()->isTextEncodingDefaulted() &&
!dbfDecodeCharset(m_eEncoding, nType, m_aHeader.trailer[17]))
{
m_eEncoding = RTL_TEXTENCODING_IBM_850;
} break; case dBaseIVMemo:
m_pFileStream->SetEndian(SvStreamEndian::LITTLE); break; default:
{
throwInvalidDbaseFormat();
}
}
}
}
void ODbaseTable::fillColumns()
{
m_pFileStream->Seek(STREAM_SEEK_TO_BEGIN); if (!checkSeek(*m_pFileStream, 32))
{
SAL_WARN("connectivity.drivers", "ODbaseTable::fillColumns: bad offset!"); return;
}
if(!m_aColumns.is())
m_aColumns = new OSQLColumns(); else
m_aColumns->clear();
sal_Int32 i = 0; for (; i < nFieldCount; i++)
{
DBFColumn aDBFColumn;
m_pFileStream->ReadBytes(aDBFColumn.db_fnm, 11);
m_pFileStream->ReadUChar(aDBFColumn.db_typ);
m_pFileStream->ReadUInt32(aDBFColumn.db_adr);
m_pFileStream->ReadUChar(aDBFColumn.db_flng);
m_pFileStream->ReadUChar(aDBFColumn.db_dez);
m_pFileStream->ReadBytes(aDBFColumn.db_free2, 14); if (!m_pFileStream->good())
{
SAL_WARN("connectivity.drivers", "ODbaseTable::fillColumns: short read!"); break;
} if ( FIELD_DESCRIPTOR_TERMINATOR == aDBFColumn.db_fnm[0] ) // 0x0D stored as the Field Descriptor terminator. break;
OSL_ENSURE( m_pConnection->matchesExtension( aURL.getExtension() ), "ODbaseTable::ODbaseTable: invalid extension!"); // getEntry is expected to ensure the correct file name
// If the memo file isn't found, the data will be displayed anyhow. // However, updates can't be done // but the operation is executed
m_pMemoStream = createStream_simpleError( aURL.GetMainURL(INetURLObject::DecodeMechanism::NONE), StreamMode::READWRITE | StreamMode::NOCREATE | StreamMode::SHARE_DENYWRITE); if ( !m_pMemoStream )
{
m_pMemoStream = createStream_simpleError( aURL.GetMainURL(INetURLObject::DecodeMechanism::NONE), StreamMode::READ | StreamMode::NOCREATE | StreamMode::SHARE_DENYNONE);
} if (m_pMemoStream)
ReadMemoHeader();
}
if (m_pMemoStream)
{ // set the buffer exactly to the length of a record
nFileSize = m_pMemoStream->TellEnd();
m_pMemoStream->Seek(STREAM_SEEK_TO_BEGIN);
void ODbaseTable::ReadMemoHeader()
{
m_pMemoStream->SetEndian(SvStreamEndian::LITTLE);
m_pMemoStream->RefreshBuffer(); // make sure that the header information is actually read again
m_pMemoStream->Seek(0);
(*m_pMemoStream).ReadUInt32( m_aMemoHeader.db_next ); switch (m_aHeader.type)
{ case dBaseIIIMemo: // dBase III: fixed block size case dBaseIVMemo: // sometimes dBase3 is attached to dBase4 memo
m_pMemoStream->Seek(20);
(*m_pMemoStream).ReadUInt16( m_aMemoHeader.db_size ); if (m_aMemoHeader.db_size > 1 && m_aMemoHeader.db_size != 512) // 1 is also for dBase 3
m_aMemoHeader.db_typ = MemodBaseIV; elseif (m_aMemoHeader.db_size == 512)
{ // There are files using size specification, though they are dBase-files char sHeader[4];
m_pMemoStream->Seek(m_aMemoHeader.db_size);
m_pMemoStream->ReadBytes(sHeader, 4);
switch(nType)
{ case DataType::INTEGER: case DataType::DOUBLE: case DataType::TIMESTAMP: case DataType::DATE: case DataType::BIT: case DataType::LONGVARCHAR: case DataType::LONGVARBINARY:
nLen = m_aRealFieldLengths[i-1]; break; case DataType::DECIMAL:
nLen = SvDbaseConverter::ConvertPrecisionToDbase(nLen,m_aScales[i-1]); break; // the sign and the comma
case DataType::BINARY: case DataType::OTHER:
nByteOffset += nLen; continue;
}
// Is the variable bound? if ( !(*_rRow)[i]->isBound() )
{ // No - next field.
nByteOffset += nLen;
OSL_ENSURE( nByteOffset <= m_nBufferSize ,"ByteOffset > m_nBufferSize!"); continue;
} // if ( !(_rRow->get())[i]->isBound() ) if ( ( nByteOffset + nLen) > m_nBufferSize ) break; // length doesn't match buffer size.
if (nType == DataType::CHAR || nType == DataType::VARCHAR)
{
sal_Int32 nLastPos = -1; for (sal_Int32 k = 0; k < nLen; ++k)
{ if (pData[k] != ' ') // Record last non-empty position.
nLastPos = k;
} if (nLastPos < 0)
{ // Empty string. Skip it.
(*_rRow)[i]->setNull();
} else
{ // Commit the string
*(*_rRow)[i] = OUString(pData, static_cast<sal_Int32>(nLastPos+1), m_eEncoding);
}
} // if (nType == DataType::CHAR || nType == DataType::VARCHAR) elseif ( DataType::TIMESTAMP == nType )
{
sal_Int32 nDate = 0,nTime = 0; if (o3tl::make_unsigned(nLen) < 8)
{
SAL_WARN("connectivity.drivers", "short TIMESTAMP"); returnfalse;
}
memcpy(&nDate, pData, 4);
memcpy(&nTime, pData + 4, 4); if ( !nDate && !nTime )
{
(*_rRow)[i]->setNull();
} else
{
css::util::DateTime aDateTime;
lcl_CalDate(nDate,nTime,aDateTime);
*(*_rRow)[i] = aDateTime;
}
} elseif ( DataType::INTEGER == nType )
{
sal_Int32 nValue = 0; if (o3tl::make_unsigned(nLen) > sizeof(nValue)) returnfalse;
memcpy(&nValue, pData, nLen);
*(*_rRow)[i] = nValue;
} elseif ( DataType::DOUBLE == nType )
{ double d = 0.0; if (getBOOL((*aIter)->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_ISCURRENCY)))) // Currency is treated separately
{
sal_Int64 nValue = 0; if (o3tl::make_unsigned(nLen) > sizeof(nValue)) returnfalse;
memcpy(&nValue, pData, nLen);
if ( m_aScales[i-1] )
d = (nValue / pow(10.0,static_cast<int>(m_aScales[i-1]))); else
d = static_cast<double>(nValue);
} else
{ if (o3tl::make_unsigned(nLen) > sizeof(d)) returnfalse;
memcpy(&d, pData, nLen);
}
*(*_rRow)[i] = d;
} else
{
sal_Int32 nPos1 = -1, nPos2 = -1; // If the string contains Nul-characters, then convert them to blanks! for (sal_Int32 k = 0; k < nLen; k++)
{ if (pData[k] == '\0')
pData[k] = ' ';
if (pData[k] != ' ')
{ if (nPos1 < 0) // first non-empty char position.
nPos1 = k;
// last non-empty char position.
nPos2 = k;
}
}
if (nPos1 < 0)
{ // Empty string. Skip it.
nByteOffset += nLen;
(*_rRow)[i]->setNull(); // no values -> done continue;
}
if ( !m_pConnection->matchesExtension( aURL.getExtension() ) )
aURL.setExtension(m_pConnection->getExtension());
try
{
Content aContent(aURL.GetMainURL(INetURLObject::DecodeMechanism::NONE),Reference<XCommandEnvironment>(), comphelper::getProcessComponentContext()); if (aContent.isDocument())
{ // Only if the file exists with length > 0 raise an error
std::unique_ptr<SvStream> pFileStream(createStream_simpleError( aURL.GetMainURL(INetURLObject::DecodeMechanism::NONE), StreamMode::READ));
if (pFileStream && pFileStream->TellEnd()) returnfalse;
}
} catch(const Exception&) // an exception is thrown when no file exists
{
}
bool bMemoFile = false;
bool bOk = CreateFile(aURL, bMemoFile);
FileClose();
if (!bOk)
{ try
{
Content aContent(aURL.GetMainURL(INetURLObject::DecodeMechanism::NONE),Reference<XCommandEnvironment>(), comphelper::getProcessComponentContext());
aContent.executeCommand( u"delete"_ustr, css::uno::Any( true ) );
} catch(const Exception&) // an exception is thrown when no file exists
{
} returnfalse;
}
if (bMemoFile)
{
OUString aExt = aURL.getExtension();
aURL.setExtension(u"dbt"); // extension for memo file
void ODbaseTable::throwInvalidColumnType(TranslateId pErrorId, const OUString& _sColumnName)
{ try
{ // we have to drop the file because it is corrupted now
DropImpl();
} catch(const Exception&)
{
}
// creates in principle dBase IV file format bool ODbaseTable::CreateFile(const INetURLObject& aFile, bool& bCreateMemo)
{
bCreateMemo = false;
Date aDate( Date::SYSTEM ); // current date
try
{ const sal_Int32 nCount = xColumns->getCount(); for(sal_Int32 i=0;i<nCount;++i)
{
xColumns->getByIndex(i) >>= xCol;
OSL_ENSURE(xCol.is(),"This should be a column!");
switch (getINT32(xCol->getPropertyValue(sPropType)))
{ case DataType::DOUBLE: case DataType::INTEGER: case DataType::TIMESTAMP: case DataType::LONGVARBINARY:
nDbaseType = VisualFoxPro;
i = nCount; // no more columns need to be checked break;
} // switch (getINT32(xCol->getPropertyValue(sPropType)))
}
} catch ( const Exception& )
{ try
{ // we have to drop the file because it is corrupted now
DropImpl();
} catch(const Exception&) { } throw;
}
char aBuffer[21] = {}; // write buffer
m_pFileStream->Seek(0);
(*m_pFileStream).WriteUChar( nDbaseType ); // dBase format
(*m_pFileStream).WriteUChar( aDate.GetYearUnsigned() % 100 ); // current date
(*m_pFileStream).WriteUChar( aDate.GetMonth() );
(*m_pFileStream).WriteUChar( aDate.GetDay() );
(*m_pFileStream).WriteUInt32( 0 ); // number of data records
(*m_pFileStream).WriteUInt16( (m_xColumns->getCount()+1) * 32 + 1 ); // header information, // pColumns contains always an additional column
(*m_pFileStream).WriteUInt16( 0 ); // record length will be determined later
m_pFileStream->WriteBytes(aBuffer, 20);
switch (getINT32(xCol->getPropertyValue(sPropType)))
{ case DataType::CHAR: case DataType::VARCHAR:
cTyp = 'C'; break; case DataType::DOUBLE: if (getBOOL(xCol->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_ISCURRENCY)))) // Currency will be treated separately
cTyp = 'Y'; else
cTyp = 'B'; break; case DataType::INTEGER:
cTyp = 'I'; break; case DataType::TINYINT: case DataType::SMALLINT: case DataType::BIGINT: case DataType::DECIMAL: case DataType::NUMERIC: case DataType::REAL:
cTyp = 'N'; // only dBase 3 format break; case DataType::TIMESTAMP:
cTyp = 'T'; break; case DataType::DATE:
cTyp = 'D'; break; case DataType::BIT:
cTyp = 'L'; break; case DataType::LONGVARBINARY:
bBinary = true;
[[fallthrough]]; case DataType::LONGVARCHAR:
cTyp = 'M'; break; default:
{
throwInvalidColumnType(STR_INVALID_COLUMN_TYPE, aName);
}
}
(*m_pFileStream).WriteUChar( FIELD_DESCRIPTOR_TERMINATOR ); // end of header
(*m_pFileStream).WriteChar( char(DBF_EOL) );
m_pFileStream->Seek(10);
(*m_pFileStream).WriteUInt16( nRecLength ); // set record length afterwards
if (bCreateMemo)
{
m_pFileStream->Seek(0); if (nDbaseType == VisualFoxPro)
(*m_pFileStream).WriteUChar( FoxProMemo ); else
(*m_pFileStream).WriteUChar( dBaseIIIMemo );
} // if (bCreateMemo)
} catch ( const Exception& )
{ try
{ // we have to drop the file because it is corrupted now
DropImpl();
} catch(const Exception&) { } throw;
} returntrue;
}
// as the inf file does not necessarily exist, we aren't allowed to use UCBContentHelper::Kill try
{
::ucbhelper::Content aDeleteContent( aURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ), Reference< XCommandEnvironment >(), comphelper::getProcessComponentContext() );
aDeleteContent.executeCommand( u"delete"_ustr, Any( true ) );
} catch(const Exception&)
{ // silently ignore this...
}
}
} return bDropped;
}
bool ODbaseTable::DropImpl()
{
FileClose();
if(!m_xIndexes)
refreshIndexes(); // look for indexes which must be deleted as well
bool bDropped = Drop_Static(getEntry(m_pConnection,m_Name),HasMemoFields(),m_xIndexes.get()); if(!bDropped)
{// we couldn't drop the table so we have to reopen it
construct(); if(m_xColumns)
m_xColumns->refresh();
} return bDropped;
}
bool ODbaseTable::InsertRow(OValueRefVector& rRow, const Reference<XIndexAccess>& _xCols)
{ // fill buffer with blanks if (!AllocBuffer()) returnfalse;
if (HasMemoFields() && m_pMemoStream)
{
m_pMemoStream->Seek(STREAM_SEEK_TO_END);
nMemoFileSize = m_pMemoStream->Tell();
}
if (!WriteBuffer())
{
m_pFileStream->SetStreamSize(nFileSize); // restore old size
if (HasMemoFields() && m_pMemoStream)
m_pMemoStream->SetStreamSize(nMemoFileSize); // restore old size
m_nFilePos = nTempPos; // restore file position
} else
{
(*m_pFileStream).WriteChar( char(DBF_EOL) ); // write EOL // raise number of datasets in the header:
m_pFileStream->Seek( 4 );
(*m_pFileStream).WriteUInt32( m_aHeader.nbRecords + 1 );
m_pFileStream->Flush();
// raise number if successfully
m_aHeader.nbRecords++;
*rRow[0] = m_nFilePos; // set bookmark
m_nFilePos = nTempPos;
}
} else
m_nFilePos = nTempPos;
return bInsertRow;
}
bool ODbaseTable::UpdateRow(OValueRefVector& rRow, OValueRefRow& pOrgRow, const Reference<XIndexAccess>& _xCols)
{ // fill buffer with blanks if (!AllocBuffer()) returnfalse;
// position on desired record:
std::size_t nPos = m_aHeader.headerLength + static_cast<tools::Long>(m_nFilePos-1) * m_aHeader.recordLength;
m_pFileStream->Seek(nPos);
m_pFileStream->ReadBytes(m_pBuffer.get(), m_aHeader.recordLength);
std::size_t nMemoFileSize( 0 ); if (HasMemoFields() && m_pMemoStream)
{
m_pMemoStream->Seek(STREAM_SEEK_TO_END);
nMemoFileSize = m_pMemoStream->Tell();
} if (!UpdateBuffer(rRow, pOrgRow, _xCols, false) || !WriteBuffer())
{ if (HasMemoFields() && m_pMemoStream)
m_pMemoStream->SetStreamSize(nMemoFileSize); // restore old size
} else
{
m_pFileStream->Flush();
} returntrue;
}
bool ODbaseTable::DeleteRow(const OSQLColumns& _rCols)
{ // Set the Delete-Flag (be it set or not): // Position on desired record:
std::size_t nFilePos = m_aHeader.headerLength + static_cast<tools::Long>(m_nFilePos-1) * m_aHeader.recordLength;
m_pFileStream->Seek(nFilePos);
OValueRefRow aRow = new OValueRefVector(_rCols.size());
if (!fetchRow(aRow,_rCols,true)) returnfalse;
Reference<XPropertySet> xCol;
OUString aColName;
::comphelper::UStringMixEqual aCase(isCaseSensitive()); for (sal_Int32 i = 0; i < m_xColumns->getCount(); i++)
{
Reference<XPropertySet> xIndex = isUniqueByColumnName(i); if (xIndex.is())
{
xCol.set(m_xColumns->getByIndex(i), css::uno::UNO_QUERY);
OSL_ENSURE(xCol.is(),"ODbaseTable::DeleteRow column is null!"); if(xCol.is())
{
xCol->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_NAME)) >>= aColName;
ODbaseIndex* pIndex = dynamic_cast<ODbaseIndex*>(xIndex.get());
assert(pIndex && "ODbaseTable::DeleteRow: No Index returned!");
Reference<XIndexAccess> xColumns(m_xColumns.get()); // first search a key that exist already in the table for (sal_Int32 i = 0; i < nColumnCount; ++i)
{
sal_Int32 nPos = i; if(_xCols != xColumns)
{
m_xColumns->getByIndex(i) >>= xCol;
OSL_ENSURE(xCol.is(),"ODbaseTable::UpdateBuffer column is null!");
xCol->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_NAME)) >>= aColName;
++nPos;
xIndex = isUniqueByColumnName(i);
aIndexedCols[i] = xIndex; if (xIndex.is())
{ // first check if the value is different to the old one and when if it conform to the index if(pOrgRow.is() && (rRow[nPos]->getValue().isNull() || rRow[nPos] == (*pOrgRow)[nPos])) continue; else
{
ODbaseIndex* pIndex = dynamic_cast<ODbaseIndex*>(xIndex.get());
assert(pIndex && "ODbaseTable::UpdateBuffer: No Index returned!");
if (pIndex->Find(0,*rRow[nPos]))
{ // There is no unique value if ( aColName.isEmpty() )
{
m_xColumns->getByIndex(i) >>= xCol;
OSL_ENSURE(xCol.is(),"ODbaseTable::UpdateBuffer column is null!");
xCol->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_NAME)) >>= aColName;
xCol.clear();
} // if ( !aColName.getLength() ) const OUString sError( getConnection()->getResources().getResourceStringWithSubstitution(
STR_DUPLICATE_VALUE_IN_COLUMN
,"$columnname$", aColName
) );
::dbtools::throwGenericSQLException( sError, *this );
}
}
}
}
// when we are here there is no double key in the table
for (sal_Int32 i = 0; i < nColumnCount && nByteOffset <= m_nBufferSize ; ++i)
{ // Lengths for each data type:
assert(i >= 0);
OSL_ENSURE(o3tl::make_unsigned(i) < m_aPrecisions.size(),"Illegal index!");
sal_Int32 nLen = 0;
sal_Int32 nType = 0;
sal_Int32 nScale = 0; if ( o3tl::make_unsigned(i) < m_aPrecisions.size() )
{
nLen = m_aPrecisions[i];
nType = m_aTypes[i];
nScale = m_aScales[i];
} else
{
m_xColumns->getByIndex(i) >>= xCol; if ( xCol.is() )
{
xCol->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_PRECISION)) >>= nLen;
xCol->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_TYPE)) >>= nType;
xCol->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_SCALE)) >>= nScale;
}
}
bool bSetZero = false; switch (nType)
{ case DataType::INTEGER: case DataType::DOUBLE: case DataType::TIMESTAMP:
bSetZero = true;
[[fallthrough]]; case DataType::LONGVARBINARY: case DataType::DATE: case DataType::BIT: case DataType::LONGVARCHAR:
nLen = m_aRealFieldLengths[i]; break; case DataType::DECIMAL:
nLen = SvDbaseConverter::ConvertPrecisionToDbase(nLen,nScale); break; // The sign and the comma default: break;
// Exactly 8 bytes to copy (even if s could hypothetically be longer):
memcpy(pData,s,8);
} break; case DataType::INTEGER:
{
sal_Int32 nValue = thisColVal.getInt32(); if (o3tl::make_unsigned(nLen) > sizeof(nValue)) returnfalse;
memcpy(pData,&nValue,nLen);
} break; case DataType::DOUBLE:
{ constdouble d = thisColVal.getDouble();
m_xColumns->getByIndex(i) >>= xCol;
if (getBOOL(xCol->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_ISCURRENCY)))) // Currency is treated separately
{
sal_Int64 nValue = 0; if ( m_aScales[i] )
nValue = static_cast<sal_Int64>(d * pow(10.0,static_cast<int>(m_aScales[i]))); else
nValue = static_cast<sal_Int64>(d); if (o3tl::make_unsigned(nLen) > sizeof(nValue)) returnfalse;
memcpy(pData,&nValue,nLen);
} // if (getBOOL(xCol->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_ISCURRENCY)))) // Currency is treated separately else
{ if (o3tl::make_unsigned(nLen) > sizeof(d)) returnfalse;
memcpy(pData,&d,nLen);
}
} break; case DataType::DECIMAL:
{
memset(pData,' ',nLen); // Clear to NULL
constdouble n = thisColVal.getDouble();
// one, because const_cast GetFormatPrecision on SvNumberFormat is not constant, // even though it really could and should be const OString aDefaultValue( ::rtl::math::doubleToString( n, rtl_math_StringFormat_F, nScale, '.', nullptr, 0)); const sal_Int32 nValueLen = aDefaultValue.getLength(); if ( nValueLen <= nLen )
{ // Write value right-justified, padded with blanks to the left.
memcpy(pData+nLen-nValueLen,aDefaultValue.getStr(),nValueLen); // write the resulting double back
*rRow[nPos] = toDouble(aDefaultValue);
} else
{
m_xColumns->getByIndex(i) >>= xCol;
OSL_ENSURE(xCol.is(),"ODbaseTable::UpdateBuffer column is null!");
xCol->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_NAME)) >>= aColName;
std::vector< std::pair<constchar* , OUString > > aStringToSubstitutes
{
{ "$columnname$", aColName },
{ "$precision$", OUString::number(nLen) },
{ "$scale$", OUString::number(nScale) },
{ "$value$", OStringToOUString(aDefaultValue,RTL_TEXTENCODING_UTF8) }
};
const OUString sError( getConnection()->getResources().getResourceStringWithSubstitution(
STR_INVALID_COLUMN_DECIMAL_VALUE
,aStringToSubstitutes
) );
::dbtools::throwGenericSQLException( sError, *this );
}
} break; case DataType::BIT:
*pData = thisColVal.getBool() ? 'T' : 'F'; break; case DataType::LONGVARBINARY: case DataType::LONGVARCHAR:
{ char cNext = pData[nLen]; // Mark's scratch and replaced by 0
pData[nLen] = '\0'; // This is because the buffer is always a sign of greater ...
std::size_t nBlockNo = strtol(pData,nullptr,10); // Block number read
// Next initial character restore again:
pData[nLen] = cNext; if (!m_pMemoStream) break;
WriteMemo(thisColVal, nBlockNo);
OString aBlock(OString::number(nBlockNo)); //align aBlock at the right of a nLen sequence, fill to the left with '0'
OStringBuffer aStr;
comphelper::string::padToLength(aStr, nLen - aBlock.getLength(), '0');
aStr.append(aBlock);
try
{
OSL_ENSURE(descriptor.is(),"ODbaseTable::alterColumn: descriptor can not be null!"); // creates a copy of 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()->supportsMixedCaseQuotedIdentifiers());
// now drop the old one if( DropImpl() ) // we don't want to delete the memo columns too
{ try
{ // rename the new one to the old one
pNewTable->renameImpl(m_Name);
} catch(const css::container::ElementExistException&)
{ const OUString sError( getConnection()->getResources().getResourceStringWithSubstitution(
STR_COULD_NOT_DELETE_FILE, "$filename$", m_Name
) );
::dbtools::throwGenericSQLException( sError, *this );
} // release the temp file
::comphelper::disposeComponent(pNewTable);
pNewTable = nullptr;
} else
{
pNewTable = nullptr;
}
FileClose();
construct(); if(m_xColumns)
m_xColumns->refresh();
xNewTable->construct(); // copy the data
copyData(xNewTable.get(),xNewTable->m_xColumns->getCount()); // drop the old table if(DropImpl())
{
xNewTable->renameImpl(m_Name); // release the temp file
}
xNewTable.clear();
// construct the new table if(!xNewTable->CreateImpl())
{ const OUString sError( getConnection()->getResources().getResourceStringWithSubstitution(
STR_COLUMN_NOT_DROP, "$position$", OUString::number(_nPos)
) );
::dbtools::throwGenericSQLException( sError, *this );
}
xNewTable->construct(); // copy the data
copyData(xNewTable.get(),_nPos); // drop the old table if(DropImpl())
xNewTable->renameImpl(m_Name); // release the temp file
void ODbaseTable::copyData(ODbaseTable* _pNewTable,sal_Int32 _nPos)
{
sal_Int32 nPos = _nPos + 1; // +1 because we always have the bookmark column as well
OValueRefRow aRow = new OValueRefVector(m_xColumns->getCount());
OValueRefRow aInsertRow; if(_nPos)
{
aInsertRow = new OValueRefVector(_pNewTable->m_xColumns->getCount());
std::for_each(aInsertRow->begin(),aInsertRow->end(),TSetRefBound(true));
} 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(),TSetRefBound(true)); if(_nPos && (_nPos < static_cast<sal_Int32>(aRow->size())))
(*aRow)[nPos]->setBound(false);
sal_Int32 nCurPos;
OValueRefVector::const_iterator aIter; for(sal_uInt32 nRowPos = 0; nRowPos < m_aHeader.nbRecords;++nRowPos)
{ bool bOk = seekRow( IResultSetHelper::BOOKMARK, nRowPos+1, nCurPos ); if ( bOk )
{
bOk = fetchRow( aRow, *m_aColumns, true); if ( bOk && !aRow->isDeleted() ) // copy only not deleted rows
{ // 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(OValueRefVector::iterator aInsertIter = aInsertRow->begin()+1; aIter != aRow->end() && aInsertIter != aInsertRow->end();++aIter,++nCount)
{ if(nPos != nCount)
{
(*aInsertIter)->setValue( (*aIter)->getValue() );
++aInsertIter;
}
}
}
bOk = _pNewTable->InsertRow(*aInsertRow, _pNewTable->m_xColumns.get());
SAL_WARN_IF(!bOk, "connectivity.drivers", "Row could not be inserted!");
} else
{
SAL_WARN_IF(!bOk, "connectivity.drivers", "Row could not be fetched!");
}
} else
{
OSL_ASSERT(false);
}
} // for(sal_uInt32 nRowPos = 0; nRowPos < m_aHeader.db_anz;++nRowPos)
}
void ODbaseTable::throwInvalidDbaseFormat()
{
FileClose(); // no dbase file
m_pFileStream->Seek(nPos); if (m_pFileStream->GetError() != ERRCODE_NONE) goto Error;
std::size_t nRead = m_pFileStream->ReadBytes(m_pBuffer.get(), nEntryLen); if (nRead != nEntryLen)
{
SAL_WARN("connectivity.drivers", "ODbaseTable::seekRow: short read!"); goto Error;
} if (m_pFileStream->GetError() != ERRCODE_NONE) goto Error;
} goto End;
Error: switch(eCursorPosition)
{ case IResultSetHelper::PRIOR: case IResultSetHelper::FIRST:
m_nFilePos = 0; break; case IResultSetHelper::LAST: case IResultSetHelper::NEXT: case IResultSetHelper::ABSOLUTE1: case IResultSetHelper::RELATIVE1: if (nOffset > 0)
m_nFilePos = nNumberOfRecords + 1; elseif (nOffset < 0)
m_nFilePos = 0; break; case IResultSetHelper::BOOKMARK:
m_nFilePos = nTempPos; // last position
} returnfalse;
End:
nCurPos = m_nFilePos; returntrue;
}
bool ODbaseTable::ReadMemo(std::size_t nBlockNo, ORowSetValue& aVariable)
{
m_pMemoStream->Seek(nBlockNo * m_aMemoHeader.db_size); switch (m_aMemoHeader.db_typ)
{ case MemodBaseIII: // dBase III-Memofield, ends with Ctrl-Z
{ constchar cEOF = char(DBF_EOL);
OStringBuffer aBStr; staticchar aBuf[514];
aBuf[512] = 0; // avoid random value bool bReady = false;
do
{
m_pMemoStream->ReadBytes(&aBuf, 512);
sal_uInt16 i = 0; while (aBuf[i] != cEOF && ++i < 512)
;
bReady = aBuf[i] == cEOF;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.