Bug Summary

File:home/maarten/src/libreoffice/core/connectivity/source/drivers/dbase/DTable.cxx
Warning:line 2541, column 16
Assigned value is garbage or undefined

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name DTable.cxx -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -mframe-pointer=all -fmath-errno -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib64/clang/11.0.0 -D BOOST_ERROR_CODE_HEADER_ONLY -D BOOST_SYSTEM_NO_DEPRECATED -D CPPU_ENV=gcc3 -D LINUX -D OSL_DEBUG_LEVEL=1 -D SAL_LOG_INFO -D SAL_LOG_WARN -D UNIX -D UNX -D X86_64 -D _PTHREADS -D _REENTRANT -D EXCEPTIONS_ON -D LIBO_INTERNAL_ONLY -I /home/maarten/src/libreoffice/core/external/boost/include -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/boost -I /home/maarten/src/libreoffice/core/include -I /usr/lib/jvm/java-11-openjdk-11.0.9.10-0.0.ea.fc33.x86_64/include -I /usr/lib/jvm/java-11-openjdk-11.0.9.10-0.0.ea.fc33.x86_64/include/linux -I /home/maarten/src/libreoffice/core/config_host -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/udkapi/normal -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/offapi/normal -I /home/maarten/src/libreoffice/core/connectivity/inc -I /home/maarten/src/libreoffice/core/connectivity/source/inc -I /home/maarten/src/libreoffice/core/workdir/YaccTarget/connectivity/source/parse -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10 -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10/x86_64-redhat-linux -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10/backward -internal-isystem /usr/local/include -internal-isystem /usr/lib64/clang/11.0.0/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O0 -Wno-missing-braces -std=c++17 -fdeprecated-macro -fdebug-compilation-dir /home/maarten/src/libreoffice/core -ferror-limit 19 -fvisibility hidden -fvisibility-inlines-hidden -stack-protector 2 -fgnuc-version=4.2.1 -fcxx-exceptions -fexceptions -debug-info-kind=constructor -analyzer-output=html -faddrsig -o /home/maarten/tmp/wis/scan-build-libreoffice/output/report/2020-10-07-141433-9725-1 -x c++ /home/maarten/src/libreoffice/core/connectivity/source/drivers/dbase/DTable.cxx
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20#include <dbase/DTable.hxx>
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>
26#include <o3tl/safeint.hxx>
27#include <svl/converter.hxx>
28#include <dbase/DConnection.hxx>
29#include <dbase/DColumns.hxx>
30#include <tools/config.hxx>
31#include <tools/diagnose_ex.h>
32#include <dbase/DIndex.hxx>
33#include <dbase/DIndexes.hxx>
34#include <comphelper/processfactory.hxx>
35#include <rtl/math.hxx>
36#include <ucbhelper/content.hxx>
37#include <com/sun/star/ucb/ContentCreationException.hpp>
38#include <connectivity/dbexception.hxx>
39#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
40#include <comphelper/property.hxx>
41#include <comphelper/servicehelper.hxx>
42#include <comphelper/string.hxx>
43#include <unotools/tempfile.hxx>
44#include <unotools/ucbhelper.hxx>
45#include <comphelper/types.hxx>
46#include <cppuhelper/typeprovider.hxx>
47#include <cppuhelper/exc_hlp.hxx>
48#include <cppuhelper/queryinterface.hxx>
49#include <connectivity/dbtools.hxx>
50#include <connectivity/FValue.hxx>
51#include <connectivity/dbconversion.hxx>
52#include <connectivity/sdbcx/VColumn.hxx>
53#include <strings.hrc>
54#include <rtl/strbuf.hxx>
55#include <sal/log.hxx>
56#include <tools/date.hxx>
57
58#include <algorithm>
59#include <cassert>
60#include <memory>
61
62using namespace ::comphelper;
63using namespace connectivity;
64using namespace connectivity::sdbcx;
65using namespace connectivity::dbase;
66using namespace connectivity::file;
67using namespace ::ucbhelper;
68using namespace ::utl;
69using namespace ::cppu;
70using namespace ::dbtools;
71using namespace ::com::sun::star::uno;
72using namespace ::com::sun::star::ucb;
73using namespace ::com::sun::star::beans;
74using namespace ::com::sun::star::sdbcx;
75using namespace ::com::sun::star::sdbc;
76using namespace ::com::sun::star::container;
77using namespace ::com::sun::star::lang;
78using namespace ::com::sun::star::i18n;
79
80// stored as the Field Descriptor terminator
81#define FIELD_DESCRIPTOR_TERMINATOR0x0D 0x0D
82#define DBF_EOL0x1A 0x1A
83
84namespace
85{
86std::size_t lcl_getFileSize(SvStream& _rStream)
87{
88 std::size_t nFileSize = 0;
89 _rStream.Seek(STREAM_SEEK_TO_END((sal_uInt64) 0xFFFFFFFFFFFFFFFFul));
90 _rStream.SeekRel(-1);
91 char cEOL;
92 _rStream.ReadChar( cEOL );
93 nFileSize = _rStream.Tell();
94 if ( cEOL == DBF_EOL0x1A )
95 nFileSize -= 1;
96 return nFileSize;
97}
98/**
99 calculates the Julian date
100*/
101void lcl_CalcJulDate(sal_Int32& _nJulianDate,sal_Int32& _nJulianTime, const css::util::DateTime& rDateTime)
102{
103 css::util::DateTime aDateTime = rDateTime;
104 // weird: months fix
105 if (aDateTime.Month > 12)
106 {
107 aDateTime.Month--;
108 sal_uInt16 delta = rDateTime.Month / 12;
109 aDateTime.Year += delta;
110 aDateTime.Month -= delta * 12;
111 aDateTime.Month++;
112 }
113
114 _nJulianTime = ((aDateTime.Hours*3600000)+(aDateTime.Minutes*60000)+(aDateTime.Seconds*1000)+(aDateTime.NanoSeconds/1000000));
115 /* conversion factors */
116 sal_uInt16 iy0;
117 sal_uInt16 im0;
118 if ( aDateTime.Month <= 2 )
119 {
120 iy0 = aDateTime.Year - 1;
121 im0 = aDateTime.Month + 12;
122 }
123 else
124 {
125 iy0 = aDateTime.Year;
126 im0 = aDateTime.Month;
127 }
128 sal_Int32 ia = iy0 / 100;
129 sal_Int32 ib = 2 - ia + (ia >> 2);
130 /* calculate julian date */
131 if ( aDateTime.Year <= 0 )
132 {
133 _nJulianDate = static_cast<sal_Int32>((365.25 * iy0) - 0.75)
134 + static_cast<sal_Int32>(30.6001 * (im0 + 1) )
135 + aDateTime.Day + 1720994;
136 } // if ( rDateTime.Year <= 0 )
137 else
138 {
139 _nJulianDate = static_cast<sal_Int32>(365.25 * iy0)
140 + static_cast<sal_Int32>(30.6001 * (im0 + 1))
141 + aDateTime.Day + 1720994;
142 }
143 double JD = _nJulianDate + 0.5;
144 _nJulianDate = static_cast<sal_Int32>( JD + 0.5);
145 const double gyr = aDateTime.Year + (0.01 * aDateTime.Month) + (0.0001 * aDateTime.Day);
146 if ( gyr >= 1582.1015 ) /* on or after 15 October 1582 */
147 _nJulianDate += ib;
148}
149
150/**
151 calculates date time from the Julian Date
152*/
153void lcl_CalDate(sal_Int32 _nJulianDate,sal_Int32 _nJulianTime,css::util::DateTime& _rDateTime)
154{
155 if ( _nJulianDate )
156 {
157 sal_Int32 ka = _nJulianDate;
158 if ( _nJulianDate >= 2299161 )
159 {
160 sal_Int32 ialp = static_cast<sal_Int32>( (static_cast<double>(_nJulianDate) - 1867216.25 ) / 36524.25 );
161 ka = _nJulianDate + 1 + ialp - ( ialp >> 2 );
162 }
163 sal_Int32 kb = ka + 1524;
164 sal_Int32 kc = static_cast<sal_Int32>( (static_cast<double>(kb) - 122.1 ) / 365.25 );
165 sal_Int32 kd = static_cast<sal_Int32>(static_cast<double>(kc) * 365.25);
166 sal_Int32 ke = static_cast<sal_Int32>(static_cast<double>( kb - kd ) / 30.6001 );
167 _rDateTime.Day = static_cast<sal_uInt16>(kb - kd - static_cast<sal_Int32>( static_cast<double>(ke) * 30.6001 ));
168 if ( ke > 13 )
169 _rDateTime.Month = static_cast<sal_uInt16>(ke - 13);
170 else
171 _rDateTime.Month = static_cast<sal_uInt16>(ke - 1);
172 if ( (_rDateTime.Month == 2) && (_rDateTime.Day > 28) )
173 _rDateTime.Day = 29;
174 if ( (_rDateTime.Month == 2) && (_rDateTime.Day == 29) && (ke == 3) )
175 _rDateTime.Year = static_cast<sal_uInt16>(kc - 4716);
176 else if ( _rDateTime.Month > 2 )
177 _rDateTime.Year = static_cast<sal_uInt16>(kc - 4716);
178 else
179 _rDateTime.Year = static_cast<sal_uInt16>(kc - 4715);
180 }
181
182 if ( _nJulianTime )
183 {
184 double d_s = _nJulianTime / 1000.0;
185 double d_m = d_s / 60.0;
186 double d_h = d_m / 60.0;
187 _rDateTime.Hours = static_cast<sal_uInt16>(d_h);
188 _rDateTime.Minutes = static_cast<sal_uInt16>((d_h - static_cast<double>(_rDateTime.Hours)) * 60.0);
189 _rDateTime.Seconds = static_cast<sal_uInt16>(((d_m - static_cast<double>(_rDateTime.Minutes)) * 60.0)
190 - (static_cast<double>(_rDateTime.Hours) * 3600.0));
191 }
192}
193
194}
195
196
197void ODbaseTable::readHeader()
198{
199 OSL_ENSURE(m_pFileStream,"No Stream available!")do { if (true && (!(m_pFileStream))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/connectivity/source/drivers/dbase/DTable.cxx"
":" "199" ": "), "%s", "No Stream available!"); } } while (false
)
;
200 if(!m_pFileStream)
201 return;
202 m_pFileStream->RefreshBuffer(); // Make sure, that the header information actually is read again
203 m_pFileStream->Seek(STREAM_SEEK_TO_BEGIN0L);
204
205 sal_uInt8 nType=0;
206 m_pFileStream->ReadUChar( nType );
207 if(ERRCODE_NONEErrCode(0) != m_pFileStream->GetErrorCode())
208 throwInvalidDbaseFormat();
209
210 m_pFileStream->ReadBytes(m_aHeader.dateElems, 3);
211 if(ERRCODE_NONEErrCode(0) != m_pFileStream->GetErrorCode())
212 throwInvalidDbaseFormat();
213
214 m_pFileStream->ReadUInt32( m_aHeader.nbRecords);
215 if(ERRCODE_NONEErrCode(0) != m_pFileStream->GetErrorCode())
216 throwInvalidDbaseFormat();
217
218 m_pFileStream->ReadUInt16( m_aHeader.headerLength);
219 if(ERRCODE_NONEErrCode(0) != m_pFileStream->GetErrorCode())
220 throwInvalidDbaseFormat();
221
222 m_pFileStream->ReadUInt16( m_aHeader.recordLength);
223 if(ERRCODE_NONEErrCode(0) != m_pFileStream->GetErrorCode())
224 throwInvalidDbaseFormat();
225 if (m_aHeader.recordLength == 0)
226 throwInvalidDbaseFormat();
227
228 m_pFileStream->ReadBytes(m_aHeader.trailer, 20);
229 if(ERRCODE_NONEErrCode(0) != m_pFileStream->GetErrorCode())
230 throwInvalidDbaseFormat();
231
232
233 if ( ( ( m_aHeader.headerLength - 1 ) / 32 - 1 ) <= 0 ) // number of fields
234 {
235 // no dBASE file
236 throwInvalidDbaseFormat();
237 }
238 else
239 {
240 // Consistency check of the header:
241 m_aHeader.type = static_cast<DBFType>(nType);
242 switch (m_aHeader.type)
243 {
244 case dBaseIII:
245 case dBaseIV:
246 case dBaseV:
247 case VisualFoxPro:
248 case VisualFoxProAuto:
249 case dBaseFS:
250 case dBaseFSMemo:
251 case dBaseIVMemoSQL:
252 case dBaseIIIMemo:
253 case FoxProMemo:
254 m_pFileStream->SetEndian(SvStreamEndian::LITTLE);
255 if( getConnection()->isTextEncodingDefaulted() &&
256 !dbfDecodeCharset(m_eEncoding, nType, m_aHeader.trailer[17]))
257 {
258 m_eEncoding = RTL_TEXTENCODING_IBM_850(((rtl_TextEncoding) 4));
259 }
260 break;
261 case dBaseIVMemo:
262 m_pFileStream->SetEndian(SvStreamEndian::LITTLE);
263 break;
264 default:
265 {
266 throwInvalidDbaseFormat();
267 }
268 }
269 }
270}
271
272void ODbaseTable::fillColumns()
273{
274 m_pFileStream->Seek(STREAM_SEEK_TO_BEGIN0L);
275 m_pFileStream->Seek(32);
276
277 if(!m_aColumns.is())
278 m_aColumns = new OSQLColumns();
279 else
280 m_aColumns->clear();
281
282 m_aTypes.clear();
283 m_aPrecisions.clear();
284 m_aScales.clear();
285
286 // Number of fields:
287 const sal_Int32 nFieldCount = (m_aHeader.headerLength - 1) / 32 - 1;
288 OSL_ENSURE(nFieldCount,"No columns in table!")do { if (true && (!(nFieldCount))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/connectivity/source/drivers/dbase/DTable.cxx"
":" "288" ": "), "%s", "No columns in table!"); } } while (false
)
;
289
290 m_aColumns->reserve(nFieldCount);
291 m_aTypes.reserve(nFieldCount);
292 m_aPrecisions.reserve(nFieldCount);
293 m_aScales.reserve(nFieldCount);
294
295 OUString aTypeName;
296 const bool bCase = getConnection()->getMetaData()->supportsMixedCaseQuotedIdentifiers();
297 const bool bFoxPro = m_aHeader.type == VisualFoxPro || m_aHeader.type == VisualFoxProAuto || m_aHeader.type == FoxProMemo;
298
299 sal_Int32 i = 0;
300 for (; i < nFieldCount; i++)
301 {
302 DBFColumn aDBFColumn;
303#if !defined(NDEBUG)
304 sal_uInt64 const nOldPos(m_pFileStream->Tell());
305#endif
306 m_pFileStream->ReadBytes(aDBFColumn.db_fnm, 11);
307 m_pFileStream->ReadUChar(aDBFColumn.db_typ);
308 m_pFileStream->ReadUInt32(aDBFColumn.db_adr);
309 m_pFileStream->ReadUChar(aDBFColumn.db_flng);
310 m_pFileStream->ReadUChar(aDBFColumn.db_dez);
311 m_pFileStream->ReadBytes(aDBFColumn.db_free2, 14);
312 assert(m_pFileStream->GetError() || m_pFileStream->Tell() == nOldPos + sizeof(aDBFColumn))(static_cast <bool> (m_pFileStream->GetError() || m_pFileStream
->Tell() == nOldPos + sizeof(aDBFColumn)) ? void (0) : __assert_fail
("m_pFileStream->GetError() || m_pFileStream->Tell() == nOldPos + sizeof(aDBFColumn)"
, "/home/maarten/src/libreoffice/core/connectivity/source/drivers/dbase/DTable.cxx"
, 312, __extension__ __PRETTY_FUNCTION__))
;
313 if (m_pFileStream->GetError())
314 {
315 SAL_WARN("connectivity.drivers", "ODbaseTable::fillColumns: short read!")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "connectivity.drivers")) { case SAL_DETAIL_LOG_ACTION_IGNORE
: break; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail
::getResult( ::sal::detail::StreamStart() << "ODbaseTable::fillColumns: short read!"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("connectivity.drivers"
), ("/home/maarten/src/libreoffice/core/connectivity/source/drivers/dbase/DTable.cxx"
":" "315" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "ODbaseTable::fillColumns: short read!"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "ODbaseTable::fillColumns: short read!"; ::sal::detail
::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("connectivity.drivers"
), ("/home/maarten/src/libreoffice/core/connectivity/source/drivers/dbase/DTable.cxx"
":" "315" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "ODbaseTable::fillColumns: short read!") == 1) { ::
sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("connectivity.drivers"
), ("/home/maarten/src/libreoffice/core/connectivity/source/drivers/dbase/DTable.cxx"
":" "315" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "ODbaseTable::fillColumns: short read!"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "ODbaseTable::fillColumns: short read!"; ::sal::detail
::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("connectivity.drivers"
), ("/home/maarten/src/libreoffice/core/connectivity/source/drivers/dbase/DTable.cxx"
":" "315" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
316 break;
317 }
318 if ( FIELD_DESCRIPTOR_TERMINATOR0x0D == aDBFColumn.db_fnm[0] ) // 0x0D stored as the Field Descriptor terminator.
319 break;
320
321 aDBFColumn.db_fnm[sizeof(aDBFColumn.db_fnm)-1] = 0; //ensure null termination for broken input
322 const OUString aColumnName(reinterpret_cast<char *>(aDBFColumn.db_fnm), strlen(reinterpret_cast<char *>(aDBFColumn.db_fnm)), m_eEncoding);
323
324 bool bIsRowVersion = bFoxPro && ( aDBFColumn.db_free2[0] & 0x01 ) == 0x01;
325
326 m_aRealFieldLengths.push_back(aDBFColumn.db_flng);
327 sal_Int32 nPrecision = aDBFColumn.db_flng;
328 sal_Int32 eType;
329 bool bIsCurrency = false;
330
331 char cType[2];
332 cType[0] = aDBFColumn.db_typ;
333 cType[1] = 0;
334 aTypeName = OUString(cType, 1, RTL_TEXTENCODING_ASCII_US(((rtl_TextEncoding) 11)));
335 SAL_INFO( "connectivity.drivers","column type: " << aDBFColumn.db_typ)do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO
, "connectivity.drivers")) { case SAL_DETAIL_LOG_ACTION_IGNORE
: break; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail
::getResult( ::sal::detail::StreamStart() << "column type: "
<< aDBFColumn.db_typ) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("connectivity.drivers"), ("/home/maarten/src/libreoffice/core/connectivity/source/drivers/dbase/DTable.cxx"
":" "335" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "column type: " << aDBFColumn.db_typ
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "column type: " << aDBFColumn.db_typ; ::sal::
detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("connectivity.drivers"
), ("/home/maarten/src/libreoffice/core/connectivity/source/drivers/dbase/DTable.cxx"
":" "335" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "column type: " << aDBFColumn.db_typ) == 1)
{ ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("connectivity.drivers"
), ("/home/maarten/src/libreoffice/core/connectivity/source/drivers/dbase/DTable.cxx"
":" "335" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "column type: " << aDBFColumn.db_typ
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "column type: " << aDBFColumn.db_typ; ::sal::
detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("connectivity.drivers"
), ("/home/maarten/src/libreoffice/core/connectivity/source/drivers/dbase/DTable.cxx"
":" "335" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
336
337 switch (aDBFColumn.db_typ)
338 {
339 case 'C':
340 eType = DataType::VARCHAR;
341 aTypeName = "VARCHAR";
342 break;
343 case 'F':
344 case 'N':
345 aTypeName = "DECIMAL";
346 if ( aDBFColumn.db_typ == 'N' )
347 aTypeName = "NUMERIC";
348 eType = DataType::DECIMAL;
349
350 // for numeric fields two characters more are written, then the precision of the column description predescribes,
351 // to keep room for the possible sign and the comma. This has to be considered...
352 nPrecision = SvDbaseConverter::ConvertPrecisionToOdbc(nPrecision,aDBFColumn.db_dez);
353 // This is not true for older versions...
354 break;
355 case 'L':
356 eType = DataType::BIT;
357 aTypeName = "BOOLEAN";
358 break;
359 case 'Y':
360 bIsCurrency = true;
361 eType = DataType::DOUBLE;
362 aTypeName = "DOUBLE";
363 break;
364 case 'D':
365 eType = DataType::DATE;
366 aTypeName = "DATE";
367 break;
368 case 'T':
369 eType = DataType::TIMESTAMP;
370 aTypeName = "TIMESTAMP";
371 break;
372 case 'I':
373 eType = DataType::INTEGER;
374 aTypeName = "INTEGER";
375 break;
376 case 'M':
377 if ( bFoxPro && ( aDBFColumn.db_free2[0] & 0x04 ) == 0x04 )
378 {
379 eType = DataType::LONGVARBINARY;
380 aTypeName = "LONGVARBINARY";
381 }
382 else
383 {
384 aTypeName = "LONGVARCHAR";
385 eType = DataType::LONGVARCHAR;
386 }
387 nPrecision = 2147483647;
388 break;
389 case 'P':
390 aTypeName = "LONGVARBINARY";
391 eType = DataType::LONGVARBINARY;
392 nPrecision = 2147483647;
393 break;
394 case '0':
395 case 'B':
396 if ( m_aHeader.type == VisualFoxPro || m_aHeader.type == VisualFoxProAuto )
397 {
398 aTypeName = "DOUBLE";
399 eType = DataType::DOUBLE;
400 }
401 else
402 {
403 aTypeName = "LONGVARBINARY";
404 eType = DataType::LONGVARBINARY;
405 nPrecision = 2147483647;
406 }
407 break;
408 default:
409 eType = DataType::OTHER;
410 }
411
412 m_aTypes.push_back(eType);
413 m_aPrecisions.push_back(nPrecision);
414 m_aScales.push_back(aDBFColumn.db_dez);
415
416 Reference< XPropertySet> xCol = new sdbcx::OColumn(aColumnName,
417 aTypeName,
418 OUString(),
419 OUString(),
420 ColumnValue::NULLABLE,
421 nPrecision,
422 aDBFColumn.db_dez,
423 eType,
424 false,
425 bIsRowVersion,
426 bIsCurrency,
427 bCase,
428 m_CatalogName, getSchema(), getName());
429 m_aColumns->push_back(xCol);
430 } // for (; i < nFieldCount; i++)
431 OSL_ENSURE(i,"No columns in table!")do { if (true && (!(i))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/connectivity/source/drivers/dbase/DTable.cxx"
":" "431" ": "), "%s", "No columns in table!"); } } while (false
)
;
432}
433
434ODbaseTable::ODbaseTable(sdbcx::OCollection* _pTables, ODbaseConnection* _pConnection)
435 : ODbaseTable_BASE(_pTables,_pConnection)
436{
437 // initialize the header
438 m_aHeader.type = dBaseIII;
439 m_eEncoding = getConnection()->getTextEncoding();
440}
441
442ODbaseTable::ODbaseTable(sdbcx::OCollection* _pTables, ODbaseConnection* _pConnection,
443 const OUString& Name,
444 const OUString& Type,
445 const OUString& Description ,
446 const OUString& SchemaName,
447 const OUString& CatalogName )
448 : ODbaseTable_BASE(_pTables,_pConnection,Name,
449 Type,
450 Description,
451 SchemaName,
452 CatalogName)
453{
454 m_eEncoding = getConnection()->getTextEncoding();
455}
456
457
458void ODbaseTable::construct()
459{
460 // initialize the header
461 m_aHeader.type = dBaseIII;
462 m_aHeader.nbRecords = 0;
463 m_aHeader.headerLength = 0;
464 m_aHeader.recordLength = 0;
465 m_aMemoHeader.db_size = 0;
466
467 OUString sFileName(getEntry(m_pConnection, m_Name));
468
469 INetURLObject aURL;
470 aURL.SetURL(sFileName);
471
472 OSL_ENSURE( m_pConnection->matchesExtension( aURL.getExtension() ),do { if (true && (!(m_pConnection->matchesExtension
( aURL.getExtension() )))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/connectivity/source/drivers/dbase/DTable.cxx"
":" "473" ": "), "%s", "ODbaseTable::ODbaseTable: invalid extension!"
); } } while (false)
473 "ODbaseTable::ODbaseTable: invalid extension!")do { if (true && (!(m_pConnection->matchesExtension
( aURL.getExtension() )))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/connectivity/source/drivers/dbase/DTable.cxx"
":" "473" ": "), "%s", "ODbaseTable::ODbaseTable: invalid extension!"
); } } while (false)
;
474 // getEntry is expected to ensure the correct file name
475
476 m_pFileStream = createStream_simpleError( sFileName, StreamMode::READWRITE | StreamMode::NOCREATE | StreamMode::SHARE_DENYWRITE);
477 m_bWriteable = ( m_pFileStream != nullptr );
478
479 if ( !m_pFileStream )
480 {
481 m_bWriteable = false;
482 m_pFileStream = createStream_simpleError( sFileName, StreamMode::READ | StreamMode::NOCREATE | StreamMode::SHARE_DENYNONE);
483 }
484
485 if(!m_pFileStream)
486 return;
487
488 readHeader();
489 if (HasMemoFields())
490 {
491 // Create Memo-Filename (.DBT):
492 // nyi: Ugly for Unix and Mac!
493
494 if ( m_aHeader.type == FoxProMemo || m_aHeader.type == VisualFoxPro || m_aHeader.type == VisualFoxProAuto) // foxpro uses another extension
495 aURL.SetExtension("fpt");
496 else
497 aURL.SetExtension("dbt");
498
499 // If the memo file isn't found, the data will be displayed anyhow.
500 // However, updates can't be done
501 // but the operation is executed
502 m_pMemoStream = createStream_simpleError( aURL.GetMainURL(INetURLObject::DecodeMechanism::NONE), StreamMode::READWRITE | StreamMode::NOCREATE | StreamMode::SHARE_DENYWRITE);
503 if ( !m_pMemoStream )
504 {
505 m_pMemoStream = createStream_simpleError( aURL.GetMainURL(INetURLObject::DecodeMechanism::NONE), StreamMode::READ | StreamMode::NOCREATE | StreamMode::SHARE_DENYNONE);
506 }
507 if (m_pMemoStream)
508 ReadMemoHeader();
509 }
510 fillColumns();
511
512 std::size_t nFileSize = lcl_getFileSize(*m_pFileStream);
513 m_pFileStream->Seek(STREAM_SEEK_TO_BEGIN0L);
514 // seems to be empty or someone wrote bullshit into the dbase file
515 // try and recover if m_aHeader.db_slng is sane
516 if (m_aHeader.nbRecords == 0 && m_aHeader.recordLength)
517 {
518 std::size_t nRecords = (nFileSize-m_aHeader.headerLength)/m_aHeader.recordLength;
519 if (nRecords > 0)
520 m_aHeader.nbRecords = nRecords;
521 }
522
523 // Buffersize dependent on the file size
524 m_pFileStream->SetBufferSize(nFileSize > 1000000 ? 32768 :
525 nFileSize > 100000 ? 16384 :
526 nFileSize > 10000 ? 4096 : 1024);
527
528 if (m_pMemoStream)
529 {
530 // set the buffer exactly to the length of a record
531 nFileSize = m_pMemoStream->TellEnd();
532 m_pMemoStream->Seek(STREAM_SEEK_TO_BEGIN0L);
533
534 // Buffersize dependent on the file size
535 m_pMemoStream->SetBufferSize(nFileSize > 1000000 ? 32768 :
536 nFileSize > 100000 ? 16384 :
537 nFileSize > 10000 ? 4096 :
538 m_aMemoHeader.db_size);
539 }
540
541 AllocBuffer();
542}
543
544void ODbaseTable::ReadMemoHeader()
545{
546 m_pMemoStream->SetEndian(SvStreamEndian::LITTLE);
547 m_pMemoStream->RefreshBuffer(); // make sure that the header information is actually read again
548 m_pMemoStream->Seek(0);
549
550 (*m_pMemoStream).ReadUInt32( m_aMemoHeader.db_next );
551 switch (m_aHeader.type)
552 {
553 case dBaseIIIMemo: // dBase III: fixed block size
554 case dBaseIVMemo:
555 // sometimes dBase3 is attached to dBase4 memo
556 m_pMemoStream->Seek(20);
557 (*m_pMemoStream).ReadUInt16( m_aMemoHeader.db_size );
558 if (m_aMemoHeader.db_size > 1 && m_aMemoHeader.db_size != 512) // 1 is also for dBase 3
559 m_aMemoHeader.db_typ = MemodBaseIV;
560 else if (m_aMemoHeader.db_size == 512)
561 {
562 // There are files using size specification, though they are dBase-files
563 char sHeader[4];
564 m_pMemoStream->Seek(m_aMemoHeader.db_size);
565 m_pMemoStream->ReadBytes(sHeader, 4);
566
567 if ((m_pMemoStream->GetErrorCode() != ERRCODE_NONEErrCode(0)) || static_cast<sal_uInt8>(sHeader[0]) != 0xFF || static_cast<sal_uInt8>(sHeader[1]) != 0xFF || static_cast<sal_uInt8>(sHeader[2]) != 0x08)
568 m_aMemoHeader.db_typ = MemodBaseIII;
569 else
570 m_aMemoHeader.db_typ = MemodBaseIV;
571 }
572 else
573 {
574 m_aMemoHeader.db_typ = MemodBaseIII;
575 m_aMemoHeader.db_size = 512;
576 }
577 break;
578 case VisualFoxPro:
579 case VisualFoxProAuto:
580 case FoxProMemo:
581 m_aMemoHeader.db_typ = MemoFoxPro;
582 m_pMemoStream->Seek(6);
583 m_pMemoStream->SetEndian(SvStreamEndian::BIG);
584 (*m_pMemoStream).ReadUInt16( m_aMemoHeader.db_size );
585 break;
586 default:
587 SAL_WARN( "connectivity.drivers", "ODbaseTable::ReadMemoHeader: unsupported memo type!" )do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "connectivity.drivers")) { case SAL_DETAIL_LOG_ACTION_IGNORE
: break; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail
::getResult( ::sal::detail::StreamStart() << "ODbaseTable::ReadMemoHeader: unsupported memo type!"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("connectivity.drivers"
), ("/home/maarten/src/libreoffice/core/connectivity/source/drivers/dbase/DTable.cxx"
":" "587" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "ODbaseTable::ReadMemoHeader: unsupported memo type!"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "ODbaseTable::ReadMemoHeader: unsupported memo type!"
; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("connectivity.drivers"
), ("/home/maarten/src/libreoffice/core/connectivity/source/drivers/dbase/DTable.cxx"
":" "587" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "ODbaseTable::ReadMemoHeader: unsupported memo type!"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("connectivity.drivers"
), ("/home/maarten/src/libreoffice/core/connectivity/source/drivers/dbase/DTable.cxx"
":" "587" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "ODbaseTable::ReadMemoHeader: unsupported memo type!"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "ODbaseTable::ReadMemoHeader: unsupported memo type!"
; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("connectivity.drivers"
), ("/home/maarten/src/libreoffice/core/connectivity/source/drivers/dbase/DTable.cxx"
":" "587" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
588 break;
589 }
590}
591
592OUString ODbaseTable::getEntry(file::OConnection const * _pConnection,const OUString& _sName )
593{
594 OUString sURL;
595 try
596 {
597 Reference< XResultSet > xDir = _pConnection->getDir()->getStaticResultSet();
598 Reference< XRow> xRow(xDir,UNO_QUERY);
599 OUString sName;
600 OUString sExt;
601 INetURLObject aURL;
602 xDir->beforeFirst();
603 while(xDir->next())
604 {
605 sName = xRow->getString(1);
606 aURL.SetSmartProtocol(INetProtocol::File);
607 OUString sUrl = _pConnection->getURL() + "/" + sName;
608 aURL.SetSmartURL( sUrl );
609
610 // cut the extension
611 sExt = aURL.getExtension();
612
613 // name and extension have to coincide
614 if ( _pConnection->matchesExtension( sExt ) )
615 {
616 sName = sName.replaceAt(sName.getLength() - (sExt.getLength() + 1), sExt.getLength() + 1, OUString());
617 if ( sName == _sName )
618 {
619 Reference< XContentAccess > xContentAccess( xDir, UNO_QUERY );
620 sURL = xContentAccess->queryContentIdentifierString();
621 break;
622 }
623 }
624 }
625 xDir->beforeFirst(); // move back to before first record
626 }
627 catch(const Exception&)
628 {
629 OSL_ASSERT(false)do { if (true && (!(false))) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/connectivity/source/drivers/dbase/DTable.cxx"
":" "629" ": "), "OSL_ASSERT: %s", "false"); } } while (false
)
;
630 }
631 return sURL;
632}
633
634void ODbaseTable::refreshColumns()
635{
636 ::osl::MutexGuard aGuard( m_aMutex );
637
638 ::std::vector< OUString> aVector;
639 aVector.reserve(m_aColumns->size());
640
641 for (auto const& column : *m_aColumns)
642 aVector.push_back(Reference< XNamed>(column,UNO_QUERY_THROW)->getName());
643
644 if(m_xColumns)
645 m_xColumns->reFill(aVector);
646 else
647 m_xColumns = new ODbaseColumns(this,m_aMutex,aVector);
648}
649
650void ODbaseTable::refreshIndexes()
651{
652 ::std::vector< OUString> aVector;
653 if(m_pFileStream && (!m_xIndexes || m_xIndexes->getCount() == 0))
654 {
655 INetURLObject aURL;
656 aURL.SetURL(getEntry(m_pConnection,m_Name));
657
658 aURL.setExtension("inf");
659 Config aInfFile(aURL.getFSysPath(FSysStyle::Detect));
660 aInfFile.SetGroup(dBASE_III_GROUP"dBase III");
661 sal_uInt16 nKeyCnt = aInfFile.GetKeyCount();
662 OString aKeyName;
663
664 for (sal_uInt16 nKey = 0; nKey < nKeyCnt; nKey++)
665 {
666 // References the key an index-file?
667 aKeyName = aInfFile.GetKeyName( nKey );
668 //...if yes, add the index list of the table
669 if (aKeyName.startsWith("NDX"))
670 {
671 OString aIndexName = aInfFile.ReadKey(aKeyName);
672 aURL.setName(OStringToOUString(aIndexName, m_eEncoding));
673 try
674 {
675 Content aCnt(aURL.GetMainURL(INetURLObject::DecodeMechanism::NONE),Reference<XCommandEnvironment>(), comphelper::getProcessComponentContext());
676 if (aCnt.isDocument())
677 {
678 aVector.push_back(aURL.getBase());
679 }
680 }
681 catch(const Exception&) // an exception is thrown when no file exists
682 {
683 }
684 }
685 }
686 }
687 if(m_xIndexes)
688 m_xIndexes->reFill(aVector);
689 else
690 m_xIndexes = new ODbaseIndexes(this,m_aMutex,aVector);
691}
692
693
694void SAL_CALL ODbaseTable::disposing()
695{
696 OFileTable::disposing();
697 ::osl::MutexGuard aGuard(m_aMutex);
698 m_aColumns = nullptr;
699}
700
701Sequence< Type > SAL_CALL ODbaseTable::getTypes( )
702{
703 Sequence< Type > aTypes = OTable_TYPEDEF::getTypes();
704 std::vector<Type> aOwnTypes;
705 aOwnTypes.reserve(aTypes.getLength());
706
707 const Type* pBegin = aTypes.getConstArray();
708 const Type* pEnd = pBegin + aTypes.getLength();
709 for(;pBegin != pEnd;++pBegin)
710 {
711 if(*pBegin != cppu::UnoType<XKeysSupplier>::get() &&
712 *pBegin != cppu::UnoType<XDataDescriptorFactory>::get())
713 {
714 aOwnTypes.push_back(*pBegin);
715 }
716 }
717 aOwnTypes.push_back(cppu::UnoType<css::lang::XUnoTunnel>::get());
718 return Sequence< Type >(aOwnTypes.data(), aOwnTypes.size());
719}
720
721
722Any SAL_CALL ODbaseTable::queryInterface( const Type & rType )
723{
724 if( rType == cppu::UnoType<XKeysSupplier>::get()||
725 rType == cppu::UnoType<XDataDescriptorFactory>::get())
726 return Any();
727
728 Any aRet = OTable_TYPEDEF::queryInterface(rType);
729 return aRet.hasValue() ? aRet : ::cppu::queryInterface(rType,static_cast< css::lang::XUnoTunnel*> (this));
730}
731
732
733Sequence< sal_Int8 > ODbaseTable::getUnoTunnelId()
734{
735 static ::cppu::OImplementationId implId;
736
737 return implId.getImplementationId();
738}
739
740// css::lang::XUnoTunnel
741
742sal_Int64 ODbaseTable::getSomething( const Sequence< sal_Int8 > & rId )
743{
744 return (isUnoTunnelId<ODbaseTable>(rId))
745 ? reinterpret_cast< sal_Int64 >( this )
746 : ODbaseTable_BASE::getSomething(rId);
747}
748
749bool ODbaseTable::fetchRow(OValueRefRow& _rRow, const OSQLColumns & _rCols, bool bRetrieveData)
750{
751 if (!m_pBuffer)
752 return false;
753
754 // Read the data
755 bool bIsCurRecordDeleted = static_cast<char>(m_pBuffer[0]) == '*';
756
757 // only read the bookmark
758
759 // Mark record as deleted
760 _rRow->setDeleted(bIsCurRecordDeleted);
761 *(*_rRow)[0] = m_nFilePos;
762
763 if (!bRetrieveData)
764 return true;
765
766 std::size_t nByteOffset = 1;
767 // Fields:
768 OSQLColumns::const_iterator aIter = _rCols.begin();
769 OSQLColumns::const_iterator aEnd = _rCols.end();
770 const std::size_t nCount = _rRow->size();
771 for (std::size_t i = 1; aIter != aEnd && nByteOffset <= m_nBufferSize && i < nCount;++aIter, i++)
772 {
773 // Lengths depending on data type:
774 sal_Int32 nLen = 0;
775 sal_Int32 nType = 0;
776 nLen = m_aPrecisions[i-1];
777 nType = m_aTypes[i-1];
778
779 switch(nType)
780 {
781 case DataType::INTEGER:
782 case DataType::DOUBLE:
783 case DataType::TIMESTAMP:
784 case DataType::DATE:
785 case DataType::BIT:
786 case DataType::LONGVARCHAR:
787 case DataType::LONGVARBINARY:
788 nLen = m_aRealFieldLengths[i-1];
789 break;
790 case DataType::DECIMAL:
791 nLen = SvDbaseConverter::ConvertPrecisionToDbase(nLen,m_aScales[i-1]);
792 break; // the sign and the comma
793
794 case DataType::BINARY:
795 case DataType::OTHER:
796 nByteOffset += nLen;
797 continue;
798 }
799
800 // Is the variable bound?
801 if ( !(*_rRow)[i]->isBound() )
802 {
803 // No - next field.
804 nByteOffset += nLen;
805 OSL_ENSURE( nByteOffset <= m_nBufferSize ,"ByteOffset > m_nBufferSize!")do { if (true && (!(nByteOffset <= m_nBufferSize))
) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/connectivity/source/drivers/dbase/DTable.cxx"
":" "805" ": "), "%s", "ByteOffset > m_nBufferSize!"); } }
while (false)
;
806 continue;
807 } // if ( !(_rRow->get())[i]->isBound() )
808 if ( ( nByteOffset + nLen) > m_nBufferSize )
809 break; // length doesn't match buffer size.
810
811 char *pData = reinterpret_cast<char *>(m_pBuffer.get() + nByteOffset);
812
813 if (nType == DataType::CHAR || nType == DataType::VARCHAR)
814 {
815 sal_Int32 nLastPos = -1;
816 for (sal_Int32 k = 0; k < nLen; ++k)
817 {
818 if (pData[k] != ' ')
819 // Record last non-empty position.
820 nLastPos = k;
821 }
822 if (nLastPos < 0)
823 {
824 // Empty string. Skip it.
825 (*_rRow)[i]->setNull();
826 }
827 else
828 {
829 // Commit the string. Use intern() to ref-count it.
830 *(*_rRow)[i] = OUString::intern(pData, static_cast<sal_Int32>(nLastPos+1), m_eEncoding);
831 }
832 } // if (nType == DataType::CHAR || nType == DataType::VARCHAR)
833 else if ( DataType::TIMESTAMP == nType )
834 {
835 sal_Int32 nDate = 0,nTime = 0;
836 memcpy(&nDate, pData, 4);
837 memcpy(&nTime, pData+ 4, 4);
838 if ( !nDate && !nTime )
839 {
840 (*_rRow)[i]->setNull();
841 }
842 else
843 {
844 css::util::DateTime aDateTime;
845 lcl_CalDate(nDate,nTime,aDateTime);
846 *(*_rRow)[i] = aDateTime;
847 }
848 }
849 else if ( DataType::INTEGER == nType )
850 {
851 sal_Int32 nValue = 0;
852 if (o3tl::make_unsigned(nLen) > sizeof(nValue))
853 return false;
854 memcpy(&nValue, pData, nLen);
855 *(*_rRow)[i] = nValue;
856 }
857 else if ( DataType::DOUBLE == nType )
858 {
859 double d = 0.0;
860 if (getBOOL((*aIter)->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_ISCURRENCY39)))) // Currency is treated separately
861 {
862 sal_Int64 nValue = 0;
863 if (o3tl::make_unsigned(nLen) > sizeof(nValue))
864 return false;
865 memcpy(&nValue, pData, nLen);
866
867 if ( m_aScales[i-1] )
868 d = (nValue / pow(10.0,static_cast<int>(m_aScales[i-1])));
869 else
870 d = static_cast<double>(nValue);
871 }
872 else
873 {
874 if (o3tl::make_unsigned(nLen) > sizeof(d))
875 return false;
876 memcpy(&d, pData, nLen);
877 }
878
879 *(*_rRow)[i] = d;
880 }
881 else
882 {
883 sal_Int32 nPos1 = -1, nPos2 = -1;
884 // If the string contains Nul-characters, then convert them to blanks!
885 for (sal_Int32 k = 0; k < nLen; k++)
886 {
887 if (pData[k] == '\0')
888 pData[k] = ' ';
889
890 if (pData[k] != ' ')
891 {
892 if (nPos1 < 0)
893 // first non-empty char position.
894 nPos1 = k;
895
896 // last non-empty char position.
897 nPos2 = k;
898 }
899 }
900
901 if (nPos1 < 0)
902 {
903 // Empty string. Skip it.
904 nByteOffset += nLen;
905 (*_rRow)[i]->setNull(); // no values -> done
906 continue;
907 }
908
909 OUString aStr = OUString::intern(pData+nPos1, nPos2-nPos1+1, m_eEncoding);
910
911 switch (nType)
912 {
913 case DataType::DATE:
914 {
915 if (aStr.getLength() != nLen)
916 {
917 (*_rRow)[i]->setNull();
918 break;
919 }
920 const sal_uInt16 nYear = static_cast<sal_uInt16>(aStr.copy( 0, 4 ).toInt32());
921 const sal_uInt16 nMonth = static_cast<sal_uInt16>(aStr.copy( 4, 2 ).toInt32());
922 const sal_uInt16 nDay = static_cast<sal_uInt16>(aStr.copy( 6, 2 ).toInt32());
923
924 const css::util::Date aDate(nDay,nMonth,nYear);
925 *(*_rRow)[i] = aDate;
926 }
927 break;
928 case DataType::DECIMAL:
929 *(*_rRow)[i] = ORowSetValue(aStr);
930 break;
931 case DataType::BIT:
932 {
933 bool b;
934 switch (*pData)
935 {
936 case 'T':
937 case 'Y':
938 case 'J': b = true; break;
939 default: b = false; break;
940 }
941 *(*_rRow)[i] = b;
942 }
943 break;
944 case DataType::LONGVARBINARY:
945 case DataType::BINARY:
946 case DataType::LONGVARCHAR:
947 {
948 const long nBlockNo = aStr.toInt32(); // read blocknumber
949 if (nBlockNo > 0 && m_pMemoStream) // Read data from memo-file, only if
950 {
951 if ( !ReadMemo(nBlockNo, (*_rRow)[i]->get()) )
952 break;
953 }
954 else
955 (*_rRow)[i]->setNull();
956 } break;
957 default:
958 SAL_WARN( "connectivity.drivers","Wrong type")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "connectivity.drivers")) { case SAL_DETAIL_LOG_ACTION_IGNORE
: break; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail
::getResult( ::sal::detail::StreamStart() << "Wrong type"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("connectivity.drivers"
), ("/home/maarten/src/libreoffice/core/connectivity/source/drivers/dbase/DTable.cxx"
":" "958" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "Wrong type"), 0); } else { ::std::ostringstream
sal_detail_stream; sal_detail_stream << "Wrong type"; ::
sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("connectivity.drivers"
), ("/home/maarten/src/libreoffice/core/connectivity/source/drivers/dbase/DTable.cxx"
":" "958" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "Wrong type") == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("connectivity.drivers"), ("/home/maarten/src/libreoffice/core/connectivity/source/drivers/dbase/DTable.cxx"
":" "958" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "Wrong type"), 0); } else { ::std::ostringstream
sal_detail_stream; sal_detail_stream << "Wrong type"; ::
sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("connectivity.drivers"
), ("/home/maarten/src/libreoffice/core/connectivity/source/drivers/dbase/DTable.cxx"
":" "958" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
959 }
960 (*_rRow)[i]->setTypeKind(nType);
961 }
962
963 nByteOffset += nLen;
964 OSL_ENSURE( nByteOffset <= m_nBufferSize ,"ByteOffset > m_nBufferSize!")do { if (true && (!(nByteOffset <= m_nBufferSize))
) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/connectivity/source/drivers/dbase/DTable.cxx"
":" "964" ": "), "%s", "ByteOffset > m_nBufferSize!"); } }
while (false)
;
965 }
966 return true;
967}
968
969
970void ODbaseTable::FileClose()
971{
972 ::osl::MutexGuard aGuard(m_aMutex);
973 // if not everything has been written yet
974 if (m_pMemoStream && m_pMemoStream->IsWritable())
975 m_pMemoStream->Flush();
976
977 m_pMemoStream.reset();
978
979 ODbaseTable_BASE::FileClose();
980}
981
982bool ODbaseTable::CreateImpl()
983{
984 OSL_ENSURE(!m_pFileStream, "SequenceError")do { if (true && (!(!m_pFileStream))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/connectivity/source/drivers/dbase/DTable.cxx"
":" "984" ": "), "%s", "SequenceError"); } } while (false)
;
985
986 if ( m_pConnection->isCheckEnabled() && ::dbtools::convertName2SQLName(m_Name,OUString()) != m_Name )
987 {
988 const OUString sError( getConnection()->getResources().getResourceStringWithSubstitution(
989 STR_SQL_NAME_ERRORreinterpret_cast<char const *>("STR_SQL_NAME_ERROR" "\004"
u8"The name '$name$' doesn't match SQL naming constraints.")
,
990 "$name$", m_Name
991 ) );
992 ::dbtools::throwGenericSQLException( sError, *this );
993 }
994
995 INetURLObject aURL;
996 aURL.SetSmartProtocol(INetProtocol::File);
997 OUString aName = getEntry(m_pConnection, m_Name);
998 if(aName.isEmpty())
999 {
1000 OUString aIdent = m_pConnection->getContent()->getIdentifier()->getContentIdentifier();
1001 if ( aIdent.lastIndexOf('/') != (aIdent.getLength()-1) )
1002 aIdent += "/";
1003 aIdent += m_Name;
1004 aName = aIdent;
1005 }
1006 aURL.SetURL(aName);
1007
1008 if ( !m_pConnection->matchesExtension( aURL.getExtension() ) )
1009 aURL.setExtension(m_pConnection->getExtension());
1010
1011 try
1012 {
1013 Content aContent(aURL.GetMainURL(INetURLObject::DecodeMechanism::NONE),Reference<XCommandEnvironment>(), comphelper::getProcessComponentContext());
1014 if (aContent.isDocument())
1015 {
1016 // Only if the file exists with length > 0 raise an error
1017 std::unique_ptr<SvStream> pFileStream(createStream_simpleError( aURL.GetMainURL(INetURLObject::DecodeMechanism::NONE), StreamMode::READ));
1018
1019 if (pFileStream && pFileStream->TellEnd())
1020 return false;
1021 }
1022 }
1023 catch(const Exception&) // an exception is thrown when no file exists
1024 {
1025 }
1026
1027 bool bMemoFile = false;
1028
1029 bool bOk = CreateFile(aURL, bMemoFile);
1030
1031 FileClose();
1032
1033 if (!bOk)
1034 {
1035 try
1036 {
1037 Content aContent(aURL.GetMainURL(INetURLObject::DecodeMechanism::NONE),Reference<XCommandEnvironment>(), comphelper::getProcessComponentContext());
1038 aContent.executeCommand( "delete", css::uno::Any( true ) );
1039 }
1040 catch(const Exception&) // an exception is thrown when no file exists
1041 {
1042 }
1043 return false;
1044 }
1045
1046 if (bMemoFile)
1047 {
1048 OUString aExt = aURL.getExtension();
1049 aURL.setExtension("dbt"); // extension for memo file
1050
1051 bool bMemoAlreadyExists = false;
1052 try
1053 {
1054 Content aMemo1Content(aURL.GetMainURL(INetURLObject::DecodeMechanism::NONE),Reference<XCommandEnvironment>(), comphelper::getProcessComponentContext());
1055 bMemoAlreadyExists = aMemo1Content.isDocument();
1056 }
1057 catch(const Exception&) // an exception is thrown when no file exists
1058 {
1059 }
1060 if (bMemoAlreadyExists)
1061 {
1062 aURL.setExtension(aExt); // kill dbf file
1063 try
1064 {
1065 Content aMemoContent(aURL.GetMainURL(INetURLObject::DecodeMechanism::NONE),Reference<XCommandEnvironment>(), comphelper::getProcessComponentContext());
1066 aMemoContent.executeCommand( "delete", css::uno::Any( true ) );
1067 }
1068 catch(const Exception&)
1069 {
1070 css::uno::Any anyEx = cppu::getCaughtException();
1071 const OUString sError( getConnection()->getResources().getResourceStringWithSubstitution(
1072 STR_COULD_NOT_DELETE_FILEreinterpret_cast<char const *>("STR_COULD_NOT_DELETE_FILE"
"\004" u8"The file $filename$ could not be deleted.")
,
1073 "$name$", aName
1074 ) );
1075 ::dbtools::throwGenericSQLException( sError, *this, anyEx );
1076 }
1077 }
1078 if (!CreateMemoFile(aURL))
1079 {
1080 aURL.setExtension(aExt); // kill dbf file
1081 try
1082 {
1083 Content aMemoContent(aURL.GetMainURL(INetURLObject::DecodeMechanism::NONE),Reference<XCommandEnvironment>(), comphelper::getProcessComponentContext());
1084 aMemoContent.executeCommand( "delete", css::uno::Any( true ) );
1085 }
1086 catch(const ContentCreationException&)
1087 {
1088 css::uno::Any anyEx = cppu::getCaughtException();
1089 const OUString sError( getConnection()->getResources().getResourceStringWithSubstitution(
1090 STR_COULD_NOT_DELETE_FILEreinterpret_cast<char const *>("STR_COULD_NOT_DELETE_FILE"
"\004" u8"The file $filename$ could not be deleted.")
,
1091 "$name$", aName
1092 ) );
1093 ::dbtools::throwGenericSQLException( sError, *this, anyEx );
1094 }
1095 return false;
1096 }
1097 m_aHeader.type = dBaseIIIMemo;
1098 }
1099 else
1100 m_aHeader.type = dBaseIII;
1101
1102 return true;
1103}
1104
1105void ODbaseTable::throwInvalidColumnType(const char* pErrorId, const OUString& _sColumnName)
1106{
1107 try
1108 {
1109 // we have to drop the file because it is corrupted now
1110 DropImpl();
1111 }
1112 catch(const Exception&)
1113 {
1114 }
1115
1116 const OUString sError( getConnection()->getResources().getResourceStringWithSubstitution(
1117 pErrorId,
1118 "$columnname$", _sColumnName
1119 ) );
1120 ::dbtools::throwGenericSQLException( sError, *this );
1121}
1122
1123// creates in principle dBase IV file format
1124bool ODbaseTable::CreateFile(const INetURLObject& aFile, bool& bCreateMemo)
1125{
1126 bCreateMemo = false;
1127 Date aDate( Date::SYSTEM ); // current date
1128
1129 m_pFileStream = createStream_simpleError( aFile.GetMainURL(INetURLObject::DecodeMechanism::NONE),StreamMode::READWRITE | StreamMode::SHARE_DENYWRITE | StreamMode::TRUNC );
1130
1131 if (!m_pFileStream)
1132 return false;
1133
1134 sal_uInt8 nDbaseType = dBaseIII;
1135 Reference<XIndexAccess> xColumns(getColumns(),UNO_QUERY);
1136 Reference<XPropertySet> xCol;
1137 const OUString sPropType = OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_TYPE12);
1138
1139 try
1140 {
1141 const sal_Int32 nCount = xColumns->getCount();
1142 for(sal_Int32 i=0;i<nCount;++i)
1143 {
1144 xColumns->getByIndex(i) >>= xCol;
1145 OSL_ENSURE(xCol.is(),"This should be a column!")do { if (true && (!(xCol.is()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/connectivity/source/drivers/dbase/DTable.cxx"
":" "1145" ": "), "%s", "This should be a column!"); } } while
(false)
;
1146
1147 switch (getINT32(xCol->getPropertyValue(sPropType)))
1148 {
1149 case DataType::DOUBLE:
1150 case DataType::INTEGER:
1151 case DataType::TIMESTAMP:
1152 case DataType::LONGVARBINARY:
1153 nDbaseType = VisualFoxPro;
1154 i = nCount; // no more columns need to be checked
1155 break;
1156 } // switch (getINT32(xCol->getPropertyValue(sPropType)))
1157 }
1158 }
1159 catch ( const Exception& )
1160 {
1161 try
1162 {
1163 // we have to drop the file because it is corrupted now
1164 DropImpl();
1165 }
1166 catch(const Exception&) { }
1167 throw;
1168 }
1169
1170 char aBuffer[21] = {}; // write buffer
1171
1172 m_pFileStream->Seek(0);
1173 (*m_pFileStream).WriteUChar( nDbaseType ); // dBase format
1174 (*m_pFileStream).WriteUChar( aDate.GetYearUnsigned() % 100 ); // current date
1175
1176
1177 (*m_pFileStream).WriteUChar( aDate.GetMonth() );
1178 (*m_pFileStream).WriteUChar( aDate.GetDay() );
1179 (*m_pFileStream).WriteUInt32( 0 ); // number of data records
1180 (*m_pFileStream).WriteUInt16( (m_xColumns->getCount()+1) * 32 + 1 ); // header information,
1181 // pColumns contains always an additional column
1182 (*m_pFileStream).WriteUInt16( 0 ); // record length will be determined later
1183 m_pFileStream->WriteBytes(aBuffer, 20);
1184
1185 sal_uInt16 nRecLength = 1; // Length 1 for deleted flag
1186 sal_Int32 nMaxFieldLength = m_pConnection->getMetaData()->getMaxColumnNameLength();
1187 OUString aName;
1188 const OUString sPropName = OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_NAME11);
1189 const OUString sPropPrec = OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_PRECISION14);
1190 const OUString sPropScale = OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_SCALE15);
1191
1192 try
1193 {
1194 const sal_Int32 nCount = xColumns->getCount();
1195 for(sal_Int32 i=0;i<nCount;++i)
1196 {
1197 xColumns->getByIndex(i) >>= xCol;
1198 OSL_ENSURE(xCol.is(),"This should be a column!")do { if (true && (!(xCol.is()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/connectivity/source/drivers/dbase/DTable.cxx"
":" "1198" ": "), "%s", "This should be a column!"); } } while
(false)
;
1199
1200 char cTyp( 'C' );
1201
1202 xCol->getPropertyValue(sPropName) >>= aName;
1203
1204 OString aCol;
1205 if ( DBTypeConversion::convertUnicodeString( aName, aCol, m_eEncoding ) > nMaxFieldLength)
1206 {
1207 throwInvalidColumnType( STR_INVALID_COLUMN_NAME_LENGTHreinterpret_cast<char const *>("STR_INVALID_COLUMN_NAME_LENGTH"
"\004" u8"Invalid column name length for column '$columnname$'."
)
, aName );
1208 }
1209
1210 m_pFileStream->WriteOString( aCol );
1211 m_pFileStream->WriteBytes(aBuffer, 11 - aCol.getLength());
1212
1213 sal_Int32 nPrecision = 0;
1214 xCol->getPropertyValue(sPropPrec) >>= nPrecision;
1215 sal_Int32 nScale = 0;
1216 xCol->getPropertyValue(sPropScale) >>= nScale;
1217
1218 bool bBinary = false;
1219
1220 switch (getINT32(xCol->getPropertyValue(sPropType)))
1221 {
1222 case DataType::CHAR:
1223 case DataType::VARCHAR:
1224 cTyp = 'C';
1225 break;
1226 case DataType::DOUBLE:
1227 if (getBOOL(xCol->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_ISCURRENCY39)))) // Currency will be treated separately
1228 cTyp = 'Y';
1229 else
1230 cTyp = 'B';
1231 break;
1232 case DataType::INTEGER:
1233 cTyp = 'I';
1234 break;
1235 case DataType::TINYINT:
1236 case DataType::SMALLINT:
1237 case DataType::BIGINT:
1238 case DataType::DECIMAL:
1239 case DataType::NUMERIC:
1240 case DataType::REAL:
1241 cTyp = 'N'; // only dBase 3 format
1242 break;
1243 case DataType::TIMESTAMP:
1244 cTyp = 'T';
1245 break;
1246 case DataType::DATE:
1247 cTyp = 'D';
1248 break;
1249 case DataType::BIT:
1250 cTyp = 'L';
1251 break;
1252 case DataType::LONGVARBINARY:
1253 bBinary = true;
1254 [[fallthrough]];
1255 case DataType::LONGVARCHAR:
1256 cTyp = 'M';
1257 break;
1258 default:
1259 {
1260 throwInvalidColumnType(STR_INVALID_COLUMN_TYPEreinterpret_cast<char const *>("STR_INVALID_COLUMN_TYPE"
"\004" u8"Invalid column type for column '$columnname$'.")
, aName);
1261 }
1262 }
1263
1264 (*m_pFileStream).WriteChar( cTyp );
1265 if ( nDbaseType == VisualFoxPro )
1266 (*m_pFileStream).WriteUInt32( nRecLength-1 );
1267 else
1268 m_pFileStream->WriteBytes(aBuffer, 4);
1269
1270 switch(cTyp)
1271 {
1272 case 'C':
1273 OSL_ENSURE(nPrecision < 255, "ODbaseTable::Create: Column too long!")do { if (true && (!(nPrecision < 255))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/connectivity/source/drivers/dbase/DTable.cxx"
":" "1273" ": "), "%s", "ODbaseTable::Create: Column too long!"
); } } while (false)
;
1274 if (nPrecision > 254)
1275 {
1276 throwInvalidColumnType(STR_INVALID_COLUMN_PRECISIONreinterpret_cast<char const *>("STR_INVALID_COLUMN_PRECISION"
"\004" u8"Invalid precision for column '$columnname$'.")
, aName);
1277 }
1278 (*m_pFileStream).WriteUChar( std::min(static_cast<unsigned>(nPrecision), 255U) ); // field length
1279 nRecLength = nRecLength + static_cast<sal_uInt16>(std::min(static_cast<sal_uInt16>(nPrecision), sal_uInt16(255UL)));
1280 (*m_pFileStream).WriteUChar( 0 ); // decimals
1281 break;
1282 case 'F':
1283 case 'N':
1284 OSL_ENSURE(nPrecision >= nScale,do { if (true && (!(nPrecision >= nScale))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/connectivity/source/drivers/dbase/DTable.cxx"
":" "1285" ": "), "%s", "ODbaseTable::Create: Field length must be larger than decimal places!"
); } } while (false)
1285 "ODbaseTable::Create: Field length must be larger than decimal places!")do { if (true && (!(nPrecision >= nScale))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/connectivity/source/drivers/dbase/DTable.cxx"
":" "1285" ": "), "%s", "ODbaseTable::Create: Field length must be larger than decimal places!"
); } } while (false)
;
1286 if (nPrecision < nScale)
1287 {
1288 throwInvalidColumnType(STR_INVALID_PRECISION_SCALEreinterpret_cast<char const *>("STR_INVALID_PRECISION_SCALE"
"\004" u8"Precision is less than scale for column '$columnname$'."
)
, aName);
1289 }
1290 if (getBOOL(xCol->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_ISCURRENCY39)))) // Currency will be treated separately
1291 {
1292 (*m_pFileStream).WriteUChar( 10 ); // standard length
1293 (*m_pFileStream).WriteUChar( 4 );
1294 nRecLength += 10;
1295 }
1296 else
1297 {
1298 sal_Int32 nPrec = SvDbaseConverter::ConvertPrecisionToDbase(nPrecision,nScale);
1299
1300 (*m_pFileStream).WriteUChar( nPrec );
1301 (*m_pFileStream).WriteUChar( nScale );
1302 nRecLength += static_cast<sal_uInt16>(nPrec);
1303 }
1304 break;
1305 case 'L':
1306 (*m_pFileStream).WriteUChar( 1 );
1307 (*m_pFileStream).WriteUChar( 0 );
1308 ++nRecLength;
1309 break;
1310 case 'I':
1311 (*m_pFileStream).WriteUChar( 4 );
1312 (*m_pFileStream).WriteUChar( 0 );
1313 nRecLength += 4;
1314 break;
1315 case 'Y':
1316 case 'B':
1317 case 'T':
1318 case 'D':
1319 (*m_pFileStream).WriteUChar( 8 );
1320 (*m_pFileStream).WriteUChar( 0 );
1321 nRecLength += 8;
1322 break;
1323 case 'M':
1324 bCreateMemo = true;
1325 (*m_pFileStream).WriteUChar( 10 );
1326 (*m_pFileStream).WriteUChar( 0 );
1327 nRecLength += 10;
1328 if ( bBinary )
1329 aBuffer[0] = 0x06;
1330 break;
1331 default:
1332 throwInvalidColumnType(STR_INVALID_COLUMN_TYPEreinterpret_cast<char const *>("STR_INVALID_COLUMN_TYPE"
"\004" u8"Invalid column type for column '$columnname$'.")
, aName);
1333 }
1334 m_pFileStream->WriteBytes(aBuffer, 14);
1335 aBuffer[0] = 0x00;
1336 }
1337
1338 (*m_pFileStream).WriteUChar( FIELD_DESCRIPTOR_TERMINATOR0x0D ); // end of header
1339 (*m_pFileStream).WriteChar( char(DBF_EOL0x1A) );
1340 m_pFileStream->Seek(10);
1341 (*m_pFileStream).WriteUInt16( nRecLength ); // set record length afterwards
1342
1343 if (bCreateMemo)
1344 {
1345 m_pFileStream->Seek(0);
1346 if (nDbaseType == VisualFoxPro)
1347 (*m_pFileStream).WriteUChar( FoxProMemo );
1348 else
1349 (*m_pFileStream).WriteUChar( dBaseIIIMemo );
1350 } // if (bCreateMemo)
1351 }
1352 catch ( const Exception& )
1353 {
1354 try
1355 {
1356 // we have to drop the file because it is corrupted now
1357 DropImpl();
1358 }
1359 catch(const Exception&) { }
1360 throw;
1361 }
1362 return true;
1363}
1364
1365
1366// creates in principle dBase III file format
1367bool ODbaseTable::CreateMemoFile(const INetURLObject& aFile)
1368{
1369 // filehandling macro for table creation
1370 m_pMemoStream = createStream_simpleError( aFile.GetMainURL(INetURLObject::DecodeMechanism::NONE),StreamMode::READWRITE | StreamMode::SHARE_DENYWRITE);
1371
1372 if (!m_pMemoStream)
1373 return false;
1374
1375 m_pMemoStream->SetStreamSize(512);
1376
1377 m_pMemoStream->Seek(0);
1378 (*m_pMemoStream).WriteUInt32( 1 ); // pointer to the first free block
1379
1380 m_pMemoStream->Flush();
1381 m_pMemoStream.reset();
1382 return true;
1383}
1384
1385bool ODbaseTable::Drop_Static(const OUString& _sUrl, bool _bHasMemoFields, OCollection* _pIndexes )
1386{
1387 INetURLObject aURL;
1388 aURL.SetURL(_sUrl);
1389
1390 bool bDropped = ::utl::UCBContentHelper::Kill(aURL.GetMainURL(INetURLObject::DecodeMechanism::NONE));
1391
1392 if(bDropped)
1393 {
1394 if (_bHasMemoFields)
1395 { // delete the memo fields
1396 aURL.setExtension("dbt");
1397 bDropped = ::utl::UCBContentHelper::Kill(aURL.GetMainURL(INetURLObject::DecodeMechanism::NONE));
1398 }
1399
1400 if(bDropped)
1401 {
1402 if(_pIndexes)
1403 {
1404 try
1405 {
1406 sal_Int32 i = _pIndexes->getCount();
1407 while (i)
1408 {
1409 _pIndexes->dropByIndex(--i);
1410 }
1411 }
1412 catch(const SQLException&)
1413 {
1414 }
1415 }
1416 aURL.setExtension("inf");
1417
1418 // as the inf file does not necessarily exist, we aren't allowed to use UCBContentHelper::Kill
1419 try
1420 {
1421 ::ucbhelper::Content aDeleteContent( aURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ), Reference< XCommandEnvironment >(), comphelper::getProcessComponentContext() );
1422 aDeleteContent.executeCommand( "delete", makeAny( true ) );
1423 }
1424 catch(const Exception&)
1425 {
1426 // silently ignore this...
1427 }
1428 }
1429 }
1430 return bDropped;
1431}
1432
1433bool ODbaseTable::DropImpl()
1434{
1435 FileClose();
1436
1437 if(!m_xIndexes)
1438 refreshIndexes(); // look for indexes which must be deleted as well
1439
1440 bool bDropped = Drop_Static(getEntry(m_pConnection,m_Name),HasMemoFields(),m_xIndexes.get());
1441 if(!bDropped)
1442 {// we couldn't drop the table so we have to reopen it
1443 construct();
1444 if(m_xColumns)
1445 m_xColumns->refresh();
1446 }
1447 return bDropped;
1448}
1449
1450
1451bool ODbaseTable::InsertRow(OValueRefVector& rRow, const Reference<XIndexAccess>& _xCols)
1452{
1453 // fill buffer with blanks
1454 if (!AllocBuffer())
1455 return false;
1456
1457 memset(m_pBuffer.get(), 0, m_aHeader.recordLength);
1458 m_pBuffer[0] = ' ';
1459
1460 // Copy new row completely:
1461 // ... and add at the end as new Record:
1462 std::size_t nTempPos = m_nFilePos;
1463
1464 m_nFilePos = static_cast<std::size_t>(m_aHeader.nbRecords) + 1;
1465 bool bInsertRow = UpdateBuffer( rRow, nullptr, _xCols, true );
1466 if ( bInsertRow )
1467 {
1468 std::size_t nFileSize = 0, nMemoFileSize = 0;
1469
1470 nFileSize = lcl_getFileSize(*m_pFileStream);
1471
1472 if (HasMemoFields() && m_pMemoStream)
1473 {
1474 m_pMemoStream->Seek(STREAM_SEEK_TO_END((sal_uInt64) 0xFFFFFFFFFFFFFFFFul));
1475 nMemoFileSize = m_pMemoStream->Tell();
1476 }
1477
1478 if (!WriteBuffer())
1479 {
1480 m_pFileStream->SetStreamSize(nFileSize); // restore old size
1481
1482 if (HasMemoFields() && m_pMemoStream)
1483 m_pMemoStream->SetStreamSize(nMemoFileSize); // restore old size
1484 m_nFilePos = nTempPos; // restore file position
1485 }
1486 else
1487 {
1488 (*m_pFileStream).WriteChar( char(DBF_EOL0x1A) ); // write EOL
1489 // raise number of datasets in the header:
1490 m_pFileStream->Seek( 4 );
1491 (*m_pFileStream).WriteUInt32( m_aHeader.nbRecords + 1 );
1492
1493 m_pFileStream->Flush();
1494
1495 // raise number if successfully
1496 m_aHeader.nbRecords++;
1497 *rRow[0] = m_nFilePos; // set bookmark
1498 m_nFilePos = nTempPos;
1499 }
1500 }
1501 else
1502 m_nFilePos = nTempPos;
1503
1504 return bInsertRow;
1505}
1506
1507
1508bool ODbaseTable::UpdateRow(OValueRefVector& rRow, OValueRefRow& pOrgRow, const Reference<XIndexAccess>& _xCols)
1509{
1510 // fill buffer with blanks
1511 if (!AllocBuffer())
1512 return false;
1513
1514 // position on desired record:
1515 std::size_t nPos = m_aHeader.headerLength + static_cast<long>(m_nFilePos-1) * m_aHeader.recordLength;
1516 m_pFileStream->Seek(nPos);
1517 m_pFileStream->ReadBytes(m_pBuffer.get(), m_aHeader.recordLength);
1518
1519 std::size_t nMemoFileSize( 0 );
1520 if (HasMemoFields() && m_pMemoStream)
1521 {
1522 m_pMemoStream->Seek(STREAM_SEEK_TO_END((sal_uInt64) 0xFFFFFFFFFFFFFFFFul));
1523 nMemoFileSize = m_pMemoStream->Tell();
1524 }
1525 if (!UpdateBuffer(rRow, pOrgRow, _xCols, false) || !WriteBuffer())
1526 {
1527 if (HasMemoFields() && m_pMemoStream)
1528 m_pMemoStream->SetStreamSize(nMemoFileSize); // restore old size
1529 }
1530 else
1531 {
1532 m_pFileStream->Flush();
1533 }
1534 return true;
1535}
1536
1537
1538bool ODbaseTable::DeleteRow(const OSQLColumns& _rCols)
1539{
1540 // Set the Delete-Flag (be it set or not):
1541 // Position on desired record:
1542 std::size_t nFilePos = m_aHeader.headerLength + static_cast<long>(m_nFilePos-1) * m_aHeader.recordLength;
1543 m_pFileStream->Seek(nFilePos);
1544
1545 OValueRefRow aRow = new OValueRefVector(_rCols.size());
1546
1547 if (!fetchRow(aRow,_rCols,true))
1548 return false;
1549
1550 Reference<XPropertySet> xCol;
1551 OUString aColName;
1552 ::comphelper::UStringMixEqual aCase(isCaseSensitive());
1553 for (sal_Int32 i = 0; i < m_xColumns->getCount(); i++)
1554 {
1555 Reference<XPropertySet> xIndex = isUniqueByColumnName(i);
1556 if (xIndex.is())
1557 {
1558 xCol.set(m_xColumns->getByIndex(i), css::uno::UNO_QUERY);
1559 OSL_ENSURE(xCol.is(),"ODbaseTable::DeleteRow column is null!")do { if (true && (!(xCol.is()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/connectivity/source/drivers/dbase/DTable.cxx"
":" "1559" ": "), "%s", "ODbaseTable::DeleteRow column is null!"
); } } while (false)
;
1560 if(xCol.is())
1561 {
1562 xCol->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_NAME11)) >>= aColName;
1563
1564 Reference<XUnoTunnel> xTunnel(xIndex,UNO_QUERY);
1565 OSL_ENSURE(xTunnel.is(),"No TunnelImplementation!")do { if (true && (!(xTunnel.is()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/connectivity/source/drivers/dbase/DTable.cxx"
":" "1565" ": "), "%s", "No TunnelImplementation!"); } } while
(false)
;
1566 ODbaseIndex* pIndex = reinterpret_cast< ODbaseIndex* >( xTunnel->getSomething(ODbaseIndex::getUnoTunnelId()) );
1567 OSL_ENSURE(pIndex,"ODbaseTable::DeleteRow: No Index returned!")do { if (true && (!(pIndex))) { sal_detail_logFormat(
(SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/connectivity/source/drivers/dbase/DTable.cxx"
":" "1567" ": "), "%s", "ODbaseTable::DeleteRow: No Index returned!"
); } } while (false)
;
1568
1569 OSQLColumns::const_iterator aIter = std::find_if(_rCols.begin(), _rCols.end(),
1570 [&aCase, &aColName](const OSQLColumns::value_type& rxCol) {
1571 return aCase(getString(rxCol->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_REALNAME37))), aColName); });
1572 if (aIter == _rCols.end())
1573 continue;
1574
1575 auto nPos = static_cast<sal_Int32>(std::distance(_rCols.begin(), aIter)) + 1;
1576 pIndex->Delete(m_nFilePos,*(*aRow)[nPos]);
1577 }
1578 }
1579 }
1580
1581 m_pFileStream->Seek(nFilePos);
1582 (*m_pFileStream).WriteUChar( '*' ); // mark the row in the table as deleted
1583 m_pFileStream->Flush();
1584 return true;
1585}
1586
1587Reference<XPropertySet> ODbaseTable::isUniqueByColumnName(sal_Int32 _nColumnPos)
1588{
1589 if(!m_xIndexes)
1590 refreshIndexes();
1591 if(m_xIndexes->hasElements())
1592 {
1593 Reference<XPropertySet> xCol;
1594 m_xColumns->getByIndex(_nColumnPos) >>= xCol;
1595 OSL_ENSURE(xCol.is(),"ODbaseTable::isUniqueByColumnName column is null!")do { if (true && (!(xCol.is()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/connectivity/source/drivers/dbase/DTable.cxx"
":" "1595" ": "), "%s", "ODbaseTable::isUniqueByColumnName column is null!"
); } } while (false)
;
1596 OUString sColName;
1597 xCol->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_NAME11)) >>= sColName;
1598
1599 Reference<XPropertySet> xIndex;
1600 for(sal_Int32 i=0;i<m_xIndexes->getCount();++i)
1601 {
1602 xIndex.set(m_xIndexes->getByIndex(i), css::uno::UNO_QUERY);
1603 if(xIndex.is() && getBOOL(xIndex->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_ISUNIQUE25))))
1604 {
1605 Reference<XNameAccess> xCols(Reference<XColumnsSupplier>(xIndex,UNO_QUERY_THROW)->getColumns());
1606 if(xCols->hasByName(sColName))
1607 return xIndex;
1608
1609 }
1610 }
1611 }
1612 return Reference<XPropertySet>();
1613}
1614
1615static double toDouble(const OString& rString)
1616{
1617 return ::rtl::math::stringToDouble( rString, '.', ',' );
1618}
1619
1620
1621bool ODbaseTable::UpdateBuffer(OValueRefVector& rRow, const OValueRefRow& pOrgRow, const Reference<XIndexAccess>& _xCols, const bool bForceAllFields)
1622{
1623 OSL_ENSURE(m_pBuffer,"Buffer is NULL!")do { if (true && (!(m_pBuffer))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/connectivity/source/drivers/dbase/DTable.cxx"
":" "1623" ": "), "%s", "Buffer is NULL!"); } } while (false
)
;
1624 if ( !m_pBuffer )
1625 return false;
1626 sal_Int32 nByteOffset = 1;
1627
1628 // Update fields:
1629 Reference<XPropertySet> xCol;
1630 Reference<XPropertySet> xIndex;
1631 OUString aColName;
1632 const sal_Int32 nColumnCount = m_xColumns->getCount();
1633 std::vector< Reference<XPropertySet> > aIndexedCols(nColumnCount);
1634
1635 ::comphelper::UStringMixEqual aCase(isCaseSensitive());
1636
1637 Reference<XIndexAccess> xColumns = m_xColumns.get();
1638 // first search a key that exist already in the table
1639 for (sal_Int32 i = 0; i < nColumnCount; ++i)
1640 {
1641 sal_Int32 nPos = i;
1642 if(_xCols != xColumns)
1643 {
1644 m_xColumns->getByIndex(i) >>= xCol;
1645 OSL_ENSURE(xCol.is(),"ODbaseTable::UpdateBuffer column is null!")do { if (true && (!(xCol.is()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/connectivity/source/drivers/dbase/DTable.cxx"
":" "1645" ": "), "%s", "ODbaseTable::UpdateBuffer column is null!"
); } } while (false)
;
1646 xCol->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_NAME11)) >>= aColName;
1647
1648 for(nPos = 0;nPos<_xCols->getCount();++nPos)
1649 {
1650 Reference<XPropertySet> xFindCol(
1651 _xCols->getByIndex(nPos), css::uno::UNO_QUERY);
1652 OSL_ENSURE(xFindCol.is(),"ODbaseTable::UpdateBuffer column is null!")do { if (true && (!(xFindCol.is()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/connectivity/source/drivers/dbase/DTable.cxx"
":" "1652" ": "), "%s", "ODbaseTable::UpdateBuffer column is null!"
); } } while (false)
;
1653 if(aCase(getString(xFindCol->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_NAME11))),aColName))
1654 break;
1655 }
1656 if (nPos >= _xCols->getCount())
1657 continue;
1658 }
1659
1660 ++nPos;
1661 xIndex = isUniqueByColumnName(i);
1662 aIndexedCols[i] = xIndex;
1663 if (xIndex.is())
1664 {
1665 // first check if the value is different to the old one and when if it conform to the index
1666 if(pOrgRow.is() && (rRow[nPos]->getValue().isNull() || rRow[nPos] == (*pOrgRow)[nPos]))
1667 continue;
1668 else
1669 {
1670 Reference<XUnoTunnel> xTunnel(xIndex,UNO_QUERY);
1671 OSL_ENSURE(xTunnel.is(),"No TunnelImplementation!")do { if (true && (!(xTunnel.is()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/connectivity/source/drivers/dbase/DTable.cxx"
":" "1671" ": "), "%s", "No TunnelImplementation!"); } } while
(false)
;
1672 ODbaseIndex* pIndex = reinterpret_cast< ODbaseIndex* >( xTunnel->getSomething(ODbaseIndex::getUnoTunnelId()) );
1673 OSL_ENSURE(pIndex,"ODbaseTable::UpdateBuffer: No Index returned!")do { if (true && (!(pIndex))) { sal_detail_logFormat(
(SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/connectivity/source/drivers/dbase/DTable.cxx"
":" "1673" ": "), "%s", "ODbaseTable::UpdateBuffer: No Index returned!"
); } } while (false)
;
1674
1675 if (pIndex->Find(0,*rRow[nPos]))
1676 {
1677 // There is no unique value
1678 if ( aColName.isEmpty() )
1679 {
1680 m_xColumns->getByIndex(i) >>= xCol;
1681 OSL_ENSURE(xCol.is(),"ODbaseTable::UpdateBuffer column is null!")do { if (true && (!(xCol.is()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/connectivity/source/drivers/dbase/DTable.cxx"
":" "1681" ": "), "%s", "ODbaseTable::UpdateBuffer column is null!"
); } } while (false)
;
1682 xCol->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_NAME11)) >>= aColName;
1683 xCol.clear();
1684 } // if ( !aColName.getLength() )
1685 const OUString sError( getConnection()->getResources().getResourceStringWithSubstitution(
1686 STR_DUPLICATE_VALUE_IN_COLUMNreinterpret_cast<char const *>("STR_DUPLICATE_VALUE_IN_COLUMN"
"\004" u8"Duplicate value found in column '$columnname$'.")
1687 ,"$columnname$", aColName
1688 ) );
1689 ::dbtools::throwGenericSQLException( sError, *this );
1690 }
1691 }
1692 }
1693 }
1694
1695 // when we are here there is no double key in the table
1696
1697 for (sal_Int32 i = 0; i < nColumnCount && nByteOffset <= m_nBufferSize ; ++i)
1698 {
1699 // Lengths for each data type:
1700 assert(i >= 0)(static_cast <bool> (i >= 0) ? void (0) : __assert_fail
("i >= 0", "/home/maarten/src/libreoffice/core/connectivity/source/drivers/dbase/DTable.cxx"
, 1700, __extension__ __PRETTY_FUNCTION__))
;
1701 OSL_ENSURE(o3tl::make_unsigned(i) < m_aPrecisions.size(),"Illegal index!")do { if (true && (!(o3tl::make_unsigned(i) < m_aPrecisions
.size()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN)
, ("legacy.osl"), ("/home/maarten/src/libreoffice/core/connectivity/source/drivers/dbase/DTable.cxx"
":" "1701" ": "), "%s", "Illegal index!"); } } while (false)
;
1702 sal_Int32 nLen = 0;
1703 sal_Int32 nType = 0;
1704 sal_Int32 nScale = 0;
1705 if ( o3tl::make_unsigned(i) < m_aPrecisions.size() )
1706 {
1707 nLen = m_aPrecisions[i];
1708 nType = m_aTypes[i];
1709 nScale = m_aScales[i];
1710 }
1711 else
1712 {
1713 m_xColumns->getByIndex(i) >>= xCol;
1714 if ( xCol.is() )
1715 {
1716 xCol->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_PRECISION14)) >>= nLen;
1717 xCol->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_TYPE12)) >>= nType;
1718 xCol->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_SCALE15)) >>= nScale;
1719 }
1720 }
1721
1722 bool bSetZero = false;
1723 switch (nType)
1724 {
1725 case DataType::INTEGER:
1726 case DataType::DOUBLE:
1727 case DataType::TIMESTAMP:
1728 bSetZero = true;
1729 [[fallthrough]];
1730 case DataType::LONGVARBINARY:
1731 case DataType::DATE:
1732 case DataType::BIT:
1733 case DataType::LONGVARCHAR:
1734 nLen = m_aRealFieldLengths[i];
1735 break;
1736 case DataType::DECIMAL:
1737 nLen = SvDbaseConverter::ConvertPrecisionToDbase(nLen,nScale);
1738 break; // The sign and the comma
1739 default:
1740 break;
1741
1742 } // switch (nType)
1743
1744 sal_Int32 nPos = i;
1745 if(_xCols != xColumns)
1746 {
1747 m_xColumns->getByIndex(i) >>= xCol;
1748 OSL_ENSURE(xCol.is(),"ODbaseTable::UpdateBuffer column is null!")do { if (true && (!(xCol.is()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/connectivity/source/drivers/dbase/DTable.cxx"
":" "1748" ": "), "%s", "ODbaseTable::UpdateBuffer column is null!"
); } } while (false)
;
1749 xCol->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_NAME11)) >>= aColName;
1750 for(nPos = 0;nPos<_xCols->getCount();++nPos)
1751 {
1752 Reference<XPropertySet> xFindCol(
1753 _xCols->getByIndex(nPos), css::uno::UNO_QUERY);
1754 if(aCase(getString(xFindCol->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_NAME11))),aColName))
1755 break;
1756 }
1757 if (nPos >= _xCols->getCount())
1758 {
1759 nByteOffset += nLen;
1760 continue;
1761 }
1762 }
1763
1764
1765 ++nPos; // the row values start at 1
1766 const ORowSetValue &thisColVal = rRow[nPos]->get();
1767 const bool thisColIsBound = thisColVal.isBound();
1768 const bool thisColIsNull = !thisColIsBound || thisColVal.isNull();
1769 // don't overwrite non-bound columns
1770 if ( ! (bForceAllFields || thisColIsBound) )
1771 {
1772 // No - don't overwrite this field, it has not changed.
1773 nByteOffset += nLen;
1774 continue;
1775 }
1776 if (aIndexedCols[i].is())
1777 {
1778 Reference<XUnoTunnel> xTunnel(aIndexedCols[i],UNO_QUERY);
1779 OSL_ENSURE(xTunnel.is(),"No TunnelImplementation!")do { if (true && (!(xTunnel.is()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/connectivity/source/drivers/dbase/DTable.cxx"
":" "1779" ": "), "%s", "No TunnelImplementation!"); } } while
(false)
;
1780 ODbaseIndex* pIndex = reinterpret_cast< ODbaseIndex* >( xTunnel->getSomething(ODbaseIndex::getUnoTunnelId()) );
1781 OSL_ENSURE(pIndex,"ODbaseTable::UpdateBuffer: No Index returned!")do { if (true && (!(pIndex))) { sal_detail_logFormat(
(SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/connectivity/source/drivers/dbase/DTable.cxx"
":" "1781" ": "), "%s", "ODbaseTable::UpdateBuffer: No Index returned!"
); } } while (false)
;
1782 // Update !!
1783 if (pOrgRow.is() && !thisColIsNull)
1784 pIndex->Update(m_nFilePos, *(*pOrgRow)[nPos], thisColVal);
1785 else
1786 pIndex->Insert(m_nFilePos, thisColVal);
1787 }
1788
1789 char* pData = reinterpret_cast<char *>(m_pBuffer.get() + nByteOffset);
1790 if (thisColIsNull)
1791 {
1792 if ( bSetZero )
1793 memset(pData,0,nLen); // Clear to NULL char ('\0')
1794 else
1795 memset(pData,' ',nLen); // Clear to space/blank ('\0x20')
1796 nByteOffset += nLen;
1797 OSL_ENSURE( nByteOffset <= m_nBufferSize ,"ByteOffset > m_nBufferSize!")do { if (true && (!(nByteOffset <= m_nBufferSize))
) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/connectivity/source/drivers/dbase/DTable.cxx"
":" "1797" ": "), "%s", "ByteOffset > m_nBufferSize!"); }
} while (false)
;
1798 continue;
1799 }
1800
1801 try
1802 {
1803 switch (nType)
1804 {
1805 case DataType::TIMESTAMP:
1806 {
1807 sal_Int32 nJulianDate = 0, nJulianTime = 0;
1808 lcl_CalcJulDate(nJulianDate,nJulianTime, thisColVal);
1809 // Exactly 8 bytes to copy:
1810 memcpy(pData,&nJulianDate,4);
1811 memcpy(pData+4,&nJulianTime,4);
1812 }
1813 break;
1814 case DataType::DATE:
1815 {
1816 css::util::Date aDate;
1817 if(thisColVal.getTypeKind() == DataType::DOUBLE)
1818 aDate = ::dbtools::DBTypeConversion::toDate(thisColVal.getDouble());
1819 else
1820 aDate = thisColVal;
1821 char s[sizeof("-327686553565535")];
1822 // reserve enough space for hypothetical max length
1823 snprintf(s,
1824 sizeof(s),
1825 "%04" SAL_PRIdINT32"d" "%02" SAL_PRIuUINT32"u" "%02" SAL_PRIuUINT32"u",
1826 static_cast<sal_Int32>(aDate.Year),
1827 static_cast<sal_uInt32>(aDate.Month),
1828 static_cast<sal_uInt32>(aDate.Day));
1829
1830 // Exactly 8 bytes to copy (even if s could hypothetically be longer):
1831 memcpy(pData,s,8);
1832 } break;
1833 case DataType::INTEGER:
1834 {
1835 sal_Int32 nValue = thisColVal;
1836 if (o3tl::make_unsigned(nLen) > sizeof(nValue))
1837 return false;
1838 memcpy(pData,&nValue,nLen);
1839 }
1840 break;
1841 case DataType::DOUBLE:
1842 {
1843 const double d = thisColVal;
1844 m_xColumns->getByIndex(i) >>= xCol;
1845
1846 if (getBOOL(xCol->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_ISCURRENCY39)))) // Currency is treated separately
1847 {
1848 sal_Int64 nValue = 0;
1849 if ( m_aScales[i] )
1850 nValue = static_cast<sal_Int64>(d * pow(10.0,static_cast<int>(m_aScales[i])));
1851 else
1852 nValue = static_cast<sal_Int64>(d);
1853 if (o3tl::make_unsigned(nLen) > sizeof(nValue))
1854 return false;
1855 memcpy(pData,&nValue,nLen);
1856 } // if (getBOOL(xCol->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_ISCURRENCY)))) // Currency is treated separately
1857 else
1858 {
1859 if (o3tl::make_unsigned(nLen) > sizeof(d))
1860 return false;
1861 memcpy(pData,&d,nLen);
1862 }
1863 }
1864 break;
1865 case DataType::DECIMAL:
1866 {
1867 memset(pData,' ',nLen); // Clear to NULL
1868
1869 const double n = thisColVal;
1870
1871 // one, because const_cast GetFormatPrecision on SvNumberFormat is not constant,
1872 // even though it really could and should be
1873 const OString aDefaultValue( ::rtl::math::doubleToString( n, rtl_math_StringFormat_F, nScale, '.', nullptr, 0));
1874 const sal_Int32 nValueLen = aDefaultValue.getLength();
1875 if ( nValueLen <= nLen )
1876 {
1877 // Write value right-justified, padded with blanks to the left.
1878 memcpy(pData+nLen-nValueLen,aDefaultValue.getStr(),nValueLen);
1879 // write the resulting double back
1880 *rRow[nPos] = toDouble(aDefaultValue);
1881 }
1882 else
1883 {
1884 m_xColumns->getByIndex(i) >>= xCol;
1885 OSL_ENSURE(xCol.is(),"ODbaseTable::UpdateBuffer column is null!")do { if (true && (!(xCol.is()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/connectivity/source/drivers/dbase/DTable.cxx"
":" "1885" ": "), "%s", "ODbaseTable::UpdateBuffer column is null!"
); } } while (false)
;
1886 xCol->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_NAME11)) >>= aColName;
1887 std::vector< std::pair<const char* , OUString > > aStringToSubstitutes;
1888 aStringToSubstitutes.push_back(std::pair<const char* , OUString >("$columnname$", aColName));
1889 aStringToSubstitutes.push_back(std::pair<const char* , OUString >("$precision$", OUString::number(nLen)));
1890 aStringToSubstitutes.push_back(std::pair<const char* , OUString >("$scale$", OUString::number(nScale)));
1891 aStringToSubstitutes.push_back(std::pair<const char* , OUString >("$value$", OStringToOUString(aDefaultValue,RTL_TEXTENCODING_UTF8(((rtl_TextEncoding) 76)))));
1892
1893 const OUString sError( getConnection()->getResources().getResourceStringWithSubstitution(
1894 STR_INVALID_COLUMN_DECIMAL_VALUEreinterpret_cast<char const *>("STR_INVALID_COLUMN_DECIMAL_VALUE"
"\004" u8"The '$columnname$' column has been defined as a \"Decimal\" type, the max. length is $precision$ characters (with $scale$ decimal places).\n\nThe specified value \"$value$ is longer than the number of digits allowed."
)
1895 ,aStringToSubstitutes
1896 ) );
1897 ::dbtools::throwGenericSQLException( sError, *this );
1898 }
1899 } break;
1900 case DataType::BIT:
1901 *pData = thisColVal.getBool() ? 'T' : 'F';
1902 break;
1903 case DataType::LONGVARBINARY:
1904 case DataType::LONGVARCHAR:
1905 {
1906 char cNext = pData[nLen]; // Mark's scratch and replaced by 0
1907 pData[nLen] = '\0'; // This is because the buffer is always a sign of greater ...
1908
1909 std::size_t nBlockNo = strtol(pData,nullptr,10); // Block number read
1910
1911 // Next initial character restore again:
1912 pData[nLen] = cNext;
1913 if (!m_pMemoStream)
1914 break;
1915 WriteMemo(thisColVal, nBlockNo);
1916
1917 OString aBlock(OString::number(nBlockNo));
1918 //align aBlock at the right of a nLen sequence, fill to the left with '0'
1919 OStringBuffer aStr;
1920 comphelper::string::padToLength(aStr, nLen - aBlock.getLength(), '0');
1921 aStr.append(aBlock);
1922
1923 // Copy characters:
1924 memcpy(pData, aStr.getStr(), nLen);
1925 } break;
1926 default:
1927 {
1928 memset(pData,' ',nLen); // Clear to NULL
1929
1930 OUString sStringToWrite( thisColVal.getString() );
1931
1932 // convert the string, using the connection's encoding
1933 OString sEncoded;
1934
1935 DBTypeConversion::convertUnicodeStringToLength( sStringToWrite, sEncoded, nLen, m_eEncoding );
1936 memcpy( pData, sEncoded.getStr(), sEncoded.getLength() );
1937
1938 }
1939 break;
1940 }
1941 }
1942 catch( const SQLException& )
1943 {
1944 throw;
1945 }
1946 catch ( const Exception& )
1947 {
1948 m_xColumns->getByIndex(i) >>= xCol;
1949 OSL_ENSURE( xCol.is(), "ODbaseTable::UpdateBuffer column is null!" )do { if (true && (!(xCol.is()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/connectivity/source/drivers/dbase/DTable.cxx"
":" "1949" ": "), "%s", "ODbaseTable::UpdateBuffer column is null!"
); } } while (false)
;
1950 if ( xCol.is() )
1951 xCol->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_NAME11)) >>= aColName;
1952
1953 const OUString sError( getConnection()->getResources().getResourceStringWithSubstitution(
1954 STR_INVALID_COLUMN_VALUEreinterpret_cast<char const *>("STR_INVALID_COLUMN_VALUE"
"\004" u8"The column '$columnname$' could not be updated. The value is invalid for that column."
)
,
1955 "$columnname$", aColName
1956 ) );
1957 ::dbtools::throwGenericSQLException( sError, *this );
1958 }
1959 // And more ...
1960 nByteOffset += nLen;
1961 OSL_ENSURE( nByteOffset <= m_nBufferSize ,"ByteOffset > m_nBufferSize!")do { if (true && (!(nByteOffset <= m_nBufferSize))
) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/connectivity/source/drivers/dbase/DTable.cxx"
":" "1961" ": "), "%s", "ByteOffset > m_nBufferSize!"); }
} while (false)
;
1962 }
1963 return true;
1964}
1965
1966
1967void ODbaseTable::WriteMemo(const ORowSetValue& aVariable, std::size_t& rBlockNr)
1968{
1969 // if the BlockNo 0 is given, the block will be appended at the end
1970 std::size_t nSize = 0;
1971 OString aStr;
1972 css::uno::Sequence<sal_Int8> aValue;
1973 sal_uInt8 nHeader[4];
1974 const bool bBinary = aVariable.getTypeKind() == DataType::LONGVARBINARY && m_aMemoHeader.db_typ == MemoFoxPro;
1975 if ( bBinary )
1976 {
1977 aValue = aVariable.getSequence();
1978 nSize = aValue.getLength();
1979 }
1980 else
1981 {
1982 nSize = DBTypeConversion::convertUnicodeString( aVariable.getString(), aStr, m_eEncoding );
1983 }
1984
1985 // append or overwrite
1986 bool bAppend = rBlockNr == 0;
1987
1988 if (!bAppend)
1989 {
1990 switch (m_aMemoHeader.db_typ)
1991 {
1992 case MemodBaseIII: // dBase III-Memofield, ends with 2 * Ctrl-Z
1993 bAppend = nSize > (512 - 2);
1994 break;
1995 case MemoFoxPro:
1996 case MemodBaseIV: // dBase IV-Memofield with length
1997 {
1998 char sHeader[4];
1999 m_pMemoStream->Seek(rBlockNr * m_aMemoHeader.db_size);
2000 m_pMemoStream->SeekRel(4);
2001 m_pMemoStream->ReadBytes(sHeader, 4);
2002
2003 std::size_t nOldSize;
2004 if (m_aMemoHeader.db_typ == MemoFoxPro)
2005 nOldSize = ((static_cast<unsigned char>(sHeader[0]) * 256 +
2006 static_cast<unsigned char>(sHeader[1])) * 256 +
2007 static_cast<unsigned char>(sHeader[2])) * 256 +
2008 static_cast<unsigned char>(sHeader[3]);
2009 else
2010 nOldSize = ((static_cast<unsigned char>(sHeader[3]) * 256 +
2011 static_cast<unsigned char>(sHeader[2])) * 256 +
2012 static_cast<unsigned char>(sHeader[1])) * 256 +
2013 static_cast<unsigned char>(sHeader[0]) - 8;
2014
2015 // fits the new length in the used blocks
2016 std::size_t nUsedBlocks = ((nSize + 8) / m_aMemoHeader.db_size) + (((nSize + 8) % m_aMemoHeader.db_size > 0) ? 1 : 0),
2017 nOldUsedBlocks = ((nOldSize + 8) / m_aMemoHeader.db_size) + (((nOldSize + 8) % m_aMemoHeader.db_size > 0) ? 1 : 0);
2018 bAppend = nUsedBlocks > nOldUsedBlocks;
2019 }
2020 }
2021 }
2022
2023 if (bAppend)
2024 {
2025 sal_uInt64 const nStreamSize = m_pMemoStream->TellEnd();
2026 // fill last block
2027 rBlockNr = (nStreamSize / m_aMemoHeader.db_size) + ((nStreamSize % m_aMemoHeader.db_size) > 0 ? 1 : 0);
2028
2029 m_pMemoStream->SetStreamSize(rBlockNr * m_aMemoHeader.db_size);
2030 m_pMemoStream->Seek(STREAM_SEEK_TO_END((sal_uInt64) 0xFFFFFFFFFFFFFFFFul));
2031 }
2032 else
2033 {
2034 m_pMemoStream->Seek(rBlockNr * m_aMemoHeader.db_size);
2035 }
2036
2037 switch (m_aMemoHeader.db_typ)
2038 {
2039 case MemodBaseIII: // dBase III-Memofield, ends with Ctrl-Z
2040 {
2041 const char cEOF = char(DBF_EOL0x1A);
2042 nSize++;
2043 m_pMemoStream->WriteBytes(aStr.getStr(), aStr.getLength());
2044 m_pMemoStream->WriteChar( cEOF ).WriteChar( cEOF );
2045 } break;
2046 case MemoFoxPro:
2047 case MemodBaseIV: // dBase IV-Memofield with length
2048 {
2049 if ( MemodBaseIV == m_aMemoHeader.db_typ )
2050 (*m_pMemoStream).WriteUChar( 0xFF )
2051 .WriteUChar( 0xFF )
2052 .WriteUChar( 0x08 );
2053 else
2054 (*m_pMemoStream).WriteUChar( 0x00 )
2055 .WriteUChar( 0x00 )
2056 .WriteUChar( 0x00 );
2057
2058 sal_uInt32 nWriteSize = nSize;
2059 if (m_aMemoHeader.db_typ == MemoFoxPro)
2060 {
2061 if ( bBinary )
2062 (*m_pMemoStream).WriteUChar( 0x00 ); // Picture
2063 else
2064 (*m_pMemoStream).WriteUChar( 0x01 ); // Memo
2065 for (int i = 4; i > 0; nWriteSize >>= 8)
2066 nHeader[--i] = static_cast<sal_uInt8>(nWriteSize % 256);
2067 }
2068 else
2069 {
2070 (*m_pMemoStream).WriteUChar( 0x00 );
2071 nWriteSize += 8;
2072 for (int i = 0; i < 4; nWriteSize >>= 8)
2073 nHeader[i++] = static_cast<sal_uInt8>(nWriteSize % 256);
2074 }
2075
2076 m_pMemoStream->WriteBytes(nHeader, 4);
2077 if ( bBinary )
2078 m_pMemoStream->WriteBytes(aValue.getConstArray(), aValue.getLength());
2079 else
2080 m_pMemoStream->WriteBytes(aStr.getStr(), aStr.getLength());
2081 m_pMemoStream->Flush();
2082 }
2083 }
2084
2085
2086 // Write the new block number
2087 if (bAppend)
2088 {
2089 sal_uInt64 const nStreamSize = m_pMemoStream->TellEnd();
2090 m_aMemoHeader.db_next = (nStreamSize / m_aMemoHeader.db_size) + ((nStreamSize % m_aMemoHeader.db_size) > 0 ? 1 : 0);
2091
2092 // Write the new block number
2093 m_pMemoStream->Seek(0);
2094 (*m_pMemoStream).WriteUInt32( m_aMemoHeader.db_next );
2095 m_pMemoStream->Flush();
2096 }
2097}
2098
2099
2100// XAlterTable
2101void SAL_CALL ODbaseTable::alterColumnByName( const OUString& colName, const Reference< XPropertySet >& descriptor )
2102{
2103 ::osl::MutexGuard aGuard(m_aMutex);
2104 checkDisposed(OTableDescriptor_BASE::rBHelper.bDisposed);
2105
2106
2107 Reference<XDataDescriptorFactory> xOldColumn;
2108 m_xColumns->getByName(colName) >>= xOldColumn;
2109
2110 try
2111 {
2112 alterColumn(m_xColumns->findColumn(colName)-1,descriptor,xOldColumn);
2113 }
2114 catch (const css::lang::IndexOutOfBoundsException&)
2115 {
2116 throw NoSuchElementException(colName, *this);
2117 }
2118}
2119
2120void SAL_CALL ODbaseTable::alterColumnByIndex( sal_Int32 index, const Reference< XPropertySet >& descriptor )
2121{
2122 ::osl::MutexGuard aGuard(m_aMutex);
2123 checkDisposed(OTableDescriptor_BASE::rBHelper.bDisposed);
2124
2125 if(index < 0 || index >= m_xColumns->getCount())
2126 throw IndexOutOfBoundsException(OUString::number(index),*this);
2127
2128 Reference<XDataDescriptorFactory> xOldColumn;
2129 m_xColumns->getByIndex(index) >>= xOldColumn;
2130 alterColumn(index,descriptor,xOldColumn);
2131}
2132
2133void ODbaseTable::alterColumn(sal_Int32 index,
2134 const Reference< XPropertySet >& descriptor ,
2135 const Reference< XDataDescriptorFactory >& xOldColumn )
2136{
2137 if(index < 0 || index >= m_xColumns->getCount())
2138 throw IndexOutOfBoundsException(OUString::number(index),*this);
2139
2140 try
2141 {
2142 OSL_ENSURE(descriptor.is(),"ODbaseTable::alterColumn: descriptor can not be null!")do { if (true && (!(descriptor.is()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/connectivity/source/drivers/dbase/DTable.cxx"
":" "2142" ": "), "%s", "ODbaseTable::alterColumn: descriptor can not be null!"
); } } while (false)
;
2143 // creates a copy of the original column and copy all properties from descriptor in xCopyColumn
2144 Reference<XPropertySet> xCopyColumn;
2145 if(xOldColumn.is())
2146 xCopyColumn = xOldColumn->createDataDescriptor();
2147 else
2148 xCopyColumn = new OColumn(getConnection()->getMetaData()->supportsMixedCaseQuotedIdentifiers());
2149
2150 ::comphelper::copyProperties(descriptor,xCopyColumn);
2151
2152 // creates a temp file
2153
2154 OUString sTempName = createTempFile();
2155
2156 ODbaseTable* pNewTable = new ODbaseTable(m_pTables,static_cast<ODbaseConnection*>(m_pConnection));
2157 Reference<XPropertySet> xHoldTable = pNewTable;
2158 pNewTable->setPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_NAME11),makeAny(sTempName));
2159 Reference<XAppend> xAppend(pNewTable->getColumns(),UNO_QUERY);
2160 OSL_ENSURE(xAppend.is(),"ODbaseTable::alterColumn: No XAppend interface!")do { if (true && (!(xAppend.is()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/connectivity/source/drivers/dbase/DTable.cxx"
":" "2160" ": "), "%s", "ODbaseTable::alterColumn: No XAppend interface!"
); } } while (false)
;
2161
2162 // copy the structure
2163 sal_Int32 i=0;
2164 for(;i < index;++i)
2165 {
2166 Reference<XPropertySet> xProp;
2167 m_xColumns->getByIndex(i) >>= xProp;
2168 Reference<XDataDescriptorFactory> xColumn(xProp,UNO_QUERY);
2169 Reference<XPropertySet> xCpy;
2170 if(xColumn.is())
2171 xCpy = xColumn->createDataDescriptor();
2172 else
2173 xCpy = new OColumn(getConnection()->getMetaData()->supportsMixedCaseQuotedIdentifiers());
2174 ::comphelper::copyProperties(xProp,xCpy);
2175 xAppend->appendByDescriptor(xCpy);
2176 }
2177 ++i; // now insert our new column
2178 xAppend->appendByDescriptor(xCopyColumn);
2179
2180 for(;i < m_xColumns->getCount();++i)
2181 {
2182 Reference<XPropertySet> xProp;
2183 m_xColumns->getByIndex(i) >>= xProp;
2184 Reference<XDataDescriptorFactory> xColumn(xProp,UNO_QUERY);
2185 Reference<XPropertySet> xCpy;
2186 if(xColumn.is())
2187 xCpy = xColumn->createDataDescriptor();
2188 else
2189 xCpy = new OColumn(getConnection()->getMetaData()->supportsMixedCaseQuotedIdentifiers());
2190 ::comphelper::copyProperties(xProp,xCpy);
2191 xAppend->appendByDescriptor(xCpy);
2192 }
2193
2194 // construct the new table
2195 if(!pNewTable->CreateImpl())
2196 {
2197 const OUString sError( getConnection()->getResources().getResourceStringWithSubstitution(
2198 STR_COLUMN_NOT_ALTERABLEreinterpret_cast<char const *>("STR_COLUMN_NOT_ALTERABLE"
"\004" u8"The column '$columnname$' could not be altered. May be the file system is write protected."
)
,
2199 "$columnname$", ::comphelper::getString(descriptor->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_NAME11)))
2200 ) );
2201 ::dbtools::throwGenericSQLException( sError, *this );
2202 }
2203
2204 pNewTable->construct();
2205
2206 // copy the data
2207 copyData(pNewTable,0);
2208
2209 // now drop the old one
2210 if( DropImpl() ) // we don't want to delete the memo columns too
2211 {
2212 try
2213 {
2214 // rename the new one to the old one
2215 pNewTable->renameImpl(m_Name);
2216 }
2217 catch(const css::container::ElementExistException&)
2218 {
2219 const OUString sError( getConnection()->getResources().getResourceStringWithSubstitution(
2220 STR_COULD_NOT_DELETE_FILEreinterpret_cast<char const *>("STR_COULD_NOT_DELETE_FILE"
"\004" u8"The file $filename$ could not be deleted.")
,
2221 "$filename$", m_Name
2222 ) );
2223 ::dbtools::throwGenericSQLException( sError, *this );
2224 }
2225 // release the temp file
2226 pNewTable = nullptr;
2227 ::comphelper::disposeComponent(xHoldTable);
2228 }
2229 else
2230 {
2231 pNewTable = nullptr;
2232 }
2233 FileClose();
2234 construct();
2235 if(m_xColumns)
2236 m_xColumns->refresh();
2237
2238 }
2239 catch(const SQLException&)
2240 {
2241 throw;
2242 }
2243 catch(const Exception&)
2244 {
2245 TOOLS_WARN_EXCEPTION( "connectivity.drivers","")do { css::uno::Any tools_warn_exception( DbgGetCaughtException
() ); do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "connectivity.drivers")) { case SAL_DETAIL_LOG_ACTION_IGNORE
: break; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail
::getResult( ::sal::detail::StreamStart() << "" <<
" " << exceptionToString(tools_warn_exception)) == 1) {
::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("connectivity.drivers"
), ("/home/maarten/src/libreoffice/core/connectivity/source/drivers/dbase/DTable.cxx"
":" "2245" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "" << " " << exceptionToString
(tools_warn_exception)), 0); } else { ::std::ostringstream sal_detail_stream
; sal_detail_stream << "" << " " << exceptionToString
(tools_warn_exception); ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("connectivity.drivers"), ("/home/maarten/src/libreoffice/core/connectivity/source/drivers/dbase/DTable.cxx"
":" "2245" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "" << " " << exceptionToString(tools_warn_exception
)) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), (
"connectivity.drivers"), ("/home/maarten/src/libreoffice/core/connectivity/source/drivers/dbase/DTable.cxx"
":" "2245" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "" << " " << exceptionToString
(tools_warn_exception)), 0); } else { ::std::ostringstream sal_detail_stream
; sal_detail_stream << "" << " " << exceptionToString
(tools_warn_exception); ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("connectivity.drivers"), ("/home/maarten/src/libreoffice/core/connectivity/source/drivers/dbase/DTable.cxx"
":" "2245" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false); } while (false)
;
2246 throw;
2247 }
2248}
2249
2250Reference< XDatabaseMetaData> ODbaseTable::getMetaData() const
2251{
2252 return getConnection()->getMetaData();
2253}
2254
2255void SAL_CALL ODbaseTable::rename( const OUString& newName )
2256{
2257 ::osl::MutexGuard aGuard(m_aMutex);
2258 checkDisposed(OTableDescriptor_BASE::rBHelper.bDisposed);
2259 if(m_pTables && m_pTables->hasByName(newName))
2260 throw ElementExistException(newName,*this);
2261
2262
2263 renameImpl(newName);
2264
2265 ODbaseTable_BASE::rename(newName);
2266
2267 construct();
2268 if(m_xColumns)
2269 m_xColumns->refresh();
2270}
2271namespace
2272{
2273 void renameFile(file::OConnection const * _pConnection,const OUString& oldName,
2274 const OUString& newName,const OUString& _sExtension)
2275 {
2276 OUString aName = ODbaseTable::getEntry(_pConnection,oldName);
2277 if(aName.isEmpty())
2278 {
2279 OUString aIdent = _pConnection->getContent()->getIdentifier()->getContentIdentifier();
2280 if ( aIdent.lastIndexOf('/') != (aIdent.getLength()-1) )
2281 aIdent += "/";
2282 aIdent += oldName;
2283 aName = aIdent;
2284 }
2285 INetURLObject aURL;
2286 aURL.SetURL(aName);
2287
2288 aURL.setExtension( _sExtension );
2289 OUString sNewName(newName + "." + _sExtension);
2290
2291 try
2292 {
2293 Content aContent(aURL.GetMainURL(INetURLObject::DecodeMechanism::NONE),Reference<XCommandEnvironment>(), comphelper::getProcessComponentContext());
2294
2295 Sequence< PropertyValue > aProps( 1 );
2296 aProps[0].Name = "Title";
2297 aProps[0].Handle = -1; // n/a
2298 aProps[0].Value <<= sNewName;
2299 Sequence< Any > aValues;
2300 aContent.executeCommand( "setPropertyValues",makeAny(aProps) ) >>= aValues;
2301 if(aValues.hasElements() && aValues[0].hasValue())
2302 throw Exception("setPropertyValues returned non-zero", nullptr);
2303 }
2304 catch(const Exception&)
2305 {
2306 throw ElementExistException(newName);
2307 }
2308 }
2309}
2310
2311void ODbaseTable::renameImpl( const OUString& newName )
2312{
2313 ::osl::MutexGuard aGuard(m_aMutex);
2314
2315 FileClose();
2316
2317
2318 renameFile(m_pConnection,m_Name,newName,m_pConnection->getExtension());
2319 if ( HasMemoFields() )
2320 { // delete the memo fields
2321 renameFile(m_pConnection,m_Name,newName,"dbt");
2322 }
2323}
2324
2325void ODbaseTable::addColumn(const Reference< XPropertySet >& _xNewColumn)
2326{
2327 OUString sTempName = createTempFile();
2328
2329 rtl::Reference xNewTable(new ODbaseTable(m_pTables,static_cast<ODbaseConnection*>(m_pConnection)));
2330 xNewTable->setPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_NAME11),makeAny(sTempName));
2331 {
2332 Reference<XAppend> xAppend(xNewTable->getColumns(),UNO_QUERY);
2333 bool bCase = getConnection()->getMetaData()->supportsMixedCaseQuotedIdentifiers();
2334 // copy the structure
2335 for(sal_Int32 i=0;i < m_xColumns->getCount();++i)
2336 {
2337 Reference<XPropertySet> xProp;
2338 m_xColumns->getByIndex(i) >>= xProp;
2339 Reference<XDataDescriptorFactory> xColumn(xProp,UNO_QUERY);
2340 Reference<XPropertySet> xCpy;
2341 if(xColumn.is())
2342 xCpy = xColumn->createDataDescriptor();
2343 else
2344 {
2345 xCpy = new OColumn(bCase);
2346 ::comphelper::copyProperties(xProp,xCpy);
2347 }
2348
2349 xAppend->appendByDescriptor(xCpy);
2350 }
2351 Reference<XPropertySet> xCpy = new OColumn(bCase);
2352 ::comphelper::copyProperties(_xNewColumn,xCpy);
2353 xAppend->appendByDescriptor(xCpy);
2354 }
2355
2356 // construct the new table
2357 if(!xNewTable->CreateImpl())
2358 {
2359 const OUString sError( getConnection()->getResources().getResourceStringWithSubstitution(
2360 STR_COLUMN_NOT_ADDABLEreinterpret_cast<char const *>("STR_COLUMN_NOT_ADDABLE"
"\004" u8"The column '$columnname$' could not be added. May be the file system is write protected."
)
,
2361 "$columnname$", ::comphelper::getString(_xNewColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_NAME11)))
2362 ) );
2363 ::dbtools::throwGenericSQLException( sError, *this );
2364 }
2365
2366 xNewTable->construct();
2367 // copy the data
2368 copyData(xNewTable.get(),xNewTable->m_xColumns->getCount());
2369 // drop the old table
2370 if(DropImpl())
2371 {
2372 xNewTable->renameImpl(m_Name);
2373 // release the temp file
2374 }
2375 xNewTable.clear();
2376
2377 FileClose();
2378 construct();
2379 if(m_xColumns)
2380 m_xColumns->refresh();
2381}
2382
2383void ODbaseTable::dropColumn(sal_Int32 _nPos)
2384{
2385 OUString sTempName = createTempFile();
2386
2387 rtl::Reference xNewTable(new ODbaseTable(m_pTables,static_cast<ODbaseConnection*>(m_pConnection)));
2388 xNewTable->setPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_NAME11),makeAny(sTempName));
2389 {
2390 Reference<XAppend> xAppend(xNewTable->getColumns(),UNO_QUERY);
2391 bool bCase = getConnection()->getMetaData()->supportsMixedCaseQuotedIdentifiers();
2392 // copy the structure
2393 for(sal_Int32 i=0;i < m_xColumns->getCount();++i)
1
Assuming the condition is false
2
Loop condition is false. Execution continues on line 109
2394 {
2395 if(_nPos != i)
2396 {
2397 Reference<XPropertySet> xProp;
2398 m_xColumns->getByIndex(i) >>= xProp;
2399 Reference<XDataDescriptorFactory> xColumn(xProp,UNO_QUERY);
2400 Reference<XPropertySet> xCpy;
2401 if(xColumn.is())
2402 xCpy = xColumn->createDataDescriptor();
2403 else
2404 {
2405 xCpy = new OColumn(bCase);
2406 ::comphelper::copyProperties(xProp,xCpy);
2407 }
2408 xAppend->appendByDescriptor(xCpy);
2409 }
2410 }
2411 }
2412
2413 // construct the new table
2414 if(!xNewTable->CreateImpl())
3
Taking false branch
2415 {
2416 const OUString sError( getConnection()->getResources().getResourceStringWithSubstitution(
2417 STR_COLUMN_NOT_DROPreinterpret_cast<char const *>("STR_COLUMN_NOT_DROP" "\004"
u8"The column at position '$position$' could not be dropped. May be the file system is write protected."
)
,
2418 "$position$", OUString::number(_nPos)
2419 ) );
2420 ::dbtools::throwGenericSQLException( sError, *this );
2421 }
2422 xNewTable->construct();
2423 // copy the data
2424 copyData(xNewTable.get(),_nPos);
4
Calling 'ODbaseTable::copyData'
2425 // drop the old table
2426 if(DropImpl())
2427 xNewTable->renameImpl(m_Name);
2428 // release the temp file
2429
2430 xNewTable.clear();
2431
2432 FileClose();
2433 construct();
2434}
2435
2436OUString ODbaseTable::createTempFile()
2437{
2438 OUString aIdent = m_pConnection->getContent()->getIdentifier()->getContentIdentifier();
2439 if ( aIdent.lastIndexOf('/') != (aIdent.getLength()-1) )
2440 aIdent += "/";
2441
2442 OUString sTempName(aIdent);
2443 OUString sExt("." + m_pConnection->getExtension());
2444 OUString sName(m_Name);
2445 TempFile aTempFile(sName, true, &sExt, &sTempName);
2446 if(!aTempFile.IsValid())
2447 getConnection()->throwGenericSQLException(STR_COULD_NOT_ALTER_TABLEreinterpret_cast<char const *>("STR_COULD_NOT_ALTER_TABLE"
"\004" u8"The table could not be altered.")
, *this);
2448
2449 INetURLObject aURL;
2450 aURL.SetSmartProtocol(INetProtocol::File);
2451 aURL.SetURL(aTempFile.GetURL());
2452
2453 OUString sNewName(aURL.getName().copy(0, aURL.getName().getLength() - sExt.getLength()));
2454
2455 return sNewName;
2456}
2457
2458void ODbaseTable::copyData(ODbaseTable* _pNewTable,sal_Int32 _nPos)
2459{
2460 sal_Int32 nPos = _nPos + 1; // +1 because we always have the bookmark column as well
2461 OValueRefRow aRow = new OValueRefVector(m_xColumns->getCount());
2462 OValueRefRow aInsertRow;
2463 if(_nPos)
5
Assuming '_nPos' is 0
6
Taking false branch
2464 {
2465 aInsertRow = new OValueRefVector(_pNewTable->m_xColumns->getCount());
2466 std::for_each(aInsertRow->begin(),aInsertRow->end(),TSetRefBound(true));
2467 }
2468 else
2469 aInsertRow = aRow;
2470
2471 // we only have to bind the values which we need to copy into the new table
2472 std::for_each(aRow->begin(),aRow->end(),TSetRefBound(true));
2473 if(_nPos
6.1
'_nPos' is 0
&& (_nPos < static_cast<sal_Int32>(aRow->size())))
2474 (*aRow)[nPos]->setBound(false);
2475
2476
2477 sal_Int32 nCurPos;
7
'nCurPos' declared without an initial value
2478 OValueRefVector::const_iterator aIter;
2479 for(sal_uInt32 nRowPos = 0; nRowPos < m_aHeader.nbRecords;++nRowPos)
8
Assuming 'nRowPos' is < field 'nbRecords'
9
Loop condition is true. Entering loop body
2480 {
2481 bool bOk = seekRow( IResultSetHelper::BOOKMARK, nRowPos+1, nCurPos );
10
Passing value via 3rd parameter 'nCurPos'
11
Calling 'ODbaseTable::seekRow'
2482 if ( bOk )
2483 {
2484 bOk = fetchRow( aRow, *m_aColumns, true);
2485 if ( bOk && !aRow->isDeleted() ) // copy only not deleted rows
2486 {
2487 // special handling when pos == 0 then we don't have to distinguish between the two rows
2488 if(_nPos)
2489 {
2490 aIter = aRow->begin()+1;
2491 sal_Int32 nCount = 1;
2492 for(OValueRefVector::iterator aInsertIter = aInsertRow->begin()+1; aIter != aRow->end() && aInsertIter != aInsertRow->end();++aIter,++nCount)
2493 {
2494 if(nPos != nCount)
2495 {
2496 (*aInsertIter)->setValue( (*aIter)->getValue() );
2497 ++aInsertIter;
2498 }
2499 }
2500 }
2501 bOk = _pNewTable->InsertRow(*aInsertRow,_pNewTable->m_xColumns.get());
2502 SAL_WARN_IF(!bOk, "connectivity.drivers", "Row could not be inserted!")do { if (true && (!bOk)) { switch (sal_detail_log_report
(::SAL_DETAIL_LOG_LEVEL_WARN, "connectivity.drivers")) { case
SAL_DETAIL_LOG_ACTION_IGNORE: break; case SAL_DETAIL_LOG_ACTION_LOG
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "Row could not be inserted!") == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_WARN), ("connectivity.drivers"), ("/home/maarten/src/libreoffice/core/connectivity/source/drivers/dbase/DTable.cxx"
":" "2502" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "Row could not be inserted!"), 0); }
else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "Row could not be inserted!"; ::sal::detail::log( (
::SAL_DETAIL_LOG_LEVEL_WARN), ("connectivity.drivers"), ("/home/maarten/src/libreoffice/core/connectivity/source/drivers/dbase/DTable.cxx"
":" "2502" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "Row could not be inserted!") == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_WARN), ("connectivity.drivers"), ("/home/maarten/src/libreoffice/core/connectivity/source/drivers/dbase/DTable.cxx"
":" "2502" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "Row could not be inserted!"), 0); }
else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "Row could not be inserted!"; ::sal::detail::log( (
::SAL_DETAIL_LOG_LEVEL_WARN), ("connectivity.drivers"), ("/home/maarten/src/libreoffice/core/connectivity/source/drivers/dbase/DTable.cxx"
":" "2502" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
2503 }
2504 else
2505 {
2506 SAL_WARN_IF(!bOk, "connectivity.drivers", "Row could not be fetched!")do { if (true && (!bOk)) { switch (sal_detail_log_report
(::SAL_DETAIL_LOG_LEVEL_WARN, "connectivity.drivers")) { case
SAL_DETAIL_LOG_ACTION_IGNORE: break; case SAL_DETAIL_LOG_ACTION_LOG
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "Row could not be fetched!") == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_WARN), ("connectivity.drivers"), ("/home/maarten/src/libreoffice/core/connectivity/source/drivers/dbase/DTable.cxx"
":" "2506" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "Row could not be fetched!"), 0); } else
{ ::std::ostringstream sal_detail_stream; sal_detail_stream <<
"Row could not be fetched!"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("connectivity.drivers"), ("/home/maarten/src/libreoffice/core/connectivity/source/drivers/dbase/DTable.cxx"
":" "2506" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "Row could not be fetched!") == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_WARN), ("connectivity.drivers"), ("/home/maarten/src/libreoffice/core/connectivity/source/drivers/dbase/DTable.cxx"
":" "2506" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "Row could not be fetched!"), 0); } else
{ ::std::ostringstream sal_detail_stream; sal_detail_stream <<
"Row could not be fetched!"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("connectivity.drivers"), ("/home/maarten/src/libreoffice/core/connectivity/source/drivers/dbase/DTable.cxx"
":" "2506" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
2507 }
2508 }
2509 else
2510 {
2511 OSL_ASSERT(false)do { if (true && (!(false))) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/connectivity/source/drivers/dbase/DTable.cxx"
":" "2511" ": "), "OSL_ASSERT: %s", "false"); } } while (false
)
;
2512 }
2513 } // for(sal_uInt32 nRowPos = 0; nRowPos < m_aHeader.db_anz;++nRowPos)
2514}
2515
2516void ODbaseTable::throwInvalidDbaseFormat()
2517{
2518 FileClose();
2519 // no dbase file
2520
2521 const OUString sError( getConnection()->getResources().getResourceStringWithSubstitution(
2522 STR_INVALID_DBASE_FILEreinterpret_cast<char const *>("STR_INVALID_DBASE_FILE"
"\004" u8"The file '$filename$' is an invalid (or unrecognized) dBase file."
)
,
2523 "$filename$", getEntry(m_pConnection,m_Name)
2524 ) );
2525 ::dbtools::throwGenericSQLException( sError, *this );
2526}
2527
2528void ODbaseTable::refreshHeader()
2529{
2530 if ( m_aHeader.nbRecords == 0 )
2531 readHeader();
2532}
2533
2534bool ODbaseTable::seekRow(IResultSetHelper::Movement eCursorPosition, sal_Int32 nOffset, sal_Int32& nCurPos)
2535{
2536 // prepare positioning:
2537 OSL_ENSURE(m_pFileStream,"ODbaseTable::seekRow: FileStream is NULL!")do { if (true && (!(m_pFileStream))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/connectivity/source/drivers/dbase/DTable.cxx"
":" "2537" ": "), "%s", "ODbaseTable::seekRow: FileStream is NULL!"
); } } while (false)
;
12
Taking false branch
13
Loop condition is false. Exiting loop
2538
2539 sal_uInt32 nNumberOfRecords = m_aHeader.nbRecords;
2540 sal_uInt32 nTempPos = m_nFilePos;
2541 m_nFilePos = nCurPos;
14
Assigned value is garbage or undefined
2542
2543 switch(eCursorPosition)
2544 {
2545 case IResultSetHelper::NEXT:
2546 ++m_nFilePos;
2547 break;
2548 case IResultSetHelper::PRIOR:
2549 if (m_nFilePos > 0)
2550 --m_nFilePos;
2551 break;
2552 case IResultSetHelper::FIRST:
2553 m_nFilePos = 1;
2554 break;
2555 case IResultSetHelper::LAST:
2556 m_nFilePos = nNumberOfRecords;
2557 break;
2558 case IResultSetHelper::RELATIVE1:
2559 m_nFilePos = (m_nFilePos + nOffset < 0) ? 0
2560 : static_cast<sal_uInt32>(m_nFilePos + nOffset);
2561 break;
2562 case IResultSetHelper::ABSOLUTE1:
2563 case IResultSetHelper::BOOKMARK:
2564 m_nFilePos = static_cast<sal_uInt32>(nOffset);
2565 break;
2566 }
2567
2568 if (m_nFilePos > static_cast<sal_Int32>(nNumberOfRecords))
2569 m_nFilePos = static_cast<sal_Int32>(nNumberOfRecords) + 1;
2570
2571 if (m_nFilePos == 0 || m_nFilePos == static_cast<sal_Int32>(nNumberOfRecords) + 1)
2572 goto Error;
2573 else
2574 {
2575 std::size_t nEntryLen = m_aHeader.recordLength;
2576
2577 OSL_ENSURE(m_nFilePos >= 1,"SdbDBFCursor::FileFetchRow: invalid record position")do { if (true && (!(m_nFilePos >= 1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/connectivity/source/drivers/dbase/DTable.cxx"
":" "2577" ": "), "%s", "SdbDBFCursor::FileFetchRow: invalid record position"
); } } while (false)
;
2578 std::size_t nPos = m_aHeader.headerLength + static_cast<std::size_t>(m_nFilePos-1) * nEntryLen;
2579
2580 m_pFileStream->Seek(nPos);
2581 if (m_pFileStream->GetError() != ERRCODE_NONEErrCode(0))
2582 goto Error;
2583
2584 std::size_t nRead = m_pFileStream->ReadBytes(m_pBuffer.get(), nEntryLen);
2585 if (nRead != nEntryLen)
2586 {
2587 SAL_WARN("connectivity.drivers", "ODbaseTable::seekRow: short read!")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "connectivity.drivers")) { case SAL_DETAIL_LOG_ACTION_IGNORE
: break; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail
::getResult( ::sal::detail::StreamStart() << "ODbaseTable::seekRow: short read!"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("connectivity.drivers"
), ("/home/maarten/src/libreoffice/core/connectivity/source/drivers/dbase/DTable.cxx"
":" "2587" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "ODbaseTable::seekRow: short read!")
, 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "ODbaseTable::seekRow: short read!"; ::sal::detail::
log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("connectivity.drivers"),
("/home/maarten/src/libreoffice/core/connectivity/source/drivers/dbase/DTable.cxx"
":" "2587" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "ODbaseTable::seekRow: short read!") == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_WARN), ("connectivity.drivers"), ("/home/maarten/src/libreoffice/core/connectivity/source/drivers/dbase/DTable.cxx"
":" "2587" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "ODbaseTable::seekRow: short read!")
, 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "ODbaseTable::seekRow: short read!"; ::sal::detail::
log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("connectivity.drivers"),
("/home/maarten/src/libreoffice/core/connectivity/source/drivers/dbase/DTable.cxx"
":" "2587" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
2588 goto Error;
2589 }
2590 if (m_pFileStream->GetError() != ERRCODE_NONEErrCode(0))
2591 goto Error;
2592 }
2593 goto End;
2594
2595Error:
2596 switch(eCursorPosition)
2597 {
2598 case IResultSetHelper::PRIOR:
2599 case IResultSetHelper::FIRST:
2600 m_nFilePos = 0;
2601 break;
2602 case IResultSetHelper::LAST:
2603 case IResultSetHelper::NEXT:
2604 case IResultSetHelper::ABSOLUTE1:
2605 case IResultSetHelper::RELATIVE1:
2606 if (nOffset > 0)
2607 m_nFilePos = nNumberOfRecords + 1;
2608 else if (nOffset < 0)
2609 m_nFilePos = 0;
2610 break;
2611 case IResultSetHelper::BOOKMARK:
2612 m_nFilePos = nTempPos; // last position
2613 }
2614 return false;
2615
2616End:
2617 nCurPos = m_nFilePos;
2618 return true;
2619}
2620
2621bool ODbaseTable::ReadMemo(std::size_t nBlockNo, ORowSetValue& aVariable)
2622{
2623 m_pMemoStream->Seek(nBlockNo * m_aMemoHeader.db_size);
2624 switch (m_aMemoHeader.db_typ)
2625 {
2626 case MemodBaseIII: // dBase III-Memofield, ends with Ctrl-Z
2627 {
2628 const char cEOF = char(DBF_EOL0x1A);
2629 OStringBuffer aBStr;
2630 static char aBuf[514];
2631 aBuf[512] = 0; // avoid random value
2632 bool bReady = false;
2633
2634 do
2635 {
2636 m_pMemoStream->ReadBytes(&aBuf, 512);
2637
2638 sal_uInt16 i = 0;
2639 while (aBuf[i] != cEOF && ++i < 512)
2640 ;
2641 bReady = aBuf[i] == cEOF;
2642
2643 aBuf[i] = 0;
2644 aBStr.append(aBuf);
2645
2646 } while (!bReady && !m_pMemoStream->eof());
2647
2648 aVariable = OStringToOUString(aBStr.makeStringAndClear(),
2649 m_eEncoding);
2650
2651 } break;
2652 case MemoFoxPro:
2653 case MemodBaseIV: // dBase IV-Memofield with length
2654 {
2655 bool bIsText = true;
2656 char sHeader[4];
2657 m_pMemoStream->ReadBytes(sHeader, 4);
2658 // Foxpro stores text and binary data
2659 if (m_aMemoHeader.db_typ == MemoFoxPro)
2660 {
2661 bIsText = sHeader[3] != 0;
2662 }
2663 else if (static_cast<sal_uInt8>(sHeader[0]) != 0xFF || static_cast<sal_uInt8>(sHeader[1]) != 0xFF || static_cast<sal_uInt8>(sHeader[2]) != 0x08)
2664 {
2665 return false;
2666 }
2667
2668 sal_uInt32 nLength(0);
2669 (*m_pMemoStream).ReadUInt32( nLength );
2670
2671 if (m_aMemoHeader.db_typ == MemodBaseIV)
2672 nLength -= 8;
2673
2674 if ( nLength )
2675 {
2676 if ( bIsText )
2677 {
2678 OStringBuffer aBuffer(read_uInt8s_ToOString(*m_pMemoStream, nLength));
2679 //pad it out with ' ' to expected length on short read
2680 sal_Int32 nRequested = sal::static_int_cast<sal_Int32>(nLength);
2681 comphelper::string::padToLength(aBuffer, nRequested, ' ');
2682 aVariable = OStringToOUString(aBuffer.makeStringAndClear(), m_eEncoding);
2683 } // if ( bIsText )
2684 else
2685 {
2686 css::uno::Sequence< sal_Int8 > aData(nLength);
2687 m_pMemoStream->ReadBytes(aData.getArray(), nLength);
2688 aVariable = aData;
2689 }
2690 } // if ( nLength )
2691 }
2692 }
2693 return true;
2694}
2695
2696bool ODbaseTable::AllocBuffer()
2697{
2698 sal_uInt16 nSize = m_aHeader.recordLength;
2699 SAL_WARN_IF(nSize == 0, "connectivity.drivers", "Size too small")do { if (true && (nSize == 0)) { switch (sal_detail_log_report
(::SAL_DETAIL_LOG_LEVEL_WARN, "connectivity.drivers")) { case
SAL_DETAIL_LOG_ACTION_IGNORE: break; case SAL_DETAIL_LOG_ACTION_LOG
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "Size too small") == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("connectivity.drivers"), ("/home/maarten/src/libreoffice/core/connectivity/source/drivers/dbase/DTable.cxx"
":" "2699" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "Size too small"), 0); } else { ::std
::ostringstream sal_detail_stream; sal_detail_stream <<
"Size too small"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("connectivity.drivers"), ("/home/maarten/src/libreoffice/core/connectivity/source/drivers/dbase/DTable.cxx"
":" "2699" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "Size too small") == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("connectivity.drivers"), ("/home/maarten/src/libreoffice/core/connectivity/source/drivers/dbase/DTable.cxx"
":" "2699" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "Size too small"), 0); } else { ::std
::ostringstream sal_detail_stream; sal_detail_stream <<
"Size too small"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("connectivity.drivers"), ("/home/maarten/src/libreoffice/core/connectivity/source/drivers/dbase/DTable.cxx"
":" "2699" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
2700
2701 if (m_nBufferSize != nSize)
2702 {
2703 m_pBuffer.reset();
2704 }
2705
2706 // if there is no buffer available: allocate:
2707 if (!m_pBuffer && nSize > 0)
2708 {
2709 m_nBufferSize = nSize;
2710 m_pBuffer.reset(new sal_uInt8[m_nBufferSize+1]);
2711 }
2712
2713 return m_pBuffer != nullptr;
2714}
2715
2716bool ODbaseTable::WriteBuffer()
2717{
2718 OSL_ENSURE(m_nFilePos >= 1,"SdbDBFCursor::FileFetchRow: invalid record position")do { if (true && (!(m_nFilePos >= 1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/connectivity/source/drivers/dbase/DTable.cxx"
":" "2718" ": "), "%s", "SdbDBFCursor::FileFetchRow: invalid record position"
); } } while (false)
;
2719
2720 // position on desired record:
2721 std::size_t nPos = m_aHeader.headerLength + static_cast<long>(m_nFilePos-1) * m_aHeader.recordLength;
2722 m_pFileStream->Seek(nPos);
2723 return m_pFileStream->WriteBytes(m_pBuffer.get(), m_aHeader.recordLength) > 0;
2724}
2725
2726sal_Int32 ODbaseTable::getCurrentLastPos() const
2727{
2728 return m_aHeader.nbRecords;
2729}
2730
2731/* vim:set shiftwidth=4 softtabstop=4 expandtab: */