1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: ETable.cxx,v $
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"
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
;
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" );
80 QuotedTokenizedString aHeaderLine
;
81 OFlatConnection
* pConnection
= (OFlatConnection
*)m_pConnection
;
82 const rtl_TextEncoding nEncoding
= m_pConnection
->getTextEncoding();
83 const sal_Bool bHasHeaderLine
= pConnection
->isHeaderLine();
86 while(bRead
&& !aHeaderLine
.Len())
88 bRead
= m_pFileStream
->ReadByteStringLine(aHeaderLine
,nEncoding
);
90 m_nStartRowFilePos
= m_pFileStream
->Tell();
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
;
107 const xub_StrLen nFieldCount
= aHeaderLine
.GetTokenCount(m_cFieldDelimiter
,m_cStringDelimiter
);
109 if(!m_aColumns
.isValid())
110 m_aColumns
= new OSQLColumns();
112 m_aColumns
->get().clear();
115 m_aPrecisions
.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
);
126 const sal_Unicode cDecimalDelimiter
= pConnection
->getDecimalDelimiter();
127 const sal_Unicode cThousandDelimiter
= pConnection
->getThousandDelimiter();
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() )
142 aColumnName
+= String::CreateFromInt32(i
+1);
147 // no column name so ...
149 aColumnName
+= String::CreateFromInt32(i
+1);
152 UINT16 nPrecision
= 0;
155 BOOL bNumeric
= FALSE
;
158 // first without fielddelimiter
160 aFirstLine
.GetTokenSpecial(aField
,nStartPosFirstLine
,m_cFieldDelimiter
,'\0');
161 if (aField
.Len() == 0 ||
162 (m_cStringDelimiter
&& m_cStringDelimiter
== aField
.GetChar(0)))
165 nStartPosFirstLine2
= nStartPosFirstLine
;
170 if ( m_cStringDelimiter
!= '\0' )
171 aFirstLine
.GetTokenSpecial(aField2
,nStartPosFirstLine2
,m_cFieldDelimiter
,m_cStringDelimiter
);
175 if (aField2
.Len() == 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
!= '-' ) ) )
196 if (cDecimalDelimiter
&& c
== cDecimalDelimiter
)
198 nPrecision
= 15; // we have an decimal value
201 } // if (cDecimalDelimiter && c == cDecimalDelimiter)
206 if (nDecimalDelCount
> 1 || nDot
> 1 ) // if there is more than one dot it isn't a number
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
)
226 // jetzt koennte es noch ein Datumsfeld sein
231 nIndex
= m_xNumberFormatter
->detectNumberFormat(::com::sun::star::util::NumberFormat::ALL
,aField2
);
240 sal_Int32 nFlags
= 0;
243 if (cDecimalDelimiter
)
247 eType
= DataType::DECIMAL
;
248 static const ::rtl::OUString
s_sDECIMAL(RTL_CONSTASCII_USTRINGPARAM("DECIMAL"));
249 aTypeName
= s_sDECIMAL
;
253 eType
= DataType::DOUBLE
;
254 static const ::rtl::OUString
s_sDOUBLE(RTL_CONSTASCII_USTRINGPARAM("DOUBLE"));
255 aTypeName
= s_sDOUBLE
;
259 eType
= DataType::INTEGER
;
260 nFlags
= ColumnSearch::BASIC
;
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"));
274 case NUMBERFORMAT_DATETIME
:
275 eType
= DataType::TIMESTAMP
;
277 static const ::rtl::OUString
s_sTIMESTAMP(RTL_CONSTASCII_USTRINGPARAM("TIMESTAMP"));
278 aTypeName
= s_sTIMESTAMP
;
281 case NUMBERFORMAT_TIME
:
282 eType
= DataType::TIME
;
284 static const ::rtl::OUString
s_sTIME(RTL_CONSTASCII_USTRINGPARAM("TIME"));
289 eType
= DataType::VARCHAR
;
290 nPrecision
= 0; // nyi: Daten koennen aber laenger sein!
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
,
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
,
339 ,m_nStartRowFilePos(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
;
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
);
375 m_pFileStream
= createStream_simpleError( aFileName
,STREAM_READ
| STREAM_NOCREATE
| STREAM_SHARE_DENYNONE
);
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
);
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
;
407 static const ::rtl::OUString
s_sSeparator(RTL_CONSTASCII_USTRINGPARAM("/"));
410 sName
= xRow
->getString(1);
411 aURL
.SetSmartProtocol(INET_PROT_FILE
);
412 String sUrl
= m_pConnection
->getURL() + s_sSeparator
+ sName
;
413 aURL
.SetSmartURL( sUrl
);
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();
430 xDir
->beforeFirst(); // move back to before first record
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());
451 m_pColumns
->reFill(aVector
);
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
);
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))
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;
507 ::osl::MutexGuard
aGuard( ::osl::Mutex::getGlobalMutex() );
510 static ::cppu::OImplementationId 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
;
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();
546 xub_StrLen nStartPos
= 0;
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
;
554 m_aCurrentLine
.GetTokenSpecial(aStr
,nStartPos
,m_cFieldDelimiter
,m_cStringDelimiter
);
557 (_rRow
->get())[i
]->setNull();
560 // Laengen je nach Datentyp:
565 nLen
= m_aPrecisions
[i
-1];
566 nType
= m_aTypes
[i
-1];
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
;
576 case DataType::TIMESTAMP
:
582 double nRes
= m_xNumberFormatter
->convertStringToNumber(::com::sun::star::util::NumberFormat::ALL
,aStr
);
587 *(_rRow
->get())[i
] = ::dbtools::DBTypeConversion::toDouble(::dbtools::DBTypeConversion::toDate(nRes
,m_aNullDate
));
589 case DataType::TIMESTAMP
:
590 *(_rRow
->get())[i
] = ::dbtools::DBTypeConversion::toDouble(::dbtools::DBTypeConversion::toDateTime(nRes
,m_aNullDate
));
593 *(_rRow
->get())[i
] = ::dbtools::DBTypeConversion::toDouble(::dbtools::DBTypeConversion::toTime(nRes
));
598 (_rRow
->get())[i
]->setNull();
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
,
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
)
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
)
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 )
638 aStrConverted
= aStr
;
639 if ( cThousandDelimiter
)
640 aStrConverted
.EraseAllChars(cThousandDelimiter
);
642 const double nVal
= ::rtl::math::stringToDouble(aStrConverted
,'.',',',NULL
,NULL
);
645 if ( DataType::DECIMAL
== nType
|| DataType::NUMERIC
== nType
)
646 *(_rRow
->get())[i
] = ::rtl::OUString::valueOf(nVal
);
648 *(_rRow
->get())[i
] = nVal
;
653 // Wert als String in Variable der Row uebernehmen
654 *(_rRow
->get())[i
] = ORowSetValue(aStr
);
658 (_rRow
->get())[i
]->setTypeKind(nType
);
663 void OFlatTable::refreshHeader()
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
:
681 case IResultSetHelper::NEXT
:
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 )
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;
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
));
708 case IResultSetHelper::PRIOR
:
712 TRowPositionsInFile::iterator aPositions
= m_aRowPosToFilePos
[m_nRowPos
];
713 m_nFilePos
= aPositions
->first
;
714 nCurPos
= aPositions
->second
;
715 m_bNeedToReadLine
= true;
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) )
736 while(seekRow(IResultSetHelper::NEXT
,1,nCurPos
)) ; // run through after last row
738 seekRow(IResultSetHelper::PRIOR
,1,nCurPos
);
741 case IResultSetHelper::RELATIVE
:
744 for(sal_Int32 i
= 0;i
<nOffset
;++i
)
745 seekRow(IResultSetHelper::NEXT
,1,nCurPos
);
749 for(sal_Int32 i
= nOffset
;i
;++i
)
750 seekRow(IResultSetHelper::PRIOR
,1,nCurPos
);
753 case IResultSetHelper::ABSOLUTE
:
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) )
767 else if(m_nMaxRowCount
&& nOffset
> m_nMaxRowCount
) // offset is outside the table
769 m_nRowPos
= m_nMaxRowCount
;
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
);
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) )
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
;
809 m_nFilePos
= nOffset
;
810 m_pFileStream
->Seek(nOffset
);
811 if (m_pFileStream
->IsEof() || !readLine(nCurPos
) )
818 //nCurPos = m_nFilePos;
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())
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
;
844 _rnCurrentPos
= m_pFileStream
->Tell();