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 <osl/diagnose.h> 31 #include "file/FStatement.hxx" 32 #include "file/FConnection.hxx" 33 #include "file/FDriver.hxx" 34 #include "file/FResultSet.hxx" 35 #include <comphelper/property.hxx> 36 #include <comphelper/uno3.hxx> 37 #include <osl/thread.h> 38 #include <com/sun/star/sdbc/ResultSetConcurrency.hpp> 39 #include <com/sun/star/sdbc/ResultSetType.hpp> 40 #include <com/sun/star/sdbc/FetchDirection.hpp> 41 #include <com/sun/star/lang/DisposedException.hpp> 42 #include <comphelper/sequence.hxx> 43 #include <cppuhelper/typeprovider.hxx> 44 #include "connectivity/dbexception.hxx" 45 #include "resource/file_res.hrc" 46 #include <algorithm> 47 #include <tools/debug.hxx> 48 #include <rtl/logfile.hxx> 49 50 #define THROW_SQL(x) \ 51 OTools::ThrowException(x,m_aStatementHandle,SQL_HANDLE_STMT,*this) 52 53 namespace connectivity 54 { 55 namespace file 56 { 57 58 //------------------------------------------------------------------------------ 59 using namespace dbtools; 60 using namespace com::sun::star::uno; 61 using namespace com::sun::star::lang; 62 using namespace com::sun::star::beans; 63 using namespace com::sun::star::sdbc; 64 using namespace com::sun::star::sdbcx; 65 using namespace com::sun::star::container; 66 DBG_NAME( file_OStatement_Base ) 67 68 //------------------------------------------------------------------------------ 69 OStatement_Base::OStatement_Base(OConnection* _pConnection ) 70 :OStatement_BASE(m_aMutex) 71 ,::comphelper::OPropertyContainer(OStatement_BASE::rBHelper) 72 ,m_xDBMetaData(_pConnection->getMetaData()) 73 ,m_aParser(_pConnection->getDriver()->getFactory()) 74 ,m_aSQLIterator( _pConnection, _pConnection->createCatalog()->getTables(), m_aParser, NULL ) 75 ,m_pConnection(_pConnection) 76 ,m_pParseTree(NULL) 77 ,m_pSQLAnalyzer(NULL) 78 ,m_pEvaluationKeySet(NULL) 79 ,m_pTable(NULL) 80 ,m_nMaxFieldSize(0) 81 ,m_nMaxRows(0) 82 ,m_nQueryTimeOut(0) 83 ,m_nFetchSize(0) 84 ,m_nResultSetType(ResultSetType::FORWARD_ONLY) 85 ,m_nFetchDirection(FetchDirection::FORWARD) 86 ,m_nResultSetConcurrency(ResultSetConcurrency::UPDATABLE) 87 ,m_bEscapeProcessing(sal_True) 88 ,rBHelper(OStatement_BASE::rBHelper) 89 { 90 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "file", "Ocke.Janssen@sun.com", "OStatement_Base::OStatement_Base" ); 91 DBG_CTOR( file_OStatement_Base, NULL ); 92 93 m_pConnection->acquire(); 94 95 sal_Int32 nAttrib = 0; 96 97 registerProperty(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_CURSORNAME), PROPERTY_ID_CURSORNAME, nAttrib,&m_aCursorName, ::getCppuType(reinterpret_cast< ::rtl::OUString*>(NULL))); 98 registerProperty(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_MAXFIELDSIZE), PROPERTY_ID_MAXFIELDSIZE, nAttrib,&m_nMaxFieldSize, ::getCppuType(reinterpret_cast<sal_Int32*>(NULL))); 99 registerProperty(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_MAXROWS), PROPERTY_ID_MAXROWS, nAttrib,&m_nMaxRows, ::getCppuType(reinterpret_cast<sal_Int32*>(NULL))); 100 registerProperty(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_QUERYTIMEOUT), PROPERTY_ID_QUERYTIMEOUT, nAttrib,&m_nQueryTimeOut, ::getCppuType(reinterpret_cast<sal_Int32*>(NULL))); 101 registerProperty(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_FETCHSIZE), PROPERTY_ID_FETCHSIZE, nAttrib,&m_nFetchSize, ::getCppuType(reinterpret_cast<sal_Int32*>(NULL))); 102 registerProperty(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_RESULTSETTYPE), PROPERTY_ID_RESULTSETTYPE, nAttrib,&m_nResultSetType, ::getCppuType(reinterpret_cast<sal_Int32*>(NULL))); 103 registerProperty(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_FETCHDIRECTION), PROPERTY_ID_FETCHDIRECTION, nAttrib,&m_nFetchDirection, ::getCppuType(reinterpret_cast<sal_Int32*>(NULL))); 104 registerProperty(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_ESCAPEPROCESSING),PROPERTY_ID_ESCAPEPROCESSING, nAttrib,&m_bEscapeProcessing,::getCppuBooleanType()); 105 106 registerProperty(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_RESULTSETCONCURRENCY), PROPERTY_ID_RESULTSETCONCURRENCY, nAttrib,&m_nResultSetConcurrency, ::getCppuType(reinterpret_cast<sal_Int32*>(NULL))); 107 } 108 // ----------------------------------------------------------------------------- 109 OStatement_Base::~OStatement_Base() 110 { 111 osl_incrementInterlockedCount( &m_refCount ); 112 disposing(); 113 delete m_pSQLAnalyzer; 114 115 DBG_DTOR( file_OStatement_Base, NULL ); 116 } 117 //------------------------------------------------------------------------------ 118 void OStatement_Base::disposeResultSet() 119 { 120 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "file", "Ocke.Janssen@sun.com", "OStatement_Base::disposeResultSet" ); 121 // free the cursor if alive 122 Reference< XComponent > xComp(m_xResultSet.get(), UNO_QUERY); 123 if (xComp.is()) 124 xComp->dispose(); 125 m_xResultSet = Reference< XResultSet>(); 126 } 127 //------------------------------------------------------------------------------ 128 void OStatement_BASE2::disposing() 129 { 130 ::osl::MutexGuard aGuard(m_aMutex); 131 132 disposeResultSet(); 133 134 if(m_pSQLAnalyzer) 135 m_pSQLAnalyzer->dispose(); 136 137 if(m_aRow.isValid()) 138 { 139 m_aRow->get().clear(); 140 m_aRow = NULL; 141 } 142 143 m_aSQLIterator.dispose(); 144 145 if(m_pTable) 146 { 147 m_pTable->release(); 148 m_pTable = NULL; 149 } 150 151 if (m_pConnection) 152 { 153 m_pConnection->release(); 154 m_pConnection = NULL; 155 } 156 157 dispose_ChildImpl(); 158 159 if ( m_pParseTree ) 160 { 161 delete m_pParseTree; 162 m_pParseTree = NULL; 163 } 164 165 OStatement_Base::disposing(); 166 } 167 // ----------------------------------------------------------------------------- 168 void SAL_CALL OStatement_Base::acquire() throw() 169 { 170 OStatement_BASE::acquire(); 171 } 172 //----------------------------------------------------------------------------- 173 void SAL_CALL OStatement_BASE2::release() throw() 174 { 175 relase_ChildImpl(); 176 } 177 //----------------------------------------------------------------------------- 178 Any SAL_CALL OStatement_Base::queryInterface( const Type & rType ) throw(RuntimeException) 179 { 180 //RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "file", "Ocke.Janssen@sun.com", "OStatement_Base::queryInterface" ); 181 const Any aRet = OStatement_BASE::queryInterface(rType); 182 return aRet.hasValue() ? aRet : OPropertySetHelper::queryInterface(rType); 183 } 184 // ------------------------------------------------------------------------- 185 Sequence< Type > SAL_CALL OStatement_Base::getTypes( ) throw(RuntimeException) 186 { 187 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "file", "Ocke.Janssen@sun.com", "OStatement_Base::getTypes" ); 188 ::cppu::OTypeCollection aTypes( ::getCppuType( (const Reference< ::com::sun::star::beans::XMultiPropertySet > *)0 ), 189 ::getCppuType( (const Reference< ::com::sun::star::beans::XFastPropertySet > *)0 ), 190 ::getCppuType( (const Reference< ::com::sun::star::beans::XPropertySet > *)0 )); 191 192 return ::comphelper::concatSequences(aTypes.getTypes(),OStatement_BASE::getTypes()); 193 } 194 // ------------------------------------------------------------------------- 195 196 void SAL_CALL OStatement_Base::cancel( ) throw(RuntimeException) 197 { 198 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "file", "Ocke.Janssen@sun.com", "OStatement_Base::cancel" ); 199 } 200 // ------------------------------------------------------------------------- 201 202 void SAL_CALL OStatement_Base::close( ) throw(SQLException, RuntimeException) 203 { 204 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "file", "Ocke.Janssen@sun.com", "OStatement_Base::close" ); 205 { 206 ::osl::MutexGuard aGuard( m_aMutex ); 207 checkDisposed(OStatement_BASE::rBHelper.bDisposed); 208 } 209 dispose(); 210 } 211 // ------------------------------------------------------------------------- 212 213 void OStatement_Base::reset() throw (SQLException) 214 { 215 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "file", "Ocke.Janssen@sun.com", "OStatement_Base::reset" ); 216 ::osl::MutexGuard aGuard( m_aMutex ); 217 checkDisposed(OStatement_BASE::rBHelper.bDisposed); 218 219 220 clearWarnings (); 221 222 if (m_xResultSet.get().is()) 223 clearMyResultSet(); 224 } 225 //-------------------------------------------------------------------- 226 // clearMyResultSet 227 // If a ResultSet was created for this Statement, close it 228 //-------------------------------------------------------------------- 229 230 void OStatement_Base::clearMyResultSet () throw (SQLException) 231 { 232 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "file", "Ocke.Janssen@sun.com", "OStatement_Base::clearMyResultSet " ); 233 ::osl::MutexGuard aGuard( m_aMutex ); 234 checkDisposed(OStatement_BASE::rBHelper.bDisposed); 235 236 try 237 { 238 Reference<XCloseable> xCloseable; 239 if ( ::comphelper::query_interface( m_xResultSet.get(), xCloseable ) ) 240 xCloseable->close(); 241 } 242 catch( const DisposedException& ) { } 243 244 m_xResultSet = Reference< XResultSet>(); 245 } 246 //-------------------------------------------------------------------- 247 // setWarning 248 // Sets the warning 249 //-------------------------------------------------------------------- 250 251 void OStatement_Base::setWarning (const SQLWarning &ex) throw( SQLException) 252 { 253 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "file", "Ocke.Janssen@sun.com", "OStatement_Base::setWarning " ); 254 ::osl::MutexGuard aGuard( m_aMutex ); 255 checkDisposed(OStatement_BASE::rBHelper.bDisposed); 256 257 258 m_aLastWarning = ex; 259 } 260 261 // ------------------------------------------------------------------------- 262 Any SAL_CALL OStatement_Base::getWarnings( ) throw(SQLException, RuntimeException) 263 { 264 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "file", "Ocke.Janssen@sun.com", "OStatement_Base::getWarnings" ); 265 ::osl::MutexGuard aGuard( m_aMutex ); 266 checkDisposed(OStatement_BASE::rBHelper.bDisposed); 267 268 return makeAny(m_aLastWarning); 269 } 270 // ------------------------------------------------------------------------- 271 void SAL_CALL OStatement_Base::clearWarnings( ) throw(SQLException, RuntimeException) 272 { 273 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "file", "Ocke.Janssen@sun.com", "OStatement_Base::clearWarnings" ); 274 ::osl::MutexGuard aGuard( m_aMutex ); 275 checkDisposed(OStatement_BASE::rBHelper.bDisposed); 276 277 m_aLastWarning = SQLWarning(); 278 } 279 // ------------------------------------------------------------------------- 280 ::cppu::IPropertyArrayHelper* OStatement_Base::createArrayHelper( ) const 281 { 282 //RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "file", "Ocke.Janssen@sun.com", "OStatement_Base::createArrayHelper" ); 283 Sequence< Property > aProps; 284 describeProperties(aProps); 285 return new ::cppu::OPropertyArrayHelper(aProps); 286 } 287 288 // ------------------------------------------------------------------------- 289 ::cppu::IPropertyArrayHelper & OStatement_Base::getInfoHelper() 290 { 291 //RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "file", "Ocke.Janssen@sun.com", "OStatement_Base::getInfoHelper" ); 292 return *const_cast<OStatement_Base*>(this)->getArrayHelper(); 293 } 294 // ------------------------------------------------------------------------- 295 OResultSet* OStatement::createResultSet() 296 { 297 return new OResultSet(this,m_aSQLIterator); 298 } 299 // ------------------------------------------------------------------------- 300 IMPLEMENT_SERVICE_INFO(OStatement,"com.sun.star.sdbc.driver.file.Statement","com.sun.star.sdbc.Statement"); 301 // ----------------------------------------------------------------------------- 302 void SAL_CALL OStatement::acquire() throw() 303 { 304 OStatement_BASE2::acquire(); 305 } 306 // ----------------------------------------------------------------------------- 307 void SAL_CALL OStatement::release() throw() 308 { 309 OStatement_BASE2::release(); 310 } 311 // ----------------------------------------------------------------------------- 312 // ------------------------------------------------------------------------- 313 sal_Bool SAL_CALL OStatement::execute( const ::rtl::OUString& sql ) throw(SQLException, RuntimeException) 314 { 315 ::osl::MutexGuard aGuard( m_aMutex ); 316 317 executeQuery(sql); 318 319 return m_aSQLIterator.getStatementType() == SQL_STATEMENT_SELECT; 320 } 321 322 // ------------------------------------------------------------------------- 323 324 Reference< XResultSet > SAL_CALL OStatement::executeQuery( const ::rtl::OUString& sql ) throw(SQLException, RuntimeException) 325 { 326 ::osl::MutexGuard aGuard( m_aMutex ); 327 checkDisposed(OStatement_BASE::rBHelper.bDisposed); 328 329 construct(sql); 330 Reference< XResultSet > xRS; 331 OResultSet* pResult = createResultSet(); 332 xRS = pResult; 333 initializeResultSet(pResult); 334 m_xResultSet = Reference<XResultSet>(pResult); 335 336 pResult->OpenImpl(); 337 338 return xRS; 339 } 340 // ------------------------------------------------------------------------- 341 Reference< XConnection > SAL_CALL OStatement::getConnection( ) throw(SQLException, RuntimeException) 342 { 343 return (Reference< XConnection >)m_pConnection; 344 } 345 // ------------------------------------------------------------------------- 346 sal_Int32 SAL_CALL OStatement::executeUpdate( const ::rtl::OUString& sql ) throw(SQLException, RuntimeException) 347 { 348 ::osl::MutexGuard aGuard( m_aMutex ); 349 checkDisposed(OStatement_BASE::rBHelper.bDisposed); 350 351 352 construct(sql); 353 OResultSet* pResult = createResultSet(); 354 Reference< XResultSet > xRS = pResult; 355 initializeResultSet(pResult); 356 pResult->OpenImpl(); 357 358 return pResult->getRowCountResult(); 359 } 360 361 // ----------------------------------------------------------------------------- 362 void SAL_CALL OStatement_Base::disposing(void) 363 { 364 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "file", "Ocke.Janssen@sun.com", "OStatement_Base::disposing" ); 365 if(m_aEvaluateRow.isValid()) 366 { 367 m_aEvaluateRow->get().clear(); 368 m_aEvaluateRow = NULL; 369 } 370 delete m_pEvaluationKeySet; 371 OStatement_BASE::disposing(); 372 } 373 // ----------------------------------------------------------------------------- 374 Reference< ::com::sun::star::beans::XPropertySetInfo > SAL_CALL OStatement_Base::getPropertySetInfo( ) throw(RuntimeException) 375 { 376 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "file", "Ocke.Janssen@sun.com", "OStatement_Base::getPropertySetInfo" ); 377 return ::cppu::OPropertySetHelper::createPropertySetInfo(getInfoHelper()); 378 } 379 // ----------------------------------------------------------------------------- 380 Any SAL_CALL OStatement::queryInterface( const Type & rType ) throw(RuntimeException) 381 { 382 Any aRet = OStatement_XStatement::queryInterface( rType); 383 return aRet.hasValue() ? aRet : OStatement_BASE2::queryInterface( rType); 384 } 385 // ----------------------------------------------------------------------------- 386 OSQLAnalyzer* OStatement_Base::createAnalyzer() 387 { 388 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "file", "Ocke.Janssen@sun.com", "OStatement_Base::createAnalyzer" ); 389 return new OSQLAnalyzer(m_pConnection); 390 } 391 // ----------------------------------------------------------------------------- 392 void OStatement_Base::anylizeSQL() 393 { 394 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "file", "Ocke.Janssen@sun.com", "OStatement_Base::anylizeSQL" ); 395 OSL_ENSURE(m_pSQLAnalyzer,"OResultSet::anylizeSQL: Analyzer isn't set!"); 396 // start analysing the statement 397 m_pSQLAnalyzer->setOrigColumns(m_xColNames); 398 m_pSQLAnalyzer->start(m_pParseTree); 399 400 const OSQLParseNode* pOrderbyClause = m_aSQLIterator.getOrderTree(); 401 if(pOrderbyClause) 402 { 403 OSQLParseNode * pOrderingSpecCommalist = pOrderbyClause->getChild(2); 404 OSL_ENSURE(SQL_ISRULE(pOrderingSpecCommalist,ordering_spec_commalist),"OResultSet: Fehler im Parse Tree"); 405 406 for (sal_uInt32 m = 0; m < pOrderingSpecCommalist->count(); m++) 407 { 408 OSQLParseNode * pOrderingSpec = pOrderingSpecCommalist->getChild(m); 409 OSL_ENSURE(SQL_ISRULE(pOrderingSpec,ordering_spec),"OResultSet: Fehler im Parse Tree"); 410 OSL_ENSURE(pOrderingSpec->count() == 2,"OResultSet: Fehler im Parse Tree"); 411 412 OSQLParseNode * pColumnRef = pOrderingSpec->getChild(0); 413 if(!SQL_ISRULE(pColumnRef,column_ref)) 414 { 415 throw SQLException(); 416 } 417 OSQLParseNode * pAscendingDescending = pOrderingSpec->getChild(1); 418 setOrderbyColumn(pColumnRef,pAscendingDescending); 419 } 420 } 421 } 422 //------------------------------------------------------------------ 423 void OStatement_Base::setOrderbyColumn( OSQLParseNode* pColumnRef, 424 OSQLParseNode* pAscendingDescending) 425 { 426 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "file", "Ocke.Janssen@sun.com", "OStatement_Base::setOrderbyColumn" ); 427 ::rtl::OUString aColumnName; 428 if (pColumnRef->count() == 1) 429 aColumnName = pColumnRef->getChild(0)->getTokenValue(); 430 else if (pColumnRef->count() == 3) 431 { 432 // Nur die Table Range-Variable darf hier vorkommen: 433 // if (!(pColumnRef->getChild(0)->getTokenValue() == aTableRange)) 434 // { 435 // aStatus.Set(SQL_STAT_ERROR, 436 // String::CreateFromAscii("S1000"), 437 // aStatus.CreateErrorMessage(String(SdbResId(STR_STAT_INVALID_RANGE_VAR))), 438 // 0, String() ); 439 // return; 440 // } 441 pColumnRef->getChild(2)->parseNodeToStr( aColumnName, getOwnConnection(), NULL, sal_False, sal_False ); 442 } 443 else 444 { 445 // aStatus.SetStatementTooComplex(); 446 throw SQLException(); 447 } 448 449 Reference<XColumnLocate> xColLocate(m_xColNames,UNO_QUERY); 450 if(!xColLocate.is()) 451 return; 452 // Alles geprueft und wir haben den Namen der Column. 453 // Die wievielte Column ist das? 454 ::vos::ORef<OSQLColumns> aSelectColumns = m_aSQLIterator.getSelectColumns(); 455 ::comphelper::UStringMixEqual aCase; 456 OSQLColumns::Vector::const_iterator aFind = ::connectivity::find(aSelectColumns->get().begin(),aSelectColumns->get().end(),aColumnName,aCase); 457 if ( aFind == aSelectColumns->get().end() ) 458 throw SQLException(); 459 m_aOrderbyColumnNumber.push_back((aFind - aSelectColumns->get().begin()) + 1); 460 461 // Ascending or Descending? 462 m_aOrderbyAscending.push_back((SQL_ISTOKEN(pAscendingDescending,DESC)) ? SQL_DESC : SQL_ASC); 463 } 464 465 // ----------------------------------------------------------------------------- 466 void OStatement_Base::construct(const ::rtl::OUString& sql) throw(SQLException, RuntimeException) 467 { 468 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "file", "Ocke.Janssen@sun.com", "OStatement_Base::construct" ); 469 ::rtl::OUString aErr; 470 m_pParseTree = m_aParser.parseTree(aErr,sql); 471 if(m_pParseTree) 472 { 473 m_aSQLIterator.setParseTree(m_pParseTree); 474 m_aSQLIterator.traverseAll(); 475 const OSQLTables& xTabs = m_aSQLIterator.getTables(); 476 477 // sanity checks 478 if ( xTabs.empty() ) 479 // no tables -> nothing to operate on -> error 480 m_pConnection->throwGenericSQLException(STR_QUERY_NO_TABLE,*this); 481 482 if ( xTabs.size() > 1 || m_aSQLIterator.hasErrors() ) 483 // more than one table -> can't operate on them -> error 484 m_pConnection->throwGenericSQLException(STR_QUERY_MORE_TABLES,*this); 485 486 if ( (m_aSQLIterator.getStatementType() == SQL_STATEMENT_SELECT) && m_aSQLIterator.getSelectColumns()->get().empty() ) 487 // SELECT statement without columns -> error 488 m_pConnection->throwGenericSQLException(STR_QUERY_NO_COLUMN,*this); 489 490 switch(m_aSQLIterator.getStatementType()) 491 { 492 case SQL_STATEMENT_CREATE_TABLE: 493 case SQL_STATEMENT_ODBC_CALL: 494 case SQL_STATEMENT_UNKNOWN: 495 m_pConnection->throwGenericSQLException(STR_QUERY_TOO_COMPLEX,*this); 496 break; 497 default: 498 break; 499 } 500 501 // at this moment we support only one table per select statement 502 Reference< ::com::sun::star::lang::XUnoTunnel> xTunnel(xTabs.begin()->second,UNO_QUERY); 503 if(xTunnel.is()) 504 { 505 if(m_pTable) 506 m_pTable->release(); 507 m_pTable = reinterpret_cast<OFileTable*>(xTunnel->getSomething(OFileTable::getUnoTunnelImplementationId())); 508 if(m_pTable) 509 m_pTable->acquire(); 510 } 511 OSL_ENSURE(m_pTable,"No table!"); 512 if ( m_pTable ) 513 m_xColNames = m_pTable->getColumns(); 514 Reference<XIndexAccess> xNames(m_xColNames,UNO_QUERY); 515 // set the binding of the resultrow 516 m_aRow = new OValueRefVector(xNames->getCount()); 517 (m_aRow->get())[0]->setBound(sal_True); 518 ::std::for_each(m_aRow->get().begin()+1,m_aRow->get().end(),TSetRefBound(sal_False)); 519 520 // set the binding of the resultrow 521 m_aEvaluateRow = new OValueRefVector(xNames->getCount()); 522 523 (m_aEvaluateRow->get())[0]->setBound(sal_True); 524 ::std::for_each(m_aEvaluateRow->get().begin()+1,m_aEvaluateRow->get().end(),TSetRefBound(sal_False)); 525 526 // set the select row 527 m_aSelectRow = new OValueRefVector(m_aSQLIterator.getSelectColumns()->get().size()); 528 ::std::for_each(m_aSelectRow->get().begin(),m_aSelectRow->get().end(),TSetRefBound(sal_True)); 529 530 // create the column mapping 531 createColumnMapping(); 532 533 m_pSQLAnalyzer = createAnalyzer(); 534 535 Reference<XIndexesSupplier> xIndexSup(xTunnel,UNO_QUERY); 536 if(xIndexSup.is()) 537 m_pSQLAnalyzer->setIndexes(xIndexSup->getIndexes()); 538 539 anylizeSQL(); 540 } 541 else 542 throw SQLException(aErr,*this,::rtl::OUString(),0,Any()); 543 } 544 // ----------------------------------------------------------------------------- 545 void OStatement_Base::createColumnMapping() 546 { 547 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "file", "Ocke.Janssen@sun.com", "OStatement_Base::createColumnMapping" ); 548 // initialize the column index map (mapping select columns to table columns) 549 ::vos::ORef<connectivity::OSQLColumns> xColumns = m_aSQLIterator.getSelectColumns(); 550 m_aColMapping.resize(xColumns->get().size() + 1); 551 for (sal_Int32 i=0; i<(sal_Int32)m_aColMapping.size(); ++i) 552 m_aColMapping[i] = i; 553 554 Reference<XIndexAccess> xNames(m_xColNames,UNO_QUERY); 555 // now check which columns are bound 556 OResultSet::setBoundedColumns(m_aRow,m_aSelectRow,xColumns,xNames,sal_True,m_xDBMetaData,m_aColMapping); 557 } 558 // ----------------------------------------------------------------------------- 559 void OStatement_Base::initializeResultSet(OResultSet* _pResult) 560 { 561 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "file", "Ocke.Janssen@sun.com", "OStatement_Base::initializeResultSet" ); 562 GetAssignValues(); 563 564 _pResult->setSqlAnalyzer(m_pSQLAnalyzer); 565 _pResult->setOrderByColumns(m_aOrderbyColumnNumber); 566 _pResult->setOrderByAscending(m_aOrderbyAscending); 567 _pResult->setBindingRow(m_aRow); 568 _pResult->setColumnMapping(m_aColMapping); 569 _pResult->setEvaluationRow(m_aEvaluateRow); 570 _pResult->setAssignValues(m_aAssignValues); 571 _pResult->setSelectRow(m_aSelectRow); 572 573 m_pSQLAnalyzer->bindSelectRow(m_aRow); 574 m_pEvaluationKeySet = m_pSQLAnalyzer->bindEvaluationRow(m_aEvaluateRow); // Werte im Code des Compilers setzen 575 _pResult->setEvaluationKeySet(m_pEvaluationKeySet); 576 } 577 // ----------------------------------------------------------------------------- 578 void OStatement_Base::GetAssignValues() 579 { 580 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "file", "Ocke.Janssen@sun.com", "OStatement_Base::GetAssignValues" ); 581 if (m_pParseTree == NULL) 582 { 583 ::dbtools::throwFunctionSequenceException(*this); 584 return; 585 } 586 587 if (SQL_ISRULE(m_pParseTree,select_statement)) 588 // Keine zu setzenden Werte bei SELECT 589 return; 590 else if (SQL_ISRULE(m_pParseTree,insert_statement)) 591 { 592 // Row fuer die zu setzenden Werte anlegen (Referenz durch new) 593 if(m_aAssignValues.isValid()) 594 m_aAssignValues->get().clear(); 595 sal_Int32 nCount = Reference<XIndexAccess>(m_xColNames,UNO_QUERY)->getCount(); 596 m_aAssignValues = new OAssignValues(nCount); 597 // unbound all 598 ::std::for_each(m_aAssignValues->get().begin()+1,m_aAssignValues->get().end(),TSetRefBound(sal_False)); 599 600 m_aParameterIndexes.resize(nCount+1,SQL_NO_PARAMETER); 601 602 // Liste der Columns-Namen, die in der column_commalist vorkommen (mit ; getrennt): 603 ::std::vector<String> aColumnNameList; 604 605 OSL_ENSURE(m_pParseTree->count() >= 4,"OResultSet: Fehler im Parse Tree"); 606 607 OSQLParseNode * pOptColumnCommalist = m_pParseTree->getChild(3); 608 OSL_ENSURE(pOptColumnCommalist != NULL,"OResultSet: Fehler im Parse Tree"); 609 OSL_ENSURE(SQL_ISRULE(pOptColumnCommalist,opt_column_commalist),"OResultSet: Fehler im Parse Tree"); 610 if (pOptColumnCommalist->count() == 0) 611 { 612 const Sequence< ::rtl::OUString>& aNames = m_xColNames->getElementNames(); 613 const ::rtl::OUString* pBegin = aNames.getConstArray(); 614 const ::rtl::OUString* pEnd = pBegin + aNames.getLength(); 615 for (; pBegin != pEnd; ++pBegin) 616 aColumnNameList.push_back(*pBegin); 617 } 618 else 619 { 620 OSL_ENSURE(pOptColumnCommalist->count() == 3,"OResultSet: Fehler im Parse Tree"); 621 622 OSQLParseNode * pColumnCommalist = pOptColumnCommalist->getChild(1); 623 OSL_ENSURE(pColumnCommalist != NULL,"OResultSet: Fehler im Parse Tree"); 624 OSL_ENSURE(SQL_ISRULE(pColumnCommalist,column_commalist),"OResultSet: Fehler im Parse Tree"); 625 OSL_ENSURE(pColumnCommalist->count() > 0,"OResultSet: Fehler im Parse Tree"); 626 627 // Alle Columns in der column_commalist ... 628 for (sal_uInt32 i = 0; i < pColumnCommalist->count(); i++) 629 { 630 OSQLParseNode * pCol = pColumnCommalist->getChild(i); 631 OSL_ENSURE(pCol != NULL,"OResultSet: Fehler im Parse Tree"); 632 aColumnNameList.push_back(pCol->getTokenValue()); 633 } 634 } 635 if ( aColumnNameList.empty() ) 636 throwFunctionSequenceException(*this); 637 638 // Werte ... 639 OSQLParseNode * pValuesOrQuerySpec = m_pParseTree->getChild(4); 640 OSL_ENSURE(pValuesOrQuerySpec != NULL,"OResultSet: pValuesOrQuerySpec darf nicht NULL sein!"); 641 OSL_ENSURE(SQL_ISRULE(pValuesOrQuerySpec,values_or_query_spec),"OResultSet: ! SQL_ISRULE(pValuesOrQuerySpec,values_or_query_spec)"); 642 OSL_ENSURE(pValuesOrQuerySpec->count() > 0,"OResultSet: pValuesOrQuerySpec->count() <= 0"); 643 644 // nur "VALUES" ist erlaubt ... 645 if (! SQL_ISTOKEN(pValuesOrQuerySpec->getChild(0),VALUES)) 646 throwFunctionSequenceException(*this); 647 648 OSL_ENSURE(pValuesOrQuerySpec->count() == 4,"OResultSet: pValuesOrQuerySpec->count() != 4"); 649 650 // Liste von Werten 651 OSQLParseNode * pInsertAtomCommalist = pValuesOrQuerySpec->getChild(2); 652 OSL_ENSURE(pInsertAtomCommalist != NULL,"OResultSet: pInsertAtomCommalist darf nicht NULL sein!"); 653 OSL_ENSURE(pInsertAtomCommalist->count() > 0,"OResultSet: pInsertAtomCommalist <= 0"); 654 655 String aColumnName; 656 OSQLParseNode * pRow_Value_Const; 657 xub_StrLen nIndex=0; 658 for (sal_uInt32 i = 0; i < pInsertAtomCommalist->count(); i++) 659 { 660 pRow_Value_Const = pInsertAtomCommalist->getChild(i); // row_value_constructor 661 OSL_ENSURE(pRow_Value_Const != NULL,"OResultSet: pRow_Value_Const darf nicht NULL sein!"); 662 if(SQL_ISRULE(pRow_Value_Const,parameter)) 663 { 664 ParseAssignValues(aColumnNameList,pRow_Value_Const,nIndex++); // kann nur ein Columnname vorhanden sein pro Schleife 665 } 666 else if(pRow_Value_Const->isToken()) 667 ParseAssignValues(aColumnNameList,pRow_Value_Const,static_cast<xub_StrLen>(i)); 668 else 669 { 670 if(pRow_Value_Const->count() == aColumnNameList.size()) 671 { 672 for (sal_uInt32 j = 0; j < pRow_Value_Const->count(); ++j) 673 ParseAssignValues(aColumnNameList,pRow_Value_Const->getChild(j),nIndex++); 674 } 675 else 676 throwFunctionSequenceException(*this); 677 } 678 } 679 } 680 else if (SQL_ISRULE(m_pParseTree,update_statement_searched)) 681 { 682 if(m_aAssignValues.isValid()) 683 m_aAssignValues->get().clear(); 684 sal_Int32 nCount = Reference<XIndexAccess>(m_xColNames,UNO_QUERY)->getCount(); 685 m_aAssignValues = new OAssignValues(nCount); 686 // unbound all 687 ::std::for_each(m_aAssignValues->get().begin()+1,m_aAssignValues->get().end(),TSetRefBound(sal_False)); 688 689 m_aParameterIndexes.resize(nCount+1,SQL_NO_PARAMETER); 690 691 OSL_ENSURE(m_pParseTree->count() >= 4,"OResultSet: Fehler im Parse Tree"); 692 693 OSQLParseNode * pAssignmentCommalist = m_pParseTree->getChild(3); 694 OSL_ENSURE(pAssignmentCommalist != NULL,"OResultSet: pAssignmentCommalist == NULL"); 695 OSL_ENSURE(SQL_ISRULE(pAssignmentCommalist,assignment_commalist),"OResultSet: Fehler im Parse Tree"); 696 OSL_ENSURE(pAssignmentCommalist->count() > 0,"OResultSet: pAssignmentCommalist->count() <= 0"); 697 698 // Alle Zuweisungen (Kommaliste) bearbeiten ... 699 ::std::vector< String> aList(1); 700 for (sal_uInt32 i = 0; i < pAssignmentCommalist->count(); i++) 701 { 702 OSQLParseNode * pAssignment = pAssignmentCommalist->getChild(i); 703 OSL_ENSURE(pAssignment != NULL,"OResultSet: pAssignment == NULL"); 704 OSL_ENSURE(SQL_ISRULE(pAssignment,assignment),"OResultSet: Fehler im Parse Tree"); 705 OSL_ENSURE(pAssignment->count() == 3,"OResultSet: pAssignment->count() != 3"); 706 707 OSQLParseNode * pCol = pAssignment->getChild(0); 708 OSL_ENSURE(pCol != NULL,"OResultSet: pCol == NULL"); 709 710 OSQLParseNode * pComp = pAssignment->getChild(1); 711 OSL_ENSURE(pComp != NULL,"OResultSet: pComp == NULL"); 712 OSL_ENSURE(pComp->getNodeType() == SQL_NODE_EQUAL,"OResultSet: pComp->getNodeType() != SQL_NODE_COMPARISON"); 713 if (pComp->getTokenValue().toChar() != '=') 714 { 715 // aStatus.SetInvalidStatement(); 716 throwFunctionSequenceException(*this); 717 } 718 719 OSQLParseNode * pVal = pAssignment->getChild(2); 720 OSL_ENSURE(pVal != NULL,"OResultSet: pVal == NULL"); 721 aList[0] = pCol->getTokenValue(); 722 ParseAssignValues(aList,pVal,0); 723 } 724 725 } 726 } 727 // ------------------------------------------------------------------------- 728 void OStatement_Base::ParseAssignValues(const ::std::vector< String>& aColumnNameList,OSQLParseNode* pRow_Value_Constructor_Elem,xub_StrLen nIndex) 729 { 730 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "file", "Ocke.Janssen@sun.com", "OStatement_Base::ParseAssignValues" ); 731 OSL_ENSURE(nIndex <= aColumnNameList.size(),"SdbFileCursor::ParseAssignValues: nIndex > aColumnNameList.GetTokenCount()"); 732 String aColumnName(aColumnNameList[nIndex]); 733 OSL_ENSURE(aColumnName.Len() > 0,"OResultSet: Column-Name nicht gefunden"); 734 OSL_ENSURE(pRow_Value_Constructor_Elem != NULL,"OResultSet: pRow_Value_Constructor_Elem darf nicht NULL sein!"); 735 736 if (pRow_Value_Constructor_Elem->getNodeType() == SQL_NODE_STRING || 737 pRow_Value_Constructor_Elem->getNodeType() == SQL_NODE_INTNUM || 738 pRow_Value_Constructor_Elem->getNodeType() == SQL_NODE_APPROXNUM) 739 { 740 // Wert setzen: 741 SetAssignValue(aColumnName, pRow_Value_Constructor_Elem->getTokenValue()); 742 } 743 else if (SQL_ISTOKEN(pRow_Value_Constructor_Elem,NULL)) 744 { 745 // NULL setzen 746 SetAssignValue(aColumnName, String(), sal_True); 747 } 748 else if (SQL_ISRULE(pRow_Value_Constructor_Elem,parameter)) 749 parseParamterElem(aColumnName,pRow_Value_Constructor_Elem); 750 else 751 { 752 // aStatus.SetStatementTooComplex(); 753 throwFunctionSequenceException(*this); 754 } 755 } 756 //------------------------------------------------------------------ 757 void OStatement_Base::SetAssignValue(const String& aColumnName, 758 const String& aValue, 759 sal_Bool bSetNull, 760 sal_uInt32 nParameter) 761 { 762 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "file", "Ocke.Janssen@sun.com", "OStatement_Base::SetAssignValue" ); 763 Reference<XPropertySet> xCol; 764 m_xColNames->getByName(aColumnName) >>= xCol; 765 sal_Int32 nId = Reference<XColumnLocate>(m_xColNames,UNO_QUERY)->findColumn(aColumnName); 766 // Kommt diese Column ueberhaupt in der Datei vor? 767 768 if (!xCol.is()) 769 { 770 // Diese Column gibt es nicht! 771 // aStatus.Set(SQL_STAT_ERROR, 772 // String::CreateFromAscii("S0022"), 773 // aStatus.CreateErrorMessage(String(SdbResId(STR_STAT_COLUMN_NOT_FOUND))), 774 // 0, String() ); 775 throwFunctionSequenceException(*this); 776 } 777 778 // Value an die Row mit den zuzuweisenden Werten binden: 779 // const ODbVariantRef& xValue = (*aAssignValues)[pFileColumn->GetId()]; 780 781 // Alles geprueft und wir haben den Namen der Column. 782 // Jetzt eine Value allozieren, den Wert setzen und die Value an die Row binden. 783 if (bSetNull) 784 (m_aAssignValues->get())[nId]->setNull(); 785 else 786 { 787 switch (::comphelper::getINT32(xCol->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_TYPE)))) 788 { 789 // Kriterium je nach Typ als String oder double in die Variable packen ... 790 case DataType::CHAR: 791 case DataType::VARCHAR: 792 case DataType::LONGVARCHAR: 793 *(m_aAssignValues->get())[nId] = ORowSetValue(aValue); 794 // Zeichensatz ist bereits konvertiert, da ja das gesamte Statement konvertiert wurde 795 break; 796 797 case DataType::BIT: 798 { 799 if (aValue.EqualsIgnoreCaseAscii("TRUE") || aValue.GetChar(0) == '1') 800 *(m_aAssignValues->get())[nId] = sal_True; 801 else if (aValue.EqualsIgnoreCaseAscii("FALSE") || aValue.GetChar(0) == '0') 802 *(m_aAssignValues->get())[nId] = sal_False; 803 else 804 { 805 // aStatus.Set(SQL_STAT_ERROR); // nyi: genauer! 806 throwFunctionSequenceException(*this); 807 } 808 } 809 break; 810 case DataType::TINYINT: 811 case DataType::SMALLINT: 812 case DataType::INTEGER: 813 case DataType::DECIMAL: 814 case DataType::NUMERIC: 815 case DataType::REAL: 816 case DataType::DOUBLE: 817 case DataType::DATE: 818 case DataType::TIME: 819 case DataType::TIMESTAMP: 820 { 821 *(m_aAssignValues->get())[nId] = ORowSetValue(aValue); // .ToDouble 822 // try 823 // { 824 // double n = xValue->toDouble(); 825 // xValue->setDouble(n); 826 // } 827 // catch ( ... ) 828 // { 829 // aStatus.SetDriverNotCapableError(); 830 // } 831 } break; 832 default: 833 throwFunctionSequenceException(*this); 834 } 835 } 836 837 // Parameter-Nr. merken (als User Data) 838 // SQL_NO_PARAMETER = kein Parameter. 839 m_aAssignValues->setParameterIndex(nId,nParameter); 840 if(nParameter != SQL_NO_PARAMETER) 841 m_aParameterIndexes[nParameter] = nId; 842 } 843 // ----------------------------------------------------------------------------- 844 void OStatement_Base::parseParamterElem(const String& /*_sColumnName*/,OSQLParseNode* /*pRow_Value_Constructor_Elem*/) 845 { 846 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "file", "Ocke.Janssen@sun.com", "OStatement_Base::parseParamterElem" ); 847 // do nothing here 848 } 849 // ============================================================================= 850 } // namespace file 851 // ============================================================================= 852 }// namespace connectivity 853 // ----------------------------------------------------------------------------- 854