update dev300-m58
[ooovba.git] / connectivity / source / drivers / ado / APreparedStatement.cxx
blob38284a3d428855283fb8199c7199f88e73e16c49
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: APreparedStatement.cxx,v $
10 * $Revision: 1.27 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_connectivity.hxx"
33 #include "connectivity/sqlparse.hxx"
34 #include "ado/APreparedStatement.hxx"
35 #include <com/sun/star/sdbc/DataType.hpp>
36 #include "ado/AResultSetMetaData.hxx"
37 #include "ado/AResultSet.hxx"
38 #include "ado/ADriver.hxx"
39 #include <com/sun/star/lang/DisposedException.hpp>
40 #include <cppuhelper/typeprovider.hxx>
41 #include <comphelper/sequence.hxx>
42 #include "connectivity/dbexception.hxx"
43 #include "connectivity/dbtools.hxx"
44 #include "resource/ado_res.hrc"
46 #include <limits>
48 #define CHECK_RETURN(x) \
49 if(!x) \
50 ADOS::ThrowException(*m_pConnection->getConnection(),*this);
52 //------------------------------------------------------------------------------
53 //------------------------------------------------------------------------------
54 using namespace connectivity::ado;
55 using namespace connectivity;
56 using namespace com::sun::star::uno;
57 using namespace com::sun::star::lang;
58 using namespace com::sun::star::beans;
59 using namespace com::sun::star::sdbc;
60 using namespace com::sun::star::util;
63 IMPLEMENT_SERVICE_INFO(OPreparedStatement,"com.sun.star.sdbcx.APreparedStatement","com.sun.star.sdbc.PreparedStatement");
65 OPreparedStatement::OPreparedStatement( OConnection* _pConnection,const OTypeInfoMap& _TypeInfo,const ::rtl::OUString& sql)
66 : OStatement_Base( _pConnection )
67 ,m_aTypeInfo(_TypeInfo)
69 osl_incrementInterlockedCount( &m_refCount );
71 OSQLParser aParser(_pConnection->getDriver()->getORB());
72 ::rtl::OUString sErrorMessage;
73 ::rtl::OUString sNewSql;
74 OSQLParseNode* pNode = aParser.parseTree(sErrorMessage,sql);
75 if(pNode)
76 { // special handling for parameters
77 /* we recusive replace all occurences of ? in the statement and replace them with name like "æ¬å" */
78 sal_Int32 nParameterCount = 0;
79 ::rtl::OUString sDefaultName = ::rtl::OUString::createFromAscii("parame");
80 replaceParameterNodeName(pNode,sDefaultName,nParameterCount);
81 pNode->parseNodeToStr( sNewSql, _pConnection );
82 delete pNode;
84 else
85 sNewSql = sql;
86 CHECK_RETURN(m_Command.put_CommandText(sNewSql))
87 CHECK_RETURN(m_Command.put_Prepared(VARIANT_TRUE))
88 m_pParameters = m_Command.get_Parameters();
89 m_pParameters->AddRef();
90 m_pParameters->Refresh();
92 osl_decrementInterlockedCount( &m_refCount );
95 // -------------------------------------------------------------------------
96 OPreparedStatement::~OPreparedStatement()
98 if (m_pParameters)
100 OSL_ENSURE( sal_False, "OPreparedStatement::~OPreparedStatement: not disposed!" );
101 m_pParameters->Release();
102 m_pParameters = NULL;
106 // -------------------------------------------------------------------------
108 Any SAL_CALL OPreparedStatement::queryInterface( const Type & rType ) throw(RuntimeException)
110 Any aRet = OStatement_Base::queryInterface(rType);
111 return aRet.hasValue() ? aRet : ::cppu::queryInterface( rType,
112 static_cast< XPreparedStatement*>(this),
113 static_cast< XParameters*>(this),
114 static_cast< XPreparedBatchExecution*>(this),
115 static_cast< XResultSetMetaDataSupplier*>(this));
117 // -------------------------------------------------------------------------
118 ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type > SAL_CALL OPreparedStatement::getTypes( ) throw(::com::sun::star::uno::RuntimeException)
120 ::cppu::OTypeCollection aTypes( ::getCppuType( (const ::com::sun::star::uno::Reference< XPreparedStatement > *)0 ),
121 ::getCppuType( (const ::com::sun::star::uno::Reference< XParameters > *)0 ),
122 ::getCppuType( (const ::com::sun::star::uno::Reference< XResultSetMetaDataSupplier > *)0 ),
123 ::getCppuType( (const ::com::sun::star::uno::Reference< XPreparedBatchExecution > *)0 ));
125 return ::comphelper::concatSequences(aTypes.getTypes(),OStatement_Base::getTypes());
127 // -------------------------------------------------------------------------
129 Reference< XResultSetMetaData > SAL_CALL OPreparedStatement::getMetaData( ) throw(SQLException, RuntimeException)
131 if(!m_xMetaData.is() && m_RecordSet.IsValid())
132 m_xMetaData = new OResultSetMetaData(m_RecordSet);
133 return m_xMetaData;
135 // -------------------------------------------------------------------------
136 void OPreparedStatement::disposing()
138 m_xMetaData.clear();
139 if (m_pParameters)
141 m_pParameters->Release();
142 m_pParameters = NULL;
144 OStatement_Base::disposing();
146 // -------------------------------------------------------------------------
148 void SAL_CALL OPreparedStatement::close( ) throw(SQLException, RuntimeException)
152 ::osl::MutexGuard aGuard( m_aMutex );
153 checkDisposed(OStatement_BASE::rBHelper.bDisposed);
156 dispose();
159 // -------------------------------------------------------------------------
161 sal_Bool SAL_CALL OPreparedStatement::execute( ) throw(SQLException, RuntimeException)
163 ::osl::MutexGuard aGuard( m_aMutex );
164 checkDisposed(OStatement_BASE::rBHelper.bDisposed);
167 SQLWarning warning;
169 // Reset warnings
171 clearWarnings ();
173 // Reset the statement handle, warning and saved Resultset
175 // reset();
177 // Call SQLExecute
179 try {
180 ADORecordset* pSet=NULL;
181 CHECK_RETURN(m_Command.Execute(m_RecordsAffected,m_Parameters,adCmdUnknown,&pSet))
182 m_RecordSet = WpADORecordset(pSet);
184 catch (SQLWarning& ex)
187 // Save pointer to warning and save with ResultSet
188 // object once it is created.
190 warning = ex;
192 return m_RecordSet.IsValid();
194 // -------------------------------------------------------------------------
196 sal_Int32 SAL_CALL OPreparedStatement::executeUpdate( ) throw(SQLException, RuntimeException)
198 ::osl::MutexGuard aGuard( m_aMutex );
199 checkDisposed(OStatement_BASE::rBHelper.bDisposed);
202 ADORecordset* pSet=NULL;
203 CHECK_RETURN(m_Command.Execute(m_RecordsAffected,m_Parameters,adCmdUnknown,&pSet))
204 if ( VT_ERROR == m_RecordsAffected.getType() )
206 ADOS::ThrowException(*m_pConnection->getConnection(),*this);
207 // to be sure that we get the error really thrown
208 throw SQLException();
210 m_RecordSet = WpADORecordset(pSet);
211 return static_cast<sal_Int32>(m_RecordsAffected);
214 // -------------------------------------------------------------------------
215 void OPreparedStatement::setParameter(sal_Int32 parameterIndex, const DataTypeEnum& _eType,
216 const sal_Int32& _nSize,const OLEVariant& _Val) throw(SQLException, RuntimeException)
218 ::osl::MutexGuard aGuard( m_aMutex );
219 checkDisposed(OStatement_BASE::rBHelper.bDisposed);
222 sal_Int32 nCount = 0;
223 m_pParameters->get_Count(&nCount);
224 if(nCount < (parameterIndex-1))
226 ::rtl::OUString sDefaultName = ::rtl::OUString::createFromAscii("parame");
227 sDefaultName += ::rtl::OUString::valueOf(parameterIndex);
228 ADOParameter* pParam = m_Command.CreateParameter(sDefaultName,_eType,adParamInput,_nSize,_Val);
229 if(pParam)
231 m_pParameters->Append(pParam);
232 #if OSL_DEBUG_LEVEL > 0
233 ADOParameter* pParam = NULL;
234 m_pParameters->get_Item(OLEVariant(sal_Int32(parameterIndex-1)),&pParam);
235 WpADOParameter aParam(pParam);
236 if(pParam)
238 DataTypeEnum eType = aParam.GetADOType();
239 (void)eType;
241 #endif
244 else
246 ADOParameter* pParam = NULL;
247 m_pParameters->get_Item(OLEVariant(sal_Int32(parameterIndex-1)),&pParam);
248 WpADOParameter aParam(pParam);
249 if(pParam)
251 #if OSL_DEBUG_LEVEL > 0
252 ::rtl::OUString sParam = aParam.GetName();
254 #endif // OSL_DEBUG_LEVEL
256 DataTypeEnum eType = aParam.GetADOType();
257 if ( _eType != eType && _eType != adDBTimeStamp )
259 aParam.put_Type(_eType);
260 eType = _eType;
261 aParam.put_Size(_nSize);
264 if ( adVarBinary == eType && aParam.GetAttributes() == adParamLong )
266 aParam.AppendChunk(_Val);
268 else
269 CHECK_RETURN(aParam.PutValue(_Val));
272 ADOS::ThrowException(*m_pConnection->getConnection(),*this);
274 // -------------------------------------------------------------------------
275 void SAL_CALL OPreparedStatement::setString( sal_Int32 parameterIndex, const ::rtl::OUString& x ) throw(SQLException, RuntimeException)
277 setParameter( parameterIndex, adLongVarWChar, ::std::numeric_limits< sal_Int32 >::max(), x );
279 // -------------------------------------------------------------------------
281 Reference< XConnection > SAL_CALL OPreparedStatement::getConnection( ) throw(SQLException, RuntimeException)
283 ::osl::MutexGuard aGuard( m_aMutex );
284 checkDisposed(OStatement_BASE::rBHelper.bDisposed);
287 return (Reference< XConnection >)m_pConnection;
289 // -------------------------------------------------------------------------
291 Reference< XResultSet > SAL_CALL OPreparedStatement::executeQuery( ) throw(SQLException, RuntimeException)
293 ::osl::MutexGuard aGuard( m_aMutex );
294 checkDisposed(OStatement_BASE::rBHelper.bDisposed);
297 // first clear the old things
298 m_xMetaData.clear();
299 disposeResultSet();
300 if(m_RecordSet.IsValid())
301 m_RecordSet.Close();
302 m_RecordSet.clear();
305 // the create the new onces
306 m_RecordSet.Create();
307 OLEVariant aCmd;
308 aCmd.setIDispatch(m_Command);
309 OLEVariant aCon;
310 aCon.setNoArg();
311 CHECK_RETURN(m_RecordSet.put_CacheSize(m_nFetchSize))
312 CHECK_RETURN(m_RecordSet.put_MaxRecords(m_nMaxRows))
313 CHECK_RETURN(m_RecordSet.Open(aCmd,aCon,m_eCursorType,m_eLockType,adOpenUnspecified))
314 CHECK_RETURN(m_RecordSet.get_CacheSize(m_nFetchSize))
315 CHECK_RETURN(m_RecordSet.get_MaxRecords(m_nMaxRows))
316 CHECK_RETURN(m_RecordSet.get_CursorType(m_eCursorType))
317 CHECK_RETURN(m_RecordSet.get_LockType(m_eLockType))
319 OResultSet* pSet = new OResultSet(m_RecordSet,this);
320 Reference< XResultSet > xRs = pSet;
321 pSet->construct();
322 pSet->setMetaData(getMetaData());
323 m_xResultSet = WeakReference<XResultSet>(xRs);
325 return xRs;
327 // -------------------------------------------------------------------------
329 void SAL_CALL OPreparedStatement::setBoolean( sal_Int32 parameterIndex, sal_Bool x ) throw(SQLException, RuntimeException)
331 setParameter(parameterIndex,adBoolean,sizeof(x),x);
333 // -------------------------------------------------------------------------
335 void SAL_CALL OPreparedStatement::setByte( sal_Int32 parameterIndex, sal_Int8 x ) throw(SQLException, RuntimeException)
337 setParameter(parameterIndex,adTinyInt,sizeof(x),x);
339 // -------------------------------------------------------------------------
341 void SAL_CALL OPreparedStatement::setDate( sal_Int32 parameterIndex, const Date& x ) throw(SQLException, RuntimeException)
343 setParameter(parameterIndex,adDBDate,sizeof(x),x);
345 // -------------------------------------------------------------------------
348 void SAL_CALL OPreparedStatement::setTime( sal_Int32 parameterIndex, const Time& x ) throw(SQLException, RuntimeException)
350 setParameter(parameterIndex,adDBTime,sizeof(x),x);
352 // -------------------------------------------------------------------------
354 void SAL_CALL OPreparedStatement::setTimestamp( sal_Int32 parameterIndex, const DateTime& x ) throw(SQLException, RuntimeException)
356 setParameter(parameterIndex,adDBTimeStamp,sizeof(x),x);
358 // -------------------------------------------------------------------------
360 void SAL_CALL OPreparedStatement::setDouble( sal_Int32 parameterIndex, double x ) throw(SQLException, RuntimeException)
362 setParameter(parameterIndex,adDouble,sizeof(x),x);
364 // -------------------------------------------------------------------------
366 void SAL_CALL OPreparedStatement::setFloat( sal_Int32 parameterIndex, float x ) throw(SQLException, RuntimeException)
368 setParameter(parameterIndex,adSingle,sizeof(x),x);
370 // -------------------------------------------------------------------------
372 void SAL_CALL OPreparedStatement::setInt( sal_Int32 parameterIndex, sal_Int32 x ) throw(SQLException, RuntimeException)
374 setParameter(parameterIndex,adInteger,sizeof(x),x);
376 // -------------------------------------------------------------------------
378 void SAL_CALL OPreparedStatement::setLong( sal_Int32 parameterIndex, sal_Int64 x ) throw(SQLException, RuntimeException)
380 setParameter(parameterIndex,adBigInt,sizeof(x),x);
382 // -------------------------------------------------------------------------
384 void SAL_CALL OPreparedStatement::setNull( sal_Int32 parameterIndex, sal_Int32 /*sqlType*/ ) throw(SQLException, RuntimeException)
386 OLEVariant aVal;
387 aVal.setNull();
388 setParameter(parameterIndex,adEmpty,0,aVal);
390 // -------------------------------------------------------------------------
392 void SAL_CALL OPreparedStatement::setClob( sal_Int32 /*parameterIndex*/, const Reference< XClob >& /*x*/ ) throw(SQLException, RuntimeException)
394 ::dbtools::throwFeatureNotImplementedException( "XRowUpdate::setClob", *this );
396 // -------------------------------------------------------------------------
398 void SAL_CALL OPreparedStatement::setBlob( sal_Int32 /*parameterIndex*/, const Reference< XBlob >& /*x*/ ) throw(SQLException, RuntimeException)
400 ::dbtools::throwFeatureNotImplementedException( "XRowUpdate::setBlob", *this );
402 // -------------------------------------------------------------------------
404 void SAL_CALL OPreparedStatement::setArray( sal_Int32 /*parameterIndex*/, const Reference< XArray >& /*x*/ ) throw(SQLException, RuntimeException)
406 ::dbtools::throwFeatureNotImplementedException( "XRowUpdate::setArray", *this );
408 // -------------------------------------------------------------------------
410 void SAL_CALL OPreparedStatement::setRef( sal_Int32 /*parameterIndex*/, const Reference< XRef >& /*x*/ ) throw(SQLException, RuntimeException)
412 ::dbtools::throwFeatureNotImplementedException( "XRowUpdate::setRef", *this );
414 // -------------------------------------------------------------------------
416 void SAL_CALL OPreparedStatement::setObjectWithInfo( sal_Int32 parameterIndex, const Any& x, sal_Int32 sqlType, sal_Int32 scale ) throw(SQLException, RuntimeException)
418 switch(sqlType)
420 case DataType::DECIMAL:
421 case DataType::NUMERIC:
422 setString(parameterIndex,::comphelper::getString(x));
423 break;
424 default:
425 ::dbtools::setObjectWithInfo(this,parameterIndex,x,sqlType,scale);
426 break;
429 // -------------------------------------------------------------------------
431 void SAL_CALL OPreparedStatement::setObjectNull( sal_Int32 parameterIndex, sal_Int32 sqlType, const ::rtl::OUString& /*typeName*/ ) throw(SQLException, RuntimeException)
433 setNull(parameterIndex,sqlType);
435 // -------------------------------------------------------------------------
437 void SAL_CALL OPreparedStatement::setObject( sal_Int32 parameterIndex, const Any& x ) throw(SQLException, RuntimeException)
439 if(!::dbtools::implSetObject(this,parameterIndex,x))
441 const ::rtl::OUString sError( m_pConnection->getResources().getResourceStringWithSubstitution(
442 STR_UNKNOWN_PARA_TYPE,
443 "$position$", ::rtl::OUString::valueOf(parameterIndex)
444 ) );
445 ::dbtools::throwGenericSQLException(sError,*this);
447 // setObject (parameterIndex, x, sqlType, 0);
449 // -------------------------------------------------------------------------
451 void SAL_CALL OPreparedStatement::setShort( sal_Int32 parameterIndex, sal_Int16 x ) throw(SQLException, RuntimeException)
453 setParameter(parameterIndex,adSmallInt,sizeof(x),x);
455 // -------------------------------------------------------------------------
457 void SAL_CALL OPreparedStatement::setBytes( sal_Int32 parameterIndex, const Sequence< sal_Int8 >& x ) throw(SQLException, RuntimeException)
459 setParameter(parameterIndex,adVarBinary,sizeof(sal_Int8)*x.getLength(),x);
462 // -------------------------------------------------------------------------
465 void SAL_CALL OPreparedStatement::setCharacterStream( sal_Int32 /*parameterIndex*/, const Reference< ::com::sun::star::io::XInputStream >& /*x*/, sal_Int32 /*length*/ ) throw(SQLException, RuntimeException)
467 ::dbtools::throwFeatureNotImplementedException( "XParameters::setCharacterStream", *this );
470 // -------------------------------------------------------------------------
472 void SAL_CALL OPreparedStatement::setBinaryStream( sal_Int32 parameterIndex, const Reference< ::com::sun::star::io::XInputStream >& x, sal_Int32 length ) throw(SQLException, RuntimeException)
474 if(x.is())
476 Sequence< sal_Int8 > aData;
477 x->readBytes(aData,length);
478 setBytes(parameterIndex,aData);
481 // -------------------------------------------------------------------------
483 void SAL_CALL OPreparedStatement::clearParameters( ) throw(SQLException, RuntimeException)
485 ::osl::MutexGuard aGuard( m_aMutex );
486 checkDisposed(OStatement_BASE::rBHelper.bDisposed);
489 if(m_pParameters)
491 sal_Int32 nCount = 0;
492 m_pParameters->get_Count(&nCount);
493 OLEVariant aVal;
494 aVal.setEmpty();
495 for(sal_Int32 i=0;i<nCount;++i)
497 ADOParameter* pParam = NULL;
498 m_pParameters->get_Item(OLEVariant(i),&pParam);
499 WpADOParameter aParam(pParam);
500 if(pParam)
502 ::rtl::OUString sParam = aParam.GetName();
503 CHECK_RETURN(aParam.PutValue(aVal));
506 // m_pParameters->Delete(OLEVariant(i));
510 // -------------------------------------------------------------------------
511 void SAL_CALL OPreparedStatement::clearBatch( ) throw(SQLException, RuntimeException)
513 // clearParameters( );
514 // m_aBatchList.erase();
516 // -------------------------------------------------------------------------
518 void SAL_CALL OPreparedStatement::addBatch( ) throw(SQLException, RuntimeException)
521 // -------------------------------------------------------------------------
523 Sequence< sal_Int32 > SAL_CALL OPreparedStatement::executeBatch( ) throw(SQLException, RuntimeException)
525 return Sequence< sal_Int32 > ();
527 // -----------------------------------------------------------------------------
528 // -----------------------------------------------------------------------------
529 void SAL_CALL OPreparedStatement::acquire() throw()
531 OStatement_Base::acquire();
533 // -----------------------------------------------------------------------------
534 void SAL_CALL OPreparedStatement::release() throw()
536 OStatement_Base::release();
538 // -----------------------------------------------------------------------------
539 void OPreparedStatement::replaceParameterNodeName(OSQLParseNode* _pNode,
540 const ::rtl::OUString& _sDefaultName,
541 sal_Int32& _rParameterCount)
543 sal_Int32 nCount = _pNode->count();
544 for(sal_Int32 i=0;i < nCount;++i)
546 OSQLParseNode* pChildNode = _pNode->getChild(i);
547 if(SQL_ISRULE(pChildNode,parameter) && pChildNode->count() == 1)
549 OSQLParseNode* pNewNode = new OSQLParseNode(::rtl::OUString::createFromAscii(":") ,SQL_NODE_PUNCTUATION,0);
550 delete pChildNode->replace(pChildNode->getChild(0),pNewNode);
551 ::rtl::OUString sParameterName = _sDefaultName;
552 sParameterName += ::rtl::OUString::valueOf(++_rParameterCount);
553 pChildNode->append(new OSQLParseNode( sParameterName,SQL_NODE_NAME,0));
555 else
556 replaceParameterNodeName(pChildNode,_sDefaultName,_rParameterCount);
560 // -----------------------------------------------------------------------------