1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include "QueryDesignView.hxx"
21 #include "QueryTableView.hxx"
22 #include "QTableWindow.hxx"
23 #include <vcl/toolbox.hxx>
24 #include "querycontroller.hxx"
25 #include <vcl/split.hxx>
26 #include <svl/undo.hxx>
27 #include <tools/diagnose_ex.h>
28 #include <osl/diagnose.h>
29 #include "adtabdlg.hxx"
30 #include <vcl/svapp.hxx>
31 #include <vcl/combobox.hxx>
32 #include <vcl/msgbox.hxx>
33 #include "browserids.hxx"
34 #include "SelectionBrowseBox.hxx"
35 #include "dbu_qry.hrc"
36 #include <unotools/configmgr.hxx>
37 #include <comphelper/extract.hxx>
38 #include <comphelper/string.hxx>
39 #include <comphelper/types.hxx>
40 #include <connectivity/dbtools.hxx>
41 #include <connectivity/dbexception.hxx>
42 #include <com/sun/star/i18n/XLocaleData.hpp>
43 #include <com/sun/star/sdbc/DataType.hpp>
44 #include <com/sun/star/container/XNameAccess.hpp>
45 #include <com/sun/star/sdbc/ColumnValue.hpp>
46 #include <connectivity/PColumn.hxx>
47 #include "QTableConnection.hxx"
48 #include "ConnectionLine.hxx"
49 #include "ConnectionLineData.hxx"
50 #include "QTableConnectionData.hxx"
51 #include "dbustrings.hrc"
52 #include "UITools.hxx"
53 #include "querycontainerwindow.hxx"
54 #include "sqlmessage.hxx"
55 #include <unotools/syslocale.hxx>
57 using namespace ::dbaui
;
58 using namespace ::utl
;
59 using namespace ::connectivity
;
60 using namespace ::dbtools
;
61 using namespace ::com::sun::star::uno
;
62 using namespace ::com::sun::star::lang
;
63 using namespace ::com::sun::star::i18n
;
64 using namespace ::com::sun::star::sdbc
;
65 using namespace ::com::sun::star::beans
;
66 using namespace ::com::sun::star::container
;
68 // here we define our functions used in the anonymous namespace to get our header file smaller
69 // please look at the book LargeScale C++ to know why
72 static const OUString
C_AND(" AND ");
73 static const OUString
C_OR(" OR ");
75 // forward declarations
76 sal_Bool
InsertJoin( const OQueryDesignView
* _pView
,
77 const ::connectivity::OSQLParseNode
*pNode
);
79 SqlParseError
InstallFields(OQueryDesignView
* _pView
,
80 const ::connectivity::OSQLParseNode
* pNode
,
81 OJoinTableView::OTableWindowMap
* pTabList
);
83 SqlParseError
GetGroupCriteria( OQueryDesignView
* _pView
,
84 OSelectionBrowseBox
* _pSelectionBrw
,
85 const ::connectivity::OSQLParseNode
* pSelectRoot
);
87 SqlParseError
GetHavingCriteria(OQueryDesignView
* _pView
,
88 OSelectionBrowseBox
* _pSelectionBrw
,
89 const ::connectivity::OSQLParseNode
* pSelectRoot
,
92 SqlParseError
GetOrderCriteria( OQueryDesignView
* _pView
,
93 OSelectionBrowseBox
* _pSelectionBrw
,
94 const ::connectivity::OSQLParseNode
* pParseRoot
);
96 SqlParseError
AddFunctionCondition(OQueryDesignView
* _pView
,
97 OSelectionBrowseBox
* _pSelectionBrw
,
98 const ::connectivity::OSQLParseNode
* pCondition
,
99 const sal_uInt16 nLevel
,
101 bool _bAddOrOnOneLine
);
103 //------------------------------------------------------------------------------
104 OUString
quoteTableAlias(sal_Bool _bQuote
, const OUString
& _sAliasName
, const OUString
& _sQuote
)
107 if ( _bQuote
&& !_sAliasName
.isEmpty() )
109 sRet
= ::dbtools::quoteName(_sQuote
,_sAliasName
);
110 const static OUString
sTableSeparater('.');
111 sRet
+= sTableSeparater
;
115 //------------------------------------------------------------------------------
116 OUString
getTableRange(const OQueryDesignView
* _pView
,const ::connectivity::OSQLParseNode
* _pTableRef
)
118 Reference
< XConnection
> xConnection
= static_cast<OQueryController
&>(_pView
->getController()).getConnection();
119 OUString sTableRange
;
122 sTableRange
= ::connectivity::OSQLParseNode::getTableRange(_pTableRef
);
123 if ( sTableRange
.isEmpty() )
124 _pTableRef
->parseNodeToStr(sTableRange
,xConnection
,NULL
,sal_False
,sal_False
);
128 //------------------------------------------------------------------------------
129 void insertConnection(const OQueryDesignView
* _pView
,const EJoinType
& _eJoinType
,OTableFieldDescRef _aDragLeft
,OTableFieldDescRef _aDragRight
,bool _bNatural
= false)
131 OQueryTableView
* pTableView
= static_cast<OQueryTableView
*>(_pView
->getTableView());
132 OQueryTableConnection
* pConn
= static_cast<OQueryTableConnection
*>( pTableView
->GetTabConn(static_cast<OTableWindow
*>(_aDragLeft
->GetTabWindow()),static_cast<OTableWindow
*>(_aDragRight
->GetTabWindow()),true));
136 OQueryTableConnectionData
* pInfoData
= new OQueryTableConnectionData();
137 TTableConnectionData::value_type
aInfoData(pInfoData
);
138 pInfoData
->InitFromDrag(_aDragLeft
, _aDragRight
);
139 pInfoData
->SetJoinType(_eJoinType
);
143 aInfoData
->ResetConnLines();
144 pInfoData
->setNatural(_bNatural
);
147 Reference
<XNameAccess
> xReferencedTableColumns(aInfoData
->getReferencedTable()->getColumns());
148 Sequence
< OUString
> aSeq
= aInfoData
->getReferencingTable()->getColumns()->getElementNames();
149 const OUString
* pIter
= aSeq
.getConstArray();
150 const OUString
* pEnd
= pIter
+ aSeq
.getLength();
151 for(;pIter
!= pEnd
;++pIter
)
153 if ( xReferencedTableColumns
->hasByName(*pIter
) )
154 aInfoData
->AppendConnLine(*pIter
,*pIter
);
157 catch( const Exception
& )
159 DBG_UNHANDLED_EXCEPTION();
163 OQueryTableConnection
aInfo(pTableView
, aInfoData
);
164 // Because OQueryTableConnection never takes ownership of the data passed to it, but only remembers the pointer,
165 // this pointer to a local variable is not critical, as aInfoData and aInfo have the same lifetime
166 pTableView
->NotifyTabConnection( aInfo
);
170 OUString
aSourceFieldName(_aDragLeft
->GetField());
171 OUString
aDestFieldName(_aDragRight
->GetField());
172 // the connection could point on the other side
173 if(pConn
->GetSourceWin() == _aDragRight
->GetTabWindow())
175 OUString
aTmp(aSourceFieldName
);
176 aSourceFieldName
= aDestFieldName
;
177 aDestFieldName
= aTmp
;
179 pConn
->GetData()->AppendConnLine( aSourceFieldName
,aDestFieldName
);
180 pConn
->UpdateLineList();
184 pConn
->RecalcLines();
185 // for the following Invalidate, the new Connection must first be able
186 // to determine its BoundingRect
187 pConn
->InvalidateConnection();
190 //------------------------------------------------------------------------------
191 OUString
ParseCondition( OQueryController
& rController
192 ,const ::connectivity::OSQLParseNode
* pCondition
193 ,const OUString _sDecimal
194 ,const ::com::sun::star::lang::Locale
& _rLocale
195 ,sal_uInt32 _nStartIndex
)
198 Reference
< XConnection
> xConnection
= rController
.getConnection();
199 if ( xConnection
.is() )
201 sal_uInt32 nCount
= pCondition
->count();
202 for(sal_uInt32 i
= _nStartIndex
; i
< nCount
; ++i
)
203 pCondition
->getChild(i
)->parseNodeToPredicateStr(aCondition
,
205 rController
.getNumberFormatter(),
207 static_cast<sal_Char
>(_sDecimal
.toChar()),
208 &rController
.getParser().getContext());
212 //------------------------------------------------------------------------------
213 SqlParseError
FillOuterJoins(OQueryDesignView
* _pView
,
214 const ::connectivity::OSQLParseNode
* pTableRefList
)
216 SqlParseError eErrorCode
= eOk
;
217 sal_uInt32 nCount
= pTableRefList
->count();
218 sal_Bool bError
= sal_False
;
219 for (sal_uInt32 i
=0; !bError
&& i
< nCount
; ++i
)
221 const ::connectivity::OSQLParseNode
* pParseNode
= pTableRefList
->getChild(i
);
222 const ::connectivity::OSQLParseNode
* pJoinNode
= NULL
;
224 if ( SQL_ISRULE( pParseNode
, qualified_join
) || SQL_ISRULE( pParseNode
, joined_table
) || SQL_ISRULE( pParseNode
, cross_union
) )
225 pJoinNode
= pParseNode
;
226 else if( SQL_ISRULE(pParseNode
,table_ref
)
227 && pParseNode
->count() == 4 ) // '{' SQL_TOKEN_OJ joined_table '}'
228 pJoinNode
= pParseNode
->getChild(2);
232 if ( !InsertJoin(_pView
,pJoinNode
) )
236 // check if error occurred
238 eErrorCode
= eIllegalJoin
;
242 // -----------------------------------------------------------------------------
244 /** FillDragInfo fills the field description out of the table
246 //------------------------------------------------------------------------------
247 SqlParseError
FillDragInfo( const OQueryDesignView
* _pView
,
248 const ::connectivity::OSQLParseNode
* pColumnRef
,
249 OTableFieldDescRef
& _rDragInfo
)
251 SqlParseError eErrorCode
= eOk
;
253 sal_Bool bErg
= sal_False
;
255 OUString aTableRange
,aColumnName
;
256 sal_uInt16 nCntAccount
;
257 ::connectivity::OSQLParseTreeIterator
& rParseIter
= static_cast<OQueryController
&>(_pView
->getController()).getParseIterator();
258 rParseIter
.getColumnRange( pColumnRef
, aColumnName
, aTableRange
);
260 if ( !aTableRange
.isEmpty() )
262 OQueryTableWindow
* pSTW
= static_cast<OQueryTableView
*>(_pView
->getTableView())->FindTable( aTableRange
);
263 bErg
= (pSTW
&& pSTW
->ExistsField( aColumnName
, _rDragInfo
) );
267 bErg
= static_cast<OQueryTableView
*>(_pView
->getTableView())->FindTableFromField(aColumnName
, _rDragInfo
, nCntAccount
);
269 bErg
= _pView
->HasFieldByAliasName(aColumnName
, _rDragInfo
);
273 eErrorCode
= eColumnNotFound
;
274 String
sError(ModuleRes(STR_QRY_COLUMN_NOT_FOUND
));
275 sError
.SearchAndReplaceAscii("$name$",aColumnName
);
276 _pView
->getController().appendError( sError
);
280 Reference
<XDatabaseMetaData
> xMeta
= _pView
->getController().getConnection()->getMetaData();
281 if ( xMeta
.is() && xMeta
->supportsMixedCaseQuotedIdentifiers() )
282 _pView
->getController().appendError( String( ModuleRes( STR_QRY_CHECK_CASESENSITIVE
) ) );
291 //------------------------------------------------------------------------------
292 OUString
BuildJoinCriteria( const Reference
< XConnection
>& _xConnection
,
293 const OConnectionLineDataVec
* pLineDataList
,
294 const OQueryTableConnectionData
* pData
)
296 OUStringBuffer aCondition
;
297 if ( _xConnection
.is() )
299 OConnectionLineDataVec::const_iterator aIter
= pLineDataList
->begin();
300 OConnectionLineDataVec::const_iterator aEnd
= pLineDataList
->end();
303 const Reference
< XDatabaseMetaData
> xMetaData
= _xConnection
->getMetaData();
304 const OUString aQuote
= xMetaData
->getIdentifierQuoteString();
305 const OUString
sEqual(" = ");
307 for(;aIter
!= aEnd
;++aIter
)
309 OConnectionLineDataRef pLineData
= *aIter
;
310 if(aCondition
.getLength())
311 aCondition
.append(C_AND
);
312 aCondition
.append(quoteTableAlias(sal_True
,pData
->GetAliasName(JTCS_FROM
),aQuote
));
313 aCondition
.append(::dbtools::quoteName(aQuote
, pLineData
->GetFieldName(JTCS_FROM
) ));
314 aCondition
.append(sEqual
);
315 aCondition
.append(quoteTableAlias(sal_True
,pData
->GetAliasName(JTCS_TO
),aQuote
));
316 aCondition
.append(::dbtools::quoteName(aQuote
, pLineData
->GetFieldName(JTCS_TO
) ));
321 OSL_FAIL("Failure while building Join criteria!");
325 return aCondition
.makeStringAndClear();
327 //------------------------------------------------------------------------------
328 /** JoinCycle looks for a join cycle and append it to the string
329 @param _xConnection the connection
330 @param _pEntryConn the table connection which holds the data
331 @param _pEntryTabTo the corresponding table window
332 @param _rJoin the String which will contain the resulting string
334 void JoinCycle( const Reference
< XConnection
>& _xConnection
,
335 OQueryTableConnection
* _pEntryConn
,
336 const OQueryTableWindow
* _pEntryTabTo
,
339 OSL_ENSURE(_pEntryConn
,"TableConnection can not be null!");
341 OQueryTableConnectionData
* pData
= static_cast< OQueryTableConnectionData
*>(_pEntryConn
->GetData().get());
342 if ( pData
->GetJoinType() != INNER_JOIN
&& _pEntryTabTo
->ExistsAVisitedConn() )
344 sal_Bool bBrace
= sal_False
;
345 if(!_rJoin
.isEmpty() && _rJoin
.lastIndexOf(')') == (_rJoin
.getLength()-1))
348 _rJoin
= _rJoin
.replaceAt(_rJoin
.getLength()-1,1,OUString(' '));
350 (_rJoin
+= C_AND
) += BuildJoinCriteria(_xConnection
,pData
->GetConnLineDataList(),pData
);
352 _rJoin
+= OUString(')');
353 _pEntryConn
->SetVisited(sal_True
);
356 //------------------------------------------------------------------------------
357 OUString
BuildTable( const Reference
< XConnection
>& _xConnection
,
358 const OQueryTableWindow
* pEntryTab
,
362 OUString
aDBName(pEntryTab
->GetComposedName());
364 if( _xConnection
.is() )
368 Reference
< XDatabaseMetaData
> xMetaData
= _xConnection
->getMetaData();
370 OUString sCatalog
, sSchema
, sTable
;
371 ::dbtools::qualifiedNameComponents( xMetaData
, aDBName
, sCatalog
, sSchema
, sTable
, ::dbtools::eInDataManipulation
);
372 OUString aTableListStr
= ::dbtools::composeTableNameForSelect( _xConnection
, sCatalog
, sSchema
, sTable
);
374 OUString aQuote
= xMetaData
->getIdentifierQuoteString();
375 if ( _bForce
|| isAppendTableAliasEnabled( _xConnection
) || pEntryTab
->GetAliasName() != aDBName
)
377 aTableListStr
+= " ";
378 if ( generateAsBeforeTableAlias( _xConnection
) )
379 aTableListStr
+= "AS ";
380 aTableListStr
+= ::dbtools::quoteName( aQuote
, pEntryTab
->GetAliasName() );
382 aDBName
= aTableListStr
;
384 catch(const SQLException
&)
386 DBG_UNHANDLED_EXCEPTION();
391 //------------------------------------------------------------------------------
392 OUString
BuildJoin( const Reference
< XConnection
>& _xConnection
,
395 const OQueryTableConnectionData
* pData
)
399 if ( pData
->isNatural() && pData
->GetJoinType() != CROSS_JOIN
)
401 switch(pData
->GetJoinType())
404 aErg
+= " LEFT OUTER ";
407 aErg
+= " RIGHT OUTER ";
410 OSL_ENSURE(!pData
->isNatural(),"OQueryDesignView::BuildJoin: This should not happen!");
414 OSL_ENSURE(pData
->isNatural(),"OQueryDesignView::BuildJoin: This should not happen!");
418 aErg
+= " FULL OUTER ";
423 if ( CROSS_JOIN
!= pData
->GetJoinType() && !pData
->isNatural() )
426 aErg
+= BuildJoinCriteria(_xConnection
,pData
->GetConnLineDataList(),pData
);
431 //------------------------------------------------------------------------------
432 OUString
BuildJoin( const Reference
< XConnection
>& _xConnection
,
433 const OQueryTableWindow
* pLh
,
434 const OQueryTableWindow
* pRh
,
435 const OQueryTableConnectionData
* pData
438 bool bForce
= pData
->GetJoinType() == CROSS_JOIN
|| pData
->isNatural();
439 return BuildJoin(_xConnection
,BuildTable(_xConnection
,pLh
,bForce
),BuildTable(_xConnection
,pRh
,bForce
),pData
);
441 //------------------------------------------------------------------------------
442 OUString
BuildJoin( const Reference
< XConnection
>& _xConnection
,
444 const OQueryTableWindow
* pRh
,
445 const OQueryTableConnectionData
* pData
448 return BuildJoin(_xConnection
,rLh
,BuildTable(_xConnection
,pRh
),pData
);
450 //------------------------------------------------------------------------------
451 OUString
BuildJoin( const Reference
< XConnection
>& _xConnection
,
452 const OQueryTableWindow
* pLh
,
454 const OQueryTableConnectionData
* pData
458 // - does not support any bracketing of JOINS
459 // - supports nested joins only in the LEFT HAND SIDE
460 // In this case, we are trying to build a join with a nested join
461 // in the right hand side.
462 // So switch the direction of the join and both hand sides.
463 OQueryTableConnectionData
data(*pData
);
464 switch (data
.GetJoinType())
467 data
.SetJoinType(RIGHT_JOIN
);
470 data
.SetJoinType(LEFT_JOIN
);
473 // the other join types are symmetric, so nothing to change
476 return BuildJoin(_xConnection
, rRh
, BuildTable(_xConnection
,pLh
), &data
);
478 //------------------------------------------------------------------------------
479 typedef ::std::map
< OUString
,sal_Bool
,::comphelper::UStringMixLess
> tableNames_t
;
480 //------------------------------------------------------------------------------
481 void addConnectionTableNames( const Reference
< XConnection
>& _xConnection
,
482 const OQueryTableConnection
* const pEntryConn
,
483 tableNames_t
&_rTableNames
)
485 // insert tables into table list to avoid double entries
486 const OQueryTableWindow
* const pEntryTabFrom
= static_cast<OQueryTableWindow
*>(pEntryConn
->GetSourceWin());
487 const OQueryTableWindow
* const pEntryTabTo
= static_cast<OQueryTableWindow
*>(pEntryConn
->GetDestWin());
489 OUString
sTabName(BuildTable(_xConnection
,pEntryTabFrom
));
490 if(_rTableNames
.find(sTabName
) == _rTableNames
.end())
491 _rTableNames
[sTabName
] = sal_True
;
492 sTabName
= BuildTable(_xConnection
,pEntryTabTo
);
493 if(_rTableNames
.find(sTabName
) == _rTableNames
.end())
494 _rTableNames
[sTabName
] = sal_True
;
496 //------------------------------------------------------------------------------
497 void GetNextJoin( const Reference
< XConnection
>& _xConnection
,
498 OQueryTableConnection
* pEntryConn
,
499 OQueryTableWindow
* pEntryTabTo
,
501 tableNames_t
&_rTableNames
)
503 OQueryTableConnectionData
* pEntryConnData
= static_cast<OQueryTableConnectionData
*>(pEntryConn
->GetData().get());
504 if ( pEntryConnData
->GetJoinType() == INNER_JOIN
&& !pEntryConnData
->isNatural() )
509 addConnectionTableNames(_xConnection
, pEntryConn
, _rTableNames
);
510 OQueryTableWindow
* pEntryTabFrom
= static_cast<OQueryTableWindow
*>(pEntryConn
->GetSourceWin());
511 aJoin
= BuildJoin(_xConnection
,pEntryTabFrom
,pEntryTabTo
,pEntryConnData
);
513 else if(pEntryTabTo
== pEntryConn
->GetDestWin())
515 addConnectionTableNames(_xConnection
, pEntryConn
, _rTableNames
);
516 aJoin
= BuildJoin(_xConnection
,aJoin
,pEntryTabTo
,pEntryConnData
);
518 else if(pEntryTabTo
== pEntryConn
->GetSourceWin())
520 addConnectionTableNames(_xConnection
, pEntryConn
, _rTableNames
);
521 aJoin
= BuildJoin(_xConnection
,pEntryTabTo
,aJoin
,pEntryConnData
);
524 pEntryConn
->SetVisited(sal_True
);
526 // first search for the "to" window
527 const ::std::vector
<OTableConnection
*>* pConnections
= pEntryConn
->GetParent()->getTableConnections();
528 ::std::vector
<OTableConnection
*>::const_iterator aIter
= pConnections
->begin();
529 ::std::vector
<OTableConnection
*>::const_iterator aEnd
= pConnections
->end();
530 for(;aIter
!= aEnd
;++aIter
)
532 OQueryTableConnection
* pNext
= static_cast<OQueryTableConnection
*>(*aIter
);
533 if(!pNext
->IsVisited() && (pNext
->GetSourceWin() == pEntryTabTo
|| pNext
->GetDestWin() == pEntryTabTo
))
535 OQueryTableWindow
* pEntryTab
= pNext
->GetSourceWin() == pEntryTabTo
? static_cast<OQueryTableWindow
*>(pNext
->GetDestWin()) : static_cast<OQueryTableWindow
*>(pNext
->GetSourceWin());
536 // exists there a connection to a OQueryTableWindow that holds a connection that has been already visited
537 JoinCycle(_xConnection
,pNext
,pEntryTab
,aJoin
);
538 if(!pNext
->IsVisited())
539 GetNextJoin(_xConnection
, pNext
, pEntryTab
, aJoin
, _rTableNames
);
543 // when nothing found found look for the "from" window
546 OQueryTableWindow
* pEntryTabFrom
= static_cast<OQueryTableWindow
*>(pEntryConn
->GetSourceWin());
547 aIter
= pConnections
->begin();
548 for(;aIter
!= aEnd
;++aIter
)
550 OQueryTableConnection
* pNext
= static_cast<OQueryTableConnection
*>(*aIter
);
551 if(!pNext
->IsVisited() && (pNext
->GetSourceWin() == pEntryTabFrom
|| pNext
->GetDestWin() == pEntryTabFrom
))
553 OQueryTableWindow
* pEntryTab
= pNext
->GetSourceWin() == pEntryTabFrom
? static_cast<OQueryTableWindow
*>(pNext
->GetDestWin()) : static_cast<OQueryTableWindow
*>(pNext
->GetSourceWin());
554 // exists there a connection to a OQueryTableWindow that holds a connection that has been already visited
555 JoinCycle(_xConnection
,pNext
,pEntryTab
,aJoin
);
556 if(!pNext
->IsVisited())
557 GetNextJoin(_xConnection
, pNext
, pEntryTab
, aJoin
, _rTableNames
);
562 //------------------------------------------------------------------------------
563 SqlParseError
InsertJoinConnection( const OQueryDesignView
* _pView
,
564 const ::connectivity::OSQLParseNode
*pNode
,
565 const EJoinType
& _eJoinType
,
566 const ::connectivity::OSQLParseNode
*pLeftTable
,
567 const ::connectivity::OSQLParseNode
*pRightTable
)
569 SqlParseError eErrorCode
= eOk
;
570 if (pNode
->count() == 3 && // statement between brackets
571 SQL_ISPUNCTUATION(pNode
->getChild(0),"(") &&
572 SQL_ISPUNCTUATION(pNode
->getChild(2),")"))
574 eErrorCode
= InsertJoinConnection(_pView
,pNode
->getChild(1), _eJoinType
,pLeftTable
,pRightTable
);
576 else if (SQL_ISRULEOR2(pNode
,search_condition
,boolean_term
) && // AND/OR-joints:
579 // only allow AND joints
580 if (!SQL_ISTOKEN(pNode
->getChild(1),AND
))
581 eErrorCode
= eIllegalJoinCondition
;
582 else if ( eOk
== (eErrorCode
= InsertJoinConnection(_pView
,pNode
->getChild(0), _eJoinType
,pLeftTable
,pRightTable
)) )
583 eErrorCode
= InsertJoinConnection(_pView
,pNode
->getChild(2), _eJoinType
,pLeftTable
,pRightTable
);
585 else if (SQL_ISRULE(pNode
,comparison_predicate
))
587 // only the comparison of columns is allowed
588 OSL_ENSURE(pNode
->count() == 3,"OQueryDesignView::InsertJoinConnection: Error in Parse Tree");
589 if (!(SQL_ISRULE(pNode
->getChild(0),column_ref
) &&
590 SQL_ISRULE(pNode
->getChild(2),column_ref
) &&
591 pNode
->getChild(1)->getNodeType() == SQL_NODE_EQUAL
))
593 String
sError(ModuleRes(STR_QRY_JOIN_COLUMN_COMPARE
));
594 _pView
->getController().appendError( sError
);
598 OTableFieldDescRef aDragLeft
= new OTableFieldDesc();
599 OTableFieldDescRef aDragRight
= new OTableFieldDesc();
600 if ( eOk
!= ( eErrorCode
= FillDragInfo(_pView
,pNode
->getChild(0),aDragLeft
)) ||
601 eOk
!= ( eErrorCode
= FillDragInfo(_pView
,pNode
->getChild(2),aDragRight
)))
606 OQueryTableWindow
* pLeftWindow
= static_cast<OQueryTableView
*>(_pView
->getTableView())->FindTable( getTableRange(_pView
,pLeftTable
->getByRule(OSQLParseNode::table_ref
) ));
607 if ( pLeftWindow
== aDragLeft
->GetTabWindow() )
608 insertConnection(_pView
,_eJoinType
,aDragLeft
,aDragRight
);
610 insertConnection(_pView
,_eJoinType
,aDragRight
,aDragLeft
);
613 insertConnection(_pView
,_eJoinType
,aDragLeft
,aDragRight
);
616 eErrorCode
= eIllegalJoin
;
619 //------------------------------------------------------------------------------
620 sal_Bool
GetInnerJoinCriteria( const OQueryDesignView
* _pView
,
621 const ::connectivity::OSQLParseNode
*pCondition
)
623 return InsertJoinConnection(_pView
,pCondition
, INNER_JOIN
,NULL
,NULL
) != eOk
;
625 //------------------------------------------------------------------------------
626 OUString
GenerateSelectList( const OQueryDesignView
* _pView
,
627 OTableFields
& _rFieldList
,
630 Reference
< XConnection
> xConnection
= static_cast<OQueryController
&>(_pView
->getController()).getConnection();
631 if ( !xConnection
.is() )
634 OUStringBuffer aTmpStr
,aFieldListStr
;
636 sal_Bool bAsterix
= sal_False
;
638 OTableFields::iterator aIter
= _rFieldList
.begin();
639 OTableFields::iterator aEnd
= _rFieldList
.end();
640 for(;aIter
!= aEnd
;++aIter
)
642 OTableFieldDescRef pEntryField
= *aIter
;
643 if ( pEntryField
->IsVisible() )
645 if ( pEntryField
->GetField().toChar() == '*' )
651 bAsterix
= sal_False
;
655 const Reference
< XDatabaseMetaData
> xMetaData
= xConnection
->getMetaData();
656 const OUString aQuote
= xMetaData
->getIdentifierQuoteString();
658 OJoinTableView::OTableWindowMap
* pTabList
= _pView
->getTableView()->GetTabWinMap();
660 const static OUString
sFieldSeparator(", ");
661 const static OUString
s_sAs(" AS ");
663 aIter
= _rFieldList
.begin();
664 for(;aIter
!= aEnd
;++aIter
)
666 OTableFieldDescRef pEntryField
= *aIter
;
667 OUString rFieldName
= pEntryField
->GetField();
668 if ( !rFieldName
.isEmpty() && pEntryField
->IsVisible() )
670 aTmpStr
= OUString();
671 const OUString rAlias
= pEntryField
->GetAlias();
672 const OUString rFieldAlias
= pEntryField
->GetFieldAlias();
674 aTmpStr
.append(quoteTableAlias((bAlias
|| bAsterix
),rAlias
,aQuote
));
676 // if we have a none numeric field, the table alias could be in the name
677 // otherwise we are not allowed to do this (e.g. 0.1 * PRICE )
678 if ( !pEntryField
->isOtherFunction() )
680 // we have to look if we have alias.* here but before we have to check if the column doesn't already exist
681 OTableFieldDescRef aInfo
= new OTableFieldDesc();
682 OJoinTableView::OTableWindowMap::iterator tableIter
= pTabList
->begin();
683 OJoinTableView::OTableWindowMap::iterator tableEnd
= pTabList
->end();
684 sal_Bool bFound
= sal_False
;
685 for(;!bFound
&& tableIter
!= tableEnd
;++tableIter
)
687 OQueryTableWindow
* pTabWin
= static_cast<OQueryTableWindow
*>(tableIter
->second
);
689 bFound
= pTabWin
->ExistsField( rFieldName
, aInfo
);
691 rFieldName
= aInfo
->GetField();
693 if ( ( rFieldName
.toChar() != '*' ) && ( rFieldName
.indexOf( aQuote
) == -1 ) )
695 OSL_ENSURE(!pEntryField
->GetTable().isEmpty(),"No table field name!");
696 aTmpStr
.append(::dbtools::quoteName(aQuote
, rFieldName
));
699 aTmpStr
.append(rFieldName
);
702 aTmpStr
.append(rFieldName
);
704 if ( pEntryField
->isAggreateFunction() )
706 OSL_ENSURE(!pEntryField
->GetFunction().isEmpty(),"Function name must not be empty! ;-(");
707 OUStringBuffer
aTmpStr2( pEntryField
->GetFunction());
708 aTmpStr2
.appendAscii("(");
709 aTmpStr2
.append(aTmpStr
.makeStringAndClear());
710 aTmpStr2
.appendAscii(")");
714 if (!rFieldAlias
.isEmpty() &&
715 (rFieldName
.toChar() != '*' ||
716 pEntryField
->isNumericOrAggreateFunction() ||
717 pEntryField
->isOtherFunction()))
719 aTmpStr
.append(s_sAs
);
720 aTmpStr
.append(::dbtools::quoteName(aQuote
, rFieldAlias
));
722 aFieldListStr
.append(aTmpStr
.makeStringAndClear());
723 aFieldListStr
.append(sFieldSeparator
);
726 if(aFieldListStr
.getLength())
727 aFieldListStr
.setLength(aFieldListStr
.getLength()-2);
731 OSL_FAIL("Failure while building select list!");
733 return aFieldListStr
.makeStringAndClear();
735 //------------------------------------------------------------------------------
736 sal_Bool
GenerateCriterias( OQueryDesignView
* _pView
,
737 OUStringBuffer
& rRetStr
,
738 OUStringBuffer
& rHavingStr
,
739 OTableFields
& _rFieldList
,
742 // * must not contain a filter : have I already shown the correct warning ?
743 sal_Bool bCritsOnAsterikWarning
= sal_False
; // ** TMFS **
745 OUString aFieldName
,aCriteria
,aWhereStr
,aHavingStr
,aWork
/*,aOrderStr*/;
746 // print line by line joined with AND
747 sal_uInt16 nMaxCriteria
= 0;
748 OTableFields::iterator aIter
= _rFieldList
.begin();
749 OTableFields::iterator aEnd
= _rFieldList
.end();
750 for(;aIter
!= aEnd
;++aIter
)
752 nMaxCriteria
= ::std::max
<sal_uInt16
>(nMaxCriteria
,(sal_uInt16
)(*aIter
)->GetCriteria().size());
754 Reference
< XConnection
> xConnection
= static_cast<OQueryController
&>(_pView
->getController()).getConnection();
755 if(!xConnection
.is())
759 const Reference
< XDatabaseMetaData
> xMetaData
= xConnection
->getMetaData();
760 const OUString aQuote
= xMetaData
->getIdentifierQuoteString();
761 const IParseContext
& rContext
= static_cast<OQueryController
&>(_pView
->getController()).getParser().getContext();
763 for (sal_uInt16 i
=0 ; i
< nMaxCriteria
; i
++)
765 aHavingStr
= aWhereStr
= OUString();
767 for(aIter
= _rFieldList
.begin();aIter
!= aEnd
;++aIter
)
769 OTableFieldDescRef pEntryField
= *aIter
;
770 aFieldName
= pEntryField
->GetField();
772 if (aFieldName
.isEmpty())
774 aCriteria
= pEntryField
->GetCriteria( i
);
775 if ( !aCriteria
.isEmpty() )
777 // * is not allowed to contain any filter, only when used in combination an aggregate function
778 if ( aFieldName
.toChar() == '*' && pEntryField
->isNoneFunction() )
780 // only show the messagebox the first time
781 if (!bCritsOnAsterikWarning
)
782 ErrorBox(_pView
, ModuleRes( ERR_QRY_CRITERIA_ON_ASTERISK
)).Execute();
783 bCritsOnAsterikWarning
= sal_True
;
789 aWork
+= quoteTableAlias(bMulti
,pEntryField
->GetAlias(),aQuote
);
791 if ( (pEntryField
->GetFunctionType() & (FKT_OTHER
|FKT_NUMERIC
)) || (aFieldName
.toChar() == '*') )
794 aWork
+= ::dbtools::quoteName(aQuote
, aFieldName
);
796 if ( pEntryField
->isAggreateFunction() || pEntryField
->IsGroupBy() )
798 if (aHavingStr
.isEmpty()) // no more criteria
799 aHavingStr
+= OUString('('); // bracket
803 if ( pEntryField
->isAggreateFunction() )
805 OSL_ENSURE(!pEntryField
->GetFunction().isEmpty(),"No function name for aggregate given!");
806 aHavingStr
+= pEntryField
->GetFunction();
807 aHavingStr
+= OUString('('); // bracket
809 aHavingStr
+= OUString(')'); // bracket
814 OUString aTmp
= aCriteria
;
816 Reference
<XPropertySet
> xColumn
;
817 SAL_WNODEPRECATED_DECLARATIONS_PUSH
818 ::std::auto_ptr
< ::connectivity::OSQLParseNode
> pParseNode(_pView
->getPredicateTreeFromEntry(pEntryField
,aTmp
,aErrorMsg
,xColumn
));
819 SAL_WNODEPRECATED_DECLARATIONS_POP
820 if (pParseNode
.get())
822 if (bMulti
&& !(pEntryField
->isOtherFunction() || (aFieldName
.toChar() == '*')))
823 pParseNode
->replaceNodeValue(pEntryField
->GetAlias(),aFieldName
);
824 OUString sHavingStr
= aHavingStr
;
826 sal_uInt32 nCount
= pParseNode
->count();
827 for( sal_uInt32 node
= 1 ; node
< nCount
; ++node
)
828 pParseNode
->getChild(node
)->parseNodeToStr( sHavingStr
,
832 !pEntryField
->isOtherFunction());
833 aHavingStr
= sHavingStr
;
836 aHavingStr
+= aCriteria
;
840 if ( aWhereStr
.isEmpty() ) // no more criteria
841 aWhereStr
+= OUString('('); // bracket
845 aWhereStr
+= OUString(' ');
846 // aCriteria could have some german numbers so I have to be sure here
847 OUString aTmp
= aCriteria
;
849 Reference
<XPropertySet
> xColumn
;
850 SAL_WNODEPRECATED_DECLARATIONS_PUSH
851 ::std::auto_ptr
< ::connectivity::OSQLParseNode
> pParseNode( _pView
->getPredicateTreeFromEntry(pEntryField
,aTmp
,aErrorMsg
,xColumn
));
852 SAL_WNODEPRECATED_DECLARATIONS_POP
853 if (pParseNode
.get())
855 if (bMulti
&& !(pEntryField
->isOtherFunction() || (aFieldName
.toChar() == '*')))
856 pParseNode
->replaceNodeValue(pEntryField
->GetAlias(),aFieldName
);
857 OUString aWhere
= aWhereStr
;
858 pParseNode
->parseNodeToStr( aWhere
,
862 !pEntryField
->isOtherFunction() );
867 aWhereStr
+= aWork
+ "=" + aCriteria
;
871 // only once for each field
872 else if ( !i
&& pEntryField
->isCondition() )
874 if (aWhereStr
.isEmpty()) // no more criteria
875 aWhereStr
+= OUString('('); // bracket
878 aWhereStr
+= pEntryField
->GetField();
881 if (!aWhereStr
.isEmpty())
883 aWhereStr
+= OUString(')'); // close bracket for the AND branch
884 if (rRetStr
.getLength()) // are there conditions on the field?
885 rRetStr
.append(C_OR
);
886 else // open bracket for the OR branch
887 rRetStr
.append(sal_Unicode('('));
888 rRetStr
.append(aWhereStr
);
890 if (!aHavingStr
.isEmpty())
892 aHavingStr
+= OUString(')'); // close bracket for the AND branch
893 if (rHavingStr
.getLength()) // are there conditions on the field?
894 rHavingStr
.append(C_OR
);
895 else // Open bracket for the OR branch
896 rHavingStr
.append(sal_Unicode('('));
897 rHavingStr
.append(aHavingStr
);
901 if (rRetStr
.getLength())
902 rRetStr
.append(sal_Unicode(')')); // close bracket for the OR branch
903 if (rHavingStr
.getLength())
904 rHavingStr
.append(sal_Unicode(')')); // close bracket for the OR branch
908 OSL_FAIL("Failure while building where clause!");
912 //------------------------------------------------------------------------------
913 SqlParseError
GenerateOrder( OQueryDesignView
* _pView
,
914 OTableFields
& _rFieldList
,
918 const OQueryController
& rController
= static_cast<OQueryController
&>(_pView
->getController());
919 Reference
< XConnection
> xConnection
= rController
.getConnection();
920 if ( !xConnection
.is() )
921 return eNoConnection
;
923 SqlParseError eErrorCode
= eOk
;
925 OUString aColumnName
;
929 const bool bColumnAliasInOrderBy
= rController
.getSdbMetaData().supportsColumnAliasInOrderBy();
930 Reference
< XDatabaseMetaData
> xMetaData
= xConnection
->getMetaData();
931 OUString aQuote
= xMetaData
->getIdentifierQuoteString();
932 // * must not containa filter - have I already shown the warning?
933 sal_Bool bCritsOnAsterikWarning
= sal_False
; // ** TMFS **
934 OTableFields::iterator aIter
= _rFieldList
.begin();
935 OTableFields::iterator aEnd
= _rFieldList
.end();
936 for(;aIter
!= aEnd
;++aIter
)
938 OTableFieldDescRef pEntryField
= *aIter
;
939 EOrderDir eOrder
= pEntryField
->GetOrderDir();
940 // only create a sort expression when the table name and the sort criteria are defined
941 // otherwise they will be built in GenerateCriteria
942 if ( eOrder
!= ORDER_NONE
)
944 aColumnName
= pEntryField
->GetField();
945 if(aColumnName
.toChar() == '*')
947 // only show the MessageBox the first time
948 if (!bCritsOnAsterikWarning
)
949 ErrorBox(_pView
, ModuleRes( ERR_QRY_ORDERBY_ON_ASTERISK
)).Execute();
950 bCritsOnAsterikWarning
= sal_True
;
954 if ( bColumnAliasInOrderBy
&& !pEntryField
->GetFieldAlias().isEmpty() )
956 aWorkStr
+= ::dbtools::quoteName(aQuote
, pEntryField
->GetFieldAlias());
958 else if ( pEntryField
->isNumericOrAggreateFunction() )
960 OSL_ENSURE(!pEntryField
->GetFunction().isEmpty(),"Function name cannot be empty! ;-(");
961 aWorkStr
+= pEntryField
->GetFunction();
962 aWorkStr
+= OUString('(');
963 aWorkStr
+= quoteTableAlias(bMulti
,pEntryField
->GetAlias(),aQuote
);
964 // only quote column name when we don't have a numeric
965 if ( pEntryField
->isNumeric() )
966 aWorkStr
+= aColumnName
;
968 aWorkStr
+= ::dbtools::quoteName(aQuote
, aColumnName
);
970 aWorkStr
+= OUString(')');
972 else if ( pEntryField
->isOtherFunction() )
974 aWorkStr
+= aColumnName
;
978 aWorkStr
+= quoteTableAlias(bMulti
,pEntryField
->GetAlias(),aQuote
);
979 aWorkStr
+= ::dbtools::quoteName(aQuote
, aColumnName
);
981 aWorkStr
+= OUString(' ');
982 aWorkStr
+= OUString( ";ASC;DESC" ).getToken( (sal_uInt16
)eOrder
, ';' );
983 aWorkStr
+= OUString(',');
988 String
sTemp(comphelper::string::stripEnd(aWorkStr
, ','));
992 if ( !aWorkStr
.isEmpty() )
994 const sal_Int32 nMaxOrder
= xMetaData
->getMaxColumnsInOrderBy();
995 String
sToken(aWorkStr
);
996 if ( nMaxOrder
&& nMaxOrder
< comphelper::string::getTokenCount(sToken
, ',') )
997 eErrorCode
= eStatementTooLong
;
1000 _rsRet
= OUString(" ORDER BY ");
1005 catch(SQLException
&)
1007 OSL_FAIL("Failure while building group by!");
1013 //------------------------------------------------------------------------------
1014 void GenerateInnerJoinCriterias(const Reference
< XConnection
>& _xConnection
,
1015 OUString
& _rJoinCrit
,
1016 const ::std::vector
<OTableConnection
*>* _pConnList
)
1018 ::std::vector
<OTableConnection
*>::const_iterator aIter
= _pConnList
->begin();
1019 ::std::vector
<OTableConnection
*>::const_iterator aEnd
= _pConnList
->end();
1020 for(;aIter
!= aEnd
;++aIter
)
1022 const OQueryTableConnection
* pEntryConn
= static_cast<const OQueryTableConnection
*>(*aIter
);
1023 OQueryTableConnectionData
* pEntryConnData
= static_cast<OQueryTableConnectionData
*>(pEntryConn
->GetData().get());
1024 if ( pEntryConnData
->GetJoinType() == INNER_JOIN
&& !pEntryConnData
->isNatural() )
1026 if(!_rJoinCrit
.isEmpty())
1027 _rJoinCrit
+= C_AND
;
1028 _rJoinCrit
+= BuildJoinCriteria(_xConnection
,pEntryConnData
->GetConnLineDataList(),pEntryConnData
);
1032 //------------------------------------------------------------------------------
1033 void searchAndAppendName(const Reference
< XConnection
>& _xConnection
,
1034 const OQueryTableWindow
* _pTableWindow
,
1035 tableNames_t
& _rTableNames
,
1036 OUString
& _rsTableListStr
1039 OUString
sTabName(BuildTable(_xConnection
,_pTableWindow
));
1041 if(_rTableNames
.find(sTabName
) == _rTableNames
.end())
1043 _rTableNames
[sTabName
] = sal_True
;
1044 _rsTableListStr
+= sTabName
;
1045 _rsTableListStr
+= OUString(',');
1048 //------------------------------------------------------------------------------
1049 OUString
GenerateFromClause( const Reference
< XConnection
>& _xConnection
,
1050 const OQueryTableView::OTableWindowMap
* pTabList
,
1051 const ::std::vector
<OTableConnection
*>* pConnList
1055 OUString aTableListStr
;
1056 // used to avoid putting a table twice in FROM clause
1057 tableNames_t aTableNames
;
1059 // generate outer join clause in from
1060 if(!pConnList
->empty())
1062 ::std::vector
<OTableConnection
*>::const_iterator aIter
= pConnList
->begin();
1063 ::std::vector
<OTableConnection
*>::const_iterator aEnd
= pConnList
->end();
1064 ::std::map
<OTableWindow
*,sal_Int32
> aConnectionCount
;
1065 for(;aIter
!= aEnd
;++aIter
)
1067 static_cast<OQueryTableConnection
*>(*aIter
)->SetVisited(sal_False
);
1068 ++aConnectionCount
[(*aIter
)->GetSourceWin()];
1069 ++aConnectionCount
[(*aIter
)->GetDestWin()];
1071 ::std::multimap
<sal_Int32
, OTableWindow
*> aMulti
;
1072 ::std::map
<OTableWindow
*,sal_Int32
>::iterator aCountIter
= aConnectionCount
.begin();
1073 ::std::map
<OTableWindow
*,sal_Int32
>::iterator aCountEnd
= aConnectionCount
.end();
1074 for(;aCountIter
!= aCountEnd
;++aCountIter
)
1076 aMulti
.insert(::std::multimap
<sal_Int32
, OTableWindow
*>::value_type(aCountIter
->second
,aCountIter
->first
));
1079 const sal_Bool bUseEscape
= ::dbtools::getBooleanDataSourceSetting( _xConnection
, PROPERTY_OUTERJOINESCAPE
);
1080 ::std::multimap
<sal_Int32
, OTableWindow
*>::reverse_iterator aRIter
= aMulti
.rbegin();
1081 ::std::multimap
<sal_Int32
, OTableWindow
*>::reverse_iterator aREnd
= aMulti
.rend();
1082 for(;aRIter
!= aREnd
;++aRIter
)
1084 ::std::vector
<OTableConnection
*>::const_iterator aConIter
= aRIter
->second
->getTableView()->getTableConnections(aRIter
->second
);
1085 for(;aConIter
!= aEnd
;++aConIter
)
1087 OQueryTableConnection
* pEntryConn
= static_cast<OQueryTableConnection
*>(*aConIter
);
1088 if(!pEntryConn
->IsVisited() && pEntryConn
->GetSourceWin() == aRIter
->second
)
1091 GetNextJoin(_xConnection
,
1093 static_cast<OQueryTableWindow
*>(pEntryConn
->GetDestWin()),
1097 if(!aJoin
.isEmpty())
1100 switch(static_cast<OQueryTableConnectionData
*>(pEntryConn
->GetData().get())->GetJoinType())
1106 // create outer join
1119 aTableListStr
+= aStr
;
1125 // and now all inner joins
1126 // these are implemented as
1127 // "FROM tbl1, tbl2 WHERE tbl1.col1=tlb2.col2"
1129 // "FROM tbl1 INNER JOIN tbl2 ON tbl1.col1=tlb2.col2"
1130 aIter
= pConnList
->begin();
1131 for(;aIter
!= aEnd
;++aIter
)
1133 OQueryTableConnection
* pEntryConn
= static_cast<OQueryTableConnection
*>(*aIter
);
1134 if(!pEntryConn
->IsVisited())
1136 searchAndAppendName(_xConnection
,
1137 static_cast<OQueryTableWindow
*>(pEntryConn
->GetSourceWin()),
1141 searchAndAppendName(_xConnection
,
1142 static_cast<OQueryTableWindow
*>(pEntryConn
->GetDestWin()),
1148 // all tables that haven't a connection to anyone
1149 OQueryTableView::OTableWindowMap::const_iterator aTabIter
= pTabList
->begin();
1150 OQueryTableView::OTableWindowMap::const_iterator aTabEnd
= pTabList
->end();
1151 for(;aTabIter
!= aTabEnd
;++aTabIter
)
1153 const OQueryTableWindow
* pEntryTab
= static_cast<const OQueryTableWindow
*>(aTabIter
->second
);
1154 if(!pEntryTab
->ExistsAConn())
1156 aTableListStr
+= BuildTable(_xConnection
,pEntryTab
);
1157 aTableListStr
+= OUString(',');
1161 if(!aTableListStr
.isEmpty())
1162 aTableListStr
= aTableListStr
.replaceAt(aTableListStr
.getLength()-1,1, OUString() );
1163 return aTableListStr
;
1165 //------------------------------------------------------------------------------
1166 OUString
GenerateGroupBy(const OQueryDesignView
* _pView
,OTableFields
& _rFieldList
, sal_Bool bMulti
)
1168 OQueryController
& rController
= static_cast<OQueryController
&>(_pView
->getController());
1169 const Reference
< XConnection
> xConnection
= rController
.getConnection();
1170 if(!xConnection
.is())
1173 ::std::map
< OUString
,bool> aGroupByNames
;
1175 OUString aGroupByStr
;
1178 const Reference
< XDatabaseMetaData
> xMetaData
= xConnection
->getMetaData();
1179 const OUString aQuote
= xMetaData
->getIdentifierQuoteString();
1181 OTableFields::iterator aIter
= _rFieldList
.begin();
1182 OTableFields::iterator aEnd
= _rFieldList
.end();
1183 for(;aIter
!= aEnd
;++aIter
)
1185 OTableFieldDescRef pEntryField
= *aIter
;
1186 if ( pEntryField
->IsGroupBy() )
1188 OSL_ENSURE(!pEntryField
->GetField().isEmpty(),"No Field Name available!;-(");
1189 OUString sGroupByPart
= quoteTableAlias(bMulti
,pEntryField
->GetAlias(),aQuote
);
1191 // only quote the field name when it isn't calculated
1192 if ( pEntryField
->isNoneFunction() )
1194 sGroupByPart
+= ::dbtools::quoteName(aQuote
, pEntryField
->GetField());
1198 OUString aTmp
= pEntryField
->GetField();
1200 Reference
<XPropertySet
> xColumn
;
1201 SAL_WNODEPRECATED_DECLARATIONS_PUSH
1202 ::std::auto_ptr
< ::connectivity::OSQLParseNode
> pParseNode(_pView
->getPredicateTreeFromEntry(pEntryField
,aTmp
,aErrorMsg
,xColumn
));
1203 SAL_WNODEPRECATED_DECLARATIONS_POP
1204 if (pParseNode
.get())
1207 pParseNode
->getChild(0)->parseNodeToStr( sGroupBy
,
1209 &rController
.getParser().getContext(),
1211 !pEntryField
->isOtherFunction());
1212 sGroupByPart
+= sGroupBy
;
1215 sGroupByPart
+= pEntryField
->GetField();
1217 if ( aGroupByNames
.find(sGroupByPart
) == aGroupByNames
.end() )
1219 aGroupByNames
.insert(::std::map
< OUString
,bool>::value_type(sGroupByPart
,true));
1220 aGroupByStr
+= sGroupByPart
;
1221 aGroupByStr
+= OUString(',');
1225 if ( !aGroupByStr
.isEmpty() )
1227 aGroupByStr
= aGroupByStr
.replaceAt(aGroupByStr
.getLength()-1,1, OUString(' ') );
1228 OUString
aGroupByStr2(" GROUP BY ");
1229 aGroupByStr2
+= aGroupByStr
;
1230 aGroupByStr
= aGroupByStr2
;
1233 catch(SQLException
&)
1235 OSL_FAIL("Failure while building group by!");
1239 // -----------------------------------------------------------------------------
1240 SqlParseError
GetORCriteria(OQueryDesignView
* _pView
,
1241 OSelectionBrowseBox
* _pSelectionBrw
,
1242 const ::connectivity::OSQLParseNode
* pCondition
,
1243 sal_uInt16
& nLevel
,
1244 sal_Bool bHaving
= sal_False
,
1245 bool bAddOrOnOneLine
= false);
1246 // -----------------------------------------------------------------------------
1247 SqlParseError
GetSelectionCriteria( OQueryDesignView
* _pView
,
1248 OSelectionBrowseBox
* _pSelectionBrw
,
1249 const ::connectivity::OSQLParseNode
* pNode
,
1250 sal_uInt16
& rLevel
)
1252 if (!SQL_ISRULE(pNode
, select_statement
))
1253 return eNoSelectStatement
;
1255 // nyi: more checking for the correct structure!
1256 pNode
= pNode
? pNode
->getChild(3)->getChild(1) : NULL
;
1257 // no where clause found
1258 if (!pNode
|| pNode
->isLeaf())
1261 // Next free sentence...
1262 SqlParseError eErrorCode
= eOk
;
1263 ::connectivity::OSQLParseNode
* pCondition
= pNode
->getChild(1);
1264 if ( pCondition
) // no where clause
1266 // now we have to check the other conditions
1267 // first make the logical easier
1268 ::connectivity::OSQLParseNode::negateSearchCondition(pCondition
);
1269 ::connectivity::OSQLParseNode
*pNodeTmp
= pNode
->getChild(1);
1271 ::connectivity::OSQLParseNode::disjunctiveNormalForm(pNodeTmp
);
1272 pNodeTmp
= pNode
->getChild(1);
1273 ::connectivity::OSQLParseNode::absorptions(pNodeTmp
);
1274 pNodeTmp
= pNode
->getChild(1);
1275 // compress sort the criteria @see http://www.openoffice.org/issues/show_bug.cgi?id=24079
1276 OSQLParseNode::compress(pNodeTmp
);
1277 pNodeTmp
= pNode
->getChild(1);
1279 // first extract the inner joins conditions
1280 GetInnerJoinCriteria(_pView
,pNodeTmp
);
1281 // now simplify again, join are checked in ComparisonPredicate
1282 ::connectivity::OSQLParseNode::absorptions(pNodeTmp
);
1283 pNodeTmp
= pNode
->getChild(1);
1285 // it could happen that pCondition is not more valid
1286 eErrorCode
= GetORCriteria(_pView
,_pSelectionBrw
,pNodeTmp
, rLevel
);
1290 //------------------------------------------------------------------------------
1291 SqlParseError
GetANDCriteria( OQueryDesignView
* _pView
,
1292 OSelectionBrowseBox
* _pSelectionBrw
,
1293 const ::connectivity::OSQLParseNode
* pCondition
,
1296 bool bAddOrOnOneLine
);
1297 //------------------------------------------------------------------------------
1298 SqlParseError
ComparisonPredicate(OQueryDesignView
* _pView
,
1299 OSelectionBrowseBox
* _pSelectionBrw
,
1300 const ::connectivity::OSQLParseNode
* pCondition
,
1301 const sal_uInt16 nLevel
,
1303 bool bAddOrOnOneLine
);
1304 //------------------------------------------------------------------------------
1305 SqlParseError
GetORCriteria(OQueryDesignView
* _pView
,
1306 OSelectionBrowseBox
* _pSelectionBrw
,
1307 const ::connectivity::OSQLParseNode
* pCondition
,
1308 sal_uInt16
& nLevel
,
1310 bool bAddOrOnOneLine
)
1312 SqlParseError eErrorCode
= eOk
;
1314 // round brackets around the printout
1315 if (pCondition
->count() == 3 &&
1316 SQL_ISPUNCTUATION(pCondition
->getChild(0),"(") &&
1317 SQL_ISPUNCTUATION(pCondition
->getChild(2),")"))
1319 eErrorCode
= GetORCriteria(_pView
,_pSelectionBrw
,pCondition
->getChild(1),nLevel
,bHaving
,bAddOrOnOneLine
);
1322 // a searchcondition can only look like this: search_condition SQL_TOKEN_OR boolean_term
1323 else if (SQL_ISRULE(pCondition
,search_condition
))
1325 for (int i
= 0; i
< 3 && eErrorCode
== eOk
; i
+=2)
1327 const ::connectivity::OSQLParseNode
* pChild
= pCondition
->getChild(i
);
1328 if ( SQL_ISRULE(pChild
,search_condition
) )
1329 eErrorCode
= GetORCriteria(_pView
,_pSelectionBrw
,pChild
,nLevel
,bHaving
,bAddOrOnOneLine
);
1332 eErrorCode
= GetANDCriteria(_pView
,_pSelectionBrw
,pChild
, nLevel
,bHaving
, i
== 0 ? false : bAddOrOnOneLine
);
1333 if ( !bAddOrOnOneLine
)
1339 eErrorCode
= GetANDCriteria( _pView
,_pSelectionBrw
,pCondition
, nLevel
, bHaving
,bAddOrOnOneLine
);
1343 //--------------------------------------------------------------------------------------------------
1344 bool CheckOrCriteria(const ::connectivity::OSQLParseNode
* _pCondition
,::connectivity::OSQLParseNode
* _pFirstColumnRef
)
1347 ::connectivity::OSQLParseNode
* pFirstColumnRef
= _pFirstColumnRef
;
1348 for (int i
= 0; i
< 3 && bRet
; i
+=2)
1350 const ::connectivity::OSQLParseNode
* pChild
= _pCondition
->getChild(i
);
1351 if ( SQL_ISRULE(pChild
,search_condition
) )
1352 bRet
= CheckOrCriteria(pChild
,pFirstColumnRef
);
1355 // this is a simple way to test columns are the same, may be we have to adjust this algo a little bit in future. :-)
1356 ::connectivity::OSQLParseNode
* pSecondColumnRef
= pChild
->getByRule(::connectivity::OSQLParseNode::column_ref
);
1357 if ( pFirstColumnRef
&& pSecondColumnRef
)
1358 bRet
= *pFirstColumnRef
== *pSecondColumnRef
;
1359 else if ( !pFirstColumnRef
)
1360 pFirstColumnRef
= pSecondColumnRef
;
1365 //--------------------------------------------------------------------------------------------------
1366 SqlParseError
GetANDCriteria( OQueryDesignView
* _pView
,
1367 OSelectionBrowseBox
* _pSelectionBrw
,
1368 const ::connectivity::OSQLParseNode
* pCondition
,
1371 bool bAddOrOnOneLine
)
1373 const ::com::sun::star::lang::Locale aLocale
= _pView
->getLocale();
1374 const OUString sDecimal
= _pView
->getDecimalSeparator();
1376 // I will need a cast pointer to my com::sun::star::sdbcx::Container
1377 OQueryController
& rController
= static_cast<OQueryController
&>(_pView
->getController());
1378 SqlParseError eErrorCode
= eOk
;
1381 if (SQL_ISRULE(pCondition
,boolean_primary
))
1383 // check if we have to put the or criteria on one line.
1384 const ::connectivity::OSQLParseNode
* pSearchCondition
= pCondition
->getChild(1);
1385 bool bMustAddOrOnOneLine
= CheckOrCriteria(pSearchCondition
,NULL
);
1386 if ( SQL_ISRULE( pSearchCondition
, search_condition
) ) // we have a or
1388 _pSelectionBrw
->DuplicateConditionLevel( nLevel
);
1389 eErrorCode
= GetORCriteria(_pView
,_pSelectionBrw
,pSearchCondition
->getChild(0), nLevel
,bHaving
,bMustAddOrOnOneLine
);
1391 eErrorCode
= GetORCriteria(_pView
,_pSelectionBrw
,pSearchCondition
->getChild(2), nLevel
,bHaving
,bMustAddOrOnOneLine
);
1394 eErrorCode
= GetORCriteria(_pView
,_pSelectionBrw
,pSearchCondition
, nLevel
,bHaving
,bMustAddOrOnOneLine
);
1396 // The first element is (again) an AND condition
1397 else if ( SQL_ISRULE(pCondition
,boolean_term
) )
1399 OSL_ENSURE(pCondition
->count() == 3,"Illegal definifiton of boolean_term");
1400 eErrorCode
= GetANDCriteria(_pView
,_pSelectionBrw
,pCondition
->getChild(0), nLevel
,bHaving
,bAddOrOnOneLine
);
1401 if ( eErrorCode
== eOk
)
1402 eErrorCode
= GetANDCriteria(_pView
,_pSelectionBrw
,pCondition
->getChild(2), nLevel
,bHaving
,bAddOrOnOneLine
);
1404 else if (SQL_ISRULE( pCondition
, comparison_predicate
))
1406 eErrorCode
= ComparisonPredicate(_pView
,_pSelectionBrw
,pCondition
,nLevel
,bHaving
,bAddOrOnOneLine
);
1408 else if( SQL_ISRULE(pCondition
,like_predicate
) )
1410 const ::connectivity::OSQLParseNode
* pValueExp
= pCondition
->getChild(0);
1411 if (SQL_ISRULE(pValueExp
, column_ref
) )
1413 OUString aColumnName
;
1414 OUString aCondition
;
1415 Reference
< XConnection
> xConnection
= rController
.getConnection();
1416 if ( xConnection
.is() )
1418 Reference
< XDatabaseMetaData
> xMetaData
= xConnection
->getMetaData();
1419 // the international doesn't matter I have a string
1420 pCondition
->parseNodeToPredicateStr(aCondition
,
1422 rController
.getNumberFormatter(),
1424 static_cast<sal_Char
>(sDecimal
.toChar()),
1425 &rController
.getParser().getContext());
1427 pValueExp
->parseNodeToPredicateStr( aColumnName
,
1429 rController
.getNumberFormatter(),
1431 static_cast<sal_Char
>(sDecimal
.toChar()),
1432 &rController
.getParser().getContext());
1434 // don't display the column name
1435 aCondition
= aCondition
.copy(aColumnName
.getLength());
1436 aCondition
= aCondition
.trim();
1439 OTableFieldDescRef aDragLeft
= new OTableFieldDesc();
1440 if ( eOk
== ( eErrorCode
= FillDragInfo(_pView
,pValueExp
,aDragLeft
) ))
1443 aDragLeft
->SetGroupBy(sal_True
);
1444 _pSelectionBrw
->AddCondition(aDragLeft
, aCondition
, nLevel
,bAddOrOnOneLine
);
1447 else if(SQL_ISRULEOR3(pValueExp
, general_set_fct
, set_fct_spec
, position_exp
) ||
1448 SQL_ISRULEOR3(pValueExp
, extract_exp
, fold
, char_substring_fct
) ||
1449 SQL_ISRULEOR2(pValueExp
, length_exp
, char_value_fct
))
1451 AddFunctionCondition( _pView
,
1460 eErrorCode
= eNoColumnInLike
;
1461 String
sError(ModuleRes(STR_QRY_LIKE_LEFT_NO_COLUMN
));
1462 _pView
->getController().appendError( sError
);
1465 else if( SQL_ISRULEOR2(pCondition
,test_for_null
,in_predicate
)
1466 || SQL_ISRULEOR2(pCondition
,all_or_any_predicate
,between_predicate
))
1468 if ( SQL_ISRULEOR2(pCondition
->getChild(0), set_fct_spec
, general_set_fct
) )
1470 AddFunctionCondition( _pView
,
1477 else if ( SQL_ISRULE(pCondition
->getChild(0), column_ref
) )
1480 OUString sCondition
= ParseCondition(rController
,pCondition
,sDecimal
,aLocale
,1);
1481 OTableFieldDescRef aDragLeft
= new OTableFieldDesc();
1482 if ( eOk
== ( eErrorCode
= FillDragInfo(_pView
,pCondition
->getChild(0),aDragLeft
)) )
1485 aDragLeft
->SetGroupBy(sal_True
);
1486 _pSelectionBrw
->AddCondition(aDragLeft
, sCondition
, nLevel
,bAddOrOnOneLine
);
1491 // Parse the function condition
1492 OUString sCondition
= ParseCondition(rController
,pCondition
,sDecimal
,aLocale
,1);
1493 Reference
< XConnection
> xConnection
= rController
.getConnection();
1494 Reference
< XDatabaseMetaData
> xMetaData
= xConnection
->getMetaData();
1495 // the international doesn't matter I have a string
1497 pCondition
->getChild(0)->parseNodeToPredicateStr(sName
,
1499 rController
.getNumberFormatter(),
1501 static_cast<sal_Char
>(sDecimal
.toChar()),
1502 &rController
.getParser().getContext());
1504 OTableFieldDescRef aDragLeft
= new OTableFieldDesc();
1505 aDragLeft
->SetField(sName
);
1506 aDragLeft
->SetFunctionType(FKT_OTHER
);
1509 aDragLeft
->SetGroupBy(sal_True
);
1510 _pSelectionBrw
->AddCondition(aDragLeft
, sCondition
, nLevel
,bAddOrOnOneLine
);
1513 else if( SQL_ISRULEOR2(pCondition
,existence_test
,unique_test
) )
1515 // Parse the function condition
1516 OUString aCondition
= ParseCondition(rController
,pCondition
,sDecimal
,aLocale
,0);
1518 OTableFieldDescRef aDragLeft
= new OTableFieldDesc();
1519 aDragLeft
->SetField(aCondition
);
1520 aDragLeft
->SetFunctionType(FKT_CONDITION
);
1522 eErrorCode
= _pSelectionBrw
->InsertField(aDragLeft
,BROWSER_INVALIDID
,sal_False
,sal_True
).is() ? eOk
: eTooManyColumns
;
1524 else //! TODO not supported yet
1525 eErrorCode
= eStatementTooComplex
;
1526 // Pass on the error code
1529 //------------------------------------------------------------------------------
1530 SqlParseError
AddFunctionCondition(OQueryDesignView
* _pView
,
1531 OSelectionBrowseBox
* _pSelectionBrw
,
1532 const ::connectivity::OSQLParseNode
* pCondition
,
1533 const sal_uInt16 nLevel
,
1535 bool bAddOrOnOneLine
)
1537 SqlParseError eErrorCode
= eOk
;
1538 OQueryController
& rController
= static_cast<OQueryController
&>(_pView
->getController());
1540 OSQLParseNode
* pFunction
= pCondition
->getChild(0);
1542 OSL_ENSURE(SQL_ISRULEOR3(pFunction
, general_set_fct
, set_fct_spec
, position_exp
) ||
1543 SQL_ISRULEOR3(pFunction
, extract_exp
, fold
, char_substring_fct
) ||
1544 SQL_ISRULEOR2(pFunction
,length_exp
,char_value_fct
),
1546 OUString aCondition
;
1547 OTableFieldDescRef aDragLeft
= new OTableFieldDesc();
1549 OUString aColumnName
;
1550 Reference
< XConnection
> xConnection
= rController
.getConnection();
1551 if(xConnection
.is())
1553 Reference
< XDatabaseMetaData
> xMetaData
= xConnection
->getMetaData();
1554 pCondition
->parseNodeToPredicateStr(aCondition
,
1556 rController
.getNumberFormatter(),
1557 _pView
->getLocale(),
1558 static_cast<sal_Char
>(_pView
->getDecimalSeparator().toChar()),
1559 &rController
.getParser().getContext());
1561 pFunction
->parseNodeToStr( aColumnName
,
1563 &rController
.getParser().getContext(),
1565 sal_True
); // quote is to true because we need quoted elements inside the function
1566 // don't display the column name
1567 aCondition
= aCondition
.copy(aColumnName
.getLength());
1568 aCondition
= aCondition
.trim();
1569 if ( aCondition
.indexOf('=',0) == 0 ) // ignore the equal sign
1570 aCondition
= aCondition
.copy(1);
1573 if ( SQL_ISRULE(pFunction
, general_set_fct
) )
1575 sal_Int32 nFunctionType
= FKT_AGGREGATE
;
1576 OSQLParseNode
* pParamNode
= pFunction
->getChild(pFunction
->count()-2);
1577 if ( pParamNode
&& pParamNode
->getTokenValue().toChar() == '*' )
1579 OJoinTableView::OTableWindowMap
* pTabList
= _pView
->getTableView()->GetTabWinMap();
1580 OJoinTableView::OTableWindowMap::iterator aIter
= pTabList
->begin();
1581 OJoinTableView::OTableWindowMap::iterator aTabEnd
= pTabList
->end();
1582 for(;aIter
!= aTabEnd
;++aIter
)
1584 OQueryTableWindow
* pTabWin
= static_cast<OQueryTableWindow
*>(aIter
->second
);
1585 if (pTabWin
->ExistsField( OUString("*"), aDragLeft
))
1587 aDragLeft
->SetAlias(String());
1588 aDragLeft
->SetTable(String());
1593 else if( eOk
!= ( eErrorCode
= FillDragInfo(_pView
,pParamNode
,aDragLeft
))
1594 && SQL_ISRULE(pParamNode
,num_value_exp
) )
1596 OUString sParameterValue
;
1597 pParamNode
->parseNodeToStr( sParameterValue
,
1599 &rController
.getParser().getContext());
1600 nFunctionType
|= FKT_NUMERIC
;
1601 aDragLeft
->SetField(sParameterValue
);
1604 aDragLeft
->SetFunctionType(nFunctionType
);
1606 aDragLeft
->SetGroupBy(sal_True
);
1607 sal_Int32 nIndex
= 0;
1608 aDragLeft
->SetFunction(aColumnName
.getToken(0,'(',nIndex
));
1612 // for an unknown function we write the whole text in the field
1613 aDragLeft
->SetField(aColumnName
);
1615 aDragLeft
->SetGroupBy(sal_True
);
1616 aDragLeft
->SetFunctionType(FKT_OTHER
|FKT_NUMERIC
);
1618 _pSelectionBrw
->AddCondition(aDragLeft
, aCondition
, nLevel
,bAddOrOnOneLine
);
1623 //------------------------------------------------------------------------------
1624 SqlParseError
ComparisonPredicate(OQueryDesignView
* _pView
,
1625 OSelectionBrowseBox
* _pSelectionBrw
,
1626 const ::connectivity::OSQLParseNode
* pCondition
,
1627 const sal_uInt16 nLevel
,
1629 ,bool bAddOrOnOneLine
)
1631 SqlParseError eErrorCode
= eOk
;
1632 OQueryController
& rController
= static_cast<OQueryController
&>(_pView
->getController());
1634 OSL_ENSURE(SQL_ISRULE( pCondition
, comparison_predicate
),"ComparisonPredicate: pCondition is not a Comparison Predicate");
1635 if ( SQL_ISRULE(pCondition
->getChild(0), column_ref
)
1636 || SQL_ISRULE(pCondition
->getChild(pCondition
->count()-1), column_ref
) )
1638 OUString aCondition
;
1639 OTableFieldDescRef aDragLeft
= new OTableFieldDesc();
1641 if ( SQL_ISRULE(pCondition
->getChild(0), column_ref
) && SQL_ISRULE(pCondition
->getChild(pCondition
->count()-1), column_ref
) )
1643 OTableFieldDescRef aDragRight
= new OTableFieldDesc();
1644 if (eOk
!= ( eErrorCode
= FillDragInfo(_pView
,pCondition
->getChild(0),aDragLeft
)) ||
1645 eOk
!= ( eErrorCode
= FillDragInfo(_pView
,pCondition
->getChild(2),aDragRight
)))
1648 OQueryTableConnection
* pConn
= static_cast<OQueryTableConnection
*>(
1649 _pView
->getTableView()->GetTabConn(static_cast<OQueryTableWindow
*>(aDragLeft
->GetTabWindow()),
1650 static_cast<OQueryTableWindow
*>(aDragRight
->GetTabWindow()),
1654 OConnectionLineDataVec
* pLineDataList
= pConn
->GetData()->GetConnLineDataList();
1655 OConnectionLineDataVec::iterator aIter
= pLineDataList
->begin();
1656 OConnectionLineDataVec::iterator aEnd
= pLineDataList
->end();
1657 for(;aIter
!= aEnd
;++aIter
)
1659 if((*aIter
)->GetSourceFieldName() == aDragLeft
->GetField() ||
1660 (*aIter
)->GetDestFieldName() == aDragLeft
->GetField() )
1668 sal_uInt32 nPos
= 0;
1669 if(SQL_ISRULE(pCondition
->getChild(0), column_ref
))
1674 // don't display the equal
1675 if (pCondition
->getChild(i
)->getNodeType() == SQL_NODE_EQUAL
)
1679 aCondition
= ParseCondition(rController
1681 ,_pView
->getDecimalSeparator()
1682 ,_pView
->getLocale()
1685 else if( SQL_ISRULE(pCondition
->getChild(pCondition
->count()-1), column_ref
) )
1687 nPos
= pCondition
->count()-1;
1689 sal_Int32 i
= static_cast<sal_Int32
>(pCondition
->count() - 2);
1690 switch (pCondition
->getChild(i
)->getNodeType())
1692 case SQL_NODE_EQUAL
:
1693 // don't display the equal
1697 // take the opposite as we change the order
1699 aCondition
= aCondition
+ OUString(">");
1701 case SQL_NODE_LESSEQ
:
1702 // take the opposite as we change the order
1704 aCondition
= aCondition
+ OUString(">=");
1706 case SQL_NODE_GREAT
:
1707 // take the opposite as we change the order
1709 aCondition
= aCondition
+ OUString("<");
1711 case SQL_NODE_GREATEQ
:
1712 // take the opposite as we change the order
1714 aCondition
= aCondition
+ OUString("<=");
1721 Reference
< XConnection
> xConnection
= rController
.getConnection();
1722 if(xConnection
.is())
1724 Reference
< XDatabaseMetaData
> xMetaData
= xConnection
->getMetaData();
1726 pCondition
->getChild(i
)->parseNodeToPredicateStr(aCondition
,
1728 rController
.getNumberFormatter(),
1729 _pView
->getLocale(),
1730 static_cast<sal_Char
>(_pView
->getDecimalSeparator().toChar()),
1731 &rController
.getParser().getContext());
1737 if( eOk
== ( eErrorCode
= FillDragInfo(_pView
,pCondition
->getChild(nPos
),aDragLeft
)))
1740 aDragLeft
->SetGroupBy(sal_True
);
1741 _pSelectionBrw
->AddCondition(aDragLeft
, aCondition
, nLevel
,bAddOrOnOneLine
);
1744 else if( SQL_ISRULEOR2(pCondition
->getChild(0), set_fct_spec
, general_set_fct
) )
1746 AddFunctionCondition( _pView
,
1753 else // it can only be an Expr
1755 OUString aName
,aCondition
;
1757 ::connectivity::OSQLParseNode
*pLhs
= pCondition
->getChild(0);
1758 ::connectivity::OSQLParseNode
*pRhs
= pCondition
->getChild(2);
1760 Reference
< XConnection
> xConnection
= rController
.getConnection();
1761 if(xConnection
.is())
1763 pLhs
->parseNodeToStr(aName
,
1765 &rController
.getParser().getContext(),
1768 aCondition
= pCondition
->getChild(1)->getTokenValue();
1769 pRhs
->parseNodeToPredicateStr(aCondition
,
1771 rController
.getNumberFormatter(),
1772 _pView
->getLocale(),
1773 static_cast<sal_Char
>(_pView
->getDecimalSeparator().toChar()),
1774 &rController
.getParser().getContext());
1777 OTableFieldDescRef aDragLeft
= new OTableFieldDesc();
1778 aDragLeft
->SetField(aName
);
1779 aDragLeft
->SetFunctionType(FKT_OTHER
|FKT_NUMERIC
);
1781 _pSelectionBrw
->AddCondition(aDragLeft
, aCondition
, nLevel
,bAddOrOnOneLine
);
1786 //------------------------------------------------------------------------------
1789 OQueryTableWindow
* lcl_findColumnInTables( const OUString
& _rColumName
, const OJoinTableView::OTableWindowMap
& _rTabList
, OTableFieldDescRef
& _rInfo
)
1791 OJoinTableView::OTableWindowMap::const_iterator aIter
= _rTabList
.begin();
1792 OJoinTableView::OTableWindowMap::const_iterator aEnd
= _rTabList
.end();
1793 for ( ; aIter
!= aEnd
; ++aIter
)
1795 OQueryTableWindow
* pTabWin
= static_cast< OQueryTableWindow
* >( aIter
->second
);
1796 if ( pTabWin
&& pTabWin
->ExistsField( _rColumName
, _rInfo
) )
1803 //------------------------------------------------------------------------------
1804 void InsertColumnRef(const OQueryDesignView
* _pView
,
1805 const ::connectivity::OSQLParseNode
* pColumnRef
,
1806 OUString
& aColumnName
,
1807 const OUString
& aColumnAlias
,
1808 OUString
& aTableRange
,
1809 OTableFieldDescRef
& _raInfo
,
1810 OJoinTableView::OTableWindowMap
* pTabList
)
1813 // Put the table names together
1814 ::connectivity::OSQLParseTreeIterator
& rParseIter
= static_cast<OQueryController
&>(_pView
->getController()).getParseIterator();
1815 rParseIter
.getColumnRange( pColumnRef
, aColumnName
, aTableRange
);
1817 sal_Bool
bFound(sal_False
);
1818 OSL_ENSURE(!aColumnName
.isEmpty(),"Column name must not be empty");
1819 if (aTableRange
.isEmpty())
1821 // SELECT column, ...
1822 bFound
= NULL
!= lcl_findColumnInTables( aColumnName
, *pTabList
, _raInfo
);
1823 if ( bFound
&& ( aColumnName
.toChar() != '*' ) )
1824 _raInfo
->SetFieldAlias(aColumnAlias
);
1828 // SELECT range.column, ...
1829 OQueryTableWindow
* pTabWin
= static_cast<OQueryTableView
*>(_pView
->getTableView())->FindTable(aTableRange
);
1831 if (pTabWin
&& pTabWin
->ExistsField(aColumnName
, _raInfo
))
1833 if(aColumnName
.toChar() != '*')
1834 _raInfo
->SetFieldAlias(aColumnAlias
);
1840 _raInfo
->SetTable(OUString());
1841 _raInfo
->SetAlias(OUString());
1842 _raInfo
->SetField(aColumnName
);
1843 _raInfo
->SetFieldAlias(aColumnAlias
); // nyi : here it continues Expr_1, Expr_2 ...
1844 _raInfo
->SetFunctionType(FKT_OTHER
);
1847 //-----------------------------------------------------------------------------
1848 sal_Bool
checkJoinConditions( const OQueryDesignView
* _pView
,
1849 const ::connectivity::OSQLParseNode
* _pNode
)
1851 const ::connectivity::OSQLParseNode
* pJoinNode
= NULL
;
1852 sal_Bool bRet
= sal_True
;
1853 if (SQL_ISRULE(_pNode
,qualified_join
))
1855 else if (SQL_ISRULE(_pNode
,table_ref
)
1856 && _pNode
->count() == 3
1857 && SQL_ISPUNCTUATION(_pNode
->getChild(0),"(")
1858 && SQL_ISPUNCTUATION(_pNode
->getChild(2),")") ) // '(' joined_table ')'
1859 pJoinNode
= _pNode
->getChild(1);
1860 else if (! ( SQL_ISRULE(_pNode
, table_ref
) && _pNode
->count() == 2) ) // table_node table_primary_as_range_column
1863 if (pJoinNode
&& !InsertJoin(_pView
,pJoinNode
))
1867 //-----------------------------------------------------------------------------
1868 sal_Bool
InsertJoin(const OQueryDesignView
* _pView
,
1869 const ::connectivity::OSQLParseNode
*pNode
)
1871 OSL_ENSURE( SQL_ISRULE( pNode
, qualified_join
) || SQL_ISRULE( pNode
, joined_table
) || SQL_ISRULE( pNode
, cross_union
),
1872 "OQueryDesignView::InsertJoin: Error in the Parse Tree");
1874 if (SQL_ISRULE(pNode
,joined_table
))
1875 return InsertJoin(_pView
,pNode
->getChild(1));
1877 // first check the left and right side
1878 const ::connectivity::OSQLParseNode
* pRightTableRef
= pNode
->getChild(3); // table_ref
1879 if ( SQL_ISRULE(pNode
, qualified_join
) && SQL_ISTOKEN(pNode
->getChild(1),NATURAL
) )
1880 pRightTableRef
= pNode
->getChild(4); // table_ref
1882 if ( !checkJoinConditions(_pView
,pNode
->getChild(0)) || !checkJoinConditions(_pView
,pRightTableRef
))
1885 // named column join may be implemented later
1886 // SQL_ISRULE(pNode->getChild(4),named_columns_join)
1887 EJoinType eJoinType
= INNER_JOIN
;
1888 bool bNatural
= false;
1889 if ( SQL_ISRULE(pNode
, qualified_join
) )
1891 ::connectivity::OSQLParseNode
* pJoinType
= pNode
->getChild(1); // join_type
1892 if ( SQL_ISTOKEN(pJoinType
,NATURAL
) )
1895 pJoinType
= pNode
->getChild(2);
1898 if (SQL_ISRULE(pJoinType
,join_type
) && (!pJoinType
->count() || SQL_ISTOKEN(pJoinType
->getChild(0),INNER
)))
1900 eJoinType
= INNER_JOIN
;
1904 if (SQL_ISRULE(pJoinType
,join_type
)) // one level deeper
1905 pJoinType
= pJoinType
->getChild(0);
1907 if (SQL_ISTOKEN(pJoinType
->getChild(0),LEFT
))
1908 eJoinType
= LEFT_JOIN
;
1909 else if(SQL_ISTOKEN(pJoinType
->getChild(0),RIGHT
))
1910 eJoinType
= RIGHT_JOIN
;
1912 eJoinType
= FULL_JOIN
;
1914 if ( SQL_ISRULE(pNode
->getChild(4),join_condition
) )
1916 if ( InsertJoinConnection(_pView
,pNode
->getChild(4)->getChild(1), eJoinType
,pNode
->getChild(0),pRightTableRef
) != eOk
)
1920 else if ( SQL_ISRULE(pNode
, cross_union
) )
1922 eJoinType
= CROSS_JOIN
;
1923 pRightTableRef
= pNode
->getChild(pNode
->count() - 1);
1928 if ( eJoinType
== CROSS_JOIN
|| bNatural
)
1931 OQueryTableWindow
* pLeftWindow
= static_cast<OQueryTableView
*>(_pView
->getTableView())->FindTable( getTableRange(_pView
,pNode
->getChild(0)) );
1932 OQueryTableWindow
* pRightWindow
= static_cast<OQueryTableView
*>(_pView
->getTableView())->FindTable( getTableRange(_pView
,pRightTableRef
) );
1933 OSL_ENSURE(pLeftWindow
&& pRightWindow
,"Table Windows could not be found!");
1934 if ( !pLeftWindow
|| !pRightWindow
)
1937 OTableFieldDescRef aDragLeft
= new OTableFieldDesc();
1938 aDragLeft
->SetTabWindow(pLeftWindow
);
1939 aDragLeft
->SetTable(pLeftWindow
->GetTableName());
1940 aDragLeft
->SetAlias(pLeftWindow
->GetAliasName());
1942 OTableFieldDescRef aDragRight
= new OTableFieldDesc();
1943 aDragRight
->SetTabWindow(pRightWindow
);
1944 aDragRight
->SetTable(pRightWindow
->GetTableName());
1945 aDragRight
->SetAlias(pRightWindow
->GetAliasName());
1947 insertConnection(_pView
,eJoinType
,aDragLeft
,aDragRight
,bNatural
);
1953 //------------------------------------------------------------------------------
1954 void insertUnUsedFields(OQueryDesignView
* _pView
,OSelectionBrowseBox
* _pSelectionBrw
)
1956 // now we have to insert the fields which aren't in the statement
1957 OQueryController
& rController
= static_cast<OQueryController
&>(_pView
->getController());
1958 OTableFields
& rUnUsedFields
= rController
.getUnUsedFields();
1959 OTableFields::iterator aEnd
= rUnUsedFields
.end();
1960 for(OTableFields::iterator aIter
= rUnUsedFields
.begin();aIter
!= aEnd
;++aIter
)
1961 if(_pSelectionBrw
->InsertField(*aIter
,BROWSER_INVALIDID
,sal_False
,sal_False
).is())
1963 OTableFields().swap( rUnUsedFields
);
1966 //------------------------------------------------------------------------------
1967 SqlParseError
InitFromParseNodeImpl(OQueryDesignView
* _pView
,OSelectionBrowseBox
* _pSelectionBrw
)
1969 SqlParseError eErrorCode
= eOk
;
1971 OQueryController
& rController
= static_cast<OQueryController
&>(_pView
->getController());
1973 _pSelectionBrw
->PreFill();
1974 _pSelectionBrw
->SetReadOnly(rController
.isReadOnly());
1975 _pSelectionBrw
->Fill();
1978 ::connectivity::OSQLParseTreeIterator
& aIterator
= rController
.getParseIterator();
1979 const ::connectivity::OSQLParseNode
* pParseTree
= aIterator
.getParseTree();
1985 // now we have to insert the fields which aren't in the statement
1986 insertUnUsedFields(_pView
,_pSelectionBrw
);
1990 if ( !rController
.isEsacpeProcessing() ) // not allowed in this mode
1992 eErrorCode
= eNativeMode
;
1996 if ( !( SQL_ISRULE( pParseTree
, select_statement
) ) )
1998 eErrorCode
= eNoSelectStatement
;
2002 const OSQLParseNode
* pTableExp
= pParseTree
->getChild(3);
2003 if ( pTableExp
->getChild(7)->count() > 0 || pTableExp
->getChild(8)->count() > 0)
2005 eErrorCode
= eStatementTooComplex
;
2009 Reference
< XConnection
> xConnection
= rController
.getConnection();
2010 if ( !xConnection
.is() )
2012 OSL_FAIL( "InitFromParseNodeImpl: no connection? no connection!" );
2016 const OSQLTables
& aMap
= aIterator
.getTables();
2017 ::comphelper::UStringMixLess
aTmp(aMap
.key_comp());
2018 ::comphelper::UStringMixEqual
aKeyComp( aTmp
.isCaseSensitive() );
2020 Reference
< XDatabaseMetaData
> xMetaData
= xConnection
->getMetaData();
2023 sal_Int32 nMax
= xMetaData
->getMaxTablesInSelect();
2024 if ( nMax
&& nMax
< (sal_Int32
)aMap
.size() )
2026 eErrorCode
= eTooManyTables
;
2030 OUString sComposedName
;
2033 OQueryTableView
* pTableView
= static_cast<OQueryTableView
*>(_pView
->getTableView());
2034 pTableView
->clearLayoutInformation();
2035 OSQLTables::const_iterator aIter
= aMap
.begin();
2036 OSQLTables::const_iterator aEnd
= aMap
.end();
2037 for(;aIter
!= aEnd
;++aIter
)
2039 OSQLTable xTable
= aIter
->second
;
2040 Reference
< XPropertySet
> xTableProps( xTable
, UNO_QUERY_THROW
);
2042 sAlias
= aIter
->first
;
2044 // check whether this is a query
2045 Reference
< XPropertySetInfo
> xPSI
= xTableProps
->getPropertySetInfo();
2046 bool bIsQuery
= xPSI
.is() && xPSI
->hasPropertyByName( PROPERTY_COMMAND
);
2049 OSL_VERIFY( xTableProps
->getPropertyValue( PROPERTY_NAME
) >>= sComposedName
);
2052 sComposedName
= ::dbtools::composeTableName( xMetaData
, xTableProps
, ::dbtools::eInDataManipulation
, false, false, false );
2054 // if the alias is the complete (composed) table, then shorten it
2055 if ( aKeyComp( sComposedName
, aIter
->first
) )
2057 OUString sCatalog
, sSchema
, sTable
;
2058 ::dbtools::qualifiedNameComponents( xMetaData
, sComposedName
, sCatalog
, sSchema
, sTable
, ::dbtools::eInDataManipulation
);
2063 // find the existent window for this alias
2064 OQueryTableWindow
* pExistentWin
= pTableView
->FindTable( sAlias
);
2065 if ( !pExistentWin
)
2067 pTableView
->AddTabWin( sComposedName
, sAlias
, sal_False
); // don't create data here
2071 // there already exists a window for this alias ....
2072 if ( !aKeyComp( pExistentWin
->GetData()->GetComposedName(), sComposedName
) )
2073 // ... but for another complete table name -> new window
2074 pTableView
->AddTabWin(sComposedName
, sAlias
);
2078 // now delete the data for which we haven't any tablewindow
2079 OJoinTableView::OTableWindowMap
aTableMap(*pTableView
->GetTabWinMap());
2080 OJoinTableView::OTableWindowMap::iterator aIterTableMap
= aTableMap
.begin();
2081 OJoinTableView::OTableWindowMap::iterator aIterTableEnd
= aTableMap
.end();
2082 for(;aIterTableMap
!= aIterTableEnd
;++aIterTableMap
)
2084 if(aMap
.find(aIterTableMap
->second
->GetComposedName()) == aMap
.end() &&
2085 aMap
.find(aIterTableMap
->first
) == aMap
.end())
2086 pTableView
->RemoveTabWin(aIterTableMap
->second
);
2089 if ( eOk
== (eErrorCode
= FillOuterJoins(_pView
,pTableExp
->getChild(0)->getChild(1))) )
2091 // check if we have a distinct statement
2092 if(SQL_ISTOKEN(pParseTree
->getChild(1),DISTINCT
))
2094 rController
.setDistinct(sal_True
);
2095 rController
.InvalidateFeature(SID_QUERY_DISTINCT_VALUES
);
2099 rController
.setDistinct(sal_False
);
2102 ///check if query has a limit
2103 if( pTableExp
->getChild(6)->count() >= 2 && pTableExp
->getChild(6)->getChild(1) )
2105 rController
.setLimit(
2106 pTableExp
->getChild(6)->getChild(1)->getTokenValue().toInt64() );
2110 rController
.setLimit(-1);
2113 if ( (eErrorCode
= InstallFields(_pView
,pParseTree
, pTableView
->GetTabWinMap())) == eOk
)
2115 // GetSelectionCriteria must be called before GetHavingCriteria
2116 sal_uInt16 nLevel
=0;
2118 if ( eOk
== (eErrorCode
= GetSelectionCriteria(_pView
,_pSelectionBrw
,pParseTree
,nLevel
)) )
2120 if ( eOk
== (eErrorCode
= GetGroupCriteria(_pView
,_pSelectionBrw
,pParseTree
)) )
2122 if ( eOk
== (eErrorCode
= GetHavingCriteria(_pView
,_pSelectionBrw
,pParseTree
,nLevel
)) )
2124 if ( eOk
== (eErrorCode
= GetOrderCriteria(_pView
,_pSelectionBrw
,pParseTree
)) )
2125 insertUnUsedFields(_pView
,_pSelectionBrw
);
2132 catch(SQLException
&)
2134 OSL_FAIL("getMaxTablesInSelect!");
2139 // New Undo-Actions were created in the Manager by the regeneration
2140 rController
.ClearUndoManager();
2141 _pSelectionBrw
->Invalidate();
2144 //------------------------------------------------------------------------------
2145 /** fillSelectSubList
2147 <TRUE/> when columns could be inserted otherwise <FALSE/>
2149 //------------------------------------------------------------------------------
2150 SqlParseError
fillSelectSubList( OQueryDesignView
* _pView
,
2151 OJoinTableView::OTableWindowMap
* _pTabList
)
2153 SqlParseError eErrorCode
= eOk
;
2154 sal_Bool bFirstField
= sal_True
;
2155 OUString
sAsterix("*");
2156 OJoinTableView::OTableWindowMap::iterator aIter
= _pTabList
->begin();
2157 OJoinTableView::OTableWindowMap::iterator aEnd
= _pTabList
->end();
2158 for(;aIter
!= aEnd
&& eOk
== eErrorCode
;++aIter
)
2160 OQueryTableWindow
* pTabWin
= static_cast<OQueryTableWindow
*>(aIter
->second
);
2161 OTableFieldDescRef aInfo
= new OTableFieldDesc();
2162 if (pTabWin
->ExistsField( sAsterix
, aInfo
))
2164 eErrorCode
= _pView
->InsertField(aInfo
, sal_True
, bFirstField
);
2165 bFirstField
= sal_False
;
2170 //------------------------------------------------------------------------------
2171 SqlParseError
InstallFields(OQueryDesignView
* _pView
,
2172 const ::connectivity::OSQLParseNode
* pNode
,
2173 OJoinTableView::OTableWindowMap
* pTabList
)
2175 if( pNode
==0 || !SQL_ISRULE(pNode
,select_statement
))
2176 return eNoSelectStatement
;
2178 ::connectivity::OSQLParseNode
* pParseTree
= pNode
->getChild(2); // selection
2179 sal_Bool bFirstField
= sal_True
; // When initializing, the first field must be reactivated
2181 SqlParseError eErrorCode
= eOk
;
2183 if ( pParseTree
->isRule() && SQL_ISPUNCTUATION(pParseTree
->getChild(0),"*") )
2186 eErrorCode
= fillSelectSubList(_pView
,pTabList
);
2188 else if (SQL_ISRULE(pParseTree
,scalar_exp_commalist
) )
2190 // SELECT column, ...
2191 OQueryController
& rController
= static_cast<OQueryController
&>(_pView
->getController());
2192 Reference
< XConnection
> xConnection
= rController
.getConnection();
2194 OUString aColumnName
,aTableRange
;
2195 for (sal_uInt32 i
= 0; i
< pParseTree
->count() && eOk
== eErrorCode
; ++i
)
2197 ::connectivity::OSQLParseNode
* pColumnRef
= pParseTree
->getChild(i
);
2201 if ( SQL_ISRULE(pColumnRef
,select_sublist
) )
2203 eErrorCode
= fillSelectSubList(_pView
,pTabList
);
2207 if ( SQL_ISRULE(pColumnRef
,derived_column
) )
2209 OUString
aColumnAlias(rController
.getParseIterator().getColumnAlias(pColumnRef
)); // might be empty
2210 pColumnRef
= pColumnRef
->getChild(0);
2211 OTableFieldDescRef aInfo
= new OTableFieldDesc();
2213 if ( pColumnRef
->getKnownRuleID() != OSQLParseNode::subquery
&&
2214 pColumnRef
->count() == 3 &&
2215 SQL_ISPUNCTUATION(pColumnRef
->getChild(0),"(") &&
2216 SQL_ISPUNCTUATION(pColumnRef
->getChild(2),")")
2218 pColumnRef
= pColumnRef
->getChild(1);
2220 if (SQL_ISRULE(pColumnRef
,column_ref
))
2222 InsertColumnRef(_pView
,pColumnRef
,aColumnName
,aColumnAlias
,aTableRange
,aInfo
,pTabList
);
2223 eErrorCode
= _pView
->InsertField(aInfo
, sal_True
, bFirstField
);
2224 bFirstField
= sal_False
;
2226 else if(SQL_ISRULEOR3(pColumnRef
, general_set_fct
, set_fct_spec
, position_exp
) ||
2227 SQL_ISRULEOR3(pColumnRef
, extract_exp
, fold
, char_substring_fct
) ||
2228 SQL_ISRULEOR2(pColumnRef
,length_exp
,char_value_fct
))
2231 pColumnRef
->parseNodeToPredicateStr(aColumns
,
2233 rController
.getNumberFormatter(),
2234 _pView
->getLocale(),
2235 static_cast<sal_Char
>(_pView
->getDecimalSeparator().toChar()),
2236 &rController
.getParser().getContext());
2238 sal_Int32 nFunctionType
= FKT_NONE
;
2239 ::connectivity::OSQLParseNode
* pParamRef
= NULL
;
2240 sal_Int32 nColumnRefPos
= pColumnRef
->count() - 2;
2241 if ( nColumnRefPos
>= 0 && static_cast<sal_uInt32
>(nColumnRefPos
) < pColumnRef
->count() )
2242 pParamRef
= pColumnRef
->getChild(nColumnRefPos
);
2244 if ( SQL_ISRULE(pColumnRef
,general_set_fct
)
2245 && SQL_ISRULE(pParamRef
,column_ref
) )
2247 // Check the parameters for Column references
2248 InsertColumnRef(_pView
,pParamRef
,aColumnName
,aColumnAlias
,aTableRange
,aInfo
,pTabList
);
2250 else if ( SQL_ISRULE(pColumnRef
,general_set_fct
) )
2252 if ( pParamRef
&& pParamRef
->getTokenValue().toChar() == '*' )
2254 OJoinTableView::OTableWindowMap::iterator aIter
= pTabList
->begin();
2255 const OJoinTableView::OTableWindowMap::const_iterator aEnd
= pTabList
->end();
2256 for(;aIter
!= aEnd
;++aIter
)
2258 OQueryTableWindow
* pTabWin
= static_cast<OQueryTableWindow
*>(aIter
->second
);
2259 if (pTabWin
->ExistsField( OUString("*"), aInfo
))
2261 aInfo
->SetAlias(String());
2262 aInfo
->SetTable(String());
2269 OUString sFieldName
= aColumns
;
2271 { // we got an aggregate function but without column name inside
2272 // so we set the whole argument of the function as field name
2273 nFunctionType
|= FKT_NUMERIC
;
2274 sFieldName
= OUString();
2275 pParamRef
->parseNodeToStr( sFieldName
,
2277 &rController
.getParser().getContext(),
2279 sal_True
); // quote is to true because we need quoted elements inside the function
2281 aInfo
->SetDataType(DataType::DOUBLE
);
2282 aInfo
->SetFieldType(TAB_NORMAL_FIELD
);
2283 aInfo
->SetField(sFieldName
);
2285 aInfo
->SetTabWindow(NULL
);
2286 aInfo
->SetFieldAlias(aColumnAlias
);
2290 _pView
->fillFunctionInfo(pColumnRef
,aColumns
,aInfo
);
2291 aInfo
->SetFieldAlias(aColumnAlias
);
2294 if ( SQL_ISRULE(pColumnRef
,general_set_fct
) )
2296 aInfo
->SetFunctionType(nFunctionType
|FKT_AGGREGATE
);
2297 String
aCol(aColumns
);
2298 aInfo
->SetFunction(comphelper::string::stripEnd(aCol
.GetToken(0,'('), ' '));
2301 aInfo
->SetFunctionType(nFunctionType
|FKT_OTHER
);
2303 eErrorCode
= _pView
->InsertField(aInfo
, sal_True
, bFirstField
);
2304 bFirstField
= sal_False
;
2309 pColumnRef
->parseNodeToStr( aColumns
,
2311 &rController
.getParser().getContext(),
2313 sal_True
); // quote is to true because we need quoted elements inside the function
2315 aInfo
->SetTabWindow( NULL
);
2317 // since we support queries in queries, the thingie might belong to an existing "table"
2318 OQueryTableWindow
* pExistingTable
= lcl_findColumnInTables( aColumns
, *pTabList
, aInfo
);
2319 if ( pExistingTable
)
2321 aInfo
->SetTabWindow( pExistingTable
);
2322 aInfo
->SetTable( pExistingTable
->GetTableName() );
2323 aInfo
->SetAlias( pExistingTable
->GetAliasName() );
2326 aInfo
->SetDataType(DataType::DOUBLE
);
2327 aInfo
->SetFieldType(TAB_NORMAL_FIELD
);
2328 aInfo
->SetField(aColumns
);
2329 aInfo
->SetFieldAlias(aColumnAlias
);
2330 aInfo
->SetFunctionType(FKT_NUMERIC
| FKT_OTHER
);
2332 eErrorCode
= _pView
->InsertField(aInfo
, sal_True
, bFirstField
);
2333 bFirstField
= sal_False
;
2339 OSL_FAIL( "InstallFields: don't know how to interpret this parse node!" );
2345 eErrorCode
= eStatementTooComplex
;
2349 //------------------------------------------------------------------------------
2350 SqlParseError
GetOrderCriteria( OQueryDesignView
* _pView
,
2351 OSelectionBrowseBox
* _pSelectionBrw
,
2352 const ::connectivity::OSQLParseNode
* pParseRoot
)
2354 SqlParseError eErrorCode
= eOk
;
2355 if (!pParseRoot
->getChild(3)->getChild(ORDER_BY_CHILD_POS
)->isLeaf())
2357 ::connectivity::OSQLParseNode
* pNode
= pParseRoot
->getChild(3)->getChild(ORDER_BY_CHILD_POS
)->getChild(2);
2358 ::connectivity::OSQLParseNode
* pParamRef
= NULL
;
2360 OQueryController
& rController
= static_cast<OQueryController
&>(_pView
->getController());
2361 EOrderDir eOrderDir
;
2362 for( sal_uInt32 i
=0 ; i
<pNode
->count() ; i
++ )
2364 OTableFieldDescRef aDragLeft
= new OTableFieldDesc();
2365 eOrderDir
= ORDER_ASC
;
2366 ::connectivity::OSQLParseNode
* pChild
= pNode
->getChild( i
);
2368 if (SQL_ISTOKEN( pChild
->getChild(1), DESC
) )
2369 eOrderDir
= ORDER_DESC
;
2371 ::connectivity::OSQLParseNode
* pArgument
= pChild
->getChild(0);
2373 if(SQL_ISRULE(pArgument
,column_ref
))
2375 if( eOk
== FillDragInfo(_pView
,pArgument
,aDragLeft
))
2376 _pSelectionBrw
->AddOrder( aDragLeft
, eOrderDir
, i
);
2377 else // it could be a alias name for a field
2379 OUString aTableRange
,aColumnName
;
2380 ::connectivity::OSQLParseTreeIterator
& rParseIter
= rController
.getParseIterator();
2381 rParseIter
.getColumnRange( pArgument
, aColumnName
, aTableRange
);
2383 OTableFields
& aList
= rController
.getTableFieldDesc();
2384 OTableFields::iterator aIter
= aList
.begin();
2385 OTableFields::iterator aEnd
= aList
.end();
2386 for(;aIter
!= aEnd
;++aIter
)
2388 OTableFieldDescRef pEntry
= *aIter
;
2389 if(pEntry
.is() && pEntry
->GetFieldAlias() == aColumnName
)
2390 pEntry
->SetOrderDir( eOrderDir
);
2394 else if(SQL_ISRULE(pArgument
, general_set_fct
) &&
2395 SQL_ISRULE(pParamRef
= pArgument
->getChild(pArgument
->count()-2),column_ref
) &&
2396 eOk
== FillDragInfo(_pView
,pParamRef
,aDragLeft
))
2397 _pSelectionBrw
->AddOrder( aDragLeft
, eOrderDir
, i
);
2398 else if( SQL_ISRULE(pArgument
, set_fct_spec
) )
2401 Reference
< XConnection
> xConnection
= rController
.getConnection();
2402 if(xConnection
.is())
2404 OUString sCondition
;
2405 pArgument
->parseNodeToPredicateStr(sCondition
,
2407 rController
.getNumberFormatter(),
2408 _pView
->getLocale(),
2409 static_cast<sal_Char
>(_pView
->getDecimalSeparator().toChar()),
2410 &rController
.getParser().getContext());
2411 _pView
->fillFunctionInfo(pArgument
,sCondition
,aDragLeft
);
2412 aDragLeft
->SetFunctionType(FKT_OTHER
);
2413 aDragLeft
->SetOrderDir(eOrderDir
);
2414 aDragLeft
->SetVisible(sal_False
);
2415 _pSelectionBrw
->AddOrder( aDragLeft
, eOrderDir
, i
);
2418 eErrorCode
= eColumnNotFound
;
2421 eErrorCode
= eColumnNotFound
;
2426 //------------------------------------------------------------------------------
2427 SqlParseError
GetHavingCriteria( OQueryDesignView
* _pView
,
2428 OSelectionBrowseBox
* _pSelectionBrw
,
2429 const ::connectivity::OSQLParseNode
* pSelectRoot
,
2430 sal_uInt16
& rLevel
)
2432 SqlParseError eErrorCode
= eOk
;
2433 if (!pSelectRoot
->getChild(3)->getChild(3)->isLeaf())
2434 eErrorCode
= GetORCriteria(_pView
,_pSelectionBrw
,pSelectRoot
->getChild(3)->getChild(3)->getChild(1),rLevel
, sal_True
);
2437 //------------------------------------------------------------------------------
2438 SqlParseError
GetGroupCriteria( OQueryDesignView
* _pView
,
2439 OSelectionBrowseBox
* _pSelectionBrw
,
2440 const ::connectivity::OSQLParseNode
* pSelectRoot
)
2442 SqlParseError eErrorCode
= eOk
;
2443 if (!pSelectRoot
->getChild(3)->getChild(2)->isLeaf()) // opt_group_by_clause
2445 OQueryController
& rController
= static_cast<OQueryController
&>(_pView
->getController());
2446 ::connectivity::OSQLParseNode
* pGroupBy
= pSelectRoot
->getChild(3)->getChild(2)->getChild(2);
2448 for( sal_uInt32 i
=0 ; i
< pGroupBy
->count() && eOk
== eErrorCode
; ++i
)
2450 OTableFieldDescRef aDragInfo
= new OTableFieldDesc();
2451 ::connectivity::OSQLParseNode
* pParamRef
= NULL
;
2452 ::connectivity::OSQLParseNode
* pArgument
= pGroupBy
->getChild( i
);
2453 if(SQL_ISRULE(pArgument
,column_ref
))
2455 if ( eOk
== (eErrorCode
= FillDragInfo(_pView
,pArgument
,aDragInfo
)) )
2457 aDragInfo
->SetGroupBy(sal_True
);
2458 _pSelectionBrw
->AddGroupBy(aDragInfo
,i
);
2461 else if(SQL_ISRULE(pArgument
, general_set_fct
) &&
2462 SQL_ISRULE(pParamRef
= pArgument
->getChild(pArgument
->count()-2),column_ref
) &&
2463 eOk
== FillDragInfo(_pView
,pParamRef
,aDragInfo
))
2465 aDragInfo
->SetGroupBy(sal_True
);
2466 _pSelectionBrw
->AddGroupBy( aDragInfo
, i
);
2468 else if( SQL_ISRULE(pArgument
, set_fct_spec
) )
2470 Reference
< XConnection
> xConnection
= rController
.getConnection();
2471 if(xConnection
.is())
2473 OUString sGroupByExpression
;
2474 pArgument
->parseNodeToStr( sGroupByExpression
,
2476 &rController
.getParser().getContext(),
2478 sal_True
); // quote is to true because we need quoted elements inside the function
2479 _pView
->fillFunctionInfo(pArgument
,sGroupByExpression
,aDragInfo
);
2480 aDragInfo
->SetFunctionType(FKT_OTHER
);
2481 aDragInfo
->SetGroupBy(sal_True
);
2482 aDragInfo
->SetVisible(sal_False
);
2483 _pSelectionBrw
->AddGroupBy( aDragInfo
, i
);
2486 eErrorCode
= eColumnNotFound
;
2493 //------------------------------------------------------------------------------
2494 String
getParseErrorMessage( SqlParseError _eErrorCode
)
2500 nResId
= STR_QRY_ILLEGAL_JOIN
;
2502 case eStatementTooLong
:
2503 nResId
= STR_QRY_TOO_LONG_STATEMENT
;
2506 nResId
= STR_QRY_SYNTAX
;
2508 case eNoSelectStatement
:
2509 nResId
= STR_QRY_NOSELECT
;
2511 case eColumnInLikeNotFound
:
2512 nResId
= STR_QRY_SYNTAX
;
2514 case eNoColumnInLike
:
2515 nResId
= STR_QRY_SYNTAX
;
2517 case eColumnNotFound
:
2518 nResId
= STR_QRY_SYNTAX
;
2521 nResId
= STR_QRY_NATIVE
;
2523 case eTooManyTables
:
2524 nResId
= STR_QRY_TOO_MANY_TABLES
;
2526 case eTooManyConditions
:
2527 nResId
= STR_QRY_TOOMANYCOND
;
2529 case eTooManyColumns
:
2530 nResId
= STR_QRY_TOO_MANY_COLUMNS
;
2532 case eStatementTooComplex
:
2533 nResId
= STR_QRY_TOOCOMPLEX
;
2536 nResId
= STR_QRY_SYNTAX
;
2540 return String( ModuleRes( nResId
) );
2543 //------------------------------------------------------------------------------
2544 //------------------------------------------------------------------------------
2546 // end of anonymouse namespace
2547 DBG_NAME(OQueryDesignView
)
2549 OQueryDesignView::OQueryDesignView( OQueryContainerWindow
* _pParent
,
2550 OQueryController
& _rController
,
2551 const Reference
< XComponentContext
>& _rxContext
)
2552 :OQueryView( _pParent
, _rController
, _rxContext
)
2553 ,m_aSplitter( this )
2554 ,m_eChildFocus(NONE
)
2555 ,m_bInSplitHandler( sal_False
)
2557 DBG_CTOR(OQueryDesignView
,NULL
);
2561 SvtSysLocale aSysLocale
;
2562 m_aLocale
= aSysLocale
.GetLanguageTag().getLocale();
2563 m_sDecimalSep
= aSysLocale
.GetLocaleData().getNumDecimalSep();
2569 m_pSelectionBox
= new OSelectionBrowseBox(this);
2571 setNoneVisbleRow(static_cast<OQueryController
&>(getController()).getVisibleRows());
2572 m_pSelectionBox
->Show();
2574 m_aSplitter
.SetSplitHdl(LINK(this, OQueryDesignView
,SplitHdl
));
2578 // -----------------------------------------------------------------------------
2579 OQueryDesignView::~OQueryDesignView()
2582 ::dbaui::notifySystemWindow(this,m_pTableView
,::comphelper::mem_fun(&TaskPaneList::RemoveWindow
));
2583 SAL_WNODEPRECATED_DECLARATIONS_PUSH
2584 ::std::auto_ptr
<Window
> aTemp(m_pSelectionBox
);
2585 SAL_WNODEPRECATED_DECLARATIONS_POP
2586 m_pSelectionBox
= NULL
;
2588 DBG_DTOR(OQueryDesignView
,NULL
);
2590 //------------------------------------------------------------------------------
2591 IMPL_LINK( OQueryDesignView
, SplitHdl
, void*, /*p*/ )
2593 if (!getController().isReadOnly())
2595 m_bInSplitHandler
= sal_True
;
2596 m_aSplitter
.SetPosPixel( Point( m_aSplitter
.GetPosPixel().X(),m_aSplitter
.GetSplitPosPixel() ) );
2597 static_cast<OQueryController
&>(getController()).setSplitPos(m_aSplitter
.GetSplitPosPixel());
2598 static_cast<OQueryController
&>(getController()).setModified( sal_True
);
2600 m_bInSplitHandler
= sal_True
;
2604 // -------------------------------------------------------------------------
2605 void OQueryDesignView::Construct()
2607 m_pTableView
= new OQueryTableView(m_pScrollWindow
,this);
2608 ::dbaui::notifySystemWindow(this,m_pTableView
,::comphelper::mem_fun(&TaskPaneList::AddWindow
));
2609 OQueryView::Construct();
2611 // -----------------------------------------------------------------------------
2612 void OQueryDesignView::initialize()
2614 if(static_cast<OQueryController
&>(getController()).getSplitPos() != -1)
2616 m_aSplitter
.SetPosPixel( Point( m_aSplitter
.GetPosPixel().X(),static_cast<OQueryController
&>(getController()).getSplitPos() ) );
2617 m_aSplitter
.SetSplitPosPixel(static_cast<OQueryController
&>(getController()).getSplitPos());
2619 m_pSelectionBox
->initialize();
2622 // -------------------------------------------------------------------------
2623 void OQueryDesignView::resizeDocumentView(Rectangle
& _rPlayground
)
2625 Point
aPlaygroundPos( _rPlayground
.TopLeft() );
2626 Size
aPlaygroundSize( _rPlayground
.GetSize() );
2628 // calc the split pos, and forward it to the controller
2629 sal_Int32 nSplitPos
= static_cast<OQueryController
&>(getController()).getSplitPos();
2630 if ( 0 != aPlaygroundSize
.Height() )
2632 if ( ( -1 == nSplitPos
)
2633 || ( nSplitPos
>= aPlaygroundSize
.Height() )
2636 // let the selection browse box determine an optimal size
2637 Size aSelectionBoxSize
= m_pSelectionBox
->CalcOptimalSize( aPlaygroundSize
);
2638 nSplitPos
= aPlaygroundSize
.Height() - aSelectionBoxSize
.Height() - m_aSplitter
.GetSizePixel().Height();
2639 // still an invalid size?
2640 if ( nSplitPos
== -1 || nSplitPos
>= aPlaygroundSize
.Height() )
2641 nSplitPos
= sal_Int32(aPlaygroundSize
.Height()*0.6);
2643 static_cast<OQueryController
&>(getController()).setSplitPos(nSplitPos
);
2646 if ( !m_bInSplitHandler
)
2647 { // the resize is triggered by something else than the split handler
2648 // our main focus is to try to preserve the size of the selectionbrowse box
2649 Size aSelBoxSize
= m_pSelectionBox
->GetSizePixel();
2650 if ( aSelBoxSize
.Height() )
2652 // keep the size of the sel box constant
2653 nSplitPos
= aPlaygroundSize
.Height() - m_aSplitter
.GetSizePixel().Height() - aSelBoxSize
.Height();
2655 // and if the box is smaller than the optimal size, try to do something about it
2656 Size aSelBoxOptSize
= m_pSelectionBox
->CalcOptimalSize( aPlaygroundSize
);
2657 if ( aSelBoxOptSize
.Height() > aSelBoxSize
.Height() )
2659 nSplitPos
= aPlaygroundSize
.Height() - m_aSplitter
.GetSizePixel().Height() - aSelBoxOptSize
.Height();
2662 static_cast< OQueryController
& >(getController()).setSplitPos( nSplitPos
);
2667 // normalize the split pos
2668 Point aSplitPos
= Point( _rPlayground
.Left(), nSplitPos
);
2669 Size aSplitSize
= Size( _rPlayground
.GetSize().Width(), m_aSplitter
.GetSizePixel().Height() );
2671 if( ( aSplitPos
.Y() + aSplitSize
.Height() ) > ( aPlaygroundSize
.Height() ))
2672 aSplitPos
.Y() = aPlaygroundSize
.Height() - aSplitSize
.Height();
2674 if( aSplitPos
.Y() <= aPlaygroundPos
.Y() )
2675 aSplitPos
.Y() = aPlaygroundPos
.Y() + sal_Int32(aPlaygroundSize
.Height() * 0.2);
2677 // position the table
2678 Size
aTableViewSize(aPlaygroundSize
.Width(), aSplitPos
.Y() - aPlaygroundPos
.Y());
2679 m_pScrollWindow
->SetPosSizePixel(aPlaygroundPos
, aTableViewSize
);
2681 // position the selection browse box
2682 Point
aPos( aPlaygroundPos
.X(), aSplitPos
.Y() + aSplitSize
.Height() );
2683 m_pSelectionBox
->SetPosSizePixel( aPos
, Size( aPlaygroundSize
.Width(), aPlaygroundSize
.Height() - aSplitSize
.Height() - aTableViewSize
.Height() ));
2685 // set the size of the splitter
2686 m_aSplitter
.SetPosSizePixel( aSplitPos
, aSplitSize
);
2687 m_aSplitter
.SetDragRectPixel( _rPlayground
);
2689 // just for completeness: there is no space left, we occupied it all ...
2690 _rPlayground
.SetPos( _rPlayground
.BottomRight() );
2691 _rPlayground
.SetSize( Size( 0, 0 ) );
2693 // -----------------------------------------------------------------------------
2694 void OQueryDesignView::setReadOnly(sal_Bool _bReadOnly
)
2696 m_pSelectionBox
->SetReadOnly(_bReadOnly
);
2698 // -----------------------------------------------------------------------------
2699 void OQueryDesignView::clear()
2701 m_pSelectionBox
->ClearAll(); // clear the whole selection
2702 m_pTableView
->ClearAll();
2704 // -----------------------------------------------------------------------------
2705 void OQueryDesignView::setStatement(const OUString
& /*_rsStatement*/)
2708 // -----------------------------------------------------------------------------
2709 void OQueryDesignView::copy()
2711 if( m_eChildFocus
== SELECTION
)
2712 m_pSelectionBox
->copy();
2714 // -----------------------------------------------------------------------------
2715 sal_Bool
OQueryDesignView::isCutAllowed()
2717 sal_Bool bAllowed
= sal_False
;
2718 if ( SELECTION
== m_eChildFocus
)
2719 bAllowed
= m_pSelectionBox
->isCutAllowed();
2722 // -----------------------------------------------------------------------------
2723 sal_Bool
OQueryDesignView::isPasteAllowed()
2725 sal_Bool bAllowed
= sal_False
;
2726 if ( SELECTION
== m_eChildFocus
)
2727 bAllowed
= m_pSelectionBox
->isPasteAllowed();
2730 // -----------------------------------------------------------------------------
2731 sal_Bool
OQueryDesignView::isCopyAllowed()
2733 sal_Bool bAllowed
= sal_False
;
2734 if ( SELECTION
== m_eChildFocus
)
2735 bAllowed
= m_pSelectionBox
->isCopyAllowed();
2738 // -----------------------------------------------------------------------------
2739 void OQueryDesignView::stopTimer()
2741 m_pSelectionBox
->stopTimer();
2743 // -----------------------------------------------------------------------------
2744 void OQueryDesignView::startTimer()
2746 m_pSelectionBox
->startTimer();
2748 // -----------------------------------------------------------------------------
2749 void OQueryDesignView::cut()
2751 if( m_eChildFocus
== SELECTION
)
2753 m_pSelectionBox
->cut();
2754 static_cast<OQueryController
&>(getController()).setModified(sal_True
);
2757 // -----------------------------------------------------------------------------
2758 void OQueryDesignView::paste()
2760 if( m_eChildFocus
== SELECTION
)
2762 m_pSelectionBox
->paste();
2763 static_cast<OQueryController
&>(getController()).setModified(sal_True
);
2766 // -----------------------------------------------------------------------------
2767 void OQueryDesignView::TableDeleted(const OUString
& rAliasName
)
2769 // message that the table was removed from the window
2770 DeleteFields(rAliasName
);
2771 static_cast<OQueryController
&>(getController()).InvalidateFeature(ID_BROWSER_ADDTABLE
); // inform the view again
2773 //------------------------------------------------------------------------------
2774 void OQueryDesignView::DeleteFields( const OUString
& rAliasName
)
2776 m_pSelectionBox
->DeleteFields( rAliasName
);
2778 // -----------------------------------------------------------------------------
2779 bool OQueryDesignView::HasFieldByAliasName(const OUString
& rFieldName
, OTableFieldDescRef
& rInfo
) const
2781 return m_pSelectionBox
->HasFieldByAliasName( rFieldName
, rInfo
);
2783 // -----------------------------------------------------------------------------
2784 SqlParseError
OQueryDesignView::InsertField( const OTableFieldDescRef
& rInfo
, sal_Bool bVis
, sal_Bool bActivate
)
2786 return m_pSelectionBox
->InsertField( rInfo
, BROWSER_INVALIDID
,bVis
, bActivate
).is() ? eOk
: eTooManyColumns
;
2788 // -----------------------------------------------------------------------------
2789 sal_Int32
OQueryDesignView::getColWidth(sal_uInt16 _nColPos
) const
2791 static sal_Int32 s_nDefaultWidth
= GetTextWidth(String(RTL_CONSTASCII_USTRINGPARAM("0"))) * 15;
2792 sal_Int32 nWidth
= static_cast<OQueryController
&>(getController()).getColWidth(_nColPos
);
2794 nWidth
= s_nDefaultWidth
;
2797 //------------------------------------------------------------------------------
2798 void OQueryDesignView::fillValidFields(const OUString
& sAliasName
, ComboBox
* pFieldList
)
2800 OSL_ENSURE(pFieldList
!= NULL
, "OQueryDesignView::FillValidFields : What the hell do you think I can do with a NULL-ptr ? This will crash !");
2801 pFieldList
->Clear();
2803 sal_Bool bAllTables
= sAliasName
.isEmpty();
2805 OJoinTableView::OTableWindowMap
* pTabWins
= m_pTableView
->GetTabWinMap();
2806 OUString strCurrentPrefix
;
2807 ::std::vector
< OUString
> aFields
;
2808 OJoinTableView::OTableWindowMap::iterator aIter
= pTabWins
->begin();
2809 OJoinTableView::OTableWindowMap::iterator aEnd
= pTabWins
->end();
2810 for(;aIter
!= aEnd
;++aIter
)
2812 OQueryTableWindow
* pCurrentWin
= static_cast<OQueryTableWindow
*>(aIter
->second
);
2813 if (bAllTables
|| (pCurrentWin
->GetAliasName() == sAliasName
))
2815 strCurrentPrefix
= pCurrentWin
->GetAliasName();
2816 strCurrentPrefix
+= OUString('.');
2818 pCurrentWin
->EnumValidFields(aFields
);
2820 ::std::vector
< OUString
>::iterator aStrIter
= aFields
.begin();
2821 ::std::vector
< OUString
>::iterator aStrEnd
= aFields
.end();
2822 for(;aStrIter
!= aStrEnd
;++aStrIter
)
2824 if (bAllTables
|| aStrIter
->toChar() == '*')
2825 pFieldList
->InsertEntry(OUString(strCurrentPrefix
) += *aStrIter
);
2827 pFieldList
->InsertEntry(*aStrIter
);
2831 // this means that I came into this block because the table name was exactly what I was looking for so I can end here
2832 // (and I prevent that fields get added more than once, if a table is repeated in TabWin)
2837 // -----------------------------------------------------------------------------
2838 long OQueryDesignView::PreNotify(NotifyEvent
& rNEvt
)
2840 switch (rNEvt
.GetType())
2842 case EVENT_GETFOCUS
:
2843 #if OSL_DEBUG_LEVEL > 0
2845 Window
* pFocus
= Application::GetFocusWindow();
2850 if ( m_pSelectionBox
&& m_pSelectionBox
->HasChildPathFocus() )
2851 m_eChildFocus
= SELECTION
;
2853 m_eChildFocus
= TABLEVIEW
;
2857 return OQueryView::PreNotify(rNEvt
);
2859 //------------------------------------------------------------------------------
2862 // -----------------------------------------------------------------------------
2863 // check if the statement is correct when not returning false
2864 sal_Bool
OQueryDesignView::checkStatement()
2866 sal_Bool bRet
= sal_True
;
2867 if ( m_pSelectionBox
)
2868 bRet
= m_pSelectionBox
->Save(); // an error occurred so we return no
2871 //-------------------------------------------------------------------------------
2872 OUString
OQueryDesignView::getStatement()
2874 OQueryController
& rController
= static_cast<OQueryController
&>(getController());
2875 m_rController
.clearError();
2876 // used for fields which aren't any longer in the statement
2877 OTableFields
& rUnUsedFields
= rController
.getUnUsedFields();
2878 OTableFields().swap( rUnUsedFields
);
2880 // create the select columns
2881 sal_uInt32 nFieldcount
= 0;
2882 OTableFields
& rFieldList
= rController
.getTableFieldDesc();
2883 OTableFields::iterator aIter
= rFieldList
.begin();
2884 OTableFields::iterator aEnd
= rFieldList
.end();
2885 for(;aIter
!= aEnd
;++aIter
)
2887 OTableFieldDescRef pEntryField
= *aIter
;
2888 if (!pEntryField
->GetField().isEmpty() && pEntryField
->IsVisible() )
2890 else if (!pEntryField
->GetField().isEmpty() &&
2891 !pEntryField
->HasCriteria() &&
2892 pEntryField
->isNoneFunction() &&
2893 pEntryField
->GetOrderDir() == ORDER_NONE
&&
2894 !pEntryField
->IsGroupBy() &&
2895 pEntryField
->GetFunction().isEmpty() )
2896 rUnUsedFields
.push_back(pEntryField
);
2898 if ( !nFieldcount
) // no visible fields so return
2900 rUnUsedFields
= rFieldList
;
2904 OQueryTableView::OTableWindowMap
* pTabList
= m_pTableView
->GetTabWinMap();
2905 sal_uInt32 nTabcount
= pTabList
->size();
2907 OUString
aFieldListStr(GenerateSelectList(this,rFieldList
,nTabcount
>1));
2908 if( aFieldListStr
.isEmpty() )
2911 // Exceptionhandling, if no fields have been passed we should not
2912 // change the tab page
2913 // TabBarSelectHdl will query the SQL-OUString for STATEMENT_NOFIELDS
2914 // and trigger a error message
2915 // ----------------- Build table list ----------------------
2917 const ::std::vector
<OTableConnection
*>* pConnList
= m_pTableView
->getTableConnections();
2918 Reference
< XConnection
> xConnection
= rController
.getConnection();
2919 OUString
aTableListStr(GenerateFromClause(xConnection
,pTabList
,pConnList
));
2920 OSL_ENSURE(!aTableListStr
.isEmpty(), "OQueryDesignView::getStatement() : unexpected : have Fields, but no Tables !");
2921 // if fields exist now, these only can be created by inserting from an already existing table; if on the other hand
2922 // a table is deleted, also the belonging fields will be deleted -> therefore it CANNOT occur that fields
2923 // exist but no tables exist (and aFieldListStr has its length, I secure this above)
2924 OUStringBuffer aHavingStr
,aCriteriaListStr
;
2925 // ----------------- Kriterien aufbauen ----------------------
2926 if (!GenerateCriterias(this,aCriteriaListStr
,aHavingStr
,rFieldList
, nTabcount
> 1))
2930 GenerateInnerJoinCriterias(xConnection
,aJoinCrit
,pConnList
);
2931 if(!aJoinCrit
.isEmpty())
2933 OUString
aTmp("( ");
2935 aTmp
+= OUString(" )");
2936 if(aCriteriaListStr
.getLength())
2939 aTmp
+= aCriteriaListStr
.makeStringAndClear();
2941 aCriteriaListStr
= aTmp
;
2943 // ----------------- construct statement ----------------------
2944 OUStringBuffer
aSqlCmd(OUString("SELECT "));
2945 if(rController
.isDistinct())
2946 aSqlCmd
.append(OUString(" DISTINCT "));
2947 aSqlCmd
.append(aFieldListStr
);
2948 aSqlCmd
.append(OUString(" FROM "));
2949 aSqlCmd
.append(aTableListStr
);
2951 if (aCriteriaListStr
.getLength())
2953 aSqlCmd
.append(OUString(" WHERE "));
2954 aSqlCmd
.append(aCriteriaListStr
.makeStringAndClear());
2956 // ----------------- construct GroupBy and attachen ------------
2957 Reference
<XDatabaseMetaData
> xMeta
;
2958 if ( xConnection
.is() )
2959 xMeta
= xConnection
->getMetaData();
2960 sal_Bool bUseAlias
= nTabcount
> 1;
2962 bUseAlias
= bUseAlias
|| !xMeta
->supportsGroupByUnrelated();
2964 aSqlCmd
.append(GenerateGroupBy(this,rFieldList
,bUseAlias
));
2965 // ----------------- attache having ------------
2966 if(aHavingStr
.getLength())
2968 aSqlCmd
.append(OUString(" HAVING "));
2969 aSqlCmd
.append(aHavingStr
.makeStringAndClear());
2971 // ----------------- construct sorting and attach ------------
2973 SqlParseError eErrorCode
= eOk
;
2974 if ( (eErrorCode
= GenerateOrder(this,rFieldList
,nTabcount
> 1,sOrder
)) == eOk
)
2975 aSqlCmd
.append(sOrder
);
2978 if ( !m_rController
.hasError() )
2979 m_rController
.appendError( getParseErrorMessage( eErrorCode
) );
2981 m_rController
.displayError();
2983 // --------------------- Limit Clause -------------------
2985 const sal_Int64 nLimit
= rController
.getLimit();
2988 aSqlCmd
.append( " LIMIT " + OUString::number(nLimit
) );
2992 OUString sSQL
= aSqlCmd
.makeStringAndClear();
2993 if ( xConnection
.is() )
2995 ::connectivity::OSQLParser
& rParser( rController
.getParser() );
2996 OUString sErrorMessage
;
2997 SAL_WNODEPRECATED_DECLARATIONS_PUSH
2998 ::std::auto_ptr
<OSQLParseNode
> pParseNode( rParser
.parseTree( sErrorMessage
, sSQL
, sal_True
) );
2999 SAL_WNODEPRECATED_DECLARATIONS_POP
3000 if ( pParseNode
.get() )
3002 OSQLParseNode
* pNode
= pParseNode
->getChild(3)->getChild(1);
3003 if ( pNode
->count() > 1 )
3005 ::connectivity::OSQLParseNode
* pCondition
= pNode
->getChild(1);
3006 if ( pCondition
) // no where clause
3008 OSQLParseNode::compress(pCondition
);
3010 pParseNode
->parseNodeToStr(sTemp
,xConnection
);
3018 // -----------------------------------------------------------------------------
3019 // -----------------------------------------------------------------------------
3020 void OQueryDesignView::setSlotEnabled(sal_Int32 _nSlotId
,sal_Bool _bEnable
)
3025 case SID_QUERY_VIEW_FUNCTIONS
:
3026 nRow
= BROW_FUNCTION_ROW
;
3028 case SID_QUERY_VIEW_TABLES
:
3029 nRow
= BROW_TABLE_ROW
;
3031 case SID_QUERY_VIEW_ALIASES
:
3032 nRow
= BROW_COLUMNALIAS_ROW
;
3039 m_pSelectionBox
->SetRowVisible(nRow
,_bEnable
);
3040 m_pSelectionBox
->Invalidate();
3042 // -----------------------------------------------------------------------------
3043 sal_Bool
OQueryDesignView::isSlotEnabled(sal_Int32 _nSlotId
)
3048 case SID_QUERY_VIEW_FUNCTIONS
:
3049 nRow
= BROW_FUNCTION_ROW
;
3051 case SID_QUERY_VIEW_TABLES
:
3052 nRow
= BROW_TABLE_ROW
;
3054 case SID_QUERY_VIEW_ALIASES
:
3055 nRow
= BROW_COLUMNALIAS_ROW
;
3062 return m_pSelectionBox
->IsRowVisible(nRow
);
3064 // -----------------------------------------------------------------------------
3065 void OQueryDesignView::SaveUIConfig()
3067 OQueryController
& rCtrl
= static_cast<OQueryController
&>(getController());
3068 rCtrl
.SaveTabWinsPosSize( m_pTableView
->GetTabWinMap(), m_pScrollWindow
->GetHScrollBar()->GetThumbPos(), m_pScrollWindow
->GetVScrollBar()->GetThumbPos() );
3069 rCtrl
.setVisibleRows( m_pSelectionBox
->GetNoneVisibleRows() );
3070 if ( m_aSplitter
.GetSplitPosPixel() != 0 )
3071 rCtrl
.setSplitPos( m_aSplitter
.GetSplitPosPixel() );
3073 // -----------------------------------------------------------------------------
3074 OSQLParseNode
* OQueryDesignView::getPredicateTreeFromEntry(OTableFieldDescRef pEntry
,
3075 const OUString
& _sCriteria
,
3076 OUString
& _rsErrorMessage
,
3077 Reference
<XPropertySet
>& _rxColumn
) const
3079 OSL_ENSURE(pEntry
.is(),"Entry is null!");
3082 Reference
< XConnection
> xConnection
= static_cast<OQueryController
&>(getController()).getConnection();
3083 if(!xConnection
.is())
3086 ::connectivity::OSQLParser
& rParser( static_cast<OQueryController
&>(getController()).getParser() );
3087 OQueryTableWindow
* pWin
= static_cast<OQueryTableWindow
*>(pEntry
->GetTabWindow());
3089 // special handling for functions
3090 if ( pEntry
->GetFunctionType() & (FKT_OTHER
| FKT_AGGREGATE
| FKT_NUMERIC
) )
3092 // we have a function here so we have to distinguish the type of return value
3094 if ( pEntry
->isNumericOrAggreateFunction() )
3095 sFunction
= pEntry
->GetFunction();
3097 if ( !sFunction
.Len() )
3098 sFunction
= pEntry
->GetField();
3100 if (comphelper::string::getTokenCount(sFunction
, '(') > 1)
3101 sFunction
= sFunction
.GetToken(0,'('); // this should be the name of the function
3103 sal_Int32 nType
= ::connectivity::OSQLParser::getFunctionReturnType(sFunction
,&rParser
.getContext());
3104 if ( nType
== DataType::OTHER
|| (!sFunction
.Len() && pEntry
->isNumericOrAggreateFunction()) )
3106 // first try the international version
3108 sSql
+= "SELECT * ";
3109 sSql
+= " FROM x WHERE ";
3110 sSql
+= pEntry
->GetField();
3112 SAL_WNODEPRECATED_DECLARATIONS_PUSH
3113 ::std::auto_ptr
<OSQLParseNode
> pParseNode( rParser
.parseTree( _rsErrorMessage
, sSql
, sal_True
) );
3114 SAL_WNODEPRECATED_DECLARATIONS_POP
3115 nType
= DataType::DOUBLE
;
3116 if ( pParseNode
.get() )
3118 OSQLParseNode
* pColumnRef
= pParseNode
->getByRule(OSQLParseNode::column_ref
);
3121 OTableFieldDescRef aField
= new OTableFieldDesc();
3122 if ( eOk
== FillDragInfo(this,pColumnRef
,aField
) )
3124 nType
= aField
->GetDataType();
3130 Reference
<XDatabaseMetaData
> xMeta
= xConnection
->getMetaData();
3131 parse::OParseColumn
* pColumn
= new parse::OParseColumn( pEntry
->GetField(),
3135 ColumnValue::NULLABLE_UNKNOWN
,
3141 xMeta
.is() && xMeta
->supportsMixedCaseQuotedIdentifiers(),
3145 _rxColumn
= pColumn
;
3146 pColumn
->setFunction(sal_True
);
3147 pColumn
->setRealName(pEntry
->GetField());
3153 Reference
<XNameAccess
> xColumns
= pWin
->GetOriginalColumns();
3154 if (xColumns
.is() && xColumns
->hasByName(pEntry
->GetField()))
3155 xColumns
->getByName(pEntry
->GetField()) >>= _rxColumn
;
3159 OUString
sTest(_sCriteria
);
3160 OSQLParseNode
* pParseNode
= rParser
.predicateTree( _rsErrorMessage
,
3162 static_cast<OQueryController
&>(getController()).getNumberFormatter(),
3166 // -----------------------------------------------------------------------------
3167 void OQueryDesignView::GetFocus()
3169 OQueryView::GetFocus();
3170 if ( m_pSelectionBox
&& !m_pSelectionBox
->HasChildPathFocus() )
3172 // first we have to deactivate the current cell to refill when necessary
3173 m_pSelectionBox
->DeactivateCell();
3174 m_pSelectionBox
->ActivateCell(m_pSelectionBox
->GetCurRow(), m_pSelectionBox
->GetCurColumnId());
3175 m_pSelectionBox
->GrabFocus();
3178 // -----------------------------------------------------------------------------
3179 void OQueryDesignView::reset()
3181 m_pTableView
->ClearAll();
3182 m_pTableView
->ReSync();
3184 // -----------------------------------------------------------------------------
3185 void OQueryDesignView::setNoneVisbleRow(sal_Int32 _nRows
)
3187 m_pSelectionBox
->SetNoneVisbleRow(_nRows
);
3190 // -----------------------------------------------------------------------------
3191 void OQueryDesignView::initByFieldDescriptions( const Sequence
< PropertyValue
>& i_rFieldDescriptions
)
3193 OQueryController
& rController
= static_cast< OQueryController
& >( getController() );
3195 m_pSelectionBox
->PreFill();
3196 m_pSelectionBox
->SetReadOnly( rController
.isReadOnly() );
3197 m_pSelectionBox
->Fill();
3199 for ( const PropertyValue
* field
= i_rFieldDescriptions
.getConstArray();
3200 field
!= i_rFieldDescriptions
.getConstArray() + i_rFieldDescriptions
.getLength();
3204 ::rtl::Reference
< OTableFieldDesc
> pField( new OTableFieldDesc() );
3205 pField
->Load( *field
, true );
3206 InsertField( pField
, sal_True
, sal_False
);
3209 rController
.ClearUndoManager();
3210 m_pSelectionBox
->Invalidate();
3213 // -----------------------------------------------------------------------------
3214 bool OQueryDesignView::initByParseIterator( ::dbtools::SQLExceptionInfo
* _pErrorInfo
)
3216 SqlParseError eErrorCode
= eNativeMode
;
3217 m_rController
.clearError();
3221 eErrorCode
= InitFromParseNodeImpl( this, m_pSelectionBox
);
3223 if ( eErrorCode
!= eOk
)
3225 if ( !m_rController
.hasError() )
3226 m_rController
.appendError( getParseErrorMessage( eErrorCode
) );
3230 *_pErrorInfo
= m_rController
.getError();
3234 m_rController
.displayError();
3238 catch ( const Exception
& )
3240 DBG_UNHANDLED_EXCEPTION();
3242 return eErrorCode
== eOk
;
3245 // Utility function for fillFunctionInfo
3247 sal_Int32
char_datatype(const::connectivity::OSQLParseNode
* pDataType
, const unsigned int offset
) {
3248 int cnt
= pDataType
->count() - offset
;
3251 OSL_FAIL("internal error in decoding character datatype specification");
3252 return DataType::VARCHAR
;
3254 else if ( cnt
== 0 )
3258 // The datatype is the node itself
3259 if ( SQL_ISTOKENOR2 (pDataType
, CHARACTER
, CHAR
) )
3260 return DataType::CHAR
;
3261 else if ( SQL_ISTOKEN (pDataType
, VARCHAR
) )
3262 return DataType::VARCHAR
;
3263 else if ( SQL_ISTOKEN (pDataType
, CLOB
) )
3264 return DataType::CLOB
;
3267 OSL_FAIL("unknown/unexpected token in decoding character datatype specification");
3268 return DataType::VARCHAR
;
3273 // No child left to read!
3274 OSL_FAIL("incomplete datatype in decoding character datatype specification");
3275 return DataType::VARCHAR
;
3279 if ( SQL_ISTOKEN(pDataType
->getChild(offset
), NATIONAL
) )
3280 return char_datatype(pDataType
, offset
+1);
3281 else if ( SQL_ISTOKENOR3(pDataType
->getChild(offset
), CHARACTER
, CHAR
, NCHAR
) )
3283 if ( cnt
> 2 && SQL_ISTOKEN(pDataType
->getChild(offset
+1), LARGE
) && SQL_ISTOKEN(pDataType
->getChild(offset
+2), OBJECT
) )
3284 return DataType::CLOB
;
3285 else if ( cnt
> 1 && SQL_ISTOKEN(pDataType
->getChild(offset
+1), VARYING
) )
3286 return DataType::VARCHAR
;
3288 return DataType::CHAR
;
3290 else if ( SQL_ISTOKEN (pDataType
->getChild(offset
), VARCHAR
) )
3291 return DataType::VARCHAR
;
3292 else if ( SQL_ISTOKENOR2 (pDataType
->getChild(offset
), CLOB
, NCLOB
) )
3293 return DataType::CLOB
;
3295 OSL_FAIL("unrecognised character datatype");
3296 return DataType::VARCHAR
;
3300 //------------------------------------------------------------------------------
3301 // Try to guess the type of an expression in simple cases.
3302 // Originally meant to be called only on a function call (hence the misnomer),
3303 // but now tries to do the best it can also in other cases.
3304 // Don't completely rely on fillFunctionInfo,
3305 // it won't look at the function's arguments to find the return type
3306 // (in particular, in the case of general_set_fct,
3307 // the return type is the type of the argument;
3308 // if that is (as is typical) a column reference,
3309 // it is the type of the column).
3310 // TODO: There is similar "guess the expression's type" code in several places:
3311 // SelectionBrowseBox.cxx: OSelectionBrowseBox::saveField
3312 // QueryDesignView.cxx: InstallFields, GetOrderCriteria, GetGroupCriteria
3313 // If possible, they should be factorised into this function
3314 // (which should then be renamed...)
3316 void OQueryDesignView::fillFunctionInfo( const ::connectivity::OSQLParseNode
* pNode
3317 ,const OUString
& sFunctionTerm
3318 ,OTableFieldDescRef
& aInfo
)
3320 // get the type of the expression, as far as easily possible
3321 OQueryController
& rController
= static_cast<OQueryController
&>(getController());
3322 sal_Int32 nDataType
= DataType::DOUBLE
;
3323 switch(pNode
->getNodeType())
3325 case SQL_NODE_CONCAT
:
3326 case SQL_NODE_STRING
:
3327 nDataType
= DataType::VARCHAR
;
3329 case SQL_NODE_INTNUM
:
3330 nDataType
= DataType::INTEGER
;
3332 case SQL_NODE_APPROXNUM
:
3333 nDataType
= DataType::DOUBLE
;
3336 case SQL_NODE_ACCESS_DATE
:
3337 nDataType
= DataType::TIMESTAMP
;
3339 case SQL_NODE_COMPARISON
:
3340 case SQL_NODE_EQUAL
:
3342 case SQL_NODE_GREAT
:
3343 case SQL_NODE_LESSEQ
:
3344 case SQL_NODE_GREATEQ
:
3345 case SQL_NODE_NOTEQUAL
:
3346 nDataType
= DataType::BOOLEAN
;
3349 case SQL_NODE_LISTRULE
:
3350 case SQL_NODE_COMMALISTRULE
:
3351 case SQL_NODE_KEYWORD
:
3352 case SQL_NODE_AMMSC
: //??
3353 case SQL_NODE_PUNCTUATION
:
3354 OSL_FAIL("Unexpected SQL Node Type");
3357 switch(pNode
->getKnownRuleID())
3359 case OSQLParseNode::select_statement
:
3360 case OSQLParseNode::table_exp
:
3361 case OSQLParseNode::table_ref_commalist
:
3362 case OSQLParseNode::table_ref
:
3363 case OSQLParseNode::catalog_name
:
3364 case OSQLParseNode::schema_name
:
3365 case OSQLParseNode::table_name
:
3366 case OSQLParseNode::opt_column_commalist
:
3367 case OSQLParseNode::column_commalist
:
3368 case OSQLParseNode::column_ref_commalist
:
3369 case OSQLParseNode::column_ref
:
3370 case OSQLParseNode::opt_order_by_clause
:
3371 case OSQLParseNode::ordering_spec_commalist
:
3372 case OSQLParseNode::ordering_spec
:
3373 case OSQLParseNode::opt_asc_desc
:
3374 case OSQLParseNode::where_clause
:
3375 case OSQLParseNode::opt_where_clause
:
3376 case OSQLParseNode::opt_escape
:
3377 case OSQLParseNode::scalar_exp_commalist
:
3378 case OSQLParseNode::scalar_exp
: // Seems to never be generated?
3379 case OSQLParseNode::parameter_ref
:
3380 case OSQLParseNode::parameter
:
3381 case OSQLParseNode::range_variable
:
3382 case OSQLParseNode::delete_statement_positioned
:
3383 case OSQLParseNode::delete_statement_searched
:
3384 case OSQLParseNode::update_statement_positioned
:
3385 case OSQLParseNode::update_statement_searched
:
3386 case OSQLParseNode::assignment_commalist
:
3387 case OSQLParseNode::assignment
:
3388 case OSQLParseNode::insert_statement
:
3389 case OSQLParseNode::insert_atom_commalist
:
3390 case OSQLParseNode::insert_atom
:
3391 case OSQLParseNode::from_clause
:
3392 case OSQLParseNode::qualified_join
:
3393 case OSQLParseNode::cross_union
:
3394 case OSQLParseNode::select_sublist
:
3395 case OSQLParseNode::join_type
:
3396 case OSQLParseNode::named_columns_join
:
3397 case OSQLParseNode::joined_table
:
3398 case OSQLParseNode::sql_not
:
3399 case OSQLParseNode::manipulative_statement
:
3400 case OSQLParseNode::value_exp_commalist
:
3401 case OSQLParseNode::union_statement
:
3402 case OSQLParseNode::outer_join_type
:
3403 case OSQLParseNode::selection
:
3404 case OSQLParseNode::base_table_def
:
3405 case OSQLParseNode::base_table_element_commalist
:
3406 case OSQLParseNode::data_type
:
3407 case OSQLParseNode::column_def
:
3408 case OSQLParseNode::table_node
:
3409 case OSQLParseNode::as_clause
:
3410 case OSQLParseNode::opt_as
:
3411 case OSQLParseNode::op_column_commalist
:
3412 case OSQLParseNode::table_primary_as_range_column
:
3413 case OSQLParseNode::character_string_type
:
3414 OSL_FAIL("Unexpected SQL RuleID");
3416 case OSQLParseNode::column
:
3417 case OSQLParseNode::column_val
:
3418 OSL_FAIL("Cannot guess column type");
3420 case OSQLParseNode::values_or_query_spec
:
3421 OSL_FAIL("Cannot guess VALUES type");
3423 case OSQLParseNode::derived_column
:
3424 OSL_FAIL("Cannot guess computed column type");
3426 case OSQLParseNode::subquery
:
3427 OSL_FAIL("Cannot guess subquery return type");
3429 case OSQLParseNode::search_condition
:
3430 case OSQLParseNode::comparison_predicate
:
3431 case OSQLParseNode::between_predicate
:
3432 case OSQLParseNode::like_predicate
:
3433 case OSQLParseNode::test_for_null
:
3434 case OSQLParseNode::boolean_term
:
3435 case OSQLParseNode::boolean_primary
:
3436 case OSQLParseNode::in_predicate
:
3437 case OSQLParseNode::existence_test
:
3438 case OSQLParseNode::unique_test
:
3439 case OSQLParseNode::all_or_any_predicate
:
3440 case OSQLParseNode::join_condition
:
3441 case OSQLParseNode::boolean_factor
:
3442 case OSQLParseNode::boolean_test
:
3443 case OSQLParseNode::comparison_predicate_part_2
:
3444 case OSQLParseNode::parenthesized_boolean_value_expression
:
3445 case OSQLParseNode::other_like_predicate_part_2
:
3446 case OSQLParseNode::between_predicate_part_2
:
3447 nDataType
= DataType::BOOLEAN
;
3449 case OSQLParseNode::num_value_exp
:
3450 case OSQLParseNode::extract_exp
:
3451 case OSQLParseNode::term
:
3452 case OSQLParseNode::factor
:
3453 // Might by an integer or a float; take the most generic
3454 nDataType
= DataType::DOUBLE
;
3456 case OSQLParseNode::value_exp_primary
:
3457 case OSQLParseNode::value_exp
:
3458 case OSQLParseNode::odbc_call_spec
:
3459 // Really, we don't know. Let the default.
3461 case OSQLParseNode::position_exp
:
3462 case OSQLParseNode::length_exp
:
3463 nDataType
= DataType::INTEGER
;
3465 case OSQLParseNode::char_value_exp
:
3466 case OSQLParseNode::char_value_fct
:
3467 case OSQLParseNode::fold
:
3468 case OSQLParseNode::char_substring_fct
:
3469 case OSQLParseNode::char_factor
:
3470 case OSQLParseNode::concatenation
:
3471 nDataType
= DataType::VARCHAR
;
3473 case OSQLParseNode::datetime_primary
:
3474 nDataType
= DataType::TIMESTAMP
;
3476 case OSQLParseNode::bit_value_fct
:
3477 nDataType
= DataType::BINARY
;
3479 case OSQLParseNode::general_set_fct
: // May depend on argument; ignore that for now
3480 case OSQLParseNode::set_fct_spec
:
3482 if (pNode
->count() == 0)
3484 // This is not a function call, no sense to continue with a function return type lookup
3485 OSL_FAIL("Got leaf SQL node where non-leaf expected");
3488 const OSQLParseNode
* pFunctionName
= pNode
->getChild(0);
3489 if ( SQL_ISPUNCTUATION(pFunctionName
,"{") )
3491 if ( pNode
->count() == 3 )
3492 return fillFunctionInfo( pNode
->getChild(1), sFunctionTerm
, aInfo
);
3494 OSL_FAIL("ODBC escape not in recognised form");
3499 if ( SQL_ISRULEOR2(pNode
,length_exp
,char_value_fct
) )
3500 pFunctionName
= pFunctionName
->getChild(0);
3502 OUString sFunctionName
= pFunctionName
->getTokenValue();
3503 if ( sFunctionName
.isEmpty() )
3504 sFunctionName
= OStringToOUString(OSQLParser::TokenIDToStr(pFunctionName
->getTokenID()),RTL_TEXTENCODING_UTF8
);
3506 nDataType
= OSQLParser::getFunctionReturnType(
3508 ,&rController
.getParser().getContext());
3512 case OSQLParseNode::odbc_fct_spec
:
3514 if (pNode
->count() != 2)
3516 OSL_FAIL("interior of ODBC escape not in recognised shape");
3520 const OSQLParseNode
* const pEscapeType
= pNode
->getChild(0);
3521 if (SQL_ISTOKEN(pEscapeType
, TS
))
3522 nDataType
= DataType::TIMESTAMP
;
3523 else if (SQL_ISTOKEN(pEscapeType
, D
))
3524 nDataType
= DataType::DATE
;
3525 else if (SQL_ISTOKEN(pEscapeType
, T
))
3526 nDataType
= DataType::TIME
;
3527 else if (SQL_ISTOKEN(pEscapeType
, FN
))
3528 return fillFunctionInfo( pNode
->getChild(1), sFunctionTerm
, aInfo
);
3530 OSL_FAIL("Unknown ODBC escape");
3533 case OSQLParseNode::cast_spec
:
3535 if ( pNode
->count() != 6 || !SQL_ISTOKEN(pNode
->getChild(3), AS
) )
3537 OSL_FAIL("CAST not in recognised shape");
3540 const OSQLParseNode
*pCastTarget
= pNode
->getChild(4);
3541 if ( SQL_ISTOKENOR2(pCastTarget
, INTEGER
, INT
) )
3542 nDataType
= DataType::INTEGER
;
3543 else if ( SQL_ISTOKEN(pCastTarget
, SMALLINT
) )
3544 nDataType
= DataType::SMALLINT
;
3545 else if ( SQL_ISTOKEN(pCastTarget
, BIGINT
) )
3546 nDataType
= DataType::BIGINT
;
3547 else if ( SQL_ISTOKEN(pCastTarget
, FLOAT
) )
3548 nDataType
= DataType::FLOAT
;
3549 else if ( SQL_ISTOKEN(pCastTarget
, REAL
) )
3550 nDataType
= DataType::REAL
;
3551 else if ( SQL_ISTOKEN(pCastTarget
, DOUBLE
) )
3552 nDataType
= DataType::DOUBLE
;
3553 else if ( SQL_ISTOKEN(pCastTarget
, BOOLEAN
) )
3554 nDataType
= DataType::BOOLEAN
;
3555 else if ( SQL_ISTOKEN(pCastTarget
, DATE
) )
3556 nDataType
= DataType::DATE
;
3557 else if ( pCastTarget
->count() > 0 )
3559 const OSQLParseNode
*pDataType
= pCastTarget
->getChild(0);
3560 while (pDataType
->count() > 0)
3562 pCastTarget
= pDataType
;
3563 pDataType
= pDataType
->getChild(0);
3565 if ( SQL_ISTOKEN (pDataType
, TIME
) )
3566 nDataType
= DataType::TIME
;
3567 else if ( SQL_ISTOKEN (pDataType
, TIMESTAMP
) )
3568 nDataType
= DataType::TIMESTAMP
;
3569 else if ( SQL_ISTOKENOR3 (pDataType
, CHARACTER
, CHAR
, NCHAR
) )
3570 nDataType
= char_datatype(pCastTarget
, 0);
3571 else if ( SQL_ISTOKEN (pDataType
, VARCHAR
) )
3572 nDataType
= DataType::VARCHAR
;
3573 else if ( SQL_ISTOKEN (pDataType
, CLOB
) )
3574 nDataType
= DataType::CLOB
;
3575 else if ( SQL_ISTOKEN (pDataType
, NATIONAL
) )
3576 nDataType
= char_datatype(pCastTarget
, 1);
3577 else if ( SQL_ISTOKEN (pDataType
, BINARY
) )
3579 if ( pCastTarget
->count() > 2 && SQL_ISTOKEN(pCastTarget
->getChild(1), LARGE
) && SQL_ISTOKEN(pCastTarget
->getChild(2), OBJECT
) )
3580 nDataType
= DataType::BLOB
;
3581 else if ( pCastTarget
->count() > 1 && SQL_ISTOKEN(pCastTarget
->getChild(1), VARYING
) )
3582 nDataType
= DataType::VARBINARY
;
3584 nDataType
= DataType::BINARY
;
3586 else if ( SQL_ISTOKEN (pDataType
, VARBINARY
) )
3587 nDataType
= DataType::VARBINARY
;
3588 else if ( SQL_ISTOKEN (pDataType
, BLOB
) )
3589 nDataType
= DataType::BLOB
;
3590 else if ( SQL_ISTOKEN (pDataType
, NUMERIC
) )
3591 nDataType
= DataType::NUMERIC
;
3592 else if ( SQL_ISTOKENOR2 (pDataType
, DECIMAL
, DEC
) )
3593 nDataType
= DataType::DECIMAL
;
3594 else if ( SQL_ISTOKEN (pDataType
, FLOAT
) )
3595 nDataType
= DataType::FLOAT
;
3596 else if ( SQL_ISTOKEN (pDataType
, DOUBLE
) )
3597 nDataType
= DataType::DOUBLE
;
3598 else if ( SQL_ISTOKEN (pDataType
, TIME
) )
3599 nDataType
= DataType::TIME
;
3600 else if ( SQL_ISTOKEN (pDataType
, TIMESTAMP
) )
3601 nDataType
= DataType::TIMESTAMP
;
3602 else if ( SQL_ISTOKEN (pDataType
, INTERVAL
) )
3603 // Not in DataType published constant (because not in JDBC...)
3604 nDataType
= DataType::VARCHAR
;
3606 OSL_FAIL("Failed to decode CAST target");
3609 OSL_FAIL("Could not decipher CAST target");
3613 OSL_FAIL("Unknown SQL RuleID");
3618 OSL_FAIL("Unknown SQL Node Type");
3622 aInfo
->SetDataType(nDataType
);
3623 aInfo
->SetFieldType(TAB_NORMAL_FIELD
);
3624 aInfo
->SetField(sFunctionTerm
);
3625 aInfo
->SetTabWindow(NULL
);
3627 // -----------------------------------------------------------------------------
3629 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */