merge the formfield patch from ooo-build
[ooovba.git] / connectivity / source / drivers / flat / ETable.cxx
blob7fbc472586799c3745a478e08e5b3bc5e6669218
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: ETable.cxx,v $
10 * $Revision: 1.62 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_connectivity.hxx"
34 #include <ctype.h>
35 #include "flat/ETable.hxx"
36 #include <com/sun/star/sdbc/ColumnValue.hpp>
37 #include <com/sun/star/sdbc/DataType.hpp>
38 #include <com/sun/star/ucb/XContentAccess.hpp>
39 #include <svtools/converter.hxx>
40 #include "flat/EConnection.hxx"
41 #include "flat/EColumns.hxx"
42 #include <osl/thread.h>
43 #include <tools/config.hxx>
44 #include <comphelper/sequence.hxx>
45 #include <svtools/zforlist.hxx>
46 #include <rtl/math.hxx>
47 #include <stdio.h> //sprintf
48 #include <comphelper/extract.hxx>
49 #include <comphelper/numbers.hxx>
50 #include "flat/EDriver.hxx"
51 #include <com/sun/star/util/NumberFormat.hpp>
52 #include <unotools/configmgr.hxx>
53 #include <i18npool/mslangid.hxx>
54 #include "connectivity/dbconversion.hxx"
55 #include <comphelper/types.hxx>
56 #include "file/quotedstring.hxx"
57 #include <svtools/syslocale.hxx>
58 #include <rtl/logfile.hxx>
60 using namespace ::comphelper;
61 using namespace connectivity;
62 using namespace connectivity::flat;
63 using namespace connectivity::file;
64 using namespace ::cppu;
65 using namespace utl;
66 using namespace ::com::sun::star::uno;
67 using namespace ::com::sun::star::ucb;
68 using namespace ::com::sun::star::beans;
69 using namespace ::com::sun::star::sdbcx;
70 using namespace ::com::sun::star::sdbc;
71 using namespace ::com::sun::star::container;
72 using namespace ::com::sun::star::lang;
74 // -------------------------------------------------------------------------
75 void OFlatTable::fillColumns(const ::com::sun::star::lang::Locale& _aLocale)
77 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "flat", "Ocke.Janssen@sun.com", "OFlatTable::fillColumns" );
78 BOOL bRead = TRUE;
80 QuotedTokenizedString aHeaderLine;
81 OFlatConnection* pConnection = (OFlatConnection*)m_pConnection;
82 const rtl_TextEncoding nEncoding = m_pConnection->getTextEncoding();
83 const sal_Bool bHasHeaderLine = pConnection->isHeaderLine();
84 if ( bHasHeaderLine )
86 while(bRead && !aHeaderLine.Len())
88 bRead = m_pFileStream->ReadByteStringLine(aHeaderLine,nEncoding);
90 m_nStartRowFilePos = m_pFileStream->Tell();
93 // read first row
94 QuotedTokenizedString aFirstLine;
95 bRead = m_pFileStream->ReadByteStringLine(aFirstLine,nEncoding);
97 if ( !bHasHeaderLine || !aHeaderLine.Len())
99 while(bRead && !aFirstLine.Len())
101 bRead = m_pFileStream->ReadByteStringLine(aFirstLine,nEncoding);
103 // use first row as headerline because we need the number of columns
104 aHeaderLine = aFirstLine;
106 // column count
107 const xub_StrLen nFieldCount = aHeaderLine.GetTokenCount(m_cFieldDelimiter,m_cStringDelimiter);
109 if(!m_aColumns.isValid())
110 m_aColumns = new OSQLColumns();
111 else
112 m_aColumns->get().clear();
114 m_aTypes.clear();
115 m_aPrecisions.clear();
116 m_aScales.clear();
117 // reserve some space
118 m_aColumns->get().reserve(nFieldCount+1);
119 m_aTypes.reserve(nFieldCount+1);
120 m_aPrecisions.reserve(nFieldCount+1);
121 m_aScales.reserve(nFieldCount+1);
123 const sal_Bool bCase = m_pConnection->getMetaData()->storesMixedCaseQuotedIdentifiers();
124 CharClass aCharClass(pConnection->getDriver()->getFactory(),_aLocale);
125 // read description
126 const sal_Unicode cDecimalDelimiter = pConnection->getDecimalDelimiter();
127 const sal_Unicode cThousandDelimiter = pConnection->getThousandDelimiter();
128 String aColumnName;
129 ::rtl::OUString aTypeName;
130 ::comphelper::UStringMixEqual aCase(bCase);
131 xub_StrLen nStartPosHeaderLine = 0; // use for eficient way to get the tokens
132 xub_StrLen nStartPosFirstLine = 0; // use for eficient way to get the tokens
133 xub_StrLen nStartPosFirstLine2 = 0;
134 for (xub_StrLen i = 0; i < nFieldCount; i++)
136 if ( bHasHeaderLine )
138 aHeaderLine.GetTokenSpecial(aColumnName,nStartPosHeaderLine,m_cFieldDelimiter,m_cStringDelimiter);
139 if ( !aColumnName.Len() )
141 aColumnName = 'C';
142 aColumnName += String::CreateFromInt32(i+1);
145 else
147 // no column name so ...
148 aColumnName = 'C';
149 aColumnName += String::CreateFromInt32(i+1);
151 sal_Int32 eType;
152 UINT16 nPrecision = 0;
153 UINT16 nScale = 0;
155 BOOL bNumeric = FALSE;
156 ULONG nIndex = 0;
158 // first without fielddelimiter
159 String aField;
160 aFirstLine.GetTokenSpecial(aField,nStartPosFirstLine,m_cFieldDelimiter,'\0');
161 if (aField.Len() == 0 ||
162 (m_cStringDelimiter && m_cStringDelimiter == aField.GetChar(0)))
164 bNumeric = FALSE;
165 nStartPosFirstLine2 = nStartPosFirstLine;
167 else
169 String aField2;
170 if ( m_cStringDelimiter != '\0' )
171 aFirstLine.GetTokenSpecial(aField2,nStartPosFirstLine2,m_cFieldDelimiter,m_cStringDelimiter);
172 else
173 aField2 = aField;
175 if (aField2.Len() == 0)
177 bNumeric = FALSE;
179 else
181 bNumeric = TRUE;
182 xub_StrLen nDot = 0;
183 xub_StrLen nDecimalDelCount = 0;
184 for (xub_StrLen j = 0; j < aField2.Len(); j++)
186 const sal_Unicode c = aField2.GetChar(j);
187 // nur Ziffern und Dezimalpunkt und Tausender-Trennzeichen?
188 if ( ( !cDecimalDelimiter || c != cDecimalDelimiter ) &&
189 ( !cThousandDelimiter || c != cThousandDelimiter ) &&
190 !aCharClass.isDigit(aField2,j) &&
191 ( j != 0 || (c != '+' && c != '-' ) ) )
193 bNumeric = FALSE;
194 break;
196 if (cDecimalDelimiter && c == cDecimalDelimiter)
198 nPrecision = 15; // we have an decimal value
199 nScale = 2;
200 ++nDecimalDelCount;
201 } // if (cDecimalDelimiter && c == cDecimalDelimiter)
202 if ( c == '.' )
203 ++nDot;
206 if (nDecimalDelCount > 1 || nDot > 1 ) // if there is more than one dot it isn't a number
207 bNumeric = FALSE;
208 if (bNumeric && cThousandDelimiter)
210 // Ist der Trenner richtig angegeben?
211 const String aValue = aField2.GetToken(0,cDecimalDelimiter);
212 for (sal_Int32 j = aValue.Len() - 4; j >= 0; j -= 4)
214 const sal_Unicode c = aValue.GetChar(static_cast<sal_uInt16>(j));
215 // nur Ziffern und Dezimalpunkt und Tausender-Trennzeichen?
216 if (c == cThousandDelimiter && j)
217 continue;
218 else
220 bNumeric = FALSE;
221 break;
226 // jetzt koennte es noch ein Datumsfeld sein
227 if (!bNumeric)
231 nIndex = m_xNumberFormatter->detectNumberFormat(::com::sun::star::util::NumberFormat::ALL,aField2);
233 catch(Exception&)
240 sal_Int32 nFlags = 0;
241 if (bNumeric)
243 if (cDecimalDelimiter)
245 if(nPrecision)
247 eType = DataType::DECIMAL;
248 static const ::rtl::OUString s_sDECIMAL(RTL_CONSTASCII_USTRINGPARAM("DECIMAL"));
249 aTypeName = s_sDECIMAL;
251 else
253 eType = DataType::DOUBLE;
254 static const ::rtl::OUString s_sDOUBLE(RTL_CONSTASCII_USTRINGPARAM("DOUBLE"));
255 aTypeName = s_sDOUBLE;
258 else
259 eType = DataType::INTEGER;
260 nFlags = ColumnSearch::BASIC;
262 else
265 switch (comphelper::getNumberFormatType(m_xNumberFormatter,nIndex))
267 case NUMBERFORMAT_DATE:
268 eType = DataType::DATE;
270 static const ::rtl::OUString s_sDATE(RTL_CONSTASCII_USTRINGPARAM("DATE"));
271 aTypeName = s_sDATE;
273 break;
274 case NUMBERFORMAT_DATETIME:
275 eType = DataType::TIMESTAMP;
277 static const ::rtl::OUString s_sTIMESTAMP(RTL_CONSTASCII_USTRINGPARAM("TIMESTAMP"));
278 aTypeName = s_sTIMESTAMP;
280 break;
281 case NUMBERFORMAT_TIME:
282 eType = DataType::TIME;
284 static const ::rtl::OUString s_sTIME(RTL_CONSTASCII_USTRINGPARAM("TIME"));
285 aTypeName = s_sTIME;
287 break;
288 default:
289 eType = DataType::VARCHAR;
290 nPrecision = 0; // nyi: Daten koennen aber laenger sein!
291 nScale = 0;
293 static const ::rtl::OUString s_sVARCHAR(RTL_CONSTASCII_USTRINGPARAM("VARCHAR"));
294 aTypeName = s_sVARCHAR;
297 nFlags |= ColumnSearch::CHAR;
300 // check if the columname already exists
301 String aAlias(aColumnName);
302 OSQLColumns::Vector::const_iterator aFind = connectivity::find(m_aColumns->get().begin(),m_aColumns->get().end(),aAlias,aCase);
303 sal_Int32 nExprCnt = 0;
304 while(aFind != m_aColumns->get().end())
306 (aAlias = aColumnName) += String::CreateFromInt32(++nExprCnt);
307 aFind = connectivity::find(m_aColumns->get().begin(),m_aColumns->get().end(),aAlias,aCase);
310 sdbcx::OColumn* pColumn = new sdbcx::OColumn(aAlias,aTypeName,::rtl::OUString(),
311 ColumnValue::NULLABLE,
312 nPrecision,
313 nScale,
314 eType,
315 sal_False,
316 sal_False,
317 sal_False,
318 bCase);
319 Reference< XPropertySet> xCol = pColumn;
320 m_aColumns->get().push_back(xCol);
321 m_aTypes.push_back(eType);
322 m_aPrecisions.push_back(nPrecision);
323 m_aScales.push_back(nScale);
325 m_pFileStream->Seek(m_nStartRowFilePos);
327 // -------------------------------------------------------------------------
328 OFlatTable::OFlatTable(sdbcx::OCollection* _pTables,OFlatConnection* _pConnection,
329 const ::rtl::OUString& _Name,
330 const ::rtl::OUString& _Type,
331 const ::rtl::OUString& _Description ,
332 const ::rtl::OUString& _SchemaName,
333 const ::rtl::OUString& _CatalogName
334 ) : OFlatTable_BASE(_pTables,_pConnection,_Name,
335 _Type,
336 _Description,
337 _SchemaName,
338 _CatalogName)
339 ,m_nStartRowFilePos(0)
340 ,m_nRowPos(0)
341 ,m_nMaxRowCount(0)
342 ,m_cStringDelimiter(_pConnection->getStringDelimiter())
343 ,m_cFieldDelimiter(_pConnection->getFieldDelimiter())
344 ,m_bNeedToReadLine(false)
346 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "flat", "Ocke.Janssen@sun.com", "OFlatTable::OFlatTable" );
349 // -----------------------------------------------------------------------------
350 void OFlatTable::construct()
352 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "flat", "Ocke.Janssen@sun.com", "OFlatTable::construct" );
353 SvtSysLocale aLocale;
354 ::com::sun::star::lang::Locale aAppLocale(aLocale.GetLocaleDataPtr()->getLocale());
355 Sequence< ::com::sun::star::uno::Any > aArg(1);
356 aArg[0] <<= aAppLocale;
358 Reference< ::com::sun::star::util::XNumberFormatsSupplier > xSupplier(m_pConnection->getDriver()->getFactory()->createInstanceWithArguments(::rtl::OUString::createFromAscii("com.sun.star.util.NumberFormatsSupplier"),aArg),UNO_QUERY);
359 m_xNumberFormatter = Reference< ::com::sun::star::util::XNumberFormatter >(m_pConnection->getDriver()->getFactory()->createInstance(::rtl::OUString::createFromAscii("com.sun.star.util.NumberFormatter")),UNO_QUERY);
360 m_xNumberFormatter->attachNumberFormatsSupplier(xSupplier);
361 Reference<XPropertySet> xProp(xSupplier->getNumberFormatSettings(),UNO_QUERY);
362 xProp->getPropertyValue(::rtl::OUString::createFromAscii("NullDate")) >>= m_aNullDate;
364 INetURLObject aURL;
365 aURL.SetURL(getEntry());
367 if(aURL.getExtension() != rtl::OUString(m_pConnection->getExtension()))
368 aURL.setExtension(m_pConnection->getExtension());
370 String aFileName = aURL.GetMainURL(INetURLObject::NO_DECODE);
372 m_pFileStream = createStream_simpleError( aFileName,STREAM_READWRITE | STREAM_NOCREATE | STREAM_SHARE_DENYWRITE);
374 if(!m_pFileStream)
375 m_pFileStream = createStream_simpleError( aFileName,STREAM_READ | STREAM_NOCREATE | STREAM_SHARE_DENYNONE);
377 if(m_pFileStream)
379 m_pFileStream->Seek(STREAM_SEEK_TO_END);
380 sal_Int32 nSize = m_pFileStream->Tell();
381 m_pFileStream->Seek(STREAM_SEEK_TO_BEGIN);
383 // Buffersize abhaengig von der Filegroesse
384 m_pFileStream->SetBufferSize(nSize > 1000000 ? 32768 :
385 nSize > 100000 ? 16384 :
386 nSize > 10000 ? 4096 : 1024);
388 fillColumns(aAppLocale);
390 refreshColumns();
393 // -------------------------------------------------------------------------
394 String OFlatTable::getEntry()
396 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "flat", "Ocke.Janssen@sun.com", "OFlatTable::getEntry" );
397 ::rtl::OUString sURL;
400 Reference< XResultSet > xDir = m_pConnection->getDir()->getStaticResultSet();
401 Reference< XRow> xRow(xDir,UNO_QUERY);
402 ::rtl::OUString sName;
403 ::rtl::OUString sExt;
405 INetURLObject aURL;
406 xDir->beforeFirst();
407 static const ::rtl::OUString s_sSeparator(RTL_CONSTASCII_USTRINGPARAM("/"));
408 while(xDir->next())
410 sName = xRow->getString(1);
411 aURL.SetSmartProtocol(INET_PROT_FILE);
412 String sUrl = m_pConnection->getURL() + s_sSeparator + sName;
413 aURL.SetSmartURL( sUrl );
415 // cut the extension
416 sExt = aURL.getExtension();
418 // name and extension have to coincide
419 if ( m_pConnection->matchesExtension( sExt ) )
421 sName = sName.replaceAt(sName.getLength()-(sExt.getLength()+1),sExt.getLength()+1,::rtl::OUString());
422 if ( sName == m_Name )
424 Reference< XContentAccess > xContentAccess( xDir, UNO_QUERY );
425 sURL = xContentAccess->queryContentIdentifierString();
426 break;
430 xDir->beforeFirst(); // move back to before first record
432 catch(Exception&)
434 OSL_ASSERT(0);
436 return sURL.getStr();
438 // -------------------------------------------------------------------------
439 void OFlatTable::refreshColumns()
441 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "flat", "Ocke.Janssen@sun.com", "OFlatTable::refreshColumns" );
442 ::osl::MutexGuard aGuard( m_aMutex );
444 TStringVector aVector;
445 aVector.reserve(m_aColumns->get().size());
447 for(OSQLColumns::Vector::const_iterator aIter = m_aColumns->get().begin();aIter != m_aColumns->get().end();++aIter)
448 aVector.push_back(Reference< XNamed>(*aIter,UNO_QUERY)->getName());
450 if(m_pColumns)
451 m_pColumns->reFill(aVector);
452 else
453 m_pColumns = new OFlatColumns(this,m_aMutex,aVector);
456 // -------------------------------------------------------------------------
457 void SAL_CALL OFlatTable::disposing(void)
459 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "flat", "Ocke.Janssen@sun.com", "OFlatTable::disposing" );
460 OFileTable::disposing();
461 ::osl::MutexGuard aGuard(m_aMutex);
462 m_aColumns = NULL;
464 // -------------------------------------------------------------------------
465 Sequence< Type > SAL_CALL OFlatTable::getTypes( ) throw(RuntimeException)
467 Sequence< Type > aTypes = OTable_TYPEDEF::getTypes();
468 ::std::vector<Type> aOwnTypes;
469 aOwnTypes.reserve(aTypes.getLength());
470 const Type* pBegin = aTypes.getConstArray();
471 const Type* pEnd = pBegin + aTypes.getLength();
472 for(;pBegin != pEnd;++pBegin)
474 if(!(*pBegin == ::getCppuType((const Reference<XKeysSupplier>*)0) ||
475 *pBegin == ::getCppuType((const Reference<XRename>*)0) ||
476 *pBegin == ::getCppuType((const Reference<XIndexesSupplier>*)0) ||
477 *pBegin == ::getCppuType((const Reference<XAlterTable>*)0) ||
478 *pBegin == ::getCppuType((const Reference<XDataDescriptorFactory>*)0)))
480 aOwnTypes.push_back(*pBegin);
483 Type *pTypes = aOwnTypes.empty() ? 0 : &aOwnTypes[0];
484 return Sequence< Type >(pTypes, aOwnTypes.size());
487 // -------------------------------------------------------------------------
488 Any SAL_CALL OFlatTable::queryInterface( const Type & rType ) throw(RuntimeException)
490 if( rType == ::getCppuType((const Reference<XKeysSupplier>*)0) ||
491 rType == ::getCppuType((const Reference<XIndexesSupplier>*)0) ||
492 rType == ::getCppuType((const Reference<XRename>*)0) ||
493 rType == ::getCppuType((const Reference<XAlterTable>*)0) ||
494 rType == ::getCppuType((const Reference<XDataDescriptorFactory>*)0))
495 return Any();
497 Any aRet = OTable_TYPEDEF::queryInterface(rType);
498 return aRet.hasValue() ? aRet : ::cppu::queryInterface(rType,static_cast< ::com::sun::star::lang::XUnoTunnel*> (this));
501 //--------------------------------------------------------------------------
502 Sequence< sal_Int8 > OFlatTable::getUnoTunnelImplementationId()
504 static ::cppu::OImplementationId * pId = 0;
505 if (! pId)
507 ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
508 if (! pId)
510 static ::cppu::OImplementationId aId;
511 pId = &aId;
514 return pId->getImplementationId();
517 // com::sun::star::lang::XUnoTunnel
518 //------------------------------------------------------------------
519 sal_Int64 OFlatTable::getSomething( const Sequence< sal_Int8 > & rId ) throw (RuntimeException)
521 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "flat", "Ocke.Janssen@sun.com", "OFlatTable::getSomething" );
522 return (rId.getLength() == 16 && 0 == rtl_compareMemory(getUnoTunnelImplementationId().getConstArray(), rId.getConstArray(), 16 ) )
523 ? reinterpret_cast< sal_Int64 >( this )
524 : OFlatTable_BASE::getSomething(rId);
526 //------------------------------------------------------------------
527 sal_Bool OFlatTable::fetchRow(OValueRefRow& _rRow,const OSQLColumns & _rCols,sal_Bool bIsTable,sal_Bool bRetrieveData)
529 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "flat", "Ocke.Janssen@sun.com", "OFlatTable::fetchRow" );
530 *(_rRow->get())[0] = m_nFilePos;
532 if (!bRetrieveData)
533 return TRUE;
534 if ( m_bNeedToReadLine )
536 sal_Int32 nCurrentPos = 0;
537 m_pFileStream->Seek(m_nFilePos);
538 readLine(nCurrentPos);
539 m_bNeedToReadLine = false;
542 OFlatConnection* pConnection = (OFlatConnection*)m_pConnection;
543 const sal_Unicode cDecimalDelimiter = pConnection->getDecimalDelimiter();
544 const sal_Unicode cThousandDelimiter = pConnection->getThousandDelimiter();
545 // Felder:
546 xub_StrLen nStartPos = 0;
547 String aStr;
548 OSQLColumns::Vector::const_iterator aIter = _rCols.get().begin();
549 OSQLColumns::Vector::const_iterator aEnd = _rCols.get().end();
550 const OValueRefVector::Vector::size_type nCount = _rRow->get().size();
551 for (OValueRefVector::Vector::size_type i = 1; aIter != aEnd && i < nCount;
552 ++aIter, i++)
554 m_aCurrentLine.GetTokenSpecial(aStr,nStartPos,m_cFieldDelimiter,m_cStringDelimiter);
556 if (aStr.Len() == 0)
557 (_rRow->get())[i]->setNull();
558 else
560 // Laengen je nach Datentyp:
561 sal_Int32 nLen,
562 nType = 0;
563 if(bIsTable)
565 nLen = m_aPrecisions[i-1];
566 nType = m_aTypes[i-1];
568 else
570 Reference< XPropertySet> xColumn = *aIter;
571 xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_PRECISION)) >>= nLen;
572 xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_TYPE)) >>= nType;
574 switch(nType)
576 case DataType::TIMESTAMP:
577 case DataType::DATE:
578 case DataType::TIME:
582 double nRes = m_xNumberFormatter->convertStringToNumber(::com::sun::star::util::NumberFormat::ALL,aStr);
584 switch(nType)
586 case DataType::DATE:
587 *(_rRow->get())[i] = ::dbtools::DBTypeConversion::toDouble(::dbtools::DBTypeConversion::toDate(nRes,m_aNullDate));
588 break;
589 case DataType::TIMESTAMP:
590 *(_rRow->get())[i] = ::dbtools::DBTypeConversion::toDouble(::dbtools::DBTypeConversion::toDateTime(nRes,m_aNullDate));
591 break;
592 default:
593 *(_rRow->get())[i] = ::dbtools::DBTypeConversion::toDouble(::dbtools::DBTypeConversion::toTime(nRes));
596 catch(Exception&)
598 (_rRow->get())[i]->setNull();
600 } break;
601 case DataType::DOUBLE:
602 case DataType::INTEGER:
603 case DataType::DECIMAL: // #99178# OJ
604 case DataType::NUMERIC:
607 String aStrConverted;
608 if ( DataType::INTEGER != nType )
610 sal_Unicode* pData = aStrConverted.AllocBuffer(aStr.Len());
611 const sal_Unicode* pStart = pData;
613 OSL_ENSURE(cDecimalDelimiter && nType != DataType::INTEGER ||
614 !cDecimalDelimiter && nType == DataType::INTEGER,
615 "FalscherTyp");
617 // In Standard-Notation (DezimalPUNKT ohne Tausender-Komma) umwandeln:
618 for (xub_StrLen j = 0; j < aStr.Len(); ++j)
620 const sal_Unicode cChar = aStr.GetChar(j);
621 if (cDecimalDelimiter && cChar == cDecimalDelimiter)
622 *pData++ = '.';
623 //aStrConverted.Append( '.' );
624 else if ( cChar == '.' ) // special case, if decimal seperator isn't '.' we have to put the string after it
625 continue; // #99189# OJ
626 else if (cThousandDelimiter && cChar == cThousandDelimiter)
628 // weglassen
630 else
631 *pData++ = cChar;
632 //aStrConverted.Append(cChar);
633 } // for (xub_StrLen j = 0; j < aStr.Len(); ++j)
634 aStrConverted.ReleaseBufferAccess(xub_StrLen(pData - pStart));
635 } // if ( DataType::INTEGER != nType )
636 else
638 aStrConverted = aStr;
639 if ( cThousandDelimiter )
640 aStrConverted.EraseAllChars(cThousandDelimiter);
642 const double nVal = ::rtl::math::stringToDouble(aStrConverted,'.',',',NULL,NULL);
644 // #99178# OJ
645 if ( DataType::DECIMAL == nType || DataType::NUMERIC == nType )
646 *(_rRow->get())[i] = ::rtl::OUString::valueOf(nVal);
647 else
648 *(_rRow->get())[i] = nVal;
649 } break;
651 default:
653 // Wert als String in Variable der Row uebernehmen
654 *(_rRow->get())[i] = ORowSetValue(aStr);
656 break;
657 } // switch(nType)
658 (_rRow->get())[i]->setTypeKind(nType);
661 return sal_True;
663 void OFlatTable::refreshHeader()
665 m_nRowPos = 0;
667 // -----------------------------------------------------------------------------
668 sal_Bool OFlatTable::seekRow(IResultSetHelper::Movement eCursorPosition, sal_Int32 nOffset, sal_Int32& nCurPos)
670 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "flat", "Ocke.Janssen@sun.com", "OFlatTable::seekRow" );
671 OSL_ENSURE(m_pFileStream,"OFlatTable::seekRow: FileStream is NULL!");
672 // ----------------------------------------------------------
673 // Positionierung vorbereiten:
674 m_nFilePos = nCurPos;
676 switch(eCursorPosition)
678 case IResultSetHelper::FIRST:
679 m_nRowPos = 0;
680 // run through
681 case IResultSetHelper::NEXT:
683 ++m_nRowPos;
684 ::std::map<sal_Int32,TRowPositionsInFile::iterator>::const_iterator aFind = m_aRowPosToFilePos.find(m_nRowPos);
685 m_bNeedToReadLine = aFind != m_aRowPosToFilePos.end();
686 if ( m_bNeedToReadLine )
688 m_nFilePos = aFind->second->first;
689 nCurPos = aFind->second->second;
690 } // if ( m_bNeedToReadLine )
691 else
693 if ( m_nRowPos == 1 )
694 m_nFilePos = m_nStartRowFilePos;
695 m_pFileStream->Seek(m_nFilePos);
696 if ( m_pFileStream->IsEof() || !readLine(nCurPos) /*|| !checkHeaderLine()*/)
698 m_nMaxRowCount = m_nRowPos -1;
699 return sal_False;
700 } // if ( m_pFileStream->IsEof() || !readLine(nCurPos) /*|| !checkHeaderLine()*/)
702 TRowPositionsInFile::iterator aPos = m_aFilePosToEndLinePos.insert(TRowPositionsInFile::value_type(m_nFilePos,nCurPos)).first;
703 m_aRowPosToFilePos.insert(::std::map<sal_Int32,TRowPositionsInFile::iterator>::value_type(m_nRowPos,aPos));
707 break;
708 case IResultSetHelper::PRIOR:
709 --m_nRowPos;
710 if(m_nRowPos > 0)
712 TRowPositionsInFile::iterator aPositions = m_aRowPosToFilePos[m_nRowPos];
713 m_nFilePos = aPositions->first;
714 nCurPos = aPositions->second;
715 m_bNeedToReadLine = true;
717 else
718 m_nRowPos = 0;
720 break;
721 case IResultSetHelper::LAST:
722 if ( m_nMaxRowCount )
724 ::std::map<sal_Int32,TRowPositionsInFile::iterator>::reverse_iterator aLastPos = m_aRowPosToFilePos.rbegin();
725 m_nRowPos = aLastPos->first;
726 m_nFilePos = aLastPos->second->first;
727 nCurPos = aLastPos->second->second;
729 //m_pFileStream->Seek(m_nFilePos);
730 m_bNeedToReadLine = true;
731 //if ( m_pFileStream->IsEof() /*|| !checkHeaderLine()*/ || !readLine(nCurPos) )
732 // return sal_False;
734 else
736 while(seekRow(IResultSetHelper::NEXT,1,nCurPos)) ; // run through after last row
737 // now I know all
738 seekRow(IResultSetHelper::PRIOR,1,nCurPos);
740 break;
741 case IResultSetHelper::RELATIVE:
742 if(nOffset > 0)
744 for(sal_Int32 i = 0;i<nOffset;++i)
745 seekRow(IResultSetHelper::NEXT,1,nCurPos);
747 else if(nOffset < 0)
749 for(sal_Int32 i = nOffset;i;++i)
750 seekRow(IResultSetHelper::PRIOR,1,nCurPos);
752 break;
753 case IResultSetHelper::ABSOLUTE:
755 if(nOffset < 0)
756 nOffset = m_nRowPos + nOffset;
757 ::std::map<sal_Int32,TRowPositionsInFile::iterator>::const_iterator aIter = m_aRowPosToFilePos.find(nOffset);
758 if(aIter != m_aRowPosToFilePos.end())
760 m_nFilePos = aIter->second->first;
761 nCurPos = aIter->second->second;
762 //m_pFileStream->Seek(m_nFilePos);
763 m_bNeedToReadLine = true;
764 //if ( m_pFileStream->IsEof() /*|| !checkHeaderLine()*/ || !readLine(nCurPos) )
765 // return sal_False;
767 else if(m_nMaxRowCount && nOffset > m_nMaxRowCount) // offset is outside the table
769 m_nRowPos = m_nMaxRowCount;
770 return sal_False;
772 else
774 aIter = m_aRowPosToFilePos.upper_bound(nOffset);
775 if(aIter == m_aRowPosToFilePos.end())
777 ::std::map<sal_Int32,TRowPositionsInFile::iterator>::reverse_iterator aLastPos = m_aRowPosToFilePos.rbegin();
778 m_nRowPos = aLastPos->first;
779 nCurPos = m_nFilePos = aLastPos->second->first;
780 while(m_nRowPos != nOffset)
781 seekRow(IResultSetHelper::NEXT,1,nCurPos);
783 else
785 --aIter;
786 m_nRowPos = aIter->first;
787 m_nFilePos = aIter->second->first;
788 nCurPos = aIter->second->second;
789 //m_pFileStream->Seek(m_nFilePos);
790 m_bNeedToReadLine = true;
791 //if ( m_pFileStream->IsEof() /*|| !checkHeaderLine()*/ || !readLine(nCurPos) )
792 // return sal_False;
797 break;
798 case IResultSetHelper::BOOKMARK:
800 TRowPositionsInFile::const_iterator aFind = m_aFilePosToEndLinePos.find(nOffset);
801 m_bNeedToReadLine = aFind != m_aFilePosToEndLinePos.end();
802 if ( m_bNeedToReadLine )
804 m_nFilePos = aFind->first;
805 nCurPos = aFind->second;
807 else
809 m_nFilePos = nOffset;
810 m_pFileStream->Seek(nOffset);
811 if (m_pFileStream->IsEof() || !readLine(nCurPos) )
812 return sal_False;
814 break;
818 //nCurPos = m_nFilePos;
820 return sal_True;
822 // -----------------------------------------------------------------------------
823 sal_Bool OFlatTable::readLine(sal_Int32& _rnCurrentPos)
825 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "flat", "Ocke.Janssen@sun.com", "OFlatTable::readLine" );
826 const rtl_TextEncoding nEncoding = m_pConnection->getTextEncoding();
827 m_pFileStream->ReadByteStringLine(m_aCurrentLine,nEncoding);
828 if (m_pFileStream->IsEof())
829 return sal_False;
831 QuotedTokenizedString sLine = m_aCurrentLine; // check if the string continues on next line
832 while( (sLine.GetString().GetTokenCount(m_cStringDelimiter) % 2) != 1 )
834 m_pFileStream->ReadByteStringLine(sLine,nEncoding);
835 if ( !m_pFileStream->IsEof() )
837 m_aCurrentLine.GetString().Append('\n');
838 m_aCurrentLine.GetString() += sLine.GetString();
839 sLine = m_aCurrentLine;
841 else
842 break;
844 _rnCurrentPos = m_pFileStream->Tell();
845 return sal_True;