LibreOffice Module connectivity (master) 1
mysqlc_statement.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
20#include <sal/config.h>
21
22#include "mysqlc_connection.hxx"
24#include "mysqlc_resultset.hxx"
25#include "mysqlc_statement.hxx"
26#include "mysqlc_general.hxx"
27
30
31using namespace connectivity::mysqlc;
32
33using namespace com::sun::star::uno;
34using namespace com::sun::star::lang;
35using namespace com::sun::star::beans;
36using namespace com::sun::star::sdbc;
37using namespace com::sun::star::sdbcx;
38using namespace com::sun::star::container;
39using namespace com::sun::star::io;
40using namespace com::sun::star::util;
41using ::osl::MutexGuard;
42
43OCommonStatement::OCommonStatement(OConnection* _pConnection)
46 , m_xConnection(_pConnection)
47{
48}
49
51
53{
54 if (m_xResultSet.is())
55 {
56 css::uno::Reference<css::sdbc::XCloseable> xClose(m_xResultSet, UNO_QUERY_THROW);
57 xClose->close();
58 m_xResultSet.clear();
59 }
60}
61
63{
64 MutexGuard aGuard(m_aMutex);
65
66 m_xConnection.clear();
67 OCommonStatement_IBase::disposing();
68}
69
70Any SAL_CALL OCommonStatement::queryInterface(const Type& rType)
71{
73 if (!aRet.hasValue())
74 {
76 }
77 return aRet;
78}
79
80Sequence<Type> SAL_CALL OCommonStatement::getTypes()
81{
85
87}
88
89Sequence<Type> SAL_CALL OStatement::getTypes()
90{
92}
93
95{
96 MutexGuard aGuard(m_aMutex);
98 // cancel the current sql statement
99}
100
102{
103 /*
104 We need a block for the checkDisposed call.
105 After the check we can call dispose() as we are not under lock ??
106 */
107 {
108 MutexGuard aGuard(m_aMutex);
110 }
111 dispose();
113}
114
115// void SAL_CALL OStatement::clearBatch()
116// {
117// mysqlc_sdbc_driver::throwFeatureNotImplementedException("com:sun:star:sdbc:XBatchExecution");
118// }
119
120sal_Bool SAL_CALL OStatement::execute(const OUString& sql)
121{
122 MutexGuard aGuard(m_aMutex);
124
126 m_nAffectedRows = -1;
127
128 OString toExec = OUStringToOString(sql, m_xConnection->getConnectionSettings().encoding);
129
130 MYSQL* pMySql = m_xConnection->getMysqlConnection();
131
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());
136
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());
141
142 return getResult();
143}
144
145Reference<XResultSet> SAL_CALL OStatement::executeQuery(const OUString& sql)
146{
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)
152 "executeQuery called on SQL command that does not return a ResultSet", "02000", 0,
153 *this);
154 if (!m_xResultSet.is())
156 "internal MySQL-SDBC error: executeQuery: no ResultSet after execute() returned true.",
157 "02000", 0, *this);
158
159 return m_xResultSet;
160}
161
162Reference<XConnection> SAL_CALL OStatement::getConnection()
163{
164 MutexGuard aGuard(m_aMutex);
166
167 // just return our connection here
168 return m_xConnection;
169}
170
171sal_Int32 SAL_CALL OStatement::getUpdateCount() { return m_nAffectedRows; }
172
173Any SAL_CALL OStatement::queryInterface(const Type& rType)
174{
176 if (!aRet.hasValue())
177 {
179 }
180 return aRet;
181}
182
183// void SAL_CALL OStatement::addBatch(const OUString&)
184// {
185// MutexGuard aGuard(m_aMutex);
186// checkDisposed(rBHelper.bDisposed);
187
188// mysqlc_sdbc_driver::throwFeatureNotImplementedException("com:sun:star:sdbc:XBatchExecution");
189// }
190
191// Sequence<sal_Int32> SAL_CALL OStatement::executeBatch()
192// {
193// MutexGuard aGuard(m_aMutex);
194// checkDisposed(rBHelper.bDisposed);
195
196// mysqlc_sdbc_driver::throwFeatureNotImplementedException("com:sun:star:sdbc:XBatchExecution");
197// }
198
199sal_Int32 SAL_CALL OStatement::executeUpdate(const OUString& sql)
200{
201 MutexGuard aGuard(m_aMutex);
203
204 execute(sql);
205 return m_nAffectedRows;
206}
207
208Reference<XResultSet> SAL_CALL OStatement::getResultSet()
209{
210 MutexGuard aGuard(m_aMutex);
212
213 return m_xResultSet;
214}
215
217{
218 // all callers already reset that
219 assert(!m_xResultSet.is());
220 assert(m_nAffectedRows == -1);
221
222 MYSQL* pMySql = m_xConnection->getMysqlConnection();
223 MYSQL_RES* pMysqlResult = mysql_store_result(pMySql);
224 if (pMysqlResult != nullptr)
225 {
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;
232 }
233 else if (mysql_field_count(pMySql) == 0)
234 {
235 m_nAffectedRows = mysql_affected_rows(pMySql);
236 return false;
237 }
238 else
239 {
241 "mysql_store_result indicated success and SQL command was supposed to return a "
242 "ResultSet, but did not.",
243 "02000", 0, *this);
244 }
245 //unreachable
246 assert(false);
247 // keep -Werror=return-type happy
248 return false;
249}
250
252{
253 MutexGuard aGuard(m_aMutex);
255
257 m_nAffectedRows = -1;
258
259 MYSQL* pMySql = m_xConnection->getMysqlConnection();
260 int status = mysql_next_result(pMySql);
261
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());
266
267 if (status == -1)
268 return false;
269
270 if (status != 0)
271 {
272 const OUString errMsg("mysql_next_result returned unexpected value: "
273 + OUString::number(status));
274 mysqlc_sdbc_driver::throwSQLExceptionWithMsg(errMsg, "02000", 0, *this);
275 }
276
277 return getResult();
278}
279
281{
282 MutexGuard aGuard(m_aMutex);
284
285 return Any(m_aLastWarning);
286}
287
289{
290 MutexGuard aGuard(m_aMutex);
292
293 m_aLastWarning = SQLWarning();
294}
295
297{
298 // this properties are define by the service statement
299 // they must in alphabetic order
300 return new ::cppu::OPropertyArrayHelper{
302 { "EscapeProcessing", PROPERTY_ID_ESCAPEPROCESSING, cppu::UnoType<bool>::get(), 0 },
308 { "ResultSetConcurrency", PROPERTY_ID_RESULTSETCONCURRENCY,
311 { "UseBookmarks", PROPERTY_ID_USEBOOKMARKS, cppu::UnoType<bool>::get(), 0 } }
312 };
313}
314
316
318 Any& /* rOldValue */, sal_Int32 /* nHandle */,
319 const Any& /* rValue */)
320{
321 // here we have to try to convert
322 return false;
323}
324
325void OCommonStatement::setFastPropertyValue_NoBroadcast(sal_Int32 nHandle, const Any& /* rValue */)
326{
327 // set the value to whatever is necessary
328 switch (nHandle)
329 {
340 default:;
341 }
342}
343
344void OCommonStatement::getFastPropertyValue(Any& _rValue, sal_Int32 nHandle) const
345{
346 switch (nHandle)
347 {
357 break;
359 _rValue <<= false;
360 break;
361 default:;
362 }
363}
364
365OUString OStatement::getImplementationName() { return "com.sun.star.sdbcx.OStatement"; }
366
367css::uno::Sequence<OUString> OStatement::getSupportedServiceNames()
368{
369 return { "com.sun.star.sdbc.Statement" };
370}
371
372sal_Bool OStatement::supportsService(OUString const& ServiceName)
373{
375}
376
378
380
381void SAL_CALL OStatement::acquire() noexcept { OCommonStatement::acquire(); }
382
383void SAL_CALL OStatement::release() noexcept { OCommonStatement::release(); }
384
385Reference<css::beans::XPropertySetInfo> SAL_CALL OCommonStatement::getPropertySetInfo()
386{
387 return ::cppu::OPropertySetHelper::createPropertySetInfo(getInfoHelper());
388}
389
390/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
virtual css::uno::Any SAL_CALL queryInterface(const css::uno::Type &rType) override
void SAL_CALL getFastPropertyValue(Any &rValue, sal_Int32 nHandle) const override
void SAL_CALL acquire() noexcept override
Any SAL_CALL queryInterface(const css::uno::Type &rType) override
rtl::Reference< OConnection > m_xConnection
css::uno::Sequence< css::uno::Type > SAL_CALL getTypes() override
css::uno::Reference< css::sdbc::XResultSet > m_xResultSet
::cppu::IPropertyArrayHelper * createArrayHelper() const override
used to implement the creation of the array helper which is shared amongst all instances of the class...
void SAL_CALL setFastPropertyValue_NoBroadcast(sal_Int32 nHandle, const Any &rValue) override
void SAL_CALL release() noexcept override
css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo() override
::cppu::IPropertyArrayHelper &SAL_CALL getInfoHelper() override
sal_Bool SAL_CALL convertFastPropertyValue(Any &rConvertedValue, Any &rOldValue, sal_Int32 nHandle, const Any &rValue) override
::cppu::IPropertyArrayHelper * getArrayHelper()
call this in the getInfoHelper method of your derived class.
sal_Int32 SAL_CALL getUpdateCount() override
css::uno::Reference< css::sdbc::XConnection > SAL_CALL getConnection() override
virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override
void SAL_CALL release() noexcept override
Any SAL_CALL queryInterface(const css::uno::Type &rType) override
css::uno::Reference< css::sdbc::XResultSet > SAL_CALL getResultSet() override
sal_Int32 SAL_CALL executeUpdate(const OUString &sql) override
virtual OUString SAL_CALL getImplementationName() override
css::uno::Reference< css::sdbc::XResultSet > SAL_CALL executeQuery(const OUString &sql) override
sal_Bool SAL_CALL getMoreResults() override
sal_Bool SAL_CALL execute(const OUString &sql) override
void SAL_CALL acquire() noexcept override
virtual sal_Bool SAL_CALL supportsService(OUString const &ServiceName) override
css::uno::Sequence< Type > SAL_CALL getTypes() override
mutable::osl::Mutex m_aMutex
virtual css::uno::Sequence< css::uno::Type > SAL_CALL getTypes() SAL_OVERRIDE
virtual css::uno::Any SAL_CALL queryInterface(css::uno::Type const &rType) SAL_OVERRIDE
OBroadcastHelper & rBHelper
css::uno::Type const & get()
virtual void SAL_CALL release() SAL_NOEXCEPT SAL_OVERRIDE
virtual css::uno::Sequence< css::uno::Type > SAL_CALL getTypes() SAL_OVERRIDE
virtual void SAL_CALL acquire() SAL_NOEXCEPT SAL_OVERRIDE
virtual void SAL_CALL dispose() SAL_OVERRIDE
virtual css::uno::Any SAL_CALL queryInterface(css::uno::Type const &rType) SAL_OVERRIDE
std::mutex m_aMutex
Type
void checkDisposed(bool _bThrow)
css::uno::Sequence< T > concatSequences(const css::uno::Sequence< T > &_rLeft, const css::uno::Sequence< T > &_rRight)
concat two sequences
bool CPPUHELPER_DLLPUBLIC supportsService(css::lang::XServiceInfo *implementation, rtl::OUString const &name)
void throwSQLExceptionWithMsg(const char *msg, const char *SQLSTATE, unsigned int errorNum, const css::uno::Reference< css::uno::XInterface > &_context, const rtl_TextEncoding encoding)
OString OUStringToOString(std::u16string_view str, ConnectionSettings const *settings)
Definition: pq_tools.cxx:100
Reference< XConnection > m_xConnection
sal_Int32 nHandle
unsigned char sal_Bool
const SvXMLTokenMapEntry aTypes[]