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);
56 //------------------------------------------------------------------------------
57 //------------------------------------------------------------------------------
58 using namespace connectivity::ado
;
59 using namespace connectivity
;
60 using namespace com::sun::star::uno
;
61 using namespace com::sun::star::lang
;
62 using namespace com::sun::star::beans
;
63 using namespace com::sun::star::sdbc
;
64 using namespace com::sun::star::util
;
67 IMPLEMENT_SERVICE_INFO(OPreparedStatement
,"com.sun.star.sdbcx.APreparedStatement","com.sun.star.sdbc.PreparedStatement");
69 OPreparedStatement::OPreparedStatement( OConnection
* _pConnection
,const OTypeInfoMap
& _TypeInfo
,const ::rtl::OUString
& sql
)
70 : OStatement_Base( _pConnection
)
71 ,m_aTypeInfo(_TypeInfo
)
73 osl_incrementInterlockedCount( &m_refCount
);
75 OSQLParser
aParser(_pConnection
->getDriver()->getORB());
76 ::rtl::OUString sErrorMessage
;
77 ::rtl::OUString sNewSql
;
78 OSQLParseNode
* pNode
= aParser
.parseTree(sErrorMessage
,sql
);
80 { // special handling for parameters
81 /* we recusive replace all occurences of ? in the statement and replace them with name like "æ¬å" */
82 sal_Int32 nParameterCount
= 0;
83 ::rtl::OUString sDefaultName
= ::rtl::OUString::createFromAscii("parame");
84 replaceParameterNodeName(pNode
,sDefaultName
,nParameterCount
);
85 pNode
->parseNodeToStr( sNewSql
, _pConnection
);
90 CHECK_RETURN(m_Command
.put_CommandText(sNewSql
))
91 CHECK_RETURN(m_Command
.put_Prepared(VARIANT_TRUE
))
92 m_pParameters
= m_Command
.get_Parameters();
93 m_pParameters
->AddRef();
94 m_pParameters
->Refresh();
96 osl_decrementInterlockedCount( &m_refCount
);
99 // -------------------------------------------------------------------------
100 OPreparedStatement::~OPreparedStatement()
104 OSL_ENSURE( sal_False
, "OPreparedStatement::~OPreparedStatement: not disposed!" );
105 m_pParameters
->Release();
106 m_pParameters
= NULL
;
110 // -------------------------------------------------------------------------
112 Any SAL_CALL
OPreparedStatement::queryInterface( const Type
& rType
) throw(RuntimeException
)
114 Any aRet
= OStatement_Base::queryInterface(rType
);
115 return aRet
.hasValue() ? aRet
: ::cppu::queryInterface( rType
,
116 static_cast< XPreparedStatement
*>(this),
117 static_cast< XParameters
*>(this),
118 static_cast< XPreparedBatchExecution
*>(this),
119 static_cast< XResultSetMetaDataSupplier
*>(this));
121 // -------------------------------------------------------------------------
122 ::com::sun::star::uno::Sequence
< ::com::sun::star::uno::Type
> SAL_CALL
OPreparedStatement::getTypes( ) throw(::com::sun::star::uno::RuntimeException
)
124 ::cppu::OTypeCollection
aTypes( ::getCppuType( (const ::com::sun::star::uno::Reference
< XPreparedStatement
> *)0 ),
125 ::getCppuType( (const ::com::sun::star::uno::Reference
< XParameters
> *)0 ),
126 ::getCppuType( (const ::com::sun::star::uno::Reference
< XResultSetMetaDataSupplier
> *)0 ),
127 ::getCppuType( (const ::com::sun::star::uno::Reference
< XPreparedBatchExecution
> *)0 ));
129 return ::comphelper::concatSequences(aTypes
.getTypes(),OStatement_Base::getTypes());
131 // -------------------------------------------------------------------------
133 Reference
< XResultSetMetaData
> SAL_CALL
OPreparedStatement::getMetaData( ) throw(SQLException
, RuntimeException
)
135 if(!m_xMetaData
.is() && m_RecordSet
.IsValid())
136 m_xMetaData
= new OResultSetMetaData(m_RecordSet
);
139 // -------------------------------------------------------------------------
140 void OPreparedStatement::disposing()
145 m_pParameters
->Release();
146 m_pParameters
= NULL
;
148 OStatement_Base::disposing();
150 // -------------------------------------------------------------------------
152 void SAL_CALL
OPreparedStatement::close( ) throw(SQLException
, RuntimeException
)
156 ::osl::MutexGuard
aGuard( m_aMutex
);
157 checkDisposed(OStatement_BASE::rBHelper
.bDisposed
);
163 // -------------------------------------------------------------------------
165 sal_Bool SAL_CALL
OPreparedStatement::execute( ) throw(SQLException
, RuntimeException
)
167 ::osl::MutexGuard
aGuard( m_aMutex
);
168 checkDisposed(OStatement_BASE::rBHelper
.bDisposed
);
177 // Reset the statement handle, warning and saved Resultset
184 ADORecordset
* pSet
=NULL
;
185 CHECK_RETURN(m_Command
.Execute(m_RecordsAffected
,m_Parameters
,adCmdUnknown
,&pSet
))
186 m_RecordSet
= WpADORecordset(pSet
);
188 catch (SQLWarning
& ex
)
191 // Save pointer to warning and save with ResultSet
192 // object once it is created.
196 return m_RecordSet
.IsValid();
198 // -------------------------------------------------------------------------
200 sal_Int32 SAL_CALL
OPreparedStatement::executeUpdate( ) throw(SQLException
, RuntimeException
)
202 ::osl::MutexGuard
aGuard( m_aMutex
);
203 checkDisposed(OStatement_BASE::rBHelper
.bDisposed
);
206 ADORecordset
* pSet
=NULL
;
207 CHECK_RETURN(m_Command
.Execute(m_RecordsAffected
,m_Parameters
,adCmdUnknown
,&pSet
))
208 if ( VT_ERROR
== m_RecordsAffected
.getType() )
210 ADOS::ThrowException(*m_pConnection
->getConnection(),*this);
211 // to be sure that we get the error really thrown
212 throw SQLException();
214 m_RecordSet
= WpADORecordset(pSet
);
215 return static_cast<sal_Int32
>(m_RecordsAffected
);
218 // -------------------------------------------------------------------------
219 void OPreparedStatement::setParameter(sal_Int32 parameterIndex
, const DataTypeEnum
& _eType
,
220 const sal_Int32
& _nSize
,const OLEVariant
& _Val
) throw(SQLException
, RuntimeException
)
222 ::osl::MutexGuard
aGuard( m_aMutex
);
223 checkDisposed(OStatement_BASE::rBHelper
.bDisposed
);
226 sal_Int32 nCount
= 0;
227 m_pParameters
->get_Count(&nCount
);
228 if(nCount
< (parameterIndex
-1))
230 ::rtl::OUString sDefaultName
= ::rtl::OUString::createFromAscii("parame");
231 sDefaultName
+= ::rtl::OUString::valueOf(parameterIndex
);
232 ADOParameter
* pParam
= m_Command
.CreateParameter(sDefaultName
,_eType
,adParamInput
,_nSize
,_Val
);
235 m_pParameters
->Append(pParam
);
236 #if OSL_DEBUG_LEVEL > 0
237 ADOParameter
* pParam
= NULL
;
238 m_pParameters
->get_Item(OLEVariant(sal_Int32(parameterIndex
-1)),&pParam
);
239 WpADOParameter
aParam(pParam
);
242 DataTypeEnum eType
= aParam
.GetADOType();
250 ADOParameter
* pParam
= NULL
;
251 m_pParameters
->get_Item(OLEVariant(sal_Int32(parameterIndex
-1)),&pParam
);
252 WpADOParameter
aParam(pParam
);
255 #if OSL_DEBUG_LEVEL > 0
256 ::rtl::OUString sParam
= aParam
.GetName();
258 #endif // OSL_DEBUG_LEVEL
260 DataTypeEnum eType
= aParam
.GetADOType();
261 if ( _eType
!= eType
&& _eType
!= adDBTimeStamp
)
263 aParam
.put_Type(_eType
);
265 aParam
.put_Size(_nSize
);
268 if ( adVarBinary
== eType
&& aParam
.GetAttributes() == adParamLong
)
270 aParam
.AppendChunk(_Val
);
273 CHECK_RETURN(aParam
.PutValue(_Val
));
276 ADOS::ThrowException(*m_pConnection
->getConnection(),*this);
278 // -------------------------------------------------------------------------
279 void SAL_CALL
OPreparedStatement::setString( sal_Int32 parameterIndex
, const ::rtl::OUString
& x
) throw(SQLException
, RuntimeException
)
281 setParameter( parameterIndex
, adLongVarWChar
, ::std::numeric_limits
< sal_Int32
>::max(), x
);
283 // -------------------------------------------------------------------------
285 Reference
< XConnection
> SAL_CALL
OPreparedStatement::getConnection( ) throw(SQLException
, RuntimeException
)
287 ::osl::MutexGuard
aGuard( m_aMutex
);
288 checkDisposed(OStatement_BASE::rBHelper
.bDisposed
);
291 return (Reference
< XConnection
>)m_pConnection
;
293 // -------------------------------------------------------------------------
295 Reference
< XResultSet
> SAL_CALL
OPreparedStatement::executeQuery( ) throw(SQLException
, RuntimeException
)
297 ::osl::MutexGuard
aGuard( m_aMutex
);
298 checkDisposed(OStatement_BASE::rBHelper
.bDisposed
);
301 // first clear the old things
304 if(m_RecordSet
.IsValid())
309 // the create the new onces
310 m_RecordSet
.Create();
312 aCmd
.setIDispatch(m_Command
);
315 CHECK_RETURN(m_RecordSet
.put_CacheSize(m_nFetchSize
))
316 CHECK_RETURN(m_RecordSet
.put_MaxRecords(m_nMaxRows
))
317 CHECK_RETURN(m_RecordSet
.Open(aCmd
,aCon
,m_eCursorType
,m_eLockType
,adOpenUnspecified
))
318 CHECK_RETURN(m_RecordSet
.get_CacheSize(m_nFetchSize
))
319 CHECK_RETURN(m_RecordSet
.get_MaxRecords(m_nMaxRows
))
320 CHECK_RETURN(m_RecordSet
.get_CursorType(m_eCursorType
))
321 CHECK_RETURN(m_RecordSet
.get_LockType(m_eLockType
))
323 OResultSet
* pSet
= new OResultSet(m_RecordSet
,this);
324 Reference
< XResultSet
> xRs
= pSet
;
326 pSet
->setMetaData(getMetaData());
327 m_xResultSet
= WeakReference
<XResultSet
>(xRs
);
331 // -------------------------------------------------------------------------
333 void SAL_CALL
OPreparedStatement::setBoolean( sal_Int32 parameterIndex
, sal_Bool x
) throw(SQLException
, RuntimeException
)
335 setParameter(parameterIndex
,adBoolean
,sizeof(x
),x
);
337 // -------------------------------------------------------------------------
339 void SAL_CALL
OPreparedStatement::setByte( sal_Int32 parameterIndex
, sal_Int8 x
) throw(SQLException
, RuntimeException
)
341 setParameter(parameterIndex
,adTinyInt
,sizeof(x
),x
);
343 // -------------------------------------------------------------------------
345 void SAL_CALL
OPreparedStatement::setDate( sal_Int32 parameterIndex
, const Date
& x
) throw(SQLException
, RuntimeException
)
347 setParameter(parameterIndex
,adDBDate
,sizeof(x
),x
);
349 // -------------------------------------------------------------------------
352 void SAL_CALL
OPreparedStatement::setTime( sal_Int32 parameterIndex
, const Time
& x
) throw(SQLException
, RuntimeException
)
354 setParameter(parameterIndex
,adDBTime
,sizeof(x
),x
);
356 // -------------------------------------------------------------------------
358 void SAL_CALL
OPreparedStatement::setTimestamp( sal_Int32 parameterIndex
, const DateTime
& x
) throw(SQLException
, RuntimeException
)
360 setParameter(parameterIndex
,adDBTimeStamp
,sizeof(x
),x
);
362 // -------------------------------------------------------------------------
364 void SAL_CALL
OPreparedStatement::setDouble( sal_Int32 parameterIndex
, double x
) throw(SQLException
, RuntimeException
)
366 setParameter(parameterIndex
,adDouble
,sizeof(x
),x
);
368 // -------------------------------------------------------------------------
370 void SAL_CALL
OPreparedStatement::setFloat( sal_Int32 parameterIndex
, float x
) throw(SQLException
, RuntimeException
)
372 setParameter(parameterIndex
,adSingle
,sizeof(x
),x
);
374 // -------------------------------------------------------------------------
376 void SAL_CALL
OPreparedStatement::setInt( sal_Int32 parameterIndex
, sal_Int32 x
) throw(SQLException
, RuntimeException
)
378 setParameter(parameterIndex
,adInteger
,sizeof(x
),x
);
380 // -------------------------------------------------------------------------
382 void SAL_CALL
OPreparedStatement::setLong( sal_Int32 parameterIndex
, sal_Int64 x
) throw(SQLException
, RuntimeException
)
384 setParameter(parameterIndex
,adBigInt
,sizeof(x
),x
);
386 // -------------------------------------------------------------------------
388 void SAL_CALL
OPreparedStatement::setNull( sal_Int32 parameterIndex
, sal_Int32
/*sqlType*/ ) throw(SQLException
, RuntimeException
)
392 setParameter(parameterIndex
,adEmpty
,0,aVal
);
394 // -------------------------------------------------------------------------
396 void SAL_CALL
OPreparedStatement::setClob( sal_Int32
/*parameterIndex*/, const Reference
< XClob
>& /*x*/ ) throw(SQLException
, RuntimeException
)
398 ::dbtools::throwFeatureNotImplementedException( "XRowUpdate::setClob", *this );
400 // -------------------------------------------------------------------------
402 void SAL_CALL
OPreparedStatement::setBlob( sal_Int32
/*parameterIndex*/, const Reference
< XBlob
>& /*x*/ ) throw(SQLException
, RuntimeException
)
404 ::dbtools::throwFeatureNotImplementedException( "XRowUpdate::setBlob", *this );
406 // -------------------------------------------------------------------------
408 void SAL_CALL
OPreparedStatement::setArray( sal_Int32
/*parameterIndex*/, const Reference
< XArray
>& /*x*/ ) throw(SQLException
, RuntimeException
)
410 ::dbtools::throwFeatureNotImplementedException( "XRowUpdate::setArray", *this );
412 // -------------------------------------------------------------------------
414 void SAL_CALL
OPreparedStatement::setRef( sal_Int32
/*parameterIndex*/, const Reference
< XRef
>& /*x*/ ) throw(SQLException
, RuntimeException
)
416 ::dbtools::throwFeatureNotImplementedException( "XRowUpdate::setRef", *this );
418 // -------------------------------------------------------------------------
420 void SAL_CALL
OPreparedStatement::setObjectWithInfo( sal_Int32 parameterIndex
, const Any
& x
, sal_Int32 sqlType
, sal_Int32 scale
) throw(SQLException
, RuntimeException
)
424 case DataType::DECIMAL
:
425 case DataType::NUMERIC
:
426 setString(parameterIndex
,::comphelper::getString(x
));
429 ::dbtools::setObjectWithInfo(this,parameterIndex
,x
,sqlType
,scale
);
433 // -------------------------------------------------------------------------
435 void SAL_CALL
OPreparedStatement::setObjectNull( sal_Int32 parameterIndex
, sal_Int32 sqlType
, const ::rtl::OUString
& /*typeName*/ ) throw(SQLException
, RuntimeException
)
437 setNull(parameterIndex
,sqlType
);
439 // -------------------------------------------------------------------------
441 void SAL_CALL
OPreparedStatement::setObject( sal_Int32 parameterIndex
, const Any
& x
) throw(SQLException
, RuntimeException
)
443 if(!::dbtools::implSetObject(this,parameterIndex
,x
))
445 const ::rtl::OUString
sError( m_pConnection
->getResources().getResourceStringWithSubstitution(
446 STR_UNKNOWN_PARA_TYPE
,
447 "$position$", ::rtl::OUString::valueOf(parameterIndex
)
449 ::dbtools::throwGenericSQLException(sError
,*this);
451 // setObject (parameterIndex, x, sqlType, 0);
453 // -------------------------------------------------------------------------
455 void SAL_CALL
OPreparedStatement::setShort( sal_Int32 parameterIndex
, sal_Int16 x
) throw(SQLException
, RuntimeException
)
457 setParameter(parameterIndex
,adSmallInt
,sizeof(x
),x
);
459 // -------------------------------------------------------------------------
461 void SAL_CALL
OPreparedStatement::setBytes( sal_Int32 parameterIndex
, const Sequence
< sal_Int8
>& x
) throw(SQLException
, RuntimeException
)
463 setParameter(parameterIndex
,adVarBinary
,sizeof(sal_Int8
)*x
.getLength(),x
);
466 // -------------------------------------------------------------------------
469 void SAL_CALL
OPreparedStatement::setCharacterStream( sal_Int32
/*parameterIndex*/, const Reference
< ::com::sun::star::io::XInputStream
>& /*x*/, sal_Int32
/*length*/ ) throw(SQLException
, RuntimeException
)
471 ::dbtools::throwFeatureNotImplementedException( "XParameters::setCharacterStream", *this );
474 // -------------------------------------------------------------------------
476 void SAL_CALL
OPreparedStatement::setBinaryStream( sal_Int32 parameterIndex
, const Reference
< ::com::sun::star::io::XInputStream
>& x
, sal_Int32 length
) throw(SQLException
, RuntimeException
)
480 Sequence
< sal_Int8
> aData
;
481 x
->readBytes(aData
,length
);
482 setBytes(parameterIndex
,aData
);
485 // -------------------------------------------------------------------------
487 void SAL_CALL
OPreparedStatement::clearParameters( ) throw(SQLException
, RuntimeException
)
489 ::osl::MutexGuard
aGuard( m_aMutex
);
490 checkDisposed(OStatement_BASE::rBHelper
.bDisposed
);
495 sal_Int32 nCount
= 0;
496 m_pParameters
->get_Count(&nCount
);
499 for(sal_Int32 i
=0;i
<nCount
;++i
)
501 ADOParameter
* pParam
= NULL
;
502 m_pParameters
->get_Item(OLEVariant(i
),&pParam
);
503 WpADOParameter
aParam(pParam
);
506 ::rtl::OUString sParam
= aParam
.GetName();
507 CHECK_RETURN(aParam
.PutValue(aVal
));
510 // m_pParameters->Delete(OLEVariant(i));
514 // -------------------------------------------------------------------------
515 void SAL_CALL
OPreparedStatement::clearBatch( ) throw(SQLException
, RuntimeException
)
517 // clearParameters( );
518 // m_aBatchList.erase();
520 // -------------------------------------------------------------------------
522 void SAL_CALL
OPreparedStatement::addBatch( ) throw(SQLException
, RuntimeException
)
525 // -------------------------------------------------------------------------
527 Sequence
< sal_Int32
> SAL_CALL
OPreparedStatement::executeBatch( ) throw(SQLException
, RuntimeException
)
529 return Sequence
< sal_Int32
> ();
531 // -----------------------------------------------------------------------------
532 // -----------------------------------------------------------------------------
533 void SAL_CALL
OPreparedStatement::acquire() throw()
535 OStatement_Base::acquire();
537 // -----------------------------------------------------------------------------
538 void SAL_CALL
OPreparedStatement::release() throw()
540 OStatement_Base::release();
542 // -----------------------------------------------------------------------------
543 void OPreparedStatement::replaceParameterNodeName(OSQLParseNode
* _pNode
,
544 const ::rtl::OUString
& _sDefaultName
,
545 sal_Int32
& _rParameterCount
)
547 sal_Int32 nCount
= _pNode
->count();
548 for(sal_Int32 i
=0;i
< nCount
;++i
)
550 OSQLParseNode
* pChildNode
= _pNode
->getChild(i
);
551 if(SQL_ISRULE(pChildNode
,parameter
) && pChildNode
->count() == 1)
553 OSQLParseNode
* pNewNode
= new OSQLParseNode(::rtl::OUString::createFromAscii(":") ,SQL_NODE_PUNCTUATION
,0);
554 delete pChildNode
->replace(pChildNode
->getChild(0),pNewNode
);
555 ::rtl::OUString sParameterName
= _sDefaultName
;
556 sParameterName
+= ::rtl::OUString::valueOf(++_rParameterCount
);
557 pChildNode
->append(new OSQLParseNode( sParameterName
,SQL_NODE_NAME
,0));
560 replaceParameterNodeName(pChildNode
,_sDefaultName
,_rParameterCount
);
564 // -----------------------------------------------------------------------------