diff options
Diffstat (limited to 'connectivity/source/drivers/evoab2')
25 files changed, 5639 insertions, 0 deletions
diff --git a/connectivity/source/drivers/evoab2/EApi.cxx b/connectivity/source/drivers/evoab2/EApi.cxx new file mode 100644 index 000000000..9ec8e0d44 --- /dev/null +++ b/connectivity/source/drivers/evoab2/EApi.cxx @@ -0,0 +1,135 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#include <rtl/ustring.hxx> +#include <osl/module.hxx> +#define DECLARE_FN_POINTERS 1 +#include "EApi.h" +static const char *eBookLibNames[] = { + "libebook-1.2.so.21", // evolution-data-server 3.45.2+ + "libebook-1.2.so.20", // evolution-data-server 3.33.2+ + "libebook-1.2.so.19", // evolution-data-server 3.24+ + "libebook-1.2.so.16" +}; + +typedef void (*SymbolFunc) (); + +namespace { + +struct ApiMap +{ + const char *sym_name; + SymbolFunc *ref_value; +}; + +} + +const ApiMap aCommonApiMap[] = +{ + { "eds_check_version", reinterpret_cast<SymbolFunc *>(&eds_check_version) }, + { "e_contact_field_name", reinterpret_cast<SymbolFunc *>(&e_contact_field_name) }, + { "e_contact_get", reinterpret_cast<SymbolFunc *>(&e_contact_get) }, + { "e_contact_get_type", reinterpret_cast<SymbolFunc *>(&e_contact_get_type) }, + { "e_contact_field_id", reinterpret_cast<SymbolFunc *>(&e_contact_field_id) }, + { "e_book_new", reinterpret_cast<SymbolFunc *>(&e_book_new) }, + { "e_book_open", reinterpret_cast<SymbolFunc *>(&e_book_open) }, + { "e_book_get_source", reinterpret_cast<SymbolFunc *>(&e_book_get_source) }, + { "e_book_get_contacts", reinterpret_cast<SymbolFunc *>(&e_book_get_contacts) }, + { "e_book_query_field_test", reinterpret_cast<SymbolFunc *>(&e_book_query_field_test) }, + { "e_book_query_and", reinterpret_cast<SymbolFunc *>(&e_book_query_and) }, + { "e_book_query_or", reinterpret_cast<SymbolFunc *>(&e_book_query_or) }, + { "e_book_query_not", reinterpret_cast<SymbolFunc *>(&e_book_query_not) }, + { "e_book_query_ref", reinterpret_cast<SymbolFunc *>(&e_book_query_ref) }, + { "e_book_query_unref", reinterpret_cast<SymbolFunc *>(&e_book_query_unref) }, + { "e_book_query_from_string", reinterpret_cast<SymbolFunc *>(&e_book_query_from_string) }, + { "e_book_query_to_string", reinterpret_cast<SymbolFunc *>(&e_book_query_to_string) }, + { "e_book_query_field_exists", reinterpret_cast<SymbolFunc *>(&e_book_query_field_exists) } +}; + +const ApiMap aNewApiMap[] = +{ + { "e_source_registry_list_sources", reinterpret_cast<SymbolFunc *>(&e_source_registry_list_sources) }, + { "e_source_registry_new_sync", reinterpret_cast<SymbolFunc *>(&e_source_registry_new_sync) }, + { "e_source_has_extension", reinterpret_cast<SymbolFunc *>(&e_source_has_extension) }, + { "e_source_get_extension", reinterpret_cast<SymbolFunc *>(&e_source_get_extension) }, + { "e_source_backend_get_backend_name", reinterpret_cast<SymbolFunc *>(&e_source_backend_get_backend_name) }, + { "e_source_get_display_name", reinterpret_cast<SymbolFunc *>(&e_source_get_display_name) }, + { "e_source_get_uid", reinterpret_cast<SymbolFunc *>(&e_source_get_uid) }, + { "e_source_registry_ref_source", reinterpret_cast<SymbolFunc *>(&e_source_registry_ref_source) }, + { "e_client_open_sync", reinterpret_cast<SymbolFunc *>(&e_client_open_sync) }, + { "e_client_get_source", reinterpret_cast<SymbolFunc *>(&e_client_get_source) }, + { "e_book_client_get_contacts_sync", reinterpret_cast<SymbolFunc *>(&e_book_client_get_contacts_sync) }, + { "e_client_util_free_object_slist", reinterpret_cast<SymbolFunc *>(&e_client_util_free_object_slist) } +}; + +//>= direct read access API (>= 3.8) +const ApiMap aClientApiMap38[] = +{ + { "e_book_client_connect_direct_sync", reinterpret_cast<SymbolFunc *>(&e_book_client_connect_direct_sync) } +}; + +template<size_t N> static bool +tryLink( osl::Module &rModule, const char *pName, const ApiMap (&pMap)[N]) +{ + for (size_t i = 0; i < N; ++i) + { + SymbolFunc aMethod = reinterpret_cast<SymbolFunc>( + rModule.getFunctionSymbol(OUString::createFromAscii(pMap[i].sym_name))); + if( !aMethod ) + { + fprintf( stderr, "Warning: missing symbol '%s' in '%s'\n", + pMap[ i ].sym_name, pName ); + return false; + } + *pMap[ i ].ref_value = aMethod; + } + return true; +} + +bool EApiInit() +{ + for( guint j = 0; j < G_N_ELEMENTS( eBookLibNames ); j++ ) + { + osl::Module aModule(OUString::createFromAscii(eBookLibNames[j]), SAL_LOADMODULE_DEFAULT); + + if (!aModule.is()) + continue; + + if (tryLink( aModule, eBookLibNames[ j ], aCommonApiMap)) + { + if (tryLink( aModule, eBookLibNames[ j ], aNewApiMap)) + { + if (tryLink( aModule, eBookLibNames[ j ], aClientApiMap38)) + { + aModule.release(); + return true; + } + } + } + } + fprintf( stderr, "Can find no compliant libebook client libraries\n" ); + return false; +} + +ESourceRegistry *get_e_source_registry() +{ + static ESourceRegistry *theInstance = e_source_registry_new_sync(nullptr, nullptr); + return theInstance; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/connectivity/source/drivers/evoab2/EApi.h b/connectivity/source/drivers/evoab2/EApi.h new file mode 100644 index 000000000..9a2138eb2 --- /dev/null +++ b/connectivity/source/drivers/evoab2/EApi.h @@ -0,0 +1,160 @@ +/* -*- 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 . + */ + +#pragma once +#include <glib-object.h> + +// Initializes the API below, returns false if not available +bool EApiInit(); + +G_BEGIN_DECLS + +// This header defined all the API methods as +// function pointers instead of real functions +// this will all evaporate as it is compiled generating +// no symbol lookups or relocations, but giving code +// clarity. + +// We attempt to define a minimum API that we use: + +// e-contact.h +#ifdef DECLARE_FN_POINTERS +#define EAPI_EXTERN +#else +#define EAPI_EXTERN extern +#endif + + +typedef void EContact; +#define E_CONTACT(a) ((EContact *)(a)) +#define E_TYPE_CONTACT (e_contact_get_type()) +typedef int EContactField; + +EAPI_EXTERN const char *(*e_contact_field_name) ( EContactField field_id); +EAPI_EXTERN gpointer (*e_contact_get) (EContact *contact, EContactField field_id); +EAPI_EXTERN gconstpointer (*e_contact_get_const) (EContact *contact, EContactField field_id); +// e-source.h +typedef void ESource; +#define E_SOURCE(a) ((ESource *)(a)) +EAPI_EXTERN const char *(*e_source_peek_name) (ESource *source); +EAPI_EXTERN const gchar *(*e_source_get_property) (ESource *source, + const gchar *property); + +EAPI_EXTERN GType (*e_contact_get_type) (void); +EAPI_EXTERN EContactField (*e_contact_field_id) (const char *field_name); + +// e-source-list.h +typedef void ESourceList; +EAPI_EXTERN GSList *(*e_source_list_peek_groups) (ESourceList *list); + +// e-source-group.h +typedef void ESourceGroup; +#define E_SOURCE_GROUP(a) ((ESourceGroup *)(a)) + +EAPI_EXTERN GSList *(*e_source_group_peek_sources) (ESourceGroup *group); +EAPI_EXTERN const char *(*e_source_group_peek_base_uri) (ESourceGroup *group); +// e-book.h +typedef enum { + E_BOOK_QUERY_IS, + E_BOOK_QUERY_CONTAINS, + E_BOOK_QUERY_BEGINS_WITH, + E_BOOK_QUERY_ENDS_WITH, +} EBookQueryTest; + +typedef void EBook; +typedef void EBookQuery; + +EAPI_EXTERN EBook *(*e_book_new) (ESource *source, + GError **error); + +EAPI_EXTERN gboolean (*e_book_open) (EBook *book, + gboolean only_if_exists, + GError **error); + +EAPI_EXTERN const char *(*e_book_get_uri) (EBook *book); +EAPI_EXTERN ESource *(*e_book_get_source)(EBook *book); + +EAPI_EXTERN gboolean (*e_book_get_addressbooks) (ESourceList **addressbook_sources, + GError **error); + +EAPI_EXTERN gboolean (*e_book_get_contacts) (EBook *book, + EBookQuery *query, + GList **contacts, + GError **error); + +EAPI_EXTERN gboolean (*e_book_authenticate_user) (EBook *book, + const char *user, + const char *passwd, + const char *auth_method, + GError **error); + +// e-book-query.h +EAPI_EXTERN EBookQuery* (*e_book_query_field_exists) (EContactField field); +EAPI_EXTERN EBookQuery* (*e_book_query_field_test) (EContactField field, + EBookQueryTest test, + const char *value); +EAPI_EXTERN EBookQuery* (*e_book_query_and) (int nqs, EBookQuery **qs, gboolean unref); +EAPI_EXTERN EBookQuery* (*e_book_query_or) (int nqs, EBookQuery **qs, gboolean unref); +EAPI_EXTERN EBookQuery* (*e_book_query_not) (EBookQuery *q, gboolean unref); +EAPI_EXTERN EBookQuery* (*e_book_query_ref) (EBookQuery *q); +EAPI_EXTERN void (*e_book_query_unref) (EBookQuery *q); +EAPI_EXTERN char* (*e_book_query_to_string) (EBookQuery *q); +EAPI_EXTERN EBookQuery* (*e_book_query_from_string) (const char *query_string); + +typedef struct { + char *address_format; /* the two letter country code that + determines the format/meaning of the + following fields */ + char *po; + char *ext; + char *street; + char *locality; + char *region; + char *code; + char *country; +} EContactAddress; + +#define E_SOURCE_EXTENSION_ADDRESS_BOOK "Address Book" +typedef void ESourceRegistry; +typedef void GCancellable; +typedef void ESourceBackend; +typedef void EClient; +typedef EClient EBookClient; +EAPI_EXTERN ESourceRegistry* (*e_source_registry_new_sync) (GCancellable *cancellable, GError **error); +EAPI_EXTERN GList* (*e_source_registry_list_sources) (ESourceRegistry *registry, const gchar *extension_name); +EAPI_EXTERN gboolean (*e_source_has_extension) (ESource *source, const gchar *extension_name); +EAPI_EXTERN gpointer (*e_source_get_extension) (ESource *source, const gchar *extension_name); +EAPI_EXTERN const gchar* (*e_source_backend_get_backend_name) (ESourceBackend *extension); +EAPI_EXTERN const gchar* (*e_source_get_display_name) (ESource *source); +EAPI_EXTERN const gchar* (*eds_check_version) (guint required_major, guint required_minor, guint required_micro); +EAPI_EXTERN const gchar* (*e_source_get_uid) (ESource *source); +EAPI_EXTERN ESource* (*e_source_registry_ref_source) (ESourceRegistry *registry, const gchar *uid); +EAPI_EXTERN EBookClient* (*e_book_client_new) (ESource *source, GError **error); +EAPI_EXTERN EBookClient* (*e_book_client_connect_direct_sync) (ESourceRegistry *registry, ESource *source, guint32 wait_for_connected_seconds, GCancellable *cancellable, GError **error); +EAPI_EXTERN gboolean (*e_client_open_sync) (EClient *client, gboolean only_if_exists, GCancellable *cancellable, GError **error); +EAPI_EXTERN ESource* (*e_client_get_source) (EClient *client); +EAPI_EXTERN gboolean (*e_book_client_get_contacts_sync) (EBookClient *client, const gchar *sexp, GSList **contacts, GCancellable *cancellable, GError **error); +EAPI_EXTERN void (*e_client_util_free_object_slist) (GSList *objects); + +ESourceRegistry *get_e_source_registry(); +bool isSourceBackend(ESource *pSource, const char *backendname); + +G_END_DECLS + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/connectivity/source/drivers/evoab2/NCatalog.cxx b/connectivity/source/drivers/evoab2/NCatalog.cxx new file mode 100644 index 000000000..6b409ce66 --- /dev/null +++ b/connectivity/source/drivers/evoab2/NCatalog.cxx @@ -0,0 +1,86 @@ +/* -*- 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 "NCatalog.hxx" +#include "NConnection.hxx" +#include "NTables.hxx" +#include <com/sun/star/sdbc/XRow.hpp> +#include <com/sun/star/sdbc/XResultSet.hpp> + + +using namespace connectivity::evoab; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::lang; + +OEvoabCatalog::OEvoabCatalog(OEvoabConnection* _pCon) : + connectivity::sdbcx::OCatalog(_pCon) + ,m_pConnection(_pCon) +{ +} +void OEvoabCatalog::refreshTables() +{ + ::std::vector< OUString> aVector; + Sequence< OUString > aTypes { "TABLE" }; + 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 OEvoabTables(m_xMetaData,*this,m_aMutex,aVector) ); +} +// XTablesSupplier +Reference< XNameAccess > SAL_CALL OEvoabCatalog::getTables( ) +{ + ::osl::MutexGuard aGuard(m_aMutex); + + try + { + if (!m_pTables) + 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/evoab2/NCatalog.hxx b/connectivity/source/drivers/evoab2/NCatalog.hxx new file mode 100644 index 000000000..b2bd80844 --- /dev/null +++ b/connectivity/source/drivers/evoab2/NCatalog.hxx @@ -0,0 +1,43 @@ +/* -*- 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 . + */ + +#pragma once + +#include <sdbcx/VCatalog.hxx> + +namespace connectivity::evoab +{ + class OEvoabConnection; + class OEvoabCatalog : public connectivity::sdbcx::OCatalog + { + OEvoabConnection *m_pConnection; + public: + explicit OEvoabCatalog(OEvoabConnection *_pCon); + OEvoabConnection* getConnection() const { return m_pConnection; } + virtual void refreshTables() override; + virtual void refreshViews() override {} + virtual void refreshGroups() override {} + virtual void refreshUsers() override {} + // XTablesSupplier + virtual css::uno::Reference< css::container::XNameAccess > SAL_CALL getTables( + ) override; + }; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/connectivity/source/drivers/evoab2/NColumns.cxx b/connectivity/source/drivers/evoab2/NColumns.cxx new file mode 100644 index 000000000..5b2b64d5d --- /dev/null +++ b/connectivity/source/drivers/evoab2/NColumns.cxx @@ -0,0 +1,87 @@ +/* -*- 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 "NColumns.hxx" +#include "NTable.hxx" +#include <connectivity/sdbcx/VColumn.hxx> +#include <com/sun/star/sdbc/XRow.hpp> + +using namespace connectivity::sdbcx; +using namespace connectivity; +using namespace ::comphelper; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::lang; +using namespace connectivity::evoab; + + +sdbcx::ObjectType OEvoabColumns::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) + { + xRet = new OColumn( + _rName, + xRow->getString(6), + xRow->getString(13), + xRow->getString(12), + xRow->getInt(11), + xRow->getInt(7), + xRow->getInt(9), + xRow->getInt(5), + false, + false, + false, + true, + sCatalogName, + sSchemaName, + sTableName); + break; + } + } + } + + return xRet; +} + +void OEvoabColumns::impl_refresh() +{ + m_pTable->refreshColumns(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/connectivity/source/drivers/evoab2/NColumns.hxx b/connectivity/source/drivers/evoab2/NColumns.hxx new file mode 100644 index 000000000..f768c51bb --- /dev/null +++ b/connectivity/source/drivers/evoab2/NColumns.hxx @@ -0,0 +1,44 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include "NTable.hxx" +#include <connectivity/sdbcx/VCollection.hxx> + +namespace connectivity::evoab +{ + class OEvoabColumns final : public sdbcx::OCollection + { + OEvoabTable* m_pTable; + + virtual sdbcx::ObjectType createObject(const OUString& _rName) override; + virtual void impl_refresh() override; + + public: + OEvoabColumns( OEvoabTable* _pTable, + ::osl::Mutex& _rMutex, + const ::std::vector< OUString> &_rVector + ) : sdbcx::OCollection(*_pTable,true,_rMutex,_rVector), + m_pTable(_pTable) + { } + }; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/connectivity/source/drivers/evoab2/NConnection.cxx b/connectivity/source/drivers/evoab2/NConnection.cxx new file mode 100644 index 000000000..02e8d476d --- /dev/null +++ b/connectivity/source/drivers/evoab2/NConnection.cxx @@ -0,0 +1,242 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include "NConnection.hxx" +#include "NDatabaseMetaData.hxx" +#include "NCatalog.hxx" +#include <com/sun/star/sdbc/TransactionIsolation.hpp> +#include "NPreparedStatement.hxx" +#include "NStatement.hxx" +#include <connectivity/dbexception.hxx> +#include <rtl/ref.hxx> +#include <rtl/ustring.hxx> +#include <sal/log.hxx> + +using namespace connectivity::evoab; +using namespace dbtools; + + +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::lang; + +OEvoabConnection::OEvoabConnection(OEvoabDriver const & _rDriver) + : m_rDriver(_rDriver) + , m_eSDBCAddressType(SDBCAddress::EVO_LOCAL) +{ +} + +OEvoabConnection::~OEvoabConnection() +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + if(!isClosed()) { + acquire(); + close(); + } +} + + +// XServiceInfo + +IMPLEMENT_SERVICE_INFO(OEvoabConnection, "com.sun.star.sdbc.drivers.evoab.Connection", "com.sun.star.sdbc.Connection") + + +void OEvoabConnection::construct(const OUString& url, const Sequence< PropertyValue >& info) +{ + osl_atomic_increment( &m_refCount ); + SAL_INFO("connectivity.evoab2", "OEvoabConnection::construct()::url = " << url ); + + OUString sPassword; + const char pPwd[] = "password"; + + const PropertyValue *pIter = info.getConstArray(); + const PropertyValue *pEnd = pIter + info.getLength(); + for(;pIter != pEnd;++pIter) + { + if(pIter->Name == pPwd) + { + pIter->Value >>= sPassword; + break; + } + } + + if ( url == "sdbc:address:evolution:groupwise" ) + setSDBCAddressType(SDBCAddress::EVO_GWISE); + else if ( url == "sdbc:address:evolution:ldap" ) + setSDBCAddressType(SDBCAddress::EVO_LDAP); + else + setSDBCAddressType(SDBCAddress::EVO_LOCAL); + setURL(url); + setPassword(OUStringToOString(sPassword,RTL_TEXTENCODING_UTF8)); + osl_atomic_decrement( &m_refCount ); +} + + +OUString SAL_CALL OEvoabConnection::nativeSQL( const OUString& _sSql ) +{ + // when you need to transform SQL92 to you driver specific you can do it here + return _sSql; +} + +Reference< XDatabaseMetaData > SAL_CALL OEvoabConnection::getMetaData( ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(OConnection_BASE::rBHelper.bDisposed); + + Reference< XDatabaseMetaData > xMetaData = m_xMetaData; + if(!xMetaData.is()) + { + xMetaData = new OEvoabDatabaseMetaData(this); + m_xMetaData = xMetaData; + } + + return xMetaData; +} + +css::uno::Reference< XTablesSupplier > OEvoabConnection::createCatalog() +{ + ::osl::MutexGuard aGuard( m_aMutex ); + Reference< XTablesSupplier > xTab = m_xCatalog; + if(!xTab.is()) + { + xTab = new OEvoabCatalog(this); + m_xCatalog = xTab; + } + return xTab; +} + +Reference< XStatement > SAL_CALL OEvoabConnection::createStatement( ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(OConnection_BASE::rBHelper.bDisposed); + + Reference< XStatement > xStmt = new OStatement(this); + m_aStatements.push_back(WeakReferenceHelper(xStmt)); + return xStmt; +} + +Reference< XPreparedStatement > SAL_CALL OEvoabConnection::prepareStatement( const OUString& sql ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(OConnection_BASE::rBHelper.bDisposed); + + rtl::Reference<OEvoabPreparedStatement> pStmt = new OEvoabPreparedStatement( this ); + pStmt->construct( sql ); + + m_aStatements.push_back(WeakReferenceHelper(*pStmt)); + return pStmt; +} + +Reference< XPreparedStatement > SAL_CALL OEvoabConnection::prepareCall( const OUString& /*sql*/ ) +{ + ::dbtools::throwFeatureNotImplementedSQLException( "XConnection::prepareCall", *this ); + return nullptr; +} +sal_Bool SAL_CALL OEvoabConnection::isClosed( ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + return OConnection_BASE::rBHelper.bDisposed; +} + + +// XCloseable +void SAL_CALL OEvoabConnection::close( ) +{ + { // we just dispose us + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(OConnection_BASE::rBHelper.bDisposed); + } + dispose(); +} + + +// XWarningsSupplier +Any SAL_CALL OEvoabConnection::getWarnings( ) +{ + return m_aWarnings.getWarnings(); +} +void SAL_CALL OEvoabConnection::clearWarnings( ) +{ + m_aWarnings.clearWarnings(); +} + + +void OEvoabConnection::disposing() +{ + // we noticed that we should be destroyed in near future so we have to dispose our statements + ::osl::MutexGuard aGuard(m_aMutex); + OConnection_BASE::disposing(); +} + +// -------------------------------- stubbed methods ------------------------------------------------ +void SAL_CALL OEvoabConnection::setAutoCommit( sal_Bool /*autoCommit*/ ) +{ + ::dbtools::throwFeatureNotImplementedSQLException( "XConnection::setAutoCommit", *this ); +} +sal_Bool SAL_CALL OEvoabConnection::getAutoCommit( ) +{ + return true; +} +void SAL_CALL OEvoabConnection::commit( ) +{ +} +void SAL_CALL OEvoabConnection::rollback( ) +{ +} +void SAL_CALL OEvoabConnection::setReadOnly( sal_Bool /*readOnly*/ ) +{ + ::dbtools::throwFeatureNotImplementedSQLException( "XConnection::setReadOnly", *this ); +} +sal_Bool SAL_CALL OEvoabConnection::isReadOnly( ) +{ + return false; +} +void SAL_CALL OEvoabConnection::setCatalog( const OUString& /*catalog*/ ) +{ + ::dbtools::throwFeatureNotImplementedSQLException( "XConnection::setCatalog", *this ); +} + +OUString SAL_CALL OEvoabConnection::getCatalog( ) +{ + return OUString(); +} +void SAL_CALL OEvoabConnection::setTransactionIsolation( sal_Int32 /*level*/ ) +{ + ::dbtools::throwFeatureNotImplementedSQLException( "XConnection::setTransactionIsolation", *this ); +} + +sal_Int32 SAL_CALL OEvoabConnection::getTransactionIsolation( ) +{ + return TransactionIsolation::NONE; +} + +Reference< css::container::XNameAccess > SAL_CALL OEvoabConnection::getTypeMap( ) +{ + ::dbtools::throwFeatureNotImplementedSQLException( "XConnection::getTypeMap", *this ); + return nullptr; +} +void SAL_CALL OEvoabConnection::setTypeMap( const Reference< css::container::XNameAccess >& /*typeMap*/ ) +{ + ::dbtools::throwFeatureNotImplementedSQLException( "XConnection::setTypeMap", *this ); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/connectivity/source/drivers/evoab2/NConnection.hxx b/connectivity/source/drivers/evoab2/NConnection.hxx new file mode 100644 index 000000000..4d6604f09 --- /dev/null +++ b/connectivity/source/drivers/evoab2/NConnection.hxx @@ -0,0 +1,106 @@ +/* -*- 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 . + */ + +#pragma once + +#include "NDriver.hxx" +#include <com/sun/star/sdbc/SQLWarning.hpp> +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/sdbcx/XTablesSupplier.hpp> +#include <connectivity/CommonTools.hxx> +#include <connectivity/warningscontainer.hxx> +#include <TConnection.hxx> +#include <cppuhelper/weakref.hxx> +#include <osl/module.h> +#include "EApi.h" + +namespace connectivity::evoab { + + namespace SDBCAddress { + typedef enum { + Unknown = 0, + EVO_LOCAL = 1, + EVO_LDAP = 2, + EVO_GWISE = 3 + } sdbc_address_type; + } + + typedef connectivity::OMetaConnection OConnection_BASE; // implements basics and text encoding + + class OEvoabConnection final :public OConnection_BASE + { + private: + const OEvoabDriver& m_rDriver; + SDBCAddress::sdbc_address_type m_eSDBCAddressType; + css::uno::Reference< css::sdbcx::XTablesSupplier > + m_xCatalog; + OString m_aPassword; + ::dbtools::WarningsContainer m_aWarnings; + + virtual ~OEvoabConnection() override; + + public: + explicit OEvoabConnection( OEvoabDriver const & _rDriver ); + /// @throws css::sdbc::SQLException + void construct(const OUString& _rUrl,const css::uno::Sequence< css::beans::PropertyValue >& _rInfo ); + + OString const & getPassword() const { return m_aPassword; } + void setPassword( OString const & aStr ) { m_aPassword = aStr; } + // own methods + const OEvoabDriver& getDriver() const { return m_rDriver; } + + SDBCAddress::sdbc_address_type getSDBCAddressType() const { return m_eSDBCAddressType;} + void setSDBCAddressType(SDBCAddress::sdbc_address_type _eSDBCAddressType) {m_eSDBCAddressType = _eSDBCAddressType;} + + // OComponentHelper + virtual void SAL_CALL disposing() override; + + // XServiceInfo + DECLARE_SERVICE_INFO(); + + // XConnection + css::uno::Reference< css::sdbcx::XTablesSupplier > createCatalog(); + 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; + }; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/connectivity/source/drivers/evoab2/NDatabaseMetaData.cxx b/connectivity/source/drivers/evoab2/NDatabaseMetaData.cxx new file mode 100644 index 000000000..dbb8cb447 --- /dev/null +++ b/connectivity/source/drivers/evoab2/NDatabaseMetaData.cxx @@ -0,0 +1,1157 @@ +/* -*- 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 "NDatabaseMetaData.hxx" +#include <com/sun/star/sdbc/DataType.hpp> +#include <com/sun/star/sdbc/TransactionIsolation.hpp> +#include <connectivity/dbexception.hxx> +#include <connectivity/FValue.hxx> +#include <com/sun/star/sdbc/ColumnSearch.hpp> +#include <rtl/ref.hxx> + +#include <cstddef> +#include <string.h> +#include <string_view> + +#include "EApi.h" + +using namespace connectivity::evoab; +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::sdbcx; + +namespace +{ + bool equal(const char *str1, const char *str2) + { + return str1 == nullptr || str2 == nullptr ? str1 == str2 : strcmp(str1, str2) == 0; + } +} + +namespace connectivity::evoab +{ + sal_Int32 const s_nCOLUMN_SIZE = 256; + sal_Int32 const s_nDECIMAL_DIGITS = 0; + sal_Int32 const s_nNULLABLE = 1; + sal_Int32 const s_nCHAR_OCTET_LENGTH = 65535; + + static ColumnProperty **pFields=nullptr; + static guint nFields = 0; + + static const char *pDenyList[] = + { + "id", + "list-show-addresses", + "address-label-home", + "address-label-work", + "address-label-other" + }; + + const SplitEvoColumns* get_evo_addr() + { + static const SplitEvoColumns evo_addr[] = { + {"addr-line1",DEFAULT_ADDR_LINE1},{"addr-line2",DEFAULT_ADDR_LINE2},{"city",DEFAULT_CITY},{"state",DEFAULT_STATE},{"country",DEFAULT_COUNTRY},{"zip",DEFAULT_ZIP}, + {"work-addr-line1",WORK_ADDR_LINE1},{"work-addr-line2",WORK_ADDR_LINE2},{"work-city",WORK_CITY},{"work-state",WORK_STATE},{"work-country",WORK_COUNTRY},{"work-zip",WORK_ZIP}, + {"home-addr-line1",HOME_ADDR_LINE1},{"home-addr-line2",HOME_ADDR_LINE2},{"home-addr-City",HOME_CITY},{"home-state",HOME_STATE},{"home-country",HOME_COUNTRY},{"home-zip",HOME_ZIP}, + {"other-addr-line1",OTHER_ADDR_LINE1},{"other-addr-line2",OTHER_ADDR_LINE2},{"other-addr-city",OTHER_CITY},{"other-addr-state",OTHER_STATE},{"other-addr-country",OTHER_COUNTRY},{"other-addr-zip",OTHER_ZIP} + }; + return evo_addr; + } + + static void + splitColumn (ColumnProperty **pToBeFields) + { + const SplitEvoColumns* evo_addr( get_evo_addr() ); + for (int i = 0; i < OTHER_ZIP; i++) + { + pToBeFields[nFields] = g_new0(ColumnProperty,1); + pToBeFields[nFields]->bIsSplittedValue = true; + pToBeFields[nFields]->pField = g_param_spec_ref(g_param_spec_string (evo_addr[i].pColumnName,evo_addr[i].pColumnName,"",nullptr,G_PARAM_WRITABLE)); + nFields++; + } + } + + static void + initFields() + { + if( pFields ) + return; + + ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ); + if( pFields ) + return; + + guint nProps; + ColumnProperty **pToBeFields; + GParamSpec **pProps; + nFields = 0; + pProps = g_object_class_list_properties + ( static_cast<GObjectClass *>(g_type_class_ref( E_TYPE_CONTACT )), + &nProps ); + pToBeFields = g_new0(ColumnProperty *, (nProps + OTHER_ZIP)/* new column(s)*/ ); + for ( guint i = 0; i < nProps; i++ ) + { + switch (pProps[i]->value_type) + { + case G_TYPE_STRING: + case G_TYPE_BOOLEAN: + { + bool bAdd = true; + const char *pName = g_param_spec_get_name( pProps[i] ); + for (unsigned int j = 0; j < G_N_ELEMENTS( pDenyList ); j++ ) + { + if( !strcmp( pDenyList[j], pName ) ) + { + bAdd = false; + break; + } + } + if( bAdd ) + { + pToBeFields[nFields]= g_new0(ColumnProperty,1); + pToBeFields[nFields]->bIsSplittedValue=false; + pToBeFields[ nFields++ ]->pField = g_param_spec_ref( pProps[i] ); + } + break; + } + default: + break; + } + } + + splitColumn(pToBeFields); + pFields = pToBeFields; + } + + + const ColumnProperty * + getField(guint n) + { + initFields(); + if( n < nFields ) + return pFields[n]; + else + return nullptr; + } + + GType + getGFieldType( guint nCol ) + { + initFields(); + + if ( nCol < nFields ) + return pFields[nCol]->pField->value_type; + return G_TYPE_STRING; + } + + sal_Int32 + getFieldType( guint nCol ) + { + sal_Int32 nType = getGFieldType( nCol ); + return nType == G_TYPE_STRING ? DataType::VARCHAR : DataType::BIT; + } + + guint findEvoabField(std::u16string_view aColName) + { + guint nRet = guint(-1); + bool bFound = false; + initFields(); + for (guint i=0;(i < nFields) && !bFound;i++) + { + OUString aName = getFieldName(i); + if (aName == aColName) + { + nRet = i; + bFound = true; + } + } + return nRet; + } + + OUString + getFieldTypeName( guint nCol ) + { + switch( getFieldType( nCol ) ) + { + case DataType::BIT: + return "BIT"; + case DataType::VARCHAR: + return "VARCHAR"; + default: + break; + } + return OUString(); + } + + OUString + getFieldName( guint nCol ) + { + const GParamSpec *pSpec = getField( nCol )->pField; + OUString aName; + initFields(); + + if( pSpec ) + { + aName = OStringToOUString( g_param_spec_get_name( const_cast<GParamSpec *>(pSpec) ), + RTL_TEXTENCODING_UTF8 ); + aName = aName.replace( '-', '_' ); + } + return aName; + } + + void + free_column_resources() + { + for (int i=nFields-1;i > 0;i--) + { + if (pFields && pFields[i] ) + { + if (pFields[i]->pField) + g_param_spec_unref(pFields[i]->pField); + g_free(pFields[i]); + } + } + if(pFields) + { + g_free(pFields); + pFields=nullptr; + } + + } + + +} + + +OEvoabDatabaseMetaData::OEvoabDatabaseMetaData(OEvoabConnection* _pCon) + : ::connectivity::ODatabaseMetaDataBase(_pCon, _pCon->getConnectionInfo()) + ,m_pConnection(_pCon) +{ + OSL_ENSURE(m_pConnection,"OEvoabDatabaseMetaData::OEvoabDatabaseMetaData: No connection set!"); +} +OEvoabDatabaseMetaData::~OEvoabDatabaseMetaData() +{ +} + + +Reference< XResultSet > SAL_CALL OEvoabDatabaseMetaData::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 + rtl::Reference<ODatabaseMetaDataResultSet> pResultSet = new ODatabaseMetaDataResultSet( ODatabaseMetaDataResultSet::eColumns ); + + ODatabaseMetaDataResultSet::ORows aRows; + ODatabaseMetaDataResultSet::ORow aRow(19); + + // **************************************************** + // Some entries in a row never change, so set them now + // **************************************************** + + // Catalog + aRow[1] = new ORowSetValueDecorator(OUString()); + // Schema + aRow[2] = new ORowSetValueDecorator(OUString()); + // 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(); + // COLUMN_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")); + + + aRow[3] = new ORowSetValueDecorator(OUString("TABLE")); + ::osl::MutexGuard aGuard( m_aMutex ); + + initFields(); + for (sal_Int32 i = 0; i < static_cast<sal_Int32>(nFields); i++) + { + if( match( columnNamePattern, getFieldName( i ), '\0' ) ) + { + aRow[5] = new ORowSetValueDecorator( static_cast<sal_Int16>( getFieldType( i ) ) ); + aRow[6] = new ORowSetValueDecorator( getFieldTypeName( i ) ); + + // COLUMN_NAME + aRow[4] = new ORowSetValueDecorator( getFieldName( i ) ); + // ORDINAL_POSITION + aRow[17] = new ORowSetValueDecorator( i ); + aRows.push_back( aRow ); + } + } + + pResultSet->setRows(std::move(aRows)); + + return pResultSet; +} + +OUString OEvoabDatabaseMetaData::impl_getCatalogSeparator_throw( ) +{ + return OUString(); +} + +sal_Int32 SAL_CALL OEvoabDatabaseMetaData::getMaxBinaryLiteralLength( ) +{ + return 0;// 0 means no limit +} + +sal_Int32 SAL_CALL OEvoabDatabaseMetaData::getMaxRowSize( ) +{ + return 0;// 0 means no limit +} + +sal_Int32 SAL_CALL OEvoabDatabaseMetaData::getMaxCatalogNameLength( ) +{ + return 0;// 0 means no limit +} + +sal_Int32 SAL_CALL OEvoabDatabaseMetaData::getMaxCharLiteralLength( ) +{ + return 0;// 0 means no limit +} + +sal_Int32 SAL_CALL OEvoabDatabaseMetaData::getMaxColumnNameLength( ) +{ + return 0;// 0 means no limit +} + +sal_Int32 SAL_CALL OEvoabDatabaseMetaData::getMaxColumnsInIndex( ) +{ + return 0;// 0 means no limit +} + +sal_Int32 SAL_CALL OEvoabDatabaseMetaData::getMaxCursorNameLength( ) +{ + return 0;// 0 means no limit +} + +sal_Int32 SAL_CALL OEvoabDatabaseMetaData::getMaxConnections( ) +{ + return 0;// 0 means no limit +} + +sal_Int32 SAL_CALL OEvoabDatabaseMetaData::getMaxColumnsInTable( ) +{ + return 0;// 0 means no limit +} + +sal_Int32 OEvoabDatabaseMetaData::impl_getMaxStatements_throw( ) +{ + return 0;// 0 means no limit +} + +sal_Int32 SAL_CALL OEvoabDatabaseMetaData::getMaxTableNameLength( ) +{ + return 0;// 0 means no limit +} + +sal_Int32 OEvoabDatabaseMetaData::impl_getMaxTablesInSelect_throw( ) +{ + // We only support a single table + return 1; +} + + +sal_Bool SAL_CALL OEvoabDatabaseMetaData::doesMaxRowSizeIncludeBlobs( ) +{ + return false; +} + +sal_Bool SAL_CALL OEvoabDatabaseMetaData::storesLowerCaseQuotedIdentifiers( ) +{ + return false; +} + +sal_Bool SAL_CALL OEvoabDatabaseMetaData::storesLowerCaseIdentifiers( ) +{ + return false; +} + +bool OEvoabDatabaseMetaData::impl_storesMixedCaseQuotedIdentifiers_throw( ) +{ + return false; +} + +sal_Bool SAL_CALL OEvoabDatabaseMetaData::storesMixedCaseIdentifiers( ) +{ + return false; +} + +sal_Bool SAL_CALL OEvoabDatabaseMetaData::storesUpperCaseQuotedIdentifiers( ) +{ + return false; +} + +sal_Bool SAL_CALL OEvoabDatabaseMetaData::storesUpperCaseIdentifiers( ) +{ + return false; +} + +bool OEvoabDatabaseMetaData::impl_supportsAlterTableWithAddColumn_throw( ) +{ + return false; +} + +bool OEvoabDatabaseMetaData::impl_supportsAlterTableWithDropColumn_throw( ) +{ + return false; +} + +sal_Int32 SAL_CALL OEvoabDatabaseMetaData::getMaxIndexLength( ) +{ + return 0;// 0 means no limit +} + +sal_Bool SAL_CALL OEvoabDatabaseMetaData::supportsNonNullableColumns( ) +{ + return false; +} + +OUString SAL_CALL OEvoabDatabaseMetaData::getCatalogTerm( ) +{ + return OUString(); +} + +OUString OEvoabDatabaseMetaData::impl_getIdentifierQuoteString_throw( ) +{ + // normally this is " + return "\""; +} + +OUString SAL_CALL OEvoabDatabaseMetaData::getExtraNameCharacters( ) +{ + return OUString(); +} + +sal_Bool SAL_CALL OEvoabDatabaseMetaData::supportsDifferentTableCorrelationNames( ) +{ + return false; +} + +bool OEvoabDatabaseMetaData::impl_isCatalogAtStart_throw( ) +{ + return false; +} + +sal_Bool SAL_CALL OEvoabDatabaseMetaData::dataDefinitionIgnoredInTransactions( ) +{ + return true; +} + +sal_Bool SAL_CALL OEvoabDatabaseMetaData::dataDefinitionCausesTransactionCommit( ) +{ + return true; +} + +sal_Bool SAL_CALL OEvoabDatabaseMetaData::supportsDataManipulationTransactionsOnly( ) +{ + return true; +} + +sal_Bool SAL_CALL OEvoabDatabaseMetaData::supportsDataDefinitionAndDataManipulationTransactions( ) +{ + return true; +} + +sal_Bool SAL_CALL OEvoabDatabaseMetaData::supportsPositionedDelete( ) +{ + return false; +} + +sal_Bool SAL_CALL OEvoabDatabaseMetaData::supportsPositionedUpdate( ) +{ + return false; +} + +sal_Bool SAL_CALL OEvoabDatabaseMetaData::supportsOpenStatementsAcrossRollback( ) +{ + return false; +} + +sal_Bool SAL_CALL OEvoabDatabaseMetaData::supportsOpenStatementsAcrossCommit( ) +{ + return false; +} + +sal_Bool SAL_CALL OEvoabDatabaseMetaData::supportsOpenCursorsAcrossCommit( ) +{ + return false; +} + +sal_Bool SAL_CALL OEvoabDatabaseMetaData::supportsOpenCursorsAcrossRollback( ) +{ + return false; +} + +sal_Bool SAL_CALL OEvoabDatabaseMetaData::supportsTransactionIsolationLevel( sal_Int32 /*level*/ ) +{ + return false; +} + +bool OEvoabDatabaseMetaData::impl_supportsSchemasInDataManipulation_throw( ) +{ + return false; +} + +sal_Bool SAL_CALL OEvoabDatabaseMetaData::supportsANSI92FullSQL( ) +{ + return false; +} + +sal_Bool SAL_CALL OEvoabDatabaseMetaData::supportsANSI92EntryLevelSQL( ) +{ + return true; // should be supported at least +} + +sal_Bool SAL_CALL OEvoabDatabaseMetaData::supportsIntegrityEnhancementFacility( ) +{ + return false; +} + +sal_Bool SAL_CALL OEvoabDatabaseMetaData::supportsSchemasInIndexDefinitions( ) +{ + return false; +} + +bool OEvoabDatabaseMetaData::impl_supportsSchemasInTableDefinitions_throw( ) +{ + return false; +} + +bool OEvoabDatabaseMetaData::impl_supportsCatalogsInTableDefinitions_throw( ) +{ + return false; +} + +sal_Bool SAL_CALL OEvoabDatabaseMetaData::supportsCatalogsInIndexDefinitions( ) +{ + return false; +} + +bool OEvoabDatabaseMetaData::impl_supportsCatalogsInDataManipulation_throw( ) +{ + return false; +} + +sal_Bool SAL_CALL OEvoabDatabaseMetaData::supportsOuterJoins( ) +{ + return false; +} + +sal_Int32 SAL_CALL OEvoabDatabaseMetaData::getMaxStatementLength( ) +{ + return 0;// 0 means no limit +} + +sal_Int32 SAL_CALL OEvoabDatabaseMetaData::getMaxProcedureNameLength( ) +{ + return 0;// 0 means no limit +} + +sal_Int32 SAL_CALL OEvoabDatabaseMetaData::getMaxSchemaNameLength( ) +{ + return 0;// 0 means no limit +} + +sal_Bool SAL_CALL OEvoabDatabaseMetaData::supportsTransactions( ) +{ + return false; +} + +sal_Bool SAL_CALL OEvoabDatabaseMetaData::allProceduresAreCallable( ) +{ + return false; +} + +sal_Bool SAL_CALL OEvoabDatabaseMetaData::supportsStoredProcedures( ) +{ + return false; +} + +sal_Bool SAL_CALL OEvoabDatabaseMetaData::supportsSelectForUpdate( ) +{ + return false; +} + +sal_Bool SAL_CALL OEvoabDatabaseMetaData::allTablesAreSelectable( ) +{ + // We allow you to select from any table. + return true; +} + +sal_Bool SAL_CALL OEvoabDatabaseMetaData::isReadOnly( ) +{ + // For now definitely read-only, no support for update/delete + return true; +} + +sal_Bool SAL_CALL OEvoabDatabaseMetaData::usesLocalFiles( ) +{ + return false; +} + +sal_Bool SAL_CALL OEvoabDatabaseMetaData::usesLocalFilePerTable( ) +{ + return false; +} + +sal_Bool SAL_CALL OEvoabDatabaseMetaData::supportsTypeConversion( ) +{ + return false; +} + +sal_Bool SAL_CALL OEvoabDatabaseMetaData::nullPlusNonNullIsNull( ) +{ + return false; +} + +sal_Bool SAL_CALL OEvoabDatabaseMetaData::supportsColumnAliasing( ) +{ + // todo add Support for this. + return false; +} + +sal_Bool SAL_CALL OEvoabDatabaseMetaData::supportsTableCorrelationNames( ) +{ + return false; +} + +sal_Bool SAL_CALL OEvoabDatabaseMetaData::supportsConvert( sal_Int32 /*fromType*/, sal_Int32 /*toType*/ ) +{ + return false; +} + +sal_Bool SAL_CALL OEvoabDatabaseMetaData::supportsExpressionsInOrderBy( ) +{ + return false; +} + +sal_Bool SAL_CALL OEvoabDatabaseMetaData::supportsGroupBy( ) +{ + return false; +} + +sal_Bool SAL_CALL OEvoabDatabaseMetaData::supportsGroupByBeyondSelect( ) +{ + return false; +} + +sal_Bool SAL_CALL OEvoabDatabaseMetaData::supportsGroupByUnrelated( ) +{ + return false; +} + +sal_Bool SAL_CALL OEvoabDatabaseMetaData::supportsMultipleTransactions( ) +{ + return false; +} + +sal_Bool SAL_CALL OEvoabDatabaseMetaData::supportsMultipleResultSets( ) +{ + return false; +} + +sal_Bool SAL_CALL OEvoabDatabaseMetaData::supportsLikeEscapeClause( ) +{ + return false; +} + +sal_Bool SAL_CALL OEvoabDatabaseMetaData::supportsOrderByUnrelated( ) +{ + return false; +} + +sal_Bool SAL_CALL OEvoabDatabaseMetaData::supportsUnion( ) +{ + return false; +} + +sal_Bool SAL_CALL OEvoabDatabaseMetaData::supportsUnionAll( ) +{ + return false; +} + +sal_Bool SAL_CALL OEvoabDatabaseMetaData::supportsMixedCaseIdentifiers( ) +{ + return false; +} + +bool OEvoabDatabaseMetaData::impl_supportsMixedCaseQuotedIdentifiers_throw( ) +{ + // Any case may be used + return true; +} + +sal_Bool SAL_CALL OEvoabDatabaseMetaData::nullsAreSortedAtEnd( ) +{ + return false; +} + +sal_Bool SAL_CALL OEvoabDatabaseMetaData::nullsAreSortedAtStart( ) +{ + return true; +} + +sal_Bool SAL_CALL OEvoabDatabaseMetaData::nullsAreSortedHigh( ) +{ + return false; +} + +sal_Bool SAL_CALL OEvoabDatabaseMetaData::nullsAreSortedLow( ) +{ + return true; +} + +sal_Bool SAL_CALL OEvoabDatabaseMetaData::supportsSchemasInProcedureCalls( ) +{ + return false; +} + +sal_Bool SAL_CALL OEvoabDatabaseMetaData::supportsSchemasInPrivilegeDefinitions( ) +{ + return false; +} + +sal_Bool SAL_CALL OEvoabDatabaseMetaData::supportsCatalogsInProcedureCalls( ) +{ + return false; +} + +sal_Bool SAL_CALL OEvoabDatabaseMetaData::supportsCatalogsInPrivilegeDefinitions( ) +{ + return false; +} + +sal_Bool SAL_CALL OEvoabDatabaseMetaData::supportsCorrelatedSubqueries( ) +{ + return false; +} + +sal_Bool SAL_CALL OEvoabDatabaseMetaData::supportsSubqueriesInComparisons( ) +{ + return false; +} + +sal_Bool SAL_CALL OEvoabDatabaseMetaData::supportsSubqueriesInExists( ) +{ + return false; +} + +sal_Bool SAL_CALL OEvoabDatabaseMetaData::supportsSubqueriesInIns( ) +{ + return false; +} + +sal_Bool SAL_CALL OEvoabDatabaseMetaData::supportsSubqueriesInQuantifieds( ) +{ + return false; +} + +sal_Bool SAL_CALL OEvoabDatabaseMetaData::supportsANSI92IntermediateSQL( ) +{ + return false; +} + +OUString SAL_CALL OEvoabDatabaseMetaData::getURL( ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + return m_pConnection->getURL(); +} + +OUString SAL_CALL OEvoabDatabaseMetaData::getUserName( ) +{ + return OUString(); +} + +OUString SAL_CALL OEvoabDatabaseMetaData::getDriverName( ) +{ + return OUString(); +} + +OUString SAL_CALL OEvoabDatabaseMetaData::getDriverVersion() +{ + return "1"; +} + +OUString SAL_CALL OEvoabDatabaseMetaData::getDatabaseProductVersion( ) +{ + return "0"; +} + +OUString SAL_CALL OEvoabDatabaseMetaData::getDatabaseProductName( ) +{ + return OUString(); +} + +OUString SAL_CALL OEvoabDatabaseMetaData::getProcedureTerm( ) +{ + return OUString(); +} + +OUString SAL_CALL OEvoabDatabaseMetaData::getSchemaTerm( ) +{ + return OUString(); +} + +sal_Int32 SAL_CALL OEvoabDatabaseMetaData::getDriverMajorVersion( ) +{ + return 1; +} + +sal_Int32 SAL_CALL OEvoabDatabaseMetaData::getDefaultTransactionIsolation( ) +{ + return TransactionIsolation::NONE; +} + +sal_Int32 SAL_CALL OEvoabDatabaseMetaData::getDriverMinorVersion( ) +{ + return 0; +} + +OUString SAL_CALL OEvoabDatabaseMetaData::getSQLKeywords( ) +{ + return OUString(); +} + +OUString SAL_CALL OEvoabDatabaseMetaData::getSearchStringEscape( ) +{ + return OUString(); +} + +OUString SAL_CALL OEvoabDatabaseMetaData::getStringFunctions( ) +{ + return OUString(); +} + +OUString SAL_CALL OEvoabDatabaseMetaData::getTimeDateFunctions( ) +{ + return OUString(); +} + +OUString SAL_CALL OEvoabDatabaseMetaData::getSystemFunctions( ) +{ + return OUString(); +} + +OUString SAL_CALL OEvoabDatabaseMetaData::getNumericFunctions( ) +{ + return OUString(); +} + +sal_Bool SAL_CALL OEvoabDatabaseMetaData::supportsExtendedSQLGrammar( ) +{ + return false; +} + +sal_Bool SAL_CALL OEvoabDatabaseMetaData::supportsCoreSQLGrammar( ) +{ + return false; +} + +sal_Bool SAL_CALL OEvoabDatabaseMetaData::supportsMinimumSQLGrammar( ) +{ + return true; +} + +sal_Bool SAL_CALL OEvoabDatabaseMetaData::supportsFullOuterJoins( ) +{ + return false; +} + +sal_Bool SAL_CALL OEvoabDatabaseMetaData::supportsLimitedOuterJoins( ) +{ + return false; +} + +sal_Int32 SAL_CALL OEvoabDatabaseMetaData::getMaxColumnsInGroupBy( ) +{ + return 0;// 0 means no limit +} + +sal_Int32 SAL_CALL OEvoabDatabaseMetaData::getMaxColumnsInOrderBy( ) +{ + return 0;// 0 means no limit +} + +sal_Int32 SAL_CALL OEvoabDatabaseMetaData::getMaxColumnsInSelect( ) +{ + return 0;// 0 means no limit +} + +sal_Int32 SAL_CALL OEvoabDatabaseMetaData::getMaxUserNameLength( ) +{ + return 0;// 0 means no limit +} + +sal_Bool SAL_CALL OEvoabDatabaseMetaData::supportsResultSetType( sal_Int32 /*setType*/ ) +{ + return false; +} + +sal_Bool SAL_CALL OEvoabDatabaseMetaData::supportsResultSetConcurrency( sal_Int32 /*setType*/, sal_Int32 /*concurrency*/ ) +{ + return false; +} + +sal_Bool SAL_CALL OEvoabDatabaseMetaData::ownUpdatesAreVisible( sal_Int32 /*setType*/ ) +{ + return false; +} + +sal_Bool SAL_CALL OEvoabDatabaseMetaData::ownDeletesAreVisible( sal_Int32 /*setType*/ ) +{ + return false; +} + +sal_Bool SAL_CALL OEvoabDatabaseMetaData::ownInsertsAreVisible( sal_Int32 /*setType*/ ) +{ + return false; +} + +sal_Bool SAL_CALL OEvoabDatabaseMetaData::othersUpdatesAreVisible( sal_Int32 /*setType*/ ) +{ + return false; +} + +sal_Bool SAL_CALL OEvoabDatabaseMetaData::othersDeletesAreVisible( sal_Int32 /*setType*/ ) +{ + return false; +} + +sal_Bool SAL_CALL OEvoabDatabaseMetaData::othersInsertsAreVisible( sal_Int32 /*setType*/ ) +{ + return false; +} + +sal_Bool SAL_CALL OEvoabDatabaseMetaData::updatesAreDetected( sal_Int32 /*setType*/ ) +{ + return false; +} + +sal_Bool SAL_CALL OEvoabDatabaseMetaData::deletesAreDetected( sal_Int32 /*setType*/ ) +{ + return false; +} + +sal_Bool SAL_CALL OEvoabDatabaseMetaData::insertsAreDetected( sal_Int32 /*setType*/ ) +{ + return false; +} + +sal_Bool SAL_CALL OEvoabDatabaseMetaData::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 OEvoabDatabaseMetaData::getTableTypes( ) +{ + /* Don't need to change as evoab driver supports only table */ + + // there exists no possibility to get table types so we have to check + static const std::u16string_view sTableTypes[] = + { + u"TABLE" // Currently we only support a 'TABLE' nothing more complex + }; + rtl::Reference<::connectivity::ODatabaseMetaDataResultSet> pResult = new ::connectivity::ODatabaseMetaDataResultSet(::connectivity::ODatabaseMetaDataResultSet::eTableTypes); + + // here we fill the rows which should be visible when ask for data from the resultset returned here + auto nNbTypes = std::size(sTableTypes); + ODatabaseMetaDataResultSet::ORows aRows; + for(std::size_t i=0;i < nNbTypes;++i) + { + // bound row + aRows.push_back( { ODatabaseMetaDataResultSet::getEmptyValue(), new ORowSetValueDecorator(OUString(sTableTypes[i])) }); + } + // here we set the rows at the resultset + pResult->setRows(std::move(aRows)); + return pResult; +} + +Reference< XResultSet > OEvoabDatabaseMetaData::impl_getTypeInfo_throw( ) +{ + /* + * Return the proper type information required by evo driver + */ + + rtl::Reference<ODatabaseMetaDataResultSet> pResultSet = new ODatabaseMetaDataResultSet(ODatabaseMetaDataResultSet::eTypeInfo); + + static ODatabaseMetaDataResultSet::ORows aRows = []() + { + ODatabaseMetaDataResultSet::ORows tmp; + ODatabaseMetaDataResultSet::ORow aRow + { + ODatabaseMetaDataResultSet::getEmptyValue() , + new ORowSetValueDecorator(OUString("VARCHAR")) , + new ORowSetValueDecorator(DataType::VARCHAR) , + new ORowSetValueDecorator(sal_Int32(s_nCHAR_OCTET_LENGTH)) , + ODatabaseMetaDataResultSet::getQuoteValue() , + ODatabaseMetaDataResultSet::getQuoteValue() , + ODatabaseMetaDataResultSet::getEmptyValue() , + ODatabaseMetaDataResultSet::get1Value() , + ODatabaseMetaDataResultSet::get1Value() , + new ORowSetValueDecorator(sal_Int32(ColumnSearch::FULL)) , + ODatabaseMetaDataResultSet::get1Value() , + ODatabaseMetaDataResultSet::get0Value() , + ODatabaseMetaDataResultSet::get0Value() , + ODatabaseMetaDataResultSet::getEmptyValue() , + ODatabaseMetaDataResultSet::get0Value() , + ODatabaseMetaDataResultSet::get0Value() , + ODatabaseMetaDataResultSet::getEmptyValue() , + ODatabaseMetaDataResultSet::getEmptyValue() , + new ORowSetValueDecorator(sal_Int32(10)) + }; + + tmp.push_back(aRow); + + aRow[1] = new ORowSetValueDecorator(OUString("VARCHAR")); + aRow[2] = new ORowSetValueDecorator(DataType::VARCHAR); + aRow[3] = new ORowSetValueDecorator(sal_Int32(65535)); + tmp.push_back(aRow); + return tmp; + }(); + pResultSet->setRows(std::move(aRows)); + return pResultSet; +} + +bool isSourceBackend(ESource *pSource, const char *backendname) +{ + if (!pSource || !e_source_has_extension (pSource, E_SOURCE_EXTENSION_ADDRESS_BOOK)) + return false; + + gpointer extension = e_source_get_extension (pSource, E_SOURCE_EXTENSION_ADDRESS_BOOK); + return extension && equal(e_source_backend_get_backend_name (extension), backendname); +} + +Reference< XResultSet > SAL_CALL OEvoabDatabaseMetaData::getTables( + const Any& /*catalog*/, const OUString& /*schemaPattern*/, + const OUString& /*tableNamePattern*/, const Sequence< OUString >& types ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + rtl::Reference<ODatabaseMetaDataResultSet> pResult = new ODatabaseMetaDataResultSet(ODatabaseMetaDataResultSet::eTables); + + // check if any type is given + // when no types are given then we have to return all tables e.g. TABLE + + static const OUStringLiteral aTable(u"TABLE"); + + bool bTableFound = true; + sal_Int32 nLength = types.getLength(); + if(nLength) + { + bTableFound = false; + + const OUString* pBegin = types.getConstArray(); + const OUString* pEnd = pBegin + nLength; + for(;pBegin != pEnd;++pBegin) + { + if(*pBegin == aTable) + { + bTableFound = true; + break; + } + } + } + if(!bTableFound) + return pResult; + + ODatabaseMetaDataResultSet::ORows aRows; + + GList *pSources = e_source_registry_list_sources(get_e_source_registry(), E_SOURCE_EXTENSION_ADDRESS_BOOK); + + for (GList* liter = pSources; liter; liter = liter->next) + { + ESource *pSource = E_SOURCE (liter->data); + bool can = false; + switch (m_pConnection->getSDBCAddressType()) + { + case SDBCAddress::EVO_GWISE: + can = isSourceBackend( pSource, "groupwise"); // not supported in evo/eds 3.6.x+, somehow + break; + case SDBCAddress::EVO_LOCAL: + can = isSourceBackend( pSource, "local"); + break; + case SDBCAddress::EVO_LDAP: + can = isSourceBackend( pSource, "ldap"); + break; + case SDBCAddress::Unknown: + can = true; + break; + } + if (!can) + continue; + + OUString aHumanName = OStringToOUString( e_source_get_display_name( pSource ), + RTL_TEXTENCODING_UTF8 ); + OUString aUID = OStringToOUString( e_source_get_uid( pSource ), + RTL_TEXTENCODING_UTF8 ); + ODatabaseMetaDataResultSet::ORow aRow{ + ORowSetValueDecoratorRef(), + ORowSetValueDecoratorRef(), + ORowSetValueDecoratorRef(), + new ORowSetValueDecorator(aHumanName), //tablename + new ORowSetValueDecorator(ORowSetValue(aTable)), + new ORowSetValueDecorator(aUID)}; //comment + //I'd prefer to swap the comment and the human name and + //just use e_source_registry_ref_source(get_e_source_registry(), aUID); + //in open book rather than search for the name again + aRows.push_back(aRow); + } + + g_list_foreach (pSources, reinterpret_cast<GFunc>(g_object_unref), nullptr); + g_list_free (pSources); + + pResult->setRows(std::move(aRows)); + + return pResult; +} + +Reference< XResultSet > SAL_CALL OEvoabDatabaseMetaData::getUDTs( const Any& /*catalog*/, const OUString& /*schemaPattern*/, const OUString& /*typeNamePattern*/, const Sequence< sal_Int32 >& /*types*/ ) +{ + ::dbtools::throwFeatureNotImplementedSQLException( "XDatabaseMetaDaza::getUDTs", *this ); + return nullptr; +} + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/connectivity/source/drivers/evoab2/NDatabaseMetaData.hxx b/connectivity/source/drivers/evoab2/NDatabaseMetaData.hxx new file mode 100644 index 000000000..a64c234e6 --- /dev/null +++ b/connectivity/source/drivers/evoab2/NDatabaseMetaData.hxx @@ -0,0 +1,218 @@ +/* -*- 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 . + */ + +#pragma once + +#include <sal/config.h> + +#include <string_view> + +#include "NConnection.hxx" +#include <TDatabaseMetaDataBase.hxx> +#include <FDatabaseMetaDataResultSet.hxx> + + +namespace connectivity::evoab +{ + + //************ Class: OEvoabDatabaseMetaData + + typedef struct{ + gboolean bIsSplittedValue; + GParamSpec *pField; + }ColumnProperty; + + typedef enum { + DEFAULT_ADDR_LINE1=1,DEFAULT_ADDR_LINE2,DEFAULT_CITY,DEFAULT_STATE,DEFAULT_COUNTRY,DEFAULT_ZIP, + WORK_ADDR_LINE1,WORK_ADDR_LINE2,WORK_CITY,WORK_STATE,WORK_COUNTRY,WORK_ZIP, + HOME_ADDR_LINE1,HOME_ADDR_LINE2,HOME_CITY,HOME_STATE,HOME_COUNTRY,HOME_ZIP, + OTHER_ADDR_LINE1,OTHER_ADDR_LINE2,OTHER_CITY,OTHER_STATE,OTHER_COUNTRY,OTHER_ZIP + }ColumnNumber; + + typedef struct { + const gchar *pColumnName; + ColumnNumber value; + }SplitEvoColumns; + + const SplitEvoColumns* get_evo_addr(); + + const ColumnProperty *getField(guint n); + GType getGFieldType(guint nCol) ; + sal_Int32 getFieldType(guint nCol) ; + OUString getFieldTypeName(guint nCol) ; + OUString getFieldName(guint nCol) ; + guint findEvoabField(std::u16string_view aColName); + + void free_column_resources(); + + class OEvoabDatabaseMetaData : public ODatabaseMetaDataBase + { + OEvoabConnection* m_pConnection; + + protected: + 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; + + virtual ~OEvoabDatabaseMetaData() override; + public: + explicit OEvoabDatabaseMetaData(OEvoabConnection* _pCon); + + // 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 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; + }; +} + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/connectivity/source/drivers/evoab2/NDriver.cxx b/connectivity/source/drivers/evoab2/NDriver.cxx new file mode 100644 index 000000000..d1b7746f4 --- /dev/null +++ b/connectivity/source/drivers/evoab2/NDriver.cxx @@ -0,0 +1,157 @@ +/* -*- 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 "NDriver.hxx" +#include "NConnection.hxx" +#include <com/sun/star/lang/DisposedException.hpp> +#include <connectivity/dbexception.hxx> +#include <cppuhelper/supportsservice.hxx> +#include <com/sun/star/ucb/XContentAccess.hpp> +#include <rtl/ref.hxx> +#include <strings.hrc> +#include <resource/sharedresources.hxx> + +using namespace osl; +using namespace connectivity::evoab; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::ucb; + + +OEvoabDriver::OEvoabDriver(const Reference< XComponentContext >& _rxContext) : + ODriver_BASE( m_aMutex ), m_xContext( _rxContext ) +{ +} + +OEvoabDriver::~OEvoabDriver() +{ +} + +void OEvoabDriver::disposing() +{ + ::osl::MutexGuard aGuard(m_aMutex); + + // when driver will be destroyed so all our connections have to be destroyed as well + for (const auto& rxConnection : m_xConnections) + { + Reference< XComponent > xComp(rxConnection.get(), UNO_QUERY); + if (xComp.is()) + { + try + { + xComp->dispose(); + } + catch (const css::lang::DisposedException&) + { + xComp.clear(); + } + } + } + m_xConnections.clear(); + connectivity::OWeakRefArray().swap(m_xConnections); // this really clears + + ODriver_BASE::disposing(); +} + +// static ServiceInfo + + +OUString SAL_CALL OEvoabDriver::getImplementationName( ) +{ + return EVOAB_DRIVER_IMPL_NAME; + // this name is referenced in the configuration and in the evoab.xml + // Please take care when changing it. +} + +sal_Bool SAL_CALL OEvoabDriver::supportsService( const OUString& _rServiceName ) +{ + return cppu::supportsService(this, _rServiceName); +} + +Sequence< OUString > SAL_CALL OEvoabDriver::getSupportedServiceNames( ) +{ + // which service is supported + // for more information @see com.sun.star.sdbc.Driver + return { "com.sun.star.sdbc.Driver" }; +} + + +Reference< XConnection > SAL_CALL OEvoabDriver::connect( const OUString& url, const Sequence< PropertyValue >& info ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + if (ODriver_BASE::rBHelper.bDisposed) + throw DisposedException(); + + if ( ! acceptsURL(url) ) + return nullptr; + + rtl::Reference<OEvoabConnection> pCon = new OEvoabConnection( *this ); + pCon->construct(url,info); + m_xConnections.push_back(WeakReferenceHelper(*pCon)); + + return pCon; +} + +sal_Bool SAL_CALL OEvoabDriver::acceptsURL( const OUString& url ) +{ + return acceptsURL_Stat(url); +} + + +Sequence< DriverPropertyInfo > SAL_CALL OEvoabDriver::getPropertyInfo( const OUString& url, const Sequence< PropertyValue >& /*info*/ ) +{ + if ( ! acceptsURL(url) ) + { + ::connectivity::SharedResources aResources; + const OUString sMessage = aResources.getResourceString(STR_URI_SYNTAX_ERROR); + ::dbtools::throwGenericSQLException(sMessage ,*this); + } // if ( ! acceptsURL(url) ) + + // if you have something special to say return it here :-) + return Sequence< DriverPropertyInfo >(); +} + + +sal_Int32 SAL_CALL OEvoabDriver::getMajorVersion( ) +{ + return 1; +} + +sal_Int32 SAL_CALL OEvoabDriver::getMinorVersion( ) +{ + return 0; +} + +bool OEvoabDriver::acceptsURL_Stat( std::u16string_view url ) +{ + return ( url == u"sdbc:address:evolution:local" || url == u"sdbc:address:evolution:groupwise" || url == u"sdbc:address:evolution:ldap" ) && EApiInit(); +} + + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface* +connectivity_OEvoabDriver_get_implementation( + css::uno::XComponentContext* context , css::uno::Sequence<css::uno::Any> const&) +{ + return cppu::acquire(new OEvoabDriver(context)); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/connectivity/source/drivers/evoab2/NDriver.hxx b/connectivity/source/drivers/evoab2/NDriver.hxx new file mode 100644 index 000000000..9d3b57fa7 --- /dev/null +++ b/connectivity/source/drivers/evoab2/NDriver.hxx @@ -0,0 +1,74 @@ +/* -*- 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 . + */ + +#pragma once + +#include <sal/config.h> + +#include <string_view> + +#include <com/sun/star/sdbc/XDriver.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <cppuhelper/compbase.hxx> +#include <connectivity/CommonTools.hxx> + +inline constexpr OUStringLiteral EVOAB_DRIVER_IMPL_NAME = u"com.sun.star.comp.sdbc.evoab.OEvoabDriver"; + +namespace connectivity::evoab + { + typedef ::cppu::WeakComponentImplHelper< css::sdbc::XDriver, + css::lang::XServiceInfo > ODriver_BASE; + + + class OEvoabDriver final : public ODriver_BASE + { + ::osl::Mutex m_aMutex; + connectivity::OWeakRefArray m_xConnections; + css::uno::Reference< css::uno::XComponentContext > m_xContext; + + public: + explicit OEvoabDriver(const css::uno::Reference< css::uno::XComponentContext >& ); + virtual ~OEvoabDriver() override; + + // OComponentHelper + virtual void SAL_CALL disposing() override; + + // XServiceInfo + virtual OUString SAL_CALL getImplementationName( ) override; + virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override; + virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames( ) override; + + + // XDriver + virtual css::uno::Reference< css::sdbc::XConnection > SAL_CALL connect( const OUString& url, const css::uno::Sequence< css::beans::PropertyValue >& info ) override; + virtual sal_Bool SAL_CALL acceptsURL( const OUString& url ) override; + virtual css::uno::Sequence< css::sdbc::DriverPropertyInfo > SAL_CALL getPropertyInfo( const OUString& url, const css::uno::Sequence< css::beans::PropertyValue >& info ) override; + virtual sal_Int32 SAL_CALL getMajorVersion( ) override; + virtual sal_Int32 SAL_CALL getMinorVersion( ) override; + + public: + const css::uno::Reference< css::uno::XComponentContext >& getComponentContext( ) const { return m_xContext; } + + // static methods + static bool acceptsURL_Stat( std::u16string_view url ); + }; +} + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/connectivity/source/drivers/evoab2/NPreparedStatement.cxx b/connectivity/source/drivers/evoab2/NPreparedStatement.cxx new file mode 100644 index 000000000..7b6172ac6 --- /dev/null +++ b/connectivity/source/drivers/evoab2/NPreparedStatement.cxx @@ -0,0 +1,319 @@ +/* -*- 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 "NPreparedStatement.hxx" +#include <connectivity/dbexception.hxx> +#include <connectivity/dbtools.hxx> +#include <rtl/ref.hxx> +#include <tools/diagnose_ex.h> + +#include <strings.hrc> + +using namespace connectivity::evoab; +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; + +IMPLEMENT_SERVICE_INFO(OEvoabPreparedStatement,"com.sun.star.sdbcx.evoab.PreparedStatement","com.sun.star.sdbc.PreparedStatement"); + + +OEvoabPreparedStatement::OEvoabPreparedStatement( OEvoabConnection* _pConnection ) + :OCommonStatement(_pConnection) +{ +} + + +void OEvoabPreparedStatement::construct( const OUString& _sql ) +{ + m_sSqlStatement = _sql; + + m_aQueryData = impl_getEBookQuery_throw( m_sSqlStatement ); + ENSURE_OR_THROW( m_aQueryData.getQuery(), "no EBookQuery" ); + ENSURE_OR_THROW( m_aQueryData.xSelectColumns.is(), "no SelectColumn" ); + + // create our meta data + rtl::Reference<OEvoabResultSetMetaData> pMeta + = new OEvoabResultSetMetaData( m_aQueryData.sTable ); + m_xMetaData = pMeta; + pMeta->setEvoabFields( m_aQueryData.xSelectColumns ); +} + + +OEvoabPreparedStatement::~OEvoabPreparedStatement() +{ +} + + +void SAL_CALL OEvoabPreparedStatement::acquire() noexcept +{ + OCommonStatement::acquire(); +} + + +void SAL_CALL OEvoabPreparedStatement::release() noexcept +{ + OCommonStatement::release(); +} + + +Any SAL_CALL OEvoabPreparedStatement::queryInterface( const Type & rType ) +{ + Any aRet = OCommonStatement::queryInterface(rType); + if(!aRet.hasValue()) + aRet = OPreparedStatement_BASE::queryInterface(rType); + return aRet; +} + +Sequence< Type > SAL_CALL OEvoabPreparedStatement::getTypes( ) +{ + return ::comphelper::concatSequences(OPreparedStatement_BASE::getTypes(),OCommonStatement::getTypes()); +} + + +Reference< XResultSetMetaData > SAL_CALL OEvoabPreparedStatement::getMetaData( ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(OCommonStatement_IBase::rBHelper.bDisposed); + + // the meta data should have been created at construction time + ENSURE_OR_THROW( m_xMetaData.is(), "internal error: no meta data" ); + return m_xMetaData; +} + + +void SAL_CALL OEvoabPreparedStatement::close( ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(OCommonStatement_IBase::rBHelper.bDisposed); + + free_column_resources(); + // Reset last warning message + try { + clearWarnings (); + OCommonStatement::close(); + } + catch (SQLException &) { + // If we get an error, ignore + } + +} + + +sal_Bool SAL_CALL OEvoabPreparedStatement::execute( ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(OCommonStatement_IBase::rBHelper.bDisposed); + + Reference< XResultSet> xRS = impl_executeQuery_throw( m_aQueryData ); + return xRS.is(); +} + + +sal_Int32 SAL_CALL OEvoabPreparedStatement::executeUpdate( ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(OCommonStatement_IBase::rBHelper.bDisposed); + ::dbtools::throwFeatureNotImplementedSQLException( "XStatement::executeUpdate", *this ); + return 0; +} + + +void SAL_CALL OEvoabPreparedStatement::setString( sal_Int32 /*parameterIndex*/, const OUString& /*x*/ ) +{ + ::dbtools::throwFunctionNotSupportedSQLException( "XParameters::setString", *this ); +} + + +Reference< XConnection > SAL_CALL OEvoabPreparedStatement::getConnection( ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(OCommonStatement_IBase::rBHelper.bDisposed); + + return impl_getConnection(); +} + + +Reference< XResultSet > SAL_CALL OEvoabPreparedStatement::executeQuery( ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(OCommonStatement_IBase::rBHelper.bDisposed); + + return impl_executeQuery_throw( m_aQueryData ); +} + + +void SAL_CALL OEvoabPreparedStatement::setBoolean( sal_Int32 /*parameterIndex*/, sal_Bool /*x*/ ) +{ + ::dbtools::throwFunctionNotSupportedSQLException( "XParameters::setBoolean", *this ); + +} + +void SAL_CALL OEvoabPreparedStatement::setByte( sal_Int32 /*parameterIndex*/, sal_Int8 /*x*/ ) +{ + ::dbtools::throwFunctionNotSupportedSQLException( "XParameters::setByte", *this ); +} + + +void SAL_CALL OEvoabPreparedStatement::setDate( sal_Int32 /*parameterIndex*/, const Date& /*aData*/ ) +{ + ::dbtools::throwFunctionNotSupportedSQLException( "XParameters::setDate", *this ); +} + + +void SAL_CALL OEvoabPreparedStatement::setTime( sal_Int32 /*parameterIndex*/, const css::util::Time& /*aVal*/ ) +{ + ::dbtools::throwFunctionNotSupportedSQLException( "XParameters::setTime", *this ); +} + + +void SAL_CALL OEvoabPreparedStatement::setTimestamp( sal_Int32 /*parameterIndex*/, const DateTime& /*aVal*/ ) +{ + ::dbtools::throwFunctionNotSupportedSQLException( "XParameters::setTimestamp", *this ); +} + + +void SAL_CALL OEvoabPreparedStatement::setDouble( sal_Int32 /*parameterIndex*/, double /*x*/ ) +{ + ::dbtools::throwFunctionNotSupportedSQLException( "XParameters::setDouble", *this ); +} + + +void SAL_CALL OEvoabPreparedStatement::setFloat( sal_Int32 /*parameterIndex*/, float /*x*/ ) +{ + ::dbtools::throwFunctionNotSupportedSQLException( "XParameters::setFloat", *this ); +} + + +void SAL_CALL OEvoabPreparedStatement::setInt( sal_Int32 /*parameterIndex*/, sal_Int32 /*x*/ ) +{ + ::dbtools::throwFunctionNotSupportedSQLException( "XParameters::setInt", *this ); +} + + +void SAL_CALL OEvoabPreparedStatement::setLong( sal_Int32 /*parameterIndex*/, sal_Int64 /*aVal*/ ) +{ + ::dbtools::throwFunctionNotSupportedSQLException( "XParameters::setLong", *this ); +} + + +void SAL_CALL OEvoabPreparedStatement::setNull( sal_Int32 /*parameterIndex*/, sal_Int32 /*sqlType*/ ) +{ + ::dbtools::throwFunctionNotSupportedSQLException( "XParameters::setNull", *this ); +} + + +void SAL_CALL OEvoabPreparedStatement::setClob( sal_Int32 /*parameterIndex*/, const Reference< XClob >& /*x*/ ) +{ + ::dbtools::throwFunctionNotSupportedSQLException( "XParameters::setClob", *this ); +} + + +void SAL_CALL OEvoabPreparedStatement::setBlob( sal_Int32 /*parameterIndex*/, const Reference< XBlob >& /*x*/ ) +{ + ::dbtools::throwFunctionNotSupportedSQLException( "XParameters::setBlob", *this ); +} + + +void SAL_CALL OEvoabPreparedStatement::setArray( sal_Int32 /*parameterIndex*/, const Reference< XArray >& /*x*/ ) +{ + ::dbtools::throwFunctionNotSupportedSQLException( "XParameters::setArray", *this ); +} + + +void SAL_CALL OEvoabPreparedStatement::setRef( sal_Int32 /*parameterIndex*/, const Reference< XRef >& /*x*/ ) +{ + ::dbtools::throwFunctionNotSupportedSQLException( "XParameters::setRef", *this ); +} + + +void SAL_CALL OEvoabPreparedStatement::setObjectWithInfo( sal_Int32 /*parameterIndex*/, const Any& /*x*/, sal_Int32 /*sqlType*/, sal_Int32 /*scale*/ ) +{ + ::dbtools::throwFunctionNotSupportedSQLException( "XParameters::setObjectWithInfo", *this ); +} + + +void SAL_CALL OEvoabPreparedStatement::setObjectNull( sal_Int32 /*parameterIndex*/, sal_Int32 /*sqlType*/, const OUString& /*typeName*/ ) +{ + ::dbtools::throwFunctionNotSupportedSQLException( "XParameters::setObjectNull", *this ); +} + + +void SAL_CALL OEvoabPreparedStatement::setObject( sal_Int32 parameterIndex, const Any& x ) +{ + if(!::dbtools::implSetObject(this,parameterIndex,x)) + { + const OUString sError( getOwnConnection()->getResources().getResourceStringWithSubstitution( + STR_UNKNOWN_PARA_TYPE, + "$position$", OUString::number(parameterIndex) + ) ); + ::dbtools::throwGenericSQLException(sError,*this); + } +} + + +void SAL_CALL OEvoabPreparedStatement::setShort( sal_Int32 /*parameterIndex*/, sal_Int16 /*x*/ ) +{ + ::dbtools::throwFunctionNotSupportedSQLException( "XParameters::setShort", *this ); +} + + +void SAL_CALL OEvoabPreparedStatement::setBytes( sal_Int32 /*parameterIndex*/, const Sequence< sal_Int8 >& /*x*/ ) +{ + ::dbtools::throwFunctionNotSupportedSQLException( "XParameters::setBytes", *this ); +} + + +void SAL_CALL OEvoabPreparedStatement::setCharacterStream( sal_Int32 /*parameterIndex*/, const Reference< XInputStream >& /*x*/, sal_Int32 /*length*/ ) +{ + ::dbtools::throwFunctionNotSupportedSQLException( "XParameters::setCharacterStream", *this ); +} + + +void SAL_CALL OEvoabPreparedStatement::setBinaryStream( sal_Int32 /*parameterIndex*/, const Reference< XInputStream >& /*x*/, sal_Int32 /*length*/ ) +{ + ::dbtools::throwFunctionNotSupportedSQLException( "XParameters::setBinaryStream", *this ); +} + + +void SAL_CALL OEvoabPreparedStatement::clearParameters( ) +{ +} + +Reference< XResultSet > SAL_CALL OEvoabPreparedStatement::getResultSet( ) +{ + return nullptr; +} + +sal_Int32 SAL_CALL OEvoabPreparedStatement::getUpdateCount( ) +{ + return 0; +} + +sal_Bool SAL_CALL OEvoabPreparedStatement::getMoreResults( ) +{ + return false; +} + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/connectivity/source/drivers/evoab2/NPreparedStatement.hxx b/connectivity/source/drivers/evoab2/NPreparedStatement.hxx new file mode 100644 index 000000000..cd42d42d5 --- /dev/null +++ b/connectivity/source/drivers/evoab2/NPreparedStatement.hxx @@ -0,0 +1,108 @@ +/* -*- 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 . + */ + +#pragma once + +#include "NStatement.hxx" +#include "NConnection.hxx" +#include "NDatabaseMetaData.hxx" +#include "NResultSet.hxx" +#include <com/sun/star/sdbc/XPreparedStatement.hpp> +#include <com/sun/star/sdbc/XParameters.hpp> +#include <com/sun/star/sdbc/XResultSetMetaDataSupplier.hpp> +#include <com/sun/star/sdbc/XPreparedBatchExecution.hpp> +#include <com/sun/star/io/XInputStream.hpp> +#include <cppuhelper/implbase5.hxx> + +namespace connectivity::evoab +{ + + typedef ::cppu::ImplHelper5< css::sdbc::XPreparedStatement, + css::sdbc::XParameters, + css::sdbc::XResultSetMetaDataSupplier, + css::sdbc::XMultipleResults, + css::lang::XServiceInfo> OPreparedStatement_BASE; + + class OEvoabPreparedStatement final:public OCommonStatement + ,public OPreparedStatement_BASE + { + // our SQL statement + OUString m_sSqlStatement; + // the EBookQuery we're working with + QueryData m_aQueryData; + // our meta data + css::uno::Reference< css::sdbc::XResultSetMetaData > m_xMetaData; + + virtual ~OEvoabPreparedStatement() override; + + public: + explicit OEvoabPreparedStatement( OEvoabConnection* _pConnection ); + + void construct( const OUString& _sql ); + + DECLARE_SERVICE_INFO(); + //XInterface + virtual css::uno::Any SAL_CALL queryInterface( const css::uno::Type & rType ) override; + virtual void SAL_CALL acquire() noexcept override; + virtual void SAL_CALL release() noexcept 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; + // XCloseable + virtual void SAL_CALL close( ) 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; + }; +} + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/connectivity/source/drivers/evoab2/NResultSet.cxx b/connectivity/source/drivers/evoab2/NResultSet.cxx new file mode 100644 index 000000000..53b50a5c3 --- /dev/null +++ b/connectivity/source/drivers/evoab2/NResultSet.cxx @@ -0,0 +1,1038 @@ +/* -*- 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 "NDatabaseMetaData.hxx" +#include "NConnection.hxx" +#include "NResultSet.hxx" +#include <propertyids.hxx> +#include <strings.hrc> + +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/sdb/ErrorCondition.hpp> +#include <com/sun/star/sdbc/FetchDirection.hpp> +#include <com/sun/star/sdbc/ResultSetConcurrency.hpp> +#include <com/sun/star/sdbc/ResultSetType.hpp> + +#include <comphelper/sequence.hxx> +#include <cppuhelper/supportsservice.hxx> +#include <connectivity/dbexception.hxx> +#include <connectivity/sqlerror.hxx> +#include <rtl/string.hxx> +#include <sal/log.hxx> +#include <tools/diagnose_ex.h> +#include <unotools/syslocale.hxx> +#include <unotools/intlwrapper.hxx> +#include <unotools/collatorwrapper.hxx> + +#include <cstring> + +namespace connectivity::evoab { + +using namespace ::comphelper; +using namespace com::sun::star; +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; +namespace ErrorCondition = ::com::sun::star::sdb::ErrorCondition; + + +OUString SAL_CALL OEvoabResultSet::getImplementationName( ) +{ + return "com.sun.star.sdbcx.evoab.ResultSet"; +} + + Sequence< OUString > SAL_CALL OEvoabResultSet::getSupportedServiceNames( ) +{ + return { "com.sun.star.sdbc.ResultSet" }; +} + +sal_Bool SAL_CALL OEvoabResultSet::supportsService( const OUString& _rServiceName ) +{ + return cppu::supportsService(this, _rServiceName); +} + +struct ComparisonData +{ + const SortDescriptor& rSortOrder; + IntlWrapper aIntlWrapper; + + ComparisonData(const SortDescriptor& _rSortOrder) + : rSortOrder(_rSortOrder) + , aIntlWrapper(SvtSysLocale().GetUILanguageTag()) + { + } +}; + +static OUString +valueToOUString( GValue& _rValue ) +{ + const char *pStr = g_value_get_string( &_rValue ); + OString aStr( pStr ? pStr : "" ); + OUString sResult( OStringToOUString( aStr, RTL_TEXTENCODING_UTF8 ) ); + g_value_unset( &_rValue ); + return sResult; +} + +static bool +valueToBool( GValue& _rValue ) +{ + bool bResult = g_value_get_boolean( &_rValue ); + g_value_unset( &_rValue ); + return bResult; +} + +static int +whichAddress(int value) +{ + int fieldEnum; + switch (value) + { + case HOME_ADDR_LINE1: + case HOME_ADDR_LINE2: + case HOME_CITY: + case HOME_STATE: + case HOME_COUNTRY: + case HOME_ZIP: + fieldEnum = e_contact_field_id("address_home"); + break; + + case WORK_ADDR_LINE1: + case WORK_ADDR_LINE2: + case WORK_CITY: + case WORK_STATE: + case WORK_COUNTRY: + case WORK_ZIP: + fieldEnum = e_contact_field_id("address_work"); + break; + + case OTHER_ADDR_LINE1: + case OTHER_ADDR_LINE2: + case OTHER_CITY: + case OTHER_STATE: + case OTHER_COUNTRY: + case OTHER_ZIP: + fieldEnum = e_contact_field_id("address_other"); + break; + + default: fieldEnum = e_contact_field_id("address_home"); + } + return fieldEnum; +} + +/* +* This function decides the default column values based on the first field of EContactAddress. +* The search order is Work->Home->other(defaults). +*/ +static EContactAddress * +getDefaultContactAddress( EContact *pContact,int *value ) +{ + EContactAddress *ec = static_cast<EContactAddress *>(e_contact_get(pContact,whichAddress(WORK_ADDR_LINE1))); + if ( ec && (ec->street[0]!='\0') ) + { + *value= *value +WORK_ADDR_LINE1 -1; + return ec; + } + else + { + ec = static_cast<EContactAddress *>(e_contact_get(pContact,whichAddress(HOME_ADDR_LINE1))); + if ( ec && (ec->street[0]!='\0') ) + { + *value=*value+HOME_ADDR_LINE1-1; + return ec; + } + } + + *value=*value+OTHER_ADDR_LINE1-1; + return static_cast<EContactAddress *>(e_contact_get(pContact,whichAddress(OTHER_ADDR_LINE1))); +} + +static EContactAddress* +getContactAddress( EContact *pContact, int * address_enum ) +{ + EContactAddress *ec = nullptr; + switch (*address_enum) { + + case DEFAULT_ADDR_LINE1: + case DEFAULT_ADDR_LINE2: + case DEFAULT_CITY: + case DEFAULT_STATE: + case DEFAULT_COUNTRY: + case DEFAULT_ZIP: + ec = getDefaultContactAddress(pContact,address_enum);break; + default: + ec = static_cast<EContactAddress *>(e_contact_get(pContact,whichAddress(*address_enum))); + } + return ec; +} + +static bool +handleSplitAddress( EContact *pContact,GValue *pStackValue, int value ) +{ + EContactAddress *ec = getContactAddress(pContact,&value) ; + + if (ec==nullptr) + return true; + + switch (value) { + case WORK_ADDR_LINE1: + g_value_set_string(pStackValue,ec->street ); break; + case WORK_ADDR_LINE2: + g_value_set_string(pStackValue,ec->po ); break; + case WORK_CITY: + g_value_set_string(pStackValue,ec->locality ); break; + case WORK_STATE: + g_value_set_string(pStackValue,ec->region ); break; + case WORK_COUNTRY: + g_value_set_string(pStackValue,ec->country ); break; + case WORK_ZIP: + g_value_set_string(pStackValue,ec->code ); break; + + case HOME_ADDR_LINE1: + g_value_set_string(pStackValue,ec->street ); break; + case HOME_ADDR_LINE2: + g_value_set_string(pStackValue,ec->po ); break; + case HOME_CITY: + g_value_set_string(pStackValue,ec->locality ); break; + case HOME_STATE: + g_value_set_string(pStackValue,ec->region ); break; + case HOME_COUNTRY: + g_value_set_string(pStackValue,ec->country ); break; + case HOME_ZIP: + g_value_set_string(pStackValue,ec->code ); break; + + case OTHER_ADDR_LINE1: + g_value_set_string(pStackValue,ec->street ); break; + case OTHER_ADDR_LINE2: + g_value_set_string(pStackValue,ec->po ); break; + case OTHER_CITY: + g_value_set_string(pStackValue,ec->locality ); break; + case OTHER_STATE: + g_value_set_string(pStackValue,ec->region ); break; + case OTHER_COUNTRY: + g_value_set_string(pStackValue,ec->country ); break; + case OTHER_ZIP: + g_value_set_string(pStackValue,ec->code ); break; + + } + + return false; +} + +static bool +getValue( EContact* pContact, sal_Int32 nColumnNum, GType nType, GValue* pStackValue, bool& _out_rWasNull ) +{ + const ColumnProperty * pSpecs = evoab::getField( nColumnNum ); + if ( !pSpecs ) + return false; + + GParamSpec* pSpec = pSpecs->pField; + bool bIsSplittedColumn = pSpecs->bIsSplittedValue; + + _out_rWasNull = true; + if ( !pSpec || !pContact) + return false; + + if ( G_PARAM_SPEC_VALUE_TYPE (pSpec) != nType ) + { + SAL_WARN("connectivity.evoab2", "Wrong type (0x" << std::hex << static_cast<int>(G_PARAM_SPEC_VALUE_TYPE(pSpec)) << ") (0x" + << std::hex << static_cast<int>(nType) << ") " << (pSpec->name ? pSpec->name : "<noname>")); + return false; + } + + g_value_init( pStackValue, nType ); + if ( bIsSplittedColumn ) + { + const SplitEvoColumns* evo_addr( get_evo_addr() ); + for (int i=0;i<OTHER_ZIP;i++) + { + if (0 == strcmp (g_param_spec_get_name (pSpec), evo_addr[i].pColumnName)) + { + _out_rWasNull = handleSplitAddress( pContact, pStackValue, evo_addr[i].value ); + return true; + } + } + } + else + { + g_object_get_property( G_OBJECT (pContact), + g_param_spec_get_name (pSpec), + pStackValue ); + if ( G_VALUE_TYPE( pStackValue ) != nType ) + { + SAL_WARN("connectivity.evoab2", "Fetched type mismatch" ); + g_value_unset( pStackValue ); + return false; + } + } + _out_rWasNull = false; + return true; +} + +extern "C" { + +static int CompareContacts( gconstpointer _lhs, gconstpointer _rhs, gpointer _userData ) +{ + EContact* lhs = const_cast< gpointer >( _lhs ); + EContact* rhs = const_cast< gpointer >( _rhs ); + + GValue aLhsValue = { 0, { { 0 } } }; + GValue aRhsValue = { 0, { { 0 } } }; + bool bLhsNull = true; + bool bRhsNull = true; + + OUString sLhs, sRhs; + bool bLhs(false), bRhs(false); + + const ComparisonData& rCompData = *static_cast< const ComparisonData* >( _userData ); + for ( const auto& sortCol : rCompData.rSortOrder ) + { + sal_Int32 nField = sortCol.nField; + int nOrder = 1; + // if descending sort, reverse order + if (!sortCol.bAscending) + nOrder = -1; + GType eFieldType = evoab::getGFieldType( nField ); + + bool success = getValue( lhs, nField, eFieldType, &aLhsValue, bLhsNull ) + && getValue( rhs, nField, eFieldType, &aRhsValue, bRhsNull ); + OSL_ENSURE( success, "CompareContacts: could not retrieve both values!" ); + if ( !success ) + return 0; + + if ( bLhsNull && !bRhsNull ) + return -1 * nOrder; + if ( !bLhsNull && bRhsNull ) + return 1 * nOrder; + if ( bLhsNull && bRhsNull ) + continue; + + if ( eFieldType == G_TYPE_STRING ) + { + sLhs = valueToOUString( aLhsValue ); + sRhs = valueToOUString( aRhsValue ); + sal_Int32 nCompResult = rCompData.aIntlWrapper.getCaseCollator()->compareString( sLhs, sRhs ); + if ( nCompResult != 0 ) + return nCompResult * nOrder; + continue; + } + + bLhs = valueToBool( aLhsValue ); + bRhs = valueToBool( aRhsValue ); + if ( bLhs && !bRhs ) + return -1 * nOrder; + if ( !bLhs && bRhs ) + return 1 * nOrder; + continue; + } + + return 0; +} + +} + +OString OEvoabVersionHelper::getUserName( EBook *pBook ) +{ + OString aName; + if( isLDAP( pBook ) ) + aName = e_source_get_property( e_book_get_source( pBook ), "binddn" ); + else + aName = e_source_get_property( e_book_get_source( pBook ), "user" ); + return aName; +} + +namespace { + +bool isBookBackend( EBookClient *pBook, const char *backendname) +{ + if (!pBook) + return false; + ESource *pSource = e_client_get_source (reinterpret_cast<EClient *>(pBook)); + return isSourceBackend(pSource, backendname); +} + +class OEvoabVersion36Helper : public OEvoabVersionHelper +{ +private: + GSList *m_pContacts; +public: + OEvoabVersion36Helper() + : m_pContacts(nullptr) + { + } + + virtual ~OEvoabVersion36Helper() override + { + freeContacts(); + } + + virtual EBook* openBook(const char *abname) override + { + //It would be better if here we had id to begin with, see + //NDatabaseMetaData.cxx + const char *id = nullptr; + GList *pSources = e_source_registry_list_sources(get_e_source_registry(), E_SOURCE_EXTENSION_ADDRESS_BOOK); + for (GList* liter = pSources; liter; liter = liter->next) + { + ESource *pSource = E_SOURCE (liter->data); + + if (strcmp(abname, e_source_get_display_name( pSource )) == 0) + { + id = e_source_get_uid( pSource ); + break; + } + } + g_list_foreach (pSources, reinterpret_cast<GFunc>(g_object_unref), nullptr); + g_list_free (pSources); + if (!id) + return nullptr; + + ESource *pSource = e_source_registry_ref_source(get_e_source_registry(), id); + EBookClient *pBook = pSource ? createClient (pSource) : nullptr; + if (pBook && !e_client_open_sync (pBook, true, nullptr, nullptr)) + { + g_object_unref (G_OBJECT (pBook)); + pBook = nullptr; + } + if (pSource) + g_object_unref (pSource); + return pBook; + } + + virtual bool isLDAP( EBook *pBook ) override + { + return isBookBackend(pBook, "ldap"); + } + + virtual bool isLocal( EBook *pBook ) override + { + return isBookBackend(pBook, "local"); + } + + virtual void freeContacts() override final + { + e_client_util_free_object_slist(m_pContacts); + m_pContacts = nullptr; + } + + virtual void executeQuery (EBook* pBook, EBookQuery* pQuery, OString &/*rPassword*/) override + { + freeContacts(); + char *sexp = e_book_query_to_string( pQuery ); + e_book_client_get_contacts_sync( pBook, sexp, &m_pContacts, nullptr, nullptr ); + g_free (sexp); + } + + virtual EContact *getContact(sal_Int32 nIndex) override + { + gpointer pData = g_slist_nth_data (m_pContacts, nIndex); + return pData ? E_CONTACT (pData) : nullptr; + } + + virtual sal_Int32 getNumContacts() override + { + return g_slist_length( m_pContacts ); + } + + virtual bool hasContacts() override + { + return m_pContacts != nullptr; + } + + virtual void sortContacts( const ComparisonData& _rCompData ) override + { + OSL_ENSURE( !_rCompData.rSortOrder.empty(), "sortContacts: no need to call this without any sort order!" ); + ENSURE_OR_THROW( _rCompData.aIntlWrapper.getCaseCollator(), "no collator for comparing strings" ); + + m_pContacts = g_slist_sort_with_data( m_pContacts, &CompareContacts, + const_cast< gpointer >( static_cast< gconstpointer >( &_rCompData ) ) ); + } + +protected: + virtual EBookClient * createClient( ESource *pSource ) + { + return e_book_client_new (pSource, nullptr); + } +}; + +class OEvoabVersion38Helper : public OEvoabVersion36Helper +{ +protected: + virtual EBookClient * createClient( ESource *pSource ) override + { + return e_book_client_connect_direct_sync (get_e_source_registry (), pSource, 10, nullptr, nullptr); + } +}; + +} + +OEvoabResultSet::OEvoabResultSet( OCommonStatement* pStmt, OEvoabConnection *pConnection ) + :OResultSet_BASE(m_aMutex) + ,::comphelper::OPropertyContainer( OResultSet_BASE::rBHelper ) + ,m_pStatement(pStmt) + ,m_pConnection(pConnection) + ,m_bWasNull(true) + ,m_nFetchSize(0) + ,m_nResultSetType(ResultSetType::SCROLL_INSENSITIVE) + ,m_nFetchDirection(FetchDirection::FORWARD) + ,m_nResultSetConcurrency(ResultSetConcurrency::READ_ONLY) + ,m_nIndex(-1) + ,m_nLength(0) +{ + m_pVersionHelper = std::make_unique<OEvoabVersion38Helper>(); + + registerProperty( + OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_FETCHSIZE), + PROPERTY_ID_FETCHSIZE, + PropertyAttribute::READONLY, + &m_nFetchSize, + cppu::UnoType<decltype(m_nFetchSize)>::get() + ); + registerProperty( + OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_RESULTSETTYPE), + PROPERTY_ID_RESULTSETTYPE, + PropertyAttribute::READONLY, + &m_nResultSetType, + cppu::UnoType<decltype(m_nResultSetType)>::get() + ); + registerProperty( + OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_FETCHDIRECTION), + PROPERTY_ID_FETCHDIRECTION, + PropertyAttribute::READONLY, + &m_nFetchDirection, + cppu::UnoType<decltype(m_nFetchDirection)>::get() + ); + registerProperty( + OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_RESULTSETCONCURRENCY), + PROPERTY_ID_RESULTSETCONCURRENCY, + PropertyAttribute::READONLY, + &m_nResultSetConcurrency, + cppu::UnoType<decltype(m_nResultSetConcurrency)>::get() + ); +} + +OEvoabResultSet::~OEvoabResultSet() +{} + +void OEvoabResultSet::construct( const QueryData& _rData ) +{ + ENSURE_OR_THROW( _rData.getQuery(), "internal error: no EBookQuery" ); + + EBook *pBook = m_pVersionHelper->openBook(OUStringToOString(_rData.sTable, RTL_TEXTENCODING_UTF8).getStr()); + if ( !pBook ) + m_pConnection->throwGenericSQLException( STR_CANNOT_OPEN_BOOK, *this ); + + m_pVersionHelper->freeContacts(); + bool bExecuteQuery = true; + switch ( _rData.eFilterType ) + { + case eFilterNone: + if ( !m_pVersionHelper->isLocal( pBook ) ) + { + SQLError aErrorFactory; + SQLException aAsException = aErrorFactory.getSQLException( ErrorCondition::DATA_CANNOT_SELECT_UNFILTERED, *this ); + m_aWarnings.appendWarning( SQLWarning( + aAsException.Message, + aAsException.Context, + aAsException.SQLState, + aAsException.ErrorCode, + aAsException.NextException + ) ); + bExecuteQuery = false; + } + break; + case eFilterAlwaysFalse: + bExecuteQuery = false; + break; + case eFilterOther: + bExecuteQuery = true; + break; + } + if ( bExecuteQuery ) + { + OString aPassword = m_pConnection->getPassword(); + m_pVersionHelper->executeQuery(pBook, _rData.getQuery(), aPassword); + m_pConnection->setPassword( aPassword ); + + if ( m_pVersionHelper->hasContacts() && !_rData.aSortOrder.empty() ) + { + ComparisonData aCompData(_rData.aSortOrder); + m_pVersionHelper->sortContacts(aCompData); + } + } + m_nLength = m_pVersionHelper->getNumContacts(); + SAL_INFO("connectivity.evoab2", "Query return " << m_nLength << " records"); + m_nIndex = -1; + + // create our meta data (need the EBookQuery for this) + m_xMetaData = new OEvoabResultSetMetaData( _rData.sTable ); + + m_xMetaData->setEvoabFields( _rData.xSelectColumns ); +} + + +void OEvoabResultSet::disposing() +{ + ::comphelper::OPropertyContainer::disposing(); + + ::osl::MutexGuard aGuard(m_aMutex); + m_pVersionHelper.reset(); + m_pStatement = nullptr; + m_xMetaData.clear(); +} + +Any SAL_CALL OEvoabResultSet::queryInterface( const Type & rType ) +{ + Any aRet = ::comphelper::OPropertyContainer::queryInterface(rType); + if(!aRet.hasValue()) + aRet = OResultSet_BASE::queryInterface(rType); + return aRet; +} + +Sequence< Type > SAL_CALL OEvoabResultSet::getTypes( ) +{ + return ::comphelper::concatSequences( + OResultSet_BASE::getTypes(), + getBaseTypes() + ); +} + + +// XRow Interface + +/** + * getString: + * @nColumnNum: The column index from the table. + * + * If the equivalent NResultSetMetaData.cxx marks the columntype of + * nColumnNum as DataType::VARCHAR this accessor is used. + */ +OUString SAL_CALL OEvoabResultSet::getString( sal_Int32 nColumnNum ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(OResultSet_BASE::rBHelper.bDisposed); + OUString aResult; + if ( m_xMetaData.is()) + { + sal_Int32 nFieldNumber = m_xMetaData->fieldAtColumn(nColumnNum); + GValue aValue = { 0, { { 0 } } }; + if ( getValue( getCur(), nFieldNumber, G_TYPE_STRING, &aValue, m_bWasNull ) ) + aResult = valueToOUString( aValue ); + } + return aResult; +} + +sal_Bool SAL_CALL OEvoabResultSet::getBoolean( sal_Int32 nColumnNum ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(OResultSet_BASE::rBHelper.bDisposed); + bool bResult = false; + + if ( m_xMetaData.is()) + { + sal_Int32 nFieldNumber = m_xMetaData->fieldAtColumn(nColumnNum); + GValue aValue = { 0, { { 0 } } }; + if ( getValue( getCur(), nFieldNumber, G_TYPE_BOOLEAN, &aValue, m_bWasNull ) ) + bResult = valueToBool( aValue ); + } + return bResult; +} + +sal_Int64 SAL_CALL OEvoabResultSet::getLong( sal_Int32 /*nColumnNum*/ ) +{ + ::dbtools::throwFunctionNotSupportedSQLException( "XRow::getLong", *this ); + return sal_Int64(); +} + +Reference< XArray > SAL_CALL OEvoabResultSet::getArray( sal_Int32 /*nColumnNum*/ ) +{ + ::dbtools::throwFunctionNotSupportedSQLException( "XRow::getArray", *this ); + return nullptr; +} + +Reference< XClob > SAL_CALL OEvoabResultSet::getClob( sal_Int32 /*nColumnNum*/ ) +{ + ::dbtools::throwFunctionNotSupportedSQLException( "XRow::getClob", *this ); + return nullptr; +} + +Reference< XBlob > SAL_CALL OEvoabResultSet::getBlob( sal_Int32 /*nColumnNum*/ ) +{ + ::dbtools::throwFunctionNotSupportedSQLException( "XRow::getBlob", *this ); + return nullptr; +} + +Reference< XRef > SAL_CALL OEvoabResultSet::getRef( sal_Int32 /*nColumnNum*/ ) +{ + ::dbtools::throwFunctionNotSupportedSQLException( "XRow::getRef", *this ); + return nullptr; +} + +Any SAL_CALL OEvoabResultSet::getObject( sal_Int32 /*nColumnNum*/, const Reference< css::container::XNameAccess >& /*typeMap*/ ) +{ + ::dbtools::throwFunctionNotSupportedSQLException( "XRow::getObject", *this ); + return Any(); +} + +sal_Int16 SAL_CALL OEvoabResultSet::getShort( sal_Int32 /*nColumnNum*/ ) +{ + ::dbtools::throwFunctionNotSupportedSQLException( "XRow::getShort", *this ); + return 0; +} + +css::util::Time SAL_CALL OEvoabResultSet::getTime( sal_Int32 /*nColumnNum*/ ) +{ + ::dbtools::throwFunctionNotSupportedSQLException( "XRow::getTime", *this ); + return css::util::Time(); +} + +util::DateTime SAL_CALL OEvoabResultSet::getTimestamp( sal_Int32 /*nColumnNum*/ ) +{ + ::dbtools::throwFunctionNotSupportedSQLException( "XRow::getTimestamp", *this ); + return css::util::DateTime(); +} + +Reference< XInputStream > SAL_CALL OEvoabResultSet::getBinaryStream( sal_Int32 /*nColumnNum*/ ) +{ + ::dbtools::throwFunctionNotSupportedSQLException( "XRow::getBinaryStream", *this ); + return nullptr; +} + +Reference< XInputStream > SAL_CALL OEvoabResultSet::getCharacterStream( sal_Int32 /*nColumnNum*/ ) +{ + ::dbtools::throwFunctionNotSupportedSQLException( "XRow::getCharacterStream", *this ); + return nullptr; +} + +sal_Int8 SAL_CALL OEvoabResultSet::getByte( sal_Int32 /*nColumnNum*/ ) +{ + ::dbtools::throwFunctionNotSupportedSQLException( "XRow::getByte", *this ); + return 0; +} + +Sequence< sal_Int8 > SAL_CALL OEvoabResultSet::getBytes( sal_Int32 /*nColumnNum*/ ) +{ + ::dbtools::throwFunctionNotSupportedSQLException( "XRow::getBytes", *this ); + return Sequence< sal_Int8 >(); +} + +css::util::Date SAL_CALL OEvoabResultSet::getDate( sal_Int32 /*nColumnNum*/ ) +{ + ::dbtools::throwFunctionNotSupportedSQLException( "XRow::getDate", *this ); + return css::util::Date(); +} + +double SAL_CALL OEvoabResultSet::getDouble( sal_Int32 /*nColumnNum*/ ) +{ + ::dbtools::throwFunctionNotSupportedSQLException( "XRow::getDouble", *this ); + return 0; +} + +float SAL_CALL OEvoabResultSet::getFloat( sal_Int32 /*nColumnNum*/ ) +{ + ::dbtools::throwFunctionNotSupportedSQLException( "XRow::getFloat", *this ); + return 0; +} + +sal_Int32 SAL_CALL OEvoabResultSet::getInt( sal_Int32 /*nColumnNum*/ ) +{ + ::dbtools::throwFunctionNotSupportedSQLException( "XRow::getInt", *this ); + return 0; +} +// XRow Interface Ends + + +// XResultSetMetaDataSupplier Interface +Reference< XResultSetMetaData > SAL_CALL OEvoabResultSet::getMetaData( ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(OResultSet_BASE::rBHelper.bDisposed); + + // the meta data should have been created at construction time + ENSURE_OR_THROW( m_xMetaData.is(), "internal error: no meta data" ); + return m_xMetaData; +} +// XResultSetMetaDataSupplier Interface Ends + + +// XResultSet Interface +sal_Bool SAL_CALL OEvoabResultSet::next( ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(OResultSet_BASE::rBHelper.bDisposed); + if (m_nIndex+1 < m_nLength) { + ++m_nIndex ; + return true; + } + else + return false; +} + +sal_Bool SAL_CALL OEvoabResultSet::wasNull( ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(OResultSet_BASE::rBHelper.bDisposed); + + return m_bWasNull; +} + +sal_Bool SAL_CALL OEvoabResultSet::isBeforeFirst( ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(OResultSet_BASE::rBHelper.bDisposed); + + return m_nIndex < 0; +} + +sal_Int32 SAL_CALL OEvoabResultSet::getRow( ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(OResultSet_BASE::rBHelper.bDisposed); + + return m_nIndex; +} + +sal_Bool SAL_CALL OEvoabResultSet::isAfterLast( ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(OResultSet_BASE::rBHelper.bDisposed); + + return m_nIndex >= m_nLength; +} + +sal_Bool SAL_CALL OEvoabResultSet::isFirst( ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(OResultSet_BASE::rBHelper.bDisposed); + + return m_nIndex == 0; +} + +sal_Bool SAL_CALL OEvoabResultSet::isLast( ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(OResultSet_BASE::rBHelper.bDisposed); + + return m_nIndex == m_nLength - 1; +} + +void SAL_CALL OEvoabResultSet::beforeFirst( ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(OResultSet_BASE::rBHelper.bDisposed); + + m_nIndex = -1; +} + +void SAL_CALL OEvoabResultSet::afterLast( ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(OResultSet_BASE::rBHelper.bDisposed); + + m_nIndex = m_nLength; +} + + +sal_Bool SAL_CALL OEvoabResultSet::first( ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(OResultSet_BASE::rBHelper.bDisposed); + + m_nIndex = 0; + return true; +} + + +sal_Bool SAL_CALL OEvoabResultSet::last( ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(OResultSet_BASE::rBHelper.bDisposed); + + m_nIndex = m_nLength - 1; + return true; +} + +sal_Bool SAL_CALL OEvoabResultSet::absolute( sal_Int32 row ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(OResultSet_BASE::rBHelper.bDisposed); + if (row < m_nLength) { + m_nIndex = row; + return true; + } + else + return false; +} + +sal_Bool SAL_CALL OEvoabResultSet::relative( sal_Int32 row ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(OResultSet_BASE::rBHelper.bDisposed); + + if ((m_nIndex+row) < m_nLength) { + m_nIndex += row; + return true; + } + else + return false; +} + +sal_Bool SAL_CALL OEvoabResultSet::previous( ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(OResultSet_BASE::rBHelper.bDisposed); + + if(m_nIndex > 0) { + m_nIndex--; + return true; + } + else + return false; +} + +Reference< XInterface > SAL_CALL OEvoabResultSet::getStatement( ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(OResultSet_BASE::rBHelper.bDisposed); + return static_cast<cppu::OWeakObject*>(m_pStatement); +} + + +sal_Bool SAL_CALL OEvoabResultSet::rowDeleted( ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(OResultSet_BASE::rBHelper.bDisposed); + + return false; +} + +sal_Bool SAL_CALL OEvoabResultSet::rowInserted( ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(OResultSet_BASE::rBHelper.bDisposed); + + return false; +} + +sal_Bool SAL_CALL OEvoabResultSet::rowUpdated( ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(OResultSet_BASE::rBHelper.bDisposed); + + return false; +} + +void SAL_CALL OEvoabResultSet::refreshRow( ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(OResultSet_BASE::rBHelper.bDisposed); +} +//XResult Interface ends + +// XCancellable + +void SAL_CALL OEvoabResultSet::cancel( ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(OResultSet_BASE::rBHelper.bDisposed); +} + +//XCloseable +void SAL_CALL OEvoabResultSet::close( ) +{ + { + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(OResultSet_BASE::rBHelper.bDisposed); + } + dispose(); +} + +// XWarningsSupplier + +void SAL_CALL OEvoabResultSet::clearWarnings( ) +{ + m_aWarnings.clearWarnings(); +} + +Any SAL_CALL OEvoabResultSet::getWarnings( ) +{ + return m_aWarnings.getWarnings(); +} + +//XColumnLocate Interface +sal_Int32 SAL_CALL OEvoabResultSet::findColumn( const OUString& columnName ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(OResultSet_BASE::rBHelper.bDisposed); + + // 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 +} + +//XColumnLocate interface ends + + +::cppu::IPropertyArrayHelper* OEvoabResultSet::createArrayHelper( ) const +{ + Sequence< Property > aProps; + describeProperties( aProps ); + return new ::cppu::OPropertyArrayHelper( aProps ); +} + +::cppu::IPropertyArrayHelper & OEvoabResultSet::getInfoHelper() +{ + return *getArrayHelper(); +} + +void SAL_CALL OEvoabResultSet::acquire() noexcept +{ + OResultSet_BASE::acquire(); +} + +void SAL_CALL OEvoabResultSet::release() noexcept +{ + OResultSet_BASE::release(); +} + +css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL +OEvoabResultSet::getPropertySetInfo( ) +{ + return ::cppu::OPropertySetHelper::createPropertySetInfo(getInfoHelper()); +} + + +} // connectivity::evoab + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/connectivity/source/drivers/evoab2/NResultSet.hxx b/connectivity/source/drivers/evoab2/NResultSet.hxx new file mode 100644 index 000000000..74a5e40dd --- /dev/null +++ b/connectivity/source/drivers/evoab2/NResultSet.hxx @@ -0,0 +1,182 @@ +/* -*- 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 . + */ + +#pragma once + +#include <memory> + +#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/sdbc/XRowUpdate.hpp> +#include <com/sun/star/sdbcx/XRowLocate.hpp> +#include <com/sun/star/sdbcx/XDeleteRows.hpp> +#include <cppuhelper/compbase.hxx> +#include <comphelper/proparrhlp.hxx> +#include <comphelper/propertycontainer.hxx> +#include <connectivity/CommonTools.hxx> +#include <connectivity/FValue.hxx> +#include <connectivity/warningscontainer.hxx> +#include "NStatement.hxx" +#include "NResultSetMetaData.hxx" + +namespace connectivity::evoab +{ + struct ComparisonData; + + class OEvoabVersionHelper + { + public: + virtual EBook* openBook(const char *abname) = 0; + virtual void executeQuery (EBook* pBook, EBookQuery* pQuery, OString &rPassword) = 0; + virtual void freeContacts() = 0; + virtual bool isLDAP( EBook *pBook ) = 0; + virtual bool isLocal( EBook *pBook ) = 0; + virtual EContact *getContact(sal_Int32 nIndex) = 0; + virtual sal_Int32 getNumContacts() = 0; + virtual bool hasContacts() = 0; + virtual void sortContacts( const ComparisonData& _rCompData ) = 0; + OString getUserName( EBook *pBook ); + virtual ~OEvoabVersionHelper() {} + }; + + 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::lang::XServiceInfo + > OResultSet_BASE; + + + class OEvoabResultSet final : public cppu::BaseMutex + ,public OResultSet_BASE + ,public ::comphelper::OPropertyContainer + ,public ::comphelper::OPropertyArrayUsageHelper<OEvoabResultSet> + { + private: + std::unique_ptr<OEvoabVersionHelper> m_pVersionHelper; + + OCommonStatement* m_pStatement; + OEvoabConnection* m_pConnection; + rtl::Reference<OEvoabResultSetMetaData> m_xMetaData; + ::dbtools::WarningsContainer m_aWarnings; + + bool m_bWasNull; + // <properties> + sal_Int32 m_nFetchSize; + sal_Int32 m_nResultSetType; + sal_Int32 m_nFetchDirection; + sal_Int32 m_nResultSetConcurrency; + // </properties> + + // Data & iteration + sal_Int32 m_nIndex; + sal_Int32 m_nLength; + EContact *getCur() + { + return m_pVersionHelper->getContact(m_nIndex); + } + + // OPropertyArrayUsageHelper + virtual ::cppu::IPropertyArrayHelper* createArrayHelper( ) const override; + // OPropertySetHelper + virtual ::cppu::IPropertyArrayHelper & SAL_CALL getInfoHelper() override; + + // you can't delete objects of this type + virtual ~OEvoabResultSet() override; + public: + DECLARE_SERVICE_INFO(); + + OEvoabResultSet( OCommonStatement *pStmt, OEvoabConnection *pConnection ); + void construct( const QueryData& _rData ); + + // ::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() noexcept override; + virtual void SAL_CALL release() noexcept 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; + // XCancellable + virtual void SAL_CALL cancel( ) override; + // XCloseable + virtual void SAL_CALL close( ) override; + // XResultSetMetaDataSupplier + virtual css::uno::Reference< css::sdbc::XResultSetMetaData > SAL_CALL getMetaData( ) 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; + }; +} + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/connectivity/source/drivers/evoab2/NResultSetMetaData.cxx b/connectivity/source/drivers/evoab2/NResultSetMetaData.cxx new file mode 100644 index 000000000..a2ce922ff --- /dev/null +++ b/connectivity/source/drivers/evoab2/NResultSetMetaData.cxx @@ -0,0 +1,174 @@ +/* -*- 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 "NResultSetMetaData.hxx" +#include "NDatabaseMetaData.hxx" +#include <connectivity/dbexception.hxx> +#include <strings.hrc> + +using namespace connectivity::evoab; +using namespace com::sun::star::uno; +using namespace com::sun::star::lang; +using namespace com::sun::star::sdbc; + +OEvoabResultSetMetaData::OEvoabResultSetMetaData(const OUString& _aTableName) + : m_aTableName(_aTableName) +{ + +} + +OEvoabResultSetMetaData::~OEvoabResultSetMetaData() +{ +} + +void OEvoabResultSetMetaData::setEvoabFields(const ::rtl::Reference<connectivity::OSQLColumns> &xColumns) +{ + static constexpr OUStringLiteral aName = u"Name"; + + for (const auto& rxColumn : *xColumns) + { + OUString aFieldName; + + rxColumn->getPropertyValue(aName) >>= aFieldName; + guint nFieldNumber = findEvoabField(aFieldName); + if (nFieldNumber == guint(-1)) + { + connectivity::SharedResources aResource; + const OUString sError( aResource.getResourceStringWithSubstitution( + STR_INVALID_COLUMNNAME, + "$columnname$", aFieldName + ) ); + ::dbtools::throwGenericSQLException( sError, *this ); + } + m_aEvoabFields.push_back(nFieldNumber); + } +} + + +sal_Int32 SAL_CALL OEvoabResultSetMetaData::getColumnDisplaySize( sal_Int32 /*nColumnNum*/ ) +{ + return 50; +} + +sal_Int32 SAL_CALL OEvoabResultSetMetaData::getColumnType( sal_Int32 nColumnNum ) +{ + sal_uInt32 nField = m_aEvoabFields[nColumnNum - 1]; + return evoab::getFieldType (nField); +} + +sal_Int32 SAL_CALL OEvoabResultSetMetaData::getColumnCount( ) +{ + return m_aEvoabFields.size(); +} + +sal_Bool SAL_CALL OEvoabResultSetMetaData::isCaseSensitive( sal_Int32 /*nColumnNum*/ ) +{ + return true; +} + +OUString SAL_CALL OEvoabResultSetMetaData::getSchemaName( sal_Int32 /*nColumnNum*/ ) +{ + return OUString(); +} + +OUString SAL_CALL OEvoabResultSetMetaData::getColumnName( sal_Int32 nColumnNum ) +{ + sal_uInt32 nField = m_aEvoabFields[nColumnNum - 1]; + return evoab::getFieldName( nField ); +} + +OUString SAL_CALL OEvoabResultSetMetaData::getColumnTypeName( sal_Int32 nColumnNum ) +{ + sal_uInt32 nField = m_aEvoabFields[nColumnNum - 1]; + return evoab::getFieldTypeName( nField ); +} + +OUString SAL_CALL OEvoabResultSetMetaData::getColumnLabel( sal_Int32 nColumnNum ) +{ + return getColumnName(nColumnNum); +} + +OUString SAL_CALL OEvoabResultSetMetaData::getColumnServiceName( sal_Int32 /*nColumnNum*/ ) +{ + return OUString(); +} + +OUString SAL_CALL OEvoabResultSetMetaData::getTableName( sal_Int32 /*nColumnNum*/ ) +{ + return m_aTableName;//OUString("TABLE"); +} + +OUString SAL_CALL OEvoabResultSetMetaData::getCatalogName( sal_Int32 /*nColumnNum*/ ) +{ + return OUString(); +} + + +sal_Bool SAL_CALL OEvoabResultSetMetaData::isCurrency( sal_Int32 /*nColumnNum*/ ) +{ + return false; +} + +sal_Bool SAL_CALL OEvoabResultSetMetaData::isAutoIncrement( sal_Int32 /*nColumnNum*/ ) +{ + return false; +} + +sal_Bool SAL_CALL OEvoabResultSetMetaData::isSigned( sal_Int32 /*nColumnNum*/ ) +{ + return false; +} + +sal_Int32 SAL_CALL OEvoabResultSetMetaData::getPrecision( sal_Int32 /*nColumnNum*/ ) +{ + return 0; +} + +sal_Int32 SAL_CALL OEvoabResultSetMetaData::getScale( sal_Int32 /*nColumnNum*/ ) +{ + return 0; +} + +sal_Int32 SAL_CALL OEvoabResultSetMetaData::isNullable( sal_Int32 /*nColumnNum*/ ) +{ + return 0; +} + +sal_Bool SAL_CALL OEvoabResultSetMetaData::isSearchable( sal_Int32 /*nColumnNum*/ ) +{ + return true; +} + +sal_Bool SAL_CALL OEvoabResultSetMetaData::isReadOnly( sal_Int32 /*nColumnNum*/ ) +{ + return true; +} + +sal_Bool SAL_CALL OEvoabResultSetMetaData::isDefinitelyWritable( sal_Int32 /*nColumnNum*/ ) +{ + return false; +} + +sal_Bool SAL_CALL OEvoabResultSetMetaData::isWritable( sal_Int32 /*nColumnNum*/ ) +{ + return false; +} + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/connectivity/source/drivers/evoab2/NResultSetMetaData.hxx b/connectivity/source/drivers/evoab2/NResultSetMetaData.hxx new file mode 100644 index 000000000..66fffb984 --- /dev/null +++ b/connectivity/source/drivers/evoab2/NResultSetMetaData.hxx @@ -0,0 +1,77 @@ +/* -*- 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 . + */ + +#pragma once + +#include <com/sun/star/sdbc/XResultSetMetaData.hpp> +#include <cppuhelper/implbase.hxx> +#include "NConnection.hxx" +#include <rtl/ref.hxx> +#include <com/sun/star/connection/XConnection.hpp> + +namespace connectivity::evoab +{ + + //************ Class: ResultSetMetaData + + typedef ::cppu::WeakImplHelper< css::sdbc::XResultSetMetaData> OResultSetMetaData_BASE; + + class OEvoabResultSetMetaData : public OResultSetMetaData_BASE + { + OUString m_aTableName; + std::vector<sal_Int32> m_aEvoabFields; + + protected: + virtual ~OEvoabResultSetMetaData() override; + public: + explicit OEvoabResultSetMetaData(const OUString& _aTableName); + /// @throws css::sdbc::SQLException + void setEvoabFields(const ::rtl::Reference<connectivity::OSQLColumns> &xColumns); + sal_uInt32 fieldAtColumn(sal_Int32 columnIndex) const + { return m_aEvoabFields[columnIndex - 1]; } + /// Avoid ambiguous cast error from the compiler. + operator css::uno::Reference< css::sdbc::XResultSetMetaData > () noexcept + { return this; } + + 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; + }; +} + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/connectivity/source/drivers/evoab2/NStatement.cxx b/connectivity/source/drivers/evoab2/NStatement.cxx new file mode 100644 index 000000000..a5554dd06 --- /dev/null +++ b/connectivity/source/drivers/evoab2/NStatement.cxx @@ -0,0 +1,682 @@ +/* -*- 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 <sal/config.h> + +#include <string_view> + +#include <osl/diagnose.h> +#include <rtl/ref.hxx> +#include <rtl/ustring.hxx> +#include <sal/log.hxx> +#include <com/sun/star/sdbc/ResultSetConcurrency.hpp> +#include <com/sun/star/sdbc/ResultSetType.hpp> +#include <com/sun/star/sdbc/FetchDirection.hpp> +#include <com/sun/star/lang/DisposedException.hpp> +#include <cppuhelper/typeprovider.hxx> +#include <propertyids.hxx> +#include "NStatement.hxx" +#include "NConnection.hxx" +#include "NDatabaseMetaData.hxx" +#include "NResultSet.hxx" +#include <sqlbison.hxx> +#include <strings.hrc> +#include <connectivity/dbexception.hxx> +#include <tools/diagnose_ex.h> + +namespace connectivity::evoab { + + +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; + +namespace { + +EBookQuery * createTrue() +{ // Not the world's most efficient unconditional true but ... + return e_book_query_from_string("(exists \"full_name\")"); +} + +EBookQuery * createTest( std::u16string_view aColumnName, + EBookQueryTest eTest, + std::u16string_view aMatch ) +{ + OString sMatch = OUStringToOString( aMatch, RTL_TEXTENCODING_UTF8 ); + OString sColumnName = OUStringToOString( aColumnName, RTL_TEXTENCODING_UTF8 ); + + return e_book_query_field_test( e_contact_field_id( sColumnName.getStr() ), + eTest, sMatch.getStr() ); +} + +} + +OCommonStatement::OCommonStatement(OEvoabConnection* _pConnection) + : OCommonStatement_IBase(m_aMutex) + , ::comphelper::OPropertyContainer(OCommonStatement_IBase::rBHelper) + , m_xResultSet(nullptr) + , m_xConnection(_pConnection) + , m_aParser(_pConnection->getDriver().getComponentContext()) + , m_aSQLIterator( _pConnection, _pConnection->createCatalog()->getTables(), m_aParser ) + , m_pParseTree(nullptr) + , m_nMaxFieldSize(0) + , m_nMaxRows(0) + , m_nQueryTimeOut(0) + , m_nFetchSize(0) + , m_nResultSetType(ResultSetType::FORWARD_ONLY) + , m_nFetchDirection(FetchDirection::FORWARD) + , m_nResultSetConcurrency(ResultSetConcurrency::UPDATABLE) + , m_bEscapeProcessing(true) +{ + registerProperty( + OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_CURSORNAME), + PROPERTY_ID_CURSORNAME, + 0, + &m_aCursorName, + cppu::UnoType<decltype(m_aCursorName)>::get() + ); + registerProperty( + OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_MAXFIELDSIZE), + PROPERTY_ID_MAXFIELDSIZE, + 0, + &m_nMaxFieldSize, + cppu::UnoType<decltype(m_nMaxFieldSize)>::get() + ); + registerProperty( + OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_MAXROWS), + PROPERTY_ID_MAXROWS, + 0, + &m_nMaxRows, + cppu::UnoType<decltype(m_nMaxRows)>::get() + ); + registerProperty( + OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_QUERYTIMEOUT), + PROPERTY_ID_QUERYTIMEOUT, + 0, + &m_nQueryTimeOut, + cppu::UnoType<decltype(m_nQueryTimeOut)>::get() + ); + registerProperty( + OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_FETCHSIZE), + PROPERTY_ID_FETCHSIZE, + 0, + &m_nFetchSize, + cppu::UnoType<decltype(m_nFetchSize)>::get() + ); + registerProperty( + OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_RESULTSETTYPE), + PROPERTY_ID_RESULTSETTYPE, + 0, + &m_nResultSetType, + cppu::UnoType<decltype(m_nResultSetType)>::get() + ); + registerProperty( + OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_FETCHDIRECTION), + PROPERTY_ID_FETCHDIRECTION, + 0, + &m_nFetchDirection, + cppu::UnoType<decltype(m_nFetchDirection)>::get() + ); + registerProperty( + OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_ESCAPEPROCESSING), + PROPERTY_ID_ESCAPEPROCESSING, + 0, + &m_bEscapeProcessing, + cppu::UnoType<decltype(m_bEscapeProcessing)>::get() + ); + registerProperty( + OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_RESULTSETCONCURRENCY), + PROPERTY_ID_RESULTSETCONCURRENCY, + 0, + &m_nResultSetConcurrency, + cppu::UnoType<decltype(m_nResultSetConcurrency)>::get() + ); +} + +OCommonStatement::~OCommonStatement() +{ +} + +void OCommonStatement::disposeResultSet() +{ + // free the cursor if alive + Reference< XComponent > xComp(m_xResultSet.get(), UNO_QUERY); + if (xComp.is()) + xComp->dispose(); + m_xResultSet.clear(); +} + +void OCommonStatement::disposing() +{ + ::osl::MutexGuard aGuard(m_aMutex); + + disposeResultSet(); + + m_xConnection.clear(); + + OCommonStatement_IBase::disposing(); +} + +Any SAL_CALL OCommonStatement::queryInterface( const Type & rType ) +{ + Any aRet = OCommonStatement_IBase::queryInterface(rType); + if(!aRet.hasValue()) + aRet = ::comphelper::OPropertyContainer::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::cancel( ) throw(RuntimeException) +//{ +//::osl::MutexGuard aGuard( m_aMutex ); +//checkDisposed(OCommonStatement_IBase::rBHelper.bDisposed); +//// cancel the current sql statement +//} + + +void SAL_CALL OCommonStatement::close( ) +{ + { + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(OCommonStatement_IBase::rBHelper.bDisposed); + + } + dispose(); +} + +OUString OCommonStatement::impl_getColumnRefColumnName_throw( const OSQLParseNode& _rColumnRef ) +{ + ENSURE_OR_THROW( SQL_ISRULE( &_rColumnRef, column_ref ), "internal error: only column_refs supported as LHS" ); + + OUString sColumnName; + switch ( _rColumnRef.count() ) + { + case 3: // SQL_TOKEN_NAME '.' column_val + { + const OSQLParseNode* pPunct = _rColumnRef.getChild( 1 ); + const OSQLParseNode* pColVal = _rColumnRef.getChild( 2 ); + if ( SQL_ISPUNCTUATION( pPunct, "." ) + && ( pColVal->count() == 1 ) + ) + { + sColumnName = pColVal->getChild( 0 )->getTokenValue(); + } + } + break; + + case 1: // column + { + sColumnName = _rColumnRef.getChild( 0 )->getTokenValue(); + } + break; + } + + if ( !sColumnName.getLength() ) + m_xConnection->throwGenericSQLException( STR_QUERY_TOO_COMPLEX, *this ); + + return sColumnName; +} + + +void OCommonStatement::orderByAnalysis( const OSQLParseNode* _pOrderByClause, SortDescriptor& _out_rSort ) +{ + ENSURE_OR_THROW( _pOrderByClause, "NULL node" ); + ENSURE_OR_THROW( SQL_ISRULE( _pOrderByClause, opt_order_by_clause ), "wrong node type" ); + + _out_rSort.clear(); + + const OSQLParseNode* pOrderList = _pOrderByClause->getByRule( OSQLParseNode::ordering_spec_commalist ); + ENSURE_OR_THROW( pOrderList, "unexpected parse tree structure" ); + + for ( size_t i=0; i<pOrderList->count(); ++i ) + { + const OSQLParseNode* pOrderBy = pOrderList->getChild(i); + if ( !pOrderBy || !SQL_ISRULE( pOrderBy, ordering_spec ) ) + continue; + const OSQLParseNode* pColumnRef = pOrderBy->count() == 2 ? pOrderBy->getChild(0) : nullptr; + const OSQLParseNode* pAscDesc = pOrderBy->count() == 2 ? pOrderBy->getChild(1) : nullptr; + ENSURE_OR_THROW( + ( pColumnRef != nullptr ) + && ( pAscDesc != nullptr ) + && ( pAscDesc->isLeaf() ) + && ( SQL_ISRULE( pAscDesc, opt_asc_desc ) + || SQL_ISTOKEN(pAscDesc, ASC) + || SQL_ISTOKEN(pAscDesc, DESC) + ), + "ordering_spec structure error" ); + + // column name -> column field + if ( !SQL_ISRULE( pColumnRef, column_ref ) ) + m_xConnection->throwGenericSQLException( STR_SORT_BY_COL_ONLY, *this ); + const OUString sColumnName( impl_getColumnRefColumnName_throw( *pColumnRef ) ); + guint nField = evoab::findEvoabField( sColumnName ); + // ascending/descending? + bool bAscending = !SQL_ISTOKEN(pAscDesc, DESC); + + _out_rSort.push_back( FieldSort( nField, bAscending ) ); + } +} + + +EBookQuery *OCommonStatement::whereAnalysis( const OSQLParseNode* parseTree ) +{ + EBookQuery *pResult = nullptr; + + ENSURE_OR_THROW( parseTree, "invalid parse tree" ); + + // Nested brackets + if( parseTree->count() == 3 && + SQL_ISPUNCTUATION( parseTree->getChild( 0 ), "(" ) && + SQL_ISPUNCTUATION( parseTree->getChild( 2 ), ")" ) ) + { + pResult = whereAnalysis( parseTree->getChild( 1 ) ); + } + + // SQL AND, OR + else if( ( SQL_ISRULE( parseTree, search_condition ) || + SQL_ISRULE( parseTree, boolean_term ) ) && + parseTree->count() == 3 ) + { + ENSURE_OR_THROW( SQL_ISTOKEN( parseTree->getChild( 1 ), OR ) + || SQL_ISTOKEN( parseTree->getChild( 1 ), AND ), + "unexpected search_condition structure" ); + + EBookQuery *pArgs[2]; + pArgs[0] = whereAnalysis( parseTree->getChild( 0 ) ); + pArgs[1] = whereAnalysis( parseTree->getChild( 2 ) ); + + if( SQL_ISTOKEN( parseTree->getChild( 1 ), OR ) ) + pResult = e_book_query_or( 2, pArgs, true ); + else + pResult = e_book_query_and( 2, pArgs, true ); + } + // SQL =, != + else if( SQL_ISRULE( parseTree, comparison_predicate ) ) + { + OSQLParseNode *pPrec = parseTree->getChild( 1 ); + + ENSURE_OR_THROW( parseTree->count() == 3, "unexpected comparison_predicate structure" ); + + OSQLParseNode* pLHS = parseTree->getChild( 0 ); + OSQLParseNode* pRHS = parseTree->getChild( 2 ); + + if ( ( ! SQL_ISRULE( pLHS, column_ref ) // on the LHS, we accept a column or a constant int value + && ( pLHS->getNodeType() != SQLNodeType::IntNum ) + ) + || ( ( pRHS->getNodeType() != SQLNodeType::String ) // on the RHS, certain literals are acceptable + && ( pRHS->getNodeType() != SQLNodeType::IntNum ) + && ( pRHS->getNodeType() != SQLNodeType::ApproxNum ) + && ! SQL_ISTOKEN( pRHS, TRUE ) + && ! SQL_ISTOKEN( pRHS, FALSE ) + ) + || ( ( pLHS->getNodeType() == SQLNodeType::IntNum ) // an int on LHS requires an int on RHS + && ( pRHS->getNodeType() != SQLNodeType::IntNum ) + ) + ) + { + m_xConnection->throwGenericSQLException( STR_QUERY_TOO_COMPLEX, *this ); + } + + if ( ( pPrec->getNodeType() != SQLNodeType::Equal ) + && ( pPrec->getNodeType() != SQLNodeType::NotEqual ) + ) + { + m_xConnection->throwGenericSQLException( STR_OPERATOR_TOO_COMPLEX, *this ); + } + + // recognize the special "0 = 1" condition + if ( ( pLHS->getNodeType() == SQLNodeType::IntNum ) + && ( pRHS->getNodeType() == SQLNodeType::IntNum ) + && ( pPrec->getNodeType() == SQLNodeType::Equal ) + ) + { + const sal_Int32 nLHS = pLHS->getTokenValue().toInt64(); + const sal_Int32 nRHS = pRHS->getTokenValue().toInt64(); + return ( nLHS == nRHS ) ? createTrue() : nullptr; + } + + OUString aColumnName( impl_getColumnRefColumnName_throw( *pLHS ) ); + + OUString aMatchString; + if ( pRHS->isToken() ) + aMatchString = pRHS->getTokenValue(); + else + aMatchString = pRHS->getChild( 0 )->getTokenValue(); + + pResult = createTest( aColumnName, E_BOOK_QUERY_IS, aMatchString ); + + if ( pResult && ( pPrec->getNodeType() == SQLNodeType::NotEqual ) ) + pResult = e_book_query_not( pResult, true ); + } + // SQL like + else if( SQL_ISRULE( parseTree, like_predicate ) ) + { + ENSURE_OR_THROW( parseTree->count() == 2, "unexpected like_predicate structure" ); + const OSQLParseNode* pPart2 = parseTree->getChild(1); + + if( ! SQL_ISRULE( parseTree->getChild( 0 ), column_ref) ) + m_xConnection->throwGenericSQLException(STR_QUERY_INVALID_LIKE_COLUMN,*this); + + OUString aColumnName( impl_getColumnRefColumnName_throw( *parseTree->getChild( 0 ) ) ); + + OSQLParseNode *pAtom = pPart2->getChild( pPart2->count() - 2 ); // Match String + bool bNotLike = pPart2->getChild(0)->isToken(); + + 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 ) ) ) + { + SAL_INFO( + "connectivity.evoab2", + "analyseSQL : pAtom->count() = " << pAtom->count()); + m_xConnection->throwGenericSQLException(STR_QUERY_INVALID_LIKE_STRING,*this); + } + + const sal_Unicode WILDCARD = '%'; + + OUString aMatchString = pAtom->getTokenValue(); + + // Determine where '%' character is... + if( aMatchString == OUStringChar(WILDCARD) ) + { + // String containing only a '%' and nothing else matches everything + pResult = createTest( aColumnName, E_BOOK_QUERY_CONTAINS, + u"" ); + } + else if( aMatchString.indexOf( WILDCARD ) == -1 ) + { // Simple string , eg. "to match" "contains in evo" + SAL_INFO( "connectivity.evoab2", "Plain contains '" << aMatchString << "'" ); + pResult = createTest( aColumnName, E_BOOK_QUERY_CONTAINS, aMatchString ); + if( pResult && bNotLike ) + pResult = e_book_query_not( pResult, true ); + } + else if( bNotLike ) + { + // We currently can't handle a 'NOT LIKE' when there are '%' + m_xConnection->throwGenericSQLException(STR_QUERY_NOT_LIKE_TOO_COMPLEX,*this); + } + else if( aMatchString.indexOf ( WILDCARD ) == aMatchString.lastIndexOf ( WILDCARD ) ) + { // One occurrence of '%' matches... + if ( aMatchString.startsWith(OUStringChar(WILDCARD)) ) + pResult = createTest( + aColumnName, E_BOOK_QUERY_ENDS_WITH, aMatchString.subView( 1 ) ); + else if ( aMatchString.indexOf ( WILDCARD ) == aMatchString.getLength() - 1 ) + pResult = createTest( aColumnName, E_BOOK_QUERY_BEGINS_WITH, aMatchString.subView( 0, aMatchString.getLength() - 1 ) ); + else + m_xConnection->throwGenericSQLException(STR_QUERY_LIKE_WILDCARD,*this); + } + else if( aMatchString.getLength() >= 3 && + aMatchString.startsWith(OUStringChar(WILDCARD)) && + aMatchString.indexOf ( WILDCARD, 1) == aMatchString.getLength() - 1 ) { + // one '%' at the start and another at the end + pResult = createTest( aColumnName, E_BOOK_QUERY_CONTAINS, aMatchString.subView (1, aMatchString.getLength() - 2) ); + } + else + m_xConnection->throwGenericSQLException(STR_QUERY_LIKE_WILDCARD_MANY,*this); + } + + return pResult; +} + +OUString OCommonStatement::getTableName() const +{ + OUString aTableName; + + if( m_pParseTree && m_aSQLIterator.getStatementType() == OSQLStatementType::Select ) + { + Any aCatalog; + OUString aSchema; + const OSQLParseNode *pSelectStmnt = m_aSQLIterator.getParseTree(); + const OSQLParseNode *pAllTableNames = pSelectStmnt->getChild( 3 )->getChild( 0 )->getChild( 1 ); + + if( OSQLParseTreeIterator::isTableNode( pAllTableNames->getChild( 0 ) ) ) + OSQLParseNode::getTableComponents( pAllTableNames->getChild( 0 ), + aCatalog,aSchema, aTableName,nullptr ); + + else if( SQL_ISRULE( pAllTableNames->getChild( 0 ), table_ref ) ) + { + OSQLParseNode *pNodeForTableName = pAllTableNames->getChild( 0 )->getChild( 0 ); + if( OSQLParseTreeIterator::isTableNode( pNodeForTableName ) ) + { + aTableName = OSQLParseNode::getTableRange(pAllTableNames->getChild( 0 )); + if( !aTableName.getLength() ) + OSQLParseNode::getTableComponents( pNodeForTableName, aCatalog, aSchema, aTableName,nullptr); + } + else + OSL_FAIL( "odd table layout" ); + } + else + OSL_FAIL( "unusual table layout" ); + } + return aTableName; +} + +void OCommonStatement::parseSql( const OUString& sql, QueryData& _out_rQueryData ) +{ + SAL_INFO( "connectivity.evoab2", "parsing " << sql ); + + _out_rQueryData.eFilterType = eFilterOther; + + OUString aErr; + m_pParseTree = m_aParser.parseTree( aErr, sql ).release(); + m_aSQLIterator.setParseTree( m_pParseTree ); + m_aSQLIterator.traverseAll(); + + _out_rQueryData.sTable = getTableName(); + + // to be sorted? + const OSQLParseNode* pOrderByClause = m_aSQLIterator.getOrderTree(); + if ( pOrderByClause ) + { + #if OSL_DEBUG_LEVEL > 1 + OUString sTreeDebug; + pOrderByClause->showParseTree( sTreeDebug ); + SAL_INFO( "connectivity.evoab2", "found order-by tree:\n" << sTreeDebug ); + #endif + + orderByAnalysis( pOrderByClause, _out_rQueryData.aSortOrder ); + } + + const OSQLParseNode* pWhereClause = m_aSQLIterator.getWhereTree(); + if ( pWhereClause && SQL_ISRULE( pWhereClause, where_clause ) ) + { + #if OSL_DEBUG_LEVEL > 1 + OUString sTreeDebug; + pWhereClause->showParseTree( sTreeDebug ); + SAL_INFO( "connectivity.evoab2", "found where tree:\n" << sTreeDebug ); + #endif + EBookQuery* pQuery = whereAnalysis( pWhereClause->getChild( 1 ) ); + if ( !pQuery ) + { + _out_rQueryData.eFilterType = eFilterAlwaysFalse; + pQuery = createTrue(); + } + _out_rQueryData.setQuery( pQuery ); + } + else + { + _out_rQueryData.eFilterType = eFilterNone; + _out_rQueryData.setQuery( createTrue() ); + } +} + + +Reference< XConnection > SAL_CALL OStatement::getConnection( ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(OCommonStatement_IBase::rBHelper.bDisposed); + + // just return our connection here + return impl_getConnection(); +} + + +Any SAL_CALL OCommonStatement::getWarnings( ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(OCommonStatement_IBase::rBHelper.bDisposed); + + + return Any(SQLWarning()); +} + + +void SAL_CALL OCommonStatement::clearWarnings( ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(OCommonStatement_IBase::rBHelper.bDisposed); + +} + +::cppu::IPropertyArrayHelper* OCommonStatement::createArrayHelper( ) const +{ + Sequence< Property > aProps; + describeProperties( aProps ); + return new ::cppu::OPropertyArrayHelper( aProps ); +} + +::cppu::IPropertyArrayHelper & OCommonStatement::getInfoHelper() +{ + return *getArrayHelper(); +} + + +void SAL_CALL OCommonStatement::acquire() noexcept +{ + OCommonStatement_IBase::acquire(); +} + +void SAL_CALL OCommonStatement::release() noexcept +{ + OCommonStatement_IBase::release(); +} + + +QueryData OCommonStatement::impl_getEBookQuery_throw( const OUString& _rSql ) +{ + QueryData aData; + parseSql( _rSql, aData ); + +#if OSL_DEBUG_LEVEL > 1 + char *pSexpr = aData.getQuery() ? e_book_query_to_string( aData.getQuery() ) : g_strdup( "<map failed>" ); + g_message( "Parsed SQL to sexpr '%s'\n", pSexpr ); + g_free( pSexpr ); +#endif + + if ( !aData.getQuery() ) + m_xConnection->throwGenericSQLException( STR_QUERY_TOO_COMPLEX, *this ); + + // a postcondition of this method is that we properly determined the SELECT columns + aData.xSelectColumns = m_aSQLIterator.getSelectColumns(); + if ( !aData.xSelectColumns.is() ) + m_xConnection->throwGenericSQLException( STR_QUERY_TOO_COMPLEX, *this ); + + return aData; +} + + +Reference< XResultSet > OCommonStatement::impl_executeQuery_throw( const QueryData& _rQueryData ) +{ + // create result set + rtl::Reference<OEvoabResultSet> pResult = new OEvoabResultSet( this, m_xConnection.get() ); + pResult->construct( _rQueryData ); + + // done + m_xResultSet = Reference<XWeak>(pResult); + return pResult; +} + + +Reference< XResultSet > OCommonStatement::impl_executeQuery_throw( const OUString& _rSql ) +{ + SAL_INFO( "connectivity.evoab2", "OCommonStatement::impl_executeQuery_throw " << _rSql ); + +#if OSL_DEBUG_LEVEL > 1 + g_message( "Parse SQL '%s'\n", + OUStringToOString(_rSql, RTL_TEXTENCODING_UTF8).getStr() ); +#endif + + return impl_executeQuery_throw( impl_getEBookQuery_throw( _rSql ) ); +} + + +Reference< XPropertySetInfo > SAL_CALL OCommonStatement::getPropertySetInfo( ) +{ + return ::cppu::OPropertySetHelper::createPropertySetInfo( getInfoHelper() ); +} + + +// = OStatement + + +IMPLEMENT_SERVICE_INFO( OStatement, "com.sun.star.comp.sdbcx.evoab.OStatement", "com.sun.star.sdbc.Statement" ); + + +IMPLEMENT_FORWARD_XINTERFACE2( OStatement, OCommonStatement, OStatement_IBase ) + + +IMPLEMENT_FORWARD_XTYPEPROVIDER2( OStatement, OCommonStatement, OStatement_IBase ) + + +sal_Bool SAL_CALL OStatement::execute( const OUString& _sql ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(OCommonStatement_IBase::rBHelper.bDisposed); + + Reference< XResultSet > xRS = impl_executeQuery_throw( _sql ); + return xRS.is(); +} + + +Reference< XResultSet > SAL_CALL OStatement::executeQuery( const OUString& _sql ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(OCommonStatement_IBase::rBHelper.bDisposed); + + return impl_executeQuery_throw( _sql ); +} + + +sal_Int32 SAL_CALL OStatement::executeUpdate( const OUString& /*sql*/ ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(OCommonStatement_IBase::rBHelper.bDisposed); + ::dbtools::throwFeatureNotImplementedSQLException( "XStatement::executeUpdate", *this ); + return 0; +} + +} // namespace ::connectivity::evoab + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/connectivity/source/drivers/evoab2/NStatement.hxx b/connectivity/source/drivers/evoab2/NStatement.hxx new file mode 100644 index 000000000..a348c5335 --- /dev/null +++ b/connectivity/source/drivers/evoab2/NStatement.hxx @@ -0,0 +1,273 @@ +/* -*- 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 . + */ + +#pragma once + +#include <com/sun/star/sdbc/XStatement.hpp> +#include <com/sun/star/sdbc/XWarningsSupplier.hpp> +#include <com/sun/star/sdbc/XMultipleResults.hpp> +#include <com/sun/star/sdbc/XCloseable.hpp> +#include <com/sun/star/sdbc/SQLWarning.hpp> +#include <comphelper/proparrhlp.hxx> +#include <cppuhelper/implbase2.hxx> +#include <cppuhelper/basemutex.hxx> +#include <comphelper/uno3.hxx> +#include <connectivity/CommonTools.hxx> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <connectivity/sqliterator.hxx> +#include <connectivity/sqlparse.hxx> +#include <connectivity/FValue.hxx> +#include <com/sun/star/util/XCancellable.hpp> +#include <cppuhelper/compbase.hxx> +#include <comphelper/propertycontainer.hxx> + +#include "EApi.h" +#include "NConnection.hxx" + +#include <vector> + +namespace connectivity::evoab +{ + typedef ::cppu::WeakComponentImplHelper< css::sdbc::XWarningsSupplier + , css::sdbc::XCloseable + > OCommonStatement_IBase; + + struct FieldSort + { + sal_Int32 nField; + bool bAscending; + + FieldSort( const sal_Int32 _nField, const bool _bAscending ) : nField( _nField ), bAscending( _bAscending ) { } + }; + typedef std::vector< FieldSort > SortDescriptor; + + enum QueryFilterType + { + eFilterAlwaysFalse, + eFilterNone, + eFilterOther + }; + + class EBookQueryWrapper + { + private: + EBookQuery* mpQuery; + public: + EBookQueryWrapper() + : mpQuery(nullptr) + { + } + EBookQueryWrapper(const EBookQueryWrapper& rhs) + : mpQuery(rhs.mpQuery) + { + if (mpQuery) + e_book_query_ref(mpQuery); + } + EBookQueryWrapper(EBookQueryWrapper&& rhs) noexcept + : mpQuery(rhs.mpQuery) + { + rhs.mpQuery = nullptr; + } + void reset(EBookQuery* pQuery) + { + if (mpQuery) + e_book_query_unref(mpQuery); + mpQuery = pQuery; + if (mpQuery) + e_book_query_ref(mpQuery); + } + EBookQueryWrapper& operator=(const EBookQueryWrapper& rhs) + { + if (this != &rhs) + reset(rhs.mpQuery); + return *this; + } + EBookQueryWrapper& operator=(EBookQueryWrapper&& rhs) + { + if (mpQuery) + e_book_query_unref(mpQuery); + mpQuery = rhs.mpQuery; + rhs.mpQuery = nullptr; + return *this; + } + ~EBookQueryWrapper() + { + if (mpQuery) + e_book_query_unref(mpQuery); + } + EBookQuery* getQuery() const + { + return mpQuery; + } + }; + + struct QueryData + { + private: + EBookQueryWrapper aQuery; + + public: + OUString sTable; + QueryFilterType eFilterType; + rtl::Reference<connectivity::OSQLColumns> xSelectColumns; + SortDescriptor aSortOrder; + + QueryData() + : sTable() + , eFilterType( eFilterOther ) + , xSelectColumns() + , aSortOrder() + { + } + + EBookQuery* getQuery() const { return aQuery.getQuery(); } + void setQuery(EBookQuery* pQuery) { aQuery.reset(pQuery); } + }; + + //************ Class: OCommonStatement + // is a base class for the normal statement and for the prepared statement + + class OCommonStatement :public cppu::BaseMutex + ,public OCommonStatement_IBase + ,public ::comphelper::OPropertyContainer + ,public ::comphelper::OPropertyArrayUsageHelper< OCommonStatement > + { + private: + css::uno::WeakReference< css::sdbc::XResultSet> m_xResultSet; // The last ResultSet created + rtl::Reference<OEvoabConnection> m_xConnection; + connectivity::OSQLParser m_aParser; + connectivity::OSQLParseTreeIterator m_aSQLIterator; + connectivity::OSQLParseNode *m_pParseTree; + + // <properties> + OUString m_aCursorName; + sal_Int32 m_nMaxFieldSize; + sal_Int32 m_nMaxRows; + sal_Int32 m_nQueryTimeOut; + sal_Int32 m_nFetchSize; + sal_Int32 m_nResultSetType; + sal_Int32 m_nFetchDirection; + sal_Int32 m_nResultSetConcurrency; + bool m_bEscapeProcessing; + // </properties> + + protected: + + void disposeResultSet(); + + // OPropertyArrayUsageHelper + virtual ::cppu::IPropertyArrayHelper* createArrayHelper() const override; + // OPropertySetHelper + virtual ::cppu::IPropertyArrayHelper & SAL_CALL getInfoHelper() override; + + virtual ~OCommonStatement() override; + + protected: + void parseSql( const OUString& sql, QueryData& _out_rQueryData ); + EBookQuery *whereAnalysis( const OSQLParseNode* parseTree ); + void orderByAnalysis( const OSQLParseNode* _pOrderByClause, SortDescriptor& _out_rSort ); + OUString getTableName() const; + + public: + + // other methods + OEvoabConnection* getOwnConnection() const { return m_xConnection.get(); } + + using OCommonStatement_IBase::operator css::uno::Reference< css::uno::XInterface >; + + protected: + explicit OCommonStatement( OEvoabConnection* _pConnection ); + + // OComponentHelper + virtual void SAL_CALL disposing() override; + // XInterface + virtual void SAL_CALL release() noexcept override; + virtual void SAL_CALL acquire() noexcept 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; + + // XWarningsSupplier + virtual css::uno::Any SAL_CALL getWarnings( ) override; + virtual void SAL_CALL clearWarnings( ) override; + + // XCloseable + virtual void SAL_CALL close( ) override; + + protected: + /** will return the EBookQuery representing the statement WHERE condition, or throw + + Also, all statement dependent members (such as the parser/iterator) will be inited afterwards. + */ + QueryData + impl_getEBookQuery_throw( const OUString& _rSql ); + + css::uno::Reference< css::sdbc::XResultSet > + impl_executeQuery_throw( const OUString& _rSql ); + + css::uno::Reference< css::sdbc::XResultSet > + impl_executeQuery_throw( const QueryData& _rData ); + + css::uno::Reference< css::sdbc::XConnection > + impl_getConnection() { return css::uno::Reference< css::sdbc::XConnection >( m_xConnection ); } + + OUString + impl_getColumnRefColumnName_throw( const ::connectivity::OSQLParseNode& _rColumnRef ); + }; + + typedef ::cppu::ImplHelper2 < css::lang::XServiceInfo + , css::sdbc::XStatement + > OStatement_IBase; + class OStatement :public OCommonStatement + ,public OStatement_IBase + { + protected: + virtual ~OStatement() override {} + + public: + explicit OStatement( OEvoabConnection* _pConnection) + :OCommonStatement( _pConnection) + { + } + + // XInterface + virtual css::uno::Any SAL_CALL queryInterface( const css::uno::Type & rType ) override; + virtual void SAL_CALL acquire() noexcept override; + virtual void SAL_CALL release() noexcept override; + + // XTypeProvider + DECLARE_XTYPEPROVIDER() + + // XServiceInfo + DECLARE_SERVICE_INFO(); + + // 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 ; + }; +} + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/connectivity/source/drivers/evoab2/NTable.cxx b/connectivity/source/drivers/evoab2/NTable.cxx new file mode 100644 index 000000000..208c52747 --- /dev/null +++ b/connectivity/source/drivers/evoab2/NTable.cxx @@ -0,0 +1,76 @@ +/* -*- 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 "NTable.hxx" +#include "NColumns.hxx" + +#include <com/sun/star/sdbc/XRow.hpp> + +using namespace connectivity; +using namespace ::comphelper; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::lang; +using namespace connectivity::evoab; + +OEvoabTable::OEvoabTable( sdbcx::OCollection* _pTables, + OEvoabConnection* _pConnection, + const OUString& Name, + const OUString& Type, + const OUString& Description , + const OUString& SchemaName, + const OUString& CatalogName + ) : OEvoabTable_TYPEDEF(_pTables,true, + Name, + Type, + Description, + SchemaName, + CatalogName), + m_pConnection(_pConnection) +{ + construct(); +} + +void OEvoabTable::refreshColumns() +{ + ::std::vector< OUString> aVector; + + if (!isNew()) + { + Reference< XResultSet > xResult = m_pConnection->getMetaData()->getColumns( + Any(), m_SchemaName, m_Name, "%"); + + if (xResult.is()) + { + Reference< XRow > xRow(xResult, UNO_QUERY); + while (xResult->next()) + aVector.push_back(xRow->getString(4)); + } + } + if (m_xColumns) + m_xColumns->reFill(aVector); + else + m_xColumns.reset(new OEvoabColumns(this,m_aMutex,aVector)); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/connectivity/source/drivers/evoab2/NTable.hxx b/connectivity/source/drivers/evoab2/NTable.hxx new file mode 100644 index 000000000..0aa30815b --- /dev/null +++ b/connectivity/source/drivers/evoab2/NTable.hxx @@ -0,0 +1,53 @@ +/* -*- 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 . + */ + +#pragma once + +#include "NConnection.hxx" +#include <connectivity/sdbcx/VTable.hxx> + +namespace connectivity::evoab +{ + typedef connectivity::sdbcx::OTable OEvoabTable_TYPEDEF; + + class OEvoabTable : public OEvoabTable_TYPEDEF + { + OEvoabConnection* m_pConnection; + + public: + OEvoabTable( sdbcx::OCollection* _pTables, + OEvoabConnection* _pConnection, + const OUString& Name, + const OUString& Type, + const OUString& Description, + const OUString& SchemaName, + const OUString& CatalogName + ); + + OEvoabConnection* getConnection() { return m_pConnection;} + + virtual void refreshColumns() override; + + OUString const & getTableName() const { return m_Name; } + OUString const & getSchema() const { return m_SchemaName; } + }; +} + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/connectivity/source/drivers/evoab2/NTables.cxx b/connectivity/source/drivers/evoab2/NTables.cxx new file mode 100644 index 000000000..69b54ba70 --- /dev/null +++ b/connectivity/source/drivers/evoab2/NTables.cxx @@ -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/. + * + * 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 "NTables.hxx" +#include <com/sun/star/sdbc/XRow.hpp> +#include <com/sun/star/sdbc/XResultSet.hpp> +#include "NCatalog.hxx" +#include <comphelper/types.hxx> +#include "NTable.hxx" +using namespace ::comphelper; + +using namespace ::cppu; +using namespace connectivity::evoab; +using namespace connectivity::sdbcx; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::lang; +using namespace dbtools; + +ObjectType OEvoabTables::createObject(const OUString& aName) +{ + Sequence< OUString > aTypes { "TABLE" }; + + Reference< XResultSet > xResult = m_xMetaData->getTables(Any(),"%",aName,aTypes); + + ObjectType xRet; + if(xResult.is()) + { + Reference< XRow > xRow(xResult,UNO_QUERY); + if(xResult->next()) // there can be only one table with this name + { + xRet = new OEvoabTable( + this, + static_cast<OEvoabCatalog&>(m_rParent).getConnection(), + aName, + xRow->getString(4), + xRow->getString(5), + "", + ""); + } + } + + ::comphelper::disposeComponent(xResult); + + return xRet; +} + +void OEvoabTables::impl_refresh( ) +{ + static_cast<OEvoabCatalog&>(m_rParent).refreshTables(); +} + +void OEvoabTables::disposing() +{ + m_xMetaData.clear(); + OCollection::disposing(); +} + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/connectivity/source/drivers/evoab2/NTables.hxx b/connectivity/source/drivers/evoab2/NTables.hxx new file mode 100644 index 000000000..7e200ff6a --- /dev/null +++ b/connectivity/source/drivers/evoab2/NTables.hxx @@ -0,0 +1,43 @@ +/* -*- 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 . + */ +#pragma once + +#include <connectivity/sdbcx/VCollection.hxx> +#include <com/sun/star/sdbc/XDatabaseMetaData.hpp> + +namespace connectivity::evoab +{ + class OEvoabTables : 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: + OEvoabTables(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) + {} + virtual void disposing() override; + }; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/connectivity/source/drivers/evoab2/evoab.component b/connectivity/source/drivers/evoab2/evoab.component new file mode 100644 index 000000000..c0928c178 --- /dev/null +++ b/connectivity/source/drivers/evoab2/evoab.component @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + --> + +<component loader="com.sun.star.loader.SharedLibrary" environment="@CPPU_ENV@" + xmlns="http://openoffice.org/2010/uno-components"> + <implementation name="com.sun.star.comp.sdbc.evoab.OEvoabDriver" + constructor="connectivity_OEvoabDriver_get_implementation"> + <service name="com.sun.star.sdbc.Driver"/> + </implementation> +</component> |