/************************************************************** * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * *************************************************************/ // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_connectivity.hxx" #include #include "flat/ETable.hxx" #include #include #include #include #include "flat/EConnection.hxx" #include "flat/EColumns.hxx" #include #include #include #include #include #include //sprintf #include #include #include "flat/EDriver.hxx" #include #include #include #include "connectivity/dbconversion.hxx" #include #include "file/quotedstring.hxx" #include #include using namespace ::comphelper; using namespace connectivity; using namespace connectivity::flat; using namespace connectivity::file; using namespace ::cppu; using namespace utl; using namespace ::com::sun::star::uno; using namespace ::com::sun::star::ucb; using namespace ::com::sun::star::beans; using namespace ::com::sun::star::sdbcx; using namespace ::com::sun::star::sdbc; using namespace ::com::sun::star::container; using namespace ::com::sun::star::lang; // ------------------------------------------------------------------------- void OFlatTable::fillColumns(const ::com::sun::star::lang::Locale& _aLocale) { RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "flat", "Ocke.Janssen@sun.com", "OFlatTable::fillColumns" ); sal_Bool bRead = sal_True; QuotedTokenizedString aHeaderLine; OFlatConnection* pConnection = (OFlatConnection*)m_pConnection; const rtl_TextEncoding nEncoding = m_pConnection->getTextEncoding(); const sal_Bool bHasHeaderLine = pConnection->isHeaderLine(); if ( bHasHeaderLine ) { while(bRead && !aHeaderLine.Len()) { bRead = m_pFileStream->ReadByteStringLine(aHeaderLine,nEncoding); } m_nStartRowFilePos = m_pFileStream->Tell(); } // read first row QuotedTokenizedString aFirstLine; bRead = m_pFileStream->ReadByteStringLine(aFirstLine,nEncoding); if ( !bHasHeaderLine || !aHeaderLine.Len()) { while(bRead && !aFirstLine.Len()) { bRead = m_pFileStream->ReadByteStringLine(aFirstLine,nEncoding); } // use first row as headerline because we need the number of columns aHeaderLine = aFirstLine; } // column count const xub_StrLen nFieldCount = aHeaderLine.GetTokenCount(m_cFieldDelimiter,m_cStringDelimiter); if(!m_aColumns.isValid()) m_aColumns = new OSQLColumns(); else m_aColumns->get().clear(); m_aTypes.clear(); m_aPrecisions.clear(); m_aScales.clear(); // reserve some space m_aColumns->get().reserve(nFieldCount+1); m_aTypes.assign(nFieldCount+1,DataType::SQLNULL); m_aPrecisions.assign(nFieldCount+1,-1); m_aScales.assign(nFieldCount+1,-1); const sal_Bool bCase = m_pConnection->getMetaData()->supportsMixedCaseQuotedIdentifiers(); CharClass aCharClass(pConnection->getDriver()->getFactory(),_aLocale); // read description const sal_Unicode cDecimalDelimiter = pConnection->getDecimalDelimiter(); const sal_Unicode cThousandDelimiter = pConnection->getThousandDelimiter(); String aColumnName; ::rtl::OUString aTypeName; ::comphelper::UStringMixEqual aCase(bCase); ::std::vector aColumnNames,m_aTypeNames; m_aTypeNames.resize(nFieldCount); const sal_Int32 nMaxRowsToScan = pConnection->getMaxRowsToScan(); sal_Int32 nRowCount = 0; do { xub_StrLen nStartPosHeaderLine = 0; // use for eficient way to get the tokens xub_StrLen nStartPosFirstLine = 0; // use for eficient way to get the tokens xub_StrLen nStartPosFirstLine2 = 0; for (xub_StrLen i = 0; i < nFieldCount; i++) { if ( nRowCount == 0) { if ( bHasHeaderLine ) { aHeaderLine.GetTokenSpecial(aColumnName,nStartPosHeaderLine,m_cFieldDelimiter,m_cStringDelimiter); if ( !aColumnName.Len() ) { aColumnName = 'C'; aColumnName += String::CreateFromInt32(i+1); } } else { // no column name so ... aColumnName = 'C'; aColumnName += String::CreateFromInt32(i+1); } aColumnNames.push_back(aColumnName); } impl_fillColumnInfo_nothrow(aFirstLine,nStartPosFirstLine,nStartPosFirstLine2,m_aTypes[i],m_aPrecisions[i],m_aScales[i],m_aTypeNames[i],cDecimalDelimiter,cThousandDelimiter,aCharClass); } ++nRowCount; } while(nRowCount < nMaxRowsToScan && m_pFileStream->ReadByteStringLine(aFirstLine,nEncoding) && !m_pFileStream->IsEof()); for (xub_StrLen i = 0; i < nFieldCount; i++) { // check if the columname already exists String aAlias(aColumnNames[i]); OSQLColumns::Vector::const_iterator aFind = connectivity::find(m_aColumns->get().begin(),m_aColumns->get().end(),aAlias,aCase); sal_Int32 nExprCnt = 0; while(aFind != m_aColumns->get().end()) { (aAlias = aColumnNames[i]) += String::CreateFromInt32(++nExprCnt); aFind = connectivity::find(m_aColumns->get().begin(),m_aColumns->get().end(),aAlias,aCase); } sdbcx::OColumn* pColumn = new sdbcx::OColumn(aAlias,m_aTypeNames[i],::rtl::OUString(),::rtl::OUString(), ColumnValue::NULLABLE, m_aPrecisions[i], m_aScales[i], m_aTypes[i], sal_False, sal_False, sal_False, bCase); Reference< XPropertySet> xCol = pColumn; m_aColumns->get().push_back(xCol); } m_pFileStream->Seek(m_nStartRowFilePos); } void OFlatTable::impl_fillColumnInfo_nothrow(QuotedTokenizedString& aFirstLine,xub_StrLen& nStartPosFirstLine,xub_StrLen& nStartPosFirstLine2 ,sal_Int32& io_nType,sal_Int32& io_nPrecisions,sal_Int32& io_nScales,String& o_sTypeName ,const sal_Unicode cDecimalDelimiter,const sal_Unicode cThousandDelimiter,const CharClass& aCharClass) { if ( io_nType != DataType::VARCHAR ) { sal_Bool bNumeric = io_nType == DataType::SQLNULL || io_nType == DataType::DOUBLE || io_nType == DataType::DECIMAL || io_nType == DataType::INTEGER; sal_uLong nIndex = 0; if ( bNumeric ) { // first without fielddelimiter String aField; aFirstLine.GetTokenSpecial(aField,nStartPosFirstLine,m_cFieldDelimiter,'\0'); if (aField.Len() == 0 || (m_cStringDelimiter && m_cStringDelimiter == aField.GetChar(0))) { bNumeric = sal_False; if ( m_cStringDelimiter != '\0' ) aFirstLine.GetTokenSpecial(aField,nStartPosFirstLine2,m_cFieldDelimiter,m_cStringDelimiter); else nStartPosFirstLine2 = nStartPosFirstLine; } else { String aField2; if ( m_cStringDelimiter != '\0' ) aFirstLine.GetTokenSpecial(aField2,nStartPosFirstLine2,m_cFieldDelimiter,m_cStringDelimiter); else aField2 = aField; if (aField2.Len() == 0) { bNumeric = sal_False; } else { bNumeric = sal_True; xub_StrLen nDot = 0; xub_StrLen nDecimalDelCount = 0; xub_StrLen nSpaceCount = 0; for (xub_StrLen j = 0; j < aField2.Len(); j++) { const sal_Unicode c = aField2.GetChar(j); if ( j == nSpaceCount && m_cFieldDelimiter != 32 && c == 32 ) { ++nSpaceCount; continue; } // nur Ziffern und Dezimalpunkt und Tausender-Trennzeichen? if ( ( !cDecimalDelimiter || c != cDecimalDelimiter ) && ( !cThousandDelimiter || c != cThousandDelimiter ) && !aCharClass.isDigit(aField2,j) && ( j != 0 || (c != '+' && c != '-' ) ) ) { bNumeric = sal_False; break; } if (cDecimalDelimiter && c == cDecimalDelimiter) { io_nPrecisions = 15; // we have an decimal value io_nScales = 2; ++nDecimalDelCount; } // if (cDecimalDelimiter && c == cDecimalDelimiter) if ( c == '.' ) ++nDot; } if (nDecimalDelCount > 1 || nDot > 1 ) // if there is more than one dot it isn't a number bNumeric = sal_False; if (bNumeric && cThousandDelimiter) { // Ist der Trenner richtig angegeben? const String aValue = aField2.GetToken(0,cDecimalDelimiter); for (sal_Int32 j = aValue.Len() - 4; j >= 0; j -= 4) { const sal_Unicode c = aValue.GetChar(static_cast(j)); // nur Ziffern und Dezimalpunkt und Tausender-Trennzeichen? if (c == cThousandDelimiter && j) continue; else { bNumeric = sal_False; break; } } } // jetzt koennte es noch ein Datumsfeld sein if (!bNumeric) { try { nIndex = m_xNumberFormatter->detectNumberFormat(::com::sun::star::util::NumberFormat::ALL,aField2); } catch(Exception&) { } } } } } else if ( io_nType == DataType::DATE || io_nType == DataType::TIMESTAMP || io_nType == DataType::TIME) { String aField; aFirstLine.GetTokenSpecial(aField,nStartPosFirstLine,m_cFieldDelimiter,'\0'); if (aField.Len() == 0 || (m_cStringDelimiter && m_cStringDelimiter == aField.GetChar(0))) { } else { String aField2; if ( m_cStringDelimiter != '\0' ) aFirstLine.GetTokenSpecial(aField2,nStartPosFirstLine2,m_cFieldDelimiter,m_cStringDelimiter); else aField2 = aField; if (aField2.Len() ) { try { nIndex = m_xNumberFormatter->detectNumberFormat(::com::sun::star::util::NumberFormat::ALL,aField2); } catch(Exception&) { } } } } sal_Int32 nFlags = 0; if (bNumeric) { if (cDecimalDelimiter) { if(io_nPrecisions) { io_nType = DataType::DECIMAL; static const ::rtl::OUString s_sDECIMAL(RTL_CONSTASCII_USTRINGPARAM("DECIMAL")); o_sTypeName = s_sDECIMAL; } else { io_nType = DataType::DOUBLE; static const ::rtl::OUString s_sDOUBLE(RTL_CONSTASCII_USTRINGPARAM("DOUBLE")); o_sTypeName = s_sDOUBLE; } } else { io_nType = DataType::INTEGER; io_nPrecisions = 0; io_nScales = 0; } nFlags = ColumnSearch::BASIC; } else { switch (comphelper::getNumberFormatType(m_xNumberFormatter,nIndex)) { case NUMBERFORMAT_DATE: io_nType = DataType::DATE; { static const ::rtl::OUString s_sDATE(RTL_CONSTASCII_USTRINGPARAM("DATE")); o_sTypeName = s_sDATE; } break; case NUMBERFORMAT_DATETIME: io_nType = DataType::TIMESTAMP; { static const ::rtl::OUString s_sTIMESTAMP(RTL_CONSTASCII_USTRINGPARAM("TIMESTAMP")); o_sTypeName = s_sTIMESTAMP; } break; case NUMBERFORMAT_TIME: io_nType = DataType::TIME; { static const ::rtl::OUString s_sTIME(RTL_CONSTASCII_USTRINGPARAM("TIME")); o_sTypeName = s_sTIME; } break; default: io_nType = DataType::VARCHAR; io_nPrecisions = 0; // nyi: Daten koennen aber laenger sein! io_nScales = 0; { static const ::rtl::OUString s_sVARCHAR(RTL_CONSTASCII_USTRINGPARAM("VARCHAR")); o_sTypeName = s_sVARCHAR; } }; nFlags |= ColumnSearch::CHAR; } } else { String aField; aFirstLine.GetTokenSpecial(aField,nStartPosFirstLine,m_cFieldDelimiter,'\0'); if (aField.Len() == 0 || (m_cStringDelimiter && m_cStringDelimiter == aField.GetChar(0))) { if ( m_cStringDelimiter != '\0' ) aFirstLine.GetTokenSpecial(aField,nStartPosFirstLine2,m_cFieldDelimiter,m_cStringDelimiter); else nStartPosFirstLine2 = nStartPosFirstLine; } else { String aField2; if ( m_cStringDelimiter != '\0' ) aFirstLine.GetTokenSpecial(aField2,nStartPosFirstLine2,m_cFieldDelimiter,m_cStringDelimiter); } } } // ------------------------------------------------------------------------- OFlatTable::OFlatTable(sdbcx::OCollection* _pTables,OFlatConnection* _pConnection, const ::rtl::OUString& _Name, const ::rtl::OUString& _Type, const ::rtl::OUString& _Description , const ::rtl::OUString& _SchemaName, const ::rtl::OUString& _CatalogName ) : OFlatTable_BASE(_pTables,_pConnection,_Name, _Type, _Description, _SchemaName, _CatalogName) ,m_nStartRowFilePos(0) ,m_nRowPos(0) ,m_nMaxRowCount(0) ,m_cStringDelimiter(_pConnection->getStringDelimiter()) ,m_cFieldDelimiter(_pConnection->getFieldDelimiter()) ,m_bNeedToReadLine(false) { RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "flat", "Ocke.Janssen@sun.com", "OFlatTable::OFlatTable" ); } // ----------------------------------------------------------------------------- void OFlatTable::construct() { RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "flat", "Ocke.Janssen@sun.com", "OFlatTable::construct" ); SvtSysLocale aLocale; ::com::sun::star::lang::Locale aAppLocale(aLocale.GetLocaleDataPtr()->getLocale()); Sequence< ::com::sun::star::uno::Any > aArg(1); aArg[0] <<= aAppLocale; Reference< ::com::sun::star::util::XNumberFormatsSupplier > xSupplier(m_pConnection->getDriver()->getFactory()->createInstanceWithArguments(::rtl::OUString::createFromAscii("com.sun.star.util.NumberFormatsSupplier"),aArg),UNO_QUERY); m_xNumberFormatter = Reference< ::com::sun::star::util::XNumberFormatter >(m_pConnection->getDriver()->getFactory()->createInstance(::rtl::OUString::createFromAscii("com.sun.star.util.NumberFormatter")),UNO_QUERY); m_xNumberFormatter->attachNumberFormatsSupplier(xSupplier); Reference xProp(xSupplier->getNumberFormatSettings(),UNO_QUERY); xProp->getPropertyValue(::rtl::OUString::createFromAscii("NullDate")) >>= m_aNullDate; INetURLObject aURL; aURL.SetURL(getEntry()); if(aURL.getExtension() != rtl::OUString(m_pConnection->getExtension())) aURL.setExtension(m_pConnection->getExtension()); String aFileName = aURL.GetMainURL(INetURLObject::NO_DECODE); m_pFileStream = createStream_simpleError( aFileName,STREAM_READWRITE | STREAM_NOCREATE | STREAM_SHARE_DENYWRITE); if(!m_pFileStream) m_pFileStream = createStream_simpleError( aFileName,STREAM_READ | STREAM_NOCREATE | STREAM_SHARE_DENYNONE); if(m_pFileStream) { m_pFileStream->Seek(STREAM_SEEK_TO_END); sal_Int32 nSize = m_pFileStream->Tell(); m_pFileStream->Seek(STREAM_SEEK_TO_BEGIN); // Buffersize abhaengig von der Filegroesse m_pFileStream->SetBufferSize(nSize > 1000000 ? 32768 : nSize > 100000 ? 16384 : nSize > 10000 ? 4096 : 1024); fillColumns(aAppLocale); refreshColumns(); } } // ------------------------------------------------------------------------- String OFlatTable::getEntry() { RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "flat", "Ocke.Janssen@sun.com", "OFlatTable::getEntry" ); ::rtl::OUString sURL; try { Reference< XResultSet > xDir = m_pConnection->getDir()->getStaticResultSet(); Reference< XRow> xRow(xDir,UNO_QUERY); ::rtl::OUString sName; ::rtl::OUString sExt; INetURLObject aURL; xDir->beforeFirst(); static const ::rtl::OUString s_sSeparator(RTL_CONSTASCII_USTRINGPARAM("/")); while(xDir->next()) { sName = xRow->getString(1); aURL.SetSmartProtocol(INET_PROT_FILE); String sUrl = m_pConnection->getURL() + s_sSeparator + sName; aURL.SetSmartURL( sUrl ); // cut the extension sExt = aURL.getExtension(); // name and extension have to coincide if ( m_pConnection->matchesExtension( sExt ) ) { if ( sExt.getLength() ) sName = sName.replaceAt(sName.getLength()-(sExt.getLength()+1),sExt.getLength()+1,::rtl::OUString()); if ( sName == m_Name ) { Reference< XContentAccess > xContentAccess( xDir, UNO_QUERY ); sURL = xContentAccess->queryContentIdentifierString(); break; } } } xDir->beforeFirst(); // move back to before first record } catch(Exception&) { OSL_ASSERT(0); } return sURL.getStr(); } // ------------------------------------------------------------------------- void OFlatTable::refreshColumns() { RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "flat", "Ocke.Janssen@sun.com", "OFlatTable::refreshColumns" ); ::osl::MutexGuard aGuard( m_aMutex ); TStringVector aVector; aVector.reserve(m_aColumns->get().size()); for(OSQLColumns::Vector::const_iterator aIter = m_aColumns->get().begin();aIter != m_aColumns->get().end();++aIter) aVector.push_back(Reference< XNamed>(*aIter,UNO_QUERY)->getName()); if(m_pColumns) m_pColumns->reFill(aVector); else m_pColumns = new OFlatColumns(this,m_aMutex,aVector); } // ------------------------------------------------------------------------- void SAL_CALL OFlatTable::disposing(void) { RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "flat", "Ocke.Janssen@sun.com", "OFlatTable::disposing" ); OFileTable::disposing(); ::osl::MutexGuard aGuard(m_aMutex); m_aColumns = NULL; } // ------------------------------------------------------------------------- Sequence< Type > SAL_CALL OFlatTable::getTypes( ) throw(RuntimeException) { Sequence< Type > aTypes = OTable_TYPEDEF::getTypes(); ::std::vector aOwnTypes; aOwnTypes.reserve(aTypes.getLength()); const Type* pBegin = aTypes.getConstArray(); const Type* pEnd = pBegin + aTypes.getLength(); for(;pBegin != pEnd;++pBegin) { if(!(*pBegin == ::getCppuType((const Reference*)0) || *pBegin == ::getCppuType((const Reference*)0) || *pBegin == ::getCppuType((const Reference*)0) || *pBegin == ::getCppuType((const Reference*)0) || *pBegin == ::getCppuType((const Reference*)0))) { aOwnTypes.push_back(*pBegin); } } Type *pTypes = aOwnTypes.empty() ? 0 : &aOwnTypes[0]; return Sequence< Type >(pTypes, aOwnTypes.size()); } // ------------------------------------------------------------------------- Any SAL_CALL OFlatTable::queryInterface( const Type & rType ) throw(RuntimeException) { if( rType == ::getCppuType((const Reference*)0) || rType == ::getCppuType((const Reference*)0) || rType == ::getCppuType((const Reference*)0) || rType == ::getCppuType((const Reference*)0) || rType == ::getCppuType((const Reference*)0)) return Any(); Any aRet = OTable_TYPEDEF::queryInterface(rType); return aRet.hasValue() ? aRet : ::cppu::queryInterface(rType,static_cast< ::com::sun::star::lang::XUnoTunnel*> (this)); } //-------------------------------------------------------------------------- Sequence< sal_Int8 > OFlatTable::getUnoTunnelImplementationId() { static ::cppu::OImplementationId * pId = 0; if (! pId) { ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ); if (! pId) { static ::cppu::OImplementationId aId; pId = &aId; } } return pId->getImplementationId(); } // com::sun::star::lang::XUnoTunnel //------------------------------------------------------------------ sal_Int64 OFlatTable::getSomething( const Sequence< sal_Int8 > & rId ) throw (RuntimeException) { RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "flat", "Ocke.Janssen@sun.com", "OFlatTable::getSomething" ); return (rId.getLength() == 16 && 0 == rtl_compareMemory(getUnoTunnelImplementationId().getConstArray(), rId.getConstArray(), 16 ) ) ? reinterpret_cast< sal_Int64 >( this ) : OFlatTable_BASE::getSomething(rId); } //------------------------------------------------------------------ sal_Bool OFlatTable::fetchRow(OValueRefRow& _rRow,const OSQLColumns & _rCols,sal_Bool bIsTable,sal_Bool bRetrieveData) { RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "flat", "Ocke.Janssen@sun.com", "OFlatTable::fetchRow" ); *(_rRow->get())[0] = m_nFilePos; if (!bRetrieveData) return sal_True; if ( m_bNeedToReadLine ) { sal_Int32 nCurrentPos = 0; m_pFileStream->Seek(m_nFilePos); readLine(nCurrentPos); m_bNeedToReadLine = false; } OFlatConnection* pConnection = (OFlatConnection*)m_pConnection; const sal_Unicode cDecimalDelimiter = pConnection->getDecimalDelimiter(); const sal_Unicode cThousandDelimiter = pConnection->getThousandDelimiter(); // Felder: xub_StrLen nStartPos = 0; String aStr; OSQLColumns::Vector::const_iterator aIter = _rCols.get().begin(); OSQLColumns::Vector::const_iterator aEnd = _rCols.get().end(); const OValueRefVector::Vector::size_type nCount = _rRow->get().size(); for (OValueRefVector::Vector::size_type i = 1; aIter != aEnd && i < nCount; ++aIter, i++) { m_aCurrentLine.GetTokenSpecial(aStr,nStartPos,m_cFieldDelimiter,m_cStringDelimiter); if (aStr.Len() == 0) (_rRow->get())[i]->setNull(); else { // Laengen je nach Datentyp: sal_Int32 nLen, nType = 0; if(bIsTable) { nLen = m_aPrecisions[i-1]; nType = m_aTypes[i-1]; } else { Reference< XPropertySet> xColumn = *aIter; xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_PRECISION)) >>= nLen; xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_TYPE)) >>= nType; } switch(nType) { case DataType::TIMESTAMP: case DataType::DATE: case DataType::TIME: { try { double nRes = m_xNumberFormatter->convertStringToNumber(::com::sun::star::util::NumberFormat::ALL,aStr); switch(nType) { case DataType::DATE: *(_rRow->get())[i] = ::dbtools::DBTypeConversion::toDouble(::dbtools::DBTypeConversion::toDate(nRes,m_aNullDate)); break; case DataType::TIMESTAMP: *(_rRow->get())[i] = ::dbtools::DBTypeConversion::toDouble(::dbtools::DBTypeConversion::toDateTime(nRes,m_aNullDate)); break; default: *(_rRow->get())[i] = ::dbtools::DBTypeConversion::toDouble(::dbtools::DBTypeConversion::toTime(nRes)); } } catch(Exception&) { (_rRow->get())[i]->setNull(); } } break; case DataType::DOUBLE: case DataType::INTEGER: case DataType::DECIMAL: // #99178# OJ case DataType::NUMERIC: { String aStrConverted; if ( DataType::INTEGER != nType ) { sal_Unicode* pData = aStrConverted.AllocBuffer(aStr.Len()); const sal_Unicode* pStart = pData; OSL_ENSURE(cDecimalDelimiter && nType != DataType::INTEGER || !cDecimalDelimiter && nType == DataType::INTEGER, "FalscherTyp"); // In Standard-Notation (DezimalPUNKT ohne Tausender-Komma) umwandeln: for (xub_StrLen j = 0; j < aStr.Len(); ++j) { const sal_Unicode cChar = aStr.GetChar(j); if (cDecimalDelimiter && cChar == cDecimalDelimiter) *pData++ = '.'; //aStrConverted.Append( '.' ); else if ( cChar == '.' ) // special case, if decimal seperator isn't '.' we have to put the string after it continue; // #99189# OJ else if (cThousandDelimiter && cChar == cThousandDelimiter) { // weglassen } else *pData++ = cChar; //aStrConverted.Append(cChar); } // for (xub_StrLen j = 0; j < aStr.Len(); ++j) aStrConverted.ReleaseBufferAccess(xub_StrLen(pData - pStart)); } // if ( DataType::INTEGER != nType ) else { aStrConverted = aStr; if ( cThousandDelimiter ) aStrConverted.EraseAllChars(cThousandDelimiter); } const double nVal = ::rtl::math::stringToDouble(aStrConverted,'.',',',NULL,NULL); // #99178# OJ if ( DataType::DECIMAL == nType || DataType::NUMERIC == nType ) *(_rRow->get())[i] = ::rtl::OUString::valueOf(nVal); else *(_rRow->get())[i] = nVal; } break; default: { // Wert als String in Variable der Row uebernehmen *(_rRow->get())[i] = ORowSetValue(aStr); } break; } // switch(nType) (_rRow->get())[i]->setTypeKind(nType); } } return sal_True; } void OFlatTable::refreshHeader() { m_nRowPos = 0; } // ----------------------------------------------------------------------------- sal_Bool OFlatTable::seekRow(IResultSetHelper::Movement eCursorPosition, sal_Int32 nOffset, sal_Int32& nCurPos) { RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "flat", "Ocke.Janssen@sun.com", "OFlatTable::seekRow" ); OSL_ENSURE(m_pFileStream,"OFlatTable::seekRow: FileStream is NULL!"); // ---------------------------------------------------------- // Positionierung vorbereiten: m_nFilePos = nCurPos; switch(eCursorPosition) { case IResultSetHelper::FIRST: m_nRowPos = 0; // run through case IResultSetHelper::NEXT: { ++m_nRowPos; ::std::map::const_iterator aFind = m_aRowPosToFilePos.find(m_nRowPos); m_bNeedToReadLine = aFind != m_aRowPosToFilePos.end(); if ( m_bNeedToReadLine ) { m_nFilePos = aFind->second->first; nCurPos = aFind->second->second; } // if ( m_bNeedToReadLine ) else { if ( m_nRowPos == 1 ) m_nFilePos = m_nStartRowFilePos; m_pFileStream->Seek(m_nFilePos); if ( m_pFileStream->IsEof() || !readLine(nCurPos) /*|| !checkHeaderLine()*/) { m_nMaxRowCount = m_nRowPos -1; return sal_False; } // if ( m_pFileStream->IsEof() || !readLine(nCurPos) /*|| !checkHeaderLine()*/) TRowPositionsInFile::iterator aPos = m_aFilePosToEndLinePos.insert(TRowPositionsInFile::value_type(m_nFilePos,nCurPos)).first; m_aRowPosToFilePos.insert(::std::map::value_type(m_nRowPos,aPos)); } } break; case IResultSetHelper::PRIOR: --m_nRowPos; if(m_nRowPos > 0) { TRowPositionsInFile::iterator aPositions = m_aRowPosToFilePos[m_nRowPos]; m_nFilePos = aPositions->first; nCurPos = aPositions->second; m_bNeedToReadLine = true; } else m_nRowPos = 0; break; case IResultSetHelper::LAST: if ( m_nMaxRowCount ) { ::std::map::reverse_iterator aLastPos = m_aRowPosToFilePos.rbegin(); m_nRowPos = aLastPos->first; m_nFilePos = aLastPos->second->first; nCurPos = aLastPos->second->second; //m_pFileStream->Seek(m_nFilePos); m_bNeedToReadLine = true; //if ( m_pFileStream->IsEof() /*|| !checkHeaderLine()*/ || !readLine(nCurPos) ) // return sal_False; } else { while(seekRow(IResultSetHelper::NEXT,1,nCurPos)) ; // run through after last row // now I know all seekRow(IResultSetHelper::PRIOR,1,nCurPos); } break; case IResultSetHelper::RELATIVE: if(nOffset > 0) { for(sal_Int32 i = 0;i::const_iterator aIter = m_aRowPosToFilePos.find(nOffset); if(aIter != m_aRowPosToFilePos.end()) { m_nFilePos = aIter->second->first; nCurPos = aIter->second->second; //m_pFileStream->Seek(m_nFilePos); m_bNeedToReadLine = true; //if ( m_pFileStream->IsEof() /*|| !checkHeaderLine()*/ || !readLine(nCurPos) ) // return sal_False; } else if(m_nMaxRowCount && nOffset > m_nMaxRowCount) // offset is outside the table { m_nRowPos = m_nMaxRowCount; return sal_False; } else { aIter = m_aRowPosToFilePos.upper_bound(nOffset); if(aIter == m_aRowPosToFilePos.end()) { ::std::map::reverse_iterator aLastPos = m_aRowPosToFilePos.rbegin(); m_nRowPos = aLastPos->first; nCurPos = m_nFilePos = aLastPos->second->first; while(m_nRowPos != nOffset) seekRow(IResultSetHelper::NEXT,1,nCurPos); } else { --aIter; m_nRowPos = aIter->first; m_nFilePos = aIter->second->first; nCurPos = aIter->second->second; //m_pFileStream->Seek(m_nFilePos); m_bNeedToReadLine = true; //if ( m_pFileStream->IsEof() /*|| !checkHeaderLine()*/ || !readLine(nCurPos) ) // return sal_False; } } } break; case IResultSetHelper::BOOKMARK: { TRowPositionsInFile::const_iterator aFind = m_aFilePosToEndLinePos.find(nOffset); m_bNeedToReadLine = aFind != m_aFilePosToEndLinePos.end(); if ( m_bNeedToReadLine ) { m_nFilePos = aFind->first; nCurPos = aFind->second; } else { m_nFilePos = nOffset; m_pFileStream->Seek(nOffset); if (m_pFileStream->IsEof() || !readLine(nCurPos) ) return sal_False; } break; } } //nCurPos = m_nFilePos; return sal_True; } // ----------------------------------------------------------------------------- sal_Bool OFlatTable::readLine(sal_Int32& _rnCurrentPos) { RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "flat", "Ocke.Janssen@sun.com", "OFlatTable::readLine" ); const rtl_TextEncoding nEncoding = m_pConnection->getTextEncoding(); m_pFileStream->ReadByteStringLine(m_aCurrentLine,nEncoding); if (m_pFileStream->IsEof()) return sal_False; QuotedTokenizedString sLine = m_aCurrentLine; // check if the string continues on next line while( (sLine.GetString().GetTokenCount(m_cStringDelimiter) % 2) != 1 ) { m_pFileStream->ReadByteStringLine(sLine,nEncoding); if ( !m_pFileStream->IsEof() ) { m_aCurrentLine.GetString().Append('\n'); m_aCurrentLine.GetString() += sLine.GetString(); sLine = m_aCurrentLine; } else break; } _rnCurrentPos = m_pFileStream->Tell(); return sal_True; }