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_dbaccess.hxx" 30 #ifndef DBAUI_QUERYDESIGNVIEW_HXX 31 #include "QueryDesignView.hxx" 32 #endif 33 #ifndef DBAUI_QUERYTABLEVIEW_HXX 34 #include "QueryTableView.hxx" 35 #endif 36 #ifndef DBAUI_QUERY_TABLEWINDOW_HXX 37 #include "QTableWindow.hxx" 38 #endif 39 #ifndef _SV_TOOLBOX_HXX 40 #include <vcl/toolbox.hxx> 41 #endif 42 #ifndef DBAUI_QUERYCONTROLLER_HXX 43 #include "querycontroller.hxx" 44 #endif 45 #ifndef _SV_SPLIT_HXX 46 #include <vcl/split.hxx> 47 #endif 48 #ifndef _UNDO_HXX 49 #include <svl/undo.hxx> 50 #endif 51 #ifndef TOOLS_DIAGNOSE_EX_H 52 #include <tools/diagnose_ex.h> 53 #endif 54 #ifndef DBAUI_QYDLGTAB_HXX 55 #include "adtabdlg.hxx" 56 #endif 57 #ifndef _SV_SVAPP_HXX 58 #include <vcl/svapp.hxx> 59 #endif 60 #ifndef _SV_COMBOBOX_HXX 61 #include <vcl/combobox.hxx> 62 #endif 63 #ifndef _SV_MSGBOX_HXX 64 #include <vcl/msgbox.hxx> 65 #endif 66 #ifndef DBACCESS_UI_BROWSER_ID_HXX 67 #include "browserids.hxx" 68 #endif 69 #ifndef DBAUI_QUERYDESIGN_OSELECTIONBROWSEBOX_HXX 70 #include "SelectionBrowseBox.hxx" 71 #endif 72 #ifndef _DBU_QRY_HRC_ 73 #include "dbu_qry.hrc" 74 #endif 75 #ifndef _UTL_CONFIGMGR_HXX_ 76 #include <unotools/configmgr.hxx> 77 #endif 78 #ifndef _COMPHELPER_TYPES_HXX_ 79 #include <comphelper/types.hxx> 80 #endif 81 #ifndef _CONNECTIVITY_DBTOOLS_HXX_ 82 #include <connectivity/dbtools.hxx> 83 #endif 84 #ifndef _DBHELPER_DBEXCEPTION_HXX_ 85 #include <connectivity/dbexception.hxx> 86 #endif 87 #ifndef _COM_SUN_STAR_I18N_XLOCALEDATA_HPP_ 88 #include <com/sun/star/i18n/XLocaleData.hpp> 89 #endif 90 #ifndef _COM_SUN_STAR_SDBC_DATATYPE_HPP_ 91 #include <com/sun/star/sdbc/DataType.hpp> 92 #endif 93 #ifndef _COM_SUN_STAR_CONTAINER_XNAMEACCESS_HPP_ 94 #include <com/sun/star/container/XNameAccess.hpp> 95 #endif 96 #ifndef _COM_SUN_STAR_SDBC_COLUMNVALUE_HPP_ 97 #include <com/sun/star/sdbc/ColumnValue.hpp> 98 #endif 99 #ifndef _CONNECTIVITY_PCOLUMN_HXX_ 100 #include <connectivity/PColumn.hxx> 101 #endif 102 #ifndef DBAUI_QUERYTABLECONNECTION_HXX 103 #include "QTableConnection.hxx" 104 #endif 105 #ifndef DBAUI_CONNECTIONLINE_HXX 106 #include "ConnectionLine.hxx" 107 #endif 108 #ifndef DBAUI_CONNECTIONLINEDATA_HXX 109 #include "ConnectionLineData.hxx" 110 #endif 111 #ifndef DBAUI_QTABLECONNECTIONDATA_HXX 112 #include "QTableConnectionData.hxx" 113 #endif 114 #ifndef DBACCESS_SHARED_DBUSTRINGS_HRC 115 #include "dbustrings.hrc" 116 #endif 117 #ifndef _COMPHELPER_EXTRACT_HXX_ 118 #include <comphelper/extract.hxx> 119 #endif 120 #ifndef DBAUI_TOOLS_HXX 121 #include "UITools.hxx" 122 #endif 123 #ifndef DBAUI_QUERYCONTAINERWINDOW_HXX 124 #include "querycontainerwindow.hxx" 125 #endif 126 #ifndef DBAUI_QUERYTABLEVIEW_HXX 127 #include "QueryTableView.hxx" 128 #endif 129 #ifndef _DBAUI_SQLMESSAGE_HXX_ 130 #include "sqlmessage.hxx" 131 #endif 132 #ifndef INCLUDED_SVTOOLS_SYSLOCALE_HXX 133 #include <unotools/syslocale.hxx> 134 #endif 135 136 using namespace ::dbaui; 137 using namespace ::utl; 138 using namespace ::connectivity; 139 using namespace ::dbtools; 140 using namespace ::com::sun::star::uno; 141 using namespace ::com::sun::star::lang; 142 using namespace ::com::sun::star::i18n; 143 using namespace ::com::sun::star::sdbc; 144 using namespace ::com::sun::star::beans; 145 using namespace ::com::sun::star::container; 146 147 #define SQL_ISRULEOR2(pParseNode, e1,e2) ((pParseNode)->isRule() && (\ 148 (pParseNode)->getRuleID() == OSQLParser::RuleID(OSQLParseNode::e1) || \ 149 (pParseNode)->getRuleID() == OSQLParser::RuleID(OSQLParseNode::e2))) 150 151 // here we define our functions used in the anonymous namespace to get our header file smaller 152 // please look at the book LargeScale C++ to know why 153 namespace 154 { 155 static const ::rtl::OUString C_AND = ::rtl::OUString::createFromAscii(" AND "); 156 static const ::rtl::OUString C_OR = ::rtl::OUString::createFromAscii(" OR "); 157 158 // forward declarations 159 sal_Bool InsertJoin( const OQueryDesignView* _pView, 160 const ::connectivity::OSQLParseNode *pNode); 161 162 SqlParseError InstallFields(OQueryDesignView* _pView, 163 const ::connectivity::OSQLParseNode* pNode, 164 OJoinTableView::OTableWindowMap* pTabList ); 165 166 SqlParseError GetGroupCriteria( OQueryDesignView* _pView, 167 OSelectionBrowseBox* _pSelectionBrw, 168 const ::connectivity::OSQLParseNode* pSelectRoot ); 169 170 SqlParseError GetHavingCriteria(OQueryDesignView* _pView, 171 OSelectionBrowseBox* _pSelectionBrw, 172 const ::connectivity::OSQLParseNode* pSelectRoot, 173 sal_uInt16& rLevel ); 174 175 SqlParseError GetOrderCriteria( OQueryDesignView* _pView, 176 OSelectionBrowseBox* _pSelectionBrw, 177 const ::connectivity::OSQLParseNode* pParseRoot ); 178 179 SqlParseError AddFunctionCondition(OQueryDesignView* _pView, 180 OSelectionBrowseBox* _pSelectionBrw, 181 const ::connectivity::OSQLParseNode * pCondition, 182 const sal_uInt16 nLevel, 183 sal_Bool bHaving, 184 bool _bAddOrOnOneLine); 185 186 //------------------------------------------------------------------------------ 187 ::rtl::OUString quoteTableAlias(sal_Bool _bQuote, const ::rtl::OUString& _sAliasName, const ::rtl::OUString& _sQuote) 188 { 189 ::rtl::OUString sRet; 190 if ( _bQuote && _sAliasName.getLength() ) 191 { 192 sRet = ::dbtools::quoteName(_sQuote,_sAliasName); 193 const static ::rtl::OUString sTableSeparater('.'); 194 sRet += sTableSeparater; 195 } 196 return sRet; 197 } 198 //------------------------------------------------------------------------------ 199 ::rtl::OUString getTableRange(const OQueryDesignView* _pView,const ::connectivity::OSQLParseNode* _pTableRef) 200 { 201 Reference< XConnection> xConnection = static_cast<OQueryController&>(_pView->getController()).getConnection(); 202 ::rtl::OUString sTableRange; 203 if ( _pTableRef ) 204 { 205 sTableRange = ::connectivity::OSQLParseNode::getTableRange(_pTableRef); 206 if ( !sTableRange.getLength() ) 207 _pTableRef->parseNodeToStr(sTableRange,xConnection,NULL,sal_False,sal_False); 208 } 209 return sTableRange; 210 } 211 //------------------------------------------------------------------------------ 212 void insertConnection(const OQueryDesignView* _pView,const EJoinType& _eJoinType,OTableFieldDescRef _aDragLeft,OTableFieldDescRef _aDragRight,bool _bNatural = false) 213 { 214 OQueryTableView* pTableView = static_cast<OQueryTableView*>(_pView->getTableView()); 215 OQueryTableConnection* pConn = static_cast<OQueryTableConnection*>( pTableView->GetTabConn(static_cast<OTableWindow*>(_aDragLeft->GetTabWindow()),static_cast<OTableWindow*>(_aDragRight->GetTabWindow()),true)); 216 217 if ( !pConn ) 218 { 219 OQueryTableConnectionData* pInfoData = new OQueryTableConnectionData(); 220 TTableConnectionData::value_type aInfoData(pInfoData); 221 pInfoData->InitFromDrag(_aDragLeft, _aDragRight); 222 pInfoData->SetJoinType(_eJoinType); 223 224 if ( _bNatural ) 225 { 226 aInfoData->ResetConnLines(); 227 pInfoData->setNatural(_bNatural); 228 try 229 { 230 Reference<XNameAccess> xReferencedTableColumns(aInfoData->getReferencedTable()->getColumns()); 231 Sequence< ::rtl::OUString> aSeq = aInfoData->getReferencingTable()->getColumns()->getElementNames(); 232 const ::rtl::OUString* pIter = aSeq.getConstArray(); 233 const ::rtl::OUString* pEnd = pIter + aSeq.getLength(); 234 for(;pIter != pEnd;++pIter) 235 { 236 if ( xReferencedTableColumns->hasByName(*pIter) ) 237 aInfoData->AppendConnLine(*pIter,*pIter); 238 } 239 } 240 catch( const Exception& ) 241 { 242 DBG_UNHANDLED_EXCEPTION(); 243 } 244 } 245 246 OQueryTableConnection aInfo(pTableView, aInfoData); 247 // da ein OQueryTableConnection-Objekt nie den Besitz der uebergebenen Daten uebernimmt, sondern sich nur den Zeiger merkt, 248 // ist dieser Zeiger auf eine lokale Variable hier unkritisch, denn aInfoData und aInfo haben die selbe Lebensdauer 249 pTableView->NotifyTabConnection( aInfo ); 250 } 251 else 252 { 253 ::rtl::OUString aSourceFieldName(_aDragLeft->GetField()); 254 ::rtl::OUString aDestFieldName(_aDragRight->GetField()); 255 // the connection could point on the other side 256 if(pConn->GetSourceWin() == _aDragRight->GetTabWindow()) 257 { 258 ::rtl::OUString aTmp(aSourceFieldName); 259 aSourceFieldName = aDestFieldName; 260 aDestFieldName = aTmp; 261 } 262 pConn->GetData()->AppendConnLine( aSourceFieldName,aDestFieldName); 263 pConn->UpdateLineList(); 264 // Modified-Flag 265 // SetModified(); 266 // und neu zeichnen 267 pConn->RecalcLines(); 268 // fuer das unten folgende Invalidate muss ich dieser neuen Connection erst mal die Moeglichkeit geben, 269 // ihr BoundingRect zu ermitteln 270 pConn->InvalidateConnection(); 271 } 272 } 273 //------------------------------------------------------------------------------ 274 ::rtl::OUString ParseCondition( OQueryController& rController 275 ,const ::connectivity::OSQLParseNode* pCondition 276 ,const ::rtl::OUString _sDecimal 277 ,const ::com::sun::star::lang::Locale& _rLocale 278 ,sal_uInt32 _nStartIndex) 279 { 280 ::rtl::OUString aCondition; 281 Reference< XConnection> xConnection = rController.getConnection(); 282 if ( xConnection.is() ) 283 { 284 sal_uInt32 nCount = pCondition->count(); 285 for(sal_uInt32 i = _nStartIndex ; i < nCount ; ++i) 286 pCondition->getChild(i)->parseNodeToPredicateStr(aCondition, 287 xConnection, 288 rController.getNumberFormatter(), 289 _rLocale, 290 static_cast<sal_Char>(_sDecimal.toChar()), 291 &rController.getParser().getContext()); 292 } 293 return aCondition; 294 } 295 //------------------------------------------------------------------------------ 296 SqlParseError FillOuterJoins(OQueryDesignView* _pView, 297 const ::connectivity::OSQLParseNode* pTableRefList) 298 { 299 SqlParseError eErrorCode = eOk; 300 sal_uInt32 nCount = pTableRefList->count(); 301 sal_Bool bError = sal_False; 302 for (sal_uInt32 i=0; !bError && i < nCount; ++i) 303 { 304 const ::connectivity::OSQLParseNode* pParseNode = pTableRefList->getChild(i); 305 const ::connectivity::OSQLParseNode* pJoinNode = NULL; 306 307 if ( SQL_ISRULE( pParseNode, qualified_join ) || SQL_ISRULE( pParseNode, joined_table ) || SQL_ISRULE( pParseNode, cross_union ) ) 308 pJoinNode = pParseNode; 309 else if( SQL_ISRULE(pParseNode,table_ref) 310 && pParseNode->count() == 4 ) // '{' SQL_TOKEN_OJ joined_table '}' 311 pJoinNode = pParseNode->getChild(2); 312 313 if ( pJoinNode ) 314 { 315 if ( !InsertJoin(_pView,pJoinNode) ) 316 bError = sal_True; 317 } 318 } 319 // check if error occured 320 if ( bError ) 321 eErrorCode = eIllegalJoin; 322 323 return eErrorCode; 324 } 325 // ----------------------------------------------------------------------------- 326 327 /** FillDragInfo fills the field description out of the table 328 */ 329 //------------------------------------------------------------------------------ 330 SqlParseError FillDragInfo( const OQueryDesignView* _pView, 331 const ::connectivity::OSQLParseNode* pColumnRef, 332 OTableFieldDescRef& _rDragInfo) 333 { 334 SqlParseError eErrorCode = eOk; 335 336 sal_Bool bErg = sal_False; 337 338 ::rtl::OUString aTableRange,aColumnName; 339 sal_uInt16 nCntAccount; 340 ::connectivity::OSQLParseTreeIterator& rParseIter = static_cast<OQueryController&>(_pView->getController()).getParseIterator(); 341 rParseIter.getColumnRange( pColumnRef, aColumnName, aTableRange ); 342 343 if ( aTableRange.getLength() ) 344 { 345 OQueryTableWindow* pSTW = static_cast<OQueryTableView*>(_pView->getTableView())->FindTable( aTableRange ); 346 bErg = (pSTW && pSTW->ExistsField( aColumnName, _rDragInfo ) ); 347 } 348 if ( !bErg ) 349 { 350 bErg = static_cast<OQueryTableView*>(_pView->getTableView())->FindTableFromField(aColumnName, _rDragInfo, nCntAccount); 351 if ( !bErg ) 352 bErg = _pView->HasFieldByAliasName(aColumnName, _rDragInfo); 353 } 354 if ( !bErg ) 355 { 356 eErrorCode = eColumnNotFound; 357 String sError(ModuleRes(STR_QRY_COLUMN_NOT_FOUND)); 358 sError.SearchAndReplaceAscii("$name$",aColumnName); 359 _pView->getController().appendError( sError ); 360 361 try 362 { 363 Reference<XDatabaseMetaData> xMeta = _pView->getController().getConnection()->getMetaData(); 364 if ( xMeta.is() && xMeta->supportsMixedCaseQuotedIdentifiers() ) 365 _pView->getController().appendError( String( ModuleRes( STR_QRY_CHECK_CASESENSITIVE ) ) ); 366 } 367 catch(Exception&) 368 { 369 } 370 } 371 372 return eErrorCode; 373 } 374 //------------------------------------------------------------------------------ 375 ::rtl::OUString BuildJoinCriteria( const Reference< XConnection>& _xConnection, 376 OConnectionLineDataVec* pLineDataList, 377 OQueryTableConnectionData* pData) 378 { 379 ::rtl::OUStringBuffer aCondition; 380 if ( _xConnection.is() ) 381 { 382 OConnectionLineDataVec::iterator aIter = pLineDataList->begin(); 383 OConnectionLineDataVec::iterator aEnd = pLineDataList->end(); 384 try 385 { 386 const Reference< XDatabaseMetaData > xMetaData = _xConnection->getMetaData(); 387 const ::rtl::OUString aQuote = xMetaData->getIdentifierQuoteString(); 388 const ::rtl::OUString sEqual(RTL_CONSTASCII_USTRINGPARAM(" = ")); 389 390 for(;aIter != aEnd;++aIter) 391 { 392 OConnectionLineDataRef pLineData = *aIter; 393 if(aCondition.getLength()) 394 aCondition.append(C_AND); 395 aCondition.append(quoteTableAlias(sal_True,pData->GetAliasName(JTCS_FROM),aQuote)); 396 aCondition.append(::dbtools::quoteName(aQuote, pLineData->GetFieldName(JTCS_FROM) )); 397 aCondition.append(sEqual); 398 aCondition.append(quoteTableAlias(sal_True,pData->GetAliasName(JTCS_TO),aQuote)); 399 aCondition.append(::dbtools::quoteName(aQuote, pLineData->GetFieldName(JTCS_TO) )); 400 } 401 } 402 catch(SQLException&) 403 { 404 OSL_ASSERT(!"Failure while building Join criteria!"); 405 } 406 } 407 408 return aCondition.makeStringAndClear(); 409 } 410 //------------------------------------------------------------------------------ 411 /** JoinCycle looks for a join cycle and append it to the string 412 @param _xConnection the connection 413 @param _pEntryConn the table connection which holds the data 414 @param _pEntryTabTo the corresponding table window 415 @param _rJoin the String which will contain the resulting string 416 */ 417 void JoinCycle( const Reference< XConnection>& _xConnection, 418 OQueryTableConnection* _pEntryConn, 419 const OQueryTableWindow* _pEntryTabTo, 420 ::rtl::OUString& _rJoin ) 421 { 422 OSL_ENSURE(_pEntryConn,"TableConnection can not be null!"); 423 424 OQueryTableConnectionData* pData = static_cast< OQueryTableConnectionData*>(_pEntryConn->GetData().get()); 425 if ( pData->GetJoinType() != INNER_JOIN && _pEntryTabTo->ExistsAVisitedConn() ) 426 { 427 sal_Bool bBrace = sal_False; 428 if(_rJoin.getLength() && _rJoin.lastIndexOf(')') == (_rJoin.getLength()-1)) 429 { 430 bBrace = sal_True; 431 _rJoin = _rJoin.replaceAt(_rJoin.getLength()-1,1,::rtl::OUString(' ')); 432 } 433 (_rJoin += C_AND) += BuildJoinCriteria(_xConnection,pData->GetConnLineDataList(),pData); 434 if(bBrace) 435 _rJoin += ::rtl::OUString(')'); 436 _pEntryConn->SetVisited(sal_True); 437 } 438 } 439 //------------------------------------------------------------------------------ 440 ::rtl::OUString BuildTable( const Reference< XConnection>& _xConnection, 441 const OQueryTableWindow* pEntryTab, 442 bool _bForce = false 443 ) 444 { 445 ::rtl::OUString aDBName(pEntryTab->GetComposedName()); 446 447 // Reference< XConnection> xConnection = static_cast<OQueryController&>(_pView->getController()).getConnection(); 448 if( _xConnection.is() ) 449 { 450 try 451 { 452 Reference< XDatabaseMetaData > xMetaData = _xConnection->getMetaData(); 453 454 ::rtl::OUString sCatalog, sSchema, sTable; 455 ::dbtools::qualifiedNameComponents( xMetaData, aDBName, sCatalog, sSchema, sTable, ::dbtools::eInDataManipulation ); 456 ::rtl::OUString aTableListStr = ::dbtools::composeTableNameForSelect( _xConnection, sCatalog, sSchema, sTable ); 457 458 ::rtl::OUString aQuote = xMetaData->getIdentifierQuoteString(); 459 if ( _bForce || isAppendTableAliasEnabled( _xConnection ) || pEntryTab->GetAliasName() != aDBName ) 460 { 461 aTableListStr += ::rtl::OUString::createFromAscii(" "); 462 if ( generateAsBeforeTableAlias( _xConnection ) ) 463 aTableListStr += ::rtl::OUString::createFromAscii("AS "); 464 aTableListStr += ::dbtools::quoteName( aQuote, pEntryTab->GetAliasName() ); 465 } 466 aDBName = aTableListStr; 467 } 468 catch(const SQLException&) 469 { 470 DBG_UNHANDLED_EXCEPTION(); 471 } 472 } 473 return aDBName; 474 } 475 //------------------------------------------------------------------------------ 476 ::rtl::OUString BuildJoin( const Reference< XConnection>& _xConnection, 477 const ::rtl::OUString& rLh, 478 const ::rtl::OUString& rRh, 479 OQueryTableConnectionData* pData) 480 { 481 482 String aErg(rLh); 483 if ( pData->isNatural() && pData->GetJoinType() != CROSS_JOIN ) 484 aErg.AppendAscii(" NATURAL "); 485 switch(pData->GetJoinType()) 486 { 487 case LEFT_JOIN: 488 aErg.AppendAscii(" LEFT OUTER "); 489 break; 490 case RIGHT_JOIN: 491 aErg.AppendAscii(" RIGHT OUTER "); 492 break; 493 case CROSS_JOIN: 494 OSL_ENSURE(!pData->isNatural(),"OQueryDesignView::BuildJoin: This should not happen!"); 495 aErg.AppendAscii(" CROSS "); 496 break; 497 case INNER_JOIN: 498 OSL_ENSURE(pData->isNatural(),"OQueryDesignView::BuildJoin: This should not happen!"); 499 aErg.AppendAscii(" INNER "); 500 break; 501 default: 502 aErg.AppendAscii(" FULL OUTER "); 503 break; 504 } 505 aErg.AppendAscii("JOIN "); 506 aErg += String(rRh); 507 if ( CROSS_JOIN != pData->GetJoinType() && !pData->isNatural() ) 508 { 509 aErg.AppendAscii(" ON "); 510 aErg += String(BuildJoinCriteria(_xConnection,pData->GetConnLineDataList(),pData)); 511 } 512 513 return aErg; 514 } 515 //------------------------------------------------------------------------------ 516 ::rtl::OUString BuildJoin( const Reference< XConnection>& _xConnection, 517 OQueryTableWindow* pLh, 518 OQueryTableWindow* pRh, 519 OQueryTableConnectionData* pData 520 ) 521 { 522 bool bForce = pData->GetJoinType() == CROSS_JOIN || pData->isNatural(); 523 return BuildJoin(_xConnection,BuildTable(_xConnection,pLh,bForce),BuildTable(_xConnection,pRh,bForce),pData); 524 } 525 //------------------------------------------------------------------------------ 526 ::rtl::OUString BuildJoin( const Reference< XConnection>& _xConnection, 527 const ::rtl::OUString &rLh, 528 OQueryTableWindow* pRh, 529 OQueryTableConnectionData* pData 530 ) 531 { 532 return BuildJoin(_xConnection,rLh,BuildTable(_xConnection,pRh),pData); 533 } 534 //------------------------------------------------------------------------------ 535 ::rtl::OUString BuildJoin( const Reference< XConnection>& _xConnection, 536 OQueryTableWindow* pLh, 537 const ::rtl::OUString &rRh, 538 OQueryTableConnectionData* pData 539 ) 540 { 541 return BuildJoin(_xConnection,BuildTable(_xConnection,pLh),rRh,pData); 542 } 543 //------------------------------------------------------------------------------ 544 void GetNextJoin( const Reference< XConnection>& _xConnection, 545 OQueryTableConnection* pEntryConn, 546 OQueryTableWindow* pEntryTabTo, 547 ::rtl::OUString &aJoin) 548 { 549 OQueryTableConnectionData* pEntryConnData = static_cast<OQueryTableConnectionData*>(pEntryConn->GetData().get()); 550 if ( pEntryConnData->GetJoinType() == INNER_JOIN && !pEntryConnData->isNatural() ) 551 return; 552 553 // Reference< XConnection> xConnection = static_cast<OQueryController&>(_pView->getController()).getConnection(); 554 555 if(!aJoin.getLength()) 556 { 557 OQueryTableWindow* pEntryTabFrom = static_cast<OQueryTableWindow*>(pEntryConn->GetSourceWin()); 558 aJoin = BuildJoin(_xConnection,pEntryTabFrom,pEntryTabTo,pEntryConnData); 559 } 560 else if(pEntryTabTo == pEntryConn->GetDestWin()) 561 { 562 aJoin = BuildJoin(_xConnection,aJoin,pEntryTabTo,pEntryConnData); 563 } 564 else if(pEntryTabTo == pEntryConn->GetSourceWin()) 565 { 566 aJoin = BuildJoin(_xConnection,pEntryTabTo,aJoin,pEntryConnData); 567 } 568 569 pEntryConn->SetVisited(sal_True); 570 571 // first search for the "to" window 572 const ::std::vector<OTableConnection*>* pConnections = pEntryConn->GetParent()->getTableConnections(); 573 ::std::vector<OTableConnection*>::const_iterator aIter = pConnections->begin(); 574 ::std::vector<OTableConnection*>::const_iterator aEnd = pConnections->end(); 575 for(;aIter != aEnd;++aIter) 576 { 577 OQueryTableConnection* pNext = static_cast<OQueryTableConnection*>(*aIter); 578 if(!pNext->IsVisited() && (pNext->GetSourceWin() == pEntryTabTo || pNext->GetDestWin() == pEntryTabTo)) 579 { 580 OQueryTableWindow* pEntryTab = pNext->GetSourceWin() == pEntryTabTo ? static_cast<OQueryTableWindow*>(pNext->GetDestWin()) : static_cast<OQueryTableWindow*>(pNext->GetSourceWin()); 581 // exists there a connection to a OQueryTableWindow that holds a connection that has been already visited 582 JoinCycle(_xConnection,pNext,pEntryTab,aJoin); 583 if(!pNext->IsVisited()) 584 GetNextJoin(_xConnection,pNext,pEntryTab,aJoin); 585 } 586 } 587 588 // when nothing found found look for the "from" window 589 if(aIter == aEnd) 590 { 591 OQueryTableWindow* pEntryTabFrom = static_cast<OQueryTableWindow*>(pEntryConn->GetSourceWin()); 592 aIter = pConnections->begin(); 593 for(;aIter != aEnd;++aIter) 594 { 595 OQueryTableConnection* pNext = static_cast<OQueryTableConnection*>(*aIter); 596 if(!pNext->IsVisited() && (pNext->GetSourceWin() == pEntryTabFrom || pNext->GetDestWin() == pEntryTabFrom)) 597 { 598 OQueryTableWindow* pEntryTab = pNext->GetSourceWin() == pEntryTabFrom ? static_cast<OQueryTableWindow*>(pNext->GetDestWin()) : static_cast<OQueryTableWindow*>(pNext->GetSourceWin()); 599 // exists there a connection to a OQueryTableWindow that holds a connection that has been already visited 600 JoinCycle(_xConnection,pNext,pEntryTab,aJoin); 601 if(!pNext->IsVisited()) 602 GetNextJoin(_xConnection,pNext,pEntryTab,aJoin); 603 } 604 } 605 } 606 } 607 //------------------------------------------------------------------------------ 608 SqlParseError InsertJoinConnection( const OQueryDesignView* _pView, 609 const ::connectivity::OSQLParseNode *pNode, 610 const EJoinType& _eJoinType, 611 const ::connectivity::OSQLParseNode *pLeftTable, 612 const ::connectivity::OSQLParseNode *pRightTable) 613 { 614 SqlParseError eErrorCode = eOk; 615 if (pNode->count() == 3 && // Ausdruck is geklammert 616 SQL_ISPUNCTUATION(pNode->getChild(0),"(") && 617 SQL_ISPUNCTUATION(pNode->getChild(2),")")) 618 { 619 eErrorCode = InsertJoinConnection(_pView,pNode->getChild(1), _eJoinType,pLeftTable,pRightTable); 620 } 621 else if (SQL_ISRULEOR2(pNode,search_condition,boolean_term) && // AND/OR-Verknuepfung: 622 pNode->count() == 3) 623 { 624 // nur AND Verkn�pfung zulassen 625 if (!SQL_ISTOKEN(pNode->getChild(1),AND)) 626 eErrorCode = eIllegalJoinCondition; 627 else if ( eOk == (eErrorCode = InsertJoinConnection(_pView,pNode->getChild(0), _eJoinType,pLeftTable,pRightTable)) ) 628 eErrorCode = InsertJoinConnection(_pView,pNode->getChild(2), _eJoinType,pLeftTable,pRightTable); 629 } 630 else if (SQL_ISRULE(pNode,comparison_predicate)) 631 { 632 // only the comparison of columns is allowed 633 DBG_ASSERT(pNode->count() == 3,"OQueryDesignView::InsertJoinConnection: Fehler im Parse Tree"); 634 if (!(SQL_ISRULE(pNode->getChild(0),column_ref) && 635 SQL_ISRULE(pNode->getChild(2),column_ref) && 636 pNode->getChild(1)->getNodeType() == SQL_NODE_EQUAL)) 637 { 638 String sError(ModuleRes(STR_QRY_JOIN_COLUMN_COMPARE)); 639 _pView->getController().appendError( sError ); 640 return eIllegalJoin; 641 } 642 643 OTableFieldDescRef aDragLeft = new OTableFieldDesc(); 644 OTableFieldDescRef aDragRight = new OTableFieldDesc(); 645 if ( eOk != ( eErrorCode = FillDragInfo(_pView,pNode->getChild(0),aDragLeft)) || 646 eOk != ( eErrorCode = FillDragInfo(_pView,pNode->getChild(2),aDragRight))) 647 return eErrorCode; 648 649 if ( pLeftTable ) 650 { 651 OQueryTableWindow* pLeftWindow = static_cast<OQueryTableView*>(_pView->getTableView())->FindTable( getTableRange(_pView,pLeftTable->getByRule(OSQLParseNode::table_ref) )); 652 // OQueryTableWindow* pRightWindow = static_cast<OQueryTableView*>(_pView->getTableView())->FindTable( getTableRange(_pView,pRightTable->getByRule(OSQLParseNode::table_ref) )); 653 if ( pLeftWindow == aDragLeft->GetTabWindow() ) 654 insertConnection(_pView,_eJoinType,aDragLeft,aDragRight); 655 else 656 insertConnection(_pView,_eJoinType,aDragRight,aDragLeft); 657 } 658 else 659 insertConnection(_pView,_eJoinType,aDragLeft,aDragRight); 660 } 661 else 662 eErrorCode = eIllegalJoin; 663 return eErrorCode; 664 } 665 //------------------------------------------------------------------------------ 666 sal_Bool GetInnerJoinCriteria( const OQueryDesignView* _pView, 667 const ::connectivity::OSQLParseNode *pCondition) 668 { 669 return InsertJoinConnection(_pView,pCondition, INNER_JOIN,NULL,NULL) != eOk; 670 } 671 //------------------------------------------------------------------------------ 672 ::rtl::OUString GenerateSelectList( const OQueryDesignView* _pView, 673 OTableFields& _rFieldList, 674 sal_Bool bAlias) 675 { 676 Reference< XConnection> xConnection = static_cast<OQueryController&>(_pView->getController()).getConnection(); 677 if ( !xConnection.is() ) 678 return ::rtl::OUString(); 679 680 ::rtl::OUStringBuffer aTmpStr,aFieldListStr; 681 682 sal_Bool bAsterix = sal_False; 683 int nVis = 0; 684 OTableFields::iterator aIter = _rFieldList.begin(); 685 OTableFields::iterator aEnd = _rFieldList.end(); 686 for(;aIter != aEnd;++aIter) 687 { 688 OTableFieldDescRef pEntryField = *aIter; 689 if ( pEntryField->IsVisible() ) 690 { 691 if ( pEntryField->GetField().toChar() == '*' ) 692 bAsterix = sal_True; 693 ++nVis; 694 } 695 } 696 if(nVis == 1) 697 bAsterix = sal_False; 698 699 try 700 { 701 const Reference< XDatabaseMetaData > xMetaData = xConnection->getMetaData(); 702 const ::rtl::OUString aQuote = xMetaData->getIdentifierQuoteString(); 703 704 OJoinTableView::OTableWindowMap* pTabList = _pView->getTableView()->GetTabWinMap(); 705 706 const static ::rtl::OUString sFieldSeparator(RTL_CONSTASCII_USTRINGPARAM(", ")); 707 const static ::rtl::OUString s_sAs(RTL_CONSTASCII_USTRINGPARAM(" AS ")); 708 709 aIter = _rFieldList.begin(); 710 for(;aIter != aEnd;++aIter) 711 { 712 OTableFieldDescRef pEntryField = *aIter; 713 ::rtl::OUString rFieldName = pEntryField->GetField(); 714 if ( rFieldName.getLength() && pEntryField->IsVisible() ) 715 { 716 aTmpStr = ::rtl::OUString(); 717 const ::rtl::OUString rAlias = pEntryField->GetAlias(); 718 const ::rtl::OUString rFieldAlias = pEntryField->GetFieldAlias(); 719 720 aTmpStr.append(quoteTableAlias((bAlias || bAsterix),rAlias,aQuote)); 721 722 // if we have a none numeric field, the table alias could be in the name 723 // otherwise we are not allowed to do this (e.g. 0.1 * PRICE ) 724 if ( !pEntryField->isOtherFunction() ) 725 { 726 // we have to look if we have alias.* here but before we have to check if the column doesn't already exist 727 String sTemp = rFieldName; 728 OTableFieldDescRef aInfo = new OTableFieldDesc(); 729 OJoinTableView::OTableWindowMap::iterator tableIter = pTabList->begin(); 730 OJoinTableView::OTableWindowMap::iterator tableEnd = pTabList->end(); 731 sal_Bool bFound = sal_False; 732 for(;!bFound && tableIter != tableEnd ;++tableIter) 733 { 734 OQueryTableWindow* pTabWin = static_cast<OQueryTableWindow*>(tableIter->second); 735 736 bFound = pTabWin->ExistsField( rFieldName, aInfo ); 737 if ( bFound ) 738 rFieldName = aInfo->GetField(); 739 } 740 if ( ( rFieldName.toChar() != '*' ) && ( rFieldName.indexOf( aQuote ) == -1 ) ) 741 { 742 OSL_ENSURE(pEntryField->GetTable().getLength(),"No table field name!"); 743 aTmpStr.append(::dbtools::quoteName(aQuote, rFieldName)); 744 } 745 else 746 aTmpStr.append(rFieldName); 747 } 748 else 749 aTmpStr.append(rFieldName); 750 751 if ( pEntryField->isAggreateFunction() ) 752 { 753 DBG_ASSERT(pEntryField->GetFunction().getLength(),"Functionname darf hier nicht leer sein! ;-("); 754 ::rtl::OUStringBuffer aTmpStr2( pEntryField->GetFunction()); 755 aTmpStr2.appendAscii("("); 756 aTmpStr2.append(aTmpStr.makeStringAndClear()); 757 aTmpStr2.appendAscii(")"); 758 aTmpStr = aTmpStr2; 759 } 760 761 if (rFieldAlias.getLength() && 762 (rFieldName.toChar() != '*' || 763 pEntryField->isNumericOrAggreateFunction() || 764 pEntryField->isOtherFunction())) 765 { 766 aTmpStr.append(s_sAs); 767 aTmpStr.append(::dbtools::quoteName(aQuote, rFieldAlias)); 768 } 769 aFieldListStr.append(aTmpStr.makeStringAndClear()); 770 aFieldListStr.append(sFieldSeparator); 771 } 772 } 773 if(aFieldListStr.getLength()) 774 aFieldListStr.setLength(aFieldListStr.getLength()-2); 775 } 776 catch(SQLException&) 777 { 778 OSL_ASSERT(!"Failure while building select list!"); 779 } 780 return aFieldListStr.makeStringAndClear(); 781 } 782 //------------------------------------------------------------------------------ 783 sal_Bool GenerateCriterias( OQueryDesignView* _pView, 784 ::rtl::OUStringBuffer& rRetStr, 785 ::rtl::OUStringBuffer& rHavingStr, 786 OTableFields& _rFieldList, 787 sal_Bool bMulti ) 788 { 789 // * darf keine Filter enthalten : habe ich die entsprechende Warnung schon angezeigt ? 790 sal_Bool bCritsOnAsterikWarning = sal_False; // ** TMFS ** 791 792 ::rtl::OUString aFieldName,aCriteria,aWhereStr,aHavingStr,aWork/*,aOrderStr*/; 793 // Zeilenweise werden die Ausdr"ucke mit AND verknuepft 794 sal_uInt16 nMaxCriteria = 0; 795 OTableFields::iterator aIter = _rFieldList.begin(); 796 OTableFields::iterator aEnd = _rFieldList.end(); 797 for(;aIter != aEnd;++aIter) 798 { 799 nMaxCriteria = ::std::max<sal_uInt16>(nMaxCriteria,(sal_uInt16)(*aIter)->GetCriteria().size()); 800 } 801 Reference< XConnection> xConnection = static_cast<OQueryController&>(_pView->getController()).getConnection(); 802 if(!xConnection.is()) 803 return sal_False; 804 try 805 { 806 const Reference< XDatabaseMetaData > xMetaData = xConnection->getMetaData(); 807 const ::rtl::OUString aQuote = xMetaData->getIdentifierQuoteString(); 808 const IParseContext& rContext = static_cast<OQueryController&>(_pView->getController()).getParser().getContext(); 809 810 for (sal_uInt16 i=0 ; i < nMaxCriteria ; i++) 811 { 812 aHavingStr = aWhereStr = ::rtl::OUString(); 813 814 for(aIter = _rFieldList.begin();aIter != aEnd;++aIter) 815 { 816 OTableFieldDescRef pEntryField = *aIter; 817 aFieldName = pEntryField->GetField(); 818 819 if (!aFieldName.getLength()) 820 continue; 821 aCriteria = pEntryField->GetCriteria( i ); 822 if ( aCriteria.getLength() ) 823 { 824 // * is not allowed to contain any filter, only when used in combination an aggregate function 825 if ( aFieldName.toChar() == '*' && pEntryField->isNoneFunction() ) 826 { 827 // only show the messagebox the first time 828 if (!bCritsOnAsterikWarning) 829 ErrorBox(_pView, ModuleRes( ERR_QRY_CRITERIA_ON_ASTERISK)).Execute(); 830 bCritsOnAsterikWarning = sal_True; 831 continue; 832 } 833 aWork = ::rtl::OUString(); 834 835 836 aWork += quoteTableAlias(bMulti,pEntryField->GetAlias(),aQuote); 837 838 if ( (pEntryField->GetFunctionType() & (FKT_OTHER|FKT_NUMERIC)) || (aFieldName.toChar() == '*') ) 839 aWork += aFieldName; 840 else 841 aWork += ::dbtools::quoteName(aQuote, aFieldName); 842 843 if ( pEntryField->isAggreateFunction() || pEntryField->IsGroupBy() ) 844 { 845 if (!aHavingStr.getLength()) // noch keine Kriterien 846 aHavingStr += ::rtl::OUString('('); // Klammern 847 else 848 aHavingStr += C_AND; 849 850 if ( pEntryField->isAggreateFunction() ) 851 { 852 OSL_ENSURE(pEntryField->GetFunction().getLength(),"No function name for aggregate given!"); 853 aHavingStr += pEntryField->GetFunction(); 854 aHavingStr += ::rtl::OUString('('); // Klammern 855 aHavingStr += aWork; 856 aHavingStr += ::rtl::OUString(')'); // Klammern 857 } 858 else 859 aHavingStr += aWork; 860 861 ::rtl::OUString aTmp = aCriteria; 862 ::rtl::OUString aErrorMsg; 863 Reference<XPropertySet> xColumn; 864 ::std::auto_ptr< ::connectivity::OSQLParseNode> pParseNode(_pView->getPredicateTreeFromEntry(pEntryField,aTmp,aErrorMsg,xColumn)); 865 if (pParseNode.get()) 866 { 867 if (bMulti && !(pEntryField->isOtherFunction() || (aFieldName.toChar() == '*'))) 868 pParseNode->replaceNodeValue(pEntryField->GetAlias(),aFieldName); 869 ::rtl::OUString sHavingStr = aHavingStr; 870 871 sal_uInt32 nCount = pParseNode->count(); 872 for( sal_uInt32 node = 1 ; node < nCount ; ++node) 873 pParseNode->getChild(node)->parseNodeToStr( sHavingStr, 874 xConnection, 875 &rContext, 876 sal_False, 877 !pEntryField->isOtherFunction()); 878 aHavingStr = sHavingStr; 879 } 880 else 881 aHavingStr += aCriteria; 882 } 883 else 884 { 885 if ( !aWhereStr.getLength() ) // noch keine Kriterien 886 aWhereStr += ::rtl::OUString('('); // Klammern 887 else 888 aWhereStr += C_AND; 889 890 aWhereStr += ::rtl::OUString(' '); 891 // aCriteria could have some german numbers so I have to be sure here 892 ::rtl::OUString aTmp = aCriteria; 893 ::rtl::OUString aErrorMsg; 894 Reference<XPropertySet> xColumn; 895 ::std::auto_ptr< ::connectivity::OSQLParseNode> pParseNode( _pView->getPredicateTreeFromEntry(pEntryField,aTmp,aErrorMsg,xColumn)); 896 if (pParseNode.get()) 897 { 898 if (bMulti && !(pEntryField->isOtherFunction() || (aFieldName.toChar() == '*'))) 899 pParseNode->replaceNodeValue(pEntryField->GetAlias(),aFieldName); 900 ::rtl::OUString aWhere = aWhereStr; 901 pParseNode->parseNodeToStr( aWhere, 902 xConnection, 903 &rContext, 904 sal_False, 905 !pEntryField->isOtherFunction() ); 906 aWhereStr = aWhere; 907 } 908 else 909 { 910 aWhereStr += aWork; 911 aWhereStr += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("=")); 912 aWhereStr += aCriteria; 913 } 914 } 915 } 916 // nur einmal f�r jedes Feld 917 else if ( !i && pEntryField->isCondition() ) 918 { 919 if (!aWhereStr.getLength()) // noch keine Kriterien 920 aWhereStr += ::rtl::OUString('('); // Klammern 921 else 922 aWhereStr += C_AND; 923 aWhereStr += pEntryField->GetField(); 924 } 925 } 926 if (aWhereStr.getLength()) 927 { 928 aWhereStr += ::rtl::OUString(')'); // Klammern zu fuer 'AND' Zweig 929 if (rRetStr.getLength()) // schon Feldbedingungen ? 930 rRetStr.append(C_OR); 931 else // Klammern auf fuer 'OR' Zweig 932 rRetStr.append(sal_Unicode('(')); 933 rRetStr.append(aWhereStr); 934 } 935 if (aHavingStr.getLength()) 936 { 937 aHavingStr += ::rtl::OUString(')'); // Klammern zu fuer 'AND' Zweig 938 if (rHavingStr.getLength()) // schon Feldbedingungen ? 939 rHavingStr.append(C_OR); 940 else // Klammern auf fuer 'OR' Zweig 941 rHavingStr.append(sal_Unicode('(')); 942 rHavingStr.append(aHavingStr); 943 } 944 } 945 946 if (rRetStr.getLength()) 947 rRetStr.append(sal_Unicode(')')); // Klammern zu fuer 'OR' Zweig 948 if (rHavingStr.getLength()) 949 rHavingStr.append(sal_Unicode(')')); // Klammern zu fuer 'OR' Zweig 950 } 951 catch(SQLException&) 952 { 953 OSL_ASSERT(!"Failure while building where clause!"); 954 } 955 return sal_True; 956 } 957 //------------------------------------------------------------------------------ 958 SqlParseError GenerateOrder( OQueryDesignView* _pView, 959 OTableFields& _rFieldList, 960 sal_Bool bMulti, 961 ::rtl::OUString& _rsRet) 962 { 963 const OQueryController& rController = static_cast<OQueryController&>(_pView->getController()); 964 Reference< XConnection> xConnection = rController.getConnection(); 965 if ( !xConnection.is() ) 966 return eNoConnection; 967 968 SqlParseError eErrorCode = eOk; 969 970 ::rtl::OUString aColumnName; 971 ::rtl::OUString aWorkStr; 972 try 973 { 974 const bool bColumnAliasInOrderBy = rController.getSdbMetaData().supportsColumnAliasInOrderBy(); 975 Reference< XDatabaseMetaData > xMetaData = xConnection->getMetaData(); 976 ::rtl::OUString aQuote = xMetaData->getIdentifierQuoteString(); 977 // * darf keine Filter enthalten : habe ich die entsprechende Warnung schon angezeigt ? 978 sal_Bool bCritsOnAsterikWarning = sal_False; // ** TMFS ** 979 OTableFields::iterator aIter = _rFieldList.begin(); 980 OTableFields::iterator aEnd = _rFieldList.end(); 981 for(;aIter != aEnd;++aIter) 982 { 983 OTableFieldDescRef pEntryField = *aIter; 984 EOrderDir eOrder = pEntryField->GetOrderDir(); 985 986 // nur wenn eine Sortierung und ein Tabellenname vorhanden ist-> erzeugen 987 // sonst werden die Expressions vom Order By im GenerateCriteria mit erzeugt 988 if ( eOrder != ORDER_NONE ) 989 { 990 aColumnName = pEntryField->GetField(); 991 if(aColumnName.toChar() == '*') 992 { 993 // die entsprechende MessageBox nur beim ersten mal anzeigen 994 if (!bCritsOnAsterikWarning) 995 ErrorBox(_pView, ModuleRes( ERR_QRY_ORDERBY_ON_ASTERISK)).Execute(); 996 bCritsOnAsterikWarning = sal_True; 997 continue; 998 } 999 1000 if ( bColumnAliasInOrderBy && pEntryField->GetFieldAlias().getLength() ) 1001 { 1002 aWorkStr += ::dbtools::quoteName(aQuote, pEntryField->GetFieldAlias()); 1003 } 1004 else if ( pEntryField->isNumericOrAggreateFunction() ) 1005 { 1006 DBG_ASSERT(pEntryField->GetFunction().getLength(),"Functionname darf hier nicht leer sein! ;-("); 1007 aWorkStr += pEntryField->GetFunction(); 1008 aWorkStr += ::rtl::OUString('('); 1009 aWorkStr += quoteTableAlias(bMulti,pEntryField->GetAlias(),aQuote); 1010 // only quote column name when we don't have a numeric 1011 if ( pEntryField->isNumeric() ) 1012 aWorkStr += aColumnName; 1013 else 1014 aWorkStr += ::dbtools::quoteName(aQuote, aColumnName); 1015 1016 aWorkStr += ::rtl::OUString(')'); 1017 } 1018 else if ( pEntryField->isOtherFunction() ) 1019 { 1020 aWorkStr += aColumnName; 1021 } 1022 else 1023 { 1024 aWorkStr += quoteTableAlias(bMulti,pEntryField->GetAlias(),aQuote); 1025 aWorkStr += ::dbtools::quoteName(aQuote, aColumnName); 1026 } 1027 aWorkStr += ::rtl::OUString(' '); 1028 aWorkStr += String::CreateFromAscii( ";ASC;DESC" ).GetToken( (sal_uInt16)eOrder ); 1029 aWorkStr += ::rtl::OUString(','); 1030 } 1031 } 1032 1033 { 1034 String sTemp(aWorkStr); 1035 sTemp.EraseTrailingChars( ',' ); 1036 aWorkStr = sTemp; 1037 } 1038 1039 if ( aWorkStr.getLength() ) 1040 { 1041 const sal_Int32 nMaxOrder = xMetaData->getMaxColumnsInOrderBy(); 1042 String sToken(aWorkStr); 1043 if ( nMaxOrder && nMaxOrder < sToken.GetTokenCount(',') ) 1044 eErrorCode = eStatementTooLong; 1045 else 1046 { 1047 _rsRet = ::rtl::OUString::createFromAscii(" ORDER BY "); 1048 _rsRet += aWorkStr; 1049 } 1050 } 1051 } 1052 catch(SQLException&) 1053 { 1054 OSL_ASSERT(!"Failure while building group by!"); 1055 } 1056 1057 return eErrorCode; 1058 } 1059 1060 //------------------------------------------------------------------------------ 1061 void GenerateInnerJoinCriterias(const Reference< XConnection>& _xConnection, 1062 ::rtl::OUString& _rJoinCrit, 1063 const ::std::vector<OTableConnection*>* _pConnList) 1064 { 1065 ::std::vector<OTableConnection*>::const_iterator aIter = _pConnList->begin(); 1066 ::std::vector<OTableConnection*>::const_iterator aEnd = _pConnList->end(); 1067 for(;aIter != aEnd;++aIter) 1068 { 1069 const OQueryTableConnection* pEntryConn = static_cast<const OQueryTableConnection*>(*aIter); 1070 OQueryTableConnectionData* pEntryConnData = static_cast<OQueryTableConnectionData*>(pEntryConn->GetData().get()); 1071 if ( pEntryConnData->GetJoinType() == INNER_JOIN && !pEntryConnData->isNatural() ) 1072 { 1073 if(_rJoinCrit.getLength()) 1074 _rJoinCrit += C_AND; 1075 _rJoinCrit += BuildJoinCriteria(_xConnection,pEntryConnData->GetConnLineDataList(),pEntryConnData); 1076 } 1077 } 1078 } 1079 //------------------------------------------------------------------------------ 1080 void searchAndAppendName(const Reference< XConnection>& _xConnection, 1081 const OQueryTableWindow* _pTableWindow, 1082 ::std::map< ::rtl::OUString,sal_Bool,::comphelper::UStringMixLess>& _rTableNames, 1083 ::rtl::OUString& _rsTableListStr 1084 ) 1085 { 1086 ::rtl::OUString sTabName(BuildTable(_xConnection,_pTableWindow)); 1087 1088 if(_rTableNames.find(sTabName) == _rTableNames.end()) 1089 { 1090 _rTableNames[sTabName] = sal_True; 1091 _rsTableListStr += sTabName; 1092 _rsTableListStr += ::rtl::OUString(','); 1093 } 1094 } 1095 //------------------------------------------------------------------------------ 1096 ::rtl::OUString GenerateFromClause( const Reference< XConnection>& _xConnection, 1097 const OQueryTableView::OTableWindowMap* pTabList, 1098 const ::std::vector<OTableConnection*>* pConnList 1099 ) 1100 { 1101 1102 ::rtl::OUString aTableListStr; 1103 // wird gebraucht um sicher zustelllen das eine Tabelle nicht doppelt vorkommt 1104 ::std::map< ::rtl::OUString,sal_Bool,::comphelper::UStringMixLess> aTableNames; 1105 1106 // generate outer join clause in from 1107 if(!pConnList->empty()) 1108 { 1109 ::std::vector<OTableConnection*>::const_iterator aIter = pConnList->begin(); 1110 ::std::vector<OTableConnection*>::const_iterator aEnd = pConnList->end(); 1111 ::std::map<OTableWindow*,sal_Int32> aConnectionCount; 1112 for(;aIter != aEnd;++aIter) 1113 { 1114 static_cast<OQueryTableConnection*>(*aIter)->SetVisited(sal_False); 1115 if ( aConnectionCount.find((*aIter)->GetSourceWin()) == aConnectionCount.end() ) 1116 aConnectionCount.insert(::std::map<OTableWindow*,sal_Int32>::value_type((*aIter)->GetSourceWin(),0)); 1117 else 1118 aConnectionCount[(*aIter)->GetSourceWin()]++; 1119 if ( aConnectionCount.find((*aIter)->GetDestWin()) == aConnectionCount.end() ) 1120 aConnectionCount.insert(::std::map<OTableWindow*,sal_Int32>::value_type((*aIter)->GetDestWin(),0)); 1121 else 1122 aConnectionCount[(*aIter)->GetDestWin()]++; 1123 } 1124 ::std::multimap<sal_Int32 , OTableWindow*> aMulti; 1125 ::std::map<OTableWindow*,sal_Int32>::iterator aCountIter = aConnectionCount.begin(); 1126 ::std::map<OTableWindow*,sal_Int32>::iterator aCountEnd = aConnectionCount.end(); 1127 for(;aCountIter != aCountEnd;++aCountIter) 1128 { 1129 aMulti.insert(::std::multimap<sal_Int32 , OTableWindow*>::value_type(aCountIter->second,aCountIter->first)); 1130 } 1131 1132 const sal_Bool bUseEscape = ::dbtools::getBooleanDataSourceSetting( _xConnection, PROPERTY_OUTERJOINESCAPE ); 1133 ::std::multimap<sal_Int32 , OTableWindow*>::reverse_iterator aRIter = aMulti.rbegin(); 1134 ::std::multimap<sal_Int32 , OTableWindow*>::reverse_iterator aREnd = aMulti.rend(); 1135 for(;aRIter != aREnd;++aRIter) 1136 { 1137 ::std::vector<OTableConnection*>::const_iterator aConIter = aRIter->second->getTableView()->getTableConnections(aRIter->second); 1138 for(;aConIter != aEnd;++aConIter) 1139 { 1140 OQueryTableConnection* pEntryConn = static_cast<OQueryTableConnection*>(*aConIter); 1141 if(!pEntryConn->IsVisited() && pEntryConn->GetSourceWin() == aRIter->second ) 1142 { 1143 ::rtl::OUString aJoin; 1144 GetNextJoin(_xConnection,pEntryConn,static_cast<OQueryTableWindow*>(pEntryConn->GetDestWin()),aJoin); 1145 1146 if(aJoin.getLength()) 1147 { 1148 // insert tables into table list to avoid double entries 1149 OQueryTableWindow* pEntryTabFrom = static_cast<OQueryTableWindow*>(pEntryConn->GetSourceWin()); 1150 OQueryTableWindow* pEntryTabTo = static_cast<OQueryTableWindow*>(pEntryConn->GetDestWin()); 1151 1152 ::rtl::OUString sTabName(BuildTable(_xConnection,pEntryTabFrom)); 1153 if(aTableNames.find(sTabName) == aTableNames.end()) 1154 aTableNames[sTabName] = sal_True; 1155 sTabName = BuildTable(_xConnection,pEntryTabTo); 1156 if(aTableNames.find(sTabName) == aTableNames.end()) 1157 aTableNames[sTabName] = sal_True; 1158 1159 ::rtl::OUString aStr; 1160 switch(static_cast<OQueryTableConnectionData*>(pEntryConn->GetData().get())->GetJoinType()) 1161 { 1162 case LEFT_JOIN: 1163 case RIGHT_JOIN: 1164 case FULL_JOIN: 1165 { 1166 // create outer join 1167 if ( bUseEscape ) 1168 aStr += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("{ OJ ")); 1169 aStr += aJoin; 1170 if ( bUseEscape ) 1171 aStr += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" }")); 1172 } 1173 break; 1174 default: 1175 aStr += aJoin; 1176 break; 1177 } 1178 aStr += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(",")); 1179 aTableListStr += aStr; 1180 } 1181 } 1182 } 1183 } 1184 1185 // and now all inner joins 1186 aIter = pConnList->begin(); 1187 for(;aIter != aEnd;++aIter) 1188 { 1189 OQueryTableConnection* pEntryConn = static_cast<OQueryTableConnection*>(*aIter); 1190 if(!pEntryConn->IsVisited()) 1191 { 1192 searchAndAppendName(_xConnection, 1193 static_cast<OQueryTableWindow*>(pEntryConn->GetSourceWin()), 1194 aTableNames, 1195 aTableListStr); 1196 1197 searchAndAppendName(_xConnection, 1198 static_cast<OQueryTableWindow*>(pEntryConn->GetDestWin()), 1199 aTableNames, 1200 aTableListStr); 1201 } 1202 } 1203 } 1204 // all tables that haven't a connection to anyone 1205 OQueryTableView::OTableWindowMap::const_iterator aTabIter = pTabList->begin(); 1206 OQueryTableView::OTableWindowMap::const_iterator aTabEnd = pTabList->end(); 1207 for(;aTabIter != aTabEnd;++aTabIter) 1208 { 1209 const OQueryTableWindow* pEntryTab = static_cast<const OQueryTableWindow*>(aTabIter->second); 1210 if(!pEntryTab->ExistsAConn()) 1211 { 1212 aTableListStr += BuildTable(_xConnection,pEntryTab); 1213 aTableListStr += ::rtl::OUString(','); 1214 } 1215 } 1216 1217 if(aTableListStr.getLength()) 1218 aTableListStr = aTableListStr.replaceAt(aTableListStr.getLength()-1,1, ::rtl::OUString() ); 1219 return aTableListStr; 1220 } 1221 //------------------------------------------------------------------------------ 1222 ::rtl::OUString GenerateGroupBy(const OQueryDesignView* _pView,OTableFields& _rFieldList, sal_Bool bMulti ) 1223 { 1224 OQueryController& rController = static_cast<OQueryController&>(_pView->getController()); 1225 const Reference< XConnection> xConnection = rController.getConnection(); 1226 if(!xConnection.is()) 1227 return ::rtl::OUString(); 1228 1229 ::std::map< rtl::OUString,bool> aGroupByNames; 1230 1231 ::rtl::OUString aGroupByStr; 1232 try 1233 { 1234 const Reference< XDatabaseMetaData > xMetaData = xConnection->getMetaData(); 1235 const ::rtl::OUString aQuote = xMetaData->getIdentifierQuoteString(); 1236 1237 OTableFields::iterator aIter = _rFieldList.begin(); 1238 OTableFields::iterator aEnd = _rFieldList.end(); 1239 for(;aIter != aEnd;++aIter) 1240 { 1241 OTableFieldDescRef pEntryField = *aIter; 1242 if ( pEntryField->IsGroupBy() ) 1243 { 1244 DBG_ASSERT(pEntryField->GetField().getLength(),"Kein FieldName vorhanden!;-("); 1245 ::rtl::OUString sGroupByPart = quoteTableAlias(bMulti,pEntryField->GetAlias(),aQuote); 1246 1247 // only quote the field name when it isn't calculated 1248 if ( pEntryField->isNoneFunction() ) 1249 { 1250 sGroupByPart += ::dbtools::quoteName(aQuote, pEntryField->GetField()); 1251 } 1252 else 1253 { 1254 ::rtl::OUString aTmp = pEntryField->GetField(); 1255 ::rtl::OUString aErrorMsg; 1256 Reference<XPropertySet> xColumn; 1257 ::std::auto_ptr< ::connectivity::OSQLParseNode> pParseNode(_pView->getPredicateTreeFromEntry(pEntryField,aTmp,aErrorMsg,xColumn)); 1258 if (pParseNode.get()) 1259 { 1260 ::rtl::OUString sGroupBy; 1261 pParseNode->getChild(0)->parseNodeToStr( sGroupBy, 1262 xConnection, 1263 &rController.getParser().getContext(), 1264 sal_False, 1265 !pEntryField->isOtherFunction()); 1266 sGroupByPart += sGroupBy; 1267 } 1268 else 1269 sGroupByPart += pEntryField->GetField(); 1270 } 1271 if ( aGroupByNames.find(sGroupByPart) == aGroupByNames.end() ) 1272 { 1273 aGroupByNames.insert(::std::map< rtl::OUString,bool>::value_type(sGroupByPart,true)); 1274 aGroupByStr += sGroupByPart; 1275 aGroupByStr += ::rtl::OUString(','); 1276 } 1277 } 1278 } 1279 if ( aGroupByStr.getLength() ) 1280 { 1281 aGroupByStr = aGroupByStr.replaceAt(aGroupByStr.getLength()-1,1, ::rtl::OUString(' ') ); 1282 ::rtl::OUString aGroupByStr2 = ::rtl::OUString::createFromAscii(" GROUP BY "); 1283 aGroupByStr2 += aGroupByStr; 1284 aGroupByStr = aGroupByStr2; 1285 } 1286 } 1287 catch(SQLException&) 1288 { 1289 OSL_ASSERT(!"Failure while building group by!"); 1290 } 1291 return aGroupByStr; 1292 } 1293 // ----------------------------------------------------------------------------- 1294 SqlParseError GetORCriteria(OQueryDesignView* _pView, 1295 OSelectionBrowseBox* _pSelectionBrw, 1296 const ::connectivity::OSQLParseNode * pCondition, 1297 sal_uInt16& nLevel , 1298 sal_Bool bHaving = sal_False, 1299 bool bAddOrOnOneLine = false); 1300 // ----------------------------------------------------------------------------- 1301 SqlParseError GetSelectionCriteria( OQueryDesignView* _pView, 1302 OSelectionBrowseBox* _pSelectionBrw, 1303 const ::connectivity::OSQLParseNode* pNode, 1304 sal_uInt16& rLevel ) 1305 { 1306 if (!SQL_ISRULE(pNode, select_statement)) 1307 return eNoSelectStatement; 1308 1309 // nyi: mehr Pruefung auf korrekte Struktur! 1310 pNode = pNode ? pNode->getChild(3)->getChild(1) : NULL; 1311 // no where clause found 1312 if (!pNode || pNode->isLeaf()) 1313 return eOk; 1314 1315 // Naechster freier Satz ... 1316 SqlParseError eErrorCode = eOk; 1317 ::connectivity::OSQLParseNode * pCondition = pNode->getChild(1); 1318 if ( pCondition ) // no where clause 1319 { 1320 // now we have to chech the other conditions 1321 // first make the logical easier 1322 ::connectivity::OSQLParseNode::negateSearchCondition(pCondition); 1323 ::connectivity::OSQLParseNode *pNodeTmp = pNode->getChild(1); 1324 1325 ::connectivity::OSQLParseNode::disjunctiveNormalForm(pNodeTmp); 1326 pNodeTmp = pNode->getChild(1); 1327 ::connectivity::OSQLParseNode::absorptions(pNodeTmp); 1328 pNodeTmp = pNode->getChild(1); 1329 // compress sort the criteria @see http://www.openoffice.org/issues/show_bug.cgi?id=24079 1330 OSQLParseNode::compress(pNodeTmp); 1331 pNodeTmp = pNode->getChild(1); 1332 1333 // first extract the inner joins conditions 1334 GetInnerJoinCriteria(_pView,pNodeTmp); 1335 // now simplify again, join are checked in ComparisonPredicate 1336 ::connectivity::OSQLParseNode::absorptions(pNodeTmp); 1337 pNodeTmp = pNode->getChild(1); 1338 1339 // it could happen that pCondition is not more valid 1340 eErrorCode = GetORCriteria(_pView,_pSelectionBrw,pNodeTmp, rLevel); 1341 } 1342 return eErrorCode; 1343 } 1344 //------------------------------------------------------------------------------ 1345 SqlParseError GetANDCriteria( OQueryDesignView* _pView, 1346 OSelectionBrowseBox* _pSelectionBrw, 1347 const ::connectivity::OSQLParseNode * pCondition, 1348 sal_uInt16& nLevel, 1349 sal_Bool bHaving, 1350 bool bAddOrOnOneLine); 1351 //------------------------------------------------------------------------------ 1352 SqlParseError ComparisonPredicate(OQueryDesignView* _pView, 1353 OSelectionBrowseBox* _pSelectionBrw, 1354 const ::connectivity::OSQLParseNode * pCondition, 1355 const sal_uInt16 nLevel, 1356 sal_Bool bHaving, 1357 bool bAddOrOnOneLine); 1358 //------------------------------------------------------------------------------ 1359 SqlParseError GetORCriteria(OQueryDesignView* _pView, 1360 OSelectionBrowseBox* _pSelectionBrw, 1361 const ::connectivity::OSQLParseNode * pCondition, 1362 sal_uInt16& nLevel , 1363 sal_Bool bHaving, 1364 bool bAddOrOnOneLine) 1365 { 1366 SqlParseError eErrorCode = eOk; 1367 1368 // Runde Klammern um den Ausdruck 1369 if (pCondition->count() == 3 && 1370 SQL_ISPUNCTUATION(pCondition->getChild(0),"(") && 1371 SQL_ISPUNCTUATION(pCondition->getChild(2),")")) 1372 { 1373 eErrorCode = GetORCriteria(_pView,_pSelectionBrw,pCondition->getChild(1),nLevel,bHaving,bAddOrOnOneLine); 1374 } 1375 // oder Verknuepfung 1376 // a searchcondition can only look like this: search_condition SQL_TOKEN_OR boolean_term 1377 else if (SQL_ISRULE(pCondition,search_condition)) 1378 { 1379 for (int i = 0; i < 3 && eErrorCode == eOk ; i+=2) 1380 { 1381 const ::connectivity::OSQLParseNode* pChild = pCondition->getChild(i); 1382 if ( SQL_ISRULE(pChild,search_condition) ) 1383 eErrorCode = GetORCriteria(_pView,_pSelectionBrw,pChild,nLevel,bHaving,bAddOrOnOneLine); 1384 else 1385 { 1386 eErrorCode = GetANDCriteria(_pView,_pSelectionBrw,pChild, nLevel,bHaving, i == 0 ? false : bAddOrOnOneLine); 1387 if ( !bAddOrOnOneLine) 1388 nLevel++; 1389 } 1390 } 1391 } 1392 else 1393 eErrorCode = GetANDCriteria( _pView,_pSelectionBrw,pCondition, nLevel, bHaving,bAddOrOnOneLine ); 1394 1395 return eErrorCode; 1396 } 1397 //-------------------------------------------------------------------------------------------------- 1398 bool CheckOrCriteria(const ::connectivity::OSQLParseNode* _pCondition,::connectivity::OSQLParseNode* _pFirstColumnRef) 1399 { 1400 bool bRet = true; 1401 ::connectivity::OSQLParseNode* pFirstColumnRef = _pFirstColumnRef; 1402 for (int i = 0; i < 3 && bRet; i+=2) 1403 { 1404 const ::connectivity::OSQLParseNode* pChild = _pCondition->getChild(i); 1405 if ( SQL_ISRULE(pChild,search_condition) ) 1406 bRet = CheckOrCriteria(pChild,pFirstColumnRef); 1407 else 1408 { 1409 // this is a simple way to test columns are the same, may be we have to adjust this algo a little bit in future. :-) 1410 ::connectivity::OSQLParseNode* pSecondColumnRef = pChild->getByRule(::connectivity::OSQLParseNode::column_ref); 1411 if ( pFirstColumnRef && pSecondColumnRef ) 1412 bRet = *pFirstColumnRef == *pSecondColumnRef; 1413 else if ( !pFirstColumnRef ) 1414 pFirstColumnRef = pSecondColumnRef; 1415 } 1416 } 1417 return bRet; 1418 } 1419 //-------------------------------------------------------------------------------------------------- 1420 SqlParseError GetANDCriteria( OQueryDesignView* _pView, 1421 OSelectionBrowseBox* _pSelectionBrw, 1422 const ::connectivity::OSQLParseNode * pCondition, 1423 sal_uInt16& nLevel, 1424 sal_Bool bHaving, 1425 bool bAddOrOnOneLine) 1426 { 1427 const ::com::sun::star::lang::Locale aLocale = _pView->getLocale(); 1428 const ::rtl::OUString sDecimal = _pView->getDecimalSeparator(); 1429 1430 // ich werde ein paar Mal einen gecasteten Pointer auf meinen ::com::sun::star::sdbcx::Container brauchen 1431 OQueryController& rController = static_cast<OQueryController&>(_pView->getController()); 1432 SqlParseError eErrorCode = eOk; 1433 1434 // Runde Klammern 1435 if (SQL_ISRULE(pCondition,boolean_primary)) 1436 { 1437 // check if we have to put the or criteria on one line. 1438 const ::connectivity::OSQLParseNode* pSearchCondition = pCondition->getChild(1); 1439 bool bMustAddOrOnOneLine = CheckOrCriteria(pSearchCondition,NULL); 1440 if ( SQL_ISRULE( pSearchCondition, search_condition) ) // we have a or 1441 { 1442 _pSelectionBrw->DuplicateConditionLevel( nLevel); 1443 eErrorCode = GetORCriteria(_pView,_pSelectionBrw,pSearchCondition->getChild(0), nLevel,bHaving,bMustAddOrOnOneLine ); 1444 ++nLevel; 1445 eErrorCode = GetORCriteria(_pView,_pSelectionBrw,pSearchCondition->getChild(2), nLevel,bHaving,bMustAddOrOnOneLine ); 1446 } 1447 else 1448 eErrorCode = GetORCriteria(_pView,_pSelectionBrw,pSearchCondition, nLevel,bHaving,bMustAddOrOnOneLine ); 1449 } 1450 // Das erste Element ist (wieder) eine AND-Verknuepfung 1451 else if ( SQL_ISRULE(pCondition,boolean_term) ) 1452 { 1453 OSL_ENSURE(pCondition->count() == 3,"Illegal definifiton of boolean_term"); 1454 eErrorCode = GetANDCriteria(_pView,_pSelectionBrw,pCondition->getChild(0), nLevel,bHaving,bAddOrOnOneLine ); 1455 if ( eErrorCode == eOk ) 1456 eErrorCode = GetANDCriteria(_pView,_pSelectionBrw,pCondition->getChild(2), nLevel,bHaving,bAddOrOnOneLine ); 1457 } 1458 else if (SQL_ISRULE( pCondition, comparison_predicate)) 1459 { 1460 eErrorCode = ComparisonPredicate(_pView,_pSelectionBrw,pCondition,nLevel,bHaving,bAddOrOnOneLine); 1461 } 1462 else if( SQL_ISRULE(pCondition,like_predicate) ) 1463 { 1464 const ::connectivity::OSQLParseNode* pValueExp = pCondition->getChild(0); 1465 if (SQL_ISRULE(pValueExp, column_ref ) ) 1466 { 1467 ::rtl::OUString aColumnName; 1468 ::rtl::OUString aCondition; 1469 Reference< XConnection> xConnection = rController.getConnection(); 1470 if ( xConnection.is() ) 1471 { 1472 Reference< XDatabaseMetaData > xMetaData = xConnection->getMetaData(); 1473 // the international doesn't matter I have a string 1474 pCondition->parseNodeToPredicateStr(aCondition, 1475 xConnection, 1476 rController.getNumberFormatter(), 1477 aLocale, 1478 static_cast<sal_Char>(sDecimal.toChar()), 1479 &rController.getParser().getContext()); 1480 1481 pValueExp->parseNodeToPredicateStr( aColumnName, 1482 xConnection, 1483 rController.getNumberFormatter(), 1484 aLocale, 1485 static_cast<sal_Char>(sDecimal.toChar()), 1486 &rController.getParser().getContext()); 1487 1488 // don't display the column name 1489 aCondition = aCondition.copy(aColumnName.getLength()); 1490 aCondition = aCondition.trim(); 1491 } 1492 1493 OTableFieldDescRef aDragLeft = new OTableFieldDesc(); 1494 if ( eOk == ( eErrorCode = FillDragInfo(_pView,pValueExp,aDragLeft) )) 1495 { 1496 if ( bHaving ) 1497 aDragLeft->SetGroupBy(sal_True); 1498 _pSelectionBrw->AddCondition(aDragLeft, aCondition, nLevel,bAddOrOnOneLine); 1499 } 1500 } 1501 else if(SQL_ISRULEOR2(pValueExp,general_set_fct ,set_fct_spec) || 1502 SQL_ISRULEOR2(pValueExp,position_exp,extract_exp) || 1503 SQL_ISRULEOR2(pValueExp,fold,char_substring_fct) || 1504 SQL_ISRULEOR2(pValueExp,length_exp,char_value_fct)) 1505 { 1506 AddFunctionCondition( _pView, 1507 _pSelectionBrw, 1508 pCondition, 1509 nLevel, 1510 bHaving, 1511 bAddOrOnOneLine); 1512 } 1513 else 1514 { 1515 eErrorCode = eNoColumnInLike; 1516 String sError(ModuleRes(STR_QRY_LIKE_LEFT_NO_COLUMN)); 1517 _pView->getController().appendError( sError ); 1518 } 1519 } 1520 else if( SQL_ISRULEOR2(pCondition,test_for_null,in_predicate) 1521 || SQL_ISRULEOR2(pCondition,all_or_any_predicate,between_predicate)) 1522 { 1523 if ( SQL_ISRULEOR2(pCondition->getChild(0), set_fct_spec , general_set_fct ) ) 1524 { 1525 AddFunctionCondition( _pView, 1526 _pSelectionBrw, 1527 pCondition, 1528 nLevel, 1529 bHaving, 1530 bAddOrOnOneLine); 1531 } 1532 else if ( SQL_ISRULE(pCondition->getChild(0), column_ref ) ) 1533 { 1534 // parse condition 1535 ::rtl::OUString sCondition = ParseCondition(rController,pCondition,sDecimal,aLocale,1); 1536 OTableFieldDescRef aDragLeft = new OTableFieldDesc(); 1537 if ( eOk == ( eErrorCode = FillDragInfo(_pView,pCondition->getChild(0),aDragLeft)) ) 1538 { 1539 if ( bHaving ) 1540 aDragLeft->SetGroupBy(sal_True); 1541 _pSelectionBrw->AddCondition(aDragLeft, sCondition, nLevel,bAddOrOnOneLine); 1542 } 1543 } 1544 else 1545 { 1546 // Funktions-Bedingung parsen 1547 ::rtl::OUString sCondition = ParseCondition(rController,pCondition,sDecimal,aLocale,1); 1548 Reference< XConnection> xConnection = rController.getConnection(); 1549 Reference< XDatabaseMetaData > xMetaData = xConnection->getMetaData(); 1550 // the international doesn't matter I have a string 1551 ::rtl::OUString sName; 1552 pCondition->getChild(0)->parseNodeToPredicateStr(sName, 1553 xConnection, 1554 rController.getNumberFormatter(), 1555 aLocale, 1556 static_cast<sal_Char>(sDecimal.toChar()), 1557 &rController.getParser().getContext()); 1558 1559 OTableFieldDescRef aDragLeft = new OTableFieldDesc(); 1560 aDragLeft->SetField(sName); 1561 aDragLeft->SetFunctionType(FKT_OTHER); 1562 1563 if ( bHaving ) 1564 aDragLeft->SetGroupBy(sal_True); 1565 _pSelectionBrw->AddCondition(aDragLeft, sCondition, nLevel,bAddOrOnOneLine); 1566 } 1567 } 1568 else if( SQL_ISRULEOR2(pCondition,existence_test,unique_test) ) 1569 { 1570 // Funktions-Bedingung parsen 1571 ::rtl::OUString aCondition = ParseCondition(rController,pCondition,sDecimal,aLocale,0); 1572 1573 OTableFieldDescRef aDragLeft = new OTableFieldDesc(); 1574 aDragLeft->SetField(aCondition); 1575 aDragLeft->SetFunctionType(FKT_CONDITION); 1576 1577 eErrorCode = _pSelectionBrw->InsertField(aDragLeft,BROWSER_INVALIDID,sal_False,sal_True).isValid() ? eOk : eTooManyColumns; 1578 } 1579 else //! TODO not supported yet 1580 eErrorCode = eStatementTooComplex; 1581 // Fehler einfach weiterreichen. 1582 return eErrorCode; 1583 } 1584 //------------------------------------------------------------------------------ 1585 SqlParseError AddFunctionCondition(OQueryDesignView* _pView, 1586 OSelectionBrowseBox* _pSelectionBrw, 1587 const ::connectivity::OSQLParseNode * pCondition, 1588 const sal_uInt16 nLevel, 1589 sal_Bool bHaving, 1590 bool bAddOrOnOneLine) 1591 { 1592 SqlParseError eErrorCode = eOk; 1593 OQueryController& rController = static_cast<OQueryController&>(_pView->getController()); 1594 1595 OSQLParseNode* pFunction = pCondition->getChild(0); 1596 1597 OSL_ENSURE(SQL_ISRULEOR2(pFunction,general_set_fct ,set_fct_spec) || 1598 SQL_ISRULEOR2(pFunction,position_exp,extract_exp) || 1599 SQL_ISRULEOR2(pFunction,fold,char_substring_fct) || 1600 SQL_ISRULEOR2(pFunction,length_exp,char_value_fct),"Illegal call!"); 1601 ::rtl::OUString aCondition; 1602 OTableFieldDescRef aDragLeft = new OTableFieldDesc(); 1603 1604 ::rtl::OUString aColumnName; 1605 Reference< XConnection> xConnection = rController.getConnection(); 1606 if(xConnection.is()) 1607 { 1608 Reference< XDatabaseMetaData > xMetaData = xConnection->getMetaData(); 1609 pCondition->parseNodeToPredicateStr(aCondition, 1610 xConnection, 1611 rController.getNumberFormatter(), 1612 _pView->getLocale(), 1613 static_cast<sal_Char>(_pView->getDecimalSeparator().toChar()), 1614 &rController.getParser().getContext()); 1615 1616 pFunction->parseNodeToStr( aColumnName, 1617 xConnection, 1618 &rController.getParser().getContext(), 1619 sal_True, 1620 sal_True); // quote is to true because we need quoted elements inside the function 1621 // i75557 1622 //pFunction->parseNodeToPredicateStr(aColumnName, 1623 // xConnection, 1624 // rController.getNumberFormatter(), 1625 // _pView->getLocale(), 1626 // static_cast<sal_Char>(_pView->getDecimalSeparator().toChar()), 1627 // &rController.getParser().getContext()); 1628 // don't display the column name 1629 aCondition = aCondition.copy(aColumnName.getLength()); 1630 aCondition = aCondition.trim(); 1631 if ( aCondition.indexOf('=',0) == 0 ) // ignore the equal sign 1632 aCondition = aCondition.copy(1); 1633 1634 1635 if ( SQL_ISRULE(pFunction, general_set_fct ) ) 1636 { 1637 sal_Int32 nFunctionType = FKT_AGGREGATE; 1638 OSQLParseNode* pParamNode = pFunction->getChild(pFunction->count()-2); 1639 if ( pParamNode && pParamNode->getTokenValue().toChar() == '*' ) 1640 { 1641 OJoinTableView::OTableWindowMap* pTabList = _pView->getTableView()->GetTabWinMap(); 1642 OJoinTableView::OTableWindowMap::iterator aIter = pTabList->begin(); 1643 OJoinTableView::OTableWindowMap::iterator aTabEnd = pTabList->end(); 1644 for(;aIter != aTabEnd;++aIter) 1645 { 1646 OQueryTableWindow* pTabWin = static_cast<OQueryTableWindow*>(aIter->second); 1647 if (pTabWin->ExistsField( ::rtl::OUString::createFromAscii("*"), aDragLeft )) 1648 { 1649 aDragLeft->SetAlias(String()); 1650 aDragLeft->SetTable(String()); 1651 break; 1652 } 1653 } 1654 } 1655 else if( eOk != ( eErrorCode = FillDragInfo(_pView,pParamNode,aDragLeft)) 1656 && SQL_ISRULE(pParamNode,num_value_exp) ) 1657 { 1658 ::rtl::OUString sParameterValue; 1659 pParamNode->parseNodeToStr( sParameterValue, 1660 xConnection, 1661 &rController.getParser().getContext()); 1662 nFunctionType |= FKT_NUMERIC; 1663 aDragLeft->SetField(sParameterValue); 1664 eErrorCode = eOk; 1665 } 1666 aDragLeft->SetFunctionType(nFunctionType); 1667 if ( bHaving ) 1668 aDragLeft->SetGroupBy(sal_True); 1669 sal_Int32 nIndex = 0; 1670 aDragLeft->SetFunction(aColumnName.getToken(0,'(',nIndex)); 1671 } 1672 else 1673 { 1674 // bei unbekannten Funktionen wird der gesamte Text in das Field gechrieben 1675 aDragLeft->SetField(aColumnName); 1676 if(bHaving) 1677 aDragLeft->SetGroupBy(sal_True); 1678 aDragLeft->SetFunctionType(FKT_OTHER|FKT_NUMERIC); 1679 } 1680 _pSelectionBrw->AddCondition(aDragLeft, aCondition, nLevel,bAddOrOnOneLine); 1681 } 1682 1683 return eErrorCode; 1684 } 1685 //------------------------------------------------------------------------------ 1686 SqlParseError ComparisonPredicate(OQueryDesignView* _pView, 1687 OSelectionBrowseBox* _pSelectionBrw, 1688 const ::connectivity::OSQLParseNode * pCondition, 1689 const sal_uInt16 nLevel, 1690 sal_Bool bHaving 1691 ,bool bAddOrOnOneLine) 1692 { 1693 SqlParseError eErrorCode = eOk; 1694 OQueryController& rController = static_cast<OQueryController&>(_pView->getController()); 1695 1696 DBG_ASSERT(SQL_ISRULE( pCondition, comparison_predicate),"ComparisonPredicate: pCondition ist kein ComparisonPredicate"); 1697 if ( SQL_ISRULE(pCondition->getChild(0), column_ref ) 1698 || SQL_ISRULE(pCondition->getChild(pCondition->count()-1), column_ref) ) 1699 { 1700 ::rtl::OUString aCondition; 1701 OTableFieldDescRef aDragLeft = new OTableFieldDesc(); 1702 1703 if ( SQL_ISRULE(pCondition->getChild(0), column_ref ) && SQL_ISRULE(pCondition->getChild(pCondition->count()-1), column_ref ) ) 1704 { 1705 OTableFieldDescRef aDragRight = new OTableFieldDesc(); 1706 if (eOk != ( eErrorCode = FillDragInfo(_pView,pCondition->getChild(0),aDragLeft)) || 1707 eOk != ( eErrorCode = FillDragInfo(_pView,pCondition->getChild(2),aDragRight))) 1708 return eErrorCode; 1709 1710 OQueryTableConnection* pConn = static_cast<OQueryTableConnection*>( 1711 _pView->getTableView()->GetTabConn(static_cast<OQueryTableWindow*>(aDragLeft->GetTabWindow()), 1712 static_cast<OQueryTableWindow*>(aDragRight->GetTabWindow()), 1713 true)); 1714 if ( pConn ) 1715 { 1716 OConnectionLineDataVec* pLineDataList = pConn->GetData()->GetConnLineDataList(); 1717 OConnectionLineDataVec::iterator aIter = pLineDataList->begin(); 1718 OConnectionLineDataVec::iterator aEnd = pLineDataList->end(); 1719 for(;aIter != aEnd;++aIter) 1720 { 1721 if((*aIter)->GetSourceFieldName() == aDragLeft->GetField() || 1722 (*aIter)->GetDestFieldName() == aDragLeft->GetField() ) 1723 break; 1724 } 1725 if(aIter != aEnd) 1726 return eOk; 1727 } 1728 } 1729 1730 sal_uInt32 nPos = 0; 1731 if(SQL_ISRULE(pCondition->getChild(0), column_ref )) 1732 { 1733 nPos = 0; 1734 sal_uInt32 i=1; 1735 1736 // don't display the equal 1737 if (pCondition->getChild(i)->getNodeType() == SQL_NODE_EQUAL) 1738 i++; 1739 1740 // Bedingung parsen 1741 aCondition = ParseCondition(rController 1742 ,pCondition 1743 ,_pView->getDecimalSeparator() 1744 ,_pView->getLocale() 1745 ,i); 1746 } 1747 else if( SQL_ISRULE(pCondition->getChild(pCondition->count()-1), column_ref ) ) 1748 { 1749 nPos = pCondition->count()-1; 1750 1751 sal_Int32 i = static_cast<sal_Int32>(pCondition->count() - 2); 1752 switch (pCondition->getChild(i)->getNodeType()) 1753 { 1754 case SQL_NODE_EQUAL: 1755 // don't display the equal 1756 i--; 1757 break; 1758 case SQL_NODE_LESS: 1759 // take the opposite as we change the order 1760 i--; 1761 aCondition = aCondition + ::rtl::OUString::createFromAscii(">"); 1762 break; 1763 case SQL_NODE_LESSEQ: 1764 // take the opposite as we change the order 1765 i--; 1766 aCondition = aCondition + ::rtl::OUString::createFromAscii(">="); 1767 break; 1768 case SQL_NODE_GREAT: 1769 // take the opposite as we change the order 1770 i--; 1771 aCondition = aCondition + ::rtl::OUString::createFromAscii("<"); 1772 break; 1773 case SQL_NODE_GREATEQ: 1774 // take the opposite as we change the order 1775 i--; 1776 aCondition = aCondition + ::rtl::OUString::createFromAscii("<="); 1777 break; 1778 default: 1779 break; 1780 } 1781 1782 // go backward 1783 Reference< XConnection> xConnection = rController.getConnection(); 1784 if(xConnection.is()) 1785 { 1786 Reference< XDatabaseMetaData > xMetaData = xConnection->getMetaData(); 1787 for (; i >= 0; i--) 1788 pCondition->getChild(i)->parseNodeToPredicateStr(aCondition, 1789 xConnection, 1790 rController.getNumberFormatter(), 1791 _pView->getLocale(), 1792 static_cast<sal_Char>(_pView->getDecimalSeparator().toChar()), 1793 &rController.getParser().getContext()); 1794 } 1795 } 1796 // else ??? 1797 1798 1799 if( eOk == ( eErrorCode = FillDragInfo(_pView,pCondition->getChild(nPos),aDragLeft))) 1800 { 1801 if(bHaving) 1802 aDragLeft->SetGroupBy(sal_True); 1803 _pSelectionBrw->AddCondition(aDragLeft, aCondition, nLevel,bAddOrOnOneLine); 1804 } 1805 } 1806 else if( SQL_ISRULEOR2(pCondition->getChild(0), set_fct_spec , general_set_fct ) ) 1807 { 1808 AddFunctionCondition( _pView, 1809 _pSelectionBrw, 1810 pCondition, 1811 nLevel, 1812 bHaving, 1813 bAddOrOnOneLine); 1814 } 1815 else // kann sich nur um einen Expr. Ausdruck handeln 1816 { 1817 ::rtl::OUString aName,aCondition; 1818 1819 ::connectivity::OSQLParseNode *pLhs = pCondition->getChild(0); 1820 ::connectivity::OSQLParseNode *pRhs = pCondition->getChild(2); 1821 // Feldnamen 1822 Reference< XConnection> xConnection = rController.getConnection(); 1823 if(xConnection.is()) 1824 { 1825 pLhs->parseNodeToStr(aName, 1826 xConnection, 1827 &rController.getParser().getContext(), 1828 sal_True); 1829 // Kriterium 1830 aCondition = pCondition->getChild(1)->getTokenValue(); 1831 pRhs->parseNodeToPredicateStr(aCondition, 1832 xConnection, 1833 rController.getNumberFormatter(), 1834 _pView->getLocale(), 1835 static_cast<sal_Char>(_pView->getDecimalSeparator().toChar()), 1836 &rController.getParser().getContext()); 1837 } 1838 1839 OTableFieldDescRef aDragLeft = new OTableFieldDesc(); 1840 aDragLeft->SetField(aName); 1841 aDragLeft->SetFunctionType(FKT_OTHER|FKT_NUMERIC); 1842 // und anh"angen 1843 _pSelectionBrw->AddCondition(aDragLeft, aCondition, nLevel,bAddOrOnOneLine); 1844 } 1845 return eErrorCode; 1846 } 1847 1848 //------------------------------------------------------------------------------ 1849 namespace 1850 { 1851 OQueryTableWindow* lcl_findColumnInTables( const ::rtl::OUString& _rColumName, const OJoinTableView::OTableWindowMap& _rTabList, OTableFieldDescRef& _rInfo ) 1852 { 1853 OJoinTableView::OTableWindowMap::const_iterator aIter = _rTabList.begin(); 1854 OJoinTableView::OTableWindowMap::const_iterator aEnd = _rTabList.end(); 1855 for ( ; aIter != aEnd; ++aIter ) 1856 { 1857 OQueryTableWindow* pTabWin = static_cast< OQueryTableWindow* >( aIter->second ); 1858 if ( pTabWin && pTabWin->ExistsField( _rColumName, _rInfo ) ) 1859 return pTabWin; 1860 } 1861 return NULL; 1862 } 1863 } 1864 1865 //------------------------------------------------------------------------------ 1866 void InsertColumnRef(const OQueryDesignView* _pView, 1867 const ::connectivity::OSQLParseNode * pColumnRef, 1868 ::rtl::OUString& aColumnName, 1869 const ::rtl::OUString& aColumnAlias, 1870 ::rtl::OUString& aTableRange, 1871 OTableFieldDescRef& _raInfo, 1872 OJoinTableView::OTableWindowMap* pTabList) 1873 { 1874 1875 // Tabellennamen zusammen setzen 1876 ::connectivity::OSQLParseTreeIterator& rParseIter = static_cast<OQueryController&>(_pView->getController()).getParseIterator(); 1877 rParseIter.getColumnRange( pColumnRef, aColumnName, aTableRange ); 1878 1879 sal_Bool bFound(sal_False); 1880 DBG_ASSERT(aColumnName.getLength(),"Columnname darf nicht leer sein"); 1881 if (!aTableRange.getLength()) 1882 { 1883 // SELECT column, ... 1884 bFound = NULL != lcl_findColumnInTables( aColumnName, *pTabList, _raInfo ); 1885 if ( bFound && ( aColumnName.toChar() != '*' ) ) 1886 _raInfo->SetFieldAlias(aColumnAlias); 1887 } 1888 else 1889 { 1890 // SELECT range.column, ... 1891 OQueryTableWindow* pTabWin = static_cast<OQueryTableView*>(_pView->getTableView())->FindTable(aTableRange); 1892 1893 if (pTabWin && pTabWin->ExistsField(aColumnName, _raInfo)) 1894 { 1895 if(aColumnName.toChar() != '*') 1896 _raInfo->SetFieldAlias(aColumnAlias); 1897 bFound = sal_True; 1898 } 1899 } 1900 if (!bFound) 1901 { 1902 _raInfo->SetTable(::rtl::OUString()); 1903 _raInfo->SetAlias(::rtl::OUString()); 1904 _raInfo->SetField(aColumnName); 1905 _raInfo->SetFieldAlias(aColumnAlias); // nyi : hier ein fortlaufendes Expr_1, Expr_2 ... 1906 _raInfo->SetFunctionType(FKT_OTHER); 1907 } 1908 } 1909 //----------------------------------------------------------------------------- 1910 sal_Bool checkJoinConditions( const OQueryDesignView* _pView, 1911 const ::connectivity::OSQLParseNode* _pNode ) 1912 { 1913 const ::connectivity::OSQLParseNode* pJoinNode = NULL; 1914 sal_Bool bRet = sal_True; 1915 if (SQL_ISRULE(_pNode,qualified_join)) 1916 pJoinNode = _pNode; 1917 else if (SQL_ISRULE(_pNode,table_ref) 1918 && _pNode->count() == 3 1919 && SQL_ISPUNCTUATION(_pNode->getChild(0),"(") 1920 && SQL_ISPUNCTUATION(_pNode->getChild(2),")") ) // '(' joined_table ')' 1921 pJoinNode = _pNode->getChild(1); 1922 else if (! ( SQL_ISRULE(_pNode, table_ref) && _pNode->count() == 2) ) // table_node table_primary_as_range_column 1923 bRet = sal_False; 1924 1925 if (pJoinNode && !InsertJoin(_pView,pJoinNode)) 1926 bRet = sal_False; 1927 return bRet; 1928 } 1929 //----------------------------------------------------------------------------- 1930 sal_Bool InsertJoin(const OQueryDesignView* _pView, 1931 const ::connectivity::OSQLParseNode *pNode) 1932 { 1933 DBG_ASSERT( SQL_ISRULE( pNode, qualified_join ) || SQL_ISRULE( pNode, joined_table ) || SQL_ISRULE( pNode, cross_union ), 1934 "OQueryDesignView::InsertJoin: Fehler im Parse Tree"); 1935 1936 if (SQL_ISRULE(pNode,joined_table)) 1937 return InsertJoin(_pView,pNode->getChild(1)); 1938 1939 // first check the left and right side 1940 const ::connectivity::OSQLParseNode* pRightTableRef = pNode->getChild(3); // table_ref 1941 if ( SQL_ISRULE(pNode, qualified_join) && SQL_ISTOKEN(pNode->getChild(1),NATURAL) ) 1942 pRightTableRef = pNode->getChild(4); // table_ref 1943 1944 if ( !checkJoinConditions(_pView,pNode->getChild(0)) || !checkJoinConditions(_pView,pRightTableRef)) 1945 return sal_False; 1946 1947 // named column join wird sp�ter vieleicht noch implementiert 1948 // SQL_ISRULE(pNode->getChild(4),named_columns_join) 1949 EJoinType eJoinType = INNER_JOIN; 1950 bool bNatural = false; 1951 if ( SQL_ISRULE(pNode, qualified_join) ) 1952 { 1953 ::connectivity::OSQLParseNode* pJoinType = pNode->getChild(1); // join_type 1954 if ( SQL_ISTOKEN(pJoinType,NATURAL) ) 1955 { 1956 bNatural = true; 1957 pJoinType = pNode->getChild(2); 1958 } 1959 1960 if (SQL_ISRULE(pJoinType,join_type) && (!pJoinType->count() || SQL_ISTOKEN(pJoinType->getChild(0),INNER))) 1961 { 1962 eJoinType = INNER_JOIN; 1963 } 1964 else 1965 { 1966 if (SQL_ISRULE(pJoinType,join_type)) // eine Ebene tiefer 1967 pJoinType = pJoinType->getChild(0); 1968 1969 if (SQL_ISTOKEN(pJoinType->getChild(0),LEFT)) 1970 eJoinType = LEFT_JOIN; 1971 else if(SQL_ISTOKEN(pJoinType->getChild(0),RIGHT)) 1972 eJoinType = RIGHT_JOIN; 1973 else 1974 eJoinType = FULL_JOIN; 1975 } 1976 if ( SQL_ISRULE(pNode->getChild(4),join_condition) ) 1977 { 1978 if ( InsertJoinConnection(_pView,pNode->getChild(4)->getChild(1), eJoinType,pNode->getChild(0),pRightTableRef) != eOk ) 1979 return sal_False; 1980 } 1981 } 1982 else if ( SQL_ISRULE(pNode, cross_union) ) 1983 { 1984 eJoinType = CROSS_JOIN; 1985 pRightTableRef = pNode->getChild(pNode->count() - 1); 1986 } 1987 else 1988 return sal_False; 1989 1990 if ( eJoinType == CROSS_JOIN || bNatural ) 1991 { 1992 1993 OQueryTableWindow* pLeftWindow = static_cast<OQueryTableView*>(_pView->getTableView())->FindTable( getTableRange(_pView,pNode->getChild(0)) ); 1994 OQueryTableWindow* pRightWindow = static_cast<OQueryTableView*>(_pView->getTableView())->FindTable( getTableRange(_pView,pRightTableRef) ); 1995 OSL_ENSURE(pLeftWindow && pRightWindow,"Table Windows could not be found!"); 1996 if ( !pLeftWindow || !pRightWindow ) 1997 return sal_False; 1998 1999 OTableFieldDescRef aDragLeft = new OTableFieldDesc(); 2000 aDragLeft->SetTabWindow(pLeftWindow); 2001 aDragLeft->SetTable(pLeftWindow->GetTableName()); 2002 aDragLeft->SetAlias(pLeftWindow->GetAliasName()); 2003 2004 OTableFieldDescRef aDragRight = new OTableFieldDesc(); 2005 aDragRight->SetTabWindow(pRightWindow); 2006 aDragRight->SetTable(pRightWindow->GetTableName()); 2007 aDragRight->SetAlias(pRightWindow->GetAliasName()); 2008 2009 insertConnection(_pView,eJoinType,aDragLeft,aDragRight,bNatural); 2010 } 2011 2012 2013 return sal_True; 2014 } 2015 //------------------------------------------------------------------------------ 2016 void insertUnUsedFields(OQueryDesignView* _pView,OSelectionBrowseBox* _pSelectionBrw) 2017 { 2018 // now we have to insert the fields which aren't in the statement 2019 OQueryController& rController = static_cast<OQueryController&>(_pView->getController()); 2020 OTableFields& rUnUsedFields = rController.getUnUsedFields(); 2021 OTableFields::iterator aEnd = rUnUsedFields.end(); 2022 for(OTableFields::iterator aIter = rUnUsedFields.begin();aIter != aEnd;++aIter) 2023 if(_pSelectionBrw->InsertField(*aIter,BROWSER_INVALIDID,sal_False,sal_False).isValid()) 2024 (*aIter) = NULL; 2025 OTableFields().swap( rUnUsedFields ); 2026 } 2027 2028 //------------------------------------------------------------------------------ 2029 SqlParseError InitFromParseNodeImpl(OQueryDesignView* _pView,OSelectionBrowseBox* _pSelectionBrw) 2030 { 2031 SqlParseError eErrorCode = eOk; 2032 2033 OQueryController& rController = static_cast<OQueryController&>(_pView->getController()); 2034 2035 _pSelectionBrw->PreFill(); 2036 _pSelectionBrw->SetReadOnly(rController.isReadOnly()); 2037 _pSelectionBrw->Fill(); 2038 2039 2040 ::connectivity::OSQLParseTreeIterator& aIterator = rController.getParseIterator(); 2041 const ::connectivity::OSQLParseNode* pParseTree = aIterator.getParseTree(); 2042 2043 do 2044 { 2045 if ( !pParseTree ) 2046 { 2047 // now we have to insert the fields which aren't in the statement 2048 insertUnUsedFields(_pView,_pSelectionBrw); 2049 break; 2050 } 2051 2052 if ( !rController.isEsacpeProcessing() ) // not allowed in this mode 2053 { 2054 eErrorCode = eNativeMode; 2055 break; 2056 } 2057 2058 if ( !( SQL_ISRULE( pParseTree, select_statement ) ) ) 2059 { 2060 eErrorCode = eNoSelectStatement; 2061 break; 2062 } 2063 2064 const OSQLParseNode* pTableExp = pParseTree->getChild(3); 2065 if ( pTableExp->getChild(6)->count() > 0 || pTableExp->getChild(7)->count() > 0 || pTableExp->getChild(8)->count() > 0) 2066 { 2067 eErrorCode = eStatementTooComplex; 2068 break; 2069 } 2070 2071 Reference< XConnection> xConnection = rController.getConnection(); 2072 if ( !xConnection.is() ) 2073 { 2074 DBG_ERROR( "InitFromParseNodeImpl: no connection? no connection!" ); 2075 break; 2076 } 2077 2078 const OSQLTables& aMap = aIterator.getTables(); 2079 ::comphelper::UStringMixLess aTmp(aMap.key_comp()); 2080 ::comphelper::UStringMixEqual aKeyComp( aTmp.isCaseSensitive() ); 2081 2082 Reference< XDatabaseMetaData > xMetaData = xConnection->getMetaData(); 2083 try 2084 { 2085 sal_Int32 nMax = xMetaData->getMaxTablesInSelect(); 2086 if ( nMax && nMax < (sal_Int32)aMap.size() ) 2087 { 2088 eErrorCode = eTooManyTables; 2089 break; 2090 } 2091 2092 ::rtl::OUString sComposedName; 2093 ::rtl::OUString aQualifierName; 2094 ::rtl::OUString sAlias; 2095 2096 OQueryTableView* pTableView = static_cast<OQueryTableView*>(_pView->getTableView()); 2097 pTableView->clearLayoutInformation(); 2098 OSQLTables::const_iterator aIter = aMap.begin(); 2099 OSQLTables::const_iterator aEnd = aMap.end(); 2100 for(;aIter != aEnd;++aIter) 2101 { 2102 OSQLTable xTable = aIter->second; 2103 Reference< XPropertySet > xTableProps( xTable, UNO_QUERY_THROW ); 2104 2105 sAlias = aIter->first; 2106 2107 // check whether this is a query 2108 Reference< XPropertySetInfo > xPSI = xTableProps->getPropertySetInfo(); 2109 bool bIsQuery = xPSI.is() && xPSI->hasPropertyByName( PROPERTY_COMMAND ); 2110 2111 if ( bIsQuery ) 2112 OSL_VERIFY( xTableProps->getPropertyValue( PROPERTY_NAME ) >>= sComposedName ); 2113 else 2114 { 2115 sComposedName = ::dbtools::composeTableName( xMetaData, xTableProps, ::dbtools::eInDataManipulation, false, false, false ); 2116 2117 // if the alias is the complete (composed) table, then shorten it 2118 if ( aKeyComp( sComposedName, aIter->first ) ) 2119 { 2120 ::rtl::OUString sCatalog, sSchema, sTable; 2121 ::dbtools::qualifiedNameComponents( xMetaData, sComposedName, sCatalog, sSchema, sTable, ::dbtools::eInDataManipulation ); 2122 sAlias = sTable; 2123 } 2124 } 2125 2126 // find the existent window for this alias 2127 OQueryTableWindow* pExistentWin = pTableView->FindTable( sAlias ); 2128 if ( !pExistentWin ) 2129 { 2130 pTableView->AddTabWin( sComposedName, sAlias, sal_False ); // don't create data here 2131 } 2132 else 2133 { 2134 // there already exists a window for this alias .... 2135 if ( !aKeyComp( pExistentWin->GetData()->GetComposedName(), sComposedName ) ) 2136 // ... but for another complete table name -> new window 2137 pTableView->AddTabWin(sComposedName, sAlias); 2138 } 2139 } 2140 2141 // now delete the data for which we haven't any tablewindow 2142 OJoinTableView::OTableWindowMap aTableMap(*pTableView->GetTabWinMap()); 2143 OJoinTableView::OTableWindowMap::iterator aIterTableMap = aTableMap.begin(); 2144 OJoinTableView::OTableWindowMap::iterator aIterTableEnd = aTableMap.end(); 2145 for(;aIterTableMap != aIterTableEnd;++aIterTableMap) 2146 { 2147 if(aMap.find(aIterTableMap->second->GetComposedName()) == aMap.end() && 2148 aMap.find(aIterTableMap->first) == aMap.end()) 2149 pTableView->RemoveTabWin(aIterTableMap->second); 2150 } 2151 2152 if ( eOk == (eErrorCode = FillOuterJoins(_pView,pTableExp->getChild(0)->getChild(1))) ) 2153 { 2154 // check if we have a distinct statement 2155 if(SQL_ISTOKEN(pParseTree->getChild(1),DISTINCT)) 2156 { 2157 rController.setDistinct(sal_True); 2158 rController.InvalidateFeature(SID_QUERY_DISTINCT_VALUES); 2159 } 2160 if ( (eErrorCode = InstallFields(_pView,pParseTree, pTableView->GetTabWinMap())) == eOk ) 2161 { 2162 // GetSelectionCriteria must be called before GetHavingCriteria 2163 sal_uInt16 nLevel=0; 2164 2165 if ( eOk == (eErrorCode = GetSelectionCriteria(_pView,_pSelectionBrw,pParseTree,nLevel)) ) 2166 { 2167 if ( eOk == (eErrorCode = GetGroupCriteria(_pView,_pSelectionBrw,pParseTree)) ) 2168 { 2169 if ( eOk == (eErrorCode = GetHavingCriteria(_pView,_pSelectionBrw,pParseTree,nLevel)) ) 2170 { 2171 if ( eOk == (eErrorCode = GetOrderCriteria(_pView,_pSelectionBrw,pParseTree)) ) 2172 insertUnUsedFields(_pView,_pSelectionBrw); 2173 } 2174 } 2175 } 2176 } 2177 } 2178 } 2179 catch(SQLException&) 2180 { 2181 OSL_ASSERT(!"getMaxTablesInSelect!"); 2182 } 2183 } 2184 while ( false ); 2185 2186 // Durch das Neuerzeugen wurden wieder Undo-Actions in den Manager gestellt 2187 rController.ClearUndoManager(); 2188 _pSelectionBrw->Invalidate(); 2189 return eErrorCode; 2190 } 2191 //------------------------------------------------------------------------------ 2192 /** fillSelectSubList 2193 @return 2194 <TRUE/> when columns could be inserted otherwise <FALSE/> 2195 */ 2196 //------------------------------------------------------------------------------ 2197 SqlParseError fillSelectSubList( OQueryDesignView* _pView, 2198 OJoinTableView::OTableWindowMap* _pTabList) 2199 { 2200 SqlParseError eErrorCode = eOk; 2201 sal_Bool bFirstField = sal_True; 2202 ::rtl::OUString sAsterix(RTL_CONSTASCII_USTRINGPARAM("*")); 2203 OJoinTableView::OTableWindowMap::iterator aIter = _pTabList->begin(); 2204 OJoinTableView::OTableWindowMap::iterator aEnd = _pTabList->end(); 2205 for(;aIter != aEnd && eOk == eErrorCode ;++aIter) 2206 { 2207 OQueryTableWindow* pTabWin = static_cast<OQueryTableWindow*>(aIter->second); 2208 OTableFieldDescRef aInfo = new OTableFieldDesc(); 2209 if (pTabWin->ExistsField( sAsterix, aInfo )) 2210 { 2211 eErrorCode = _pView->InsertField(aInfo, sal_True, bFirstField); 2212 bFirstField = sal_False; 2213 } 2214 } 2215 return eErrorCode; 2216 } 2217 //------------------------------------------------------------------------------ 2218 SqlParseError InstallFields(OQueryDesignView* _pView, 2219 const ::connectivity::OSQLParseNode* pNode, 2220 OJoinTableView::OTableWindowMap* pTabList ) 2221 { 2222 if( pNode==0 || !SQL_ISRULE(pNode,select_statement)) 2223 return eNoSelectStatement; 2224 2225 ::connectivity::OSQLParseNode* pParseTree = pNode->getChild(2); // selection 2226 sal_Bool bFirstField = sal_True; // bei der Initialisierung mu� auf alle Faelle das erste Feld neu aktiviert werden 2227 2228 SqlParseError eErrorCode = eOk; 2229 2230 if ( pParseTree->isRule() && SQL_ISPUNCTUATION(pParseTree->getChild(0),"*") ) 2231 { 2232 // SELECT * ... 2233 eErrorCode = fillSelectSubList(_pView,pTabList); 2234 } 2235 else if (SQL_ISRULE(pParseTree,scalar_exp_commalist) ) 2236 { 2237 // SELECT column, ... 2238 OQueryController& rController = static_cast<OQueryController&>(_pView->getController()); 2239 Reference< XConnection> xConnection = rController.getConnection(); 2240 2241 ::rtl::OUString aColumnName,aTableRange; 2242 for (sal_uInt32 i = 0; i < pParseTree->count() && eOk == eErrorCode ; ++i) 2243 { 2244 ::connectivity::OSQLParseNode * pColumnRef = pParseTree->getChild(i); 2245 2246 do { 2247 2248 if ( SQL_ISRULE(pColumnRef,select_sublist) ) 2249 { 2250 eErrorCode = fillSelectSubList(_pView,pTabList); 2251 break; 2252 } 2253 2254 if ( SQL_ISRULE(pColumnRef,derived_column) ) 2255 { 2256 ::rtl::OUString aColumnAlias(rController.getParseIterator().getColumnAlias(pColumnRef)); // kann leer sein 2257 pColumnRef = pColumnRef->getChild(0); 2258 OTableFieldDescRef aInfo = new OTableFieldDesc(); 2259 2260 if ( pColumnRef->count() == 3 && 2261 SQL_ISPUNCTUATION(pColumnRef->getChild(0),"(") && 2262 SQL_ISPUNCTUATION(pColumnRef->getChild(2),")") 2263 ) 2264 pColumnRef = pColumnRef->getChild(1); 2265 2266 if (SQL_ISRULE(pColumnRef,column_ref)) 2267 { 2268 InsertColumnRef(_pView,pColumnRef,aColumnName,aColumnAlias,aTableRange,aInfo,pTabList); 2269 eErrorCode = _pView->InsertField(aInfo, sal_True, bFirstField); 2270 bFirstField = sal_False; 2271 } 2272 else if(SQL_ISRULEOR2(pColumnRef,general_set_fct ,set_fct_spec) || 2273 SQL_ISRULEOR2(pColumnRef,position_exp,extract_exp) || 2274 SQL_ISRULEOR2(pColumnRef,fold,char_substring_fct) || 2275 SQL_ISRULEOR2(pColumnRef,length_exp,char_value_fct)) 2276 { 2277 ::rtl::OUString aColumns; 2278 pColumnRef->parseNodeToPredicateStr(aColumns, 2279 xConnection, 2280 rController.getNumberFormatter(), 2281 _pView->getLocale(), 2282 static_cast<sal_Char>(_pView->getDecimalSeparator().toChar()), 2283 &rController.getParser().getContext()); 2284 //pColumnRef->parseNodeToStr( aColumns, 2285 // xConnection, 2286 // &rController.getParser().getContext(), 2287 // sal_True, 2288 // sal_True); // quote is to true because we need quoted elements inside the function 2289 2290 sal_Int32 nFunctionType = FKT_NONE; 2291 ::connectivity::OSQLParseNode* pParamRef = NULL; 2292 sal_Int32 nColumnRefPos = pColumnRef->count() - 2; 2293 if ( nColumnRefPos >= 0 && static_cast<sal_uInt32>(nColumnRefPos) < pColumnRef->count() ) 2294 pParamRef = pColumnRef->getChild(nColumnRefPos); 2295 2296 if ( SQL_ISRULE(pColumnRef,general_set_fct) 2297 && SQL_ISRULE(pParamRef,column_ref) ) 2298 { 2299 // Parameter auf Columnref pr"ufen 2300 InsertColumnRef(_pView,pParamRef,aColumnName,aColumnAlias,aTableRange,aInfo,pTabList); 2301 } 2302 else if ( SQL_ISRULE(pColumnRef,general_set_fct) ) 2303 { 2304 if ( pParamRef && pParamRef->getTokenValue().toChar() == '*' ) 2305 { 2306 OJoinTableView::OTableWindowMap::iterator aIter = pTabList->begin(); 2307 OJoinTableView::OTableWindowMap::iterator aEnd = pTabList->end(); 2308 for(;aIter != aEnd;++aIter) 2309 { 2310 OQueryTableWindow* pTabWin = static_cast<OQueryTableWindow*>(aIter->second); 2311 if (pTabWin->ExistsField( ::rtl::OUString::createFromAscii("*"), aInfo )) 2312 { 2313 aInfo->SetAlias(String()); 2314 aInfo->SetTable(String()); 2315 break; 2316 } 2317 } 2318 } 2319 else 2320 { 2321 ::rtl::OUString sFieldName = aColumns; 2322 if ( pParamRef ) 2323 { // we got an aggregate function but without column name inside 2324 // so we set the whole argument of the function as field name 2325 nFunctionType |= FKT_NUMERIC; 2326 sFieldName = ::rtl::OUString(); 2327 pParamRef->parseNodeToStr( sFieldName, 2328 xConnection, 2329 &rController.getParser().getContext(), 2330 sal_True, 2331 sal_True); // quote is to true because we need quoted elements inside the function 2332 } 2333 aInfo->SetDataType(DataType::DOUBLE); 2334 aInfo->SetFieldType(TAB_NORMAL_FIELD); 2335 aInfo->SetField(sFieldName); 2336 } 2337 aInfo->SetTabWindow(NULL); 2338 aInfo->SetFieldAlias(aColumnAlias); 2339 } 2340 else 2341 { 2342 _pView->fillFunctionInfo(pColumnRef,aColumns,aInfo); 2343 aInfo->SetFieldAlias(aColumnAlias); 2344 } 2345 2346 if ( SQL_ISRULE(pColumnRef,general_set_fct) ) 2347 { 2348 aInfo->SetFunctionType(nFunctionType|FKT_AGGREGATE); 2349 String aCol(aColumns); 2350 aInfo->SetFunction(aCol.GetToken(0,'(').EraseTrailingChars(' ')); 2351 } 2352 else 2353 aInfo->SetFunctionType(nFunctionType|FKT_OTHER); 2354 2355 eErrorCode = _pView->InsertField(aInfo, sal_True, bFirstField); 2356 bFirstField = sal_False; 2357 } 2358 else //if(SQL_ISRULE(pColumnRef,num_value_exp) || SQL_ISRULE(pColumnRef,term)) 2359 { 2360 ::rtl::OUString aColumns; 2361 pColumnRef->parseNodeToStr( aColumns, 2362 xConnection, 2363 &rController.getParser().getContext(), 2364 sal_True, 2365 sal_True); // quote is to true because we need quoted elements inside the function 2366 2367 aInfo->SetTabWindow( NULL ); 2368 2369 // since we support queries in queries, the thingie might belong to an existing "table" 2370 OQueryTableWindow* pExistingTable = lcl_findColumnInTables( aColumns, *pTabList, aInfo ); 2371 if ( pExistingTable ) 2372 { 2373 aInfo->SetTabWindow( pExistingTable ); 2374 aInfo->SetTable( pExistingTable->GetTableName() ); 2375 aInfo->SetAlias( pExistingTable->GetAliasName() ); 2376 } 2377 2378 aInfo->SetDataType(DataType::DOUBLE); 2379 aInfo->SetFieldType(TAB_NORMAL_FIELD); 2380 aInfo->SetField(aColumns); 2381 aInfo->SetFieldAlias(aColumnAlias); 2382 aInfo->SetFunctionType(FKT_NUMERIC | FKT_OTHER); 2383 2384 eErrorCode = _pView->InsertField(aInfo, sal_True, bFirstField); 2385 bFirstField = sal_False; 2386 } 2387 2388 break; 2389 } 2390 2391 DBG_ERROR( "InstallFields: don't know how to interpret this parse node!" ); 2392 2393 } while ( false ); 2394 } 2395 } 2396 else 2397 eErrorCode = eStatementTooComplex; 2398 2399 return eErrorCode; 2400 } 2401 //------------------------------------------------------------------------------ 2402 SqlParseError GetOrderCriteria( OQueryDesignView* _pView, 2403 OSelectionBrowseBox* _pSelectionBrw, 2404 const ::connectivity::OSQLParseNode* pParseRoot ) 2405 { 2406 SqlParseError eErrorCode = eOk; 2407 if (!pParseRoot->getChild(3)->getChild(4)->isLeaf()) 2408 { 2409 ::connectivity::OSQLParseNode* pNode = pParseRoot->getChild(3)->getChild(4)->getChild(2); 2410 ::connectivity::OSQLParseNode* pParamRef = NULL; 2411 2412 OQueryController& rController = static_cast<OQueryController&>(_pView->getController()); 2413 EOrderDir eOrderDir; 2414 OTableFieldDescRef aDragLeft = new OTableFieldDesc(); 2415 for( sal_uInt32 i=0 ; i<pNode->count() ; i++ ) 2416 { 2417 eOrderDir = ORDER_ASC; 2418 ::connectivity::OSQLParseNode* pChild = pNode->getChild( i ); 2419 2420 if (SQL_ISTOKEN( pChild->getChild(1), DESC ) ) 2421 eOrderDir = ORDER_DESC; 2422 2423 ::connectivity::OSQLParseNode* pArgument = pChild->getChild(0); 2424 2425 if(SQL_ISRULE(pArgument,column_ref)) 2426 { 2427 if( eOk == FillDragInfo(_pView,pArgument,aDragLeft)) 2428 _pSelectionBrw->AddOrder( aDragLeft, eOrderDir, i); 2429 else // it could be a alias name for a field 2430 { 2431 ::rtl::OUString aTableRange,aColumnName; 2432 ::connectivity::OSQLParseTreeIterator& rParseIter = rController.getParseIterator(); 2433 rParseIter.getColumnRange( pArgument, aColumnName, aTableRange ); 2434 2435 OTableFields& aList = rController.getTableFieldDesc(); 2436 OTableFields::iterator aIter = aList.begin(); 2437 OTableFields::iterator aEnd = aList.end(); 2438 for(;aIter != aEnd;++aIter) 2439 { 2440 OTableFieldDescRef pEntry = *aIter; 2441 if(pEntry.isValid() && pEntry->GetFieldAlias() == aColumnName) 2442 pEntry->SetOrderDir( eOrderDir ); 2443 } 2444 } 2445 } 2446 else if(SQL_ISRULE(pArgument, general_set_fct ) && 2447 SQL_ISRULE(pParamRef = pArgument->getChild(pArgument->count()-2),column_ref) && 2448 eOk == FillDragInfo(_pView,pParamRef,aDragLeft)) 2449 _pSelectionBrw->AddOrder( aDragLeft, eOrderDir, i ); 2450 else if( SQL_ISRULE(pArgument, set_fct_spec ) ) 2451 { 2452 2453 Reference< XConnection> xConnection = rController.getConnection(); 2454 if(xConnection.is()) 2455 { 2456 ::rtl::OUString sCondition; 2457 pArgument->parseNodeToPredicateStr(sCondition, 2458 xConnection, 2459 rController.getNumberFormatter(), 2460 _pView->getLocale(), 2461 static_cast<sal_Char>(_pView->getDecimalSeparator().toChar()), 2462 &rController.getParser().getContext()); 2463 _pView->fillFunctionInfo(pArgument,sCondition,aDragLeft); 2464 aDragLeft->SetFunctionType(FKT_OTHER); 2465 aDragLeft->SetOrderDir(eOrderDir); 2466 aDragLeft->SetVisible(sal_False); 2467 _pSelectionBrw->AddOrder( aDragLeft, eOrderDir, i ); 2468 } 2469 else 2470 eErrorCode = eColumnNotFound; 2471 } 2472 else 2473 eErrorCode = eColumnNotFound; 2474 } 2475 } 2476 return eErrorCode; 2477 } 2478 //------------------------------------------------------------------------------ 2479 SqlParseError GetHavingCriteria( OQueryDesignView* _pView, 2480 OSelectionBrowseBox* _pSelectionBrw, 2481 const ::connectivity::OSQLParseNode* pSelectRoot, 2482 sal_uInt16& rLevel ) 2483 { 2484 SqlParseError eErrorCode = eOk; 2485 if (!pSelectRoot->getChild(3)->getChild(3)->isLeaf()) 2486 eErrorCode = GetORCriteria(_pView,_pSelectionBrw,pSelectRoot->getChild(3)->getChild(3)->getChild(1),rLevel, sal_True); 2487 return eErrorCode; 2488 } 2489 //------------------------------------------------------------------------------ 2490 SqlParseError GetGroupCriteria( OQueryDesignView* _pView, 2491 OSelectionBrowseBox* _pSelectionBrw, 2492 const ::connectivity::OSQLParseNode* pSelectRoot ) 2493 { 2494 SqlParseError eErrorCode = eOk; 2495 if (!pSelectRoot->getChild(3)->getChild(2)->isLeaf()) // opt_group_by_clause 2496 { 2497 OQueryController& rController = static_cast<OQueryController&>(_pView->getController()); 2498 ::connectivity::OSQLParseNode* pGroupBy = pSelectRoot->getChild(3)->getChild(2)->getChild(2); 2499 2500 for( sal_uInt32 i=0 ; i < pGroupBy->count() && eOk == eErrorCode; ++i ) 2501 { 2502 OTableFieldDescRef aDragInfo = new OTableFieldDesc(); 2503 ::connectivity::OSQLParseNode* pParamRef = NULL; 2504 ::connectivity::OSQLParseNode* pArgument = pGroupBy->getChild( i ); 2505 if(SQL_ISRULE(pArgument,column_ref)) 2506 { 2507 if ( eOk == (eErrorCode = FillDragInfo(_pView,pArgument,aDragInfo)) ) 2508 { 2509 aDragInfo->SetGroupBy(sal_True); 2510 _pSelectionBrw->AddGroupBy(aDragInfo,i); 2511 } 2512 } 2513 else if(SQL_ISRULE(pArgument, general_set_fct ) && 2514 SQL_ISRULE(pParamRef = pArgument->getChild(pArgument->count()-2),column_ref) && 2515 eOk == FillDragInfo(_pView,pParamRef,aDragInfo)) 2516 { 2517 aDragInfo->SetGroupBy(sal_True); 2518 _pSelectionBrw->AddGroupBy( aDragInfo, i ); 2519 } 2520 else if( SQL_ISRULE(pArgument, set_fct_spec ) ) 2521 { 2522 Reference< XConnection> xConnection = rController.getConnection(); 2523 if(xConnection.is()) 2524 { 2525 ::rtl::OUString sGroupByExpression; 2526 pArgument->parseNodeToStr( sGroupByExpression, 2527 xConnection, 2528 &rController.getParser().getContext(), 2529 sal_True, 2530 sal_True); // quote is to true because we need quoted elements inside the function 2531 _pView->fillFunctionInfo(pArgument,sGroupByExpression,aDragInfo); 2532 aDragInfo->SetFunctionType(FKT_OTHER); 2533 aDragInfo->SetGroupBy(sal_True); 2534 aDragInfo->SetVisible(sal_False); 2535 _pSelectionBrw->AddGroupBy( aDragInfo, i ); 2536 } 2537 else 2538 eErrorCode = eColumnNotFound; 2539 } 2540 } 2541 } 2542 return eErrorCode; 2543 } 2544 2545 //------------------------------------------------------------------------------ 2546 String getParseErrorMessage( SqlParseError _eErrorCode ) 2547 { 2548 sal_uInt16 nResId; 2549 switch(_eErrorCode) 2550 { 2551 case eIllegalJoin: 2552 nResId = STR_QRY_ILLEGAL_JOIN; 2553 break; 2554 case eStatementTooLong: 2555 nResId = STR_QRY_TOO_LONG_STATEMENT; 2556 break; 2557 case eNoConnection: 2558 nResId = STR_QRY_SYNTAX; 2559 break; 2560 case eNoSelectStatement: 2561 nResId = STR_QRY_NOSELECT; 2562 break; 2563 case eColumnInLikeNotFound: 2564 nResId = STR_QRY_SYNTAX; 2565 break; 2566 case eNoColumnInLike: 2567 nResId = STR_QRY_SYNTAX; 2568 break; 2569 case eColumnNotFound: 2570 nResId = STR_QRY_SYNTAX; 2571 break; 2572 case eNativeMode: 2573 nResId = STR_QRY_NATIVE; 2574 break; 2575 case eTooManyTables: 2576 nResId = STR_QRY_TOO_MANY_TABLES; 2577 break; 2578 case eTooManyConditions: 2579 nResId = STR_QRY_TOOMANYCOND; 2580 break; 2581 case eTooManyColumns: 2582 nResId = STR_QRY_TOO_MANY_COLUMNS; 2583 break; 2584 case eStatementTooComplex: 2585 nResId = STR_QRY_TOOCOMPLEX; 2586 break; 2587 default: 2588 nResId = STR_QRY_SYNTAX; 2589 break; 2590 } 2591 ; 2592 return String( ModuleRes( nResId ) ); 2593 } 2594 2595 //------------------------------------------------------------------------------ 2596 //------------------------------------------------------------------------------ 2597 } 2598 // end of anonymouse namespace 2599 DBG_NAME(OQueryDesignView) 2600 2601 OQueryDesignView::OQueryDesignView( OQueryContainerWindow* _pParent, 2602 OQueryController& _rController, 2603 const Reference< XMultiServiceFactory >& _rFactory) 2604 :OQueryView( _pParent, _rController, _rFactory ) 2605 ,m_aSplitter( this ) 2606 ,m_eChildFocus(NONE) 2607 ,m_bInKeyEvent(sal_False) 2608 ,m_bInSplitHandler( sal_False ) 2609 { 2610 DBG_CTOR(OQueryDesignView,NULL); 2611 2612 try 2613 { 2614 SvtSysLocale aSysLocale; 2615 m_aLocale = aSysLocale.GetLocaleData().getLocale(); 2616 m_sDecimalSep = aSysLocale.GetLocaleData().getNumDecimalSep(); 2617 } 2618 catch(Exception&) 2619 { 2620 } 2621 2622 m_pSelectionBox = new OSelectionBrowseBox(this); 2623 2624 setNoneVisbleRow(static_cast<OQueryController&>(getController()).getVisibleRows()); 2625 m_pSelectionBox->Show(); 2626 // Splitter einrichten 2627 m_aSplitter.SetSplitHdl(LINK(this, OQueryDesignView,SplitHdl)); 2628 m_aSplitter.Show(); 2629 2630 } 2631 // ----------------------------------------------------------------------------- 2632 OQueryDesignView::~OQueryDesignView() 2633 { 2634 if ( m_pTableView ) 2635 ::dbaui::notifySystemWindow(this,m_pTableView,::comphelper::mem_fun(&TaskPaneList::RemoveWindow)); 2636 ::std::auto_ptr<Window> aTemp(m_pSelectionBox); 2637 m_pSelectionBox = NULL; 2638 2639 DBG_DTOR(OQueryDesignView,NULL); 2640 } 2641 //------------------------------------------------------------------------------ 2642 IMPL_LINK( OQueryDesignView, SplitHdl, void*, /*p*/ ) 2643 { 2644 if (!getController().isReadOnly()) 2645 { 2646 m_bInSplitHandler = sal_True; 2647 m_aSplitter.SetPosPixel( Point( m_aSplitter.GetPosPixel().X(),m_aSplitter.GetSplitPosPixel() ) ); 2648 static_cast<OQueryController&>(getController()).setSplitPos(m_aSplitter.GetSplitPosPixel()); 2649 static_cast<OQueryController&>(getController()).setModified( sal_True ); 2650 Resize(); 2651 m_bInSplitHandler = sal_True; 2652 } 2653 return 0L; 2654 } 2655 // ------------------------------------------------------------------------- 2656 void OQueryDesignView::Construct() 2657 { 2658 m_pTableView = new OQueryTableView(m_pScrollWindow,this); 2659 ::dbaui::notifySystemWindow(this,m_pTableView,::comphelper::mem_fun(&TaskPaneList::AddWindow)); 2660 OQueryView::Construct(); 2661 } 2662 // ----------------------------------------------------------------------------- 2663 void OQueryDesignView::initialize() 2664 { 2665 if(static_cast<OQueryController&>(getController()).getSplitPos() != -1) 2666 { 2667 m_aSplitter.SetPosPixel( Point( m_aSplitter.GetPosPixel().X(),static_cast<OQueryController&>(getController()).getSplitPos() ) ); 2668 m_aSplitter.SetSplitPosPixel(static_cast<OQueryController&>(getController()).getSplitPos()); 2669 } 2670 m_pSelectionBox->initialize(); 2671 reset(); 2672 } 2673 // ------------------------------------------------------------------------- 2674 void OQueryDesignView::resizeDocumentView(Rectangle& _rPlayground) 2675 { 2676 Point aPlaygroundPos( _rPlayground.TopLeft() ); 2677 Size aPlaygroundSize( _rPlayground.GetSize() ); 2678 2679 // calc the split pos, and forward it to the controller 2680 sal_Int32 nSplitPos = static_cast<OQueryController&>(getController()).getSplitPos(); 2681 if ( 0 != aPlaygroundSize.Height() ) 2682 { 2683 if ( ( -1 == nSplitPos ) 2684 || ( nSplitPos >= aPlaygroundSize.Height() ) 2685 ) 2686 { 2687 // let the selection browse box determine an optimal size 2688 Size aSelectionBoxSize = m_pSelectionBox->CalcOptimalSize( aPlaygroundSize ); 2689 nSplitPos = aPlaygroundSize.Height() - aSelectionBoxSize.Height() - m_aSplitter.GetSizePixel().Height(); 2690 // still an invalid size? 2691 if ( nSplitPos == -1 || nSplitPos >= aPlaygroundSize.Height() ) 2692 nSplitPos = sal_Int32(aPlaygroundSize.Height()*0.6); 2693 2694 static_cast<OQueryController&>(getController()).setSplitPos(nSplitPos); 2695 } 2696 2697 if ( !m_bInSplitHandler ) 2698 { // the resize is triggered by something else than the split handler 2699 // our main focus is to try to preserve the size of the selectionbrowse box 2700 Size aSelBoxSize = m_pSelectionBox->GetSizePixel(); 2701 if ( aSelBoxSize.Height() ) 2702 { 2703 // keep the size of the sel box constant 2704 nSplitPos = aPlaygroundSize.Height() - m_aSplitter.GetSizePixel().Height() - aSelBoxSize.Height(); 2705 2706 // and if the box is smaller than the optimal size, try to do something about it 2707 Size aSelBoxOptSize = m_pSelectionBox->CalcOptimalSize( aPlaygroundSize ); 2708 if ( aSelBoxOptSize.Height() > aSelBoxSize.Height() ) 2709 { 2710 nSplitPos = aPlaygroundSize.Height() - m_aSplitter.GetSizePixel().Height() - aSelBoxOptSize.Height(); 2711 } 2712 2713 static_cast< OQueryController& >(getController()).setSplitPos( nSplitPos ); 2714 } 2715 } 2716 } 2717 2718 // normalize the split pos 2719 Point aSplitPos = Point( _rPlayground.Left(), nSplitPos ); 2720 Size aSplitSize = Size( _rPlayground.GetSize().Width(), m_aSplitter.GetSizePixel().Height() ); 2721 2722 if( ( aSplitPos.Y() + aSplitSize.Height() ) > ( aPlaygroundSize.Height() )) 2723 aSplitPos.Y() = aPlaygroundSize.Height() - aSplitSize.Height(); 2724 2725 if( aSplitPos.Y() <= aPlaygroundPos.Y() ) 2726 aSplitPos.Y() = aPlaygroundPos.Y() + sal_Int32(aPlaygroundSize.Height() * 0.2); 2727 2728 // position the table 2729 Size aTableViewSize(aPlaygroundSize.Width(), aSplitPos.Y() - aPlaygroundPos.Y()); 2730 m_pScrollWindow->SetPosSizePixel(aPlaygroundPos, aTableViewSize); 2731 2732 // position the selection browse box 2733 Point aPos( aPlaygroundPos.X(), aSplitPos.Y() + aSplitSize.Height() ); 2734 m_pSelectionBox->SetPosSizePixel( aPos, Size( aPlaygroundSize.Width(), aPlaygroundSize.Height() - aSplitSize.Height() - aTableViewSize.Height() )); 2735 2736 // set the size of the splitter 2737 m_aSplitter.SetPosSizePixel( aSplitPos, aSplitSize ); 2738 m_aSplitter.SetDragRectPixel( _rPlayground ); 2739 2740 // just for completeness: there is no space left, we occupied it all ... 2741 _rPlayground.SetPos( _rPlayground.BottomRight() ); 2742 _rPlayground.SetSize( Size( 0, 0 ) ); 2743 } 2744 // ----------------------------------------------------------------------------- 2745 void OQueryDesignView::setReadOnly(sal_Bool _bReadOnly) 2746 { 2747 m_pSelectionBox->SetReadOnly(_bReadOnly); 2748 } 2749 // ----------------------------------------------------------------------------- 2750 void OQueryDesignView::clear() 2751 { 2752 m_pSelectionBox->ClearAll(); // clear the whole selection 2753 m_pTableView->ClearAll(); 2754 } 2755 // ----------------------------------------------------------------------------- 2756 void OQueryDesignView::setStatement(const ::rtl::OUString& /*_rsStatement*/) 2757 { 2758 } 2759 // ----------------------------------------------------------------------------- 2760 void OQueryDesignView::copy() 2761 { 2762 if( m_eChildFocus == SELECTION) 2763 m_pSelectionBox->copy(); 2764 } 2765 // ----------------------------------------------------------------------------- 2766 sal_Bool OQueryDesignView::isCutAllowed() 2767 { 2768 sal_Bool bAllowed = sal_False; 2769 if ( SELECTION == m_eChildFocus ) 2770 bAllowed = m_pSelectionBox->isCutAllowed(); 2771 return bAllowed; 2772 } 2773 // ----------------------------------------------------------------------------- 2774 sal_Bool OQueryDesignView::isPasteAllowed() 2775 { 2776 sal_Bool bAllowed = sal_False; 2777 if ( SELECTION == m_eChildFocus ) 2778 bAllowed = m_pSelectionBox->isPasteAllowed(); 2779 return bAllowed; 2780 } 2781 // ----------------------------------------------------------------------------- 2782 sal_Bool OQueryDesignView::isCopyAllowed() 2783 { 2784 sal_Bool bAllowed = sal_False; 2785 if ( SELECTION == m_eChildFocus ) 2786 bAllowed = m_pSelectionBox->isCopyAllowed(); 2787 return bAllowed; 2788 } 2789 // ----------------------------------------------------------------------------- 2790 void OQueryDesignView::stopTimer() 2791 { 2792 m_pSelectionBox->stopTimer(); 2793 } 2794 // ----------------------------------------------------------------------------- 2795 void OQueryDesignView::startTimer() 2796 { 2797 m_pSelectionBox->startTimer(); 2798 } 2799 // ----------------------------------------------------------------------------- 2800 void OQueryDesignView::cut() 2801 { 2802 if( m_eChildFocus == SELECTION) 2803 { 2804 m_pSelectionBox->cut(); 2805 static_cast<OQueryController&>(getController()).setModified(sal_True); 2806 } 2807 } 2808 // ----------------------------------------------------------------------------- 2809 void OQueryDesignView::paste() 2810 { 2811 if( m_eChildFocus == SELECTION) 2812 { 2813 m_pSelectionBox->paste(); 2814 static_cast<OQueryController&>(getController()).setModified(sal_True); 2815 } 2816 } 2817 // ----------------------------------------------------------------------------- 2818 void OQueryDesignView::TableDeleted(const ::rtl::OUString& rAliasName) 2819 { 2820 // Nachricht, dass Tabelle aus dem Fenster gel"oscht wurde 2821 DeleteFields(rAliasName); 2822 static_cast<OQueryController&>(getController()).InvalidateFeature(ID_BROWSER_ADDTABLE); // view nochmal bescheid sagen 2823 } 2824 //------------------------------------------------------------------------------ 2825 void OQueryDesignView::DeleteFields( const ::rtl::OUString& rAliasName ) 2826 { 2827 m_pSelectionBox->DeleteFields( rAliasName ); 2828 } 2829 // ----------------------------------------------------------------------------- 2830 bool OQueryDesignView::HasFieldByAliasName(const ::rtl::OUString& rFieldName, OTableFieldDescRef& rInfo) const 2831 { 2832 return m_pSelectionBox->HasFieldByAliasName( rFieldName, rInfo); 2833 } 2834 // ----------------------------------------------------------------------------- 2835 SqlParseError OQueryDesignView::InsertField( const OTableFieldDescRef& rInfo, sal_Bool bVis, sal_Bool bActivate) 2836 { 2837 return m_pSelectionBox->InsertField( rInfo, BROWSER_INVALIDID,bVis, bActivate ).isValid() ? eOk : eTooManyColumns; 2838 } 2839 // ----------------------------------------------------------------------------- 2840 sal_Int32 OQueryDesignView::getColWidth(sal_uInt16 _nColPos) const 2841 { 2842 static sal_Int32 s_nDefaultWidth = GetTextWidth(String(RTL_CONSTASCII_USTRINGPARAM("0"))) * 15; 2843 sal_Int32 nWidth = static_cast<OQueryController&>(getController()).getColWidth(_nColPos); 2844 if ( !nWidth ) 2845 nWidth = s_nDefaultWidth; 2846 return nWidth; 2847 } 2848 //------------------------------------------------------------------------------ 2849 void OQueryDesignView::fillValidFields(const ::rtl::OUString& sAliasName, ComboBox* pFieldList) 2850 { 2851 DBG_ASSERT(pFieldList != NULL, "OQueryDesignView::FillValidFields : What the hell do you think I can do with a NULL-ptr ? This will crash !"); 2852 pFieldList->Clear(); 2853 2854 sal_Bool bAllTables = sAliasName.getLength() == 0; 2855 2856 OJoinTableView::OTableWindowMap* pTabWins = m_pTableView->GetTabWinMap(); 2857 ::rtl::OUString strCurrentPrefix; 2858 ::std::vector< ::rtl::OUString> aFields; 2859 OJoinTableView::OTableWindowMap::iterator aIter = pTabWins->begin(); 2860 OJoinTableView::OTableWindowMap::iterator aEnd = pTabWins->end(); 2861 for(;aIter != aEnd;++aIter) 2862 { 2863 OQueryTableWindow* pCurrentWin = static_cast<OQueryTableWindow*>(aIter->second); 2864 if (bAllTables || (pCurrentWin->GetAliasName() == sAliasName)) 2865 { 2866 strCurrentPrefix = pCurrentWin->GetAliasName(); 2867 strCurrentPrefix += ::rtl::OUString('.'); 2868 2869 pCurrentWin->EnumValidFields(aFields); 2870 2871 ::std::vector< ::rtl::OUString>::iterator aStrIter = aFields.begin(); 2872 ::std::vector< ::rtl::OUString>::iterator aStrEnd = aFields.end(); 2873 for(;aStrIter != aStrEnd;++aStrIter) 2874 { 2875 if (bAllTables || aStrIter->toChar() == '*') 2876 pFieldList->InsertEntry(::rtl::OUString(strCurrentPrefix) += *aStrIter); 2877 else 2878 pFieldList->InsertEntry(*aStrIter); 2879 } 2880 2881 if (!bAllTables) 2882 // das heisst, dass ich in diesen Block kam, weil der Tabellenname genau der gesuchte war, also bin ich fertig 2883 // (dadurch verhindere ich auch das doppelte Einfuegen von Feldern, wenn eine Tabelle mehrmals als TabWin vorkommt) 2884 break; 2885 } 2886 } 2887 } 2888 // ----------------------------------------------------------------------------- 2889 long OQueryDesignView::PreNotify(NotifyEvent& rNEvt) 2890 { 2891 switch (rNEvt.GetType()) 2892 { 2893 case EVENT_GETFOCUS: 2894 #if OSL_DEBUG_LEVEL > 0 2895 { 2896 Window* pFocus = Application::GetFocusWindow(); 2897 (void)pFocus; 2898 } 2899 #endif 2900 2901 if ( m_pSelectionBox && m_pSelectionBox->HasChildPathFocus() ) 2902 m_eChildFocus = SELECTION; 2903 else 2904 m_eChildFocus = TABLEVIEW; 2905 break; 2906 } 2907 2908 return OQueryView::PreNotify(rNEvt); 2909 } 2910 //------------------------------------------------------------------------------ 2911 2912 2913 // ----------------------------------------------------------------------------- 2914 // check if the statement is correct when not returning false 2915 sal_Bool OQueryDesignView::checkStatement() 2916 { 2917 sal_Bool bRet = sal_True; 2918 if ( m_pSelectionBox ) 2919 bRet = m_pSelectionBox->Save(); // a error occured so we return no 2920 return bRet; 2921 } 2922 //------------------------------------------------------------------------------- 2923 ::rtl::OUString OQueryDesignView::getStatement() 2924 { 2925 OQueryController& rController = static_cast<OQueryController&>(getController()); 2926 m_rController.clearError(); 2927 // used for fields which aren't any longer in the statement 2928 OTableFields& rUnUsedFields = rController.getUnUsedFields(); 2929 OTableFields().swap( rUnUsedFields ); 2930 2931 // create the select columns 2932 sal_uInt32 nFieldcount = 0; 2933 OTableFields& rFieldList = rController.getTableFieldDesc(); 2934 OTableFields::iterator aIter = rFieldList.begin(); 2935 OTableFields::iterator aEnd = rFieldList.end(); 2936 for(;aIter != aEnd;++aIter) 2937 { 2938 OTableFieldDescRef pEntryField = *aIter; 2939 if ( pEntryField->GetField().getLength() && pEntryField->IsVisible() ) 2940 ++nFieldcount; 2941 else if (pEntryField->GetField().getLength() && 2942 !pEntryField->HasCriteria() && 2943 pEntryField->isNoneFunction() && 2944 pEntryField->GetOrderDir() == ORDER_NONE && 2945 !pEntryField->IsGroupBy() && 2946 !pEntryField->GetFunction().getLength() ) 2947 rUnUsedFields.push_back(pEntryField); 2948 } 2949 if ( !nFieldcount ) // keine Felder sichtbar also zur"uck 2950 { 2951 rUnUsedFields = rFieldList; 2952 return ::rtl::OUString(); 2953 } 2954 2955 OQueryTableView::OTableWindowMap* pTabList = m_pTableView->GetTabWinMap(); 2956 sal_uInt32 nTabcount = pTabList->size(); 2957 2958 ::rtl::OUString aFieldListStr(GenerateSelectList(this,rFieldList,nTabcount>1)); 2959 if( !aFieldListStr.getLength() ) 2960 return ::rtl::OUString(); 2961 // Ausnahmebehandlung, wenn keine Felder angegeben worden sind 2962 // Dann darf die Tabpage nicht gewechselt werden 2963 // Im TabBarSelectHdl wird der SQL-::rtl::OUString auf STATEMENT_NOFIELDS abgefragt 2964 // und eine Errormeldung erzeugt 2965 // ----------------- Tabellenliste aufbauen ---------------------- 2966 2967 const ::std::vector<OTableConnection*>* pConnList = m_pTableView->getTableConnections(); 2968 Reference< XConnection> xConnection = rController.getConnection(); 2969 ::rtl::OUString aTableListStr(GenerateFromClause(xConnection,pTabList,pConnList)); 2970 DBG_ASSERT(aTableListStr.getLength(), "OQueryDesignView::getStatement() : unerwartet : habe Felder, aber keine Tabellen !"); 2971 // wenn es Felder gibt, koennen die nur durch Einfuegen aus einer schon existenten Tabelle entstanden sein; wenn andererseits 2972 // eine Tabelle geloescht wird, verschwinden auch die zugehoerigen Felder -> ergo KANN es das nicht geben, dass Felder 2973 // existieren, aber keine Tabellen (und aFieldListStr hat schon eine Laenge, das stelle ich oben sicher) 2974 ::rtl::OUStringBuffer aHavingStr,aCriteriaListStr; 2975 // ----------------- Kriterien aufbauen ---------------------- 2976 if (!GenerateCriterias(this,aCriteriaListStr,aHavingStr,rFieldList, nTabcount > 1)) 2977 return ::rtl::OUString(); 2978 2979 ::rtl::OUString aJoinCrit; 2980 GenerateInnerJoinCriterias(xConnection,aJoinCrit,pConnList); 2981 if(aJoinCrit.getLength()) 2982 { 2983 ::rtl::OUString aTmp = ::rtl::OUString::createFromAscii("( "); 2984 aTmp += aJoinCrit; 2985 aTmp += ::rtl::OUString::createFromAscii(" )"); 2986 if(aCriteriaListStr.getLength()) 2987 { 2988 aTmp += C_AND; 2989 aTmp += aCriteriaListStr.makeStringAndClear(); 2990 } 2991 aCriteriaListStr = aTmp; 2992 } 2993 // ----------------- Statement aufbauen ---------------------- 2994 ::rtl::OUStringBuffer aSqlCmd(::rtl::OUString::createFromAscii("SELECT ")); 2995 if(static_cast<OQueryController&>(getController()).isDistinct()) 2996 aSqlCmd.append(::rtl::OUString::createFromAscii(" DISTINCT ")); 2997 aSqlCmd.append(aFieldListStr); 2998 aSqlCmd.append(::rtl::OUString::createFromAscii(" FROM ")); 2999 aSqlCmd.append(aTableListStr); 3000 3001 if (aCriteriaListStr.getLength()) 3002 { 3003 aSqlCmd.append(::rtl::OUString::createFromAscii(" WHERE ")); 3004 aSqlCmd.append(aCriteriaListStr.makeStringAndClear()); 3005 } 3006 // ----------------- GroupBy aufbauen und Anh"angen ------------ 3007 Reference<XDatabaseMetaData> xMeta; 3008 if ( xConnection.is() ) 3009 xMeta = xConnection->getMetaData(); 3010 sal_Bool bUseAlias = nTabcount > 1; 3011 if ( xMeta.is() ) 3012 bUseAlias = bUseAlias || !xMeta->supportsGroupByUnrelated(); 3013 3014 aSqlCmd.append(GenerateGroupBy(this,rFieldList,bUseAlias)); 3015 // ----------------- having Anh"angen ------------ 3016 if(aHavingStr.getLength()) 3017 { 3018 aSqlCmd.append(::rtl::OUString::createFromAscii(" HAVING ")); 3019 aSqlCmd.append(aHavingStr.makeStringAndClear()); 3020 } 3021 // ----------------- Sortierung aufbauen und Anh"angen ------------ 3022 ::rtl::OUString sOrder; 3023 SqlParseError eErrorCode = eOk; 3024 if ( (eErrorCode = GenerateOrder(this,rFieldList,nTabcount > 1,sOrder)) == eOk) 3025 aSqlCmd.append(sOrder); 3026 else 3027 { 3028 if ( !m_rController.hasError() ) 3029 m_rController.appendError( getParseErrorMessage( eErrorCode ) ); 3030 3031 m_rController.displayError(); 3032 } 3033 3034 ::rtl::OUString sSQL = aSqlCmd.makeStringAndClear(); 3035 if ( xConnection.is() ) 3036 { 3037 ::connectivity::OSQLParser& rParser( rController.getParser() ); 3038 ::rtl::OUString sErrorMessage; 3039 ::std::auto_ptr<OSQLParseNode> pParseNode( rParser.parseTree( sErrorMessage, sSQL, sal_True ) ); 3040 if ( pParseNode.get() ) 3041 { 3042 OSQLParseNode* pNode = pParseNode->getChild(3)->getChild(1); 3043 if ( pNode->count() > 1 ) 3044 { 3045 ::connectivity::OSQLParseNode * pCondition = pNode->getChild(1); 3046 if ( pCondition ) // no where clause 3047 { 3048 OSQLParseNode::compress(pCondition); 3049 ::rtl::OUString sTemp; 3050 pParseNode->parseNodeToStr(sTemp,xConnection); 3051 sSQL = sTemp; 3052 } 3053 } 3054 } 3055 } 3056 return sSQL; 3057 } 3058 // ----------------------------------------------------------------------------- 3059 // ----------------------------------------------------------------------------- 3060 void OQueryDesignView::setSlotEnabled(sal_Int32 _nSlotId,sal_Bool _bEnable) 3061 { 3062 sal_uInt16 nRow; 3063 switch (_nSlotId) 3064 { 3065 case SID_QUERY_VIEW_FUNCTIONS: 3066 nRow = BROW_FUNCTION_ROW; 3067 break; 3068 case SID_QUERY_VIEW_TABLES: 3069 nRow = BROW_TABLE_ROW; 3070 break; 3071 case SID_QUERY_VIEW_ALIASES: 3072 nRow = BROW_COLUMNALIAS_ROW; 3073 break; 3074 default: 3075 // ???????????? 3076 nRow = 0; 3077 break; 3078 } 3079 m_pSelectionBox->SetRowVisible(nRow,_bEnable); 3080 m_pSelectionBox->Invalidate(); 3081 } 3082 // ----------------------------------------------------------------------------- 3083 sal_Bool OQueryDesignView::isSlotEnabled(sal_Int32 _nSlotId) 3084 { 3085 sal_uInt16 nRow; 3086 switch (_nSlotId) 3087 { 3088 case SID_QUERY_VIEW_FUNCTIONS: 3089 nRow = BROW_FUNCTION_ROW; 3090 break; 3091 case SID_QUERY_VIEW_TABLES: 3092 nRow = BROW_TABLE_ROW; 3093 break; 3094 case SID_QUERY_VIEW_ALIASES: 3095 nRow = BROW_COLUMNALIAS_ROW; 3096 break; 3097 default: 3098 // ????????? 3099 nRow = 0; 3100 break; 3101 } 3102 return m_pSelectionBox->IsRowVisible(nRow); 3103 } 3104 // ----------------------------------------------------------------------------- 3105 void OQueryDesignView::SaveUIConfig() 3106 { 3107 OQueryController& rCtrl = static_cast<OQueryController&>(getController()); 3108 rCtrl.SaveTabWinsPosSize( m_pTableView->GetTabWinMap(), m_pScrollWindow->GetHScrollBar()->GetThumbPos(), m_pScrollWindow->GetVScrollBar()->GetThumbPos() ); 3109 // rCtrl.SaveTabFieldsWidth( m_pSelectionBox ); 3110 rCtrl.setVisibleRows( m_pSelectionBox->GetNoneVisibleRows() ); 3111 if ( m_aSplitter.GetSplitPosPixel() != 0 ) 3112 rCtrl.setSplitPos( m_aSplitter.GetSplitPosPixel() ); 3113 } 3114 // ----------------------------------------------------------------------------- 3115 OSQLParseNode* OQueryDesignView::getPredicateTreeFromEntry(OTableFieldDescRef pEntry, 3116 const String& _sCriteria, 3117 ::rtl::OUString& _rsErrorMessage, 3118 Reference<XPropertySet>& _rxColumn) const 3119 { 3120 OSL_ENSURE(pEntry.isValid(),"Entry is null!"); 3121 if(!pEntry.isValid()) 3122 return NULL; 3123 Reference< XConnection> xConnection = static_cast<OQueryController&>(getController()).getConnection(); 3124 if(!xConnection.is()) 3125 return NULL; 3126 3127 ::connectivity::OSQLParser& rParser( static_cast<OQueryController&>(getController()).getParser() ); 3128 OQueryTableWindow* pWin = static_cast<OQueryTableWindow*>(pEntry->GetTabWindow()); 3129 3130 String sTest(_sCriteria); 3131 // special handling for functions 3132 if ( pEntry->GetFunctionType() & (FKT_OTHER | FKT_AGGREGATE | FKT_NUMERIC) ) 3133 { 3134 // we have a function here so we have to distinguish the type of return value 3135 String sFunction; 3136 if ( pEntry->isNumericOrAggreateFunction() ) 3137 sFunction = pEntry->GetFunction(); 3138 3139 if ( !sFunction.Len() ) 3140 sFunction = pEntry->GetField(); 3141 3142 if(sFunction.GetTokenCount('(') > 1) 3143 sFunction = sFunction.GetToken(0,'('); // this should be the name of the function 3144 3145 sal_Int32 nType = ::connectivity::OSQLParser::getFunctionReturnType(sFunction,&rParser.getContext()); 3146 if ( nType == DataType::OTHER || (!sFunction.Len() && pEntry->isNumericOrAggreateFunction()) ) 3147 { 3148 // first try the international version 3149 ::rtl::OUString sSql; 3150 sSql += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("SELECT * ")); 3151 sSql += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" FROM x WHERE ")); 3152 sSql += pEntry->GetField(); 3153 sSql += _sCriteria; 3154 ::std::auto_ptr<OSQLParseNode> pParseNode( rParser.parseTree( _rsErrorMessage, sSql, sal_True ) ); 3155 nType = DataType::DOUBLE; 3156 if ( pParseNode.get() ) 3157 { 3158 OSQLParseNode* pColumnRef = pParseNode->getByRule(OSQLParseNode::column_ref); 3159 if ( pColumnRef ) 3160 { 3161 OTableFieldDescRef aField = new OTableFieldDesc(); 3162 if ( eOk == FillDragInfo(this,pColumnRef,aField) ) 3163 { 3164 nType = aField->GetDataType(); 3165 } 3166 } 3167 } 3168 } 3169 3170 Reference<XDatabaseMetaData> xMeta = xConnection->getMetaData(); 3171 parse::OParseColumn* pColumn = new parse::OParseColumn( pEntry->GetField(), 3172 ::rtl::OUString(), 3173 ::rtl::OUString(), 3174 ::rtl::OUString(), 3175 ColumnValue::NULLABLE_UNKNOWN, 3176 0, 3177 0, 3178 nType, 3179 sal_False, 3180 sal_False, 3181 xMeta.is() && xMeta->supportsMixedCaseQuotedIdentifiers()); 3182 _rxColumn = pColumn; 3183 pColumn->setFunction(sal_True); 3184 pColumn->setRealName(pEntry->GetField()); 3185 } 3186 else 3187 { 3188 if (pWin) 3189 { 3190 Reference<XNameAccess> xColumns = pWin->GetOriginalColumns(); 3191 if (xColumns.is() && xColumns->hasByName(pEntry->GetField())) 3192 xColumns->getByName(pEntry->GetField()) >>= _rxColumn; 3193 } 3194 } 3195 3196 OSQLParseNode* pParseNode = rParser.predicateTree( _rsErrorMessage, 3197 sTest, 3198 static_cast<OQueryController&>(getController()).getNumberFormatter(), 3199 _rxColumn); 3200 return pParseNode; 3201 } 3202 // ----------------------------------------------------------------------------- 3203 void OQueryDesignView::GetFocus() 3204 { 3205 OQueryView::GetFocus(); 3206 if ( m_pSelectionBox && !m_pSelectionBox->HasChildPathFocus() ) 3207 { 3208 // first we have to deactivate the current cell to refill when nescessary 3209 m_pSelectionBox->DeactivateCell(); 3210 m_pSelectionBox->ActivateCell(m_pSelectionBox->GetCurRow(), m_pSelectionBox->GetCurColumnId()); 3211 m_pSelectionBox->GrabFocus(); 3212 } 3213 } 3214 // ----------------------------------------------------------------------------- 3215 void OQueryDesignView::reset() 3216 { 3217 m_pTableView->ClearAll(); 3218 m_pTableView->ReSync(); 3219 } 3220 // ----------------------------------------------------------------------------- 3221 void OQueryDesignView::setNoneVisbleRow(sal_Int32 _nRows) 3222 { 3223 m_pSelectionBox->SetNoneVisbleRow(_nRows); 3224 } 3225 3226 // ----------------------------------------------------------------------------- 3227 void OQueryDesignView::initByFieldDescriptions( const Sequence< PropertyValue >& i_rFieldDescriptions ) 3228 { 3229 OQueryController& rController = static_cast< OQueryController& >( getController() ); 3230 3231 m_pSelectionBox->PreFill(); 3232 m_pSelectionBox->SetReadOnly( rController.isReadOnly() ); 3233 m_pSelectionBox->Fill(); 3234 3235 for ( const PropertyValue* field = i_rFieldDescriptions.getConstArray(); 3236 field != i_rFieldDescriptions.getConstArray() + i_rFieldDescriptions.getLength(); 3237 ++field 3238 ) 3239 { 3240 ::vos::ORef< OTableFieldDesc > pField( new OTableFieldDesc() ); 3241 pField->Load( *field, true ); 3242 InsertField( pField, sal_True, sal_False ); 3243 } 3244 3245 rController.ClearUndoManager(); 3246 m_pSelectionBox->Invalidate(); 3247 } 3248 3249 // ----------------------------------------------------------------------------- 3250 bool OQueryDesignView::initByParseIterator( ::dbtools::SQLExceptionInfo* _pErrorInfo ) 3251 { 3252 SqlParseError eErrorCode = eNativeMode; 3253 m_rController.clearError(); 3254 3255 try 3256 { 3257 eErrorCode = InitFromParseNodeImpl( this, m_pSelectionBox ); 3258 3259 if ( eErrorCode != eOk ) 3260 { 3261 if ( !m_rController.hasError() ) 3262 m_rController.appendError( getParseErrorMessage( eErrorCode ) ); 3263 3264 if ( _pErrorInfo ) 3265 { 3266 *_pErrorInfo = m_rController.getError(); 3267 } 3268 else 3269 { 3270 m_rController.displayError(); 3271 } 3272 } 3273 } 3274 catch ( const Exception& ) 3275 { 3276 DBG_UNHANDLED_EXCEPTION(); 3277 } 3278 return eErrorCode == eOk; 3279 } 3280 //------------------------------------------------------------------------------ 3281 void OQueryDesignView::fillFunctionInfo( const ::connectivity::OSQLParseNode* pNode 3282 ,const ::rtl::OUString& sFunctionTerm 3283 ,OTableFieldDescRef& aInfo) 3284 { 3285 // get the type out of the funtion name 3286 OQueryController& rController = static_cast<OQueryController&>(getController()); 3287 sal_Int32 nDataType = DataType::DOUBLE; 3288 ::rtl::OUString sFieldName = sFunctionTerm; 3289 OSQLParseNode* pFunctionName = pNode->getChild(0); 3290 if ( !SQL_ISPUNCTUATION(pFunctionName,"{") ) 3291 { 3292 if ( SQL_ISRULEOR2(pNode,length_exp,char_value_fct) ) 3293 pFunctionName = pFunctionName->getChild(0); 3294 3295 ::rtl::OUString sFunctionName = pFunctionName->getTokenValue(); 3296 if ( !sFunctionName.getLength() ) 3297 sFunctionName = ::rtl::OStringToOUString(OSQLParser::TokenIDToStr(pFunctionName->getTokenID()),RTL_TEXTENCODING_UTF8); 3298 3299 nDataType = OSQLParser::getFunctionReturnType( 3300 sFunctionName 3301 ,&rController.getParser().getContext()); 3302 } 3303 aInfo->SetDataType(nDataType); 3304 aInfo->SetFieldType(TAB_NORMAL_FIELD); 3305 aInfo->SetField(sFieldName); 3306 aInfo->SetTabWindow(NULL); 3307 } 3308 // ----------------------------------------------------------------------------- 3309