bump product version to 7.2.5.1
[LibreOffice.git] / connectivity / source / drivers / firebird / StatementCommonBase.cxx
blob01ae41dca1209ffd8b21cd4a8bcf41f121253183
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 "Driver.hxx"
21 #include "StatementCommonBase.hxx"
22 #include "Util.hxx"
24 #include <sal/log.hxx>
25 #include <comphelper/sequence.hxx>
26 #include <cppuhelper/typeprovider.hxx>
27 #include <propertyids.hxx>
28 #include <vcl/svapp.hxx>
29 #include <TConnection.hxx>
31 #include <com/sun/star/sdbc/SQLException.hpp>
33 using namespace ::connectivity::firebird;
35 using namespace ::com::sun::star;
36 using namespace ::com::sun::star::uno;
37 using namespace ::com::sun::star::lang;
38 using namespace ::com::sun::star::beans;
39 using namespace ::com::sun::star::sdbc;
40 using namespace ::com::sun::star::sdbcx;
41 using namespace ::com::sun::star::container;
42 using namespace ::com::sun::star::io;
43 using namespace ::com::sun::star::util;
45 using namespace ::comphelper;
46 using namespace ::osl;
47 using namespace ::std;
49 OStatementCommonBase::OStatementCommonBase(Connection* _pConnection)
50 : OStatementCommonBase_Base(m_aMutex),
51 OPropertySetHelper(OStatementCommonBase_Base::rBHelper),
52 m_pConnection(_pConnection),
53 #if SAL_TYPES_SIZEOFPOINTER == 8
54 m_aStatementHandle(0)
55 #else
56 m_aStatementHandle(nullptr)
57 #endif
61 OStatementCommonBase::~OStatementCommonBase()
65 void OStatementCommonBase::disposeResultSet()
67 uno::Reference< XComponent > xComp(m_xResultSet, UNO_QUERY);
68 if (xComp.is())
69 xComp->dispose();
70 m_xResultSet.clear();
73 void OStatementCommonBase::freeStatementHandle()
75 if (m_aStatementHandle)
77 isc_dsql_free_statement(m_statusVector,
78 &m_aStatementHandle,
79 DSQL_drop);
80 evaluateStatusVector(m_statusVector,
81 u"isc_dsql_free_statement",
82 *this);
87 Any SAL_CALL OStatementCommonBase::queryInterface( const Type & rType )
89 Any aRet = OStatementCommonBase_Base::queryInterface(rType);
90 if(!aRet.hasValue())
91 aRet = OPropertySetHelper::queryInterface(rType);
92 return aRet;
95 Sequence< Type > SAL_CALL OStatementCommonBase::getTypes( )
97 ::cppu::OTypeCollection aTypes(
98 ::cppu::UnoType<XMultiPropertySet>::get(),
99 ::cppu::UnoType<XFastPropertySet>::get(),
100 ::cppu::UnoType<XPropertySet>::get());
102 return concatSequences(aTypes.getTypes(),OStatementCommonBase_Base::getTypes());
106 void SAL_CALL OStatementCommonBase::cancel( )
108 MutexGuard aGuard(m_aMutex);
109 checkDisposed(OStatementCommonBase_Base::rBHelper.bDisposed);
110 // cancel the current sql statement
113 void SAL_CALL OStatementCommonBase::close()
115 SAL_INFO("connectivity.firebird", "close");
118 MutexGuard aGuard(m_aMutex);
119 checkDisposed(OStatementCommonBase_Base::rBHelper.bDisposed);
120 disposeResultSet();
121 freeStatementHandle();
124 dispose();
127 void OStatementCommonBase::prepareAndDescribeStatement(std::u16string_view sql,
128 XSQLDA*& pOutSqlda,
129 XSQLDA* pInSqlda)
131 SolarMutexGuard g; // tdf#122129
133 freeStatementHandle();
135 if (!pOutSqlda)
137 pOutSqlda = static_cast<XSQLDA*>(calloc(1, XSQLDA_LENGTH(10)));
138 pOutSqlda->version = SQLDA_VERSION1;
139 pOutSqlda->sqln = 10;
142 ISC_STATUS aErr = isc_dsql_allocate_statement(m_statusVector,
143 &m_pConnection->getDBHandle(),
144 &m_aStatementHandle);
146 if (aErr)
148 evaluateStatusVector(m_statusVector,
149 u"isc_dsql_allocate_statement",
150 *this);
152 else
154 aErr = isc_dsql_prepare(m_statusVector,
155 &m_pConnection->getTransaction(),
156 &m_aStatementHandle,
158 OUStringToOString(sql, RTL_TEXTENCODING_UTF8).getStr(),
159 FIREBIRD_SQL_DIALECT,
160 pInSqlda);
162 if (aErr)
164 evaluateStatusVector(m_statusVector,
165 u"isc_dsql_prepare",
166 *this);
168 else
170 aErr = isc_dsql_describe(m_statusVector,
171 &m_aStatementHandle,
173 pOutSqlda);
175 if (aErr)
177 // TODO: free statement handle, etc.?
178 evaluateStatusVector(m_statusVector,
179 u"isc_dsql_describe",
180 *this);
182 else
184 // Ensure we have enough space in pOutSqlda
185 if (pOutSqlda->sqld > pOutSqlda->sqln)
187 int n = pOutSqlda->sqld;
188 free(pOutSqlda);
189 pOutSqlda = static_cast<XSQLDA*>(calloc(1, XSQLDA_LENGTH(n)));
190 pOutSqlda->version = SQLDA_VERSION1;
191 pOutSqlda->sqln = n;
192 aErr = isc_dsql_describe(m_statusVector,
193 &m_aStatementHandle,
195 pOutSqlda);
198 // Process each XSQLVAR parameter structure in the output XSQLDA
199 if (aErr)
201 evaluateStatusVector(m_statusVector,
202 u"isc_dsql_describe",
203 *this);
205 else
207 mallocSQLVAR(pOutSqlda);
211 if(aErr)
213 freeStatementHandle();
216 if(aErr)
218 free(pOutSqlda);
219 pOutSqlda = nullptr;
223 // ---- XMultipleResults - UNSUPPORTED ----------------------------------------
224 uno::Reference< XResultSet > SAL_CALL OStatementCommonBase::getResultSet()
226 // TODO: verify we really can't support this
227 // return uno::Reference< XResultSet >();
228 MutexGuard aGuard(m_aMutex);
229 checkDisposed(OStatementCommonBase_Base::rBHelper.bDisposed);
231 return m_xResultSet;
234 sal_Bool SAL_CALL OStatementCommonBase::getMoreResults()
236 // TODO: verify we really can't support this
237 return false;
238 // MutexGuard aGuard( m_aMutex );
239 // checkDisposed(OStatementCommonBase_Base::rBHelper.bDisposed);
242 sal_Int32 SAL_CALL OStatementCommonBase::getUpdateCount()
244 // TODO: verify we really can't support this
245 return -1;
249 // ---- XWarningsSupplier - UNSUPPORTED ----------------------------------------
250 Any SAL_CALL OStatementCommonBase::getWarnings()
252 return Any();
255 void SAL_CALL OStatementCommonBase::clearWarnings()
259 ::cppu::IPropertyArrayHelper* OStatementCommonBase::createArrayHelper( ) const
261 // this properties are define by the service statement
262 // they must in alphabetic order
263 Sequence< Property > aProps(10);
264 Property* pProperties = aProps.getArray();
265 sal_Int32 nPos = 0;
266 pProperties[nPos++] = css::beans::Property(::connectivity::OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_CURSORNAME),
267 PROPERTY_ID_CURSORNAME, cppu::UnoType<OUString>::get(), 0);
268 pProperties[nPos++] = css::beans::Property(::connectivity::OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_ESCAPEPROCESSING),
269 PROPERTY_ID_ESCAPEPROCESSING, cppu::UnoType<bool>::get(), 0);
270 pProperties[nPos++] = css::beans::Property(::connectivity::OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_FETCHDIRECTION),
271 PROPERTY_ID_FETCHDIRECTION, cppu::UnoType<sal_Int32>::get(), 0);
272 pProperties[nPos++] = css::beans::Property(::connectivity::OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_FETCHSIZE),
273 PROPERTY_ID_FETCHSIZE, cppu::UnoType<sal_Int32>::get(), 0);
274 pProperties[nPos++] = css::beans::Property(::connectivity::OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_MAXFIELDSIZE),
275 PROPERTY_ID_MAXFIELDSIZE, cppu::UnoType<sal_Int32>::get(), 0);
276 pProperties[nPos++] = css::beans::Property(::connectivity::OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_MAXROWS),
277 PROPERTY_ID_MAXROWS, cppu::UnoType<sal_Int32>::get(), 0);
278 pProperties[nPos++] = css::beans::Property(::connectivity::OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_QUERYTIMEOUT),
279 PROPERTY_ID_QUERYTIMEOUT, cppu::UnoType<sal_Int32>::get(), 0);
280 pProperties[nPos++] = css::beans::Property(::connectivity::OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_RESULTSETCONCURRENCY),
281 PROPERTY_ID_RESULTSETCONCURRENCY, cppu::UnoType<sal_Int32>::get(), 0);
282 pProperties[nPos++] = css::beans::Property(::connectivity::OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_RESULTSETTYPE),
283 PROPERTY_ID_RESULTSETTYPE, cppu::UnoType<sal_Int32>::get(), 0);
284 pProperties[nPos++] = css::beans::Property(::connectivity::OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_USEBOOKMARKS),
285 PROPERTY_ID_USEBOOKMARKS, cppu::UnoType<bool>::get(), 0);
287 return new ::cppu::OPropertyArrayHelper(aProps);
291 ::cppu::IPropertyArrayHelper & OStatementCommonBase::getInfoHelper()
293 return *getArrayHelper();
296 sal_Bool OStatementCommonBase::convertFastPropertyValue(
297 Any &,
298 Any &,
299 sal_Int32,
300 const Any& )
302 // here we have to try to convert
303 return false;
306 void OStatementCommonBase::setFastPropertyValue_NoBroadcast(sal_Int32 nHandle,const Any&)
308 // set the value to whatever is necessary
309 switch(nHandle)
311 case PROPERTY_ID_QUERYTIMEOUT:
312 case PROPERTY_ID_MAXFIELDSIZE:
313 case PROPERTY_ID_MAXROWS:
314 case PROPERTY_ID_CURSORNAME:
315 case PROPERTY_ID_RESULTSETCONCURRENCY:
316 case PROPERTY_ID_RESULTSETTYPE:
317 case PROPERTY_ID_FETCHDIRECTION:
318 case PROPERTY_ID_FETCHSIZE:
319 case PROPERTY_ID_ESCAPEPROCESSING:
320 case PROPERTY_ID_USEBOOKMARKS:
321 default:
326 void OStatementCommonBase::getFastPropertyValue(Any&,sal_Int32 nHandle) const
328 switch(nHandle)
330 case PROPERTY_ID_QUERYTIMEOUT:
331 case PROPERTY_ID_MAXFIELDSIZE:
332 case PROPERTY_ID_MAXROWS:
333 case PROPERTY_ID_CURSORNAME:
334 case PROPERTY_ID_RESULTSETCONCURRENCY:
335 case PROPERTY_ID_RESULTSETTYPE:
336 case PROPERTY_ID_FETCHDIRECTION:
337 case PROPERTY_ID_FETCHSIZE:
338 case PROPERTY_ID_ESCAPEPROCESSING:
339 case PROPERTY_ID_USEBOOKMARKS:
340 default:
345 void SAL_CALL OStatementCommonBase::acquire() noexcept
347 OStatementCommonBase_Base::acquire();
350 void SAL_CALL OStatementCommonBase::release() noexcept
352 OStatementCommonBase_Base::release();
355 uno::Reference< css::beans::XPropertySetInfo > SAL_CALL OStatementCommonBase::getPropertySetInfo( )
357 return ::cppu::OPropertySetHelper::createPropertySetInfo(getInfoHelper());
360 short OStatementCommonBase::getSqlInfoItem(char aInfoItem)
362 ISC_STATUS_ARRAY aStatusVector;
363 ISC_STATUS aErr;
365 char aInfoItems[] = {aInfoItem};
366 char aResultsBuffer[8];
368 aErr = isc_dsql_sql_info(aStatusVector,
369 &m_aStatementHandle,
370 sizeof(aInfoItems),
371 aInfoItems,
372 sizeof(aResultsBuffer),
373 aResultsBuffer);
375 if (!aErr && aResultsBuffer[0] == aInfoItem)
377 const short aBytes = static_cast<short>(isc_vax_integer(aResultsBuffer+1, 2));
378 return static_cast<short>(isc_vax_integer(aResultsBuffer+3, aBytes));
381 evaluateStatusVector(aStatusVector,
382 u"isc_dsq_sql_info",
383 *this);
384 return 0;
387 bool OStatementCommonBase::isDDLStatement()
389 return getSqlInfoItem(isc_info_sql_stmt_type) == isc_info_sql_stmt_ddl;
392 sal_Int32 OStatementCommonBase::getStatementChangeCount()
394 const short aStatementType = getSqlInfoItem(isc_info_sql_stmt_type);
397 ISC_STATUS_ARRAY aStatusVector;
398 ISC_STATUS aErr;
400 // This is somewhat undocumented so I'm just guessing and hoping for the best.
401 char aInfoItems[] = {isc_info_sql_records};
402 char aResultsBuffer[1024];
404 aErr = isc_dsql_sql_info(aStatusVector,
405 &m_aStatementHandle,
406 sizeof(aInfoItems),
407 aInfoItems,
408 sizeof(aResultsBuffer),
409 aResultsBuffer);
411 if (aErr)
413 evaluateStatusVector(aStatusVector,
414 u"isc_dsq_sql_info",
415 *this);
416 return 0;
419 short aDesiredInfoType = 0;
420 switch (aStatementType)
422 case isc_info_sql_stmt_select:
423 aDesiredInfoType = isc_info_req_select_count;
424 break;
425 case isc_info_sql_stmt_insert:
426 aDesiredInfoType = isc_info_req_insert_count;
427 break;
428 case isc_info_sql_stmt_update:
429 aDesiredInfoType = isc_info_req_update_count;
430 break;
431 case isc_info_sql_stmt_delete:
432 aDesiredInfoType = isc_info_req_delete_count;
433 break;
434 case isc_info_sql_stmt_exec_procedure:
435 return 0; // cannot determine
436 default:
437 throw SQLException(); // TODO: better error message?
440 char* pResults = aResultsBuffer;
441 if (static_cast<short>(*pResults++) == isc_info_sql_records)
443 // const short aTotalLength = (short) isc_vax_integer(pResults, 2);
444 pResults += 2;
446 // Seems to be of form TOKEN (1 byte), LENGTH (2 bytes), DATA (LENGTH bytes)
447 while (*pResults != isc_info_rsb_end)
449 const char aToken = *pResults;
450 const short aLength = static_cast<short>(isc_vax_integer(pResults+1, 2));
452 if (aToken == aDesiredInfoType)
454 return isc_vax_integer(pResults + 3, aLength);
457 pResults += (3 + aLength);
461 return 0;
464 /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */