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