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