1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_dbaccess.hxx"
26 #ifndef _DBA_COREAPI_STATEMENT_HXX_
27 #include <statement.hxx>
28 #endif
29 #ifndef _DBA_COREAPI_RESULTSET_HXX_
30 #include <resultset.hxx>
31 #endif
32 #ifndef DBACCESS_SHARED_DBASTRINGS_HRC
33 #include "dbastrings.hrc"
34 #endif
35 #ifndef _COM_SUN_STAR_LANG_DISPOSEDEXCEPTION_HPP_
36 #include <com/sun/star/lang/DisposedException.hpp>
37 #endif
38 #ifndef _COM_SUN_STAR_SDBC_XDATABASEMETADATA_HPP_
39 #include <com/sun/star/sdbc/XDatabaseMetaData.hpp>
40 #endif
41 #ifndef _COMPHELPER_SEQUENCE_HXX_
42 #include <comphelper/sequence.hxx>
43 #endif
44 #ifndef _CPPUHELPER_TYPEPROVIDER_HXX_
45 #include <cppuhelper/typeprovider.hxx>
46 #endif
47 #ifndef _COMPHELPER_PROPERTY_HXX_
48 #include <comphelper/property.hxx>
49 #endif
50 #ifndef _COMPHELPER_TYPES_HXX_
51 #include <comphelper/types.hxx>
52 #endif
53 #ifndef _TOOLS_DEBUG_HXX //autogen
54 #include <tools/debug.hxx>
55 #endif
56 #ifndef TOOLS_DIAGNOSE_EX_H
57 #include <tools/diagnose_ex.h>
58 #endif
59 #ifndef _DBHELPER_DBEXCEPTION_HXX_
60 #include <connectivity/dbexception.hxx>
61 #endif
62 #include <rtl/logfile.hxx>
63
64 using namespace ::com::sun::star::sdb;
65 using namespace ::com::sun::star::sdbc;
66 using namespace ::com::sun::star::beans;
67 using namespace ::com::sun::star::uno;
68 using namespace ::com::sun::star::lang;
69 using namespace ::cppu;
70 using namespace ::osl;
71 using namespace dbaccess;
72 using namespace dbtools;
73
DBG_NAME(OStatementBase)74 DBG_NAME(OStatementBase)
75
76 //--------------------------------------------------------------------------
77 OStatementBase::OStatementBase(const Reference< XConnection > & _xConn,
78 const Reference< XInterface > & _xStatement)
79 :OSubComponent(m_aMutex, _xConn)
80 ,OPropertySetHelper(OComponentHelper::rBHelper)
81 ,m_bUseBookmarks( sal_False )
82 ,m_bEscapeProcessing( sal_True )
83
84 {
85 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStatementBase::OStatementBase" );
86 DBG_CTOR(OStatementBase, NULL);
87 OSL_ENSURE(_xStatement.is() ,"Statement is NULL!");
88 m_xAggregateAsSet.set(_xStatement,UNO_QUERY);
89 m_xAggregateAsCancellable = Reference< ::com::sun::star::util::XCancellable > (m_xAggregateAsSet, UNO_QUERY);
90 }
91
92 //--------------------------------------------------------------------------
~OStatementBase()93 OStatementBase::~OStatementBase()
94 {
95 DBG_DTOR(OStatementBase, NULL);
96 }
97
98 // com::sun::star::lang::XTypeProvider
99 //--------------------------------------------------------------------------
getTypes()100 Sequence< Type > OStatementBase::getTypes() throw (RuntimeException)
101 {
102 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStatementBase::getTypes" );
103 OTypeCollection aTypes(::getCppuType( (const Reference< XPropertySet > *)0 ),
104 ::getCppuType( (const Reference< XWarningsSupplier > *)0 ),
105 ::getCppuType( (const Reference< XCloseable > *)0 ),
106 ::getCppuType( (const Reference< XMultipleResults > *)0 ),
107 ::getCppuType( (const Reference< ::com::sun::star::util::XCancellable > *)0 ),
108 OSubComponent::getTypes() );
109 Reference< XGeneratedResultSet > xGRes(m_xAggregateAsSet, UNO_QUERY);
110 if ( xGRes.is() )
111 aTypes = OTypeCollection(::getCppuType( (const Reference< XGeneratedResultSet > *)0 ),aTypes.getTypes());
112 Reference< XPreparedBatchExecution > xPreparedBatchExecution(m_xAggregateAsSet, UNO_QUERY);
113 if ( xPreparedBatchExecution.is() )
114 aTypes = OTypeCollection(::getCppuType( (const Reference< XPreparedBatchExecution > *)0 ),aTypes.getTypes());
115
116 return aTypes.getTypes();
117 }
118
119 // com::sun::star::uno::XInterface
120 //--------------------------------------------------------------------------
queryInterface(const Type & rType)121 Any OStatementBase::queryInterface( const Type & rType ) throw (RuntimeException)
122 {
123 //RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStatementBase::queryInterface" );
124 Any aIface = OSubComponent::queryInterface( rType );
125 if (!aIface.hasValue())
126 {
127 aIface = ::cppu::queryInterface(
128 rType,
129 static_cast< XPropertySet * >( this ),
130 static_cast< XWarningsSupplier * >( this ),
131 static_cast< XCloseable * >( this ),
132 static_cast< XMultipleResults * >( this ),
133 static_cast< ::com::sun::star::util::XCancellable * >( this ));
134 if ( !aIface.hasValue() )
135 {
136 Reference< XGeneratedResultSet > xGRes(m_xAggregateAsSet, UNO_QUERY);
137 if ( ::getCppuType( (const Reference< XGeneratedResultSet > *)0 ) == rType && xGRes.is() )
138 aIface = ::cppu::queryInterface(rType,static_cast< XGeneratedResultSet * >( this ));
139 } // if ( !aIface.hasValue() )
140 if ( !aIface.hasValue() )
141 {
142 Reference< XPreparedBatchExecution > xGRes(m_xAggregateAsSet, UNO_QUERY);
143 if ( ::getCppuType( (const Reference< XPreparedBatchExecution > *)0 ) == rType && xGRes.is() )
144 aIface = ::cppu::queryInterface(rType,static_cast< XPreparedBatchExecution * >( this ));
145 }
146 }
147 return aIface;
148 }
149
150 //--------------------------------------------------------------------------
acquire()151 void OStatementBase::acquire() throw ()
152 {
153 OSubComponent::acquire();
154 }
155
156 //--------------------------------------------------------------------------
release()157 void OStatementBase::release() throw ()
158 {
159 OSubComponent::release();
160 }
161
162 //------------------------------------------------------------------------------
disposeResultSet()163 void OStatementBase::disposeResultSet()
164 {
165 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStatementBase::disposeResultSet" );
166 // free the cursor if alive
167 Reference< XComponent > xComp(m_aResultSet.get(), UNO_QUERY);
168 if (xComp.is())
169 xComp->dispose();
170 m_aResultSet = NULL;
171 }
172
173 // OComponentHelper
174 //------------------------------------------------------------------------------
disposing()175 void OStatementBase::disposing()
176 {
177 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStatementBase::disposing" );
178 OPropertySetHelper::disposing();
179
180 MutexGuard aGuard(m_aMutex);
181
182 // free pending results
183 disposeResultSet();
184
185 // free the original statement
186 {
187 MutexGuard aCancelGuard(m_aCancelMutex);
188 m_xAggregateAsCancellable = NULL;
189 }
190
191 if ( m_xAggregateAsSet.is() )
192 {
193 try
194 {
195 Reference< XCloseable > (m_xAggregateAsSet, UNO_QUERY)->close();
196 }
197 catch(RuntimeException& )
198 {// don't care for anymore
199 }
200 }
201 m_xAggregateAsSet = NULL;
202
203 // free the parent at last
204 OSubComponent::disposing();
205 }
206
207 // XCloseable
208 //------------------------------------------------------------------------------
close(void)209 void OStatementBase::close(void) throw( SQLException, RuntimeException )
210 {
211 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStatementBase::close" );
212 {
213 MutexGuard aGuard( m_aMutex );
214 ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed);
215 }
216 dispose();
217 }
218
219 // OPropertySetHelper
220 //------------------------------------------------------------------------------
getPropertySetInfo()221 Reference< XPropertySetInfo > OStatementBase::getPropertySetInfo() throw (RuntimeException)
222 {
223 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStatementBase::getPropertySetInfo" );
224 return createPropertySetInfo( getInfoHelper() ) ;
225 }
226
227 // comphelper::OPropertyArrayUsageHelper
228 //------------------------------------------------------------------------------
createArrayHelper() const229 ::cppu::IPropertyArrayHelper* OStatementBase::createArrayHelper( ) const
230 {
231 //RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStatementBase::createArrayHelper" );
232 BEGIN_PROPERTY_HELPER(10)
233 DECL_PROP0(CURSORNAME, ::rtl::OUString);
234 DECL_PROP0_BOOL(ESCAPE_PROCESSING);
235 DECL_PROP0(FETCHDIRECTION, sal_Int32);
236 DECL_PROP0(FETCHSIZE, sal_Int32);
237 DECL_PROP0(MAXFIELDSIZE, sal_Int32);
238 DECL_PROP0(MAXROWS, sal_Int32);
239 DECL_PROP0(QUERYTIMEOUT, sal_Int32);
240 DECL_PROP0(RESULTSETCONCURRENCY, sal_Int32);
241 DECL_PROP0(RESULTSETTYPE, sal_Int32);
242 DECL_PROP0_BOOL(USEBOOKMARKS);
243 END_PROPERTY_HELPER();
244 }
245
246 // cppu::OPropertySetHelper
247 //------------------------------------------------------------------------------
getInfoHelper()248 ::cppu::IPropertyArrayHelper& OStatementBase::getInfoHelper()
249 {
250 //RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStatementBase::getInfoHelper" );
251 return *getArrayHelper();
252 }
253
254 //------------------------------------------------------------------------------
convertFastPropertyValue(Any & rConvertedValue,Any & rOldValue,sal_Int32 nHandle,const Any & rValue)255 sal_Bool OStatementBase::convertFastPropertyValue( Any & rConvertedValue, Any & rOldValue, sal_Int32 nHandle, const Any& rValue ) throw( IllegalArgumentException )
256 {
257 //RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStatementBase::convertFastPropertyValue" );
258 sal_Bool bModified(sal_False);
259 switch (nHandle)
260 {
261 case PROPERTY_ID_USEBOOKMARKS:
262 bModified = ::comphelper::tryPropertyValue( rConvertedValue, rOldValue, rValue, m_bUseBookmarks );
263 break;
264
265 case PROPERTY_ID_ESCAPE_PROCESSING:
266 bModified = ::comphelper::tryPropertyValue( rConvertedValue, rOldValue, rValue, m_bEscapeProcessing );
267 break;
268
269 default:
270 if ( m_xAggregateAsSet.is() )
271 {
272 // get the property name
273 ::rtl::OUString sPropName;
274 getInfoHelper().fillPropertyMembersByHandle( &sPropName, NULL, nHandle );
275
276 // now set the value
277 Any aCurrentValue = m_xAggregateAsSet->getPropertyValue( sPropName );
278 if ( aCurrentValue != rValue )
279 {
280 rOldValue = aCurrentValue;
281 rConvertedValue = rValue;
282 bModified = sal_True;
283 }
284 }
285 break;
286 }
287 return bModified;
288 }
289
290 //------------------------------------------------------------------------------
setFastPropertyValue_NoBroadcast(sal_Int32 nHandle,const Any & rValue)291 void OStatementBase::setFastPropertyValue_NoBroadcast( sal_Int32 nHandle, const Any& rValue ) throw (Exception)
292 {
293 //RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStatementBase::setFastPropertyValue_NoBroadcast" );
294 switch ( nHandle )
295 {
296 case PROPERTY_ID_USEBOOKMARKS:
297 {
298 m_bUseBookmarks = ::comphelper::getBOOL( rValue );
299 if ( m_xAggregateAsSet.is() && m_xAggregateAsSet->getPropertySetInfo()->hasPropertyByName( PROPERTY_USEBOOKMARKS ) )
300 m_xAggregateAsSet->setPropertyValue( PROPERTY_USEBOOKMARKS, rValue );
301 }
302 break;
303
304 case PROPERTY_ID_ESCAPE_PROCESSING:
305 m_bEscapeProcessing = ::comphelper::getBOOL( rValue );
306 if ( m_xAggregateAsSet.is() )
307 m_xAggregateAsSet->setPropertyValue( PROPERTY_ESCAPE_PROCESSING, rValue );
308 break;
309
310 default:
311 if ( m_xAggregateAsSet.is() )
312 {
313 ::rtl::OUString sPropName;
314 getInfoHelper().fillPropertyMembersByHandle( &sPropName, NULL, nHandle );
315 m_xAggregateAsSet->setPropertyValue( sPropName, rValue );
316 }
317 break;
318 }
319 }
320
321 //------------------------------------------------------------------------------
getFastPropertyValue(Any & rValue,sal_Int32 nHandle) const322 void OStatementBase::getFastPropertyValue( Any& rValue, sal_Int32 nHandle ) const
323 {
324 //RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStatementBase::getFastPropertyValue" );
325 switch (nHandle)
326 {
327 case PROPERTY_ID_USEBOOKMARKS:
328 rValue <<= m_bUseBookmarks;
329 break;
330
331 case PROPERTY_ID_ESCAPE_PROCESSING:
332 // don't rely on our aggregate - if it implements this wrong, and always returns
333 // TRUE here, then we would loop in impl_doEscapeProcessing_nothrow
334 rValue <<= m_bEscapeProcessing;
335 break;
336
337 default:
338 if ( m_xAggregateAsSet.is() )
339 {
340 ::rtl::OUString sPropName;
341 const_cast< OStatementBase* >( this )->getInfoHelper().fillPropertyMembersByHandle( &sPropName, NULL, nHandle );
342 rValue = m_xAggregateAsSet->getPropertyValue( sPropName );
343 }
344 break;
345 }
346 }
347
348 // XWarningsSupplier
349 //------------------------------------------------------------------------------
getWarnings(void)350 Any OStatementBase::getWarnings(void) throw( SQLException, RuntimeException )
351 {
352 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStatementBase::getWarnings" );
353 MutexGuard aGuard(m_aMutex);
354 ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed);
355
356 return Reference< XWarningsSupplier >(m_xAggregateAsSet, UNO_QUERY)->getWarnings();
357 }
358
359 //------------------------------------------------------------------------------
clearWarnings(void)360 void OStatementBase::clearWarnings(void) throw( SQLException, RuntimeException )
361 {
362 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStatementBase::clearWarnings" );
363 MutexGuard aGuard(m_aMutex);
364 ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed);
365
366 Reference< XWarningsSupplier >(m_xAggregateAsSet, UNO_QUERY)->clearWarnings();
367 }
368
369 // ::com::sun::star::util::XCancellable
370 //------------------------------------------------------------------------------
cancel(void)371 void OStatementBase::cancel(void) throw( RuntimeException )
372 {
373 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStatementBase::cancel" );
374 // no blocking as cancel is typically called from a different thread
375 ClearableMutexGuard aCancelGuard(m_aCancelMutex);
376 if (m_xAggregateAsCancellable.is())
377 m_xAggregateAsCancellable->cancel();
378 // else do nothing
379 }
380
381 // XMultipleResults
382 //------------------------------------------------------------------------------
getResultSet()383 Reference< XResultSet > SAL_CALL OStatementBase::getResultSet( ) throw(SQLException, RuntimeException)
384 {
385 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStatementBase::getResultSet" );
386 MutexGuard aGuard(m_aMutex);
387 ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed);
388
389 // first check the meta data
390 Reference<XDatabaseMetaData> xMeta = Reference< XConnection > (m_xParent, UNO_QUERY)->getMetaData();
391 if (!xMeta.is() && !xMeta->supportsMultipleResultSets())
392 throwFunctionSequenceException(*this);
393
394 return Reference< XMultipleResults >(m_xAggregateAsSet, UNO_QUERY)->getResultSet();
395 }
396
397 //------------------------------------------------------------------------------
getUpdateCount()398 sal_Int32 SAL_CALL OStatementBase::getUpdateCount( ) throw(SQLException, RuntimeException)
399 {
400 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStatementBase::getUpdateCount" );
401 MutexGuard aGuard(m_aMutex);
402 ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed);
403
404 // first check the meta data
405 Reference<XDatabaseMetaData> xMeta = Reference< XConnection > (m_xParent, UNO_QUERY)->getMetaData();
406 if (!xMeta.is() && !xMeta->supportsMultipleResultSets())
407 throwFunctionSequenceException(*this);
408
409 return Reference< XMultipleResults >(m_xAggregateAsSet, UNO_QUERY)->getUpdateCount();
410 }
411
412 //------------------------------------------------------------------------------
getMoreResults()413 sal_Bool SAL_CALL OStatementBase::getMoreResults( ) throw(SQLException, RuntimeException)
414 {
415 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStatementBase::getMoreResults" );
416 MutexGuard aGuard(m_aMutex);
417 ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed);
418
419 // first check the meta data
420 Reference<XDatabaseMetaData> xMeta = Reference< XConnection > (m_xParent, UNO_QUERY)->getMetaData();
421 if (!xMeta.is() && !xMeta->supportsMultipleResultSets())
422 throwFunctionSequenceException(*this);
423 throwFunctionSequenceException(*this);
424
425 // free the previous results
426 disposeResultSet();
427
428 return Reference< XMultipleResults >(m_xAggregateAsSet, UNO_QUERY)->getMoreResults();
429 }
430
431 // XPreparedBatchExecution
432 //------------------------------------------------------------------------------
addBatch()433 void SAL_CALL OStatementBase::addBatch( ) throw(SQLException, RuntimeException)
434 {
435 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStatementBase::addBatch" );
436 MutexGuard aGuard(m_aMutex);
437 ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed);
438
439 // first check the meta data
440 Reference<XDatabaseMetaData> xMeta = Reference< XConnection > (m_xParent, UNO_QUERY)->getMetaData();
441 if (!xMeta.is() && !xMeta->supportsBatchUpdates())
442 throwFunctionSequenceException(*this);
443
444 Reference< XPreparedBatchExecution >(m_xAggregateAsSet, UNO_QUERY)->addBatch();
445 }
446
447 //------------------------------------------------------------------------------
clearBatch()448 void SAL_CALL OStatementBase::clearBatch( ) throw(SQLException, RuntimeException)
449 {
450 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStatementBase::clearBatch" );
451 MutexGuard aGuard(m_aMutex);
452 ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed);
453
454 // first check the meta data
455 Reference<XDatabaseMetaData> xMeta = Reference< XConnection > (m_xParent, UNO_QUERY)->getMetaData();
456 if (!xMeta.is() && !xMeta->supportsBatchUpdates())
457 throwFunctionSequenceException(*this);
458
459 Reference< XPreparedBatchExecution >(m_xAggregateAsSet, UNO_QUERY)->clearBatch();
460 }
461
462 //------------------------------------------------------------------------------
executeBatch()463 Sequence< sal_Int32 > SAL_CALL OStatementBase::executeBatch( ) throw(SQLException, RuntimeException)
464 {
465 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStatementBase::executeBatch" );
466 MutexGuard aGuard(m_aMutex);
467 ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed);
468
469 // first check the meta data
470 Reference<XDatabaseMetaData> xMeta = Reference< XConnection > (m_xParent, UNO_QUERY)->getMetaData();
471 if (!xMeta.is() && !xMeta->supportsBatchUpdates())
472 throwFunctionSequenceException(*this);
473
474 // free the previous results
475 disposeResultSet();
476
477 return Reference< XPreparedBatchExecution >(m_xAggregateAsSet, UNO_QUERY)->executeBatch();
478 }
479 // -----------------------------------------------------------------------------
getGeneratedValues()480 Reference< XResultSet > SAL_CALL OStatementBase::getGeneratedValues( ) throw (SQLException, RuntimeException)
481 {
482 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStatementBase::getGeneratedValues" );
483 MutexGuard aGuard(m_aMutex);
484 ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed);
485 Reference< XGeneratedResultSet > xGRes(m_xAggregateAsSet, UNO_QUERY);
486
487 if ( xGRes.is() )
488 return xGRes->getGeneratedValues( );
489 return Reference< XResultSet >();
490 }
491
492 //************************************************************
493 // OStatement
494 //************************************************************
495 //------------------------------------------------------------------------------
OStatement(const Reference<XConnection> & _xConn,const Reference<XInterface> & _xStatement)496 OStatement::OStatement( const Reference< XConnection >& _xConn, const Reference< XInterface > & _xStatement )
497 :OStatementBase( _xConn, _xStatement )
498 ,m_bAttemptedComposerCreation( false )
499 {
500 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStatement::OStatement" );
501 m_xAggregateStatement.set( _xStatement, UNO_QUERY_THROW );
502 }
503
504 //------------------------------------------------------------------------------
505 IMPLEMENT_FORWARD_XINTERFACE2( OStatement, OStatementBase, OStatement_IFACE );
506 IMPLEMENT_FORWARD_XTYPEPROVIDER2( OStatement, OStatementBase, OStatement_IFACE );
507
508 // XServiceInfo
509 //------------------------------------------------------------------------------
getImplementationName()510 rtl::OUString OStatement::getImplementationName( ) throw(RuntimeException)
511 {
512 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStatement::getImplementationName" );
513 return rtl::OUString::createFromAscii("com.sun.star.sdb.OStatement");
514 }
515
516 //------------------------------------------------------------------------------
supportsService(const::rtl::OUString & _rServiceName)517 sal_Bool OStatement::supportsService( const ::rtl::OUString& _rServiceName ) throw (RuntimeException)
518 {
519 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStatement::supportsService" );
520 return ::comphelper::findValue(getSupportedServiceNames(), _rServiceName, sal_True).getLength() != 0;
521 }
522
523 //------------------------------------------------------------------------------
getSupportedServiceNames()524 Sequence< ::rtl::OUString > OStatement::getSupportedServiceNames( ) throw (RuntimeException)
525 {
526 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStatement::getSupportedServiceNames" );
527 Sequence< ::rtl::OUString > aSNS( 1 );
528 aSNS.getArray()[0] = SERVICE_SDBC_STATEMENT;
529 return aSNS;
530 }
531
532 // XStatement
533 //------------------------------------------------------------------------------
executeQuery(const rtl::OUString & _rSQL)534 Reference< XResultSet > OStatement::executeQuery( const rtl::OUString& _rSQL ) throw( SQLException, RuntimeException )
535 {
536 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStatement::executeQuery" );
537 MutexGuard aGuard(m_aMutex);
538 ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed);
539
540 disposeResultSet();
541 Reference< XResultSet > xResultSet;
542
543 ::rtl::OUString sSQL( impl_doEscapeProcessing_nothrow( _rSQL ) );
544
545 Reference< XResultSet > xInnerResultSet = m_xAggregateStatement->executeQuery( sSQL );
546 Reference< XConnection > xConnection( m_xParent, UNO_QUERY_THROW );
547
548 if ( xInnerResultSet.is() )
549 {
550 Reference< XDatabaseMetaData > xMeta = xConnection->getMetaData();
551 sal_Bool bCaseSensitive = xMeta.is() && xMeta->supportsMixedCaseQuotedIdentifiers();
552 xResultSet = new OResultSet( xInnerResultSet, *this, bCaseSensitive );
553
554 // keep the resultset weak
555 m_aResultSet = xResultSet;
556 }
557
558 return xResultSet;
559 }
560
561 //------------------------------------------------------------------------------
executeUpdate(const rtl::OUString & _rSQL)562 sal_Int32 OStatement::executeUpdate( const rtl::OUString& _rSQL ) throw( SQLException, RuntimeException )
563 {
564 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStatement::executeUpdate" );
565 MutexGuard aGuard(m_aMutex);
566 ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed);
567
568 disposeResultSet();
569
570 ::rtl::OUString sSQL( impl_doEscapeProcessing_nothrow( _rSQL ) );
571 return m_xAggregateStatement->executeUpdate( sSQL );
572 }
573
574 //------------------------------------------------------------------------------
execute(const rtl::OUString & _rSQL)575 sal_Bool OStatement::execute( const rtl::OUString& _rSQL ) throw( SQLException, RuntimeException )
576 {
577 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStatement::execute" );
578 MutexGuard aGuard(m_aMutex);
579 ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed);
580
581 disposeResultSet();
582
583 ::rtl::OUString sSQL( impl_doEscapeProcessing_nothrow( _rSQL ) );
584 return m_xAggregateStatement->execute( sSQL );
585 }
586 //------------------------------------------------------------------------------
addBatch(const rtl::OUString & _rSQL)587 void OStatement::addBatch( const rtl::OUString& _rSQL ) throw( SQLException, RuntimeException )
588 {
589 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStatement::execute" );
590 MutexGuard aGuard(m_aMutex);
591 ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed);
592
593 // first check the meta data
594 Reference<XDatabaseMetaData> xMeta = Reference< XConnection > (m_xParent, UNO_QUERY)->getMetaData();
595 if (!xMeta.is() && !xMeta->supportsBatchUpdates())
596 throwFunctionSequenceException(*this);
597
598 ::rtl::OUString sSQL( impl_doEscapeProcessing_nothrow( _rSQL ) );
599 Reference< XBatchExecution >(m_xAggregateAsSet, UNO_QUERY)->addBatch( sSQL );
600 }
601 //------------------------------------------------------------------------------
clearBatch()602 void OStatement::clearBatch( ) throw( SQLException, RuntimeException )
603 {
604 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStatement::execute" );
605 MutexGuard aGuard(m_aMutex);
606 ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed);
607 // first check the meta data
608 Reference<XDatabaseMetaData> xMeta = Reference< XConnection > (m_xParent, UNO_QUERY)->getMetaData();
609 if (!xMeta.is() && !xMeta->supportsBatchUpdates())
610 throwFunctionSequenceException(*this);
611
612 Reference< XBatchExecution >(m_xAggregateAsSet, UNO_QUERY)->clearBatch();
613 }
614 //------------------------------------------------------------------------------
executeBatch()615 Sequence< sal_Int32 > OStatement::executeBatch( ) throw( SQLException, RuntimeException )
616 {
617 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStatement::execute" );
618 MutexGuard aGuard(m_aMutex);
619 ::connectivity::checkDisposed(OComponentHelper::rBHelper.bDisposed);
620 // first check the meta data
621 Reference<XDatabaseMetaData> xMeta = Reference< XConnection > (m_xParent, UNO_QUERY)->getMetaData();
622 if (!xMeta.is() && !xMeta->supportsBatchUpdates())
623 throwFunctionSequenceException(*this);
624 return Reference< XBatchExecution >(m_xAggregateAsSet, UNO_QUERY)->executeBatch( );
625 }
626
627 //------------------------------------------------------------------------------
getConnection(void)628 Reference< XConnection > OStatement::getConnection(void) throw( SQLException, RuntimeException )
629 {
630 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStatement::getConnection" );
631 return Reference< XConnection >( m_xParent, UNO_QUERY );
632 }
633
634 // -----------------------------------------------------------------------------
disposing()635 void SAL_CALL OStatement::disposing()
636 {
637 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStatement::disposing" );
638 OStatementBase::disposing();
639 m_xComposer.clear();
640 m_xAggregateStatement.clear();
641 }
642
643 // -----------------------------------------------------------------------------
impl_doEscapeProcessing_nothrow(const::rtl::OUString & _rSQL) const644 ::rtl::OUString OStatement::impl_doEscapeProcessing_nothrow( const ::rtl::OUString& _rSQL ) const
645 {
646 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStatement::impl_doEscapeProcessing_nothrow" );
647 if ( !m_bEscapeProcessing )
648 return _rSQL;
649 try
650 {
651 if ( !impl_ensureComposer_nothrow() )
652 return _rSQL;
653
654 bool bParseable = false;
655 try { m_xComposer->setQuery( _rSQL ); bParseable = true; }
656 catch( const SQLException& ) { }
657
658 if ( !bParseable )
659 // if we cannot parse it, silently accept this. The driver is probably able to cope with it then
660 return _rSQL;
661
662 ::rtl::OUString sLowLevelSQL = m_xComposer->getQueryWithSubstitution();
663 return sLowLevelSQL;
664 }
665 catch( const Exception& )
666 {
667 DBG_UNHANDLED_EXCEPTION();
668 }
669
670 return _rSQL;
671 }
672
673 // -----------------------------------------------------------------------------
impl_ensureComposer_nothrow() const674 bool OStatement::impl_ensureComposer_nothrow() const
675 {
676 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OStatement::impl_ensureComposer_nothrow" );
677 if ( m_bAttemptedComposerCreation )
678 return m_xComposer.is();
679
680 const_cast< OStatement* >( this )->m_bAttemptedComposerCreation = true;
681 try
682 {
683 Reference< XMultiServiceFactory > xFactory( m_xParent, UNO_QUERY_THROW );
684 const_cast< OStatement* >( this )->m_xComposer.set( xFactory->createInstance( SERVICE_NAME_SINGLESELECTQUERYCOMPOSER ), UNO_QUERY_THROW );
685 }
686 catch( const Exception& )
687 {
688 DBG_UNHANDLED_EXCEPTION();
689 }
690
691 return m_xComposer.is();
692 }
693