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