summaryrefslogtreecommitdiffstats
path: root/connectivity/source/drivers/mork
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-27 16:51:28 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-27 16:51:28 +0000
commit940b4d1848e8c70ab7642901a68594e8016caffc (patch)
treeeb72f344ee6c3d9b80a7ecc079ea79e9fba8676d /connectivity/source/drivers/mork
parentInitial commit. (diff)
downloadlibreoffice-upstream.tar.xz
libreoffice-upstream.zip
Adding upstream version 1:7.0.4.upstream/1%7.0.4upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'connectivity/source/drivers/mork')
-rw-r--r--connectivity/source/drivers/mork/MCatalog.cxx104
-rw-r--r--connectivity/source/drivers/mork/MCatalog.hxx52
-rw-r--r--connectivity/source/drivers/mork/MColumnAlias.cxx133
-rw-r--r--connectivity/source/drivers/mork/MColumnAlias.hxx72
-rw-r--r--connectivity/source/drivers/mork/MColumns.cxx80
-rw-r--r--connectivity/source/drivers/mork/MColumns.hxx48
-rw-r--r--connectivity/source/drivers/mork/MConnection.cxx377
-rw-r--r--connectivity/source/drivers/mork/MConnection.hxx98
-rw-r--r--connectivity/source/drivers/mork/MDatabaseMetaData.cxx957
-rw-r--r--connectivity/source/drivers/mork/MDatabaseMetaData.hxx191
-rw-r--r--connectivity/source/drivers/mork/MDatabaseMetaDataHelper.cxx123
-rw-r--r--connectivity/source/drivers/mork/MDatabaseMetaDataHelper.hxx39
-rw-r--r--connectivity/source/drivers/mork/MDriver.cxx133
-rw-r--r--connectivity/source/drivers/mork/MDriver.hxx79
-rw-r--r--connectivity/source/drivers/mork/MErrorResource.hxx56
-rw-r--r--connectivity/source/drivers/mork/MPreparedStatement.cxx486
-rw-r--r--connectivity/source/drivers/mork/MPreparedStatement.hxx134
-rw-r--r--connectivity/source/drivers/mork/MQueryHelper.cxx321
-rw-r--r--connectivity/source/drivers/mork/MQueryHelper.hxx184
-rw-r--r--connectivity/source/drivers/mork/MResultSet.cxx1710
-rw-r--r--connectivity/source/drivers/mork/MResultSet.hxx350
-rw-r--r--connectivity/source/drivers/mork/MResultSetMetaData.cxx192
-rw-r--r--connectivity/source/drivers/mork/MResultSetMetaData.hxx88
-rw-r--r--connectivity/source/drivers/mork/MStatement.cxx471
-rw-r--r--connectivity/source/drivers/mork/MStatement.hxx184
-rw-r--r--connectivity/source/drivers/mork/MTable.cxx57
-rw-r--r--connectivity/source/drivers/mork/MTable.hxx61
-rw-r--r--connectivity/source/drivers/mork/MTables.cxx70
-rw-r--r--connectivity/source/drivers/mork/MTables.hxx47
-rw-r--r--connectivity/source/drivers/mork/MorkParser.cxx757
-rw-r--r--connectivity/source/drivers/mork/MorkParser.hxx152
-rw-r--r--connectivity/source/drivers/mork/README41
-rw-r--r--connectivity/source/drivers/mork/dllapi.h25
-rw-r--r--connectivity/source/drivers/mork/license.txt31
-rw-r--r--connectivity/source/drivers/mork/mork.component17
-rw-r--r--connectivity/source/drivers/mork/mork_helper.cxx54
36 files changed, 7974 insertions, 0 deletions
diff --git a/connectivity/source/drivers/mork/MCatalog.cxx b/connectivity/source/drivers/mork/MCatalog.cxx
new file mode 100644
index 000000000..743d1e5ab
--- /dev/null
+++ b/connectivity/source/drivers/mork/MCatalog.cxx
@@ -0,0 +1,104 @@
+/* -*- 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 "MCatalog.hxx"
+#include "MConnection.hxx"
+#include "MTables.hxx"
+
+#include <com/sun/star/sdbc/XRow.hpp>
+
+
+using namespace connectivity::mork;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::container;
+
+
+OCatalog::OCatalog(OConnection* _pCon) : connectivity::sdbcx::OCatalog(_pCon)
+ ,m_pConnection(_pCon)
+{
+// osl_atomic_increment( &m_refCount );
+// refreshTables();
+// refreshViews();
+// refreshGroups();
+// refreshUsers();
+// osl_atomic_decrement( &m_refCount );
+}
+
+void OCatalog::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);
+ OUString aName;
+ while(xResult->next())
+ {
+ aName = xRow->getString(3);
+ aVector.push_back(aName);
+ }
+ }
+ if(m_pTables)
+ m_pTables->reFill(aVector);
+ else
+ m_pTables.reset( new OTables(m_xMetaData,*this,m_aMutex,aVector) );
+}
+
+void OCatalog::refreshViews()
+{
+}
+
+void OCatalog::refreshGroups()
+{
+}
+
+void OCatalog::refreshUsers()
+{
+}
+
+
+// XTablesSupplier
+Reference< XNameAccess > SAL_CALL OCatalog::getTables( )
+{
+ ::osl::MutexGuard aGuard(m_aMutex);
+ checkDisposed(rBHelper.bDisposed);
+
+ try
+ {
+ if(!m_pTables || OConnection::getForceLoadTables())
+ refreshTables();
+ }
+ catch( const RuntimeException& )
+ {
+ // allowed to leave this method
+ throw;
+ }
+ catch( const Exception& )
+ {
+ // allowed
+ }
+
+ return m_pTables.get();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/mork/MCatalog.hxx b/connectivity/source/drivers/mork/MCatalog.hxx
new file mode 100644
index 000000000..170809f7c
--- /dev/null
+++ b/connectivity/source/drivers/mork/MCatalog.hxx
@@ -0,0 +1,52 @@
+/* -*- 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 .
+ */
+#ifndef INCLUDED_CONNECTIVITY_SOURCE_DRIVERS_MORK_MCATALOG_HXX
+#define INCLUDED_CONNECTIVITY_SOURCE_DRIVERS_MORK_MCATALOG_HXX
+
+#include <sdbcx/VCatalog.hxx>
+
+namespace connectivity
+{
+ namespace mork
+ {
+ // please don't name the class the same name as in another namespaces
+ // some compilers have problems with this task as I noticed on windows
+ class OConnection;
+ class OCatalog : public connectivity::sdbcx::OCatalog
+ {
+ OConnection* m_pConnection; // used to get the metadata
+
+ public:
+ // implementation of the pure virtual methods
+ virtual void refreshTables() override;
+ virtual void refreshViews() override ;
+ virtual void refreshGroups() override;
+ virtual void refreshUsers() override ;
+ virtual css::uno::Reference< css::container::XNameAccess > SAL_CALL getTables( ) override;
+ public:
+ explicit OCatalog(OConnection* _pCon);
+
+ OConnection* getConnection() const { return m_pConnection; }
+
+ };
+ }
+}
+#endif // INCLUDED_CONNECTIVITY_SOURCE_DRIVERS_MORK_MCATALOG_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/mork/MColumnAlias.cxx b/connectivity/source/drivers/mork/MColumnAlias.cxx
new file mode 100644
index 000000000..b320d8c45
--- /dev/null
+++ b/connectivity/source/drivers/mork/MColumnAlias.cxx
@@ -0,0 +1,133 @@
+/* -*- 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 "MColumnAlias.hxx"
+
+#include <com/sun/star/container/XHierarchicalNameAccess.hpp>
+#include <com/sun/star/container/XNameAccess.hpp>
+#include <officecfg/Office/DataAccess.hxx>
+
+#include <osl/diagnose.h>
+#include <sal/log.hxx>
+
+#include <algorithm>
+
+using namespace ::connectivity::mork;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::container;
+
+
+OColumnAlias::OColumnAlias( const css::uno::Reference< css::lang::XMultiServiceFactory >& _rxORB )
+{
+ static const char* s_pProgrammaticNames[] =
+ {
+ "FirstName",
+ "LastName",
+ "DisplayName",
+ "NickName",
+ "PrimaryEmail",
+ "SecondEmail",
+ "PreferMailFormat",
+ "WorkPhone",
+ "HomePhone",
+ "FaxNumber",
+ "PagerNumber",
+ "CellularNumber",
+ "HomeAddress",
+ "HomeAddress2",
+ "HomeCity",
+ "HomeState",
+ "HomeZipCode",
+ "HomeCountry",
+ "WorkAddress",
+ "WorkAddress2",
+ "WorkCity",
+ "WorkState",
+ "WorkZipCode",
+ "WorkCountry",
+ "JobTitle",
+ "Department",
+ "Company",
+ "WebPage1",
+ "WebPage2",
+ "BirthYear",
+ "BirthMonth",
+ "BirthDay",
+ "Custom1",
+ "Custom2",
+ "Custom3",
+ "Custom4",
+ "Notes",
+ };
+
+ for ( size_t i = 0; i < SAL_N_ELEMENTS( s_pProgrammaticNames ); ++i )
+ m_aAliasMap[ OUString::createFromAscii( s_pProgrammaticNames[i] ) ] = AliasEntry( s_pProgrammaticNames[i], i );
+
+ initialize( _rxORB );
+}
+
+
+void OColumnAlias::initialize( const css::uno::Reference< css::lang::XMultiServiceFactory >& _rxORB )
+{
+ Reference< XNameAccess > xAliasesNode(
+ officecfg::Office::DataAccess::DriverSettings::
+ com_sun_star_comp_sdbc_MozabDriver::ColumnAliases::get(
+ comphelper::getComponentContext(_rxORB)),
+ UNO_QUERY_THROW);
+ const Sequence< OUString > aProgrammaticNames(xAliasesNode->getElementNames());
+ for (const auto& rProgrammaticName : aProgrammaticNames) {
+ OString sAsciiProgrammaticName(
+ OUStringToOString(
+ rProgrammaticName, RTL_TEXTENCODING_ASCII_US));
+ auto j = std::find_if(m_aAliasMap.begin(), m_aAliasMap.end(),
+ [&sAsciiProgrammaticName](const AliasMap::value_type& rEntry) {
+ return rEntry.second.programmaticAsciiName == sAsciiProgrammaticName; });
+ if (j != m_aAliasMap.end()) {
+ OUString sAssignedAlias;
+ xAliasesNode->getByName(rProgrammaticName) >>=
+ sAssignedAlias;
+ if (sAssignedAlias.isEmpty()) {
+ sAssignedAlias = rProgrammaticName;
+ }
+ AliasEntry entry(j->second);
+ m_aAliasMap.erase(j);
+ m_aAliasMap[sAssignedAlias] = entry;
+ }
+ else {
+ SAL_WARN(
+ "connectivity.mork",
+ "unknown programmatic name " << rProgrammaticName
+ <<" from configuration");
+ }
+ }
+}
+
+
+OString OColumnAlias::getProgrammaticNameOrFallbackToUTF8Alias( const OUString& _rAlias ) const
+{
+ AliasMap::const_iterator pos = m_aAliasMap.find( _rAlias );
+ if ( pos == m_aAliasMap.end() )
+ {
+ OSL_FAIL( "OColumnAlias::getProgrammaticNameOrFallbackToUTF8Alias: no programmatic name for this alias!" );
+ return OUStringToOString( _rAlias, RTL_TEXTENCODING_UTF8 );
+ }
+ return pos->second.programmaticAsciiName;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/mork/MColumnAlias.hxx b/connectivity/source/drivers/mork/MColumnAlias.hxx
new file mode 100644
index 000000000..3900b324b
--- /dev/null
+++ b/connectivity/source/drivers/mork/MColumnAlias.hxx
@@ -0,0 +1,72 @@
+/* -*- 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 .
+ */
+
+
+#ifndef INCLUDED_CONNECTIVITY_SOURCE_DRIVERS_MORK_MCOLUMNALIAS_HXX
+#define INCLUDED_CONNECTIVITY_SOURCE_DRIVERS_MORK_MCOLUMNALIAS_HXX
+
+#include <unotools/confignode.hxx>
+
+#include <unordered_map>
+
+namespace connectivity
+{
+ namespace mork
+ {
+ class OColumnAlias
+ {
+ public:
+ struct AliasEntry
+ {
+ OString programmaticAsciiName;
+ size_t columnPosition;
+
+ AliasEntry()
+ :programmaticAsciiName()
+ ,columnPosition( 0 )
+ {
+ }
+ AliasEntry( const char* _programmaticAsciiName, size_t _columnPosition )
+ :programmaticAsciiName( _programmaticAsciiName )
+ ,columnPosition( _columnPosition )
+ {
+ }
+ };
+ typedef std::unordered_map< OUString, AliasEntry > AliasMap;
+
+ private:
+ AliasMap m_aAliasMap;
+
+ public:
+ explicit OColumnAlias( const css::uno::Reference< css::lang::XMultiServiceFactory > & );
+
+ OString getProgrammaticNameOrFallbackToUTF8Alias( const OUString& _rAlias ) const;
+
+ AliasMap::const_iterator begin() const { return m_aAliasMap.begin(); }
+ AliasMap::const_iterator end() const { return m_aAliasMap.end(); }
+
+
+ private:
+ void initialize( const css::uno::Reference< css::lang::XMultiServiceFactory >& _rxORB );
+ };
+ }
+}
+#endif // INCLUDED_CONNECTIVITY_SOURCE_DRIVERS_MORK_MCOLUMNALIAS_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/mork/MColumns.cxx b/connectivity/source/drivers/mork/MColumns.cxx
new file mode 100644
index 000000000..c9163a6ab
--- /dev/null
+++ b/connectivity/source/drivers/mork/MColumns.cxx
@@ -0,0 +1,80 @@
+/* -*- 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 "MColumns.hxx"
+#include <com/sun/star/sdbc/XRow.hpp>
+#include <connectivity/sdbcx/VColumn.hxx>
+
+using namespace connectivity::mork;
+using namespace connectivity::sdbcx;
+using namespace connectivity;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::sdbc;
+
+
+sdbcx::ObjectType OColumns::createObject(const OUString& _rName)
+{
+ const Any aCatalog;
+ const OUString sCatalogName;
+ const OUString sSchemaName(m_pTable->getSchema());
+ const OUString sTableName(m_pTable->getTableName());
+ Reference< XResultSet > xResult = m_pTable->getConnection()->getMetaData()->getColumns(
+ aCatalog, sSchemaName, sTableName, _rName);
+
+ sdbcx::ObjectType xRet;
+ if(xResult.is())
+ {
+ Reference< XRow > xRow(xResult,UNO_QUERY);
+ while(xResult->next())
+ {
+ if(xRow->getString(4) == _rName)
+ {
+ sal_Int32 nType = xRow->getInt(5);
+ OUString sTypeName = xRow->getString(6);
+ sal_Int32 nPrec = xRow->getInt(7);
+
+ OColumn* pRet = new OColumn(_rName,
+ sTypeName,
+ xRow->getString(13),
+ xRow->getString(12),
+ xRow->getInt(11),
+ nPrec,
+ xRow->getInt(9),
+ nType,
+ false,false,false,true,
+ sCatalogName,
+ sSchemaName,
+ sTableName);
+ xRet = pRet;
+ break;
+ }
+ }
+ }
+
+ return xRet;
+}
+
+
+void OColumns::impl_refresh()
+{
+ m_pTable->refreshColumns();
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/mork/MColumns.hxx b/connectivity/source/drivers/mork/MColumns.hxx
new file mode 100644
index 000000000..b0774af27
--- /dev/null
+++ b/connectivity/source/drivers/mork/MColumns.hxx
@@ -0,0 +1,48 @@
+/* -*- 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 .
+ */
+
+#ifndef INCLUDED_CONNECTIVITY_SOURCE_DRIVERS_MORK_MCOLUMNS_HXX
+#define INCLUDED_CONNECTIVITY_SOURCE_DRIVERS_MORK_MCOLUMNS_HXX
+
+#include <connectivity/sdbcx/VCollection.hxx>
+#include "MTable.hxx"
+
+namespace connectivity
+{
+ namespace mork
+ {
+ class OColumns final : public sdbcx::OCollection
+ {
+ OTable* m_pTable;
+
+ virtual sdbcx::ObjectType createObject(const OUString& _rName) override;
+ virtual void impl_refresh() override;
+ public:
+ OColumns( OTable* _pTable,
+ ::osl::Mutex& _rMutex,
+ const ::std::vector< OUString> &_rVector
+ ) : sdbcx::OCollection(*_pTable, true, _rMutex, _rVector)
+ ,m_pTable(_pTable)
+ {}
+ };
+ }
+}
+#endif // INCLUDED_CONNECTIVITY_SOURCE_DRIVERS_MORK_MCOLUMNS_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/mork/MConnection.cxx b/connectivity/source/drivers/mork/MConnection.cxx
new file mode 100644
index 000000000..e6658b6dc
--- /dev/null
+++ b/connectivity/source/drivers/mork/MConnection.cxx
@@ -0,0 +1,377 @@
+/* -*- 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/.
+ */
+
+#include "MConnection.hxx"
+#include "MDriver.hxx"
+#include "MDatabaseMetaData.hxx"
+#include "MCatalog.hxx"
+#include "MPreparedStatement.hxx"
+#include "MorkParser.hxx"
+
+#include <connectivity/dbexception.hxx>
+#include <sal/log.hxx>
+
+#include <strings.hrc>
+
+#include <com/sun/star/sdbc/TransactionIsolation.hpp>
+
+using namespace dbtools;
+
+
+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;
+
+
+namespace connectivity::mork {
+
+static const int defaultScope = 0x80;
+
+
+OConnection::OConnection(MorkDriver* _pDriver)
+ :m_xDriver(_pDriver)
+ ,m_aColumnAlias( _pDriver->getFactory() )
+{
+ m_pBook.reset( new MorkParser() );
+ m_pHistory.reset( new MorkParser() );
+}
+
+OConnection::~OConnection()
+{
+ if(!isClosed())
+ close();
+ m_pBook.reset();
+ m_pHistory.reset();
+}
+
+void OConnection::construct(const OUString& url)
+{
+ SAL_INFO("connectivity.mork", "=> OConnection::construct()" );
+ // open file
+ setURL(url);
+
+ // Skip 'sdbc:mozab: part of URL
+
+ sal_Int32 nLen = url.indexOf(':');
+ nLen = url.indexOf(':',nLen+1);
+ OSL_ENSURE( url.startsWith("sdbc:address:"), "OConnection::construct: invalid start of the URI - should never have survived XDriver::acceptsURL!" );
+
+ OUString aAddrbookURI(url.copy(nLen+1));
+ // Get Scheme
+ nLen = aAddrbookURI.indexOf(':');
+ OUString aAddrbookScheme;
+ if ( nLen == -1 )
+ {
+ // There isn't any subschema: - but could be just subschema
+ if ( !aAddrbookURI.isEmpty() )
+ {
+ aAddrbookScheme= aAddrbookURI;
+ }
+ else
+ {
+ SAL_WARN("connectivity.mork", "No subschema given!!!");
+ throwGenericSQLException( STR_URI_SYNTAX_ERROR, *this );
+ }
+ }
+ else
+ {
+ aAddrbookScheme = aAddrbookURI.copy(0, nLen);
+ }
+
+ SAL_INFO("connectivity.mork", "URI = " << aAddrbookURI );
+ SAL_INFO("connectivity.mork", "Scheme = " << aAddrbookScheme );
+
+ OUString abook;
+ OUString history;
+ const OUString UNITTEST_URL = "thunderbird:unittest:";
+ sal_Int32 unittestIndex = url.indexOf(UNITTEST_URL);
+
+ // production?
+ if (unittestIndex == -1)
+ {
+ OUString path = m_xDriver->getProfilePath();
+ SAL_INFO("connectivity.mork", "ProfilePath: " << path);
+ abook = path + "/abook.mab";
+ history = path + "/history.mab";
+ SAL_INFO("connectivity.mork", "AdressbookPath (abook): " << abook);
+ SAL_INFO("connectivity.mork", "AdressbookPath (history): " << history);
+ }
+ else
+ {
+ abook = aAddrbookURI.replaceFirst(UNITTEST_URL, "");
+ SAL_INFO("connectivity.mork", "unit test: " << abook);
+ }
+
+ OString strPath = OUStringToOString(abook, RTL_TEXTENCODING_UTF8);
+
+ // Open and parse mork file
+ if (!m_pBook->open(strPath.getStr()))
+ {
+ SAL_WARN("connectivity.mork", "Can not parse abook mork file: " << strPath);
+ const OUString sError( getResources().getResourceStringWithSubstitution(
+ STR_COULD_NOT_LOAD_FILE, "$filename$", abook));
+ ::dbtools::throwGenericSQLException( sError, *this );
+ }
+
+ // read history only in production
+ if (unittestIndex == -1)
+ {
+ strPath = OUStringToOString(history, RTL_TEXTENCODING_UTF8);
+ if (!m_pHistory->open(strPath.getStr()))
+ {
+ SAL_WARN("connectivity.mork", "Can not parse history mork file: " << strPath);
+ const OUString sError( getResources().getResourceStringWithSubstitution(
+ STR_COULD_NOT_LOAD_FILE, "$filename$", history));
+ ::dbtools::throwGenericSQLException( sError, *this );
+ }
+ }
+
+ // check that we can retrieve the tables:
+ MorkTableMap *Tables = m_pBook->getTables( defaultScope );
+ if (Tables)
+ {
+ // Iterate all tables
+ for ( const auto& rEntry : Tables->map )
+ {
+ if ( 0 == rEntry.first ) continue;
+ SAL_INFO("connectivity.mork", "table->first : " << rEntry.first);
+ }
+ }
+ // check that we can retrieve the history tables:
+ MorkTableMap *Tables_hist = m_pHistory->getTables( defaultScope );
+ if (Tables_hist)
+ {
+ // Iterate all tables
+ for ( const auto& rEntry : Tables_hist->map )
+ {
+ if ( 0 == rEntry.first ) continue;
+ SAL_INFO("connectivity.mork", "table->first : " << rEntry.first);
+ }
+ }
+}
+
+// XServiceInfo
+
+IMPLEMENT_SERVICE_INFO(OConnection, "com.sun.star.sdbc.drivers.mork.OConnection", "com.sun.star.sdbc.Connection")
+
+
+Reference< XStatement > SAL_CALL OConnection::createStatement( )
+{
+ SAL_INFO("connectivity.mork", "=> OConnection::createStatement()" );
+
+ ::osl::MutexGuard aGuard( m_aMutex );
+ checkDisposed(OConnection_BASE::rBHelper.bDisposed);
+
+ // create a statement
+ // the statement can only be executed once
+ Reference< XStatement > xReturn = new OStatement(this);
+ m_aStatements.push_back(WeakReferenceHelper(xReturn));
+ return xReturn;
+}
+
+Reference< XPreparedStatement > SAL_CALL OConnection::prepareStatement( const OUString& _sSql )
+{
+ SAL_INFO("connectivity.mork", "=> OConnection::prepareStatement()" );
+ SAL_INFO("connectivity.mork", "OConnection::prepareStatement( " << _sSql << " )");
+
+ ::osl::MutexGuard aGuard( m_aMutex );
+ checkDisposed(OConnection_BASE::rBHelper.bDisposed);
+
+ // the pre
+ // create a statement
+ // the statement can only be executed more than once
+ OPreparedStatement* pPrepared = new OPreparedStatement(this,_sSql);
+ Reference< XPreparedStatement > xReturn = pPrepared;
+ pPrepared->lateInit();
+
+ m_aStatements.push_back(WeakReferenceHelper(xReturn));
+ return xReturn;
+}
+
+Reference< XPreparedStatement > SAL_CALL OConnection::prepareCall( const OUString& _sSql )
+{
+ SAL_INFO("connectivity.mork", "=> OConnection::prepareCall()" );
+ SAL_INFO("connectivity.mork", "sql: " << _sSql);
+ ::dbtools::throwFeatureNotImplementedSQLException( "XConnection::prepareCall", *this );
+ SAL_INFO("connectivity.mork", "OConnection::prepareCall( " << _sSql << " )");
+ return nullptr;
+}
+
+OUString SAL_CALL OConnection::nativeSQL( const OUString& _sSql )
+{
+ SAL_INFO("connectivity.mork", "=> OConnection::nativeSQL()" );
+ SAL_INFO("connectivity.mork", "sql: " << _sSql);
+
+ ::osl::MutexGuard aGuard( m_aMutex );
+ // when you need to transform SQL92 to you driver specific you can do it here
+ SAL_INFO("connectivity.mork", "OConnection::nativeSQL(" << _sSql << " )" );
+
+ return _sSql;
+}
+
+void SAL_CALL OConnection::setAutoCommit( sal_Bool /*autoCommit*/ )
+{
+ ::dbtools::throwFeatureNotImplementedSQLException( "XConnection::setAutoCommit", *this );
+}
+
+sal_Bool SAL_CALL OConnection::getAutoCommit( )
+{
+ // you have to distinguish which if you are in autocommit mode or not
+ // at normal case true should be fine here
+
+ return true;
+}
+
+void SAL_CALL OConnection::commit( )
+{
+ // when you database does support transactions you should commit here
+}
+
+void SAL_CALL OConnection::rollback( )
+{
+ // same as commit but for the other case
+}
+
+sal_Bool SAL_CALL OConnection::isClosed( )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ // just simple -> we are close when we are disposed that means someone called dispose(); (XComponent)
+ return OConnection_BASE::rBHelper.bDisposed;
+}
+
+Reference< XDatabaseMetaData > SAL_CALL OConnection::getMetaData( )
+{
+ SAL_INFO("connectivity.mork", "=> OConnection::getMetaData()" );
+
+ ::osl::MutexGuard aGuard( m_aMutex );
+ checkDisposed(OConnection_BASE::rBHelper.bDisposed);
+
+ // here we have to create the class with biggest interface
+ // The answer is 42 :-)
+ Reference< XDatabaseMetaData > xMetaData = m_xMetaData;
+ if(!xMetaData.is())
+ {
+ xMetaData = new ODatabaseMetaData(this); // need the connection because it can return it
+ m_xMetaData = xMetaData;
+ }
+
+ return xMetaData;
+}
+
+void SAL_CALL OConnection::setReadOnly( sal_Bool /*readOnly*/ )
+{
+ ::dbtools::throwFeatureNotImplementedSQLException( "XConnection::setReadOnly", *this );
+}
+
+sal_Bool SAL_CALL OConnection::isReadOnly( )
+{
+ // return if your connection to readonly
+ return false;
+}
+
+void SAL_CALL OConnection::setCatalog( const OUString& /*catalog*/ )
+{
+ ::dbtools::throwFeatureNotImplementedSQLException( "XConnection::setCatalog", *this );
+}
+
+OUString SAL_CALL OConnection::getCatalog( )
+{
+ return OUString();
+}
+
+void SAL_CALL OConnection::setTransactionIsolation( sal_Int32 /*level*/ )
+{
+ ::dbtools::throwFeatureNotImplementedSQLException( "XConnection::setTransactionIsolation", *this );
+}
+
+sal_Int32 SAL_CALL OConnection::getTransactionIsolation( )
+{
+ // please have a look at @see com.sun.star.sdbc.TransactionIsolation
+ return TransactionIsolation::NONE;
+}
+
+Reference< css::container::XNameAccess > SAL_CALL OConnection::getTypeMap( )
+{
+ // if your driver has special database types you can return it here
+ return nullptr;
+}
+
+void SAL_CALL OConnection::setTypeMap( const Reference< css::container::XNameAccess >& /*typeMap*/ )
+{
+ ::dbtools::throwFeatureNotImplementedSQLException( "XConnection::setTypeMap", *this );
+}
+
+// XCloseable
+void SAL_CALL OConnection::close( )
+{
+ // we just dispose us
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+ checkDisposed(OConnection_BASE::rBHelper.bDisposed);
+
+ }
+ dispose();
+}
+
+// XWarningsSupplier
+Any SAL_CALL OConnection::getWarnings( )
+{
+ // when you collected some warnings -> return it
+ return Any();
+}
+
+void SAL_CALL OConnection::clearWarnings( )
+{
+ // you should clear your collected warnings here
+}
+
+void OConnection::disposing()
+{
+ // we noticed that we should be destroyed in near future so we have to dispose our statements
+ ::osl::MutexGuard aGuard(m_aMutex);
+ m_xCatalog.clear();
+}
+
+Reference< XTablesSupplier > OConnection::createCatalog()
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ Reference< XTablesSupplier > xTab = m_xCatalog;
+ if(!m_xCatalog.is())
+ {
+ OCatalog *pCat = new OCatalog(this);
+ xTab = pCat;
+ m_xCatalog = xTab;
+ }
+ return xTab;
+}
+
+void OConnection::throwSQLException( const ErrorDescriptor& _rError, const Reference< XInterface >& _rxContext )
+{
+ if (_rError.getResId() != nullptr)
+ {
+ throwGenericSQLException( _rError.getResId(), _rxContext );
+ OSL_FAIL( "OConnection::throwSQLException: unreachable (2)!" );
+ }
+
+ throwGenericSQLException( STR_UNSPECIFIED_ERROR, _rxContext );
+}
+
+void OConnection::throwSQLException( const char* pErrorResourceId, const Reference< XInterface >& _rxContext )
+{
+ ErrorDescriptor aError;
+ aError.setResId(pErrorResourceId);
+ throwSQLException(aError, _rxContext);
+}
+
+} // namespace connectivity::mork
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/mork/MConnection.hxx b/connectivity/source/drivers/mork/MConnection.hxx
new file mode 100644
index 000000000..0bcb936bd
--- /dev/null
+++ b/connectivity/source/drivers/mork/MConnection.hxx
@@ -0,0 +1,98 @@
+/* -*- 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/.
+ */
+
+#ifndef INCLUDED_CONNECTIVITY_SOURCE_DRIVERS_MORK_MCONNECTION_HXX
+#define INCLUDED_CONNECTIVITY_SOURCE_DRIVERS_MORK_MCONNECTION_HXX
+
+#include <TConnection.hxx>
+#include "MColumnAlias.hxx"
+
+#include <com/sun/star/sdbcx/XTablesSupplier.hpp>
+
+// do we want here namespace too?
+class MorkParser;
+
+namespace connectivity
+{
+ namespace mork
+ {
+ class MorkDriver;
+ class ErrorDescriptor;
+
+ typedef connectivity::OMetaConnection OConnection_BASE; // implements basics and text encoding
+
+ class OConnection final : public OConnection_BASE
+ {
+ // Data attributes
+
+ rtl::Reference<MorkDriver> m_xDriver; // Pointer to the owning
+ // driver object
+ OColumnAlias m_aColumnAlias;
+ // Mork Parser (abook)
+ std::unique_ptr<MorkParser> m_pBook;
+ // Mork Parser (history)
+ std::unique_ptr<MorkParser> m_pHistory;
+ // Store Catalog
+ css::uno::Reference< css::sdbcx::XTablesSupplier> m_xCatalog;
+
+ public:
+ /// @throws css::sdbc::SQLException
+ void construct( const OUString& url);
+ explicit OConnection(MorkDriver* const driver);
+ virtual ~OConnection() override;
+
+ const rtl::Reference<MorkDriver>& getDriver() const {return m_xDriver;};
+ MorkParser* getMorkParser(const OString& t) {return t == "CollectedAddressBook" ? m_pHistory.get() : m_pBook.get();};
+
+ // OComponentHelper
+ virtual void SAL_CALL disposing() override;
+
+ // XServiceInfo
+ DECLARE_SERVICE_INFO();
+ // XConnection
+ virtual css::uno::Reference< css::sdbc::XStatement > SAL_CALL createStatement( ) override;
+ virtual css::uno::Reference< css::sdbc::XPreparedStatement > SAL_CALL prepareStatement( const OUString& sql ) override;
+ virtual css::uno::Reference< css::sdbc::XPreparedStatement > SAL_CALL prepareCall( const OUString& sql ) override;
+ virtual OUString SAL_CALL nativeSQL( const OUString& sql ) override;
+ virtual void SAL_CALL setAutoCommit( sal_Bool autoCommit ) override;
+ virtual sal_Bool SAL_CALL getAutoCommit( ) override;
+ virtual void SAL_CALL commit( ) override;
+ virtual void SAL_CALL rollback( ) override;
+ virtual sal_Bool SAL_CALL isClosed( ) override;
+ virtual css::uno::Reference< css::sdbc::XDatabaseMetaData > SAL_CALL getMetaData( ) override;
+ virtual void SAL_CALL setReadOnly( sal_Bool readOnly ) override;
+ virtual sal_Bool SAL_CALL isReadOnly( ) override;
+ virtual void SAL_CALL setCatalog( const OUString& catalog ) override;
+ virtual OUString SAL_CALL getCatalog( ) override;
+ virtual void SAL_CALL setTransactionIsolation( sal_Int32 level ) override;
+ virtual sal_Int32 SAL_CALL getTransactionIsolation( ) override;
+ virtual css::uno::Reference< css::container::XNameAccess > SAL_CALL getTypeMap( ) override;
+ virtual void SAL_CALL setTypeMap( const css::uno::Reference< css::container::XNameAccess >& typeMap ) override;
+ // XCloseable
+ virtual void SAL_CALL close( ) override;
+ // XWarningsSupplier
+ virtual css::uno::Any SAL_CALL getWarnings( ) override;
+ virtual void SAL_CALL clearWarnings() override;
+
+ const OColumnAlias & getColumnAlias() const { return m_aColumnAlias; }
+
+ static bool getForceLoadTables() {return true;}
+
+ // Added to enable me to use SQLInterpreter which requires an
+ // XNameAccess i/f to access tables.
+ css::uno::Reference< css::sdbcx::XTablesSupplier > createCatalog();
+
+ void throwSQLException( const ErrorDescriptor& _rError, const css::uno::Reference< css::uno::XInterface >& _rxContext );
+ void throwSQLException( const char* pErrorResourceId, const css::uno::Reference< css::uno::XInterface >& _rxContext );
+ };
+ }
+}
+#endif // INCLUDED_CONNECTIVITY_SOURCE_DRIVERS_MORK_MCONNECTION_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/mork/MDatabaseMetaData.cxx b/connectivity/source/drivers/mork/MDatabaseMetaData.cxx
new file mode 100644
index 000000000..7858230b0
--- /dev/null
+++ b/connectivity/source/drivers/mork/MDatabaseMetaData.cxx
@@ -0,0 +1,957 @@
+/* -*- 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/.
+ */
+
+#include "MConnection.hxx"
+#include "MDatabaseMetaData.hxx"
+
+#include <com/sun/star/sdbc/TransactionIsolation.hpp>
+#include <com/sun/star/sdbc/ColumnSearch.hpp>
+#include <sal/log.hxx>
+#include <vector>
+
+#include "MDatabaseMetaDataHelper.hxx"
+
+using namespace connectivity::mork;
+using namespace connectivity;
+
+using namespace com::sun::star::uno;
+using namespace com::sun::star::sdbc;
+
+
+namespace connectivity::mork
+{
+ static sal_Int32 const s_nCOLUMN_SIZE = 256;
+ static sal_Int32 const s_nDECIMAL_DIGITS = 0;
+ static sal_Int32 const s_nNULLABLE = 1;
+ static sal_Int32 const s_nCHAR_OCTET_LENGTH = 65535;
+}
+
+ODatabaseMetaData::ODatabaseMetaData(OConnection* _pCon)
+ : ::connectivity::ODatabaseMetaDataBase(_pCon,_pCon->getConnectionInfo())
+ ,m_pConnection(_pCon)
+ ,m_pMetaDataHelper(new MDatabaseMetaDataHelper)
+{
+ OSL_ENSURE(m_pConnection,"ODatabaseMetaData::ODatabaseMetaData: No connection set!");
+}
+
+ODatabaseMetaData::~ODatabaseMetaData()
+{
+}
+
+
+ODatabaseMetaDataResultSet::ORows ODatabaseMetaData::getColumnRows(
+ const OUString& tableNamePattern,
+ const OUString& columnNamePattern )
+{
+ SAL_INFO("connectivity.mork", "=> ODatabaseMetaData::getColumnRows()" );
+ SAL_INFO("connectivity.mork", "tableNamePattern: " << tableNamePattern);
+ SAL_INFO("connectivity.mork", "columnNamePattern: " << columnNamePattern);
+
+ ODatabaseMetaDataResultSet::ORows aRows;
+ ODatabaseMetaDataResultSet::ORow aRow(19);
+
+ ::osl::MutexGuard aGuard( m_aMutex );
+ std::vector< OUString > tables;
+ connectivity::mork::MDatabaseMetaDataHelper::getTableStrings(m_pConnection, tables);
+
+ // ****************************************************
+ // Some entries in a row never change, so set them now
+ // ****************************************************
+
+ // Catalog
+ aRow[1] = new ORowSetValueDecorator(OUString());
+ // Schema
+ aRow[2] = new ORowSetValueDecorator(OUString());
+ // DATA_TYPE
+ aRow[5] = new ORowSetValueDecorator(static_cast<sal_Int16>(DataType::VARCHAR));
+ // TYPE_NAME, not used
+ aRow[6] = new ORowSetValueDecorator(OUString("VARCHAR"));
+ // COLUMN_SIZE
+ aRow[7] = new ORowSetValueDecorator(s_nCOLUMN_SIZE);
+ // BUFFER_LENGTH, not used
+ aRow[8] = ODatabaseMetaDataResultSet::getEmptyValue();
+ // DECIMAL_DIGITS.
+ aRow[9] = new ORowSetValueDecorator(s_nDECIMAL_DIGITS);
+ // NUM_PREC_RADIX
+ aRow[10] = new ORowSetValueDecorator(sal_Int32(10));
+ // NULLABLE
+ aRow[11] = new ORowSetValueDecorator(s_nNULLABLE);
+ // REMARKS
+ aRow[12] = ODatabaseMetaDataResultSet::getEmptyValue();
+ // COULUMN_DEF, not used
+ aRow[13] = ODatabaseMetaDataResultSet::getEmptyValue();
+ // SQL_DATA_TYPE, not used
+ aRow[14] = ODatabaseMetaDataResultSet::getEmptyValue();
+ // SQL_DATETIME_SUB, not used
+ aRow[15] = ODatabaseMetaDataResultSet::getEmptyValue();
+ // CHAR_OCTET_LENGTH, refer to [5]
+ aRow[16] = new ORowSetValueDecorator(s_nCHAR_OCTET_LENGTH);
+ // IS_NULLABLE
+ aRow[18] = new ORowSetValueDecorator(OUString("YES"));
+
+ // Iterate over all tables
+ for(const OUString & table : tables) {
+ if(match(tableNamePattern, table,'\0')) {
+ // TABLE_NAME
+ aRow[3] = new ORowSetValueDecorator( table );
+
+ const OColumnAlias& colNames = m_pConnection->getColumnAlias();
+
+ SAL_INFO("connectivity.mork", "\tTableName = : " << table);
+ // Iterate over all columns in the table.
+ for (const auto& [rName, rAlias] : colNames)
+ {
+ if ( match( columnNamePattern, rName, '\0' ) )
+ {
+ SAL_INFO("connectivity.mork", "\t\tColumnNam : " << rName);
+
+ // COLUMN_NAME
+ aRow[4] = new ORowSetValueDecorator( rName );
+ // ORDINAL_POSITION
+ aRow[17] = new ORowSetValueDecorator( static_cast< sal_Int32 >( rAlias.columnPosition ) + 1 );
+ aRows.push_back(aRow);
+ }
+ }
+ }
+ }
+ return aRows;
+}
+
+OUString ODatabaseMetaData::impl_getCatalogSeparator_throw( )
+{
+ return OUString();
+}
+
+sal_Int32 SAL_CALL ODatabaseMetaData::getMaxBinaryLiteralLength( )
+{
+ return 65535; // 0 means no limit
+}
+
+sal_Int32 SAL_CALL ODatabaseMetaData::getMaxRowSize( )
+{
+ return 0; // 0 means no limit
+}
+
+sal_Int32 SAL_CALL ODatabaseMetaData::getMaxCatalogNameLength( )
+{
+ return 0; // 0 means no limit
+}
+
+sal_Int32 SAL_CALL ODatabaseMetaData::getMaxCharLiteralLength( )
+{
+ return 254; // 0 means no limit
+}
+
+sal_Int32 SAL_CALL ODatabaseMetaData::getMaxColumnNameLength( )
+{
+ return 20; // 0 means no limit
+}
+
+sal_Int32 SAL_CALL ODatabaseMetaData::getMaxColumnsInIndex( )
+{
+ return 0; // 0 means no limit
+}
+
+sal_Int32 SAL_CALL ODatabaseMetaData::getMaxCursorNameLength( )
+{
+ return 0; // 0 means no limit
+}
+
+sal_Int32 SAL_CALL ODatabaseMetaData::getMaxConnections( )
+{
+ return 0; // 0 means no limit
+}
+
+sal_Int32 SAL_CALL ODatabaseMetaData::getMaxColumnsInTable( )
+{
+ return 0; // 0 means no limit
+}
+
+sal_Int32 ODatabaseMetaData::impl_getMaxStatements_throw( )
+{
+ return 0;
+}
+
+sal_Int32 SAL_CALL ODatabaseMetaData::getMaxTableNameLength( )
+{
+ return 0; // 0 means no limit
+}
+
+sal_Int32 ODatabaseMetaData::impl_getMaxTablesInSelect_throw( )
+{
+ // We only support a single table
+ return 1;
+}
+
+
+sal_Bool SAL_CALL ODatabaseMetaData::doesMaxRowSizeIncludeBlobs( )
+{
+ return false;
+}
+
+sal_Bool SAL_CALL ODatabaseMetaData::storesLowerCaseQuotedIdentifiers( )
+{
+ return false;
+}
+
+sal_Bool SAL_CALL ODatabaseMetaData::storesLowerCaseIdentifiers( )
+{
+ return false;
+}
+
+bool ODatabaseMetaData::impl_storesMixedCaseQuotedIdentifiers_throw( )
+{
+ return false;
+}
+
+sal_Bool SAL_CALL ODatabaseMetaData::storesMixedCaseIdentifiers( )
+{
+ return false;
+}
+
+sal_Bool SAL_CALL ODatabaseMetaData::storesUpperCaseQuotedIdentifiers( )
+{
+ return false;
+}
+
+sal_Bool SAL_CALL ODatabaseMetaData::storesUpperCaseIdentifiers( )
+{
+ return false;
+}
+
+bool ODatabaseMetaData::impl_supportsAlterTableWithAddColumn_throw( )
+{
+ return false;
+}
+
+bool ODatabaseMetaData::impl_supportsAlterTableWithDropColumn_throw( )
+{
+ return false;
+}
+
+sal_Int32 SAL_CALL ODatabaseMetaData::getMaxIndexLength( )
+{
+ return 0; // 0 means no limit
+}
+
+sal_Bool SAL_CALL ODatabaseMetaData::supportsNonNullableColumns( )
+{
+ return false;
+}
+
+OUString SAL_CALL ODatabaseMetaData::getCatalogTerm( )
+{
+ return OUString();
+}
+
+OUString ODatabaseMetaData::impl_getIdentifierQuoteString_throw( )
+{
+ // normally this is "
+ return "\"";
+}
+
+OUString SAL_CALL ODatabaseMetaData::getExtraNameCharacters( )
+{
+ return OUString();
+}
+
+sal_Bool SAL_CALL ODatabaseMetaData::supportsDifferentTableCorrelationNames( )
+{
+ return true;
+}
+
+bool ODatabaseMetaData::impl_isCatalogAtStart_throw( )
+{
+ return true;
+}
+
+sal_Bool SAL_CALL ODatabaseMetaData::dataDefinitionIgnoredInTransactions( )
+{
+ return true;
+}
+
+sal_Bool SAL_CALL ODatabaseMetaData::dataDefinitionCausesTransactionCommit( )
+{
+ return true;
+}
+
+sal_Bool SAL_CALL ODatabaseMetaData::supportsDataManipulationTransactionsOnly( )
+{
+ //We support create table
+ return false;
+}
+
+sal_Bool SAL_CALL ODatabaseMetaData::supportsDataDefinitionAndDataManipulationTransactions( )
+{
+ return false;
+}
+
+sal_Bool SAL_CALL ODatabaseMetaData::supportsPositionedDelete( )
+{
+ return false;
+}
+
+sal_Bool SAL_CALL ODatabaseMetaData::supportsPositionedUpdate( )
+{
+ return false;
+}
+
+sal_Bool SAL_CALL ODatabaseMetaData::supportsOpenStatementsAcrossRollback( )
+{
+ return false;
+}
+
+sal_Bool SAL_CALL ODatabaseMetaData::supportsOpenStatementsAcrossCommit( )
+{
+ return false;
+}
+
+sal_Bool SAL_CALL ODatabaseMetaData::supportsOpenCursorsAcrossCommit( )
+{
+ return false;
+}
+
+sal_Bool SAL_CALL ODatabaseMetaData::supportsOpenCursorsAcrossRollback( )
+{
+ return false;
+}
+
+sal_Bool SAL_CALL ODatabaseMetaData::supportsTransactionIsolationLevel( sal_Int32 /*level*/ )
+{
+ return false;
+}
+
+bool ODatabaseMetaData::impl_supportsSchemasInDataManipulation_throw( )
+{
+ return false;
+}
+
+sal_Bool SAL_CALL ODatabaseMetaData::supportsANSI92FullSQL( )
+{
+ return false;
+}
+
+sal_Bool SAL_CALL ODatabaseMetaData::supportsANSI92EntryLevelSQL( )
+{
+ return true; // should be supported at least
+}
+
+sal_Bool SAL_CALL ODatabaseMetaData::supportsIntegrityEnhancementFacility( )
+{
+ return false;
+}
+
+sal_Bool SAL_CALL ODatabaseMetaData::supportsSchemasInIndexDefinitions( )
+{
+ return false;
+}
+
+bool ODatabaseMetaData::impl_supportsSchemasInTableDefinitions_throw( )
+{
+ return false;
+}
+
+bool ODatabaseMetaData::impl_supportsCatalogsInTableDefinitions_throw( )
+{
+ return false;
+}
+
+sal_Bool SAL_CALL ODatabaseMetaData::supportsCatalogsInIndexDefinitions( )
+{
+ return false;
+}
+
+bool ODatabaseMetaData::impl_supportsCatalogsInDataManipulation_throw( )
+{
+ return false;
+}
+
+sal_Bool SAL_CALL ODatabaseMetaData::supportsOuterJoins( )
+{
+ return false;
+}
+
+sal_Int32 SAL_CALL ODatabaseMetaData::getMaxStatementLength( )
+{
+ return 0;// 0 means no limit
+}
+
+sal_Int32 SAL_CALL ODatabaseMetaData::getMaxProcedureNameLength( )
+{
+ return 0; // 0 means no limit
+}
+
+sal_Int32 SAL_CALL ODatabaseMetaData::getMaxSchemaNameLength( )
+{
+ return 0; // 0 means no limit
+}
+
+sal_Bool SAL_CALL ODatabaseMetaData::supportsTransactions( )
+{
+ return false;
+}
+
+sal_Bool SAL_CALL ODatabaseMetaData::allProceduresAreCallable( )
+{
+ return false;
+}
+
+sal_Bool SAL_CALL ODatabaseMetaData::supportsStoredProcedures( )
+{
+ return false;
+}
+
+sal_Bool SAL_CALL ODatabaseMetaData::supportsSelectForUpdate( )
+{
+ return false;
+}
+
+sal_Bool SAL_CALL ODatabaseMetaData::allTablesAreSelectable( )
+{
+ // We allow you to select from any table.
+ return true;
+}
+
+sal_Bool SAL_CALL ODatabaseMetaData::isReadOnly( )
+{
+ //we support insert/update/delete now
+ //But we have to set this to return sal_True otherwise the UI will add create "table/edit table"
+ //entry to the popup menu. We should avoid them.
+ return true;
+}
+
+sal_Bool SAL_CALL ODatabaseMetaData::usesLocalFiles( )
+{
+ return false;
+}
+
+sal_Bool SAL_CALL ODatabaseMetaData::usesLocalFilePerTable( )
+{
+ return false;
+}
+
+sal_Bool SAL_CALL ODatabaseMetaData::supportsTypeConversion( )
+{
+ return false;
+}
+
+sal_Bool SAL_CALL ODatabaseMetaData::nullPlusNonNullIsNull( )
+{
+ return false;
+}
+
+sal_Bool SAL_CALL ODatabaseMetaData::supportsColumnAliasing( )
+{
+ // Support added for this.
+ return true;
+}
+
+sal_Bool SAL_CALL ODatabaseMetaData::supportsTableCorrelationNames( )
+{
+ return false;
+}
+
+sal_Bool SAL_CALL ODatabaseMetaData::supportsConvert( sal_Int32 /*fromType*/, sal_Int32 /*toType*/ )
+{
+ return false;
+}
+
+sal_Bool SAL_CALL ODatabaseMetaData::supportsExpressionsInOrderBy( )
+{
+ return false;
+}
+
+sal_Bool SAL_CALL ODatabaseMetaData::supportsGroupBy( )
+{
+ return false;
+}
+
+sal_Bool SAL_CALL ODatabaseMetaData::supportsGroupByBeyondSelect( )
+{
+ return false;
+}
+
+sal_Bool SAL_CALL ODatabaseMetaData::supportsGroupByUnrelated( )
+{
+ return false;
+}
+
+sal_Bool SAL_CALL ODatabaseMetaData::supportsMultipleTransactions( )
+{
+ return false;
+}
+
+sal_Bool SAL_CALL ODatabaseMetaData::supportsMultipleResultSets( )
+{
+ return false;
+}
+
+sal_Bool SAL_CALL ODatabaseMetaData::supportsLikeEscapeClause( )
+{
+ return false;
+}
+
+sal_Bool SAL_CALL ODatabaseMetaData::supportsOrderByUnrelated( )
+{
+ return false;
+}
+
+sal_Bool SAL_CALL ODatabaseMetaData::supportsUnion( )
+{
+ return false;
+}
+
+sal_Bool SAL_CALL ODatabaseMetaData::supportsUnionAll( )
+{
+ return false;
+}
+
+sal_Bool SAL_CALL ODatabaseMetaData::supportsMixedCaseIdentifiers( )
+{
+ return true;
+}
+
+bool ODatabaseMetaData::impl_supportsMixedCaseQuotedIdentifiers_throw( )
+{
+ // Any case may be used
+ return true;
+}
+
+sal_Bool SAL_CALL ODatabaseMetaData::nullsAreSortedAtEnd( )
+{
+ return false;
+}
+
+sal_Bool SAL_CALL ODatabaseMetaData::nullsAreSortedAtStart( )
+{
+ return true;
+}
+
+sal_Bool SAL_CALL ODatabaseMetaData::nullsAreSortedHigh( )
+{
+ return false;
+}
+
+sal_Bool SAL_CALL ODatabaseMetaData::nullsAreSortedLow( )
+{
+ return true;
+}
+
+sal_Bool SAL_CALL ODatabaseMetaData::supportsSchemasInProcedureCalls( )
+{
+ return false;
+}
+
+sal_Bool SAL_CALL ODatabaseMetaData::supportsSchemasInPrivilegeDefinitions( )
+{
+ return false;
+}
+
+sal_Bool SAL_CALL ODatabaseMetaData::supportsCatalogsInProcedureCalls( )
+{
+ return false;
+}
+
+sal_Bool SAL_CALL ODatabaseMetaData::supportsCatalogsInPrivilegeDefinitions( )
+{
+ return false;
+}
+
+sal_Bool SAL_CALL ODatabaseMetaData::supportsCorrelatedSubqueries( )
+{
+ return false;
+}
+
+sal_Bool SAL_CALL ODatabaseMetaData::supportsSubqueriesInComparisons( )
+{
+ return false;
+}
+
+sal_Bool SAL_CALL ODatabaseMetaData::supportsSubqueriesInExists( )
+{
+ return false;
+}
+
+sal_Bool SAL_CALL ODatabaseMetaData::supportsSubqueriesInIns( )
+{
+ return false;
+}
+
+sal_Bool SAL_CALL ODatabaseMetaData::supportsSubqueriesInQuantifieds( )
+{
+ return false;
+}
+
+sal_Bool SAL_CALL ODatabaseMetaData::supportsANSI92IntermediateSQL( )
+{
+ return false;
+}
+
+OUString SAL_CALL ODatabaseMetaData::getURL( )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ return m_pConnection->getURL();
+}
+
+OUString SAL_CALL ODatabaseMetaData::getUserName( )
+{
+ return OUString();
+}
+
+OUString SAL_CALL ODatabaseMetaData::getDriverName( )
+{
+ return OUString();
+}
+
+OUString SAL_CALL ODatabaseMetaData::getDriverVersion()
+{
+ OUString aValue = OUString::number(1);
+ return aValue;
+}
+
+OUString SAL_CALL ODatabaseMetaData::getDatabaseProductVersion( )
+{
+ OUString aValue = OUString::number(0);
+ return aValue;
+}
+
+OUString SAL_CALL ODatabaseMetaData::getDatabaseProductName( )
+{
+ return OUString();
+}
+
+OUString SAL_CALL ODatabaseMetaData::getProcedureTerm( )
+{
+ return OUString();
+}
+
+OUString SAL_CALL ODatabaseMetaData::getSchemaTerm( )
+{
+ return OUString();
+}
+
+sal_Int32 SAL_CALL ODatabaseMetaData::getDriverMajorVersion( )
+{
+ return 1;
+}
+
+sal_Int32 SAL_CALL ODatabaseMetaData::getDefaultTransactionIsolation( )
+{
+ return TransactionIsolation::NONE;
+}
+
+sal_Int32 SAL_CALL ODatabaseMetaData::getDriverMinorVersion( )
+{
+ return 0;
+}
+
+OUString SAL_CALL ODatabaseMetaData::getSQLKeywords( )
+{
+ return OUString();
+}
+
+OUString SAL_CALL ODatabaseMetaData::getSearchStringEscape( )
+{
+ return OUString();
+}
+
+OUString SAL_CALL ODatabaseMetaData::getStringFunctions( )
+{
+ return OUString();
+}
+
+OUString SAL_CALL ODatabaseMetaData::getTimeDateFunctions( )
+{
+ return OUString();
+}
+
+OUString SAL_CALL ODatabaseMetaData::getSystemFunctions( )
+{
+ return OUString();
+}
+
+OUString SAL_CALL ODatabaseMetaData::getNumericFunctions( )
+{
+ return OUString();
+}
+
+sal_Bool SAL_CALL ODatabaseMetaData::supportsExtendedSQLGrammar( )
+{
+ return false;
+}
+
+sal_Bool SAL_CALL ODatabaseMetaData::supportsCoreSQLGrammar( )
+{
+ return false;
+}
+
+sal_Bool SAL_CALL ODatabaseMetaData::supportsMinimumSQLGrammar( )
+{
+ return true;
+}
+
+sal_Bool SAL_CALL ODatabaseMetaData::supportsFullOuterJoins( )
+{
+ return false;
+}
+
+sal_Bool SAL_CALL ODatabaseMetaData::supportsLimitedOuterJoins( )
+{
+ return false;
+}
+
+sal_Int32 SAL_CALL ODatabaseMetaData::getMaxColumnsInGroupBy( )
+{
+ return 0; // 0 means no limit
+}
+
+sal_Int32 SAL_CALL ODatabaseMetaData::getMaxColumnsInOrderBy( )
+{
+ return 0; // 0 means no limit
+}
+
+sal_Int32 SAL_CALL ODatabaseMetaData::getMaxColumnsInSelect( )
+{
+ return 0; // 0 means no limit
+}
+
+sal_Int32 SAL_CALL ODatabaseMetaData::getMaxUserNameLength( )
+{
+ return 0; // 0 means no limit
+}
+
+sal_Bool SAL_CALL ODatabaseMetaData::supportsResultSetType( sal_Int32 /*setType*/ )
+{
+ return false;
+}
+
+sal_Bool SAL_CALL ODatabaseMetaData::supportsResultSetConcurrency( sal_Int32 /*setType*/, sal_Int32 /*concurrency*/ )
+{
+ return false;
+}
+
+sal_Bool SAL_CALL ODatabaseMetaData::ownUpdatesAreVisible( sal_Int32 /*setType*/ )
+{
+ return true;
+}
+
+sal_Bool SAL_CALL ODatabaseMetaData::ownDeletesAreVisible( sal_Int32 /*setType*/ )
+{
+ return true;
+}
+
+sal_Bool SAL_CALL ODatabaseMetaData::ownInsertsAreVisible( sal_Int32 /*setType*/ )
+{
+ return true;
+}
+
+sal_Bool SAL_CALL ODatabaseMetaData::othersUpdatesAreVisible( sal_Int32 /*setType*/ )
+{
+ return false;
+}
+
+sal_Bool SAL_CALL ODatabaseMetaData::othersDeletesAreVisible( sal_Int32 /*setType*/ )
+{
+ return false;
+}
+
+sal_Bool SAL_CALL ODatabaseMetaData::othersInsertsAreVisible( sal_Int32 /*setType*/ )
+{
+ return false;
+}
+
+sal_Bool SAL_CALL ODatabaseMetaData::updatesAreDetected( sal_Int32 /*setType*/ )
+{
+ return true;
+}
+
+sal_Bool SAL_CALL ODatabaseMetaData::deletesAreDetected( sal_Int32 /*setType*/ )
+{
+ return true;
+}
+
+sal_Bool SAL_CALL ODatabaseMetaData::insertsAreDetected( sal_Int32 /*setType*/ )
+{
+ return true;
+}
+
+sal_Bool SAL_CALL ODatabaseMetaData::supportsBatchUpdates( )
+{
+ return false;
+}
+
+// here follow all methods which return a resultset
+// the first methods is an example implementation how to use this resultset
+// of course you could implement it on your and you should do this because
+// the general way is more memory expensive
+
+Reference< XResultSet > SAL_CALL ODatabaseMetaData::getTableTypes( )
+{
+ // there exists no possibility to get table types so we have to check
+ static const OUStringLiteral sTableTypes[] =
+ {
+ "TABLE",
+ "VIEW"
+ // Currently we only support a 'TABLE' and 'VIEW' nothing more complex
+
+ // OUString("SYSTEM TABLE"),
+ // OUString("GLOBAL TEMPORARY"),
+ // OUString("LOCAL TEMPORARY"),
+ // OUString("ALIAS"),
+ // OUString("SYNONYM")
+ };
+ ::connectivity::ODatabaseMetaDataResultSet* pResult = new ::connectivity::ODatabaseMetaDataResultSet(ODatabaseMetaDataResultSet::eTableTypes);
+ Reference< XResultSet > xRef = pResult;
+
+ // here we fill the rows which should be visible when ask for data from the resultset returned here
+ ODatabaseMetaDataResultSet::ORows aRows;
+ for(const auto & sTableType : sTableTypes)
+ {
+ ODatabaseMetaDataResultSet::ORow aRow;
+ aRow.push_back(ODatabaseMetaDataResultSet::getEmptyValue());
+ aRow.push_back(new ORowSetValueDecorator(OUString(sTableType)));
+ // bound row
+ aRows.push_back(aRow);
+ }
+ // here we set the rows at the resultset
+ pResult->setRows(aRows);
+ return xRef;
+}
+
+Reference< XResultSet > ODatabaseMetaData::impl_getTypeInfo_throw( )
+{
+ // this returns an empty resultset where the column-names are already set
+ // in special the metadata of the resultset already returns the right columns
+ ODatabaseMetaDataResultSet* pResultSet = new ODatabaseMetaDataResultSet(ODatabaseMetaDataResultSet::eTypeInfo);
+ Reference< XResultSet > xResultSet = pResultSet;
+ static ODatabaseMetaDataResultSet::ORows aRows = [&]()
+ {
+ ODatabaseMetaDataResultSet::ORows tmp;
+ ODatabaseMetaDataResultSet::ORow aRow;
+ aRow.reserve(19);
+ aRow.push_back(ODatabaseMetaDataResultSet::getEmptyValue());
+ aRow.push_back(new ORowSetValueDecorator(OUString("VARCHAR")));
+ aRow.push_back(new ORowSetValueDecorator(DataType::VARCHAR));
+ aRow.push_back(new ORowSetValueDecorator(sal_Int32(s_nCHAR_OCTET_LENGTH)));
+ aRow.push_back(ODatabaseMetaDataResultSet::getQuoteValue());
+ aRow.push_back(ODatabaseMetaDataResultSet::getQuoteValue());
+ aRow.push_back(ODatabaseMetaDataResultSet::getEmptyValue());
+ // aRow.push_back(new ORowSetValueDecorator((sal_Int32)ColumnValue::NULLABLE));
+ aRow.push_back(ODatabaseMetaDataResultSet::get1Value());
+ aRow.push_back(ODatabaseMetaDataResultSet::get1Value());
+ aRow.push_back(new ORowSetValueDecorator(sal_Int32(ColumnSearch::CHAR)));
+ aRow.push_back(ODatabaseMetaDataResultSet::get1Value());
+ aRow.push_back(ODatabaseMetaDataResultSet::get0Value());
+ aRow.push_back(ODatabaseMetaDataResultSet::get0Value());
+ aRow.push_back(ODatabaseMetaDataResultSet::getEmptyValue());
+ aRow.push_back(ODatabaseMetaDataResultSet::get0Value());
+ aRow.push_back(ODatabaseMetaDataResultSet::get0Value());
+ aRow.push_back(ODatabaseMetaDataResultSet::getEmptyValue());
+ aRow.push_back(ODatabaseMetaDataResultSet::getEmptyValue());
+ aRow.push_back(new ORowSetValueDecorator(sal_Int32(10)));
+
+ tmp.push_back(aRow);
+ return tmp;
+ }();
+ pResultSet->setRows(aRows);
+ return xResultSet;
+}
+
+Reference< XResultSet > SAL_CALL ODatabaseMetaData::getColumns(
+ const Any& /*catalog*/, const OUString& /*schemaPattern*/, const OUString& tableNamePattern,
+ const OUString& columnNamePattern )
+{
+ // this returns an empty resultset where the column-names are already set
+ // in special the metadata of the resultset already returns the right columns
+ ODatabaseMetaDataResultSet* pResultSet = new ODatabaseMetaDataResultSet(ODatabaseMetaDataResultSet::eColumns);
+ Reference< XResultSet > xResultSet = pResultSet;
+ pResultSet->setRows( getColumnRows( tableNamePattern, columnNamePattern ));
+ return xResultSet;
+}
+
+Reference< XResultSet > SAL_CALL ODatabaseMetaData::getTables(
+ const Any& /*catalog*/, const OUString& /*schemaPattern*/,
+ const OUString& tableNamePattern, const Sequence< OUString >& /*types*/ )
+{
+ SAL_INFO("connectivity.mork", "=> ODatabaseMetaData::getTables()" );
+ // this returns an empty resultset where the column-names are already set
+ // in special the metadata of the resultset already returns the right columns
+ ODatabaseMetaDataResultSet* pResultSet = new ODatabaseMetaDataResultSet(ODatabaseMetaDataResultSet::eTables);
+ Reference< XResultSet > xResultSet = pResultSet;
+
+ // ODatabaseMetaDataResultSet::ORows aRows;
+ // aRows = m_pDbMetaDataHelper->getTables( m_pConnection, tableNamePattern );
+ // pResultSet->setRows( aRows );
+ ODatabaseMetaDataResultSet::ORows _rRows;
+ connectivity::mork::MDatabaseMetaDataHelper::getTables( m_pConnection, tableNamePattern, _rRows );
+ pResultSet->setRows( _rRows );
+
+ return xResultSet;
+}
+
+Reference< XResultSet > SAL_CALL ODatabaseMetaData::getTablePrivileges(
+ const Any& /*catalog*/, const OUString& /*schemaPattern*/, const OUString& tableNamePattern )
+{
+ SAL_INFO("connectivity.mork", "=> ODatabaseMetaData::getTablePrivileges()" );
+ ::connectivity::ODatabaseMetaDataResultSet* pResult = new ::connectivity::ODatabaseMetaDataResultSet(ODatabaseMetaDataResultSet::eTablePrivileges);
+ Reference< XResultSet > xRef = pResult;
+
+ std::vector< OUString > tables;
+ connectivity::mork::MDatabaseMetaDataHelper::getTableStrings( m_pConnection, tables);
+
+ ::connectivity::ODatabaseMetaDataResultSet::ORows aRows;
+ ::connectivity::ODatabaseMetaDataResultSet::ORow aRow(8);
+ aRows.reserve(8);
+ aRow[0] = ::connectivity::ODatabaseMetaDataResultSet::getEmptyValue();
+ aRow[1] = ::connectivity::ODatabaseMetaDataResultSet::getEmptyValue();
+ aRow[3] = ::connectivity::ODatabaseMetaDataResultSet::getEmptyValue();
+ aRow[4] = ::connectivity::ODatabaseMetaDataResultSet::getEmptyValue();
+ aRow[5] = new ::connectivity::ORowSetValueDecorator(getUserName());
+ aRow[7] = new ::connectivity::ORowSetValueDecorator(OUString("NO"));
+
+
+ // Iterate over all tables
+ for(const OUString & table : tables) {
+ if(match(tableNamePattern, table,'\0'))
+ {
+ // TABLE_NAME
+ aRow[2] = new ORowSetValueDecorator( table );
+
+ SAL_INFO("connectivity.mork", "\tTableName = : " << table);
+
+ aRow[6] = ::connectivity::ODatabaseMetaDataResultSet::getSelectValue();
+ aRows.push_back(aRow);
+ aRow[6] = ::connectivity::ODatabaseMetaDataResultSet::getInsertValue();
+ aRows.push_back(aRow);
+ aRow[6] = ::connectivity::ODatabaseMetaDataResultSet::getDeleteValue();
+ aRows.push_back(aRow);
+ aRow[6] = ::connectivity::ODatabaseMetaDataResultSet::getUpdateValue();
+ aRows.push_back(aRow);
+ aRow[6] = ::connectivity::ODatabaseMetaDataResultSet::getCreateValue();
+ aRows.push_back(aRow);
+ aRow[6] = ::connectivity::ODatabaseMetaDataResultSet::getReadValue();
+ aRows.push_back(aRow);
+ aRow[6] = ::connectivity::ODatabaseMetaDataResultSet::getAlterValue();
+ aRows.push_back(aRow);
+ aRow[6] = ::connectivity::ODatabaseMetaDataResultSet::getDropValue();
+ aRows.push_back(aRow);
+ }
+ }
+ pResult->setRows(aRows);
+ return xRef;
+}
+
+Reference< XResultSet > SAL_CALL ODatabaseMetaData::getUDTs( const Any& /*catalog*/, const OUString& /*schemaPattern*/, const OUString& /*typeNamePattern*/, const Sequence< sal_Int32 >& /*types*/ )
+{
+ return nullptr;
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/mork/MDatabaseMetaData.hxx b/connectivity/source/drivers/mork/MDatabaseMetaData.hxx
new file mode 100644
index 000000000..8677fc7aa
--- /dev/null
+++ b/connectivity/source/drivers/mork/MDatabaseMetaData.hxx
@@ -0,0 +1,191 @@
+/* -*- 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/.
+ */
+
+#ifndef INCLUDED_CONNECTIVITY_SOURCE_DRIVERS_MORK_MDATABASEMETADATA_HXX
+#define INCLUDED_CONNECTIVITY_SOURCE_DRIVERS_MORK_MDATABASEMETADATA_HXX
+
+#include <memory>
+#include <TDatabaseMetaDataBase.hxx>
+#include "MConnection.hxx"
+
+namespace connectivity
+{
+ namespace mork
+ {
+ class MDatabaseMetaDataHelper;
+
+ //************ Class: ODatabaseMetaData
+
+
+ class ODatabaseMetaData : public ODatabaseMetaDataBase
+ {
+ OConnection* m_pConnection;
+ std::unique_ptr<MDatabaseMetaDataHelper>
+ m_pMetaDataHelper;
+
+ /// @throws css::sdbc::SQLException
+ ODatabaseMetaDataResultSet::ORows getColumnRows( const OUString& tableNamePattern, const OUString& columnNamePattern );
+
+ protected:
+ virtual ~ODatabaseMetaData() override;
+
+ public:
+ explicit ODatabaseMetaData(OConnection* _pCon);
+
+ private:
+ virtual css::uno::Reference< css::sdbc::XResultSet > impl_getTypeInfo_throw() override;
+ // cached database information
+ virtual OUString impl_getIdentifierQuoteString_throw( ) override;
+ virtual bool impl_isCatalogAtStart_throw( ) override;
+ virtual OUString impl_getCatalogSeparator_throw( ) override;
+ virtual bool impl_supportsCatalogsInTableDefinitions_throw( ) override;
+ virtual bool impl_supportsSchemasInTableDefinitions_throw( ) override ;
+ virtual bool impl_supportsCatalogsInDataManipulation_throw( ) override;
+ virtual bool impl_supportsSchemasInDataManipulation_throw( ) override ;
+ virtual bool impl_supportsMixedCaseQuotedIdentifiers_throw( ) override ;
+ virtual bool impl_supportsAlterTableWithAddColumn_throw( ) override;
+ virtual bool impl_supportsAlterTableWithDropColumn_throw( ) override;
+ virtual sal_Int32 impl_getMaxStatements_throw( ) override;
+ virtual sal_Int32 impl_getMaxTablesInSelect_throw( ) override;
+ virtual bool impl_storesMixedCaseQuotedIdentifiers_throw( ) override;
+
+ // as I mentioned before this interface is really BIG
+ // XDatabaseMetaData
+ virtual sal_Bool SAL_CALL allProceduresAreCallable( ) override;
+ virtual sal_Bool SAL_CALL allTablesAreSelectable( ) override;
+ virtual OUString SAL_CALL getURL( ) override;
+ virtual OUString SAL_CALL getUserName( ) override;
+ virtual sal_Bool SAL_CALL isReadOnly( ) override;
+ virtual sal_Bool SAL_CALL nullsAreSortedHigh( ) override;
+ virtual sal_Bool SAL_CALL nullsAreSortedLow( ) override;
+ virtual sal_Bool SAL_CALL nullsAreSortedAtStart( ) override;
+ virtual sal_Bool SAL_CALL nullsAreSortedAtEnd( ) override;
+ virtual OUString SAL_CALL getDatabaseProductName( ) override;
+ virtual OUString SAL_CALL getDatabaseProductVersion( ) override;
+ virtual OUString SAL_CALL getDriverName( ) override;
+ virtual OUString SAL_CALL getDriverVersion( ) override;
+ virtual sal_Int32 SAL_CALL getDriverMajorVersion( ) override;
+ virtual sal_Int32 SAL_CALL getDriverMinorVersion( ) override;
+ virtual sal_Bool SAL_CALL usesLocalFiles( ) override;
+ virtual sal_Bool SAL_CALL usesLocalFilePerTable( ) override;
+ virtual sal_Bool SAL_CALL supportsMixedCaseIdentifiers( ) override;
+ virtual sal_Bool SAL_CALL storesUpperCaseIdentifiers( ) override;
+ virtual sal_Bool SAL_CALL storesLowerCaseIdentifiers( ) override;
+ virtual sal_Bool SAL_CALL storesMixedCaseIdentifiers( ) override;
+ virtual sal_Bool SAL_CALL storesUpperCaseQuotedIdentifiers( ) override;
+ virtual sal_Bool SAL_CALL storesLowerCaseQuotedIdentifiers( ) override;
+ virtual OUString SAL_CALL getSQLKeywords( ) override;
+ virtual OUString SAL_CALL getNumericFunctions( ) override;
+ virtual OUString SAL_CALL getStringFunctions( ) override;
+ virtual OUString SAL_CALL getSystemFunctions( ) override;
+ virtual OUString SAL_CALL getTimeDateFunctions( ) override;
+ virtual OUString SAL_CALL getSearchStringEscape( ) override;
+ virtual OUString SAL_CALL getExtraNameCharacters( ) override;
+ virtual sal_Bool SAL_CALL supportsColumnAliasing( ) override;
+ virtual sal_Bool SAL_CALL nullPlusNonNullIsNull( ) override;
+ virtual sal_Bool SAL_CALL supportsTypeConversion( ) override;
+ virtual sal_Bool SAL_CALL supportsConvert( sal_Int32 fromType, sal_Int32 toType ) override;
+ virtual sal_Bool SAL_CALL supportsTableCorrelationNames( ) override;
+ virtual sal_Bool SAL_CALL supportsDifferentTableCorrelationNames( ) override;
+ virtual sal_Bool SAL_CALL supportsExpressionsInOrderBy( ) override;
+ virtual sal_Bool SAL_CALL supportsOrderByUnrelated( ) override;
+ virtual sal_Bool SAL_CALL supportsGroupBy( ) override;
+ virtual sal_Bool SAL_CALL supportsGroupByUnrelated( ) override;
+ virtual sal_Bool SAL_CALL supportsGroupByBeyondSelect( ) override;
+ virtual sal_Bool SAL_CALL supportsLikeEscapeClause( ) override;
+ virtual sal_Bool SAL_CALL supportsMultipleResultSets( ) override;
+ virtual sal_Bool SAL_CALL supportsMultipleTransactions( ) override;
+ virtual sal_Bool SAL_CALL supportsNonNullableColumns( ) override;
+ virtual sal_Bool SAL_CALL supportsMinimumSQLGrammar( ) override;
+ virtual sal_Bool SAL_CALL supportsCoreSQLGrammar( ) override;
+ virtual sal_Bool SAL_CALL supportsExtendedSQLGrammar( ) override;
+ virtual sal_Bool SAL_CALL supportsANSI92EntryLevelSQL( ) override;
+ virtual sal_Bool SAL_CALL supportsANSI92IntermediateSQL( ) override;
+ virtual sal_Bool SAL_CALL supportsANSI92FullSQL( ) override;
+ virtual sal_Bool SAL_CALL supportsIntegrityEnhancementFacility( ) override;
+ virtual sal_Bool SAL_CALL supportsOuterJoins( ) override;
+ virtual sal_Bool SAL_CALL supportsFullOuterJoins( ) override;
+ virtual sal_Bool SAL_CALL supportsLimitedOuterJoins( ) override;
+ virtual OUString SAL_CALL getSchemaTerm( ) override;
+ virtual OUString SAL_CALL getProcedureTerm( ) override;
+ virtual OUString SAL_CALL getCatalogTerm( ) override;
+ virtual sal_Bool SAL_CALL supportsSchemasInProcedureCalls( ) override;
+ virtual sal_Bool SAL_CALL supportsSchemasInIndexDefinitions( ) override;
+ virtual sal_Bool SAL_CALL supportsSchemasInPrivilegeDefinitions( ) override;
+ virtual sal_Bool SAL_CALL supportsCatalogsInProcedureCalls( ) override;
+ virtual sal_Bool SAL_CALL supportsCatalogsInIndexDefinitions( ) override;
+ virtual sal_Bool SAL_CALL supportsCatalogsInPrivilegeDefinitions( ) override;
+ virtual sal_Bool SAL_CALL supportsPositionedDelete( ) override;
+ virtual sal_Bool SAL_CALL supportsPositionedUpdate( ) override;
+ virtual sal_Bool SAL_CALL supportsSelectForUpdate( ) override;
+ virtual sal_Bool SAL_CALL supportsStoredProcedures( ) override;
+ virtual sal_Bool SAL_CALL supportsSubqueriesInComparisons( ) override;
+ virtual sal_Bool SAL_CALL supportsSubqueriesInExists( ) override;
+ virtual sal_Bool SAL_CALL supportsSubqueriesInIns( ) override;
+ virtual sal_Bool SAL_CALL supportsSubqueriesInQuantifieds( ) override;
+ virtual sal_Bool SAL_CALL supportsCorrelatedSubqueries( ) override;
+ virtual sal_Bool SAL_CALL supportsUnion( ) override;
+ virtual sal_Bool SAL_CALL supportsUnionAll( ) override;
+ virtual sal_Bool SAL_CALL supportsOpenCursorsAcrossCommit( ) override;
+ virtual sal_Bool SAL_CALL supportsOpenCursorsAcrossRollback( ) override;
+ virtual sal_Bool SAL_CALL supportsOpenStatementsAcrossCommit( ) override;
+ virtual sal_Bool SAL_CALL supportsOpenStatementsAcrossRollback( ) override;
+ virtual sal_Int32 SAL_CALL getMaxBinaryLiteralLength( ) override;
+ virtual sal_Int32 SAL_CALL getMaxCharLiteralLength( ) override;
+ virtual sal_Int32 SAL_CALL getMaxColumnNameLength( ) override;
+ virtual sal_Int32 SAL_CALL getMaxColumnsInGroupBy( ) override;
+ virtual sal_Int32 SAL_CALL getMaxColumnsInIndex( ) override;
+ virtual sal_Int32 SAL_CALL getMaxColumnsInOrderBy( ) override;
+ virtual sal_Int32 SAL_CALL getMaxColumnsInSelect( ) override;
+ virtual sal_Int32 SAL_CALL getMaxColumnsInTable( ) override;
+ virtual sal_Int32 SAL_CALL getMaxConnections( ) override;
+ virtual sal_Int32 SAL_CALL getMaxCursorNameLength( ) override;
+ virtual sal_Int32 SAL_CALL getMaxIndexLength( ) override;
+ virtual sal_Int32 SAL_CALL getMaxSchemaNameLength( ) override;
+ virtual sal_Int32 SAL_CALL getMaxProcedureNameLength( ) override;
+ virtual sal_Int32 SAL_CALL getMaxCatalogNameLength( ) override;
+ virtual sal_Int32 SAL_CALL getMaxRowSize( ) override;
+ virtual sal_Bool SAL_CALL doesMaxRowSizeIncludeBlobs( ) override;
+ virtual sal_Int32 SAL_CALL getMaxStatementLength( ) override;
+ virtual sal_Int32 SAL_CALL getMaxTableNameLength( ) override;
+ virtual sal_Int32 SAL_CALL getMaxUserNameLength( ) override;
+ virtual sal_Int32 SAL_CALL getDefaultTransactionIsolation( ) override;
+ virtual sal_Bool SAL_CALL supportsTransactions( ) override;
+ virtual sal_Bool SAL_CALL supportsTransactionIsolationLevel( sal_Int32 level ) override;
+ virtual sal_Bool SAL_CALL supportsDataDefinitionAndDataManipulationTransactions( ) override;
+ virtual sal_Bool SAL_CALL supportsDataManipulationTransactionsOnly( ) override;
+ virtual sal_Bool SAL_CALL dataDefinitionCausesTransactionCommit( ) override;
+ virtual sal_Bool SAL_CALL dataDefinitionIgnoredInTransactions( ) override;
+
+ virtual css::uno::Reference< css::sdbc::XResultSet > SAL_CALL getTables( const css::uno::Any& catalog, const OUString& schemaPattern, const OUString& tableNamePattern, const css::uno::Sequence< OUString >& types ) override;
+ virtual css::uno::Reference< css::sdbc::XResultSet > SAL_CALL getTableTypes( ) override;
+ virtual css::uno::Reference< css::sdbc::XResultSet > SAL_CALL getTablePrivileges( const css::uno::Any& catalog, const OUString& schemaPattern, const OUString& tableNamePattern ) override;
+ virtual css::uno::Reference< css::sdbc::XResultSet > SAL_CALL getColumns( const css::uno::Any& catalog, const OUString& schemaPattern, const OUString& tableNamePattern, const OUString& columnNamePattern ) override;
+
+ virtual sal_Bool SAL_CALL supportsResultSetType( sal_Int32 setType ) override;
+ virtual sal_Bool SAL_CALL supportsResultSetConcurrency( sal_Int32 setType, sal_Int32 concurrency ) override;
+ virtual sal_Bool SAL_CALL ownUpdatesAreVisible( sal_Int32 setType ) override;
+ virtual sal_Bool SAL_CALL ownDeletesAreVisible( sal_Int32 setType ) override;
+ virtual sal_Bool SAL_CALL ownInsertsAreVisible( sal_Int32 setType ) override;
+ virtual sal_Bool SAL_CALL othersUpdatesAreVisible( sal_Int32 setType ) override;
+ virtual sal_Bool SAL_CALL othersDeletesAreVisible( sal_Int32 setType ) override;
+ virtual sal_Bool SAL_CALL othersInsertsAreVisible( sal_Int32 setType ) override;
+ virtual sal_Bool SAL_CALL updatesAreDetected( sal_Int32 setType ) override;
+ virtual sal_Bool SAL_CALL deletesAreDetected( sal_Int32 setType ) override;
+ virtual sal_Bool SAL_CALL insertsAreDetected( sal_Int32 setType ) override;
+ virtual sal_Bool SAL_CALL supportsBatchUpdates( ) override;
+
+ virtual css::uno::Reference< css::sdbc::XResultSet > SAL_CALL getUDTs( const css::uno::Any& catalog, const OUString& schemaPattern, const OUString& typeNamePattern, const css::uno::Sequence< sal_Int32 >& types ) override;
+ };
+ }
+}
+
+#endif // INCLUDED_CONNECTIVITY_SOURCE_DRIVERS_MORK_MDATABASEMETADATA_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/mork/MDatabaseMetaDataHelper.cxx b/connectivity/source/drivers/mork/MDatabaseMetaDataHelper.cxx
new file mode 100644
index 000000000..ca699bafa
--- /dev/null
+++ b/connectivity/source/drivers/mork/MDatabaseMetaDataHelper.cxx
@@ -0,0 +1,123 @@
+/* -*- 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/.
+ */
+
+#include "MConnection.hxx"
+#include "MDatabaseMetaDataHelper.hxx"
+
+// do we need it?
+static ::osl::Mutex m_aMetaMutex;
+
+#include <sal/log.hxx>
+
+#include "MorkParser.hxx"
+
+using namespace connectivity;
+using namespace connectivity::mork;
+
+
+MDatabaseMetaDataHelper::MDatabaseMetaDataHelper()
+{
+ SAL_INFO("connectivity.mork", "=> MDatabaseMetaDataHelper::MDatabaseMetaDataHelper()" );
+}
+
+
+MDatabaseMetaDataHelper::~MDatabaseMetaDataHelper()
+{
+}
+
+void MDatabaseMetaDataHelper::getTableStrings( OConnection* _pCon,
+ std::vector< OUString >& _rStrings)
+{
+ SAL_INFO("connectivity.mork", "=> MDatabaseMetaDataHelper::getTableStrings()");
+
+ /* add default tables */
+ _rStrings.push_back("AddressBook");
+ _rStrings.push_back("CollectedAddressBook");
+
+ /* retrieve list table names (not from collected ab) */
+ std::set<std::string> lists;
+ MorkParser* pMork = _pCon->getMorkParser("AddressBook");
+ pMork->retrieveLists(lists);
+ for (auto const& elem : lists)
+ {
+ OUString groupTableName = OStringToOUString(elem.c_str(), RTL_TEXTENCODING_UTF8);
+ SAL_INFO("connectivity.mork", "add Table " << groupTableName);
+
+ _rStrings.push_back(groupTableName);
+ // remember the list in the mork parser, we'll use it later
+ pMork->lists_.push_back(groupTableName);
+ }
+
+ std::set<std::string> lists_history;
+ pMork = _pCon->getMorkParser("CollectedAddressBook");
+ pMork->retrieveLists(lists_history);
+ for (auto const& elem : lists_history)
+ {
+ OUString groupTableName = OStringToOUString(elem.c_str(), RTL_TEXTENCODING_UTF8);
+ SAL_INFO("connectivity.mork", "add Table " << groupTableName);
+
+ _rStrings.push_back(groupTableName);
+ // remember the list in the mork parser, we'll use it later
+ pMork->lists_.push_back(groupTableName);
+ }
+}
+
+void MDatabaseMetaDataHelper::getTables( OConnection* _pCon,
+ const OUString& tableNamePattern,
+ ODatabaseMetaDataResultSet::ORows& _rRows)
+{
+
+ SAL_INFO("connectivity.mork", "=> MDatabaseMetaDataHelper::getTables()");
+
+ static ODatabaseMetaDataResultSet::ORows aRows;
+
+ SAL_INFO("connectivity.mork", "=> MDatabaseMetaDataHelper::getTables()" );
+ SAL_INFO("connectivity.mork", "tableNamePattern : " << tableNamePattern);
+ ::osl::MutexGuard aGuard( m_aMetaMutex );
+
+ ODatabaseMetaDataResultSet::ORows().swap(aRows); // this makes real clear where memory is freed as well
+ aRows.clear();
+
+ std::vector< OUString > tables;
+
+ getTableStrings( _pCon, tables );
+
+ for (OUString& aTableName : tables) {
+ ODatabaseMetaDataResultSet::ORow aRow { nullptr, nullptr, nullptr };
+
+ SAL_INFO("connectivity.mork", "TableName: " << aTableName );
+
+
+ // return tables to caller
+ if (match( tableNamePattern, aTableName, '\0' ))
+ {
+ if ( aTableName.isEmpty() ) {
+ aTableName = "AddressBook";
+ }
+
+ SAL_INFO("connectivity.mork", "TableName: " << aTableName);
+
+ aRow.push_back( new ORowSetValueDecorator( aTableName ) ); // Table/View name
+ if ((aTableName == "AddressBook") || (aTableName == "CollectedAddressBook"))
+ {
+ aRow.push_back( new ORowSetValueDecorator( OUString("TABLE") ) ); // Table type
+ }
+ else
+ {
+ aRow.push_back( new ORowSetValueDecorator( OUString("VIEW") ) ); // View type
+ }
+ aRow.push_back( ODatabaseMetaDataResultSet::getEmptyValue() ); // Remarks
+ aRows.push_back(aRow);
+ }
+ }
+
+ _rRows = aRows;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/mork/MDatabaseMetaDataHelper.hxx b/connectivity/source/drivers/mork/MDatabaseMetaDataHelper.hxx
new file mode 100644
index 000000000..0ae96dac9
--- /dev/null
+++ b/connectivity/source/drivers/mork/MDatabaseMetaDataHelper.hxx
@@ -0,0 +1,39 @@
+/* -*- 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/.
+ */
+
+#ifndef INCLUDED_CONNECTIVITY_SOURCE_DRIVERS_MORK_MDATABASEMETADATAHELPER_HXX
+#define INCLUDED_CONNECTIVITY_SOURCE_DRIVERS_MORK_MDATABASEMETADATAHELPER_HXX
+
+#include <FDatabaseMetaDataResultSet.hxx>
+#include "MConnection.hxx"
+
+namespace connectivity
+{
+ namespace mork
+ {
+ class MDatabaseMetaDataHelper
+ {
+ public:
+ MDatabaseMetaDataHelper();
+ ~MDatabaseMetaDataHelper();
+
+
+ static void getTableStrings( OConnection* _pCon,
+ std::vector< OUString >& _rStrings);
+
+ static void getTables( OConnection* _pCon,
+ const OUString& tableNamePattern,
+ ODatabaseMetaDataResultSet::ORows& _rRows);
+ };
+ }
+}
+
+#endif // INCLUDED_CONNECTIVITY_SOURCE_DRIVERS_MORK_MDATABASEMETADATAHELPER_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/mork/MDriver.cxx b/connectivity/source/drivers/mork/MDriver.cxx
new file mode 100644
index 000000000..0351b6c3e
--- /dev/null
+++ b/connectivity/source/drivers/mork/MDriver.cxx
@@ -0,0 +1,133 @@
+/* -*- 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/.
+ */
+
+#include "MDriver.hxx"
+#include "MConnection.hxx"
+
+#include <com/sun/star/mozilla/XMozillaBootstrap.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+
+#include <sal/log.hxx>
+
+using namespace connectivity::mork;
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * com_sun_star_comp_sdbc_MorkDriver_get_implementation(
+ css::uno::XComponentContext* context,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new MorkDriver(context));
+}
+
+MorkDriver::MorkDriver(const css::uno::Reference< css::uno::XComponentContext >& context):
+ context_(context),
+ m_xFactory(context_->getServiceManager(), css::uno::UNO_QUERY)
+{
+ SAL_INFO("connectivity.mork", "=> MorkDriver::MorkDriver()" );
+}
+
+OUString SAL_CALL MorkDriver::getImplementationName()
+{
+ return MORK_DRIVER_IMPL_NAME;
+}
+
+sal_Bool SAL_CALL MorkDriver::supportsService(const OUString& serviceName)
+{
+ return cppu::supportsService(this, serviceName);
+}
+
+css::uno::Sequence< OUString > MorkDriver::getSupportedServiceNames()
+{
+ return { "com.sun.star.sdbc.Driver" };
+}
+
+css::uno::Reference< css::sdbc::XConnection > MorkDriver::connect(
+ OUString const & url,
+ css::uno::Sequence< css::beans::PropertyValue > const &)
+{
+ SAL_INFO("connectivity.mork", "=> MorkDriver::connect()" );
+
+ // Profile discovery
+ css::uno::Reference<css::uno::XInterface> xInstance = context_->getServiceManager()->createInstanceWithContext("com.sun.star.mozilla.MozillaBootstrap", context_);
+ OSL_ENSURE( xInstance.is(), "failed to create instance" );
+
+ css::uno::Reference<css::mozilla::XMozillaBootstrap> xMozillaBootstrap(xInstance, css::uno::UNO_QUERY);
+ OSL_ENSURE( xMozillaBootstrap.is(), "failed to create instance" );
+
+ if (xMozillaBootstrap.is())
+ {
+ OUString defaultProfile = xMozillaBootstrap->getDefaultProfile(css::mozilla::MozillaProductType_Thunderbird);
+
+ if (!defaultProfile.isEmpty())
+ {
+ m_sProfilePath = xMozillaBootstrap->getProfilePath(css::mozilla::MozillaProductType_Thunderbird, defaultProfile);
+ SAL_INFO("connectivity.mork", "Using Thunderbird profile " << m_sProfilePath);
+ }
+ }
+
+ css::uno::Reference< css::sdbc::XConnection > xCon;
+ OConnection* pCon = new OConnection(this);
+ xCon = pCon; // important here because otherwise the connection could be deleted inside (refcount goes -> 0)
+ pCon->construct(url);
+ return xCon;
+}
+
+sal_Bool MorkDriver::acceptsURL(OUString const & url)
+{
+ SAL_INFO("connectivity.mork", "=> MorkDriver::acceptsURL()" );
+ // Skip 'sdbc:mozab: part of URL
+
+ sal_Int32 nLen = url.indexOf(':');
+ nLen = url.indexOf(':',nLen+1);
+ OUString aAddrbookURI(url.copy(nLen+1));
+ // Get Scheme
+ nLen = aAddrbookURI.indexOf(':');
+ OUString aAddrbookScheme;
+ if ( nLen == -1 )
+ {
+ // There isn't any subschema: - but could be just subschema
+ if ( !aAddrbookURI.isEmpty() )
+ {
+ aAddrbookScheme= aAddrbookURI;
+ }
+ else if( url == "sdbc:address:" )
+ {
+ return false;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ else
+ {
+ aAddrbookScheme = aAddrbookURI.copy(0, nLen);
+ }
+
+ return aAddrbookScheme == "thunderbird" || aAddrbookScheme == "mozilla";
+}
+
+css::uno::Sequence< css::sdbc::DriverPropertyInfo > MorkDriver::getPropertyInfo(
+ OUString const &,
+ css::uno::Sequence< css::beans::PropertyValue > const &)
+{
+ //... TODO
+ return css::uno::Sequence< css::sdbc::DriverPropertyInfo >();
+}
+
+sal_Int32 MorkDriver::getMajorVersion() {
+ //... TODO
+ return 0;
+}
+
+sal_Int32 MorkDriver::getMinorVersion() {
+ //... TODO
+ return 0;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/mork/MDriver.hxx b/connectivity/source/drivers/mork/MDriver.hxx
new file mode 100644
index 000000000..6f6946af6
--- /dev/null
+++ b/connectivity/source/drivers/mork/MDriver.hxx
@@ -0,0 +1,79 @@
+/* -*- 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/.
+ */
+
+#ifndef INCLUDED_CONNECTIVITY_SOURCE_DRIVERS_MORK_MDRIVER_HXX
+#define INCLUDED_CONNECTIVITY_SOURCE_DRIVERS_MORK_MDRIVER_HXX
+
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/sdbc/DriverPropertyInfo.hpp>
+
+#include <com/sun/star/sdbc/XDriver.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <cppuhelper/implbase.hxx>
+
+#define MORK_DRIVER_IMPL_NAME "com.sun.star.comp.sdbc.MorkDriver"
+
+namespace com::sun::star {
+ namespace uno {
+ class XComponentContext;
+ class XInterface;
+ }
+}
+
+namespace connectivity::mork {
+class ProfileAccess;
+
+class MorkDriver:
+ public cppu::WeakImplHelper< css::lang::XServiceInfo, css::sdbc::XDriver >
+{
+public:
+ explicit MorkDriver(const css::uno::Reference< css::uno::XComponentContext >& context);
+
+ const css::uno::Reference< com::sun::star::lang::XMultiServiceFactory >& getFactory() const {return m_xFactory;}
+ const OUString& getProfilePath() const {return m_sProfilePath;}
+private:
+
+ MorkDriver(const MorkDriver&) = delete;
+ MorkDriver& operator=(const MorkDriver&) = delete;
+
+ virtual ~MorkDriver() override {}
+
+ virtual OUString SAL_CALL getImplementationName() override;
+
+ virtual sal_Bool SAL_CALL supportsService(OUString const & ServiceName) override;
+
+ virtual css::uno::Sequence< OUString > SAL_CALL
+ getSupportedServiceNames() override;
+
+ virtual css::uno::Reference< css::sdbc::XConnection > SAL_CALL connect(
+ OUString const & url,
+ css::uno::Sequence< css::beans::PropertyValue > const & info) override;
+
+ virtual sal_Bool SAL_CALL acceptsURL(
+ OUString const & url) override;
+
+ virtual css::uno::Sequence< css::sdbc::DriverPropertyInfo > SAL_CALL
+ getPropertyInfo(
+ OUString const & url,
+ css::uno::Sequence< css::beans::PropertyValue > const & info) override;
+
+ virtual sal_Int32 SAL_CALL getMajorVersion() override;
+
+ virtual sal_Int32 SAL_CALL getMinorVersion() override;
+
+ css::uno::Reference< css::uno::XComponentContext > context_;
+ css::uno::Reference< css::lang::XMultiServiceFactory > m_xFactory;
+ OUString m_sProfilePath;
+};
+
+}
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/mork/MErrorResource.hxx b/connectivity/source/drivers/mork/MErrorResource.hxx
new file mode 100644
index 000000000..0691b1813
--- /dev/null
+++ b/connectivity/source/drivers/mork/MErrorResource.hxx
@@ -0,0 +1,56 @@
+/* -*- 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 .
+ */
+
+#ifndef INCLUDED_CONNECTIVITY_SOURCE_DRIVERS_MORK_MERRORRESOURCE_HXX
+#define INCLUDED_CONNECTIVITY_SOURCE_DRIVERS_MORK_MERRORRESOURCE_HXX
+
+namespace connectivity
+{
+ namespace mork
+ {
+ class ErrorDescriptor
+ {
+ private:
+ const char* m_pErrorResourceId;
+
+ public:
+ ErrorDescriptor()
+ :m_pErrorResourceId(nullptr)
+ {
+ }
+
+ void setResId(const char* pErrorResourceId)
+ {
+ m_pErrorResourceId = pErrorResourceId;
+ }
+ void reset()
+ {
+ m_pErrorResourceId = nullptr;
+ }
+
+ const char* getResId() const { return m_pErrorResourceId; }
+
+ bool is() const { return m_pErrorResourceId != nullptr; }
+ };
+ }
+}
+
+#endif // INCLUDED_CONNECTIVITY_SOURCE_DRIVERS_MORK_MERRORRESOURCE_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/mork/MPreparedStatement.cxx b/connectivity/source/drivers/mork/MPreparedStatement.cxx
new file mode 100644
index 000000000..f2cd8fdc7
--- /dev/null
+++ b/connectivity/source/drivers/mork/MPreparedStatement.cxx
@@ -0,0 +1,486 @@
+/* -*- 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/.
+ */
+
+#include <connectivity/sdbcx/VColumn.hxx>
+#include "MPreparedStatement.hxx"
+#include "MResultSetMetaData.hxx"
+#include <connectivity/dbtools.hxx>
+#include <comphelper/types.hxx>
+#include <com/sun/star/sdbc/ColumnValue.hpp>
+#include <sal/log.hxx>
+
+using namespace ::comphelper;
+using namespace connectivity;
+using namespace connectivity::mork;
+using namespace com::sun::star::uno;
+using namespace com::sun::star::sdbc;
+using namespace com::sun::star::container;
+using namespace com::sun::star::util;
+
+IMPLEMENT_SERVICE_INFO(OPreparedStatement,"com.sun.star.sdbcx.mork.PreparedStatement","com.sun.star.sdbc.PreparedStatement");
+
+
+OPreparedStatement::OPreparedStatement( OConnection* _pConnection,const OUString& sql)
+ :OCommonStatement(_pConnection)
+ ,m_sSqlStatement(sql)
+ ,m_pResultSet()
+{
+}
+
+OPreparedStatement::~OPreparedStatement()
+{
+}
+
+void OPreparedStatement::lateInit()
+{
+ if ( eSelect != parseSql( m_sSqlStatement ) )
+ throw SQLException();
+}
+
+void SAL_CALL OPreparedStatement::disposing()
+{
+ ::osl::MutexGuard aGuard(m_aMutex);
+
+ OCommonStatement::disposing();
+
+ m_xMetaData.clear();
+ if(m_aParameterRow.is())
+ {
+ m_aParameterRow->clear();
+ m_aParameterRow = nullptr;
+ }
+ m_xParamColumns = nullptr;
+}
+
+OCommonStatement::StatementType OPreparedStatement::parseSql( const OUString& sql , bool bAdjusted )
+{
+ StatementType eStatementType = OCommonStatement::parseSql( sql, bAdjusted );
+ if ( eStatementType != eSelect )
+ return eStatementType;
+
+ m_xParamColumns = new OSQLColumns();
+
+ // describe all parameters need for the resultset
+ describeParameter();
+
+ Reference<XIndexAccess> xNames(m_xColNames,UNO_QUERY);
+ OResultSet::setBoundedColumns( m_aRow, m_xParamColumns, xNames, false, m_xDBMetaData, m_aColMapping );
+
+ return eStatementType;
+}
+
+void OPreparedStatement::initializeResultSet( OResultSet* _pResult )
+{
+ OCommonStatement::initializeResultSet( _pResult );
+ _pResult->setParameterRow( m_aParameterRow );
+}
+
+
+void OPreparedStatement::clearCachedResultSet()
+{
+ OCommonStatement::clearCachedResultSet();
+ m_pResultSet.clear();
+ m_xMetaData.clear();
+}
+
+void OPreparedStatement::cacheResultSet( const ::rtl::Reference< OResultSet >& _pResult )
+{
+ OCommonStatement::cacheResultSet( _pResult );
+ OSL_PRECOND( m_pResultSet == nullptr, "OPreparedStatement::parseSql: you should call clearCachedResultSet before!" );
+ m_pResultSet = _pResult;
+}
+
+
+void SAL_CALL OPreparedStatement::acquire() throw()
+{
+ OCommonStatement::acquire();
+}
+
+void SAL_CALL OPreparedStatement::release() throw()
+{
+ OCommonStatement::release();
+}
+
+Any SAL_CALL OPreparedStatement::queryInterface( const Type & rType )
+{
+ Any aRet = OCommonStatement::queryInterface(rType);
+ if(!aRet.hasValue())
+ aRet = OPreparedStatement_BASE::queryInterface(rType);
+ return aRet;
+}
+
+css::uno::Sequence< css::uno::Type > SAL_CALL OPreparedStatement::getTypes( )
+{
+ return ::comphelper::concatSequences(OPreparedStatement_BASE::getTypes(),OCommonStatement::getTypes());
+}
+
+
+Reference< XResultSetMetaData > SAL_CALL OPreparedStatement::getMetaData( )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ checkDisposed(OCommonStatement_IBASE::rBHelper.bDisposed);
+
+ bool bReadOnly = true;
+ if ( m_pResultSet.is() )
+ bReadOnly = m_pResultSet->determineReadOnly();
+ // if we do not have a result set, then we have not been executed, yet. In this case, assuming readonly=true is
+ // okay, /me thinks.
+
+ if ( !m_xMetaData.is() )
+ m_xMetaData = new OResultSetMetaData( m_pSQLIterator->getSelectColumns(), m_pSQLIterator->getTables().begin()->first ,m_pTable,bReadOnly );
+
+ return m_xMetaData;
+}
+
+
+sal_Bool SAL_CALL OPreparedStatement::execute( )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ checkDisposed(OCommonStatement_IBASE::rBHelper.bDisposed);
+
+ Reference< XResultSet> xResult = executeQuery();
+ return xResult.is();
+}
+
+
+sal_Int32 SAL_CALL OPreparedStatement::executeUpdate( )
+{
+ ::dbtools::throwFeatureNotImplementedSQLException( "XStatement::executeUpdate", *this );
+ return 0;
+}
+
+
+void SAL_CALL OPreparedStatement::setString( sal_Int32 parameterIndex, const OUString& x )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ checkDisposed(OCommonStatement_IBASE::rBHelper.bDisposed);
+
+ setParameter( parameterIndex, x );
+}
+
+
+Reference< XConnection > SAL_CALL OPreparedStatement::getConnection( )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ checkDisposed(OCommonStatement_IBASE::rBHelper.bDisposed);
+
+ return Reference< XConnection >(m_pConnection.get());
+}
+
+
+Reference< XResultSet > SAL_CALL OPreparedStatement::executeQuery( )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ checkDisposed(OCommonStatement_IBASE::rBHelper.bDisposed);
+
+ // our statement has already been parsed in lateInit, no need to do all this (potentially expensive)
+ // stuff again. Just execute.
+ return impl_executeCurrentQuery();
+}
+
+
+void SAL_CALL OPreparedStatement::setBoolean( sal_Int32 /*parameterIndex*/, sal_Bool /*x*/ )
+{
+ ::dbtools::throwFeatureNotImplementedSQLException( "XParameters::setBoolean", *this );
+}
+
+void SAL_CALL OPreparedStatement::setByte( sal_Int32 /*parameterIndex*/, sal_Int8 /*x*/ )
+{
+ ::dbtools::throwFeatureNotImplementedSQLException( "XParameters::setByte", *this );
+}
+
+
+void SAL_CALL OPreparedStatement::setDate( sal_Int32 /*parameterIndex*/, const Date& /*aData*/ )
+{
+ ::dbtools::throwFeatureNotImplementedSQLException( "XParameters::setDate", *this );
+}
+
+
+void SAL_CALL OPreparedStatement::setTime( sal_Int32 /*parameterIndex*/, const css::util::Time& /*aVal*/ )
+{
+ ::dbtools::throwFeatureNotImplementedSQLException( "XParameters::setTime", *this );
+}
+
+
+void SAL_CALL OPreparedStatement::setTimestamp( sal_Int32 /*parameterIndex*/, const DateTime& /*aVal*/ )
+{
+ ::dbtools::throwFeatureNotImplementedSQLException( "XParameters::setTimestamp", *this );
+}
+
+
+void SAL_CALL OPreparedStatement::setDouble( sal_Int32 /*parameterIndex*/, double /*x*/ )
+{
+ ::dbtools::throwFeatureNotImplementedSQLException( "XParameters::setDouble", *this );
+}
+
+
+void SAL_CALL OPreparedStatement::setFloat( sal_Int32 /*parameterIndex*/, float /*x*/ )
+{
+ ::dbtools::throwFeatureNotImplementedSQLException( "XParameters::setFloat", *this );
+}
+
+
+void SAL_CALL OPreparedStatement::setInt( sal_Int32 /*parameterIndex*/, sal_Int32 /*x*/ )
+{
+ ::dbtools::throwFeatureNotImplementedSQLException( "XParameters::setInt", *this );
+}
+
+
+void SAL_CALL OPreparedStatement::setLong( sal_Int32 /*parameterIndex*/, sal_Int64 /*aVal*/ )
+{
+ ::dbtools::throwFeatureNotImplementedSQLException( "XParameters::setLong", *this );
+}
+
+
+void SAL_CALL OPreparedStatement::setNull( sal_Int32 parameterIndex, sal_Int32 /*sqlType*/ )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ checkDisposed(OCommonStatement_IBASE::rBHelper.bDisposed);
+
+ checkAndResizeParameters(parameterIndex);
+
+ (*m_aParameterRow)[parameterIndex].setNull();
+}
+
+
+void SAL_CALL OPreparedStatement::setClob( sal_Int32 /*parameterIndex*/, const Reference< XClob >& /*x*/ )
+{
+ ::dbtools::throwFeatureNotImplementedSQLException( "XParameters::setClob", *this );
+}
+
+
+void SAL_CALL OPreparedStatement::setBlob( sal_Int32 /*parameterIndex*/, const Reference< XBlob >& /*x*/ )
+{
+ ::dbtools::throwFeatureNotImplementedSQLException( "XParameters::setBlob", *this );
+}
+
+
+void SAL_CALL OPreparedStatement::setArray( sal_Int32 /*parameterIndex*/, const Reference< XArray >& /*x*/ )
+{
+ ::dbtools::throwFeatureNotImplementedSQLException( "XParameters::setArray", *this );
+}
+
+
+void SAL_CALL OPreparedStatement::setRef( sal_Int32 /*parameterIndex*/, const Reference< XRef >& /*x*/ )
+{
+ ::dbtools::throwFeatureNotImplementedSQLException( "XParameters::setRef", *this );
+}
+
+
+void SAL_CALL OPreparedStatement::setObjectWithInfo( sal_Int32 /*parameterIndex*/, const Any& /*x*/, sal_Int32 /*sqlType*/, sal_Int32 /*scale*/ )
+{
+ ::dbtools::throwFeatureNotImplementedSQLException( "XParameters::setObjectWithInfo", *this );
+}
+
+
+void SAL_CALL OPreparedStatement::setObjectNull( sal_Int32 parameterIndex, sal_Int32 sqlType, const OUString& /*typeName*/ )
+{
+ setNull(parameterIndex,sqlType);
+}
+
+
+void SAL_CALL OPreparedStatement::setObject( sal_Int32 parameterIndex, const Any& x )
+{
+ ::dbtools::implSetObject(this,parameterIndex,x);
+}
+
+
+void SAL_CALL OPreparedStatement::setShort( sal_Int32 /*parameterIndex*/, sal_Int16 /*x*/ )
+{
+ ::dbtools::throwFeatureNotImplementedSQLException( "XParameters::setShort", *this );
+}
+
+
+void SAL_CALL OPreparedStatement::setBytes( sal_Int32 /*parameterIndex*/, const Sequence< sal_Int8 >& /*x*/ )
+{
+ ::dbtools::throwFeatureNotImplementedSQLException( "XParameters::setBytes", *this );
+}
+
+
+void SAL_CALL OPreparedStatement::setCharacterStream( sal_Int32 /*parameterIndex*/, const Reference< css::io::XInputStream >& /*x*/, sal_Int32 /*length*/ )
+{
+ ::dbtools::throwFeatureNotImplementedSQLException( "XParameters::setCharacterStream", *this );
+}
+
+
+void SAL_CALL OPreparedStatement::setBinaryStream( sal_Int32 /*parameterIndex*/, const Reference< css::io::XInputStream >& /*x*/, sal_Int32 /*length*/ )
+{
+ ::dbtools::throwFeatureNotImplementedSQLException( "XParameters::setBinaryStream", *this );
+}
+
+
+void SAL_CALL OPreparedStatement::clearParameters( )
+{
+}
+
+void OPreparedStatement::setFastPropertyValue_NoBroadcast(sal_Int32 nHandle,const Any& rValue)
+{
+ switch(nHandle)
+ {
+ case PROPERTY_ID_RESULTSETCONCURRENCY:
+ break;
+ case PROPERTY_ID_RESULTSETTYPE:
+ break;
+ case PROPERTY_ID_FETCHDIRECTION:
+ break;
+ case PROPERTY_ID_USEBOOKMARKS:
+ break;
+ default:
+ OCommonStatement::setFastPropertyValue_NoBroadcast(nHandle,rValue);
+ }
+}
+
+
+void OPreparedStatement::checkAndResizeParameters(sal_Int32 parameterIndex)
+{
+ ::connectivity::checkDisposed(OCommonStatement_IBASE::rBHelper.bDisposed);
+
+ if ( !m_aParameterRow.is() ) {
+ m_aParameterRow = new OValueVector();
+ m_aParameterRow->push_back(sal_Int32(0));
+ }
+
+ if (static_cast<sal_Int32>(m_aParameterRow->size()) <= parameterIndex)
+ m_aParameterRow->resize(parameterIndex+1);
+}
+
+void OPreparedStatement::setParameter(sal_Int32 parameterIndex, const
+ORowSetValue& x)
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ checkAndResizeParameters(parameterIndex);
+
+ SAL_INFO(
+ "connectivity.mork",
+ "setParameter(" << parameterIndex << ", '" << x.getString() << "')");
+ (*m_aParameterRow)[parameterIndex] = x;
+}
+
+
+void OPreparedStatement::AddParameter(OSQLParseNode const * pParameter, const Reference<XPropertySet>& _xCol)
+{
+ OSL_ENSURE(SQL_ISRULE(pParameter,parameter),"OResultSet::AddParameter: Argument is not a Parameter");
+ OSL_ENSURE(pParameter->count() > 0,"OResultSet: error in parse tree");
+
+ OUString sParameterName;
+
+ // set up Parameter-Column:
+ sal_Int32 eType = DataType::VARCHAR;
+ sal_uInt32 nPrecision = 255;
+ sal_Int32 nScale = 0;
+ sal_Int32 nNullable = ColumnValue::NULLABLE;
+
+ if (_xCol.is())
+ {
+ // Type, Precision, Scale ... utilize the selected Columns,
+ // then this Column will get the value assigned or with this
+ // Column will the value be compared.
+ eType = getINT32(_xCol->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_TYPE)));
+ nPrecision = getINT32(_xCol->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_PRECISION)));
+ nScale = getINT32(_xCol->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_SCALE)));
+ nNullable = getINT32(_xCol->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_ISNULLABLE)));
+ _xCol->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_NAME)) >>= sParameterName;
+ }
+
+ Reference<XPropertySet> xParaColumn = new connectivity::sdbcx::OColumn(sParameterName
+ ,OUString()
+ ,OUString()
+ ,OUString()
+ ,nNullable
+ ,nPrecision
+ ,nScale
+ ,eType
+ ,false
+ ,false
+ ,false
+ ,m_pSQLIterator->isCaseSensitive()
+ ,OUString()
+ ,OUString()
+ ,OUString());
+ m_xParamColumns->push_back(xParaColumn);
+}
+
+void OPreparedStatement::describeColumn(OSQLParseNode const * _pParameter,
+ OSQLParseNode const * _pNode,
+ const OSQLTable& _xTable)
+{
+ Reference<XPropertySet> xProp;
+ if(SQL_ISRULE(_pNode,column_ref))
+ {
+ OUString sColumnName,sTableRange;
+ m_pSQLIterator->getColumnRange(_pNode,sColumnName,sTableRange);
+ if(!sColumnName.isEmpty())
+ {
+ Reference<XNameAccess> xNameAccess = _xTable->getColumns();
+ if(xNameAccess->hasByName(sColumnName))
+ xNameAccess->getByName(sColumnName) >>= xProp;
+ AddParameter(_pParameter,xProp);
+ }
+ }
+ // else
+ // AddParameter(_pParameter,xProp);
+}
+
+void OPreparedStatement::describeParameter()
+{
+ std::vector< OSQLParseNode*> aParseNodes;
+ scanParameter(m_pParseTree.get(), aParseNodes);
+ if(aParseNodes.empty())
+ return;
+
+ m_xParamColumns = new OSQLColumns();
+ const OSQLTables& rTabs = m_pSQLIterator->getTables();
+ if(!rTabs.empty())
+ {
+ OSQLTable xTable = rTabs.begin()->second;
+ for (auto const& parseNode : aParseNodes)
+ {
+ describeColumn(parseNode,parseNode->getParent()->getChild(0),xTable);
+ }
+ }
+}
+
+
+void OPreparedStatement::scanParameter(OSQLParseNode* pParseNode,std::vector< OSQLParseNode*>& _rParaNodes)
+{
+ OSL_ENSURE(pParseNode != nullptr,"OResultSet: internal error: invalid ParseNode");
+
+ // Parameter Name-Row found?
+ if (SQL_ISRULE(pParseNode,parameter))
+ {
+ OSL_ENSURE(pParseNode->count() >= 1,"OResultSet: Faulty Parse Tree");
+ OSL_ENSURE(pParseNode->getChild(0)->getNodeType() == SQLNodeType::Punctuation,"OResultSet: Faulty Parse Tree");
+
+ _rParaNodes.push_back(pParseNode);
+ // further search isn't necessary
+ return;
+ }
+
+ // Search on in Parse Tree
+ for (size_t i = 0; i < pParseNode->count(); i++)
+ scanParameter(pParseNode->getChild(i),_rParaNodes);
+}
+
+css::uno::Reference< css::sdbc::XResultSet > SAL_CALL OPreparedStatement::getResultSet( )
+{
+ return nullptr;
+}
+
+sal_Int32 SAL_CALL OPreparedStatement::getUpdateCount( )
+{
+ return 0;
+}
+
+sal_Bool SAL_CALL OPreparedStatement::getMoreResults( )
+{
+ return false;
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/mork/MPreparedStatement.hxx b/connectivity/source/drivers/mork/MPreparedStatement.hxx
new file mode 100644
index 000000000..c40ffc909
--- /dev/null
+++ b/connectivity/source/drivers/mork/MPreparedStatement.hxx
@@ -0,0 +1,134 @@
+/* -*- 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 .
+ */
+
+#ifndef INCLUDED_CONNECTIVITY_SOURCE_DRIVERS_MORK_MPREPAREDSTATEMENT_HXX
+#define INCLUDED_CONNECTIVITY_SOURCE_DRIVERS_MORK_MPREPAREDSTATEMENT_HXX
+
+#include "MResultSet.hxx"
+#include <com/sun/star/sdbc/XParameters.hpp>
+#include <com/sun/star/sdbc/XMultipleResults.hpp>
+#include <cppuhelper/implbase5.hxx>
+
+namespace connectivity
+{
+ namespace mork
+ {
+
+ typedef ::cppu::ImplHelper5< css::sdbc::XPreparedStatement,
+ css::sdbc::XParameters,
+ css::sdbc::XResultSetMetaDataSupplier,
+ css::sdbc::XMultipleResults,
+ css::lang::XServiceInfo> OPreparedStatement_BASE;
+
+ class OPreparedStatement final : public OCommonStatement,
+ public OPreparedStatement_BASE
+ {
+ // Data attributes
+
+ OUString m_sSqlStatement;
+ css::uno::Reference< css::sdbc::XResultSetMetaData > m_xMetaData;
+ ::rtl::Reference< OResultSet > m_pResultSet;
+ ::rtl::Reference<connectivity::OSQLColumns> m_xParamColumns; // the parameter columns
+ OValueRow m_aParameterRow;
+
+ virtual void SAL_CALL setFastPropertyValue_NoBroadcast(sal_Int32 nHandle,
+ const css::uno::Any& rValue) override;
+ virtual ~OPreparedStatement() override;
+
+ virtual void SAL_CALL disposing() override;
+
+ // OCommonStatement overridables
+ virtual StatementType
+ parseSql( const OUString& sql , bool bAdjusted = false) override;
+ virtual void initializeResultSet( OResultSet* _pResult ) override;
+ virtual void clearCachedResultSet() override;
+ virtual void cacheResultSet( const ::rtl::Reference< OResultSet >& _pResult ) override;
+
+
+ void checkAndResizeParameters(sal_Int32 parameterIndex);
+ void setParameter(sal_Int32 parameterIndex, const ORowSetValue& x);
+
+ void AddParameter(connectivity::OSQLParseNode const * pParameter,
+ const css::uno::Reference< css::beans::XPropertySet>& _xCol);
+ void scanParameter(OSQLParseNode* pParseNode,std::vector< OSQLParseNode*>& _rParaNodes);
+ void describeColumn(OSQLParseNode const * _pParameter, OSQLParseNode const * _pNode, const OSQLTable& _xTable);
+ void describeParameter();
+
+ public:
+ DECLARE_SERVICE_INFO();
+ // A ctor need for returning the object
+ OPreparedStatement( OConnection* _pConnection,const OUString& sql);
+ void lateInit();
+
+ //XInterface
+ virtual css::uno::Any SAL_CALL queryInterface( const css::uno::Type & rType ) override;
+ virtual void SAL_CALL acquire() throw() override;
+ virtual void SAL_CALL release() throw() override;
+ //XTypeProvider
+ virtual css::uno::Sequence< css::uno::Type > SAL_CALL getTypes( ) override;
+
+ // XPreparedStatement
+ virtual css::uno::Reference< css::sdbc::XResultSet > SAL_CALL executeQuery( ) override;
+ virtual sal_Int32 SAL_CALL executeUpdate( ) override;
+ virtual sal_Bool SAL_CALL execute( ) override;
+ virtual css::uno::Reference< css::sdbc::XConnection > SAL_CALL getConnection( ) override;
+ // XParameters
+ virtual void SAL_CALL setNull( sal_Int32 parameterIndex, sal_Int32 sqlType ) override;
+ virtual void SAL_CALL setObjectNull( sal_Int32 parameterIndex, sal_Int32 sqlType, const OUString& typeName ) override;
+ virtual void SAL_CALL setBoolean( sal_Int32 parameterIndex, sal_Bool x ) override;
+ virtual void SAL_CALL setByte( sal_Int32 parameterIndex, sal_Int8 x ) override;
+ virtual void SAL_CALL setShort( sal_Int32 parameterIndex, sal_Int16 x ) override;
+ virtual void SAL_CALL setInt( sal_Int32 parameterIndex, sal_Int32 x ) override;
+ virtual void SAL_CALL setLong( sal_Int32 parameterIndex, sal_Int64 x ) override;
+ virtual void SAL_CALL setFloat( sal_Int32 parameterIndex, float x ) override;
+ virtual void SAL_CALL setDouble( sal_Int32 parameterIndex, double x ) override;
+ virtual void SAL_CALL setString( sal_Int32 parameterIndex, const OUString& x ) override;
+ virtual void SAL_CALL setBytes( sal_Int32 parameterIndex, const css::uno::Sequence< sal_Int8 >& x ) override;
+ virtual void SAL_CALL setDate( sal_Int32 parameterIndex, const css::util::Date& x ) override;
+ virtual void SAL_CALL setTime( sal_Int32 parameterIndex, const css::util::Time& x ) override;
+ virtual void SAL_CALL setTimestamp( sal_Int32 parameterIndex, const css::util::DateTime& x ) override;
+ virtual void SAL_CALL setBinaryStream( sal_Int32 parameterIndex, const css::uno::Reference< css::io::XInputStream >& x, sal_Int32 length ) override;
+ virtual void SAL_CALL setCharacterStream( sal_Int32 parameterIndex, const css::uno::Reference< css::io::XInputStream >& x, sal_Int32 length ) override;
+ virtual void SAL_CALL setObject( sal_Int32 parameterIndex, const css::uno::Any& x ) override;
+ virtual void SAL_CALL setObjectWithInfo( sal_Int32 parameterIndex, const css::uno::Any& x, sal_Int32 targetSqlType, sal_Int32 scale ) override;
+ virtual void SAL_CALL setRef( sal_Int32 parameterIndex, const css::uno::Reference< css::sdbc::XRef >& x ) override;
+ virtual void SAL_CALL setBlob( sal_Int32 parameterIndex, const css::uno::Reference< css::sdbc::XBlob >& x ) override;
+ virtual void SAL_CALL setClob( sal_Int32 parameterIndex, const css::uno::Reference< css::sdbc::XClob >& x ) override;
+ virtual void SAL_CALL setArray( sal_Int32 parameterIndex, const css::uno::Reference< css::sdbc::XArray >& x ) override;
+ virtual void SAL_CALL clearParameters( ) override;
+ // XResultSetMetaDataSupplier
+ virtual css::uno::Reference< css::sdbc::XResultSetMetaData > SAL_CALL getMetaData( ) override;
+ // XMultipleResults
+ virtual css::uno::Reference< css::sdbc::XResultSet > SAL_CALL getResultSet( ) override;
+ virtual sal_Int32 SAL_CALL getUpdateCount( ) override;
+ virtual sal_Bool SAL_CALL getMoreResults( ) override;
+
+ public:
+ using OCommonStatement::executeQuery;
+ using OCommonStatement::executeUpdate;
+ using OCommonStatement::execute;
+ private:
+ using OPropertySetHelper::getFastPropertyValue;
+ };
+ }
+}
+
+#endif // INCLUDED_CONNECTIVITY_SOURCE_DRIVERS_MORK_MPREPAREDSTATEMENT_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/mork/MQueryHelper.cxx b/connectivity/source/drivers/mork/MQueryHelper.cxx
new file mode 100644
index 000000000..aaf8cac6a
--- /dev/null
+++ b/connectivity/source/drivers/mork/MQueryHelper.cxx
@@ -0,0 +1,321 @@
+/* -*- 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 "MColumnAlias.hxx"
+#include "MQueryHelper.hxx"
+#include "MConnection.hxx"
+
+#include "MorkParser.hxx"
+#include <string>
+#include <vector>
+#include <algorithm>
+
+#include <strings.hrc>
+
+#include <unotools/textsearch.hxx>
+#include <sal/log.hxx>
+
+using namespace connectivity::mork;
+using namespace connectivity;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::sdbc;
+
+
+static
+std::vector<bool> entryMatchedByExpression(MQueryHelper* _aQuery, MQueryExpression const * _aExpr, MQueryHelperResultEntry* entry);
+
+MQueryHelperResultEntry::MQueryHelperResultEntry()
+{
+}
+
+MQueryHelperResultEntry::~MQueryHelperResultEntry()
+{
+}
+
+OUString MQueryHelperResultEntry::getValue( const OString &key ) const
+{
+ FieldMap::const_iterator iter = m_Fields.find( key );
+ if ( iter == m_Fields.end() )
+ {
+ return OUString();
+ }
+ else
+ {
+ return iter->second;
+ }
+}
+
+void MQueryHelperResultEntry::setValue( const OString &key, const OUString & rValue)
+{
+ m_Fields[ key ] = rValue;
+}
+
+MQueryHelper::MQueryHelper(const OColumnAlias& _ca)
+ :m_rColumnAlias( _ca )
+ ,m_aError()
+{
+ m_aResults.clear();
+}
+
+MQueryHelper::~MQueryHelper()
+{
+ clear_results();
+}
+
+
+void MQueryHelper::setAddressbook(OUString const &ab)
+{
+ ::osl::MutexGuard aGuard(m_aMutex);
+ m_aAddressbook = ab;
+}
+
+void MQueryHelper::append(std::unique_ptr<MQueryHelperResultEntry> resEnt)
+{
+ assert(resEnt);
+ m_aResults.push_back( std::move(resEnt) );
+}
+
+void MQueryHelper::clear_results()
+{
+ m_aResults.clear();
+}
+
+void MQueryHelper::reset()
+{
+ clear_results();
+ m_aError.reset();
+}
+
+MQueryHelperResultEntry*
+MQueryHelper::getByIndex(sal_uInt32 nRow)
+{
+ // Row numbers are from 1 to N, need to ensure this, and then
+ // subtract 1
+ if ( nRow < 1 ) {
+ return nullptr;
+ }
+ return m_aResults[nRow -1].get();
+}
+
+sal_Int32 MQueryHelper::getResultCount() const
+{
+ sal_Int32 result = static_cast<sal_Int32>(m_aResults.size());
+
+ return result;
+}
+
+bool MQueryHelper::getRowValue( ORowSetValue& rValue, sal_Int32 nDBRow,const OUString& aDBColumnName, sal_Int32 nType )
+{
+ MQueryHelperResultEntry* pResEntry = getByIndex( nDBRow );
+
+ OSL_ENSURE( pResEntry != nullptr, "xResEntry == NULL");
+ if (pResEntry == nullptr )
+ {
+ rValue.setNull();
+ return false;
+ }
+ switch ( nType )
+ {
+ case DataType::VARCHAR:
+ rValue = pResEntry->getValue( m_rColumnAlias.getProgrammaticNameOrFallbackToUTF8Alias( aDBColumnName ) );
+ break;
+
+ default:
+ rValue.setNull();
+ break;
+ }
+
+ return true;
+}
+
+sal_Int32 MQueryHelper::executeQuery(OConnection* xConnection, MQueryExpression & expr)
+{
+ reset();
+
+ OString oStringTable = OUStringToOString( m_aAddressbook, RTL_TEXTENCODING_UTF8 );
+ std::set<int> listRecords;
+ bool handleListTable = false;
+ MorkParser* pMork;
+
+ // check if we are retrieving the default table
+ if (oStringTable == "AddressBook" || oStringTable == "CollectedAddressBook")
+ {
+ pMork = xConnection->getMorkParser(oStringTable);
+ }
+ else
+ {
+ // Let's try to retrieve the list in Collected Addresses book
+ pMork = xConnection->getMorkParser("CollectedAddressBook");
+ if (std::find(pMork->lists_.begin(), pMork->lists_.end(), m_aAddressbook) == pMork->lists_.end())
+ {
+ // so the list is in Address book
+ // TODO : manage case where an address book has been created
+ pMork = xConnection->getMorkParser("AddressBook");
+ }
+ handleListTable = true;
+ // retrieve row ids for that list table
+ std::string listTable = oStringTable.getStr();
+ pMork->getRecordKeysForListTable(listTable, listRecords);
+ }
+
+ MorkTableMap *Tables = pMork->getTables( 0x80 );
+ if (!Tables)
+ return -1;
+
+ MorkRowMap *Rows = nullptr;
+
+ // Iterate all tables
+ for (auto & table : Tables->map)
+ {
+ if (table.first != 1) break;
+ Rows = MorkParser::getRows( 0x80, &table.second );
+ if ( Rows )
+ {
+ // Iterate all rows
+ for (auto const& row : Rows->map)
+ {
+ // list specific table
+ // only retrieve rowIds that belong to that list table.
+ if (handleListTable)
+ {
+ int rowId = row.first;
+ // belongs this row id to the list table?
+ if (listRecords.end() == listRecords.find(rowId))
+ {
+ // no, skip it
+ continue;
+ }
+ }
+
+ std::unique_ptr<MQueryHelperResultEntry> entry(new MQueryHelperResultEntry());
+ for (auto const& cell : row.second)
+ {
+ std::string column = pMork->getColumn(cell.first);
+ std::string value = pMork->getValue(cell.second);
+ OString key(column.c_str(), static_cast<sal_Int32>(column.size()));
+ OString valueOString(value.c_str(), static_cast<sal_Int32>(value.size()));
+ OUString valueOUString = OStringToOUString( valueOString, RTL_TEXTENCODING_UTF8 );
+ entry->setValue(key, valueOUString);
+ }
+ bool result = true;
+ for (bool elem : entryMatchedByExpression(this, &expr, entry.get()))
+ {
+ result = result && elem;
+ }
+ if (result)
+ {
+ append(std::move(entry));
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+std::vector<bool> entryMatchedByExpression(MQueryHelper* _aQuery, MQueryExpression const * _aExpr, MQueryHelperResultEntry* entry)
+{
+ std::vector<bool> resultVector;
+ for (auto const& expr : _aExpr->getExpressions())
+ {
+ if ( expr->isStringExpr() ) {
+ MQueryExpressionString* evStr = static_cast<MQueryExpressionString*> (expr);
+ // Set the 'name' property of the boolString.
+ OString attrName = _aQuery->getColumnAlias().getProgrammaticNameOrFallbackToUTF8Alias( evStr->getName() );
+ SAL_INFO("connectivity.mork", "Name = " << attrName);
+ bool bRequiresValue = true;
+ OUString currentValue = entry->getValue(attrName);
+ if (evStr->getCond() == MQueryOp::Exists || evStr->getCond() == MQueryOp::DoesNotExist)
+ {
+ bRequiresValue = false;
+ }
+ if (bRequiresValue)
+ {
+ SAL_INFO("connectivity.mork", "Value = " << evStr->getValue() );
+ const OUString& searchedValue = evStr->getValue();
+ if (evStr->getCond() == MQueryOp::Is) {
+ SAL_INFO("connectivity.mork", "MQueryOp::Is; done");
+ resultVector.push_back(currentValue == searchedValue);
+ } else if (evStr->getCond() == MQueryOp::IsNot) {
+ SAL_INFO("connectivity.mork", "MQueryOp::IsNot; done");
+ resultVector.push_back(currentValue != searchedValue);
+ } else if (evStr->getCond() == MQueryOp::EndsWith) {
+ SAL_INFO("connectivity.mork", "MQueryOp::EndsWith; done");
+ resultVector.push_back(currentValue.endsWith(searchedValue));
+ } else if (evStr->getCond() == MQueryOp::BeginsWith) {
+ SAL_INFO("connectivity.mork", "MQueryOp::BeginsWith; done");
+ resultVector.push_back(currentValue.startsWith(searchedValue));
+ } else if (evStr->getCond() == MQueryOp::Contains) {
+ SAL_INFO("connectivity.mork", "MQueryOp::Contains; done");
+ resultVector.push_back(currentValue.indexOf(searchedValue) != -1);
+ } else if (evStr->getCond() == MQueryOp::DoesNotContain) {
+ SAL_INFO("connectivity.mork", "MQueryOp::DoesNotContain; done");
+ resultVector.push_back(currentValue.indexOf(searchedValue) == -1);
+ } else if (evStr->getCond() == MQueryOp::RegExp) {
+ SAL_INFO("connectivity.mork", "MQueryOp::RegExp; done");
+ utl::SearchParam param(
+ searchedValue, utl::SearchParam::SearchType::Regexp);
+ utl::TextSearch ts(param, LANGUAGE_DONTKNOW);
+ sal_Int32 start = 0;
+ sal_Int32 end = currentValue.getLength();
+ resultVector.push_back(
+ ts.SearchForward(currentValue, &start, &end));
+ }
+ } else if (evStr->getCond() == MQueryOp::Exists) {
+ SAL_INFO("connectivity.mork", "MQueryOp::Exists; done");
+ resultVector.push_back(!currentValue.isEmpty());
+ } else if (evStr->getCond() == MQueryOp::DoesNotExist) {
+ SAL_INFO("connectivity.mork", "MQueryOp::DoesNotExist; done");
+ resultVector.push_back(currentValue.isEmpty());
+ }
+ }
+ else if ( expr->isExpr() ) {
+ SAL_INFO("connectivity.mork", "Appending Subquery Expression");
+ MQueryExpression* queryExpression = static_cast<MQueryExpression*> (expr);
+ // recursive call
+ std::vector<bool> subquery_result = entryMatchedByExpression(_aQuery, queryExpression, entry);
+ MQueryExpression::bool_cond condition = queryExpression->getExpressionCondition();
+ if (condition == MQueryExpression::OR) {
+ bool result = false;
+ for (bool elem : subquery_result)
+ {
+ result = result || elem;
+ }
+ resultVector.push_back(result);
+ } else {
+ assert(condition == MQueryExpression::AND && "only OR or AND should exist");
+ bool result = true;
+ for (bool elem : subquery_result)
+ {
+ result = result && elem;
+ }
+ resultVector.push_back(result);
+ }
+ }
+ else {
+ // Should never see this...
+ SAL_WARN("connectivity.mork", "Unknown Expression Type!");
+ _aQuery->getError().setResId(STR_ERROR_GET_ROW);
+ return resultVector;
+ }
+ }
+ return resultVector;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/mork/MQueryHelper.hxx b/connectivity/source/drivers/mork/MQueryHelper.hxx
new file mode 100644
index 000000000..67d2b081d
--- /dev/null
+++ b/connectivity/source/drivers/mork/MQueryHelper.hxx
@@ -0,0 +1,184 @@
+/* -*- 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 .
+ */
+
+#ifndef INCLUDED_CONNECTIVITY_SOURCE_DRIVERS_MORK_MQUERYHELPER_HXX
+#define INCLUDED_CONNECTIVITY_SOURCE_DRIVERS_MORK_MQUERYHELPER_HXX
+
+#include <connectivity/FValue.hxx>
+#include "MErrorResource.hxx"
+#include "MColumnAlias.hxx"
+
+namespace connectivity
+{
+ namespace mork
+ {
+ class OConnection;
+ class MQueryHelper;
+ class ErrorDescriptor;
+
+ namespace MQueryOp {
+ typedef enum {
+ Exists = 0,
+ DoesNotExist = 1,
+ Contains = 2,
+ DoesNotContain = 3,
+ Is = 4,
+ IsNot = 5,
+ BeginsWith = 6,
+ EndsWith = 7,
+ RegExp = 8
+ } cond_type;
+ }
+
+ class MQueryExpressionBase {
+ public:
+ enum class node_type {
+ StringExpr,
+ Expr
+ };
+
+ protected:
+ node_type m_eNodeType;
+
+ explicit MQueryExpressionBase( node_type _eNodeType ) : m_eNodeType( _eNodeType ) {}
+
+ public:
+ virtual ~MQueryExpressionBase() {}
+
+ bool isStringExpr( ) const { return m_eNodeType == node_type::StringExpr; }
+ bool isExpr( ) const { return m_eNodeType == node_type::Expr; }
+ };
+
+ class MQueryExpressionString final : public MQueryExpressionBase {
+ OUString m_aName; // LHS
+ MQueryOp::cond_type m_aBooleanCondition;
+ OUString m_aValue; // RHS
+
+ public:
+
+ MQueryExpressionString( const OUString& lhs,
+ MQueryOp::cond_type cond,
+ const OUString& rhs )
+ : MQueryExpressionBase( MQueryExpressionBase::node_type::StringExpr )
+ , m_aName( lhs )
+ , m_aBooleanCondition( cond )
+ , m_aValue( rhs )
+ {
+ }
+
+ MQueryExpressionString( const OUString& lhs,
+ MQueryOp::cond_type cond )
+ : MQueryExpressionBase( MQueryExpressionBase::node_type::StringExpr )
+ , m_aName( lhs )
+ , m_aBooleanCondition( cond )
+ , m_aValue( OUString() )
+ {
+ }
+
+ const OUString& getName() const { return m_aName; }
+ MQueryOp::cond_type getCond() const { return m_aBooleanCondition; }
+ const OUString& getValue() const { return m_aValue; }
+ };
+
+ class MQueryExpression final : public MQueryExpressionBase
+ {
+ friend class MQueryHelper;
+
+ public:
+ typedef std::vector< MQueryExpressionBase* > ExprVector;
+
+ typedef enum {
+ AND,
+ OR
+ } bool_cond;
+
+ // All expressions on a peer level use same condition operator
+ void setExpressionCondition( bool_cond _cond )
+ { m_aExprCondType = _cond; }
+
+ void addExpression(MQueryExpressionBase * expr)
+ { m_aExprVector.push_back(expr); }
+
+ ExprVector const & getExpressions( ) const
+ { return m_aExprVector; }
+
+ // All expressions on a peer level use same condition operator
+ bool_cond getExpressionCondition( ) const
+ { return m_aExprCondType; }
+
+ MQueryExpression() : MQueryExpressionBase( MQueryExpressionBase::node_type::Expr ),
+ m_aExprCondType( OR )
+ {}
+
+ private:
+ ExprVector m_aExprVector;
+ bool_cond m_aExprCondType;
+
+ MQueryExpression(const MQueryExpression&) = delete;
+ MQueryExpression& operator=(const MQueryExpression&) = delete;
+ };
+
+ class MQueryHelperResultEntry
+ {
+ private:
+ typedef std::unordered_map< OString, OUString > FieldMap;
+
+ FieldMap m_Fields;
+
+ public:
+ MQueryHelperResultEntry();
+ ~MQueryHelperResultEntry();
+
+ OUString getValue( const OString &key ) const;
+ void setValue( const OString &key, const OUString & rValue);
+ };
+
+ class MQueryHelper final
+ {
+ private:
+
+ mutable ::osl::Mutex m_aMutex;
+ std::vector< std::unique_ptr<MQueryHelperResultEntry> > m_aResults;
+ void append(std::unique_ptr<MQueryHelperResultEntry> resEnt );
+ void clear_results();
+ OColumnAlias m_rColumnAlias;
+ ErrorDescriptor m_aError;
+ OUString m_aAddressbook;
+
+ public:
+ explicit MQueryHelper(const OColumnAlias& _ca);
+ ~MQueryHelper();
+
+ void reset();
+ MQueryHelperResultEntry* getByIndex( sal_uInt32 nRow );
+ sal_Int32 getResultCount() const;
+ bool getRowValue( ORowSetValue& rValue, sal_Int32 nDBRow,const OUString& aDBColumnName, sal_Int32 nType );
+ sal_Int32 executeQuery(OConnection* xConnection, MQueryExpression & expr);
+ const OColumnAlias& getColumnAlias() const { return m_rColumnAlias; }
+ bool hadError() const { return m_aError.is(); }
+ ErrorDescriptor& getError() { return m_aError; }
+
+ void setAddressbook( OUString const &);
+ };
+ }
+}
+
+#endif // INCLUDED_CONNECTIVITY_SOURCE_DRIVERS_MORK_MQUERYHELPER_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/mork/MResultSet.cxx b/connectivity/source/drivers/mork/MResultSet.cxx
new file mode 100644
index 000000000..ab6b11a9d
--- /dev/null
+++ b/connectivity/source/drivers/mork/MResultSet.cxx
@@ -0,0 +1,1710 @@
+/* -*- 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/sdbc/ResultSetType.hpp>
+#include <com/sun/star/sdbc/FetchDirection.hpp>
+#include <com/sun/star/sdbc/ResultSetConcurrency.hpp>
+#include <com/sun/star/sdbcx/CompareBookmark.hpp>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <connectivity/dbtools.hxx>
+#include <comphelper/types.hxx>
+#include <cppuhelper/typeprovider.hxx>
+#include <o3tl/safeint.hxx>
+#include <sal/log.hxx>
+
+#include <vector>
+#include <algorithm>
+#include "MResultSet.hxx"
+#include <sqlbison.hxx>
+#include "MResultSetMetaData.hxx"
+#include <FDatabaseMetaDataResultSet.hxx>
+
+#include <strings.hrc>
+
+using namespace ::comphelper;
+using namespace connectivity;
+using namespace connectivity::mork;
+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;
+using namespace com::sun::star::container;
+using namespace com::sun::star::io;
+using namespace com::sun::star::util;
+
+
+// IMPLEMENT_SERVICE_INFO(OResultSet,"com.sun.star.sdbcx.OResultSet","com.sun.star.sdbc.ResultSet");
+OUString SAL_CALL OResultSet::getImplementationName( )
+{
+ return "com.sun.star.sdbcx.mork.ResultSet";
+}
+
+ Sequence< OUString > SAL_CALL OResultSet::getSupportedServiceNames( )
+{
+ return {"com.sun.star.sdbc.ResultSet","com.sun.star.sdbcx.ResultSet"};
+}
+
+sal_Bool SAL_CALL OResultSet::supportsService( const OUString& _rServiceName )
+{
+ return cppu::supportsService(this, _rServiceName);
+}
+
+
+OResultSet::OResultSet(OCommonStatement* pStmt, const std::shared_ptr< connectivity::OSQLParseTreeIterator >& _pSQLIterator )
+ : OResultSet_BASE(m_aMutex)
+ ,OPropertySetHelper(OResultSet_BASE::rBHelper)
+ ,m_pStatement(pStmt)
+ ,m_xStatement(*pStmt)
+ ,m_nRowPos(0)
+ ,m_bWasNull(false)
+ ,m_nResultSetType(ResultSetType::SCROLL_INSENSITIVE)
+ ,m_nFetchDirection(FetchDirection::FORWARD)
+ ,m_pSQLIterator( _pSQLIterator )
+ ,m_pParseTree( _pSQLIterator->getParseTree() )
+ ,m_aQueryHelper(pStmt->getOwnConnection()->getColumnAlias())
+ ,m_CurrentRowCount(0)
+ ,m_nParamIndex(0)
+ ,m_bIsAlwaysFalseQuery(false)
+ ,m_bIsReadOnly(TRISTATE_INDET)
+{
+ //m_aQuery.setMaxNrOfReturns(pStmt->getOwnConnection()->getMaxResultRecords());
+}
+
+OResultSet::~OResultSet()
+{
+}
+
+
+void OResultSet::disposing()
+{
+ OPropertySetHelper::disposing();
+
+ ::osl::MutexGuard aGuard(m_aMutex);
+
+ m_xStatement.clear();
+ m_xMetaData.clear();
+ m_pParseTree = nullptr;
+ m_xColumns = nullptr;
+ m_pKeySet = nullptr;
+ m_xTable.clear();
+}
+
+Any SAL_CALL OResultSet::queryInterface( const Type & rType )
+{
+ Any aRet = OPropertySetHelper::queryInterface(rType);
+ if(!aRet.hasValue())
+ aRet = OResultSet_BASE::queryInterface(rType);
+ return aRet;
+}
+
+ Sequence< Type > SAL_CALL OResultSet::getTypes( )
+{
+ OTypeCollection aTypes( cppu::UnoType<css::beans::XMultiPropertySet>::get(),
+ cppu::UnoType<css::beans::XFastPropertySet>::get(),
+ cppu::UnoType<css::beans::XPropertySet>::get());
+
+ return ::comphelper::concatSequences(aTypes.getTypes(),OResultSet_BASE::getTypes());
+}
+
+void OResultSet::methodEntry()
+{
+ checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
+ if ( !m_xTable.is() )
+ {
+ OSL_FAIL( "OResultSet::methodEntry: looks like we're disposed, but how is this possible?" );
+ throw DisposedException( OUString(), *this );
+ }
+}
+
+
+sal_Int32 SAL_CALL OResultSet::findColumn( const OUString& columnName )
+{
+ ResultSetEntryGuard aGuard( *this );
+
+ // find the first column with the name columnName
+ Reference< XResultSetMetaData > xMeta = getMetaData();
+ sal_Int32 nLen = xMeta->getColumnCount();
+ sal_Int32 i = 1;
+ for(;i<=nLen;++i)
+ {
+ if(xMeta->isCaseSensitive(i) ? columnName == xMeta->getColumnName(i) :
+ columnName.equalsIgnoreAsciiCase(xMeta->getColumnName(i)))
+ return i;
+ }
+
+ ::dbtools::throwInvalidColumnException( columnName, *this );
+ assert(false);
+ return 0; // Never reached
+}
+
+Reference< XInputStream > SAL_CALL OResultSet::getBinaryStream( sal_Int32 /*columnIndex*/ )
+{
+ return nullptr;
+}
+
+Reference< XInputStream > SAL_CALL OResultSet::getCharacterStream( sal_Int32 /*columnIndex*/ )
+{
+ return nullptr;
+}
+
+
+sal_Bool SAL_CALL OResultSet::getBoolean( sal_Int32 /*columnIndex*/ )
+{
+ ResultSetEntryGuard aGuard( *this );
+ m_bWasNull = true;
+ return false;
+}
+
+
+sal_Int8 SAL_CALL OResultSet::getByte( sal_Int32 /*columnIndex*/ )
+{
+ return 0;
+}
+
+
+Sequence< sal_Int8 > SAL_CALL OResultSet::getBytes( sal_Int32 /*columnIndex*/ )
+{
+ return Sequence< sal_Int8 >();
+}
+
+
+Date SAL_CALL OResultSet::getDate( sal_Int32 /*columnIndex*/ )
+{
+ return Date();
+}
+
+
+double SAL_CALL OResultSet::getDouble( sal_Int32 /*columnIndex*/ )
+{
+ return 0.0;
+}
+
+
+float SAL_CALL OResultSet::getFloat( sal_Int32 /*columnIndex*/ )
+{
+ return 0;
+}
+
+
+sal_Int32 SAL_CALL OResultSet::getInt( sal_Int32 /*columnIndex*/ )
+{
+ return 0;
+}
+
+
+sal_Int32 SAL_CALL OResultSet::getRow( )
+{
+ ResultSetEntryGuard aGuard( *this );
+
+ SAL_INFO("connectivity.mork", "return = " << m_nRowPos);
+ return m_nRowPos;
+}
+
+
+sal_Int64 SAL_CALL OResultSet::getLong( sal_Int32 /*columnIndex*/ )
+{
+ return sal_Int64();
+}
+
+
+Reference< XResultSetMetaData > SAL_CALL OResultSet::getMetaData( )
+{
+ ResultSetEntryGuard aGuard( *this );
+
+ if(!m_xMetaData.is())
+ m_xMetaData = new OResultSetMetaData(
+ m_pSQLIterator->getSelectColumns(), m_pSQLIterator->getTables().begin()->first, m_xTable.get(), determineReadOnly());
+ return m_xMetaData;
+}
+
+Reference< XArray > SAL_CALL OResultSet::getArray( sal_Int32 /*columnIndex*/ )
+{
+ return nullptr;
+}
+
+
+Reference< XClob > SAL_CALL OResultSet::getClob( sal_Int32 /*columnIndex*/ )
+{
+ return nullptr;
+}
+
+Reference< XBlob > SAL_CALL OResultSet::getBlob( sal_Int32 /*columnIndex*/ )
+{
+ return nullptr;
+}
+
+
+Reference< XRef > SAL_CALL OResultSet::getRef( sal_Int32 /*columnIndex*/ )
+{
+ return nullptr;
+}
+
+
+Any SAL_CALL OResultSet::getObject( sal_Int32 /*columnIndex*/, const Reference< css::container::XNameAccess >& /*typeMap*/ )
+{
+ return Any();
+}
+
+
+sal_Int16 SAL_CALL OResultSet::getShort( sal_Int32 /*columnIndex*/ )
+{
+ return 0;
+}
+
+
+void OResultSet::checkIndex(sal_Int32 columnIndex )
+{
+ if(columnIndex <= 0 || columnIndex > static_cast<sal_Int32>(m_xColumns->size()))
+ ::dbtools::throwInvalidIndexException(*this);
+}
+
+sal_uInt32 OResultSet::currentRowCount()
+{
+ if ( m_bIsAlwaysFalseQuery )
+ return 0;
+ //return 0;//m_aQuery.getRealRowCount() - deletedCount();
+ // new implementation
+ return m_aQueryHelper.getResultCount();
+}
+
+
+bool OResultSet::fetchCurrentRow( )
+{
+ SAL_INFO("connectivity.mork", "m_nRowPos = " << m_nRowPos);
+ return fetchRow(getCurrentCardNumber());
+}
+
+
+bool OResultSet::fetchRow(sal_Int32 cardNumber,bool bForceReload)
+{
+ SAL_INFO("connectivity.mork", "cardNumber = " << cardNumber);
+ if (!bForceReload)
+ {
+ // Check whether we've already fetched the row...
+ if ( !(*m_aRow)[0].isNull() && static_cast<sal_Int32>((*m_aRow)[0]) == cardNumber )
+ return true;
+ }
+// else
+// m_aQuery.resyncRow(cardNumber);
+
+ if ( !validRow( cardNumber ) )
+ return false;
+
+ (*m_aRow)[0] = cardNumber;
+ sal_Int32 nCount = m_aColumnNames.getLength();
+ //m_RowStates = m_aQuery.getRowStates(cardNumber);
+ for( sal_Int32 i = 1; i <= nCount; i++ )
+ {
+ if ( (*m_aRow)[i].isBound() )
+ {
+
+ // Everything in the addressbook is a string!
+
+ if ( !m_aQueryHelper.getRowValue( (*m_aRow)[i], cardNumber, m_aColumnNames[i-1], DataType::VARCHAR ))
+ {
+ m_pStatement->getOwnConnection()->throwSQLException( m_aQueryHelper.getError(), *this );
+ }
+ }
+ }
+ return true;
+
+}
+
+
+const ORowSetValue& OResultSet::getValue(sal_Int32 cardNumber, sal_Int32 columnIndex )
+{
+ if ( !fetchRow( cardNumber ) )
+ {
+ OSL_FAIL("fetchRow() returned False" );
+ m_bWasNull = true;
+ return *ODatabaseMetaDataResultSet::getEmptyValue();
+ }
+
+ m_bWasNull = (*m_aRow)[columnIndex].isNull();
+ return (*m_aRow)[columnIndex];
+
+}
+
+
+OUString SAL_CALL OResultSet::getString( sal_Int32 columnIndex )
+{
+ ResultSetEntryGuard aGuard( *this );
+
+ OSL_ENSURE(m_xColumns.is(), "Need the Columns!!");
+ OSL_ENSURE(columnIndex <= static_cast<sal_Int32>(m_xColumns->size()), "Trying to access invalid columns number");
+ checkIndex( columnIndex );
+
+ // If this query was sorted then we should have a valid KeySet, so use it
+ return getValue(getCurrentCardNumber(), mapColumn( columnIndex ) );
+
+}
+
+
+Time SAL_CALL OResultSet::getTime( sal_Int32 /*columnIndex*/ )
+{
+ ResultSetEntryGuard aGuard( *this );
+ return Time();
+}
+
+
+DateTime SAL_CALL OResultSet::getTimestamp( sal_Int32 /*columnIndex*/ )
+{
+ ResultSetEntryGuard aGuard( *this );
+ return DateTime();
+}
+
+
+sal_Bool SAL_CALL OResultSet::isBeforeFirst( )
+{
+ ResultSetEntryGuard aGuard( *this );
+
+ // here you have to implement your movements
+ // return true means there is no data
+ return( m_nRowPos < 1 );
+}
+
+sal_Bool SAL_CALL OResultSet::isAfterLast( )
+{
+ SAL_WARN("connectivity.mork", "OResultSet::isAfterLast() NOT IMPLEMENTED!");
+ ResultSetEntryGuard aGuard( *this );
+
+ return m_nRowPos > currentRowCount();
+}
+
+sal_Bool SAL_CALL OResultSet::isFirst( )
+{
+ ResultSetEntryGuard aGuard( *this );
+
+ return m_nRowPos == 1;
+}
+
+sal_Bool SAL_CALL OResultSet::isLast( )
+{
+ SAL_WARN("connectivity.mork", "OResultSet::isLast() NOT IMPLEMENTED!");
+ ResultSetEntryGuard aGuard( *this );
+
+// return sal_True;
+ return m_nRowPos == currentRowCount();
+}
+
+void SAL_CALL OResultSet::beforeFirst( )
+{
+ ResultSetEntryGuard aGuard( *this );
+
+ // move before the first row so that isBeforeFirst returns false
+ if ( first() )
+ previous();
+}
+
+void SAL_CALL OResultSet::afterLast( )
+{
+ ResultSetEntryGuard aGuard( *this );
+
+ if(last())
+ next();
+}
+
+
+void SAL_CALL OResultSet::close()
+{
+ dispose();
+}
+
+
+sal_Bool SAL_CALL OResultSet::first( )
+{
+ return seekRow( FIRST_POS );
+}
+
+
+sal_Bool SAL_CALL OResultSet::last( )
+{
+ return seekRow( LAST_POS );
+}
+
+sal_Bool SAL_CALL OResultSet::absolute( sal_Int32 row )
+{
+ return seekRow( ABSOLUTE_POS, row );
+}
+
+sal_Bool SAL_CALL OResultSet::relative( sal_Int32 row )
+{
+ return seekRow( RELATIVE_POS, row );
+}
+
+sal_Bool SAL_CALL OResultSet::previous( )
+{
+ ResultSetEntryGuard aGuard( *this );
+ return seekRow( PRIOR_POS );
+}
+
+Reference< XInterface > SAL_CALL OResultSet::getStatement( )
+{
+ ResultSetEntryGuard aGuard( *this );
+ return m_xStatement;
+}
+
+
+sal_Bool SAL_CALL OResultSet::rowDeleted( )
+{
+ SAL_WARN("connectivity.mork", "OResultSet::rowDeleted() NOT IMPLEMENTED!");
+ ResultSetEntryGuard aGuard( *this );
+ return true;//return ((m_RowStates & RowStates_Deleted) == RowStates_Deleted) ;
+}
+
+sal_Bool SAL_CALL OResultSet::rowInserted( )
+{
+ SAL_WARN("connectivity.mork", "OResultSet::rowInserted() NOT IMPLEMENTED!");
+ ResultSetEntryGuard aGuard( *this );
+ return true;//return ((m_RowStates & RowStates_Inserted) == RowStates_Inserted);
+}
+
+sal_Bool SAL_CALL OResultSet::rowUpdated( )
+{
+ SAL_WARN("connectivity.mork", "OResultSet::rowUpdated() NOT IMPLEMENTED!");
+ ResultSetEntryGuard aGuard( *this );
+ return true;// return ((m_RowStates & RowStates_Updated) == RowStates_Updated) ;
+}
+
+
+sal_Bool SAL_CALL OResultSet::next( )
+{
+ return seekRow( NEXT_POS );
+}
+
+
+sal_Bool SAL_CALL OResultSet::wasNull( )
+{
+ ResultSetEntryGuard aGuard( *this );
+
+ return m_bWasNull;
+}
+
+
+void SAL_CALL OResultSet::cancel( )
+{
+}
+
+void SAL_CALL OResultSet::clearWarnings( )
+{
+}
+
+Any SAL_CALL OResultSet::getWarnings( )
+{
+ return Any();
+}
+
+void SAL_CALL OResultSet::refreshRow( )
+{
+ if (fetchRow(getCurrentCardNumber(),true)) {
+ //force fetch current row will cause we lose all change to the current row
+ m_pStatement->getOwnConnection()->throwSQLException( STR_ERROR_REFRESH_ROW, *this );
+ }
+}
+
+IPropertyArrayHelper* OResultSet::createArrayHelper( ) const
+{
+ Sequence< Property > aProps(5);
+ Property* pProperties = aProps.getArray();
+ sal_Int32 nPos = 0;
+ pProperties[nPos++] = css::beans::Property(::connectivity::OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_FETCHDIRECTION),
+ PROPERTY_ID_FETCHDIRECTION, cppu::UnoType<sal_Int32>::get(), 0);
+
+ pProperties[nPos++] = css::beans::Property(::connectivity::OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_FETCHSIZE),
+ PROPERTY_ID_FETCHSIZE, cppu::UnoType<sal_Int32>::get(), 0);
+
+ pProperties[nPos++] = css::beans::Property(::connectivity::OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_ISBOOKMARKABLE),
+ PROPERTY_ID_ISBOOKMARKABLE, cppu::UnoType<bool>::get(), PropertyAttribute::READONLY);
+
+ pProperties[nPos++] = css::beans::Property(::connectivity::OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_RESULTSETCONCURRENCY),
+ PROPERTY_ID_RESULTSETCONCURRENCY, cppu::UnoType<sal_Int32>::get(), PropertyAttribute::READONLY);
+
+ pProperties[nPos++] = css::beans::Property(::connectivity::OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_RESULTSETTYPE),
+ PROPERTY_ID_RESULTSETTYPE, cppu::UnoType<sal_Int32>::get(), PropertyAttribute::READONLY);
+
+ return new OPropertyArrayHelper(aProps);
+}
+
+IPropertyArrayHelper & OResultSet::getInfoHelper()
+{
+ return *getArrayHelper();
+}
+
+sal_Bool OResultSet::convertFastPropertyValue(
+ Any & /*rConvertedValue*/,
+ Any & /*rOldValue*/,
+ sal_Int32 nHandle,
+ const Any& /*rValue*/ )
+{
+ OSL_FAIL( "OResultSet::convertFastPropertyValue: not implemented!" );
+ switch(nHandle)
+ {
+ case PROPERTY_ID_ISBOOKMARKABLE:
+ case PROPERTY_ID_RESULTSETCONCURRENCY:
+ case PROPERTY_ID_RESULTSETTYPE:
+ throw css::lang::IllegalArgumentException();
+ case PROPERTY_ID_FETCHDIRECTION:
+ case PROPERTY_ID_FETCHSIZE:
+ default:
+ ;
+ }
+ return false;
+}
+
+void OResultSet::setFastPropertyValue_NoBroadcast(
+ sal_Int32 nHandle,
+ const Any& /*rValue*/
+ )
+{
+ OSL_FAIL( "OResultSet::setFastPropertyValue_NoBroadcast: not implemented!" );
+ switch(nHandle)
+ {
+ case PROPERTY_ID_ISBOOKMARKABLE:
+ case PROPERTY_ID_RESULTSETCONCURRENCY:
+ case PROPERTY_ID_RESULTSETTYPE:
+ throw Exception("cannot set prop " + OUString::number(nHandle), nullptr);
+ case PROPERTY_ID_FETCHDIRECTION:
+ break;
+ case PROPERTY_ID_FETCHSIZE:
+ break;
+ default:
+ ;
+ }
+}
+
+void OResultSet::getFastPropertyValue(
+ Any& rValue,
+ sal_Int32 nHandle
+ ) const
+{
+ switch(nHandle)
+ {
+ case PROPERTY_ID_RESULTSETCONCURRENCY:
+ rValue <<= sal_Int32(ResultSetConcurrency::UPDATABLE);
+ break;
+ case PROPERTY_ID_RESULTSETTYPE:
+ rValue <<= m_nResultSetType;
+ break;
+ case PROPERTY_ID_FETCHDIRECTION:
+ rValue <<= m_nFetchDirection;
+ break;
+ case PROPERTY_ID_FETCHSIZE:
+ rValue <<= sal_Int32(0);
+ break;
+ case PROPERTY_ID_ISBOOKMARKABLE:
+ const_cast< OResultSet* >( this )->determineReadOnly();
+ rValue <<= (m_bIsReadOnly == TRISTATE_FALSE);
+ break;
+ }
+}
+
+void SAL_CALL OResultSet::acquire() throw()
+{
+ OResultSet_BASE::acquire();
+}
+
+void SAL_CALL OResultSet::release() throw()
+{
+ OResultSet_BASE::release();
+}
+
+css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL OResultSet::getPropertySetInfo( )
+{
+ return ::cppu::OPropertySetHelper::createPropertySetInfo(getInfoHelper());
+}
+
+
+void OResultSet::parseParameter( const OSQLParseNode* pNode, OUString& rMatchString )
+{
+ OSL_ENSURE(pNode->count() > 0,"Error parsing parameter in Parse Tree");
+ OSQLParseNode *pMark = pNode->getChild(0);
+
+ // Initialize to empty string
+ rMatchString.clear();
+
+ OUString aParameterName;
+ if (SQL_ISPUNCTUATION(pMark,"?")) {
+ aParameterName = "?";
+ }
+ else if (SQL_ISPUNCTUATION(pMark,":")) {
+ aParameterName = pNode->getChild(1)->getTokenValue();
+ }
+ // XXX - Now we know name, what's value????
+ m_nParamIndex ++;
+ SAL_INFO(
+ "connectivity.mork",
+ "Parameter name [" << m_nParamIndex << "]: " << aParameterName);
+
+ if ( m_aParameterRow.is() ) {
+ OSL_ENSURE( m_nParamIndex < static_cast<sal_Int32>(m_aParameterRow->size()) + 1, "More parameters than values found" );
+ rMatchString = (*m_aParameterRow)[static_cast<sal_uInt16>(m_nParamIndex)];
+ SAL_INFO("connectivity.mork", "Prop Value: " << rMatchString);
+ }
+ else {
+ SAL_INFO("connectivity.mork", "Prop Value: Invalid ParameterRow!");
+ }
+}
+
+#define WILDCARD "%"
+#define ALT_WILDCARD "*"
+static const sal_Unicode MATCHCHAR = '_';
+
+void OResultSet::analyseWhereClause( const OSQLParseNode* parseTree,
+ MQueryExpression &queryExpression)
+{
+ OUString columnName;
+ MQueryOp::cond_type op( MQueryOp::Is );
+ OUString matchString;
+
+ if ( parseTree == nullptr )
+ return;
+
+ if ( m_pSQLIterator->getParseTree() != nullptr ) {
+ ::rtl::Reference<OSQLColumns> xColumns = m_pSQLIterator->getParameters();
+ if(xColumns.is())
+ {
+ OUString aColName, aParameterValue;
+ sal_Int32 i = 1;
+ for (auto const& column : *xColumns)
+ {
+ column->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_NAME)) >>= aColName;
+ SAL_INFO("connectivity.mork", "Prop Column Name: " << aColName);
+ if ( m_aParameterRow.is() ) {
+ aParameterValue = (*m_aParameterRow)[static_cast<sal_uInt16>(i)];
+ SAL_INFO("connectivity.mork", "Prop Value: " << aParameterValue);
+ }
+ else {
+ SAL_INFO("connectivity.mork", "Prop Value: Invalid ParameterRow!");
+ }
+ i++;
+ }
+ }
+
+ }
+
+ if ( SQL_ISRULE(parseTree,where_clause) )
+ {
+ // Reset Parameter Counter
+ resetParameters();
+ analyseWhereClause( parseTree->getChild( 1 ), queryExpression );
+ }
+ else if ( parseTree->count() == 3 && // Handle ()'s
+ SQL_ISPUNCTUATION(parseTree->getChild(0),"(") &&
+ SQL_ISPUNCTUATION(parseTree->getChild(2),")"))
+ {
+ MQueryExpression *subExpression = new MQueryExpression();
+ analyseWhereClause( parseTree->getChild( 1 ), *subExpression );
+ queryExpression.addExpression( subExpression );
+ }
+ else if ((SQL_ISRULE(parseTree,search_condition) || SQL_ISRULE(parseTree,boolean_term))
+ && parseTree->count() == 3) // Handle AND/OR
+ {
+ // TODO - Need to take care or AND, for now match is always OR
+ analyseWhereClause( parseTree->getChild( 0 ), queryExpression );
+ analyseWhereClause( parseTree->getChild( 2 ), queryExpression );
+
+ if (SQL_ISTOKEN(parseTree->getChild(1),OR)) { // OR-Operator
+ queryExpression.setExpressionCondition( MQueryExpression::OR );
+ }
+ else if (SQL_ISTOKEN(parseTree->getChild(1),AND)) { // AND-Operator
+ queryExpression.setExpressionCondition( MQueryExpression::AND );
+ }
+ else {
+ OSL_FAIL("analyseSQL: Error in Parse Tree");
+ }
+ }
+ else if (SQL_ISRULE(parseTree,comparison_predicate))
+ {
+ OSL_ENSURE(parseTree->count() == 3, "Error parsing COMPARE predicate");
+ if (!(SQL_ISRULE(parseTree->getChild(0),column_ref) ||
+ parseTree->getChild(2)->getNodeType() == SQLNodeType::String ||
+ parseTree->getChild(2)->getNodeType() == SQLNodeType::IntNum ||
+ parseTree->getChild(2)->getNodeType() == SQLNodeType::ApproxNum ||
+ SQL_ISTOKEN(parseTree->getChild(2),TRUE) ||
+ SQL_ISTOKEN(parseTree->getChild(2),FALSE) ||
+ SQL_ISRULE(parseTree->getChild(2),parameter) ||
+ // odbc date
+ (SQL_ISRULE(parseTree->getChild(2),set_fct_spec) && SQL_ISPUNCTUATION(parseTree->getChild(2)->getChild(0),"{"))))
+ {
+ m_pStatement->getOwnConnection()->throwSQLException( STR_QUERY_TOO_COMPLEX, *this );
+ }
+
+ OSQLParseNode *pPrec = parseTree->getChild(1);
+ if (pPrec->getNodeType() == SQLNodeType::Equal)
+ op = MQueryOp::Is;
+ else if (pPrec->getNodeType() == SQLNodeType::NotEqual)
+ op = MQueryOp::IsNot;
+
+ OUString sTableRange;
+ if(SQL_ISRULE(parseTree->getChild(0),column_ref))
+ m_pSQLIterator->getColumnRange(parseTree->getChild(0),columnName,sTableRange);
+ else if(parseTree->getChild(0)->isToken())
+ columnName = parseTree->getChild(0)->getTokenValue();
+
+ if ( SQL_ISRULE(parseTree->getChild(2),parameter) ) {
+ parseParameter( parseTree->getChild(2), matchString );
+ }
+ else {
+ matchString = parseTree->getChild(2)->getTokenValue();
+ }
+
+ if ( columnName == "0" && op == MQueryOp::Is && matchString == "1" ) {
+ m_bIsAlwaysFalseQuery = true;
+ }
+ queryExpression.addExpression( new MQueryExpressionString( columnName, op, matchString ));
+ }
+ else if (SQL_ISRULE(parseTree,like_predicate))
+ {
+ OSL_ENSURE(parseTree->count() == 2, "Error parsing LIKE predicate");
+
+ if ( !SQL_ISRULE(parseTree->getChild(0), column_ref) )
+ {
+ m_pStatement->getOwnConnection()->throwSQLException( STR_QUERY_INVALID_LIKE_COLUMN, *this );
+ }
+
+
+ OSQLParseNode *pColumn;
+ OSQLParseNode *pAtom;
+ OSQLParseNode *pOptEscape;
+ const OSQLParseNode* pPart2 = parseTree->getChild(1);
+ pColumn = parseTree->getChild(0); // Match Item
+ pAtom = pPart2->getChild(static_cast<sal_uInt32>(pPart2->count()-2)); // Match String
+ pOptEscape = pPart2->getChild(static_cast<sal_uInt32>(pPart2->count()-1)); // Opt Escape Rule
+ (void)pOptEscape;
+ const bool bNot = SQL_ISTOKEN(pPart2->getChild(0), NOT);
+
+ if (!(pAtom->getNodeType() == SQLNodeType::String ||
+ pAtom->getNodeType() == SQLNodeType::Name ||
+ SQL_ISRULE(pAtom,parameter) ||
+ ( pAtom->getChild(0) && pAtom->getChild(0)->getNodeType() == SQLNodeType::Name ) ||
+ ( pAtom->getChild(0) && pAtom->getChild(0)->getNodeType() == SQLNodeType::String )
+ ) )
+ {
+ m_pStatement->getOwnConnection()->throwSQLException( STR_QUERY_INVALID_LIKE_STRING, *this );
+ }
+
+ OUString sTableRange;
+ if(SQL_ISRULE(pColumn,column_ref))
+ m_pSQLIterator->getColumnRange(pColumn,columnName,sTableRange);
+
+ SAL_INFO("connectivity.mork", "ColumnName = " << columnName);
+
+ if ( SQL_ISRULE(pAtom,parameter) ) {
+ parseParameter( pAtom, matchString );
+ // Replace all '*' with '%' : UI Usually does this but not with
+ // Parameters for some reason.
+ matchString = matchString.replaceAll( ALT_WILDCARD, WILDCARD );
+ }
+ else
+ {
+ matchString = pAtom->getTokenValue();
+ }
+
+ // Determine where '%' character is...
+
+ if ( matchString == WILDCARD )
+ {
+ // String containing only a '%' and nothing else
+ op = MQueryOp::Exists;
+ // Will be ignored for Exists case, but clear anyway.
+ matchString.clear();
+ }
+ else if ( matchString.indexOf ( WILDCARD ) == -1 &&
+ matchString.indexOf ( MATCHCHAR ) == -1 )
+ {
+ // Simple string , eg. "to match"
+ if ( bNot )
+ op = MQueryOp::DoesNotContain;
+ else
+ op = MQueryOp::Contains;
+ }
+ else if ( matchString.startsWith( WILDCARD )
+ && matchString.endsWith( WILDCARD )
+ && matchString.indexOf ( WILDCARD, 1 ) == matchString.lastIndexOf ( WILDCARD )
+ && matchString.indexOf( MATCHCHAR ) == -1
+ )
+ {
+ // Relatively simple "%string%" - ie, contains...
+ // Cut '%' from front and rear
+ matchString = matchString.replaceAt( 0, 1, OUString() );
+ matchString = matchString.replaceAt( matchString.getLength() -1 , 1, OUString() );
+
+ if (bNot)
+ op = MQueryOp::DoesNotContain;
+ else
+ op = MQueryOp::Contains;
+ }
+ else if ( bNot )
+ {
+ // We currently can't handle a 'NOT LIKE' when there are '%' or
+ // '_' dispersed throughout
+ m_pStatement->getOwnConnection()->throwSQLException( STR_QUERY_NOT_LIKE_TOO_COMPLEX, *this );
+ }
+ else
+ {
+ if ( (matchString.indexOf ( WILDCARD ) == matchString.lastIndexOf ( WILDCARD ))
+ && matchString.indexOf( MATCHCHAR ) == -1
+ )
+ {
+ // One occurrence of '%' - no '_' matches...
+ if ( matchString.startsWith( WILDCARD ) )
+ {
+ op = MQueryOp::EndsWith;
+ matchString = matchString.replaceAt( 0, 1, OUString());
+ }
+ else if ( matchString.indexOf ( WILDCARD ) == matchString.getLength() -1 )
+ {
+ op = MQueryOp::BeginsWith;
+ matchString = matchString.replaceAt( matchString.getLength() -1 , 1, OUString() );
+ }
+ else
+ {
+ sal_Int32 pos = matchString.indexOf ( WILDCARD );
+ matchString = matchString.replaceAt( pos, 1, ".*" );
+ op = MQueryOp::RegExp;
+ }
+
+ }
+ else
+ {
+ // Most Complex, need to use a RE
+ sal_Int32 pos;
+ while ( (pos = matchString.indexOf ( WILDCARD )) != -1 )
+ {
+ matchString = matchString.replaceAt( pos, 1, ".*" );
+ }
+
+ while ( (pos = matchString.indexOf( MATCHCHAR )) != -1 )
+ {
+ matchString = matchString.replaceAt( pos, 1, "." );
+ }
+
+ op = MQueryOp::RegExp;
+ }
+ }
+
+ queryExpression.addExpression( new MQueryExpressionString( columnName, op, matchString ));
+ }
+ else if (SQL_ISRULE(parseTree,test_for_null))
+ {
+ OSL_ENSURE(parseTree->count() == 2,"Error in ParseTree");
+ const OSQLParseNode* pPart2 = parseTree->getChild(1);
+ OSL_ENSURE(SQL_ISTOKEN(pPart2->getChild(0),IS),"Error in ParseTree");
+
+ if (!SQL_ISRULE(parseTree->getChild(0),column_ref))
+ {
+ m_pStatement->getOwnConnection()->throwSQLException( STR_QUERY_INVALID_IS_NULL_COLUMN, *this );
+ }
+
+ if (SQL_ISTOKEN(pPart2->getChild(1),NOT))
+ {
+ op = MQueryOp::Exists;
+ }
+ else
+ {
+ op = MQueryOp::DoesNotExist;
+ }
+
+ OUString sTableRange;
+ m_pSQLIterator->getColumnRange(parseTree->getChild(0),columnName,sTableRange);
+
+ queryExpression.addExpression( new MQueryExpressionString( columnName, op ));
+ }
+ else
+ {
+ SAL_WARN("connectivity.mork", "Unexpected statement!!!" );
+ m_pStatement->getOwnConnection()->throwSQLException( STR_QUERY_TOO_COMPLEX, *this );
+ }
+}
+
+void OResultSet::fillRowData()
+{
+ OSL_ENSURE( m_pStatement, "Require a statement" );
+
+ MQueryExpression queryExpression;
+
+ OConnection* pConnection = static_cast<OConnection*>(m_pStatement->getConnection().get());
+ m_xColumns = m_pSQLIterator->getSelectColumns();
+
+ OSL_ENSURE(m_xColumns.is(), "Need the Columns!!");
+
+ const OUString sPropertyName = OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_NAME);
+ OUString sName;
+ sal_Int32 i = 1;
+ for (const auto& rxColumn : *m_xColumns)
+ {
+ rxColumn->getPropertyValue(sPropertyName) >>= sName;
+ SAL_INFO(
+ "connectivity.mork", "Query Columns : (" << i << ") " << sName);
+ i++;
+ }
+
+ // Generate Match Conditions for Query
+ const OSQLParseNode* pParseTree = m_pSQLIterator->getWhereTree();
+
+ m_bIsAlwaysFalseQuery = false;
+ if ( pParseTree != nullptr )
+ {
+ // Extract required info
+
+ analyseWhereClause( pParseTree, queryExpression );
+ }
+ // If the query is a 0=1 then set Row count to 0 and return
+ if ( m_bIsAlwaysFalseQuery )
+ {
+ m_bIsReadOnly = TRISTATE_TRUE;
+ return;
+ }
+
+ OUString aStr( m_xTable->getName() );
+ m_aQueryHelper.setAddressbook( aStr );
+
+ sal_Int32 rv = m_aQueryHelper.executeQuery(pConnection, queryExpression);
+ if ( rv == -1 ) {
+ m_pStatement->getOwnConnection()->throwSQLException( STR_ERR_EXECUTING_QUERY, *this );
+ }
+
+ if (m_aQueryHelper.hadError())
+ {
+ m_pStatement->getOwnConnection()->throwSQLException( m_aQueryHelper.getError(), *this );
+ }
+
+ //determine whether the address book is readonly
+ determineReadOnly();
+
+ SAL_INFO("connectivity.mork", "executeQuery returned " << rv);
+}
+
+
+static bool matchRow( OValueRow const & row1, OValueRow const & row2 )
+{
+ // the first column is the bookmark column
+ return std::equal(std::next(row1->begin()), row1->end(), std::next(row2->begin()),
+ [](const ORowSetValue& a, const ORowSetValue& b) { return !a.isBound() || a == b; });
+}
+
+sal_Int32 OResultSet::getRowForCardNumber(sal_Int32 nCardNum)
+{
+ SAL_INFO("connectivity.mork", "nCardNum = " << nCardNum);
+
+ if ( m_pKeySet.is() )
+ {
+ sal_Int32 nPos;
+ for(nPos=0;nPos < static_cast<sal_Int32>(m_pKeySet->size());nPos++)
+ {
+ if (nCardNum == (*m_pKeySet)[nPos])
+ {
+ SAL_INFO("connectivity.mork", "return = " << nPos+1);
+ return nPos+1;
+ }
+ }
+ }
+
+ m_pStatement->getOwnConnection()->throwSQLException( STR_INVALID_BOOKMARK, *this );
+
+ return 0;
+}
+
+void OResultSet::executeQuery()
+{
+ ResultSetEntryGuard aGuard( *this );
+
+ OSL_ENSURE( m_xTable.is(), "Need a Table object");
+ if(!m_xTable.is())
+ {
+ const OSQLTables& rTabs = m_pSQLIterator->getTables();
+ if (rTabs.empty() || !rTabs.begin()->second.is())
+ m_pStatement->getOwnConnection()->throwSQLException( STR_QUERY_TOO_COMPLEX, *this );
+
+ m_xTable = static_cast< OTable* > (rTabs.begin()->second.get());
+ }
+
+ m_nRowPos = 0;
+
+ fillRowData();
+
+ OSL_ENSURE(m_xColumns.is(), "Need the Columns!!");
+
+ switch( m_pSQLIterator->getStatementType() )
+ {
+ case OSQLStatementType::Select:
+ {
+ if(m_bIsAlwaysFalseQuery) {
+ break;
+ }
+ else if(isCount())
+ {
+ m_pStatement->getOwnConnection()->throwSQLException( STR_NO_COUNT_SUPPORT, *this );
+ }
+ else
+ {
+ bool bDistinct = false;
+ OSQLParseNode *pDistinct = m_pParseTree->getChild(1);
+ if (pDistinct && pDistinct->getTokenID() == SQL_TOKEN_DISTINCT)
+ {
+ if(!IsSorted())
+ {
+ m_aOrderbyColumnNumber.push_back(m_aColMapping[1]);
+ m_aOrderbyAscending.push_back(TAscendingOrder::DESC);
+ }
+ bDistinct = true;
+ }
+
+ OSortIndex::TKeyTypeVector eKeyType(m_aOrderbyColumnNumber.size());
+ std::vector<sal_Int16>::size_type index = 0;
+ for (const auto& rColIndex : m_aOrderbyColumnNumber)
+ {
+ OSL_ENSURE(static_cast<sal_Int32>(m_aRow->size()) > rColIndex,"Invalid Index");
+ switch ((m_aRow->begin()+rColIndex)->getTypeKind())
+ {
+ case DataType::CHAR:
+ case DataType::VARCHAR:
+ eKeyType[index] = OKeyType::String;
+ break;
+
+ case DataType::OTHER:
+ case DataType::TINYINT:
+ case DataType::SMALLINT:
+ case DataType::INTEGER:
+ case DataType::DECIMAL:
+ case DataType::NUMERIC:
+ case DataType::REAL:
+ case DataType::DOUBLE:
+ case DataType::DATE:
+ case DataType::TIME:
+ case DataType::TIMESTAMP:
+ case DataType::BIT:
+ eKeyType[index] = OKeyType::Double;
+ break;
+
+ // Other types aren't implemented (so they are always FALSE)
+ default:
+ eKeyType[index] = OKeyType::NONE;
+ OSL_FAIL("MResultSet::executeQuery: Order By Data Type not implemented");
+ break;
+ }
+ ++index;
+ }
+
+ if (IsSorted())
+ {
+ // Implement Sorting
+
+ // So that we can sort we need to wait until the executed
+ // query to the mozilla addressbooks has returned all
+ // values.
+
+ OSortIndex aSortIndex(eKeyType,m_aOrderbyAscending);
+
+#if OSL_DEBUG_LEVEL > 0
+ for ( std::vector<sal_Int32>::size_type i = 0; i < m_aColMapping.size(); i++ )
+ SAL_INFO(
+ "connectivity.mork",
+ "Mapped: " << i << " -> " << m_aColMapping[i]);
+#endif
+ for ( sal_Int32 nRow = 1; nRow <= m_aQueryHelper.getResultCount(); nRow++ ) {
+
+ std::unique_ptr<OKeyValue> pKeyValue = OKeyValue::createKeyValue(nRow);
+
+ for (const auto& rColIndex : m_aOrderbyColumnNumber)
+ {
+ const ORowSetValue& value = getValue(nRow, rColIndex);
+
+ SAL_INFO(
+ "connectivity.mork",
+ "Adding Value: (" << nRow << "," << rColIndex
+ << ") : " << value.getString());
+
+ pKeyValue->pushKey(new ORowSetValueDecorator(value));
+ }
+
+ aSortIndex.AddKeyValue( std::move(pKeyValue) );
+ }
+
+ m_pKeySet = aSortIndex.CreateKeySet();
+ m_CurrentRowCount = static_cast<sal_Int32>(m_pKeySet->size());
+#if OSL_DEBUG_LEVEL > 0
+ for( OKeySet::size_type i = 0; i < m_pKeySet->size(); i++ )
+ SAL_INFO(
+ "connectivity.mork",
+ "Sorted: " << i << " -> " << (*m_pKeySet)[i]);
+#endif
+
+ beforeFirst(); // Go back to start
+ }
+ else //we always need m_pKeySet now
+ m_pKeySet = new OKeySet();
+
+ // Handle the DISTINCT case
+ if ( bDistinct && m_pKeySet.is() )
+ {
+ OValueRow aSearchRow = new OValueVector( m_aRow->size() );
+
+ for(sal_Int32 & i : *m_pKeySet)
+ {
+ fetchRow( i ); // Fills m_aRow
+ if ( matchRow( m_aRow, aSearchRow ) )
+ {
+ i = 0; // Marker for later to be removed
+ }
+ else
+ {
+ // They don't match, so it's not a duplicate.
+ // Use the current Row as the next one to match against
+ *aSearchRow = *m_aRow;
+ }
+ }
+ // Now remove any keys marked with a 0
+ m_pKeySet->erase(std::remove_if(m_pKeySet->begin(),m_pKeySet->end()
+ ,[](sal_Int32 n) { return n == 0; })
+ ,m_pKeySet->end());
+
+ }
+ }
+ } break;
+
+ case OSQLStatementType::Update:
+ case OSQLStatementType::Delete:
+ case OSQLStatementType::Insert:
+ break;
+ default:
+ m_pStatement->getOwnConnection()->throwSQLException( STR_STMT_TYPE_NOT_SUPPORTED, *this );
+ break;
+ }
+}
+
+void OResultSet::setBoundedColumns(const OValueRow& _rRow,
+ const ::rtl::Reference<connectivity::OSQLColumns>& _rxColumns,
+ const Reference<XIndexAccess>& _xNames,
+ bool _bSetColumnMapping,
+ const Reference<XDatabaseMetaData>& _xMetaData,
+ std::vector<sal_Int32>& _rColMapping)
+{
+ ::comphelper::UStringMixEqual aCase(_xMetaData->supportsMixedCaseQuotedIdentifiers());
+
+ Reference<XPropertySet> xTableColumn;
+ OUString sTableColumnName, sSelectColumnRealName;
+
+ const OUString sName = OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_NAME);
+ const OUString sRealName = OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_REALNAME);
+
+ std::vector< OUString> aColumnNames;
+ aColumnNames.reserve(_rxColumns->size());
+ OValueVector::iterator aRowIter = _rRow->begin()+1;
+ for (sal_Int32 i=0; // the first column is the bookmark column
+ aRowIter != _rRow->end();
+ ++i, ++aRowIter
+ )
+ {
+ try
+ {
+ // get the table column and its name
+ _xNames->getByIndex(i) >>= xTableColumn;
+ OSL_ENSURE(xTableColumn.is(), "OResultSet::setBoundedColumns: invalid table column!");
+ if (xTableColumn.is())
+ xTableColumn->getPropertyValue(sName) >>= sTableColumnName;
+ else
+ sTableColumnName.clear();
+
+ // look if we have such a select column
+ // TODO: would like to have a O(log n) search here ...
+ sal_Int32 nColumnPos = 0;
+ for (const auto& rxColumn : *_rxColumns)
+ {
+ if ( nColumnPos < static_cast<sal_Int32>(aColumnNames.size()) )
+ sSelectColumnRealName = aColumnNames[nColumnPos];
+ else
+ {
+ if(rxColumn->getPropertySetInfo()->hasPropertyByName(sRealName))
+ rxColumn->getPropertyValue(sRealName) >>= sSelectColumnRealName;
+ else
+ rxColumn->getPropertyValue(sName) >>= sSelectColumnRealName;
+ aColumnNames.push_back(sSelectColumnRealName);
+ }
+
+ if (aCase(sTableColumnName, sSelectColumnRealName))
+ {
+ if(_bSetColumnMapping)
+ {
+ sal_Int32 nSelectColumnPos = nColumnPos + 1;
+ // the getXXX methods are 1-based ...
+ sal_Int32 nTableColumnPos = i + 1;
+ // get first table column is the bookmark column
+
+ SAL_INFO(
+ "connectivity.mork",
+ "Set Col Mapping: " << nSelectColumnPos << " -> "
+ << nTableColumnPos);
+ _rColMapping[nSelectColumnPos] = nTableColumnPos;
+ }
+
+ aRowIter->setBound(true);
+ aRowIter->setTypeKind(DataType::VARCHAR);
+ }
+
+ ++nColumnPos;
+ }
+ }
+ catch (Exception&)
+ {
+ OSL_FAIL("OResultSet::setBoundedColumns: caught an Exception!");
+ }
+ }
+}
+
+
+bool OResultSet::isCount() const
+{
+ return (m_pParseTree &&
+ m_pParseTree->count() > 2 &&
+ SQL_ISRULE(m_pParseTree->getChild(2),scalar_exp_commalist) &&
+ SQL_ISRULE(m_pParseTree->getChild(2)->getChild(0),derived_column) &&
+ SQL_ISRULE(m_pParseTree->getChild(2)->getChild(0)->getChild(0),general_set_fct) &&
+ m_pParseTree->getChild(2)->getChild(0)->getChild(0)->count() == 4
+ );
+}
+
+
+// Check for valid row in m_aQuery
+
+bool OResultSet::validRow( sal_uInt32 nRow)
+{
+ sal_Int32 nNumberOfRecords = m_aQueryHelper.getResultCount();
+
+ if (( nRow == 0 ) ||
+ ( nRow > o3tl::make_unsigned(nNumberOfRecords)) ){
+ SAL_INFO("connectivity.mork", "validRow(" << nRow << "): return False");
+ return false;
+ }
+ SAL_INFO("connectivity.mork", "validRow(" << nRow << "): return True");
+
+ return true;
+}
+
+void OResultSet::fillKeySet(sal_Int32 nMaxCardNumber)
+{
+ impl_ensureKeySet();
+ if (m_CurrentRowCount < nMaxCardNumber)
+ {
+ sal_Int32 nKeyValue;
+ if ( static_cast<sal_Int32>(m_pKeySet->capacity()) < nMaxCardNumber )
+ m_pKeySet->reserve(nMaxCardNumber + 20 );
+
+ for (nKeyValue = m_CurrentRowCount+1; nKeyValue <= nMaxCardNumber; nKeyValue ++)
+ m_pKeySet->push_back( nKeyValue );
+ m_CurrentRowCount = nMaxCardNumber;
+ }
+}
+
+sal_Int32 OResultSet::deletedCount()
+{
+ impl_ensureKeySet();
+ return m_CurrentRowCount - static_cast<sal_Int32>(m_pKeySet->size());
+
+}
+
+bool OResultSet::seekRow( eRowPosition pos, sal_Int32 nOffset )
+{
+ ResultSetEntryGuard aGuard( *this );
+ if ( !m_pKeySet.is() )
+ m_pStatement->getOwnConnection()->throwSQLException( STR_ILLEGAL_MOVEMENT, *this );
+
+ sal_Int32 nNumberOfRecords = m_aQueryHelper.getResultCount();
+ sal_Int32 nRetrievedRows = currentRowCount();
+ sal_Int32 nCurPos = m_nRowPos;
+
+ SAL_INFO("connectivity.mork", "nCurPos = " << nCurPos);
+ switch( pos ) {
+ case NEXT_POS:
+ nCurPos++;
+ break;
+ case PRIOR_POS:
+ if ( nCurPos > 0 )
+ nCurPos--;
+ break;
+ case FIRST_POS:
+ nCurPos = 1;
+ break;
+ case LAST_POS:
+ nCurPos = nRetrievedRows;
+ break;
+ case ABSOLUTE_POS:
+ nCurPos = nOffset;
+ break;
+ case RELATIVE_POS:
+ nCurPos += sal_uInt32( nOffset );
+ break;
+ }
+
+ if ( nCurPos <= 0 ) {
+ m_nRowPos = 0;
+ SAL_INFO(
+ "connectivity.mork", "return False, m_nRowPos = " << m_nRowPos);
+ return false;
+ }
+ sal_Int32 nCurCard;
+ if ( nCurPos < static_cast<sal_Int32>(m_pKeySet->size()) ) //The requested row is exist in m_pKeySet, so we just use it
+ {
+ nCurCard = (*m_pKeySet)[nCurPos-1];
+ }
+ else //The requested row has not been retrieved until now. We should get the right card for it.
+ nCurCard = nCurPos + deletedCount();
+
+ if ( nCurCard > nNumberOfRecords) {
+ fillKeySet(nNumberOfRecords);
+ m_nRowPos = static_cast<sal_uInt32>(m_pKeySet->size() + 1);
+ SAL_INFO(
+ "connectivity.mork", "return False, m_nRowPos = " << m_nRowPos);
+ return false;
+ }
+ //Insert new retrieved items for later use
+ fillKeySet(nNumberOfRecords);
+ m_nRowPos = static_cast<sal_uInt32>(nCurPos);
+ SAL_INFO("connectivity.mork", "return True, m_nRowPos = " << m_nRowPos);
+ fetchCurrentRow();
+ return true;
+}
+
+void OResultSet::setColumnMapping(const std::vector<sal_Int32>& _aColumnMapping)
+{
+ m_aColMapping = _aColumnMapping;
+#if OSL_DEBUG_LEVEL > 0
+ for ( size_t i = 0; i < m_aColMapping.size(); i++ )
+ SAL_INFO(
+ "connectivity.mork",
+ "Set Mapped: " << i << " -> " << m_aColMapping[i]);
+#endif
+}
+
+
+css::uno::Any OResultSet::getBookmark( )
+{
+ SAL_INFO("connectivity.mork", "m_nRowPos = " << m_nRowPos);
+ ResultSetEntryGuard aGuard( *this );
+ if ( !fetchCurrentRow() ) {
+ m_pStatement->getOwnConnection()->throwSQLException( STR_ERROR_GET_ROW, *this );
+ }
+
+ OSL_ENSURE((!m_aRow->isDeleted()),"getBookmark called for deleted row");
+ return makeAny(static_cast<sal_Int32>((*m_aRow)[0]));
+}
+sal_Bool OResultSet::moveToBookmark( const css::uno::Any& bookmark )
+{
+ ResultSetEntryGuard aGuard( *this );
+ SAL_INFO(
+ "connectivity.mork", "bookmark = " << comphelper::getINT32(bookmark));
+ sal_Int32 nCardNum = comphelper::getINT32(bookmark);
+ m_nRowPos = getRowForCardNumber(nCardNum);
+ fetchCurrentRow();
+ return true;
+}
+sal_Bool OResultSet::moveRelativeToBookmark( const css::uno::Any& bookmark, sal_Int32 rows )
+{
+ ResultSetEntryGuard aGuard( *this );
+ SAL_INFO(
+ "connectivity.mork",
+ "bookmark = " << comphelper::getINT32(bookmark) << " rows= " << rows);
+ sal_Int32 nCardNum = comphelper::getINT32(bookmark);
+ m_nRowPos = getRowForCardNumber(nCardNum);
+ return seekRow(RELATIVE_POS,rows );
+}
+sal_Int32 OResultSet::compareBookmarks( const css::uno::Any& lhs, const css::uno::Any& rhs )
+{
+ ResultSetEntryGuard aGuard( *this );
+ SAL_INFO("connectivity.mork", "m_nRowPos = " << m_nRowPos);
+ sal_Int32 nFirst=0;
+ sal_Int32 nSecond=0;
+ sal_Int32 nResult=0;
+
+ if ( !( lhs >>= nFirst ) || !( rhs >>= nSecond ) ) {
+ m_pStatement->getOwnConnection()->throwSQLException( STR_INVALID_BOOKMARK, *this );
+ }
+
+ if(nFirst < nSecond)
+ nResult = CompareBookmark::LESS;
+ else if(nFirst > nSecond)
+ nResult = CompareBookmark::GREATER;
+ else
+ nResult = CompareBookmark::EQUAL;
+
+ return nResult;
+}
+sal_Bool OResultSet::hasOrderedBookmarks( )
+{
+ ResultSetEntryGuard aGuard( *this );
+ SAL_INFO("connectivity.mork", "m_nRowPos = " << m_nRowPos);
+ return true;
+}
+sal_Int32 OResultSet::hashBookmark( const css::uno::Any& bookmark )
+{
+ ResultSetEntryGuard aGuard( *this );
+ SAL_INFO("connectivity.mork", "m_nRowPos = " << m_nRowPos);
+ return comphelper::getINT32(bookmark);
+}
+
+sal_Int32 OResultSet::getCurrentCardNumber()
+{
+ if ( ( m_nRowPos == 0 ) || !m_pKeySet.is() )
+ return 0;
+ if (m_pKeySet->size() < m_nRowPos)
+ return 0;
+ return (*m_pKeySet)[m_nRowPos-1];
+}
+void OResultSet::checkPendingUpdate()
+{
+ OSL_FAIL( "OResultSet::checkPendingUpdate() not implemented" );
+/*
+ const sal_Int32 nCurrentRow = getCurrentCardNumber();
+
+ if ((m_nNewRow && nCurrentRow != m_nNewRow)
+ || ( m_nUpdatedRow && m_nUpdatedRow != nCurrentRow))
+ {
+ const OUString sError( m_pStatement->getOwnConnection()->getResources().getResourceStringWithSubstitution(
+ STR_COMMIT_ROW,
+ "$position$", OUString::valueOf(nCurrentRow)
+ ) );
+ ::dbtools::throwGenericSQLException(sError,*this);
+ }
+*/
+
+}
+void OResultSet::updateValue(sal_Int32 columnIndex ,const ORowSetValue& x)
+{
+ SAL_INFO("connectivity.mork", "m_nRowPos = " << m_nRowPos);
+ ResultSetEntryGuard aGuard( *this );
+ if ( !fetchCurrentRow() ) {
+ m_pStatement->getOwnConnection()->throwSQLException( STR_ERROR_GET_ROW, *this );
+ }
+
+ checkPendingUpdate();
+
+ checkIndex(columnIndex );
+ columnIndex = mapColumn(columnIndex);
+
+ (*m_aRow)[columnIndex].setBound(true);
+ (*m_aRow)[columnIndex] = x;
+}
+
+
+void SAL_CALL OResultSet::updateNull( sal_Int32 columnIndex )
+{
+ SAL_INFO("connectivity.mork", "m_nRowPos = " << m_nRowPos);
+ ResultSetEntryGuard aGuard( *this );
+ if ( !fetchCurrentRow() )
+ m_pStatement->getOwnConnection()->throwSQLException( STR_ERROR_GET_ROW, *this );
+
+ checkPendingUpdate();
+ checkIndex(columnIndex );
+ columnIndex = mapColumn(columnIndex);
+
+ (*m_aRow)[columnIndex].setBound(true);
+ (*m_aRow)[columnIndex].setNull();
+}
+
+
+void SAL_CALL OResultSet::updateBoolean( sal_Int32 columnIndex, sal_Bool x )
+{
+ updateValue(columnIndex, static_cast<bool>(x));
+}
+
+void SAL_CALL OResultSet::updateByte( sal_Int32 columnIndex, sal_Int8 x )
+{
+ updateValue(columnIndex,x);
+}
+
+
+void SAL_CALL OResultSet::updateShort( sal_Int32 columnIndex, sal_Int16 x )
+{
+ updateValue(columnIndex,x);
+}
+
+void SAL_CALL OResultSet::updateInt( sal_Int32 columnIndex, sal_Int32 x )
+{
+ updateValue(columnIndex,x);
+}
+
+void SAL_CALL OResultSet::updateLong( sal_Int32 /*columnIndex*/, sal_Int64 /*x*/ )
+{
+ ::dbtools::throwFeatureNotImplementedSQLException( "XRowUpdate::updateLong", *this );
+}
+
+void SAL_CALL OResultSet::updateFloat( sal_Int32 columnIndex, float x )
+{
+ updateValue(columnIndex,x);
+}
+
+
+void SAL_CALL OResultSet::updateDouble( sal_Int32 columnIndex, double x )
+{
+ updateValue(columnIndex,x);
+}
+
+void SAL_CALL OResultSet::updateString( sal_Int32 columnIndex, const OUString& x )
+{
+ updateValue(columnIndex,x);
+}
+
+void SAL_CALL OResultSet::updateBytes( sal_Int32 columnIndex, const Sequence< sal_Int8 >& x )
+{
+ updateValue(columnIndex,x);
+}
+
+void SAL_CALL OResultSet::updateDate( sal_Int32 columnIndex, const css::util::Date& x )
+{
+ updateValue(columnIndex,x);
+}
+
+
+void SAL_CALL OResultSet::updateTime( sal_Int32 columnIndex, const css::util::Time& x )
+{
+ updateValue(columnIndex,x);
+}
+
+
+void SAL_CALL OResultSet::updateTimestamp( sal_Int32 columnIndex, const css::util::DateTime& x )
+{
+ updateValue(columnIndex,x);
+}
+
+
+void SAL_CALL OResultSet::updateBinaryStream( sal_Int32 columnIndex, const Reference< css::io::XInputStream >& x, sal_Int32 length )
+{
+ ResultSetEntryGuard aGuard( *this );
+
+ if(!x.is())
+ ::dbtools::throwFunctionSequenceException(*this);
+
+ Sequence<sal_Int8> aSeq;
+ x->readBytes(aSeq,length);
+ updateValue(columnIndex,aSeq);
+}
+
+void SAL_CALL OResultSet::updateCharacterStream( sal_Int32 columnIndex, const Reference< css::io::XInputStream >& x, sal_Int32 length )
+{
+ updateBinaryStream(columnIndex,x,length);
+}
+
+void SAL_CALL OResultSet::updateObject( sal_Int32 columnIndex, const Any& x )
+{
+ if (!::dbtools::implUpdateObject(this, columnIndex, x))
+ {
+ const OUString sError( m_pStatement->getOwnConnection()->getResources().getResourceStringWithSubstitution(
+ STR_COLUMN_NOT_UPDATEABLE,
+ "$position$", OUString::number(columnIndex)
+ ) );
+ ::dbtools::throwGenericSQLException(sError,*this);
+ } // if (!::dbtools::implUpdateObject(this, columnIndex, x))
+ }
+
+
+void SAL_CALL OResultSet::updateNumericObject( sal_Int32 columnIndex, const Any& x, sal_Int32 /*scale*/ )
+{
+ if (!::dbtools::implUpdateObject(this, columnIndex, x))
+ {
+ const OUString sError( m_pStatement->getOwnConnection()->getResources().getResourceStringWithSubstitution(
+ STR_COLUMN_NOT_UPDATEABLE,
+ "$position$", OUString::number(columnIndex)
+ ) );
+ ::dbtools::throwGenericSQLException(sError,*this);
+ }
+}
+
+// XResultSetUpdate
+
+void SAL_CALL OResultSet::insertRow( )
+{
+ ResultSetEntryGuard aGuard( *this );
+ SAL_INFO("connectivity.mork", "in, m_nRowPos = " << m_nRowPos);
+// m_RowStates = RowStates_Inserted;
+ updateRow();
+ //m_aQueryHelper.setRowStates(getCurrentCardNumber(),m_RowStates);
+ SAL_INFO("connectivity.mork", "out, m_nRowPos = " << m_nRowPos);
+}
+
+void SAL_CALL OResultSet::updateRow( )
+{
+ OSL_FAIL( "OResultSet::updateRow( ) not implemented" );
+}
+
+void SAL_CALL OResultSet::deleteRow( )
+{
+ OSL_FAIL( "OResultSet::deleteRow( ) not implemented" );
+}
+
+void SAL_CALL OResultSet::cancelRowUpdates( )
+{
+ OSL_FAIL( "OResultSet::cancelRowUpdates( ) not implemented" );
+}
+
+void SAL_CALL OResultSet::moveToInsertRow( )
+{
+ OSL_FAIL( "OResultSet::moveToInsertRow( ) not implemented" );
+}
+
+void SAL_CALL OResultSet::moveToCurrentRow( )
+{
+ ResultSetEntryGuard aGuard( *this );
+ SAL_INFO("connectivity.mork", "m_nRowPos = " << m_nRowPos);
+ if (rowInserted())
+ {
+ m_nRowPos = 0;
+ fetchCurrentRow();
+ }
+}
+
+bool OResultSet::determineReadOnly()
+{
+// OSL_FAIL( "OResultSet::determineReadOnly( ) not implemented" );
+
+ if (m_bIsReadOnly == TRISTATE_INDET)
+ {
+ m_bIsReadOnly = TRISTATE_TRUE;
+// OConnection* xConnection = static_cast<OConnection*>(m_pStatement->getConnection().get());
+// m_bIsReadOnly = !m_aQueryHelper.isWritable(xConnection) || m_bIsAlwaysFalseQuery;
+ }
+
+ return m_bIsReadOnly != TRISTATE_FALSE;
+}
+
+void OResultSet::setTable(OTable* _rTable)
+{
+ m_xTable = _rTable;
+ m_xTableColumns = m_xTable->getColumns();
+ if(m_xTableColumns.is())
+ m_aColumnNames = m_xTableColumns->getElementNames();
+}
+
+void OResultSet::setOrderByColumns(const std::vector<sal_Int32>& _aColumnOrderBy)
+{
+ m_aOrderbyColumnNumber = _aColumnOrderBy;
+}
+
+void OResultSet::setOrderByAscending(const std::vector<TAscendingOrder>& _aOrderbyAsc)
+{
+ m_aOrderbyAscending = _aOrderbyAsc;
+}
+Sequence< sal_Int32 > SAL_CALL OResultSet::deleteRows( const Sequence< Any >& /*rows*/ )
+{
+ ::dbtools::throwFeatureNotImplementedSQLException( "XDeleteRows::deleteRows", *this );
+ return Sequence< sal_Int32 >();
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/mork/MResultSet.hxx b/connectivity/source/drivers/mork/MResultSet.hxx
new file mode 100644
index 000000000..0531781d7
--- /dev/null
+++ b/connectivity/source/drivers/mork/MResultSet.hxx
@@ -0,0 +1,350 @@
+/* -*- 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 .
+ */
+
+#ifndef INCLUDED_CONNECTIVITY_SOURCE_DRIVERS_MORK_MRESULTSET_HXX
+#define INCLUDED_CONNECTIVITY_SOURCE_DRIVERS_MORK_MRESULTSET_HXX
+
+#include <com/sun/star/sdbc/XResultSet.hpp>
+#include <com/sun/star/sdbc/XRow.hpp>
+#include <com/sun/star/sdbc/XResultSetMetaDataSupplier.hpp>
+#include <com/sun/star/sdbc/XCloseable.hpp>
+#include <com/sun/star/sdbc/XColumnLocate.hpp>
+#include <com/sun/star/util/XCancellable.hpp>
+#include <com/sun/star/sdbc/XWarningsSupplier.hpp>
+#include <com/sun/star/sdbc/XResultSetUpdate.hpp>
+#include <com/sun/star/sdbcx/XRowLocate.hpp>
+#include <com/sun/star/sdbcx/XDeleteRows.hpp>
+#include <com/sun/star/sdbc/XRowUpdate.hpp>
+#include <cppuhelper/compbase.hxx>
+#include <comphelper/proparrhlp.hxx>
+#include <tools/gen.hxx>
+#include <rtl/ref.hxx>
+#include "MStatement.hxx"
+#include "MQueryHelper.hxx"
+#include <connectivity/CommonTools.hxx>
+#include <connectivity/FValue.hxx>
+#include <connectivity/sqliterator.hxx>
+#include <TSortIndex.hxx>
+
+namespace connectivity
+{
+ namespace mork
+ {
+
+ /*
+ ** java_sql_ResultSet
+ */
+ typedef ::cppu::WeakComponentImplHelper< css::sdbc::XResultSet,
+ css::sdbc::XRow,
+ css::sdbc::XResultSetMetaDataSupplier,
+ css::util::XCancellable,
+ css::sdbc::XWarningsSupplier,
+ css::sdbc::XCloseable,
+ css::sdbc::XColumnLocate,
+ css::sdbc::XResultSetUpdate,
+ css::sdbc::XRowUpdate,
+ css::sdbcx::XRowLocate,
+ css::sdbcx::XDeleteRows,
+ css::lang::XServiceInfo> OResultSet_BASE;
+
+
+ typedef sal_Int64 TVoidPtr;
+ typedef std::allocator< TVoidPtr > TVoidAlloc;
+ typedef std::vector<TVoidPtr> TVoidVector;
+
+ class OResultSet : public cppu::BaseMutex,
+ public OResultSet_BASE,
+ public ::cppu::OPropertySetHelper,
+ public ::comphelper::OPropertyArrayUsageHelper<OResultSet>
+ {
+ protected:
+ OCommonStatement* m_pStatement;
+ css::uno::Reference< css::uno::XInterface> m_xStatement;
+ css::uno::Reference< css::sdbc::XResultSetMetaData> m_xMetaData;
+ sal_uInt32 m_nRowPos;
+ bool m_bWasNull;
+ sal_Int32 m_nResultSetType;
+ sal_Int32 m_nFetchDirection;
+
+
+ std::shared_ptr< ::connectivity::OSQLParseTreeIterator >
+ m_pSQLIterator;
+ const connectivity::OSQLParseNode* m_pParseTree;
+
+ // OPropertyArrayUsageHelper
+ virtual ::cppu::IPropertyArrayHelper* createArrayHelper( ) const override;
+ // OPropertySetHelper
+ virtual ::cppu::IPropertyArrayHelper & SAL_CALL getInfoHelper() override;
+
+ virtual sal_Bool SAL_CALL convertFastPropertyValue(
+ css::uno::Any & rConvertedValue,
+ css::uno::Any & rOldValue,
+ sal_Int32 nHandle,
+ const css::uno::Any& rValue ) override;
+ virtual void SAL_CALL setFastPropertyValue_NoBroadcast(
+ sal_Int32 nHandle,
+ const css::uno::Any& rValue
+ ) override;
+ virtual void SAL_CALL getFastPropertyValue(
+ css::uno::Any& rValue,
+ sal_Int32 nHandle
+ ) const override;
+
+ // you can't delete objects of this type
+ virtual ~OResultSet() override;
+ public:
+ DECLARE_SERVICE_INFO();
+
+ OResultSet(OCommonStatement* pStmt, const std::shared_ptr< ::connectivity::OSQLParseTreeIterator >& _pSQLIterator );
+
+ // ::cppu::OComponentHelper
+ virtual void SAL_CALL disposing() override;
+ // XInterface
+ virtual css::uno::Any SAL_CALL queryInterface( const css::uno::Type & rType ) override;
+ virtual void SAL_CALL acquire() throw() override;
+ virtual void SAL_CALL release() throw() override;
+ //XTypeProvider
+ virtual css::uno::Sequence< css::uno::Type > SAL_CALL getTypes( ) override;
+ // XPropertySet
+ virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo( ) override;
+ // XResultSet
+ virtual sal_Bool SAL_CALL next( ) override;
+ virtual sal_Bool SAL_CALL isBeforeFirst( ) override;
+ virtual sal_Bool SAL_CALL isAfterLast( ) override;
+ virtual sal_Bool SAL_CALL isFirst( ) override;
+ virtual sal_Bool SAL_CALL isLast( ) override;
+ virtual void SAL_CALL beforeFirst( ) override;
+ virtual void SAL_CALL afterLast( ) override;
+ virtual sal_Bool SAL_CALL first( ) override;
+ virtual sal_Bool SAL_CALL last( ) override;
+ virtual sal_Int32 SAL_CALL getRow( ) override;
+ virtual sal_Bool SAL_CALL absolute( sal_Int32 row ) override;
+ virtual sal_Bool SAL_CALL relative( sal_Int32 rows ) override;
+ virtual sal_Bool SAL_CALL previous( ) override;
+ virtual void SAL_CALL refreshRow( ) override;
+ virtual sal_Bool SAL_CALL rowUpdated( ) override;
+ virtual sal_Bool SAL_CALL rowInserted( ) override;
+ virtual sal_Bool SAL_CALL rowDeleted( ) override;
+ virtual css::uno::Reference< css::uno::XInterface > SAL_CALL getStatement( ) override;
+ // XRow
+ virtual sal_Bool SAL_CALL wasNull( ) override;
+ virtual OUString SAL_CALL getString( sal_Int32 columnIndex ) override;
+ virtual sal_Bool SAL_CALL getBoolean( sal_Int32 columnIndex ) override;
+ virtual sal_Int8 SAL_CALL getByte( sal_Int32 columnIndex ) override;
+ virtual sal_Int16 SAL_CALL getShort( sal_Int32 columnIndex ) override;
+ virtual sal_Int32 SAL_CALL getInt( sal_Int32 columnIndex ) override;
+ virtual sal_Int64 SAL_CALL getLong( sal_Int32 columnIndex ) override;
+ virtual float SAL_CALL getFloat( sal_Int32 columnIndex ) override;
+ virtual double SAL_CALL getDouble( sal_Int32 columnIndex ) override;
+ virtual css::uno::Sequence< sal_Int8 > SAL_CALL getBytes( sal_Int32 columnIndex ) override;
+ virtual css::util::Date SAL_CALL getDate( sal_Int32 columnIndex ) override;
+ virtual css::util::Time SAL_CALL getTime( sal_Int32 columnIndex ) override;
+ virtual css::util::DateTime SAL_CALL getTimestamp( sal_Int32 columnIndex ) override;
+ virtual css::uno::Reference< css::io::XInputStream > SAL_CALL getBinaryStream( sal_Int32 columnIndex ) override;
+ virtual css::uno::Reference< css::io::XInputStream > SAL_CALL getCharacterStream( sal_Int32 columnIndex ) override;
+ virtual css::uno::Any SAL_CALL getObject( sal_Int32 columnIndex, const css::uno::Reference< css::container::XNameAccess >& typeMap ) override;
+ virtual css::uno::Reference< css::sdbc::XRef > SAL_CALL getRef( sal_Int32 columnIndex ) override;
+ virtual css::uno::Reference< css::sdbc::XBlob > SAL_CALL getBlob( sal_Int32 columnIndex ) override;
+ virtual css::uno::Reference< css::sdbc::XClob > SAL_CALL getClob( sal_Int32 columnIndex ) override;
+ virtual css::uno::Reference< css::sdbc::XArray > SAL_CALL getArray( sal_Int32 columnIndex ) override;
+ // XResultSetMetaDataSupplier
+ virtual css::uno::Reference< css::sdbc::XResultSetMetaData > SAL_CALL getMetaData( ) override;
+ // XCancellable
+ virtual void SAL_CALL cancel( ) override;
+ // XCloseable
+ virtual void SAL_CALL close( ) override;
+ // XWarningsSupplier
+ virtual css::uno::Any SAL_CALL getWarnings( ) override;
+ virtual void SAL_CALL clearWarnings( ) override;
+ // XColumnLocate
+ virtual sal_Int32 SAL_CALL findColumn( const OUString& columnName ) override;
+
+ // XResultSetUpdate
+ virtual void SAL_CALL insertRow( ) override;
+ virtual void SAL_CALL updateRow( ) override;
+ virtual void SAL_CALL deleteRow( ) override;
+ virtual void SAL_CALL cancelRowUpdates( ) override;
+ virtual void SAL_CALL moveToInsertRow( ) override;
+ virtual void SAL_CALL moveToCurrentRow( ) override;
+ // XRowUpdate
+ virtual void SAL_CALL updateNull( sal_Int32 columnIndex ) override;
+ virtual void SAL_CALL updateBoolean( sal_Int32 columnIndex, sal_Bool x ) override;
+ virtual void SAL_CALL updateByte( sal_Int32 columnIndex, sal_Int8 x ) override;
+ virtual void SAL_CALL updateShort( sal_Int32 columnIndex, sal_Int16 x ) override;
+ virtual void SAL_CALL updateInt( sal_Int32 columnIndex, sal_Int32 x ) override;
+ virtual void SAL_CALL updateLong( sal_Int32 columnIndex, sal_Int64 x ) override;
+ virtual void SAL_CALL updateFloat( sal_Int32 columnIndex, float x ) override;
+ virtual void SAL_CALL updateDouble( sal_Int32 columnIndex, double x ) override;
+ virtual void SAL_CALL updateString( sal_Int32 columnIndex, const OUString& x ) override;
+ virtual void SAL_CALL updateBytes( sal_Int32 columnIndex, const css::uno::Sequence< sal_Int8 >& x ) override;
+ virtual void SAL_CALL updateDate( sal_Int32 columnIndex, const css::util::Date& x ) override;
+ virtual void SAL_CALL updateTime( sal_Int32 columnIndex, const css::util::Time& x ) override;
+ virtual void SAL_CALL updateTimestamp( sal_Int32 columnIndex, const css::util::DateTime& x ) override;
+ virtual void SAL_CALL updateBinaryStream( sal_Int32 columnIndex, const css::uno::Reference< css::io::XInputStream >& x, sal_Int32 length ) override;
+ virtual void SAL_CALL updateCharacterStream( sal_Int32 columnIndex, const css::uno::Reference< css::io::XInputStream >& x, sal_Int32 length ) override;
+ virtual void SAL_CALL updateObject( sal_Int32 columnIndex, const css::uno::Any& x ) override;
+ virtual void SAL_CALL updateNumericObject( sal_Int32 columnIndex, const css::uno::Any& x, sal_Int32 scale ) override;
+ // XRowLocate
+ virtual css::uno::Any SAL_CALL getBookmark( ) override;
+ virtual sal_Bool SAL_CALL moveToBookmark( const css::uno::Any& bookmark ) override;
+ virtual sal_Bool SAL_CALL moveRelativeToBookmark( const css::uno::Any& bookmark, sal_Int32 rows ) override;
+ virtual sal_Int32 SAL_CALL compareBookmarks( const css::uno::Any& first, const css::uno::Any& second ) override;
+ virtual sal_Bool SAL_CALL hasOrderedBookmarks( ) override;
+ virtual sal_Int32 SAL_CALL hashBookmark( const css::uno::Any& bookmark ) override;
+ // XDeleteRows
+ virtual css::uno::Sequence< sal_Int32 > SAL_CALL deleteRows( const css::uno::Sequence< css::uno::Any >& rows ) override;
+
+protected:
+ //MQuery m_aQuery;
+ MQueryHelper m_aQueryHelper;
+ rtl::Reference<OTable> m_xTable;
+ sal_Int32 m_CurrentRowCount;
+ css::uno::Reference< css::container::XNameAccess >
+ m_xTableColumns;
+
+ std::vector<sal_Int32> m_aColMapping; // pos 0 is unused so we don't have to decrement 1 every time
+ std::vector<sal_Int32> m_aOrderbyColumnNumber;
+ std::vector<TAscendingOrder> m_aOrderbyAscending;
+ css::uno::Sequence< OUString> m_aColumnNames;
+ OValueRow m_aRow;
+ OValueRow m_aParameterRow;
+ sal_Int32 m_nParamIndex;
+ bool m_bIsAlwaysFalseQuery;
+ ::rtl::Reference<OKeySet> m_pKeySet;
+ TriState m_bIsReadOnly;
+ void resetParameters() { m_nParamIndex = 0; }
+
+ ::rtl::Reference<connectivity::OSQLColumns> m_xColumns; // this are the select columns
+
+ void parseParameter( const OSQLParseNode* pNode, OUString& rMatchString );
+ /// @throws css::sdbc::SQLException
+ /// @throws css::uno::RuntimeException
+ void fillRowData();
+ void analyseWhereClause( const OSQLParseNode* parseTree,
+ MQueryExpression &queryExpression);
+
+ bool isCount() const;
+
+ bool IsSorted() const { return !m_aOrderbyColumnNumber.empty(); }
+
+ enum eRowPosition {
+ NEXT_POS, PRIOR_POS, FIRST_POS, LAST_POS, ABSOLUTE_POS, RELATIVE_POS
+ };
+
+ sal_uInt32 currentRowCount();
+
+ /// @throws css::sdbc::SQLException
+ /// @throws css::uno::RuntimeException
+ bool fetchRow(sal_Int32 rowIndex,bool bForceReload=false);
+ /// @throws css::sdbc::SQLException
+ /// @throws css::uno::RuntimeException
+ bool fetchCurrentRow();
+ bool validRow( sal_uInt32 nRow );
+ bool seekRow( eRowPosition pos, sal_Int32 nOffset = 0 );
+ sal_Int32 deletedCount();
+ void fillKeySet(sal_Int32 nMaxCardNumber); //When we get new rows, fill the m_pKeySet items for them
+ sal_Int32 getRowForCardNumber(sal_Int32 nCardNum);
+ /// @throws css::sdbc::SQLException
+ /// @throws css::uno::RuntimeException
+ const ORowSetValue& getValue(sal_Int32 rowIndex, sal_Int32 columnIndex);
+
+ /// @throws css::sdbc::SQLException
+ /// @throws css::uno::RuntimeException
+ void updateValue(sal_Int32 columnIndex,const ORowSetValue& x );
+ /// @throws css::sdbc::SQLException
+ /// @throws css::uno::RuntimeException
+ static void checkPendingUpdate();
+ sal_Int32 getCurrentCardNumber();
+
+public:
+ bool determineReadOnly();
+ // MozAddressbook Specific methods
+ /// @throws css::sdbc::SQLException
+ /// @throws css::uno::RuntimeException
+ void executeQuery();
+
+ void setTable(OTable* _rTable);
+
+ void setParameterRow(const OValueRow& _rParaRow)
+ { m_aParameterRow = _rParaRow; }
+
+ void setBindingRow(const OValueRow& _aRow)
+ { m_aRow = _aRow; }
+
+ void setColumnMapping(const std::vector<sal_Int32>& _aColumnMapping);
+
+ void setOrderByColumns(const std::vector<sal_Int32>& _aColumnOrderBy);
+
+ void setOrderByAscending(const std::vector<TAscendingOrder>& _aOrderbyAsc);
+
+ inline sal_Int32 mapColumn(sal_Int32 column);
+
+ /// @throws css::sdbc::SQLException
+ void checkIndex(sal_Int32 columnIndex );
+
+ static void setBoundedColumns(
+ const OValueRow& _rRow,
+ const ::rtl::Reference<connectivity::OSQLColumns>& _rxColumns,
+ const css::uno::Reference< css::container::XIndexAccess>& _xNames,
+ bool _bSetColumnMapping,
+ const css::uno::Reference< css::sdbc::XDatabaseMetaData>& _xMetaData,
+ std::vector<sal_Int32>& _rColMapping);
+
+ ::osl::Mutex& getMutex() { return m_aMutex; }
+ void methodEntry();
+
+ private:
+ void impl_ensureKeySet()
+ {
+ if ( !m_pKeySet.is() )
+ m_pKeySet = new OKeySet();
+ }
+
+ protected:
+ using OPropertySetHelper::getFastPropertyValue;
+ };
+
+ inline sal_Int32 OResultSet::mapColumn(sal_Int32 column)
+ {
+ sal_Int32 map = column;
+
+ OSL_ENSURE(column > 0, "OResultSet::mapColumn: invalid column index!");
+ // the first column (index 0) is for convenience only. The
+ // first real select column is no 1.
+ if ((column > 0) && (column < static_cast<sal_Int32>(m_aColMapping.size())))
+ map = m_aColMapping[column];
+
+ return map;
+ }
+
+ class ResultSetEntryGuard : public ::osl::MutexGuard
+ {
+ public:
+ explicit ResultSetEntryGuard( OResultSet& _rRS ) : ::osl::MutexGuard( _rRS.getMutex() )
+ {
+ _rRS.methodEntry();
+ }
+ };
+
+ }
+}
+
+#endif // INCLUDED_CONNECTIVITY_SOURCE_DRIVERS_MORK_MRESULTSET_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/mork/MResultSetMetaData.cxx b/connectivity/source/drivers/mork/MResultSetMetaData.cxx
new file mode 100644
index 000000000..e05eced22
--- /dev/null
+++ b/connectivity/source/drivers/mork/MResultSetMetaData.cxx
@@ -0,0 +1,192 @@
+/* -*- 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 <connectivity/dbexception.hxx>
+#include <comphelper/types.hxx>
+#include <comphelper/extract.hxx>
+#include <tools/diagnose_ex.h>
+#include "MResultSetMetaData.hxx"
+#include <com/sun/star/sdbc/DataType.hpp>
+
+using namespace connectivity::mork;
+using namespace com::sun::star::uno;
+using namespace com::sun::star::lang;
+using namespace com::sun::star::sdbc;
+using namespace com::sun::star::beans;
+using namespace ::dbtools;
+using namespace ::comphelper;
+
+
+OResultSetMetaData::~OResultSetMetaData()
+{
+ m_xColumns = nullptr;
+}
+
+
+void OResultSetMetaData::checkColumnIndex(sal_Int32 column)
+{
+ if(column <= 0 || column > static_cast<sal_Int32>(m_xColumns->size()))
+ throwInvalidIndexException(*this);
+}
+
+sal_Int32 SAL_CALL OResultSetMetaData::getColumnDisplaySize( sal_Int32 column )
+{
+ return getPrecision(column);
+}
+
+
+sal_Int32 SAL_CALL OResultSetMetaData::getColumnType( sal_Int32 /*column*/ )
+{
+ return DataType::VARCHAR; // at the moment there exists only this type
+}
+
+
+sal_Int32 SAL_CALL OResultSetMetaData::getColumnCount( )
+{
+ return static_cast<sal_Int32>(m_xColumns->size());
+}
+
+
+sal_Bool SAL_CALL OResultSetMetaData::isCaseSensitive( sal_Int32 /*column*/ )
+{
+ return false;
+}
+
+
+OUString SAL_CALL OResultSetMetaData::getSchemaName( sal_Int32 /*column*/ )
+{
+ return OUString();
+}
+
+
+OUString SAL_CALL OResultSetMetaData::getColumnName( sal_Int32 column )
+{
+ checkColumnIndex(column);
+
+ OUString sColumnName;
+ try
+ {
+ Reference< XPropertySet > xColumnProps( (*m_xColumns)[column-1], UNO_SET_THROW );
+ OSL_VERIFY( xColumnProps->getPropertyValue( OMetaConnection::getPropMap().getNameByIndex( PROPERTY_ID_NAME ) ) >>= sColumnName );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("connectivity.mork");
+ }
+ return sColumnName;
+}
+
+OUString SAL_CALL OResultSetMetaData::getTableName( sal_Int32 /*column*/ )
+{
+ return m_aTableName;
+}
+
+OUString SAL_CALL OResultSetMetaData::getCatalogName( sal_Int32 /*column*/ )
+{
+ return OUString();
+}
+
+OUString SAL_CALL OResultSetMetaData::getColumnTypeName( sal_Int32 column )
+{
+ checkColumnIndex(column);
+ return getString((*m_xColumns)[column-1]->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_TYPENAME)));
+}
+
+OUString SAL_CALL OResultSetMetaData::getColumnLabel( sal_Int32 column )
+{
+ return getColumnName(column);
+}
+
+OUString SAL_CALL OResultSetMetaData::getColumnServiceName( sal_Int32 /*column*/ )
+{
+ return OUString();
+}
+
+
+sal_Bool SAL_CALL OResultSetMetaData::isCurrency( sal_Int32 column )
+{
+ checkColumnIndex(column);
+ return getBOOL((*m_xColumns)[column-1]->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_ISCURRENCY)));
+}
+
+
+sal_Bool SAL_CALL OResultSetMetaData::isAutoIncrement( sal_Int32 /*column*/ )
+{
+ return false;
+}
+
+sal_Bool SAL_CALL OResultSetMetaData::isSigned( sal_Int32 /*column*/ )
+{
+ return false;
+}
+
+sal_Int32 SAL_CALL OResultSetMetaData::getPrecision( sal_Int32 column )
+{
+ checkColumnIndex(column);
+ return getINT32((*m_xColumns)[column-1]->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_PRECISION)));
+}
+
+sal_Int32 SAL_CALL OResultSetMetaData::getScale( sal_Int32 column )
+{
+ checkColumnIndex(column);
+ return getINT32((*m_xColumns)[column-1]->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_SCALE)));
+}
+
+
+sal_Int32 SAL_CALL OResultSetMetaData::isNullable( sal_Int32 column )
+{
+ checkColumnIndex(column);
+ return getINT32((*m_xColumns)[column-1]->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_ISNULLABLE)));
+}
+
+
+sal_Bool SAL_CALL OResultSetMetaData::isSearchable( sal_Int32 /*column*/ )
+{
+ if ( !m_pTable || !m_pTable->getConnection() )
+ {
+ OSL_FAIL( "OResultSetMetaData::isSearchable: suspicious: called without table or connection!" );
+ return false;
+ }
+
+ return true;
+}
+
+
+sal_Bool SAL_CALL OResultSetMetaData::isReadOnly( sal_Int32 column )
+{
+ checkColumnIndex(column);
+ bool bReadOnly = (*m_xColumns)[column-1]->getPropertySetInfo()->hasPropertyByName(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_FUNCTION)) &&
+ ::cppu::any2bool((*m_xColumns)[column-1]->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_FUNCTION)));
+
+ return m_bReadOnly || bReadOnly || OTable::isReadOnly();
+}
+
+
+sal_Bool SAL_CALL OResultSetMetaData::isDefinitelyWritable( sal_Int32 column )
+{
+ return !isReadOnly(column);
+}
+
+sal_Bool SAL_CALL OResultSetMetaData::isWritable( sal_Int32 column )
+{
+ return !isReadOnly(column);
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/mork/MResultSetMetaData.hxx b/connectivity/source/drivers/mork/MResultSetMetaData.hxx
new file mode 100644
index 000000000..5362a4ac0
--- /dev/null
+++ b/connectivity/source/drivers/mork/MResultSetMetaData.hxx
@@ -0,0 +1,88 @@
+/* -*- 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 .
+ */
+
+#ifndef INCLUDED_CONNECTIVITY_SOURCE_DRIVERS_MORK_MRESULTSETMETADATA_HXX
+#define INCLUDED_CONNECTIVITY_SOURCE_DRIVERS_MORK_MRESULTSETMETADATA_HXX
+
+#include <com/sun/star/sdbc/XResultSetMetaData.hpp>
+#include <cppuhelper/implbase.hxx>
+#include <rtl/ref.hxx>
+#include "MTable.hxx"
+
+namespace connectivity
+{
+ namespace mork
+ {
+
+ //************ Class: ResultSetMetaData
+
+ typedef ::cppu::WeakImplHelper<css::sdbc::XResultSetMetaData> OResultSetMetaData_BASE;
+
+ class OResultSetMetaData : public OResultSetMetaData_BASE
+ {
+ OUString m_aTableName;
+ ::rtl::Reference<connectivity::OSQLColumns> m_xColumns;
+ OTable* m_pTable;
+ bool m_bReadOnly;
+
+ protected:
+ virtual ~OResultSetMetaData() override;
+ public:
+ // a constructor that is needed to return the object:
+ // OResultSetMetaData(OConnection* _pConnection) : m_pConnection(_pConnection){}
+ OResultSetMetaData(const ::rtl::Reference<connectivity::OSQLColumns>& _rxColumns,
+ const OUString& _aTableName,OTable* _pTable,bool aReadOnly
+ )
+ :m_aTableName(_aTableName)
+ ,m_xColumns(_rxColumns)
+ ,m_pTable(_pTable)
+ ,m_bReadOnly(aReadOnly)
+ {}
+
+ /// @throws css::sdbc::SQLException
+ /// @throws css::uno::RuntimeException
+ void checkColumnIndex(sal_Int32 column);
+ virtual sal_Int32 SAL_CALL getColumnCount( ) override;
+ virtual sal_Bool SAL_CALL isAutoIncrement( sal_Int32 column ) override;
+ virtual sal_Bool SAL_CALL isCaseSensitive( sal_Int32 column ) override;
+ virtual sal_Bool SAL_CALL isSearchable( sal_Int32 column ) override;
+ virtual sal_Bool SAL_CALL isCurrency( sal_Int32 column ) override;
+ virtual sal_Int32 SAL_CALL isNullable( sal_Int32 column ) override;
+ virtual sal_Bool SAL_CALL isSigned( sal_Int32 column ) override;
+ virtual sal_Int32 SAL_CALL getColumnDisplaySize( sal_Int32 column ) override;
+ virtual OUString SAL_CALL getColumnLabel( sal_Int32 column ) override;
+ virtual OUString SAL_CALL getColumnName( sal_Int32 column ) override;
+ virtual OUString SAL_CALL getSchemaName( sal_Int32 column ) override;
+ virtual sal_Int32 SAL_CALL getPrecision( sal_Int32 column ) override;
+ virtual sal_Int32 SAL_CALL getScale( sal_Int32 column ) override;
+ virtual OUString SAL_CALL getTableName( sal_Int32 column ) override;
+ virtual OUString SAL_CALL getCatalogName( sal_Int32 column ) override;
+ virtual sal_Int32 SAL_CALL getColumnType( sal_Int32 column ) override;
+ virtual OUString SAL_CALL getColumnTypeName( sal_Int32 column ) override;
+ virtual sal_Bool SAL_CALL isReadOnly( sal_Int32 column ) override;
+ virtual sal_Bool SAL_CALL isWritable( sal_Int32 column ) override;
+ virtual sal_Bool SAL_CALL isDefinitelyWritable( sal_Int32 column ) override;
+ virtual OUString SAL_CALL getColumnServiceName( sal_Int32 column ) override;
+ };
+ }
+}
+
+#endif // INCLUDED_CONNECTIVITY_SOURCE_DRIVERS_MORK_MRESULTSETMETADATA_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/mork/MStatement.cxx b/connectivity/source/drivers/mork/MStatement.cxx
new file mode 100644
index 000000000..bd153afa6
--- /dev/null
+++ b/connectivity/source/drivers/mork/MStatement.cxx
@@ -0,0 +1,471 @@
+/* -*- 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 <tools/diagnose_ex.h>
+#include <sal/log.hxx>
+#include <cppuhelper/queryinterface.hxx>
+#include <cppuhelper/typeprovider.hxx>
+#include <comphelper/processfactory.hxx>
+#include <connectivity/dbexception.hxx>
+
+#include <algorithm>
+
+#include "MDriver.hxx"
+#include "MStatement.hxx"
+#include <sqlbison.hxx>
+#include "MResultSet.hxx"
+
+#include <strings.hrc>
+
+static ::osl::Mutex m_ThreadMutex;
+
+using namespace ::comphelper;
+using namespace connectivity::mork;
+using namespace connectivity;
+
+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::container;
+using namespace com::sun::star::io;
+using namespace com::sun::star::util;
+
+
+OStatement::OStatement( OConnection* _pConnection) : OCommonStatement( _pConnection)
+{
+}
+
+OCommonStatement::OCommonStatement(OConnection* _pConnection )
+ :OCommonStatement_IBASE(m_aMutex)
+ ,OPropertySetHelper(OCommonStatement_IBASE::rBHelper)
+ ,m_xDBMetaData (_pConnection->getMetaData())
+ ,m_pTable(nullptr)
+ ,m_pConnection(_pConnection)
+ ,m_aParser( comphelper::getComponentContext(_pConnection->getDriver()->getFactory()) )
+ ,m_pSQLIterator( std::make_shared<OSQLParseTreeIterator>( _pConnection, _pConnection->createCatalog()->getTables(), m_aParser ) )
+{
+}
+
+
+OCommonStatement::~OCommonStatement()
+{
+}
+
+
+void OCommonStatement::disposing()
+{
+ ::osl::MutexGuard aGuard(m_aMutex);
+
+ clearWarnings();
+ clearCachedResultSet();
+
+ m_pConnection.clear();
+
+ m_pSQLIterator->dispose();
+ m_pParseTree.reset();
+
+ OCommonStatement_IBASE::disposing();
+}
+
+Any SAL_CALL OCommonStatement::queryInterface( const Type & rType )
+{
+ Any aRet = OCommonStatement_IBASE::queryInterface(rType);
+ if(!aRet.hasValue())
+ aRet = OPropertySetHelper::queryInterface(rType);
+ return aRet;
+}
+
+Sequence< Type > SAL_CALL OCommonStatement::getTypes( )
+{
+ ::cppu::OTypeCollection aTypes( cppu::UnoType<XMultiPropertySet>::get(),
+ cppu::UnoType<XFastPropertySet>::get(),
+ cppu::UnoType<XPropertySet>::get());
+
+ return ::comphelper::concatSequences(aTypes.getTypes(),OCommonStatement_IBASE::getTypes());
+}
+
+void SAL_CALL OCommonStatement::close( )
+{
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+ checkDisposed(OCommonStatement_IBASE::rBHelper.bDisposed);
+ }
+ dispose();
+}
+
+OCommonStatement::StatementType OCommonStatement::parseSql( const OUString& sql , bool bAdjusted)
+{
+ OUString aErr;
+
+ m_pParseTree = m_aParser.parseTree(aErr,sql);
+
+ if(m_pParseTree)
+ {
+ m_pSQLIterator->setParseTree(m_pParseTree.get());
+ m_pSQLIterator->traverseAll();
+ const OSQLTables& rTabs = m_pSQLIterator->getTables();
+
+ if (rTabs.empty())
+ {
+ getOwnConnection()->throwSQLException( STR_QUERY_AT_LEAST_ONE_TABLES, *this );
+ }
+
+ Reference<XIndexAccess> xNames;
+ switch(m_pSQLIterator->getStatementType())
+ {
+ case OSQLStatementType::Select:
+
+ // at this moment we support only one table per select statement
+
+ OSL_ENSURE( !rTabs.empty(), "Need a Table");
+
+ m_pTable = static_cast< OTable* > (rTabs.begin()->second.get());
+ m_xColNames = m_pTable->getColumns();
+ xNames.set(m_xColNames,UNO_QUERY);
+ // set the binding of the resultrow
+ m_aRow = new OValueVector(xNames->getCount());
+ (*m_aRow)[0].setBound(true);
+ std::for_each(m_aRow->begin()+1,m_aRow->end(),TSetBound(false));
+ // create the column mapping
+ createColumnMapping();
+
+ analyseSQL();
+ return eSelect;
+
+ case OSQLStatementType::CreateTable:
+ return eCreateTable;
+
+ default:
+ break;
+ }
+ }
+ else if(!bAdjusted) //Our sql parser does not support a statement like "create table foo"
+ // So we append ("E-mail" varchar) to the last of it to make it work
+ {
+ return parseSql(sql + "(""E-mail"" character)", true);
+ }
+
+ getOwnConnection()->throwSQLException( STR_QUERY_TOO_COMPLEX, *this );
+ OSL_FAIL( "OCommonStatement::parseSql: unreachable!" );
+ return eSelect;
+
+}
+
+Reference< XResultSet > OCommonStatement::impl_executeCurrentQuery()
+{
+ clearCachedResultSet();
+
+ ::rtl::Reference pResult( new OResultSet( this, m_pSQLIterator ) );
+ initializeResultSet( pResult.get() );
+
+ pResult->executeQuery();
+ cacheResultSet( pResult ); // only cache if we survived the execution
+
+ return pResult.get();
+
+}
+
+
+void OCommonStatement::initializeResultSet( OResultSet* _pResult )
+{
+ ENSURE_OR_THROW( _pResult, "invalid result set" );
+
+ _pResult->setColumnMapping(m_aColMapping);
+ _pResult->setOrderByColumns(m_aOrderbyColumnNumber);
+ _pResult->setOrderByAscending(m_aOrderbyAscending);
+ _pResult->setBindingRow(m_aRow);
+ _pResult->setTable(m_pTable);
+}
+
+
+void OCommonStatement::clearCachedResultSet()
+{
+ Reference< XResultSet > xResultSet( m_xResultSet.get(), UNO_QUERY );
+ if ( !xResultSet.is() )
+ return;
+
+ Reference< XCloseable >( xResultSet, UNO_QUERY_THROW )->close();
+
+ m_xResultSet.clear();
+}
+
+
+void OCommonStatement::cacheResultSet( const ::rtl::Reference< OResultSet >& _pResult )
+{
+ ENSURE_OR_THROW( _pResult.is(), "invalid result set" );
+ m_xResultSet = Reference< XResultSet >( _pResult.get() );
+}
+
+
+sal_Bool SAL_CALL OCommonStatement::execute( const OUString& sql )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ checkDisposed(OCommonStatement_IBASE::rBHelper.bDisposed);
+
+ Reference< XResultSet > xRS = executeQuery( sql );
+ // returns true when a resultset is available
+ return xRS.is();
+}
+
+
+Reference< XResultSet > SAL_CALL OCommonStatement::executeQuery( const OUString& sql )
+{
+ ::osl::MutexGuard aGuard( m_ThreadMutex );
+ checkDisposed(OCommonStatement_IBASE::rBHelper.bDisposed);
+
+ // parse the statement
+ StatementType eStatementType = parseSql( sql );
+ if ( eStatementType != eSelect )
+ return nullptr;
+
+ return impl_executeCurrentQuery();
+}
+
+
+Reference< XConnection > SAL_CALL OCommonStatement::getConnection( )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ checkDisposed(OCommonStatement_IBASE::rBHelper.bDisposed);
+
+ // just return our connection here
+ return Reference< XConnection >(m_pConnection.get());
+}
+
+Any SAL_CALL OStatement::queryInterface( const Type & rType )
+{
+ Any aRet = ::cppu::queryInterface(rType,static_cast< XServiceInfo*> (this));
+ if(!aRet.hasValue())
+ aRet = OCommonStatement::queryInterface(rType);
+ return aRet;
+}
+
+sal_Int32 SAL_CALL OCommonStatement::executeUpdate( const OUString& /*sql*/ )
+{
+ ::dbtools::throwFeatureNotImplementedSQLException( "XStatement::executeUpdate", *this );
+ return 0;
+
+}
+
+Any SAL_CALL OCommonStatement::getWarnings( )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ checkDisposed(OCommonStatement_IBASE::rBHelper.bDisposed);
+
+ return makeAny(m_aLastWarning);
+}
+
+
+void SAL_CALL OCommonStatement::clearWarnings( )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ checkDisposed(OCommonStatement_IBASE::rBHelper.bDisposed);
+
+
+ m_aLastWarning = SQLWarning();
+}
+
+::cppu::IPropertyArrayHelper* OCommonStatement::createArrayHelper( ) const
+{
+ // this properties are define by the service resultset
+ // they must in alphabetic order
+ Sequence< Property > aProps(9);
+ Property* pProperties = aProps.getArray();
+ sal_Int32 nPos = 0;
+ pProperties[nPos++] = css::beans::Property(::connectivity::OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_CURSORNAME),
+ PROPERTY_ID_CURSORNAME, cppu::UnoType<OUString>::get(), 0);
+ pProperties[nPos++] = css::beans::Property(::connectivity::OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_ESCAPEPROCESSING),
+ PROPERTY_ID_ESCAPEPROCESSING, cppu::UnoType<bool>::get(), 0);
+ pProperties[nPos++] = css::beans::Property(::connectivity::OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_FETCHDIRECTION),
+ PROPERTY_ID_FETCHDIRECTION, cppu::UnoType<sal_Int32>::get(), 0);
+ pProperties[nPos++] = css::beans::Property(::connectivity::OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_FETCHSIZE),
+ PROPERTY_ID_FETCHSIZE, cppu::UnoType<sal_Int32>::get(), 0);
+ pProperties[nPos++] = css::beans::Property(::connectivity::OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_MAXFIELDSIZE),
+ PROPERTY_ID_MAXFIELDSIZE, cppu::UnoType<sal_Int32>::get(), 0);
+ pProperties[nPos++] = css::beans::Property(::connectivity::OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_MAXROWS),
+ PROPERTY_ID_MAXROWS, cppu::UnoType<sal_Int32>::get(), 0);
+ pProperties[nPos++] = css::beans::Property(::connectivity::OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_QUERYTIMEOUT),
+ PROPERTY_ID_QUERYTIMEOUT, cppu::UnoType<sal_Int32>::get(), 0);
+ pProperties[nPos++] = css::beans::Property(::connectivity::OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_RESULTSETCONCURRENCY),
+ PROPERTY_ID_RESULTSETCONCURRENCY, cppu::UnoType<sal_Int32>::get(), 0);
+ pProperties[nPos++] = css::beans::Property(::connectivity::OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_RESULTSETTYPE),
+ PROPERTY_ID_RESULTSETTYPE, cppu::UnoType<sal_Int32>::get(), 0);
+
+ return new ::cppu::OPropertyArrayHelper(aProps);
+}
+
+
+::cppu::IPropertyArrayHelper & OCommonStatement::getInfoHelper()
+{
+ return *getArrayHelper();
+}
+
+sal_Bool OCommonStatement::convertFastPropertyValue(
+ Any & /*rConvertedValue*/,
+ Any & /*rOldValue*/,
+ sal_Int32 /*nHandle*/,
+ const Any& /*rValue*/ )
+{
+ // here we have to try to convert
+ return false;
+}
+
+void OCommonStatement::setFastPropertyValue_NoBroadcast(sal_Int32 nHandle,const Any& /*rValue*/)
+{
+ // set the value to whatever is necessary
+ switch(nHandle)
+ {
+ case PROPERTY_ID_QUERYTIMEOUT:
+ case PROPERTY_ID_MAXFIELDSIZE:
+ case PROPERTY_ID_MAXROWS:
+ case PROPERTY_ID_RESULTSETCONCURRENCY:
+ case PROPERTY_ID_RESULTSETTYPE:
+ case PROPERTY_ID_FETCHDIRECTION:
+ case PROPERTY_ID_FETCHSIZE:
+ case PROPERTY_ID_ESCAPEPROCESSING:
+ default:
+ ;
+ }
+}
+
+void OCommonStatement::getFastPropertyValue(Any& /*rValue*/,sal_Int32 nHandle) const
+{
+ switch(nHandle)
+ {
+ case PROPERTY_ID_QUERYTIMEOUT:
+ case PROPERTY_ID_MAXFIELDSIZE:
+ case PROPERTY_ID_MAXROWS:
+ case PROPERTY_ID_RESULTSETCONCURRENCY:
+ case PROPERTY_ID_RESULTSETTYPE:
+ case PROPERTY_ID_FETCHDIRECTION:
+ case PROPERTY_ID_FETCHSIZE:
+ case PROPERTY_ID_ESCAPEPROCESSING:
+ default:
+ ;
+ }
+}
+
+IMPLEMENT_SERVICE_INFO(OStatement,"com.sun.star.sdbcx.OStatement","com.sun.star.sdbc.Statement");
+
+void SAL_CALL OCommonStatement::acquire() throw()
+{
+ OCommonStatement_IBASE::acquire();
+}
+
+void SAL_CALL OCommonStatement::release() throw()
+{
+ OCommonStatement_IBASE::release();
+}
+
+void SAL_CALL OStatement::acquire() throw()
+{
+ OCommonStatement::acquire();
+}
+
+void SAL_CALL OStatement::release() throw()
+{
+ OCommonStatement::release();
+}
+
+Reference< css::beans::XPropertySetInfo > SAL_CALL OCommonStatement::getPropertySetInfo( )
+{
+ return ::cppu::OPropertySetHelper::createPropertySetInfo(getInfoHelper());
+}
+
+void OCommonStatement::createColumnMapping()
+{
+ size_t i;
+
+ // initialize the column index map (mapping select columns to table columns)
+ ::rtl::Reference<connectivity::OSQLColumns> xColumns = m_pSQLIterator->getSelectColumns();
+ m_aColMapping.resize(xColumns->size() + 1);
+ for (i=0; i<m_aColMapping.size(); ++i)
+ m_aColMapping[i] = static_cast<sal_Int32>(i);
+
+ Reference<XIndexAccess> xNames(m_xColNames,UNO_QUERY);
+ // now check which columns are bound
+#if OSL_DEBUG_LEVEL > 0
+ for ( i = 0; i < m_aColMapping.size(); i++ )
+ SAL_INFO(
+ "connectivity.mork",
+ "BEFORE Mapped: " << i << " -> " << m_aColMapping[i]);
+#endif
+ OResultSet::setBoundedColumns(m_aRow,xColumns,xNames,true,m_xDBMetaData,m_aColMapping);
+#if OSL_DEBUG_LEVEL > 0
+ for ( i = 0; i < m_aColMapping.size(); i++ )
+ SAL_INFO(
+ "connectivity.mork",
+ "AFTER Mapped: " << i << " -> " << m_aColMapping[i]);
+#endif
+}
+
+
+void OCommonStatement::analyseSQL()
+{
+ const OSQLParseNode* pOrderbyClause = m_pSQLIterator->getOrderTree();
+ if(!pOrderbyClause)
+ return;
+
+ OSQLParseNode * pOrderingSpecCommalist = pOrderbyClause->getChild(2);
+ OSL_ENSURE(SQL_ISRULE(pOrderingSpecCommalist,ordering_spec_commalist),"OResultSet: Error in Parse Tree");
+
+ for (size_t m = 0; m < pOrderingSpecCommalist->count(); m++)
+ {
+ OSQLParseNode * pOrderingSpec = pOrderingSpecCommalist->getChild(m);
+ OSL_ENSURE(SQL_ISRULE(pOrderingSpec,ordering_spec),"OResultSet: Error in Parse Tree");
+ OSL_ENSURE(pOrderingSpec->count() == 2,"OResultSet: Error in Parse Tree");
+
+ OSQLParseNode * pColumnRef = pOrderingSpec->getChild(0);
+ if(!SQL_ISRULE(pColumnRef,column_ref))
+ {
+ throw SQLException();
+ }
+ OSQLParseNode * pAscendingDescending = pOrderingSpec->getChild(1);
+ setOrderbyColumn(pColumnRef,pAscendingDescending);
+ }
+}
+
+void OCommonStatement::setOrderbyColumn(OSQLParseNode const * pColumnRef,
+ OSQLParseNode const * pAscendingDescending)
+{
+ OUString aColumnName;
+ if (pColumnRef->count() == 1)
+ aColumnName = pColumnRef->getChild(0)->getTokenValue();
+ else if (pColumnRef->count() == 3)
+ {
+ pColumnRef->getChild(2)->parseNodeToStr( aColumnName, getOwnConnection(), nullptr, false, false );
+ }
+ else
+ {
+ throw SQLException();
+ }
+
+ Reference<XColumnLocate> xColLocate(m_xColNames,UNO_QUERY);
+ if(!xColLocate.is())
+ return;
+
+ m_aOrderbyColumnNumber.push_back(xColLocate->findColumn(aColumnName));
+
+ // Ascending or Descending?
+ m_aOrderbyAscending.push_back(SQL_ISTOKEN(pAscendingDescending,DESC) ? TAscendingOrder::DESC : TAscendingOrder::ASC);
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/mork/MStatement.hxx b/connectivity/source/drivers/mork/MStatement.hxx
new file mode 100644
index 000000000..3cd7113a8
--- /dev/null
+++ b/connectivity/source/drivers/mork/MStatement.hxx
@@ -0,0 +1,184 @@
+/* -*- 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 .
+ */
+
+#ifndef INCLUDED_CONNECTIVITY_SOURCE_DRIVERS_MORK_MSTATEMENT_HXX
+#define INCLUDED_CONNECTIVITY_SOURCE_DRIVERS_MORK_MSTATEMENT_HXX
+
+#include <comphelper/proparrhlp.hxx>
+#include <connectivity/sqliterator.hxx>
+#include <connectivity/sqlparse.hxx>
+#include <com/sun/star/sdbc/SQLWarning.hpp>
+#include <TSortIndex.hxx>
+#include "MTable.hxx"
+
+#include <memory>
+
+namespace connectivity
+{
+ namespace mork
+ {
+ class OResultSet;
+
+ typedef ::cppu::WeakComponentImplHelper< css::sdbc::XStatement,
+ css::sdbc::XWarningsSupplier,
+ css::sdbc::XCloseable> OCommonStatement_IBASE;
+
+
+ //************ Class: OCommonStatement
+ // is a base class for the normal statement and for the prepared statement
+
+ class OCommonStatement;
+
+ class OCommonStatement :public cppu::BaseMutex
+ ,public OCommonStatement_IBASE
+ ,public ::cppu::OPropertySetHelper
+ ,public ::comphelper::OPropertyArrayUsageHelper< OCommonStatement >
+ {
+ private:
+ css::sdbc::SQLWarning m_aLastWarning;
+
+ protected:
+ css::uno::WeakReference< css::sdbc::XResultSet > m_xResultSet;
+ css::uno::Reference< css::sdbc::XDatabaseMetaData> m_xDBMetaData;
+ css::uno::Reference< css::container::XNameAccess> m_xColNames; // table columns
+
+ // for this Statement
+
+ OTable* m_pTable;
+ rtl::Reference<OConnection> m_pConnection; // The owning Connection object
+
+ OValueRow m_aRow;
+
+ connectivity::OSQLParser m_aParser;
+ std::shared_ptr< ::connectivity::OSQLParseTreeIterator >
+ m_pSQLIterator;
+
+ std::unique_ptr<connectivity::OSQLParseNode> m_pParseTree;
+
+ std::vector<sal_Int32> m_aColMapping;
+ std::vector<sal_Int32> m_aOrderbyColumnNumber;
+ std::vector<TAscendingOrder> m_aOrderbyAscending;
+
+ protected:
+
+ // OPropertyArrayUsageHelper
+ virtual ::cppu::IPropertyArrayHelper* createArrayHelper( ) const override;
+ // OPropertySetHelper
+ virtual ::cppu::IPropertyArrayHelper & SAL_CALL getInfoHelper() override;
+ virtual sal_Bool SAL_CALL convertFastPropertyValue(
+ css::uno::Any & rConvertedValue,
+ css::uno::Any & rOldValue,
+ sal_Int32 nHandle,
+ const css::uno::Any& rValue ) override;
+ virtual void SAL_CALL setFastPropertyValue_NoBroadcast(
+ sal_Int32 nHandle,
+ const css::uno::Any& rValue) override;
+ virtual void SAL_CALL getFastPropertyValue(
+ css::uno::Any& rValue,
+ sal_Int32 nHandle) const override;
+ virtual ~OCommonStatement() override;
+
+ protected:
+
+ // Driver Internal Methods
+
+ enum StatementType { eSelect, eCreateTable };
+ /** called to do the parsing of a to-be-executed SQL statement, and set all members as needed
+
+ @throws css::sdbc::SQLException
+ @throws css::uno::RuntimeException
+ */
+ virtual StatementType
+ parseSql( const OUString& sql , bool bAdjusted = false);
+ /** called to initialize a result set, according to a previously parsed SQL statement
+ */
+ virtual void initializeResultSet( OResultSet* _pResult );
+ /** called when a possible cached instance of our last result set should be cleared
+ */
+ virtual void clearCachedResultSet();
+ /** caches a result set which has just been created by an execution of an SQL statement
+ */
+ virtual void cacheResultSet( const ::rtl::Reference< OResultSet >& _pResult );
+
+
+ /** executes the current query (the one which has been passed to the last parseSql call)
+ */
+ css::uno::Reference< css::sdbc::XResultSet >
+ impl_executeCurrentQuery();
+
+ void createColumnMapping();
+ void analyseSQL();
+ void setOrderbyColumn( connectivity::OSQLParseNode const * pColumnRef,
+ connectivity::OSQLParseNode const * pAscendingDescending);
+
+ public:
+ // other methods
+ OConnection* getOwnConnection() const { return m_pConnection.get(); }
+
+ explicit OCommonStatement(OConnection* _pConnection );
+ using OCommonStatement_IBASE::operator css::uno::Reference< css::uno::XInterface >;
+
+ // OComponentHelper
+ virtual void SAL_CALL disposing() override;
+
+ // XInterface
+ virtual void SAL_CALL release() throw() override;
+ virtual void SAL_CALL acquire() throw() override;
+ // XInterface
+ virtual css::uno::Any SAL_CALL queryInterface( const css::uno::Type & rType ) override;
+ //XTypeProvider
+ virtual css::uno::Sequence< css::uno::Type > SAL_CALL getTypes( ) override;
+
+ // XPropertySet
+ virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo( ) override;
+ // XStatement
+ virtual css::uno::Reference< css::sdbc::XResultSet > SAL_CALL executeQuery( const OUString& sql ) override ;
+ virtual sal_Int32 SAL_CALL executeUpdate( const OUString& sql ) override ;
+ virtual sal_Bool SAL_CALL execute( const OUString& sql ) override ;
+ virtual css::uno::Reference< css::sdbc::XConnection > SAL_CALL getConnection( ) override ;
+ // XWarningsSupplier
+ virtual css::uno::Any SAL_CALL getWarnings( ) override;
+ virtual void SAL_CALL clearWarnings( ) override;
+ // XCloseable
+ virtual void SAL_CALL close( ) override;
+
+ protected:
+ using OPropertySetHelper::getFastPropertyValue;
+ };
+
+ class OStatement : public OCommonStatement,
+ public css::lang::XServiceInfo
+ {
+ protected:
+ virtual ~OStatement() override {}
+ public:
+ // a constructor, for when the object needs to be returned:
+ explicit OStatement( OConnection* _pConnection);
+ DECLARE_SERVICE_INFO();
+
+ virtual css::uno::Any SAL_CALL queryInterface( const css::uno::Type & rType ) override;
+ virtual void SAL_CALL acquire() throw() override;
+ virtual void SAL_CALL release() throw() override;
+ };
+ }
+}
+
+#endif // INCLUDED_CONNECTIVITY_SOURCE_DRIVERS_MORK_MSTATEMENT_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/mork/MTable.cxx b/connectivity/source/drivers/mork/MTable.cxx
new file mode 100644
index 000000000..76db19fc6
--- /dev/null
+++ b/connectivity/source/drivers/mork/MTable.cxx
@@ -0,0 +1,57 @@
+/* -*- 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 "MTable.hxx"
+#include "MColumns.hxx"
+#include <connectivity/TKeys.hxx>
+#include <connectivity/TIndexes.hxx>
+
+
+using namespace connectivity::mork;
+using namespace connectivity;
+
+
+OTable::OTable( sdbcx::OCollection* _pTables, OConnection* _pConnection,
+ const OUString& Name, const OUString& Type, const OUString& Description )
+ :OTable_Base(_pTables, _pConnection, true, Name, Type, Description )
+ ,m_pConnection( _pConnection )
+{
+ construct();
+}
+
+
+sdbcx::OCollection* OTable::createColumns( const ::std::vector< OUString>& _rNames )
+{
+ return new OColumns( this, m_aMutex, _rNames );
+}
+
+
+sdbcx::OCollection* OTable::createKeys(const ::std::vector< OUString>& _rNames)
+{
+ return new OKeysHelper( this, m_aMutex, _rNames );
+}
+
+
+sdbcx::OCollection* OTable::createIndexes(const ::std::vector< OUString>& _rNames)
+{
+ return new OIndexesHelper( this, m_aMutex, _rNames );
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/mork/MTable.hxx b/connectivity/source/drivers/mork/MTable.hxx
new file mode 100644
index 000000000..7cbe216be
--- /dev/null
+++ b/connectivity/source/drivers/mork/MTable.hxx
@@ -0,0 +1,61 @@
+/* -*- 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 .
+ */
+
+#ifndef INCLUDED_CONNECTIVITY_SOURCE_DRIVERS_MORK_MTABLE_HXX
+#define INCLUDED_CONNECTIVITY_SOURCE_DRIVERS_MORK_MTABLE_HXX
+
+#include <connectivity/TTableHelper.hxx>
+#include "MConnection.hxx"
+
+namespace connectivity
+{
+ namespace mork
+ {
+ typedef ::connectivity::OTableHelper OTable_Base;
+
+ class OTable : public OTable_Base
+ {
+ OConnection* m_pConnection;
+
+ public:
+ OTable( sdbcx::OCollection* _pTables,
+ OConnection* _pConnection,
+ const OUString& Name,
+ const OUString& Type,
+ const OUString& Description );
+
+ OConnection* getConnection() { return m_pConnection;}
+
+ static bool isReadOnly() { return false; }
+
+ const OUString& getTableName() const { return m_Name; }
+ const OUString& getSchema() const { return m_SchemaName; }
+
+ // OTableHelper overridables
+ virtual sdbcx::OCollection* createColumns( const ::std::vector< OUString>& _rNames ) override;
+ virtual sdbcx::OCollection* createKeys(const ::std::vector< OUString>& _rNames) override;
+ virtual sdbcx::OCollection* createIndexes(const ::std::vector< OUString>& _rNames) override;
+ private:
+ using OTable_Base::getConnection;
+ };
+ }
+}
+#endif // INCLUDED_CONNECTIVITY_SOURCE_DRIVERS_MORK_MTABLE_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/mork/MTables.cxx b/connectivity/source/drivers/mork/MTables.cxx
new file mode 100644
index 000000000..f1f169e2a
--- /dev/null
+++ b/connectivity/source/drivers/mork/MTables.cxx
@@ -0,0 +1,70 @@
+/* -*- 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 "MTables.hxx"
+#include "MTable.hxx"
+#include "MCatalog.hxx"
+#include <comphelper/types.hxx>
+
+#include <com/sun/star/sdbc/XRow.hpp>
+
+using namespace connectivity;
+using namespace connectivity::mork;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::sdbc;
+
+sdbcx::ObjectType OTables::createObject(const OUString& _rName)
+{
+ OUString aName,aSchema;
+ aSchema = "%";
+ aName = _rName;
+
+ Sequence< OUString > aTypes { "%" };
+
+ Reference< XResultSet > xResult = m_xMetaData->getTables(Any(),aSchema,aName,aTypes);
+
+ sdbcx::ObjectType xRet;
+ if(xResult.is())
+ {
+ Reference< XRow > xRow(xResult,UNO_QUERY);
+ if(xResult->next()) // there can be only one table with this name
+ {
+ OTable* pRet = new OTable( this, static_cast<OCatalog&>(m_rParent).getConnection(),
+ aName,xRow->getString(4),xRow->getString(5));
+ xRet = pRet;
+ }
+ }
+ ::comphelper::disposeComponent(xResult);
+
+ return xRet;
+}
+
+void OTables::impl_refresh( )
+{
+ static_cast<OCatalog&>(m_rParent).refreshTables();
+}
+
+void OTables::disposing()
+{
+ m_xMetaData.clear();
+ OCollection::disposing();
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/mork/MTables.hxx b/connectivity/source/drivers/mork/MTables.hxx
new file mode 100644
index 000000000..ac3730f9a
--- /dev/null
+++ b/connectivity/source/drivers/mork/MTables.hxx
@@ -0,0 +1,47 @@
+/* -*- 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 .
+ */
+#ifndef INCLUDED_CONNECTIVITY_SOURCE_DRIVERS_MORK_MTABLES_HXX
+#define INCLUDED_CONNECTIVITY_SOURCE_DRIVERS_MORK_MTABLES_HXX
+
+#include <connectivity/sdbcx/VCollection.hxx>
+#include <com/sun/star/sdbc/XDatabaseMetaData.hpp>
+namespace connectivity
+{
+ namespace mork
+ {
+ class OTables : public sdbcx::OCollection
+ {
+ css::uno::Reference< css::sdbc::XDatabaseMetaData > m_xMetaData;
+ protected:
+ virtual sdbcx::ObjectType createObject(const OUString& _rName) override;
+ virtual void impl_refresh() override;
+ public:
+ OTables(const css::uno::Reference< css::sdbc::XDatabaseMetaData >& _rMetaData,::cppu::OWeakObject& _rParent, ::osl::Mutex& _rMutex,
+ const ::std::vector< OUString> &_rVector) : sdbcx::OCollection(_rParent, true, _rMutex, _rVector)
+ ,m_xMetaData(_rMetaData)
+ {}
+
+ // only the name is identical to ::cppu::OComponentHelper
+ virtual void disposing() override;
+ };
+ }
+}
+#endif // INCLUDED_CONNECTIVITY_SOURCE_DRIVERS_MORK_MTABLES_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/mork/MorkParser.cxx b/connectivity/source/drivers/mork/MorkParser.cxx
new file mode 100644
index 000000000..188f8e6fb
--- /dev/null
+++ b/connectivity/source/drivers/mork/MorkParser.cxx
@@ -0,0 +1,757 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * Software License Agreement (BSD License)
+ *
+ * Copyright (c) 2006, ScalingWeb.com
+ * All rights reserved.
+ *
+ * Redistribution and use of this software in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the
+ * following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the
+ * following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * * Neither the name of ScalingWeb.com nor the names of its
+ * contributors may be used to endorse or promote products
+ * derived from this software without specific prior
+ * written permission of ScalingWeb.com.
+
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "MorkParser.hxx"
+#include <boost/io/ios_state.hpp>
+#include <stdlib.h>
+#include <string>
+#include <string.h>
+#include <fstream>
+#include <iostream>
+
+std::string const g_Empty = "";
+
+const char * const MorkDictColumnMeta = "<(a=c)>";
+
+static const int defaultScope_ = 0x80;
+
+MorkParser::MorkParser() :
+ columns_(),
+ values_(),
+ mork_(),
+ currentCells_(nullptr),
+ error_(NoError),
+ morkData_(),
+ morkPos_(0),
+ nextAddValueId_(0x7fffffff),
+ defaultTableId_(1),
+ nowParsing_(NP::Values)
+{
+}
+
+bool MorkParser::open( const std::string &path )
+{
+ initVars();
+ std::string line;
+ std::ifstream infile(path.c_str(), std::ios_base::in);
+ if(!infile.is_open())
+ {
+ error_ = FailedToOpen;
+ return false;
+ }
+
+ while (getline(infile, line, '\n'))
+ {
+ morkData_.append(line);
+ morkData_.append("\n");
+ }
+
+ // Parse mork
+ return parse();
+}
+
+void MorkParser::initVars()
+{
+ error_ = NoError;
+ morkPos_ = 0;
+ nowParsing_ = NP::Values;
+ currentCells_ = nullptr;
+ nextAddValueId_ = 0x7fffffff;
+}
+
+bool MorkParser::parse()
+{
+ bool Result = true;
+
+ // Run over mork chars and parse each term
+ char cur = nextChar();
+
+ while ( Result && cur )
+ {
+ if ( !isWhiteSpace( cur ) )
+ {
+ // Figure out what a term
+ switch ( cur )
+ {
+ case '<':
+ // Dict
+ Result = parseDict();
+ break;
+ case '/':
+ // Comment
+ Result = parseComment();
+ break;
+ case '{':
+ Result = parseTable();
+ // Table
+ break;
+ case '[':
+ Result = parseRow( 0, 0 );
+ // Row
+ break;
+ case '@':
+ parseGroup();
+ // Group
+ break;
+ default:
+ error_ = DefectedFormat;
+ Result = false;
+ break;
+ }
+ }
+
+ // Get next char
+ cur = nextChar();
+ }
+
+ return Result;
+}
+
+bool MorkParser::isWhiteSpace( char c )
+{
+ switch ( c )
+ {
+ case ' ':
+ case '\t':
+ case '\r':
+ case '\n':
+ case '\f':
+ return true;
+ default:
+ return false;
+ }
+}
+
+inline char MorkParser::nextChar()
+{
+ char cur = 0;
+
+
+ if ( morkPos_ < morkData_.length() )
+ {
+ cur = morkData_[ morkPos_ ];
+ morkPos_++;
+ }
+
+ if ( !cur )
+ {
+ cur = 0;
+ }
+
+ return cur;
+}
+
+bool MorkParser::parseDict()
+{
+ char cur = nextChar();
+ bool Result = true;
+ nowParsing_ = NP::Values;
+
+ while ( Result && cur != '>' && cur )
+ {
+ if ( !isWhiteSpace( cur ) )
+ {
+ switch ( cur )
+ {
+ case '<':
+ {
+
+ if ( morkData_.substr( morkPos_ - 1, strlen( MorkDictColumnMeta ) ) == MorkDictColumnMeta )
+ {
+ nowParsing_ = NP::Columns;
+ morkPos_ += strlen( MorkDictColumnMeta ) - 1;
+ }
+
+
+ break;
+ }
+ case '(':
+ Result = parseCell();
+ break;
+ case '/':
+ Result = parseComment();
+ break;
+
+ }
+ }
+
+ cur = nextChar();
+ }
+
+ return Result;
+}
+
+inline bool MorkParser::parseComment()
+{
+ char cur = nextChar();
+ if ( '/' != cur ) return false;
+
+ while ( cur != '\r' && cur != '\n' && cur )
+ {
+ cur = nextChar();
+ }
+
+ return true;
+}
+
+bool MorkParser::parseCell()
+{
+ bool Result = true;
+ bool bValueOid = false;
+ bool bColumn = true;
+ int Corners = 0;
+
+ // Column = Value
+ std::string Column;
+ std::string Text;
+ Column.reserve( 4 );
+ Text.reserve( 32 );
+
+ char cur = nextChar();
+
+ // Process cell start with column (bColumn == true)
+ while ( Result && cur != ')' && cur )
+ {
+ switch ( cur )
+ {
+ case '^':
+ // Oids
+ Corners++;
+ if ( 1 == Corners )
+ {
+ }
+ else if ( 2 == Corners )
+ {
+ bColumn = false;
+ bValueOid = true;
+ }
+ else
+ {
+ Text += cur;
+ }
+
+ break;
+ case '=':
+ // From column to value
+ if ( bColumn )
+ {
+ bColumn = false;
+ }
+ else
+ {
+ Text += cur;
+ }
+ break;
+ case '\\':
+ {
+ // Get next two chars
+ char NextChar= nextChar();
+ if ( '\r' != NextChar && '\n' != NextChar )
+ {
+ Text += NextChar;
+ }
+ else
+ {
+ (void)nextChar();
+ }
+ }
+ break;
+ case '$':
+ {
+ // Get next two chars
+ std::string HexChar;
+ HexChar += nextChar();
+ HexChar += nextChar();
+ Text += static_cast<char>(strtoul(HexChar.c_str(), nullptr, 16));
+ }
+ break;
+ default:
+ // Just a char
+ if ( bColumn )
+ {
+ Column += cur;
+ }
+ else
+ {
+ Text += cur;
+ }
+ break;
+ }
+
+ cur = nextChar();
+ }
+
+ // Apply column and text
+ int ColumnId = strtoul(Column.c_str(), nullptr, 16);
+
+ if ( NP::Rows != nowParsing_ )
+ {
+ // Dicts
+ if ( !Text.empty() )
+ {
+ if ( nowParsing_ == NP::Columns )
+ {
+ columns_[ ColumnId ] = Text;
+ }
+ else
+ {
+ values_[ ColumnId ] = Text;
+ }
+ }
+ }
+ else
+ {
+ if ( !Text.empty() )
+ {
+ // Rows
+ //int ValueId = string( Text.c_str() ).toInt( 0, 16 );
+ int ValueId = strtoul(Text.c_str(), nullptr, 16);
+
+ if ( bValueOid )
+ {
+ ( *currentCells_ )[ ColumnId ] = ValueId;
+ }
+ else
+ {
+ nextAddValueId_--;
+ values_[ nextAddValueId_ ] = Text;
+ ( *currentCells_ )[ ColumnId ] = nextAddValueId_;
+ }
+ }
+ }
+
+ return Result;
+}
+
+bool MorkParser::parseTable()
+{
+ bool Result = true;
+ std::string TextId;
+ int Id = 0, Scope = 0;
+
+ char cur = nextChar();
+
+ // Get id
+ while ( cur != '{' && cur != '[' && cur != '}' && cur )
+ {
+ if ( !isWhiteSpace( cur ) )
+ {
+ TextId += cur;
+ }
+
+ cur = nextChar();
+ }
+
+ parseScopeId( TextId, &Id, &Scope );
+
+ // Parse the table
+ while ( Result && cur != '}' && cur )
+ {
+ if ( !isWhiteSpace( cur ) )
+ {
+ switch ( cur )
+ {
+ case '{':
+ parseMeta( '}' );
+ break;
+ case '[':
+ Result = parseRow( Id, Scope );
+ break;
+ case '-':
+ case '+':
+ break;
+ default:
+ {
+ std::string JustId;
+ while ( !isWhiteSpace( cur ) && cur )
+ {
+ JustId += cur;
+ cur = nextChar();
+
+ if ( cur == '}' )
+ {
+ return Result;
+ }
+ }
+
+ int JustIdNum = 0, JustScopeNum = 0;
+ parseScopeId( JustId, &JustIdNum, &JustScopeNum );
+
+ setCurrentRow( Scope, Id, JustScopeNum, JustIdNum );
+ }
+ break;
+ }
+ }
+
+ cur = nextChar();
+ }
+
+ return Result;
+}
+
+void MorkParser::parseScopeId( const std::string &TextId, int *Id, int *Scope )
+{
+ int Pos = 0;
+
+ if ( ( Pos = TextId.find( ':' ) ) >= 0 )
+ {
+ std::string tId = TextId.substr( 0, Pos );
+ std::string tSc = TextId.substr( Pos + 1, TextId.length() - Pos );
+
+ if ( tSc.length() > 1 && '^' == tSc[ 0 ] )
+ {
+ // Delete '^'
+ tSc.erase( 0, 1 );
+ }
+
+ *Id = strtoul(tId.c_str(), nullptr, 16);
+
+ *Scope = strtoul(tSc.c_str(), nullptr, 16);
+ }
+ else
+ {
+ *Id = strtoul(TextId.c_str(), nullptr, 16);
+ }
+}
+
+inline void MorkParser::setCurrentRow( int TableScope, int TableId, int RowScope, int RowId )
+{
+ if ( !RowScope )
+ {
+ RowScope = defaultScope_;
+ }
+
+ if ( !TableScope )
+ {
+ TableScope = defaultScope_;
+ }
+
+ // 01.08.2012 davido
+ // TableId 0 is wrong here.
+ // Straying rows (rows that defined outside the table) belong to the default scope and table is the last was seen: 1:^80
+ // (at least i read so the specification)
+ if (TableId)
+ {
+ defaultTableId_ = TableId;
+ }
+
+ if (!TableId)
+ {
+ TableId = defaultTableId_;
+ }
+
+ currentCells_ = &( mork_.map[ abs( TableScope ) ].map[ abs( TableId ) ].map[ abs( RowScope ) ].map[ abs( RowId ) ] );
+}
+
+bool MorkParser::parseRow( int TableId, int TableScope )
+{
+ bool Result = true;
+ std::string TextId;
+ int Id = 0, Scope = 0;
+ nowParsing_ = NP::Rows;
+
+ char cur = nextChar();
+
+ // Get id
+ while ( cur != '(' && cur != ']' && cur != '[' && cur )
+ {
+ if ( !isWhiteSpace( cur ) )
+ {
+ TextId += cur;
+ }
+
+ cur = nextChar();
+ }
+
+ parseScopeId( TextId, &Id, &Scope );
+ setCurrentRow( TableScope, TableId, Scope, Id );
+
+ // Parse the row
+ while ( Result && cur != ']' && cur )
+ {
+ if ( !isWhiteSpace( cur ) )
+ {
+ switch ( cur )
+ {
+ case '(':
+ Result = parseCell();
+ break;
+ case '[':
+ parseMeta( ']' );
+ break;
+ default:
+ Result = false;
+ break;
+ }
+ }
+
+ cur = nextChar();
+ }
+
+ return Result;
+}
+
+void MorkParser::parseGroup()
+{
+ parseMeta( '@' );
+}
+
+void MorkParser::parseMeta( char c )
+{
+ char cur = nextChar();
+
+ while ( cur != c && cur )
+ {
+ cur = nextChar();
+ }
+}
+
+MorkTableMap *MorkParser::getTables( int TableScope )
+{
+ TableScopeMap::Map::iterator iter = mork_.map.find( TableScope );
+
+ if ( iter == mork_.map.end() )
+ {
+ return nullptr;
+ }
+
+ return &iter->second;
+}
+
+MorkRowMap *MorkParser::getRows( int RowScope, RowScopeMap *table )
+{
+ RowScopeMap::Map::iterator iter = table->map.find( RowScope );
+
+ if ( iter == table->map.end() )
+ {
+ return nullptr;
+ }
+
+ return &iter->second;
+}
+
+std::string const &MorkParser::getValue( int oid )
+{
+ MorkDict::iterator foundIter = values_.find( oid );
+
+ if ( values_.end() == foundIter )
+ {
+ return g_Empty;
+ }
+
+ return foundIter->second;
+}
+
+std::string const &MorkParser::getColumn( int oid )
+{
+ MorkDict::iterator foundIter = columns_.find( oid );
+
+ if ( columns_.end() == foundIter )
+ {
+ return g_Empty;
+ }
+
+ return foundIter->second;
+}
+
+void MorkParser::retrieveLists(std::set<std::string>& lists)
+{
+#ifdef VERBOSE
+ boost::io::ios_all_saver ias(std::cout);
+ std::cout << std::hex << std::uppercase;
+#endif
+
+ MorkTableMap* tables = getTables(defaultScope_);
+ if (!tables) return;
+ for (auto& rTable : tables->map)
+ {
+#ifdef VERBOSE
+ std::cout << "\t Table:"
+ << ( ( int ) rTable.first < 0 ? "-" : " " )
+ << rTable.first << std::endl;
+#endif
+ MorkRowMap* rows = getRows( 0x81/*defaultListScope*/, &rTable.second );
+ if (!rows) return;
+ for ( const auto& rRow : rows->map )
+ {
+#ifdef VERBOSE
+ std::cout << "\t\t\t Row Id:"
+ << ( ( int ) rRow.first < 0 ? "-" : " ")
+ << rRow.first << std::endl;
+ std::cout << "\t\t\t\t Cells:\r\n";
+#endif
+ // Get cells
+ MorkCells::const_iterator cellsIter = rRow.second.find(0xC1);
+ if (cellsIter != rRow.second.end())
+ lists.insert(getValue( cellsIter->second ));
+ }
+ }
+}
+
+void MorkParser::getRecordKeysForListTable(std::string const & listName, std::set<int>& records)
+{
+#ifdef VERBOSE
+ boost::io::ios_all_saver ias(std::cout);
+ std::cout << std::hex << std::uppercase;
+#endif
+
+ MorkTableMap* tables = getTables(defaultScope_);
+ if (!tables) return;
+ for (auto& rTable : tables->map)
+ {
+#ifdef VERBOSE
+ std::cout << "\t Table:"
+ << ( ( int ) rTable.first < 0 ? "-" : " " )
+ << rTable.first << std::endl;
+#endif
+ MorkRowMap* rows = getRows( 0x81, &rTable.second );
+ if (!rows) return;
+ for ( const auto& rRow : rows->map )
+ {
+#ifdef VERBOSE
+ std::cout << "\t\t\t Row Id:"
+ << ( ( int ) rRow.first < 0 ? "-" : " ")
+ << rRow.first << std::endl;
+ std::cout << "\t\t\t\t Cells:\r\n";
+#endif
+ // Get cells
+ bool isListFound = false;
+ for ( const auto& [rColumnId, rValueId] : rRow.second )
+ {
+ if (isListFound)
+ {
+ if (rColumnId >= 0xC7)
+ {
+ std::string value = getValue(rValueId);
+ int id = strtoul(value.c_str(), nullptr, 16);
+ records.insert(id);
+ }
+ }
+ else if ((rColumnId == 0xC1) &&
+ listName == getValue( rValueId ))
+ {
+ isListFound = true;
+ }
+ }
+
+ }
+ }
+}
+
+void MorkParser::dump()
+{
+ boost::io::ios_all_saver ias(std::cout);
+ std::cout << std::hex << std::uppercase;
+
+ std::cout << "Column Dict:\r\n";
+ std::cout << "=============================================\r\n\r\n";
+
+ //// columns dict
+ for ( const auto& [rColumnId, rText] : columns_ )
+ {
+ std::cout << rColumnId
+ << " : "
+ << rText
+ << std::endl;
+ }
+
+ //// values dict
+ std::cout << "\r\nValues Dict:\r\n";
+ std::cout << "=============================================\r\n\r\n";
+
+ for ( const auto& [rValueId, rText] : values_ )
+ {
+ if (rValueId >= nextAddValueId_) {
+ continue;
+ }
+
+ std::cout << rValueId
+ << " : "
+ << rText
+ << "\r\n";
+ }
+
+ std::cout << std::endl << "Data:" << std::endl;
+ std::cout << "============================================="
+ << std::endl << std::endl;
+
+ //// Mork data
+ for ( const auto& [rTableScopeId, rTableScope] : mork_.map )
+ {
+ std::cout << "\r\n Scope:" << rTableScopeId << std::endl;
+
+ for ( const auto& [rTableId, rTable] : rTableScope.map )
+ {
+ std::cout << "\t Table:"
+ << ( rTableId < 0 ? "-" : " " )
+ << rTableId << std::endl;
+
+ for (const auto& [rRowScopeId, rRowScope] : rTable.map)
+ {
+ std::cout << "\t\t RowScope:"
+ << rRowScopeId << std::endl;
+
+ for (const auto& [rRowId, rRow] : rRowScope.map)
+ {
+ std::cout << "\t\t\t Row Id:"
+ << (rRowId < 0 ? "-" : " ")
+ << rRowId << std::endl;
+ std::cout << "\t\t\t\t Cells:" << std::endl;
+
+ for (const auto& [rColumnId, rValueId] : rRow)
+ {
+ // Write ids
+ std::cout << "\t\t\t\t\t"
+ << rColumnId
+ << " : "
+ << rValueId
+ << " => ";
+
+ MorkDict::const_iterator FoundIter = values_.find( rValueId );
+ if ( FoundIter != values_.end() )
+ {
+ // Write string values
+ std::cout << columns_[ rColumnId ].c_str()
+ << " : "
+ << FoundIter->second.c_str()
+ << std::endl;
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/mork/MorkParser.hxx b/connectivity/source/drivers/mork/MorkParser.hxx
new file mode 100644
index 000000000..d16fc417d
--- /dev/null
+++ b/connectivity/source/drivers/mork/MorkParser.hxx
@@ -0,0 +1,152 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * Software License Agreement (BSD License)
+ *
+ * Copyright (c) 2006, ScalingWeb.com
+ * All rights reserved.
+ *
+ * Redistribution and use of this software in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the
+ * following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the
+ * following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * * Neither the name of ScalingWeb.com nor the names of its
+ * contributors may be used to endorse or promote products
+ * derived from this software without specific prior
+ * written permission of ScalingWeb.com.
+
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef INCLUDED_CONNECTIVITY_SOURCE_DRIVERS_MORK_MORKPARSER_HXX
+#define INCLUDED_CONNECTIVITY_SOURCE_DRIVERS_MORK_MORKPARSER_HXX
+
+#include <rtl/ustring.hxx>
+
+#include <string>
+#include <map>
+#include <set>
+#include <vector>
+
+#include "dllapi.h"
+
+// Types
+
+typedef std::map< int, std::string > MorkDict;
+typedef std::map< int, int > MorkCells; // ColumnId : ValueId
+struct MorkRowMap { typedef std::map< int, MorkCells > Map; Map map; }; // Row id
+struct RowScopeMap { typedef std::map< int, MorkRowMap > Map; Map map; }; // Row scope
+struct MorkTableMap { typedef std::map< int, RowScopeMap > Map; Map map; }; // Table id
+struct TableScopeMap { typedef std::map< int, MorkTableMap > Map; Map map; }; // Table Scope
+
+// Error codes
+enum MorkErrors
+{
+ NoError = 0,
+ FailedToOpen,
+ DefectedFormat
+};
+
+
+/// Class MorkParser
+
+class LO_DLLPUBLIC_MORK MorkParser final
+{
+public:
+
+ explicit MorkParser();
+
+ /// Open and parse mork file
+
+ bool open( const std::string &path );
+
+ /// Returns all tables of specified scope
+
+ MorkTableMap *getTables( int tableScope );
+
+ /// Returns all rows under specified scope
+
+ static MorkRowMap *getRows( int rowScope, RowScopeMap *table );
+
+ /// Return value of specified value oid
+
+ std::string const &getValue( int oid );
+
+ /// Return value of specified column oid
+
+ std::string const &getColumn( int oid );
+
+ void retrieveLists(std::set<std::string>& lists);
+ void getRecordKeysForListTable(std::string const & listName, std::set<int>& records);
+
+ void dump();
+
+ // All lists
+ std::vector<OUString> lists_;
+
+private: // Members
+
+ void initVars();
+
+ static bool isWhiteSpace( char c );
+ char nextChar();
+
+ static void parseScopeId( const std::string &TextId, int *Id, int *Scope );
+ void setCurrentRow( int TableScope, int TableId, int RowScope, int RowId );
+
+ // Parse methods
+ bool parse();
+ bool parseDict();
+ bool parseComment();
+ bool parseCell();
+ bool parseTable();
+ void parseMeta( char c );
+ bool parseRow( int TableId, int TableScope );
+ void parseGroup();
+
+private: // Data
+
+ // Columns in mork means value names
+ MorkDict columns_;
+ MorkDict values_;
+
+ // All mork file data
+ TableScopeMap mork_;
+ MorkCells *currentCells_;
+
+ // Error status of last operation
+ MorkErrors error_;
+
+ // All Mork data
+ std::string morkData_;
+
+
+ unsigned morkPos_;
+ int nextAddValueId_;
+ int defaultTableId_;
+
+ // Indicates entity is being parsed
+ enum class NP { Columns, Values, Rows } nowParsing_;
+
+ MorkParser(const MorkParser &) = delete;
+ MorkParser &operator=(const MorkParser &) = delete;
+
+};
+
+#endif // __MorkParser_h__
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/mork/README b/connectivity/source/drivers/mork/README
new file mode 100644
index 000000000..0d4207b0c
--- /dev/null
+++ b/connectivity/source/drivers/mork/README
@@ -0,0 +1,41 @@
+Mork Format Parsing Library
+=============================
+
+Description
+-----------
+
+Cross Platform Mozilla Mork format reader.
+
+
+Compilation
+------------
+
+g++ -o MorkParser main.cpp MorkParser.cpp
+
+
+License
+-------
+
+This program is licensed under permissive BSD license.
+See the license.txt file for more information.
+
+
+Date: October 16th, 2007
+
+Project Maintainers:
+ Yuriy Soroka
+ ysoroka@scalingweb.com
+
+ http://www.scalingweb.com/
+
+Thanks
+-------------
+Thanks to Petr Stejskal <stejsky@volny.cz> who helped with porting this code from Qt to STL.
+
+
+How you can help
+----------------
+
+ Comments, patches, bug reports are welcome.
+
+
diff --git a/connectivity/source/drivers/mork/dllapi.h b/connectivity/source/drivers/mork/dllapi.h
new file mode 100644
index 000000000..adf269107
--- /dev/null
+++ b/connectivity/source/drivers/mork/dllapi.h
@@ -0,0 +1,25 @@
+
+/* -*- 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/.
+ */
+
+#ifndef INCLUDED_CONNECTIVITY_SOURCE_DRIVERS_MORK_DLLAPI_H
+#define INCLUDED_CONNECTIVITY_SOURCE_DRIVERS_MORK_DLLAPI_H
+
+#include <sal/config.h>
+#include <sal/types.h>
+
+#if defined LO_DLLIMPLEMENTATION_MORK
+#define LO_DLLPUBLIC_MORK SAL_DLLPUBLIC_EXPORT
+#else
+#define LO_DLLPUBLIC_MORK SAL_DLLPUBLIC_IMPORT
+#endif
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/mork/license.txt b/connectivity/source/drivers/mork/license.txt
new file mode 100644
index 000000000..3e41befc7
--- /dev/null
+++ b/connectivity/source/drivers/mork/license.txt
@@ -0,0 +1,31 @@
+Software License Agreement (BSD License)
+
+Copyright (c) 2006, ScalingWeb.com
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms, with or without modification, are
+permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of ScalingWeb.com nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of ScalingWeb.com.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
diff --git a/connectivity/source/drivers/mork/mork.component b/connectivity/source/drivers/mork/mork.component
new file mode 100644
index 000000000..1eeb6affb
--- /dev/null
+++ b/connectivity/source/drivers/mork/mork.component
@@ -0,0 +1,17 @@
+<?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/.
+ *
+-->
+
+<component loader="com.sun.star.loader.SharedLibrary" environment="@CPPU_ENV@"
+ xmlns="http://openoffice.org/2010/uno-components">
+ <implementation name="com.sun.star.comp.sdbc.MorkDriver"
+ constructor="com_sun_star_comp_sdbc_MorkDriver_get_implementation">
+ <service name="com.sun.star.sdbc.Driver"/>
+ </implementation>
+</component>
diff --git a/connectivity/source/drivers/mork/mork_helper.cxx b/connectivity/source/drivers/mork/mork_helper.cxx
new file mode 100644
index 000000000..4cb11864f
--- /dev/null
+++ b/connectivity/source/drivers/mork/mork_helper.cxx
@@ -0,0 +1,54 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+
+#include "MorkParser.hxx"
+#include <iostream>
+#include <sal/log.hxx>
+
+static bool openAddressBook(const std::string& path)
+{
+ MorkParser mork;
+ // Open and parse mork file
+ if (!mork.open(path))
+ {
+ return false;
+ }
+
+ const int defaultScope = 0x80;
+ MorkTableMap *Tables = mork.getTables( defaultScope );
+ if ( Tables )
+ {
+ // Iterate all tables
+ for (auto const& table : Tables->map)
+ {
+ if ( 0 == table.first ) continue;
+ SAL_INFO("connectivity.mork", "table->first : " << table.first);
+ std::string column = mork.getColumn( table.first );
+ std::string value = mork.getValue( table.first );
+ SAL_INFO("connectivity.mork", "table.column : " << column);
+ SAL_INFO("connectivity.mork", "table.value : " << value);
+ }
+ }
+
+ mork.dump();
+
+ return true;
+}
+
+int main(int argc, char* argv[])
+{
+ if (argc < 2)
+ {
+ std::cerr << "Usage: " << argv[0] << " <path-to>/abook.mab" << std::endl;
+ std::cerr << "Example: " << argv[0] << " /home/johndoe/.thunderbird/m0tpqlky.default/abook.mab" << std::endl;
+
+ return 1;
+ }
+
+ OString aOString(argv[1]);
+ SAL_INFO("connectivity.mork", "abook.mab: " << aOString);
+ openAddressBook(aOString.getStr());
+
+ return 0;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */