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"
22 #include "ResultSet.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
;
48 OStatementCommonBase::OStatementCommonBase(Connection
* _pConnection
)
49 : OStatementCommonBase_Base(m_aMutex
),
50 OPropertySetHelper(OStatementCommonBase_Base::rBHelper
),
51 m_pConnection(_pConnection
),
52 #if SAL_TYPES_SIZEOFPOINTER == 8
55 m_aStatementHandle(nullptr)
60 OStatementCommonBase::~OStatementCommonBase()
64 void OStatementCommonBase::disposeResultSet()
66 if (m_xResultSet
.is())
67 m_xResultSet
->dispose();
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 assert(pOutSqlda
&& "Don't handle OOM conditions");
135 pOutSqlda
->version
= SQLDA_VERSION1
;
136 pOutSqlda
->sqln
= 10;
139 ISC_STATUS aErr
= isc_dsql_allocate_statement(m_statusVector
,
140 &m_pConnection
->getDBHandle(),
141 &m_aStatementHandle
);
145 evaluateStatusVector(m_statusVector
,
146 u
"isc_dsql_allocate_statement",
151 aErr
= isc_dsql_prepare(m_statusVector
,
152 &m_pConnection
->getTransaction(),
155 OUStringToOString(sql
, RTL_TEXTENCODING_UTF8
).getStr(),
161 evaluateStatusVector(m_statusVector
,
167 // Ensure we have enough space in pOutSqlda
168 if (pOutSqlda
->sqld
> pOutSqlda
->sqln
)
170 int n
= pOutSqlda
->sqld
;
172 pOutSqlda
= static_cast<XSQLDA
*>(calloc(1, XSQLDA_LENGTH(n
)));
173 assert(pOutSqlda
&& "Don't handle OOM conditions");
174 pOutSqlda
->version
= SQLDA_VERSION1
;
176 aErr
= isc_dsql_describe(m_statusVector
,
182 // Process each XSQLVAR parameter structure in the output XSQLDA
185 evaluateStatusVector(m_statusVector
,
186 u
"isc_dsql_describe",
191 mallocSQLVAR(pOutSqlda
);
196 freeStatementHandle();
206 // ---- XMultipleResults - UNSUPPORTED ----------------------------------------
207 uno::Reference
< XResultSet
> SAL_CALL
OStatementCommonBase::getResultSet()
209 // TODO: verify we really can't support this
210 // return uno::Reference< XResultSet >();
211 MutexGuard
aGuard(m_aMutex
);
212 checkDisposed(OStatementCommonBase_Base::rBHelper
.bDisposed
);
217 sal_Bool SAL_CALL
OStatementCommonBase::getMoreResults()
219 // TODO: verify we really can't support this
221 // MutexGuard aGuard( m_aMutex );
222 // checkDisposed(OStatementCommonBase_Base::rBHelper.bDisposed);
225 sal_Int32 SAL_CALL
OStatementCommonBase::getUpdateCount()
227 // TODO: verify we really can't support this
232 // ---- XWarningsSupplier - UNSUPPORTED ----------------------------------------
233 Any SAL_CALL
OStatementCommonBase::getWarnings()
238 void SAL_CALL
OStatementCommonBase::clearWarnings()
242 ::cppu::IPropertyArrayHelper
* OStatementCommonBase::createArrayHelper( ) const
244 // this properties are define by the service statement
245 // they must in alphabetic order
246 return new ::cppu::OPropertyArrayHelper
250 ::connectivity::OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_CURSORNAME
),
251 PROPERTY_ID_CURSORNAME
,
252 cppu::UnoType
<OUString
>::get(),
256 ::connectivity::OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_ESCAPEPROCESSING
),
257 PROPERTY_ID_ESCAPEPROCESSING
,
258 cppu::UnoType
<bool>::get(),
262 ::connectivity::OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_FETCHDIRECTION
),
263 PROPERTY_ID_FETCHDIRECTION
,
264 cppu::UnoType
<sal_Int32
>::get(),
268 ::connectivity::OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_FETCHSIZE
),
269 PROPERTY_ID_FETCHSIZE
,
270 cppu::UnoType
<sal_Int32
>::get(),
274 ::connectivity::OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_MAXFIELDSIZE
),
275 PROPERTY_ID_MAXFIELDSIZE
,
276 cppu::UnoType
<sal_Int32
>::get(),
280 ::connectivity::OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_MAXROWS
),
282 cppu::UnoType
<sal_Int32
>::get(),
286 ::connectivity::OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_QUERYTIMEOUT
),
287 PROPERTY_ID_QUERYTIMEOUT
,
288 cppu::UnoType
<sal_Int32
>::get(),
292 ::connectivity::OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_RESULTSETCONCURRENCY
),
293 PROPERTY_ID_RESULTSETCONCURRENCY
,
294 cppu::UnoType
<sal_Int32
>::get(),
298 ::connectivity::OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_RESULTSETTYPE
),
299 PROPERTY_ID_RESULTSETTYPE
,
300 cppu::UnoType
<sal_Int32
>::get(),
304 ::connectivity::OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_USEBOOKMARKS
),
305 PROPERTY_ID_USEBOOKMARKS
,
306 cppu::UnoType
<bool>::get(),
314 ::cppu::IPropertyArrayHelper
& OStatementCommonBase::getInfoHelper()
316 return *getArrayHelper();
319 sal_Bool
OStatementCommonBase::convertFastPropertyValue(
325 // here we have to try to convert
329 void OStatementCommonBase::setFastPropertyValue_NoBroadcast(sal_Int32 nHandle
,const Any
&)
331 // set the value to whatever is necessary
334 case PROPERTY_ID_QUERYTIMEOUT
:
335 case PROPERTY_ID_MAXFIELDSIZE
:
336 case PROPERTY_ID_MAXROWS
:
337 case PROPERTY_ID_CURSORNAME
:
338 case PROPERTY_ID_RESULTSETCONCURRENCY
:
339 case PROPERTY_ID_RESULTSETTYPE
:
340 case PROPERTY_ID_FETCHDIRECTION
:
341 case PROPERTY_ID_FETCHSIZE
:
342 case PROPERTY_ID_ESCAPEPROCESSING
:
343 case PROPERTY_ID_USEBOOKMARKS
:
349 void OStatementCommonBase::getFastPropertyValue(Any
&,sal_Int32 nHandle
) const
353 case PROPERTY_ID_QUERYTIMEOUT
:
354 case PROPERTY_ID_MAXFIELDSIZE
:
355 case PROPERTY_ID_MAXROWS
:
356 case PROPERTY_ID_CURSORNAME
:
357 case PROPERTY_ID_RESULTSETCONCURRENCY
:
358 case PROPERTY_ID_RESULTSETTYPE
:
359 case PROPERTY_ID_FETCHDIRECTION
:
360 case PROPERTY_ID_FETCHSIZE
:
361 case PROPERTY_ID_ESCAPEPROCESSING
:
362 case PROPERTY_ID_USEBOOKMARKS
:
368 void SAL_CALL
OStatementCommonBase::acquire() noexcept
370 OStatementCommonBase_Base::acquire();
373 void SAL_CALL
OStatementCommonBase::release() noexcept
375 OStatementCommonBase_Base::release();
378 uno::Reference
< css::beans::XPropertySetInfo
> SAL_CALL
OStatementCommonBase::getPropertySetInfo( )
380 return ::cppu::OPropertySetHelper::createPropertySetInfo(getInfoHelper());
383 short OStatementCommonBase::getSqlInfoItem(char aInfoItem
)
385 ISC_STATUS_ARRAY aStatusVector
;
388 char aInfoItems
[] = {aInfoItem
};
389 char aResultsBuffer
[8];
391 aErr
= isc_dsql_sql_info(aStatusVector
,
395 sizeof(aResultsBuffer
),
398 if (!aErr
&& aResultsBuffer
[0] == aInfoItem
)
400 const short aBytes
= static_cast<short>(isc_vax_integer(aResultsBuffer
+1, 2));
401 return static_cast<short>(isc_vax_integer(aResultsBuffer
+3, aBytes
));
404 evaluateStatusVector(aStatusVector
,
410 bool OStatementCommonBase::isDDLStatement()
412 return getSqlInfoItem(isc_info_sql_stmt_type
) == isc_info_sql_stmt_ddl
;
415 sal_Int32
OStatementCommonBase::getStatementChangeCount()
417 const short aStatementType
= getSqlInfoItem(isc_info_sql_stmt_type
);
420 ISC_STATUS_ARRAY aStatusVector
;
423 // This is somewhat undocumented so I'm just guessing and hoping for the best.
424 char aInfoItems
[] = {isc_info_sql_records
};
425 char aResultsBuffer
[1024];
427 aErr
= isc_dsql_sql_info(aStatusVector
,
431 sizeof(aResultsBuffer
),
436 evaluateStatusVector(aStatusVector
,
442 short aDesiredInfoType
= 0;
443 switch (aStatementType
)
445 case isc_info_sql_stmt_select
:
446 aDesiredInfoType
= isc_info_req_select_count
;
448 case isc_info_sql_stmt_insert
:
449 aDesiredInfoType
= isc_info_req_insert_count
;
451 case isc_info_sql_stmt_update
:
452 aDesiredInfoType
= isc_info_req_update_count
;
454 case isc_info_sql_stmt_delete
:
455 aDesiredInfoType
= isc_info_req_delete_count
;
457 case isc_info_sql_stmt_exec_procedure
:
458 case isc_info_sql_stmt_ddl
:
459 return 0; // cannot determine
461 throw SQLException(); // TODO: better error message?
464 char* pResults
= aResultsBuffer
;
465 if (static_cast<short>(*pResults
++) != isc_info_sql_records
)
468 // const short aTotalLength = (short) isc_vax_integer(pResults, 2);
471 // Seems to be of form TOKEN (1 byte), LENGTH (2 bytes), DATA (LENGTH bytes)
472 while (*pResults
!= isc_info_rsb_end
)
474 const char aToken
= *pResults
;
475 const short aLength
= static_cast<short>(isc_vax_integer(pResults
+1, 2));
477 if (aToken
== aDesiredInfoType
)
479 return isc_vax_integer(pResults
+ 3, aLength
);
482 pResults
+= (3 + aLength
);
488 /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */