1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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"
36 #define CHECK_RETURN(x) \
38 ADOS::ThrowException(*m_pConnection->getConnection(),*this);
44 //------------------------------------------------------------------------------
45 //------------------------------------------------------------------------------
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
;
55 IMPLEMENT_SERVICE_INFO(OPreparedStatement
,"com.sun.star.sdbcx.APreparedStatement","com.sun.star.sdbc.PreparedStatement");
57 OPreparedStatement::OPreparedStatement( OConnection
* _pConnection
,const OTypeInfoMap
& _TypeInfo
,const OUString
& sql
)
58 : OStatement_Base( _pConnection
)
59 ,m_aTypeInfo(_TypeInfo
)
61 osl_atomic_increment( &m_refCount
);
63 OSQLParser
aParser(comphelper::getComponentContext(_pConnection
->getDriver()->getORB()));
64 OUString sErrorMessage
;
66 OSQLParseNode
* pNode
= aParser
.parseTree(sErrorMessage
,sql
);
68 { // special handling for parameters
69 /* we recusive replace all occurrences of ? in the statement and replace them with name like "æ¬å" */
70 sal_Int32 nParameterCount
= 0;
71 OUString
sDefaultName( "parame" );
72 replaceParameterNodeName(pNode
,sDefaultName
,nParameterCount
);
73 pNode
->parseNodeToStr( sNewSql
, _pConnection
);
78 CHECK_RETURN(m_Command
.put_CommandText(sNewSql
))
79 CHECK_RETURN(m_Command
.put_Prepared(VARIANT_TRUE
))
80 m_pParameters
= m_Command
.get_Parameters();
81 m_pParameters
->AddRef();
82 m_pParameters
->Refresh();
84 osl_atomic_decrement( &m_refCount
);
87 // -------------------------------------------------------------------------
88 OPreparedStatement::~OPreparedStatement()
92 OSL_FAIL( "OPreparedStatement::~OPreparedStatement: not disposed!" );
93 m_pParameters
->Release();
98 // -------------------------------------------------------------------------
100 Any SAL_CALL
OPreparedStatement::queryInterface( const Type
& rType
) throw(RuntimeException
)
102 Any aRet
= OStatement_Base::queryInterface(rType
);
103 return aRet
.hasValue() ? aRet
: ::cppu::queryInterface( rType
,
104 static_cast< XPreparedStatement
*>(this),
105 static_cast< XParameters
*>(this),
106 static_cast< XPreparedBatchExecution
*>(this),
107 static_cast< XResultSetMetaDataSupplier
*>(this));
109 // -------------------------------------------------------------------------
110 ::com::sun::star::uno::Sequence
< ::com::sun::star::uno::Type
> SAL_CALL
OPreparedStatement::getTypes( ) throw(::com::sun::star::uno::RuntimeException
)
112 ::cppu::OTypeCollection
aTypes( ::getCppuType( (const ::com::sun::star::uno::Reference
< XPreparedStatement
> *)0 ),
113 ::getCppuType( (const ::com::sun::star::uno::Reference
< XParameters
> *)0 ),
114 ::getCppuType( (const ::com::sun::star::uno::Reference
< XResultSetMetaDataSupplier
> *)0 ),
115 ::getCppuType( (const ::com::sun::star::uno::Reference
< XPreparedBatchExecution
> *)0 ));
117 return ::comphelper::concatSequences(aTypes
.getTypes(),OStatement_Base::getTypes());
119 // -------------------------------------------------------------------------
121 Reference
< XResultSetMetaData
> SAL_CALL
OPreparedStatement::getMetaData( ) throw(SQLException
, RuntimeException
)
123 if(!m_xMetaData
.is() && m_RecordSet
.IsValid())
124 m_xMetaData
= new OResultSetMetaData(m_RecordSet
);
127 // -------------------------------------------------------------------------
128 void OPreparedStatement::disposing()
133 m_pParameters
->Release();
134 m_pParameters
= NULL
;
136 OStatement_Base::disposing();
138 // -------------------------------------------------------------------------
140 void SAL_CALL
OPreparedStatement::close( ) throw(SQLException
, RuntimeException
)
144 ::osl::MutexGuard
aGuard( m_aMutex
);
145 checkDisposed(OStatement_BASE::rBHelper
.bDisposed
);
151 // -------------------------------------------------------------------------
153 sal_Bool SAL_CALL
OPreparedStatement::execute( ) throw(SQLException
, RuntimeException
)
155 ::osl::MutexGuard
aGuard( m_aMutex
);
156 checkDisposed(OStatement_BASE::rBHelper
.bDisposed
);
165 // Reset the statement handle, warning and saved Resultset
172 ADORecordset
* pSet
=NULL
;
173 CHECK_RETURN(m_Command
.Execute(m_RecordsAffected
,m_Parameters
,adCmdUnknown
,&pSet
))
174 m_RecordSet
= WpADORecordset(pSet
);
176 catch (SQLWarning
& ex
)
179 // Save pointer to warning and save with ResultSet
180 // object once it is created.
184 return m_RecordSet
.IsValid();
186 // -------------------------------------------------------------------------
188 sal_Int32 SAL_CALL
OPreparedStatement::executeUpdate( ) throw(SQLException
, RuntimeException
)
190 ::osl::MutexGuard
aGuard( m_aMutex
);
191 checkDisposed(OStatement_BASE::rBHelper
.bDisposed
);
194 ADORecordset
* pSet
=NULL
;
195 CHECK_RETURN(m_Command
.Execute(m_RecordsAffected
,m_Parameters
,adCmdUnknown
,&pSet
))
196 if ( VT_ERROR
== m_RecordsAffected
.getType() )
198 ADOS::ThrowException(*m_pConnection
->getConnection(),*this);
199 // to be sure that we get the error really thrown
200 throw SQLException();
202 m_RecordSet
= WpADORecordset(pSet
);
203 return static_cast<sal_Int32
>(m_RecordsAffected
);
206 // -------------------------------------------------------------------------
207 void OPreparedStatement::setParameter(sal_Int32 parameterIndex
, const DataTypeEnum
& _eType
,
208 const sal_Int32
& _nSize
,const OLEVariant
& _Val
) throw(SQLException
, RuntimeException
)
210 ::osl::MutexGuard
aGuard( m_aMutex
);
211 checkDisposed(OStatement_BASE::rBHelper
.bDisposed
);
214 sal_Int32 nCount
= 0;
215 m_pParameters
->get_Count(&nCount
);
216 if(nCount
< (parameterIndex
-1))
218 OUString
sDefaultName( "parame" );
219 sDefaultName
+= OUString::valueOf(parameterIndex
);
220 ADOParameter
* pParam
= m_Command
.CreateParameter(sDefaultName
,_eType
,adParamInput
,_nSize
,_Val
);
223 m_pParameters
->Append(pParam
);
224 #if OSL_DEBUG_LEVEL > 0
225 ADOParameter
* pParam
= NULL
;
226 m_pParameters
->get_Item(OLEVariant(sal_Int32(parameterIndex
-1)),&pParam
);
227 WpADOParameter
aParam(pParam
);
230 DataTypeEnum eType
= aParam
.GetADOType();
238 ADOParameter
* pParam
= NULL
;
239 m_pParameters
->get_Item(OLEVariant(sal_Int32(parameterIndex
-1)),&pParam
);
240 WpADOParameter
aParam(pParam
);
243 #if OSL_DEBUG_LEVEL > 0
244 OUString sParam
= aParam
.GetName();
246 #endif // OSL_DEBUG_LEVEL
248 DataTypeEnum eType
= aParam
.GetADOType();
249 if ( _eType
!= eType
&& _eType
!= adDBTimeStamp
)
251 aParam
.put_Type(_eType
);
253 aParam
.put_Size(_nSize
);
256 if ( adVarBinary
== eType
&& aParam
.GetAttributes() == adParamLong
)
258 aParam
.AppendChunk(_Val
);
261 CHECK_RETURN(aParam
.PutValue(_Val
));
264 ADOS::ThrowException(*m_pConnection
->getConnection(),*this);
266 // -------------------------------------------------------------------------
267 void SAL_CALL
OPreparedStatement::setString( sal_Int32 parameterIndex
, const OUString
& x
) throw(SQLException
, RuntimeException
)
269 setParameter( parameterIndex
, adLongVarWChar
, ::std::numeric_limits
< sal_Int32
>::max(), x
);
271 // -------------------------------------------------------------------------
273 Reference
< XConnection
> SAL_CALL
OPreparedStatement::getConnection( ) throw(SQLException
, RuntimeException
)
275 ::osl::MutexGuard
aGuard( m_aMutex
);
276 checkDisposed(OStatement_BASE::rBHelper
.bDisposed
);
279 return (Reference
< XConnection
>)m_pConnection
;
281 // -------------------------------------------------------------------------
283 Reference
< XResultSet
> SAL_CALL
OPreparedStatement::executeQuery( ) throw(SQLException
, RuntimeException
)
285 ::osl::MutexGuard
aGuard( m_aMutex
);
286 checkDisposed(OStatement_BASE::rBHelper
.bDisposed
);
289 // first clear the old things
292 if(m_RecordSet
.IsValid())
297 // the create the new onces
298 m_RecordSet
.Create();
300 aCmd
.setIDispatch(m_Command
);
303 CHECK_RETURN(m_RecordSet
.put_CacheSize(m_nFetchSize
))
304 CHECK_RETURN(m_RecordSet
.put_MaxRecords(m_nMaxRows
))
305 CHECK_RETURN(m_RecordSet
.Open(aCmd
,aCon
,m_eCursorType
,m_eLockType
,adOpenUnspecified
))
306 CHECK_RETURN(m_RecordSet
.get_CacheSize(m_nFetchSize
))
307 CHECK_RETURN(m_RecordSet
.get_MaxRecords(m_nMaxRows
))
308 CHECK_RETURN(m_RecordSet
.get_CursorType(m_eCursorType
))
309 CHECK_RETURN(m_RecordSet
.get_LockType(m_eLockType
))
311 OResultSet
* pSet
= new OResultSet(m_RecordSet
,this);
312 Reference
< XResultSet
> xRs
= pSet
;
314 pSet
->setMetaData(getMetaData());
315 m_xResultSet
= WeakReference
<XResultSet
>(xRs
);
319 // -------------------------------------------------------------------------
321 void SAL_CALL
OPreparedStatement::setBoolean( sal_Int32 parameterIndex
, sal_Bool x
) throw(SQLException
, RuntimeException
)
323 setParameter(parameterIndex
,adBoolean
,sizeof(x
),x
);
325 // -------------------------------------------------------------------------
327 void SAL_CALL
OPreparedStatement::setByte( sal_Int32 parameterIndex
, sal_Int8 x
) throw(SQLException
, RuntimeException
)
329 setParameter(parameterIndex
,adTinyInt
,sizeof(x
),x
);
331 // -------------------------------------------------------------------------
333 void SAL_CALL
OPreparedStatement::setDate( sal_Int32 parameterIndex
, const Date
& x
) throw(SQLException
, RuntimeException
)
335 setParameter(parameterIndex
,adDBDate
,sizeof(x
),x
);
337 // -------------------------------------------------------------------------
340 void SAL_CALL
OPreparedStatement::setTime( sal_Int32 parameterIndex
, const Time
& x
) throw(SQLException
, RuntimeException
)
342 setParameter(parameterIndex
,adDBTime
,sizeof(x
),x
);
344 // -------------------------------------------------------------------------
346 void SAL_CALL
OPreparedStatement::setTimestamp( sal_Int32 parameterIndex
, const DateTime
& x
) throw(SQLException
, RuntimeException
)
348 setParameter(parameterIndex
,adDBTimeStamp
,sizeof(x
),x
);
350 // -------------------------------------------------------------------------
352 void SAL_CALL
OPreparedStatement::setDouble( sal_Int32 parameterIndex
, double x
) throw(SQLException
, RuntimeException
)
354 setParameter(parameterIndex
,adDouble
,sizeof(x
),x
);
356 // -------------------------------------------------------------------------
358 void SAL_CALL
OPreparedStatement::setFloat( sal_Int32 parameterIndex
, float x
) throw(SQLException
, RuntimeException
)
360 setParameter(parameterIndex
,adSingle
,sizeof(x
),x
);
362 // -------------------------------------------------------------------------
364 void SAL_CALL
OPreparedStatement::setInt( sal_Int32 parameterIndex
, sal_Int32 x
) throw(SQLException
, RuntimeException
)
366 setParameter(parameterIndex
,adInteger
,sizeof(x
),x
);
368 // -------------------------------------------------------------------------
370 void SAL_CALL
OPreparedStatement::setLong( sal_Int32 parameterIndex
, sal_Int64 x
) throw(SQLException
, RuntimeException
)
372 setParameter(parameterIndex
,adBigInt
,sizeof(x
),x
);
374 // -------------------------------------------------------------------------
376 void SAL_CALL
OPreparedStatement::setNull( sal_Int32 parameterIndex
, sal_Int32
/*sqlType*/ ) throw(SQLException
, RuntimeException
)
380 setParameter(parameterIndex
,adEmpty
,0,aVal
);
382 // -------------------------------------------------------------------------
384 void SAL_CALL
OPreparedStatement::setClob( sal_Int32
/*parameterIndex*/, const Reference
< XClob
>& /*x*/ ) throw(SQLException
, RuntimeException
)
386 ::dbtools::throwFeatureNotImplementedException( "XRowUpdate::setClob", *this );
388 // -------------------------------------------------------------------------
390 void SAL_CALL
OPreparedStatement::setBlob( sal_Int32
/*parameterIndex*/, const Reference
< XBlob
>& /*x*/ ) throw(SQLException
, RuntimeException
)
392 ::dbtools::throwFeatureNotImplementedException( "XRowUpdate::setBlob", *this );
394 // -------------------------------------------------------------------------
396 void SAL_CALL
OPreparedStatement::setArray( sal_Int32
/*parameterIndex*/, const Reference
< XArray
>& /*x*/ ) throw(SQLException
, RuntimeException
)
398 ::dbtools::throwFeatureNotImplementedException( "XRowUpdate::setArray", *this );
400 // -------------------------------------------------------------------------
402 void SAL_CALL
OPreparedStatement::setRef( sal_Int32
/*parameterIndex*/, const Reference
< XRef
>& /*x*/ ) throw(SQLException
, RuntimeException
)
404 ::dbtools::throwFeatureNotImplementedException( "XRowUpdate::setRef", *this );
406 // -------------------------------------------------------------------------
408 void SAL_CALL
OPreparedStatement::setObjectWithInfo( sal_Int32 parameterIndex
, const Any
& x
, sal_Int32 sqlType
, sal_Int32 scale
) throw(SQLException
, RuntimeException
)
412 case DataType::DECIMAL
:
413 case DataType::NUMERIC
:
414 setString(parameterIndex
,::comphelper::getString(x
));
417 ::dbtools::setObjectWithInfo(this,parameterIndex
,x
,sqlType
,scale
);
421 // -------------------------------------------------------------------------
423 void SAL_CALL
OPreparedStatement::setObjectNull( sal_Int32 parameterIndex
, sal_Int32 sqlType
, const OUString
& /*typeName*/ ) throw(SQLException
, RuntimeException
)
425 setNull(parameterIndex
,sqlType
);
427 // -------------------------------------------------------------------------
429 void SAL_CALL
OPreparedStatement::setObject( sal_Int32 parameterIndex
, const Any
& x
) throw(SQLException
, RuntimeException
)
431 if(!::dbtools::implSetObject(this,parameterIndex
,x
))
433 const OUString
sError( m_pConnection
->getResources().getResourceStringWithSubstitution(
434 STR_UNKNOWN_PARA_TYPE
,
435 "$position$", OUString::valueOf(parameterIndex
)
437 ::dbtools::throwGenericSQLException(sError
,*this);
439 // setObject (parameterIndex, x, sqlType, 0);
441 // -------------------------------------------------------------------------
443 void SAL_CALL
OPreparedStatement::setShort( sal_Int32 parameterIndex
, sal_Int16 x
) throw(SQLException
, RuntimeException
)
445 setParameter(parameterIndex
,adSmallInt
,sizeof(x
),x
);
447 // -------------------------------------------------------------------------
449 void SAL_CALL
OPreparedStatement::setBytes( sal_Int32 parameterIndex
, const Sequence
< sal_Int8
>& x
) throw(SQLException
, RuntimeException
)
451 setParameter(parameterIndex
,adVarBinary
,sizeof(sal_Int8
)*x
.getLength(),x
);
454 // -------------------------------------------------------------------------
457 void SAL_CALL
OPreparedStatement::setCharacterStream( sal_Int32
/*parameterIndex*/, const Reference
< ::com::sun::star::io::XInputStream
>& /*x*/, sal_Int32
/*length*/ ) throw(SQLException
, RuntimeException
)
459 ::dbtools::throwFeatureNotImplementedException( "XParameters::setCharacterStream", *this );
462 // -------------------------------------------------------------------------
464 void SAL_CALL
OPreparedStatement::setBinaryStream( sal_Int32 parameterIndex
, const Reference
< ::com::sun::star::io::XInputStream
>& x
, sal_Int32 length
) throw(SQLException
, RuntimeException
)
468 Sequence
< sal_Int8
> aData
;
469 x
->readBytes(aData
,length
);
470 setBytes(parameterIndex
,aData
);
473 // -------------------------------------------------------------------------
475 void SAL_CALL
OPreparedStatement::clearParameters( ) throw(SQLException
, RuntimeException
)
477 ::osl::MutexGuard
aGuard( m_aMutex
);
478 checkDisposed(OStatement_BASE::rBHelper
.bDisposed
);
483 sal_Int32 nCount
= 0;
484 m_pParameters
->get_Count(&nCount
);
487 for(sal_Int32 i
=0;i
<nCount
;++i
)
489 ADOParameter
* pParam
= NULL
;
490 m_pParameters
->get_Item(OLEVariant(i
),&pParam
);
491 WpADOParameter
aParam(pParam
);
494 OUString sParam
= aParam
.GetName();
495 CHECK_RETURN(aParam
.PutValue(aVal
));
498 // m_pParameters->Delete(OLEVariant(i));
502 // -------------------------------------------------------------------------
503 void SAL_CALL
OPreparedStatement::clearBatch( ) throw(SQLException
, RuntimeException
)
505 // clearParameters( );
506 // m_aBatchList.erase();
508 // -------------------------------------------------------------------------
510 void SAL_CALL
OPreparedStatement::addBatch( ) throw(SQLException
, RuntimeException
)
513 // -------------------------------------------------------------------------
515 Sequence
< sal_Int32
> SAL_CALL
OPreparedStatement::executeBatch( ) throw(SQLException
, RuntimeException
)
517 return Sequence
< sal_Int32
> ();
519 // -----------------------------------------------------------------------------
520 // -----------------------------------------------------------------------------
521 void SAL_CALL
OPreparedStatement::acquire() throw()
523 OStatement_Base::acquire();
525 // -----------------------------------------------------------------------------
526 void SAL_CALL
OPreparedStatement::release() throw()
528 OStatement_Base::release();
530 // -----------------------------------------------------------------------------
531 void OPreparedStatement::replaceParameterNodeName(OSQLParseNode
* _pNode
,
532 const OUString
& _sDefaultName
,
533 sal_Int32
& _rParameterCount
)
535 sal_Int32 nCount
= _pNode
->count();
536 for(sal_Int32 i
=0;i
< nCount
;++i
)
538 OSQLParseNode
* pChildNode
= _pNode
->getChild(i
);
539 if(SQL_ISRULE(pChildNode
,parameter
) && pChildNode
->count() == 1)
541 OSQLParseNode
* pNewNode
= new OSQLParseNode(OUString(":") ,SQL_NODE_PUNCTUATION
,0);
542 delete pChildNode
->replace(pChildNode
->getChild(0),pNewNode
);
543 OUString sParameterName
= _sDefaultName
;
544 sParameterName
+= OUString::valueOf(++_rParameterCount
);
545 pChildNode
->append(new OSQLParseNode( sParameterName
,SQL_NODE_NAME
,0));
548 replaceParameterNodeName(pChildNode
,_sDefaultName
,_rParameterCount
);
552 // -----------------------------------------------------------------------------
556 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */