21#include <com/sun/star/container/ElementExistException.hpp> 
   22#include <com/sun/star/sdbc/ColumnValue.hpp> 
   23#include <com/sun/star/sdbc/DataType.hpp> 
   24#include <com/sun/star/ucb/XContentAccess.hpp> 
   25#include <com/sun/star/sdbc/XRow.hpp> 
   35#include <rtl/math.hxx> 
   37#include <com/sun/star/ucb/ContentCreationException.hpp> 
   39#include <com/sun/star/lang/IndexOutOfBoundsException.hpp> 
   55#include <rtl/strbuf.hxx> 
   72using namespace ::
cppu;
 
   84#define FIELD_DESCRIPTOR_TERMINATOR 0x0D 
   89std::size_t lcl_getFileSize(
SvStream& _rStream)
 
   91    std::size_t nFileSize = 0;
 
   96    nFileSize = _rStream.
Tell();
 
  104void lcl_CalcJulDate(sal_Int32& _nJulianDate,sal_Int32& _nJulianTime, 
const css::util::DateTime& rDateTime)
 
  106    css::util::DateTime aDateTime = rDateTime;
 
  108    if (aDateTime.Month > 12)
 
  111        sal_uInt16 delta = rDateTime.Month / 12;
 
  112        aDateTime.Year += delta;
 
  113        aDateTime.Month -= delta * 12;
 
  117    _nJulianTime = ((aDateTime.Hours*3600000)+(aDateTime.Minutes*60000)+(aDateTime.Seconds*1000)+(aDateTime.NanoSeconds/1000000));
 
  121    if ( aDateTime.Month <= 2 )
 
  123        iy0 = aDateTime.Year - 1;
 
  124        im0 = aDateTime.Month + 12;
 
  128        iy0 = aDateTime.Year;
 
  129        im0 = aDateTime.Month;
 
  131    sal_Int32 ia = iy0 / 100;
 
  132    sal_Int32 ib = 2 - ia + (ia >> 2);
 
  134    if ( aDateTime.Year <= 0 )
 
  136        _nJulianDate = 
static_cast<sal_Int32
>((365.25 * iy0) - 0.75)
 
  138            + aDateTime.Day + 1720994;
 
  142        _nJulianDate = 
static_cast<sal_Int32
>(365.25 * iy0)
 
  144            + aDateTime.Day + 1720994;
 
  146    double JD = _nJulianDate + 0.5;
 
  147    _nJulianDate = 
static_cast<sal_Int32
>( JD + 0.5);
 
  148    const double gyr = aDateTime.Year + (0.01 * aDateTime.Month) + (0.0001 * aDateTime.Day);
 
  149    if ( gyr >= 1582.1015 ) 
 
  156void lcl_CalDate(sal_Int32 _nJulianDate,sal_Int32 _nJulianTime,css::util::DateTime& _rDateTime)
 
  160        sal_Int64 ka = _nJulianDate;
 
  161        if ( _nJulianDate >= 2299161 )
 
  163            sal_Int64 ialp = 
static_cast<sal_Int64
>( (
static_cast<double>(_nJulianDate) - 1867216.25 ) / 36524.25 );
 
  164            ka = ka + 1 + ialp - ( ialp >> 2 );
 
  166        sal_Int64 kb = ka + 1524;
 
  167        sal_Int64 kc = 
static_cast<sal_Int64
>((
static_cast<double>(kb) - 122.1) / 365.25);
 
  168        sal_Int64 kd = 
static_cast<sal_Int64
>(
static_cast<double>(kc) * 365.25);
 
  172            _rDateTime.Month = 
static_cast<sal_uInt16
>(ke - 13);
 
  174            _rDateTime.Month = 
static_cast<sal_uInt16
>(ke - 1);
 
  175        if ( (_rDateTime.Month == 2) && (_rDateTime.Day > 28) )
 
  177        if ( (_rDateTime.Month == 2) && (_rDateTime.Day == 29) && (ke == 3) )
 
  178            _rDateTime.Year = 
static_cast<sal_uInt16
>(kc - 4716);
 
  179        else if ( _rDateTime.Month > 2 )
 
  180            _rDateTime.Year = 
static_cast<sal_uInt16
>(kc - 4716);
 
  182            _rDateTime.Year = 
static_cast<sal_uInt16
>(kc - 4715);
 
  187        double d_s = _nJulianTime / 1000.0;
 
  188        double d_m = d_s / 60.0;
 
  189        double d_h  = d_m / 60.0;
 
  190        _rDateTime.Hours = 
static_cast<sal_uInt16
>(d_h);
 
  191        _rDateTime.Minutes = 
static_cast<sal_uInt16
>((d_h - 
static_cast<double>(_rDateTime.Hours)) * 60.0);
 
  192        _rDateTime.Seconds = 
static_cast<sal_uInt16
>(((d_m - 
static_cast<double>(_rDateTime.Minutes)) * 60.0)
 
  193                - (
static_cast<double>(_rDateTime.Hours) * 3600.0));
 
  200void ODbaseTable::readHeader()
 
  280        SAL_WARN(
"connectivity.drivers", 
"ODbaseTable::fillColumns: bad offset!");
 
  295    if (nFieldCount <= 0)
 
  297        SAL_WARN(
"connectivity.drivers", 
"No columns in table!");
 
  302    auto nMaxPossibleRecords = nRemainingsize / 32;
 
  305        SAL_WARN(
"connectivity.drivers", 
"Parsing error: " << nMaxPossibleRecords <<
 
  306                 " max possible entries, but " << nFieldCount << 
" claimed, truncating");
 
  307        nFieldCount = nMaxPossibleRecords;
 
  320    for (; 
i < nFieldCount; 
i++)
 
  331            SAL_WARN(
"connectivity.drivers", 
"ODbaseTable::fillColumns: short read!");
 
  338        const OUString aColumnName(
reinterpret_cast<char *
>(aDBFColumn.
db_fnm), strlen(
reinterpret_cast<char *
>(aDBFColumn.
db_fnm)), 
m_eEncoding);
 
  340        bool bIsRowVersion = bFoxPro && ( aDBFColumn.
db_free2[0] & 0x01 ) == 0x01;
 
  343        sal_Int32 nPrecision = aDBFColumn.
db_flng;
 
  345        bool bIsCurrency = 
false;
 
  348        cType[0] = aDBFColumn.
db_typ;
 
  350        aTypeName = OUString(cType, 1, RTL_TEXTENCODING_ASCII_US);
 
  351        SAL_INFO( 
"connectivity.drivers",
"column type: " << aDBFColumn.
db_typ);
 
  353        switch (aDBFColumn.
db_typ)
 
  356            eType = DataType::VARCHAR;
 
  357            aTypeName = 
"VARCHAR";
 
  361            aTypeName = 
"DECIMAL";
 
  362            if ( aDBFColumn.
db_typ == 
'N' )
 
  363                aTypeName = 
"NUMERIC";
 
  364            eType = DataType::DECIMAL;
 
  372            eType = DataType::BIT;
 
  373            aTypeName = 
"BOOLEAN";
 
  377            eType = DataType::DOUBLE;
 
  378            aTypeName = 
"DOUBLE";
 
  381            eType = DataType::DATE;
 
  385            eType = DataType::TIMESTAMP;
 
  386            aTypeName = 
"TIMESTAMP";
 
  389            eType = DataType::INTEGER;
 
  390            aTypeName = 
"INTEGER";
 
  393            if ( bFoxPro && ( aDBFColumn.
db_free2[0] & 0x04 ) == 0x04 )
 
  395                eType = DataType::LONGVARBINARY;
 
  396                aTypeName = 
"LONGVARBINARY";
 
  400                aTypeName = 
"LONGVARCHAR";
 
  401                eType = DataType::LONGVARCHAR;
 
  403            nPrecision = 2147483647;
 
  406            aTypeName = 
"LONGVARBINARY";
 
  407            eType = DataType::LONGVARBINARY;
 
  408            nPrecision = 2147483647;
 
  414                aTypeName = 
"DOUBLE";
 
  415                eType = DataType::DOUBLE;
 
  419                aTypeName = 
"LONGVARBINARY";
 
  420                eType = DataType::LONGVARBINARY;
 
  421                nPrecision = 2147483647;
 
  425            eType = DataType::OTHER;
 
  436                                                    ColumnValue::NULLABLE,
 
  447    OSL_ENSURE(
i,
"No columns in table!");
 
  459                         const OUString& Name,
 
  460                         const OUString& 
Type,
 
  461                         const OUString& Description ,
 
  462                         const OUString& SchemaName,
 
  463                         const OUString& CatalogName )
 
  485    aURL.SetURL(sFileName);
 
  488        "ODbaseTable::ODbaseTable: invalid extension!");
 
  509        SAL_WARN(
"connectivity.drivers", 
"Parsing error: " << nFileSize <<
 
  521            SAL_WARN(
"connectivity.drivers", 
"Parsing warning: 0 records claimed, recovering");
 
  526            SAL_WARN(
"connectivity.drivers", 
"Parsing error: " << nMaxPossibleRecords <<
 
  538            aURL.SetExtension(
u"fpt");
 
  540            aURL.SetExtension(
u"dbt");
 
  560                              nFileSize > 100000 ? 16384 :
 
  561                              nFileSize > 10000 ? 4096 : 1024);
 
  571                                      nFileSize > 100000 ? 16384 :
 
  572                                      nFileSize > 10000 ? 4096 :
 
  622            SAL_WARN( 
"connectivity.drivers", 
"ODbaseTable::ReadMemoHeader: unsupported memo type!" );
 
  640            sName = xRow->getString(1);
 
  641            aURL.SetSmartProtocol(INetProtocol::File);
 
  642            OUString sUrl = _pConnection->
getURL() + 
"/" + 
sName;
 
  643            aURL.SetSmartURL( sUrl );
 
  646            sExt = 
aURL.getExtension();
 
  651                sName = 
sName.replaceAt(
sName.getLength() - (sExt.getLength() + 1), sExt.getLength() + 1, 
u"");
 
  652                if ( 
sName == _sName )
 
  655                    sURL = xContentAccess->queryContentIdentifierString();
 
  671    ::osl::MutexGuard aGuard( 
m_aMutex );
 
  673    ::std::vector< OUString> aVector;
 
  687    ::std::vector< OUString> aVector;
 
  693        aURL.setExtension(
u"inf");
 
  694        Config aInfFile(
aURL.getFSysPath(FSysStyle::Detect));
 
  699        for (sal_uInt16 nKey = 0; nKey < nKeyCnt; nKey++)
 
  704            if (aKeyName.startsWith(
"NDX"))
 
  706                OString aIndexName = aInfFile.
ReadKey(aKeyName);
 
  711                    if (aCnt.isDocument())
 
  713                        aVector.push_back(
aURL.getBase());
 
  731    OFileTable::disposing();
 
  739    std::vector<Type> aOwnTypes;
 
  740    aOwnTypes.reserve(
aTypes.getLength());
 
  743    const Type* pEnd = pBegin + 
aTypes.getLength();
 
  744    for(;pBegin != pEnd;++pBegin)
 
  749            aOwnTypes.push_back(*pBegin);
 
  774    bool bIsCurRecordDeleted = 
m_pBuffer[0] == 
'*';
 
  779    _rRow->setDeleted(bIsCurRecordDeleted);
 
  785    std::size_t nByteOffset = 1;
 
  787    OSQLColumns::const_iterator aIter = _rCols.begin();
 
  788    OSQLColumns::const_iterator aEnd  = _rCols.end();
 
  789    const std::size_t 
nCount = _rRow->size();
 
  798            case DataType::INTEGER:
 
  799            case DataType::DOUBLE:
 
  800            case DataType::TIMESTAMP:
 
  803            case DataType::LONGVARCHAR:
 
  804            case DataType::LONGVARBINARY:
 
  807            case DataType::DECIMAL:
 
  811            case DataType::BINARY:
 
  812            case DataType::OTHER:
 
  818        if ( !(*_rRow)[
i]->isBound() )
 
  822            OSL_ENSURE( nByteOffset <= m_nBufferSize ,"ByteOffset > 
m_nBufferSize!
"); 
  824        } // if ( !(_rRow->get())[i]->isBound() ) 
  825        if ( ( nByteOffset + nLen) > m_nBufferSize ) 
  826            break; // length doesn't match buffer size. 
  828        char *pData = reinterpret_cast<char *>(m_pBuffer.get() + nByteOffset); 
  830        if (nType == DataType::CHAR || nType == DataType::VARCHAR) 
  832            sal_Int32 nLastPos = -1; 
  833            for (sal_Int32 k = 0; k < nLen; ++k) 
  836                    // Record last non-empty position. 
  841                // Empty string.  Skip it. 
  842                (*_rRow)[i]->setNull(); 
  847                *(*_rRow)[i] = OUString(pData, static_cast<sal_Int32>(nLastPos+1), m_eEncoding); 
  849        } // if (nType == DataType::CHAR || nType == DataType::VARCHAR) 
  850        else if ( DataType::TIMESTAMP == nType ) 
  852            sal_Int32 nDate = 0,nTime = 0; 
  853            if (o3tl::make_unsigned(nLen) < 8) 
  858            memcpy(&nDate, pData, 4); 
  859            memcpy(&nTime, pData + 4, 4); 
  860            if ( !nDate && !nTime ) 
  862                (*_rRow)[i]->setNull(); 
  866                css::util::DateTime aDateTime; 
  867                lcl_CalDate(nDate,nTime,aDateTime); 
  868                *(*_rRow)[i] = aDateTime; 
  871        else if ( DataType::INTEGER == nType ) 
  873            sal_Int32 nValue = 0; 
  874            if (o3tl::make_unsigned(nLen) > sizeof(nValue)) 
  876            memcpy(&nValue, pData, nLen); 
  877            *(*_rRow)[i] = nValue; 
  879        else if ( DataType::DOUBLE == nType ) 
  882            if (getBOOL((*aIter)->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_ISCURRENCY)))) // Currency is treated separately 
  884                sal_Int64 nValue = 0; 
  885                if (o3tl::make_unsigned(nLen) > sizeof(nValue)) 
  887                memcpy(&nValue, pData, nLen); 
  889                if ( m_aScales[i-1] ) 
  890                    d = (nValue / pow(10.0,static_cast<int>(m_aScales[i-1]))); 
  892                    d = static_cast<double>(nValue); 
  896                if (o3tl::make_unsigned(nLen) > sizeof(d)) 
  898                memcpy(&d, pData, nLen); 
  905            sal_Int32 nPos1 = -1, nPos2 = -1; 
  906            // If the string contains Nul-characters, then convert them to blanks! 
  907            for (sal_Int32 k = 0; k < nLen; k++) 
  909                if (pData[k] == '\0') 
  915                        // first non-empty char position. 
  918                    // last non-empty char position. 
  925                // Empty string.  Skip it. 
  927                (*_rRow)[i]->setNull();   // no values -> done 
  931            OUString aStr(pData+nPos1, nPos2-nPos1+1, m_eEncoding); 
  937                    if (nLen < 8 || aStr.getLength() != nLen) 
  939                        (*_rRow)[i]->setNull(); 
  942                    const sal_uInt16  nYear   = static_cast<sal_uInt16>(o3tl::toInt32(aStr.subView( 0, 4 ))); 
  943                    const sal_uInt16  nMonth  = static_cast<sal_uInt16>(o3tl::toInt32(aStr.subView( 4, 2 ))); 
  944                    const sal_uInt16  nDay    = static_cast<sal_uInt16>(o3tl::toInt32(aStr.subView( 6, 2 ))); 
  946                    const css::util::Date aDate(nDay,nMonth,nYear); 
  947                    *(*_rRow)[i] = aDate; 
  950                case DataType::DECIMAL: 
  951                    *(*_rRow)[i] = ORowSetValue(aStr); 
  960                        case 'J':   b = true; break; 
  961                        default:    b = false; break; 
  966                case DataType::LONGVARBINARY: 
  967                case DataType::BINARY: 
  968                case DataType::LONGVARCHAR: 
  970                    const tools::Long nBlockNo = aStr.toInt32();   // read blocknumber 
  971                    if (nBlockNo > 0 && m_pMemoStream) // Read data from memo-file, only if 
  973                        if ( !ReadMemo(nBlockNo, (*_rRow)[i]->get()) ) 
  977                        (*_rRow)[i]->setNull(); 
  982            (*_rRow)[i]->setTypeKind(nType); 
  986        OSL_ENSURE( nByteOffset <= m_nBufferSize ,"ByteOffset > 
m_nBufferSize!
"); 
  992void ODbaseTable::FileClose() 
  994    ::osl::MutexGuard aGuard(m_aMutex); 
  996    m_pMemoStream.reset(); 
  998    ODbaseTable_BASE::FileClose(); 
 1001bool ODbaseTable::CreateImpl() 
 1003    OSL_ENSURE(!m_pFileStream, "SequenceError
"); 
 1005    if ( m_pConnection->isCheckEnabled() && ::dbtools::convertName2SQLName(m_Name, u"") != m_Name ) 
 1007        const OUString sError( getConnection()->getResources().getResourceStringWithSubstitution( 
 1011        ::dbtools::throwGenericSQLException( sError, *this ); 
 1015    aURL.SetSmartProtocol(INetProtocol::File); 
 1016    OUString aName = getEntry(m_pConnection, m_Name); 
 1019        OUString aIdent = m_pConnection->getContent()->getIdentifier()->getContentIdentifier(); 
 1020        if ( aIdent.lastIndexOf('/') != (aIdent.getLength()-1) ) 
 1027    if ( !m_pConnection->matchesExtension( aURL.getExtension() ) ) 
 1028        aURL.setExtension(m_pConnection->getExtension()); 
 1032        Content aContent(aURL.GetMainURL(INetURLObject::DecodeMechanism::NONE),Reference<XCommandEnvironment>(), comphelper::getProcessComponentContext()); 
 1033        if (aContent.isDocument()) 
 1035            // Only if the file exists with length > 0 raise an error 
 1036            std::unique_ptr<SvStream> pFileStream(createStream_simpleError( aURL.GetMainURL(INetURLObject::DecodeMechanism::NONE), StreamMode::READ)); 
 1038            if (pFileStream && pFileStream->TellEnd()) 
 1042    catch(const Exception&) // an exception is thrown when no file exists 
 1046    bool bMemoFile = false; 
 1048    bool bOk = CreateFile(aURL, bMemoFile); 
 1056            Content aContent(aURL.GetMainURL(INetURLObject::DecodeMechanism::NONE),Reference<XCommandEnvironment>(), comphelper::getProcessComponentContext()); 
 1057            aContent.executeCommand( "delete", css::uno::Any( true ) ); 
 1059        catch(const Exception&) // an exception is thrown when no file exists 
 1067        OUString aExt = aURL.getExtension(); 
 1068        aURL.setExtension(u"dbt
");                      // extension for memo file 
 1070        bool bMemoAlreadyExists = false; 
 1073            Content aMemo1Content(aURL.GetMainURL(INetURLObject::DecodeMechanism::NONE),Reference<XCommandEnvironment>(), comphelper::getProcessComponentContext()); 
 1074            bMemoAlreadyExists = aMemo1Content.isDocument(); 
 1076        catch(const Exception&) // an exception is thrown when no file exists 
 1079        if (bMemoAlreadyExists) 
 1081            aURL.setExtension(aExt);      // kill dbf file 
 1084                Content aMemoContent(aURL.GetMainURL(INetURLObject::DecodeMechanism::NONE),Reference<XCommandEnvironment>(), comphelper::getProcessComponentContext()); 
 1085                aMemoContent.executeCommand( "delete", css::uno::Any( true ) ); 
 1087            catch(const Exception&) 
 1089                css::uno::Any anyEx = cppu::getCaughtException(); 
 1090                const OUString sError( getConnection()->getResources().getResourceStringWithSubstitution( 
 1091                        STR_COULD_NOT_DELETE_FILE, 
 1094                ::dbtools::throwGenericSQLException( sError, *this, anyEx ); 
 1097        if (!CreateMemoFile(aURL)) 
 1099            aURL.setExtension(aExt);      // kill dbf file 
 1102                Content aMemoContent(aURL.GetMainURL(INetURLObject::DecodeMechanism::NONE),Reference<XCommandEnvironment>(), comphelper::getProcessComponentContext()); 
 1103                aMemoContent.executeCommand( "delete", css::uno::Any( true ) ); 
 1105            catch(const ContentCreationException&) 
 1107                css::uno::Any anyEx = cppu::getCaughtException(); 
 1108                const OUString sError( getConnection()->getResources().getResourceStringWithSubstitution( 
 1109                        STR_COULD_NOT_DELETE_FILE, 
 1112                ::dbtools::throwGenericSQLException( sError, *this, anyEx ); 
 1116        m_aHeader.type = dBaseIIIMemo; 
 1119        m_aHeader.type = dBaseIII; 
 1124void ODbaseTable::throwInvalidColumnType(TranslateId pErrorId, const OUString& _sColumnName) 
 1128        // we have to drop the file because it is corrupted now 
 1131    catch(const Exception&) 
 1135    const OUString sError( getConnection()->getResources().getResourceStringWithSubstitution( 
 1137            "$columnname$
", _sColumnName 
 1139    ::dbtools::throwGenericSQLException( sError, *this ); 
 1142// creates in principle dBase IV file format 
 1143bool ODbaseTable::CreateFile(const INetURLObject& aFile, bool& bCreateMemo) 
 1145    bCreateMemo = false; 
 1146    Date aDate( Date::SYSTEM );                     // current date 
 1148    m_pFileStream = createStream_simpleError( aFile.GetMainURL(INetURLObject::DecodeMechanism::NONE),StreamMode::READWRITE | StreamMode::SHARE_DENYWRITE | StreamMode::TRUNC ); 
 1153    sal_uInt8 nDbaseType = dBaseIII; 
 1154    Reference<XIndexAccess> xColumns(getColumns(),UNO_QUERY); 
 1155    Reference<XPropertySet> xCol; 
 1156    const OUString sPropType = OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_TYPE); 
 1160        const sal_Int32 nCount = xColumns->getCount(); 
 1161        for(sal_Int32 i=0;i<nCount;++i) 
 1163            xColumns->getByIndex(i) >>= xCol; 
 1164            OSL_ENSURE(xCol.is(),"This should be a column!
"); 
 1166            switch (getINT32(xCol->getPropertyValue(sPropType))) 
 1168                case DataType::DOUBLE: 
 1169                case DataType::INTEGER: 
 1170                case DataType::TIMESTAMP: 
 1171                case DataType::LONGVARBINARY: 
 1172                    nDbaseType = VisualFoxPro; 
 1173                    i = nCount; // no more columns need to be checked 
 1175            } // switch (getINT32(xCol->getPropertyValue(sPropType))) 
 1178    catch ( const Exception& ) 
 1182            // we have to drop the file because it is corrupted now 
 1185        catch(const Exception&) { } 
 1189    char aBuffer[21] = {}; // write buffer 
 1191    m_pFileStream->Seek(0); 
 1192    (*m_pFileStream).WriteUChar( nDbaseType );                            // dBase format 
 1193    (*m_pFileStream).WriteUChar( aDate.GetYearUnsigned() % 100 );         // current date 
 1196    (*m_pFileStream).WriteUChar( aDate.GetMonth() ); 
 1197    (*m_pFileStream).WriteUChar( aDate.GetDay() ); 
 1198    (*m_pFileStream).WriteUInt32( 0 );                                    // number of data records 
 1199    (*m_pFileStream).WriteUInt16( (m_xColumns->getCount()+1) * 32 + 1 );  // header information, 
 1200                                                                          // pColumns contains always an additional column 
 1201    (*m_pFileStream).WriteUInt16( 0 );                                     // record length will be determined later 
 1202    m_pFileStream->WriteBytes(aBuffer, 20); 
 1204    sal_uInt16 nRecLength = 1;                                              // Length 1 for deleted flag 
 1205    sal_Int32  nMaxFieldLength = m_pConnection->getMetaData()->getMaxColumnNameLength(); 
 1207    const OUString sPropName = OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_NAME); 
 1208    const OUString sPropPrec = OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_PRECISION); 
 1209    const OUString sPropScale = OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_SCALE); 
 1213        const sal_Int32 nCount = xColumns->getCount(); 
 1214        for(sal_Int32 i=0;i<nCount;++i) 
 1216            xColumns->getByIndex(i) >>= xCol; 
 1217            OSL_ENSURE(xCol.is(),"This should be a column!
"); 
 1221            xCol->getPropertyValue(sPropName) >>= aName; 
 1224            if ( DBTypeConversion::convertUnicodeString( aName, aCol, m_eEncoding ) > nMaxFieldLength) 
 1226                throwInvalidColumnType( STR_INVALID_COLUMN_NAME_LENGTH, aName ); 
 1229            m_pFileStream->WriteOString( aCol ); 
 1230            m_pFileStream->WriteBytes(aBuffer, 11 - aCol.getLength()); 
 1232            sal_Int32 nPrecision = 0; 
 1233            xCol->getPropertyValue(sPropPrec) >>= nPrecision; 
 1234            sal_Int32 nScale = 0; 
 1235            xCol->getPropertyValue(sPropScale) >>= nScale; 
 1237            bool bBinary = false; 
 1239            switch (getINT32(xCol->getPropertyValue(sPropType))) 
 1241                case DataType::CHAR: 
 1242                case DataType::VARCHAR: 
 1245                case DataType::DOUBLE: 
 1246                    if (getBOOL(xCol->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_ISCURRENCY)))) // Currency will be treated separately 
 1251                case DataType::INTEGER: 
 1254                case DataType::TINYINT: 
 1255                case DataType::SMALLINT: 
 1256                case DataType::BIGINT: 
 1257                case DataType::DECIMAL: 
 1258                case DataType::NUMERIC: 
 1259                case DataType::REAL: 
 1260                    cTyp = 'N';                             // only dBase 3 format 
 1262                case DataType::TIMESTAMP: 
 1265                case DataType::DATE: 
 1271                case DataType::LONGVARBINARY: 
 1274                case DataType::LONGVARCHAR: 
 1279                        throwInvalidColumnType(STR_INVALID_COLUMN_TYPE, aName); 
 1283            (*m_pFileStream).WriteChar( cTyp ); 
 1284            if ( nDbaseType == VisualFoxPro ) 
 1285                (*m_pFileStream).WriteUInt32( nRecLength-1 ); 
 1287                m_pFileStream->WriteBytes(aBuffer, 4); 
 1292                    OSL_ENSURE(nPrecision < 255, "ODbaseTable::Create: 
Column too 
long!
"); 
 1293                    if (nPrecision > 254) 
 1295                        throwInvalidColumnType(STR_INVALID_COLUMN_PRECISION, aName); 
 1297                    (*m_pFileStream).WriteUChar( std::min(static_cast<unsigned>(nPrecision), 255U) );      // field length 
 1298                    nRecLength = nRecLength + static_cast<sal_uInt16>(std::min(static_cast<sal_uInt16>(nPrecision), sal_uInt16(255UL))); 
 1299                    (*m_pFileStream).WriteUChar( 0 );                                                                // decimals 
 1303                    OSL_ENSURE(nPrecision >=  nScale, 
 1304                            "ODbaseTable::Create: Field length must be larger than decimal places!
"); 
 1305                    if (nPrecision <  nScale) 
 1307                        throwInvalidColumnType(STR_INVALID_PRECISION_SCALE, aName); 
 1309                    if (getBOOL(xCol->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_ISCURRENCY)))) // Currency will be treated separately 
 1311                        (*m_pFileStream).WriteUChar( 10 );          // standard length 
 1312                        (*m_pFileStream).WriteUChar( 4 ); 
 1317                        sal_Int32 nPrec = SvDbaseConverter::ConvertPrecisionToDbase(nPrecision,nScale); 
 1319                        (*m_pFileStream).WriteUChar( nPrec ); 
 1320                        (*m_pFileStream).WriteUChar( nScale ); 
 1321                        nRecLength += static_cast<sal_uInt16>(nPrec); 
 1325                    (*m_pFileStream).WriteUChar( 1 ); 
 1326                    (*m_pFileStream).WriteUChar( 0 ); 
 1330                    (*m_pFileStream).WriteUChar( 4 ); 
 1331                    (*m_pFileStream).WriteUChar( 0 ); 
 1338                    (*m_pFileStream).WriteUChar( 8 ); 
 1339                    (*m_pFileStream).WriteUChar( 0 ); 
 1344                    (*m_pFileStream).WriteUChar( 10 ); 
 1345                    (*m_pFileStream).WriteUChar( 0 ); 
 1351                    throwInvalidColumnType(STR_INVALID_COLUMN_TYPE, aName); 
 1353            m_pFileStream->WriteBytes(aBuffer, 14); 
 1357        (*m_pFileStream).WriteUChar( FIELD_DESCRIPTOR_TERMINATOR );              // end of header 
 1358        (*m_pFileStream).WriteChar( char(DBF_EOL) ); 
 1359        m_pFileStream->Seek(10); 
 1360        (*m_pFileStream).WriteUInt16( nRecLength );                                     // set record length afterwards 
 1364            m_pFileStream->Seek(0); 
 1365            if (nDbaseType == VisualFoxPro) 
 1366                (*m_pFileStream).WriteUChar( FoxProMemo ); 
 1368                (*m_pFileStream).WriteUChar( dBaseIIIMemo ); 
 1369        } // if (bCreateMemo) 
 1371    catch ( const Exception& ) 
 1375            // we have to drop the file because it is corrupted now 
 1378        catch(const Exception&) { } 
 1384bool ODbaseTable::HasMemoFields() const 
 1386    return m_aHeader.type > dBaseIV && !utl::ConfigManager::IsFuzzing(); 
 1389// creates in principle dBase III file format 
 1390bool ODbaseTable::CreateMemoFile(const INetURLObject& aFile) 
 1392    // filehandling macro for table creation 
 1393    m_pMemoStream = createStream_simpleError( aFile.GetMainURL(INetURLObject::DecodeMechanism::NONE),StreamMode::READWRITE | StreamMode::SHARE_DENYWRITE); 
 1398    m_pMemoStream->SetStreamSize(512); 
 1400    m_pMemoStream->Seek(0); 
 1401    (*m_pMemoStream).WriteUInt32( 1 );                  // pointer to the first free block 
 1403    m_pMemoStream.reset(); 
 1407bool ODbaseTable::Drop_Static(std::u16string_view _sUrl, bool _bHasMemoFields, OCollection* _pIndexes ) 
 1412    bool bDropped = ::utl::UCBContentHelper::Kill(aURL.GetMainURL(INetURLObject::DecodeMechanism::NONE)); 
 1416        if (_bHasMemoFields) 
 1417        {  // delete the memo fields 
 1418            aURL.setExtension(u"dbt
"); 
 1419            bDropped = ::utl::UCBContentHelper::Kill(aURL.GetMainURL(INetURLObject::DecodeMechanism::NONE)); 
 1428                    sal_Int32 i = _pIndexes->getCount(); 
 1431                        _pIndexes->dropByIndex(--i); 
 1434                catch(const SQLException&) 
 1438            aURL.setExtension(u"inf
"); 
 1440            // as the inf file does not necessarily exist, we aren't allowed to use UCBContentHelper::Kill 
 1443                ::ucbhelper::Content aDeleteContent( aURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ), Reference< XCommandEnvironment >(), comphelper::getProcessComponentContext() ); 
 1444                aDeleteContent.executeCommand( "delete", Any( true ) ); 
 1446            catch(const Exception&) 
 1448                // silently ignore this... 
 1455bool ODbaseTable::DropImpl() 
 1460        refreshIndexes(); // look for indexes which must be deleted as well 
 1462    bool bDropped = Drop_Static(getEntry(m_pConnection,m_Name),HasMemoFields(),m_xIndexes.get()); 
 1464    {// we couldn't drop the table so we have to reopen it 
 1467            m_xColumns->refresh(); 
 1473bool ODbaseTable::InsertRow(OValueRefVector& rRow, const Reference<XIndexAccess>& _xCols) 
 1475    // fill buffer with blanks 
 1479    memset(m_pBuffer.get(), 0, m_aHeader.recordLength); 
 1482    // Copy new row completely: 
 1483    // ... and add at the end as new Record: 
 1484    std::size_t nTempPos = m_nFilePos; 
 1486    m_nFilePos = static_cast<std::size_t>(m_aHeader.nbRecords) + 1; 
 1487    bool bInsertRow = UpdateBuffer( rRow, nullptr, _xCols, true ); 
 1490        std::size_t nFileSize = 0, nMemoFileSize = 0; 
 1492        nFileSize = lcl_getFileSize(*m_pFileStream); 
 1494        if (HasMemoFields() && m_pMemoStream) 
 1496            m_pMemoStream->Seek(STREAM_SEEK_TO_END); 
 1497            nMemoFileSize = m_pMemoStream->Tell(); 
 1502            m_pFileStream->SetStreamSize(nFileSize);                // restore old size 
 1504            if (HasMemoFields() && m_pMemoStream) 
 1505                m_pMemoStream->SetStreamSize(nMemoFileSize);    // restore old size 
 1506            m_nFilePos = nTempPos;              // restore file position 
 1510            (*m_pFileStream).WriteChar( char(DBF_EOL) ); // write EOL 
 1511            // raise number of datasets in the header: 
 1512            m_pFileStream->Seek( 4 ); 
 1513            (*m_pFileStream).WriteUInt32( m_aHeader.nbRecords + 1 ); 
 1515            m_pFileStream->Flush(); 
 1517            // raise number if successfully 
 1518            m_aHeader.nbRecords++; 
 1519            *rRow[0] = m_nFilePos;                                // set bookmark 
 1520            m_nFilePos = nTempPos; 
 1524        m_nFilePos = nTempPos; 
 1530bool ODbaseTable::UpdateRow(OValueRefVector& rRow, OValueRefRow& pOrgRow, const Reference<XIndexAccess>& _xCols) 
 1532    // fill buffer with blanks 
 1536    // position on desired record: 
 1537    std::size_t nPos = m_aHeader.headerLength + static_cast<tools::Long>(m_nFilePos-1) * m_aHeader.recordLength; 
 1538    m_pFileStream->Seek(nPos); 
 1539    m_pFileStream->ReadBytes(m_pBuffer.get(), m_aHeader.recordLength); 
 1541    std::size_t nMemoFileSize( 0 ); 
 1542    if (HasMemoFields() && m_pMemoStream) 
 1544        m_pMemoStream->Seek(STREAM_SEEK_TO_END); 
 1545        nMemoFileSize = m_pMemoStream->Tell(); 
 1547    if (!UpdateBuffer(rRow, pOrgRow, _xCols, false) || !WriteBuffer()) 
 1549        if (HasMemoFields() && m_pMemoStream) 
 1550            m_pMemoStream->SetStreamSize(nMemoFileSize);    // restore old size 
 1554        m_pFileStream->Flush(); 
 1560bool ODbaseTable::DeleteRow(const OSQLColumns& _rCols) 
 1562    // Set the Delete-Flag (be it set or not): 
 1563    // Position on desired record: 
 1564    std::size_t nFilePos = m_aHeader.headerLength + static_cast<tools::Long>(m_nFilePos-1) * m_aHeader.recordLength; 
 1565    m_pFileStream->Seek(nFilePos); 
 1567    OValueRefRow aRow = new OValueRefVector(_rCols.size()); 
 1569    if (!fetchRow(aRow,_rCols,true)) 
 1572    Reference<XPropertySet> xCol; 
 1574    ::comphelper::UStringMixEqual aCase(isCaseSensitive()); 
 1575    for (sal_Int32 i = 0; i < m_xColumns->getCount(); i++) 
 1577        Reference<XPropertySet> xIndex = isUniqueByColumnName(i); 
 1580            xCol.set(m_xColumns->getByIndex(i), css::uno::UNO_QUERY); 
 1584                xCol->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_NAME)) >>= aColName; 
 1586                ODbaseIndex* pIndex = dynamic_cast<ODbaseIndex*>(xIndex.get()); 
 1589                OSQLColumns::const_iterator aIter = std::find_if(_rCols.begin(), _rCols.end(), 
 1590                    [&aCase, &aColName](const OSQLColumns::value_type& rxCol) { 
 1591                        return aCase(getString(rxCol->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_REALNAME))), aColName); }); 
 1592                if (aIter == _rCols.end()) 
 1595                auto nPos = static_cast<sal_Int32>(std::distance(_rCols.begin(), aIter)) + 1; 
 1596                pIndex->Delete(m_nFilePos,*(*aRow)[nPos]); 
 1601    m_pFileStream->Seek(nFilePos); 
 1602    (*m_pFileStream).WriteUChar( '*' ); // mark the row in the table as deleted 
 1603    m_pFileStream->Flush(); 
 1607Reference<XPropertySet> ODbaseTable::isUniqueByColumnName(sal_Int32 _nColumnPos) 
 1611    if(m_xIndexes->hasElements()) 
 1613        Reference<XPropertySet> xCol; 
 1614        m_xColumns->getByIndex(_nColumnPos) >>= xCol; 
 1617        xCol->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_NAME)) >>= sColName; 
 1619        Reference<XPropertySet> xIndex; 
 1620        for(sal_Int32 i=0;i<m_xIndexes->getCount();++i) 
 1622            xIndex.set(m_xIndexes->getByIndex(i), css::uno::UNO_QUERY); 
 1623            if(xIndex.is() && getBOOL(xIndex->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_ISUNIQUE)))) 
 1625                Reference<XNameAccess> xCols(Reference<XColumnsSupplier>(xIndex,UNO_QUERY_THROW)->getColumns()); 
 1626                if(xCols->hasByName(sColName)) 
 1632    return Reference<XPropertySet>(); 
 1635static double toDouble(std::string_view rString) 
 1637    return ::rtl::math::stringToDouble( rString, '.', ',' ); 
 1641bool ODbaseTable::UpdateBuffer(OValueRefVector& rRow, const OValueRefRow& pOrgRow, const Reference<XIndexAccess>& _xCols, const bool bForceAllFields) 
 1643    OSL_ENSURE(m_pBuffer,"Buffer is NULL!
"); 
 1646    sal_Int32 nByteOffset  = 1; 
 1649    Reference<XPropertySet> xCol; 
 1650    Reference<XPropertySet> xIndex; 
 1652    const sal_Int32 nColumnCount = m_xColumns->getCount(); 
 1653    std::vector< Reference<XPropertySet> > aIndexedCols(nColumnCount); 
 1655    ::comphelper::UStringMixEqual aCase(isCaseSensitive()); 
 1657    Reference<XIndexAccess> xColumns(m_xColumns.get()); 
 1658    // first search a key that exist already in the table 
 1659    for (sal_Int32 i = 0; i < nColumnCount; ++i) 
 1662        if(_xCols != xColumns) 
 1664            m_xColumns->getByIndex(i) >>= xCol; 
 1666            xCol->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_NAME)) >>= aColName; 
 1668            for(nPos = 0;nPos<_xCols->getCount();++nPos) 
 1670                Reference<XPropertySet> xFindCol( 
 1671                    _xCols->getByIndex(nPos), css::uno::UNO_QUERY); 
 1673                if(aCase(getString(xFindCol->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_NAME))),aColName)) 
 1676            if (nPos >= _xCols->getCount()) 
 1681        xIndex = isUniqueByColumnName(i); 
 1682        aIndexedCols[i] = xIndex; 
 1685            // first check if the value is different to the old one and when if it conform to the index 
 1686            if(pOrgRow.is() && (rRow[nPos]->getValue().isNull() || rRow[nPos] == (*pOrgRow)[nPos])) 
 1690                ODbaseIndex* pIndex = dynamic_cast<ODbaseIndex*>(xIndex.get()); 
 1693                if (pIndex->Find(0,*rRow[nPos])) 
 1695                    // There is no unique value 
 1696                    if ( aColName.isEmpty() ) 
 1698                        m_xColumns->getByIndex(i) >>= xCol; 
 1700                        xCol->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_NAME)) >>= aColName; 
 1702                    } // if ( !aColName.getLength() ) 
 1703                    const OUString sError( getConnection()->getResources().getResourceStringWithSubstitution( 
 1704                            STR_DUPLICATE_VALUE_IN_COLUMN 
 1705                            ,"$columnname$
", aColName 
 1707                    ::dbtools::throwGenericSQLException( sError, *this ); 
 1713    // when we are here there is no double key in the table 
 1715    for (sal_Int32 i = 0; i < nColumnCount && nByteOffset <= m_nBufferSize ; ++i) 
 1717        // Lengths for each data type: 
 1719        OSL_ENSURE(o3tl::make_unsigned(i) < m_aPrecisions.size(),"Illegal index!
"); 
 1721        sal_Int32 nType = 0; 
 1722        sal_Int32 nScale = 0; 
 1723        if ( o3tl::make_unsigned(i) < m_aPrecisions.size() ) 
 1725            nLen    = m_aPrecisions[i]; 
 1726            nType   = m_aTypes[i]; 
 1727            nScale  = m_aScales[i]; 
 1731            m_xColumns->getByIndex(i) >>= xCol; 
 1734                xCol->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_PRECISION)) >>= nLen; 
 1735                xCol->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_TYPE))      >>= nType; 
 1736                xCol->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_SCALE))     >>= nScale; 
 1740        bool bSetZero = false; 
 1743            case DataType::INTEGER: 
 1744            case DataType::DOUBLE: 
 1745            case DataType::TIMESTAMP: 
 1748            case DataType::LONGVARBINARY: 
 1749            case DataType::DATE: 
 1751            case DataType::LONGVARCHAR: 
 1752                nLen = m_aRealFieldLengths[i]; 
 1754            case DataType::DECIMAL: 
 1755                nLen = SvDbaseConverter::ConvertPrecisionToDbase(nLen,nScale); 
 1756                break;  // The sign and the comma 
 1763        if(_xCols != xColumns) 
 1765            m_xColumns->getByIndex(i) >>= xCol; 
 1767            xCol->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_NAME)) >>= aColName; 
 1768            for(nPos = 0;nPos<_xCols->getCount();++nPos) 
 1770                Reference<XPropertySet> xFindCol( 
 1771                    _xCols->getByIndex(nPos), css::uno::UNO_QUERY); 
 1772                if(aCase(getString(xFindCol->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_NAME))),aColName)) 
 1775            if (nPos >= _xCols->getCount()) 
 1777                nByteOffset += nLen; 
 1783        ++nPos; // the row values start at 1 
 1784        const ORowSetValue &thisColVal = rRow[nPos]->get(); 
 1785        const bool thisColIsBound = thisColVal.isBound(); 
 1786        const bool thisColIsNull = !thisColIsBound || thisColVal.isNull(); 
 1787        // don't overwrite non-bound columns 
 1788        if ( ! (bForceAllFields || thisColIsBound) ) 
 1790            // No - don't overwrite this field, it has not changed. 
 1791            nByteOffset += nLen; 
 1794        if (aIndexedCols[i].is()) 
 1796            ODbaseIndex* pIndex = dynamic_cast<ODbaseIndex*>(aIndexedCols[i].get()); 
 1799            if (pOrgRow.is() && !thisColIsNull) 
 1800                pIndex->Update(m_nFilePos, *(*pOrgRow)[nPos], thisColVal); 
 1802                pIndex->Insert(m_nFilePos, thisColVal); 
 1805        char* pData = reinterpret_cast<char *>(m_pBuffer.get() + nByteOffset); 
 1809                memset(pData,0,nLen);   // Clear to NULL char ('\0') 
 1811                memset(pData,' ',nLen); // Clear to space/blank ('\0x20') 
 1812            nByteOffset += nLen; 
 1813            OSL_ENSURE( nByteOffset <= m_nBufferSize ,"ByteOffset > 
m_nBufferSize!
"); 
 1821                case DataType::TIMESTAMP: 
 1823                        sal_Int32 nJulianDate = 0, nJulianTime = 0; 
 1824                        lcl_CalcJulDate(nJulianDate,nJulianTime, thisColVal.getDateTime()); 
 1825                        // Exactly 8 bytes to copy: 
 1826                        memcpy(pData,&nJulianDate,4); 
 1827                        memcpy(pData+4,&nJulianTime,4); 
 1830                case DataType::DATE: 
 1832                    css::util::Date aDate; 
 1833                    if(thisColVal.getTypeKind() == DataType::DOUBLE) 
 1834                        aDate = ::dbtools::DBTypeConversion::toDate(thisColVal.getDouble()); 
 1836                        aDate = thisColVal.getDate(); 
 1837                    char s[sizeof("-327686553565535
")]; 
 1838                        // reserve enough space for hypothetical max length 
 1841                        "%04
" SAL_PRIdINT32 "%02
" SAL_PRIuUINT32 "%02
" SAL_PRIuUINT32, 
 1842                        static_cast<sal_Int32>(aDate.Year), 
 1843                        static_cast<sal_uInt32>(aDate.Month), 
 1844                        static_cast<sal_uInt32>(aDate.Day)); 
 1846                    // Exactly 8 bytes to copy (even if s could hypothetically be longer): 
 1849                case DataType::INTEGER: 
 1851                        sal_Int32 nValue = thisColVal.getInt32(); 
 1852                        if (o3tl::make_unsigned(nLen) > sizeof(nValue)) 
 1854                        memcpy(pData,&nValue,nLen); 
 1857                case DataType::DOUBLE: 
 1859                        const double d = thisColVal.getDouble(); 
 1860                        m_xColumns->getByIndex(i) >>= xCol; 
 1862                        if (getBOOL(xCol->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_ISCURRENCY)))) // Currency is treated separately 
 1864                            sal_Int64 nValue = 0; 
 1866                                nValue = static_cast<sal_Int64>(d * pow(10.0,static_cast<int>(m_aScales[i]))); 
 1868                                nValue = static_cast<sal_Int64>(d); 
 1869                            if (o3tl::make_unsigned(nLen) > sizeof(nValue)) 
 1871                            memcpy(pData,&nValue,nLen); 
 1872                        } // if (getBOOL(xCol->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_ISCURRENCY)))) // Currency is treated separately 
 1875                            if (o3tl::make_unsigned(nLen) > sizeof(d)) 
 1877                            memcpy(pData,&d,nLen); 
 1881                case DataType::DECIMAL: 
 1883                    memset(pData,' ',nLen); // Clear to NULL 
 1885                    const double n = thisColVal.getDouble(); 
 1887                    // one, because const_cast GetFormatPrecision on SvNumberFormat is not constant, 
 1888                    // even though it really could and should be 
 1889                    const OString aDefaultValue( ::rtl::math::doubleToString( n, rtl_math_StringFormat_F, nScale, '.', nullptr, 0)); 
 1890                    const sal_Int32 nValueLen = aDefaultValue.getLength(); 
 1891                    if ( nValueLen <= nLen ) 
 1893                        // Write value right-justified, padded with blanks to the left. 
 1894                        memcpy(pData+nLen-nValueLen,aDefaultValue.getStr(),nValueLen); 
 1895                        // write the resulting double back 
 1896                        *rRow[nPos] = toDouble(aDefaultValue); 
 1900                        m_xColumns->getByIndex(i) >>= xCol; 
 1902                        xCol->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_NAME)) >>= aColName; 
 1903                        std::vector< std::pair<const char* , OUString > > aStringToSubstitutes 
 1905                            { "$columnname$
", aColName }, 
 1906                            { "$precision$
", OUString::number(nLen) }, 
 1907                            { "$scale$
", OUString::number(nScale) }, 
 1908                            { "$value$
", OStringToOUString(aDefaultValue,RTL_TEXTENCODING_UTF8) } 
 1911                        const OUString sError( getConnection()->getResources().getResourceStringWithSubstitution( 
 1912                                STR_INVALID_COLUMN_DECIMAL_VALUE 
 1913                                ,aStringToSubstitutes 
 1915                        ::dbtools::throwGenericSQLException( sError, *this ); 
 1919                    *pData = thisColVal.getBool() ? 'T' : 'F'; 
 1921                case DataType::LONGVARBINARY: 
 1922                case DataType::LONGVARCHAR: 
 1924                    char cNext = pData[nLen]; // Mark's scratch and replaced by 0 
 1925                    pData[nLen] = '\0';       // This is because the buffer is always a sign of greater ... 
 1927                    std::size_t nBlockNo = strtol(pData,nullptr,10); // Block number read 
 1929                    // Next initial character restore again: 
 1930                    pData[nLen] = cNext; 
 1933                    WriteMemo(thisColVal, nBlockNo); 
 1935                    OString aBlock(OString::number(nBlockNo)); 
 1936                    //align aBlock at the right of a nLen sequence, fill to the left with '0' 
 1938                    comphelper::string::padToLength(aStr, nLen - aBlock.getLength(), '0'); 
 1939                    aStr.append(aBlock); 
 1942                    memcpy(pData, aStr.getStr(), nLen); 
 1946                    memset(pData,' ',nLen); // Clear to NULL 
 1948                    OUString sStringToWrite( thisColVal.getString() ); 
 1950                    // convert the string, using the connection's encoding 
 1953                    DBTypeConversion::convertUnicodeStringToLength( sStringToWrite, sEncoded, nLen, m_eEncoding ); 
 1954                    memcpy( pData, sEncoded.getStr(), sEncoded.getLength() ); 
 1960        catch( const SQLException&  ) 
 1964        catch ( const Exception& ) 
 1966            m_xColumns->getByIndex(i) >>= xCol; 
 1969                xCol->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_NAME)) >>= aColName; 
 1971            const OUString sError( getConnection()->getResources().getResourceStringWithSubstitution( 
 1972                    STR_INVALID_COLUMN_VALUE, 
 1973                    "$columnname$
", aColName 
 1975            ::dbtools::throwGenericSQLException( sError, *this ); 
 1978        nByteOffset += nLen; 
 1979        OSL_ENSURE( nByteOffset <= m_nBufferSize ,"ByteOffset > 
m_nBufferSize!
"); 
 1985void ODbaseTable::WriteMemo(const ORowSetValue& aVariable, std::size_t& rBlockNr) 
 1987    // if the BlockNo 0 is given, the block will be appended at the end 
 1988    std::size_t nSize = 0; 
 1990    css::uno::Sequence<sal_Int8> aValue; 
 1991    sal_uInt8 nHeader[4]; 
 1992    const bool bBinary = aVariable.getTypeKind() == DataType::LONGVARBINARY && m_aMemoHeader.db_typ == MemoFoxPro; 
 1995        aValue = aVariable.getSequence(); 
 1996        nSize = aValue.getLength(); 
 2000        nSize = DBTypeConversion::convertUnicodeString( aVariable.getString(), aStr, m_eEncoding ); 
 2003    // append or overwrite 
 2004    bool bAppend = rBlockNr == 0; 
 2008        switch (m_aMemoHeader.db_typ) 
 2010            case MemodBaseIII: // dBase III-Memofield, ends with 2 * Ctrl-Z 
 2011                bAppend = nSize > (512 - 2); 
 2014            case MemodBaseIV: // dBase IV-Memofield with length 
 2017                m_pMemoStream->Seek(rBlockNr * m_aMemoHeader.db_size); 
 2018                m_pMemoStream->SeekRel(4); 
 2019                m_pMemoStream->ReadBytes(sHeader, 4); 
 2021                std::size_t nOldSize; 
 2022                if (m_aMemoHeader.db_typ == MemoFoxPro) 
 2023                    nOldSize = ((static_cast<unsigned char>(sHeader[0]) * 256 + 
 2024                                 static_cast<unsigned char>(sHeader[1])) * 256 + 
 2025                                 static_cast<unsigned char>(sHeader[2])) * 256 + 
 2026                                 static_cast<unsigned char>(sHeader[3]); 
 2028                    nOldSize = ((static_cast<unsigned char>(sHeader[3]) * 256 + 
 2029                                 static_cast<unsigned char>(sHeader[2])) * 256 + 
 2030                                 static_cast<unsigned char>(sHeader[1])) * 256 + 
 2031                                 static_cast<unsigned char>(sHeader[0])  - 8; 
 2033                // fits the new length in the used blocks 
 2034                std::size_t nUsedBlocks = ((nSize + 8) / m_aMemoHeader.db_size) + (((nSize + 8) % m_aMemoHeader.db_size > 0) ? 1 : 0), 
 2035                      nOldUsedBlocks = ((nOldSize + 8) / m_aMemoHeader.db_size) + (((nOldSize + 8) % m_aMemoHeader.db_size > 0) ? 1 : 0); 
 2036                bAppend = nUsedBlocks > nOldUsedBlocks; 
 2043        sal_uInt64 const nStreamSize = m_pMemoStream->TellEnd(); 
 2045        rBlockNr = (nStreamSize / m_aMemoHeader.db_size) + ((nStreamSize % m_aMemoHeader.db_size) > 0 ? 1 : 0); 
 2047        m_pMemoStream->SetStreamSize(rBlockNr * m_aMemoHeader.db_size); 
 2048        m_pMemoStream->Seek(STREAM_SEEK_TO_END); 
 2052        m_pMemoStream->Seek(rBlockNr * m_aMemoHeader.db_size); 
 2055    switch (m_aMemoHeader.db_typ) 
 2057        case MemodBaseIII: // dBase III-Memofield, ends with Ctrl-Z 
 2059            const char cEOF = char(DBF_EOL); 
 2061            m_pMemoStream->WriteBytes(aStr.getStr(), aStr.getLength()); 
 2062            m_pMemoStream->WriteChar( cEOF ).WriteChar( cEOF ); 
 2065        case MemodBaseIV: // dBase IV-Memofield with length 
 2067            if ( MemodBaseIV == m_aMemoHeader.db_typ ) 
 2068                (*m_pMemoStream).WriteUChar( 0xFF ) 
 2070                                .WriteUChar( 0x08 ); 
 2072                (*m_pMemoStream).WriteUChar( 0x00 ) 
 2074                                .WriteUChar( 0x00 ); 
 2076            sal_uInt32 nWriteSize = nSize; 
 2077            if (m_aMemoHeader.db_typ == MemoFoxPro) 
 2080                    (*m_pMemoStream).WriteUChar( 0x00 ); // Picture 
 2082                    (*m_pMemoStream).WriteUChar( 0x01 ); // Memo 
 2083                for (int i = 4; i > 0; nWriteSize >>= 8) 
 2084                    nHeader[--i] = static_cast<sal_uInt8>(nWriteSize % 256); 
 2088                (*m_pMemoStream).WriteUChar( 0x00 ); 
 2090                for (int i = 0; i < 4; nWriteSize >>= 8) 
 2091                    nHeader[i++] = static_cast<sal_uInt8>(nWriteSize % 256); 
 2094            m_pMemoStream->WriteBytes(nHeader, 4); 
 2096                m_pMemoStream->WriteBytes(aValue.getConstArray(), aValue.getLength()); 
 2098                m_pMemoStream->WriteBytes(aStr.getStr(), aStr.getLength()); 
 2099            m_pMemoStream->Flush(); 
 2104    // Write the new block number 
 2107        sal_uInt64 const nStreamSize = m_pMemoStream->TellEnd(); 
 2108        m_aMemoHeader.db_next = (nStreamSize / m_aMemoHeader.db_size) + ((nStreamSize % m_aMemoHeader.db_size) > 0 ? 1 : 0); 
 2110        // Write the new block number 
 2111        m_pMemoStream->Seek(0); 
 2112        (*m_pMemoStream).WriteUInt32( m_aMemoHeader.db_next ); 
 2113        m_pMemoStream->Flush(); 
 2119void SAL_CALL ODbaseTable::alterColumnByName( const OUString& colName, const Reference< XPropertySet >& descriptor ) 
 2121    ::osl::MutexGuard aGuard(m_aMutex); 
 2122    checkDisposed(OTableDescriptor_BASE::rBHelper.bDisposed); 
 2125    Reference<XDataDescriptorFactory> xOldColumn; 
 2126    m_xColumns->getByName(colName) >>= xOldColumn; 
 2130        alterColumn(m_xColumns->findColumn(colName)-1,descriptor,xOldColumn); 
 2132    catch (const css::lang::IndexOutOfBoundsException&) 
 2134        throw NoSuchElementException(colName, *this); 
 2138void SAL_CALL ODbaseTable::alterColumnByIndex( sal_Int32 index, const Reference< XPropertySet >& descriptor ) 
 2140    ::osl::MutexGuard aGuard(m_aMutex); 
 2141    checkDisposed(OTableDescriptor_BASE::rBHelper.bDisposed); 
 2143    if(index < 0 || index >= m_xColumns->getCount()) 
 2144        throw IndexOutOfBoundsException(OUString::number(index),*this); 
 2146    Reference<XDataDescriptorFactory> xOldColumn; 
 2147    m_xColumns->getByIndex(index) >>= xOldColumn; 
 2148    alterColumn(index,descriptor,xOldColumn); 
 2151void ODbaseTable::alterColumn(sal_Int32 index, 
 2152                              const Reference< XPropertySet >& descriptor , 
 2153                              const Reference< XDataDescriptorFactory >& xOldColumn ) 
 2155    if(index < 0 || index >= m_xColumns->getCount()) 
 2156        throw IndexOutOfBoundsException(OUString::number(index),*this); 
 2161        // creates a copy of the original column and copy all properties from descriptor in xCopyColumn 
 2162        Reference<XPropertySet> xCopyColumn; 
 2164            xCopyColumn = xOldColumn->createDataDescriptor(); 
 2166            xCopyColumn = new OColumn(getConnection()->getMetaData()->supportsMixedCaseQuotedIdentifiers()); 
 2168        ::comphelper::copyProperties(descriptor,xCopyColumn); 
 2170        // creates a temp file 
 2172        OUString sTempName = createTempFile(); 
 2174        rtl::Reference<ODbaseTable> pNewTable = new ODbaseTable(m_pTables,static_cast<ODbaseConnection*>(m_pConnection)); 
 2175        Reference<XPropertySet> xHoldTable = pNewTable; 
 2176        pNewTable->setPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_NAME),Any(sTempName)); 
 2177        Reference<XAppend> xAppend(pNewTable->getColumns(),UNO_QUERY); 
 2180        // copy the structure 
 2184            Reference<XPropertySet> xProp; 
 2185            m_xColumns->getByIndex(i) >>= xProp; 
 2186            Reference<XDataDescriptorFactory> xColumn(xProp,UNO_QUERY); 
 2187            Reference<XPropertySet> xCpy; 
 2189                xCpy = xColumn->createDataDescriptor(); 
 2191                xCpy = new OColumn(getConnection()->getMetaData()->supportsMixedCaseQuotedIdentifiers()); 
 2192            ::comphelper::copyProperties(xProp,xCpy); 
 2193            xAppend->appendByDescriptor(xCpy); 
 2195        ++i; // now insert our new column 
 2196        xAppend->appendByDescriptor(xCopyColumn); 
 2198        for(;i < m_xColumns->getCount();++i) 
 2200            Reference<XPropertySet> xProp; 
 2201            m_xColumns->getByIndex(i) >>= xProp; 
 2202            Reference<XDataDescriptorFactory> xColumn(xProp,UNO_QUERY); 
 2203            Reference<XPropertySet> xCpy; 
 2205                xCpy = xColumn->createDataDescriptor(); 
 2207                xCpy = new OColumn(getConnection()->getMetaData()->supportsMixedCaseQuotedIdentifiers()); 
 2208            ::comphelper::copyProperties(xProp,xCpy); 
 2209            xAppend->appendByDescriptor(xCpy); 
 2212        // construct the new table 
 2213        if(!pNewTable->CreateImpl()) 
 2215            const OUString sError( getConnection()->getResources().getResourceStringWithSubstitution( 
 2216                    STR_COLUMN_NOT_ALTERABLE, 
 2217                    "$columnname$
", ::comphelper::getString(descriptor->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_NAME))) 
 2219            ::dbtools::throwGenericSQLException( sError, *this ); 
 2222        pNewTable->construct(); 
 2225        copyData(pNewTable.get(),0); 
 2227        // now drop the old one 
 2228        if( DropImpl() ) // we don't want to delete the memo columns too 
 2232                // rename the new one to the old one 
 2233                pNewTable->renameImpl(m_Name); 
 2235            catch(const css::container::ElementExistException&) 
 2237                const OUString sError( getConnection()->getResources().getResourceStringWithSubstitution( 
 2238                        STR_COULD_NOT_DELETE_FILE, 
 2239                        "$filename$
", m_Name 
 2241                ::dbtools::throwGenericSQLException( sError, *this ); 
 2243            // release the temp file 
 2244            pNewTable = nullptr; 
 2245            ::comphelper::disposeComponent(xHoldTable); 
 2249            pNewTable = nullptr; 
 2254            m_xColumns->refresh(); 
 2257    catch(const SQLException&) 
 2261    catch(const Exception&) 
 2268Reference< XDatabaseMetaData> ODbaseTable::getMetaData() const 
 2270    return getConnection()->getMetaData(); 
 2273void SAL_CALL ODbaseTable::rename( const OUString& newName ) 
 2275    ::osl::MutexGuard aGuard(m_aMutex); 
 2276    checkDisposed(OTableDescriptor_BASE::rBHelper.bDisposed); 
 2277    if(m_pTables && m_pTables->hasByName(newName)) 
 2278        throw ElementExistException(newName,*this); 
 2281    renameImpl(newName); 
 2283    ODbaseTable_BASE::rename(newName); 
 2287        m_xColumns->refresh(); 
 2291    void renameFile(file::OConnection const * _pConnection,std::u16string_view oldName, 
 2292                    const OUString& newName, std::u16string_view _sExtension) 
 2294        OUString aName = ODbaseTable::getEntry(_pConnection,oldName); 
 2297            OUString aIdent = _pConnection->getContent()->getIdentifier()->getContentIdentifier(); 
 2298            if ( aIdent.lastIndexOf('/') != (aIdent.getLength()-1) ) 
 2306        aURL.setExtension( _sExtension ); 
 2307        OUString sNewName(newName + ".
" + _sExtension); 
 2311            Content aContent(aURL.GetMainURL(INetURLObject::DecodeMechanism::NONE),Reference<XCommandEnvironment>(), comphelper::getProcessComponentContext()); 
 2313            Sequence< PropertyValue > aProps{ { "Title
", 
 2316                                                css::beans::PropertyState_DIRECT_VALUE } }; 
 2317            Sequence< Any > aValues; 
 2318            aContent.executeCommand( "setPropertyValues
",Any(aProps) ) >>= aValues; 
 2319            if(aValues.hasElements() && aValues[0].hasValue()) 
 2320                throw Exception("setPropertyValues returned non-zero
", nullptr); 
 2322        catch(const Exception&) 
 2324            throw ElementExistException(newName); 
 2329void ODbaseTable::renameImpl( const OUString& newName ) 
 2331    ::osl::MutexGuard aGuard(m_aMutex); 
 2336    renameFile(m_pConnection,m_Name,newName,m_pConnection->getExtension()); 
 2337    if ( HasMemoFields() ) 
 2338    {  // delete the memo fields 
 2339        renameFile(m_pConnection,m_Name,newName,u"dbt
"); 
 2343void ODbaseTable::addColumn(const Reference< XPropertySet >& _xNewColumn) 
 2345    OUString sTempName = createTempFile(); 
 2347    rtl::Reference xNewTable(new ODbaseTable(m_pTables,static_cast<ODbaseConnection*>(m_pConnection))); 
 2348    xNewTable->setPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_NAME),Any(sTempName)); 
 2350        Reference<XAppend> xAppend(xNewTable->getColumns(),UNO_QUERY); 
 2351        bool bCase = getConnection()->getMetaData()->supportsMixedCaseQuotedIdentifiers(); 
 2352        // copy the structure 
 2353        for(sal_Int32 i=0;i < m_xColumns->getCount();++i) 
 2355            Reference<XPropertySet> xProp; 
 2356            m_xColumns->getByIndex(i) >>= xProp; 
 2357            Reference<XDataDescriptorFactory> xColumn(xProp,UNO_QUERY); 
 2358            Reference<XPropertySet> xCpy; 
 2360                xCpy = xColumn->createDataDescriptor(); 
 2363                xCpy = new OColumn(bCase); 
 2364                ::comphelper::copyProperties(xProp,xCpy); 
 2367            xAppend->appendByDescriptor(xCpy); 
 2369        Reference<XPropertySet> xCpy = new OColumn(bCase); 
 2370        ::comphelper::copyProperties(_xNewColumn,xCpy); 
 2371        xAppend->appendByDescriptor(xCpy); 
 2374    // construct the new table 
 2375    if(!xNewTable->CreateImpl()) 
 2377        const OUString sError( getConnection()->getResources().getResourceStringWithSubstitution( 
 2378                STR_COLUMN_NOT_ADDABLE, 
 2379                "$columnname$
", ::comphelper::getString(_xNewColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_NAME))) 
 2381        ::dbtools::throwGenericSQLException( sError, *this ); 
 2384    xNewTable->construct(); 
 2386    copyData(xNewTable.get(),xNewTable->m_xColumns->getCount()); 
 2387    // drop the old table 
 2390        xNewTable->renameImpl(m_Name); 
 2391        // release the temp file 
 2398        m_xColumns->refresh(); 
 2401void ODbaseTable::dropColumn(sal_Int32 _nPos) 
 2403    OUString sTempName = createTempFile(); 
 2405    rtl::Reference xNewTable(new ODbaseTable(m_pTables,static_cast<ODbaseConnection*>(m_pConnection))); 
 2406    xNewTable->setPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_NAME),Any(sTempName)); 
 2408        Reference<XAppend> xAppend(xNewTable->getColumns(),UNO_QUERY); 
 2409        bool bCase = getConnection()->getMetaData()->supportsMixedCaseQuotedIdentifiers(); 
 2410        // copy the structure 
 2411        for(sal_Int32 i=0;i < m_xColumns->getCount();++i) 
 2415                Reference<XPropertySet> xProp; 
 2416                m_xColumns->getByIndex(i) >>= xProp; 
 2417                Reference<XDataDescriptorFactory> xColumn(xProp,UNO_QUERY); 
 2418                Reference<XPropertySet> xCpy; 
 2420                    xCpy = xColumn->createDataDescriptor(); 
 2423                    xCpy = new OColumn(bCase); 
 2424                    ::comphelper::copyProperties(xProp,xCpy); 
 2426                xAppend->appendByDescriptor(xCpy); 
 2431    // construct the new table 
 2432    if(!xNewTable->CreateImpl()) 
 2434        const OUString sError( getConnection()->getResources().getResourceStringWithSubstitution( 
 2435                STR_COLUMN_NOT_DROP, 
 2436                "$position$
", OUString::number(_nPos) 
 2438        ::dbtools::throwGenericSQLException( sError, *this ); 
 2440    xNewTable->construct(); 
 2442    copyData(xNewTable.get(),_nPos); 
 2443    // drop the old table 
 2445        xNewTable->renameImpl(m_Name); 
 2446        // release the temp file 
 2454OUString ODbaseTable::createTempFile() 
 2456    OUString aIdent = m_pConnection->getContent()->getIdentifier()->getContentIdentifier(); 
 2457    if ( aIdent.lastIndexOf('/') != (aIdent.getLength()-1) ) 
 2460    OUString sExt(".
" + m_pConnection->getExtension()); 
 2461    OUString aTempFileURL = utl::CreateTempURL(m_Name, true, sExt, &aIdent); 
 2462    if(aTempFileURL.isEmpty()) 
 2463        getConnection()->throwGenericSQLException(STR_COULD_NOT_ALTER_TABLE, *this); 
 2466    aURL.SetSmartProtocol(INetProtocol::File); 
 2467    aURL.SetURL(aTempFileURL); 
 2469    OUString sNewName(aURL.getName().copy(0, aURL.getName().getLength() - sExt.getLength())); 
 2474void ODbaseTable::copyData(ODbaseTable* _pNewTable,sal_Int32 _nPos) 
 2476    sal_Int32 nPos = _nPos + 1; // +1 because we always have the bookmark column as well 
 2477    OValueRefRow aRow = new OValueRefVector(m_xColumns->getCount()); 
 2478    OValueRefRow aInsertRow; 
 2481        aInsertRow = new OValueRefVector(_pNewTable->m_xColumns->getCount()); 
 2482        std::for_each(aInsertRow->begin(),aInsertRow->end(),TSetRefBound(true)); 
 2487    // we only have to bind the values which we need to copy into the new table 
 2488    std::for_each(aRow->begin(),aRow->end(),TSetRefBound(true)); 
 2489    if(_nPos && (_nPos < static_cast<sal_Int32>(aRow->size()))) 
 2490        (*aRow)[nPos]->setBound(false); 
 2494    OValueRefVector::const_iterator aIter; 
 2495    for(sal_uInt32 nRowPos = 0; nRowPos < m_aHeader.nbRecords;++nRowPos) 
 2497        bool bOk = seekRow( IResultSetHelper::BOOKMARK, nRowPos+1, nCurPos ); 
 2500            bOk = fetchRow( aRow, *m_aColumns, true); 
 2501            if ( bOk && !aRow->isDeleted() ) // copy only not deleted rows 
 2503                // special handling when pos == 0 then we don't have to distinguish between the two rows 
 2506                    aIter = aRow->begin()+1; 
 2507                    sal_Int32 nCount = 1; 
 2508                    for(OValueRefVector::iterator aInsertIter = aInsertRow->begin()+1; aIter != aRow->end() && aInsertIter != aInsertRow->end();++aIter,++nCount) 
 2512                            (*aInsertIter)->setValue( (*aIter)->getValue() ); 
 2517                bOk = _pNewTable->InsertRow(*aInsertRow, _pNewTable->m_xColumns.get()); 
 2518                SAL_WARN_IF(!bOk, "connectivity.drivers
", "Row could not be inserted!
"); 
 2522                SAL_WARN_IF(!bOk, "connectivity.drivers
", "Row could not be fetched!
"); 
 2529    } // for(sal_uInt32 nRowPos = 0; nRowPos < m_aHeader.db_anz;++nRowPos) 
 2532void ODbaseTable::throwInvalidDbaseFormat() 
 2537    const OUString sError( getConnection()->getResources().getResourceStringWithSubstitution( 
 2538                STR_INVALID_DBASE_FILE, 
 2539                "$filename$
", getEntry(m_pConnection,m_Name) 
 2541    ::dbtools::throwGenericSQLException( sError, *this ); 
 2544void ODbaseTable::refreshHeader() 
 2546    if ( m_aHeader.nbRecords == 0 ) 
 2550bool ODbaseTable::seekRow(IResultSetHelper::Movement eCursorPosition, sal_Int32 nOffset, sal_Int32& nCurPos) 
 2552    // prepare positioning: 
 2555    sal_uInt32  nNumberOfRecords = m_aHeader.nbRecords; 
 2556    sal_uInt32 nTempPos = m_nFilePos; 
 2557    m_nFilePos = nCurPos; 
 2559    switch(eCursorPosition) 
 2561        case IResultSetHelper::NEXT: 
 2564        case IResultSetHelper::PRIOR: 
 2568        case IResultSetHelper::FIRST: 
 2571        case IResultSetHelper::LAST: 
 2572            m_nFilePos = nNumberOfRecords; 
 2574        case IResultSetHelper::RELATIVE1: 
 2575            m_nFilePos = (m_nFilePos + nOffset < 0) ? 0 
 2576                            : static_cast<sal_uInt32>(m_nFilePos + nOffset); 
 2578        case IResultSetHelper::ABSOLUTE1: 
 2579        case IResultSetHelper::BOOKMARK: 
 2580            m_nFilePos = static_cast<sal_uInt32>(nOffset); 
 2584    if (m_nFilePos > static_cast<sal_Int32>(nNumberOfRecords)) 
 2585        m_nFilePos = static_cast<sal_Int32>(nNumberOfRecords) + 1; 
 2587    if (m_nFilePos == 0 || m_nFilePos == static_cast<sal_Int32>(nNumberOfRecords) + 1) 
 2591        std::size_t nEntryLen = m_aHeader.recordLength; 
 2593        OSL_ENSURE(m_nFilePos >= 1,"SdbDBFCursor::FileFetchRow: invalid record position
"); 
 2594        std::size_t nPos = m_aHeader.headerLength + static_cast<std::size_t>(m_nFilePos-1) * nEntryLen; 
 2596        m_pFileStream->Seek(nPos); 
 2597        if (m_pFileStream->GetError() != ERRCODE_NONE) 
 2600        std::size_t nRead = m_pFileStream->ReadBytes(m_pBuffer.get(), nEntryLen); 
 2601        if (nRead != nEntryLen) 
 2606        if (m_pFileStream->GetError() != ERRCODE_NONE) 
 2612    switch(eCursorPosition) 
 2614        case IResultSetHelper::PRIOR: 
 2615        case IResultSetHelper::FIRST: 
 2618        case IResultSetHelper::LAST: 
 2619        case IResultSetHelper::NEXT: 
 2620        case IResultSetHelper::ABSOLUTE1: 
 2621        case IResultSetHelper::RELATIVE1: 
 2623                m_nFilePos = nNumberOfRecords + 1; 
 2624            else if (nOffset < 0) 
 2627        case IResultSetHelper::BOOKMARK: 
 2628            m_nFilePos = nTempPos;   // last position 
 2633    nCurPos = m_nFilePos; 
 2637bool ODbaseTable::ReadMemo(std::size_t nBlockNo, ORowSetValue& aVariable) 
 2639    m_pMemoStream->Seek(nBlockNo * m_aMemoHeader.db_size); 
 2640    switch (m_aMemoHeader.db_typ) 
 2642        case MemodBaseIII: // dBase III-Memofield, ends with Ctrl-Z 
 2644            const char cEOF = char(DBF_EOL); 
 2645            OStringBuffer aBStr; 
 2646            static char aBuf[514]; 
 2647            aBuf[512] = 0;          // avoid random value 
 2648            bool bReady = false; 
 2652                m_pMemoStream->ReadBytes(&aBuf, 512); 
 2655                while (aBuf[i] != cEOF && ++i < 512) 
 2657                bReady = aBuf[i] == cEOF; 
 2662            } while (!bReady && !m_pMemoStream->eof()); 
 2664            aVariable = OStringToOUString(aBStr, 
 2669        case MemodBaseIV: // dBase IV-Memofield with length 
 2671            bool bIsText = true; 
 2673            m_pMemoStream->ReadBytes(sHeader, 4); 
 2674            // Foxpro stores text and binary data 
 2675            if (m_aMemoHeader.db_typ == MemoFoxPro) 
 2677                bIsText = sHeader[3] != 0; 
 2679            else if (static_cast<sal_uInt8>(sHeader[0]) != 0xFF || static_cast<sal_uInt8>(sHeader[1]) != 0xFF || static_cast<sal_uInt8>(sHeader[2]) != 0x08) 
 2684            sal_uInt32 nLength(0); 
 2685            (*m_pMemoStream).ReadUInt32( nLength ); 
 2687            if (m_aMemoHeader.db_typ == MemodBaseIV) 
 2694                    OStringBuffer aBuffer(read_uInt8s_ToOString(*m_pMemoStream, nLength)); 
 2695                    //pad it out with ' ' to expected length on short read 
 2696                    sal_Int32 nRequested = sal::static_int_cast<sal_Int32>(nLength); 
 2697                    comphelper::string::padToLength(aBuffer, nRequested, ' '); 
 2698                    aVariable = OStringToOUString(aBuffer, m_eEncoding); 
 2702                    css::uno::Sequence< sal_Int8 > aData(nLength); 
 2703                    m_pMemoStream->ReadBytes(aData.getArray(), nLength); 
 2712bool ODbaseTable::AllocBuffer() 
 2714    sal_uInt16 nSize = m_aHeader.recordLength; 
 2717    if (m_nBufferSize != nSize) 
 2722    // if there is no buffer available: allocate: 
 2723    if (!m_pBuffer && nSize > 0) 
 2725        m_nBufferSize = nSize; 
 2726        m_pBuffer.reset(new sal_uInt8[m_nBufferSize+1]); 
 2729    return m_pBuffer != nullptr; 
 2732bool ODbaseTable::WriteBuffer() 
 2734    OSL_ENSURE(m_nFilePos >= 1,"SdbDBFCursor::FileFetchRow: invalid record position
"); 
 2736    // position on desired record: 
 2737    std::size_t nPos = m_aHeader.headerLength + static_cast<tools::Long>(m_nFilePos-1) * m_aHeader.recordLength; 
 2738    m_pFileStream->Seek(nPos); 
 2739    return m_pFileStream->WriteBytes(m_pBuffer.get(), m_aHeader.recordLength) > 0; 
 2742sal_Int32 ODbaseTable::getCurrentLastPos() const 
 2744    return m_aHeader.nbRecords; 
 2747/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ 
constexpr OStringLiteral dBASE_III_GROUP
 
#define FIELD_DESCRIPTOR_TERMINATOR
 
css::uno::Sequence< sal_Int8 > Buffer
 
OString GetKeyName(sal_uInt16 nKey) const
 
void SetGroup(const OString &rGroup)
 
sal_uInt16 GetKeyCount() const
 
OString ReadKey(const OString &rKey) const
 
static SVL_DLLPUBLIC sal_Int32 ConvertPrecisionToOdbc(sal_Int32 _nLen, sal_Int32 _nScale)
 
static SVL_DLLPUBLIC sal_Int32 ConvertPrecisionToDbase(sal_Int32 _nLen, sal_Int32 _nScale)
 
SvStream & ReadChar(char &rChar)
 
sal_uInt64 Seek(sal_uInt64 nPos)
 
sal_uInt64 SeekRel(sal_Int64 nPos)
 
rtl_TextEncoding m_eEncoding
 
virtual bool seekRow(IResultSetHelper::Movement eCursorPosition, sal_Int32 nOffset, sal_Int32 &nCurPos) override
 
virtual css::uno::Any SAL_CALL queryInterface(const css::uno::Type &rType) override
 
virtual void refreshColumns() override
 
std::vector< sal_Int32 > m_aScales
 
virtual void SAL_CALL disposing() override
 
void construct() override
 
DBFMemoHeader m_aMemoHeader
 
ODbaseTable(sdbcx::OCollection *_pTables, ODbaseConnection *_pConnection)
 
std::vector< sal_Int32 > m_aRealFieldLengths
 
css::uno::Reference< css::beans::XPropertySet > isUniqueByColumnName(sal_Int32 _nColumnPos)
 
std::vector< sal_Int32 > m_aPrecisions
 
std::vector< sal_Int32 > m_aTypes
 
void throwInvalidDbaseFormat()
 
virtual bool DeleteRow(const OSQLColumns &_rCols) override
 
static OUString getEntry(file::OConnection const *_pConnection, std::u16string_view _sURL)
 
std::unique_ptr< SvStream > m_pMemoStream
 
void alterColumn(sal_Int32 index, const css::uno::Reference< css::beans::XPropertySet > &descriptor, const css::uno::Reference< css::sdbcx::XDataDescriptorFactory > &xOldColumn)
 
bool HasMemoFields() const
 
bool UpdateBuffer(OValueRefVector &rRow, const OValueRefRow &pOrgRow, const css::uno::Reference< css::container::XIndexAccess > &_xCols, bool bForceAllFields)
 
virtual css::uno::Sequence< css::uno::Type > SAL_CALL getTypes() override
 
virtual void refreshIndexes() override
 
virtual bool fetchRow(OValueRefRow &_rRow, const OSQLColumns &_rCols, bool bRetrieveData) override
 
bool matchesExtension(const OUString &_rExt) const
 
virtual css::uno::Reference< css::sdbc::XDatabaseMetaData > SAL_CALL getMetaData() override
 
css::uno::Reference< css::ucb::XDynamicResultSet > getDir() const
 
bool isTextEncodingDefaulted() const
 
OConnection * m_pConnection
 
const OUString & getSchema() const
 
OUString SAL_CALL getName() override
 
static std::unique_ptr< SvStream > createStream_simpleError(const OUString &_rFileName, StreamMode _eOpenMode)
 
::rtl::Reference< OSQLColumns > m_aColumns
 
std::unique_ptr< sal_uInt8[]> m_pBuffer
 
std::unique_ptr< SvStream > m_pFileStream
 
OConnection * getConnection() const
 
std::unique_ptr< OCollection > m_xIndexes
 
std::unique_ptr< OCollection > m_xColumns
 
virtual css::uno::Sequence< css::uno::Type > SAL_CALL getTypes() override
 
virtual css::uno::Any SAL_CALL queryInterface(const css::uno::Type &rType) override
 
mutable::osl::Mutex m_aMutex
 
#define SAL_WARN(area, stream)
 
#define SAL_INFO(area, stream)
 
if(aStr !=aBuf) UpdateName_Impl(m_xFollowLb.get()
 
Reference< XComponentContext > getProcessComponentContext()
 
bool dbfDecodeCharset(rtl_TextEncoding &_out_encoding, sal_uInt8 nType, sal_uInt8 nCodepage)
decode a DBase file's codepage byte to a RTL charset
 
ORefVector< css::uno::Reference< css::beans::XPropertySet > > OSQLColumns
 
constexpr double monthDaysWithoutJanFeb
 
constexpr std::enable_if_t< std::is_signed_v< T >, std::make_unsigned_t< T > > make_unsigned(T value)
 
#define STREAM_SEEK_TO_END
 
#define STREAM_SEEK_TO_BEGIN
 
TOOLS_DLLPUBLIC bool checkSeek(SvStream &rSt, sal_uInt64 nOffset)