1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_ado.hxx"
26 #include "connectivity/sqlparse.hxx"
27 #include "ado/APreparedStatement.hxx"
28 #include <com/sun/star/sdbc/DataType.hpp>
29 #include "ado/AResultSetMetaData.hxx"
30 #include "ado/AResultSet.hxx"
31 #include "ado/ADriver.hxx"
32 #include <com/sun/star/lang/DisposedException.hpp>
33 #include <cppuhelper/typeprovider.hxx>
34 #include <comphelper/sequence.hxx>
35 #include "connectivity/dbexception.hxx"
36 #include "connectivity/dbtools.hxx"
37 #include "resource/ado_res.hrc"
38
39 #include <limits>
40
41 #define CHECK_RETURN(x) \
42 if(!x) \
43 ADOS::ThrowException(*m_pConnection->getConnection(),*this);
44
45 #ifdef max
46 # undef max
47 #endif
48
49 //------------------------------------------------------------------------------
50 //------------------------------------------------------------------------------
51 using namespace connectivity::ado;
52 using namespace connectivity;
53 using namespace com::sun::star::uno;
54 using namespace com::sun::star::lang;
55 using namespace com::sun::star::beans;
56 using namespace com::sun::star::sdbc;
57 using namespace com::sun::star::util;
58
59
60 IMPLEMENT_SERVICE_INFO(OPreparedStatement,"com.sun.star.sdbcx.APreparedStatement","com.sun.star.sdbc.PreparedStatement");
61
OPreparedStatement(OConnection * _pConnection,const OTypeInfoMap & _TypeInfo,const::rtl::OUString & sql)62 OPreparedStatement::OPreparedStatement( OConnection* _pConnection,const OTypeInfoMap& _TypeInfo,const ::rtl::OUString& sql)
63 : OStatement_Base( _pConnection )
64 ,m_aTypeInfo(_TypeInfo)
65 {
66 osl_incrementInterlockedCount( &m_refCount );
67
68 OSQLParser aParser(_pConnection->getDriver()->getORB());
69 ::rtl::OUString sErrorMessage;
70 ::rtl::OUString sNewSql;
71 OSQLParseNode* pNode = aParser.parseTree(sErrorMessage,sql);
72 if(pNode)
73 { // special handling for parameters
74 /* we recusive replace all occurences of ? in the statement and replace them with name like "��" */
75 sal_Int32 nParameterCount = 0;
76 ::rtl::OUString sDefaultName = ::rtl::OUString::createFromAscii("parame");
77 replaceParameterNodeName(pNode,sDefaultName,nParameterCount);
78 pNode->parseNodeToStr( sNewSql, _pConnection );
79 delete pNode;
80 }
81 else
82 sNewSql = sql;
83 CHECK_RETURN(m_Command.put_CommandText(sNewSql))
84 CHECK_RETURN(m_Command.put_Prepared(VARIANT_TRUE))
85 m_pParameters = m_Command.get_Parameters();
86 m_pParameters->AddRef();
87 m_pParameters->Refresh();
88
89 osl_decrementInterlockedCount( &m_refCount );
90 }
91
92 // -------------------------------------------------------------------------
~OPreparedStatement()93 OPreparedStatement::~OPreparedStatement()
94 {
95 if (m_pParameters)
96 {
97 OSL_ENSURE( sal_False, "OPreparedStatement::~OPreparedStatement: not disposed!" );
98 m_pParameters->Release();
99 m_pParameters = NULL;
100 }
101 }
102
103 // -------------------------------------------------------------------------
104
queryInterface(const Type & rType)105 Any SAL_CALL OPreparedStatement::queryInterface( const Type & rType )
106 {
107 Any aRet = OStatement_Base::queryInterface(rType);
108 return aRet.hasValue() ? aRet : ::cppu::queryInterface( rType,
109 static_cast< XPreparedStatement*>(this),
110 static_cast< XParameters*>(this),
111 static_cast< XPreparedBatchExecution*>(this),
112 static_cast< XResultSetMetaDataSupplier*>(this));
113 }
114 // -------------------------------------------------------------------------
getTypes()115 ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type > SAL_CALL OPreparedStatement::getTypes( )
116 {
117 ::cppu::OTypeCollection aTypes( ::getCppuType( (const ::com::sun::star::uno::Reference< XPreparedStatement > *)0 ),
118 ::getCppuType( (const ::com::sun::star::uno::Reference< XParameters > *)0 ),
119 ::getCppuType( (const ::com::sun::star::uno::Reference< XResultSetMetaDataSupplier > *)0 ),
120 ::getCppuType( (const ::com::sun::star::uno::Reference< XPreparedBatchExecution > *)0 ));
121
122 return ::comphelper::concatSequences(aTypes.getTypes(),OStatement_Base::getTypes());
123 }
124 // -------------------------------------------------------------------------
125
getMetaData()126 Reference< XResultSetMetaData > SAL_CALL OPreparedStatement::getMetaData( )
127 {
128 if(!m_xMetaData.is() && m_RecordSet.IsValid())
129 m_xMetaData = new OResultSetMetaData(m_RecordSet);
130 return m_xMetaData;
131 }
132 // -------------------------------------------------------------------------
disposing()133 void OPreparedStatement::disposing()
134 {
135 m_xMetaData.clear();
136 if (m_pParameters)
137 {
138 m_pParameters->Release();
139 m_pParameters = NULL;
140 }
141 OStatement_Base::disposing();
142 }
143 // -------------------------------------------------------------------------
144
close()145 void SAL_CALL OPreparedStatement::close( )
146 {
147
148 {
149 ::osl::MutexGuard aGuard( m_aMutex );
150 checkDisposed(OStatement_BASE::rBHelper.bDisposed);
151
152 }
153 dispose();
154
155 }
156 // -------------------------------------------------------------------------
157
execute()158 sal_Bool SAL_CALL OPreparedStatement::execute( )
159 {
160 ::osl::MutexGuard aGuard( m_aMutex );
161 checkDisposed(OStatement_BASE::rBHelper.bDisposed);
162
163
164 SQLWarning warning;
165
166 // Reset warnings
167
168 clearWarnings ();
169
170 // Reset the statement handle, warning and saved Resultset
171
172 // reset();
173
174 // Call SQLExecute
175
176 try {
177 ADORecordset* pSet=NULL;
178 CHECK_RETURN(m_Command.Execute(m_RecordsAffected,m_Parameters,adCmdUnknown,&pSet))
179 m_RecordSet = WpADORecordset(pSet);
180 }
181 catch (SQLWarning& ex)
182 {
183
184 // Save pointer to warning and save with ResultSet
185 // object once it is created.
186
187 warning = ex;
188 }
189 return m_RecordSet.IsValid();
190 }
191 // -------------------------------------------------------------------------
192
executeUpdate()193 sal_Int32 SAL_CALL OPreparedStatement::executeUpdate( )
194 {
195 ::osl::MutexGuard aGuard( m_aMutex );
196 checkDisposed(OStatement_BASE::rBHelper.bDisposed);
197
198
199 ADORecordset* pSet=NULL;
200 CHECK_RETURN(m_Command.Execute(m_RecordsAffected,m_Parameters,adCmdUnknown,&pSet))
201 if ( VT_ERROR == m_RecordsAffected.getType() )
202 {
203 ADOS::ThrowException(*m_pConnection->getConnection(),*this);
204 // to be sure that we get the error really thrown
205 throw SQLException();
206 }
207 m_RecordSet = WpADORecordset(pSet);
208 return static_cast<sal_Int32>(m_RecordsAffected);
209 }
210
211 // -------------------------------------------------------------------------
setParameter(sal_Int32 parameterIndex,const DataTypeEnum & _eType,const sal_Int32 & _nSize,const OLEVariant & _Val)212 void OPreparedStatement::setParameter(sal_Int32 parameterIndex, const DataTypeEnum& _eType,
213 const sal_Int32& _nSize,const OLEVariant& _Val)
214 {
215 ::osl::MutexGuard aGuard( m_aMutex );
216 checkDisposed(OStatement_BASE::rBHelper.bDisposed);
217
218
219 sal_Int32 nCount = 0;
220 m_pParameters->get_Count(&nCount);
221 if(nCount < (parameterIndex-1))
222 {
223 ::rtl::OUString sDefaultName = ::rtl::OUString::createFromAscii("parame");
224 sDefaultName += ::rtl::OUString::valueOf(parameterIndex);
225 ADOParameter* pParam = m_Command.CreateParameter(sDefaultName,_eType,adParamInput,_nSize,_Val);
226 if(pParam)
227 {
228 m_pParameters->Append(pParam);
229 #if OSL_DEBUG_LEVEL > 0
230 ADOParameter* pParam = NULL;
231 m_pParameters->get_Item(OLEVariant(sal_Int32(parameterIndex-1)),&pParam);
232 WpADOParameter aParam(pParam);
233 if(pParam)
234 {
235 DataTypeEnum eType = aParam.GetADOType();
236 (void)eType;
237 }
238 #endif
239 }
240 }
241 else
242 {
243 ADOParameter* pParam = NULL;
244 m_pParameters->get_Item(OLEVariant(sal_Int32(parameterIndex-1)),&pParam);
245 WpADOParameter aParam(pParam);
246 if(pParam)
247 {
248 #if OSL_DEBUG_LEVEL > 0
249 ::rtl::OUString sParam = aParam.GetName();
250
251 #endif // OSL_DEBUG_LEVEL
252
253 DataTypeEnum eType = aParam.GetADOType();
254 if ( _eType != eType && _eType != adDBTimeStamp )
255 {
256 aParam.put_Type(_eType);
257 eType = _eType;
258 aParam.put_Size(_nSize);
259 }
260
261 if ( adVarBinary == eType && aParam.GetAttributes() == adParamLong )
262 {
263 aParam.AppendChunk(_Val);
264 }
265 else
266 CHECK_RETURN(aParam.PutValue(_Val));
267 }
268 }
269 ADOS::ThrowException(*m_pConnection->getConnection(),*this);
270 }
271 // -------------------------------------------------------------------------
setString(sal_Int32 parameterIndex,const::rtl::OUString & x)272 void SAL_CALL OPreparedStatement::setString( sal_Int32 parameterIndex, const ::rtl::OUString& x )
273 {
274 setParameter( parameterIndex, adLongVarWChar, ::std::numeric_limits< sal_Int32 >::max(), x );
275 }
276 // -------------------------------------------------------------------------
277
getConnection()278 Reference< XConnection > SAL_CALL OPreparedStatement::getConnection( )
279 {
280 ::osl::MutexGuard aGuard( m_aMutex );
281 checkDisposed(OStatement_BASE::rBHelper.bDisposed);
282
283
284 return (Reference< XConnection >)m_pConnection;
285 }
286 // -------------------------------------------------------------------------
287
executeQuery()288 Reference< XResultSet > SAL_CALL OPreparedStatement::executeQuery( )
289 {
290 ::osl::MutexGuard aGuard( m_aMutex );
291 checkDisposed(OStatement_BASE::rBHelper.bDisposed);
292
293
294 // first clear the old things
295 m_xMetaData.clear();
296 disposeResultSet();
297 if(m_RecordSet.IsValid())
298 m_RecordSet.Close();
299 m_RecordSet.clear();
300
301
302 // the create the new onces
303 m_RecordSet.Create();
304 OLEVariant aCmd;
305 aCmd.setIDispatch(m_Command);
306 OLEVariant aCon;
307 aCon.setNoArg();
308 CHECK_RETURN(m_RecordSet.put_CacheSize(m_nFetchSize))
309 sal_IntPtr maxRows = m_nMaxRows;
310 CHECK_RETURN(m_RecordSet.put_MaxRecords(maxRows))
311 CHECK_RETURN(m_RecordSet.Open(aCmd,aCon,m_eCursorType,m_eLockType,adOpenUnspecified))
312 CHECK_RETURN(m_RecordSet.get_CacheSize(m_nFetchSize))
313 CHECK_RETURN(m_RecordSet.get_MaxRecords(maxRows))
314 m_nMaxRows = maxRows;
315 CHECK_RETURN(m_RecordSet.get_CursorType(m_eCursorType))
316 CHECK_RETURN(m_RecordSet.get_LockType(m_eLockType))
317
318 OResultSet* pSet = new OResultSet(m_RecordSet,this);
319 Reference< XResultSet > xRs = pSet;
320 pSet->construct();
321 pSet->setMetaData(getMetaData());
322 m_xResultSet = WeakReference<XResultSet>(xRs);
323
324 return xRs;
325 }
326 // -------------------------------------------------------------------------
327
setBoolean(sal_Int32 parameterIndex,sal_Bool x)328 void SAL_CALL OPreparedStatement::setBoolean( sal_Int32 parameterIndex, sal_Bool x )
329 {
330 setParameter(parameterIndex,adBoolean,sizeof(x),x);
331 }
332 // -------------------------------------------------------------------------
333
setByte(sal_Int32 parameterIndex,sal_Int8 x)334 void SAL_CALL OPreparedStatement::setByte( sal_Int32 parameterIndex, sal_Int8 x )
335 {
336 setParameter(parameterIndex,adTinyInt,sizeof(x),x);
337 }
338 // -------------------------------------------------------------------------
339
setDate(sal_Int32 parameterIndex,const Date & x)340 void SAL_CALL OPreparedStatement::setDate( sal_Int32 parameterIndex, const Date& x )
341 {
342 setParameter(parameterIndex,adDBDate,sizeof(x),x);
343 }
344 // -------------------------------------------------------------------------
345
346
setTime(sal_Int32 parameterIndex,const Time & x)347 void SAL_CALL OPreparedStatement::setTime( sal_Int32 parameterIndex, const Time& x )
348 {
349 setParameter(parameterIndex,adDBTime,sizeof(x),x);
350 }
351 // -------------------------------------------------------------------------
352
setTimestamp(sal_Int32 parameterIndex,const DateTime & x)353 void SAL_CALL OPreparedStatement::setTimestamp( sal_Int32 parameterIndex, const DateTime& x )
354 {
355 setParameter(parameterIndex,adDBTimeStamp,sizeof(x),x);
356 }
357 // -------------------------------------------------------------------------
358
setDouble(sal_Int32 parameterIndex,double x)359 void SAL_CALL OPreparedStatement::setDouble( sal_Int32 parameterIndex, double x )
360 {
361 setParameter(parameterIndex,adDouble,sizeof(x),x);
362 }
363 // -------------------------------------------------------------------------
364
setFloat(sal_Int32 parameterIndex,float x)365 void SAL_CALL OPreparedStatement::setFloat( sal_Int32 parameterIndex, float x )
366 {
367 setParameter(parameterIndex,adSingle,sizeof(x),x);
368 }
369 // -------------------------------------------------------------------------
370
setInt(sal_Int32 parameterIndex,sal_Int32 x)371 void SAL_CALL OPreparedStatement::setInt( sal_Int32 parameterIndex, sal_Int32 x )
372 {
373 setParameter(parameterIndex,adInteger,sizeof(x),x);
374 }
375 // -------------------------------------------------------------------------
376
setLong(sal_Int32 parameterIndex,sal_Int64 x)377 void SAL_CALL OPreparedStatement::setLong( sal_Int32 parameterIndex, sal_Int64 x )
378 {
379 setParameter(parameterIndex,adBigInt,sizeof(x),x);
380 }
381 // -------------------------------------------------------------------------
382
setNull(sal_Int32 parameterIndex,sal_Int32)383 void SAL_CALL OPreparedStatement::setNull( sal_Int32 parameterIndex, sal_Int32 /*sqlType*/ )
384 {
385 OLEVariant aVal;
386 aVal.setNull();
387 setParameter(parameterIndex,adEmpty,0,aVal);
388 }
389 // -------------------------------------------------------------------------
390
setClob(sal_Int32,const Reference<XClob> &)391 void SAL_CALL OPreparedStatement::setClob( sal_Int32 /*parameterIndex*/, const Reference< XClob >& /*x*/ )
392 {
393 ::dbtools::throwFeatureNotImplementedException( "XRowUpdate::setClob", *this );
394 }
395 // -------------------------------------------------------------------------
396
setBlob(sal_Int32,const Reference<XBlob> &)397 void SAL_CALL OPreparedStatement::setBlob( sal_Int32 /*parameterIndex*/, const Reference< XBlob >& /*x*/ )
398 {
399 ::dbtools::throwFeatureNotImplementedException( "XRowUpdate::setBlob", *this );
400 }
401 // -------------------------------------------------------------------------
402
setArray(sal_Int32,const Reference<XArray> &)403 void SAL_CALL OPreparedStatement::setArray( sal_Int32 /*parameterIndex*/, const Reference< XArray >& /*x*/ )
404 {
405 ::dbtools::throwFeatureNotImplementedException( "XRowUpdate::setArray", *this );
406 }
407 // -------------------------------------------------------------------------
408
setRef(sal_Int32,const Reference<XRef> &)409 void SAL_CALL OPreparedStatement::setRef( sal_Int32 /*parameterIndex*/, const Reference< XRef >& /*x*/ )
410 {
411 ::dbtools::throwFeatureNotImplementedException( "XRowUpdate::setRef", *this );
412 }
413 // -------------------------------------------------------------------------
414
setObjectWithInfo(sal_Int32 parameterIndex,const Any & x,sal_Int32 sqlType,sal_Int32 scale)415 void SAL_CALL OPreparedStatement::setObjectWithInfo( sal_Int32 parameterIndex, const Any& x, sal_Int32 sqlType, sal_Int32 scale )
416 {
417 switch(sqlType)
418 {
419 case DataType::DECIMAL:
420 case DataType::NUMERIC:
421 setString(parameterIndex,::comphelper::getString(x));
422 break;
423 default:
424 ::dbtools::setObjectWithInfo(this,parameterIndex,x,sqlType,scale);
425 break;
426 }
427 }
428 // -------------------------------------------------------------------------
429
setObjectNull(sal_Int32 parameterIndex,sal_Int32 sqlType,const::rtl::OUString &)430 void SAL_CALL OPreparedStatement::setObjectNull( sal_Int32 parameterIndex, sal_Int32 sqlType, const ::rtl::OUString& /*typeName*/ )
431 {
432 setNull(parameterIndex,sqlType);
433 }
434 // -------------------------------------------------------------------------
435
setObject(sal_Int32 parameterIndex,const Any & x)436 void SAL_CALL OPreparedStatement::setObject( sal_Int32 parameterIndex, const Any& x )
437 {
438 if(!::dbtools::implSetObject(this,parameterIndex,x))
439 {
440 const ::rtl::OUString sError( m_pConnection->getResources().getResourceStringWithSubstitution(
441 STR_UNKNOWN_PARA_TYPE,
442 "$position$", ::rtl::OUString::valueOf(parameterIndex)
443 ) );
444 ::dbtools::throwGenericSQLException(sError,*this);
445 }
446 // setObject (parameterIndex, x, sqlType, 0);
447 }
448 // -------------------------------------------------------------------------
449
setShort(sal_Int32 parameterIndex,sal_Int16 x)450 void SAL_CALL OPreparedStatement::setShort( sal_Int32 parameterIndex, sal_Int16 x )
451 {
452 setParameter(parameterIndex,adSmallInt,sizeof(x),x);
453 }
454 // -------------------------------------------------------------------------
455
setBytes(sal_Int32 parameterIndex,const Sequence<sal_Int8> & x)456 void SAL_CALL OPreparedStatement::setBytes( sal_Int32 parameterIndex, const Sequence< sal_Int8 >& x )
457 {
458 setParameter(parameterIndex,adVarBinary,sizeof(sal_Int8)*x.getLength(),x);
459 }
460
461 // -------------------------------------------------------------------------
462
463
setCharacterStream(sal_Int32,const Reference<::com::sun::star::io::XInputStream> &,sal_Int32)464 void SAL_CALL OPreparedStatement::setCharacterStream( sal_Int32 /*parameterIndex*/, const Reference< ::com::sun::star::io::XInputStream >& /*x*/, sal_Int32 /*length*/ )
465 {
466 ::dbtools::throwFeatureNotImplementedException( "XParameters::setCharacterStream", *this );
467 }
468
469 // -------------------------------------------------------------------------
470
setBinaryStream(sal_Int32 parameterIndex,const Reference<::com::sun::star::io::XInputStream> & x,sal_Int32 length)471 void SAL_CALL OPreparedStatement::setBinaryStream( sal_Int32 parameterIndex, const Reference< ::com::sun::star::io::XInputStream >& x, sal_Int32 length )
472 {
473 if(x.is())
474 {
475 Sequence< sal_Int8 > aData;
476 x->readBytes(aData,length);
477 setBytes(parameterIndex,aData);
478 }
479 }
480 // -------------------------------------------------------------------------
481
clearParameters()482 void SAL_CALL OPreparedStatement::clearParameters( )
483 {
484 ::osl::MutexGuard aGuard( m_aMutex );
485 checkDisposed(OStatement_BASE::rBHelper.bDisposed);
486
487
488 if(m_pParameters)
489 {
490 sal_Int32 nCount = 0;
491 m_pParameters->get_Count(&nCount);
492 OLEVariant aVal;
493 aVal.setEmpty();
494 for(sal_Int32 i=0;i<nCount;++i)
495 {
496 ADOParameter* pParam = NULL;
497 m_pParameters->get_Item(OLEVariant(i),&pParam);
498 WpADOParameter aParam(pParam);
499 if(pParam)
500 {
501 ::rtl::OUString sParam = aParam.GetName();
502 CHECK_RETURN(aParam.PutValue(aVal));
503 }
504 }
505 // m_pParameters->Delete(OLEVariant(i));
506
507 }
508 }
509 // -------------------------------------------------------------------------
clearBatch()510 void SAL_CALL OPreparedStatement::clearBatch( )
511 {
512 // clearParameters( );
513 // m_aBatchList.erase();
514 }
515 // -------------------------------------------------------------------------
516
addBatch()517 void SAL_CALL OPreparedStatement::addBatch( )
518 {
519 }
520 // -------------------------------------------------------------------------
521
executeBatch()522 Sequence< sal_Int32 > SAL_CALL OPreparedStatement::executeBatch( )
523 {
524 return Sequence< sal_Int32 > ();
525 }
526 // -----------------------------------------------------------------------------
527 // -----------------------------------------------------------------------------
acquire()528 void SAL_CALL OPreparedStatement::acquire() throw()
529 {
530 OStatement_Base::acquire();
531 }
532 // -----------------------------------------------------------------------------
release()533 void SAL_CALL OPreparedStatement::release() throw()
534 {
535 OStatement_Base::release();
536 }
537 // -----------------------------------------------------------------------------
replaceParameterNodeName(OSQLParseNode * _pNode,const::rtl::OUString & _sDefaultName,sal_Int32 & _rParameterCount)538 void OPreparedStatement::replaceParameterNodeName(OSQLParseNode* _pNode,
539 const ::rtl::OUString& _sDefaultName,
540 sal_Int32& _rParameterCount)
541 {
542 sal_Int32 nCount = _pNode->count();
543 for(sal_Int32 i=0;i < nCount;++i)
544 {
545 OSQLParseNode* pChildNode = _pNode->getChild(i);
546 if(SQL_ISRULE(pChildNode,parameter) && pChildNode->count() == 1)
547 {
548 OSQLParseNode* pNewNode = new OSQLParseNode(::rtl::OUString::createFromAscii(":") ,SQL_NODE_PUNCTUATION,0);
549 delete pChildNode->replace(pChildNode->getChild(0),pNewNode);
550 ::rtl::OUString sParameterName = _sDefaultName;
551 sParameterName += ::rtl::OUString::valueOf(++_rParameterCount);
552 pChildNode->append(new OSQLParseNode( sParameterName,SQL_NODE_NAME,0));
553 }
554 else
555 replaceParameterNodeName(pChildNode,_sDefaultName,_rParameterCount);
556
557 }
558 }
559 // -----------------------------------------------------------------------------
560