Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
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 .
18 : */
19 :
20 : #include "Driver.hxx"
21 : #include "ResultSet.hxx"
22 : #include "StatementCommonBase.hxx"
23 : #include "Util.hxx"
24 :
25 : #include <comphelper/sequence.hxx>
26 : #include <cppuhelper/typeprovider.hxx>
27 : #include <propertyids.hxx>
28 : #include <TConnection.hxx>
29 :
30 : using namespace ::connectivity::firebird;
31 :
32 : using namespace ::com::sun::star;
33 : using namespace ::com::sun::star::uno;
34 : using namespace ::com::sun::star::lang;
35 : using namespace ::com::sun::star::beans;
36 : using namespace ::com::sun::star::sdbc;
37 : using namespace ::com::sun::star::sdbcx;
38 : using namespace ::com::sun::star::container;
39 : using namespace ::com::sun::star::io;
40 : using namespace ::com::sun::star::util;
41 :
42 : using namespace ::comphelper;
43 : using namespace ::osl;
44 : using namespace ::rtl;
45 : using namespace ::std;
46 :
47 0 : OStatementCommonBase::OStatementCommonBase(Connection* _pConnection)
48 : : OStatementCommonBase_Base(m_aMutex),
49 : OPropertySetHelper(OStatementCommonBase_Base::rBHelper),
50 : m_pConnection(_pConnection),
51 : m_aStatementHandle( 0 ),
52 0 : rBHelper(OStatementCommonBase_Base::rBHelper)
53 : {
54 0 : m_pConnection->acquire();
55 0 : }
56 :
57 0 : OStatementCommonBase::~OStatementCommonBase()
58 : {
59 0 : }
60 :
61 0 : void OStatementCommonBase::disposeResultSet()
62 : {
63 0 : uno::Reference< XComponent > xComp(m_xResultSet.get(), UNO_QUERY);
64 0 : if (xComp.is())
65 0 : xComp->dispose();
66 0 : m_xResultSet = uno::Reference< XResultSet>();
67 0 : }
68 :
69 0 : void OStatementCommonBase::freeStatementHandle()
70 : throw (SQLException)
71 : {
72 0 : if (m_aStatementHandle)
73 : {
74 : isc_dsql_free_statement(m_statusVector,
75 : &m_aStatementHandle,
76 0 : DSQL_drop);
77 : evaluateStatusVector(m_statusVector,
78 : "isc_dsql_free_statement",
79 0 : *this);
80 : }
81 0 : }
82 :
83 :
84 0 : Any SAL_CALL OStatementCommonBase::queryInterface( const Type & rType ) throw(RuntimeException, std::exception)
85 : {
86 0 : Any aRet = OStatementCommonBase_Base::queryInterface(rType);
87 0 : if(!aRet.hasValue())
88 0 : aRet = OPropertySetHelper::queryInterface(rType);
89 0 : return aRet;
90 : }
91 :
92 0 : Sequence< Type > SAL_CALL OStatementCommonBase::getTypes( ) throw(RuntimeException, std::exception)
93 : {
94 : ::cppu::OTypeCollection aTypes(
95 0 : ::cppu::UnoType< uno::Reference< XMultiPropertySet > >::get(),
96 0 : ::cppu::UnoType< uno::Reference< XFastPropertySet > >::get(),
97 0 : ::cppu::UnoType< uno::Reference< XPropertySet > >::get());
98 :
99 0 : return concatSequences(aTypes.getTypes(),OStatementCommonBase_Base::getTypes());
100 : }
101 :
102 :
103 0 : void SAL_CALL OStatementCommonBase::cancel( ) throw(RuntimeException, std::exception)
104 : {
105 0 : MutexGuard aGuard(m_aMutex);
106 0 : checkDisposed(OStatementCommonBase_Base::rBHelper.bDisposed);
107 : // cancel the current sql statement
108 0 : }
109 :
110 0 : void SAL_CALL OStatementCommonBase::close()
111 : throw(SQLException, RuntimeException, std::exception)
112 : {
113 : SAL_INFO("connectivity.firebird", "close");
114 :
115 : {
116 0 : MutexGuard aGuard(m_aMutex);
117 0 : checkDisposed(OStatementCommonBase_Base::rBHelper.bDisposed);
118 0 : disposeResultSet();
119 0 : freeStatementHandle();
120 : }
121 :
122 0 : dispose();
123 0 : }
124 :
125 0 : void OStatementCommonBase::prepareAndDescribeStatement(const OUString& sql,
126 : XSQLDA*& pOutSqlda,
127 : XSQLDA* pInSqlda)
128 : throw (SQLException)
129 : {
130 0 : MutexGuard aGuard(m_aMutex);
131 :
132 0 : freeStatementHandle();
133 :
134 0 : if (!pOutSqlda)
135 : {
136 0 : pOutSqlda = (XSQLDA*) malloc(XSQLDA_LENGTH(10));
137 0 : pOutSqlda->version = SQLDA_VERSION1;
138 0 : pOutSqlda->sqln = 10;
139 : }
140 :
141 0 : ISC_STATUS aErr = 0;
142 :
143 : aErr = isc_dsql_allocate_statement(m_statusVector,
144 0 : &m_pConnection->getDBHandle(),
145 0 : &m_aStatementHandle);
146 :
147 0 : if (aErr)
148 : {
149 0 : free(pOutSqlda);
150 0 : pOutSqlda = 0;
151 : evaluateStatusVector(m_statusVector,
152 : "isc_dsql_allocate_statement",
153 0 : *this);
154 : }
155 :
156 : aErr = isc_dsql_prepare(m_statusVector,
157 0 : &m_pConnection->getTransaction(),
158 : &m_aStatementHandle,
159 : 0,
160 : OUStringToOString(sql, RTL_TEXTENCODING_UTF8).getStr(),
161 : FIREBIRD_SQL_DIALECT,
162 0 : pInSqlda);
163 :
164 0 : if (aErr)
165 : {
166 : // TODO: free statement handle?
167 0 : free(pOutSqlda);
168 0 : pOutSqlda = 0;
169 : evaluateStatusVector(m_statusVector,
170 : "isc_dsql_prepare",
171 0 : *this);
172 : }
173 :
174 : aErr = isc_dsql_describe(m_statusVector,
175 : &m_aStatementHandle,
176 : 1,
177 0 : pOutSqlda);
178 :
179 :
180 0 : if (aErr)
181 : {
182 : // TODO: free statement handle, etc.?
183 0 : free(pOutSqlda);
184 0 : pOutSqlda = 0;
185 : evaluateStatusVector(m_statusVector,
186 : "isc_dsql_describe",
187 0 : *this);
188 : }
189 :
190 : // Ensure we have enough space in pOutSqlda
191 0 : if (pOutSqlda->sqld > pOutSqlda->sqln)
192 : {
193 0 : int n = pOutSqlda->sqld;
194 0 : free(pOutSqlda);
195 0 : pOutSqlda = (XSQLDA*) malloc(XSQLDA_LENGTH(n));
196 0 : pOutSqlda->version = SQLDA_VERSION1;
197 : aErr = isc_dsql_describe(m_statusVector,
198 : &m_aStatementHandle,
199 : 1,
200 0 : pOutSqlda);
201 : }
202 :
203 : // Process each XSQLVAR parameter structure in the output XSQLDA
204 0 : if (aErr)
205 : evaluateStatusVector(m_statusVector,
206 : "isc_dsql_describe",
207 0 : *this);
208 :
209 0 : mallocSQLVAR(pOutSqlda);
210 0 : }
211 :
212 : // ---- XMultipleResults - UNSUPPORTED ----------------------------------------
213 0 : uno::Reference< XResultSet > SAL_CALL OStatementCommonBase::getResultSet() throw(SQLException, RuntimeException, std::exception)
214 : {
215 : // TODO: verify we really can't support this
216 : // return uno::Reference< XResultSet >();
217 0 : MutexGuard aGuard(m_aMutex);
218 0 : checkDisposed(OStatementCommonBase_Base::rBHelper.bDisposed);
219 :
220 0 : return m_xResultSet;
221 : }
222 :
223 0 : sal_Bool SAL_CALL OStatementCommonBase::getMoreResults() throw(SQLException, RuntimeException, std::exception)
224 : {
225 : // TODO: verify we really can't support this
226 0 : return sal_False;
227 : // MutexGuard aGuard( m_aMutex );
228 : // checkDisposed(OStatementCommonBase_Base::rBHelper.bDisposed);
229 : }
230 :
231 0 : sal_Int32 SAL_CALL OStatementCommonBase::getUpdateCount() throw(SQLException, RuntimeException, std::exception)
232 : {
233 : // TODO: verify we really can't support this
234 0 : return 0;
235 : }
236 :
237 :
238 : // ---- XWarningsSupplier - UNSUPPORTED ----------------------------------------
239 0 : Any SAL_CALL OStatementCommonBase::getWarnings() throw(SQLException, RuntimeException, std::exception)
240 : {
241 0 : return Any();
242 : }
243 :
244 0 : void SAL_CALL OStatementCommonBase::clearWarnings() throw(SQLException, RuntimeException, std::exception)
245 : {
246 0 : }
247 :
248 0 : ::cppu::IPropertyArrayHelper* OStatementCommonBase::createArrayHelper( ) const
249 : {
250 : // this properties are define by the service statement
251 : // they must in alphabetic order
252 0 : Sequence< Property > aProps(10);
253 0 : Property* pProperties = aProps.getArray();
254 0 : sal_Int32 nPos = 0;
255 0 : DECL_PROP0(CURSORNAME, OUString);
256 0 : DECL_BOOL_PROP0(ESCAPEPROCESSING);
257 0 : DECL_PROP0(FETCHDIRECTION,sal_Int32);
258 0 : DECL_PROP0(FETCHSIZE, sal_Int32);
259 0 : DECL_PROP0(MAXFIELDSIZE,sal_Int32);
260 0 : DECL_PROP0(MAXROWS, sal_Int32);
261 0 : DECL_PROP0(QUERYTIMEOUT,sal_Int32);
262 0 : DECL_PROP0(RESULTSETCONCURRENCY,sal_Int32);
263 0 : DECL_PROP0(RESULTSETTYPE,sal_Int32);
264 0 : DECL_BOOL_PROP0(USEBOOKMARKS);
265 :
266 0 : return new ::cppu::OPropertyArrayHelper(aProps);
267 : }
268 :
269 :
270 0 : ::cppu::IPropertyArrayHelper & OStatementCommonBase::getInfoHelper()
271 : {
272 0 : return *const_cast<OStatementCommonBase*>(this)->getArrayHelper();
273 : }
274 :
275 0 : sal_Bool OStatementCommonBase::convertFastPropertyValue(
276 : Any & rConvertedValue,
277 : Any & rOldValue,
278 : sal_Int32 nHandle,
279 : const Any& rValue )
280 : throw (IllegalArgumentException)
281 : {
282 : (void) rConvertedValue;
283 : (void) rOldValue;
284 : (void) nHandle;
285 : (void) rValue;
286 0 : sal_Bool bConverted = sal_False;
287 : // here we have to try to convert
288 0 : return bConverted;
289 : }
290 :
291 0 : void OStatementCommonBase::setFastPropertyValue_NoBroadcast(sal_Int32 nHandle,const Any& rValue) throw (Exception, std::exception)
292 : {
293 : (void) rValue;
294 : // set the value to what ever is necessary
295 : switch(nHandle)
296 : {
297 : case PROPERTY_ID_QUERYTIMEOUT:
298 : case PROPERTY_ID_MAXFIELDSIZE:
299 : case PROPERTY_ID_MAXROWS:
300 : case PROPERTY_ID_CURSORNAME:
301 : case PROPERTY_ID_RESULTSETCONCURRENCY:
302 : case PROPERTY_ID_RESULTSETTYPE:
303 : case PROPERTY_ID_FETCHDIRECTION:
304 : case PROPERTY_ID_FETCHSIZE:
305 : case PROPERTY_ID_ESCAPEPROCESSING:
306 : case PROPERTY_ID_USEBOOKMARKS:
307 : default:
308 : ;
309 : }
310 0 : }
311 :
312 0 : void OStatementCommonBase::getFastPropertyValue(Any& rValue,sal_Int32 nHandle) const
313 : {
314 : (void) rValue;
315 : switch(nHandle)
316 : {
317 : case PROPERTY_ID_QUERYTIMEOUT:
318 : case PROPERTY_ID_MAXFIELDSIZE:
319 : case PROPERTY_ID_MAXROWS:
320 : case PROPERTY_ID_CURSORNAME:
321 : case PROPERTY_ID_RESULTSETCONCURRENCY:
322 : case PROPERTY_ID_RESULTSETTYPE:
323 : case PROPERTY_ID_FETCHDIRECTION:
324 : case PROPERTY_ID_FETCHSIZE:
325 : case PROPERTY_ID_ESCAPEPROCESSING:
326 : case PROPERTY_ID_USEBOOKMARKS:
327 : default:
328 : ;
329 : }
330 0 : }
331 :
332 0 : void SAL_CALL OStatementCommonBase::acquire() throw()
333 : {
334 0 : OStatementCommonBase_Base::acquire();
335 0 : }
336 :
337 0 : void SAL_CALL OStatementCommonBase::release() throw()
338 : {
339 0 : OStatementCommonBase_Base::release();
340 0 : }
341 :
342 0 : uno::Reference< ::com::sun::star::beans::XPropertySetInfo > SAL_CALL OStatementCommonBase::getPropertySetInfo( ) throw(RuntimeException, std::exception)
343 : {
344 0 : return ::cppu::OPropertySetHelper::createPropertySetInfo(getInfoHelper());
345 : }
346 :
347 0 : short OStatementCommonBase::getSqlInfoItem(char aInfoItem)
348 : throw (SQLException)
349 : {
350 : ISC_STATUS_ARRAY aStatusVector;
351 : ISC_STATUS aErr;
352 :
353 0 : char aInfoItems[] = {aInfoItem};
354 : char aResultsBuffer[8];
355 :
356 : aErr = isc_dsql_sql_info(aStatusVector,
357 : &m_aStatementHandle,
358 : sizeof(aInfoItems),
359 : aInfoItems,
360 : sizeof(aResultsBuffer),
361 0 : aResultsBuffer);
362 :
363 0 : if (!aErr && aResultsBuffer[0] == aInfoItem)
364 : {
365 0 : const short aBytes = (short) isc_vax_integer(aResultsBuffer+1, 2);
366 0 : return (short) isc_vax_integer(aResultsBuffer+3, aBytes);
367 : }
368 :
369 : evaluateStatusVector(aStatusVector,
370 : "isc_dsq_sql_info",
371 0 : *this);
372 0 : return 0;
373 : }
374 :
375 0 : bool OStatementCommonBase::isDDLStatement()
376 : throw (SQLException)
377 : {
378 0 : if (getSqlInfoItem(isc_info_sql_stmt_type) == isc_info_sql_stmt_ddl)
379 0 : return true;
380 : else
381 0 : return false;
382 : }
383 :
384 0 : sal_Int32 OStatementCommonBase::getStatementChangeCount()
385 : throw (SQLException)
386 : {
387 0 : const short aStatementType = getSqlInfoItem(isc_info_sql_stmt_type);
388 :
389 :
390 :
391 : ISC_STATUS_ARRAY aStatusVector;
392 : ISC_STATUS aErr;
393 :
394 : // This is somewhat undocumented so I'm just guessing and hoping for the best.
395 0 : char aInfoItems[] = {isc_info_sql_records};
396 : char aResultsBuffer[1024];
397 :
398 : aErr = isc_dsql_sql_info(aStatusVector,
399 : &m_aStatementHandle,
400 : sizeof(aInfoItems),
401 : aInfoItems,
402 : sizeof(aResultsBuffer),
403 0 : aResultsBuffer);
404 :
405 0 : if (aErr)
406 : {
407 : evaluateStatusVector(aStatusVector,
408 : "isc_dsq_sql_info",
409 0 : *this);
410 0 : return 0;
411 : }
412 :
413 0 : short aDesiredInfoType = 0;
414 0 : switch (aStatementType)
415 : {
416 : case isc_info_sql_stmt_select:
417 0 : aDesiredInfoType = isc_info_req_select_count;
418 0 : break;
419 : case isc_info_sql_stmt_insert:
420 0 : aDesiredInfoType = isc_info_req_insert_count;
421 0 : break;
422 : case isc_info_sql_stmt_update:
423 0 : aDesiredInfoType = isc_info_req_update_count;
424 0 : break;
425 : case isc_info_sql_stmt_delete:
426 0 : aDesiredInfoType = isc_info_req_delete_count;
427 0 : break;
428 : default:
429 0 : throw SQLException(); // TODO: better error message?
430 : }
431 :
432 0 : char* pResults = aResultsBuffer;
433 0 : if (((short) *pResults++) == isc_info_sql_records)
434 : {
435 : // const short aTotalLength = (short) isc_vax_integer(pResults, 2);
436 0 : pResults += 2;
437 :
438 : // Seems to be of form TOKEN (1 byte), LENGTH (2 bytes), DATA (LENGTH bytes)
439 0 : while (*pResults != isc_info_rsb_end)
440 : {
441 0 : const char aToken = *pResults;
442 0 : const short aLength = (short) isc_vax_integer(pResults+1, 2);
443 :
444 0 : if (aToken == aDesiredInfoType)
445 : {
446 0 : return sal_Int32(isc_vax_integer(pResults + 3, aLength));
447 : }
448 :
449 0 : pResults += (3 + aLength);
450 : }
451 : }
452 :
453 0 : return 0;
454 0 : }
455 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|