summaryrefslogtreecommitdiffstats
path: root/connectivity/source/drivers/flat
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-15 05:54:39 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-15 05:54:39 +0000
commit267c6f2ac71f92999e969232431ba04678e7437e (patch)
tree358c9467650e1d0a1d7227a21dac2e3d08b622b2 /connectivity/source/drivers/flat
parentInitial commit. (diff)
downloadlibreoffice-267c6f2ac71f92999e969232431ba04678e7437e.tar.xz
libreoffice-267c6f2ac71f92999e969232431ba04678e7437e.zip
Adding upstream version 4:24.2.0.upstream/4%24.2.0
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'connectivity/source/drivers/flat')
-rw-r--r--connectivity/source/drivers/flat/ECatalog.cxx58
-rw-r--r--connectivity/source/drivers/flat/EColumns.cxx44
-rw-r--r--connectivity/source/drivers/flat/EConnection.cxx176
-rw-r--r--connectivity/source/drivers/flat/EDatabaseMetaData.cxx242
-rw-r--r--connectivity/source/drivers/flat/EDriver.cxx135
-rw-r--r--connectivity/source/drivers/flat/EPreparedStatement.cxx35
-rw-r--r--connectivity/source/drivers/flat/EResultSet.cxx169
-rw-r--r--connectivity/source/drivers/flat/EStatement.cxx34
-rw-r--r--connectivity/source/drivers/flat/ETable.cxx947
-rw-r--r--connectivity/source/drivers/flat/ETables.cxx44
-rw-r--r--connectivity/source/drivers/flat/flat.component27
11 files changed, 1911 insertions, 0 deletions
diff --git a/connectivity/source/drivers/flat/ECatalog.cxx b/connectivity/source/drivers/flat/ECatalog.cxx
new file mode 100644
index 0000000000..aed042fdd5
--- /dev/null
+++ b/connectivity/source/drivers/flat/ECatalog.cxx
@@ -0,0 +1,58 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+#include <flat/ECatalog.hxx>
+
+#include <flat/EConnection.hxx>
+#include <flat/ETables.hxx>
+#include <com/sun/star/sdbc/XRow.hpp>
+#include <com/sun/star/sdbc/XResultSet.hpp>
+
+using namespace ::com::sun::star::uno;
+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 connectivity::flat;
+
+OFlatCatalog::OFlatCatalog(OFlatConnection* _pCon)
+ : file::OFileCatalog(_pCon)
+{
+}
+
+void OFlatCatalog::refreshTables()
+{
+ ::std::vector<OUString> aVector;
+ Sequence<OUString> aTypes;
+ Reference<XResultSet> xResult = m_xMetaData->getTables(Any(), "%", "%", aTypes);
+
+ if (xResult.is())
+ {
+ Reference<XRow> xRow(xResult, UNO_QUERY);
+ while (xResult->next())
+ aVector.push_back(xRow->getString(3));
+ }
+ if (m_pTables)
+ m_pTables->reFill(aVector);
+ else
+ m_pTables.reset(new OFlatTables(m_xMetaData, *this, m_aMutex, aVector));
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/flat/EColumns.cxx b/connectivity/source/drivers/flat/EColumns.cxx
new file mode 100644
index 0000000000..a9e210321b
--- /dev/null
+++ b/connectivity/source/drivers/flat/EColumns.cxx
@@ -0,0 +1,44 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+#include <flat/EColumns.hxx>
+#include <flat/ETable.hxx>
+
+using namespace connectivity::flat;
+using namespace connectivity;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::sdbcx;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::container;
+
+
+sdbcx::ObjectType OFlatColumns::createObject(const OUString& _rName)
+{
+ OFlatTable* pTable = static_cast<OFlatTable*>(m_pTable);
+ const ::rtl::Reference<OSQLColumns>& aCols = pTable->getTableColumns();
+ OSQLColumns::const_iterator aIter = find(aCols->begin(),aCols->end(),_rName,::comphelper::UStringMixEqual(isCaseSensitive()));
+ sdbcx::ObjectType xRet;
+ if(aIter != aCols->end())
+ xRet = sdbcx::ObjectType(*aIter,UNO_QUERY);
+ return xRet;
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/flat/EConnection.cxx b/connectivity/source/drivers/flat/EConnection.cxx
new file mode 100644
index 0000000000..288a53fa64
--- /dev/null
+++ b/connectivity/source/drivers/flat/EConnection.cxx
@@ -0,0 +1,176 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+#include <flat/EConnection.hxx>
+#include <flat/EDatabaseMetaData.hxx>
+#include <flat/ECatalog.hxx>
+#include <flat/EDriver.hxx>
+#include <flat/EPreparedStatement.hxx>
+#include <flat/EStatement.hxx>
+#include <connectivity/dbexception.hxx>
+#include <sal/log.hxx>
+
+using namespace connectivity::flat;
+using namespace connectivity::file;
+
+typedef connectivity::file::OConnection OConnection_B;
+
+
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::sdbcx;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::lang;
+
+
+OFlatConnection::OFlatConnection(ODriver* _pDriver) : OConnection(_pDriver)
+ ,m_nMaxRowsToScan(50)
+ ,m_bHeaderLine(true)
+ ,m_cFieldDelimiter(';')
+ ,m_cStringDelimiter('"')
+ ,m_cDecimalDelimiter(',')
+ ,m_cThousandDelimiter('.')
+{
+}
+
+OFlatConnection::~OFlatConnection()
+{
+}
+
+// XServiceInfo
+
+IMPLEMENT_SERVICE_INFO(OFlatConnection, "com.sun.star.sdbc.drivers.flat.Connection", "com.sun.star.sdbc.Connection")
+
+
+void OFlatConnection::construct(const OUString& url,const Sequence< PropertyValue >& info)
+{
+ osl_atomic_increment( &m_refCount );
+
+ const PropertyValue *pBegin = info.getConstArray();
+ const PropertyValue *pEnd = pBegin + info.getLength();
+ for(;pBegin != pEnd;++pBegin)
+ {
+ if(pBegin->Name == "HeaderLine")
+ {
+ if( ! (pBegin->Value >>= m_bHeaderLine) )
+ SAL_WARN("connectivity.flat", "construct: unable to get property HeaderLine");
+ }
+ else if(pBegin->Name == "FieldDelimiter")
+ {
+ OUString aVal;
+ if( ! (pBegin->Value >>= aVal) )
+ SAL_WARN("connectivity.flat", "construct: unable to get property FieldDelimiter");
+
+ m_cFieldDelimiter = aVal.toChar();
+ }
+ else if(pBegin->Name == "StringDelimiter")
+ {
+ OUString aVal;
+ if( ! (pBegin->Value >>= aVal) )
+ SAL_WARN("connectivity.flat", "construct: unable to get property StringDelimiter");
+
+ m_cStringDelimiter = aVal.toChar();
+ }
+ else if(pBegin->Name == "DecimalDelimiter")
+ {
+ OUString aVal;
+ if( ! (pBegin->Value >>= aVal) )
+ SAL_WARN("connectivity.flat", "construct: unable to get property DecimalDelimiter");
+
+ m_cDecimalDelimiter = aVal.toChar();
+ }
+ else if(pBegin->Name == "ThousandDelimiter")
+ {
+ OUString aVal;
+ if( ! (pBegin->Value >>= aVal) )
+ SAL_WARN("connectivity.flat", "construct: unable to get property ThousandDelimiter");
+
+ m_cThousandDelimiter = aVal.toChar();
+ }
+ else if ( pBegin->Name == "MaxRowScan" )
+ {
+ pBegin->Value >>= m_nMaxRowsToScan;
+ }
+ }
+
+ osl_atomic_decrement( &m_refCount );
+ OConnection::construct(url,info);
+ m_bShowDeleted = true; // we do not supported rows for this type
+}
+
+Reference< XDatabaseMetaData > SAL_CALL OFlatConnection::getMetaData( )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ checkDisposed(OConnection_B::rBHelper.bDisposed);
+
+
+ Reference< XDatabaseMetaData > xMetaData = m_xMetaData;
+ if(!xMetaData.is())
+ {
+ xMetaData = new OFlatDatabaseMetaData(this);
+ m_xMetaData = xMetaData;
+ }
+
+ return xMetaData;
+}
+
+css::uno::Reference< XTablesSupplier > OFlatConnection::createCatalog()
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ Reference< XTablesSupplier > xTab = m_xCatalog;
+ if(!xTab.is())
+ {
+ xTab = new OFlatCatalog(this);
+ m_xCatalog = xTab;
+ }
+ return xTab;
+}
+
+Reference< XStatement > SAL_CALL OFlatConnection::createStatement( )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ checkDisposed(OConnection_B::rBHelper.bDisposed);
+
+ rtl::Reference<OFlatStatement> pStmt = new OFlatStatement(this);
+ m_aStatements.push_back(WeakReferenceHelper(*pStmt));
+ return pStmt;
+}
+
+Reference< XPreparedStatement > SAL_CALL OFlatConnection::prepareStatement( const OUString& sql )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ checkDisposed(OConnection_B::rBHelper.bDisposed);
+
+ rtl::Reference<OFlatPreparedStatement> pStmt = new OFlatPreparedStatement(this);
+ pStmt->construct(sql);
+ m_aStatements.push_back(WeakReferenceHelper(*pStmt));
+ return pStmt;
+}
+
+Reference< XPreparedStatement > SAL_CALL OFlatConnection::prepareCall( const OUString& /*sql*/ )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ checkDisposed(OConnection_B::rBHelper.bDisposed);
+
+ ::dbtools::throwFeatureNotImplementedSQLException( "XConnection::prepareCall", *this );
+ return nullptr;
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/flat/EDatabaseMetaData.cxx b/connectivity/source/drivers/flat/EDatabaseMetaData.cxx
new file mode 100644
index 0000000000..729b55ef9e
--- /dev/null
+++ b/connectivity/source/drivers/flat/EDatabaseMetaData.cxx
@@ -0,0 +1,242 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+#include <flat/EDatabaseMetaData.hxx>
+#include <com/sun/star/sdbc/ColumnSearch.hpp>
+#include <com/sun/star/sdbc/DataType.hpp>
+#include <com/sun/star/sdbc/ColumnValue.hpp>
+#include <com/sun/star/sdbc/SQLException.hpp>
+#include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
+#include <FDatabaseMetaDataResultSet.hxx>
+#include <comphelper/types.hxx>
+
+using namespace ::comphelper;
+
+using namespace connectivity;
+using namespace connectivity::flat;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::sdbcx;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::container;
+
+
+OFlatDatabaseMetaData::OFlatDatabaseMetaData(::connectivity::file::OConnection* _pCon) :ODatabaseMetaData(_pCon)
+{
+}
+
+OFlatDatabaseMetaData::~OFlatDatabaseMetaData()
+{
+}
+
+Reference< XResultSet > OFlatDatabaseMetaData::impl_getTypeInfo_throw( )
+{
+ rtl::Reference<::connectivity::ODatabaseMetaDataResultSet> pResult = new ::connectivity::ODatabaseMetaDataResultSet(::connectivity::ODatabaseMetaDataResultSet::eTypeInfo);
+
+ static ODatabaseMetaDataResultSet::ORows aRows = []()
+ {
+ ODatabaseMetaDataResultSet::ORows tmp;
+ ODatabaseMetaDataResultSet::ORow aRow
+ {
+ ODatabaseMetaDataResultSet::getEmptyValue() ,
+ new ORowSetValueDecorator(OUString("CHAR")) ,
+ new ORowSetValueDecorator(DataType::CHAR) ,
+ new ORowSetValueDecorator(sal_Int32(254)) ,
+ ODatabaseMetaDataResultSet::getQuoteValue() ,
+ ODatabaseMetaDataResultSet::getQuoteValue() ,
+ ODatabaseMetaDataResultSet::getEmptyValue() ,
+ new ORowSetValueDecorator(sal_Int32(ColumnValue::NULLABLE)) ,
+ ODatabaseMetaDataResultSet::get1Value() ,
+ new ORowSetValueDecorator(sal_Int32(ColumnSearch::CHAR)) ,
+ ODatabaseMetaDataResultSet::get1Value() ,
+ ODatabaseMetaDataResultSet::get0Value() ,
+ ODatabaseMetaDataResultSet::get0Value() ,
+ ODatabaseMetaDataResultSet::getEmptyValue() ,
+ ODatabaseMetaDataResultSet::get0Value() ,
+ ODatabaseMetaDataResultSet::get0Value() ,
+ ODatabaseMetaDataResultSet::getEmptyValue() ,
+ ODatabaseMetaDataResultSet::getEmptyValue() ,
+ new ORowSetValueDecorator(sal_Int32(10))
+ };
+
+ tmp.push_back(aRow);
+
+ aRow[1] = new ORowSetValueDecorator(OUString("VARCHAR"));
+ aRow[2] = new ORowSetValueDecorator(DataType::VARCHAR);
+ aRow[4] = ODatabaseMetaDataResultSet::getQuoteValue();
+ aRow[5] = ODatabaseMetaDataResultSet::getQuoteValue();
+ tmp.push_back(aRow);
+
+
+ aRow[1] = new ORowSetValueDecorator(OUString("LONGVARCHAR"));
+ aRow[2] = new ORowSetValueDecorator(DataType::LONGVARCHAR);
+ aRow[3] = new ORowSetValueDecorator(sal_Int32(65535));
+ aRow[4] = ODatabaseMetaDataResultSet::getQuoteValue();
+ aRow[5] = ODatabaseMetaDataResultSet::getQuoteValue();
+ tmp.push_back(aRow);
+
+ aRow[1] = new ORowSetValueDecorator(OUString("DATE"));
+ aRow[2] = new ORowSetValueDecorator(DataType::DATE);
+ aRow[3] = new ORowSetValueDecorator(sal_Int32(10));
+ aRow[4] = ODatabaseMetaDataResultSet::getQuoteValue();
+ aRow[5] = ODatabaseMetaDataResultSet::getQuoteValue();
+ tmp.push_back(aRow);
+
+ aRow[1] = new ORowSetValueDecorator(OUString("TIME"));
+ aRow[2] = new ORowSetValueDecorator(DataType::TIME);
+ aRow[3] = new ORowSetValueDecorator(sal_Int32(8));
+ aRow[4] = ODatabaseMetaDataResultSet::getQuoteValue();
+ aRow[5] = ODatabaseMetaDataResultSet::getQuoteValue();
+ tmp.push_back(aRow);
+
+ aRow[1] = new ORowSetValueDecorator(OUString("TIMESTAMP"));
+ aRow[2] = new ORowSetValueDecorator(DataType::TIMESTAMP);
+ aRow[3] = new ORowSetValueDecorator(sal_Int32(19));
+ aRow[4] = ODatabaseMetaDataResultSet::getQuoteValue();
+ aRow[5] = ODatabaseMetaDataResultSet::getQuoteValue();
+ tmp.push_back(aRow);
+
+ aRow[1] = new ORowSetValueDecorator(OUString("BOOL"));
+ aRow[2] = new ORowSetValueDecorator(DataType::BIT);
+ aRow[3] = ODatabaseMetaDataResultSet::get1Value();
+ aRow[9] = ODatabaseMetaDataResultSet::getBasicValue();
+ tmp.push_back(aRow);
+
+ aRow[1] = new ORowSetValueDecorator(OUString("DECIMAL"));
+ aRow[2] = new ORowSetValueDecorator(DataType::DECIMAL);
+ aRow[3] = new ORowSetValueDecorator(sal_Int32(20));
+ aRow[15] = new ORowSetValueDecorator(sal_Int32(15));
+ tmp.push_back(aRow);
+
+ aRow[1] = new ORowSetValueDecorator(OUString("DOUBLE"));
+ aRow[2] = new ORowSetValueDecorator(DataType::DOUBLE);
+ aRow[3] = new ORowSetValueDecorator(sal_Int32(20));
+ aRow[15] = ODatabaseMetaDataResultSet::get0Value();
+ tmp.push_back(aRow);
+
+ aRow[1] = new ORowSetValueDecorator(OUString("NUMERIC"));
+ aRow[2] = new ORowSetValueDecorator(DataType::NUMERIC);
+ aRow[3] = new ORowSetValueDecorator(sal_Int32(20));
+ aRow[15] = new ORowSetValueDecorator(sal_Int32(20));
+ tmp.push_back(aRow);
+
+ return tmp;
+ }();
+
+ pResult->setRows(std::move(aRows));
+ return pResult;
+}
+
+Reference< XResultSet > SAL_CALL OFlatDatabaseMetaData::getColumns(
+ const Any& /*catalog*/, const OUString& /*schemaPattern*/, const OUString& tableNamePattern,
+ const OUString& columnNamePattern )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ Reference< XTablesSupplier > xTables = m_pConnection->createCatalog();
+ if(!xTables.is())
+ throw SQLException();
+
+ Reference< XNameAccess> xNames = xTables->getTables();
+ if(!xNames.is())
+ throw SQLException();
+
+ ODatabaseMetaDataResultSet::ORows aRows;
+ ODatabaseMetaDataResultSet::ORow aRow(19);
+ aRow[10] = new ORowSetValueDecorator(sal_Int32(10));
+ Sequence< OUString> aTabNames(xNames->getElementNames());
+ const OUString* pTabBegin = aTabNames.getConstArray();
+ const OUString* pTabEnd = pTabBegin + aTabNames.getLength();
+ for(;pTabBegin != pTabEnd;++pTabBegin)
+ {
+ if(match(tableNamePattern,*pTabBegin,'\0'))
+ {
+ Reference< XColumnsSupplier> xTable(
+ xNames->getByName(*pTabBegin), css::uno::UNO_QUERY);
+ aRow[3] = new ORowSetValueDecorator(*pTabBegin);
+
+ Reference< XNameAccess> xColumns = xTable->getColumns();
+ if(!xColumns.is())
+ throw SQLException();
+
+ Sequence< OUString> aColNames(xColumns->getElementNames());
+
+ const OUString* pBegin = aColNames.getConstArray();
+ const OUString* pEnd = pBegin + aColNames.getLength();
+ Reference< XPropertySet> xColumn;
+ for(sal_Int32 i=1;pBegin != pEnd;++pBegin,++i)
+ {
+ if(match(columnNamePattern,*pBegin,'\0'))
+ {
+ aRow[4] = new ORowSetValueDecorator(*pBegin);
+
+ xColumn.set(
+ xColumns->getByName(*pBegin), css::uno::UNO_QUERY);
+ OSL_ENSURE(xColumn.is(),"Columns contains a column who isn't a fastpropertyset!");
+ aRow[5] = new ORowSetValueDecorator(getINT32(xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_TYPE))));
+ aRow[6] = new ORowSetValueDecorator(getString(xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_TYPENAME))));
+ aRow[7] = new ORowSetValueDecorator(getINT32(xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_PRECISION))));
+ aRow[9] = new ORowSetValueDecorator(getINT32(xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_SCALE))));
+ aRow[11] = new ORowSetValueDecorator(getINT32(xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_ISNULLABLE))));
+ aRow[13] = new ORowSetValueDecorator(getString(xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_DEFAULTVALUE))));
+
+ switch(aRow[5]->getValue().getInt32())
+ {
+ case DataType::CHAR:
+ case DataType::VARCHAR:
+ aRow[16] = new ORowSetValueDecorator(sal_Int32(254));
+ break;
+ case DataType::LONGVARCHAR:
+ aRow[16] = new ORowSetValueDecorator(sal_Int32(65535));
+ break;
+ default:
+ aRow[16] = new ORowSetValueDecorator(sal_Int32(0));
+ }
+ aRow[17] = new ORowSetValueDecorator(i);
+ switch(aRow[11]->getValue().getInt32())
+ {
+ case ColumnValue::NO_NULLS:
+ aRow[18] = new ORowSetValueDecorator(OUString("NO"));
+ break;
+ case ColumnValue::NULLABLE:
+ aRow[18] = new ORowSetValueDecorator(OUString("YES"));
+ break;
+ default:
+ aRow[18] = new ORowSetValueDecorator(OUString());
+ }
+ aRows.push_back(aRow);
+ }
+ }
+ }
+ }
+
+ rtl::Reference<::connectivity::ODatabaseMetaDataResultSet> pResult = new ::connectivity::ODatabaseMetaDataResultSet(::connectivity::ODatabaseMetaDataResultSet::eColumns);
+ pResult->setRows(std::move(aRows));
+
+ return pResult;
+}
+
+OUString SAL_CALL OFlatDatabaseMetaData::getURL( )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ return "sdbc:flat:" + m_pConnection->getURL();
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/flat/EDriver.cxx b/connectivity/source/drivers/flat/EDriver.cxx
new file mode 100644
index 0000000000..51e3576115
--- /dev/null
+++ b/connectivity/source/drivers/flat/EDriver.cxx
@@ -0,0 +1,135 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+#include <flat/EDriver.hxx>
+#include <flat/EConnection.hxx>
+#include <com/sun/star/lang/DisposedException.hpp>
+#include <connectivity/dbexception.hxx>
+#include <comphelper/sequence.hxx>
+#include <strings.hrc>
+#include <resource/sharedresources.hxx>
+
+
+using namespace connectivity::flat;
+using namespace connectivity::file;
+using namespace css::uno;
+using namespace css::beans;
+using namespace css::sdbcx;
+using namespace css::sdbc;
+using namespace css::lang;
+
+
+// XServiceInfo
+
+OUString SAL_CALL ODriver::getImplementationName( )
+{
+ return "com.sun.star.comp.sdbc.flat.ODriver";
+}
+
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+connectivity_flat_ODriver(
+ css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const&)
+{
+ rtl::Reference<ODriver> ret;
+ try {
+ ret = new ODriver(context);
+ } catch (...) {
+ }
+ if (ret)
+ ret->acquire();
+ return getXWeak(ret.get());
+}
+
+Reference< XConnection > SAL_CALL ODriver::connect( const OUString& url, const Sequence< PropertyValue >& info )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ if (ODriver_BASE::rBHelper.bDisposed)
+ throw DisposedException();
+
+ if ( ! acceptsURL(url) )
+ return nullptr;
+
+ rtl::Reference<OFlatConnection> pCon = new OFlatConnection(this);
+ pCon->construct(url,info);
+ m_xConnections.push_back(WeakReferenceHelper(*pCon));
+
+ return pCon;
+}
+
+sal_Bool SAL_CALL ODriver::acceptsURL( const OUString& url )
+{
+ return url.startsWith("sdbc:flat:");
+}
+
+Sequence< DriverPropertyInfo > SAL_CALL ODriver::getPropertyInfo( const OUString& url, const Sequence< PropertyValue >& info )
+{
+ if ( acceptsURL(url) )
+ {
+ Sequence< OUString > aBoolean { "0", "1" };
+
+ std::vector< DriverPropertyInfo > aDriverInfo
+ {
+ {
+ "FieldDelimiter"
+ ,"Field separator."
+ ,false
+ ,{}
+ ,{}
+ },
+ {
+ "HeaderLine"
+ ,"Text contains headers."
+ ,false
+ ,"0"
+ ,aBoolean
+ },
+ {
+ "StringDelimiter"
+ ,"Text separator."
+ ,false
+ ,"0"
+ ,aBoolean
+ },
+ {
+ "DecimalDelimiter"
+ ,"Decimal separator."
+ ,false
+ ,"0"
+ ,aBoolean
+ },
+ {
+ "ThousandDelimiter"
+ ,"Thousands separator."
+ ,false
+ ,"0"
+ ,aBoolean
+ }
+ };
+ return ::comphelper::concatSequences(OFileDriver::getPropertyInfo(url,info ),
+ Sequence< DriverPropertyInfo >(aDriverInfo.data(),aDriverInfo.size()));
+ }
+ ::connectivity::SharedResources aResources;
+ const OUString sMessage = aResources.getResourceString(STR_URI_SYNTAX_ERROR);
+ ::dbtools::throwGenericSQLException(sMessage ,*this);
+ return Sequence< DriverPropertyInfo >();
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/flat/EPreparedStatement.cxx b/connectivity/source/drivers/flat/EPreparedStatement.cxx
new file mode 100644
index 0000000000..f4095ac2c0
--- /dev/null
+++ b/connectivity/source/drivers/flat/EPreparedStatement.cxx
@@ -0,0 +1,35 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+#include <flat/EPreparedStatement.hxx>
+#include <flat/EResultSet.hxx>
+
+using namespace connectivity::flat;
+using namespace connectivity::file;
+using namespace ::com::sun::star::uno;
+
+rtl::Reference<OResultSet> OFlatPreparedStatement::createResultSet()
+{
+ return new OFlatResultSet(this, m_aSQLIterator);
+}
+
+IMPLEMENT_SERVICE_INFO(OFlatPreparedStatement, "com.sun.star.sdbc.driver.flat.PreparedStatement",
+ "com.sun.star.sdbc.PreparedStatement");
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/flat/EResultSet.cxx b/connectivity/source/drivers/flat/EResultSet.cxx
new file mode 100644
index 0000000000..9d1975c77e
--- /dev/null
+++ b/connectivity/source/drivers/flat/EResultSet.cxx
@@ -0,0 +1,169 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+#include <com/sun/star/sdbcx/CompareBookmark.hpp>
+#include <com/sun/star/sdbcx/XDeleteRows.hpp>
+#include <flat/EResultSet.hxx>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <comphelper/sequence.hxx>
+#include <comphelper/types.hxx>
+#include <cppuhelper/supportsservice.hxx>
+
+using namespace ::comphelper;
+
+using namespace connectivity::flat;
+using namespace connectivity::file;
+using namespace ::cppu;
+using namespace com::sun::star::uno;
+using namespace com::sun::star::lang;
+using namespace com::sun::star::beans;
+using namespace com::sun::star::sdbc;
+using namespace com::sun::star::sdbcx;
+
+
+OFlatResultSet::OFlatResultSet( OStatement_Base* pStmt,connectivity::OSQLParseTreeIterator& _aSQLIterator)
+ : file::OResultSet(pStmt,_aSQLIterator)
+ ,m_bBookmarkable(true)
+{
+ registerProperty(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_ISBOOKMARKABLE), PROPERTY_ID_ISBOOKMARKABLE, PropertyAttribute::READONLY,&m_bBookmarkable, cppu::UnoType<bool>::get());
+}
+
+OUString SAL_CALL OFlatResultSet::getImplementationName( )
+{
+ return "com.sun.star.sdbcx.flat.ResultSet";
+}
+
+Sequence< OUString > SAL_CALL OFlatResultSet::getSupportedServiceNames( )
+{
+ return { "com.sun.star.sdbc.ResultSet", "com.sun.star.sdbcx.ResultSet" };
+}
+
+sal_Bool SAL_CALL OFlatResultSet::supportsService( const OUString& _rServiceName )
+{
+ return cppu::supportsService(this, _rServiceName);
+}
+
+Any SAL_CALL OFlatResultSet::queryInterface( const Type & rType )
+{
+ if(rType == cppu::UnoType<XDeleteRows>::get()|| rType == cppu::UnoType<XResultSetUpdate>::get()
+ || rType == cppu::UnoType<XRowUpdate>::get())
+ return Any();
+
+ const Any aRet = OResultSet::queryInterface(rType);
+ return aRet.hasValue() ? aRet : OFlatResultSet_BASE::queryInterface(rType);
+}
+
+Sequence< Type > SAL_CALL OFlatResultSet::getTypes( )
+{
+ Sequence< Type > aTypes = OResultSet::getTypes();
+ std::vector<Type> aOwnTypes;
+ aOwnTypes.reserve(aTypes.getLength());
+ const Type* pBegin = aTypes.getConstArray();
+ const Type* pEnd = pBegin + aTypes.getLength();
+ for(;pBegin != pEnd;++pBegin)
+ {
+ if(!(*pBegin == cppu::UnoType<XDeleteRows>::get()||
+ *pBegin == cppu::UnoType<XResultSetUpdate>::get()||
+ *pBegin == cppu::UnoType<XRowUpdate>::get()))
+ {
+ aOwnTypes.push_back(*pBegin);
+ }
+ }
+ Sequence< Type > aRet(aOwnTypes.data(), aOwnTypes.size());
+ return ::comphelper::concatSequences(aRet,OFlatResultSet_BASE::getTypes());
+}
+
+
+// XRowLocate
+Any SAL_CALL OFlatResultSet::getBookmark( )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
+
+ return Any((*m_aRow)[0]->getValue().getInt32());
+}
+
+sal_Bool SAL_CALL OFlatResultSet::moveToBookmark( const Any& bookmark )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
+
+
+ m_bRowDeleted = m_bRowInserted = m_bRowUpdated = false;
+
+ return Move(IResultSetHelper::BOOKMARK,comphelper::getINT32(bookmark),true);
+}
+
+sal_Bool SAL_CALL OFlatResultSet::moveRelativeToBookmark( const Any& bookmark, sal_Int32 rows )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
+
+ m_bRowDeleted = m_bRowInserted = m_bRowUpdated = false;
+
+ Move(IResultSetHelper::BOOKMARK,comphelper::getINT32(bookmark),false);
+
+ return relative(rows);
+}
+
+
+sal_Int32 SAL_CALL OFlatResultSet::compareBookmarks( const Any& lhs, const Any& rhs )
+{
+ return (lhs == rhs) ? CompareBookmark::EQUAL : CompareBookmark::NOT_EQUAL;
+}
+
+sal_Bool SAL_CALL OFlatResultSet::hasOrderedBookmarks( )
+{
+ return true;
+}
+
+sal_Int32 SAL_CALL OFlatResultSet::hashBookmark( const Any& bookmark )
+{
+ return comphelper::getINT32(bookmark);
+}
+
+IPropertyArrayHelper* OFlatResultSet::createArrayHelper( ) const
+{
+ Sequence< Property > aProps;
+ describeProperties(aProps);
+ return new ::cppu::OPropertyArrayHelper(aProps);
+}
+
+IPropertyArrayHelper & OFlatResultSet::getInfoHelper()
+{
+ return *OFlatResultSet_BASE3::getArrayHelper();
+}
+
+void SAL_CALL OFlatResultSet::acquire() noexcept
+{
+ OFlatResultSet_BASE2::acquire();
+}
+
+void SAL_CALL OFlatResultSet::release() noexcept
+{
+ OFlatResultSet_BASE2::release();
+}
+
+css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL OFlatResultSet::getPropertySetInfo( )
+{
+ return ::cppu::OPropertySetHelper::createPropertySetInfo(getInfoHelper());
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/flat/EStatement.cxx b/connectivity/source/drivers/flat/EStatement.cxx
new file mode 100644
index 0000000000..dc801ac486
--- /dev/null
+++ b/connectivity/source/drivers/flat/EStatement.cxx
@@ -0,0 +1,34 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+#include <flat/EStatement.hxx>
+#include <flat/EResultSet.hxx>
+
+using namespace connectivity::flat;
+using namespace connectivity::file;
+using namespace css::uno;
+
+rtl::Reference<OResultSet> OFlatStatement::createResultSet()
+{
+ return new OFlatResultSet(this,m_aSQLIterator);
+}
+
+IMPLEMENT_SERVICE_INFO(OFlatStatement,"com.sun.star.sdbc.driver.flat.Statement","com.sun.star.sdbc.Statement");
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/flat/ETable.cxx b/connectivity/source/drivers/flat/ETable.cxx
new file mode 100644
index 0000000000..9cab6b13da
--- /dev/null
+++ b/connectivity/source/drivers/flat/ETable.cxx
@@ -0,0 +1,947 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+#include <flat/ETable.hxx>
+#include <com/sun/star/sdbc/ColumnValue.hpp>
+#include <com/sun/star/sdbc/DataType.hpp>
+#include <com/sun/star/sdbc/XRow.hpp>
+#include <com/sun/star/ucb/XContentAccess.hpp>
+#include <flat/EConnection.hxx>
+#include <flat/EColumns.hxx>
+#include <o3tl/safeint.hxx>
+#include <rtl/math.hxx>
+#include <sal/log.hxx>
+#include <tools/urlobj.hxx>
+#include <cppuhelper/queryinterface.hxx>
+#include <comphelper/numbers.hxx>
+#include <comphelper/servicehelper.hxx>
+#include <com/sun/star/util/NumberFormat.hpp>
+#include <com/sun/star/util/NumberFormatter.hpp>
+#include <com/sun/star/util/NumberFormatsSupplier.hpp>
+#include <i18nlangtag/languagetag.hxx>
+#include <connectivity/dbconversion.hxx>
+#include <connectivity/sdbcx/VColumn.hxx>
+#include <file/quotedstring.hxx>
+#include <file/FDriver.hxx>
+#include <unotools/syslocale.hxx>
+#include <unotools/charclass.hxx>
+
+using namespace ::comphelper;
+using namespace connectivity;
+using namespace connectivity::flat;
+using namespace connectivity::file;
+using namespace ::cppu;
+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;
+using namespace ::com::sun::star::util;
+using std::vector;
+using std::lower_bound;
+
+
+void OFlatTable::fillColumns(const css::lang::Locale& _aLocale)
+{
+ m_bNeedToReadLine = true; // we overwrite m_aCurrentLine, seek the stream, ...
+ m_pFileStream->Seek(0);
+ // tdf#123055 - start to read unicode text in order to avoid the BOM
+ m_pFileStream->StartReadingUnicodeText(RTL_TEXTENCODING_DONTKNOW);
+ m_aCurrentLine = QuotedTokenizedString();
+ bool bRead = true;
+
+ const OFlatConnection* const pConnection = getFlatConnection();
+ const bool bHasHeaderLine = pConnection->isHeaderLine();
+
+ QuotedTokenizedString aHeaderLine;
+ const sal_Int32 nPos = static_cast<sal_Int32>(m_pFileStream->Tell());
+ TRowPositionInFile rowPos(nPos, nPos);
+ sal_Int32 rowNum(0);
+ if ( bHasHeaderLine )
+ {
+ bRead = readLine(&rowPos.second, &rowPos.first, true);
+ if(bRead)
+ aHeaderLine = m_aCurrentLine;
+ }
+ setRowPos(rowNum++, rowPos);
+
+ // read first row
+ if(bRead)
+ {
+ bRead = readLine(&rowPos.second, &rowPos.first);
+ if(bRead)
+ setRowPos(rowNum++, rowPos);
+ }
+
+ if ( !bHasHeaderLine || !aHeaderLine.Len())
+ {
+ // use first non-empty row as headerline because we need the number of columns
+ while(bRead && m_aCurrentLine.Len() == 0)
+ {
+ bRead = readLine(&rowPos.second, &rowPos.first);
+ if(bRead)
+ setRowPos(rowNum++, rowPos);
+ }
+ aHeaderLine = m_aCurrentLine;
+ }
+ // column count
+ const sal_Int32 nFieldCount = aHeaderLine.GetTokenCount(m_cFieldDelimiter,m_cStringDelimiter);
+
+ if(!m_aColumns.is())
+ m_aColumns = new OSQLColumns();
+ else
+ m_aColumns->clear();
+
+ m_aTypes.clear();
+ m_aPrecisions.clear();
+ m_aScales.clear();
+ // reserve some space
+ m_aColumns->reserve(nFieldCount+1);
+ m_aTypes.assign(nFieldCount+1,DataType::SQLNULL);
+ m_aPrecisions.assign(nFieldCount+1,-1);
+ m_aScales.assign(nFieldCount+1,-1);
+
+ const bool bCase = m_pConnection->getMetaData()->supportsMixedCaseQuotedIdentifiers();
+ CharClass aCharClass( pConnection->getDriver()->getComponentContext(), LanguageTag( _aLocale));
+ // read description
+ const sal_Unicode cDecimalDelimiter = pConnection->getDecimalDelimiter();
+ const sal_Unicode cThousandDelimiter = pConnection->getThousandDelimiter();
+ ::comphelper::UStringMixEqual aCase(bCase);
+ vector<OUString> aColumnNames;
+ vector<OUString> aTypeNames;
+ aTypeNames.resize(nFieldCount);
+ const sal_Int32 nMaxRowsToScan = pConnection->getMaxRowsToScan();
+ sal_Int32 nRowCount = 0;
+
+ do
+ {
+ sal_Int32 nStartPosHeaderLine = 0; // use for efficient way to get the tokens
+ sal_Int32 nStartPosFirstLine = 0; // use for efficient way to get the tokens
+ sal_Int32 nStartPosFirstLine2 = 0;
+ for( sal_Int32 i = 0; i < nFieldCount; i++ )
+ {
+ if ( nRowCount == 0)
+ {
+ OUString aColumnName;
+ if ( bHasHeaderLine )
+ {
+ aColumnName = aHeaderLine.GetTokenSpecial(nStartPosHeaderLine,m_cFieldDelimiter,m_cStringDelimiter);
+ }
+ if ( aColumnName.isEmpty() )
+ {
+ aColumnName = "C" + OUString::number(i+1);
+ }
+ aColumnNames.push_back(aColumnName);
+ }
+ if(bRead)
+ {
+ impl_fillColumnInfo_nothrow(m_aCurrentLine, nStartPosFirstLine, nStartPosFirstLine2,
+ m_aTypes[i], m_aPrecisions[i], m_aScales[i], aTypeNames[i],
+ cDecimalDelimiter, cThousandDelimiter, aCharClass);
+ }
+ }
+ ++nRowCount;
+ bRead = readLine(&rowPos.second, &rowPos.first);
+ if(bRead)
+ setRowPos(rowNum++, rowPos);
+ }
+ while(nRowCount < nMaxRowsToScan && bRead);
+
+ for( sal_Int32 i = 0; i < nFieldCount; i++ )
+ {
+ // check if the columname already exists
+ OUString aAlias(aColumnNames[i]);
+ OSQLColumns::const_iterator aFind = connectivity::find(m_aColumns->begin(),m_aColumns->end(),aAlias,aCase);
+ sal_Int32 nExprCnt = 0;
+ while(aFind != m_aColumns->end())
+ {
+ aAlias = aColumnNames[i] + OUString::number(++nExprCnt);
+ aFind = connectivity::find(m_aColumns->begin(),m_aColumns->end(),aAlias,aCase);
+ }
+
+ rtl::Reference<sdbcx::OColumn> pColumn = new sdbcx::OColumn(aAlias,aTypeNames[i],OUString(),OUString(),
+ ColumnValue::NULLABLE,
+ m_aPrecisions[i],
+ m_aScales[i],
+ m_aTypes[i],
+ false,
+ false,
+ false,
+ bCase,
+ m_CatalogName, getSchema(), getName());
+ m_aColumns->push_back(pColumn);
+ }
+
+ m_pFileStream->Seek(m_aRowPosToFilePos[0].second);
+}
+
+void OFlatTable::impl_fillColumnInfo_nothrow(QuotedTokenizedString const & aFirstLine, sal_Int32& nStartPosFirstLine, sal_Int32& nStartPosFirstLine2,
+ sal_Int32& io_nType, sal_Int32& io_nPrecisions, sal_Int32& io_nScales, OUString& o_sTypeName,
+ const sal_Unicode cDecimalDelimiter, const sal_Unicode cThousandDelimiter, const CharClass& aCharClass)
+{
+ if ( io_nType != DataType::VARCHAR )
+ {
+ bool bNumeric = io_nType == DataType::SQLNULL || io_nType == DataType::DOUBLE || io_nType == DataType::DECIMAL || io_nType == DataType::INTEGER;
+ sal_Int32 nIndex = 0;
+
+ if ( bNumeric )
+ {
+ // first without fielddelimiter
+ OUString aField = aFirstLine.GetTokenSpecial(nStartPosFirstLine,m_cFieldDelimiter);
+ if (aField.isEmpty() ||
+ (m_cStringDelimiter && m_cStringDelimiter == aField[0]))
+ {
+ bNumeric = false;
+ if ( m_cStringDelimiter != '\0' )
+ aField = aFirstLine.GetTokenSpecial(nStartPosFirstLine2,m_cFieldDelimiter,m_cStringDelimiter);
+ else
+ nStartPosFirstLine2 = nStartPosFirstLine;
+ }
+ else
+ {
+ OUString aField2;
+ if ( m_cStringDelimiter != '\0' )
+ aField2 = aFirstLine.GetTokenSpecial(nStartPosFirstLine2,m_cFieldDelimiter,m_cStringDelimiter);
+ else
+ aField2 = aField;
+
+ if (aField2.isEmpty())
+ {
+ bNumeric = false;
+ }
+ else
+ {
+ bNumeric = true;
+ sal_Int32 nDot = 0;
+ sal_Int32 nDecimalDelCount = 0;
+ sal_Int32 nSpaceCount = 0;
+ for( sal_Int32 j = 0; j < aField2.getLength(); j++ )
+ {
+ const sal_Unicode c = aField2[j];
+ if ( j == nSpaceCount && m_cFieldDelimiter != 32 && c == 32 )
+ {
+ ++nSpaceCount;
+ continue;
+ }
+ // just digits, decimal- and thousands-delimiter?
+ if ( ( !cDecimalDelimiter || c != cDecimalDelimiter ) &&
+ ( !cThousandDelimiter || c != cThousandDelimiter ) &&
+ !aCharClass.isDigit(aField2,j) &&
+ ( j != 0 || (c != '+' && c != '-' ) ) )
+ {
+ bNumeric = false;
+ break;
+ }
+ if (cDecimalDelimiter && c == cDecimalDelimiter)
+ {
+ io_nPrecisions = 15; // we have a 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 = false;
+ if (bNumeric && cThousandDelimiter)
+ {
+ // Is the delimiter correct?
+ const std::u16string_view aValue = o3tl::getToken(aField2, 0, cDecimalDelimiter);
+ for( sal_Int32 j = static_cast<sal_Int32>(aValue.size()) - 4; j >= 0; j -= 4)
+ {
+ const sal_Unicode c = aValue[j];
+ // just digits, decimal- and thousands-delimiter?
+ if (c == cThousandDelimiter && j)
+ continue;
+ else
+ {
+ bNumeric = false;
+ break;
+ }
+ }
+ }
+
+ // now also check for a date field
+ if (!bNumeric)
+ {
+ try
+ {
+ nIndex = m_xNumberFormatter->detectNumberFormat(css::util::NumberFormat::ALL,aField2);
+ }
+ catch(Exception&)
+ {
+ }
+ }
+ }
+ }
+ }
+ else if ( io_nType == DataType::DATE || io_nType == DataType::TIMESTAMP || io_nType == DataType::TIME)
+ {
+ OUString aField = aFirstLine.GetTokenSpecial(nStartPosFirstLine,m_cFieldDelimiter);
+ if (aField.isEmpty() ||
+ (m_cStringDelimiter && m_cStringDelimiter == aField[0]))
+ {
+ }
+ else
+ {
+ OUString aField2;
+ if ( m_cStringDelimiter != '\0' )
+ aField2 = aFirstLine.GetTokenSpecial(nStartPosFirstLine2,m_cFieldDelimiter,m_cStringDelimiter);
+ else
+ aField2 = aField;
+ if (!aField2.isEmpty() )
+ {
+ try
+ {
+ nIndex = m_xNumberFormatter->detectNumberFormat(css::util::NumberFormat::ALL,aField2);
+ }
+ catch(Exception&)
+ {
+ }
+ }
+ }
+ }
+
+ if (bNumeric)
+ {
+ if (cDecimalDelimiter)
+ {
+ if(io_nPrecisions)
+ {
+ io_nType = DataType::DECIMAL;
+ o_sTypeName = "DECIMAL";
+ }
+ else
+ {
+ io_nType = DataType::DOUBLE;
+ o_sTypeName = "DOUBLE";
+ }
+ }
+ else
+ {
+ io_nType = DataType::INTEGER;
+ io_nPrecisions = 0;
+ io_nScales = 0;
+ }
+ }
+ else
+ {
+ switch (comphelper::getNumberFormatType(m_xNumberFormatter,nIndex))
+ {
+ case css::util::NumberFormat::DATE:
+ io_nType = DataType::DATE;
+ o_sTypeName = "DATE";
+ break;
+ case css::util::NumberFormat::DATETIME:
+ io_nType = DataType::TIMESTAMP;
+ o_sTypeName = "TIMESTAMP";
+ break;
+ case css::util::NumberFormat::TIME:
+ io_nType = DataType::TIME;
+ o_sTypeName = "TIME";
+ break;
+ default:
+ io_nType = DataType::VARCHAR;
+ io_nPrecisions = 0; // nyi: Data can be longer!
+ io_nScales = 0;
+ o_sTypeName = "VARCHAR";
+ };
+ }
+ }
+ else
+ {
+ OUString aField = aFirstLine.GetTokenSpecial(nStartPosFirstLine,m_cFieldDelimiter);
+ if (aField.isEmpty() ||
+ (m_cStringDelimiter && m_cStringDelimiter == aField[0]))
+ {
+ if ( m_cStringDelimiter != '\0' )
+ aField = aFirstLine.GetTokenSpecial(nStartPosFirstLine2, m_cFieldDelimiter, m_cStringDelimiter);
+ else
+ nStartPosFirstLine2 = nStartPosFirstLine;
+ }
+ else
+ {
+ if ( m_cStringDelimiter != '\0' )
+ aFirstLine.GetTokenSpecial(nStartPosFirstLine2, m_cFieldDelimiter, m_cStringDelimiter);
+ }
+ }
+}
+
+OFlatTable::OFlatTable(sdbcx::OCollection* _pTables,OFlatConnection* _pConnection,
+ const OUString& Name,
+ const OUString& Type,
+ const OUString& Description ,
+ const OUString& SchemaName,
+ const OUString& CatalogName
+ ) : OFlatTable_BASE(_pTables,_pConnection,Name,
+ Type,
+ Description,
+ SchemaName,
+ CatalogName)
+ ,m_nRowPos(0)
+ ,m_nMaxRowCount(0)
+ ,m_cStringDelimiter(_pConnection->getStringDelimiter())
+ ,m_cFieldDelimiter(_pConnection->getFieldDelimiter())
+ ,m_bNeedToReadLine(false)
+{
+
+}
+
+void OFlatTable::construct()
+{
+ SvtSysLocale aLocale;
+ css::lang::Locale aAppLocale(aLocale.GetLanguageTag().getLocale());
+
+ Reference< XNumberFormatsSupplier > xSupplier = NumberFormatsSupplier::createWithLocale( m_pConnection->getDriver()->getComponentContext(), aAppLocale );
+ m_xNumberFormatter.set( NumberFormatter::create( m_pConnection->getDriver()->getComponentContext()), UNO_QUERY_THROW);
+ m_xNumberFormatter->attachNumberFormatsSupplier(xSupplier);
+ Reference<XPropertySet> xProp = xSupplier->getNumberFormatSettings();
+ xProp->getPropertyValue("NullDate") >>= m_aNullDate;
+
+ INetURLObject aURL;
+ aURL.SetURL(getEntry());
+
+ if(aURL.getExtension() != m_pConnection->getExtension())
+ aURL.setExtension(m_pConnection->getExtension());
+
+ OUString aFileName = aURL.GetMainURL(INetURLObject::DecodeMechanism::NONE);
+
+ m_pFileStream = createStream_simpleError( aFileName, StreamMode::READWRITE | StreamMode::NOCREATE | StreamMode::SHARE_DENYWRITE);
+
+ if(!m_pFileStream)
+ m_pFileStream = createStream_simpleError( aFileName, StreamMode::READ | StreamMode::NOCREATE | StreamMode::SHARE_DENYNONE);
+
+ if(!m_pFileStream)
+ return;
+
+ sal_uInt64 const nSize = m_pFileStream->remainingSize();
+
+ // Buffersize is dependent on the file-size
+ m_pFileStream->SetBufferSize(nSize > 1000000 ? 32768 :
+ nSize > 100000 ? 16384 :
+ nSize > 10000 ? 4096 : 1024);
+
+ fillColumns(aAppLocale);
+
+ refreshColumns();
+}
+
+OUString OFlatTable::getEntry() const
+{
+ OUString sURL;
+ try
+ {
+ Reference< XResultSet > xDir = m_pConnection->getDir()->getStaticResultSet();
+ Reference< XRow> xRow(xDir,UNO_QUERY);
+ OUString sName;
+ OUString sExt;
+
+ INetURLObject aURL;
+ xDir->beforeFirst();
+ while(xDir->next())
+ {
+ sName = xRow->getString(1);
+ aURL.SetSmartProtocol(INetProtocol::File);
+ OUString sUrl = m_pConnection->getURL() + "/" + sName;
+ aURL.SetSmartURL( sUrl );
+
+ // cut the extension
+ sExt = aURL.getExtension();
+
+ // name and extension have to coincide
+ if ( m_pConnection->matchesExtension( sExt ) )
+ {
+ if ( !sExt.isEmpty() )
+ sName = sName.replaceAt(sName.getLength() - (sExt.getLength() + 1), sExt.getLength()+1, u"");
+ if ( sName == m_Name )
+ {
+ Reference< XContentAccess > xContentAccess( xDir, UNO_QUERY );
+ sURL = xContentAccess->queryContentIdentifierString();
+ break;
+ }
+ }
+ }
+ xDir->beforeFirst(); // move back to before first record
+ }
+ catch(const Exception&)
+ {
+ OSL_ASSERT(false);
+ }
+ return sURL;
+}
+
+void OFlatTable::refreshColumns()
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ ::std::vector< OUString> aVector;
+ aVector.reserve(m_aColumns->size());
+
+ for (auto const& column : *m_aColumns)
+ aVector.push_back(Reference< XNamed>(column,UNO_QUERY_THROW)->getName());
+
+ if(m_xColumns)
+ m_xColumns->reFill(aVector);
+ else
+ m_xColumns.reset(new OFlatColumns(this,m_aMutex,aVector));
+}
+
+
+void SAL_CALL OFlatTable::disposing()
+{
+ OFileTable::disposing();
+ ::osl::MutexGuard aGuard(m_aMutex);
+ m_aColumns = nullptr;
+}
+
+Sequence< Type > SAL_CALL OFlatTable::getTypes( )
+{
+ Sequence< Type > aTypes = OTable_TYPEDEF::getTypes();
+ vector<Type> aOwnTypes;
+ aOwnTypes.reserve(aTypes.getLength());
+ const Type* pBegin = aTypes.getConstArray();
+ const Type* pEnd = pBegin + aTypes.getLength();
+ for(;pBegin != pEnd;++pBegin)
+ {
+ if(!(*pBegin == cppu::UnoType<XKeysSupplier>::get()||
+ *pBegin == cppu::UnoType<XRename>::get()||
+ *pBegin == cppu::UnoType<XIndexesSupplier>::get()||
+ *pBegin == cppu::UnoType<XAlterTable>::get()||
+ *pBegin == cppu::UnoType<XDataDescriptorFactory>::get()))
+ {
+ aOwnTypes.push_back(*pBegin);
+ }
+ }
+ return Sequence< Type >(aOwnTypes.data(), aOwnTypes.size());
+}
+
+
+Any SAL_CALL OFlatTable::queryInterface( const Type & rType )
+{
+ if( rType == cppu::UnoType<XKeysSupplier>::get()||
+ rType == cppu::UnoType<XIndexesSupplier>::get()||
+ rType == cppu::UnoType<XRename>::get()||
+ rType == cppu::UnoType<XAlterTable>::get()||
+ rType == cppu::UnoType<XDataDescriptorFactory>::get())
+ return Any();
+
+ Any aRet = OTable_TYPEDEF::queryInterface(rType);
+ return aRet;
+}
+
+
+bool OFlatTable::fetchRow(OValueRefRow& _rRow, const OSQLColumns & _rCols, bool bRetrieveData)
+{
+ *(*_rRow)[0] = m_nFilePos;
+
+ if (!bRetrieveData)
+ return true;
+
+ bool result = false;
+ if ( m_bNeedToReadLine )
+ {
+ m_pFileStream->Seek(m_nFilePos);
+ TRowPositionInFile rowPos(0, 0);
+ if(readLine(&rowPos.second, &rowPos.first))
+ {
+ setRowPos(m_nRowPos, rowPos);
+ m_bNeedToReadLine = false;
+ result = true;
+ }
+ // else let run through so that we set _rRow to all NULL
+ }
+
+ const OFlatConnection * const pConnection = getFlatConnection();
+ const sal_Unicode cDecimalDelimiter = pConnection->getDecimalDelimiter();
+ const sal_Unicode cThousandDelimiter = pConnection->getThousandDelimiter();
+ // Fields:
+ sal_Int32 nStartPos = 0;
+ OSQLColumns::const_iterator aIter = _rCols.begin();
+ OSQLColumns::const_iterator aEnd = _rCols.end();
+ const OValueRefVector::size_type nCount = _rRow->size();
+ for (OValueRefVector::size_type i = 1;
+ aIter != aEnd && i < nCount;
+ ++aIter, i++)
+ {
+ OUString aStr = m_aCurrentLine.GetTokenSpecial(nStartPos,m_cFieldDelimiter,m_cStringDelimiter);
+
+ if (aStr.isEmpty())
+ {
+ (*_rRow)[i]->setNull();
+ }
+ else
+ {
+ sal_Int32 nType = m_aTypes[i-1];
+ switch(nType)
+ {
+ case DataType::TIMESTAMP:
+ case DataType::DATE:
+ case DataType::TIME:
+ {
+ try
+ {
+ double nRes = m_xNumberFormatter->convertStringToNumber(css::util::NumberFormat::ALL,aStr);
+
+ switch(nType)
+ {
+ case DataType::DATE:
+ *(*_rRow)[i] = ::dbtools::DBTypeConversion::toDouble(::dbtools::DBTypeConversion::toDate(nRes,m_aNullDate));
+ break;
+ case DataType::TIMESTAMP:
+ *(*_rRow)[i] = ::dbtools::DBTypeConversion::toDouble(::dbtools::DBTypeConversion::toDateTime(nRes,m_aNullDate));
+ break;
+ default:
+ *(*_rRow)[i] = ::dbtools::DBTypeConversion::toDouble(::dbtools::DBTypeConversion::toTime(nRes));
+ }
+ }
+ catch(Exception&)
+ {
+ (*_rRow)[i]->setNull();
+ }
+ } break;
+ case DataType::DOUBLE:
+ case DataType::INTEGER:
+ case DataType::DECIMAL:
+ case DataType::NUMERIC:
+ {
+
+ OUString aStrConverted;
+ if ( DataType::INTEGER != nType )
+ {
+ OSL_ENSURE((cDecimalDelimiter && nType != DataType::INTEGER) ||
+ (!cDecimalDelimiter && nType == DataType::INTEGER),
+ "Wrong type");
+
+ OUStringBuffer aBuf(aStr.getLength());
+ // convert to Standard-Notation (DecimalPOINT without thousands-comma):
+ for (sal_Int32 j = 0; j < aStr.getLength(); ++j)
+ {
+ const sal_Unicode cChar = aStr[j];
+ if (cDecimalDelimiter && cChar == cDecimalDelimiter)
+ aBuf.append('.');
+ else if ( cChar == '.' ) // special case, if decimal separator isn't '.' we have to put the string after it
+ continue;
+ else if (cThousandDelimiter && cChar == cThousandDelimiter)
+ {
+ // leave out
+ }
+ else
+ aBuf.append(cChar);
+ } // for (j = 0; j < aStr.(); ++j)
+ aStrConverted = aBuf.makeStringAndClear();
+ } // if ( DataType::INTEGER != nType )
+ else
+ {
+ if ( cThousandDelimiter )
+ aStrConverted = aStr.replaceAll(OUStringChar(cThousandDelimiter), "");
+ else
+ aStrConverted = aStr;
+ }
+ const double nVal = ::rtl::math::stringToDouble(aStrConverted,'.',',');
+
+ // #99178# OJ
+ if ( DataType::DECIMAL == nType || DataType::NUMERIC == nType )
+ *(*_rRow)[i] = OUString::number(nVal);
+ else
+ *(*_rRow)[i] = nVal;
+ } break;
+
+ default:
+ {
+ // Copy Value as String in Row-Variable
+ *(*_rRow)[i] = ORowSetValue(aStr);
+ }
+ break;
+ } // switch(nType)
+ (*_rRow)[i]->setTypeKind(nType);
+ }
+ }
+ return result;
+}
+
+
+void OFlatTable::refreshHeader()
+{
+ SAL_INFO( "connectivity.flat", "flat lionel@mamane.lu OFlatTable::refreshHeader" );
+}
+
+
+namespace
+{
+ template< typename Tp, typename Te> struct RangeBefore
+ {
+ bool operator() (const Tp &p, const Te &e)
+ {
+ assert(p.first <= p.second);
+ return p.second <= e;
+ }
+ };
+}
+
+bool OFlatTable::seekRow(IResultSetHelper::Movement eCursorPosition, sal_Int32 nOffset, sal_Int32& nCurPos)
+{
+ OSL_ENSURE(m_pFileStream,"OFlatTable::seekRow: FileStream is NULL!");
+
+
+ switch(eCursorPosition)
+ {
+ case IResultSetHelper::FIRST:
+ m_nRowPos = 0;
+ [[fallthrough]];
+ case IResultSetHelper::NEXT:
+ {
+ assert(m_nRowPos >= 0);
+ if(m_nMaxRowCount != 0 && m_nRowPos > m_nMaxRowCount)
+ return false;
+ ++m_nRowPos;
+ if(m_aRowPosToFilePos.size() > o3tl::make_unsigned(m_nRowPos))
+ {
+ m_bNeedToReadLine = true;
+ m_nFilePos = m_aRowPosToFilePos[m_nRowPos].first;
+ nCurPos = m_aRowPosToFilePos[m_nRowPos].second;
+ }
+ else
+ {
+ assert(m_aRowPosToFilePos.size() == static_cast< vector< TRowPositionInFile >::size_type >(m_nRowPos));
+ const TRowPositionInFile &lastRowPos(m_aRowPosToFilePos.back());
+ // Our ResultSet is allowed to disagree with us only
+ // on the position of the first line
+ // (because of the special case of the header...)
+ assert(m_nRowPos == 1 || nCurPos == lastRowPos.second);
+
+ m_nFilePos = lastRowPos.second;
+ m_pFileStream->Seek(m_nFilePos);
+
+ TRowPositionInFile newRowPos;
+ if(!readLine(&newRowPos.second, &newRowPos.first))
+ {
+ m_nMaxRowCount = m_nRowPos - 1;
+ return false;
+ }
+
+ nCurPos = newRowPos.second;
+ setRowPos(m_nRowPos, newRowPos);
+ }
+ }
+
+ break;
+ case IResultSetHelper::PRIOR:
+ assert(m_nRowPos >= 0);
+
+ if(m_nRowPos == 0)
+ return false;
+
+ --m_nRowPos;
+ {
+ assert (m_nRowPos >= 0);
+ assert(m_aRowPosToFilePos.size() >= o3tl::make_unsigned(m_nRowPos));
+ const TRowPositionInFile &aPositions(m_aRowPosToFilePos[m_nRowPos]);
+ m_nFilePos = aPositions.first;
+ nCurPos = aPositions.second;
+ m_bNeedToReadLine = true;
+ }
+
+ break;
+ case IResultSetHelper::LAST:
+ if (m_nMaxRowCount == 0)
+ {
+ while(seekRow(IResultSetHelper::NEXT, 1, nCurPos)) ; // run through after last row
+ }
+ // m_nMaxRowCount can still be zero, but now it means there a genuinely zero rows in the table
+ return seekRow(IResultSetHelper::ABSOLUTE1, m_nMaxRowCount, nCurPos);
+ case IResultSetHelper::RELATIVE1:
+ {
+ const sal_Int32 nNewRowPos = m_nRowPos + nOffset;
+ if (nNewRowPos < 0)
+ return false;
+ // ABSOLUTE will take care of case nNewRowPos > nMaxRowCount
+ return seekRow(IResultSetHelper::ABSOLUTE1, nNewRowPos, nCurPos);
+ }
+ case IResultSetHelper::ABSOLUTE1:
+ {
+ if(nOffset < 0)
+ {
+ if (m_nMaxRowCount == 0)
+ {
+ if (!seekRow(IResultSetHelper::LAST, 0, nCurPos))
+ return false;
+ }
+ // m_nMaxRowCount can still be zero, but now it means there a genuinely zero rows in the table
+ nOffset = m_nMaxRowCount + nOffset;
+ }
+ if(nOffset < 0)
+ {
+ seekRow(IResultSetHelper::ABSOLUTE1, 0, nCurPos);
+ return false;
+ }
+ if(m_nMaxRowCount && nOffset > m_nMaxRowCount)
+ {
+ m_nRowPos = m_nMaxRowCount + 1;
+ const TRowPositionInFile &lastRowPos(m_aRowPosToFilePos.back());
+ m_nFilePos = lastRowPos.second;
+ nCurPos = lastRowPos.second;
+ return false;
+ }
+
+ assert(m_nRowPos >=0);
+ assert(m_aRowPosToFilePos.size() > o3tl::make_unsigned(m_nRowPos));
+ assert(nOffset >= 0);
+ if(m_aRowPosToFilePos.size() > o3tl::make_unsigned(nOffset))
+ {
+ m_nFilePos = m_aRowPosToFilePos[nOffset].first;
+ nCurPos = m_aRowPosToFilePos[nOffset].second;
+ m_nRowPos = nOffset;
+ m_bNeedToReadLine = true;
+ }
+ else
+ {
+ assert(m_nRowPos < nOffset);
+ while(m_nRowPos < nOffset)
+ {
+ if(!seekRow(IResultSetHelper::NEXT, 1, nCurPos))
+ return false;
+ }
+ assert(m_nRowPos == nOffset);
+ }
+ }
+
+ break;
+ case IResultSetHelper::BOOKMARK:
+ {
+ vector< TRowPositionInFile >::const_iterator aFind = lower_bound(m_aRowPosToFilePos.begin(),
+ m_aRowPosToFilePos.end(),
+ nOffset,
+ RangeBefore< TRowPositionInFile, sal_Int32 >());
+
+ if(aFind == m_aRowPosToFilePos.end() || aFind->first != nOffset)
+ //invalid bookmark
+ return false;
+
+ m_bNeedToReadLine = true;
+ m_nFilePos = aFind->first;
+ nCurPos = aFind->second;
+ m_nRowPos = aFind - m_aRowPosToFilePos.begin();
+ break;
+ }
+ }
+
+ return true;
+}
+
+
+bool OFlatTable::readLine(sal_Int32 * const pEndPos, sal_Int32 * const pStartPos, const bool nonEmpty)
+{
+ const rtl_TextEncoding nEncoding = m_pConnection->getTextEncoding();
+ m_aCurrentLine = QuotedTokenizedString();
+ do
+ {
+ if (pStartPos)
+ *pStartPos = static_cast<sal_Int32>(m_pFileStream->Tell());
+ m_pFileStream->ReadByteStringLine(m_aCurrentLine, nEncoding);
+ if (m_pFileStream->eof())
+ return false;
+
+ QuotedTokenizedString sLine = m_aCurrentLine; // check if the string continues on next line
+ sal_Int32 nLastOffset = 0;
+ bool isQuoted = false;
+ bool isFieldStarting = true;
+ while (true)
+ {
+ bool wasQuote = false;
+ const sal_Unicode *p = sLine.GetString().getStr() + nLastOffset;
+ while (*p)
+ {
+ if (isQuoted)
+ {
+ if (*p == m_cStringDelimiter)
+ wasQuote = !wasQuote;
+ else
+ {
+ if (wasQuote)
+ {
+ wasQuote = false;
+ isQuoted = false;
+ if (*p == m_cFieldDelimiter)
+ isFieldStarting = true;
+ }
+ }
+ }
+ else
+ {
+ if (isFieldStarting)
+ {
+ isFieldStarting = false;
+ if (*p == m_cStringDelimiter)
+ isQuoted = true;
+ else if (*p == m_cFieldDelimiter)
+ isFieldStarting = true;
+ }
+ else if (*p == m_cFieldDelimiter)
+ isFieldStarting = true;
+ }
+ ++p;
+ }
+
+ if (wasQuote)
+ isQuoted = false;
+
+ if (isQuoted)
+ {
+ nLastOffset = sLine.Len();
+ m_pFileStream->ReadByteStringLine(sLine,nEncoding);
+ if ( !m_pFileStream->eof() )
+ {
+ OUString aStr = m_aCurrentLine.GetString() + "\n" + sLine.GetString();
+ m_aCurrentLine.SetString(aStr);
+ sLine = m_aCurrentLine;
+ }
+ else
+ break;
+ }
+ else
+ break;
+ }
+ }
+ while(nonEmpty && m_aCurrentLine.Len() == 0);
+
+ if(pEndPos)
+ *pEndPos = static_cast<sal_Int32>(m_pFileStream->Tell());
+ return true;
+}
+
+
+void OFlatTable::setRowPos(const vector<TRowPositionInFile>::size_type rowNum, const TRowPositionInFile &rowPos)
+{
+ assert(m_aRowPosToFilePos.size() >= rowNum);
+ if(m_aRowPosToFilePos.size() == rowNum)
+ m_aRowPosToFilePos.push_back(rowPos);
+ else
+ {
+ SAL_WARN_IF(m_aRowPosToFilePos[rowNum] != rowPos,
+ "connectivity.flat",
+ "Setting position for row " << rowNum << " to (" << rowPos.first << ", " << rowPos.second << "), "
+ "but already had different position (" << m_aRowPosToFilePos[rowNum].first << ", " << m_aRowPosToFilePos[rowNum].second << ")");
+ m_aRowPosToFilePos[rowNum] = rowPos;
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/flat/ETables.cxx b/connectivity/source/drivers/flat/ETables.cxx
new file mode 100644
index 0000000000..2e4dd377ed
--- /dev/null
+++ b/connectivity/source/drivers/flat/ETables.cxx
@@ -0,0 +1,44 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+#include <flat/ETables.hxx>
+#include <flat/ETable.hxx>
+#include <file/FCatalog.hxx>
+
+using namespace connectivity;
+using namespace ::comphelper;
+using namespace connectivity::flat;
+using namespace connectivity::file;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::sdbcx;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::container;
+
+sdbcx::ObjectType OFlatTables::createObject(const OUString& _rName)
+{
+ rtl::Reference<OFlatTable> pRet = new OFlatTable(this, static_cast<OFlatConnection*>(static_cast<OFileCatalog&>(m_rParent).getConnection()),
+ _rName,"TABLE");
+ pRet->construct();
+ return pRet;
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/flat/flat.component b/connectivity/source/drivers/flat/flat.component
new file mode 100644
index 0000000000..715fbecd89
--- /dev/null
+++ b/connectivity/source/drivers/flat/flat.component
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ -->
+
+<component loader="com.sun.star.loader.SharedLibrary" environment="@CPPU_ENV@"
+ xmlns="http://openoffice.org/2010/uno-components">
+ <implementation name="com.sun.star.comp.sdbc.flat.ODriver"
+ constructor="connectivity_flat_ODriver">
+ <service name="com.sun.star.sdbc.Driver"/>
+ <service name="com.sun.star.sdbcx.Driver"/>
+ </implementation>
+</component>