Version 7.6.3.2-android, tag libreoffice-7.6.3.2-android
[LibreOffice.git] / connectivity / source / drivers / firebird / StatementCommonBase.cxx
blob917f801c7a9dcbb09fc61ebd5459b3bd40449b82
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
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 "StatementCommonBase.hxx"
21 #include "Util.hxx"
23 #include <sal/log.hxx>
24 #include <comphelper/sequence.hxx>
25 #include <cppuhelper/typeprovider.hxx>
26 #include <propertyids.hxx>
27 #include <vcl/svapp.hxx>
28 #include <TConnection.hxx>
30 #include <com/sun/star/sdbc/SQLException.hpp>
32 using namespace ::connectivity::firebird;
34 using namespace ::com::sun::star;
35 using namespace ::com::sun::star::uno;
36 using namespace ::com::sun::star::lang;
37 using namespace ::com::sun::star::beans;
38 using namespace ::com::sun::star::sdbc;
39 using namespace ::com::sun::star::sdbcx;
40 using namespace ::com::sun::star::container;
41 using namespace ::com::sun::star::io;
42 using namespace ::com::sun::star::util;
44 using namespace ::comphelper;
45 using namespace ::osl;
47 OStatementCommonBase::OStatementCommonBase(Connection* _pConnection)
48 : OStatementCommonBase_Base(m_aMutex),
49 OPropertySetHelper(OStatementCommonBase_Base::rBHelper),
50 m_pConnection(_pConnection),
51 #if SAL_TYPES_SIZEOFPOINTER == 8
52 m_aStatementHandle(0)
53 #else
54 m_aStatementHandle(nullptr)
55 #endif
59 OStatementCommonBase::~OStatementCommonBase()
63 void OStatementCommonBase::disposeResultSet()
65 uno::Reference< XComponent > xComp(m_xResultSet, UNO_QUERY);
66 if (xComp.is())
67 xComp->dispose();
68 m_xResultSet.clear();
71 void OStatementCommonBase::freeStatementHandle()
73 if (m_aStatementHandle)
75 isc_dsql_free_statement(m_statusVector,
76 &m_aStatementHandle,
77 DSQL_drop);
78 evaluateStatusVector(m_statusVector,
79 u"isc_dsql_free_statement",
80 *this);
85 Any SAL_CALL OStatementCommonBase::queryInterface( const Type & rType )
87 Any aRet = OStatementCommonBase_Base::queryInterface(rType);
88 if(!aRet.hasValue())
89 aRet = OPropertySetHelper::queryInterface(rType);
90 return aRet;
93 Sequence< Type > SAL_CALL OStatementCommonBase::getTypes( )
95 ::cppu::OTypeCollection aTypes(
96 ::cppu::UnoType<XMultiPropertySet>::get(),
97 ::cppu::UnoType<XFastPropertySet>::get(),
98 ::cppu::UnoType<XPropertySet>::get());
100 return concatSequences(aTypes.getTypes(),OStatementCommonBase_Base::getTypes());
104 void SAL_CALL OStatementCommonBase::cancel( )
106 MutexGuard aGuard(m_aMutex);
107 checkDisposed(OStatementCommonBase_Base::rBHelper.bDisposed);
108 // cancel the current sql statement
111 void SAL_CALL OStatementCommonBase::close()
113 SAL_INFO("connectivity.firebird", "close");
116 MutexGuard aGuard(m_aMutex);
117 checkDisposed(OStatementCommonBase_Base::rBHelper.bDisposed);
118 disposeResultSet();
119 freeStatementHandle();
122 dispose();
125 void OStatementCommonBase::prepareAndDescribeStatement(std::u16string_view sql, XSQLDA*& pOutSqlda)
127 SolarMutexGuard g; // tdf#122129
129 freeStatementHandle();
131 if (!pOutSqlda)
133 pOutSqlda = static_cast<XSQLDA*>(calloc(1, XSQLDA_LENGTH(10)));
134 pOutSqlda->version = SQLDA_VERSION1;
135 pOutSqlda->sqln = 10;
138 ISC_STATUS aErr = isc_dsql_allocate_statement(m_statusVector,
139 &m_pConnection->getDBHandle(),
140 &m_aStatementHandle);
142 if (aErr)
144 evaluateStatusVector(m_statusVector,
145 u"isc_dsql_allocate_statement",
146 *this);
148 else
150 aErr = isc_dsql_prepare(m_statusVector,
151 &m_pConnection->getTransaction(),
152 &m_aStatementHandle,
154 OUStringToOString(sql, RTL_TEXTENCODING_UTF8).getStr(),
155 SQL_DIALECT_CURRENT,
156 pOutSqlda);
158 if (aErr)
160 evaluateStatusVector(m_statusVector,
161 u"isc_dsql_prepare",
162 *this);
164 else
166 // Ensure we have enough space in pOutSqlda
167 if (pOutSqlda->sqld > pOutSqlda->sqln)
169 int n = pOutSqlda->sqld;
170 free(pOutSqlda);
171 pOutSqlda = static_cast<XSQLDA*>(calloc(1, XSQLDA_LENGTH(n)));
172 pOutSqlda->version = SQLDA_VERSION1;
173 pOutSqlda->sqln = n;
174 aErr = isc_dsql_describe(m_statusVector,
175 &m_aStatementHandle,
177 pOutSqlda);
180 // Process each XSQLVAR parameter structure in the output XSQLDA
181 if (aErr)
183 evaluateStatusVector(m_statusVector,
184 u"isc_dsql_describe",
185 *this);
187 else
189 mallocSQLVAR(pOutSqlda);
192 if(aErr)
194 freeStatementHandle();
197 if(aErr)
199 free(pOutSqlda);
200 pOutSqlda = nullptr;
204 // ---- XMultipleResults - UNSUPPORTED ----------------------------------------
205 uno::Reference< XResultSet > SAL_CALL OStatementCommonBase::getResultSet()
207 // TODO: verify we really can't support this
208 // return uno::Reference< XResultSet >();
209 MutexGuard aGuard(m_aMutex);
210 checkDisposed(OStatementCommonBase_Base::rBHelper.bDisposed);
212 return m_xResultSet;
215 sal_Bool SAL_CALL OStatementCommonBase::getMoreResults()
217 // TODO: verify we really can't support this
218 return false;
219 // MutexGuard aGuard( m_aMutex );
220 // checkDisposed(OStatementCommonBase_Base::rBHelper.bDisposed);
223 sal_Int32 SAL_CALL OStatementCommonBase::getUpdateCount()
225 // TODO: verify we really can't support this
226 return -1;
230 // ---- XWarningsSupplier - UNSUPPORTED ----------------------------------------
231 Any SAL_CALL OStatementCommonBase::getWarnings()
233 return Any();
236 void SAL_CALL OStatementCommonBase::clearWarnings()
240 ::cppu::IPropertyArrayHelper* OStatementCommonBase::createArrayHelper( ) const
242 // this properties are define by the service statement
243 // they must in alphabetic order
244 return new ::cppu::OPropertyArrayHelper
248 ::connectivity::OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_CURSORNAME),
249 PROPERTY_ID_CURSORNAME,
250 cppu::UnoType<OUString>::get(),
254 ::connectivity::OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_ESCAPEPROCESSING),
255 PROPERTY_ID_ESCAPEPROCESSING,
256 cppu::UnoType<bool>::get(),
260 ::connectivity::OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_FETCHDIRECTION),
261 PROPERTY_ID_FETCHDIRECTION,
262 cppu::UnoType<sal_Int32>::get(),
266 ::connectivity::OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_FETCHSIZE),
267 PROPERTY_ID_FETCHSIZE,
268 cppu::UnoType<sal_Int32>::get(),
272 ::connectivity::OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_MAXFIELDSIZE),
273 PROPERTY_ID_MAXFIELDSIZE,
274 cppu::UnoType<sal_Int32>::get(),
278 ::connectivity::OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_MAXROWS),
279 PROPERTY_ID_MAXROWS,
280 cppu::UnoType<sal_Int32>::get(),
284 ::connectivity::OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_QUERYTIMEOUT),
285 PROPERTY_ID_QUERYTIMEOUT,
286 cppu::UnoType<sal_Int32>::get(),
290 ::connectivity::OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_RESULTSETCONCURRENCY),
291 PROPERTY_ID_RESULTSETCONCURRENCY,
292 cppu::UnoType<sal_Int32>::get(),
296 ::connectivity::OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_RESULTSETTYPE),
297 PROPERTY_ID_RESULTSETTYPE,
298 cppu::UnoType<sal_Int32>::get(),
302 ::connectivity::OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_USEBOOKMARKS),
303 PROPERTY_ID_USEBOOKMARKS,
304 cppu::UnoType<bool>::get(),
312 ::cppu::IPropertyArrayHelper & OStatementCommonBase::getInfoHelper()
314 return *getArrayHelper();
317 sal_Bool OStatementCommonBase::convertFastPropertyValue(
318 Any &,
319 Any &,
320 sal_Int32,
321 const Any& )
323 // here we have to try to convert
324 return false;
327 void OStatementCommonBase::setFastPropertyValue_NoBroadcast(sal_Int32 nHandle,const Any&)
329 // set the value to whatever is necessary
330 switch(nHandle)
332 case PROPERTY_ID_QUERYTIMEOUT:
333 case PROPERTY_ID_MAXFIELDSIZE:
334 case PROPERTY_ID_MAXROWS:
335 case PROPERTY_ID_CURSORNAME:
336 case PROPERTY_ID_RESULTSETCONCURRENCY:
337 case PROPERTY_ID_RESULTSETTYPE:
338 case PROPERTY_ID_FETCHDIRECTION:
339 case PROPERTY_ID_FETCHSIZE:
340 case PROPERTY_ID_ESCAPEPROCESSING:
341 case PROPERTY_ID_USEBOOKMARKS:
342 default:
347 void OStatementCommonBase::getFastPropertyValue(Any&,sal_Int32 nHandle) const
349 switch(nHandle)
351 case PROPERTY_ID_QUERYTIMEOUT:
352 case PROPERTY_ID_MAXFIELDSIZE:
353 case PROPERTY_ID_MAXROWS:
354 case PROPERTY_ID_CURSORNAME:
355 case PROPERTY_ID_RESULTSETCONCURRENCY:
356 case PROPERTY_ID_RESULTSETTYPE:
357 case PROPERTY_ID_FETCHDIRECTION:
358 case PROPERTY_ID_FETCHSIZE:
359 case PROPERTY_ID_ESCAPEPROCESSING:
360 case PROPERTY_ID_USEBOOKMARKS:
361 default:
366 void SAL_CALL OStatementCommonBase::acquire() noexcept
368 OStatementCommonBase_Base::acquire();
371 void SAL_CALL OStatementCommonBase::release() noexcept
373 OStatementCommonBase_Base::release();
376 uno::Reference< css::beans::XPropertySetInfo > SAL_CALL OStatementCommonBase::getPropertySetInfo( )
378 return ::cppu::OPropertySetHelper::createPropertySetInfo(getInfoHelper());
381 short OStatementCommonBase::getSqlInfoItem(char aInfoItem)
383 ISC_STATUS_ARRAY aStatusVector;
384 ISC_STATUS aErr;
386 char aInfoItems[] = {aInfoItem};
387 char aResultsBuffer[8];
389 aErr = isc_dsql_sql_info(aStatusVector,
390 &m_aStatementHandle,
391 sizeof(aInfoItems),
392 aInfoItems,
393 sizeof(aResultsBuffer),
394 aResultsBuffer);
396 if (!aErr && aResultsBuffer[0] == aInfoItem)
398 const short aBytes = static_cast<short>(isc_vax_integer(aResultsBuffer+1, 2));
399 return static_cast<short>(isc_vax_integer(aResultsBuffer+3, aBytes));
402 evaluateStatusVector(aStatusVector,
403 u"isc_dsq_sql_info",
404 *this);
405 return 0;
408 bool OStatementCommonBase::isDDLStatement()
410 return getSqlInfoItem(isc_info_sql_stmt_type) == isc_info_sql_stmt_ddl;
413 sal_Int32 OStatementCommonBase::getStatementChangeCount()
415 const short aStatementType = getSqlInfoItem(isc_info_sql_stmt_type);
418 ISC_STATUS_ARRAY aStatusVector;
419 ISC_STATUS aErr;
421 // This is somewhat undocumented so I'm just guessing and hoping for the best.
422 char aInfoItems[] = {isc_info_sql_records};
423 char aResultsBuffer[1024];
425 aErr = isc_dsql_sql_info(aStatusVector,
426 &m_aStatementHandle,
427 sizeof(aInfoItems),
428 aInfoItems,
429 sizeof(aResultsBuffer),
430 aResultsBuffer);
432 if (aErr)
434 evaluateStatusVector(aStatusVector,
435 u"isc_dsq_sql_info",
436 *this);
437 return 0;
440 short aDesiredInfoType = 0;
441 switch (aStatementType)
443 case isc_info_sql_stmt_select:
444 aDesiredInfoType = isc_info_req_select_count;
445 break;
446 case isc_info_sql_stmt_insert:
447 aDesiredInfoType = isc_info_req_insert_count;
448 break;
449 case isc_info_sql_stmt_update:
450 aDesiredInfoType = isc_info_req_update_count;
451 break;
452 case isc_info_sql_stmt_delete:
453 aDesiredInfoType = isc_info_req_delete_count;
454 break;
455 case isc_info_sql_stmt_exec_procedure:
456 return 0; // cannot determine
457 default:
458 throw SQLException(); // TODO: better error message?
461 char* pResults = aResultsBuffer;
462 if (static_cast<short>(*pResults++) != isc_info_sql_records)
463 return 0;
465 // const short aTotalLength = (short) isc_vax_integer(pResults, 2);
466 pResults += 2;
468 // Seems to be of form TOKEN (1 byte), LENGTH (2 bytes), DATA (LENGTH bytes)
469 while (*pResults != isc_info_rsb_end)
471 const char aToken = *pResults;
472 const short aLength = static_cast<short>(isc_vax_integer(pResults+1, 2));
474 if (aToken == aDesiredInfoType)
476 return isc_vax_integer(pResults + 3, aLength);
479 pResults += (3 + aLength);
482 return 0;
485 /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */