1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: APreparedStatement.cxx,v $
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"
48 #define CHECK_RETURN(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
);
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
);
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()
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
);
135 // -------------------------------------------------------------------------
136 void OPreparedStatement::disposing()
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
);
159 // -------------------------------------------------------------------------
161 sal_Bool SAL_CALL
OPreparedStatement::execute( ) throw(SQLException
, RuntimeException
)
163 ::osl::MutexGuard
aGuard( m_aMutex
);
164 checkDisposed(OStatement_BASE::rBHelper
.bDisposed
);
173 // Reset the statement handle, warning and saved Resultset
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.
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
);
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
);
238 DataTypeEnum eType
= aParam
.GetADOType();
246 ADOParameter
* pParam
= NULL
;
247 m_pParameters
->get_Item(OLEVariant(sal_Int32(parameterIndex
-1)),&pParam
);
248 WpADOParameter
aParam(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
);
261 aParam
.put_Size(_nSize
);
264 if ( adVarBinary
== eType
&& aParam
.GetAttributes() == adParamLong
)
266 aParam
.AppendChunk(_Val
);
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
300 if(m_RecordSet
.IsValid())
305 // the create the new onces
306 m_RecordSet
.Create();
308 aCmd
.setIDispatch(m_Command
);
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
;
322 pSet
->setMetaData(getMetaData());
323 m_xResultSet
= WeakReference
<XResultSet
>(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
)
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
)
420 case DataType::DECIMAL
:
421 case DataType::NUMERIC
:
422 setString(parameterIndex
,::comphelper::getString(x
));
425 ::dbtools::setObjectWithInfo(this,parameterIndex
,x
,sqlType
,scale
);
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
)
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
)
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
);
491 sal_Int32 nCount
= 0;
492 m_pParameters
->get_Count(&nCount
);
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
);
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));
556 replaceParameterNodeName(pChildNode
,_sDefaultName
,_rParameterCount
);
560 // -----------------------------------------------------------------------------