File: | home/maarten/src/libreoffice/core/connectivity/source/drivers/dbase/DTable.cxx |
Warning: | line 2541, column 16 Assigned value is garbage or undefined |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
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 | ||||
62 | using namespace ::comphelper; | |||
63 | using namespace connectivity; | |||
64 | using namespace connectivity::sdbcx; | |||
65 | using namespace connectivity::dbase; | |||
66 | using namespace connectivity::file; | |||
67 | using namespace ::ucbhelper; | |||
68 | using namespace ::utl; | |||
69 | using namespace ::cppu; | |||
70 | using namespace ::dbtools; | |||
71 | using namespace ::com::sun::star::uno; | |||
72 | using namespace ::com::sun::star::ucb; | |||
73 | using namespace ::com::sun::star::beans; | |||
74 | using namespace ::com::sun::star::sdbcx; | |||
75 | using namespace ::com::sun::star::sdbc; | |||
76 | using namespace ::com::sun::star::container; | |||
77 | using namespace ::com::sun::star::lang; | |||
78 | using 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 | ||||
84 | namespace | |||
85 | { | |||
86 | std::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 | */ | |||
101 | void 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 | */ | |||
153 | void 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 | ||||
197 | void 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 | ||||
272 | void 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 | ||||
434 | ODbaseTable::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 | ||||
442 | ODbaseTable::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 | ||||
458 | void 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 | ||||
544 | void 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 | ||||
592 | OUString 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 | ||||
634 | void 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 | ||||
650 | void 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 | ||||
694 | void SAL_CALL ODbaseTable::disposing() | |||
695 | { | |||
696 | OFileTable::disposing(); | |||
697 | ::osl::MutexGuard aGuard(m_aMutex); | |||
698 | m_aColumns = nullptr; | |||
699 | } | |||
700 | ||||
701 | Sequence< 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 | ||||
722 | Any 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 | ||||
733 | Sequence< sal_Int8 > ODbaseTable::getUnoTunnelId() | |||
734 | { | |||
735 | static ::cppu::OImplementationId implId; | |||
736 | ||||
737 | return implId.getImplementationId(); | |||
738 | } | |||
739 | ||||
740 | // css::lang::XUnoTunnel | |||
741 | ||||
742 | sal_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 | ||||
749 | bool 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 | ||||
970 | void 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 | ||||
982 | bool 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 | ||||
1105 | void 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 | |||
1124 | bool 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 | |||
1367 | bool 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 | ||||
1385 | bool 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 | ||||
1433 | bool 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 | ||||
1451 | bool 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 | ||||
1508 | bool 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 | ||||
1538 | bool 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 | ||||
1587 | Reference<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 | ||||
1615 | static double toDouble(const OString& rString) | |||
1616 | { | |||
1617 | return ::rtl::math::stringToDouble( rString, '.', ',' ); | |||
1618 | } | |||
1619 | ||||
1620 | ||||
1621 | bool 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 | ||||
1967 | void 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 | |||
2101 | void 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 | ||||
2120 | void 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 | ||||
2133 | void 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 | ||||
2250 | Reference< XDatabaseMetaData> ODbaseTable::getMetaData() const | |||
2251 | { | |||
2252 | return getConnection()->getMetaData(); | |||
2253 | } | |||
2254 | ||||
2255 | void 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 | } | |||
2271 | namespace | |||
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 | ||||
2311 | void 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 | ||||
2325 | void 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 | ||||
2383 | void 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) | |||
| ||||
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()) | |||
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); | |||
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 | ||||
2436 | OUString 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 | ||||
2458 | void 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) | |||
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
| |||
2474 | (*aRow)[nPos]->setBound(false); | |||
2475 | ||||
2476 | ||||
2477 | sal_Int32 nCurPos; | |||
2478 | OValueRefVector::const_iterator aIter; | |||
2479 | for(sal_uInt32 nRowPos = 0; nRowPos < m_aHeader.nbRecords;++nRowPos) | |||
2480 | { | |||
2481 | bool bOk = seekRow( IResultSetHelper::BOOKMARK, nRowPos+1, nCurPos ); | |||
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 | ||||
2516 | void 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 | ||||
2528 | void ODbaseTable::refreshHeader() | |||
2529 | { | |||
2530 | if ( m_aHeader.nbRecords == 0 ) | |||
2531 | readHeader(); | |||
2532 | } | |||
2533 | ||||
2534 | bool 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); | |||
2538 | ||||
2539 | sal_uInt32 nNumberOfRecords = m_aHeader.nbRecords; | |||
2540 | sal_uInt32 nTempPos = m_nFilePos; | |||
2541 | m_nFilePos = nCurPos; | |||
| ||||
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 | ||||
2595 | Error: | |||
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 | ||||
2616 | End: | |||
2617 | nCurPos = m_nFilePos; | |||
2618 | return true; | |||
2619 | } | |||
2620 | ||||
2621 | bool 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 | ||||
2696 | bool 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 | ||||
2716 | bool 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 | ||||
2726 | sal_Int32 ODbaseTable::getCurrentLastPos() const | |||
2727 | { | |||
2728 | return m_aHeader.nbRecords; | |||
2729 | } | |||
2730 | ||||
2731 | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |