bump product version to 6.3.0.0.beta1
[LibreOffice.git] / connectivity / source / drivers / ado / APreparedStatement.cxx
blobecd4ed538d836e054d4f1b6c6e342f3fb66e5e87
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 <cppuhelper/queryinterface.hxx>
29 #include <comphelper/processfactory.hxx>
30 #include <comphelper/sequence.hxx>
31 #include <comphelper/types.hxx>
32 #include <connectivity/dbexception.hxx>
33 #include <connectivity/dbtools.hxx>
34 #include <strings.hrc>
36 #include <limits>
38 #define CHECK_RETURN(x) \
39 if(!x) \
40 ADOS::ThrowException(*m_pConnection->getConnection(),*this);
42 #ifdef max
43 # undef max
44 #endif
46 using namespace connectivity::ado;
47 using namespace connectivity;
48 using namespace com::sun::star::uno;
49 using namespace com::sun::star::lang;
50 using namespace com::sun::star::beans;
51 using namespace com::sun::star::sdbc;
52 using namespace com::sun::star::util;
54 IMPLEMENT_SERVICE_INFO(OPreparedStatement,"com.sun.star.sdbcx.APreparedStatement","com.sun.star.sdbc.PreparedStatement");
56 OPreparedStatement::OPreparedStatement( OConnection* _pConnection, const OUString& sql)
57 : OStatement_Base( _pConnection )
59 osl_atomic_increment( &m_refCount );
61 OSQLParser aParser(comphelper::getComponentContext(_pConnection->getDriver()->getORB()));
62 OUString sErrorMessage;
63 OUString sNewSql;
64 std::unique_ptr<OSQLParseNode> pNode = aParser.parseTree(sErrorMessage,sql);
65 if(pNode)
66 { // special handling for parameters
67 // we recursive replace all occurrences of ? in the statement and
68 // replace them with name like "parame" */
69 sal_Int32 nParameterCount = 0;
70 replaceParameterNodeName(pNode.get(), "parame", nParameterCount);
71 pNode->parseNodeToStr( sNewSql, _pConnection );
73 else
74 sNewSql = sql;
75 CHECK_RETURN(m_Command.put_CommandText(sNewSql))
76 CHECK_RETURN(m_Command.put_Prepared(VARIANT_TRUE))
77 m_pParameters = m_Command.get_Parameters();
78 m_pParameters->AddRef();
79 m_pParameters->Refresh();
81 osl_atomic_decrement( &m_refCount );
84 OPreparedStatement::~OPreparedStatement()
86 if (m_pParameters)
88 OSL_FAIL( "OPreparedStatement::~OPreparedStatement: not disposed!" );
89 m_pParameters->Release();
90 m_pParameters = nullptr;
94 Any SAL_CALL OPreparedStatement::queryInterface( const Type & rType )
96 Any aRet = OStatement_Base::queryInterface(rType);
97 return aRet.hasValue() ? aRet : ::cppu::queryInterface( rType,
98 static_cast< XPreparedStatement*>(this),
99 static_cast< XParameters*>(this),
100 static_cast< XResultSetMetaDataSupplier*>(this));
103 css::uno::Sequence< css::uno::Type > SAL_CALL OPreparedStatement::getTypes( )
105 ::cppu::OTypeCollection aTypes( cppu::UnoType<XPreparedStatement>::get(),
106 cppu::UnoType<XParameters>::get(),
107 cppu::UnoType<XResultSetMetaDataSupplier>::get());
109 return ::comphelper::concatSequences(aTypes.getTypes(),OStatement_Base::getTypes());
112 Reference< XResultSetMetaData > SAL_CALL OPreparedStatement::getMetaData( )
114 if(!m_xMetaData.is() && m_RecordSet.IsValid())
115 m_xMetaData = new OResultSetMetaData(m_RecordSet);
116 return m_xMetaData;
119 void OPreparedStatement::disposing()
121 m_xMetaData.clear();
122 if (m_pParameters)
124 m_pParameters->Release();
125 m_pParameters = nullptr;
127 OStatement_Base::disposing();
130 void SAL_CALL OPreparedStatement::close( )
134 ::osl::MutexGuard aGuard( m_aMutex );
135 checkDisposed(OStatement_BASE::rBHelper.bDisposed);
138 dispose();
142 sal_Bool SAL_CALL OPreparedStatement::execute( )
144 ::osl::MutexGuard aGuard( m_aMutex );
145 checkDisposed(OStatement_BASE::rBHelper.bDisposed);
147 SQLWarning warning;
148 clearWarnings ();
150 // Call SQLExecute
151 try {
152 ADORecordset* pSet=nullptr;
153 CHECK_RETURN(m_Command.Execute(m_RecordsAffected,m_Parameters,adCmdUnknown,&pSet))
154 m_RecordSet = WpADORecordset(pSet);
156 catch (SQLWarning& ex)
158 // Save pointer to warning and save with ResultSet
159 // object once it is created.
161 warning = ex;
163 return m_RecordSet.IsValid();
166 sal_Int32 SAL_CALL OPreparedStatement::executeUpdate( )
168 ::osl::MutexGuard aGuard( m_aMutex );
169 checkDisposed(OStatement_BASE::rBHelper.bDisposed);
172 ADORecordset* pSet=nullptr;
173 CHECK_RETURN(m_Command.Execute(m_RecordsAffected,m_Parameters,adCmdUnknown,&pSet))
174 if ( VT_ERROR == m_RecordsAffected.getType() )
176 ADOS::ThrowException(*m_pConnection->getConnection(),*this);
177 // to be sure that we get the error really thrown
178 throw SQLException();
180 m_RecordSet = WpADORecordset(pSet);
181 return m_RecordsAffected.getInt32();
184 void OPreparedStatement::setParameter(sal_Int32 parameterIndex, const DataTypeEnum& _eType,
185 sal_Int32 _nSize,const OLEVariant& Val)
187 ::osl::MutexGuard aGuard( m_aMutex );
188 checkDisposed(OStatement_BASE::rBHelper.bDisposed);
191 sal_Int32 nCount = 0;
192 m_pParameters->get_Count(&nCount);
193 if(nCount < (parameterIndex-1))
195 OUString sDefaultName = "parame" + OUString::number(parameterIndex);
196 ADOParameter* pParam = m_Command.CreateParameter(sDefaultName,_eType,adParamInput,_nSize,Val);
197 if(pParam)
199 m_pParameters->Append(pParam);
202 else
204 ADOParameter* pParam = nullptr;
205 m_pParameters->get_Item(OLEVariant(sal_Int32(parameterIndex-1)),&pParam);
206 WpADOParameter aParam(pParam);
207 if(pParam)
209 DataTypeEnum eType = aParam.GetADOType();
210 if ( _eType != eType && _eType != adDBTimeStamp )
212 aParam.put_Type(_eType);
213 eType = _eType;
214 aParam.put_Size(_nSize);
217 if ( adVarBinary == eType && aParam.GetAttributes() == adParamLong )
219 aParam.AppendChunk(Val);
221 else
222 CHECK_RETURN(aParam.PutValue(Val));
225 ADOS::ThrowException(*m_pConnection->getConnection(),*this);
228 void SAL_CALL OPreparedStatement::setString( sal_Int32 parameterIndex, const OUString& x )
230 setParameter( parameterIndex, adLongVarWChar, std::numeric_limits< sal_Int32 >::max(), x );
233 Reference< XConnection > SAL_CALL OPreparedStatement::getConnection( )
235 ::osl::MutexGuard aGuard( m_aMutex );
236 checkDisposed(OStatement_BASE::rBHelper.bDisposed);
238 return static_cast<Reference< XConnection >>(m_pConnection);
241 Reference< XResultSet > SAL_CALL OPreparedStatement::executeQuery( )
243 ::osl::MutexGuard aGuard( m_aMutex );
244 checkDisposed(OStatement_BASE::rBHelper.bDisposed);
246 // first clear the old things
247 m_xMetaData.clear();
248 disposeResultSet();
249 if(m_RecordSet.IsValid())
250 m_RecordSet.Close();
251 m_RecordSet.clear();
253 // then create the new ones
254 m_RecordSet.Create();
255 OLEVariant aCmd;
256 aCmd.setIDispatch(m_Command);
257 OLEVariant aCon;
258 aCon.setNoArg();
259 CHECK_RETURN(m_RecordSet.put_CacheSize(m_nFetchSize))
260 CHECK_RETURN(m_RecordSet.put_MaxRecords(m_nMaxRows))
261 CHECK_RETURN(m_RecordSet.Open(aCmd,aCon,m_eCursorType,m_eLockType,adOpenUnspecified))
262 CHECK_RETURN(m_RecordSet.get_CacheSize(m_nFetchSize))
263 CHECK_RETURN(m_RecordSet.get_MaxRecords(m_nMaxRows))
264 CHECK_RETURN(m_RecordSet.get_CursorType(m_eCursorType))
265 CHECK_RETURN(m_RecordSet.get_LockType(m_eLockType))
267 OResultSet* pSet = new OResultSet(m_RecordSet,this);
268 Reference< XResultSet > xRs = pSet;
269 pSet->construct();
270 pSet->setMetaData(getMetaData());
271 m_xResultSet = WeakReference<XResultSet>(xRs);
273 return xRs;
276 void SAL_CALL OPreparedStatement::setBoolean( sal_Int32 parameterIndex, sal_Bool x )
278 setParameter(parameterIndex,adBoolean,sizeof(x),bool(x));
281 void SAL_CALL OPreparedStatement::setByte( sal_Int32 parameterIndex, sal_Int8 x )
283 setParameter(parameterIndex,adTinyInt,sizeof(x),x);
286 void SAL_CALL OPreparedStatement::setDate( sal_Int32 parameterIndex, const Date& x )
288 setParameter(parameterIndex,adDBDate,sizeof(x),x);
291 void SAL_CALL OPreparedStatement::setTime( sal_Int32 parameterIndex, const css::util::Time& x )
293 setParameter(parameterIndex,adDBTime,sizeof(x),x);
296 void SAL_CALL OPreparedStatement::setTimestamp( sal_Int32 parameterIndex, const DateTime& x )
298 setParameter(parameterIndex,adDBTimeStamp,sizeof(x),x);
301 void SAL_CALL OPreparedStatement::setDouble( sal_Int32 parameterIndex, double x )
303 setParameter(parameterIndex,adDouble,sizeof(x),x);
306 void SAL_CALL OPreparedStatement::setFloat( sal_Int32 parameterIndex, float x )
308 setParameter(parameterIndex,adSingle,sizeof(x),x);
311 void SAL_CALL OPreparedStatement::setInt( sal_Int32 parameterIndex, sal_Int32 x )
313 setParameter(parameterIndex,adInteger,sizeof(x),x);
316 void SAL_CALL OPreparedStatement::setLong( sal_Int32 parameterIndex, sal_Int64 x )
318 setParameter(parameterIndex,adBigInt,sizeof(x),x);
321 void SAL_CALL OPreparedStatement::setNull( sal_Int32 parameterIndex, sal_Int32 /*sqlType*/ )
323 OLEVariant aVal;
324 aVal.setNull();
325 setParameter(parameterIndex,adEmpty,0,aVal);
328 void SAL_CALL OPreparedStatement::setClob( sal_Int32 /*parameterIndex*/, const Reference< XClob >& /*x*/ )
330 ::dbtools::throwFeatureNotImplementedSQLException( "XRowUpdate::setClob", *this );
333 void SAL_CALL OPreparedStatement::setBlob( sal_Int32 /*parameterIndex*/, const Reference< XBlob >& /*x*/ )
335 ::dbtools::throwFeatureNotImplementedSQLException( "XRowUpdate::setBlob", *this );
338 void SAL_CALL OPreparedStatement::setArray( sal_Int32 /*parameterIndex*/, const Reference< XArray >& /*x*/ )
340 ::dbtools::throwFeatureNotImplementedSQLException( "XRowUpdate::setArray", *this );
343 void SAL_CALL OPreparedStatement::setRef( sal_Int32 /*parameterIndex*/, const Reference< XRef >& /*x*/ )
345 ::dbtools::throwFeatureNotImplementedSQLException( "XRowUpdate::setRef", *this );
348 void SAL_CALL OPreparedStatement::setObjectWithInfo( sal_Int32 parameterIndex, const Any& x, sal_Int32 sqlType, sal_Int32 scale )
350 switch(sqlType)
352 case DataType::DECIMAL:
353 case DataType::NUMERIC:
354 setString(parameterIndex,::comphelper::getString(x));
355 break;
356 default:
357 ::dbtools::setObjectWithInfo(this,parameterIndex,x,sqlType,scale);
358 break;
362 void SAL_CALL OPreparedStatement::setObjectNull( sal_Int32 parameterIndex, sal_Int32 sqlType, const OUString& /*typeName*/ )
364 setNull(parameterIndex,sqlType);
367 void SAL_CALL OPreparedStatement::setObject( sal_Int32 parameterIndex, const Any& x )
369 if(!::dbtools::implSetObject(this,parameterIndex,x))
371 const OUString sError( m_pConnection->getResources().getResourceStringWithSubstitution(
372 STR_UNKNOWN_PARA_TYPE,
373 "$position$", OUString::number(parameterIndex)
374 ) );
375 ::dbtools::throwGenericSQLException(sError,*this);
379 void SAL_CALL OPreparedStatement::setShort( sal_Int32 parameterIndex, sal_Int16 x )
381 setParameter(parameterIndex,adSmallInt,sizeof(x),x);
384 void SAL_CALL OPreparedStatement::setBytes( sal_Int32 parameterIndex, const Sequence< sal_Int8 >& x )
386 setParameter(parameterIndex,adVarBinary,sizeof(sal_Int8)*x.getLength(),x);
389 void SAL_CALL OPreparedStatement::setCharacterStream( sal_Int32 /*parameterIndex*/, const Reference< css::io::XInputStream >& /*x*/, sal_Int32 /*length*/ )
391 ::dbtools::throwFeatureNotImplementedSQLException( "XParameters::setCharacterStream", *this );
394 void SAL_CALL OPreparedStatement::setBinaryStream( sal_Int32 parameterIndex, const Reference< css::io::XInputStream >& x, sal_Int32 length )
396 if(x.is())
398 Sequence< sal_Int8 > aData;
399 x->readBytes(aData,length);
400 setBytes(parameterIndex,aData);
404 void SAL_CALL OPreparedStatement::clearParameters( )
406 ::osl::MutexGuard aGuard( m_aMutex );
407 checkDisposed(OStatement_BASE::rBHelper.bDisposed);
410 if(m_pParameters)
412 sal_Int32 nCount = 0;
413 m_pParameters->get_Count(&nCount);
414 OLEVariant aVal;
415 aVal.setEmpty();
416 for(sal_Int32 i=0;i<nCount;++i)
418 ADOParameter* pParam = nullptr;
419 m_pParameters->get_Item(OLEVariant(i),&pParam);
420 WpADOParameter aParam(pParam);
421 if(pParam)
423 CHECK_RETURN(aParam.PutValue(aVal));
429 void SAL_CALL OPreparedStatement::acquire() throw()
431 OStatement_Base::acquire();
434 void SAL_CALL OPreparedStatement::release() throw()
436 OStatement_Base::release();
439 void OPreparedStatement::replaceParameterNodeName(OSQLParseNode const * _pNode,
440 const OUString& _sDefaultName,
441 sal_Int32& _rParameterCount)
443 sal_Int32 nCount = _pNode->count();
444 for(sal_Int32 i=0;i < nCount;++i)
446 OSQLParseNode* pChildNode = _pNode->getChild(i);
447 if(SQL_ISRULE(pChildNode,parameter) && pChildNode->count() == 1)
449 OSQLParseNode* pNewNode = new OSQLParseNode(OUString(":") ,SQLNodeType::Punctuation,0);
450 delete pChildNode->replace(pChildNode->getChild(0),pNewNode);
451 OUString sParameterName = _sDefaultName + OUString::number(++_rParameterCount);
452 pChildNode->append(new OSQLParseNode( sParameterName,SQLNodeType::Name,0));
454 else
455 replaceParameterNodeName(pChildNode,_sDefaultName,_rParameterCount);
460 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */