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_connectivity.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 CHECK_RETURN(m_RecordSet.put_MaxRecords(m_nMaxRows)) 310 CHECK_RETURN(m_RecordSet.Open(aCmd,aCon,m_eCursorType,m_eLockType,adOpenUnspecified)) 311 CHECK_RETURN(m_RecordSet.get_CacheSize(m_nFetchSize)) 312 CHECK_RETURN(m_RecordSet.get_MaxRecords(m_nMaxRows)) 313 CHECK_RETURN(m_RecordSet.get_CursorType(m_eCursorType)) 314 CHECK_RETURN(m_RecordSet.get_LockType(m_eLockType)) 315 316 OResultSet* pSet = new OResultSet(m_RecordSet,this); 317 Reference< XResultSet > xRs = pSet; 318 pSet->construct(); 319 pSet->setMetaData(getMetaData()); 320 m_xResultSet = WeakReference<XResultSet>(xRs); 321 322 return xRs; 323 } 324 // ------------------------------------------------------------------------- 325 326 void SAL_CALL OPreparedStatement::setBoolean( sal_Int32 parameterIndex, sal_Bool x ) throw(SQLException, RuntimeException) 327 { 328 setParameter(parameterIndex,adBoolean,sizeof(x),x); 329 } 330 // ------------------------------------------------------------------------- 331 332 void SAL_CALL OPreparedStatement::setByte( sal_Int32 parameterIndex, sal_Int8 x ) throw(SQLException, RuntimeException) 333 { 334 setParameter(parameterIndex,adTinyInt,sizeof(x),x); 335 } 336 // ------------------------------------------------------------------------- 337 338 void SAL_CALL OPreparedStatement::setDate( sal_Int32 parameterIndex, const Date& x ) throw(SQLException, RuntimeException) 339 { 340 setParameter(parameterIndex,adDBDate,sizeof(x),x); 341 } 342 // ------------------------------------------------------------------------- 343 344 345 void SAL_CALL OPreparedStatement::setTime( sal_Int32 parameterIndex, const Time& x ) throw(SQLException, RuntimeException) 346 { 347 setParameter(parameterIndex,adDBTime,sizeof(x),x); 348 } 349 // ------------------------------------------------------------------------- 350 351 void SAL_CALL OPreparedStatement::setTimestamp( sal_Int32 parameterIndex, const DateTime& x ) throw(SQLException, RuntimeException) 352 { 353 setParameter(parameterIndex,adDBTimeStamp,sizeof(x),x); 354 } 355 // ------------------------------------------------------------------------- 356 357 void SAL_CALL OPreparedStatement::setDouble( sal_Int32 parameterIndex, double x ) throw(SQLException, RuntimeException) 358 { 359 setParameter(parameterIndex,adDouble,sizeof(x),x); 360 } 361 // ------------------------------------------------------------------------- 362 363 void SAL_CALL OPreparedStatement::setFloat( sal_Int32 parameterIndex, float x ) throw(SQLException, RuntimeException) 364 { 365 setParameter(parameterIndex,adSingle,sizeof(x),x); 366 } 367 // ------------------------------------------------------------------------- 368 369 void SAL_CALL OPreparedStatement::setInt( sal_Int32 parameterIndex, sal_Int32 x ) throw(SQLException, RuntimeException) 370 { 371 setParameter(parameterIndex,adInteger,sizeof(x),x); 372 } 373 // ------------------------------------------------------------------------- 374 375 void SAL_CALL OPreparedStatement::setLong( sal_Int32 parameterIndex, sal_Int64 x ) throw(SQLException, RuntimeException) 376 { 377 setParameter(parameterIndex,adBigInt,sizeof(x),x); 378 } 379 // ------------------------------------------------------------------------- 380 381 void SAL_CALL OPreparedStatement::setNull( sal_Int32 parameterIndex, sal_Int32 /*sqlType*/ ) throw(SQLException, RuntimeException) 382 { 383 OLEVariant aVal; 384 aVal.setNull(); 385 setParameter(parameterIndex,adEmpty,0,aVal); 386 } 387 // ------------------------------------------------------------------------- 388 389 void SAL_CALL OPreparedStatement::setClob( sal_Int32 /*parameterIndex*/, const Reference< XClob >& /*x*/ ) throw(SQLException, RuntimeException) 390 { 391 ::dbtools::throwFeatureNotImplementedException( "XRowUpdate::setClob", *this ); 392 } 393 // ------------------------------------------------------------------------- 394 395 void SAL_CALL OPreparedStatement::setBlob( sal_Int32 /*parameterIndex*/, const Reference< XBlob >& /*x*/ ) throw(SQLException, RuntimeException) 396 { 397 ::dbtools::throwFeatureNotImplementedException( "XRowUpdate::setBlob", *this ); 398 } 399 // ------------------------------------------------------------------------- 400 401 void SAL_CALL OPreparedStatement::setArray( sal_Int32 /*parameterIndex*/, const Reference< XArray >& /*x*/ ) throw(SQLException, RuntimeException) 402 { 403 ::dbtools::throwFeatureNotImplementedException( "XRowUpdate::setArray", *this ); 404 } 405 // ------------------------------------------------------------------------- 406 407 void SAL_CALL OPreparedStatement::setRef( sal_Int32 /*parameterIndex*/, const Reference< XRef >& /*x*/ ) throw(SQLException, RuntimeException) 408 { 409 ::dbtools::throwFeatureNotImplementedException( "XRowUpdate::setRef", *this ); 410 } 411 // ------------------------------------------------------------------------- 412 413 void SAL_CALL OPreparedStatement::setObjectWithInfo( sal_Int32 parameterIndex, const Any& x, sal_Int32 sqlType, sal_Int32 scale ) throw(SQLException, RuntimeException) 414 { 415 switch(sqlType) 416 { 417 case DataType::DECIMAL: 418 case DataType::NUMERIC: 419 setString(parameterIndex,::comphelper::getString(x)); 420 break; 421 default: 422 ::dbtools::setObjectWithInfo(this,parameterIndex,x,sqlType,scale); 423 break; 424 } 425 } 426 // ------------------------------------------------------------------------- 427 428 void SAL_CALL OPreparedStatement::setObjectNull( sal_Int32 parameterIndex, sal_Int32 sqlType, const ::rtl::OUString& /*typeName*/ ) throw(SQLException, RuntimeException) 429 { 430 setNull(parameterIndex,sqlType); 431 } 432 // ------------------------------------------------------------------------- 433 434 void SAL_CALL OPreparedStatement::setObject( sal_Int32 parameterIndex, const Any& x ) throw(SQLException, RuntimeException) 435 { 436 if(!::dbtools::implSetObject(this,parameterIndex,x)) 437 { 438 const ::rtl::OUString sError( m_pConnection->getResources().getResourceStringWithSubstitution( 439 STR_UNKNOWN_PARA_TYPE, 440 "$position$", ::rtl::OUString::valueOf(parameterIndex) 441 ) ); 442 ::dbtools::throwGenericSQLException(sError,*this); 443 } 444 // setObject (parameterIndex, x, sqlType, 0); 445 } 446 // ------------------------------------------------------------------------- 447 448 void SAL_CALL OPreparedStatement::setShort( sal_Int32 parameterIndex, sal_Int16 x ) throw(SQLException, RuntimeException) 449 { 450 setParameter(parameterIndex,adSmallInt,sizeof(x),x); 451 } 452 // ------------------------------------------------------------------------- 453 454 void SAL_CALL OPreparedStatement::setBytes( sal_Int32 parameterIndex, const Sequence< sal_Int8 >& x ) throw(SQLException, RuntimeException) 455 { 456 setParameter(parameterIndex,adVarBinary,sizeof(sal_Int8)*x.getLength(),x); 457 } 458 459 // ------------------------------------------------------------------------- 460 461 462 void SAL_CALL OPreparedStatement::setCharacterStream( sal_Int32 /*parameterIndex*/, const Reference< ::com::sun::star::io::XInputStream >& /*x*/, sal_Int32 /*length*/ ) throw(SQLException, RuntimeException) 463 { 464 ::dbtools::throwFeatureNotImplementedException( "XParameters::setCharacterStream", *this ); 465 } 466 467 // ------------------------------------------------------------------------- 468 469 void SAL_CALL OPreparedStatement::setBinaryStream( sal_Int32 parameterIndex, const Reference< ::com::sun::star::io::XInputStream >& x, sal_Int32 length ) throw(SQLException, RuntimeException) 470 { 471 if(x.is()) 472 { 473 Sequence< sal_Int8 > aData; 474 x->readBytes(aData,length); 475 setBytes(parameterIndex,aData); 476 } 477 } 478 // ------------------------------------------------------------------------- 479 480 void SAL_CALL OPreparedStatement::clearParameters( ) throw(SQLException, RuntimeException) 481 { 482 ::osl::MutexGuard aGuard( m_aMutex ); 483 checkDisposed(OStatement_BASE::rBHelper.bDisposed); 484 485 486 if(m_pParameters) 487 { 488 sal_Int32 nCount = 0; 489 m_pParameters->get_Count(&nCount); 490 OLEVariant aVal; 491 aVal.setEmpty(); 492 for(sal_Int32 i=0;i<nCount;++i) 493 { 494 ADOParameter* pParam = NULL; 495 m_pParameters->get_Item(OLEVariant(i),&pParam); 496 WpADOParameter aParam(pParam); 497 if(pParam) 498 { 499 ::rtl::OUString sParam = aParam.GetName(); 500 CHECK_RETURN(aParam.PutValue(aVal)); 501 } 502 } 503 // m_pParameters->Delete(OLEVariant(i)); 504 505 } 506 } 507 // ------------------------------------------------------------------------- 508 void SAL_CALL OPreparedStatement::clearBatch( ) throw(SQLException, RuntimeException) 509 { 510 // clearParameters( ); 511 // m_aBatchList.erase(); 512 } 513 // ------------------------------------------------------------------------- 514 515 void SAL_CALL OPreparedStatement::addBatch( ) throw(SQLException, RuntimeException) 516 { 517 } 518 // ------------------------------------------------------------------------- 519 520 Sequence< sal_Int32 > SAL_CALL OPreparedStatement::executeBatch( ) throw(SQLException, RuntimeException) 521 { 522 return Sequence< sal_Int32 > (); 523 } 524 // ----------------------------------------------------------------------------- 525 // ----------------------------------------------------------------------------- 526 void SAL_CALL OPreparedStatement::acquire() throw() 527 { 528 OStatement_Base::acquire(); 529 } 530 // ----------------------------------------------------------------------------- 531 void SAL_CALL OPreparedStatement::release() throw() 532 { 533 OStatement_Base::release(); 534 } 535 // ----------------------------------------------------------------------------- 536 void OPreparedStatement::replaceParameterNodeName(OSQLParseNode* _pNode, 537 const ::rtl::OUString& _sDefaultName, 538 sal_Int32& _rParameterCount) 539 { 540 sal_Int32 nCount = _pNode->count(); 541 for(sal_Int32 i=0;i < nCount;++i) 542 { 543 OSQLParseNode* pChildNode = _pNode->getChild(i); 544 if(SQL_ISRULE(pChildNode,parameter) && pChildNode->count() == 1) 545 { 546 OSQLParseNode* pNewNode = new OSQLParseNode(::rtl::OUString::createFromAscii(":") ,SQL_NODE_PUNCTUATION,0); 547 delete pChildNode->replace(pChildNode->getChild(0),pNewNode); 548 ::rtl::OUString sParameterName = _sDefaultName; 549 sParameterName += ::rtl::OUString::valueOf(++_rParameterCount); 550 pChildNode->append(new OSQLParseNode( sParameterName,SQL_NODE_NAME,0)); 551 } 552 else 553 replaceParameterNodeName(pChildNode,_sDefaultName,_rParameterCount); 554 555 } 556 } 557 // ----------------------------------------------------------------------------- 558 559 560 561