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 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 // ------------------------------------------------------------------------- 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 105 Any SAL_CALL OPreparedStatement::queryInterface( const Type & rType ) throw(RuntimeException) 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 // ------------------------------------------------------------------------- 115 ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type > SAL_CALL OPreparedStatement::getTypes( ) throw(::com::sun::star::uno::RuntimeException) 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 126 Reference< XResultSetMetaData > SAL_CALL OPreparedStatement::getMetaData( ) throw(SQLException, RuntimeException) 127 { 128 if(!m_xMetaData.is() && m_RecordSet.IsValid()) 129 m_xMetaData = new OResultSetMetaData(m_RecordSet); 130 return m_xMetaData; 131 } 132 // ------------------------------------------------------------------------- 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 145 void SAL_CALL OPreparedStatement::close( ) throw(SQLException, RuntimeException) 146 { 147 148 { 149 ::osl::MutexGuard aGuard( m_aMutex ); 150 checkDisposed(OStatement_BASE::rBHelper.bDisposed); 151 152 } 153 dispose(); 154 155 } 156 // ------------------------------------------------------------------------- 157 158 sal_Bool SAL_CALL OPreparedStatement::execute( ) throw(SQLException, RuntimeException) 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 193 sal_Int32 SAL_CALL OPreparedStatement::executeUpdate( ) throw(SQLException, RuntimeException) 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 // ------------------------------------------------------------------------- 212 void OPreparedStatement::setParameter(sal_Int32 parameterIndex, const DataTypeEnum& _eType, 213 const sal_Int32& _nSize,const OLEVariant& _Val) throw(SQLException, RuntimeException) 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 // ------------------------------------------------------------------------- 272 void SAL_CALL OPreparedStatement::setString( sal_Int32 parameterIndex, const ::rtl::OUString& x ) throw(SQLException, RuntimeException) 273 { 274 setParameter( parameterIndex, adLongVarWChar, ::std::numeric_limits< sal_Int32 >::max(), x ); 275 } 276 // ------------------------------------------------------------------------- 277 278 Reference< XConnection > SAL_CALL OPreparedStatement::getConnection( ) throw(SQLException, RuntimeException) 279 { 280 ::osl::MutexGuard aGuard( m_aMutex ); 281 checkDisposed(OStatement_BASE::rBHelper.bDisposed); 282 283 284 return (Reference< XConnection >)m_pConnection; 285 } 286 // ------------------------------------------------------------------------- 287 288 Reference< XResultSet > SAL_CALL OPreparedStatement::executeQuery( ) throw(SQLException, RuntimeException) 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 328 void SAL_CALL OPreparedStatement::setBoolean( sal_Int32 parameterIndex, sal_Bool x ) throw(SQLException, RuntimeException) 329 { 330 setParameter(parameterIndex,adBoolean,sizeof(x),x); 331 } 332 // ------------------------------------------------------------------------- 333 334 void SAL_CALL OPreparedStatement::setByte( sal_Int32 parameterIndex, sal_Int8 x ) throw(SQLException, RuntimeException) 335 { 336 setParameter(parameterIndex,adTinyInt,sizeof(x),x); 337 } 338 // ------------------------------------------------------------------------- 339 340 void SAL_CALL OPreparedStatement::setDate( sal_Int32 parameterIndex, const Date& x ) throw(SQLException, RuntimeException) 341 { 342 setParameter(parameterIndex,adDBDate,sizeof(x),x); 343 } 344 // ------------------------------------------------------------------------- 345 346 347 void SAL_CALL OPreparedStatement::setTime( sal_Int32 parameterIndex, const Time& x ) throw(SQLException, RuntimeException) 348 { 349 setParameter(parameterIndex,adDBTime,sizeof(x),x); 350 } 351 // ------------------------------------------------------------------------- 352 353 void SAL_CALL OPreparedStatement::setTimestamp( sal_Int32 parameterIndex, const DateTime& x ) throw(SQLException, RuntimeException) 354 { 355 setParameter(parameterIndex,adDBTimeStamp,sizeof(x),x); 356 } 357 // ------------------------------------------------------------------------- 358 359 void SAL_CALL OPreparedStatement::setDouble( sal_Int32 parameterIndex, double x ) throw(SQLException, RuntimeException) 360 { 361 setParameter(parameterIndex,adDouble,sizeof(x),x); 362 } 363 // ------------------------------------------------------------------------- 364 365 void SAL_CALL OPreparedStatement::setFloat( sal_Int32 parameterIndex, float x ) throw(SQLException, RuntimeException) 366 { 367 setParameter(parameterIndex,adSingle,sizeof(x),x); 368 } 369 // ------------------------------------------------------------------------- 370 371 void SAL_CALL OPreparedStatement::setInt( sal_Int32 parameterIndex, sal_Int32 x ) throw(SQLException, RuntimeException) 372 { 373 setParameter(parameterIndex,adInteger,sizeof(x),x); 374 } 375 // ------------------------------------------------------------------------- 376 377 void SAL_CALL OPreparedStatement::setLong( sal_Int32 parameterIndex, sal_Int64 x ) throw(SQLException, RuntimeException) 378 { 379 setParameter(parameterIndex,adBigInt,sizeof(x),x); 380 } 381 // ------------------------------------------------------------------------- 382 383 void SAL_CALL OPreparedStatement::setNull( sal_Int32 parameterIndex, sal_Int32 /*sqlType*/ ) throw(SQLException, RuntimeException) 384 { 385 OLEVariant aVal; 386 aVal.setNull(); 387 setParameter(parameterIndex,adEmpty,0,aVal); 388 } 389 // ------------------------------------------------------------------------- 390 391 void SAL_CALL OPreparedStatement::setClob( sal_Int32 /*parameterIndex*/, const Reference< XClob >& /*x*/ ) throw(SQLException, RuntimeException) 392 { 393 ::dbtools::throwFeatureNotImplementedException( "XRowUpdate::setClob", *this ); 394 } 395 // ------------------------------------------------------------------------- 396 397 void SAL_CALL OPreparedStatement::setBlob( sal_Int32 /*parameterIndex*/, const Reference< XBlob >& /*x*/ ) throw(SQLException, RuntimeException) 398 { 399 ::dbtools::throwFeatureNotImplementedException( "XRowUpdate::setBlob", *this ); 400 } 401 // ------------------------------------------------------------------------- 402 403 void SAL_CALL OPreparedStatement::setArray( sal_Int32 /*parameterIndex*/, const Reference< XArray >& /*x*/ ) throw(SQLException, RuntimeException) 404 { 405 ::dbtools::throwFeatureNotImplementedException( "XRowUpdate::setArray", *this ); 406 } 407 // ------------------------------------------------------------------------- 408 409 void SAL_CALL OPreparedStatement::setRef( sal_Int32 /*parameterIndex*/, const Reference< XRef >& /*x*/ ) throw(SQLException, RuntimeException) 410 { 411 ::dbtools::throwFeatureNotImplementedException( "XRowUpdate::setRef", *this ); 412 } 413 // ------------------------------------------------------------------------- 414 415 void SAL_CALL OPreparedStatement::setObjectWithInfo( sal_Int32 parameterIndex, const Any& x, sal_Int32 sqlType, sal_Int32 scale ) throw(SQLException, RuntimeException) 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 430 void SAL_CALL OPreparedStatement::setObjectNull( sal_Int32 parameterIndex, sal_Int32 sqlType, const ::rtl::OUString& /*typeName*/ ) throw(SQLException, RuntimeException) 431 { 432 setNull(parameterIndex,sqlType); 433 } 434 // ------------------------------------------------------------------------- 435 436 void SAL_CALL OPreparedStatement::setObject( sal_Int32 parameterIndex, const Any& x ) throw(SQLException, RuntimeException) 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 450 void SAL_CALL OPreparedStatement::setShort( sal_Int32 parameterIndex, sal_Int16 x ) throw(SQLException, RuntimeException) 451 { 452 setParameter(parameterIndex,adSmallInt,sizeof(x),x); 453 } 454 // ------------------------------------------------------------------------- 455 456 void SAL_CALL OPreparedStatement::setBytes( sal_Int32 parameterIndex, const Sequence< sal_Int8 >& x ) throw(SQLException, RuntimeException) 457 { 458 setParameter(parameterIndex,adVarBinary,sizeof(sal_Int8)*x.getLength(),x); 459 } 460 461 // ------------------------------------------------------------------------- 462 463 464 void SAL_CALL OPreparedStatement::setCharacterStream( sal_Int32 /*parameterIndex*/, const Reference< ::com::sun::star::io::XInputStream >& /*x*/, sal_Int32 /*length*/ ) throw(SQLException, RuntimeException) 465 { 466 ::dbtools::throwFeatureNotImplementedException( "XParameters::setCharacterStream", *this ); 467 } 468 469 // ------------------------------------------------------------------------- 470 471 void SAL_CALL OPreparedStatement::setBinaryStream( sal_Int32 parameterIndex, const Reference< ::com::sun::star::io::XInputStream >& x, sal_Int32 length ) throw(SQLException, RuntimeException) 472 { 473 if(x.is()) 474 { 475 Sequence< sal_Int8 > aData; 476 x->readBytes(aData,length); 477 setBytes(parameterIndex,aData); 478 } 479 } 480 // ------------------------------------------------------------------------- 481 482 void SAL_CALL OPreparedStatement::clearParameters( ) throw(SQLException, RuntimeException) 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 // ------------------------------------------------------------------------- 510 void SAL_CALL OPreparedStatement::clearBatch( ) throw(SQLException, RuntimeException) 511 { 512 // clearParameters( ); 513 // m_aBatchList.erase(); 514 } 515 // ------------------------------------------------------------------------- 516 517 void SAL_CALL OPreparedStatement::addBatch( ) throw(SQLException, RuntimeException) 518 { 519 } 520 // ------------------------------------------------------------------------- 521 522 Sequence< sal_Int32 > SAL_CALL OPreparedStatement::executeBatch( ) throw(SQLException, RuntimeException) 523 { 524 return Sequence< sal_Int32 > (); 525 } 526 // ----------------------------------------------------------------------------- 527 // ----------------------------------------------------------------------------- 528 void SAL_CALL OPreparedStatement::acquire() throw() 529 { 530 OStatement_Base::acquire(); 531 } 532 // ----------------------------------------------------------------------------- 533 void SAL_CALL OPreparedStatement::release() throw() 534 { 535 OStatement_Base::release(); 536 } 537 // ----------------------------------------------------------------------------- 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