summaryrefslogtreecommitdiff
path: root/connectivity/source/drivers/mysqlc
diff options
context:
space:
mode:
authorTamas Bunth <tamas.bunth@collabora.co.uk>2018-08-16 16:35:17 +0200
committerAndras Timar <andras.timar@collabora.com>2018-08-28 20:29:12 +0200
commit490c6cd0ed877a0bd22a7592b42d70edd83114ca (patch)
tree340f64246980e3ee793309dac0453584676c3790 /connectivity/source/drivers/mysqlc
parent4e8a7a6cbca2ba4119647dfeb59da68bedb3e157 (diff)
Moving mysqlc into connectivity as a library
Additionally I erased the remains of the old mysql C++ connector. Also update the code where the clang plugins were unhappy after moving the mysqlc module. Remove mysql-cpp-connector external. Change-Id: I771cc7afacf5012fc349afb6b36828fb0fee5a66 Reviewed-on: https://gerrit.libreoffice.org/59200 Tested-by: Jenkins Reviewed-by: Tamás Bunth <btomi96@gmail.com> Reviewed-on: https://gerrit.libreoffice.org/59713 Reviewed-by: Andras Timar <andras.timar@collabora.com> Tested-by: Andras Timar <andras.timar@collabora.com>
Diffstat (limited to 'connectivity/source/drivers/mysqlc')
-rw-r--r--connectivity/source/drivers/mysqlc/DataAccess.xcu35
-rw-r--r--connectivity/source/drivers/mysqlc/META-INF/manifest.xml25
-rw-r--r--connectivity/source/drivers/mysqlc/description-en-US.txt1
-rw-r--r--connectivity/source/drivers/mysqlc/description.xml40
-rw-r--r--connectivity/source/drivers/mysqlc/mysqlc.component15
-rw-r--r--connectivity/source/drivers/mysqlc/mysqlc_connection.cxx499
-rw-r--r--connectivity/source/drivers/mysqlc/mysqlc_connection.hxx183
-rw-r--r--connectivity/source/drivers/mysqlc/mysqlc_databasemetadata.cxx989
-rw-r--r--connectivity/source/drivers/mysqlc/mysqlc_databasemetadata.hxx245
-rw-r--r--connectivity/source/drivers/mysqlc/mysqlc_driver.cxx169
-rw-r--r--connectivity/source/drivers/mysqlc/mysqlc_driver.hxx101
-rw-r--r--connectivity/source/drivers/mysqlc/mysqlc_general.cxx354
-rw-r--r--connectivity/source/drivers/mysqlc/mysqlc_general.hxx125
-rw-r--r--connectivity/source/drivers/mysqlc/mysqlc_prepared_resultset.cxx1097
-rw-r--r--connectivity/source/drivers/mysqlc/mysqlc_prepared_resultset.hxx248
-rw-r--r--connectivity/source/drivers/mysqlc/mysqlc_preparedstatement.cxx595
-rw-r--r--connectivity/source/drivers/mysqlc/mysqlc_preparedstatement.hxx161
-rw-r--r--connectivity/source/drivers/mysqlc/mysqlc_propertyids.hxx51
-rw-r--r--connectivity/source/drivers/mysqlc/mysqlc_resultset.cxx1068
-rw-r--r--connectivity/source/drivers/mysqlc/mysqlc_resultset.hxx246
-rw-r--r--connectivity/source/drivers/mysqlc/mysqlc_resultsetmetadata.cxx203
-rw-r--r--connectivity/source/drivers/mysqlc/mysqlc_resultsetmetadata.hxx109
-rw-r--r--connectivity/source/drivers/mysqlc/mysqlc_services.cxx107
-rw-r--r--connectivity/source/drivers/mysqlc/mysqlc_statement.cxx361
-rw-r--r--connectivity/source/drivers/mysqlc/mysqlc_statement.hxx185
-rw-r--r--connectivity/source/drivers/mysqlc/mysqlc_subcomponent.hxx164
-rw-r--r--connectivity/source/drivers/mysqlc/mysqlc_types.cxx680
-rw-r--r--connectivity/source/drivers/mysqlc/mysqlc_types.hxx46
28 files changed, 8102 insertions, 0 deletions
diff --git a/connectivity/source/drivers/mysqlc/DataAccess.xcu b/connectivity/source/drivers/mysqlc/DataAccess.xcu
new file mode 100644
index 000000000000..2b652ec87649
--- /dev/null
+++ b/connectivity/source/drivers/mysqlc/DataAccess.xcu
@@ -0,0 +1,35 @@
+<!--
+ * 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 .
+ -->
+<oor:node xmlns:oor="http://openoffice.org/2001/registry" xmlns:xs="http://www.w3.org/2001/XMLSchema" oor:name="DataAccess" oor:package="org.openoffice.Office">
+ <node oor:name="UserDefinedDriverSettings">
+ <node oor:name="org.openoffice.comp.connectivity.mysql_native.Driver" oor:op="replace">
+ <prop oor:name="DriverName">
+ <value>org.openoffice.comp.connectivity.mysql_native.Driver</value>
+ </prop>
+ <prop oor:name="DriverPageDisplayName">
+ <value>MySQL native driver</value>
+ </prop>
+ <prop oor:name="DriverTypeDisplayName">
+ <value>MySQL native driver</value>
+ </prop>
+ <prop oor:name="DriverDsnPrefix">
+ <value>sdbc:mysqlc:</value>
+ </prop>
+ </node>
+ </node>
+</oor:node>
diff --git a/connectivity/source/drivers/mysqlc/META-INF/manifest.xml b/connectivity/source/drivers/mysqlc/META-INF/manifest.xml
new file mode 100644
index 000000000000..b3a94aca14c1
--- /dev/null
+++ b/connectivity/source/drivers/mysqlc/META-INF/manifest.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE manifest:manifest PUBLIC "-//OpenOffice.org//DTD Manifest 1.0//EN" "Manifest.dtd">
+<!--
+ * 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 .
+ -->
+<manifest:manifest xmlns:manifest="http://openoffice.org/2001/manifest">
+ <manifest:file-entry manifest:media-type="application/vnd.sun.star.uno-components;platform=@PLATFORM@"
+ manifest:full-path="components.rdb"/>
+ <manifest:file-entry manifest:media-type="application/vnd.sun.star.configuration-data"
+ manifest:full-path="registry/data/org/openoffice/Office/DataAccess/Drivers.xcu"/>
+</manifest:manifest>
diff --git a/connectivity/source/drivers/mysqlc/description-en-US.txt b/connectivity/source/drivers/mysqlc/description-en-US.txt
new file mode 100644
index 000000000000..d99ac31d4374
--- /dev/null
+++ b/connectivity/source/drivers/mysqlc/description-en-US.txt
@@ -0,0 +1 @@
+MySQL Connector installs a native MySQL database driver. It is faster, seamless integrated, easier to administrate and there is no need to install and setup a JDBC or ODBC driver separately. It was never easier to use MySQL databases in LibreOffice Base.
diff --git a/connectivity/source/drivers/mysqlc/description.xml b/connectivity/source/drivers/mysqlc/description.xml
new file mode 100644
index 000000000000..7335fb5d1add
--- /dev/null
+++ b/connectivity/source/drivers/mysqlc/description.xml
@@ -0,0 +1,40 @@
+<?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 .
+ -->
+<description xmlns="http://openoffice.org/extensions/description/2006" xmlns:d="http://openoffice.org/extensions/description/2006"
+ xmlns:xlink="http://www.w3.org/1999/xlink">
+
+ <identifier value="com.sun.star.mysql-connector-ooo-@PLATFORM@"/>
+ <version value="1.0.2" />
+ <platform value="@PLATFORM@" />
+ <display-name>
+ <name lang="en-US">MySQL Connector</name>
+ </display-name>
+ <dependencies>
+ <OpenOffice.org-minimal-version value="3.3" d:name="OpenOffice.org 3.3"/>
+ </dependencies>
+ <publisher>
+ <name xlink:href="http://www.documentfoundation.org" lang="en-US">The Document Foundation</name>
+ </publisher>
+ <icon>
+ <default xlink:href="images/extension_32.png" />
+ </icon>
+ <extension-description>
+ <src lang="en-US" xlink:href="description-en-US.txt"/>
+ </extension-description>
+</description>
diff --git a/connectivity/source/drivers/mysqlc/mysqlc.component b/connectivity/source/drivers/mysqlc/mysqlc.component
new file mode 100644
index 000000000000..e4295110f84b
--- /dev/null
+++ b/connectivity/source/drivers/mysqlc/mysqlc.component
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+-->
+<component xmlns="http://openoffice.org/2010/uno-components"
+ loader="com.sun.star.loader.SharedLibrary">
+ <implementation name="com.sun.star.comp.sdbc.mysqlc.MysqlCDriver">
+ <service name="com.sun.star.sdbc.Driver"/>
+ </implementation>
+</component>
diff --git a/connectivity/source/drivers/mysqlc/mysqlc_connection.cxx b/connectivity/source/drivers/mysqlc/mysqlc_connection.cxx
new file mode 100644
index 000000000000..74c68b2dbe11
--- /dev/null
+++ b/connectivity/source/drivers/mysqlc/mysqlc_connection.cxx
@@ -0,0 +1,499 @@
+/* -*- 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 <memory>
+#include "mysqlc_connection.hxx"
+#include "mysqlc_databasemetadata.hxx"
+
+#include "mysqlc_driver.hxx"
+#include "mysqlc_statement.hxx"
+#include "mysqlc_preparedstatement.hxx"
+#include "mysqlc_general.hxx"
+
+#include <com/sun/star/sdbc/ColumnValue.hpp>
+#include <com/sun/star/sdbc/XRow.hpp>
+#include <com/sun/star/sdbc/TransactionIsolation.hpp>
+#include <com/sun/star/lang/DisposedException.hpp>
+#include <com/sun/star/beans/NamedValue.hpp>
+
+#include <osl/module.hxx>
+#include <osl/thread.h>
+#include <osl/file.h>
+#include <sal/log.hxx>
+#include <osl/diagnose.h>
+#include <rtl/uri.hxx>
+#include <rtl/ustrbuf.hxx>
+
+using namespace connectivity::mysqlc;
+
+#include <stdio.h>
+
+using namespace com::sun::star::uno;
+using namespace com::sun::star::container;
+using namespace com::sun::star::lang;
+using namespace com::sun::star::beans;
+using namespace com::sun::star::sdbc;
+using ::osl::MutexGuard;
+
+#define MYSQLC_URI_PREFIX "sdbc:mysqlc:"
+
+namespace
+{
+void lcl_executeUpdate(MYSQL* pMySql, const rtl::OString& sql)
+{
+ mysql_real_query(pMySql, sql.getStr(), sql.getLength());
+ // TODO handle error
+}
+}
+
+OConnection::OConnection(MysqlCDriver& _rDriver)
+ : OMetaConnection_BASE(m_aMutex)
+ , m_xMetaData(nullptr)
+ , m_xDriver(&_rDriver)
+{
+}
+
+OConnection::~OConnection()
+{
+ if (!isClosed())
+ {
+ close();
+ }
+}
+
+void OConnection::construct(const rtl::OUString& url, const Sequence<PropertyValue>& info)
+{
+ MutexGuard aGuard(m_aMutex);
+
+ mysql_library_init(0, nullptr, nullptr);
+ mysql_init(&m_mysql);
+
+ // use TCP as connection
+ mysql_protocol_type protocol = MYSQL_PROTOCOL_TCP;
+ mysql_options(&m_mysql, MYSQL_OPT_PROTOCOL, &protocol);
+
+ sal_Int32 nIndex;
+ rtl::OUString token;
+ rtl::OUString aHostName("localhost");
+ sal_Int32 nPort = 3306;
+ rtl::OUString aDbName;
+
+ m_settings.encoding = MysqlCDriver::getDefaultEncoding();
+
+ // parse url. Url has the following format:
+ // external server: sdbc:mysqlc:[hostname]:[port]/[dbname]
+
+ if (url.startsWith(MYSQLC_URI_PREFIX))
+ {
+ nIndex = 12;
+ }
+ else
+ {
+ // sdbc:mysql:mysqlc:[hostname]:[port]/[dbname]
+ nIndex = 18;
+ }
+
+ token = url.getToken(0, '/', nIndex);
+ if (!token.isEmpty())
+ {
+ sal_Int32 nIndex1 = 0;
+ rtl::OUString hostandport = token.getToken(0, ':', nIndex1);
+ if (!hostandport.isEmpty())
+ {
+ aHostName = hostandport;
+ hostandport = token.getToken(0, ':', nIndex1);
+ if (!hostandport.isEmpty() && nIndex1)
+ {
+ nPort = hostandport.toInt32();
+ }
+ token = url.getToken(0, '/', nIndex);
+ if (!token.isEmpty() && nIndex)
+ {
+ aDbName = token;
+ }
+ }
+ }
+
+ // get user and password for mysql connection
+ const PropertyValue* pIter = info.getConstArray();
+ const PropertyValue* pEnd = pIter + info.getLength();
+ rtl::OUString aUser, aPass, sUnixSocket, sNamedPipe;
+ bool unixSocketPassed = false;
+ bool namedPipePassed = false;
+
+ m_settings.connectionURL = url;
+ for (; pIter != pEnd; ++pIter)
+ {
+ if (pIter->Name == "user")
+ {
+ OSL_VERIFY(pIter->Value >>= aUser);
+ }
+ else if (pIter->Name == "password")
+ {
+ OSL_VERIFY(pIter->Value >>= aPass);
+ }
+ else if (pIter->Name == "LocalSocket")
+ {
+ OSL_VERIFY(pIter->Value >>= sUnixSocket);
+ unixSocketPassed = !sUnixSocket.isEmpty();
+ }
+ else if (pIter->Name == "NamedPipe")
+ {
+ OSL_VERIFY(pIter->Value >>= sNamedPipe);
+ namedPipePassed = !sNamedPipe.isEmpty();
+ }
+ else if (pIter->Name == "PublicConnectionURL")
+ {
+ OSL_VERIFY(pIter->Value >>= m_settings.connectionURL);
+ }
+ else if (pIter->Name == "NewURL")
+ { // legacy name for "PublicConnectionURL"
+ OSL_VERIFY(pIter->Value >>= m_settings.connectionURL);
+ }
+ }
+
+ rtl::OString host_str = rtl::OUStringToOString(aHostName, m_settings.encoding);
+ rtl::OString user_str = rtl::OUStringToOString(aUser, m_settings.encoding);
+ rtl::OString pass_str = rtl::OUStringToOString(aPass, m_settings.encoding);
+ rtl::OString schema_str = rtl::OUStringToOString(aDbName, m_settings.encoding);
+ rtl::OString socket_str;
+ if (unixSocketPassed)
+ {
+ socket_str = rtl::OUStringToOString(sUnixSocket, m_settings.encoding);
+ }
+ else if (namedPipePassed)
+ {
+ socket_str = rtl::OUStringToOString(sNamedPipe, m_settings.encoding);
+ }
+
+ // flags can also be passed as last parameter
+ if (!mysql_real_connect(&m_mysql, host_str.getStr(), user_str.getStr(), pass_str.getStr(),
+ schema_str.getStr(), nPort, socket_str.getStr(), 0))
+ mysqlc_sdbc_driver::throwSQLExceptionWithMsg(mysql_error(&m_mysql), mysql_errno(&m_mysql),
+ *this, getConnectionEncoding());
+
+ m_settings.schema = aDbName;
+
+ // Check if the server is 4.1 or above
+ if (getMysqlVersion() < 40100)
+ {
+ throw SQLException("MariaDB LibreOffice Connector requires MySQL Server 4.1 or above",
+ *this, rtl::OUString(), 0, Any());
+ }
+
+ lcl_executeUpdate(&m_mysql, rtl::OString{ "SET session sql_mode='ANSI_QUOTES'" });
+ lcl_executeUpdate(&m_mysql, rtl::OString{ "SET NAMES utf8" });
+}
+
+rtl::OUString OConnection::getImplementationName()
+{
+ return rtl::OUString("com.sun.star.sdbc.drivers.mysqlc.OConnection");
+}
+
+css::uno::Sequence<rtl::OUString> OConnection::getSupportedServiceNames()
+{
+ css::uno::Sequence<rtl::OUString> s(1);
+ s[0] = "com.sun.star.sdbc.Connection";
+ return s;
+}
+
+sal_Bool OConnection::supportsService(rtl::OUString const& ServiceName)
+{
+ return cppu::supportsService(this, ServiceName);
+}
+
+Reference<XStatement> SAL_CALL OConnection::createStatement()
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OConnection_BASE::rBHelper.bDisposed);
+
+ // create a statement
+ Reference<XStatement> xReturn;
+ // the statement can only be executed once
+ xReturn = new OStatement(this);
+ m_aStatements.push_back(WeakReferenceHelper(xReturn));
+
+ return xReturn;
+}
+
+Reference<XPreparedStatement> SAL_CALL OConnection::prepareStatement(const rtl::OUString& _sSql)
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OConnection_BASE::rBHelper.bDisposed);
+ const rtl::OString sSqlStatement
+ = rtl::OUStringToOString(_sSql, getConnectionEncoding()); // FIXME transform statement ?
+
+ MYSQL_STMT* pStmt = mysql_stmt_init(&m_mysql);
+ mysql_stmt_prepare(pStmt, sSqlStatement.getStr(), sSqlStatement.getLength());
+
+ unsigned int nErrorNum = mysql_errno(&m_mysql);
+ if (nErrorNum != 0)
+ mysqlc_sdbc_driver::throwSQLExceptionWithMsg(mysql_error(&m_mysql), nErrorNum, *this,
+ getConnectionEncoding());
+
+ Reference<XPreparedStatement> xStatement;
+ xStatement = new OPreparedStatement(this, pStmt);
+ m_aStatements.push_back(WeakReferenceHelper(xStatement));
+ return xStatement;
+}
+
+Reference<XPreparedStatement> SAL_CALL OConnection::prepareCall(const rtl::OUString& /*_sSql*/)
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OConnection_BASE::rBHelper.bDisposed);
+
+ mysqlc_sdbc_driver::throwFeatureNotImplementedException("OConnection::prepareCall", *this);
+ return Reference<XPreparedStatement>();
+}
+
+rtl::OUString SAL_CALL OConnection::nativeSQL(const rtl::OUString& /*_sSql*/)
+{
+ MutexGuard aGuard(m_aMutex);
+
+ // const rtl::OUString sSqlStatement = transFormPreparedStatement( _sSql );
+ rtl::OUString sNativeSQL;
+ // TODO
+ return sNativeSQL;
+}
+
+void SAL_CALL OConnection::setAutoCommit(sal_Bool autoCommit)
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OConnection_BASE::rBHelper.bDisposed);
+ if (!mysql_autocommit(&m_mysql, autoCommit))
+ mysqlc_sdbc_driver::throwSQLExceptionWithMsg(mysql_error(&m_mysql), mysql_errno(&m_mysql),
+ *this, getConnectionEncoding());
+}
+
+sal_Bool SAL_CALL OConnection::getAutoCommit()
+{
+ // you have to distinguish which if you are in autocommit mode or not
+ // at normal case true should be fine here
+
+ // TODO use SELECT @@autocommit query for that
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OConnection_BASE::rBHelper.bDisposed);
+
+ bool autoCommit = false;
+ return autoCommit;
+}
+
+void SAL_CALL OConnection::commit()
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OConnection_BASE::rBHelper.bDisposed);
+
+ if (!mysql_commit(&m_mysql))
+ mysqlc_sdbc_driver::throwSQLExceptionWithMsg(mysql_error(&m_mysql), mysql_errno(&m_mysql),
+ *this, getConnectionEncoding());
+}
+
+void SAL_CALL OConnection::rollback()
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OConnection_BASE::rBHelper.bDisposed);
+
+ if (!mysql_rollback(&m_mysql))
+ mysqlc_sdbc_driver::throwSQLExceptionWithMsg(mysql_error(&m_mysql), mysql_errno(&m_mysql),
+ *this, getConnectionEncoding());
+}
+
+sal_Bool SAL_CALL OConnection::isClosed()
+{
+ MutexGuard aGuard(m_aMutex);
+
+ // just simple -> we are close when we are disposed that means someone called dispose(); (XComponent)
+ return OConnection_BASE::rBHelper.bDisposed;
+}
+
+Reference<XDatabaseMetaData> SAL_CALL OConnection::getMetaData()
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OConnection_BASE::rBHelper.bDisposed);
+
+ Reference<XDatabaseMetaData> xMetaData = m_xMetaData;
+ if (!xMetaData.is())
+ {
+ xMetaData = new ODatabaseMetaData(*this, &m_mysql);
+ m_xMetaData = xMetaData;
+ }
+
+ return xMetaData;
+}
+
+void SAL_CALL OConnection::setReadOnly(sal_Bool readOnly)
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OConnection_BASE::rBHelper.bDisposed);
+
+ m_settings.readOnly = readOnly;
+}
+
+sal_Bool SAL_CALL OConnection::isReadOnly()
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OConnection_BASE::rBHelper.bDisposed);
+
+ // return if your connection to readonly
+ return m_settings.readOnly;
+}
+
+void SAL_CALL OConnection::setCatalog(const rtl::OUString& /*catalog*/)
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OConnection_BASE::rBHelper.bDisposed);
+
+ // TODO How?
+}
+
+rtl::OUString SAL_CALL OConnection::getCatalog()
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OConnection_BASE::rBHelper.bDisposed);
+
+ // TODO How?
+ return OUString{};
+}
+
+void SAL_CALL OConnection::setTransactionIsolation(sal_Int32 /*level*/)
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OConnection_BASE::rBHelper.bDisposed);
+
+ // TODO
+}
+
+sal_Int32 SAL_CALL OConnection::getTransactionIsolation()
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OConnection_BASE::rBHelper.bDisposed);
+
+ return 0; // TODO
+}
+
+Reference<XNameAccess> SAL_CALL OConnection::getTypeMap()
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OConnection_BASE::rBHelper.bDisposed);
+
+ Reference<XNameAccess> t = m_typeMap;
+ return t;
+}
+
+void SAL_CALL OConnection::setTypeMap(const Reference<XNameAccess>& typeMap)
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OConnection_BASE::rBHelper.bDisposed);
+
+ m_typeMap = typeMap;
+}
+
+// XCloseable
+void SAL_CALL OConnection::close()
+{
+ /*
+ we need block, because the mutex is a local variable,
+ which will guard the block
+ */
+ {
+ // we just dispose us
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OConnection_BASE::rBHelper.bDisposed);
+ }
+ mysql_close(&m_mysql);
+ mysql_library_end();
+ dispose();
+}
+
+// XWarningsSupplier
+Any SAL_CALL OConnection::getWarnings()
+{
+ Any x = Any();
+ // when you collected some warnings -> return it
+ return x;
+}
+
+void SAL_CALL OConnection::clearWarnings()
+{
+ // you should clear your collected warnings here#
+}
+
+void OConnection::disposing()
+{
+ // we noticed that we should be destroyed in near future so we have to dispose our statements
+ MutexGuard aGuard(m_aMutex);
+
+ for (auto const& statement : m_aStatements)
+ {
+ Reference<XComponent> xComp(statement.get(), UNO_QUERY);
+ if (xComp.is())
+ {
+ xComp->dispose();
+ }
+ }
+ m_aStatements.clear();
+
+ m_xMetaData = WeakReference<XDatabaseMetaData>();
+
+ OConnection_BASE::disposing();
+}
+
+sal_Int32 OConnection::getMysqlVersion()
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OConnection_BASE::rBHelper.bDisposed);
+
+ unsigned long version = mysql_get_server_version(&m_mysql);
+ return static_cast<sal_Int32>(version);
+}
+
+rtl::OUString OConnection::transFormPreparedStatement(const rtl::OUString& _sSQL)
+{
+ rtl::OUString sSqlStatement = _sSQL;
+ if (!m_xParameterSubstitution.is())
+ {
+ try
+ {
+ Sequence<Any> aArgs(1);
+ Reference<XConnection> xCon = this;
+ aArgs[0] <<= NamedValue("ActiveConnection", makeAny(xCon));
+
+ m_xParameterSubstitution.set(
+ m_xDriver->getFactory()->createInstanceWithArguments(
+ "org.openoffice.comp.helper.ParameterSubstitution", aArgs),
+ UNO_QUERY);
+ }
+ catch (const Exception&)
+ {
+ }
+ }
+ if (m_xParameterSubstitution.is())
+ {
+ try
+ {
+ sSqlStatement = m_xParameterSubstitution->substituteVariables(sSqlStatement, true);
+ }
+ catch (const Exception&)
+ {
+ }
+ }
+ return sSqlStatement;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/mysqlc/mysqlc_connection.hxx b/connectivity/source/drivers/mysqlc/mysqlc_connection.hxx
new file mode 100644
index 000000000000..f2bca68fff15
--- /dev/null
+++ b/connectivity/source/drivers/mysqlc/mysqlc_connection.hxx
@@ -0,0 +1,183 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef INCLUDED_MYSQLC_SOURCE_MYSQLC_CONNECTION_HXX
+#define INCLUDED_MYSQLC_SOURCE_MYSQLC_CONNECTION_HXX
+
+#include <memory>
+#include "mysqlc_subcomponent.hxx"
+#include "mysqlc_types.hxx"
+
+#include <com/sun/star/beans/PropertyValue.hpp>
+#include <com/sun/star/lang/DisposedException.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/lang/XUnoTunnel.hpp>
+#include <com/sun/star/sdbc/ColumnSearch.hpp>
+#include <com/sun/star/sdbc/ColumnValue.hpp>
+#include <com/sun/star/sdbc/DataType.hpp>
+#include <com/sun/star/sdbc/SQLWarning.hpp>
+#include <com/sun/star/sdbc/XConnection.hpp>
+#include <com/sun/star/sdbc/XWarningsSupplier.hpp>
+#include <com/sun/star/util/XStringSubstitution.hpp>
+
+#include <cppuhelper/compbase3.hxx>
+#include <cppuhelper/weakref.hxx>
+#include <rtl/string.hxx>
+#include <rtl/ref.hxx>
+
+#include <mysql.h>
+
+#include <map>
+
+namespace sql
+{
+class SQLException;
+}
+
+namespace connectivity
+{
+class OMetaConnection;
+class ODatabaseMetaData;
+
+namespace mysqlc
+{
+using ::com::sun::star::sdbc::SQLException;
+using ::com::sun::star::sdbc::SQLWarning;
+using ::com::sun::star::uno::RuntimeException;
+typedef css::uno::Reference<css::container::XNameAccess> my_XNameAccessRef;
+
+typedef ::cppu::WeakComponentImplHelper3<css::sdbc::XConnection, css::sdbc::XWarningsSupplier,
+ css::lang::XServiceInfo>
+ OMetaConnection_BASE;
+struct ConnectionSettings
+{
+ rtl_TextEncoding encoding;
+ rtl::OUString schema;
+ rtl::OUString connectionURL;
+ bool readOnly;
+};
+
+class MysqlCDriver;
+
+typedef OMetaConnection_BASE OConnection_BASE;
+
+typedef std::vector<css::uno::WeakReferenceHelper> OWeakRefArray;
+
+class OConnection final : public OBase_Mutex, public OConnection_BASE
+{
+private:
+ MYSQL m_mysql;
+ ConnectionSettings m_settings;
+ css::uno::Reference<css::container::XNameAccess> m_typeMap;
+ css::uno::Reference<css::util::XStringSubstitution> m_xParameterSubstitution;
+
+ // Data attributes
+
+ css::uno::WeakReference<css::sdbc::XDatabaseMetaData> m_xMetaData;
+
+ OWeakRefArray m_aStatements; // vector containing a list
+ // of all the Statement objects
+ // for this Connection
+
+ rtl::Reference<MysqlCDriver> m_xDriver; // Pointer to the owning driver object
+public:
+ MYSQL* getMysqlConnection() { return &m_mysql; }
+
+ /// @throws SQLException
+ /// @throws RuntimeException
+ sal_Int32 getMysqlVersion();
+
+ /// @throws SQLException
+ void construct(const rtl::OUString& url,
+ const css::uno::Sequence<css::beans::PropertyValue>& info);
+
+ OConnection(MysqlCDriver& _rDriver);
+ virtual ~OConnection() override;
+
+ rtl_TextEncoding getConnectionEncoding() const { return m_settings.encoding; }
+
+ // OComponentHelper
+ virtual void SAL_CALL disposing() SAL_OVERRIDE;
+
+ // XServiceInfo
+ virtual rtl::OUString SAL_CALL getImplementationName() SAL_OVERRIDE;
+
+ virtual sal_Bool SAL_CALL supportsService(rtl::OUString const& ServiceName) SAL_OVERRIDE;
+
+ virtual css::uno::Sequence<rtl::OUString> SAL_CALL getSupportedServiceNames() SAL_OVERRIDE;
+
+ // XConnection
+ css::uno::Reference<css::sdbc::XStatement> SAL_CALL createStatement() SAL_OVERRIDE;
+
+ css::uno::Reference<css::sdbc::XPreparedStatement>
+ SAL_CALL prepareStatement(const rtl::OUString& sql) SAL_OVERRIDE;
+
+ css::uno::Reference<css::sdbc::XPreparedStatement>
+ SAL_CALL prepareCall(const rtl::OUString& sql) SAL_OVERRIDE;
+
+ rtl::OUString SAL_CALL nativeSQL(const rtl::OUString& sql) SAL_OVERRIDE;
+
+ void SAL_CALL setAutoCommit(sal_Bool autoCommit) SAL_OVERRIDE;
+
+ sal_Bool SAL_CALL getAutoCommit() SAL_OVERRIDE;
+
+ void SAL_CALL commit() SAL_OVERRIDE;
+
+ void SAL_CALL rollback() SAL_OVERRIDE;
+
+ sal_Bool SAL_CALL isClosed() SAL_OVERRIDE;
+
+ css::uno::Reference<css::sdbc::XDatabaseMetaData> SAL_CALL getMetaData() SAL_OVERRIDE;
+
+ void SAL_CALL setReadOnly(sal_Bool readOnly) SAL_OVERRIDE;
+
+ sal_Bool SAL_CALL isReadOnly() SAL_OVERRIDE;
+
+ void SAL_CALL setCatalog(const rtl::OUString& catalog) SAL_OVERRIDE;
+
+ rtl::OUString SAL_CALL getCatalog() SAL_OVERRIDE;
+
+ void SAL_CALL setTransactionIsolation(sal_Int32 level) SAL_OVERRIDE;
+
+ sal_Int32 SAL_CALL getTransactionIsolation() SAL_OVERRIDE;
+
+ my_XNameAccessRef SAL_CALL getTypeMap() SAL_OVERRIDE;
+
+ void SAL_CALL setTypeMap(const my_XNameAccessRef& typeMap) SAL_OVERRIDE;
+ // XCloseable
+ void SAL_CALL close() SAL_OVERRIDE;
+ // XWarningsSupplier
+ css::uno::Any SAL_CALL getWarnings() SAL_OVERRIDE;
+ void SAL_CALL clearWarnings() SAL_OVERRIDE;
+
+ // TODO: Not used
+ //sal_Int32 sdbcColumnType(rtl::OUString typeName);
+ const ConnectionSettings& getConnectionSettings() const { return m_settings; }
+ rtl::OUString transFormPreparedStatement(const rtl::OUString& _sSQL);
+
+ const MysqlCDriver& getDriver() const { return *m_xDriver.get(); }
+
+}; /* OConnection */
+// TODO: Not used.
+//inline rtl::OUString getPattern(rtl::OUString p) { return (p.getLength()) ? p : ASC2OU("%"); }
+} /* mysqlc */
+} /* connectivity */
+#endif // INCLUDED_MYSQLC_SOURCE_MYSQLC_CONNECTION_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/mysqlc/mysqlc_databasemetadata.cxx b/connectivity/source/drivers/mysqlc/mysqlc_databasemetadata.cxx
new file mode 100644
index 000000000000..1fe3f3976ae5
--- /dev/null
+++ b/connectivity/source/drivers/mysqlc/mysqlc_databasemetadata.cxx
@@ -0,0 +1,989 @@
+/* -*- 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 "mysqlc_databasemetadata.hxx"
+#include <memory>
+#include <com/sun/star/sdbc/DataType.hpp>
+#include <com/sun/star/sdbc/ResultSetType.hpp>
+#include <com/sun/star/sdbc/ResultSetConcurrency.hpp>
+#include <com/sun/star/sdbc/TransactionIsolation.hpp>
+#include <com/sun/star/sdbc/KeyRule.hpp>
+#include <com/sun/star/sdbc/Deferrability.hpp>
+#include <com/sun/star/sdbc/IndexType.hpp>
+#include <com/sun/star/sdbc/BestRowScope.hpp>
+#include <com/sun/star/sdbc/ColumnType.hpp>
+#include <com/sun/star/lang/XInitialization.hpp>
+
+#include <rtl/ustrbuf.hxx>
+#include "mysqlc_general.hxx"
+#include "mysqlc_statement.hxx"
+#include "mysqlc_driver.hxx"
+#include "mysqlc_preparedstatement.hxx"
+
+#include <stdio.h>
+
+using namespace connectivity::mysqlc;
+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 mysqlc_sdbc_driver::getStringFromAny;
+
+#include <sal/macros.h>
+
+static std::string wild("%");
+
+void lcl_setRows_throw(const Reference<XResultSet>& _xResultSet, sal_Int32 _nType,
+ const std::vector<std::vector<Any>>& _rRows)
+{
+ Reference<XInitialization> xIni(_xResultSet, UNO_QUERY);
+ Sequence<Any> aArgs(2);
+ aArgs[0] <<= _nType;
+
+ Sequence<Sequence<Any>> aRows(_rRows.size());
+
+ std::vector<std::vector<Any>>::const_iterator aIter = _rRows.begin();
+ Sequence<Any>* pRowsIter = aRows.getArray();
+ Sequence<Any>* pRowsEnd = pRowsIter + aRows.getLength();
+ for (; pRowsIter != pRowsEnd; ++pRowsIter, ++aIter)
+ {
+ if (!aIter->empty())
+ {
+ Sequence<Any> aSeq(&(*aIter->begin()), aIter->size());
+ (*pRowsIter) = aSeq;
+ }
+ }
+ aArgs[1] <<= aRows;
+ xIni->initialize(aArgs);
+}
+
+ODatabaseMetaData::ODatabaseMetaData(OConnection& _rCon, MYSQL* pMySql)
+ : m_rConnection(_rCon)
+ , m_pMySql(pMySql)
+{
+}
+
+ODatabaseMetaData::~ODatabaseMetaData() {}
+
+rtl::OUString SAL_CALL ODatabaseMetaData::getCatalogSeparator() { return rtl::OUString(); }
+
+sal_Int32 SAL_CALL ODatabaseMetaData::getMaxBinaryLiteralLength() { return 16777208L; }
+
+sal_Int32 SAL_CALL ODatabaseMetaData::getMaxRowSize()
+{
+ return 2147483647L - 8; // Max buffer size - HEADER
+}
+
+sal_Int32 SAL_CALL ODatabaseMetaData::getMaxCatalogNameLength() { return 32; }
+
+sal_Int32 SAL_CALL ODatabaseMetaData::getMaxCharLiteralLength() { return 16777208; }
+
+sal_Int32 SAL_CALL ODatabaseMetaData::getMaxColumnNameLength() { return 64; }
+
+sal_Int32 SAL_CALL ODatabaseMetaData::getMaxColumnsInIndex() { return 16; }
+
+sal_Int32 SAL_CALL ODatabaseMetaData::getMaxCursorNameLength() { return 64; }
+
+sal_Int32 SAL_CALL ODatabaseMetaData::getMaxConnections()
+{
+ // TODO
+ // SELECT @@max_connections
+ return 100;
+}
+
+sal_Int32 SAL_CALL ODatabaseMetaData::getMaxColumnsInTable() { return 512; }
+
+sal_Int32 SAL_CALL ODatabaseMetaData::getMaxStatementLength()
+{
+ // TODO
+ // "SHOW VARIABLES LIKE 'max_allowed_packet'"
+ return 32767;
+}
+
+sal_Int32 SAL_CALL ODatabaseMetaData::getMaxTableNameLength() { return 64; }
+
+sal_Int32 SAL_CALL ODatabaseMetaData::getMaxTablesInSelect() { return 256; }
+
+sal_Bool SAL_CALL ODatabaseMetaData::doesMaxRowSizeIncludeBlobs() { return true; }
+
+sal_Bool SAL_CALL ODatabaseMetaData::storesLowerCaseQuotedIdentifiers()
+{
+ // TODO
+ return false;
+}
+
+sal_Bool SAL_CALL ODatabaseMetaData::storesLowerCaseIdentifiers()
+{
+ //TODO;
+ return false;
+}
+
+sal_Bool SAL_CALL ODatabaseMetaData::storesMixedCaseQuotedIdentifiers()
+{
+ // TODO
+ return false;
+}
+
+sal_Bool SAL_CALL ODatabaseMetaData::storesMixedCaseIdentifiers()
+{
+ // TODO
+ return false;
+}
+
+sal_Bool SAL_CALL ODatabaseMetaData::storesUpperCaseQuotedIdentifiers()
+{
+ // TODO
+ return false;
+}
+
+sal_Bool SAL_CALL ODatabaseMetaData::storesUpperCaseIdentifiers()
+{
+ // TODO
+ return false;
+}
+
+sal_Bool SAL_CALL ODatabaseMetaData::supportsAlterTableWithAddColumn() { return true; }
+
+sal_Bool SAL_CALL ODatabaseMetaData::supportsAlterTableWithDropColumn() { return true; }
+
+sal_Int32 SAL_CALL ODatabaseMetaData::getMaxIndexLength() { return 256; }
+
+sal_Bool SAL_CALL ODatabaseMetaData::supportsNonNullableColumns() { return true; }
+
+rtl::OUString SAL_CALL ODatabaseMetaData::getCatalogTerm() { return rtl::OUString("n/a"); }
+
+rtl::OUString SAL_CALL ODatabaseMetaData::getIdentifierQuoteString() { return rtl::OUString("\""); }
+
+rtl::OUString SAL_CALL ODatabaseMetaData::getExtraNameCharacters() { return rtl::OUString("#@"); }
+
+sal_Bool SAL_CALL ODatabaseMetaData::supportsDifferentTableCorrelationNames() { return true; }
+
+sal_Bool SAL_CALL ODatabaseMetaData::isCatalogAtStart() { return true; }
+
+sal_Bool SAL_CALL ODatabaseMetaData::dataDefinitionIgnoredInTransactions() { return false; }
+
+sal_Bool SAL_CALL ODatabaseMetaData::dataDefinitionCausesTransactionCommit() { return true; }
+
+sal_Bool SAL_CALL ODatabaseMetaData::supportsDataManipulationTransactionsOnly() { return false; }
+
+sal_Bool SAL_CALL ODatabaseMetaData::supportsDataDefinitionAndDataManipulationTransactions()
+{
+ return false;
+}
+
+sal_Bool SAL_CALL ODatabaseMetaData::supportsPositionedDelete() { return false; }
+
+sal_Bool SAL_CALL ODatabaseMetaData::supportsPositionedUpdate() { return false; }
+
+sal_Bool SAL_CALL ODatabaseMetaData::supportsOpenStatementsAcrossRollback() { return false; }
+
+sal_Bool SAL_CALL ODatabaseMetaData::supportsOpenStatementsAcrossCommit() { return false; }
+
+sal_Bool SAL_CALL ODatabaseMetaData::supportsOpenCursorsAcrossCommit() { return false; }
+
+sal_Bool SAL_CALL ODatabaseMetaData::supportsOpenCursorsAcrossRollback() { return false; }
+
+sal_Bool SAL_CALL ODatabaseMetaData::supportsTransactionIsolationLevel(sal_Int32 /*level*/)
+{
+ return true;
+}
+
+sal_Bool SAL_CALL ODatabaseMetaData::supportsSchemasInDataManipulation() { return true; }
+
+sal_Bool SAL_CALL ODatabaseMetaData::supportsANSI92FullSQL() { return false; }
+
+sal_Bool SAL_CALL ODatabaseMetaData::supportsANSI92EntryLevelSQL() { return true; }
+
+sal_Bool SAL_CALL ODatabaseMetaData::supportsIntegrityEnhancementFacility() { return false; }
+
+sal_Bool SAL_CALL ODatabaseMetaData::supportsSchemasInIndexDefinitions() { return true; }
+
+sal_Bool SAL_CALL ODatabaseMetaData::supportsSchemasInTableDefinitions() { return true; }
+
+sal_Bool SAL_CALL ODatabaseMetaData::supportsCatalogsInTableDefinitions() { return false; }
+
+sal_Bool SAL_CALL ODatabaseMetaData::supportsCatalogsInIndexDefinitions() { return false; }
+
+sal_Bool SAL_CALL ODatabaseMetaData::supportsCatalogsInDataManipulation() { return false; }
+
+sal_Bool SAL_CALL ODatabaseMetaData::supportsOuterJoins() { return true; }
+
+sal_Int32 SAL_CALL ODatabaseMetaData::getMaxStatements() { return 0; }
+
+sal_Int32 SAL_CALL ODatabaseMetaData::getMaxProcedureNameLength() { return 64; }
+
+sal_Int32 SAL_CALL ODatabaseMetaData::getMaxSchemaNameLength() { return 64; }
+
+sal_Bool SAL_CALL ODatabaseMetaData::supportsTransactions() { return true; }
+
+sal_Bool SAL_CALL ODatabaseMetaData::allProceduresAreCallable() { return false; }
+
+sal_Bool SAL_CALL ODatabaseMetaData::supportsStoredProcedures()
+{
+ return m_rConnection.getMysqlVersion() >= 50000;
+}
+
+sal_Bool SAL_CALL ODatabaseMetaData::supportsSelectForUpdate()
+{
+ return m_rConnection.getMysqlVersion() >= 40000;
+}
+
+sal_Bool SAL_CALL ODatabaseMetaData::allTablesAreSelectable() { return false; }
+
+sal_Bool SAL_CALL ODatabaseMetaData::isReadOnly() { return false; }
+
+sal_Bool SAL_CALL ODatabaseMetaData::usesLocalFiles() { return false; }
+
+sal_Bool SAL_CALL ODatabaseMetaData::usesLocalFilePerTable() { return false; }
+
+sal_Bool SAL_CALL ODatabaseMetaData::supportsTypeConversion() { return true; }
+
+sal_Bool SAL_CALL ODatabaseMetaData::nullPlusNonNullIsNull() { return true; }
+
+sal_Bool SAL_CALL ODatabaseMetaData::supportsColumnAliasing() { return true; }
+
+sal_Bool SAL_CALL ODatabaseMetaData::supportsTableCorrelationNames() { return true; }
+
+sal_Bool SAL_CALL ODatabaseMetaData::supportsConvert(sal_Int32 /*fromType*/, sal_Int32 /*toType*/)
+{
+ // TODO
+ return false;
+}
+
+sal_Bool SAL_CALL ODatabaseMetaData::supportsExpressionsInOrderBy() { return true; }
+
+sal_Bool SAL_CALL ODatabaseMetaData::supportsGroupBy() { return true; }
+
+sal_Bool SAL_CALL ODatabaseMetaData::supportsGroupByBeyondSelect() { return true; }
+
+sal_Bool SAL_CALL ODatabaseMetaData::supportsGroupByUnrelated() { return true; }
+
+sal_Bool SAL_CALL ODatabaseMetaData::supportsMultipleTransactions() { return true; }
+
+sal_Bool SAL_CALL ODatabaseMetaData::supportsMultipleResultSets() { return false; }
+
+sal_Bool SAL_CALL ODatabaseMetaData::supportsLikeEscapeClause() { return true; }
+
+sal_Bool SAL_CALL ODatabaseMetaData::supportsOrderByUnrelated() { return false; }
+
+sal_Bool SAL_CALL ODatabaseMetaData::supportsUnion()
+{
+ return m_rConnection.getMysqlVersion() >= 40000;
+}
+
+sal_Bool SAL_CALL ODatabaseMetaData::supportsUnionAll()
+{
+ return m_rConnection.getMysqlVersion() >= 40000;
+}
+
+sal_Bool SAL_CALL ODatabaseMetaData::supportsMixedCaseIdentifiers()
+{
+ // TODO
+ return false;
+}
+
+sal_Bool SAL_CALL ODatabaseMetaData::supportsMixedCaseQuotedIdentifiers()
+{
+ // TODO
+ return false;
+}
+
+sal_Bool SAL_CALL ODatabaseMetaData::nullsAreSortedAtEnd() { return false; }
+
+sal_Bool SAL_CALL ODatabaseMetaData::nullsAreSortedAtStart()
+{
+ return m_rConnection.getMysqlVersion() > 40001 && m_rConnection.getMysqlVersion() < 40011;
+}
+
+sal_Bool SAL_CALL ODatabaseMetaData::nullsAreSortedHigh() { return false; }
+
+sal_Bool SAL_CALL ODatabaseMetaData::nullsAreSortedLow() { return !nullsAreSortedHigh(); }
+
+sal_Bool SAL_CALL ODatabaseMetaData::supportsSchemasInProcedureCalls()
+{
+ return m_rConnection.getMysqlVersion() >= 32200;
+}
+
+sal_Bool SAL_CALL ODatabaseMetaData::supportsSchemasInPrivilegeDefinitions()
+{
+ return m_rConnection.getMysqlVersion() >= 32200;
+}
+
+sal_Bool SAL_CALL ODatabaseMetaData::supportsCatalogsInProcedureCalls() { return false; }
+
+sal_Bool SAL_CALL ODatabaseMetaData::supportsCatalogsInPrivilegeDefinitions() { return false; }
+
+sal_Bool SAL_CALL ODatabaseMetaData::supportsCorrelatedSubqueries()
+{
+ return m_rConnection.getMysqlVersion() >= 40100;
+}
+
+sal_Bool SAL_CALL ODatabaseMetaData::supportsSubqueriesInComparisons()
+{
+ return m_rConnection.getMysqlVersion() >= 40100;
+}
+
+sal_Bool SAL_CALL ODatabaseMetaData::supportsSubqueriesInExists()
+{
+ return m_rConnection.getMysqlVersion() >= 40100;
+}
+
+sal_Bool SAL_CALL ODatabaseMetaData::supportsSubqueriesInIns()
+{
+ return m_rConnection.getMysqlVersion() >= 40100;
+}
+
+sal_Bool SAL_CALL ODatabaseMetaData::supportsSubqueriesInQuantifieds()
+{
+ return m_rConnection.getMysqlVersion() >= 40100;
+}
+
+sal_Bool SAL_CALL ODatabaseMetaData::supportsANSI92IntermediateSQL() { return false; }
+
+rtl::OUString SAL_CALL ODatabaseMetaData::getURL()
+{
+ return m_rConnection.getConnectionSettings().connectionURL;
+}
+
+rtl::OUString SAL_CALL ODatabaseMetaData::getUserName()
+{
+ // TODO execute "SELECT USER()"
+ return rtl::OUString();
+}
+
+rtl::OUString SAL_CALL ODatabaseMetaData::getDriverName()
+{
+ return rtl::OUString("MySQL Connector/OO.org");
+}
+
+rtl::OUString SAL_CALL ODatabaseMetaData::getDriverVersion() { return rtl::OUString("0.9.2"); }
+
+rtl::OUString SAL_CALL ODatabaseMetaData::getDatabaseProductVersion()
+{
+ return rtl::OStringToOUString(mysql_get_server_info(m_pMySql),
+ m_rConnection.getConnectionEncoding());
+}
+
+rtl::OUString SAL_CALL ODatabaseMetaData::getDatabaseProductName()
+{
+ return rtl::OUString("MySQL");
+}
+
+rtl::OUString SAL_CALL ODatabaseMetaData::getProcedureTerm() { return rtl::OUString("procedure"); }
+
+rtl::OUString SAL_CALL ODatabaseMetaData::getSchemaTerm() { return rtl::OUString("database"); }
+
+sal_Int32 SAL_CALL ODatabaseMetaData::getDriverMajorVersion()
+{
+ // TODO
+ return MARIADBC_VERSION_MAJOR;
+}
+
+sal_Int32 SAL_CALL ODatabaseMetaData::getDefaultTransactionIsolation()
+{
+ return m_rConnection.getMysqlVersion() >= 32336 ? TransactionIsolation::READ_COMMITTED
+ : TransactionIsolation::NONE;
+}
+
+sal_Int32 SAL_CALL ODatabaseMetaData::getDriverMinorVersion()
+{
+ // TODO
+ return MARIADBC_VERSION_MINOR;
+}
+
+rtl::OUString SAL_CALL ODatabaseMetaData::getSQLKeywords()
+{
+ return rtl::OUString("ACCESSIBLE, ADD, ALL,"
+ "ALTER, ANALYZE, AND, AS, ASC, ASENSITIVE, BEFORE,"
+ "BETWEEN, BIGINT, BINARY, BLOB, BOTH, BY, CALL,"
+ "CASCADE, CASE, CHANGE, CHAR, CHARACTER, CHECK,"
+ "COLLATE, COLUMN, CONDITION, CONNECTION, CONSTRAINT,"
+ "CONTINUE, CONVERT, CREATE, CROSS, CURRENT_DATE,"
+ "CURRENT_TIME, CURRENT_TIMESTAMP, CURRENT_USER, CURSOR,"
+ "DATABASE, DATABASES, DAY_HOUR, DAY_MICROSECOND,"
+ "DAY_MINUTE, DAY_SECOND, DEC, DECIMAL, DECLARE,"
+ "DEFAULT, DELAYED, DELETE, DESC, DESCRIBE,"
+ "DETERMINISTIC, DISTINCT, DISTINCTROW, DIV, DOUBLE,"
+ "DROP, DUAL, EACH, ELSE, ELSEIF, ENCLOSED,"
+ "ESCAPED, EXISTS, EXIT, EXPLAIN, FALSE, FETCH,"
+ "FLOAT, FLOAT4, FLOAT8, FOR, FORCE, FOREIGN, FROM,"
+ "FULLTEXT, GRANT, GROUP, HAVING, HIGH_PRIORITY,"
+ "HOUR_MICROSECOND, HOUR_MINUTE, HOUR_SECOND, IF,"
+ "IGNORE, IN, INDEX, INFILE, INNER, INOUT,"
+ "INSENSITIVE, INSERT, INT, INT1, INT2, INT3, INT4,"
+ "INT8, INTEGER, INTERVAL, INTO, IS, ITERATE, JOIN,"
+ "KEY, KEYS, KILL, LEADING, LEAVE, LEFT, LIKE,"
+ "LOCALTIMESTAMP, LOCK, LONG, LONGBLOB, LONGTEXT,"
+ "LOOP, LOW_PRIORITY, MATCH, MEDIUMBLOB, MEDIUMINT,"
+ "MEDIUMTEXT, MIDDLEINT, MINUTE_MICROSECOND,"
+ "MINUTE_SECOND, MOD, MODIFIES, NATURAL, NOT,"
+ "NO_WRITE_TO_BINLOG, NULL, NUMERIC, ON, OPTIMIZE,"
+ "OPTION, OPTIONALLY, OR, ORDER, OUT, OUTER,"
+ "OUTFILE, PRECISION, PRIMARY, PROCEDURE, PURGE,"
+ "RANGE, READ, READS, READ_ONLY, READ_WRITE, REAL,"
+ "REFERENCES, REGEXP, RELEASE, RENAME, REPEAT,"
+ "REPLACE, REQUIRE, RESTRICT, RETURN, REVOKE, RIGHT,"
+ "RLIKE, SCHEMA, SCHEMAS, SECOND_MICROSECOND, SELECT,"
+ "SENSITIVE, SEPARATOR, SET, SHOW, SMALLINT, SPATIAL,"
+ "SPECIFIC, SQL, SQLEXCEPTION, SQLSTATE, SQLWARNING,"
+ "SQL_BIG_RESULT, SQL_CALC_FOUND_ROWS, SQL_SMALL_RESULT,"
+ "SSL, STARTING, STRAIGHT_JOIN, TABLE, TERMINATED,"
+ "THEN, TINYBLOB, TINYINT, TINYTEXT, TO, TRAILING,"
+ "TRIGGER, TRUE, UNDO, UNION, UNIQUE, UNLOCK,"
+ "UNSIGNED, UPDATE, USAGE, USE, USING, UTC_DATE,"
+ "UTC_TIME, UTC_TIMESTAMP, VALUES, VARBINARY, VARCHAR,"
+ "VARCHARACTER, VARYING, WHEN, WHERE, WHILE, WITH,"
+ "WRITE, X509, XOR, YEAR_MONTH, ZEROFILL"
+ "GENERAL, IGNORE_SERVER_IDS, MASTER_HEARTBEAT_PERIOD,"
+ "MAXVALUE, RESIGNAL, SIGNAL, SLOW");
+}
+
+rtl::OUString SAL_CALL ODatabaseMetaData::getSearchStringEscape() { return rtl::OUString("\\"); }
+
+rtl::OUString SAL_CALL ODatabaseMetaData::getStringFunctions()
+{
+ return rtl::OUString("ASCII,BIN,BIT_LENGTH,CHAR,CHARACTER_LENGTH,CHAR_LENGTH,CONCAT,"
+ "CONCAT_WS,CONV,ELT,EXPORT_SET,FIELD,FIND_IN_SET,HEX,INSERT,"
+ "INSTR,LCASE,LEFT,LENGTH,LOAD_FILE,LOCATE,LOCATE,LOWER,LPAD,"
+ "LTRIM,MAKE_SET,MATCH,MID,OCT,OCTET_LENGTH,ORD,POSITION,"
+ "QUOTE,REPEAT,REPLACE,REVERSE,RIGHT,RPAD,RTRIM,SOUNDEX,"
+ "SPACE,STRCMP,SUBSTRING,SUBSTRING,SUBSTRING,SUBSTRING,"
+ "SUBSTRING_INDEX,TRIM,UCASE,UPPER");
+}
+
+rtl::OUString SAL_CALL ODatabaseMetaData::getTimeDateFunctions()
+{
+ return rtl::OUString("DAYOFWEEK,WEEKDAY,DAYOFMONTH,DAYOFYEAR,MONTH,DAYNAME,"
+ "MONTHNAME,QUARTER,WEEK,YEAR,HOUR,MINUTE,SECOND,PERIOD_ADD,"
+ "PERIOD_DIFF,TO_DAYS,FROM_DAYS,DATE_FORMAT,TIME_FORMAT,"
+ "CURDATE,CURRENT_DATE,CURTIME,CURRENT_TIME,NOW,SYSDATE,"
+ "CURRENT_TIMESTAMP,UNIX_TIMESTAMP,FROM_UNIXTIME,"
+ "SEC_TO_TIME,TIME_TO_SEC");
+}
+
+rtl::OUString SAL_CALL ODatabaseMetaData::getSystemFunctions()
+{
+ return rtl::OUString("DATABASE,USER,SYSTEM_USER,"
+ "SESSION_USER,PASSWORD,ENCRYPT,LAST_INSERT_ID,VERSION");
+}
+
+rtl::OUString SAL_CALL ODatabaseMetaData::getNumericFunctions()
+{
+ return rtl::OUString("ABS,ACOS,ASIN,ATAN,ATAN2,BIT_COUNT,CEILING,COS,"
+ "COT,DEGREES,EXP,FLOOR,LOG,LOG10,MAX,MIN,MOD,PI,POW,"
+ "POWER,RADIANS,RAND,ROUND,SIN,SQRT,TAN,TRUNCATE");
+}
+
+sal_Bool SAL_CALL ODatabaseMetaData::supportsExtendedSQLGrammar() { return false; }
+
+sal_Bool SAL_CALL ODatabaseMetaData::supportsCoreSQLGrammar() { return true; }
+
+sal_Bool SAL_CALL ODatabaseMetaData::supportsMinimumSQLGrammar() { return true; }
+
+sal_Bool SAL_CALL ODatabaseMetaData::supportsFullOuterJoins() { return false; }
+
+sal_Bool SAL_CALL ODatabaseMetaData::supportsLimitedOuterJoins() { return true; }
+
+sal_Int32 SAL_CALL ODatabaseMetaData::getMaxColumnsInGroupBy() { return 64; }
+
+sal_Int32 SAL_CALL ODatabaseMetaData::getMaxColumnsInOrderBy() { return 64; }
+
+sal_Int32 SAL_CALL ODatabaseMetaData::getMaxColumnsInSelect() { return 256; }
+
+sal_Int32 SAL_CALL ODatabaseMetaData::getMaxUserNameLength() { return 16; }
+
+sal_Bool SAL_CALL ODatabaseMetaData::supportsResultSetType(sal_Int32 setType)
+{
+ return setType == ResultSetType::SCROLL_SENSITIVE;
+}
+
+sal_Bool SAL_CALL ODatabaseMetaData::supportsResultSetConcurrency(sal_Int32 /*setType*/,
+ sal_Int32 /*concurrency*/)
+{
+ return false;
+}
+
+sal_Bool SAL_CALL ODatabaseMetaData::ownUpdatesAreVisible(sal_Int32 /*setType*/) { return false; }
+
+sal_Bool SAL_CALL ODatabaseMetaData::ownDeletesAreVisible(sal_Int32 /*setType*/) { return false; }
+
+sal_Bool SAL_CALL ODatabaseMetaData::ownInsertsAreVisible(sal_Int32 /*setType*/) { return false; }
+
+sal_Bool SAL_CALL ODatabaseMetaData::othersUpdatesAreVisible(sal_Int32 /*setType*/)
+{
+ return false;
+}
+
+sal_Bool SAL_CALL ODatabaseMetaData::othersDeletesAreVisible(sal_Int32 /*setType*/)
+{
+ return false;
+}
+
+sal_Bool SAL_CALL ODatabaseMetaData::othersInsertsAreVisible(sal_Int32 /*setType*/)
+{
+ return false;
+}
+
+sal_Bool SAL_CALL ODatabaseMetaData::updatesAreDetected(sal_Int32 /*setType*/) { return false; }
+
+sal_Bool SAL_CALL ODatabaseMetaData::deletesAreDetected(sal_Int32 /*setType*/) { return false; }
+
+sal_Bool SAL_CALL ODatabaseMetaData::insertsAreDetected(sal_Int32 /*setType*/) { return false; }
+
+sal_Bool SAL_CALL ODatabaseMetaData::supportsBatchUpdates() { return true; }
+
+Reference<XConnection> SAL_CALL ODatabaseMetaData::getConnection() { return &m_rConnection; }
+
+/*
+ Here follow all methods which return(a resultset
+ the first methods is an example implementation how to use this resultset
+ of course you could implement it on your and you should do this because
+ the general way is more memory expensive
+*/
+
+Reference<XResultSet> SAL_CALL ODatabaseMetaData::getTableTypes()
+{
+ const char* const table_types[] = { "TABLE", "VIEW" };
+ sal_Int32 const requiredVersion[] = { 0, 50000 };
+
+ Reference<XResultSet> xResultSet(getOwnConnection().getDriver().getFactory()->createInstance(
+ "org.openoffice.comp.helper.DatabaseMetaDataResultSet"),
+ UNO_QUERY);
+ std::vector<std::vector<Any>> rRows;
+ rtl_TextEncoding encoding = m_rConnection.getConnectionEncoding();
+
+ for (sal_uInt32 i = 0; i < 2; i++)
+ {
+ if (m_rConnection.getMysqlVersion() >= requiredVersion[i])
+ {
+ std::vector<Any> aRow{ Any() };
+ aRow.push_back(makeAny(mysqlc_sdbc_driver::convert(table_types[i], encoding)));
+ rRows.push_back(aRow);
+ }
+ }
+ lcl_setRows_throw(xResultSet, 5, rRows);
+ return xResultSet;
+}
+
+Reference<XResultSet> SAL_CALL ODatabaseMetaData::getTypeInfo()
+{
+ Reference<XResultSet> xResultSet(getOwnConnection().getDriver().getFactory()->createInstance(
+ "org.openoffice.comp.helper.DatabaseMetaDataResultSet"),
+ UNO_QUERY);
+
+ std::vector<std::vector<Any>> rRows;
+
+ rtl_TextEncoding encoding = m_rConnection.getConnectionEncoding();
+ unsigned int i = 0;
+ while (mysqlc_types[i].typeName)
+ {
+ std::vector<Any> aRow{ Any() };
+
+ aRow.push_back(makeAny(mysqlc_sdbc_driver::convert(mysqlc_types[i].typeName, encoding)));
+ aRow.push_back(makeAny(mysqlc_types[i].dataType));
+ aRow.push_back(makeAny(mysqlc_types[i].precision));
+ aRow.push_back(
+ makeAny(mysqlc_sdbc_driver::convert(mysqlc_types[i].literalPrefix, encoding)));
+ aRow.push_back(
+ makeAny(mysqlc_sdbc_driver::convert(mysqlc_types[i].literalSuffix, encoding)));
+ aRow.push_back(
+ makeAny(mysqlc_sdbc_driver::convert(mysqlc_types[i].createParams, encoding)));
+ aRow.push_back(makeAny(mysqlc_types[i].nullable));
+ aRow.push_back(makeAny(mysqlc_types[i].caseSensitive));
+ aRow.push_back(makeAny(mysqlc_types[i].searchable));
+ aRow.push_back(makeAny(mysqlc_types[i].isUnsigned));
+ aRow.push_back(makeAny(mysqlc_types[i].fixedPrecScale));
+ aRow.push_back(makeAny(mysqlc_types[i].autoIncrement));
+ aRow.push_back(
+ makeAny(mysqlc_sdbc_driver::convert(mysqlc_types[i].localTypeName, encoding)));
+ aRow.push_back(makeAny(mysqlc_types[i].minScale));
+ aRow.push_back(makeAny(mysqlc_types[i].maxScale));
+ aRow.push_back(makeAny(sal_Int32(0)));
+ aRow.push_back(makeAny(sal_Int32(0)));
+ aRow.push_back(makeAny(sal_Int32(10)));
+
+ rRows.push_back(aRow);
+ i++;
+ }
+
+ lcl_setRows_throw(xResultSet, 14, rRows);
+ return xResultSet;
+}
+
+Reference<XResultSet> SAL_CALL ODatabaseMetaData::getCatalogs()
+{
+ Reference<XResultSet> xResultSet(getOwnConnection().getDriver().getFactory()->createInstance(
+ "org.openoffice.comp.helper.DatabaseMetaDataResultSet"),
+ UNO_QUERY);
+ return xResultSet;
+}
+
+Reference<XResultSet> SAL_CALL ODatabaseMetaData::getSchemas()
+{
+ Reference<XResultSet> xResultSet(getOwnConnection().getDriver().getFactory()->createInstance(
+ "org.openoffice.comp.helper.DatabaseMetaDataResultSet"),
+ UNO_QUERY);
+ std::vector<std::vector<Any>> rRows;
+
+ rtl::OUString sSql
+ = m_rConnection.getMysqlVersion() > 49999
+ ? rtl::OUString{ "SELECT SCHEMA_NAME AS TABLE_SCHEM, CATALOG_NAME AS TABLE_CATALOG "
+ "FROM INFORMATION_SCHEMA.SCHEMATA ORDER BY SCHEMA_NAME" }
+ : rtl::OUString{ "SHOW DATABASES" };
+
+ Reference<XStatement> statement = m_rConnection.createStatement();
+ Reference<XInterface> executed = statement->executeQuery(sSql);
+ Reference<XResultSet> rs(executed, UNO_QUERY_THROW);
+ Reference<XResultSetMetaDataSupplier> supp(executed, UNO_QUERY_THROW);
+ Reference<XResultSetMetaData> rs_meta = supp->getMetaData();
+
+ Reference<XRow> xRow(rs, UNO_QUERY_THROW);
+ sal_uInt32 columns = rs_meta->getColumnCount();
+ while (rs->next())
+ {
+ std::vector<Any> aRow{ Any() };
+ bool informationSchema = false;
+ for (sal_uInt32 i = 1; i <= columns; i++)
+ {
+ rtl::OUString columnStringValue = xRow->getString(i);
+ if (i == 1)
+ { // TABLE_SCHEM
+ informationSchema = !columnStringValue.equalsIgnoreAsciiCase("information_schema");
+ }
+ aRow.push_back(makeAny(columnStringValue));
+ }
+ if (!informationSchema)
+ {
+ rRows.push_back(aRow);
+ }
+ }
+
+ lcl_setRows_throw(xResultSet, 1, rRows);
+ return xResultSet;
+}
+
+Reference<XResultSet> SAL_CALL ODatabaseMetaData::getColumnPrivileges(
+ const Any& /*catalog*/, const rtl::OUString& schema, const rtl::OUString& table,
+ const rtl::OUString& columnNamePattern)
+{
+ rtl::OUString query("SELECT TABLE_CATALOG AS TABLE_CAT, TABLE_SCHEMA AS "
+ "TABLE_SCHEM, TABLE_NAME, COLUMN_NAME, NULL AS GRANTOR, "
+ "GRANTEE, PRIVILEGE_TYPE AS PRIVILEGE, IS_GRANTABLE FROM "
+ "INFORMATION_SCHEMA.COLUMN_PRIVILEGES WHERE TABLE_SCHEMA LIKE "
+ "'?' AND TABLE_NAME='?' AND COLUMN_NAME LIKE '?' ORDER BY "
+ "COLUMN_NAME, PRIVILEGE_TYPE");
+
+ query = query.replaceFirst("?", schema);
+ query = query.replaceFirst("?", table);
+ query = query.replaceFirst("?", columnNamePattern);
+
+ Reference<XStatement> statement = m_rConnection.createStatement();
+ Reference<XResultSet> rs = statement->executeQuery(query);
+ return rs;
+}
+
+Reference<XResultSet> SAL_CALL ODatabaseMetaData::getColumns(const Any& /*catalog*/,
+ const rtl::OUString& /*schemaPattern*/,
+ const rtl::OUString& tableNamePattern,
+ const rtl::OUString& columnNamePattern)
+{
+ rtl::OUStringBuffer queryBuf("SELECT TABLE_CATALOG AS TABLE_CAT, " // 1
+ "TABLE_SCHEMA AS TABLE_SCHEM, " // 2
+ "TABLE_NAME, " // 3
+ "COLUMN_NAME, " // 4
+ "DATA_TYPE, " // 5
+ // TYPE_NAME missing
+ "CHARACTER_MAXIMUM_LENGTH, " // 6
+ "NUMERIC_PRECISION, " // 7
+ // buffer length missing
+ "NUMERIC_SCALE AS DECIMAL_DIGITS, " // 8
+ // NUM_PREC_RADIX missing
+ // NULLABLE missing
+ "COLUMN_COMMENT AS REMARKS, " // 9
+ "COLUMN_DEFAULT AS COLUMN_DEF," // 10
+ "CHARACTER_OCTET_LENGTH, " // 11
+ "ORDINAL_POSITION, " // 12
+ "IS_NULLABLE, " // 13
+ "COLUMN_TYPE " // 14
+ "FROM INFORMATION_SCHEMA.COLUMNS "
+ "WHERE (1 = 1) ");
+
+ if (!tableNamePattern.isEmpty())
+ {
+ rtl::OUString sAppend;
+ if (tableNamePattern.match("%"))
+ sAppend = "AND TABLE_NAME LIKE '%' ";
+ else
+ sAppend = "AND TABLE_NAME = '%' ";
+ queryBuf.append(sAppend.replaceAll("%", tableNamePattern));
+ }
+ if (!columnNamePattern.isEmpty())
+ {
+ rtl::OUString sAppend;
+ if (columnNamePattern.match("%"))
+ sAppend = "AND COLUMN_NAME LIKE '%' ";
+ else
+ sAppend = "AND COLUMN_NAME = '%' ";
+ queryBuf.append(sAppend.replaceAll("%", columnNamePattern));
+ }
+
+ rtl::OUString query = queryBuf.makeStringAndClear();
+ Reference<XStatement> statement = m_rConnection.createStatement();
+ Reference<XResultSet> rs = statement->executeQuery(query.getStr());
+ Reference<XRow> xRow(rs, UNO_QUERY_THROW);
+
+ Reference<XResultSet> xResultSet(getOwnConnection().getDriver().getFactory()->createInstance(
+ "org.openoffice.comp.helper.DatabaseMetaDataResultSet"),
+ UNO_QUERY);
+ std::vector<std::vector<Any>> aRows;
+ while (rs->next())
+ {
+ std::vector<Any> aRow{ Any() }; // 0. element is unused
+
+ // catalog name
+ aRow.push_back(makeAny(xRow->getString(1)));
+ // schema name
+ aRow.push_back(makeAny(xRow->getString(2)));
+ // table name
+ aRow.push_back(makeAny(xRow->getString(3)));
+ // column name
+ aRow.push_back(makeAny(xRow->getString(4)));
+ // data type
+ rtl::OUString sDataType = xRow->getString(5);
+ aRow.push_back(makeAny(mysqlc_sdbc_driver::mysqlStrToOOOType(sDataType)));
+ // type name
+ aRow.push_back(makeAny(sDataType)); // TODO
+ // column size
+ sal_Int32 nColumnSize = 0;
+ rtl::OUString sColumnType = xRow->getString(14);
+ sal_Int32 nCharMaxLen = xRow->getShort(6);
+ bool bIsCharMax = !xRow->wasNull();
+ if (sDataType.equalsIgnoreAsciiCase("year"))
+ nColumnSize = sColumnType.copy(6, 1).toInt32(); // 'year(' length is 5
+ else if (sDataType.equalsIgnoreAsciiCase("date"))
+ nColumnSize = 10;
+ else if (sDataType.equalsIgnoreAsciiCase("date"))
+ nColumnSize = 8;
+ else if (sDataType.equalsIgnoreAsciiCase("datetime")
+ || sDataType.equalsIgnoreAsciiCase("timestamp"))
+ nColumnSize = 19;
+ else if (!bIsCharMax)
+ nColumnSize = xRow->getShort(7); // numeric precision
+ else
+ nColumnSize = nCharMaxLen;
+ aRow.push_back(makeAny(nColumnSize));
+ aRow.push_back(Any()); // buffer length - unused
+ // decimal digits (scale)
+ aRow.push_back(makeAny(xRow->getShort(8)));
+ // num_prec_radix
+ aRow.push_back(makeAny(sal_Int32(10)));
+ // nullable
+ rtl::OUString sIsNullable = xRow->getString(13);
+ if (xRow->wasNull())
+ aRow.push_back(makeAny(ColumnValue::NULLABLE_UNKNOWN));
+ else if (sIsNullable.equalsIgnoreAsciiCase("YES"))
+ aRow.push_back(makeAny(ColumnValue::NULLABLE));
+ else
+ aRow.push_back(makeAny(ColumnValue::NO_NULLS));
+ // remarks
+ aRow.push_back(makeAny(xRow->getString(9)));
+ // default
+ aRow.push_back(makeAny(xRow->getString(10)));
+
+ aRow.push_back(Any{}); // sql_data_type - unused
+ aRow.push_back(Any{}); // sql_datetime_sub - unused
+
+ // character octet length
+ aRow.push_back(makeAny(xRow->getString(11)));
+ // ordinal position
+ aRow.push_back(makeAny(xRow->getString(12)));
+ // is nullable
+ aRow.push_back(makeAny(sIsNullable));
+ aRows.push_back(aRow);
+ }
+ lcl_setRows_throw(xResultSet, 1, aRows);
+ return xResultSet;
+}
+
+Reference<XResultSet> SAL_CALL ODatabaseMetaData::getTables(
+ const Any& /*catalog*/, const rtl::OUString& schemaPattern,
+ const rtl::OUString& tableNamePattern, const Sequence<rtl::OUString>& /*types */)
+{
+ rtl::OUString query(
+ "SELECT TABLE_CATALOG AS TABLE_CAT, TABLE_SCHEMA AS TABLE_SCHEM, TABLE_NAME,"
+ "IF(STRCMP(TABLE_TYPE,'BASE TABLE'), TABLE_TYPE, 'TABLE') AS TABLE_TYPE, TABLE_COMMENT AS "
+ "REMARKS "
+ "FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA LIKE '?' AND TABLE_NAME LIKE '?' "
+ "ORDER BY TABLE_TYPE, TABLE_SCHEMA, TABLE_NAME");
+
+ // TODO use prepared stmt instead
+ // TODO escape schema, table name ?
+ query = query.replaceFirst("?", schemaPattern);
+ query = query.replaceFirst("?", tableNamePattern);
+
+ Reference<XStatement> statement = m_rConnection.createStatement();
+ Reference<XResultSet> rs = statement->executeQuery(query);
+ return rs;
+}
+
+Reference<XResultSet> SAL_CALL ODatabaseMetaData::getProcedureColumns(
+ const Any& /* catalog */, const rtl::OUString& /* schemaPattern */,
+ const rtl::OUString& /* procedureNamePattern */, const rtl::OUString& /* columnNamePattern */)
+{
+ // Currently there is no information available
+ return nullptr;
+}
+
+Reference<XResultSet>
+ SAL_CALL ODatabaseMetaData::getProcedures(const Any& /*catalog*/,
+ const rtl::OUString& /*schemaPattern*/,
+ const rtl::OUString& /*procedureNamePattern*/)
+{
+ Reference<XResultSet> xResultSet(getOwnConnection().getDriver().getFactory()->createInstance(
+ "org.openoffice.comp.helper.DatabaseMetaDataResultSet"),
+ UNO_QUERY);
+ std::vector<std::vector<Any>> rRows;
+ // TODO IMPL
+ lcl_setRows_throw(xResultSet, 7, rRows);
+ return xResultSet;
+}
+
+Reference<XResultSet> SAL_CALL ODatabaseMetaData::getVersionColumns(
+ const Any& /* catalog */, const rtl::OUString& /* schema */, const rtl::OUString& /* table */)
+{
+ Reference<XResultSet> xResultSet(getOwnConnection().getDriver().getFactory()->createInstance(
+ "org.openoffice.comp.helper.DatabaseMetaDataResultSet"),
+ UNO_QUERY);
+ std::vector<std::vector<Any>> rRows;
+ lcl_setRows_throw(xResultSet, 16, rRows);
+ return xResultSet;
+}
+
+Reference<XResultSet> SAL_CALL ODatabaseMetaData::getExportedKeys(const Any& /*catalog */,
+ const rtl::OUString& /*schema */,
+ const rtl::OUString& /*table */)
+{
+ Reference<XResultSet> xResultSet(getOwnConnection().getDriver().getFactory()->createInstance(
+ "org.openoffice.comp.helper.DatabaseMetaDataResultSet"),
+ UNO_QUERY);
+ std::vector<std::vector<Any>> rRows;
+ // TODO implement
+ lcl_setRows_throw(xResultSet, 8, rRows);
+ return xResultSet;
+}
+
+Reference<XResultSet> SAL_CALL ODatabaseMetaData::getImportedKeys(const Any& /*catalog*/,
+ const rtl::OUString& /*schema*/,
+ const rtl::OUString& /*table*/)
+{
+ Reference<XResultSet> xResultSet(getOwnConnection().getDriver().getFactory()->createInstance(
+ "org.openoffice.comp.helper.DatabaseMetaDataResultSet"),
+ UNO_QUERY);
+ std::vector<std::vector<Any>> rRows;
+ // TODO implement
+ lcl_setRows_throw(xResultSet, 9, rRows);
+ return xResultSet;
+}
+
+Reference<XResultSet> SAL_CALL ODatabaseMetaData::getPrimaryKeys(const Any& /*catalog*/,
+ const rtl::OUString& schema,
+ const rtl::OUString& table)
+{
+ rtl::OUString query(
+ "SELECT TABLE_CATALOG AS TABLE_CAT, TABLE_SCHEMA "
+ "AS TABLE_SCHEM, TABLE_NAME, "
+ "COLUMN_NAME, SEQ_IN_INDEX AS KEY_SEQ,"
+ "INDEX_NAME AS PK_NAME FROM INFORMATION_SCHEMA.STATISTICS "
+ "WHERE TABLE_SCHEMA LIKE '?' AND TABLE_NAME LIKE '?' AND INDEX_NAME='PRIMARY' "
+ "ORDER BY TABLE_SCHEMA, TABLE_NAME, INDEX_NAME, SEQ_IN_INDEX");
+
+ // TODO use prepared stmt instead
+ // TODO escape schema, table name ?
+ query = query.replaceFirst("?", schema);
+ query = query.replaceFirst("?", table);
+
+ Reference<XStatement> statement = m_rConnection.createStatement();
+ Reference<XResultSet> rs = statement->executeQuery(query);
+ return rs;
+}
+
+Reference<XResultSet> SAL_CALL ODatabaseMetaData::getIndexInfo(const Any& /*catalog*/,
+ const rtl::OUString& /*schema*/,
+ const rtl::OUString& /*table*/,
+ sal_Bool /*unique*/,
+ sal_Bool /*approximate*/)
+{
+ Reference<XResultSet> xResultSet(getOwnConnection().getDriver().getFactory()->createInstance(
+ "org.openoffice.comp.helper.DatabaseMetaDataResultSet"),
+ UNO_QUERY);
+ std::vector<std::vector<Any>> rRows;
+ // TODO
+ lcl_setRows_throw(xResultSet, 11, rRows);
+ return xResultSet;
+}
+
+Reference<XResultSet> SAL_CALL ODatabaseMetaData::getBestRowIdentifier(
+ const Any& /*catalog*/, const rtl::OUString& /*schema*/, const rtl::OUString& /*table*/,
+ sal_Int32 /*scope*/, sal_Bool /*nullable*/)
+{
+ Reference<XResultSet> xResultSet(getOwnConnection().getDriver().getFactory()->createInstance(
+ "org.openoffice.comp.helper.DatabaseMetaDataResultSet"),
+ UNO_QUERY);
+ std::vector<std::vector<Any>> rRows;
+ // TODO
+ lcl_setRows_throw(xResultSet, 15, rRows);
+ return xResultSet;
+}
+
+Reference<XResultSet>
+ SAL_CALL ODatabaseMetaData::getTablePrivileges(const Any& /*catalog*/,
+ const rtl::OUString& /*schemaPattern*/,
+ const rtl::OUString& /*tableNamePattern*/)
+{
+ Reference<XResultSet> xResultSet(getOwnConnection().getDriver().getFactory()->createInstance(
+ "org.openoffice.comp.helper.DatabaseMetaDataResultSet"),
+ UNO_QUERY);
+ std::vector<std::vector<Any>> rRows;
+ // TODO
+ lcl_setRows_throw(xResultSet, 12, rRows);
+ return xResultSet;
+}
+
+Reference<XResultSet> SAL_CALL ODatabaseMetaData::getCrossReference(
+ const Any& /*primaryCatalog*/, const rtl::OUString& /*primarySchema_*/,
+ const rtl::OUString& /*primaryTable_*/, const Any& /*foreignCatalog*/,
+ const rtl::OUString& /*foreignSchema*/, const rtl::OUString& /*foreignTable*/)
+{
+ Reference<XResultSet> xResultSet(getOwnConnection().getDriver().getFactory()->createInstance(
+ "org.openoffice.comp.helper.DatabaseMetaDataResultSet"),
+ UNO_QUERY);
+ std::vector<std::vector<Any>> rRows;
+ // TODO
+ lcl_setRows_throw(xResultSet, 13, rRows);
+ return xResultSet;
+}
+
+Reference<XResultSet> SAL_CALL ODatabaseMetaData::getUDTs(
+ const Any& /* catalog */, const rtl::OUString& /* schemaPattern */,
+ const rtl::OUString& /* typeNamePattern */, const Sequence<sal_Int32>& /* types */)
+{
+ mysqlc_sdbc_driver::throwFeatureNotImplementedException("ODatabaseMetaData::getUDTs", *this);
+ return nullptr;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/mysqlc/mysqlc_databasemetadata.hxx b/connectivity/source/drivers/mysqlc/mysqlc_databasemetadata.hxx
new file mode 100644
index 000000000000..2ed4eca4179b
--- /dev/null
+++ b/connectivity/source/drivers/mysqlc/mysqlc_databasemetadata.hxx
@@ -0,0 +1,245 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef INCLUDED_MYSQLC_SOURCE_MYSQLC_DATABASEMETADATA_HXX
+#define INCLUDED_MYSQLC_SOURCE_MYSQLC_DATABASEMETADATA_HXX
+
+#include "mysqlc_connection.hxx"
+
+#include <com/sun/star/sdbc/XDatabaseMetaData.hpp>
+#include <cppuhelper/implbase1.hxx>
+
+namespace connectivity
+{
+namespace mysqlc
+{
+using ::com::sun::star::uno::Any;
+
+//************ Class: ODatabaseMetaData
+
+typedef ::cppu::WeakImplHelper1<css::sdbc::XDatabaseMetaData> ODatabaseMetaData_BASE;
+
+class ODatabaseMetaData final : public ODatabaseMetaData_BASE
+{
+ OConnection& m_rConnection;
+ MYSQL* m_pMySql;
+ rtl::OUString identifier_quote_string;
+
+public:
+ const OConnection& getOwnConnection() const { return m_rConnection; }
+
+ explicit ODatabaseMetaData(OConnection& _rCon, MYSQL* pMySql);
+ virtual ~ODatabaseMetaData() override;
+
+ // as I mentioned before this interface is really BIG
+ // XDatabaseMetaData
+ sal_Bool SAL_CALL allProceduresAreCallable() SAL_OVERRIDE;
+ sal_Bool SAL_CALL allTablesAreSelectable() SAL_OVERRIDE;
+ rtl::OUString SAL_CALL getURL() SAL_OVERRIDE;
+ rtl::OUString SAL_CALL getUserName() SAL_OVERRIDE;
+ sal_Bool SAL_CALL isReadOnly() SAL_OVERRIDE;
+ sal_Bool SAL_CALL nullsAreSortedHigh() SAL_OVERRIDE;
+ sal_Bool SAL_CALL nullsAreSortedLow() SAL_OVERRIDE;
+ sal_Bool SAL_CALL nullsAreSortedAtStart() SAL_OVERRIDE;
+ sal_Bool SAL_CALL nullsAreSortedAtEnd() SAL_OVERRIDE;
+ rtl::OUString SAL_CALL getDatabaseProductName() SAL_OVERRIDE;
+ rtl::OUString SAL_CALL getDatabaseProductVersion() SAL_OVERRIDE;
+ rtl::OUString SAL_CALL getDriverName() SAL_OVERRIDE;
+ rtl::OUString SAL_CALL getDriverVersion() SAL_OVERRIDE;
+ sal_Int32 SAL_CALL getDriverMajorVersion() SAL_OVERRIDE;
+ sal_Int32 SAL_CALL getDriverMinorVersion() SAL_OVERRIDE;
+ sal_Bool SAL_CALL usesLocalFiles() SAL_OVERRIDE;
+ sal_Bool SAL_CALL usesLocalFilePerTable() SAL_OVERRIDE;
+ sal_Bool SAL_CALL supportsMixedCaseIdentifiers() SAL_OVERRIDE;
+ sal_Bool SAL_CALL storesUpperCaseIdentifiers() SAL_OVERRIDE;
+ sal_Bool SAL_CALL storesLowerCaseIdentifiers() SAL_OVERRIDE;
+ sal_Bool SAL_CALL storesMixedCaseIdentifiers() SAL_OVERRIDE;
+ sal_Bool SAL_CALL supportsMixedCaseQuotedIdentifiers() SAL_OVERRIDE;
+ sal_Bool SAL_CALL storesUpperCaseQuotedIdentifiers() SAL_OVERRIDE;
+ sal_Bool SAL_CALL storesLowerCaseQuotedIdentifiers() SAL_OVERRIDE;
+ sal_Bool SAL_CALL storesMixedCaseQuotedIdentifiers() SAL_OVERRIDE;
+ rtl::OUString SAL_CALL getIdentifierQuoteString() SAL_OVERRIDE;
+ rtl::OUString SAL_CALL getSQLKeywords() SAL_OVERRIDE;
+ rtl::OUString SAL_CALL getNumericFunctions() SAL_OVERRIDE;
+ rtl::OUString SAL_CALL getStringFunctions() SAL_OVERRIDE;
+ rtl::OUString SAL_CALL getSystemFunctions() SAL_OVERRIDE;
+ rtl::OUString SAL_CALL getTimeDateFunctions() SAL_OVERRIDE;
+ rtl::OUString SAL_CALL getSearchStringEscape() SAL_OVERRIDE;
+ rtl::OUString SAL_CALL getExtraNameCharacters() SAL_OVERRIDE;
+ sal_Bool SAL_CALL supportsAlterTableWithAddColumn() SAL_OVERRIDE;
+ sal_Bool SAL_CALL supportsAlterTableWithDropColumn() SAL_OVERRIDE;
+ sal_Bool SAL_CALL supportsColumnAliasing() SAL_OVERRIDE;
+ sal_Bool SAL_CALL nullPlusNonNullIsNull() SAL_OVERRIDE;
+ sal_Bool SAL_CALL supportsTypeConversion() SAL_OVERRIDE;
+ sal_Bool SAL_CALL supportsConvert(sal_Int32 fromType, sal_Int32 toType) SAL_OVERRIDE;
+ sal_Bool SAL_CALL supportsTableCorrelationNames() SAL_OVERRIDE;
+ sal_Bool SAL_CALL supportsDifferentTableCorrelationNames() SAL_OVERRIDE;
+ sal_Bool SAL_CALL supportsExpressionsInOrderBy() SAL_OVERRIDE;
+ sal_Bool SAL_CALL supportsOrderByUnrelated() SAL_OVERRIDE;
+ sal_Bool SAL_CALL supportsGroupBy() SAL_OVERRIDE;
+ sal_Bool SAL_CALL supportsGroupByUnrelated() SAL_OVERRIDE;
+ sal_Bool SAL_CALL supportsGroupByBeyondSelect() SAL_OVERRIDE;
+ sal_Bool SAL_CALL supportsLikeEscapeClause() SAL_OVERRIDE;
+ sal_Bool SAL_CALL supportsMultipleResultSets() SAL_OVERRIDE;
+ sal_Bool SAL_CALL supportsMultipleTransactions() SAL_OVERRIDE;
+ sal_Bool SAL_CALL supportsNonNullableColumns() SAL_OVERRIDE;
+ sal_Bool SAL_CALL supportsMinimumSQLGrammar() SAL_OVERRIDE;
+ sal_Bool SAL_CALL supportsCoreSQLGrammar() SAL_OVERRIDE;
+ sal_Bool SAL_CALL supportsExtendedSQLGrammar() SAL_OVERRIDE;
+ sal_Bool SAL_CALL supportsANSI92EntryLevelSQL() SAL_OVERRIDE;
+ sal_Bool SAL_CALL supportsANSI92IntermediateSQL() SAL_OVERRIDE;
+ sal_Bool SAL_CALL supportsANSI92FullSQL() SAL_OVERRIDE;
+ sal_Bool SAL_CALL supportsIntegrityEnhancementFacility() SAL_OVERRIDE;
+ sal_Bool SAL_CALL supportsOuterJoins() SAL_OVERRIDE;
+ sal_Bool SAL_CALL supportsFullOuterJoins() SAL_OVERRIDE;
+ sal_Bool SAL_CALL supportsLimitedOuterJoins() SAL_OVERRIDE;
+ rtl::OUString SAL_CALL getSchemaTerm() SAL_OVERRIDE;
+ rtl::OUString SAL_CALL getProcedureTerm() SAL_OVERRIDE;
+ rtl::OUString SAL_CALL getCatalogTerm() SAL_OVERRIDE;
+ sal_Bool SAL_CALL isCatalogAtStart() SAL_OVERRIDE;
+ rtl::OUString SAL_CALL getCatalogSeparator() SAL_OVERRIDE;
+ sal_Bool SAL_CALL supportsSchemasInDataManipulation() SAL_OVERRIDE;
+ sal_Bool SAL_CALL supportsSchemasInProcedureCalls() SAL_OVERRIDE;
+ sal_Bool SAL_CALL supportsSchemasInTableDefinitions() SAL_OVERRIDE;
+ sal_Bool SAL_CALL supportsSchemasInIndexDefinitions() SAL_OVERRIDE;
+ sal_Bool SAL_CALL supportsSchemasInPrivilegeDefinitions() SAL_OVERRIDE;
+ sal_Bool SAL_CALL supportsCatalogsInDataManipulation() SAL_OVERRIDE;
+ sal_Bool SAL_CALL supportsCatalogsInProcedureCalls() SAL_OVERRIDE;
+ sal_Bool SAL_CALL supportsCatalogsInTableDefinitions() SAL_OVERRIDE;
+ sal_Bool SAL_CALL supportsCatalogsInIndexDefinitions() SAL_OVERRIDE;
+ sal_Bool SAL_CALL supportsCatalogsInPrivilegeDefinitions() SAL_OVERRIDE;
+ sal_Bool SAL_CALL supportsPositionedDelete() SAL_OVERRIDE;
+ sal_Bool SAL_CALL supportsPositionedUpdate() SAL_OVERRIDE;
+ sal_Bool SAL_CALL supportsSelectForUpdate() SAL_OVERRIDE;
+ sal_Bool SAL_CALL supportsStoredProcedures() SAL_OVERRIDE;
+ sal_Bool SAL_CALL supportsSubqueriesInComparisons() SAL_OVERRIDE;
+ sal_Bool SAL_CALL supportsSubqueriesInExists() SAL_OVERRIDE;
+ sal_Bool SAL_CALL supportsSubqueriesInIns() SAL_OVERRIDE;
+ sal_Bool SAL_CALL supportsSubqueriesInQuantifieds() SAL_OVERRIDE;
+ sal_Bool SAL_CALL supportsCorrelatedSubqueries() SAL_OVERRIDE;
+ sal_Bool SAL_CALL supportsUnion() SAL_OVERRIDE;
+ sal_Bool SAL_CALL supportsUnionAll() SAL_OVERRIDE;
+ sal_Bool SAL_CALL supportsOpenCursorsAcrossCommit() SAL_OVERRIDE;
+ sal_Bool SAL_CALL supportsOpenCursorsAcrossRollback() SAL_OVERRIDE;
+ sal_Bool SAL_CALL supportsOpenStatementsAcrossCommit() SAL_OVERRIDE;
+ sal_Bool SAL_CALL supportsOpenStatementsAcrossRollback() SAL_OVERRIDE;
+ sal_Int32 SAL_CALL getMaxBinaryLiteralLength() SAL_OVERRIDE;
+ sal_Int32 SAL_CALL getMaxCharLiteralLength() SAL_OVERRIDE;
+ sal_Int32 SAL_CALL getMaxColumnNameLength() SAL_OVERRIDE;
+ sal_Int32 SAL_CALL getMaxColumnsInGroupBy() SAL_OVERRIDE;
+ sal_Int32 SAL_CALL getMaxColumnsInIndex() SAL_OVERRIDE;
+ sal_Int32 SAL_CALL getMaxColumnsInOrderBy() SAL_OVERRIDE;
+ sal_Int32 SAL_CALL getMaxColumnsInSelect() SAL_OVERRIDE;
+ sal_Int32 SAL_CALL getMaxColumnsInTable() SAL_OVERRIDE;
+ sal_Int32 SAL_CALL getMaxConnections() SAL_OVERRIDE;
+ sal_Int32 SAL_CALL getMaxCursorNameLength() SAL_OVERRIDE;
+ sal_Int32 SAL_CALL getMaxIndexLength() SAL_OVERRIDE;
+ sal_Int32 SAL_CALL getMaxSchemaNameLength() SAL_OVERRIDE;
+ sal_Int32 SAL_CALL getMaxProcedureNameLength() SAL_OVERRIDE;
+ sal_Int32 SAL_CALL getMaxCatalogNameLength() SAL_OVERRIDE;
+ sal_Int32 SAL_CALL getMaxRowSize() SAL_OVERRIDE;
+ sal_Bool SAL_CALL doesMaxRowSizeIncludeBlobs() SAL_OVERRIDE;
+ sal_Int32 SAL_CALL getMaxStatementLength() SAL_OVERRIDE;
+ sal_Int32 SAL_CALL getMaxStatements() SAL_OVERRIDE;
+ sal_Int32 SAL_CALL getMaxTableNameLength() SAL_OVERRIDE;
+ sal_Int32 SAL_CALL getMaxTablesInSelect() SAL_OVERRIDE;
+ sal_Int32 SAL_CALL getMaxUserNameLength() SAL_OVERRIDE;
+ sal_Int32 SAL_CALL getDefaultTransactionIsolation() SAL_OVERRIDE;
+ sal_Bool SAL_CALL supportsTransactions() SAL_OVERRIDE;
+ sal_Bool SAL_CALL supportsTransactionIsolationLevel(sal_Int32 level) SAL_OVERRIDE;
+ sal_Bool SAL_CALL supportsDataDefinitionAndDataManipulationTransactions() SAL_OVERRIDE;
+ sal_Bool SAL_CALL supportsDataManipulationTransactionsOnly() SAL_OVERRIDE;
+ sal_Bool SAL_CALL dataDefinitionCausesTransactionCommit() SAL_OVERRIDE;
+ sal_Bool SAL_CALL dataDefinitionIgnoredInTransactions() SAL_OVERRIDE;
+ css::uno::Reference<css::sdbc::XResultSet>
+ SAL_CALL getProcedures(const Any& catalog, const rtl::OUString& schemaPattern,
+ const rtl::OUString& procedureNamePattern) SAL_OVERRIDE;
+ css::uno::Reference<css::sdbc::XResultSet>
+ SAL_CALL getProcedureColumns(const Any& catalog, const rtl::OUString& schemaPattern,
+ const rtl::OUString& procedureNamePattern,
+ const rtl::OUString& columnNamePattern) SAL_OVERRIDE;
+ css::uno::Reference<css::sdbc::XResultSet>
+ SAL_CALL getTables(const Any& catalog, const rtl::OUString& schemaPattern,
+ const rtl::OUString& tableNamePattern,
+ const css::uno::Sequence<rtl::OUString>& types) SAL_OVERRIDE;
+ css::uno::Reference<css::sdbc::XResultSet> SAL_CALL getSchemas() SAL_OVERRIDE;
+ css::uno::Reference<css::sdbc::XResultSet> SAL_CALL getCatalogs() SAL_OVERRIDE;
+ css::uno::Reference<css::sdbc::XResultSet> SAL_CALL getTableTypes() SAL_OVERRIDE;
+ css::uno::Reference<css::sdbc::XResultSet>
+ SAL_CALL getColumns(const Any& catalog, const rtl::OUString& schemaPattern,
+ const rtl::OUString& tableNamePattern,
+ const rtl::OUString& columnNamePattern) SAL_OVERRIDE;
+ css::uno::Reference<css::sdbc::XResultSet>
+ SAL_CALL getColumnPrivileges(const Any& catalog, const rtl::OUString& schema,
+ const rtl::OUString& table,
+ const rtl::OUString& columnNamePattern) SAL_OVERRIDE;
+ css::uno::Reference<css::sdbc::XResultSet>
+ SAL_CALL getTablePrivileges(const Any& catalog, const rtl::OUString& schemaPattern,
+ const rtl::OUString& tableNamePattern) SAL_OVERRIDE;
+ css::uno::Reference<css::sdbc::XResultSet>
+ SAL_CALL getBestRowIdentifier(const Any& catalog, const rtl::OUString& schema,
+ const rtl::OUString& table, sal_Int32 scope,
+ sal_Bool nullable) SAL_OVERRIDE;
+ css::uno::Reference<css::sdbc::XResultSet>
+ SAL_CALL getVersionColumns(const Any& catalog, const rtl::OUString& schema,
+ const rtl::OUString& table) SAL_OVERRIDE;
+ css::uno::Reference<css::sdbc::XResultSet>
+ SAL_CALL getPrimaryKeys(const Any& catalog, const rtl::OUString& schema,
+ const rtl::OUString& table) SAL_OVERRIDE;
+ css::uno::Reference<css::sdbc::XResultSet>
+ SAL_CALL getImportedKeys(const Any& catalog, const rtl::OUString& schema,
+ const rtl::OUString& table) SAL_OVERRIDE;
+ css::uno::Reference<css::sdbc::XResultSet>
+ SAL_CALL getExportedKeys(const Any& catalog, const rtl::OUString& schema,
+ const rtl::OUString& table) SAL_OVERRIDE;
+ css::uno::Reference<css::sdbc::XResultSet>
+ SAL_CALL getCrossReference(const Any& primaryCatalog, const rtl::OUString& primarySchema,
+ const rtl::OUString& primaryTable, const Any& foreignCatalog,
+ const rtl::OUString& foreignSchema,
+ const rtl::OUString& foreignTable) SAL_OVERRIDE;
+ css::uno::Reference<css::sdbc::XResultSet> SAL_CALL getTypeInfo() SAL_OVERRIDE;
+ css::uno::Reference<css::sdbc::XResultSet>
+ SAL_CALL getIndexInfo(const Any& catalog, const rtl::OUString& schema,
+ const rtl::OUString& table, sal_Bool unique,
+ sal_Bool approximate) SAL_OVERRIDE;
+ sal_Bool SAL_CALL supportsResultSetType(sal_Int32 setType) SAL_OVERRIDE;
+ sal_Bool SAL_CALL supportsResultSetConcurrency(sal_Int32 setType,
+ sal_Int32 concurrency) SAL_OVERRIDE;
+ sal_Bool SAL_CALL ownUpdatesAreVisible(sal_Int32 setType) SAL_OVERRIDE;
+ sal_Bool SAL_CALL ownDeletesAreVisible(sal_Int32 setType) SAL_OVERRIDE;
+ sal_Bool SAL_CALL ownInsertsAreVisible(sal_Int32 setType) SAL_OVERRIDE;
+ sal_Bool SAL_CALL othersUpdatesAreVisible(sal_Int32 setType) SAL_OVERRIDE;
+ sal_Bool SAL_CALL othersDeletesAreVisible(sal_Int32 setType) SAL_OVERRIDE;
+ sal_Bool SAL_CALL othersInsertsAreVisible(sal_Int32 setType) SAL_OVERRIDE;
+ sal_Bool SAL_CALL updatesAreDetected(sal_Int32 setType) SAL_OVERRIDE;
+ sal_Bool SAL_CALL deletesAreDetected(sal_Int32 setType) SAL_OVERRIDE;
+ sal_Bool SAL_CALL insertsAreDetected(sal_Int32 setType) SAL_OVERRIDE;
+ sal_Bool SAL_CALL supportsBatchUpdates() SAL_OVERRIDE;
+ css::uno::Reference<css::sdbc::XResultSet>
+ SAL_CALL getUDTs(const Any& catalog, const rtl::OUString& schemaPattern,
+ const rtl::OUString& typeNamePattern,
+ const css::uno::Sequence<sal_Int32>& types) SAL_OVERRIDE;
+ css::uno::Reference<css::sdbc::XConnection> SAL_CALL getConnection() SAL_OVERRIDE;
+};
+}
+}
+
+#endif // INCLUDED_MYSQLC_SOURCE_MYSQLC_DATABASEMETADATA_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/mysqlc/mysqlc_driver.cxx b/connectivity/source/drivers/mysqlc/mysqlc_driver.cxx
new file mode 100644
index 000000000000..2651ec5f9a79
--- /dev/null
+++ b/connectivity/source/drivers/mysqlc/mysqlc_driver.cxx
@@ -0,0 +1,169 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
+/*
+ * 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 "mysqlc_driver.hxx"
+#include "mysqlc_connection.hxx"
+#include "mysqlc_general.hxx"
+
+using namespace css::uno;
+using namespace css::lang;
+using namespace css::beans;
+using namespace css::sdbc;
+using namespace connectivity::mysqlc;
+
+#include <cppuhelper/supportsservice.hxx>
+#include <stdio.h>
+
+MysqlCDriver::MysqlCDriver(const Reference<XMultiServiceFactory>& _rxFactory)
+ : ODriver_BASE(m_aMutex)
+ , m_xFactory(_rxFactory)
+{
+}
+
+void MysqlCDriver::disposing()
+{
+ ::osl::MutexGuard aGuard(m_aMutex);
+
+ // when driver will be destroyed so all our connections have to be destroyed as well
+ for (auto const& connection : m_xConnections)
+ {
+ Reference<XComponent> xComp(connection.get(), UNO_QUERY);
+ if (xComp.is())
+ {
+ xComp->dispose();
+ }
+ }
+ m_xConnections.clear();
+
+ ODriver_BASE::disposing();
+}
+
+// static ServiceInfo
+OUString MysqlCDriver::getImplementationName_Static()
+{
+ return OUString("com.sun.star.comp.sdbc.mysqlc.MysqlCDriver");
+}
+
+Sequence<OUString> MysqlCDriver::getSupportedServiceNames_Static()
+{
+ Sequence<OUString> aSNS(1);
+ aSNS[0] = "com.sun.star.sdbc.Driver";
+ return aSNS;
+}
+
+OUString SAL_CALL MysqlCDriver::getImplementationName() { return getImplementationName_Static(); }
+
+sal_Bool SAL_CALL MysqlCDriver::supportsService(const OUString& _rServiceName)
+{
+ return cppu::supportsService(this, _rServiceName);
+}
+
+Sequence<OUString> SAL_CALL MysqlCDriver::getSupportedServiceNames()
+{
+ return getSupportedServiceNames_Static();
+}
+
+void MysqlCDriver::impl_initCppConn_lck_throw()
+{
+#ifdef BUNDLE_MARIADB
+ if (!m_bAttemptedLoadCConn)
+ {
+ const OUString sModuleName(BUNDLE_MARIADB);
+ m_hCConnModule = osl_loadModuleRelative(&thisModule, sModuleName.pData, 0);
+ m_bAttemptedLoadCConn = true;
+ }
+
+ // attempted to load - was it successful?
+ if (!m_hCConnModule)
+ {
+ OSL_FAIL("MysqlCDriver::impl_initCppConn_lck_throw: could not load the " BUNDLE_MARIADB
+ " library!");
+ throw SQLException("Unable to load the " BUNDLE_MARIADB " library.", *this,
+ OUString("08001"), // "unable to connect"
+ 0, Any());
+ }
+#endif
+}
+
+Reference<XConnection> SAL_CALL MysqlCDriver::connect(const OUString& url,
+ const Sequence<PropertyValue>& info)
+{
+ ::osl::MutexGuard aGuard(m_aMutex);
+
+ if (!acceptsURL(url))
+ {
+ return nullptr;
+ }
+
+ Reference<XConnection> xConn;
+ // create a new connection with the given properties and append it to our vector
+ OConnection* pCon = new OConnection(*this);
+ xConn = pCon;
+
+ pCon->construct(url, info);
+ m_xConnections.push_back(WeakReferenceHelper(*pCon));
+ return xConn;
+}
+
+sal_Bool SAL_CALL MysqlCDriver::acceptsURL(const OUString& url)
+{
+ return url.startsWith("sdbc:mysqlc:") || url.startsWith("sdbc:mysql:mysqlc:");
+}
+
+Sequence<DriverPropertyInfo> SAL_CALL
+MysqlCDriver::getPropertyInfo(const OUString& url, const Sequence<PropertyValue>& /* info */)
+{
+ if (acceptsURL(url))
+ {
+ ::std::vector<DriverPropertyInfo> aDriverInfo;
+
+ aDriverInfo.push_back(DriverPropertyInfo("Hostname", "Name of host", true, "localhost",
+ Sequence<OUString>()));
+ aDriverInfo.push_back(
+ DriverPropertyInfo("Port", "Port", true, "3306", Sequence<OUString>()));
+ return Sequence<DriverPropertyInfo>(&(aDriverInfo[0]), aDriverInfo.size());
+ }
+
+ return Sequence<DriverPropertyInfo>();
+}
+
+sal_Int32 SAL_CALL MysqlCDriver::getMajorVersion() { return MARIADBC_VERSION_MAJOR; }
+
+sal_Int32 SAL_CALL MysqlCDriver::getMinorVersion() { return MARIADBC_VERSION_MINOR; }
+
+namespace connectivity
+{
+namespace mysqlc
+{
+Reference<XInterface> MysqlCDriver_CreateInstance(const Reference<XMultiServiceFactory>& _rxFactory)
+{
+ return (*(new MysqlCDriver(_rxFactory)));
+}
+
+void checkDisposed(bool _bThrow)
+{
+ if (_bThrow)
+ {
+ throw DisposedException();
+ }
+}
+
+} /* mysqlc */
+} /* connectivity */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/connectivity/source/drivers/mysqlc/mysqlc_driver.hxx b/connectivity/source/drivers/mysqlc/mysqlc_driver.hxx
new file mode 100644
index 000000000000..89c57630823e
--- /dev/null
+++ b/connectivity/source/drivers/mysqlc/mysqlc_driver.hxx
@@ -0,0 +1,101 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef INCLUDED_MYSQLC_SOURCE_MYSQLC_DRIVER_HXX
+#define INCLUDED_MYSQLC_SOURCE_MYSQLC_DRIVER_HXX
+
+#include "mysqlc_connection.hxx"
+
+#include <com/sun/star/sdbc/XDriver.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+
+#include <cppuhelper/compbase2.hxx>
+#include <osl/module.h>
+
+namespace connectivity
+{
+namespace mysqlc
+{
+using css::sdbc::SQLException;
+using css::uno::Exception;
+using css::uno::Reference;
+using css::uno::RuntimeException;
+using css::uno::Sequence;
+using rtl::OUString;
+
+Reference<css::uno::XInterface>
+MysqlCDriver_CreateInstance(const Reference<css::lang::XMultiServiceFactory>& _rxFactory);
+
+typedef ::cppu::WeakComponentImplHelper2<css::sdbc::XDriver, css::lang::XServiceInfo> ODriver_BASE;
+
+typedef void* (*OMysqlCConnection_CreateInstanceFunction)(void* _pDriver);
+
+class MysqlCDriver : public ODriver_BASE
+{
+protected:
+ Reference<css::lang::XMultiServiceFactory> m_xFactory;
+ ::osl::Mutex m_aMutex; // mutex is need to control member access
+ OWeakRefArray m_xConnections; // vector containing a list
+ // of all the Connection objects
+ // for this Driver
+#ifndef SYSTEM_MYSQL_CPPCONN
+#ifdef BUNDLE_MARIADB
+ oslModule m_hCConnModule;
+ bool m_bAttemptedLoadCConn;
+#endif
+#endif
+public:
+ explicit MysqlCDriver(const Reference<css::lang::XMultiServiceFactory>& _rxFactory);
+
+ // OComponentHelper
+ void SAL_CALL disposing() SAL_OVERRIDE;
+ // XInterface
+ static OUString getImplementationName_Static();
+ static Sequence<OUString> getSupportedServiceNames_Static();
+
+ // XServiceInfo
+ OUString SAL_CALL getImplementationName() SAL_OVERRIDE;
+ sal_Bool SAL_CALL supportsService(const OUString& ServiceName) SAL_OVERRIDE;
+ Sequence<OUString> SAL_CALL getSupportedServiceNames() SAL_OVERRIDE;
+
+ // XDriver
+ Reference<css::sdbc::XConnection> SAL_CALL
+ connect(const OUString& url, const Sequence<css::beans::PropertyValue>& info) SAL_OVERRIDE;
+
+ sal_Bool SAL_CALL acceptsURL(const OUString& url) SAL_OVERRIDE;
+ Sequence<css::sdbc::DriverPropertyInfo>
+ SAL_CALL getPropertyInfo(const OUString& url,
+ const Sequence<css::beans::PropertyValue>& info) SAL_OVERRIDE;
+
+ sal_Int32 SAL_CALL getMajorVersion() SAL_OVERRIDE;
+ sal_Int32 SAL_CALL getMinorVersion() SAL_OVERRIDE;
+
+ const Reference<css::lang::XMultiServiceFactory>& getFactory() const { return m_xFactory; }
+
+ static rtl_TextEncoding getDefaultEncoding() { return RTL_TEXTENCODING_UTF8; }
+
+private:
+ void impl_initCppConn_lck_throw();
+};
+} /* mysqlc */
+} /* connectivity */
+
+#endif // INCLUDED_MYSQLC_SOURCE_MYSQLC_DRIVER_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/connectivity/source/drivers/mysqlc/mysqlc_general.cxx b/connectivity/source/drivers/mysqlc/mysqlc_general.cxx
new file mode 100644
index 000000000000..1e5a6026a5d0
--- /dev/null
+++ b/connectivity/source/drivers/mysqlc/mysqlc_general.cxx
@@ -0,0 +1,354 @@
+/* -*- 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 "mysqlc_general.hxx"
+#include "mysqlc_resultsetmetadata.hxx"
+
+#include <sal/log.hxx>
+#include <rtl/ustring.hxx>
+
+using com::sun::star::sdbc::SQLException;
+
+using com::sun::star::uno::Any;
+using com::sun::star::uno::Reference;
+using com::sun::star::uno::XInterface;
+
+using namespace rtl;
+
+namespace mysqlc_sdbc_driver
+{
+void allocateSqlVar(void** mem, enum_field_types eType, unsigned nSize)
+{
+ assert(mem);
+ switch (eType)
+ {
+ case MYSQL_TYPE_LONG:
+ case MYSQL_TYPE_INT24:
+ *mem = malloc(sizeof(sal_Int32));
+ break;
+ case MYSQL_TYPE_SHORT:
+ *mem = malloc(sizeof(sal_Int16));
+ break;
+ case MYSQL_TYPE_BIT:
+ case MYSQL_TYPE_TINY:
+ *mem = malloc(sizeof(sal_Int8));
+ break;
+ case MYSQL_TYPE_LONGLONG:
+ *mem = malloc(sizeof(sal_Int64));
+ break;
+ case MYSQL_TYPE_FLOAT:
+ *mem = malloc(sizeof(float));
+ break;
+ case MYSQL_TYPE_DOUBLE:
+ *mem = malloc(sizeof(double));
+ break;
+ case MYSQL_TYPE_DATE:
+ case MYSQL_TYPE_TIME:
+ case MYSQL_TYPE_DATETIME:
+ case MYSQL_TYPE_TIMESTAMP:
+ case MYSQL_TYPE_YEAR: // FIXME below
+ case MYSQL_TYPE_NEWDATE:
+ case MYSQL_TYPE_ENUM:
+ case MYSQL_TYPE_SET:
+ case MYSQL_TYPE_GEOMETRY:
+ *mem = malloc(sizeof(MYSQL_TIME));
+ break;
+ case MYSQL_TYPE_STRING:
+ case MYSQL_TYPE_VAR_STRING:
+ case MYSQL_TYPE_VARCHAR:
+ case MYSQL_TYPE_DECIMAL:
+ case MYSQL_TYPE_NEWDECIMAL:
+ *mem = malloc(sizeof(char) * nSize);
+ break;
+ case MYSQL_TYPE_NULL:
+ case MYSQL_TYPE_BLOB:
+ case MYSQL_TYPE_TINY_BLOB:
+ case MYSQL_TYPE_MEDIUM_BLOB:
+ case MYSQL_TYPE_LONG_BLOB:
+ *mem = nullptr;
+ break;
+ default:
+ SAL_WARN("mysqlc", "unknown enum_field_type");
+ }
+}
+
+/// Use this intead of mysql_real_escape_string, because that one also escapes
+/// single quote ('), which should not be escaped
+rtl::OString escapeSql(const rtl::OString& from)
+{
+ rtl::OString sRet = from.replaceAll("\\", "\\\\");
+ sRet = sRet.replaceAll("\"", "\\\"");
+ sRet = sRet.replaceAll("`", "\\`");
+ return sRet;
+}
+
+void throwFeatureNotImplementedException(const sal_Char* _pAsciiFeatureName,
+ const css::uno::Reference<XInterface>& _rxContext)
+{
+ const rtl::OUString sMessage
+ = rtl::OUString::createFromAscii(_pAsciiFeatureName) + ": feature not implemented.";
+ throw SQLException(sMessage, _rxContext, "HYC00", 0, Any());
+}
+
+void throwInvalidArgumentException(const sal_Char* _pAsciiFeatureName,
+ const css::uno::Reference<XInterface>& _rxContext)
+{
+ const rtl::OUString sMessage
+ = rtl::OUString::createFromAscii(_pAsciiFeatureName) + ": invalid arguments.";
+ throw SQLException(sMessage, _rxContext, "HYC00", 0, Any());
+}
+
+void throwSQLExceptionWithMsg(const char* msg, unsigned int errorNum,
+ const css::uno::Reference<css::uno::XInterface>& _context,
+ const rtl_TextEncoding encoding)
+{
+ rtl::OString errorMsg{ msg };
+ // TODO error code?
+ throw SQLException(rtl::OStringToOUString(errorMsg, encoding), _context, rtl::OUString(),
+ errorNum, Any());
+}
+
+rtl::OUString getStringFromAny(const Any& _rAny)
+{
+ rtl::OUString nReturn;
+ OSL_VERIFY(_rAny >>= nReturn);
+ return nReturn;
+}
+
+sal_Int32 mysqlToOOOType(int eType, int charsetnr) noexcept
+{
+ // charset number 63 indicates binary
+ switch (eType)
+ {
+ case MYSQL_TYPE_BIT:
+ return css::sdbc::DataType::VARCHAR;
+
+ case MYSQL_TYPE_TINY:
+ return css::sdbc::DataType::TINYINT;
+
+ case MYSQL_TYPE_SHORT:
+ return css::sdbc::DataType::SMALLINT;
+
+ case MYSQL_TYPE_INT24:
+ case MYSQL_TYPE_LONG:
+ return css::sdbc::DataType::INTEGER;
+
+ case MYSQL_TYPE_LONGLONG:
+ return css::sdbc::DataType::BIGINT;
+
+ case MYSQL_TYPE_FLOAT:
+ return css::sdbc::DataType::REAL;
+
+ case MYSQL_TYPE_DOUBLE:
+ return css::sdbc::DataType::DOUBLE;
+
+ case MYSQL_TYPE_DECIMAL:
+ case MYSQL_TYPE_NEWDECIMAL:
+ return css::sdbc::DataType::DECIMAL;
+
+ case MYSQL_TYPE_STRING:
+ if (charsetnr == 63)
+ return css::sdbc::DataType::BINARY;
+ return css::sdbc::DataType::CHAR;
+
+ case MYSQL_TYPE_ENUM:
+ case MYSQL_TYPE_SET:
+ case MYSQL_TYPE_VAR_STRING:
+ if (charsetnr == 63)
+ return css::sdbc::DataType::VARBINARY;
+ return css::sdbc::DataType::VARCHAR;
+
+ case MYSQL_TYPE_BLOB:
+ if (charsetnr == 63)
+ return css::sdbc::DataType::LONGVARBINARY;
+ return css::sdbc::DataType::LONGVARCHAR;
+
+ case MYSQL_TYPE_TIMESTAMP:
+ case MYSQL_TYPE_DATETIME:
+ return css::sdbc::DataType::TIMESTAMP;
+
+ case MYSQL_TYPE_DATE:
+ return css::sdbc::DataType::DATE;
+
+ case MYSQL_TYPE_TIME:
+ return css::sdbc::DataType::TIME;
+
+ case MYSQL_TYPE_GEOMETRY:
+ return css::sdbc::DataType::VARCHAR;
+
+ case MYSQL_TYPE_NULL:
+ return css::sdbc::DataType::SQLNULL;
+ }
+
+ OSL_FAIL("mysqlToOOOType: unhandled case, falling back to VARCHAR");
+ return css::sdbc::DataType::VARCHAR;
+}
+
+sal_Int32 mysqlStrToOOOType(const rtl::OUString& sType)
+{
+ // TODO other types.
+ if (sType.equalsIgnoreAsciiCase("tiny") || sType.equalsIgnoreAsciiCase("tinyint"))
+ return css::sdbc::DataType::TINYINT;
+ if (sType.equalsIgnoreAsciiCase("smallint"))
+ return css::sdbc::DataType::SMALLINT;
+ if (sType.equalsIgnoreAsciiCase("longtext"))
+ return css::sdbc::DataType::LONGVARCHAR;
+ if (sType.equalsIgnoreAsciiCase("int"))
+ return css::sdbc::DataType::INTEGER;
+ if (sType.equalsIgnoreAsciiCase("varchar") || sType.equalsIgnoreAsciiCase("set")
+ || sType.equalsIgnoreAsciiCase("enum"))
+ return css::sdbc::DataType::VARCHAR;
+ if (sType.equalsIgnoreAsciiCase("bigint"))
+ return css::sdbc::DataType::BIGINT;
+ if (sType.equalsIgnoreAsciiCase("blob") || sType.equalsIgnoreAsciiCase("longblob"))
+ return css::sdbc::DataType::BLOB;
+ if (sType.equalsIgnoreAsciiCase("varbinary"))
+ return css::sdbc::DataType::VARBINARY;
+ if (sType.equalsIgnoreAsciiCase("text"))
+ return css::sdbc::DataType::CHAR;
+ if (sType.equalsIgnoreAsciiCase("binary"))
+ return css::sdbc::DataType::BINARY;
+ if (sType.equalsIgnoreAsciiCase("time"))
+ return css::sdbc::DataType::TIME;
+ if (sType.equalsIgnoreAsciiCase("date"))
+ return css::sdbc::DataType::DATE;
+ if (sType.equalsIgnoreAsciiCase("datetime"))
+ return css::sdbc::DataType::TIMESTAMP;
+ if (sType.equalsIgnoreAsciiCase("decimal"))
+ return css::sdbc::DataType::DECIMAL;
+ if (sType.equalsIgnoreAsciiCase("real") || sType.equalsIgnoreAsciiCase("float"))
+ return css::sdbc::DataType::REAL;
+ if (sType.equalsIgnoreAsciiCase("double"))
+ return css::sdbc::DataType::DOUBLE;
+ if (sType.equalsIgnoreAsciiCase("bit") || sType.equalsIgnoreAsciiCase("bool")
+ || sType.equalsIgnoreAsciiCase("boolean"))
+ return css::sdbc::DataType::BOOLEAN;
+ OSL_FAIL("Unknown type name from string, failing back to varchar.");
+ return css::sdbc::DataType::VARCHAR;
+}
+
+rtl::OUString mysqlTypeToStr(MYSQL_FIELD* field)
+{
+ bool isUnsigned = (field->flags & UNSIGNED_FLAG) != 0;
+ bool isZerofill = (field->flags & ZEROFILL_FLAG) != 0;
+ switch (field->type)
+ {
+ case MYSQL_TYPE_BIT:
+ return OUString{ "BIT" };
+ case MYSQL_TYPE_DECIMAL:
+ case MYSQL_TYPE_NEWDECIMAL:
+ return isUnsigned ? (isZerofill ? OUString{ "DECIMAL UNSIGNED ZEROFILL" }
+ : OUString{ "DECIMAL UNSIGNED" })
+ : OUString{ "DECIMAL" };
+ case MYSQL_TYPE_TINY:
+ return isUnsigned ? (isZerofill ? OUString{ "TINYINT UNSIGNED ZEROFILL" }
+ : OUString{ "TINYINT UNSIGNED" })
+ : OUString{ "TINYINT" };
+ case MYSQL_TYPE_SHORT:
+ return isUnsigned ? (isZerofill ? OUString{ "SMALLINT UNSIGNED ZEROFILL" }
+ : OUString{ "SMALLINT UNSIGNED" })
+ : OUString{ "SMALLINT" };
+ case MYSQL_TYPE_LONG:
+ return isUnsigned ? (isZerofill ? OUString{ "INT UNSIGNED ZEROFILL" }
+ : OUString{ "INT UNSIGNED" })
+ : OUString{ "INT" };
+ case MYSQL_TYPE_FLOAT:
+ return isUnsigned ? (isZerofill ? OUString{ "FLOAT UNSIGNED ZEROFILL" }
+ : OUString{ "FLOAT UNSIGNED" })
+ : OUString{ "FLOAT" };
+ case MYSQL_TYPE_DOUBLE:
+ return isUnsigned ? (isZerofill ? OUString{ "DOUBLE UNSIGNED ZEROFILL" }
+ : OUString{ "DOUBLE UNSIGNED" })
+ : OUString{ "DOUBLE" };
+ case MYSQL_TYPE_NULL:
+ return OUString{ "NULL" };
+ case MYSQL_TYPE_TIMESTAMP:
+ return OUString{ "TIMESTAMP" };
+ case MYSQL_TYPE_LONGLONG:
+ return isUnsigned ? (isZerofill ? OUString{ "BIGINT UNSIGNED ZEROFILL" }
+ : OUString{ "BIGINT UNSIGNED" })
+ : OUString{ "BIGINT" };
+ case MYSQL_TYPE_INT24:
+ return isUnsigned ? (isZerofill ? OUString{ "MEDIUMINT UNSIGNED ZEROFILL" }
+ : OUString{ "MEDIUMINT UNSIGNED" })
+ : OUString{ "MEDIUMINT" };
+ case MYSQL_TYPE_DATE:
+ return OUString{ "DATE" };
+ case MYSQL_TYPE_TIME:
+ return OUString{ "TIME" };
+ case MYSQL_TYPE_DATETIME:
+ return OUString{ "DATETIME" };
+ case MYSQL_TYPE_TINY_BLOB:
+ {
+ return OUString{ "TINYBLOB" };
+ }
+ case MYSQL_TYPE_MEDIUM_BLOB:
+ {
+ return OUString{ "MEDIUMBLOB" };
+ }
+ case MYSQL_TYPE_LONG_BLOB:
+ {
+ return OUString{ "LONGBLOB" };
+ }
+ case MYSQL_TYPE_BLOB:
+ {
+ return OUString{ "BLOB" };
+ }
+ case MYSQL_TYPE_VARCHAR:
+ case MYSQL_TYPE_VAR_STRING:
+ if (field->flags & ENUM_FLAG)
+ {
+ return OUString{ "ENUM" };
+ }
+ if (field->flags & SET_FLAG)
+ {
+ return OUString{ "SET" };
+ }
+ return OUString{ "VARCHAR" };
+ case MYSQL_TYPE_STRING:
+ if (field->flags & ENUM_FLAG)
+ {
+ return OUString{ "ENUM" };
+ }
+ if (field->flags & SET_FLAG)
+ {
+ return OUString{ "SET" };
+ }
+ return OUString{ "CHAR" };
+ case MYSQL_TYPE_YEAR:
+ return OUString{ "YEAR" };
+ case MYSQL_TYPE_GEOMETRY:
+ return OUString{ "GEOMETRY" };
+ default:
+ return OUString{ "UNKNOWN" };
+ }
+}
+
+rtl::OUString convert(const ::std::string& _string, const rtl_TextEncoding encoding)
+{
+ return rtl::OUString(_string.c_str(), _string.size(), encoding);
+}
+
+::std::string convert(const rtl::OUString& _string, const rtl_TextEncoding encoding)
+{
+ return ::std::string(rtl::OUStringToOString(_string, encoding).getStr());
+}
+
+} /* namespace */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/mysqlc/mysqlc_general.hxx b/connectivity/source/drivers/mysqlc/mysqlc_general.hxx
new file mode 100644
index 000000000000..2c0879a14d9c
--- /dev/null
+++ b/connectivity/source/drivers/mysqlc/mysqlc_general.hxx
@@ -0,0 +1,125 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef INCLUDED_MYSQLC_SOURCE_MYSQLC_GENERAL_HXX
+#define INCLUDED_MYSQLC_SOURCE_MYSQLC_GENERAL_HXX
+
+#include <config_lgpl.h>
+
+#include <com/sun/star/uno/XInterface.hpp>
+#include <com/sun/star/sdbc/SQLException.hpp>
+
+#include <osl/diagnose.h>
+#include <mysql.h>
+
+#if defined __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wdeprecated"
+#endif
+
+#if defined __GNUC__
+#pragma GCC diagnostic pop
+#endif
+
+namespace mysqlc_sdbc_driver
+{
+template <typename T>
+void resetSqlVar(void** target, T* pValue, enum_field_types type, sal_Int32 nSize = 0)
+{
+ if (*target)
+ {
+ free(*target);
+ *target = nullptr;
+ }
+ constexpr auto nUnitSize = sizeof(T);
+ switch (type)
+ {
+ case MYSQL_TYPE_INT24:
+ case MYSQL_TYPE_YEAR:
+ case MYSQL_TYPE_NEWDATE:
+ case MYSQL_TYPE_BIT:
+ case MYSQL_TYPE_GEOMETRY:
+ case MYSQL_TYPE_LONG:
+ case MYSQL_TYPE_SHORT:
+ case MYSQL_TYPE_TINY:
+ case MYSQL_TYPE_LONGLONG:
+ case MYSQL_TYPE_FLOAT:
+ case MYSQL_TYPE_DOUBLE:
+ case MYSQL_TYPE_TIME:
+ case MYSQL_TYPE_DATE:
+ case MYSQL_TYPE_DATETIME:
+ case MYSQL_TYPE_TIMESTAMP:
+ *target = malloc(nUnitSize);
+ memcpy(*target, pValue, nUnitSize);
+ break;
+ case MYSQL_TYPE_STRING:
+ case MYSQL_TYPE_BLOB:
+ case MYSQL_TYPE_DECIMAL:
+ case MYSQL_TYPE_VARCHAR:
+ case MYSQL_TYPE_NEWDECIMAL:
+ case MYSQL_TYPE_ENUM:
+ case MYSQL_TYPE_SET:
+ case MYSQL_TYPE_VAR_STRING:
+ case MYSQL_TYPE_TINY_BLOB:
+ case MYSQL_TYPE_MEDIUM_BLOB:
+ case MYSQL_TYPE_LONG_BLOB:
+ *target = malloc(nUnitSize * nSize);
+ memcpy(*target, pValue, nUnitSize * nSize);
+ break;
+ case MYSQL_TYPE_NULL:
+ // nothing I guess
+ break;
+ default:
+ OSL_FAIL("resetSqlVar: unknown enum_field_type");
+ }
+}
+
+void allocateSqlVar(void** mem, enum_field_types eType, unsigned nSize = 0);
+
+rtl::OString escapeSql(const rtl::OString& from);
+
+rtl::OUString getStringFromAny(const css::uno::Any& _rAny);
+
+/// @throws css::sdbc::SQLException
+void throwFeatureNotImplementedException(
+ const sal_Char* _pAsciiFeatureName,
+ const css::uno::Reference<css::uno::XInterface>& _rxContext);
+
+/// @throws css::sdbc::SQLException
+void throwInvalidArgumentException(const sal_Char* _pAsciiFeatureName,
+ const css::uno::Reference<css::uno::XInterface>& _rxContext);
+
+void throwSQLExceptionWithMsg(const char* msg, unsigned int errorNum,
+ const css::uno::Reference<css::uno::XInterface>& _context,
+ const rtl_TextEncoding encoding);
+
+sal_Int32 mysqlToOOOType(int eType, int charsetnr) noexcept;
+
+rtl::OUString mysqlTypeToStr(MYSQL_FIELD* pField);
+
+sal_Int32 mysqlStrToOOOType(const rtl::OUString& sType);
+
+rtl::OUString convert(const ::std::string& _string, const rtl_TextEncoding encoding);
+
+::std::string convert(const rtl::OUString& _string, const rtl_TextEncoding encoding);
+}
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/mysqlc/mysqlc_prepared_resultset.cxx b/connectivity/source/drivers/mysqlc/mysqlc_prepared_resultset.cxx
new file mode 100644
index 000000000000..7b84661b8e21
--- /dev/null
+++ b/connectivity/source/drivers/mysqlc/mysqlc_prepared_resultset.cxx
@@ -0,0 +1,1097 @@
+/* -*- 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 "mysqlc_propertyids.hxx"
+#include "mysqlc_general.hxx"
+#include "mysqlc_prepared_resultset.hxx"
+#include "mysqlc_resultsetmetadata.hxx"
+
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/lang/DisposedException.hpp>
+#include <com/sun/star/sdbc/DataType.hpp>
+#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/sdbcx/CompareBookmark.hpp>
+#include <cppuhelper/supportsservice.hxx>
+#include <cppuhelper/typeprovider.hxx>
+
+using namespace rtl;
+#include <comphelper/string.hxx>
+
+#include <cstdlib>
+
+using namespace connectivity::mysqlc;
+using namespace cppu;
+using namespace com::sun::star;
+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;
+using namespace ::comphelper;
+using ::osl::MutexGuard;
+
+#include <stdio.h>
+
+rtl::OUString SAL_CALL OPreparedResultSet::getImplementationName()
+{
+ return rtl::OUString("com.sun.star.sdbcx.mysqlc.ResultSet");
+}
+
+uno::Sequence<rtl::OUString> SAL_CALL OPreparedResultSet::getSupportedServiceNames()
+{
+ uno::Sequence<rtl::OUString> aSupported(2);
+ aSupported[0] = "com.sun.star.sdbc.ResultSet";
+ aSupported[1] = "com.sun.star.sdbcx.ResultSet";
+ return aSupported;
+}
+
+sal_Bool SAL_CALL OPreparedResultSet::supportsService(const rtl::OUString& _rServiceName)
+{
+ return cppu::supportsService(this, _rServiceName);
+}
+OPreparedResultSet::OPreparedResultSet(OConnection& rConn, OPreparedStatement* pPrepared,
+ MYSQL_STMT* pStmt)
+ : OPreparedResultSet_BASE(m_aMutex)
+ , OPropertySetHelper(OPreparedResultSet_BASE::rBHelper)
+ , m_rConnection(rConn)
+ , m_aStatement(static_cast<OWeakObject*>(pPrepared))
+ , m_xMetaData(nullptr)
+ , m_pStmt(pStmt)
+ , m_encoding(rConn.getConnectionEncoding())
+{
+ m_nFieldCount = mysql_stmt_field_count(pStmt);
+ m_pResult = mysql_stmt_result_metadata(m_pStmt);
+ m_aFields = mysql_fetch_fields(m_pResult);
+}
+
+OPreparedResultSet::~OPreparedResultSet() {}
+
+void OPreparedResultSet::disposing()
+{
+ OPropertySetHelper::disposing();
+
+ MutexGuard aGuard(m_aMutex);
+
+ m_aStatement = nullptr;
+ m_xMetaData = nullptr;
+}
+
+Any SAL_CALL OPreparedResultSet::queryInterface(const Type& rType)
+{
+ Any aRet = OPropertySetHelper::queryInterface(rType);
+ if (!aRet.hasValue())
+ {
+ aRet = OPreparedResultSet_BASE::queryInterface(rType);
+ }
+ return aRet;
+}
+
+uno::Sequence<Type> SAL_CALL OPreparedResultSet::getTypes()
+{
+ OTypeCollection aTypes(cppu::UnoType<XMultiPropertySet>::get(),
+ cppu::UnoType<XFastPropertySet>::get(),
+ cppu::UnoType<XPropertySet>::get());
+
+ return concatSequences(aTypes.getTypes(), OPreparedResultSet_BASE::getTypes());
+}
+
+sal_Int32 SAL_CALL OPreparedResultSet::findColumn(const rtl::OUString& columnName)
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed);
+
+ MYSQL_FIELD* pFields = mysql_fetch_field(m_pResult);
+ for (sal_Int32 i = 0; i < m_nFieldCount; ++i)
+ {
+ if (columnName.equalsIgnoreAsciiCaseAscii(pFields[i].name))
+ return i + 1; // sdbc indexes from 1
+ }
+
+ throw SQLException("The column name '" + columnName + "' is not valid.", *this, "42S22", 0,
+ Any());
+}
+
+uno::Reference<XInputStream> SAL_CALL OPreparedResultSet::getBinaryStream(sal_Int32 column)
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed);
+ checkColumnIndex(column);
+
+ mysqlc_sdbc_driver::throwFeatureNotImplementedException("OPreparedResultSet::getBinaryStream",
+ *this);
+ return nullptr;
+}
+
+uno::Reference<XInputStream> SAL_CALL OPreparedResultSet::getCharacterStream(sal_Int32 column)
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed);
+ checkColumnIndex(column);
+
+ mysqlc_sdbc_driver::throwFeatureNotImplementedException(
+ "OPreparedResultSet::getCharacterStream", *this);
+ return nullptr;
+}
+
+sal_Bool SAL_CALL OPreparedResultSet::getBoolean(sal_Int32 column)
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed);
+ checkColumnIndex(column);
+
+ if (*m_aData[column - 1].is_null)
+ {
+ m_bWasNull = true;
+ return false;
+ }
+ m_bWasNull = false;
+ return *reinterpret_cast<bool*>(m_aData[column - 1].buffer);
+}
+
+sal_Int8 SAL_CALL OPreparedResultSet::getByte(sal_Int32 column)
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed);
+ checkColumnIndex(column);
+
+ if (*m_aData[column - 1].is_null)
+ {
+ m_bWasNull = true;
+ return 0;
+ }
+ m_bWasNull = false;
+ return *reinterpret_cast<sal_Int8*>(m_aData[column - 1].buffer);
+}
+
+uno::Sequence<sal_Int8> SAL_CALL OPreparedResultSet::getBytes(sal_Int32 column)
+{
+ checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed);
+ MutexGuard aGuard(m_aMutex);
+
+ if (*m_aData[column - 1].is_null)
+ {
+ m_bWasNull = true;
+ return uno::Sequence<sal_Int8>();
+ }
+ m_bWasNull = false;
+
+ return uno::Sequence<sal_Int8>(reinterpret_cast<sal_Int8 const*>(m_aData[column - 1].buffer),
+ *m_aData[column - 1].length);
+}
+
+Date SAL_CALL OPreparedResultSet::getDate(sal_Int32 column)
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed);
+ checkColumnIndex(column);
+
+ if (*m_aData[column - 1].is_null)
+ {
+ m_bWasNull = true;
+ return Date{}; // TODO init
+ }
+ m_bWasNull = false;
+
+ const MYSQL_TIME* pTime = reinterpret_cast<MYSQL_TIME*>(m_aData[column - 1].buffer);
+
+ assert(pTime != nullptr);
+
+ Date d;
+ d.Year = pTime->year;
+ d.Month = pTime->month;
+ d.Day = pTime->day;
+ return d;
+}
+
+double SAL_CALL OPreparedResultSet::getDouble(sal_Int32 column)
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed);
+ checkColumnIndex(column);
+
+ if (*m_aData[column - 1].is_null)
+ {
+ m_bWasNull = true;
+ return double{};
+ }
+ m_bWasNull = false;
+
+ if (m_aFields[column - 1].type == MYSQL_TYPE_FLOAT)
+ return *reinterpret_cast<float*>(m_aData[column - 1].buffer);
+
+ return *reinterpret_cast<double*>(m_aData[column - 1].buffer);
+}
+
+float SAL_CALL OPreparedResultSet::getFloat(sal_Int32 column)
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed);
+ checkColumnIndex(column);
+
+ if (*m_aData[column - 1].is_null)
+ {
+ m_bWasNull = true;
+ return float{};
+ }
+ m_bWasNull = false;
+
+ return *reinterpret_cast<float*>(m_aData[column - 1].buffer);
+}
+
+sal_Int32 SAL_CALL OPreparedResultSet::getInt(sal_Int32 column)
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed);
+ if (*m_aData[column - 1].is_null)
+ {
+ m_bWasNull = true;
+ return sal_Int32{};
+ }
+ m_bWasNull = false;
+
+ return *reinterpret_cast<sal_Int32*>(m_aData[column - 1].buffer);
+}
+
+sal_Int32 SAL_CALL OPreparedResultSet::getRow()
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed);
+
+ return static_cast<sal_Int32>(mysql_field_tell(m_pResult));
+}
+
+sal_Int64 SAL_CALL OPreparedResultSet::getLong(sal_Int32 column)
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed);
+ checkColumnIndex(column);
+
+ if (*m_aData[column - 1].is_null)
+ return sal_Int64{};
+
+ return *reinterpret_cast<sal_Int64*>(m_aData[column - 1].buffer);
+}
+
+uno::Reference<XResultSetMetaData> SAL_CALL OPreparedResultSet::getMetaData()
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed);
+ if (!m_xMetaData.is())
+ {
+ m_xMetaData = new OResultSetMetaData(m_rConnection, m_pResult, m_encoding);
+ }
+ return m_xMetaData;
+}
+
+uno::Reference<XArray> SAL_CALL OPreparedResultSet::getArray(sal_Int32 column)
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed);
+ checkColumnIndex(column);
+
+ mysqlc_sdbc_driver::throwFeatureNotImplementedException("OPreparedResultSet::getArray", *this);
+ return nullptr;
+}
+
+uno::Reference<XClob> SAL_CALL OPreparedResultSet::getClob(sal_Int32 column)
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed);
+ checkColumnIndex(column);
+
+ mysqlc_sdbc_driver::throwFeatureNotImplementedException("OPreparedResultSet::getClob", *this);
+ return nullptr;
+}
+
+uno::Reference<XBlob> SAL_CALL OPreparedResultSet::getBlob(sal_Int32 column)
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed);
+ checkColumnIndex(column);
+
+ mysqlc_sdbc_driver::throwFeatureNotImplementedException("OPreparedResultSet::getBlob", *this);
+ return nullptr;
+}
+
+uno::Reference<XRef> SAL_CALL OPreparedResultSet::getRef(sal_Int32 column)
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed);
+ checkColumnIndex(column);
+
+ mysqlc_sdbc_driver::throwFeatureNotImplementedException("OPreparedResultSet::getRef", *this);
+ return nullptr;
+}
+
+Any SAL_CALL OPreparedResultSet::getObject(sal_Int32 column,
+ const uno::Reference<XNameAccess>& /* typeMap */)
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed);
+ checkColumnIndex(column);
+
+ Any aRet = Any();
+
+ mysqlc_sdbc_driver::throwFeatureNotImplementedException("OPreparedResultSet::getObject", *this);
+ return aRet;
+}
+
+sal_Int16 SAL_CALL OPreparedResultSet::getShort(sal_Int32 column)
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed);
+ checkColumnIndex(column);
+
+ if (*m_aData[column - 1].is_null)
+ {
+ m_bWasNull = true;
+ return sal_Int16{};
+ }
+ m_bWasNull = false;
+
+ return *reinterpret_cast<sal_Int16*>(m_aData[column - 1].buffer);
+}
+
+rtl::OUString SAL_CALL OPreparedResultSet::getString(sal_Int32 column)
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed);
+ checkColumnIndex(column);
+ if (*m_aData[column - 1].is_null)
+ {
+ m_bWasNull = true;
+ return OUString{};
+ }
+ m_bWasNull = false;
+
+ if (m_aFields[column - 1].type == MYSQL_TYPE_BIT)
+ {
+ if (*reinterpret_cast<sal_Int8*>(m_aData[column - 1].buffer) != 0)
+ return OUString{ "YES" };
+ return OUString{ "NO" };
+ }
+
+ const char* sStr = reinterpret_cast<const char*>(m_aData[column - 1].buffer);
+
+ OUString sReturn = rtl::OUString(sStr, *m_aData[column - 1].length, m_encoding);
+ return sReturn;
+}
+
+Time SAL_CALL OPreparedResultSet::getTime(sal_Int32 column)
+{
+ checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed);
+ MutexGuard aGuard(m_aMutex);
+ checkColumnIndex(column);
+
+ if (*m_aData[column - 1].is_null)
+ {
+ m_bWasNull = true;
+ return Time{}; // TODO init
+ }
+ m_bWasNull = false;
+
+ const MYSQL_TIME* pTime = reinterpret_cast<MYSQL_TIME*>(m_aData[column - 1].buffer);
+
+ assert(pTime != nullptr);
+
+ Time t;
+ t.Hours = pTime->hour;
+ t.Minutes = pTime->minute;
+ t.Seconds = pTime->second;
+ return t;
+}
+
+DateTime SAL_CALL OPreparedResultSet::getTimestamp(sal_Int32 column)
+{
+ checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed);
+ MutexGuard aGuard(m_aMutex);
+ checkColumnIndex(column);
+
+ if (*m_aData[column - 1].is_null)
+ {
+ m_bWasNull = true;
+ return DateTime{};
+ }
+ m_bWasNull = false;
+
+ const MYSQL_TIME* pTime = reinterpret_cast<MYSQL_TIME*>(m_aData[column - 1].buffer);
+
+ assert(pTime != nullptr);
+
+ DateTime t;
+ t.Year = pTime->year;
+ t.Month = pTime->month;
+ t.Day = pTime->day;
+ t.Hours = pTime->hour;
+ t.Minutes = pTime->minute;
+ t.Seconds = pTime->second;
+ return t;
+}
+
+sal_Bool SAL_CALL OPreparedResultSet::isBeforeFirst()
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed);
+
+ return m_nCurrentField == 0;
+}
+
+sal_Bool SAL_CALL OPreparedResultSet::isAfterLast()
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed);
+
+ return m_nCurrentField >= m_nFieldCount;
+}
+
+sal_Bool SAL_CALL OPreparedResultSet::isFirst()
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed);
+
+ return m_nCurrentField == 1 && !isAfterLast();
+}
+
+sal_Bool SAL_CALL OPreparedResultSet::isLast()
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed);
+
+ return mysql_field_tell(m_pResult) == static_cast<unsigned>(m_nFieldCount);
+}
+
+void SAL_CALL OPreparedResultSet::beforeFirst()
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed);
+
+ mysqlc_sdbc_driver::throwFeatureNotImplementedException("OPreparedResultSet::beforeFirst",
+ *this);
+}
+
+void SAL_CALL OPreparedResultSet::afterLast()
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed);
+
+ mysqlc_sdbc_driver::throwFeatureNotImplementedException("OPreparedResultSet::afterLast", *this);
+}
+
+void SAL_CALL OPreparedResultSet::close()
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed);
+
+ if (m_aData)
+ {
+ delete[] m_aData;
+ delete[] m_aMetaData;
+ }
+
+ if (m_pResult)
+ mysql_free_result(m_pResult);
+ mysql_stmt_free_result(m_pStmt);
+ dispose();
+}
+
+sal_Bool SAL_CALL OPreparedResultSet::first()
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed);
+
+ mysql_stmt_data_seek(m_pStmt, 0);
+ next();
+
+ return true;
+}
+
+sal_Bool SAL_CALL OPreparedResultSet::last()
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed);
+
+ mysql_stmt_data_seek(m_pStmt, m_nFieldCount - 1);
+ next();
+
+ return true;
+}
+
+sal_Bool SAL_CALL OPreparedResultSet::absolute(sal_Int32 row)
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed);
+
+ sal_Int32 nFields = static_cast<sal_Int32>(m_nFieldCount);
+ sal_Int32 nToGo = row < 0 ? nFields - row : row - 1;
+
+ if (nToGo >= nFields)
+ nToGo = nFields - 1;
+ if (nToGo < 0)
+ nToGo = 0;
+
+ mysql_stmt_data_seek(m_pStmt, nToGo);
+ next();
+
+ return true;
+}
+
+sal_Bool SAL_CALL OPreparedResultSet::relative(sal_Int32 row)
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed);
+
+ sal_Int32 nFields = static_cast<sal_Int32>(m_nFieldCount);
+ if (row == 0)
+ return true;
+
+ sal_Int32 nToGo = m_nCurrentField + row;
+ if (nToGo >= nFields)
+ nToGo = nFields - 1;
+ if (nToGo < 0)
+ nToGo = 0;
+
+ mysql_stmt_data_seek(m_pStmt, nToGo);
+ next();
+ m_nCurrentField += row;
+
+ return true;
+}
+
+sal_Bool SAL_CALL OPreparedResultSet::previous()
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed);
+
+ if (m_nCurrentField <= 1)
+ return false;
+
+ mysql_stmt_data_seek(m_pStmt, m_nCurrentField - 2);
+ next();
+ --m_nFieldCount;
+ return true;
+}
+
+uno::Reference<uno::XInterface> SAL_CALL OPreparedResultSet::getStatement()
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed);
+
+ return m_aStatement.get();
+}
+
+sal_Bool SAL_CALL OPreparedResultSet::rowDeleted()
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed);
+
+ return false;
+}
+
+sal_Bool SAL_CALL OPreparedResultSet::rowInserted()
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed);
+
+ return false;
+}
+
+sal_Bool SAL_CALL OPreparedResultSet::rowUpdated()
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed);
+
+ return false;
+}
+
+sal_Bool SAL_CALL OPreparedResultSet::next()
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed);
+
+ bool bFirstRun = false;
+ // allocate array if it does not exist
+ if (m_aData == nullptr)
+ {
+ bFirstRun = true;
+ m_aData = new MYSQL_BIND[m_nFieldCount];
+ memset(m_aData, 0, m_nFieldCount * sizeof(MYSQL_BIND));
+ m_aMetaData = new BindMetaData[m_nFieldCount];
+ }
+ for (sal_Int32 i = 0; i < m_nFieldCount; ++i)
+ {
+ m_aMetaData[i].is_null = 0;
+ m_aMetaData[i].length = 0l;
+ m_aMetaData[i].error = 0;
+
+ m_aData[i].is_null = &m_aMetaData[i].is_null;
+ m_aData[i].buffer_length = m_aFields[i].type == MYSQL_TYPE_BLOB ? 0 : m_aFields[i].length;
+ m_aData[i].length = &m_aMetaData[i].length;
+ m_aData[i].error = &m_aMetaData[i].error;
+ m_aData[i].buffer = nullptr;
+ m_aData[i].buffer_type = m_aFields[i].type;
+
+ // allocates memory, if it is a fixed size type. If not then nullptr
+ mysqlc_sdbc_driver::allocateSqlVar(&m_aData[i].buffer, m_aData[i].buffer_type,
+ m_aFields[i].length);
+ }
+ mysql_stmt_bind_result(m_pStmt, m_aData);
+ if (bFirstRun)
+ mysql_stmt_store_result(m_pStmt);
+ int failure = mysql_stmt_fetch(m_pStmt);
+
+ for (sal_Int32 i = 0; i < m_nFieldCount; ++i)
+ {
+ if (*m_aData[i].error)
+ {
+ // expected if we have a BLOB, as buffer_length is set to 0. We want to
+ // fetch it piece by piece
+ // see https://bugs.mysql.com/file.php?id=12361&bug_id=33086
+ if (m_aData[i].buffer == nullptr)
+ {
+ m_aData[i].buffer_length = *m_aData[i].length;
+ m_aData[i].buffer = malloc(*m_aData[i].length);
+ mysql_stmt_fetch_column(m_pStmt, &m_aData[i], i, 0);
+ }
+ }
+ }
+
+ if (failure == 1)
+ {
+ MYSQL* pMysql = m_rConnection.getMysqlConnection();
+ mysqlc_sdbc_driver::throwSQLExceptionWithMsg(mysql_error(pMysql), mysql_errno(pMysql),
+ *this, m_encoding);
+ }
+ else if (failure == MYSQL_NO_DATA)
+ return false;
+
+ // current field cannot be asked as a number. We have to keep track it
+ // manually.
+ m_nCurrentField += 1;
+
+ return true;
+}
+
+sal_Bool SAL_CALL OPreparedResultSet::wasNull()
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed);
+
+ return m_bWasNull;
+}
+
+void SAL_CALL OPreparedResultSet::cancel()
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed);
+}
+
+void SAL_CALL OPreparedResultSet::clearWarnings() {}
+
+Any SAL_CALL OPreparedResultSet::getWarnings()
+{
+ Any aRet = Any();
+ return aRet;
+}
+
+void SAL_CALL OPreparedResultSet::insertRow()
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed);
+ // you only have to implement this if you want to insert new rows
+ mysqlc_sdbc_driver::throwFeatureNotImplementedException("OPreparedResultSet::insertRow", *this);
+}
+
+void SAL_CALL OPreparedResultSet::updateRow()
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed);
+
+ // only when you allow updates
+ mysqlc_sdbc_driver::throwFeatureNotImplementedException("OPreparedResultSet::updateRow", *this);
+}
+
+void SAL_CALL OPreparedResultSet::deleteRow()
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed);
+ mysqlc_sdbc_driver::throwFeatureNotImplementedException("OPreparedResultSet::deleteRow", *this);
+}
+
+void SAL_CALL OPreparedResultSet::cancelRowUpdates()
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed);
+ mysqlc_sdbc_driver::throwFeatureNotImplementedException("OPreparedResultSet::cancelRowUpdates",
+ *this);
+}
+
+void SAL_CALL OPreparedResultSet::moveToInsertRow()
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed);
+
+ // only when you allow insert's
+ mysqlc_sdbc_driver::throwFeatureNotImplementedException("OPreparedResultSet::moveToInsertRow",
+ *this);
+}
+
+void SAL_CALL OPreparedResultSet::moveToCurrentRow()
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed);
+}
+
+void SAL_CALL OPreparedResultSet::updateNull(sal_Int32 column)
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed);
+ checkColumnIndex(column);
+ mysqlc_sdbc_driver::throwFeatureNotImplementedException("OPreparedResultSet::updateNull",
+ *this);
+}
+
+void SAL_CALL OPreparedResultSet::updateBoolean(sal_Int32 column, sal_Bool /* x */)
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed);
+ checkColumnIndex(column);
+ mysqlc_sdbc_driver::throwFeatureNotImplementedException("OPreparedResultSet::updateBoolean",
+ *this);
+}
+
+void SAL_CALL OPreparedResultSet::updateByte(sal_Int32 column, sal_Int8 /* x */)
+{
+ checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed);
+ MutexGuard aGuard(m_aMutex);
+ checkColumnIndex(column);
+ mysqlc_sdbc_driver::throwFeatureNotImplementedException("OPreparedResultSet::updateByte",
+ *this);
+}
+
+void SAL_CALL OPreparedResultSet::updateShort(sal_Int32 column, sal_Int16 /* x */)
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed);
+ checkColumnIndex(column);
+ mysqlc_sdbc_driver::throwFeatureNotImplementedException("OPreparedResultSet::updateShort",
+ *this);
+}
+
+void SAL_CALL OPreparedResultSet::updateInt(sal_Int32 column, sal_Int32 /* x */)
+{
+ checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed);
+ MutexGuard aGuard(m_aMutex);
+ checkColumnIndex(column);
+ mysqlc_sdbc_driver::throwFeatureNotImplementedException("OPreparedResultSet::updateInt", *this);
+}
+
+void SAL_CALL OPreparedResultSet::updateLong(sal_Int32 column, sal_Int64 /* x */)
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed);
+ checkColumnIndex(column);
+ mysqlc_sdbc_driver::throwFeatureNotImplementedException("OPreparedResultSet::updateLong",
+ *this);
+}
+
+void SAL_CALL OPreparedResultSet::updateFloat(sal_Int32 column, float /* x */)
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed);
+ checkColumnIndex(column);
+ mysqlc_sdbc_driver::throwFeatureNotImplementedException("OPreparedResultSet::updateFloat",
+ *this);
+}
+
+void SAL_CALL OPreparedResultSet::updateDouble(sal_Int32 column, double /* x */)
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed);
+ checkColumnIndex(column);
+ mysqlc_sdbc_driver::throwFeatureNotImplementedException("OPreparedResultSet::updateDouble",
+ *this);
+}
+
+void SAL_CALL OPreparedResultSet::updateString(sal_Int32 column, const rtl::OUString& /* x */)
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed);
+ checkColumnIndex(column);
+ mysqlc_sdbc_driver::throwFeatureNotImplementedException("OPreparedResultSet::updateString",
+ *this);
+}
+
+void SAL_CALL OPreparedResultSet::updateBytes(sal_Int32 column,
+ const uno::Sequence<sal_Int8>& /* x */)
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed);
+ checkColumnIndex(column);
+ mysqlc_sdbc_driver::throwFeatureNotImplementedException("OPreparedResultSet::updateBytes",
+ *this);
+}
+
+void SAL_CALL OPreparedResultSet::updateDate(sal_Int32 column, const Date& /* x */)
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed);
+ checkColumnIndex(column);
+ mysqlc_sdbc_driver::throwFeatureNotImplementedException("OPreparedResultSet::updateDate",
+ *this);
+}
+
+void SAL_CALL OPreparedResultSet::updateTime(sal_Int32 column, const Time& /* x */)
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed);
+ checkColumnIndex(column);
+ mysqlc_sdbc_driver::throwFeatureNotImplementedException("OPreparedResultSet::updateTime",
+ *this);
+}
+
+void SAL_CALL OPreparedResultSet::updateTimestamp(sal_Int32 column, const DateTime& /* x */)
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed);
+ checkColumnIndex(column);
+ mysqlc_sdbc_driver::throwFeatureNotImplementedException("OPreparedResultSet::updateTimestamp",
+ *this);
+}
+
+void SAL_CALL OPreparedResultSet::updateBinaryStream(sal_Int32 column,
+ const uno::Reference<XInputStream>& /* x */,
+ sal_Int32 /* length */)
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed);
+ checkColumnIndex(column);
+ mysqlc_sdbc_driver::throwFeatureNotImplementedException(
+ "OPreparedResultSet::updateBinaryStream", *this);
+}
+
+void SAL_CALL OPreparedResultSet::updateCharacterStream(sal_Int32 column,
+ const uno::Reference<XInputStream>& /* x */,
+ sal_Int32 /* length */)
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed);
+ checkColumnIndex(column);
+ mysqlc_sdbc_driver::throwFeatureNotImplementedException(
+ "OPreparedResultSet::updateCharacterStream", *this);
+}
+
+void SAL_CALL OPreparedResultSet::refreshRow()
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed);
+ mysqlc_sdbc_driver::throwFeatureNotImplementedException("OPreparedResultSet::refreshRow",
+ *this);
+}
+
+void SAL_CALL OPreparedResultSet::updateObject(sal_Int32 column, const Any& /* x */)
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed);
+ checkColumnIndex(column);
+ mysqlc_sdbc_driver::throwFeatureNotImplementedException("OPreparedResultSet::updateObject",
+ *this);
+}
+
+void SAL_CALL OPreparedResultSet::updateNumericObject(sal_Int32 column, const Any& /* x */,
+ sal_Int32 /* scale */)
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed);
+ checkColumnIndex(column);
+ mysqlc_sdbc_driver::throwFeatureNotImplementedException(
+ "OPreparedResultSet::updateNumericObject", *this);
+}
+
+// XRowLocate
+Any SAL_CALL OPreparedResultSet::getBookmark()
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed);
+ Any aRet = Any();
+
+ // if you don't want to support bookmark you must remove the XRowLocate interface
+ mysqlc_sdbc_driver::throwFeatureNotImplementedException("OPreparedResultSet::getBookmark",
+ *this);
+
+ return aRet;
+}
+
+sal_Bool SAL_CALL OPreparedResultSet::moveToBookmark(const Any& /* bookmark */)
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed);
+
+ return false;
+}
+
+sal_Bool SAL_CALL OPreparedResultSet::moveRelativeToBookmark(const Any& /* bookmark */,
+ sal_Int32 /* rows */)
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed);
+
+ mysqlc_sdbc_driver::throwFeatureNotImplementedException(
+ "OPreparedResultSet::moveRelativeToBookmark", *this);
+ return false;
+}
+
+sal_Int32 SAL_CALL OPreparedResultSet::compareBookmarks(const Any& /* n1 */, const Any& /* n2 */)
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed);
+
+ mysqlc_sdbc_driver::throwFeatureNotImplementedException("OPreparedResultSet::compareBookmarks",
+ *this);
+
+ return CompareBookmark::NOT_EQUAL;
+}
+
+sal_Bool SAL_CALL OPreparedResultSet::hasOrderedBookmarks() { return false; }
+
+sal_Int32 SAL_CALL OPreparedResultSet::hashBookmark(const Any& /* bookmark */)
+{
+ mysqlc_sdbc_driver::throwFeatureNotImplementedException("OPreparedResultSet::hashBookmark",
+ *this);
+ return 0;
+}
+
+// XDeleteRows
+uno::Sequence<sal_Int32>
+ SAL_CALL OPreparedResultSet::deleteRows(const uno::Sequence<Any>& /* rows */)
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OPreparedResultSet_BASE::rBHelper.bDisposed);
+ uno::Sequence<sal_Int32> aRet = uno::Sequence<sal_Int32>();
+
+ mysqlc_sdbc_driver::throwFeatureNotImplementedException("OPreparedResultSet::deleteRows",
+ *this);
+ return aRet;
+}
+
+IPropertyArrayHelper* OPreparedResultSet::createArrayHelper() const
+{
+ uno::Sequence<Property> aProps(5);
+ Property* pProperties = aProps.getArray();
+ sal_Int32 nPos = 0;
+ pProperties[nPos++] = Property("FetchDirection", PROPERTY_ID_FETCHDIRECTION,
+ cppu::UnoType<sal_Int32>::get(), 0);
+ pProperties[nPos++]
+ = Property("FetchSize", PROPERTY_ID_FETCHSIZE, cppu::UnoType<sal_Int32>::get(), 0);
+ pProperties[nPos++] = Property("IsBookmarkable", PROPERTY_ID_ISBOOKMARKABLE,
+ cppu::UnoType<bool>::get(), PropertyAttribute::READONLY);
+ pProperties[nPos++] = Property("ResultSetConcurrency", PROPERTY_ID_RESULTSETCONCURRENCY,
+ cppu::UnoType<sal_Int32>::get(), PropertyAttribute::READONLY);
+ pProperties[nPos++] = Property("ResultSetType", PROPERTY_ID_RESULTSETTYPE,
+ cppu::UnoType<sal_Int32>::get(), PropertyAttribute::READONLY);
+
+ return new OPropertyArrayHelper(aProps);
+}
+
+IPropertyArrayHelper& OPreparedResultSet::getInfoHelper() { return *getArrayHelper(); }
+
+sal_Bool OPreparedResultSet::convertFastPropertyValue(Any& /* rConvertedValue */,
+ Any& /* rOldValue */, sal_Int32 nHandle,
+ const Any& /* rValue */)
+{
+ switch (nHandle)
+ {
+ case PROPERTY_ID_ISBOOKMARKABLE:
+ case PROPERTY_ID_CURSORNAME:
+ case PROPERTY_ID_RESULTSETCONCURRENCY:
+ case PROPERTY_ID_RESULTSETTYPE:
+ throw css::lang::IllegalArgumentException();
+ case PROPERTY_ID_FETCHDIRECTION:
+ case PROPERTY_ID_FETCHSIZE:
+ default:;
+ }
+ return false;
+}
+
+void OPreparedResultSet::setFastPropertyValue_NoBroadcast(sal_Int32 nHandle,
+ const Any& /* rValue */)
+{
+ switch (nHandle)
+ {
+ case PROPERTY_ID_ISBOOKMARKABLE:
+ case PROPERTY_ID_CURSORNAME:
+ case PROPERTY_ID_RESULTSETCONCURRENCY:
+ case PROPERTY_ID_RESULTSETTYPE:
+ throw uno::Exception("cannot set prop " + rtl::OUString::number(nHandle), nullptr);
+ case PROPERTY_ID_FETCHDIRECTION:
+ break;
+ case PROPERTY_ID_FETCHSIZE:
+ break;
+ default:;
+ }
+}
+
+void OPreparedResultSet::getFastPropertyValue(Any& _rValue, sal_Int32 nHandle) const
+{
+ switch (nHandle)
+ {
+ case PROPERTY_ID_ISBOOKMARKABLE:
+ _rValue <<= false;
+ break;
+ case PROPERTY_ID_CURSORNAME:
+ break;
+ case PROPERTY_ID_RESULTSETCONCURRENCY:
+ _rValue <<= ResultSetConcurrency::READ_ONLY;
+ break;
+ case PROPERTY_ID_RESULTSETTYPE:
+ _rValue <<= ResultSetType::SCROLL_INSENSITIVE;
+ break;
+ case PROPERTY_ID_FETCHDIRECTION:
+ _rValue <<= FetchDirection::FORWARD;
+ break;
+ case PROPERTY_ID_FETCHSIZE:
+ _rValue <<= sal_Int32(50);
+ break;
+ ;
+ default:;
+ }
+}
+
+void SAL_CALL OPreparedResultSet::acquire() throw() { OPreparedResultSet_BASE::acquire(); }
+
+void SAL_CALL OPreparedResultSet::release() throw() { OPreparedResultSet_BASE::release(); }
+
+css::uno::Reference<css::beans::XPropertySetInfo> SAL_CALL OPreparedResultSet::getPropertySetInfo()
+{
+ return ::cppu::OPropertySetHelper::createPropertySetInfo(getInfoHelper());
+}
+
+void OPreparedResultSet::checkColumnIndex(sal_Int32 index)
+{
+ if (index < 1 || index > static_cast<int>(m_nFieldCount))
+ {
+ /* static object for efficiency or thread safety is a problem ? */
+ throw SQLException("index out of range", *this, rtl::OUString(), 1, Any());
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/mysqlc/mysqlc_prepared_resultset.hxx b/connectivity/source/drivers/mysqlc/mysqlc_prepared_resultset.hxx
new file mode 100644
index 000000000000..5cbb37f5bd6d
--- /dev/null
+++ b/connectivity/source/drivers/mysqlc/mysqlc_prepared_resultset.hxx
@@ -0,0 +1,248 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef INCLUDED_MYSQLC_SOURCE_MYSQLC_RESULTSET_HXX
+#define INCLUDED_MYSQLC_SOURCE_MYSQLC_RESULTSET_HXX
+
+#include "mysqlc_preparedstatement.hxx"
+#include "mysqlc_statement.hxx"
+#include "mysqlc_subcomponent.hxx"
+#include "mysqlc_connection.hxx"
+
+#include <com/sun/star/sdbc/XCloseable.hpp>
+#include <com/sun/star/sdbc/XColumnLocate.hpp>
+#include <com/sun/star/sdbc/XResultSet.hpp>
+#include <com/sun/star/sdbc/XResultSetMetaDataSupplier.hpp>
+#include <com/sun/star/sdbc/XResultSetUpdate.hpp>
+#include <com/sun/star/sdbc/XRow.hpp>
+#include <com/sun/star/sdbc/XRowUpdate.hpp>
+#include <com/sun/star/sdbc/XWarningsSupplier.hpp>
+#include <com/sun/star/sdbcx/XDeleteRows.hpp>
+#include <com/sun/star/sdbcx/XRowLocate.hpp>
+#include <com/sun/star/util/XCancellable.hpp>
+
+#include <cppuhelper/compbase12.hxx>
+
+namespace connectivity
+{
+namespace mysqlc
+{
+using ::com::sun::star::sdbc::SQLException;
+using ::com::sun::star::uno::Any;
+using ::com::sun::star::uno::RuntimeException;
+
+typedef ::cppu::WeakComponentImplHelper12<
+ css::sdbc::XResultSet, css::sdbc::XRow, css::sdbc::XResultSetMetaDataSupplier,
+ css::util::XCancellable, css::sdbc::XWarningsSupplier, css::sdbc::XResultSetUpdate,
+ css::sdbc::XRowUpdate, css::sdbcx::XRowLocate, css::sdbcx::XDeleteRows, css::sdbc::XCloseable,
+ css::sdbc::XColumnLocate, css::lang::XServiceInfo>
+ OPreparedResultSet_BASE;
+
+class OPreparedResultSet final : public OBase_Mutex,
+ public OPreparedResultSet_BASE,
+ public ::cppu::OPropertySetHelper,
+ public OPropertyArrayUsageHelper<OPreparedResultSet>
+{
+ OConnection& m_rConnection;
+ css::uno::WeakReferenceHelper m_aStatement;
+ css::uno::Reference<css::sdbc::XResultSetMetaData> m_xMetaData;
+ MYSQL_RES* m_pResult;
+ MYSQL_STMT* m_pStmt;
+ rtl_TextEncoding m_encoding;
+ sal_Int32 m_nCurrentField = 0;
+ sal_Int32 m_nFieldCount;
+
+ // Use c style arrays, because we have to work with pointers
+ // on these.
+ MYSQL_BIND* m_aData = nullptr;
+ MYSQL_FIELD* m_aFields = nullptr;
+ BindMetaData* m_aMetaData = nullptr;
+
+ bool m_bWasNull = false;
+
+ // OPropertyArrayUsageHelper
+ ::cppu::IPropertyArrayHelper* createArrayHelper() const SAL_OVERRIDE;
+ // OPropertySetHelper
+ ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper() SAL_OVERRIDE;
+
+ sal_Bool SAL_CALL convertFastPropertyValue(Any& rConvertedValue, Any& rOldValue,
+ sal_Int32 nHandle, const Any& rValue) SAL_OVERRIDE;
+
+ void SAL_CALL setFastPropertyValue_NoBroadcast(sal_Int32 nHandle,
+ const Any& rValue) SAL_OVERRIDE;
+
+ void SAL_CALL getFastPropertyValue(Any& rValue, sal_Int32 nHandle) const SAL_OVERRIDE;
+
+ // you can't delete objects of this type
+ virtual ~OPreparedResultSet() override;
+
+public:
+ virtual rtl::OUString SAL_CALL getImplementationName() SAL_OVERRIDE;
+
+ virtual sal_Bool SAL_CALL supportsService(rtl::OUString const& ServiceName) SAL_OVERRIDE;
+
+ virtual css::uno::Sequence<rtl::OUString> SAL_CALL getSupportedServiceNames() SAL_OVERRIDE;
+
+ OPreparedResultSet(OConnection& rConn, OPreparedStatement* pStmt, MYSQL_STMT* pMyStmt);
+
+ // ::cppu::OComponentHelper
+ void SAL_CALL disposing() SAL_OVERRIDE;
+
+ // XInterface
+ Any SAL_CALL queryInterface(const css::uno::Type& rType) SAL_OVERRIDE;
+
+ void SAL_CALL acquire() throw() SAL_OVERRIDE;
+ void SAL_CALL release() throw() SAL_OVERRIDE;
+
+ //XTypeProvider
+ css::uno::Sequence<css::uno::Type> SAL_CALL getTypes() SAL_OVERRIDE;
+
+ // XPropertySet
+ css::uno::Reference<css::beans::XPropertySetInfo> SAL_CALL getPropertySetInfo() SAL_OVERRIDE;
+
+ // XResultSet
+ sal_Bool SAL_CALL next() SAL_OVERRIDE;
+ sal_Bool SAL_CALL isBeforeFirst() SAL_OVERRIDE;
+ sal_Bool SAL_CALL isAfterLast() SAL_OVERRIDE;
+ sal_Bool SAL_CALL isFirst() SAL_OVERRIDE;
+ sal_Bool SAL_CALL isLast() SAL_OVERRIDE;
+
+ void SAL_CALL beforeFirst() SAL_OVERRIDE;
+ void SAL_CALL afterLast() SAL_OVERRIDE;
+
+ sal_Bool SAL_CALL first() SAL_OVERRIDE;
+ sal_Bool SAL_CALL last() SAL_OVERRIDE;
+
+ sal_Int32 SAL_CALL getRow() SAL_OVERRIDE;
+
+ sal_Bool SAL_CALL absolute(sal_Int32 row) SAL_OVERRIDE;
+ sal_Bool SAL_CALL relative(sal_Int32 rows) SAL_OVERRIDE;
+ sal_Bool SAL_CALL previous() SAL_OVERRIDE;
+
+ void SAL_CALL refreshRow() SAL_OVERRIDE;
+
+ sal_Bool SAL_CALL rowUpdated() SAL_OVERRIDE;
+ sal_Bool SAL_CALL rowInserted() SAL_OVERRIDE;
+ sal_Bool SAL_CALL rowDeleted() SAL_OVERRIDE;
+
+ css::uno::Reference<css::uno::XInterface> SAL_CALL getStatement() SAL_OVERRIDE;
+ // XRow
+ sal_Bool SAL_CALL wasNull() SAL_OVERRIDE;
+
+ rtl::OUString SAL_CALL getString(sal_Int32 column) SAL_OVERRIDE;
+
+ sal_Bool SAL_CALL getBoolean(sal_Int32 column) SAL_OVERRIDE;
+ sal_Int8 SAL_CALL getByte(sal_Int32 column) SAL_OVERRIDE;
+ sal_Int16 SAL_CALL getShort(sal_Int32 column) SAL_OVERRIDE;
+ sal_Int32 SAL_CALL getInt(sal_Int32 column) SAL_OVERRIDE;
+ sal_Int64 SAL_CALL getLong(sal_Int32 column) SAL_OVERRIDE;
+
+ float SAL_CALL getFloat(sal_Int32 column) SAL_OVERRIDE;
+ double SAL_CALL getDouble(sal_Int32 column) SAL_OVERRIDE;
+
+ css::uno::Sequence<sal_Int8> SAL_CALL getBytes(sal_Int32 column) SAL_OVERRIDE;
+ css::util::Date SAL_CALL getDate(sal_Int32 column) SAL_OVERRIDE;
+ css::util::Time SAL_CALL getTime(sal_Int32 column) SAL_OVERRIDE;
+ css::util::DateTime SAL_CALL getTimestamp(sal_Int32 column) SAL_OVERRIDE;
+
+ css::uno::Reference<css::io::XInputStream>
+ SAL_CALL getBinaryStream(sal_Int32 column) SAL_OVERRIDE;
+ css::uno::Reference<css::io::XInputStream>
+ SAL_CALL getCharacterStream(sal_Int32 column) SAL_OVERRIDE;
+
+ Any SAL_CALL getObject(sal_Int32 column, const my_XNameAccessRef& typeMap) SAL_OVERRIDE;
+
+ css::uno::Reference<css::sdbc::XRef> SAL_CALL getRef(sal_Int32 column) SAL_OVERRIDE;
+ css::uno::Reference<css::sdbc::XBlob> SAL_CALL getBlob(sal_Int32 column) SAL_OVERRIDE;
+ css::uno::Reference<css::sdbc::XClob> SAL_CALL getClob(sal_Int32 column) SAL_OVERRIDE;
+ css::uno::Reference<css::sdbc::XArray> SAL_CALL getArray(sal_Int32 column) SAL_OVERRIDE;
+
+ // XResultSetMetaDataSupplier
+ css::uno::Reference<css::sdbc::XResultSetMetaData> SAL_CALL getMetaData() SAL_OVERRIDE;
+
+ // XCancellable
+ void SAL_CALL cancel() SAL_OVERRIDE;
+
+ // XCloseable
+ void SAL_CALL close() SAL_OVERRIDE;
+
+ // XWarningsSupplier
+ Any SAL_CALL getWarnings() SAL_OVERRIDE;
+
+ void SAL_CALL clearWarnings() SAL_OVERRIDE;
+
+ // XResultSetUpdate
+ void SAL_CALL insertRow() SAL_OVERRIDE;
+ void SAL_CALL updateRow() SAL_OVERRIDE;
+ void SAL_CALL deleteRow() SAL_OVERRIDE;
+ void SAL_CALL cancelRowUpdates() SAL_OVERRIDE;
+ void SAL_CALL moveToInsertRow() SAL_OVERRIDE;
+ void SAL_CALL moveToCurrentRow() SAL_OVERRIDE;
+
+ // XRowUpdate
+ void SAL_CALL updateNull(sal_Int32 column) SAL_OVERRIDE;
+ void SAL_CALL updateBoolean(sal_Int32 column, sal_Bool x) SAL_OVERRIDE;
+ void SAL_CALL updateByte(sal_Int32 column, sal_Int8 x) SAL_OVERRIDE;
+ void SAL_CALL updateShort(sal_Int32 column, sal_Int16 x) SAL_OVERRIDE;
+ void SAL_CALL updateInt(sal_Int32 column, sal_Int32 x) SAL_OVERRIDE;
+ void SAL_CALL updateLong(sal_Int32 column, sal_Int64 x) SAL_OVERRIDE;
+ void SAL_CALL updateFloat(sal_Int32 column, float x) SAL_OVERRIDE;
+ void SAL_CALL updateDouble(sal_Int32 column, double x) SAL_OVERRIDE;
+ void SAL_CALL updateString(sal_Int32 column, const rtl::OUString& x) SAL_OVERRIDE;
+ void SAL_CALL updateBytes(sal_Int32 column, const css::uno::Sequence<sal_Int8>& x) SAL_OVERRIDE;
+ void SAL_CALL updateDate(sal_Int32 column, const css::util::Date& x) SAL_OVERRIDE;
+ void SAL_CALL updateTime(sal_Int32 column, const css::util::Time& x) SAL_OVERRIDE;
+ void SAL_CALL updateTimestamp(sal_Int32 column, const css::util::DateTime& x) SAL_OVERRIDE;
+ void SAL_CALL updateBinaryStream(sal_Int32 column,
+ const css::uno::Reference<css::io::XInputStream>& x,
+ sal_Int32 length) SAL_OVERRIDE;
+ void SAL_CALL updateCharacterStream(sal_Int32 column,
+ const css::uno::Reference<css::io::XInputStream>& x,
+ sal_Int32 length) SAL_OVERRIDE;
+ void SAL_CALL updateObject(sal_Int32 column, const Any& x) SAL_OVERRIDE;
+ void SAL_CALL updateNumericObject(sal_Int32 column, const Any& x, sal_Int32 scale) SAL_OVERRIDE;
+
+ // XColumnLocate
+ sal_Int32 SAL_CALL findColumn(const rtl::OUString& columnName) SAL_OVERRIDE;
+
+ // XRowLocate
+ Any SAL_CALL getBookmark() SAL_OVERRIDE;
+
+ sal_Bool SAL_CALL moveToBookmark(const Any& bookmark) SAL_OVERRIDE;
+ sal_Bool SAL_CALL moveRelativeToBookmark(const Any& bookmark, sal_Int32 rows) SAL_OVERRIDE;
+ sal_Int32 SAL_CALL compareBookmarks(const Any& first, const Any& second) SAL_OVERRIDE;
+ sal_Bool SAL_CALL hasOrderedBookmarks() SAL_OVERRIDE;
+ sal_Int32 SAL_CALL hashBookmark(const Any& bookmark) SAL_OVERRIDE;
+
+ // XDeleteRows
+ css::uno::Sequence<sal_Int32>
+ SAL_CALL deleteRows(const css::uno::Sequence<Any>& rows) SAL_OVERRIDE;
+
+ /// @throws SQLException
+ /// @throws RuntimeException
+ void checkColumnIndex(sal_Int32 index);
+
+private:
+ using ::cppu::OPropertySetHelper::getFastPropertyValue;
+};
+} /* mysqlc */
+} /* connectivity */
+#endif // CONNECTIVITY_SRESULTSET_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/mysqlc/mysqlc_preparedstatement.cxx b/connectivity/source/drivers/mysqlc/mysqlc_preparedstatement.cxx
new file mode 100644
index 000000000000..d26eacb7ba7c
--- /dev/null
+++ b/connectivity/source/drivers/mysqlc/mysqlc_preparedstatement.cxx
@@ -0,0 +1,595 @@
+/* -*- 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 "mysqlc_general.hxx"
+#include "mysqlc_prepared_resultset.hxx"
+#include "mysqlc_preparedstatement.hxx"
+#include "mysqlc_propertyids.hxx"
+#include "mysqlc_resultsetmetadata.hxx"
+
+#include <boost/config.hpp>
+#include <com/sun/star/lang/DisposedException.hpp>
+#include <com/sun/star/sdbc/DataType.hpp>
+#include <cppuhelper/typeprovider.hxx>
+
+#include <stdio.h>
+
+#ifdef _MSC_VER
+#define snprintf _snprintf
+#endif
+
+using namespace connectivity::mysqlc;
+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;
+using ::osl::MutexGuard;
+
+rtl::OUString OPreparedStatement::getImplementationName()
+{
+ return rtl::OUString("com.sun.star.sdbcx.mysqlc.PreparedStatement");
+}
+
+css::uno::Sequence<rtl::OUString> OPreparedStatement::getSupportedServiceNames()
+{
+ css::uno::Sequence<rtl::OUString> s(1);
+ s[0] = "com.sun.star.sdbc.PreparedStatement";
+ return s;
+}
+
+sal_Bool OPreparedStatement::supportsService(rtl::OUString const& ServiceName)
+{
+ return cppu::supportsService(this, ServiceName);
+}
+
+OPreparedStatement::OPreparedStatement(OConnection* _pConnection, MYSQL_STMT* pStmt)
+ : OCommonStatement(_pConnection)
+ , m_pStmt(pStmt)
+{
+ m_paramCount = mysql_stmt_param_count(m_pStmt);
+ m_binds.reserve(m_paramCount);
+ m_bindMetas.reserve(m_paramCount);
+ for (unsigned i = 0; i < m_paramCount; ++i)
+ {
+ MYSQL_BIND bind;
+ memset(&bind, 0, sizeof(MYSQL_BIND));
+ m_binds.push_back(bind);
+ m_bindMetas.push_back(BindMetaData{});
+ m_binds.back().is_null = &m_bindMetas.back().is_null;
+ m_binds.back().length = &m_bindMetas.back().length;
+ m_binds.back().buffer = nullptr;
+ }
+}
+
+OPreparedStatement::~OPreparedStatement() {}
+
+void SAL_CALL OPreparedStatement::acquire() throw() { OCommonStatement::acquire(); }
+
+void SAL_CALL OPreparedStatement::release() throw() { OCommonStatement::release(); }
+
+Any SAL_CALL OPreparedStatement::queryInterface(const Type& rType)
+{
+ Any aRet = OCommonStatement::queryInterface(rType);
+ if (!aRet.hasValue())
+ {
+ aRet = OPreparedStatement_BASE::queryInterface(rType);
+ }
+ return aRet;
+}
+
+Sequence<Type> SAL_CALL OPreparedStatement::getTypes()
+{
+ return concatSequences(OPreparedStatement_BASE::getTypes(), OCommonStatement::getTypes());
+}
+
+Reference<XResultSetMetaData> SAL_CALL OPreparedStatement::getMetaData()
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OPreparedStatement::rBHelper.bDisposed);
+
+ if (!m_xMetaData.is())
+ {
+ MYSQL_RES* pRes = mysql_stmt_result_metadata(m_pStmt);
+ // TODO warning or error if no meta data.
+ m_xMetaData = new OResultSetMetaData(*m_xConnection.get(), pRes,
+ getOwnConnection()->getConnectionEncoding());
+ }
+ return m_xMetaData;
+}
+
+void SAL_CALL OPreparedStatement::close()
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OPreparedStatement::rBHelper.bDisposed);
+
+ if (mysql_stmt_close(m_pStmt))
+ {
+ SAL_WARN("connectivity", "failed to close mysql prepared statement");
+ }
+ m_pStmt = nullptr; // it's deallocated already
+ clearWarnings();
+ clearParameters();
+ OCommonStatement::close();
+}
+
+sal_Bool SAL_CALL OPreparedStatement::execute()
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OPreparedStatement::rBHelper.bDisposed);
+
+ if (!m_binds.empty() && mysql_stmt_bind_param(m_pStmt, m_binds.data()))
+ {
+ MYSQL* pMysql = m_xConnection.get()->getMysqlConnection();
+ mysqlc_sdbc_driver::throwSQLExceptionWithMsg(mysql_stmt_error(m_pStmt), mysql_errno(pMysql),
+ *this,
+ m_xConnection.get()->getConnectionEncoding());
+ }
+
+ int nFail = mysql_stmt_execute(m_pStmt);
+ if (nFail != 0)
+ {
+ MYSQL* pMysql = m_xConnection.get()->getMysqlConnection();
+ mysqlc_sdbc_driver::throwSQLExceptionWithMsg(mysql_stmt_error(m_pStmt), mysql_errno(pMysql),
+ *this,
+ m_xConnection.get()->getConnectionEncoding());
+ }
+
+ return !nFail;
+}
+
+sal_Int32 SAL_CALL OPreparedStatement::executeUpdate()
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OPreparedStatement::rBHelper.bDisposed);
+
+ if (!m_binds.empty() && mysql_stmt_bind_param(m_pStmt, m_binds.data()))
+ {
+ MYSQL* pMysql = m_xConnection.get()->getMysqlConnection();
+ mysqlc_sdbc_driver::throwSQLExceptionWithMsg(mysql_stmt_error(m_pStmt), mysql_errno(pMysql),
+ *this,
+ m_xConnection.get()->getConnectionEncoding());
+ }
+
+ int nFail = mysql_stmt_execute(m_pStmt);
+
+ if (nFail != 0)
+ {
+ MYSQL* pMysql = m_xConnection.get()->getMysqlConnection();
+ mysqlc_sdbc_driver::throwSQLExceptionWithMsg(mysql_stmt_error(m_pStmt), mysql_errno(pMysql),
+ *this,
+ m_xConnection.get()->getConnectionEncoding());
+ }
+
+ sal_Int32 affectedRows = mysql_stmt_affected_rows(m_pStmt);
+ return affectedRows;
+}
+
+void SAL_CALL OPreparedStatement::setString(sal_Int32 parameter, const rtl::OUString& x)
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OPreparedStatement::rBHelper.bDisposed);
+ checkParameterIndex(parameter);
+
+ rtl::OString stringie(rtl::OUStringToOString(x, m_xConnection->getConnectionEncoding()));
+ const sal_Int32 nIndex = parameter - 1;
+ m_binds[nIndex].buffer_type = MYSQL_TYPE_STRING;
+ mysqlc_sdbc_driver::resetSqlVar(&m_binds[nIndex].buffer, stringie.getStr(), MYSQL_TYPE_STRING,
+ stringie.getLength());
+ m_bindMetas[nIndex].is_null = 0;
+ m_bindMetas[nIndex].length = stringie.getLength();
+}
+
+Reference<XConnection> SAL_CALL OPreparedStatement::getConnection()
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OPreparedStatement::rBHelper.bDisposed);
+
+ return m_xConnection.get();
+}
+
+Reference<XResultSet> SAL_CALL OPreparedStatement::executeQuery()
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OPreparedStatement::rBHelper.bDisposed);
+
+ if (!m_binds.empty() && mysql_stmt_bind_param(m_pStmt, m_binds.data()))
+ {
+ MYSQL* pMysql = m_xConnection.get()->getMysqlConnection();
+ mysqlc_sdbc_driver::throwSQLExceptionWithMsg(mysql_stmt_error(m_pStmt), mysql_errno(pMysql),
+ *this,
+ m_xConnection.get()->getConnectionEncoding());
+ }
+
+ int nFail = mysql_stmt_execute(m_pStmt);
+
+ if (nFail != 0)
+ {
+ MYSQL* pMysql = m_xConnection.get()->getMysqlConnection();
+ mysqlc_sdbc_driver::throwSQLExceptionWithMsg(mysql_stmt_error(m_pStmt), mysql_errno(pMysql),
+ *this,
+ m_xConnection.get()->getConnectionEncoding());
+ }
+
+ Reference<XResultSet> xResultSet;
+ xResultSet = new OPreparedResultSet(*m_xConnection.get(), this, m_pStmt);
+ return xResultSet;
+}
+
+void SAL_CALL OPreparedStatement::setBoolean(sal_Int32 parameter, sal_Bool x)
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OPreparedStatement::rBHelper.bDisposed);
+ checkParameterIndex(parameter);
+
+ const sal_Int32 nIndex = parameter - 1;
+ m_binds[nIndex].buffer_type = MYSQL_TYPE_TINY;
+ mysqlc_sdbc_driver::resetSqlVar(&m_binds[nIndex].buffer, &x, MYSQL_TYPE_TINY);
+ m_bindMetas[nIndex].is_null = 0;
+}
+
+void SAL_CALL OPreparedStatement::setByte(sal_Int32 parameter, sal_Int8 x)
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OPreparedStatement::rBHelper.bDisposed);
+ checkParameterIndex(parameter);
+
+ const sal_Int32 nIndex = parameter - 1;
+ m_binds[nIndex].buffer_type = MYSQL_TYPE_TINY;
+ mysqlc_sdbc_driver::resetSqlVar(&m_binds[nIndex].buffer, &x, MYSQL_TYPE_TINY);
+ m_bindMetas[nIndex].is_null = 0;
+}
+
+void SAL_CALL OPreparedStatement::setDate(sal_Int32 parameter, const Date& aData)
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OPreparedStatement::rBHelper.bDisposed);
+ checkParameterIndex(parameter);
+
+ MYSQL_TIME my_time;
+
+ my_time.year = aData.Year;
+ my_time.month = aData.Month;
+ my_time.day = aData.Day;
+
+ const sal_Int32 nIndex = parameter - 1;
+ m_binds[nIndex].buffer_type = MYSQL_TYPE_DATE;
+ mysqlc_sdbc_driver::resetSqlVar(&m_binds[nIndex].buffer, &my_time, MYSQL_TYPE_DATE);
+ m_bindMetas[nIndex].is_null = 0;
+}
+
+void SAL_CALL OPreparedStatement::setTime(sal_Int32 parameter, const Time& aVal)
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OPreparedStatement::rBHelper.bDisposed);
+ checkParameterIndex(parameter);
+
+ MYSQL_TIME my_time;
+
+ my_time.hour = aVal.Hours;
+ my_time.minute = aVal.Minutes;
+ my_time.second = aVal.Seconds;
+
+ const sal_Int32 nIndex = parameter - 1;
+ m_binds[nIndex].buffer_type = MYSQL_TYPE_TIME;
+ mysqlc_sdbc_driver::resetSqlVar(&m_binds[nIndex].buffer, &my_time, MYSQL_TYPE_TIME);
+ m_bindMetas[nIndex].is_null = 0;
+}
+
+void SAL_CALL OPreparedStatement::setTimestamp(sal_Int32 parameter, const DateTime& aVal)
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OPreparedStatement::rBHelper.bDisposed);
+ checkParameterIndex(parameter);
+
+ MYSQL_TIME my_time;
+
+ my_time.hour = aVal.Hours;
+ my_time.minute = aVal.Minutes;
+ my_time.second = aVal.Seconds;
+ my_time.year = aVal.Year;
+ my_time.month = aVal.Month;
+ my_time.day = aVal.Day;
+
+ const sal_Int32 nIndex = parameter - 1;
+ m_binds[nIndex].buffer_type = MYSQL_TYPE_TIME;
+ mysqlc_sdbc_driver::resetSqlVar(&m_binds[nIndex].buffer, &my_time, MYSQL_TYPE_DATETIME);
+ m_bindMetas[nIndex].is_null = 0;
+}
+
+void SAL_CALL OPreparedStatement::setDouble(sal_Int32 parameter, double x)
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OPreparedStatement::rBHelper.bDisposed);
+ checkParameterIndex(parameter);
+
+ const sal_Int32 nIndex = parameter - 1;
+ m_binds[nIndex].buffer_type = MYSQL_TYPE_DOUBLE;
+ mysqlc_sdbc_driver::resetSqlVar(&m_binds[nIndex].buffer, &x, MYSQL_TYPE_DOUBLE);
+ m_bindMetas[nIndex].is_null = 0;
+}
+
+void SAL_CALL OPreparedStatement::setFloat(sal_Int32 parameter, float x)
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OPreparedStatement::rBHelper.bDisposed);
+ checkParameterIndex(parameter);
+
+ const sal_Int32 nIndex = parameter - 1;
+ m_binds[nIndex].buffer_type = MYSQL_TYPE_FLOAT;
+ mysqlc_sdbc_driver::resetSqlVar(&m_binds[nIndex].buffer, &x, MYSQL_TYPE_FLOAT);
+ m_bindMetas[nIndex].is_null = 0;
+}
+
+void SAL_CALL OPreparedStatement::setInt(sal_Int32 parameter, sal_Int32 x)
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OPreparedStatement::rBHelper.bDisposed);
+ checkParameterIndex(parameter);
+
+ const sal_Int32 nIndex = parameter - 1;
+ m_binds[nIndex].buffer_type = MYSQL_TYPE_LONG;
+ mysqlc_sdbc_driver::resetSqlVar(&m_binds[nIndex].buffer, &x, MYSQL_TYPE_LONG);
+ m_bindMetas[nIndex].is_null = 0;
+}
+
+void SAL_CALL OPreparedStatement::setLong(sal_Int32 parameter, sal_Int64 aVal)
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OPreparedStatement::rBHelper.bDisposed);
+ checkParameterIndex(parameter);
+
+ const sal_Int32 nIndex = parameter - 1;
+ m_binds[nIndex].buffer_type = MYSQL_TYPE_LONGLONG;
+ mysqlc_sdbc_driver::resetSqlVar(&m_binds[nIndex].buffer, &aVal, MYSQL_TYPE_LONGLONG);
+ m_bindMetas[nIndex].is_null = 0;
+}
+
+void SAL_CALL OPreparedStatement::setNull(sal_Int32 parameter, sal_Int32 /*sqlType*/)
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OPreparedStatement::rBHelper.bDisposed);
+ checkParameterIndex(parameter);
+
+ const sal_Int32 nIndex = parameter - 1;
+ m_bindMetas[nIndex].is_null = 1;
+ free(m_binds[nIndex].buffer);
+ m_binds[nIndex].buffer = nullptr;
+}
+
+void SAL_CALL OPreparedStatement::setClob(sal_Int32 parameter, const Reference<XClob>& /* x */)
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OPreparedStatement::rBHelper.bDisposed);
+ checkParameterIndex(parameter);
+
+ mysqlc_sdbc_driver::throwFeatureNotImplementedException("OPreparedStatement::setClob", *this);
+}
+
+void SAL_CALL OPreparedStatement::setBlob(sal_Int32 parameter, const Reference<XBlob>& /* x */)
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OPreparedStatement::rBHelper.bDisposed);
+ checkParameterIndex(parameter);
+
+ mysqlc_sdbc_driver::throwFeatureNotImplementedException("OPreparedStatement::setBlob", *this);
+}
+
+void SAL_CALL OPreparedStatement::setArray(sal_Int32 parameter, const Reference<XArray>& /* x */)
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OPreparedStatement::rBHelper.bDisposed);
+ checkParameterIndex(parameter);
+
+ mysqlc_sdbc_driver::throwFeatureNotImplementedException("OPreparedStatement::setArray", *this);
+}
+
+void SAL_CALL OPreparedStatement::setRef(sal_Int32 parameter, const Reference<XRef>& /* x */)
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OPreparedStatement::rBHelper.bDisposed);
+ checkParameterIndex(parameter);
+
+ mysqlc_sdbc_driver::throwFeatureNotImplementedException("OPreparedStatement::setRef", *this);
+}
+
+void SAL_CALL OPreparedStatement::setObjectWithInfo(sal_Int32 parameterIndex, const Any& value,
+ sal_Int32 targetSqlType, sal_Int32 /* scale */)
+{
+ checkDisposed(OPreparedStatement::rBHelper.bDisposed);
+ MutexGuard aGuard(m_aMutex);
+ checkParameterIndex(parameterIndex);
+
+ const sal_Int32 nIndex = parameterIndex - 1;
+ if (!value.hasValue())
+ {
+ free(m_binds[nIndex].buffer);
+ m_binds[nIndex].buffer = nullptr;
+ m_bindMetas[parameterIndex - 1].is_null = 1;
+ return;
+ }
+
+ switch (targetSqlType)
+ {
+ case DataType::DECIMAL:
+ case DataType::NUMERIC:
+ {
+ double nValue(0.0);
+ rtl::OUString sValue;
+ if (value >>= nValue)
+ {
+ setDouble(parameterIndex, nValue);
+ break;
+ }
+ else if (value >>= sValue)
+ {
+ rtl::OString sAscii
+ = rtl::OUStringToOString(sValue, getOwnConnection()->getConnectionEncoding());
+ std::stringstream sStream{ sAscii.getStr() };
+ sStream >> nValue;
+ m_binds[nIndex].buffer_type = MYSQL_TYPE_DOUBLE;
+ mysqlc_sdbc_driver::resetSqlVar(&m_binds[nIndex].buffer, &nValue, MYSQL_TYPE_DOUBLE,
+ sValue.getLength());
+ m_bindMetas[nIndex].is_null = 0;
+ break;
+ }
+
+#if defined __GNUC__ && __GNUC__ >= 7
+ [[fallthrough]];
+#else
+ BOOST_FALLTHROUGH;
+#endif
+ }
+
+ // TODO other types
+
+ default:
+ mysqlc_sdbc_driver::throwInvalidArgumentException(
+ "OPreparedStatement::setObjectWithInfo", *this);
+ break;
+ }
+}
+
+void SAL_CALL OPreparedStatement::setObjectNull(sal_Int32 parameter, sal_Int32 /* sqlType */,
+ const rtl::OUString& /* typeName */)
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OPreparedStatement::rBHelper.bDisposed);
+ checkParameterIndex(parameter);
+
+ mysqlc_sdbc_driver::throwFeatureNotImplementedException("OPreparedStatement::setObjectNull",
+ *this);
+}
+
+void SAL_CALL OPreparedStatement::setObject(sal_Int32 parameter, const Any& /* x */)
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OPreparedStatement::rBHelper.bDisposed);
+ checkParameterIndex(parameter);
+
+ mysqlc_sdbc_driver::throwFeatureNotImplementedException("OPreparedStatement::setObject", *this);
+}
+
+void SAL_CALL OPreparedStatement::setShort(sal_Int32 parameter, sal_Int16 x)
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OPreparedStatement::rBHelper.bDisposed);
+ checkParameterIndex(parameter);
+
+ const sal_Int32 nIndex = parameter - 1;
+ m_binds[nIndex].buffer_type = MYSQL_TYPE_SHORT;
+ mysqlc_sdbc_driver::resetSqlVar(&m_binds[nIndex].buffer, &x, MYSQL_TYPE_SHORT);
+ m_bindMetas[nIndex].is_null = 0;
+}
+
+void SAL_CALL OPreparedStatement::setBytes(sal_Int32 parameter, const Sequence<sal_Int8>& x)
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OPreparedStatement::rBHelper.bDisposed);
+ checkParameterIndex(parameter);
+
+ const sal_Int32 nIndex = parameter - 1;
+ m_binds[nIndex].buffer_type = MYSQL_TYPE_BLOB; // FIXME
+ mysqlc_sdbc_driver::resetSqlVar(&m_binds[nIndex].buffer, &x, MYSQL_TYPE_BLOB);
+ m_bindMetas[nIndex].is_null = 0;
+}
+
+void SAL_CALL OPreparedStatement::setCharacterStream(sal_Int32 parameter,
+ const Reference<XInputStream>& /* x */,
+ sal_Int32 /* length */)
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OPreparedStatement::rBHelper.bDisposed);
+ checkParameterIndex(parameter);
+
+ mysqlc_sdbc_driver::throwFeatureNotImplementedException(
+ "OPreparedStatement::setCharacterStream", *this);
+}
+
+void SAL_CALL OPreparedStatement::setBinaryStream(sal_Int32 parameter,
+ const Reference<XInputStream>& /* x */,
+ sal_Int32 /* length */)
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OPreparedStatement::rBHelper.bDisposed);
+ checkParameterIndex(parameter);
+
+ mysqlc_sdbc_driver::throwFeatureNotImplementedException("OPreparedStatement::setBinaryStream",
+ *this);
+}
+
+void SAL_CALL OPreparedStatement::clearParameters()
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OPreparedStatement::rBHelper.bDisposed);
+
+ for (size_t i = 0; i < m_binds.size(); ++i)
+ {
+ m_bindMetas[i].is_null = 1;
+ free(m_binds[i].buffer);
+ m_binds[i].buffer = nullptr;
+ }
+}
+
+void SAL_CALL OPreparedStatement::clearBatch()
+{
+ mysqlc_sdbc_driver::throwFeatureNotImplementedException("OPreparedStatement::clearBatch",
+ *this);
+}
+
+void SAL_CALL OPreparedStatement::addBatch()
+{
+ mysqlc_sdbc_driver::throwFeatureNotImplementedException("OPreparedStatement::addBatch", *this);
+}
+
+Sequence<sal_Int32> SAL_CALL OPreparedStatement::executeBatch()
+{
+ Sequence<sal_Int32> aRet = Sequence<sal_Int32>();
+ return aRet;
+}
+
+void OPreparedStatement::setFastPropertyValue_NoBroadcast(sal_Int32 nHandle, const Any& rValue)
+{
+ switch (nHandle)
+ {
+ case PROPERTY_ID_RESULTSETCONCURRENCY:
+ break;
+ case PROPERTY_ID_RESULTSETTYPE:
+ break;
+ case PROPERTY_ID_FETCHDIRECTION:
+ break;
+ case PROPERTY_ID_USEBOOKMARKS:
+ break;
+ default:
+ /* XXX: Recursion ?? */
+ OPreparedStatement::setFastPropertyValue_NoBroadcast(nHandle, rValue);
+ }
+}
+
+void OPreparedStatement::checkParameterIndex(sal_Int32 column)
+{
+ if (column < 1 || column > static_cast<sal_Int32>(m_paramCount))
+ {
+ throw SQLException("Parameter index out of range", *this, rtl::OUString(), 1, Any());
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/mysqlc/mysqlc_preparedstatement.hxx b/connectivity/source/drivers/mysqlc/mysqlc_preparedstatement.hxx
new file mode 100644
index 000000000000..d8179e0ee43d
--- /dev/null
+++ b/connectivity/source/drivers/mysqlc/mysqlc_preparedstatement.hxx
@@ -0,0 +1,161 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef INCLUDED_MYSQLC_SOURCE_MYSQLC_PREPAREDSTATEMENT_HXX
+#define INCLUDED_MYSQLC_SOURCE_MYSQLC_PREPAREDSTATEMENT_HXX
+#include "mysqlc_statement.hxx"
+#include "mysqlc_resultset.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>
+
+namespace connectivity
+{
+namespace mysqlc
+{
+using ::com::sun::star::sdbc::SQLException;
+using ::com::sun::star::sdbc::XResultSetMetaData;
+using ::com::sun::star::uno::Any;
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::RuntimeException;
+using ::com::sun::star::uno::Type;
+
+struct BindMetaData
+{
+ char is_null = 0;
+ unsigned long length = 0;
+ char error = 0;
+};
+
+typedef ::cppu::ImplHelper5<css::sdbc::XPreparedStatement, css::sdbc::XParameters,
+ css::sdbc::XPreparedBatchExecution,
+ css::sdbc::XResultSetMetaDataSupplier, css::lang::XServiceInfo>
+ OPreparedStatement_BASE;
+
+class OPreparedStatement final : public OCommonStatement, public OPreparedStatement_BASE
+{
+ unsigned int m_paramCount = 0; // number of placeholders
+ Reference<XResultSetMetaData> m_xMetaData;
+ MYSQL_STMT* m_pStmt;
+ std::vector<MYSQL_BIND> m_binds;
+ std::vector<BindMetaData> m_bindMetas;
+
+ void checkParameterIndex(sal_Int32 parameter);
+
+ void SAL_CALL setFastPropertyValue_NoBroadcast(sal_Int32 nHandle,
+ const Any& rValue) SAL_OVERRIDE;
+ virtual ~OPreparedStatement() override;
+
+public:
+ virtual rtl::OUString SAL_CALL getImplementationName() SAL_OVERRIDE;
+
+ virtual sal_Bool SAL_CALL supportsService(rtl::OUString const& ServiceName) SAL_OVERRIDE;
+
+ virtual css::uno::Sequence<rtl::OUString> SAL_CALL getSupportedServiceNames() SAL_OVERRIDE;
+
+ OPreparedStatement(OConnection* _pConnection, MYSQL_STMT* pStmt);
+
+ //XInterface
+ Any SAL_CALL queryInterface(const Type& rType) SAL_OVERRIDE;
+ void SAL_CALL acquire() throw() SAL_OVERRIDE;
+ void SAL_CALL release() throw() SAL_OVERRIDE;
+
+ //XTypeProvider
+ css::uno::Sequence<Type> SAL_CALL getTypes() SAL_OVERRIDE;
+
+ // XPreparedStatement
+ Reference<css::sdbc::XResultSet> SAL_CALL executeQuery() SAL_OVERRIDE;
+ sal_Int32 SAL_CALL executeUpdate() SAL_OVERRIDE;
+ sal_Bool SAL_CALL execute() SAL_OVERRIDE;
+ Reference<css::sdbc::XConnection> SAL_CALL getConnection() SAL_OVERRIDE;
+
+ // XStatement
+ using OCommonStatement::execute;
+ using OCommonStatement::executeQuery;
+ using OCommonStatement::executeUpdate;
+
+ // XParameters
+ void SAL_CALL setNull(sal_Int32 parameter, sal_Int32 sqlType) SAL_OVERRIDE;
+
+ void SAL_CALL setObjectNull(sal_Int32 parameter, sal_Int32 sqlType,
+ const rtl::OUString& typeName) SAL_OVERRIDE;
+
+ void SAL_CALL setBoolean(sal_Int32 parameter, sal_Bool x) SAL_OVERRIDE;
+
+ void SAL_CALL setByte(sal_Int32 parameter, sal_Int8 x) SAL_OVERRIDE;
+
+ void SAL_CALL setShort(sal_Int32 parameter, sal_Int16 x) SAL_OVERRIDE;
+
+ void SAL_CALL setInt(sal_Int32 parameter, sal_Int32 x) SAL_OVERRIDE;
+
+ void SAL_CALL setLong(sal_Int32 parameter, sal_Int64 x) SAL_OVERRIDE;
+
+ void SAL_CALL setFloat(sal_Int32 parameter, float x) SAL_OVERRIDE;
+
+ void SAL_CALL setDouble(sal_Int32 parameter, double x) SAL_OVERRIDE;
+
+ void SAL_CALL setString(sal_Int32 parameter, const rtl::OUString& x) SAL_OVERRIDE;
+
+ void SAL_CALL setBytes(sal_Int32 parameter, const css::uno::Sequence<sal_Int8>& x) SAL_OVERRIDE;
+
+ void SAL_CALL setDate(sal_Int32 parameter, const css::util::Date& x) SAL_OVERRIDE;
+
+ void SAL_CALL setTime(sal_Int32 parameter, const css::util::Time& x) SAL_OVERRIDE;
+ void SAL_CALL setTimestamp(sal_Int32 parameter, const css::util::DateTime& x) SAL_OVERRIDE;
+
+ void SAL_CALL setBinaryStream(sal_Int32 parameter, const Reference<css::io::XInputStream>& x,
+ sal_Int32 length) SAL_OVERRIDE;
+
+ void SAL_CALL setCharacterStream(sal_Int32 parameter, const Reference<css::io::XInputStream>& x,
+ sal_Int32 length) SAL_OVERRIDE;
+
+ void SAL_CALL setObject(sal_Int32 parameter, const Any& x) SAL_OVERRIDE;
+
+ void SAL_CALL setObjectWithInfo(sal_Int32 parameter, const Any& x, sal_Int32 targetSqlType,
+ sal_Int32 scale) SAL_OVERRIDE;
+
+ void SAL_CALL setRef(sal_Int32 parameter, const Reference<css::sdbc::XRef>& x) SAL_OVERRIDE;
+
+ void SAL_CALL setBlob(sal_Int32 parameter, const Reference<css::sdbc::XBlob>& x) SAL_OVERRIDE;
+
+ void SAL_CALL setClob(sal_Int32 parameter, const Reference<css::sdbc::XClob>& x) SAL_OVERRIDE;
+
+ void SAL_CALL setArray(sal_Int32 parameter, const Reference<css::sdbc::XArray>& x) SAL_OVERRIDE;
+
+ void SAL_CALL clearParameters() SAL_OVERRIDE;
+
+ // XPreparedBatchExecution
+ void SAL_CALL addBatch() SAL_OVERRIDE;
+ void SAL_CALL clearBatch() SAL_OVERRIDE;
+ css::uno::Sequence<sal_Int32> SAL_CALL executeBatch() SAL_OVERRIDE;
+
+ // XCloseable
+ void SAL_CALL close() SAL_OVERRIDE;
+
+ // XResultSetMetaDataSupplier
+ Reference<css::sdbc::XResultSetMetaData> SAL_CALL getMetaData() SAL_OVERRIDE;
+};
+} /* mysqlc */
+} /* connectivity */
+#endif // INCLUDED_MYSQLC_SOURCE_MYSQLC_PREPAREDSTATEMENT_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/mysqlc/mysqlc_propertyids.hxx b/connectivity/source/drivers/mysqlc/mysqlc_propertyids.hxx
new file mode 100644
index 000000000000..e69fcab53c41
--- /dev/null
+++ b/connectivity/source/drivers/mysqlc/mysqlc_propertyids.hxx
@@ -0,0 +1,51 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef INCLUDED_MYSQLC_SOURCE_MYSQLC_PROPERTYIDS_HXX
+#define INCLUDED_MYSQLC_SOURCE_MYSQLC_PROPERTYIDS_HXX
+
+// this define has to be set to split the names into different dll's or so's
+// every dll has his own set of property names
+#include <rtl/ustring.hxx>
+#include <map>
+
+namespace connectivity
+{
+namespace mysqlc
+{
+enum
+{
+ PROPERTY_ID_QUERYTIMEOUT = 1,
+ PROPERTY_ID_MAXFIELDSIZE,
+ PROPERTY_ID_MAXROWS,
+ PROPERTY_ID_CURSORNAME,
+ PROPERTY_ID_RESULTSETCONCURRENCY,
+ PROPERTY_ID_RESULTSETTYPE,
+ PROPERTY_ID_FETCHDIRECTION,
+ PROPERTY_ID_FETCHSIZE,
+ PROPERTY_ID_ESCAPEPROCESSING,
+ PROPERTY_ID_USEBOOKMARKS,
+ PROPERTY_ID_ISBOOKMARKABLE
+};
+} /* mysqlc */
+} /* connectivity */
+
+#endif // INCLUDED_MYSQLC_SOURCE_MYSQLC_PROPERTYIDS_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/mysqlc/mysqlc_resultset.cxx b/connectivity/source/drivers/mysqlc/mysqlc_resultset.cxx
new file mode 100644
index 000000000000..24e2b2560968
--- /dev/null
+++ b/connectivity/source/drivers/mysqlc/mysqlc_resultset.cxx
@@ -0,0 +1,1068 @@
+/* -*- 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 "mysqlc_propertyids.hxx"
+#include "mysqlc_general.hxx"
+#include "mysqlc_resultset.hxx"
+#include "mysqlc_resultsetmetadata.hxx"
+
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/lang/DisposedException.hpp>
+#include <com/sun/star/sdbc/DataType.hpp>
+#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/sdbcx/CompareBookmark.hpp>
+#include <cppuhelper/supportsservice.hxx>
+#include <cppuhelper/typeprovider.hxx>
+
+using namespace rtl;
+#include <comphelper/string.hxx>
+
+#include <cstdlib>
+
+using namespace connectivity::mysqlc;
+using namespace cppu;
+using namespace com::sun::star;
+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;
+using namespace ::comphelper;
+using ::osl::MutexGuard;
+
+#include <stdio.h>
+
+namespace
+{
+// copied from string misc, it should be replaced when library is not an
+// extension anymore
+std::vector<OUString> lcl_split(const OUString& rStr, sal_Unicode cSeparator)
+{
+ std::vector<OUString> vec;
+ sal_Int32 idx = 0;
+ do
+ {
+ OUString kw = rStr.getToken(0, cSeparator, idx);
+ kw = kw.trim();
+ if (!kw.isEmpty())
+ {
+ vec.push_back(kw);
+ }
+ } while (idx >= 0);
+ return vec;
+}
+}
+
+rtl::OUString SAL_CALL OResultSet::getImplementationName()
+{
+ return rtl::OUString("com.sun.star.sdbcx.mysqlc.ResultSet");
+}
+
+uno::Sequence<rtl::OUString> SAL_CALL OResultSet::getSupportedServiceNames()
+{
+ uno::Sequence<rtl::OUString> aSupported(2);
+ aSupported[0] = "com.sun.star.sdbc.ResultSet";
+ aSupported[1] = "com.sun.star.sdbcx.ResultSet";
+ return aSupported;
+}
+
+sal_Bool SAL_CALL OResultSet::supportsService(const rtl::OUString& _rServiceName)
+{
+ return cppu::supportsService(this, _rServiceName);
+}
+
+OResultSet::OResultSet(OConnection& rConn, OCommonStatement* pStmt, MYSQL_RES* pResult,
+ rtl_TextEncoding _encoding)
+ : OResultSet_BASE(m_aMutex)
+ , OPropertySetHelper(OResultSet_BASE::rBHelper)
+ , m_rConnection(rConn)
+ , m_pMysql(rConn.getMysqlConnection())
+ , m_aStatement(static_cast<OWeakObject*>(pStmt))
+ , m_xMetaData(nullptr)
+ , m_pResult(pResult)
+ , fieldCount(0)
+ , m_encoding(_encoding)
+{
+ fieldCount = mysql_num_fields(pResult);
+}
+
+OResultSet::~OResultSet() {}
+
+void OResultSet::disposing()
+{
+ OPropertySetHelper::disposing();
+
+ MutexGuard aGuard(m_aMutex);
+
+ m_aStatement = nullptr;
+ m_xMetaData = nullptr;
+}
+
+Any SAL_CALL OResultSet::queryInterface(const Type& rType)
+{
+ Any aRet = OPropertySetHelper::queryInterface(rType);
+ if (!aRet.hasValue())
+ {
+ aRet = OResultSet_BASE::queryInterface(rType);
+ }
+ return aRet;
+}
+
+uno::Sequence<Type> SAL_CALL OResultSet::getTypes()
+{
+ OTypeCollection aTypes(cppu::UnoType<XMultiPropertySet>::get(),
+ cppu::UnoType<XFastPropertySet>::get(),
+ cppu::UnoType<XPropertySet>::get());
+
+ return concatSequences(aTypes.getTypes(), OResultSet_BASE::getTypes());
+}
+
+sal_Int32 SAL_CALL OResultSet::findColumn(const rtl::OUString& columnName)
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
+
+ MYSQL_FIELD* pFields = mysql_fetch_field(m_pResult);
+ for (unsigned int i = 0; i < fieldCount; ++i)
+ {
+ if (columnName.equalsIgnoreAsciiCaseAscii(pFields[i].name))
+ return i + 1; // sdbc indexes from 1
+ }
+
+ throw SQLException("The column name '" + columnName + "' is not valid.", *this, "42S22", 0,
+ Any());
+}
+
+uno::Reference<XInputStream> SAL_CALL OResultSet::getBinaryStream(sal_Int32 column)
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
+ checkColumnIndex(column);
+
+ mysqlc_sdbc_driver::throwFeatureNotImplementedException("OResultSet::getBinaryStream", *this);
+ return nullptr;
+}
+
+uno::Reference<XInputStream> SAL_CALL OResultSet::getCharacterStream(sal_Int32 column)
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
+ checkColumnIndex(column);
+
+ mysqlc_sdbc_driver::throwFeatureNotImplementedException("OResultSet::getCharacterStream",
+ *this);
+ return nullptr;
+}
+
+sal_Bool SAL_CALL OResultSet::getBoolean(sal_Int32 column)
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
+ checkColumnIndex(column);
+
+ char* pValue = m_aRow[column - 1];
+ if (!pValue)
+ {
+ m_bWasNull = true;
+ return false;
+ }
+
+ m_bWasNull = false;
+ return static_cast<bool>(std::atoi(pValue));
+}
+
+sal_Int8 SAL_CALL OResultSet::getByte(sal_Int32 column)
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
+ checkColumnIndex(column);
+
+ char* pValue = m_aRow[column - 1];
+ if (!pValue)
+ {
+ m_bWasNull = true;
+ return 0;
+ }
+
+ m_bWasNull = false;
+ return static_cast<sal_Int8>(std::atoi(pValue));
+}
+
+uno::Sequence<sal_Int8> SAL_CALL OResultSet::getBytes(sal_Int32 column)
+{
+ checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
+ MutexGuard aGuard(m_aMutex);
+
+ char* pValue = m_aRow[column - 1];
+ if (!pValue)
+ {
+ m_bWasNull = true;
+ return uno::Sequence<sal_Int8>();
+ }
+ m_bWasNull = false;
+ return uno::Sequence<sal_Int8>(reinterpret_cast<sal_Int8 const*>(pValue),
+ m_aLengths[column - 1]);
+}
+
+Date SAL_CALL OResultSet::getDate(sal_Int32 column)
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
+ checkColumnIndex(column);
+
+ Date d; // TODO initialize
+ char* dateStr = m_aRow[column - 1];
+ if (!dateStr)
+ {
+ m_bWasNull = true;
+ return d;
+ }
+
+ rtl::OString dateString(dateStr);
+ rtl::OString token;
+ sal_Int32 nIndex = 0, i = 0;
+ do
+ {
+ token = dateString.getToken(0, '-', nIndex);
+ switch (i)
+ {
+ case 0:
+ d.Year = static_cast<sal_uInt16>(token.toUInt32());
+ break;
+ case 1:
+ d.Month = static_cast<sal_uInt16>(token.toUInt32());
+ break;
+ case 2:
+ d.Day = static_cast<sal_uInt16>(token.toUInt32());
+ break;
+ default:;
+ }
+ i++;
+ } while (nIndex >= 0);
+ m_bWasNull = false;
+ return d;
+}
+
+double SAL_CALL OResultSet::getDouble(sal_Int32 column)
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
+ checkColumnIndex(column);
+
+ char* pValue = m_aRow[column - 1];
+ if (!pValue)
+ {
+ m_bWasNull = true;
+ return 0.0;
+ }
+
+ m_bWasNull = false;
+ return std::strtod(pValue, nullptr);
+}
+
+float SAL_CALL OResultSet::getFloat(sal_Int32 column)
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
+ checkColumnIndex(column);
+
+ char* pValue = m_aRow[column - 1];
+ if (!pValue)
+ {
+ m_bWasNull = true;
+ return 0.0f;
+ }
+
+ m_bWasNull = false;
+ return std::strtod(pValue, nullptr);
+}
+
+sal_Int32 SAL_CALL OResultSet::getInt(sal_Int32 column)
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
+ char* pValue = m_aRow[column - 1];
+ if (!pValue)
+ {
+ m_bWasNull = true;
+ return 0;
+ }
+
+ m_bWasNull = false;
+ return std::atoi(pValue);
+}
+
+sal_Int32 SAL_CALL OResultSet::getRow()
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
+
+ return static_cast<sal_Int32>(mysql_field_tell(m_pResult));
+}
+
+sal_Int64 SAL_CALL OResultSet::getLong(sal_Int32 column)
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
+ checkColumnIndex(column);
+
+ char* pValue = m_aRow[column - 1];
+ if (!pValue)
+ {
+ m_bWasNull = true;
+ return 0LL;
+ }
+
+ m_bWasNull = false;
+ return std::atol(pValue);
+}
+
+uno::Reference<XResultSetMetaData> SAL_CALL OResultSet::getMetaData()
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
+ if (!m_xMetaData.is())
+ {
+ m_xMetaData = new OResultSetMetaData(m_rConnection, m_pResult, m_encoding);
+ }
+ return m_xMetaData;
+}
+
+uno::Reference<XArray> SAL_CALL OResultSet::getArray(sal_Int32 column)
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
+ checkColumnIndex(column);
+
+ mysqlc_sdbc_driver::throwFeatureNotImplementedException("OResultSet::getArray", *this);
+ return nullptr;
+}
+
+uno::Reference<XClob> SAL_CALL OResultSet::getClob(sal_Int32 column)
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
+ checkColumnIndex(column);
+
+ mysqlc_sdbc_driver::throwFeatureNotImplementedException("OResultSet::getClob", *this);
+ return nullptr;
+}
+
+uno::Reference<XBlob> SAL_CALL OResultSet::getBlob(sal_Int32 column)
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
+ checkColumnIndex(column);
+
+ mysqlc_sdbc_driver::throwFeatureNotImplementedException("OResultSet::getBlob", *this);
+ return nullptr;
+}
+
+uno::Reference<XRef> SAL_CALL OResultSet::getRef(sal_Int32 column)
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
+ checkColumnIndex(column);
+
+ mysqlc_sdbc_driver::throwFeatureNotImplementedException("OResultSet::getRef", *this);
+ return nullptr;
+}
+
+Any SAL_CALL OResultSet::getObject(sal_Int32 column,
+ const uno::Reference<XNameAccess>& /* typeMap */)
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
+ checkColumnIndex(column);
+
+ Any aRet = Any();
+
+ mysqlc_sdbc_driver::throwFeatureNotImplementedException("OResultSet::getObject", *this);
+ return aRet;
+}
+
+sal_Int16 SAL_CALL OResultSet::getShort(sal_Int32 column)
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
+ checkColumnIndex(column);
+
+ char* pValue = m_aRow[column - 1];
+ if (!pValue)
+ {
+ m_bWasNull = true;
+ return 0;
+ }
+ m_bWasNull = false;
+ return std::atoi(pValue);
+}
+
+rtl::OUString SAL_CALL OResultSet::getString(sal_Int32 column)
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
+ checkColumnIndex(column);
+
+ char* pValue = m_aRow[column - 1];
+ if (!pValue)
+ {
+ m_bWasNull = true;
+ return rtl::OUString{};
+ }
+ m_bWasNull = false;
+ return rtl::OUString(pValue, static_cast<sal_Int32>(m_aLengths[column - 1]), m_encoding);
+}
+
+Time SAL_CALL OResultSet::getTime(sal_Int32 column)
+{
+ checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
+ MutexGuard aGuard(m_aMutex);
+
+ checkColumnIndex(column);
+ Time t; // initialize
+ char* pValue = m_aRow[column - 1];
+ if (!pValue)
+ {
+ m_bWasNull = true;
+ return t;
+ }
+ rtl::OUString timeString{ pValue, static_cast<sal_Int32>(m_aLengths[column - 1]), m_encoding };
+ rtl::OUString token;
+ sal_Int32 nIndex, i = 0;
+
+ nIndex = timeString.indexOf(' ') + 1;
+ do
+ {
+ token = timeString.getToken(0, ':', nIndex);
+ switch (i)
+ {
+ case 0:
+ t.Hours = static_cast<sal_uInt16>(token.toUInt32());
+ break;
+ case 1:
+ t.Minutes = static_cast<sal_uInt16>(token.toUInt32());
+ break;
+ case 2:
+ t.Seconds = static_cast<sal_uInt16>(token.toUInt32());
+ break;
+ }
+ i++;
+ } while (nIndex >= 0);
+
+ m_bWasNull = false;
+ return t;
+}
+
+DateTime SAL_CALL OResultSet::getTimestamp(sal_Int32 column)
+{
+ checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
+ MutexGuard aGuard(m_aMutex);
+ checkColumnIndex(column);
+
+ char* pValue = m_aRow[column - 1];
+ if (!pValue)
+ {
+ m_bWasNull = true;
+ return DateTime{}; // init
+ }
+
+ // YY-MM-DD HH:MM:SS
+ std::vector<rtl::OUString> dateAndTime = lcl_split(
+ rtl::OUString{ pValue, static_cast<sal_Int32>(m_aLengths[column - 1]), m_encoding }, u' ');
+
+ auto dateParts = lcl_split(dateAndTime.at(0), u'-');
+ auto timeParts = lcl_split(dateAndTime.at(1), u':');
+
+ DateTime dt;
+
+ dt.Year = dateParts.at(0).toUInt32();
+ dt.Month = dateParts.at(1).toUInt32();
+ dt.Day = dateParts.at(2).toUInt32();
+ dt.Hours = timeParts.at(0).toUInt32();
+ dt.Minutes = timeParts.at(1).toUInt32();
+ dt.Seconds = timeParts.at(2).toUInt32();
+ m_bWasNull = false;
+ return dt;
+}
+
+sal_Bool SAL_CALL OResultSet::isBeforeFirst()
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
+
+ return m_nCurrentField == 0;
+}
+
+sal_Bool SAL_CALL OResultSet::isAfterLast()
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
+
+ return m_nCurrentField >= static_cast<sal_Int32>(fieldCount);
+}
+
+sal_Bool SAL_CALL OResultSet::isFirst()
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
+
+ return m_nCurrentField == 1 && !isAfterLast();
+}
+
+sal_Bool SAL_CALL OResultSet::isLast()
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
+
+ return mysql_field_tell(m_pResult) == fieldCount;
+}
+
+void SAL_CALL OResultSet::beforeFirst()
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
+
+ mysqlc_sdbc_driver::throwFeatureNotImplementedException("OResultSet::beforeFirst", *this);
+}
+
+void SAL_CALL OResultSet::afterLast()
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
+
+ mysqlc_sdbc_driver::throwFeatureNotImplementedException("OResultSet::afterLast", *this);
+}
+
+void SAL_CALL OResultSet::close()
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
+
+ mysql_free_result(m_pResult);
+ dispose();
+}
+
+sal_Bool SAL_CALL OResultSet::first()
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
+
+ mysql_data_seek(m_pResult, 0);
+ next();
+
+ return true;
+}
+
+sal_Bool SAL_CALL OResultSet::last()
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
+
+ mysql_data_seek(m_pResult, fieldCount - 1);
+ next();
+
+ return true;
+}
+
+sal_Bool SAL_CALL OResultSet::absolute(sal_Int32 row)
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
+
+ sal_Int32 nFields = static_cast<sal_Int32>(fieldCount);
+ sal_Int32 nToGo = row < 0 ? nFields - row : row - 1;
+
+ if (nToGo >= nFields)
+ nToGo = nFields - 1;
+ if (nToGo < 0)
+ nToGo = 0;
+
+ mysql_data_seek(m_pResult, nToGo);
+ next();
+
+ return true;
+}
+
+sal_Bool SAL_CALL OResultSet::relative(sal_Int32 row)
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
+
+ sal_Int32 nFields = static_cast<sal_Int32>(fieldCount);
+ if (row == 0)
+ return true;
+
+ sal_Int32 nToGo = m_nCurrentField + row;
+ if (nToGo >= nFields)
+ nToGo = nFields - 1;
+ if (nToGo < 0)
+ nToGo = 0;
+
+ mysql_data_seek(m_pResult, nToGo);
+ next();
+
+ return true;
+}
+
+sal_Bool SAL_CALL OResultSet::previous()
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
+
+ if (m_nCurrentField <= 1)
+ return false;
+
+ mysql_data_seek(m_pResult, m_nCurrentField - 2);
+ next();
+ return true;
+}
+
+uno::Reference<uno::XInterface> SAL_CALL OResultSet::getStatement()
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
+
+ return m_aStatement.get();
+}
+
+sal_Bool SAL_CALL OResultSet::rowDeleted()
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
+
+ return false;
+}
+
+sal_Bool SAL_CALL OResultSet::rowInserted()
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
+
+ return false;
+}
+
+sal_Bool SAL_CALL OResultSet::rowUpdated()
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
+
+ return false;
+}
+
+sal_Bool SAL_CALL OResultSet::next()
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
+
+ m_aRow = mysql_fetch_row(m_pResult);
+ m_aLengths = mysql_fetch_lengths(m_pResult);
+ m_nCurrentField = mysql_field_tell(m_pResult);
+
+ unsigned errorNum = mysql_errno(m_pMysql);
+ if (errorNum)
+ mysqlc_sdbc_driver::throwSQLExceptionWithMsg(mysql_error(m_pMysql), errorNum, *this,
+ m_encoding);
+
+ return m_aRow != nullptr;
+}
+
+sal_Bool SAL_CALL OResultSet::wasNull()
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
+
+ return m_bWasNull;
+}
+
+void SAL_CALL OResultSet::cancel()
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
+}
+
+void SAL_CALL OResultSet::clearWarnings() {}
+
+Any SAL_CALL OResultSet::getWarnings()
+{
+ Any aRet = Any();
+ return aRet;
+}
+
+void SAL_CALL OResultSet::insertRow()
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
+ // you only have to implement this if you want to insert new rows
+ mysqlc_sdbc_driver::throwFeatureNotImplementedException("OResultSet::insertRow", *this);
+}
+
+void SAL_CALL OResultSet::updateRow()
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
+
+ // only when you allow updates
+ mysqlc_sdbc_driver::throwFeatureNotImplementedException("OResultSet::updateRow", *this);
+}
+
+void SAL_CALL OResultSet::deleteRow()
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
+ mysqlc_sdbc_driver::throwFeatureNotImplementedException("OResultSet::deleteRow", *this);
+}
+
+void SAL_CALL OResultSet::cancelRowUpdates()
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
+ mysqlc_sdbc_driver::throwFeatureNotImplementedException("OResultSet::cancelRowUpdates", *this);
+}
+
+void SAL_CALL OResultSet::moveToInsertRow()
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
+
+ // only when you allow insert's
+ mysqlc_sdbc_driver::throwFeatureNotImplementedException("OResultSet::moveToInsertRow", *this);
+}
+
+void SAL_CALL OResultSet::moveToCurrentRow()
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
+}
+
+void SAL_CALL OResultSet::updateNull(sal_Int32 column)
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
+ checkColumnIndex(column);
+ mysqlc_sdbc_driver::throwFeatureNotImplementedException("OResultSet::updateNull", *this);
+}
+
+void SAL_CALL OResultSet::updateBoolean(sal_Int32 column, sal_Bool /* x */)
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
+ checkColumnIndex(column);
+ mysqlc_sdbc_driver::throwFeatureNotImplementedException("OResultSet::updateBoolean", *this);
+}
+
+void SAL_CALL OResultSet::updateByte(sal_Int32 column, sal_Int8 /* x */)
+{
+ checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
+ MutexGuard aGuard(m_aMutex);
+ checkColumnIndex(column);
+ mysqlc_sdbc_driver::throwFeatureNotImplementedException("OResultSet::updateByte", *this);
+}
+
+void SAL_CALL OResultSet::updateShort(sal_Int32 column, sal_Int16 /* x */)
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
+ checkColumnIndex(column);
+ mysqlc_sdbc_driver::throwFeatureNotImplementedException("OResultSet::updateShort", *this);
+}
+
+void SAL_CALL OResultSet::updateInt(sal_Int32 column, sal_Int32 /* x */)
+{
+ checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
+ MutexGuard aGuard(m_aMutex);
+ checkColumnIndex(column);
+ mysqlc_sdbc_driver::throwFeatureNotImplementedException("OResultSet::updateInt", *this);
+}
+
+void SAL_CALL OResultSet::updateLong(sal_Int32 column, sal_Int64 /* x */)
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
+ checkColumnIndex(column);
+ mysqlc_sdbc_driver::throwFeatureNotImplementedException("OResultSet::updateLong", *this);
+}
+
+void SAL_CALL OResultSet::updateFloat(sal_Int32 column, float /* x */)
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
+ checkColumnIndex(column);
+ mysqlc_sdbc_driver::throwFeatureNotImplementedException("OResultSet::updateFloat", *this);
+}
+
+void SAL_CALL OResultSet::updateDouble(sal_Int32 column, double /* x */)
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
+ checkColumnIndex(column);
+ mysqlc_sdbc_driver::throwFeatureNotImplementedException("OResultSet::updateDouble", *this);
+}
+
+void SAL_CALL OResultSet::updateString(sal_Int32 column, const rtl::OUString& /* x */)
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
+ checkColumnIndex(column);
+ mysqlc_sdbc_driver::throwFeatureNotImplementedException("OResultSet::updateString", *this);
+}
+
+void SAL_CALL OResultSet::updateBytes(sal_Int32 column, const uno::Sequence<sal_Int8>& /* x */)
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
+ checkColumnIndex(column);
+ mysqlc_sdbc_driver::throwFeatureNotImplementedException("OResultSet::updateBytes", *this);
+}
+
+void SAL_CALL OResultSet::updateDate(sal_Int32 column, const Date& /* x */)
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
+ checkColumnIndex(column);
+ mysqlc_sdbc_driver::throwFeatureNotImplementedException("OResultSet::updateDate", *this);
+}
+
+void SAL_CALL OResultSet::updateTime(sal_Int32 column, const Time& /* x */)
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
+ checkColumnIndex(column);
+ mysqlc_sdbc_driver::throwFeatureNotImplementedException("OResultSet::updateTime", *this);
+}
+
+void SAL_CALL OResultSet::updateTimestamp(sal_Int32 column, const DateTime& /* x */)
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
+ checkColumnIndex(column);
+ mysqlc_sdbc_driver::throwFeatureNotImplementedException("OResultSet::updateTimestamp", *this);
+}
+
+void SAL_CALL OResultSet::updateBinaryStream(sal_Int32 column,
+ const uno::Reference<XInputStream>& /* x */,
+ sal_Int32 /* length */)
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
+ checkColumnIndex(column);
+ mysqlc_sdbc_driver::throwFeatureNotImplementedException("OResultSet::updateBinaryStream",
+ *this);
+}
+
+void SAL_CALL OResultSet::updateCharacterStream(sal_Int32 column,
+ const uno::Reference<XInputStream>& /* x */,
+ sal_Int32 /* length */)
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
+ checkColumnIndex(column);
+ mysqlc_sdbc_driver::throwFeatureNotImplementedException("OResultSet::updateCharacterStream",
+ *this);
+}
+
+void SAL_CALL OResultSet::refreshRow()
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
+ mysqlc_sdbc_driver::throwFeatureNotImplementedException("OResultSet::refreshRow", *this);
+}
+
+void SAL_CALL OResultSet::updateObject(sal_Int32 column, const Any& /* x */)
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
+ checkColumnIndex(column);
+ mysqlc_sdbc_driver::throwFeatureNotImplementedException("OResultSet::updateObject", *this);
+}
+
+void SAL_CALL OResultSet::updateNumericObject(sal_Int32 column, const Any& /* x */,
+ sal_Int32 /* scale */)
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
+ checkColumnIndex(column);
+ mysqlc_sdbc_driver::throwFeatureNotImplementedException("OResultSet::updateNumericObject",
+ *this);
+}
+
+// XRowLocate
+Any SAL_CALL OResultSet::getBookmark()
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
+ Any aRet = Any();
+
+ // if you don't want to support bookmark you must remove the XRowLocate interface
+ mysqlc_sdbc_driver::throwFeatureNotImplementedException("OResultSet::getBookmark", *this);
+
+ return aRet;
+}
+
+sal_Bool SAL_CALL OResultSet::moveToBookmark(const Any& /* bookmark */)
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
+
+ return false;
+}
+
+sal_Bool SAL_CALL OResultSet::moveRelativeToBookmark(const Any& /* bookmark */,
+ sal_Int32 /* rows */)
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
+
+ mysqlc_sdbc_driver::throwFeatureNotImplementedException("OResultSet::moveRelativeToBookmark",
+ *this);
+ return false;
+}
+
+sal_Int32 SAL_CALL OResultSet::compareBookmarks(const Any& /* n1 */, const Any& /* n2 */)
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
+
+ mysqlc_sdbc_driver::throwFeatureNotImplementedException("OResultSet::compareBookmarks", *this);
+
+ return CompareBookmark::NOT_EQUAL;
+}
+
+sal_Bool SAL_CALL OResultSet::hasOrderedBookmarks() { return false; }
+
+sal_Int32 SAL_CALL OResultSet::hashBookmark(const Any& /* bookmark */)
+{
+ mysqlc_sdbc_driver::throwFeatureNotImplementedException("OResultSet::hashBookmark", *this);
+ return 0;
+}
+
+// XDeleteRows
+uno::Sequence<sal_Int32> SAL_CALL OResultSet::deleteRows(const uno::Sequence<Any>& /* rows */)
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
+ uno::Sequence<sal_Int32> aRet = uno::Sequence<sal_Int32>();
+
+ mysqlc_sdbc_driver::throwFeatureNotImplementedException("OResultSet::deleteRows", *this);
+ return aRet;
+}
+
+IPropertyArrayHelper* OResultSet::createArrayHelper() const
+{
+ uno::Sequence<Property> aProps(5);
+ Property* pProperties = aProps.getArray();
+ sal_Int32 nPos = 0;
+ pProperties[nPos++] = Property("FetchDirection", PROPERTY_ID_FETCHDIRECTION,
+ cppu::UnoType<sal_Int32>::get(), 0);
+ pProperties[nPos++]
+ = Property("FetchSize", PROPERTY_ID_FETCHSIZE, cppu::UnoType<sal_Int32>::get(), 0);
+ pProperties[nPos++] = Property("IsBookmarkable", PROPERTY_ID_ISBOOKMARKABLE,
+ cppu::UnoType<bool>::get(), PropertyAttribute::READONLY);
+ pProperties[nPos++] = Property("ResultSetConcurrency", PROPERTY_ID_RESULTSETCONCURRENCY,
+ cppu::UnoType<sal_Int32>::get(), PropertyAttribute::READONLY);
+ pProperties[nPos++] = Property("ResultSetType", PROPERTY_ID_RESULTSETTYPE,
+ cppu::UnoType<sal_Int32>::get(), PropertyAttribute::READONLY);
+
+ return new OPropertyArrayHelper(aProps);
+}
+
+IPropertyArrayHelper& OResultSet::getInfoHelper() { return *getArrayHelper(); }
+
+sal_Bool OResultSet::convertFastPropertyValue(Any& /* rConvertedValue */, Any& /* rOldValue */,
+ sal_Int32 nHandle, const Any& /* rValue */)
+{
+ switch (nHandle)
+ {
+ case PROPERTY_ID_ISBOOKMARKABLE:
+ case PROPERTY_ID_CURSORNAME:
+ case PROPERTY_ID_RESULTSETCONCURRENCY:
+ case PROPERTY_ID_RESULTSETTYPE:
+ throw css::lang::IllegalArgumentException();
+ case PROPERTY_ID_FETCHDIRECTION:
+ case PROPERTY_ID_FETCHSIZE:
+ default:;
+ }
+ return false;
+}
+
+void OResultSet::setFastPropertyValue_NoBroadcast(sal_Int32 nHandle, const Any& /* rValue */)
+{
+ switch (nHandle)
+ {
+ case PROPERTY_ID_ISBOOKMARKABLE:
+ case PROPERTY_ID_CURSORNAME:
+ case PROPERTY_ID_RESULTSETCONCURRENCY:
+ case PROPERTY_ID_RESULTSETTYPE:
+ throw uno::Exception("cannot set prop " + rtl::OUString::number(nHandle), nullptr);
+ case PROPERTY_ID_FETCHDIRECTION:
+ break;
+ case PROPERTY_ID_FETCHSIZE:
+ break;
+ default:;
+ }
+}
+
+void OResultSet::getFastPropertyValue(Any& _rValue, sal_Int32 nHandle) const
+{
+ switch (nHandle)
+ {
+ case PROPERTY_ID_ISBOOKMARKABLE:
+ _rValue <<= false;
+ break;
+ case PROPERTY_ID_CURSORNAME:
+ break;
+ case PROPERTY_ID_RESULTSETCONCURRENCY:
+ _rValue <<= ResultSetConcurrency::READ_ONLY;
+ break;
+ case PROPERTY_ID_RESULTSETTYPE:
+ _rValue <<= ResultSetType::SCROLL_INSENSITIVE;
+ break;
+ case PROPERTY_ID_FETCHDIRECTION:
+ _rValue <<= FetchDirection::FORWARD;
+ break;
+ case PROPERTY_ID_FETCHSIZE:
+ _rValue <<= sal_Int32(50);
+ break;
+ ;
+ default:;
+ }
+}
+
+void SAL_CALL OResultSet::acquire() throw() { OResultSet_BASE::acquire(); }
+
+void SAL_CALL OResultSet::release() throw() { OResultSet_BASE::release(); }
+
+css::uno::Reference<css::beans::XPropertySetInfo> SAL_CALL OResultSet::getPropertySetInfo()
+{
+ return ::cppu::OPropertySetHelper::createPropertySetInfo(getInfoHelper());
+}
+
+void OResultSet::checkColumnIndex(sal_Int32 index)
+{
+ if (index < 1 || index > static_cast<int>(fieldCount))
+ {
+ /* static object for efficiency or thread safety is a problem ? */
+ throw SQLException("index out of range", *this, rtl::OUString(), 1, Any());
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/mysqlc/mysqlc_resultset.hxx b/connectivity/source/drivers/mysqlc/mysqlc_resultset.hxx
new file mode 100644
index 000000000000..c4a203cda91e
--- /dev/null
+++ b/connectivity/source/drivers/mysqlc/mysqlc_resultset.hxx
@@ -0,0 +1,246 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef INCLUDED_MYSQLC_SOURCE_MYSQLC_RESULTSET_HXX
+#define INCLUDED_MYSQLC_SOURCE_MYSQLC_RESULTSET_HXX
+
+#include "mysqlc_preparedstatement.hxx"
+#include "mysqlc_statement.hxx"
+#include "mysqlc_subcomponent.hxx"
+#include "mysqlc_connection.hxx"
+
+#include <com/sun/star/sdbc/XCloseable.hpp>
+#include <com/sun/star/sdbc/XColumnLocate.hpp>
+#include <com/sun/star/sdbc/XResultSet.hpp>
+#include <com/sun/star/sdbc/XResultSetMetaDataSupplier.hpp>
+#include <com/sun/star/sdbc/XResultSetUpdate.hpp>
+#include <com/sun/star/sdbc/XRow.hpp>
+#include <com/sun/star/sdbc/XRowUpdate.hpp>
+#include <com/sun/star/sdbc/XWarningsSupplier.hpp>
+#include <com/sun/star/sdbcx/XDeleteRows.hpp>
+#include <com/sun/star/sdbcx/XRowLocate.hpp>
+#include <com/sun/star/util/XCancellable.hpp>
+
+#include <cppuhelper/compbase12.hxx>
+
+namespace connectivity
+{
+namespace mysqlc
+{
+using ::com::sun::star::sdbc::SQLException;
+using ::com::sun::star::uno::Any;
+using ::com::sun::star::uno::RuntimeException;
+
+/*
+ ** OResultSet
+ */
+typedef ::cppu::WeakComponentImplHelper12<
+ css::sdbc::XResultSet, css::sdbc::XRow, css::sdbc::XResultSetMetaDataSupplier,
+ css::util::XCancellable, css::sdbc::XWarningsSupplier, css::sdbc::XResultSetUpdate,
+ css::sdbc::XRowUpdate, css::sdbcx::XRowLocate, css::sdbcx::XDeleteRows, css::sdbc::XCloseable,
+ css::sdbc::XColumnLocate, css::lang::XServiceInfo>
+ OResultSet_BASE;
+
+class OResultSet final : public OBase_Mutex,
+ public OResultSet_BASE,
+ public ::cppu::OPropertySetHelper,
+ public OPropertyArrayUsageHelper<OResultSet>
+{
+ OConnection& m_rConnection;
+ MYSQL_ROW m_aRow;
+ unsigned long* m_aLengths = nullptr;
+ MYSQL* m_pMysql = nullptr;
+ css::uno::WeakReferenceHelper m_aStatement;
+ css::uno::Reference<css::sdbc::XResultSetMetaData> m_xMetaData;
+ MYSQL_RES* m_pResult;
+ unsigned int fieldCount;
+ rtl_TextEncoding m_encoding;
+ sal_Int32 m_nCurrentField = 0;
+ bool m_bWasNull = false; // did the last getXXX result null?
+ // OPropertyArrayUsageHelper
+ ::cppu::IPropertyArrayHelper* createArrayHelper() const SAL_OVERRIDE;
+ // OPropertySetHelper
+ ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper() SAL_OVERRIDE;
+
+ sal_Bool SAL_CALL convertFastPropertyValue(Any& rConvertedValue, Any& rOldValue,
+ sal_Int32 nHandle, const Any& rValue) SAL_OVERRIDE;
+
+ void SAL_CALL setFastPropertyValue_NoBroadcast(sal_Int32 nHandle,
+ const Any& rValue) SAL_OVERRIDE;
+
+ void SAL_CALL getFastPropertyValue(Any& rValue, sal_Int32 nHandle) const SAL_OVERRIDE;
+
+ // you can't delete objects of this type
+ virtual ~OResultSet() override;
+
+public:
+ virtual rtl::OUString SAL_CALL getImplementationName() SAL_OVERRIDE;
+
+ virtual sal_Bool SAL_CALL supportsService(rtl::OUString const& ServiceName) SAL_OVERRIDE;
+
+ virtual css::uno::Sequence<rtl::OUString> SAL_CALL getSupportedServiceNames() SAL_OVERRIDE;
+
+ OResultSet(OConnection& rConn, OCommonStatement* pStmt, MYSQL_RES* pResult,
+ rtl_TextEncoding _encoding);
+
+ // ::cppu::OComponentHelper
+ void SAL_CALL disposing() SAL_OVERRIDE;
+
+ // XInterface
+ Any SAL_CALL queryInterface(const css::uno::Type& rType) SAL_OVERRIDE;
+
+ void SAL_CALL acquire() throw() SAL_OVERRIDE;
+ void SAL_CALL release() throw() SAL_OVERRIDE;
+
+ //XTypeProvider
+ css::uno::Sequence<css::uno::Type> SAL_CALL getTypes() SAL_OVERRIDE;
+
+ // XPropertySet
+ css::uno::Reference<css::beans::XPropertySetInfo> SAL_CALL getPropertySetInfo() SAL_OVERRIDE;
+
+ // XResultSet
+ sal_Bool SAL_CALL next() SAL_OVERRIDE;
+ sal_Bool SAL_CALL isBeforeFirst() SAL_OVERRIDE;
+ sal_Bool SAL_CALL isAfterLast() SAL_OVERRIDE;
+ sal_Bool SAL_CALL isFirst() SAL_OVERRIDE;
+ sal_Bool SAL_CALL isLast() SAL_OVERRIDE;
+
+ void SAL_CALL beforeFirst() SAL_OVERRIDE;
+ void SAL_CALL afterLast() SAL_OVERRIDE;
+
+ sal_Bool SAL_CALL first() SAL_OVERRIDE;
+ sal_Bool SAL_CALL last() SAL_OVERRIDE;
+
+ sal_Int32 SAL_CALL getRow() SAL_OVERRIDE;
+
+ sal_Bool SAL_CALL absolute(sal_Int32 row) SAL_OVERRIDE;
+ sal_Bool SAL_CALL relative(sal_Int32 rows) SAL_OVERRIDE;
+ sal_Bool SAL_CALL previous() SAL_OVERRIDE;
+
+ void SAL_CALL refreshRow() SAL_OVERRIDE;
+
+ sal_Bool SAL_CALL rowUpdated() SAL_OVERRIDE;
+ sal_Bool SAL_CALL rowInserted() SAL_OVERRIDE;
+ sal_Bool SAL_CALL rowDeleted() SAL_OVERRIDE;
+
+ css::uno::Reference<css::uno::XInterface> SAL_CALL getStatement() SAL_OVERRIDE;
+ // XRow
+ sal_Bool SAL_CALL wasNull() SAL_OVERRIDE;
+
+ rtl::OUString SAL_CALL getString(sal_Int32 column) SAL_OVERRIDE;
+
+ sal_Bool SAL_CALL getBoolean(sal_Int32 column) SAL_OVERRIDE;
+ sal_Int8 SAL_CALL getByte(sal_Int32 column) SAL_OVERRIDE;
+ sal_Int16 SAL_CALL getShort(sal_Int32 column) SAL_OVERRIDE;
+ sal_Int32 SAL_CALL getInt(sal_Int32 column) SAL_OVERRIDE;
+ sal_Int64 SAL_CALL getLong(sal_Int32 column) SAL_OVERRIDE;
+
+ float SAL_CALL getFloat(sal_Int32 column) SAL_OVERRIDE;
+ double SAL_CALL getDouble(sal_Int32 column) SAL_OVERRIDE;
+
+ css::uno::Sequence<sal_Int8> SAL_CALL getBytes(sal_Int32 column) SAL_OVERRIDE;
+ css::util::Date SAL_CALL getDate(sal_Int32 column) SAL_OVERRIDE;
+ css::util::Time SAL_CALL getTime(sal_Int32 column) SAL_OVERRIDE;
+ css::util::DateTime SAL_CALL getTimestamp(sal_Int32 column) SAL_OVERRIDE;
+
+ css::uno::Reference<css::io::XInputStream>
+ SAL_CALL getBinaryStream(sal_Int32 column) SAL_OVERRIDE;
+ css::uno::Reference<css::io::XInputStream>
+ SAL_CALL getCharacterStream(sal_Int32 column) SAL_OVERRIDE;
+
+ Any SAL_CALL getObject(sal_Int32 column, const my_XNameAccessRef& typeMap) SAL_OVERRIDE;
+
+ css::uno::Reference<css::sdbc::XRef> SAL_CALL getRef(sal_Int32 column) SAL_OVERRIDE;
+ css::uno::Reference<css::sdbc::XBlob> SAL_CALL getBlob(sal_Int32 column) SAL_OVERRIDE;
+ css::uno::Reference<css::sdbc::XClob> SAL_CALL getClob(sal_Int32 column) SAL_OVERRIDE;
+ css::uno::Reference<css::sdbc::XArray> SAL_CALL getArray(sal_Int32 column) SAL_OVERRIDE;
+
+ // XResultSetMetaDataSupplier
+ css::uno::Reference<css::sdbc::XResultSetMetaData> SAL_CALL getMetaData() SAL_OVERRIDE;
+
+ // XCancellable
+ void SAL_CALL cancel() SAL_OVERRIDE;
+
+ // XCloseable
+ void SAL_CALL close() SAL_OVERRIDE;
+
+ // XWarningsSupplier
+ Any SAL_CALL getWarnings() SAL_OVERRIDE;
+
+ void SAL_CALL clearWarnings() SAL_OVERRIDE;
+
+ // XResultSetUpdate
+ void SAL_CALL insertRow() SAL_OVERRIDE;
+ void SAL_CALL updateRow() SAL_OVERRIDE;
+ void SAL_CALL deleteRow() SAL_OVERRIDE;
+ void SAL_CALL cancelRowUpdates() SAL_OVERRIDE;
+ void SAL_CALL moveToInsertRow() SAL_OVERRIDE;
+ void SAL_CALL moveToCurrentRow() SAL_OVERRIDE;
+
+ // XRowUpdate
+ void SAL_CALL updateNull(sal_Int32 column) SAL_OVERRIDE;
+ void SAL_CALL updateBoolean(sal_Int32 column, sal_Bool x) SAL_OVERRIDE;
+ void SAL_CALL updateByte(sal_Int32 column, sal_Int8 x) SAL_OVERRIDE;
+ void SAL_CALL updateShort(sal_Int32 column, sal_Int16 x) SAL_OVERRIDE;
+ void SAL_CALL updateInt(sal_Int32 column, sal_Int32 x) SAL_OVERRIDE;
+ void SAL_CALL updateLong(sal_Int32 column, sal_Int64 x) SAL_OVERRIDE;
+ void SAL_CALL updateFloat(sal_Int32 column, float x) SAL_OVERRIDE;
+ void SAL_CALL updateDouble(sal_Int32 column, double x) SAL_OVERRIDE;
+ void SAL_CALL updateString(sal_Int32 column, const rtl::OUString& x) SAL_OVERRIDE;
+ void SAL_CALL updateBytes(sal_Int32 column, const css::uno::Sequence<sal_Int8>& x) SAL_OVERRIDE;
+ void SAL_CALL updateDate(sal_Int32 column, const css::util::Date& x) SAL_OVERRIDE;
+ void SAL_CALL updateTime(sal_Int32 column, const css::util::Time& x) SAL_OVERRIDE;
+ void SAL_CALL updateTimestamp(sal_Int32 column, const css::util::DateTime& x) SAL_OVERRIDE;
+ void SAL_CALL updateBinaryStream(sal_Int32 column,
+ const css::uno::Reference<css::io::XInputStream>& x,
+ sal_Int32 length) SAL_OVERRIDE;
+ void SAL_CALL updateCharacterStream(sal_Int32 column,
+ const css::uno::Reference<css::io::XInputStream>& x,
+ sal_Int32 length) SAL_OVERRIDE;
+ void SAL_CALL updateObject(sal_Int32 column, const Any& x) SAL_OVERRIDE;
+ void SAL_CALL updateNumericObject(sal_Int32 column, const Any& x, sal_Int32 scale) SAL_OVERRIDE;
+
+ // XColumnLocate
+ sal_Int32 SAL_CALL findColumn(const rtl::OUString& columnName) SAL_OVERRIDE;
+
+ // XRowLocate
+ Any SAL_CALL getBookmark() SAL_OVERRIDE;
+
+ sal_Bool SAL_CALL moveToBookmark(const Any& bookmark) SAL_OVERRIDE;
+ sal_Bool SAL_CALL moveRelativeToBookmark(const Any& bookmark, sal_Int32 rows) SAL_OVERRIDE;
+ sal_Int32 SAL_CALL compareBookmarks(const Any& first, const Any& second) SAL_OVERRIDE;
+ sal_Bool SAL_CALL hasOrderedBookmarks() SAL_OVERRIDE;
+ sal_Int32 SAL_CALL hashBookmark(const Any& bookmark) SAL_OVERRIDE;
+
+ // XDeleteRows
+ css::uno::Sequence<sal_Int32>
+ SAL_CALL deleteRows(const css::uno::Sequence<Any>& rows) SAL_OVERRIDE;
+
+ /// @throws SQLException
+ /// @throws RuntimeException
+ void checkColumnIndex(sal_Int32 index);
+
+private:
+ using ::cppu::OPropertySetHelper::getFastPropertyValue;
+};
+} /* mysqlc */
+} /* connectivity */
+#endif // CONNECTIVITY_SRESULTSET_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/mysqlc/mysqlc_resultsetmetadata.cxx b/connectivity/source/drivers/mysqlc/mysqlc_resultsetmetadata.cxx
new file mode 100644
index 000000000000..eeadf2bd03a9
--- /dev/null
+++ b/connectivity/source/drivers/mysqlc/mysqlc_resultsetmetadata.cxx
@@ -0,0 +1,203 @@
+/* -*- 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 "mysqlc_resultsetmetadata.hxx"
+#include "mysqlc_resultset.hxx"
+#include "mysqlc_general.hxx"
+
+#include <com/sun/star/sdbc/XRow.hpp>
+#include <rtl/ustrbuf.hxx>
+
+using namespace connectivity::mysqlc;
+using namespace com::sun::star::uno;
+using namespace com::sun::star::lang;
+using namespace com::sun::star::sdbc;
+
+MYSQL_FIELD* OResultSetMetaData::getField(sal_Int32 column) const
+{
+ return mysql_fetch_field_direct(m_pRes, column - 1);
+}
+
+sal_Int32 SAL_CALL OResultSetMetaData::getColumnDisplaySize(sal_Int32 column)
+{
+ MYSQL_FIELD* pField = getField(column);
+ return pField->length;
+}
+
+sal_Int32 SAL_CALL OResultSetMetaData::getColumnType(sal_Int32 column)
+{
+ checkColumnIndex(column);
+ MYSQL_FIELD* pField = getField(column);
+
+ return mysqlc_sdbc_driver::mysqlToOOOType(pField->type, pField->charsetnr);
+}
+
+sal_Int32 SAL_CALL OResultSetMetaData::getColumnCount() { return mysql_num_fields(m_pRes); }
+
+sal_Bool SAL_CALL OResultSetMetaData::isCaseSensitive(sal_Int32 column)
+{
+ checkColumnIndex(column);
+ // MYSQL_FIELD::charsetnr is the collation identifier
+ // _ci postfix means it's insensitive
+ MYSQL_FIELD* pField = getField(column);
+ rtl::OUStringBuffer sql{ "SHOW COLLATION WHERE Id =" };
+ sql.append(rtl::OUString::number(pField->charsetnr));
+
+ Reference<XStatement> stmt = m_rConnection.createStatement();
+ Reference<XResultSet> rs = stmt->executeQuery(sql.makeStringAndClear());
+ Reference<XRow> xRow(rs, UNO_QUERY_THROW);
+
+ rs->next(); // fetch first and only row
+ rtl::OUString sColName = xRow->getString(1); // first column is Collation name
+
+ return !sColName.isEmpty() && !sColName.endsWith("_ci");
+}
+
+rtl::OUString SAL_CALL OResultSetMetaData::getSchemaName(sal_Int32 column)
+{
+ checkColumnIndex(column);
+ MYSQL_FIELD* pField = getField(column);
+
+ return rtl::OStringToOUString(pField->db, m_rConnection.getConnectionEncoding());
+}
+
+rtl::OUString SAL_CALL OResultSetMetaData::getColumnName(sal_Int32 column)
+{
+ checkColumnIndex(column);
+
+ MYSQL_FIELD* pField = getField(column);
+ return rtl::OStringToOUString(pField->name, m_rConnection.getConnectionEncoding());
+}
+
+rtl::OUString SAL_CALL OResultSetMetaData::getTableName(sal_Int32 column)
+{
+ checkColumnIndex(column);
+ MYSQL_FIELD* pField = getField(column);
+ return rtl::OStringToOUString(pField->table, m_rConnection.getConnectionEncoding());
+}
+
+rtl::OUString SAL_CALL OResultSetMetaData::getCatalogName(sal_Int32 column)
+{
+ checkColumnIndex(column);
+ MYSQL_FIELD* pField = getField(column);
+ return rtl::OStringToOUString(pField->catalog, m_rConnection.getConnectionEncoding());
+}
+
+rtl::OUString SAL_CALL OResultSetMetaData::getColumnTypeName(sal_Int32 column)
+{
+ checkColumnIndex(column);
+ MYSQL_FIELD* pField = getField(column);
+
+ return mysqlc_sdbc_driver::mysqlTypeToStr(pField);
+}
+
+rtl::OUString SAL_CALL OResultSetMetaData::getColumnLabel(sal_Int32 column)
+{
+ checkColumnIndex(column);
+ MYSQL_FIELD* pField = getField(column);
+ return rtl::OStringToOUString(pField->name, m_rConnection.getConnectionEncoding());
+}
+
+rtl::OUString SAL_CALL OResultSetMetaData::getColumnServiceName(sal_Int32 column)
+{
+ checkColumnIndex(column);
+
+ rtl::OUString aRet = rtl::OUString();
+ return aRet;
+}
+
+sal_Bool SAL_CALL OResultSetMetaData::isCurrency(sal_Int32 /*column*/)
+{
+ return false; // TODO
+}
+
+sal_Bool SAL_CALL OResultSetMetaData::isAutoIncrement(sal_Int32 column)
+{
+ checkColumnIndex(column);
+
+ MYSQL_FIELD* pField = getField(column);
+ return pField->flags & AUTO_INCREMENT_FLAG;
+}
+
+sal_Bool SAL_CALL OResultSetMetaData::isSigned(sal_Int32 column)
+{
+ checkColumnIndex(column);
+
+ MYSQL_FIELD* pField = getField(column);
+ return !(pField->flags & UNSIGNED_FLAG);
+}
+
+sal_Int32 SAL_CALL OResultSetMetaData::getPrecision(sal_Int32 column)
+{
+ checkColumnIndex(column);
+ MYSQL_FIELD* pField = getField(column);
+ return pField->max_length - pField->decimals;
+}
+
+sal_Int32 SAL_CALL OResultSetMetaData::getScale(sal_Int32 column)
+{
+ checkColumnIndex(column);
+ MYSQL_FIELD* pField = getField(column);
+ return pField->decimals;
+}
+
+sal_Int32 SAL_CALL OResultSetMetaData::isNullable(sal_Int32 column)
+{
+ checkColumnIndex(column);
+ MYSQL_FIELD* pField = getField(column);
+ return !(pField->flags & NOT_NULL_FLAG);
+}
+
+sal_Bool SAL_CALL OResultSetMetaData::isSearchable(sal_Int32 /*column*/) { return true; }
+
+sal_Bool SAL_CALL OResultSetMetaData::isReadOnly(sal_Int32 column)
+{
+ checkColumnIndex(column);
+ MYSQL_FIELD* pField = getField(column);
+ return !(pField->db && strlen(pField->db));
+}
+
+sal_Bool SAL_CALL OResultSetMetaData::isDefinitelyWritable(sal_Int32 column)
+{
+ checkColumnIndex(column);
+ return !isReadOnly(column);
+}
+
+sal_Bool SAL_CALL OResultSetMetaData::isWritable(sal_Int32 column)
+{
+ checkColumnIndex(column);
+ return !isReadOnly(column);
+}
+
+void OResultSetMetaData::checkColumnIndex(sal_Int32 columnIndex)
+{
+ unsigned nColCount = mysql_num_fields(m_pRes);
+ if (columnIndex < 1 || columnIndex > static_cast<sal_Int32>(nColCount))
+ {
+ rtl::OUStringBuffer buf;
+ buf.append("Column index out of range (expected 1 to ");
+ buf.append(sal_Int32(nColCount));
+ buf.append(", got ");
+ buf.append(columnIndex);
+ buf.append('.');
+ throw SQLException(buf.makeStringAndClear(), *this, rtl::OUString(), 1, Any());
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/mysqlc/mysqlc_resultsetmetadata.hxx b/connectivity/source/drivers/mysqlc/mysqlc_resultsetmetadata.hxx
new file mode 100644
index 000000000000..a78b8c9eb694
--- /dev/null
+++ b/connectivity/source/drivers/mysqlc/mysqlc_resultsetmetadata.hxx
@@ -0,0 +1,109 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef INCLUDED_MYSQLC_SOURCE_MYSQLC_RESULTSETMETADATA_HXX
+#define INCLUDED_MYSQLC_SOURCE_MYSQLC_RESULTSETMETADATA_HXX
+
+#include "mysqlc_connection.hxx"
+
+#include <com/sun/star/sdbc/XResultSetMetaData.hpp>
+#include <com/sun/star/sdbc/XConnection.hpp>
+#include <com/sun/star/sdbc/SQLException.hpp>
+
+#include <cppuhelper/implbase1.hxx>
+#include <mysql.h>
+
+namespace connectivity
+{
+namespace mysqlc
+{
+using ::com::sun::star::sdbc::SQLException;
+using ::com::sun::star::uno::RuntimeException;
+using ::com::sun::star::uno::RuntimeException;
+
+//************ Class: ResultSetMetaData
+
+typedef ::cppu::WeakImplHelper1<css::sdbc::XResultSetMetaData> OResultSetMetaData_BASE;
+
+class OResultSetMetaData final : public OResultSetMetaData_BASE
+{
+private:
+ OConnection& m_rConnection;
+ MYSQL_RES* m_pRes;
+ rtl_TextEncoding m_encoding;
+
+ virtual ~OResultSetMetaData() override = default;
+ MYSQL_FIELD* getField(sal_Int32 column) const;
+
+public:
+ OResultSetMetaData(OConnection& rConn, MYSQL_RES* pResult, rtl_TextEncoding _encoding)
+ : m_rConnection(rConn)
+ , m_pRes(pResult)
+ , m_encoding(_encoding)
+ {
+ }
+
+ rtl::OUString convert(const ::std::string& _string) const
+ {
+ return rtl::OUString(_string.c_str(), _string.size(), m_encoding);
+ }
+
+ sal_Int32 SAL_CALL getColumnCount() SAL_OVERRIDE;
+
+ sal_Bool SAL_CALL isAutoIncrement(sal_Int32 column) SAL_OVERRIDE;
+ sal_Bool SAL_CALL isCaseSensitive(sal_Int32 column) SAL_OVERRIDE;
+ sal_Bool SAL_CALL isSearchable(sal_Int32 column) SAL_OVERRIDE;
+ sal_Bool SAL_CALL isCurrency(sal_Int32 column) SAL_OVERRIDE;
+
+ sal_Int32 SAL_CALL isNullable(sal_Int32 column) SAL_OVERRIDE;
+
+ sal_Bool SAL_CALL isSigned(sal_Int32 column) SAL_OVERRIDE;
+
+ sal_Int32 SAL_CALL getColumnDisplaySize(sal_Int32 column) SAL_OVERRIDE;
+
+ rtl::OUString SAL_CALL getColumnLabel(sal_Int32 column) SAL_OVERRIDE;
+ rtl::OUString SAL_CALL getColumnName(sal_Int32 column) SAL_OVERRIDE;
+ rtl::OUString SAL_CALL getSchemaName(sal_Int32 column) SAL_OVERRIDE;
+
+ sal_Int32 SAL_CALL getPrecision(sal_Int32 column) SAL_OVERRIDE;
+ sal_Int32 SAL_CALL getScale(sal_Int32 column) SAL_OVERRIDE;
+
+ rtl::OUString SAL_CALL getTableName(sal_Int32 column) SAL_OVERRIDE;
+ rtl::OUString SAL_CALL getCatalogName(sal_Int32 column) SAL_OVERRIDE;
+
+ sal_Int32 SAL_CALL getColumnType(sal_Int32 column) SAL_OVERRIDE;
+
+ rtl::OUString SAL_CALL getColumnTypeName(sal_Int32 column) SAL_OVERRIDE;
+
+ sal_Bool SAL_CALL isReadOnly(sal_Int32 column) SAL_OVERRIDE;
+ sal_Bool SAL_CALL isWritable(sal_Int32 column) SAL_OVERRIDE;
+ sal_Bool SAL_CALL isDefinitelyWritable(sal_Int32 column) SAL_OVERRIDE;
+
+ rtl::OUString SAL_CALL getColumnServiceName(sal_Int32 column) SAL_OVERRIDE;
+
+ /// @throws SQLException
+ /// @throws RuntimeException
+ void checkColumnIndex(sal_Int32 columnIndex);
+};
+}
+}
+
+#endif // INCLUDED_MYSQLC_SOURCE_MYSQLC_RESULTSETMETADATA_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/mysqlc/mysqlc_services.cxx b/connectivity/source/drivers/mysqlc/mysqlc_services.cxx
new file mode 100644
index 000000000000..3ddf55e298a0
--- /dev/null
+++ b/connectivity/source/drivers/mysqlc/mysqlc_services.cxx
@@ -0,0 +1,107 @@
+/* -*- 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 "mysqlc_driver.hxx"
+
+#include <cppuhelper/factory.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <uno/lbnames.h>
+
+using namespace connectivity::mysqlc;
+using ::com::sun::star::lang::XMultiServiceFactory;
+using ::com::sun::star::lang::XSingleServiceFactory;
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::Sequence;
+
+typedef Reference<XSingleServiceFactory> (*createFactoryFunc)(
+ const Reference<XMultiServiceFactory>& rServiceManager, const rtl::OUString& rComponentName,
+ ::cppu::ComponentInstantiation pCreateFunction, const Sequence<rtl::OUString>& rServiceNames,
+ rtl_ModuleCount*);
+
+struct ProviderRequest
+{
+ Reference<XSingleServiceFactory> xRet;
+ Reference<XMultiServiceFactory> const xServiceManager;
+ rtl::OUString const sImplementationName;
+
+ ProviderRequest(void* pServiceManager, sal_Char const* pImplementationName)
+ : xServiceManager(static_cast<XMultiServiceFactory*>(pServiceManager))
+ , sImplementationName(rtl::OUString::createFromAscii(pImplementationName))
+ {
+ }
+
+ bool CREATE_PROVIDER(const rtl::OUString& Implname, const Sequence<rtl::OUString>& Services,
+ ::cppu::ComponentInstantiation Factory, createFactoryFunc creator)
+ {
+ if (!xRet.is() && (Implname == sImplementationName))
+ {
+ try
+ {
+ xRet = creator(xServiceManager, sImplementationName, Factory, Services, nullptr);
+ }
+ catch (...)
+ {
+ }
+ }
+ return xRet.is();
+ }
+
+ void* getProvider() const { return xRet.get(); }
+};
+
+extern "C" SAL_DLLPUBLIC_EXPORT void* component_getFactory(const sal_Char* pImplementationName,
+ void* pServiceManager,
+ void* /* pRegistryKey */)
+{
+ void* pRet = nullptr;
+ if (pServiceManager)
+ {
+ ProviderRequest aReq(pServiceManager, pImplementationName);
+
+ aReq.CREATE_PROVIDER(MysqlCDriver::getImplementationName_Static(),
+ MysqlCDriver::getSupportedServiceNames_Static(),
+ MysqlCDriver_CreateInstance, ::cppu::createSingleFactory);
+
+ if (aReq.xRet.is())
+ {
+ aReq.xRet->acquire();
+ }
+
+ pRet = aReq.getProvider();
+ }
+
+ return pRet;
+};
+
+extern "C" SAL_DLLPUBLIC_EXPORT void
+component_getImplementationEnvironment(char const** ppEnvTypeName, uno_Environment**)
+{
+ *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME;
+}
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: noet sw=4 ts=4 fdm=marker
+ * vim<600: noet sw=4 ts=4
+ */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/mysqlc/mysqlc_statement.cxx b/connectivity/source/drivers/mysqlc/mysqlc_statement.cxx
new file mode 100644
index 000000000000..97cd50969879
--- /dev/null
+++ b/connectivity/source/drivers/mysqlc/mysqlc_statement.cxx
@@ -0,0 +1,361 @@
+/* -*- 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 <memory>
+#include <stdio.h>
+
+#include "mysqlc_connection.hxx"
+#include "mysqlc_propertyids.hxx"
+#include "mysqlc_resultset.hxx"
+#include "mysqlc_statement.hxx"
+#include "mysqlc_general.hxx"
+
+#include <com/sun/star/lang/DisposedException.hpp>
+#include <com/sun/star/sdbc/FetchDirection.hpp>
+#include <com/sun/star/sdbc/ResultSetConcurrency.hpp>
+#include <com/sun/star/sdbc/ResultSetType.hpp>
+
+#include <cppuhelper/typeprovider.hxx>
+#include <cppuhelper/queryinterface.hxx>
+#include <osl/thread.h>
+
+using namespace connectivity::mysqlc;
+
+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;
+using ::osl::MutexGuard;
+
+OCommonStatement::OCommonStatement(OConnection* _pConnection)
+ : OCommonStatement_IBase(m_aMutex)
+ , OPropertySetHelper(OCommonStatement_IBase::rBHelper)
+ , m_xConnection(_pConnection)
+{
+}
+
+OCommonStatement::~OCommonStatement() {}
+
+void OCommonStatement::disposeResultSet()
+{
+ // free the cursor if alive
+ if (m_pMysqlResult != nullptr)
+ {
+ mysql_free_result(m_pMysqlResult);
+ m_pMysqlResult = nullptr;
+ }
+}
+
+void OCommonStatement::disposing()
+{
+ MutexGuard aGuard(m_aMutex);
+
+ m_xConnection.clear();
+ OCommonStatement_IBase::disposing();
+}
+
+Any SAL_CALL OCommonStatement::queryInterface(const Type& rType)
+{
+ Any aRet = OCommonStatement_IBase::queryInterface(rType);
+ if (!aRet.hasValue())
+ {
+ aRet = OPropertySetHelper::queryInterface(rType);
+ }
+ return aRet;
+}
+
+Sequence<Type> SAL_CALL OCommonStatement::getTypes()
+{
+ ::cppu::OTypeCollection aTypes(cppu::UnoType<XMultiPropertySet>::get(),
+ cppu::UnoType<XFastPropertySet>::get(),
+ cppu::UnoType<XPropertySet>::get());
+
+ return concatSequences(aTypes.getTypes(), OCommonStatement_IBase::getTypes());
+}
+
+void SAL_CALL OCommonStatement::cancel()
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(rBHelper.bDisposed);
+ // cancel the current sql statement
+}
+
+void SAL_CALL OCommonStatement::close()
+{
+ /*
+ We need a block for the checkDisposed call.
+ After the check we can call dispose() as we are not under lock ??
+ */
+ {
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(rBHelper.bDisposed);
+ }
+ dispose();
+ disposeResultSet();
+}
+
+void SAL_CALL OStatement::clearBatch()
+{
+ // if you support batches clear it here
+}
+
+sal_Bool SAL_CALL OCommonStatement::execute(const rtl::OUString& sql)
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(rBHelper.bDisposed);
+ const rtl::OUString sSqlStatement = m_xConnection->transFormPreparedStatement(sql);
+
+ rtl::OString toExec
+ = rtl::OUStringToOString(sSqlStatement, m_xConnection->getConnectionSettings().encoding);
+
+ MYSQL* pMySql = m_xConnection->getMysqlConnection();
+
+ // NOTE: differs from MySQL C API, where mysql_real_escape_string_quote()
+ // should be used.
+ // toExec = mysqlc_sdbc_driver::escapeSql(toExec);
+ int failure = mysql_real_query(pMySql, toExec.getStr(), toExec.getLength());
+
+ if (failure)
+ mysqlc_sdbc_driver::throwSQLExceptionWithMsg(mysql_error(pMySql), mysql_errno(pMySql),
+ *this, m_xConnection->getConnectionEncoding());
+ m_nAffectedRows = mysql_affected_rows(pMySql);
+
+ return !failure;
+}
+
+Reference<XResultSet> SAL_CALL OCommonStatement::executeQuery(const rtl::OUString& sql)
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(rBHelper.bDisposed);
+ const rtl::OUString sSqlStatement
+ = sql; // TODO m_xConnection->transFormPreparedStatement( sql );
+ rtl::OString toExec
+ = rtl::OUStringToOString(sSqlStatement, m_xConnection->getConnectionSettings().encoding);
+
+ MYSQL* pMySql = m_xConnection->getMysqlConnection();
+ // toExec = mysqlc_sdbc_driver::escapeSql(toExec);
+ int failure = mysql_real_query(pMySql, toExec.getStr(), toExec.getLength());
+ if (failure)
+ mysqlc_sdbc_driver::throwSQLExceptionWithMsg(mysql_error(pMySql), mysql_errno(pMySql),
+ *this, m_xConnection->getConnectionEncoding());
+
+ m_pMysqlResult = mysql_store_result(pMySql);
+ if (m_pMysqlResult == nullptr)
+ {
+ mysqlc_sdbc_driver::throwSQLExceptionWithMsg(mysql_error(pMySql), mysql_errno(pMySql),
+ *this, m_xConnection->getConnectionEncoding());
+ }
+
+ m_xResultSet = new OResultSet(*getOwnConnection(), this, m_pMysqlResult,
+ m_xConnection->getConnectionEncoding());
+ return m_xResultSet;
+}
+
+Reference<XConnection> SAL_CALL OCommonStatement::getConnection()
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(rBHelper.bDisposed);
+
+ // just return our connection here
+ return m_xConnection.get();
+}
+
+sal_Int32 SAL_CALL OCommonStatement::getUpdateCount() { return m_nAffectedRows; }
+
+Any SAL_CALL OStatement::queryInterface(const Type& rType)
+{
+ Any aRet = ::cppu::queryInterface(rType, static_cast<XBatchExecution*>(this));
+ if (!aRet.hasValue())
+ {
+ aRet = OCommonStatement::queryInterface(rType);
+ }
+ return aRet;
+}
+
+void SAL_CALL OStatement::addBatch(const rtl::OUString&)
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(rBHelper.bDisposed);
+}
+
+Sequence<sal_Int32> SAL_CALL OStatement::executeBatch()
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(rBHelper.bDisposed);
+
+ Sequence<sal_Int32> aRet = Sequence<sal_Int32>();
+ return aRet;
+}
+
+sal_Int32 SAL_CALL OCommonStatement::executeUpdate(const rtl::OUString& sql)
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(rBHelper.bDisposed);
+
+ execute(sql);
+ return m_nAffectedRows;
+}
+
+Reference<XResultSet> SAL_CALL OCommonStatement::getResultSet()
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(rBHelper.bDisposed);
+
+ return m_xResultSet;
+}
+
+sal_Bool SAL_CALL OCommonStatement::getMoreResults()
+{
+ return false; // TODO IMPL
+}
+
+Any SAL_CALL OCommonStatement::getWarnings()
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(rBHelper.bDisposed);
+
+ return makeAny(m_aLastWarning);
+}
+
+void SAL_CALL OCommonStatement::clearWarnings()
+{
+ MutexGuard aGuard(m_aMutex);
+ checkDisposed(rBHelper.bDisposed);
+
+ m_aLastWarning = SQLWarning();
+}
+
+::cppu::IPropertyArrayHelper* OCommonStatement::createArrayHelper() const
+{
+ // this properties are define by the service statement
+ // they must in alphabetic order
+ Sequence<Property> aProps(10);
+ Property* pProperties = aProps.getArray();
+ sal_Int32 nPos = 0;
+ pProperties[nPos++]
+ = Property("CursorName", PROPERTY_ID_CURSORNAME, cppu::UnoType<rtl::OUString>::get(), 0);
+ pProperties[nPos++]
+ = Property("EscapeProcessing", PROPERTY_ID_ESCAPEPROCESSING, cppu::UnoType<bool>::get(), 0);
+ pProperties[nPos++] = Property("FetchDirection", PROPERTY_ID_FETCHDIRECTION,
+ cppu::UnoType<sal_Int32>::get(), 0);
+ pProperties[nPos++]
+ = Property("FetchSize", PROPERTY_ID_FETCHSIZE, cppu::UnoType<sal_Int32>::get(), 0);
+ pProperties[nPos++]
+ = Property("MaxFieldSize", PROPERTY_ID_MAXFIELDSIZE, cppu::UnoType<sal_Int32>::get(), 0);
+ pProperties[nPos++]
+ = Property("MaxRows", PROPERTY_ID_MAXROWS, cppu::UnoType<sal_Int32>::get(), 0);
+ pProperties[nPos++]
+ = Property("QueryTimeOut", PROPERTY_ID_QUERYTIMEOUT, cppu::UnoType<sal_Int32>::get(), 0);
+ pProperties[nPos++] = Property("ResultSetConcurrency", PROPERTY_ID_RESULTSETCONCURRENCY,
+ cppu::UnoType<sal_Int32>::get(), 0);
+ pProperties[nPos++]
+ = Property("ResultSetType", PROPERTY_ID_RESULTSETTYPE, cppu::UnoType<sal_Int32>::get(), 0);
+ pProperties[nPos++]
+ = Property("UseBookmarks", PROPERTY_ID_USEBOOKMARKS, cppu::UnoType<bool>::get(), 0);
+
+ return new ::cppu::OPropertyArrayHelper(aProps);
+}
+
+::cppu::IPropertyArrayHelper& OCommonStatement::getInfoHelper() { return *getArrayHelper(); }
+
+sal_Bool OCommonStatement::convertFastPropertyValue(Any& /* rConvertedValue */,
+ Any& /* rOldValue */, sal_Int32 /* nHandle */,
+ const Any& /* rValue */)
+{
+ // here we have to try to convert
+ return false;
+}
+
+void OCommonStatement::setFastPropertyValue_NoBroadcast(sal_Int32 nHandle, const Any& /* rValue */)
+{
+ // set the value to what ever is necessary
+ switch (nHandle)
+ {
+ case PROPERTY_ID_QUERYTIMEOUT:
+ case PROPERTY_ID_MAXFIELDSIZE:
+ case PROPERTY_ID_MAXROWS:
+ case PROPERTY_ID_CURSORNAME:
+ case PROPERTY_ID_RESULTSETCONCURRENCY:
+ case PROPERTY_ID_RESULTSETTYPE:
+ case PROPERTY_ID_FETCHDIRECTION:
+ case PROPERTY_ID_FETCHSIZE:
+ case PROPERTY_ID_ESCAPEPROCESSING:
+ case PROPERTY_ID_USEBOOKMARKS:
+ default:;
+ }
+}
+
+void OCommonStatement::getFastPropertyValue(Any& _rValue, sal_Int32 nHandle) const
+{
+ switch (nHandle)
+ {
+ case PROPERTY_ID_QUERYTIMEOUT:
+ case PROPERTY_ID_MAXFIELDSIZE:
+ case PROPERTY_ID_MAXROWS:
+ case PROPERTY_ID_CURSORNAME:
+ case PROPERTY_ID_RESULTSETCONCURRENCY:
+ case PROPERTY_ID_RESULTSETTYPE:
+ case PROPERTY_ID_FETCHDIRECTION:
+ case PROPERTY_ID_FETCHSIZE:
+ case PROPERTY_ID_ESCAPEPROCESSING:
+ break;
+ case PROPERTY_ID_USEBOOKMARKS:
+ _rValue <<= false;
+ break;
+ default:;
+ }
+}
+
+rtl::OUString OStatement::getImplementationName()
+{
+ return rtl::OUString("com.sun.star.sdbcx.OStatement");
+}
+
+css::uno::Sequence<rtl::OUString> OStatement::getSupportedServiceNames()
+{
+ css::uno::Sequence<rtl::OUString> s(1);
+ s[0] = "com.sun.star.sdbc.Statement";
+ return s;
+}
+
+sal_Bool OStatement::supportsService(rtl::OUString const& ServiceName)
+{
+ return cppu::supportsService(this, ServiceName);
+}
+
+void SAL_CALL OCommonStatement::acquire() throw() { OCommonStatement_IBase::acquire(); }
+
+void SAL_CALL OCommonStatement::release() throw() { OCommonStatement_IBase::release(); }
+
+void SAL_CALL OStatement::acquire() throw() { OCommonStatement::acquire(); }
+
+void SAL_CALL OStatement::release() throw() { OCommonStatement::release(); }
+
+Reference<css::beans::XPropertySetInfo> SAL_CALL OCommonStatement::getPropertySetInfo()
+{
+ return ::cppu::OPropertySetHelper::createPropertySetInfo(getInfoHelper());
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/mysqlc/mysqlc_statement.hxx b/connectivity/source/drivers/mysqlc/mysqlc_statement.hxx
new file mode 100644
index 000000000000..154b104beea3
--- /dev/null
+++ b/connectivity/source/drivers/mysqlc/mysqlc_statement.hxx
@@ -0,0 +1,185 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef INCLUDED_MYSQLC_SOURCE_MYSQLC_STATEMENT_HXX
+#define INCLUDED_MYSQLC_SOURCE_MYSQLC_STATEMENT_HXX
+
+#include "mysqlc_connection.hxx"
+#include "mysqlc_subcomponent.hxx"
+
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/sdbc/SQLWarning.hpp>
+#include <com/sun/star/sdbc/XBatchExecution.hpp>
+#include <com/sun/star/sdbc/XCloseable.hpp>
+#include <com/sun/star/sdbc/XMultipleResults.hpp>
+#include <com/sun/star/sdbc/XStatement.hpp>
+#include <com/sun/star/sdbc/XWarningsSupplier.hpp>
+#include <com/sun/star/util/XCancellable.hpp>
+
+#include <cppuhelper/compbase5.hxx>
+#include <rtl/ref.hxx>
+
+namespace connectivity
+{
+namespace mysqlc
+{
+using ::com::sun::star::sdbc::SQLException;
+using ::com::sun::star::sdbc::SQLWarning;
+using ::com::sun::star::uno::Any;
+using ::com::sun::star::uno::RuntimeException;
+
+typedef ::cppu::WeakComponentImplHelper5<css::sdbc::XStatement, css::sdbc::XWarningsSupplier,
+ css::util::XCancellable, css::sdbc::XCloseable,
+ css::sdbc::XMultipleResults>
+ OCommonStatement_IBase;
+
+//************ Class: OCommonStatement
+// is a base class for the normal statement and for the prepared statement
+
+class OCommonStatement : public OBase_Mutex,
+ public OCommonStatement_IBase,
+ public ::cppu::OPropertySetHelper,
+ public OPropertyArrayUsageHelper<OCommonStatement>
+
+{
+private:
+ SQLWarning m_aLastWarning;
+
+protected:
+ rtl::Reference<OConnection> m_xConnection; // The owning Connection object
+
+ css::uno::Reference<css::sdbc::XResultSet> m_xResultSet;
+ MYSQL_RES* m_pMysqlResult = nullptr;
+
+ // number of rows affected by an UPDATE, DELETE or INSERT statement.
+ sal_Int32 m_nAffectedRows = 0;
+
+protected:
+ void disposeResultSet();
+
+ // OPropertyArrayUsageHelper
+ ::cppu::IPropertyArrayHelper* createArrayHelper() const SAL_OVERRIDE;
+
+ // OPropertySetHelper
+ ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper() SAL_OVERRIDE;
+ sal_Bool SAL_CALL convertFastPropertyValue(Any& rConvertedValue, Any& rOldValue,
+ sal_Int32 nHandle, const Any& rValue) SAL_OVERRIDE;
+
+ void SAL_CALL setFastPropertyValue_NoBroadcast(sal_Int32 nHandle,
+ const Any& rValue) SAL_OVERRIDE;
+
+ void SAL_CALL getFastPropertyValue(Any& rValue, sal_Int32 nHandle) const SAL_OVERRIDE;
+ virtual ~OCommonStatement() override;
+
+protected:
+ OCommonStatement(OConnection* _pConnection);
+
+public:
+ using OCommonStatement_IBase::rBHelper;
+ using OCommonStatement_IBase::operator css::uno::Reference<css::uno::XInterface>;
+
+ // OComponentHelper
+ void SAL_CALL disposing() SAL_OVERRIDE;
+
+ // XInterface
+ void SAL_CALL release() throw() SAL_OVERRIDE;
+
+ void SAL_CALL acquire() throw() SAL_OVERRIDE;
+
+ // XInterface
+ Any SAL_CALL queryInterface(const css::uno::Type& rType) SAL_OVERRIDE;
+
+ //XTypeProvider
+ css::uno::Sequence<css::uno::Type> SAL_CALL getTypes() SAL_OVERRIDE;
+
+ // XPropertySet
+ css::uno::Reference<css::beans::XPropertySetInfo> SAL_CALL getPropertySetInfo() SAL_OVERRIDE;
+
+ // XStatement
+ css::uno::Reference<css::sdbc::XResultSet>
+ SAL_CALL executeQuery(const rtl::OUString& sql) SAL_OVERRIDE;
+
+ sal_Int32 SAL_CALL executeUpdate(const rtl::OUString& sql) SAL_OVERRIDE;
+
+ sal_Bool SAL_CALL execute(const rtl::OUString& sql) SAL_OVERRIDE;
+
+ css::uno::Reference<css::sdbc::XConnection> SAL_CALL getConnection() SAL_OVERRIDE;
+
+ // XWarningsSupplier
+ Any SAL_CALL getWarnings() SAL_OVERRIDE;
+
+ void SAL_CALL clearWarnings() SAL_OVERRIDE;
+
+ // XCancellable
+ void SAL_CALL cancel() SAL_OVERRIDE;
+
+ // XCloseable
+ void SAL_CALL close() SAL_OVERRIDE;
+
+ // XMultipleResults
+ css::uno::Reference<css::sdbc::XResultSet> SAL_CALL getResultSet() SAL_OVERRIDE;
+
+ sal_Int32 SAL_CALL getUpdateCount() SAL_OVERRIDE;
+
+ sal_Bool SAL_CALL getMoreResults() SAL_OVERRIDE;
+
+ // other methods
+ OConnection* getOwnConnection() const { return m_xConnection.get(); }
+
+private:
+ using ::cppu::OPropertySetHelper::getFastPropertyValue;
+};
+
+class OStatement final : public OCommonStatement,
+ public css::sdbc::XBatchExecution,
+ public css::lang::XServiceInfo
+
+{
+ virtual ~OStatement() override = default;
+
+public:
+ // A constructor which is required for the return of the objects
+ OStatement(OConnection* _pConnection)
+ : OCommonStatement(_pConnection)
+ {
+ }
+
+ virtual rtl::OUString SAL_CALL getImplementationName() SAL_OVERRIDE;
+
+ virtual sal_Bool SAL_CALL supportsService(rtl::OUString const& ServiceName) SAL_OVERRIDE;
+
+ virtual css::uno::Sequence<rtl::OUString> SAL_CALL getSupportedServiceNames() SAL_OVERRIDE;
+
+ Any SAL_CALL queryInterface(const css::uno::Type& rType) SAL_OVERRIDE;
+
+ void SAL_CALL acquire() throw() SAL_OVERRIDE;
+ void SAL_CALL release() throw() SAL_OVERRIDE;
+
+ // XBatchExecution
+ void SAL_CALL addBatch(const rtl::OUString& sql) SAL_OVERRIDE;
+
+ void SAL_CALL clearBatch() SAL_OVERRIDE;
+
+ css::uno::Sequence<sal_Int32> SAL_CALL executeBatch() SAL_OVERRIDE;
+};
+}
+}
+#endif // INCLUDED_MYSQLC_SOURCE_MYSQLC_STATEMENT_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/mysqlc/mysqlc_subcomponent.hxx b/connectivity/source/drivers/mysqlc/mysqlc_subcomponent.hxx
new file mode 100644
index 000000000000..9e27cd3596cb
--- /dev/null
+++ b/connectivity/source/drivers/mysqlc/mysqlc_subcomponent.hxx
@@ -0,0 +1,164 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef INCLUDED_MYSQLC_SOURCE_MYSQLC_SUBCOMPONENT_HXX
+#define INCLUDED_MYSQLC_SOURCE_MYSQLC_SUBCOMPONENT_HXX
+
+#include <com/sun/star/lang/DisposedException.hpp>
+#include <cppuhelper/interfacecontainer.h>
+#include <cppuhelper/propshlp.hxx>
+#include <cppuhelper/supportsservice.hxx>
+#include <cppuhelper/weak.hxx>
+#include <osl/diagnose.h>
+#include <osl/mutex.hxx>
+
+namespace cppu
+{
+class IPropertyArrayHelper;
+}
+
+namespace com
+{
+namespace sun
+{
+namespace star
+{
+namespace lang
+{
+class XComponent;
+}
+}
+}
+}
+
+namespace connectivity
+{
+namespace mysqlc
+{
+/// @throws css::lang::DisposedException
+void checkDisposed(bool _bThrow);
+
+template <class TYPE> class OPropertyArrayUsageHelper
+{
+protected:
+ static sal_Int32 s_nRefCount;
+ static ::cppu::IPropertyArrayHelper* s_pProps;
+ static ::osl::Mutex s_aMutex;
+
+public:
+ OPropertyArrayUsageHelper();
+ virtual ~OPropertyArrayUsageHelper();
+
+ /** call this in the getInfoHelper method of your derived class. The method returns the array helper of the
+ class, which is created if necessary.
+ */
+ ::cppu::IPropertyArrayHelper* getArrayHelper();
+
+protected:
+ /** used to implement the creation of the array helper which is shared amongst all instances of the class.
+ This method needs to be implemented in derived classes.
+ <BR>
+ The method gets called with s_aMutex acquired.
+ @return an pointer to the newly created array helper. Must not be NULL.
+ */
+ virtual ::cppu::IPropertyArrayHelper* createArrayHelper() const = 0;
+};
+
+template <class TYPE> sal_Int32 OPropertyArrayUsageHelper<TYPE>::s_nRefCount = 0;
+
+template <class TYPE>
+::cppu::IPropertyArrayHelper* OPropertyArrayUsageHelper<TYPE>::s_pProps = nullptr;
+
+template <class TYPE>::osl::Mutex OPropertyArrayUsageHelper<TYPE>::s_aMutex;
+
+template <class TYPE> OPropertyArrayUsageHelper<TYPE>::OPropertyArrayUsageHelper()
+{
+ ::osl::MutexGuard aGuard(s_aMutex);
+ ++s_nRefCount;
+}
+
+template <class TYPE> OPropertyArrayUsageHelper<TYPE>::~OPropertyArrayUsageHelper()
+{
+ ::osl::MutexGuard aGuard(s_aMutex);
+ OSL_ENSURE(s_nRefCount > 0, "OPropertyArrayUsageHelper::~OPropertyArrayUsageHelper : "
+ "suspicious call : have a refcount of 0 !");
+ if (!--s_nRefCount)
+ {
+ delete s_pProps;
+ s_pProps = nullptr;
+ }
+}
+
+template <class TYPE>::cppu::IPropertyArrayHelper* OPropertyArrayUsageHelper<TYPE>::getArrayHelper()
+{
+ OSL_ENSURE(
+ s_nRefCount,
+ "OPropertyArrayUsageHelper::getArrayHelper : suspicious call : have a refcount of 0 !");
+ if (!s_pProps)
+ {
+ ::osl::MutexGuard aGuard(s_aMutex);
+ if (!s_pProps)
+ {
+ s_pProps = createArrayHelper();
+ OSL_ENSURE(s_pProps, "OPropertyArrayUsageHelper::getArrayHelper : createArrayHelper "
+ "returned nonsense !");
+ }
+ }
+ return s_pProps;
+}
+
+class OBase_Mutex
+{
+public:
+ ::osl::Mutex m_aMutex;
+};
+
+namespace internal
+{
+template <class T> void implCopySequence(const T* _pSource, T*& _pDest, sal_Int32 _nSourceLen)
+{
+ for (sal_Int32 i = 0; i < _nSourceLen; ++i, ++_pSource, ++_pDest)
+ *_pDest = *_pSource;
+}
+}
+
+/// concat two sequences
+template <class T>
+css::uno::Sequence<T> concatSequences(const css::uno::Sequence<T>& _rLeft,
+ const css::uno::Sequence<T>& _rRight)
+{
+ sal_Int32 nLeft(_rLeft.getLength()), nRight(_rRight.getLength());
+ const T* pLeft = _rLeft.getConstArray();
+ const T* pRight = _rRight.getConstArray();
+
+ sal_Int32 nReturnLen(nLeft + nRight);
+ css::uno::Sequence<T> aReturn(nReturnLen);
+ T* pReturn = aReturn.getArray();
+
+ internal::implCopySequence(pLeft, pReturn, nLeft);
+ internal::implCopySequence(pRight, pReturn, nRight);
+
+ return aReturn;
+}
+}
+}
+
+#endif // INCLUDED_MYSQLC_SOURCE_MYSQLC_SUBCOMPONENT_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/mysqlc/mysqlc_types.cxx b/connectivity/source/drivers/mysqlc/mysqlc_types.cxx
new file mode 100644
index 000000000000..b79c7ce8431f
--- /dev/null
+++ b/connectivity/source/drivers/mysqlc/mysqlc_types.cxx
@@ -0,0 +1,680 @@
+/* -*- 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 <stdio.h>
+#include <com/sun/star/sdbc/DataType.hpp>
+#include <com/sun/star/sdbc/ColumnValue.hpp>
+#include <com/sun/star/sdbc/ColumnSearch.hpp>
+#include "mysqlc_types.hxx"
+
+using namespace com::sun::star::sdbc;
+
+TypeInfoDef mysqlc_types[] = {
+
+ // ------------- MySQL-Type: BIT. SDBC-Type: Bit -------------
+ {
+ "BIT", // Typename
+ com::sun::star::sdbc::DataType::BIT, // sdbc-type
+ 1, // Precision
+ "", // Literal prefix
+ "", // Literal suffix
+ "", // Create params
+ com::sun::star::sdbc::ColumnValue::NULLABLE, // nullable
+ true, // case sensitive
+ com::sun::star::sdbc::ColumnSearch::FULL, // searchable
+ false, // unsignable
+ false, // fixed_prec_scale
+ false, // auto_increment
+ "BIT", // local type name
+ 0, // minimum scale
+ 0 // maximum scale
+ },
+
+ // ------------ MySQL-Type: BOOL. SDBC-Type: Bit -------------
+ {
+ "BOOL", // Typename
+ com::sun::star::sdbc::DataType::BIT, // sdbc-type
+ 1, // Precision
+ "", // Literal prefix
+ "", // Literal suffix
+ "", // Create params
+ com::sun::star::sdbc::ColumnValue::NULLABLE, // nullable
+ true, // case sensitive
+ com::sun::star::sdbc::ColumnSearch::FULL, // searchable
+ false, // unsignable
+ false, // fixed_prec_scale
+ false, // auto_increment
+ "BOOL", // local type name
+ 0, // minimum scale
+ 0 // maximum scale
+ },
+
+ // --------- MySQL-Type: TINYINT SDBC-Type: TINYINT ----------
+ {
+ "TINYINT", // Typename
+ com::sun::star::sdbc::DataType::TINYINT, // sdbc-type
+ 3, // Precision
+ "", // Literal prefix
+ "", // Literal suffix
+ "[(M)] [UNSIGNED] [ZEROFILL]", // Create params
+ com::sun::star::sdbc::ColumnValue::NULLABLE, // nullable
+ false, // case sensitive
+ com::sun::star::sdbc::ColumnSearch::FULL, // searchable
+ true, // unsignable
+ false, // fixed_prec_scale
+ true, // auto_increment
+ "TINYINT", // local type name
+ 0, // minimum scale
+ 0 // maximum scale
+ },
+
+ // ----------- MySQL-Type: BIGINT SDBC-Type: BIGINT ----------
+ {
+ "BIGINT", // Typename
+ com::sun::star::sdbc::DataType::BIGINT, // sdbc-type
+ 19, // Precision
+ "", // Literal prefix
+ "", // Literal suffix
+ "[(M)] [UNSIGNED] [ZEROFILL]", // Create params
+ com::sun::star::sdbc::ColumnValue::NULLABLE, // nullable
+ false, // case sensitive
+ com::sun::star::sdbc::ColumnSearch::FULL, // searchable
+ true, // unsignable
+ false, // fixed_prec_scale
+ true, // auto_increment
+ "BIGINT", // local type name
+ 0, // minimum scale
+ 0 // maximum scale
+ },
+
+ // ----------- MySQL-Type: LONG VARBINARY SDBC-Type: LONGVARBINARY ----------
+ {
+ "LONG VARBINARY", // Typename
+ com::sun::star::sdbc::DataType::LONGVARBINARY, // sdbc-type
+ 16777215, // Precision
+ "'", // Literal prefix
+ "'", // Literal suffix
+ "", // Create params
+ com::sun::star::sdbc::ColumnValue::NULLABLE, // nullable
+ true, // case sensitive
+ com::sun::star::sdbc::ColumnSearch::FULL, // searchable
+ false, // unsignable
+ false, // fixed_prec_scale
+ false, // auto_increment
+ "LONG VARBINARY", // local type name
+ 0, // minimum scale
+ 0 // maximum scale
+ },
+
+ // ----------- MySQL-Type: MEDIUMBLOB SDBC-Type: LONGVARBINARY ----------
+ {
+ "MEDIUMBLOB", // Typename
+ com::sun::star::sdbc::DataType::LONGVARBINARY, // sdbc-type
+ 16777215, // Precision
+ "'", // Literal prefix
+ "'", // Literal suffix
+ "", // Create params
+ com::sun::star::sdbc::ColumnValue::NULLABLE, // nullable
+ true, // case sensitive
+ com::sun::star::sdbc::ColumnSearch::FULL, // searchable
+ false, // unsignable
+ false, // fixed_prec_scale
+ false, // auto_increment
+ "MEDIUMBLOB", // local type name
+ 0, // minimum scale
+ 0 // maximum scale
+ },
+
+ // ----------- MySQL-Type: LONGBLOB SDBC-Type: LONGVARBINARY ----------
+ {
+ "LONGBLOB", // Typename
+ com::sun::star::sdbc::DataType::LONGVARBINARY, // sdbc-type
+ -1, // Precision
+ "'", // Literal prefix
+ "'", // Literal suffix
+ "", // Create params
+ com::sun::star::sdbc::ColumnValue::NULLABLE, // nullable
+ true, // case sensitive
+ com::sun::star::sdbc::ColumnSearch::FULL, // searchable
+ false, // unsignable
+ false, // fixed_prec_scale
+ false, // auto_increment
+ "LONGBLOB", // local type name
+ 0, // minimum scale
+ 0 // maximum scale
+ },
+
+ // ----------- MySQL-Type: BLOB SDBC-Type: LONGVARBINARY ----------
+ {
+ "BLOB", // Typename
+ com::sun::star::sdbc::DataType::LONGVARBINARY, // sdbc-type
+ 0xFFFF, // Precision
+ "'", // Literal prefix
+ "'", // Literal suffix
+ "", // Create params
+ com::sun::star::sdbc::ColumnValue::NULLABLE, // nullable
+ true, // case sensitive
+ com::sun::star::sdbc::ColumnSearch::FULL, // searchable
+ false, // unsignable
+ false, // fixed_prec_scale
+ false, // auto_increment
+ "BLOB", // local type name
+ 0, // minimum scale
+ 0 // maximum scale
+ },
+
+ // ----------- MySQL-Type: TINYBLOB SDBC-Type: LONGVARBINARY ----------
+ {
+ "TINYBLOB", // Typename
+ com::sun::star::sdbc::DataType::LONGVARBINARY, // sdbc-type
+ 0xFF, // Precision
+ "'", // Literal prefix
+ "'", // Literal suffix
+ "", // Create params
+ com::sun::star::sdbc::ColumnValue::NULLABLE, // nullable
+ true, // case sensitive
+ com::sun::star::sdbc::ColumnSearch::FULL, // searchable
+ false, // unsignable
+ false, // fixed_prec_scale
+ false, // auto_increment
+ "TINYBLOB", // local type name
+ 0, // minimum scale
+ 0 // maximum scale
+ },
+
+ // ----------- MySQL-Type: VARBINARY SDBC-Type: VARBINARY ----------
+ {
+ "VARBINARY", // Typename
+ com::sun::star::sdbc::DataType::VARBINARY, // sdbc-type
+ 0xFF, // Precision
+ "'", // Literal prefix
+ "'", // Literal suffix
+ "(M)", // Create params
+ com::sun::star::sdbc::ColumnValue::NULLABLE, // nullable
+ true, // case sensitive
+ com::sun::star::sdbc::ColumnSearch::FULL, // searchable
+ false, // unsignable
+ false, // fixed_prec_scale
+ false, // auto_increment
+ "VARBINARY", // local type name
+ 0, // minimum scale
+ 0 // maximum scale
+ },
+
+ // ----------- MySQL-Type: BINARY SDBC-Type: BINARY ----------
+ {
+ "BINARY", // Typename
+ com::sun::star::sdbc::DataType::BINARY, // sdbc-type
+ 0xFF, // Precision
+ "'", // Literal prefix
+ "'", // Literal suffix
+ "(M)", // Create params
+ com::sun::star::sdbc::ColumnValue::NULLABLE, // nullable
+ true, // case sensitive
+ com::sun::star::sdbc::ColumnSearch::FULL, // searchable
+ false, // unsignable
+ false, // fixed_prec_scale
+ false, // auto_increment
+ "VARBINARY", // local type name
+ 0, // minimum scale
+ 0 // maximum scale
+ },
+
+ // ----------- MySQL-Type: LONG VARCHAR SDBC-Type: LONG VARCHAR ----------
+ {
+ "LONG VARCHAR", // Typename
+ com::sun::star::sdbc::DataType::LONGVARCHAR, // sdbc-type
+ 0xFFFFFF, // Precision
+ "'", // Literal prefix
+ "'", // Literal suffix
+ "", // Create params
+ com::sun::star::sdbc::ColumnValue::NULLABLE, // nullable
+ false, // case sensitive
+ com::sun::star::sdbc::ColumnSearch::FULL, // searchable
+ false, // unsignable
+ false, // fixed_prec_scale
+ false, // auto_increment
+ "LONG VARCHAR", // local type name
+ 0, // minimum scale
+ 0 // maximum scale
+ },
+
+ // ----------- MySQL-Type: MEDIUMTEXT SDBC-Type: LONG VARCHAR ----------
+ {
+ "MEDIUMTEXT", // Typename
+ com::sun::star::sdbc::DataType::LONGVARCHAR, // sdbc-type
+ 0xFFFFFF, // Precision
+ "'", // Literal prefix
+ "'", // Literal suffix
+ "", // Create params
+ com::sun::star::sdbc::ColumnValue::NULLABLE, // nullable
+ false, // case sensitive
+ com::sun::star::sdbc::ColumnSearch::FULL, // searchable
+ false, // unsignable
+ false, // fixed_prec_scale
+ false, // auto_increment
+ "MEDIUMTEXT", // local type name
+ 0, // minimum scale
+ 0 // maximum scale
+ },
+
+ // ----------- MySQL-Type: LONGTEXT SDBC-Type: LONG VARCHAR ----------
+ {
+ "LONGTEXT", // Typename
+ com::sun::star::sdbc::DataType::LONGVARCHAR, // sdbc-type
+ 0xFFFFFF, // Precision
+ "'", // Literal prefix
+ "'", // Literal suffix
+ "", // Create params
+ com::sun::star::sdbc::ColumnValue::NULLABLE, // nullable
+ false, // case sensitive
+ com::sun::star::sdbc::ColumnSearch::FULL, // searchable
+ false, // unsignable
+ false, // fixed_prec_scale
+ false, // auto_increment
+ "LONGTEXT", // local type name
+ 0, // minimum scale
+ 0 // maximum scale
+ },
+
+ // ----------- MySQL-Type: TEXT SDBC-Type: LONG VARCHAR ----------
+ {
+ "TEXT", // Typename
+ com::sun::star::sdbc::DataType::LONGVARCHAR, // sdbc-type
+ 0xFFFF, // Precision
+ "'", // Literal prefix
+ "'", // Literal suffix
+ "", // Create params
+ com::sun::star::sdbc::ColumnValue::NULLABLE, // nullable
+ false, // case sensitive
+ com::sun::star::sdbc::ColumnSearch::FULL, // searchable
+ false, // unsignable
+ false, // fixed_prec_scale
+ false, // auto_increment
+ "TEXT", // local type name
+ 0, // minimum scale
+ 0 // maximum scale
+ },
+
+ // ----------- MySQL-Type: TINYTEXT SDBC-Type: LONG VARCHAR ----------
+ {
+ "TINYTEXT", // Typename
+ com::sun::star::sdbc::DataType::LONGVARCHAR, // sdbc-type
+ 0xFF, // Precision
+ "'", // Literal prefix
+ "'", // Literal suffix
+ "", // Create params
+ com::sun::star::sdbc::ColumnValue::NULLABLE, // nullable
+ false, // case sensitive
+ com::sun::star::sdbc::ColumnSearch::FULL, // searchable
+ false, // unsignable
+ false, // fixed_prec_scale
+ false, // auto_increment
+ "TINYTEXT", // local type name
+ 0, // minimum scale
+ 0 // maximum scale
+ },
+
+ // ----------- MySQL-Type: CHAR SDBC-Type: CHAR ----------
+ {
+ "CHAR", // Typename
+ com::sun::star::sdbc::DataType::CHAR, // sdbc-type
+ 0xFF, // Precision
+ "'", // Literal prefix
+ "'", // Literal suffix
+ "(M)", // Create params
+ com::sun::star::sdbc::ColumnValue::NULLABLE, // nullable
+ false, // case sensitive
+ com::sun::star::sdbc::ColumnSearch::FULL, // searchable
+ false, // unsignable
+ false, // fixed_prec_scale
+ false, // auto_increment
+ "NUMERIC", // local type name
+ 0, // minimum scale
+ 0 // maximum scale
+ },
+
+ // ----------- MySQL-Type: DECIMAL SDBC-Type: DECIMAL ----------
+ {
+ "DECIMAL", // Typename
+ com::sun::star::sdbc::DataType::DECIMAL, // sdbc-type
+ 17, // Precision
+ "", // Literal prefix
+ "", // Literal suffix
+ "[(M[,D])] [ZEROFILL]", // Create params
+ com::sun::star::sdbc::ColumnValue::NULLABLE, // nullable
+ false, // case sensitive
+ com::sun::star::sdbc::ColumnSearch::FULL, // searchable
+ false, // unsignable
+ false, // fixed_prec_scale
+ true, // auto_increment
+ "DECIMAL", // local type name
+ -308, // minimum scale
+ 308 // maximum scale
+ },
+
+ // ----------- MySQL-Type: NUMERIC SDBC-Type: NUMERIC ----------
+ {
+ "NUMERIC", // Typename
+ com::sun::star::sdbc::DataType::NUMERIC, // sdbc-type
+ 17, // Precision
+ "", // Literal prefix
+ "", // Literal suffix
+ "[(M[,D])] [ZEROFILL]", // Create params
+ com::sun::star::sdbc::ColumnValue::NULLABLE, // nullable
+ false, // case sensitive
+ com::sun::star::sdbc::ColumnSearch::FULL, // searchable
+ false, // unsignable
+ false, // fixed_prec_scale
+ true, // auto_increment
+ "NUMERIC", // local type name
+ -308, // minimum scale
+ 308 // maximum scale
+ },
+
+ // ----------- MySQL-Type: INTEGER SDBC-Type: INTEGER ----------
+ {
+ "INTEGER", // Typename
+ com::sun::star::sdbc::DataType::INTEGER, // sdbc-type
+ 10, // Precision
+ "", // Literal prefix
+ "", // Literal suffix
+ "[(M)] [UNSIGNED] [ZEROFILL]", // Create params
+ com::sun::star::sdbc::ColumnValue::NULLABLE, // nullable
+ false, // case sensitive
+ com::sun::star::sdbc::ColumnSearch::FULL, // searchable
+ true, // unsignable
+ false, // fixed_prec_scale
+ true, // auto_increment
+ "INTEGER", // local type name
+ 0, // minimum scale
+ 0 // maximum scale
+ },
+
+ // ----------- MySQL-Type: INT SDBC-Type: INTEGER ----------
+ {
+ "INT", // Typename
+ com::sun::star::sdbc::DataType::INTEGER, // sdbc-type
+ 10, // Precision
+ "", // Literal prefix
+ "", // Literal suffix
+ "[(M)] [UNSIGNED] [ZEROFILL]", // Create params
+ com::sun::star::sdbc::ColumnValue::NULLABLE, // nullable
+ false, // case sensitive
+ com::sun::star::sdbc::ColumnSearch::FULL, // searchable
+ true, // unsignable
+ false, // fixed_prec_scale
+ true, // auto_increment
+ "INT", // local type name
+ 0, // minimum scale
+ 0 // maximum scale
+ },
+
+ // ----------- MySQL-Type: MEDIUMINT SDBC-Type: INTEGER ----------
+ {
+ "MEDIUMINT", // Typename
+ com::sun::star::sdbc::DataType::INTEGER, // sdbc-type
+ 7, // Precision
+ "", // Literal prefix
+ "", // Literal suffix
+ "[(M)] [UNSIGNED] [ZEROFILL]", // Create params
+ com::sun::star::sdbc::ColumnValue::NULLABLE, // nullable
+ false, // case sensitive
+ com::sun::star::sdbc::ColumnSearch::FULL, // searchable
+ true, // unsignable
+ false, // fixed_prec_scale
+ true, // auto_increment
+ "MEDIUMINT", // local type name
+ 0, // minimum scale
+ 0 // maximum scale
+ },
+
+ // ----------- MySQL-Type: SMALLINT SDBC-Type: INTEGER ----------
+ {
+ "SMALLINT", // Typename
+ com::sun::star::sdbc::DataType::SMALLINT, // sdbc-type
+ 5, // Precision
+ "", // Literal prefix
+ "", // Literal suffix
+ "[(M)] [UNSIGNED] [ZEROFILL]", // Create params
+ com::sun::star::sdbc::ColumnValue::NULLABLE, // nullable
+ false, // case sensitive
+ com::sun::star::sdbc::ColumnSearch::FULL, // searchable
+ true, // unsignable
+ false, // fixed_prec_scale
+ true, // auto_increment
+ "SMALLINT", // local type name
+ 0, // minimum scale
+ 0 // maximum scale
+ },
+
+ // ----------- MySQL-Type: FLOAT SDBC-Type: REAL ----------
+ {
+ "FLOAT", // Typename
+ com::sun::star::sdbc::DataType::REAL, // sdbc-type
+ 10, // Precision
+ "", // Literal prefix
+ "", // Literal suffix
+ "[(M,D)] [ZEROFILL]", // Create params
+ com::sun::star::sdbc::ColumnValue::NULLABLE, // nullable
+ false, // case sensitive
+ com::sun::star::sdbc::ColumnSearch::FULL, // searchable
+ false, // unsignable
+ false, // fixed_prec_scale
+ true, // auto_increment
+ "FLOAT", // local type name
+ -38, // minimum scale
+ 38 // maximum scale
+ },
+
+ // ----------- MySQL-Type: DOUBLE SDBC-Type: DOUBLE ----------
+ {
+ "DOUBLE", // Typename
+ com::sun::star::sdbc::DataType::DOUBLE, // sdbc-type
+ 17, // Precision
+ "", // Literal prefix
+ "", // Literal suffix
+ "[(M,D)] [ZEROFILL]", // Create params
+ com::sun::star::sdbc::ColumnValue::NULLABLE, // nullable
+ false, // case sensitive
+ com::sun::star::sdbc::ColumnSearch::FULL, // searchable
+ false, // unsignable
+ false, // fixed_prec_scale
+ true, // auto_increment
+ "DOUBLE", // local type name
+ -308, // minimum scale
+ 308 // maximum scale
+ },
+
+ // ----------- MySQL-Type: DOUBLE PRECISION SDBC-Type: DOUBLE ----------
+ {
+ "DOUBLE PRECISION", // Typename
+ com::sun::star::sdbc::DataType::DOUBLE, // sdbc-type
+ 17, // Precision
+ "", // Literal prefix
+ "", // Literal suffix
+ "[(M,D)] [ZEROFILL]", // Create params
+ com::sun::star::sdbc::ColumnValue::NULLABLE, // nullable
+ false, // case sensitive
+ com::sun::star::sdbc::ColumnSearch::FULL, // searchable
+ false, // unsignable
+ false, // fixed_prec_scale
+ true, // auto_increment
+ "DOUBLE PRECISION", // local type name
+ -308, // minimum scale
+ 308 // maximum scale
+ },
+
+ // ----------- MySQL-Type: REAL SDBC-Type: DOUBLE ----------
+ {
+ "REAL", // Typename
+ com::sun::star::sdbc::DataType::DOUBLE, // sdbc-type
+ 17, // Precision
+ "", // Literal prefix
+ "", // Literal suffix
+ "[(M,D)] [ZEROFILL]", // Create params
+ com::sun::star::sdbc::ColumnValue::NULLABLE, // nullable
+ false, // case sensitive
+ com::sun::star::sdbc::ColumnSearch::FULL, // searchable
+ false, // unsignable
+ false, // fixed_prec_scale
+ true, // auto_increment
+ "REAL", // local type name
+ -308, // minimum scale
+ 308 // maximum scale
+ },
+
+ // ----------- MySQL-Type: VARCHAR SDBC-Type: VARCHAR ----------
+ {
+ "VARCHAR", // Typename
+ com::sun::star::sdbc::DataType::VARCHAR, // sdbc-type
+ 255, // Precision
+ "'", // Literal prefix
+ "'", // Literal suffix
+ "(M)", // Create params
+ com::sun::star::sdbc::ColumnValue::NULLABLE, // nullable
+ false, // case sensitive
+ com::sun::star::sdbc::ColumnSearch::FULL, // searchable
+ false, // unsignable
+ false, // fixed_prec_scale
+ false, // auto_increment
+ "VARCHAR", // local type name
+ 0, // minimum scale
+ 0 // maximum scale
+ },
+
+ // ----------- MySQL-Type: ENUM SDBC-Type: VARCHAR ----------
+ {
+ "ENUM", // Typename
+ com::sun::star::sdbc::DataType::VARCHAR, // sdbc-type
+ 0xFFFF, // Precision
+ "'", // Literal prefix
+ "'", // Literal suffix
+ "", // Create params
+ com::sun::star::sdbc::ColumnValue::NULLABLE, // nullable
+ false, // case sensitive
+ com::sun::star::sdbc::ColumnSearch::FULL, // searchable
+ false, // unsignable
+ false, // fixed_prec_scale
+ false, // auto_increment
+ "ENUM", // local type name
+ 0, // minimum scale
+ 0 // maximum scale
+ },
+
+ // ----------- MySQL-Type: SET SDBC-Type: VARCHAR ----------
+ {
+ "SET", // Typename
+ com::sun::star::sdbc::DataType::VARCHAR, // sdbc-type
+ 64, // Precision
+ "'", // Literal prefix
+ "'", // Literal suffix
+ "", // Create params
+ com::sun::star::sdbc::ColumnValue::NULLABLE, // nullable
+ false, // case sensitive
+ com::sun::star::sdbc::ColumnSearch::FULL, // searchable
+ false, // unsignable
+ false, // fixed_prec_scale
+ false, // auto_increment
+ "SET", // local type name
+ 0, // minimum scale
+ 0 // maximum scale
+ },
+
+ // ----------- MySQL-Type: DATE SDBC-Type: DATE ----------
+ {
+ "DATE", // Typename
+ com::sun::star::sdbc::DataType::DATE, // sdbc-type
+ 0, // Precision
+ "'", // Literal prefix
+ "'", // Literal suffix
+ "", // Create params
+ com::sun::star::sdbc::ColumnValue::NULLABLE, // nullable
+ false, // case sensitive
+ com::sun::star::sdbc::ColumnSearch::FULL, // searchable
+ false, // unsignable
+ false, // fixed_prec_scale
+ false, // auto_increment
+ "DATE", // local type name
+ 0, // minimum scale
+ 0 // maximum scale
+ },
+
+ // ----------- MySQL-Type: TIME SDBC-Type: TIME ----------
+ {
+ "TIME", // Typename
+ com::sun::star::sdbc::DataType::TIME, // sdbc-type
+ 0, // Precision
+ "'", // Literal prefix
+ "'", // Literal suffix
+ "", // Create params
+ com::sun::star::sdbc::ColumnValue::NULLABLE, // nullable
+ false, // case sensitive
+ com::sun::star::sdbc::ColumnSearch::FULL, // searchable
+ false, // unsignable
+ false, // fixed_prec_scale
+ false, // auto_increment
+ "TIME", // local type name
+ 0, // minimum scale
+ 0 // maximum scale
+ },
+
+ // ----------- MySQL-Type: DATETIME SDBC-Type: TIMESTAMP ----------
+ {
+ "DATETIME", // Typename
+ com::sun::star::sdbc::DataType::TIMESTAMP, // sdbc-type
+ 0, // Precision
+ "'", // Literal prefix
+ "'", // Literal suffix
+ "", // Create params
+ com::sun::star::sdbc::ColumnValue::NULLABLE, // nullable
+ false, // case sensitive
+ com::sun::star::sdbc::ColumnSearch::FULL, // searchable
+ false, // unsignable
+ false, // fixed_prec_scale
+ false, // auto_increment
+ "DATETIME", // local type name
+ 0, // minimum scale
+ 0 // maximum scale
+ },
+
+ // ----------- MySQL-Type: TIMESTAMP SDBC-Type: TIMESTAMP ----------
+ {
+ "TIMESTAMP", // Typename
+ com::sun::star::sdbc::DataType::TIMESTAMP, // sdbc-type
+ 0, // Precision
+ "'", // Literal prefix
+ "'", // Literal suffix
+ "[(M)]", // Create params
+ com::sun::star::sdbc::ColumnValue::NULLABLE, // nullable
+ false, // case sensitive
+ com::sun::star::sdbc::ColumnSearch::FULL, // searchable
+ false, // unsignable
+ false, // fixed_prec_scale
+ false, // auto_increment
+ "TIMESTAMP", // local type name
+ 0, // minimum scale
+ 0 // maximum scale
+ },
+
+ // ----------- MySQL-Type: TIMESTAMP SDBC-Type: TIMESTAMP ----------
+ { nullptr, 0, 0, nullptr, nullptr, nullptr, 0, false, 0, false, false, false, nullptr, 0, 0 }
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/connectivity/source/drivers/mysqlc/mysqlc_types.hxx b/connectivity/source/drivers/mysqlc/mysqlc_types.hxx
new file mode 100644
index 000000000000..54f054d1ba6d
--- /dev/null
+++ b/connectivity/source/drivers/mysqlc/mysqlc_types.hxx
@@ -0,0 +1,46 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef INCLUDED_MYSQLC_SOURCE_MYSQLC_TYPES_HXX
+#define INCLUDED_MYSQLC_SOURCE_MYSQLC_TYPES_HXX
+
+struct TypeInfoDef
+{
+ const char* typeName;
+ sal_Int32 dataType;
+ sal_Int32 precision;
+ const char* literalPrefix;
+ const char* literalSuffix;
+ const char* createParams;
+ sal_Int16 nullable;
+ bool caseSensitive;
+ sal_Int16 searchable;
+ bool isUnsigned;
+ bool fixedPrecScale;
+ bool autoIncrement;
+ const char* localTypeName;
+ sal_Int32 minScale;
+ sal_Int32 maxScale;
+};
+
+extern TypeInfoDef mysqlc_types[];
+
+#endif // INCLUDED_MYSQLC_SOURCE_MYSQLC_TYPES_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */