bump product version to 7.2.5.1
[LibreOffice.git] / connectivity / source / drivers / mysqlc / mysqlc_statement.cxx
blob6e14d9ec60bc2ddf9e27a7ebb423572e555928e7
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <sal/config.h>
22 #include "mysqlc_connection.hxx"
23 #include "mysqlc_propertyids.hxx"
24 #include "mysqlc_resultset.hxx"
25 #include "mysqlc_statement.hxx"
26 #include "mysqlc_general.hxx"
28 #include <cppuhelper/typeprovider.hxx>
29 #include <cppuhelper/supportsservice.hxx>
31 using namespace connectivity::mysqlc;
33 using namespace com::sun::star::uno;
34 using namespace com::sun::star::lang;
35 using namespace com::sun::star::beans;
36 using namespace com::sun::star::sdbc;
37 using namespace com::sun::star::sdbcx;
38 using namespace com::sun::star::container;
39 using namespace com::sun::star::io;
40 using namespace com::sun::star::util;
41 using ::osl::MutexGuard;
43 OCommonStatement::OCommonStatement(OConnection* _pConnection)
44 : OCommonStatement_IBase(m_aMutex)
45 , OPropertySetHelper(OCommonStatement_IBase::rBHelper)
46 , m_xConnection(_pConnection)
50 OCommonStatement::~OCommonStatement() {}
52 void OCommonStatement::closeResultSet()
54 if (m_xResultSet.is())
56 css::uno::Reference<css::sdbc::XCloseable> xClose(m_xResultSet, UNO_QUERY_THROW);
57 xClose->close();
58 m_xResultSet.clear();
62 void OCommonStatement::disposing()
64 MutexGuard aGuard(m_aMutex);
66 m_xConnection.clear();
67 OCommonStatement_IBase::disposing();
70 Any SAL_CALL OCommonStatement::queryInterface(const Type& rType)
72 Any aRet = OCommonStatement_IBase::queryInterface(rType);
73 if (!aRet.hasValue())
75 aRet = OPropertySetHelper::queryInterface(rType);
77 return aRet;
80 Sequence<Type> SAL_CALL OCommonStatement::getTypes()
82 ::cppu::OTypeCollection aTypes(cppu::UnoType<XMultiPropertySet>::get(),
83 cppu::UnoType<XFastPropertySet>::get(),
84 cppu::UnoType<XPropertySet>::get());
86 return concatSequences(aTypes.getTypes(), OCommonStatement_IBase::getTypes());
89 Sequence<Type> SAL_CALL OStatement::getTypes()
91 return concatSequences(OStatement_BASE::getTypes(), OCommonStatement::getTypes());
94 void SAL_CALL OCommonStatement::cancel()
96 MutexGuard aGuard(m_aMutex);
97 checkDisposed(rBHelper.bDisposed);
98 // cancel the current sql statement
101 void SAL_CALL OCommonStatement::close()
104 We need a block for the checkDisposed call.
105 After the check we can call dispose() as we are not under lock ??
108 MutexGuard aGuard(m_aMutex);
109 checkDisposed(rBHelper.bDisposed);
111 dispose();
112 closeResultSet();
115 // void SAL_CALL OStatement::clearBatch()
116 // {
117 // mysqlc_sdbc_driver::throwFeatureNotImplementedException("com:sun:star:sdbc:XBatchExecution");
118 // }
120 sal_Bool SAL_CALL OStatement::execute(const OUString& sql)
122 MutexGuard aGuard(m_aMutex);
123 checkDisposed(rBHelper.bDisposed);
125 closeResultSet();
126 m_nAffectedRows = -1;
128 OString toExec = OUStringToOString(sql, m_xConnection->getConnectionSettings().encoding);
130 MYSQL* pMySql = m_xConnection->getMysqlConnection();
132 // NOTE: differs from MySQL C API, where mysql_real_escape_string_quote()
133 // should be used.
134 // toExec = mysqlc_sdbc_driver::escapeSql(toExec);
135 int failure = mysql_real_query(pMySql, toExec.getStr(), toExec.getLength());
137 if (failure || mysql_errno(pMySql))
138 mysqlc_sdbc_driver::throwSQLExceptionWithMsg(mysql_error(pMySql), mysql_sqlstate(pMySql),
139 mysql_errno(pMySql), *this,
140 m_xConnection->getConnectionEncoding());
142 return getResult();
145 Reference<XResultSet> SAL_CALL OStatement::executeQuery(const OUString& sql)
147 bool isRS(execute(sql));
148 // if a MySQL error occurred, it was already thrown and the below is not executed
149 assert(isRS == m_xResultSet.is());
150 if (!isRS)
151 mysqlc_sdbc_driver::throwSQLExceptionWithMsg(
152 "executeQuery called on SQL command that does not return a ResultSet", "02000", 0,
153 *this);
154 if (!m_xResultSet.is())
155 mysqlc_sdbc_driver::throwSQLExceptionWithMsg(
156 "internal MySQL-SDBC error: executeQuery: no ResultSet after execute() returned true.",
157 "02000", 0, *this);
159 return m_xResultSet;
162 Reference<XConnection> SAL_CALL OStatement::getConnection()
164 MutexGuard aGuard(m_aMutex);
165 checkDisposed(rBHelper.bDisposed);
167 // just return our connection here
168 return m_xConnection;
171 sal_Int32 SAL_CALL OStatement::getUpdateCount() { return m_nAffectedRows; }
173 Any SAL_CALL OStatement::queryInterface(const Type& rType)
175 Any aRet = OCommonStatement::queryInterface(rType);
176 if (!aRet.hasValue())
178 aRet = OStatement_BASE::queryInterface(rType);
180 return aRet;
183 // void SAL_CALL OStatement::addBatch(const OUString&)
184 // {
185 // MutexGuard aGuard(m_aMutex);
186 // checkDisposed(rBHelper.bDisposed);
188 // mysqlc_sdbc_driver::throwFeatureNotImplementedException("com:sun:star:sdbc:XBatchExecution");
189 // }
191 // Sequence<sal_Int32> SAL_CALL OStatement::executeBatch()
192 // {
193 // MutexGuard aGuard(m_aMutex);
194 // checkDisposed(rBHelper.bDisposed);
196 // mysqlc_sdbc_driver::throwFeatureNotImplementedException("com:sun:star:sdbc:XBatchExecution");
197 // }
199 sal_Int32 SAL_CALL OStatement::executeUpdate(const OUString& sql)
201 MutexGuard aGuard(m_aMutex);
202 checkDisposed(rBHelper.bDisposed);
204 execute(sql);
205 return m_nAffectedRows;
208 Reference<XResultSet> SAL_CALL OStatement::getResultSet()
210 MutexGuard aGuard(m_aMutex);
211 checkDisposed(rBHelper.bDisposed);
213 return m_xResultSet;
216 bool OStatement::getResult()
218 // all callers already reset that
219 assert(!m_xResultSet.is());
220 assert(m_nAffectedRows == -1);
222 MYSQL* pMySql = m_xConnection->getMysqlConnection();
223 MYSQL_RES* pMysqlResult = mysql_store_result(pMySql);
224 if (pMysqlResult != nullptr)
226 // MariaDB/MySQL will return the number of rows in the ResultSet from mysql_affected_rows();
227 // sdbc mandates -1 when the command (query) returns a ResultSet
228 assert(m_nAffectedRows == -1);
229 m_xResultSet = new OResultSet(*getOwnConnection(), this, pMysqlResult,
230 m_xConnection->getConnectionEncoding());
231 return true;
233 else if (mysql_field_count(pMySql) == 0)
235 m_nAffectedRows = mysql_affected_rows(pMySql);
236 return false;
238 else
240 mysqlc_sdbc_driver::throwSQLExceptionWithMsg(
241 "mysql_store_result indicated success and SQL command was supposed to return a "
242 "ResultSet, but did not.",
243 "02000", 0, *this);
245 //unreachable
246 assert(false);
247 // keep -Werror=return-type happy
248 return false;
251 sal_Bool SAL_CALL OStatement::getMoreResults()
253 MutexGuard aGuard(m_aMutex);
254 checkDisposed(rBHelper.bDisposed);
256 closeResultSet();
257 m_nAffectedRows = -1;
259 MYSQL* pMySql = m_xConnection->getMysqlConnection();
260 int status = mysql_next_result(pMySql);
262 if (status > 0 || mysql_errno(pMySql))
263 mysqlc_sdbc_driver::throwSQLExceptionWithMsg(mysql_error(pMySql), mysql_sqlstate(pMySql),
264 mysql_errno(pMySql), *this,
265 m_xConnection->getConnectionEncoding());
267 if (status == -1)
268 return false;
270 if (status != 0)
272 const OUString errMsg("mysql_next_result returned unexpected value: "
273 + OUString::number(status));
274 mysqlc_sdbc_driver::throwSQLExceptionWithMsg(errMsg, "02000", 0, *this);
277 return getResult();
280 Any SAL_CALL OCommonStatement::getWarnings()
282 MutexGuard aGuard(m_aMutex);
283 checkDisposed(rBHelper.bDisposed);
285 return makeAny(m_aLastWarning);
288 void SAL_CALL OCommonStatement::clearWarnings()
290 MutexGuard aGuard(m_aMutex);
291 checkDisposed(rBHelper.bDisposed);
293 m_aLastWarning = SQLWarning();
296 ::cppu::IPropertyArrayHelper* OCommonStatement::createArrayHelper() const
298 // this properties are define by the service statement
299 // they must in alphabetic order
300 Sequence<Property> aProps(10);
301 Property* pProperties = aProps.getArray();
302 sal_Int32 nPos = 0;
303 pProperties[nPos++]
304 = Property("CursorName", PROPERTY_ID_CURSORNAME, cppu::UnoType<OUString>::get(), 0);
305 pProperties[nPos++]
306 = Property("EscapeProcessing", PROPERTY_ID_ESCAPEPROCESSING, cppu::UnoType<bool>::get(), 0);
307 pProperties[nPos++] = Property("FetchDirection", PROPERTY_ID_FETCHDIRECTION,
308 cppu::UnoType<sal_Int32>::get(), 0);
309 pProperties[nPos++]
310 = Property("FetchSize", PROPERTY_ID_FETCHSIZE, cppu::UnoType<sal_Int32>::get(), 0);
311 pProperties[nPos++]
312 = Property("MaxFieldSize", PROPERTY_ID_MAXFIELDSIZE, cppu::UnoType<sal_Int32>::get(), 0);
313 pProperties[nPos++]
314 = Property("MaxRows", PROPERTY_ID_MAXROWS, cppu::UnoType<sal_Int32>::get(), 0);
315 pProperties[nPos++]
316 = Property("QueryTimeOut", PROPERTY_ID_QUERYTIMEOUT, cppu::UnoType<sal_Int32>::get(), 0);
317 pProperties[nPos++] = Property("ResultSetConcurrency", PROPERTY_ID_RESULTSETCONCURRENCY,
318 cppu::UnoType<sal_Int32>::get(), 0);
319 pProperties[nPos++]
320 = Property("ResultSetType", PROPERTY_ID_RESULTSETTYPE, cppu::UnoType<sal_Int32>::get(), 0);
321 pProperties[nPos++]
322 = Property("UseBookmarks", PROPERTY_ID_USEBOOKMARKS, cppu::UnoType<bool>::get(), 0);
324 return new ::cppu::OPropertyArrayHelper(aProps);
327 ::cppu::IPropertyArrayHelper& OCommonStatement::getInfoHelper() { return *getArrayHelper(); }
329 sal_Bool OCommonStatement::convertFastPropertyValue(Any& /* rConvertedValue */,
330 Any& /* rOldValue */, sal_Int32 /* nHandle */,
331 const Any& /* rValue */)
333 // here we have to try to convert
334 return false;
337 void OCommonStatement::setFastPropertyValue_NoBroadcast(sal_Int32 nHandle, const Any& /* rValue */)
339 // set the value to whatever is necessary
340 switch (nHandle)
342 case PROPERTY_ID_QUERYTIMEOUT:
343 case PROPERTY_ID_MAXFIELDSIZE:
344 case PROPERTY_ID_MAXROWS:
345 case PROPERTY_ID_CURSORNAME:
346 case PROPERTY_ID_RESULTSETCONCURRENCY:
347 case PROPERTY_ID_RESULTSETTYPE:
348 case PROPERTY_ID_FETCHDIRECTION:
349 case PROPERTY_ID_FETCHSIZE:
350 case PROPERTY_ID_ESCAPEPROCESSING:
351 case PROPERTY_ID_USEBOOKMARKS:
352 default:;
356 void OCommonStatement::getFastPropertyValue(Any& _rValue, sal_Int32 nHandle) const
358 switch (nHandle)
360 case PROPERTY_ID_QUERYTIMEOUT:
361 case PROPERTY_ID_MAXFIELDSIZE:
362 case PROPERTY_ID_MAXROWS:
363 case PROPERTY_ID_CURSORNAME:
364 case PROPERTY_ID_RESULTSETCONCURRENCY:
365 case PROPERTY_ID_RESULTSETTYPE:
366 case PROPERTY_ID_FETCHDIRECTION:
367 case PROPERTY_ID_FETCHSIZE:
368 case PROPERTY_ID_ESCAPEPROCESSING:
369 break;
370 case PROPERTY_ID_USEBOOKMARKS:
371 _rValue <<= false;
372 break;
373 default:;
377 OUString OStatement::getImplementationName() { return "com.sun.star.sdbcx.OStatement"; }
379 css::uno::Sequence<OUString> OStatement::getSupportedServiceNames()
381 return { "com.sun.star.sdbc.Statement" };
384 sal_Bool OStatement::supportsService(OUString const& ServiceName)
386 return cppu::supportsService(this, ServiceName);
389 void SAL_CALL OCommonStatement::acquire() noexcept { OCommonStatement_IBase::acquire(); }
391 void SAL_CALL OCommonStatement::release() noexcept { OCommonStatement_IBase::release(); }
393 void SAL_CALL OStatement::acquire() noexcept { OCommonStatement::acquire(); }
395 void SAL_CALL OStatement::release() noexcept { OCommonStatement::release(); }
397 Reference<css::beans::XPropertySetInfo> SAL_CALL OCommonStatement::getPropertySetInfo()
399 return ::cppu::OPropertySetHelper::createPropertySetInfo(getInfoHelper());
402 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */