1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
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"
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
54 m_aStatementHandle(nullptr)
59 OStatementCommonBase::~OStatementCommonBase()
63 void OStatementCommonBase::disposeResultSet()
65 uno::Reference
< XComponent
> xComp(m_xResultSet
, UNO_QUERY
);
71 void OStatementCommonBase::freeStatementHandle()
73 if (m_aStatementHandle
)
75 isc_dsql_free_statement(m_statusVector
,
78 evaluateStatusVector(m_statusVector
,
79 u
"isc_dsql_free_statement",
85 Any SAL_CALL
OStatementCommonBase::queryInterface( const Type
& rType
)
87 Any aRet
= OStatementCommonBase_Base::queryInterface(rType
);
89 aRet
= OPropertySetHelper::queryInterface(rType
);
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
);
119 freeStatementHandle();
125 void OStatementCommonBase::prepareAndDescribeStatement(std::u16string_view sql
, XSQLDA
*& pOutSqlda
)
127 SolarMutexGuard g
; // tdf#122129
129 freeStatementHandle();
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
);
144 evaluateStatusVector(m_statusVector
,
145 u
"isc_dsql_allocate_statement",
150 aErr
= isc_dsql_prepare(m_statusVector
,
151 &m_pConnection
->getTransaction(),
154 OUStringToOString(sql
, RTL_TEXTENCODING_UTF8
).getStr(),
160 evaluateStatusVector(m_statusVector
,
166 // Ensure we have enough space in pOutSqlda
167 if (pOutSqlda
->sqld
> pOutSqlda
->sqln
)
169 int n
= pOutSqlda
->sqld
;
171 pOutSqlda
= static_cast<XSQLDA
*>(calloc(1, XSQLDA_LENGTH(n
)));
172 pOutSqlda
->version
= SQLDA_VERSION1
;
174 aErr
= isc_dsql_describe(m_statusVector
,
180 // Process each XSQLVAR parameter structure in the output XSQLDA
183 evaluateStatusVector(m_statusVector
,
184 u
"isc_dsql_describe",
189 mallocSQLVAR(pOutSqlda
);
194 freeStatementHandle();
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
);
215 sal_Bool SAL_CALL
OStatementCommonBase::getMoreResults()
217 // TODO: verify we really can't support this
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
230 // ---- XWarningsSupplier - UNSUPPORTED ----------------------------------------
231 Any SAL_CALL
OStatementCommonBase::getWarnings()
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
),
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(
323 // here we have to try to convert
327 void OStatementCommonBase::setFastPropertyValue_NoBroadcast(sal_Int32 nHandle
,const Any
&)
329 // set the value to whatever is necessary
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
:
347 void OStatementCommonBase::getFastPropertyValue(Any
&,sal_Int32 nHandle
) const
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
:
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
;
386 char aInfoItems
[] = {aInfoItem
};
387 char aResultsBuffer
[8];
389 aErr
= isc_dsql_sql_info(aStatusVector
,
393 sizeof(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
,
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
;
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
,
429 sizeof(aResultsBuffer
),
434 evaluateStatusVector(aStatusVector
,
440 short aDesiredInfoType
= 0;
441 switch (aStatementType
)
443 case isc_info_sql_stmt_select
:
444 aDesiredInfoType
= isc_info_req_select_count
;
446 case isc_info_sql_stmt_insert
:
447 aDesiredInfoType
= isc_info_req_insert_count
;
449 case isc_info_sql_stmt_update
:
450 aDesiredInfoType
= isc_info_req_update_count
;
452 case isc_info_sql_stmt_delete
:
453 aDesiredInfoType
= isc_info_req_delete_count
;
455 case isc_info_sql_stmt_exec_procedure
:
456 return 0; // cannot determine
458 throw SQLException(); // TODO: better error message?
461 char* pResults
= aResultsBuffer
;
462 if (static_cast<short>(*pResults
++) != isc_info_sql_records
)
465 // const short aTotalLength = (short) isc_vax_integer(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
);
485 /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */