Version 4.3.0.0.beta1, tag libreoffice-4.3.0.0.beta1
[LibreOffice.git] / connectivity / source / drivers / ado / APreparedStatement.cxx
blob31ed7ac31cc4be1ce9279e213b969c2e51858f56
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "connectivity/sqlparse.hxx"
21 #include "ado/APreparedStatement.hxx"
22 #include <com/sun/star/sdbc/DataType.hpp>
23 #include "ado/AResultSetMetaData.hxx"
24 #include "ado/AResultSet.hxx"
25 #include "ado/ADriver.hxx"
26 #include <com/sun/star/lang/DisposedException.hpp>
27 #include <cppuhelper/typeprovider.hxx>
28 #include <comphelper/processfactory.hxx>
29 #include <comphelper/sequence.hxx>
30 #include "connectivity/dbexception.hxx"
31 #include "connectivity/dbtools.hxx"
32 #include "resource/ado_res.hrc"
34 #include <limits>
36 #define CHECK_RETURN(x) \
37 if(!x) \
38 ADOS::ThrowException(*m_pConnection->getConnection(),*this);
40 #ifdef max
41 # undef max
42 #endif
44 using namespace connectivity::ado;
45 using namespace connectivity;
46 using namespace com::sun::star::uno;
47 using namespace com::sun::star::lang;
48 using namespace com::sun::star::beans;
49 using namespace com::sun::star::sdbc;
50 using namespace com::sun::star::util;
52 IMPLEMENT_SERVICE_INFO(OPreparedStatement,"com.sun.star.sdbcx.APreparedStatement","com.sun.star.sdbc.PreparedStatement");
54 OPreparedStatement::OPreparedStatement( OConnection* _pConnection,const OTypeInfoMap& _TypeInfo,const OUString& sql)
55 : OStatement_Base( _pConnection )
56 ,m_aTypeInfo(_TypeInfo)
58 osl_atomic_increment( &m_refCount );
60 OSQLParser aParser(comphelper::getComponentContext(_pConnection->getDriver()->getORB()));
61 OUString sErrorMessage;
62 OUString sNewSql;
63 OSQLParseNode* pNode = aParser.parseTree(sErrorMessage,sql);
64 if(pNode)
65 { // special handling for parameters
66 // we recursive replace all occurrences of ? in the statement and
67 // replace them with name like "parame" */
68 sal_Int32 nParameterCount = 0;
69 OUString sDefaultName( "parame" );
70 replaceParameterNodeName(pNode,sDefaultName,nParameterCount);
71 pNode->parseNodeToStr( sNewSql, _pConnection );
72 delete pNode;
74 else
75 sNewSql = sql;
76 CHECK_RETURN(m_Command.put_CommandText(sNewSql))
77 CHECK_RETURN(m_Command.put_Prepared(VARIANT_TRUE))
78 m_pParameters = m_Command.get_Parameters();
79 m_pParameters->AddRef();
80 m_pParameters->Refresh();
82 osl_atomic_decrement( &m_refCount );
85 OPreparedStatement::~OPreparedStatement()
87 if (m_pParameters)
89 OSL_FAIL( "OPreparedStatement::~OPreparedStatement: not disposed!" );
90 m_pParameters->Release();
91 m_pParameters = NULL;
95 Any SAL_CALL OPreparedStatement::queryInterface( const Type & rType ) throw(RuntimeException)
97 Any aRet = OStatement_Base::queryInterface(rType);
98 return aRet.hasValue() ? aRet : ::cppu::queryInterface( rType,
99 static_cast< XPreparedStatement*>(this),
100 static_cast< XParameters*>(this),
101 static_cast< XPreparedBatchExecution*>(this),
102 static_cast< XResultSetMetaDataSupplier*>(this));
105 ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type > SAL_CALL OPreparedStatement::getTypes( ) throw(::com::sun::star::uno::RuntimeException)
107 ::cppu::OTypeCollection aTypes( ::getCppuType( (const ::com::sun::star::uno::Reference< XPreparedStatement > *)0 ),
108 ::getCppuType( (const ::com::sun::star::uno::Reference< XParameters > *)0 ),
109 ::getCppuType( (const ::com::sun::star::uno::Reference< XResultSetMetaDataSupplier > *)0 ),
110 ::getCppuType( (const ::com::sun::star::uno::Reference< XPreparedBatchExecution > *)0 ));
112 return ::comphelper::concatSequences(aTypes.getTypes(),OStatement_Base::getTypes());
115 Reference< XResultSetMetaData > SAL_CALL OPreparedStatement::getMetaData( ) throw(SQLException, RuntimeException)
117 if(!m_xMetaData.is() && m_RecordSet.IsValid())
118 m_xMetaData = new OResultSetMetaData(m_RecordSet);
119 return m_xMetaData;
122 void OPreparedStatement::disposing()
124 m_xMetaData.clear();
125 if (m_pParameters)
127 m_pParameters->Release();
128 m_pParameters = NULL;
130 OStatement_Base::disposing();
133 void SAL_CALL OPreparedStatement::close( ) throw(SQLException, RuntimeException)
137 ::osl::MutexGuard aGuard( m_aMutex );
138 checkDisposed(OStatement_BASE::rBHelper.bDisposed);
141 dispose();
145 sal_Bool SAL_CALL OPreparedStatement::execute( ) throw(SQLException, RuntimeException)
147 ::osl::MutexGuard aGuard( m_aMutex );
148 checkDisposed(OStatement_BASE::rBHelper.bDisposed);
150 SQLWarning warning;
151 clearWarnings ();
153 // Call SQLExecute
154 try {
155 ADORecordset* pSet=NULL;
156 CHECK_RETURN(m_Command.Execute(m_RecordsAffected,m_Parameters,adCmdUnknown,&pSet))
157 m_RecordSet = WpADORecordset(pSet);
159 catch (SQLWarning& ex)
161 // Save pointer to warning and save with ResultSet
162 // object once it is created.
164 warning = ex;
166 return m_RecordSet.IsValid();
169 sal_Int32 SAL_CALL OPreparedStatement::executeUpdate( ) throw(SQLException, RuntimeException)
171 ::osl::MutexGuard aGuard( m_aMutex );
172 checkDisposed(OStatement_BASE::rBHelper.bDisposed);
175 ADORecordset* pSet=NULL;
176 CHECK_RETURN(m_Command.Execute(m_RecordsAffected,m_Parameters,adCmdUnknown,&pSet))
177 if ( VT_ERROR == m_RecordsAffected.getType() )
179 ADOS::ThrowException(*m_pConnection->getConnection(),*this);
180 // to be sure that we get the error really thrown
181 throw SQLException();
183 m_RecordSet = WpADORecordset(pSet);
184 return static_cast<sal_Int32>(m_RecordsAffected);
187 void OPreparedStatement::setParameter(sal_Int32 parameterIndex, const DataTypeEnum& _eType,
188 const sal_Int32& _nSize,const OLEVariant& _Val) throw(SQLException, RuntimeException)
190 ::osl::MutexGuard aGuard( m_aMutex );
191 checkDisposed(OStatement_BASE::rBHelper.bDisposed);
194 sal_Int32 nCount = 0;
195 m_pParameters->get_Count(&nCount);
196 if(nCount < (parameterIndex-1))
198 OUString sDefaultName( "parame" );
199 sDefaultName += OUString::number(parameterIndex);
200 ADOParameter* pParam = m_Command.CreateParameter(sDefaultName,_eType,adParamInput,_nSize,_Val);
201 if(pParam)
203 m_pParameters->Append(pParam);
204 #if OSL_DEBUG_LEVEL > 0
205 ADOParameter* pParam = NULL;
206 m_pParameters->get_Item(OLEVariant(sal_Int32(parameterIndex-1)),&pParam);
207 WpADOParameter aParam(pParam);
208 if(pParam)
210 DataTypeEnum eType = aParam.GetADOType();
211 (void)eType;
213 #endif
216 else
218 ADOParameter* pParam = NULL;
219 m_pParameters->get_Item(OLEVariant(sal_Int32(parameterIndex-1)),&pParam);
220 WpADOParameter aParam(pParam);
221 if(pParam)
223 #if OSL_DEBUG_LEVEL > 0
224 OUString sParam = aParam.GetName();
226 #endif // OSL_DEBUG_LEVEL
228 DataTypeEnum eType = aParam.GetADOType();
229 if ( _eType != eType && _eType != adDBTimeStamp )
231 aParam.put_Type(_eType);
232 eType = _eType;
233 aParam.put_Size(_nSize);
236 if ( adVarBinary == eType && aParam.GetAttributes() == adParamLong )
238 aParam.AppendChunk(_Val);
240 else
241 CHECK_RETURN(aParam.PutValue(_Val));
244 ADOS::ThrowException(*m_pConnection->getConnection(),*this);
247 void SAL_CALL OPreparedStatement::setString( sal_Int32 parameterIndex, const OUString& x ) throw(SQLException, RuntimeException)
249 setParameter( parameterIndex, adLongVarWChar, ::std::numeric_limits< sal_Int32 >::max(), x );
252 Reference< XConnection > SAL_CALL OPreparedStatement::getConnection( ) throw(SQLException, RuntimeException)
254 ::osl::MutexGuard aGuard( m_aMutex );
255 checkDisposed(OStatement_BASE::rBHelper.bDisposed);
257 return (Reference< XConnection >)m_pConnection;
260 Reference< XResultSet > SAL_CALL OPreparedStatement::executeQuery( ) throw(SQLException, RuntimeException)
262 ::osl::MutexGuard aGuard( m_aMutex );
263 checkDisposed(OStatement_BASE::rBHelper.bDisposed);
265 // first clear the old things
266 m_xMetaData.clear();
267 disposeResultSet();
268 if(m_RecordSet.IsValid())
269 m_RecordSet.Close();
270 m_RecordSet.clear();
272 // the create the new onces
273 m_RecordSet.Create();
274 OLEVariant aCmd;
275 aCmd.setIDispatch(m_Command);
276 OLEVariant aCon;
277 aCon.setNoArg();
278 CHECK_RETURN(m_RecordSet.put_CacheSize(m_nFetchSize))
279 CHECK_RETURN(m_RecordSet.put_MaxRecords(m_nMaxRows))
280 CHECK_RETURN(m_RecordSet.Open(aCmd,aCon,m_eCursorType,m_eLockType,adOpenUnspecified))
281 CHECK_RETURN(m_RecordSet.get_CacheSize(m_nFetchSize))
282 CHECK_RETURN(m_RecordSet.get_MaxRecords(m_nMaxRows))
283 CHECK_RETURN(m_RecordSet.get_CursorType(m_eCursorType))
284 CHECK_RETURN(m_RecordSet.get_LockType(m_eLockType))
286 OResultSet* pSet = new OResultSet(m_RecordSet,this);
287 Reference< XResultSet > xRs = pSet;
288 pSet->construct();
289 pSet->setMetaData(getMetaData());
290 m_xResultSet = WeakReference<XResultSet>(xRs);
292 return xRs;
295 void SAL_CALL OPreparedStatement::setBoolean( sal_Int32 parameterIndex, sal_Bool x ) throw(SQLException, RuntimeException)
297 setParameter(parameterIndex,adBoolean,sizeof(x),bool(x));
300 void SAL_CALL OPreparedStatement::setByte( sal_Int32 parameterIndex, sal_Int8 x ) throw(SQLException, RuntimeException)
302 setParameter(parameterIndex,adTinyInt,sizeof(x),x);
305 void SAL_CALL OPreparedStatement::setDate( sal_Int32 parameterIndex, const Date& x ) throw(SQLException, RuntimeException)
307 setParameter(parameterIndex,adDBDate,sizeof(x),x);
310 void SAL_CALL OPreparedStatement::setTime( sal_Int32 parameterIndex, const Time& x ) throw(SQLException, RuntimeException)
312 setParameter(parameterIndex,adDBTime,sizeof(x),x);
315 void SAL_CALL OPreparedStatement::setTimestamp( sal_Int32 parameterIndex, const DateTime& x ) throw(SQLException, RuntimeException)
317 setParameter(parameterIndex,adDBTimeStamp,sizeof(x),x);
320 void SAL_CALL OPreparedStatement::setDouble( sal_Int32 parameterIndex, double x ) throw(SQLException, RuntimeException)
322 setParameter(parameterIndex,adDouble,sizeof(x),x);
325 void SAL_CALL OPreparedStatement::setFloat( sal_Int32 parameterIndex, float x ) throw(SQLException, RuntimeException)
327 setParameter(parameterIndex,adSingle,sizeof(x),x);
330 void SAL_CALL OPreparedStatement::setInt( sal_Int32 parameterIndex, sal_Int32 x ) throw(SQLException, RuntimeException)
332 setParameter(parameterIndex,adInteger,sizeof(x),x);
335 void SAL_CALL OPreparedStatement::setLong( sal_Int32 parameterIndex, sal_Int64 x ) throw(SQLException, RuntimeException)
337 setParameter(parameterIndex,adBigInt,sizeof(x),x);
340 void SAL_CALL OPreparedStatement::setNull( sal_Int32 parameterIndex, sal_Int32 /*sqlType*/ ) throw(SQLException, RuntimeException)
342 OLEVariant aVal;
343 aVal.setNull();
344 setParameter(parameterIndex,adEmpty,0,aVal);
347 void SAL_CALL OPreparedStatement::setClob( sal_Int32 /*parameterIndex*/, const Reference< XClob >& /*x*/ ) throw(SQLException, RuntimeException)
349 ::dbtools::throwFeatureNotImplementedException( "XRowUpdate::setClob", *this );
352 void SAL_CALL OPreparedStatement::setBlob( sal_Int32 /*parameterIndex*/, const Reference< XBlob >& /*x*/ ) throw(SQLException, RuntimeException)
354 ::dbtools::throwFeatureNotImplementedException( "XRowUpdate::setBlob", *this );
357 void SAL_CALL OPreparedStatement::setArray( sal_Int32 /*parameterIndex*/, const Reference< XArray >& /*x*/ ) throw(SQLException, RuntimeException)
359 ::dbtools::throwFeatureNotImplementedException( "XRowUpdate::setArray", *this );
362 void SAL_CALL OPreparedStatement::setRef( sal_Int32 /*parameterIndex*/, const Reference< XRef >& /*x*/ ) throw(SQLException, RuntimeException)
364 ::dbtools::throwFeatureNotImplementedException( "XRowUpdate::setRef", *this );
367 void SAL_CALL OPreparedStatement::setObjectWithInfo( sal_Int32 parameterIndex, const Any& x, sal_Int32 sqlType, sal_Int32 scale ) throw(SQLException, RuntimeException)
369 switch(sqlType)
371 case DataType::DECIMAL:
372 case DataType::NUMERIC:
373 setString(parameterIndex,::comphelper::getString(x));
374 break;
375 default:
376 ::dbtools::setObjectWithInfo(this,parameterIndex,x,sqlType,scale);
377 break;
381 void SAL_CALL OPreparedStatement::setObjectNull( sal_Int32 parameterIndex, sal_Int32 sqlType, const OUString& /*typeName*/ ) throw(SQLException, RuntimeException)
383 setNull(parameterIndex,sqlType);
386 void SAL_CALL OPreparedStatement::setObject( sal_Int32 parameterIndex, const Any& x ) throw(SQLException, RuntimeException)
388 if(!::dbtools::implSetObject(this,parameterIndex,x))
390 const OUString sError( m_pConnection->getResources().getResourceStringWithSubstitution(
391 STR_UNKNOWN_PARA_TYPE,
392 "$position$", OUString::number(parameterIndex)
393 ) );
394 ::dbtools::throwGenericSQLException(sError,*this);
398 void SAL_CALL OPreparedStatement::setShort( sal_Int32 parameterIndex, sal_Int16 x ) throw(SQLException, RuntimeException)
400 setParameter(parameterIndex,adSmallInt,sizeof(x),x);
403 void SAL_CALL OPreparedStatement::setBytes( sal_Int32 parameterIndex, const Sequence< sal_Int8 >& x ) throw(SQLException, RuntimeException)
405 setParameter(parameterIndex,adVarBinary,sizeof(sal_Int8)*x.getLength(),x);
408 void SAL_CALL OPreparedStatement::setCharacterStream( sal_Int32 /*parameterIndex*/, const Reference< ::com::sun::star::io::XInputStream >& /*x*/, sal_Int32 /*length*/ ) throw(SQLException, RuntimeException)
410 ::dbtools::throwFeatureNotImplementedException( "XParameters::setCharacterStream", *this );
413 void SAL_CALL OPreparedStatement::setBinaryStream( sal_Int32 parameterIndex, const Reference< ::com::sun::star::io::XInputStream >& x, sal_Int32 length ) throw(SQLException, RuntimeException)
415 if(x.is())
417 Sequence< sal_Int8 > aData;
418 x->readBytes(aData,length);
419 setBytes(parameterIndex,aData);
423 void SAL_CALL OPreparedStatement::clearParameters( ) throw(SQLException, RuntimeException)
425 ::osl::MutexGuard aGuard( m_aMutex );
426 checkDisposed(OStatement_BASE::rBHelper.bDisposed);
429 if(m_pParameters)
431 sal_Int32 nCount = 0;
432 m_pParameters->get_Count(&nCount);
433 OLEVariant aVal;
434 aVal.setEmpty();
435 for(sal_Int32 i=0;i<nCount;++i)
437 ADOParameter* pParam = NULL;
438 m_pParameters->get_Item(OLEVariant(i),&pParam);
439 WpADOParameter aParam(pParam);
440 if(pParam)
442 OUString sParam = aParam.GetName();
443 CHECK_RETURN(aParam.PutValue(aVal));
449 void SAL_CALL OPreparedStatement::clearBatch( ) throw(SQLException, RuntimeException)
453 void SAL_CALL OPreparedStatement::addBatch( ) throw(SQLException, RuntimeException)
457 Sequence< sal_Int32 > SAL_CALL OPreparedStatement::executeBatch( ) throw(SQLException, RuntimeException)
459 return Sequence< sal_Int32 > ();
462 void SAL_CALL OPreparedStatement::acquire() throw()
464 OStatement_Base::acquire();
467 void SAL_CALL OPreparedStatement::release() throw()
469 OStatement_Base::release();
472 void OPreparedStatement::replaceParameterNodeName(OSQLParseNode* _pNode,
473 const OUString& _sDefaultName,
474 sal_Int32& _rParameterCount)
476 sal_Int32 nCount = _pNode->count();
477 for(sal_Int32 i=0;i < nCount;++i)
479 OSQLParseNode* pChildNode = _pNode->getChild(i);
480 if(SQL_ISRULE(pChildNode,parameter) && pChildNode->count() == 1)
482 OSQLParseNode* pNewNode = new OSQLParseNode(OUString(":") ,SQL_NODE_PUNCTUATION,0);
483 delete pChildNode->replace(pChildNode->getChild(0),pNewNode);
484 OUString sParameterName = _sDefaultName;
485 sParameterName += OUString::number(++_rParameterCount);
486 pChildNode->append(new OSQLParseNode( sParameterName,SQL_NODE_NAME,0));
488 else
489 replaceParameterNodeName(pChildNode,_sDefaultName,_rParameterCount);
494 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */