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 .
21 #include "StatementCommonBase.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
56 m_aStatementHandle(nullptr)
61 OStatementCommonBase::~OStatementCommonBase()
65 void OStatementCommonBase::disposeResultSet()
67 uno::Reference
< XComponent
> xComp(m_xResultSet
, UNO_QUERY
);
73 void OStatementCommonBase::freeStatementHandle()
75 if (m_aStatementHandle
)
77 isc_dsql_free_statement(m_statusVector
,
80 evaluateStatusVector(m_statusVector
,
81 u
"isc_dsql_free_statement",
87 Any SAL_CALL
OStatementCommonBase::queryInterface( const Type
& rType
)
89 Any aRet
= OStatementCommonBase_Base::queryInterface(rType
);
91 aRet
= OPropertySetHelper::queryInterface(rType
);
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
);
121 freeStatementHandle();
127 void OStatementCommonBase::prepareAndDescribeStatement(std::u16string_view sql
,
131 SolarMutexGuard g
; // tdf#122129
133 freeStatementHandle();
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
);
148 evaluateStatusVector(m_statusVector
,
149 u
"isc_dsql_allocate_statement",
154 aErr
= isc_dsql_prepare(m_statusVector
,
155 &m_pConnection
->getTransaction(),
158 OUStringToOString(sql
, RTL_TEXTENCODING_UTF8
).getStr(),
159 FIREBIRD_SQL_DIALECT
,
164 evaluateStatusVector(m_statusVector
,
170 aErr
= isc_dsql_describe(m_statusVector
,
177 // TODO: free statement handle, etc.?
178 evaluateStatusVector(m_statusVector
,
179 u
"isc_dsql_describe",
184 // Ensure we have enough space in pOutSqlda
185 if (pOutSqlda
->sqld
> pOutSqlda
->sqln
)
187 int n
= pOutSqlda
->sqld
;
189 pOutSqlda
= static_cast<XSQLDA
*>(calloc(1, XSQLDA_LENGTH(n
)));
190 pOutSqlda
->version
= SQLDA_VERSION1
;
192 aErr
= isc_dsql_describe(m_statusVector
,
198 // Process each XSQLVAR parameter structure in the output XSQLDA
201 evaluateStatusVector(m_statusVector
,
202 u
"isc_dsql_describe",
207 mallocSQLVAR(pOutSqlda
);
213 freeStatementHandle();
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
);
234 sal_Bool SAL_CALL
OStatementCommonBase::getMoreResults()
236 // TODO: verify we really can't support this
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
249 // ---- XWarningsSupplier - UNSUPPORTED ----------------------------------------
250 Any SAL_CALL
OStatementCommonBase::getWarnings()
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();
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(
302 // here we have to try to convert
306 void OStatementCommonBase::setFastPropertyValue_NoBroadcast(sal_Int32 nHandle
,const Any
&)
308 // set the value to whatever is necessary
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
:
326 void OStatementCommonBase::getFastPropertyValue(Any
&,sal_Int32 nHandle
) const
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
:
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
;
365 char aInfoItems
[] = {aInfoItem
};
366 char aResultsBuffer
[8];
368 aErr
= isc_dsql_sql_info(aStatusVector
,
372 sizeof(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
,
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
;
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
,
408 sizeof(aResultsBuffer
),
413 evaluateStatusVector(aStatusVector
,
419 short aDesiredInfoType
= 0;
420 switch (aStatementType
)
422 case isc_info_sql_stmt_select
:
423 aDesiredInfoType
= isc_info_req_select_count
;
425 case isc_info_sql_stmt_insert
:
426 aDesiredInfoType
= isc_info_req_insert_count
;
428 case isc_info_sql_stmt_update
:
429 aDesiredInfoType
= isc_info_req_update_count
;
431 case isc_info_sql_stmt_delete
:
432 aDesiredInfoType
= isc_info_req_delete_count
;
434 case isc_info_sql_stmt_exec_procedure
:
435 return 0; // cannot determine
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);
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
);
464 /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */