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