Files
libreoffice/dbaccess/source/ui/querydesign/QueryDesignView.cxx
Release Engineers cb1400a076 CWS-TOOLING: integrate CWS dba32c
2009-06-29 20:53:25 +0200 fs  r273484 : #i103138# Rectangle conversion
2009-06-29 20:51:50 +0200 fs  r273483 : #i103138# yet more refactoring, now also setting the proper zoom level at the proper point in time
2009-06-29 13:40:26 +0200 fs  r273470 : added svn:ignore to ignore output paths
2009-06-29 10:08:54 +0200 fs  r273455 : #i103138#
refactored the code for positioning/zooming the control
Basically, we now allow adjustControlGeometry_throw (formerly known as positionControl_throw and setControlZoom) to
take an additional ViewTransformation parameter, describing the transformation to obtain the actual
control position/size. Consequently, positionControl itself also allows for a ViewTransformation parameter.
This has become necessary since during painting, the device which we created our control for might not necessarily
have a proper MapMode set. In this case, if we would use this map mode for calculating the control's position/size,
this would lead to wrong results.
Note that this problem was introduced by the fix for #i101398#: During the fix, we postponed the control creation
to a later time (when it is really needed). At this later time, the MapMode at the device is broken, at the earlier
time where we formerly crearted the control (createPrimitive2DSequence), it is not yet broken.
Whether or not the MapMode is defined as "broken" might depend on one's point of view, however ...
I consider it broken, since:
- we need the map mode to obtain the proper zoom level, which is to be forwarded to the control
- there are scenarios where the MapMode is *not* set to MAP_PIXEL (in those scenarios, everything works
  fine), and there are scenarios where it *is* set to MAP_PIXEL (in those the bug 103138 appears).
It somehow feels wrong that one cannot rely on the device's map mode this way, but on the other hand
one has no possibility to obtain the current zoom by other means.
Note that one issue (still to be submitted) is left: In the page pane of a Draw/Impress document, controls
have a wrong text size. This is because in this pane, the above-mentioned "broken" map mode is used,
which means the controls have a zoom of "1:1" set, which is wrong here.
2009-06-25 13:41:35 +0200 msc  r273380 : #100000# the tabs changed die to new properties
2009-06-24 12:42:40 +0200 msc  r273330 : #102082# remove issue warning
2009-06-22 10:43:14 +0200 fs  r273201 : createPrimitive2DSequence: care for being disposed
2009-06-18 12:35:13 +0200 oj  r273109 : #i102305# make nooptfiles for gcc
2009-06-17 12:14:37 +0200 oj  r273056 : #i102305# fix for linux
2009-06-17 07:20:22 +0200 oj  r273046 : #i102305# move ValueTransfer into the for loop to avoid a crash under Linux
2009-06-17 07:17:28 +0200 oj  r273045 : #i102305# use varchar
2009-06-15 14:11:27 +0200 fs  r272983 : added since tag
2009-06-15 12:11:39 +0200 oj  r272973 : #i102305# SAL_DLLPUBLIC_EXPORT inserted
2009-06-15 11:08:53 +0200 fs  r272969 : #i10000#
2009-06-15 09:25:13 +0200 fs  r272963 : merging fix for P1 issue #i102701#
2009-06-11 11:31:24 +0200 fs  r272858 : #i10000# copied the fix which before the rebase was done in ../dialog/macropg.src
2009-06-11 09:38:14 +0200 fs  r272846 : CWS-TOOLING: rebase CWS dba32c to trunk@272827 (milestone: DEV300:m50)
2009-06-02 09:53:10 +0200 fs  r272483 : #i10000#
2009-05-29 15:55:03 +0200 fs  r272465 : #i100818#
2009-05-29 12:58:43 +0200 fs  r272452 : don't apply comphelper::getString on possibly VOID any
2009-05-29 10:38:35 +0200 oj  r272437 : #i101519# handle where condition
2009-05-29 09:53:39 +0200 fs  r272434 : #i100818# call into releaseStubs /without/ locked GlobalMutex
2009-05-28 07:53:44 +0200 oj  r272375 : #i101369# parse tree changed
2009-05-27 14:53:36 +0200 fs  r272347 : #i10000#
2009-05-27 09:29:15 +0200 oj  r272327 : #i101626# check for double before hard cast
2009-05-27 09:13:58 +0200 oj  r272326 : #i101626# handle void correctly
2009-05-27 08:04:39 +0200 oj  r272321 : #i102256# wrong method signature used
2009-05-27 07:55:52 +0200 oj  r272320 : #i101519# look up parameter typ if used in function
2009-05-27 06:49:07 +0200 oj  r272319 : #i101519# set parameter from rowset as well
2009-05-26 13:30:56 +0200 oj  r272297 : #i101987# impl XBatchExecution
2009-05-26 12:44:34 +0200 oj  r272293 : #i101700# check if group is not set
2009-05-26 12:16:53 +0200 oj  r272290 : #i101369# resolved some reduce7reduce problems with boolean_term and search_condition
2009-05-26 12:12:42 +0200 oj  r272289 : #i101369# fix for or on one line criteria
2009-05-25 16:02:25 +0200 fs  r272257 : #i999704# +PROPERTY_MOUSE_WHEEL_BEHAVIOR
2009-05-25 16:01:55 +0200 fs  r272256 : merging the changes from CWS dba32b herein
2009-05-25 15:49:57 +0200 fs  r272254 : #i999704#
2009-05-25 15:32:57 +0200 fs  r272252 : #i99704# grid columns also to respect the MouseWheelBehavior property
2009-05-25 15:23:43 +0200 fs  r272251 : don't pass empty Anys to ::comphelper::getString
2009-05-25 14:48:43 +0200 fs  r272248 : merged changes from CWS dba32b herein
2009-05-25 14:44:40 +0200 fs  r272247 : #i99704# support new MouseWheelBehavior property
2009-05-25 14:43:18 +0200 fs  r272246 : #i99704# WheelWithoutFocus (peer property) superseded by MouseWheelBehavior (model property)
2009-05-25 14:41:03 +0200 fs  r272245 : #i99704# no need to set the mouse wheel behavior at the peer, this is now a model property, having the right default
2009-05-25 14:39:31 +0200 fs  r272243 : removed dead import
2009-05-25 14:35:36 +0200 fs  r272242 : the new EnableVisible doesn't make sense for grid columns
2009-05-25 14:34:33 +0200 fs  r272241 : #i99704# +MouseWheelBehavior - allow to enable/disable the mouse wheel for the control, or make it focus-dependent
2009-05-25 14:26:11 +0200 fs  r272240 : #i99704# change MouseSettings wheel flag (NoWheelActionWithoutFocus) to a three-state option, allowing to completely ignore the mouse wheel
2009-05-23 21:35:59 +0200 fs  r272213 : localize 'sub component opened/closed' event
2009-05-22 21:42:47 +0200 fs  r272211 : #i102003#
2009-05-22 21:42:20 +0200 fs  r272210 : grammar
2009-05-22 21:36:10 +0200 fs  r272209 : #i102140# load only once, not twice, and show error messages during loading (and during any form action, that is) asynchronously
2009-05-22 21:35:11 +0200 fs  r272208 : #i102140# +clear
2009-05-22 14:50:30 +0200 fs  r272194 : #i102139# for newly created DB docs, set the MacroExecutionMode to USE_CONFIG
2009-05-22 12:03:42 +0200 fs  r272180 : #i88878#
provided by noel.power@novell.com
implement a visibility property (EnableVisible) for toolkit controls, and usage in forms and UNO dialogs
2009-05-15 15:37:31 +0200 fs  r271942 : #i100671# corrected some @since tags, so autodoc has better chances of correctly reading them
2009-05-15 15:33:11 +0200 fs  r271940 : don't call comphelper::getFOO for VOID values
2009-05-15 15:08:31 +0200 fs  r271937 : includes
2009-05-15 13:39:22 +0200 fs  r271934 : #i101398# createPrimitive2DSequence: when we already have a control, use the old code. In particular, call positionControlForPaint
2009-05-15 12:33:48 +0200 fs  r271933 : make the geometry a part of the ControlPrimitive2D's identity
2009-05-15 10:15:44 +0200 fs  r271928 : #i10000#
2009-05-14 20:55:38 +0200 fs  r271921 : #i101398# don't reuse the name PRIMITIVE_ID_CONTROLPRIMITIVE2D, make the name of our own ControlPrimitive2D unique
2009-05-14 20:55:31 +0200 fs  r271920 : #i101398# don't reuse the name PRIMITIVE_ID_CONTROLPRIMITIVE2D, make the name of our own ControlPrimitive2D unique
2009-05-14 20:23:23 +0200 fs  r271919 : #i101622#
2009-05-14 16:04:38 +0200 fs  r271898 : don't use comphelper::getInt32 on voids
2009-05-14 16:04:12 +0200 fs  r271897 : merge fix for issue whose number just slipped my memory ... (originally fixed in CWS dba32b)
2009-05-14 15:36:55 +0200 fs  r271895 : merging changes from DEV300:m48
2009-05-07 14:43:19 +0200 fs  r271670 : #i101477#
2009-05-07 14:37:30 +0200 fs  r271668 : #i101477#
2009-05-07 09:27:30 +0200 oj  r271628 : #i101343# remove pch
2009-05-06 09:36:02 +0200 fs  r271568 : getFoo: diagnostics
2009-05-04 09:23:06 +0200 oj  r271438 : CWS-TOOLING: rebase CWS dba32c to trunk@271427 (milestone: DEV300:m47)
2009-04-29 23:18:13 +0200 fs  r271394 : #i101398# use a dedicated 2DPrimitive for UNO Controls, which is able to provide the B2DRange *without* actually creating the control
2009-04-29 13:52:25 +0200 fs  r271366 : #i101308#
2009-07-03 14:21:50 +00:00

3289 lines
150 KiB
C++
Raw Blame History

/*************************************************************************
*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* Copyright 2008 by Sun Microsystems, Inc.
*
* OpenOffice.org - a multi-platform office productivity suite
*
* $RCSfile: QueryDesignView.cxx,v $
* $Revision: 1.96.8.1 $
*
* This file is part of OpenOffice.org.
*
* OpenOffice.org is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License version 3
* only, as published by the Free Software Foundation.
*
* OpenOffice.org is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License version 3 for more details
* (a copy is included in the LICENSE file that accompanied this code).
*
* You should have received a copy of the GNU Lesser General Public License
* version 3 along with OpenOffice.org. If not, see
* <http://www.openoffice.org/license.html>
* for a copy of the LGPLv3 License.
*
************************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_dbaccess.hxx"
#ifndef DBAUI_QUERYDESIGNVIEW_HXX
#include "QueryDesignView.hxx"
#endif
#ifndef DBAUI_QUERYTABLEVIEW_HXX
#include "QueryTableView.hxx"
#endif
#ifndef DBAUI_QUERY_TABLEWINDOW_HXX
#include "QTableWindow.hxx"
#endif
#ifndef _SV_TOOLBOX_HXX
#include <vcl/toolbox.hxx>
#endif
#ifndef DBAUI_QUERYCONTROLLER_HXX
#include "querycontroller.hxx"
#endif
#ifndef _SV_SPLIT_HXX
#include <vcl/split.hxx>
#endif
#ifndef _UNDO_HXX
#include <svtools/undo.hxx>
#endif
#ifndef TOOLS_DIAGNOSE_EX_H
#include <tools/diagnose_ex.h>
#endif
#ifndef DBAUI_QYDLGTAB_HXX
#include "adtabdlg.hxx"
#endif
#ifndef _SV_SVAPP_HXX
#include <vcl/svapp.hxx>
#endif
#ifndef _SV_COMBOBOX_HXX
#include <vcl/combobox.hxx>
#endif
#ifndef _SV_MSGBOX_HXX
#include <vcl/msgbox.hxx>
#endif
#ifndef DBACCESS_UI_BROWSER_ID_HXX
#include "browserids.hxx"
#endif
#ifndef DBAUI_QUERYDESIGN_OSELECTIONBROWSEBOX_HXX
#include "SelectionBrowseBox.hxx"
#endif
#ifndef _DBU_QRY_HRC_
#include "dbu_qry.hrc"
#endif
#ifndef _UTL_CONFIGMGR_HXX_
#include <unotools/configmgr.hxx>
#endif
#ifndef _COMPHELPER_TYPES_HXX_
#include <comphelper/types.hxx>
#endif
#ifndef _CONNECTIVITY_DBTOOLS_HXX_
#include <connectivity/dbtools.hxx>
#endif
#ifndef _DBHELPER_DBEXCEPTION_HXX_
#include <connectivity/dbexception.hxx>
#endif
#ifndef _COM_SUN_STAR_I18N_XLOCALEDATA_HPP_
#include <com/sun/star/i18n/XLocaleData.hpp>
#endif
#ifndef _COM_SUN_STAR_SDBC_DATATYPE_HPP_
#include <com/sun/star/sdbc/DataType.hpp>
#endif
#ifndef _COM_SUN_STAR_CONTAINER_XNAMEACCESS_HPP_
#include <com/sun/star/container/XNameAccess.hpp>
#endif
#ifndef _COM_SUN_STAR_SDBC_COLUMNVALUE_HPP_
#include <com/sun/star/sdbc/ColumnValue.hpp>
#endif
#ifndef _CONNECTIVITY_PCOLUMN_HXX_
#include <connectivity/PColumn.hxx>
#endif
#ifndef DBAUI_QUERYTABLECONNECTION_HXX
#include "QTableConnection.hxx"
#endif
#ifndef DBAUI_CONNECTIONLINE_HXX
#include "ConnectionLine.hxx"
#endif
#ifndef DBAUI_CONNECTIONLINEDATA_HXX
#include "ConnectionLineData.hxx"
#endif
#ifndef DBAUI_QTABLECONNECTIONDATA_HXX
#include "QTableConnectionData.hxx"
#endif
#ifndef DBACCESS_SHARED_DBUSTRINGS_HRC
#include "dbustrings.hrc"
#endif
#ifndef _COMPHELPER_EXTRACT_HXX_
#include <comphelper/extract.hxx>
#endif
#ifndef DBAUI_TOOLS_HXX
#include "UITools.hxx"
#endif
#ifndef DBAUI_QUERYCONTAINERWINDOW_HXX
#include "querycontainerwindow.hxx"
#endif
#ifndef DBAUI_QUERYTABLEVIEW_HXX
#include "QueryTableView.hxx"
#endif
#ifndef _DBAUI_SQLMESSAGE_HXX_
#include "sqlmessage.hxx"
#endif
#ifndef INCLUDED_SVTOOLS_SYSLOCALE_HXX
#include <svtools/syslocale.hxx>
#endif
using namespace ::dbaui;
using namespace ::utl;
using namespace ::connectivity;
using namespace ::dbtools;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::lang;
using namespace ::com::sun::star::i18n;
using namespace ::com::sun::star::sdbc;
using namespace ::com::sun::star::beans;
using namespace ::com::sun::star::container;
#define SQL_ISRULEOR2(pParseNode, e1,e2) ((pParseNode)->isRule() && (\
(pParseNode)->getRuleID() == OSQLParser::RuleID(OSQLParseNode::e1) || \
(pParseNode)->getRuleID() == OSQLParser::RuleID(OSQLParseNode::e2)))
// here we define our functions used in the anonymous namespace to get our header file smaller
// please look at the book LargeScale C++ to know why
namespace
{
static const ::rtl::OUString C_AND = ::rtl::OUString::createFromAscii(" AND ");
static const ::rtl::OUString C_OR = ::rtl::OUString::createFromAscii(" OR ");
// forward declarations
sal_Bool InsertJoin( const OQueryDesignView* _pView,
const ::connectivity::OSQLParseNode *pNode);
SqlParseError InstallFields(OQueryDesignView* _pView,
const ::connectivity::OSQLParseNode* pNode,
OJoinTableView::OTableWindowMap* pTabList );
SqlParseError GetGroupCriteria( OQueryDesignView* _pView,
OSelectionBrowseBox* _pSelectionBrw,
const ::connectivity::OSQLParseNode* pSelectRoot );
SqlParseError GetHavingCriteria(OQueryDesignView* _pView,
OSelectionBrowseBox* _pSelectionBrw,
const ::connectivity::OSQLParseNode* pSelectRoot,
sal_uInt16& rLevel );
SqlParseError GetOrderCriteria( OQueryDesignView* _pView,
OSelectionBrowseBox* _pSelectionBrw,
const ::connectivity::OSQLParseNode* pParseRoot );
SqlParseError AddFunctionCondition(OQueryDesignView* _pView,
OSelectionBrowseBox* _pSelectionBrw,
const ::connectivity::OSQLParseNode * pCondition,
const sal_uInt16 nLevel,
sal_Bool bHaving,
bool _bAddOrOnOneLine);
void fillFunctionInfo( OQueryDesignView* _pView
,const ::connectivity::OSQLParseNode* pNode
,const ::rtl::OUString& sFunctionTerm
,OTableFieldDescRef& aInfo);
//------------------------------------------------------------------------------
::rtl::OUString quoteTableAlias(sal_Bool _bQuote, const ::rtl::OUString& _sAliasName, const ::rtl::OUString& _sQuote)
{
::rtl::OUString sRet;
if ( _bQuote && _sAliasName.getLength() )
{
sRet = ::dbtools::quoteName(_sQuote,_sAliasName);
const static ::rtl::OUString sTableSeparater('.');
sRet += sTableSeparater;
}
return sRet;
}
//------------------------------------------------------------------------------
::rtl::OUString getTableRange(const OQueryDesignView* _pView,const ::connectivity::OSQLParseNode* _pTableRef)
{
Reference< XConnection> xConnection = static_cast<OQueryController&>(_pView->getController()).getConnection();
::rtl::OUString sTableRange;
if ( _pTableRef )
{
sTableRange = ::connectivity::OSQLParseNode::getTableRange(_pTableRef);
if ( !sTableRange.getLength() )
_pTableRef->parseNodeToStr(sTableRange,xConnection,NULL,sal_False,sal_False);
}
return sTableRange;
}
//------------------------------------------------------------------------------
void insertConnection(const OQueryDesignView* _pView,const EJoinType& _eJoinType,OTableFieldDescRef _aDragLeft,OTableFieldDescRef _aDragRight,bool _bNatural = false)
{
OQueryTableView* pTableView = static_cast<OQueryTableView*>(_pView->getTableView());
OQueryTableConnection* pConn = static_cast<OQueryTableConnection*>( pTableView->GetTabConn(static_cast<OTableWindow*>(_aDragLeft->GetTabWindow()),static_cast<OTableWindow*>(_aDragRight->GetTabWindow()),true));
if ( !pConn )
{
OQueryTableConnectionData* pInfoData = new OQueryTableConnectionData();
TTableConnectionData::value_type aInfoData(pInfoData);
pInfoData->InitFromDrag(_aDragLeft, _aDragRight);
pInfoData->SetJoinType(_eJoinType);
if ( _bNatural )
{
aInfoData->ResetConnLines();
pInfoData->setNatural(_bNatural);
try
{
Reference<XNameAccess> xReferencedTableColumns(aInfoData->getReferencedTable()->getColumns());
Sequence< ::rtl::OUString> aSeq = aInfoData->getReferencingTable()->getColumns()->getElementNames();
const ::rtl::OUString* pIter = aSeq.getConstArray();
const ::rtl::OUString* pEnd = pIter + aSeq.getLength();
for(;pIter != pEnd;++pIter)
{
if ( xReferencedTableColumns->hasByName(*pIter) )
aInfoData->AppendConnLine(*pIter,*pIter);
}
}
catch( const Exception& )
{
DBG_UNHANDLED_EXCEPTION();
}
}
OQueryTableConnection aInfo(pTableView, aInfoData);
// da ein OQueryTableConnection-Objekt nie den Besitz der uebergebenen Daten uebernimmt, sondern sich nur den Zeiger merkt,
// ist dieser Zeiger auf eine lokale Variable hier unkritisch, denn aInfoData und aInfo haben die selbe Lebensdauer
pTableView->NotifyTabConnection( aInfo );
}
else
{
::rtl::OUString aSourceFieldName(_aDragLeft->GetField());
::rtl::OUString aDestFieldName(_aDragRight->GetField());
// the connection could point on the other side
if(pConn->GetSourceWin() == _aDragRight->GetTabWindow())
{
::rtl::OUString aTmp(aSourceFieldName);
aSourceFieldName = aDestFieldName;
aDestFieldName = aTmp;
}
pConn->GetData()->AppendConnLine( aSourceFieldName,aDestFieldName);
pConn->UpdateLineList();
// Modified-Flag
// SetModified();
// und neu zeichnen
pConn->RecalcLines();
// fuer das unten folgende Invalidate muss ich dieser neuen Connection erst mal die Moeglichkeit geben,
// ihr BoundingRect zu ermitteln
pConn->InvalidateConnection();
}
}
//------------------------------------------------------------------------------
::rtl::OUString ParseCondition( OQueryController& rController
,const ::connectivity::OSQLParseNode* pCondition
,const ::rtl::OUString _sDecimal
,const ::com::sun::star::lang::Locale& _rLocale
,sal_uInt32 _nStartIndex)
{
::rtl::OUString aCondition;
Reference< XConnection> xConnection = rController.getConnection();
if ( xConnection.is() )
{
sal_uInt32 nCount = pCondition->count();
for(sal_uInt32 i = _nStartIndex ; i < nCount ; ++i)
pCondition->getChild(i)->parseNodeToPredicateStr(aCondition,
xConnection,
rController.getNumberFormatter(),
_rLocale,
static_cast<sal_Char>(_sDecimal.toChar()),
&rController.getParser().getContext());
}
return aCondition;
}
//------------------------------------------------------------------------------
SqlParseError FillOuterJoins(OQueryDesignView* _pView,
const ::connectivity::OSQLParseNode* pTableRefList)
{
SqlParseError eErrorCode = eOk;
sal_uInt32 nCount = pTableRefList->count();
sal_Bool bError = sal_False;
for (sal_uInt32 i=0; !bError && i < nCount; ++i)
{
const ::connectivity::OSQLParseNode* pParseNode = pTableRefList->getChild(i);
const ::connectivity::OSQLParseNode* pJoinNode = NULL;
if ( SQL_ISRULE( pParseNode, qualified_join ) || SQL_ISRULE( pParseNode, joined_table ) || SQL_ISRULE( pParseNode, cross_union ) )
pJoinNode = pParseNode;
else if( SQL_ISRULE(pParseNode,table_ref)
&& pParseNode->count() == 4 ) // '{' SQL_TOKEN_OJ joined_table '}'
pJoinNode = pParseNode->getChild(2);
if ( pJoinNode )
{
if ( !InsertJoin(_pView,pJoinNode) )
bError = sal_True;
}
}
// check if error occured
if ( bError )
eErrorCode = eIllegalJoin;
return eErrorCode;
}
//------------------------------------------------------------------------------
::rtl::OUString QuoteField( const OQueryDesignView* _pView,const ::rtl::OUString& rValue, sal_Int32 aType )
{
::rtl::OUString rNewValue;
switch (rValue.toChar())
{
case '?':
if (rValue.getLength() != 1)
break;
case '\'': // ::rtl::OUString Quotierung oder Datum
//case '#': // Datumsquotierung // jetengine
case ':': // Parameter
case '[': // Parameter
return rValue;
}
Reference< XConnection> xConnection = static_cast<OQueryController&>(_pView->getController()).getConnection();
Reference< XDatabaseMetaData > xMetaData;
if(xConnection.is())
xMetaData = xConnection->getMetaData();
::rtl::OUString aQuote;
try
{
if(xMetaData.is())
aQuote = xMetaData->getIdentifierQuoteString();
switch( aType )
{
case DataType::DATE:
case DataType::TIME:
case DataType::TIMESTAMP:
if (rValue.toChar() != '{') // nur quoten, wenn kein Access Datum
rNewValue = ::dbtools::quoteName(aQuote,rValue);
else
rNewValue = rValue;
break;
case DataType::CHAR:
case DataType::VARCHAR:
case DataType::LONGVARCHAR:
rNewValue = ::dbtools::quoteName(aQuote,rValue);
break;
case DataType::DECIMAL:
case DataType::NUMERIC:
case DataType::TINYINT:
case DataType::SMALLINT:
case DataType::INTEGER:
case DataType::BIGINT:
case DataType::REAL:
case DataType::DOUBLE:
case DataType::BINARY:
case DataType::VARBINARY:
case DataType::LONGVARBINARY:
rNewValue = rValue;
break;
case DataType::BIT:
case DataType::BOOLEAN:
{
if(xMetaData.is())
{
::comphelper::UStringMixEqual bCase(xMetaData->supportsMixedCaseQuotedIdentifiers());
if (bCase(rValue, String(ModuleRes(STR_QUERY_TRUE))))
rNewValue = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("TRUE"));
else if (bCase(rValue, String(ModuleRes(STR_QUERY_FALSE))))
rNewValue = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("FALSE"));
else
rNewValue = rValue;
}
}
break;
default:
DBG_ERROR( "QuoteField: illegal type" );
break;
}
}
catch(SQLException&)
{
DBG_ERROR( "QuoteField: Exception" );
}
return rNewValue;
}
// -----------------------------------------------------------------------------
/** FillDragInfo fills the field description out of the table
*/
//------------------------------------------------------------------------------
SqlParseError FillDragInfo( const OQueryDesignView* _pView,
const ::connectivity::OSQLParseNode* pColumnRef,
OTableFieldDescRef& _rDragInfo)
{
SqlParseError eErrorCode = eOk;
sal_Bool bErg = sal_False;
::rtl::OUString aTableRange,aColumnName;
sal_uInt16 nCntAccount;
::connectivity::OSQLParseTreeIterator& rParseIter = static_cast<OQueryController&>(_pView->getController()).getParseIterator();
rParseIter.getColumnRange( pColumnRef, aColumnName, aTableRange );
if ( aTableRange.getLength() )
{
OQueryTableWindow* pSTW = static_cast<OQueryTableView*>(_pView->getTableView())->FindTable( aTableRange );
bErg = (pSTW && pSTW->ExistsField( aColumnName, _rDragInfo ) );
}
if ( !bErg )
{
bErg = static_cast<OQueryTableView*>(_pView->getTableView())->FindTableFromField(aColumnName, _rDragInfo, nCntAccount);
if ( !bErg )
bErg = _pView->HasFieldByAliasName(aColumnName, _rDragInfo);
}
if ( !bErg )
{
eErrorCode = eColumnNotFound;
String sError(ModuleRes(STR_QRY_COLUMN_NOT_FOUND));
sError.SearchAndReplaceAscii("$name$",aColumnName);
_pView->getController().appendError( sError );
try
{
Reference<XDatabaseMetaData> xMeta = _pView->getController().getConnection()->getMetaData();
if ( xMeta.is() && xMeta->supportsMixedCaseQuotedIdentifiers() )
_pView->getController().appendError( String( ModuleRes( STR_QRY_CHECK_CASESENSITIVE ) ) );
}
catch(Exception&)
{
}
}
return eErrorCode;
}
//------------------------------------------------------------------------------
::rtl::OUString BuildJoinCriteria( const Reference< XConnection>& _xConnection,
OConnectionLineDataVec* pLineDataList,
OQueryTableConnectionData* pData)
{
::rtl::OUStringBuffer aCondition;
if ( _xConnection.is() )
{
OConnectionLineDataVec::iterator aIter = pLineDataList->begin();
OConnectionLineDataVec::iterator aEnd = pLineDataList->end();
try
{
const Reference< XDatabaseMetaData > xMetaData = _xConnection->getMetaData();
const ::rtl::OUString aQuote = xMetaData->getIdentifierQuoteString();
const ::rtl::OUString sEqual(RTL_CONSTASCII_USTRINGPARAM(" = "));
for(;aIter != aEnd;++aIter)
{
OConnectionLineDataRef pLineData = *aIter;
if(aCondition.getLength())
aCondition.append(C_AND);
aCondition.append(quoteTableAlias(sal_True,pData->GetAliasName(JTCS_FROM),aQuote));
aCondition.append(::dbtools::quoteName(aQuote, pLineData->GetFieldName(JTCS_FROM) ));
aCondition.append(sEqual);
aCondition.append(quoteTableAlias(sal_True,pData->GetAliasName(JTCS_TO),aQuote));
aCondition.append(::dbtools::quoteName(aQuote, pLineData->GetFieldName(JTCS_TO) ));
}
}
catch(SQLException&)
{
OSL_ASSERT(!"Failure while building Join criteria!");
}
}
return aCondition.makeStringAndClear();
}
//------------------------------------------------------------------------------
/** JoinCycle looks for a join cycle and append it to the string
@param _xConnection the connection
@param _pEntryConn the table connection which holds the data
@param _pEntryTabTo the corresponding table window
@param _rJoin the String which will contain the resulting string
*/
void JoinCycle( const Reference< XConnection>& _xConnection,
OQueryTableConnection* _pEntryConn,
const OQueryTableWindow* _pEntryTabTo,
::rtl::OUString& _rJoin )
{
OSL_ENSURE(_pEntryConn,"TableConnection can not be null!");
OQueryTableConnectionData* pData = static_cast< OQueryTableConnectionData*>(_pEntryConn->GetData().get());
if ( pData->GetJoinType() != INNER_JOIN && _pEntryTabTo->ExistsAVisitedConn() )
{
sal_Bool bBrace = sal_False;
if(_rJoin.getLength() && _rJoin.lastIndexOf(')') == (_rJoin.getLength()-1))
{
bBrace = sal_True;
_rJoin = _rJoin.replaceAt(_rJoin.getLength()-1,1,::rtl::OUString(' '));
}
(_rJoin += C_AND) += BuildJoinCriteria(_xConnection,pData->GetConnLineDataList(),pData);
if(bBrace)
_rJoin += ::rtl::OUString(')');
_pEntryConn->SetVisited(sal_True);
}
}
//------------------------------------------------------------------------------
::rtl::OUString BuildTable( const Reference< XConnection>& _xConnection,
const OQueryTableWindow* pEntryTab,
bool _bForce = false
)
{
::rtl::OUString aDBName(pEntryTab->GetComposedName());
// Reference< XConnection> xConnection = static_cast<OQueryController&>(_pView->getController()).getConnection();
if( _xConnection.is() )
{
try
{
Reference< XDatabaseMetaData > xMetaData = _xConnection->getMetaData();
::rtl::OUString sCatalog, sSchema, sTable;
::dbtools::qualifiedNameComponents( xMetaData, aDBName, sCatalog, sSchema, sTable, ::dbtools::eInDataManipulation );
::rtl::OUString aTableListStr = ::dbtools::composeTableNameForSelect( _xConnection, sCatalog, sSchema, sTable );
::rtl::OUString aQuote = xMetaData->getIdentifierQuoteString();
if ( _bForce || isAppendTableAliasEnabled( _xConnection ) || pEntryTab->GetAliasName() != aDBName )
{
aTableListStr += ::rtl::OUString::createFromAscii(" ");
if ( generateAsBeforeTableAlias( _xConnection ) )
aTableListStr += ::rtl::OUString::createFromAscii("AS ");
aTableListStr += ::dbtools::quoteName( aQuote, pEntryTab->GetAliasName() );
}
aDBName = aTableListStr;
}
catch(const SQLException&)
{
DBG_UNHANDLED_EXCEPTION();
}
}
return aDBName;
}
//------------------------------------------------------------------------------
::rtl::OUString BuildJoin( const Reference< XConnection>& _xConnection,
const ::rtl::OUString& rLh,
const ::rtl::OUString& rRh,
OQueryTableConnectionData* pData)
{
String aErg(rLh);
if ( pData->isNatural() && pData->GetJoinType() != CROSS_JOIN )
aErg.AppendAscii(" NATURAL ");
switch(pData->GetJoinType())
{
case LEFT_JOIN:
aErg.AppendAscii(" LEFT OUTER ");
break;
case RIGHT_JOIN:
aErg.AppendAscii(" RIGHT OUTER ");
break;
case CROSS_JOIN:
OSL_ENSURE(!pData->isNatural(),"OQueryDesignView::BuildJoin: This should not happen!");
aErg.AppendAscii(" CROSS ");
break;
case INNER_JOIN:
OSL_ENSURE(pData->isNatural(),"OQueryDesignView::BuildJoin: This should not happen!");
aErg.AppendAscii(" INNER ");
break;
default:
aErg.AppendAscii(" FULL OUTER ");
break;
}
aErg.AppendAscii("JOIN ");
aErg += String(rRh);
if ( CROSS_JOIN != pData->GetJoinType() && !pData->isNatural() )
{
aErg.AppendAscii(" ON ");
aErg += String(BuildJoinCriteria(_xConnection,pData->GetConnLineDataList(),pData));
}
return aErg;
}
//------------------------------------------------------------------------------
::rtl::OUString BuildJoin( const Reference< XConnection>& _xConnection,
OQueryTableWindow* pLh,
OQueryTableWindow* pRh,
OQueryTableConnectionData* pData
)
{
bool bForce = pData->GetJoinType() == CROSS_JOIN || pData->isNatural();
return BuildJoin(_xConnection,BuildTable(_xConnection,pLh,bForce),BuildTable(_xConnection,pRh,bForce),pData);
}
//------------------------------------------------------------------------------
::rtl::OUString BuildJoin( const Reference< XConnection>& _xConnection,
const ::rtl::OUString &rLh,
OQueryTableWindow* pRh,
OQueryTableConnectionData* pData
)
{
return BuildJoin(_xConnection,rLh,BuildTable(_xConnection,pRh),pData);
}
//------------------------------------------------------------------------------
::rtl::OUString BuildJoin( const Reference< XConnection>& _xConnection,
OQueryTableWindow* pLh,
const ::rtl::OUString &rRh,
OQueryTableConnectionData* pData
)
{
return BuildJoin(_xConnection,BuildTable(_xConnection,pLh),rRh,pData);
}
//------------------------------------------------------------------------------
void GetNextJoin( const Reference< XConnection>& _xConnection,
OQueryTableConnection* pEntryConn,
OQueryTableWindow* pEntryTabTo,
::rtl::OUString &aJoin)
{
OQueryTableConnectionData* pEntryConnData = static_cast<OQueryTableConnectionData*>(pEntryConn->GetData().get());
if ( pEntryConnData->GetJoinType() == INNER_JOIN && !pEntryConnData->isNatural() )
return;
// Reference< XConnection> xConnection = static_cast<OQueryController&>(_pView->getController()).getConnection();
if(!aJoin.getLength())
{
OQueryTableWindow* pEntryTabFrom = static_cast<OQueryTableWindow*>(pEntryConn->GetSourceWin());
aJoin = BuildJoin(_xConnection,pEntryTabFrom,pEntryTabTo,pEntryConnData);
}
else if(pEntryTabTo == pEntryConn->GetDestWin())
{
aJoin = BuildJoin(_xConnection,aJoin,pEntryTabTo,pEntryConnData);
}
else if(pEntryTabTo == pEntryConn->GetSourceWin())
{
aJoin = BuildJoin(_xConnection,pEntryTabTo,aJoin,pEntryConnData);
}
pEntryConn->SetVisited(sal_True);
// first search for the "to" window
const ::std::vector<OTableConnection*>* pConnections = pEntryConn->GetParent()->getTableConnections();
::std::vector<OTableConnection*>::const_iterator aIter = pConnections->begin();
::std::vector<OTableConnection*>::const_iterator aEnd = pConnections->end();
for(;aIter != aEnd;++aIter)
{
OQueryTableConnection* pNext = static_cast<OQueryTableConnection*>(*aIter);
if(!pNext->IsVisited() && (pNext->GetSourceWin() == pEntryTabTo || pNext->GetDestWin() == pEntryTabTo))
{
OQueryTableWindow* pEntryTab = pNext->GetSourceWin() == pEntryTabTo ? static_cast<OQueryTableWindow*>(pNext->GetDestWin()) : static_cast<OQueryTableWindow*>(pNext->GetSourceWin());
// exists there a connection to a OQueryTableWindow that holds a connection that has been already visited
JoinCycle(_xConnection,pNext,pEntryTab,aJoin);
if(!pNext->IsVisited())
GetNextJoin(_xConnection,pNext,pEntryTab,aJoin);
}
}
// when nothing found found look for the "from" window
if(aIter == aEnd)
{
OQueryTableWindow* pEntryTabFrom = static_cast<OQueryTableWindow*>(pEntryConn->GetSourceWin());
aIter = pConnections->begin();
for(;aIter != aEnd;++aIter)
{
OQueryTableConnection* pNext = static_cast<OQueryTableConnection*>(*aIter);
if(!pNext->IsVisited() && (pNext->GetSourceWin() == pEntryTabFrom || pNext->GetDestWin() == pEntryTabFrom))
{
OQueryTableWindow* pEntryTab = pNext->GetSourceWin() == pEntryTabFrom ? static_cast<OQueryTableWindow*>(pNext->GetDestWin()) : static_cast<OQueryTableWindow*>(pNext->GetSourceWin());
// exists there a connection to a OQueryTableWindow that holds a connection that has been already visited
JoinCycle(_xConnection,pNext,pEntryTab,aJoin);
if(!pNext->IsVisited())
GetNextJoin(_xConnection,pNext,pEntryTab,aJoin);
}
}
}
}
//------------------------------------------------------------------------------
SqlParseError InsertJoinConnection( const OQueryDesignView* _pView,
const ::connectivity::OSQLParseNode *pNode,
const EJoinType& _eJoinType)
{
SqlParseError eErrorCode = eOk;
if (pNode->count() == 3 && // Ausdruck is geklammert
SQL_ISPUNCTUATION(pNode->getChild(0),"(") &&
SQL_ISPUNCTUATION(pNode->getChild(2),")"))
{
eErrorCode = InsertJoinConnection(_pView,pNode->getChild(1), _eJoinType);
}
else if (SQL_ISRULEOR2(pNode,search_condition,boolean_term) && // AND/OR-Verknuepfung:
pNode->count() == 3)
{
// nur AND Verkn<6B>pfung zulassen
if (!SQL_ISTOKEN(pNode->getChild(1),AND))
eErrorCode = eIllegalJoinCondition;
else if ( eOk == (eErrorCode = InsertJoinConnection(_pView,pNode->getChild(0), _eJoinType)) )
eErrorCode = InsertJoinConnection(_pView,pNode->getChild(2), _eJoinType);
}
else if (SQL_ISRULE(pNode,comparison_predicate))
{
// only the comparison of columns is allowed
DBG_ASSERT(pNode->count() == 3,"OQueryDesignView::InsertJoinConnection: Fehler im Parse Tree");
if (!(SQL_ISRULE(pNode->getChild(0),column_ref) &&
SQL_ISRULE(pNode->getChild(2),column_ref) &&
pNode->getChild(1)->getNodeType() == SQL_NODE_EQUAL))
{
String sError(ModuleRes(STR_QRY_JOIN_COLUMN_COMPARE));
_pView->getController().appendError( sError );
return eIllegalJoin;
}
OTableFieldDescRef aDragLeft = new OTableFieldDesc();
OTableFieldDescRef aDragRight = new OTableFieldDesc();
if ( eOk != ( eErrorCode = FillDragInfo(_pView,pNode->getChild(0),aDragLeft)) ||
eOk != ( eErrorCode = FillDragInfo(_pView,pNode->getChild(2),aDragRight)))
return eErrorCode;
insertConnection(_pView,_eJoinType,aDragLeft,aDragRight);
}
else
eErrorCode = eIllegalJoin;
return eErrorCode;
}
//------------------------------------------------------------------------------
sal_Bool GetInnerJoinCriteria( const OQueryDesignView* _pView,
const ::connectivity::OSQLParseNode *pCondition)
{
return InsertJoinConnection(_pView,pCondition, INNER_JOIN) != eOk;
}
//------------------------------------------------------------------------------
::rtl::OUString GenerateSelectList( const OQueryDesignView* _pView,
OTableFields& _rFieldList,
sal_Bool bAlias)
{
Reference< XConnection> xConnection = static_cast<OQueryController&>(_pView->getController()).getConnection();
if ( !xConnection.is() )
return ::rtl::OUString();
::rtl::OUStringBuffer aTmpStr,aFieldListStr;
sal_Bool bAsterix = sal_False;
int nVis = 0;
OTableFields::iterator aIter = _rFieldList.begin();
OTableFields::iterator aEnd = _rFieldList.end();
for(;aIter != aEnd;++aIter)
{
OTableFieldDescRef pEntryField = *aIter;
if ( pEntryField->IsVisible() )
{
if ( pEntryField->GetField().toChar() == '*' )
bAsterix = sal_True;
++nVis;
}
}
if(nVis == 1)
bAsterix = sal_False;
try
{
const Reference< XDatabaseMetaData > xMetaData = xConnection->getMetaData();
const ::rtl::OUString aQuote = xMetaData->getIdentifierQuoteString();
OJoinTableView::OTableWindowMap* pTabList = _pView->getTableView()->GetTabWinMap();
const static ::rtl::OUString sFieldSeparator(RTL_CONSTASCII_USTRINGPARAM(", "));
const static ::rtl::OUString s_sAs(RTL_CONSTASCII_USTRINGPARAM(" AS "));
aIter = _rFieldList.begin();
for(;aIter != aEnd;++aIter)
{
OTableFieldDescRef pEntryField = *aIter;
::rtl::OUString rFieldName = pEntryField->GetField();
if ( rFieldName.getLength() && pEntryField->IsVisible() )
{
aTmpStr = ::rtl::OUString();
const ::rtl::OUString rAlias = pEntryField->GetAlias();
const ::rtl::OUString rFieldAlias = pEntryField->GetFieldAlias();
aTmpStr.append(quoteTableAlias((bAlias || bAsterix),rAlias,aQuote));
// if we have a none numeric field, the table alias could be in the name
// otherwise we are not allowed to do this (e.g. 0.1 * PRICE )
if ( !pEntryField->isNumeric() )
{
// we have to look if we have alias.* here but before we have to check if the column doesn't already exist
String sTemp = rFieldName;
OTableFieldDescRef aInfo = new OTableFieldDesc();
OJoinTableView::OTableWindowMap::iterator tableIter = pTabList->begin();
OJoinTableView::OTableWindowMap::iterator tableEnd = pTabList->end();
sal_Bool bFound = sal_False;
for(;!bFound && tableIter != tableEnd ;++tableIter)
{
OQueryTableWindow* pTabWin = static_cast<OQueryTableWindow*>(tableIter->second);
bFound = pTabWin->ExistsField( rFieldName, aInfo );
if ( bFound )
rFieldName = aInfo->GetField();
}
if ( ( rFieldName.toChar() != '*' ) && ( rFieldName.indexOf( aQuote ) == -1 ) )
{
OSL_ENSURE(pEntryField->GetTable().getLength(),"No table field name!");
aTmpStr.append(::dbtools::quoteName(aQuote, rFieldName));
}
else
aTmpStr.append(rFieldName);
}
else
aTmpStr.append(rFieldName);
if ( pEntryField->isAggreateFunction() )
{
DBG_ASSERT(pEntryField->GetFunction().getLength(),"Functionname darf hier nicht leer sein! ;-(");
::rtl::OUStringBuffer aTmpStr2( pEntryField->GetFunction());
aTmpStr2.appendAscii("(");
aTmpStr2.append(aTmpStr.makeStringAndClear());
aTmpStr2.appendAscii(")");
aTmpStr = aTmpStr2;
}
if (rFieldAlias.getLength() &&
(rFieldName.toChar() != '*' ||
pEntryField->isNumericOrAggreateFunction() ||
pEntryField->isOtherFunction()))
{
aTmpStr.append(s_sAs);
aTmpStr.append(::dbtools::quoteName(aQuote, rFieldAlias));
}
aFieldListStr.append(aTmpStr.makeStringAndClear());
aFieldListStr.append(sFieldSeparator);
}
}
if(aFieldListStr.getLength())
aFieldListStr.setLength(aFieldListStr.getLength()-2);
}
catch(SQLException&)
{
OSL_ASSERT(!"Failure while building select list!");
}
return aFieldListStr.makeStringAndClear();
}
//------------------------------------------------------------------------------
sal_Bool GenerateCriterias( OQueryDesignView* _pView,
::rtl::OUStringBuffer& rRetStr,
::rtl::OUStringBuffer& rHavingStr,
OTableFields& _rFieldList,
sal_Bool bMulti )
{
// * darf keine Filter enthalten : habe ich die entsprechende Warnung schon angezeigt ?
sal_Bool bCritsOnAsterikWarning = sal_False; // ** TMFS **
::rtl::OUString aFieldName,aCriteria,aWhereStr,aHavingStr,aWork/*,aOrderStr*/;
// Zeilenweise werden die Ausdr"ucke mit AND verknuepft
sal_uInt16 nMaxCriteria = 0;
OTableFields::iterator aIter = _rFieldList.begin();
OTableFields::iterator aEnd = _rFieldList.end();
for(;aIter != aEnd;++aIter)
{
nMaxCriteria = ::std::max<sal_uInt16>(nMaxCriteria,(sal_uInt16)(*aIter)->GetCriteria().size());
}
Reference< XConnection> xConnection = static_cast<OQueryController&>(_pView->getController()).getConnection();
if(!xConnection.is())
return FALSE;
try
{
const Reference< XDatabaseMetaData > xMetaData = xConnection->getMetaData();
const ::rtl::OUString aQuote = xMetaData->getIdentifierQuoteString();
const IParseContext& rContext = static_cast<OQueryController&>(_pView->getController()).getParser().getContext();
for (sal_uInt16 i=0 ; i < nMaxCriteria ; i++)
{
aHavingStr = aWhereStr = ::rtl::OUString();
for(aIter = _rFieldList.begin();aIter != aEnd;++aIter)
{
OTableFieldDescRef pEntryField = *aIter;
aFieldName = pEntryField->GetField();
if (!aFieldName.getLength())
continue;
aCriteria = pEntryField->GetCriteria( i );
if ( aCriteria.getLength() )
{
// * is not allowed to contain any filter, only when used in combination an aggregate function
if ( aFieldName.toChar() == '*' && pEntryField->isNoneFunction() )
{
// only show the messagebox the first time
if (!bCritsOnAsterikWarning)
ErrorBox(_pView, ModuleRes( ERR_QRY_CRITERIA_ON_ASTERISK)).Execute();
bCritsOnAsterikWarning = sal_True;
continue;
}
aWork = ::rtl::OUString();
aWork += quoteTableAlias(bMulti,pEntryField->GetAlias(),aQuote);
if ( (pEntryField->GetFunctionType() & (FKT_OTHER|FKT_NUMERIC)) || (aFieldName.toChar() == '*') )
aWork += aFieldName;
else
aWork += ::dbtools::quoteName(aQuote, aFieldName);
if ( pEntryField->isAggreateFunction() || pEntryField->IsGroupBy() )
{
if (!aHavingStr.getLength()) // noch keine Kriterien
aHavingStr += ::rtl::OUString('('); // Klammern
else
aHavingStr += C_AND;
if ( pEntryField->isAggreateFunction() )
{
OSL_ENSURE(pEntryField->GetFunction().getLength(),"No function name for aggregate given!");
aHavingStr += pEntryField->GetFunction();
aHavingStr += ::rtl::OUString('('); // Klammern
aHavingStr += aWork;
aHavingStr += ::rtl::OUString(')'); // Klammern
}
else
aHavingStr += aWork;
::rtl::OUString aTmp = aCriteria;
::rtl::OUString aErrorMsg;
Reference<XPropertySet> xColumn;
::std::auto_ptr< ::connectivity::OSQLParseNode> pParseNode(_pView->getPredicateTreeFromEntry(pEntryField,aTmp,aErrorMsg,xColumn));
if (pParseNode.get())
{
if (bMulti && !(pEntryField->isOtherFunction() || (aFieldName.toChar() == '*')))
pParseNode->replaceNodeValue(pEntryField->GetAlias(),aFieldName);
::rtl::OUString sHavingStr = aHavingStr;
sal_uInt32 nCount = pParseNode->count();
for( sal_uInt32 node = 1 ; node < nCount ; ++node)
pParseNode->getChild(node)->parseNodeToStr( sHavingStr,
xConnection,
&rContext,
sal_False,
!pEntryField->isOtherFunction());
aHavingStr = sHavingStr;
}
else
aHavingStr += aCriteria;
}
else
{
if ( !aWhereStr.getLength() ) // noch keine Kriterien
aWhereStr += ::rtl::OUString('('); // Klammern
else
aWhereStr += C_AND;
aWhereStr += ::rtl::OUString(' ');
// aCriteria could have some german numbers so I have to be sure here
::rtl::OUString aTmp = aCriteria;
::rtl::OUString aErrorMsg;
Reference<XPropertySet> xColumn;
::std::auto_ptr< ::connectivity::OSQLParseNode> pParseNode( _pView->getPredicateTreeFromEntry(pEntryField,aTmp,aErrorMsg,xColumn));
if (pParseNode.get())
{
if (bMulti && !(pEntryField->isOtherFunction() || (aFieldName.toChar() == '*')))
pParseNode->replaceNodeValue(pEntryField->GetAlias(),aFieldName);
::rtl::OUString aWhere = aWhereStr;
pParseNode->parseNodeToStr( aWhere,
xConnection,
&rContext,
sal_False,
!pEntryField->isOtherFunction() );
aWhereStr = aWhere;
}
else
{
aWhereStr += aWork;
aWhereStr += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("="));
aWhereStr += aCriteria;
}
}
}
// nur einmal f<>r jedes Feld
else if ( !i && pEntryField->isCondition() )
{
if (!aWhereStr.getLength()) // noch keine Kriterien
aWhereStr += ::rtl::OUString('('); // Klammern
else
aWhereStr += C_AND;
aWhereStr += pEntryField->GetField();
}
}
if (aWhereStr.getLength())
{
aWhereStr += ::rtl::OUString(')'); // Klammern zu fuer 'AND' Zweig
if (rRetStr.getLength()) // schon Feldbedingungen ?
rRetStr.append(C_OR);
else // Klammern auf fuer 'OR' Zweig
rRetStr.append(sal_Unicode('('));
rRetStr.append(aWhereStr);
}
if (aHavingStr.getLength())
{
aHavingStr += ::rtl::OUString(')'); // Klammern zu fuer 'AND' Zweig
if (rHavingStr.getLength()) // schon Feldbedingungen ?
rHavingStr.append(C_OR);
else // Klammern auf fuer 'OR' Zweig
rHavingStr.append(sal_Unicode('('));
rHavingStr.append(aHavingStr);
}
}
if (rRetStr.getLength())
rRetStr.append(sal_Unicode(')')); // Klammern zu fuer 'OR' Zweig
if (rHavingStr.getLength())
rHavingStr.append(sal_Unicode(')')); // Klammern zu fuer 'OR' Zweig
}
catch(SQLException&)
{
OSL_ASSERT(!"Failure while building where clause!");
}
return sal_True;
}
//------------------------------------------------------------------------------
SqlParseError GenerateOrder( OQueryDesignView* _pView,
OTableFields& _rFieldList,
sal_Bool bMulti,
::rtl::OUString& _rsRet)
{
const OQueryController& rController = static_cast<OQueryController&>(_pView->getController());
Reference< XConnection> xConnection = rController.getConnection();
if ( !xConnection.is() )
return eNoConnection;
SqlParseError eErrorCode = eOk;
::rtl::OUString aColumnName;
::rtl::OUString aWorkStr;
try
{
const bool bColumnAliasInOrderBy = rController.getSdbMetaData().supportsColumnAliasInOrderBy();
Reference< XDatabaseMetaData > xMetaData = xConnection->getMetaData();
::rtl::OUString aQuote = xMetaData->getIdentifierQuoteString();
// * darf keine Filter enthalten : habe ich die entsprechende Warnung schon angezeigt ?
sal_Bool bCritsOnAsterikWarning = sal_False; // ** TMFS **
OTableFields::iterator aIter = _rFieldList.begin();
OTableFields::iterator aEnd = _rFieldList.end();
for(;aIter != aEnd;++aIter)
{
OTableFieldDescRef pEntryField = *aIter;
EOrderDir eOrder = pEntryField->GetOrderDir();
// nur wenn eine Sortierung und ein Tabellenname vorhanden ist-> erzeugen
// sonst werden die Expressions vom Order By im GenerateCriteria mit erzeugt
if ( eOrder != ORDER_NONE )
{
aColumnName = pEntryField->GetField();
if(aColumnName.toChar() == '*')
{
// die entsprechende MessageBox nur beim ersten mal anzeigen
if (!bCritsOnAsterikWarning)
ErrorBox(_pView, ModuleRes( ERR_QRY_ORDERBY_ON_ASTERISK)).Execute();
bCritsOnAsterikWarning = sal_True;
continue;
}
if ( bColumnAliasInOrderBy && pEntryField->GetFieldAlias().getLength() )
{
aWorkStr += ::dbtools::quoteName(aQuote, pEntryField->GetFieldAlias());
}
else if ( pEntryField->isNumericOrAggreateFunction() )
{
DBG_ASSERT(pEntryField->GetFunction().getLength(),"Functionname darf hier nicht leer sein! ;-(");
aWorkStr += pEntryField->GetFunction();
aWorkStr += ::rtl::OUString('(');
aWorkStr += quoteTableAlias(bMulti,pEntryField->GetAlias(),aQuote);
// only quote column name when we don't have a numeric
if ( pEntryField->isNumeric() )
aWorkStr += aColumnName;
else
aWorkStr += ::dbtools::quoteName(aQuote, aColumnName);
aWorkStr += ::rtl::OUString(')');
}
else if ( pEntryField->isOtherFunction() )
{
aWorkStr += aColumnName;
}
else
{
aWorkStr += quoteTableAlias(bMulti,pEntryField->GetAlias(),aQuote);
aWorkStr += ::dbtools::quoteName(aQuote, aColumnName);
}
aWorkStr += ::rtl::OUString(' ');
aWorkStr += String::CreateFromAscii( ";ASC;DESC" ).GetToken( (USHORT)eOrder );
aWorkStr += ::rtl::OUString(',');
}
}
{
String sTemp(aWorkStr);
sTemp.EraseTrailingChars( ',' );
aWorkStr = sTemp;
}
if ( aWorkStr.getLength() )
{
const sal_Int32 nMaxOrder = xMetaData->getMaxColumnsInOrderBy();
String sToken(aWorkStr);
if ( nMaxOrder && nMaxOrder < sToken.GetTokenCount(',') )
eErrorCode = eStatementTooLong;
else
{
_rsRet = ::rtl::OUString::createFromAscii(" ORDER BY ");
_rsRet += aWorkStr;
}
}
}
catch(SQLException&)
{
OSL_ASSERT(!"Failure while building group by!");
}
return eErrorCode;
}
//------------------------------------------------------------------------------
void GenerateInnerJoinCriterias(const Reference< XConnection>& _xConnection,
::rtl::OUString& _rJoinCrit,
const ::std::vector<OTableConnection*>* _pConnList)
{
::std::vector<OTableConnection*>::const_iterator aIter = _pConnList->begin();
::std::vector<OTableConnection*>::const_iterator aEnd = _pConnList->end();
for(;aIter != aEnd;++aIter)
{
const OQueryTableConnection* pEntryConn = static_cast<const OQueryTableConnection*>(*aIter);
OQueryTableConnectionData* pEntryConnData = static_cast<OQueryTableConnectionData*>(pEntryConn->GetData().get());
if ( pEntryConnData->GetJoinType() == INNER_JOIN && !pEntryConnData->isNatural() )
{
if(_rJoinCrit.getLength())
_rJoinCrit += C_AND;
_rJoinCrit += BuildJoinCriteria(_xConnection,pEntryConnData->GetConnLineDataList(),pEntryConnData);
}
}
}
//------------------------------------------------------------------------------
void searchAndAppendName(const Reference< XConnection>& _xConnection,
const OQueryTableWindow* _pTableWindow,
::std::map< ::rtl::OUString,sal_Bool,::comphelper::UStringMixLess>& _rTableNames,
::rtl::OUString& _rsTableListStr
)
{
::rtl::OUString sTabName(BuildTable(_xConnection,_pTableWindow));
if(_rTableNames.find(sTabName) == _rTableNames.end())
{
_rTableNames[sTabName] = sal_True;
_rsTableListStr += sTabName;
_rsTableListStr += ::rtl::OUString(',');
}
}
//------------------------------------------------------------------------------
::rtl::OUString GenerateFromClause( const Reference< XConnection>& _xConnection,
const OQueryTableView::OTableWindowMap* pTabList,
const ::std::vector<OTableConnection*>* pConnList
)
{
::rtl::OUString aTableListStr;
// wird gebraucht um sicher zustelllen das eine Tabelle nicht doppelt vorkommt
::std::map< ::rtl::OUString,sal_Bool,::comphelper::UStringMixLess> aTableNames;
// generate outer join clause in from
if(!pConnList->empty())
{
::std::vector<OTableConnection*>::const_iterator aIter = pConnList->begin();
::std::vector<OTableConnection*>::const_iterator aEnd = pConnList->end();
for(;aIter != aEnd;++aIter)
static_cast<OQueryTableConnection*>(*aIter)->SetVisited(sal_False);
aIter = pConnList->begin();
const sal_Bool bUseEscape = ::dbtools::getBooleanDataSourceSetting( _xConnection, PROPERTY_OUTERJOINESCAPE );
for(;aIter != aEnd;++aIter)
{
OQueryTableConnection* pEntryConn = static_cast<OQueryTableConnection*>(*aIter);
if(!pEntryConn->IsVisited())
{
::rtl::OUString aJoin;
GetNextJoin(_xConnection,pEntryConn,static_cast<OQueryTableWindow*>(pEntryConn->GetDestWin()),aJoin);
if(aJoin.getLength())
{
// insert tables into table list to avoid double entries
OQueryTableWindow* pEntryTabFrom = static_cast<OQueryTableWindow*>(pEntryConn->GetSourceWin());
OQueryTableWindow* pEntryTabTo = static_cast<OQueryTableWindow*>(pEntryConn->GetDestWin());
::rtl::OUString sTabName(BuildTable(_xConnection,pEntryTabFrom));
if(aTableNames.find(sTabName) == aTableNames.end())
aTableNames[sTabName] = sal_True;
sTabName = BuildTable(_xConnection,pEntryTabTo);
if(aTableNames.find(sTabName) == aTableNames.end())
aTableNames[sTabName] = sal_True;
::rtl::OUString aStr;
switch(static_cast<OQueryTableConnectionData*>(pEntryConn->GetData().get())->GetJoinType())
{
case LEFT_JOIN:
case RIGHT_JOIN:
case FULL_JOIN:
{
// create outer join
if ( bUseEscape )
aStr += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("{ OJ "));
aStr += aJoin;
if ( bUseEscape )
aStr += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" }"));
}
break;
default:
aStr += aJoin;
break;
}
aStr += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(","));
aTableListStr += aStr;
}
}
}
// and now all inner joins
aIter = pConnList->begin();
for(;aIter != aEnd;++aIter)
{
OQueryTableConnection* pEntryConn = static_cast<OQueryTableConnection*>(*aIter);
if(!pEntryConn->IsVisited())
{
searchAndAppendName(_xConnection,
static_cast<OQueryTableWindow*>(pEntryConn->GetSourceWin()),
aTableNames,
aTableListStr);
searchAndAppendName(_xConnection,
static_cast<OQueryTableWindow*>(pEntryConn->GetDestWin()),
aTableNames,
aTableListStr);
}
}
}
// all tables that haven't a connection to anyone
OQueryTableView::OTableWindowMap::const_iterator aTabIter = pTabList->begin();
OQueryTableView::OTableWindowMap::const_iterator aTabEnd = pTabList->end();
for(;aTabIter != aTabEnd;++aTabIter)
{
const OQueryTableWindow* pEntryTab = static_cast<const OQueryTableWindow*>(aTabIter->second);
if(!pEntryTab->ExistsAConn())
{
aTableListStr += BuildTable(_xConnection,pEntryTab);
aTableListStr += ::rtl::OUString(',');
}
}
if(aTableListStr.getLength())
aTableListStr = aTableListStr.replaceAt(aTableListStr.getLength()-1,1, ::rtl::OUString() );
return aTableListStr;
}
//------------------------------------------------------------------------------
::rtl::OUString GenerateGroupBy(const OQueryDesignView* _pView,OTableFields& _rFieldList, sal_Bool bMulti )
{
OQueryController& rController = static_cast<OQueryController&>(_pView->getController());
const Reference< XConnection> xConnection = rController.getConnection();
if(!xConnection.is())
return ::rtl::OUString();
::std::map< rtl::OUString,bool> aGroupByNames;
::rtl::OUString aGroupByStr;
try
{
const Reference< XDatabaseMetaData > xMetaData = xConnection->getMetaData();
const ::rtl::OUString aQuote = xMetaData->getIdentifierQuoteString();
OTableFields::iterator aIter = _rFieldList.begin();
OTableFields::iterator aEnd = _rFieldList.end();
for(;aIter != aEnd;++aIter)
{
OTableFieldDescRef pEntryField = *aIter;
if ( pEntryField->IsGroupBy() )
{
DBG_ASSERT(pEntryField->GetField().getLength(),"Kein FieldName vorhanden!;-(");
::rtl::OUString sGroupByPart = quoteTableAlias(bMulti,pEntryField->GetAlias(),aQuote);
// only quote the field name when it isn't calculated
if ( pEntryField->isNoneFunction() )
{
sGroupByPart += ::dbtools::quoteName(aQuote, pEntryField->GetField());
}
else
{
::rtl::OUString aTmp = pEntryField->GetField();
::rtl::OUString aErrorMsg;
Reference<XPropertySet> xColumn;
::std::auto_ptr< ::connectivity::OSQLParseNode> pParseNode(_pView->getPredicateTreeFromEntry(pEntryField,aTmp,aErrorMsg,xColumn));
if (pParseNode.get())
{
::rtl::OUString sGroupBy;
pParseNode->parseNodeToStr( sGroupBy,
xConnection,
&rController.getParser().getContext(),
sal_False,
!pEntryField->isOtherFunction());
sGroupByPart += sGroupBy;
}
else
sGroupByPart += pEntryField->GetField();
}
if ( aGroupByNames.find(sGroupByPart) == aGroupByNames.end() )
{
aGroupByNames.insert(::std::map< rtl::OUString,bool>::value_type(sGroupByPart,true));
aGroupByStr += sGroupByPart;
aGroupByStr += ::rtl::OUString(',');
}
}
}
if ( aGroupByStr.getLength() )
{
aGroupByStr = aGroupByStr.replaceAt(aGroupByStr.getLength()-1,1, ::rtl::OUString(' ') );
::rtl::OUString aGroupByStr2 = ::rtl::OUString::createFromAscii(" GROUP BY ");
aGroupByStr2 += aGroupByStr;
aGroupByStr = aGroupByStr2;
}
}
catch(SQLException&)
{
OSL_ASSERT(!"Failure while building group by!");
}
return aGroupByStr;
}
// -----------------------------------------------------------------------------
SqlParseError GetORCriteria(OQueryDesignView* _pView,
OSelectionBrowseBox* _pSelectionBrw,
const ::connectivity::OSQLParseNode * pCondition,
sal_uInt16& nLevel ,
sal_Bool bHaving = sal_False,
bool bAddOrOnOneLine = false);
// -----------------------------------------------------------------------------
SqlParseError GetSelectionCriteria( OQueryDesignView* _pView,
OSelectionBrowseBox* _pSelectionBrw,
const ::connectivity::OSQLParseNode* pNode,
sal_uInt16& rLevel )
{
if (!SQL_ISRULE(pNode, select_statement))
return eNoSelectStatement;
// nyi: mehr Pruefung auf korrekte Struktur!
pNode = pNode ? pNode->getChild(3)->getChild(1) : NULL;
// no where clause found
if (!pNode || pNode->isLeaf())
return eOk;
// Naechster freier Satz ...
SqlParseError eErrorCode = eOk;
::connectivity::OSQLParseNode * pCondition = pNode->getChild(1);
if ( pCondition ) // no where clause
{
// now we have to chech the other conditions
// first make the logical easier
::connectivity::OSQLParseNode::negateSearchCondition(pCondition);
::connectivity::OSQLParseNode *pNodeTmp = pNode->getChild(1);
::connectivity::OSQLParseNode::disjunctiveNormalForm(pNodeTmp);
pNodeTmp = pNode->getChild(1);
::connectivity::OSQLParseNode::absorptions(pNodeTmp);
pNodeTmp = pNode->getChild(1);
// compress sort the criteria @see http://www.openoffice.org/issues/show_bug.cgi?id=24079
OSQLParseNode::compress(pNodeTmp);
pNodeTmp = pNode->getChild(1);
// first extract the inner joins conditions
GetInnerJoinCriteria(_pView,pNodeTmp);
// it could happen that pCondition is not more valid
eErrorCode = GetORCriteria(_pView,_pSelectionBrw,pNodeTmp, rLevel);
}
return eErrorCode;
}
//------------------------------------------------------------------------------
SqlParseError GetANDCriteria( OQueryDesignView* _pView,
OSelectionBrowseBox* _pSelectionBrw,
const ::connectivity::OSQLParseNode * pCondition,
const sal_uInt16 nLevel,
sal_Bool bHaving,
bool bAddOrOnOneLine);
//------------------------------------------------------------------------------
SqlParseError ComparisonPredicate(OQueryDesignView* _pView,
OSelectionBrowseBox* _pSelectionBrw,
const ::connectivity::OSQLParseNode * pCondition,
const sal_uInt16 nLevel,
sal_Bool bHaving,
bool bAddOrOnOneLine);
//------------------------------------------------------------------------------
SqlParseError GetORCriteria(OQueryDesignView* _pView,
OSelectionBrowseBox* _pSelectionBrw,
const ::connectivity::OSQLParseNode * pCondition,
sal_uInt16& nLevel ,
sal_Bool bHaving,
bool bAddOrOnOneLine)
{
SqlParseError eErrorCode = eOk;
// Runde Klammern um den Ausdruck
if (pCondition->count() == 3 &&
SQL_ISPUNCTUATION(pCondition->getChild(0),"(") &&
SQL_ISPUNCTUATION(pCondition->getChild(2),")"))
{
eErrorCode = GetORCriteria(_pView,_pSelectionBrw,pCondition->getChild(1),nLevel,bHaving,bAddOrOnOneLine);
}
// oder Verknuepfung
// a searchcondition can only look like this: search_condition SQL_TOKEN_OR boolean_term
else if (SQL_ISRULE(pCondition,search_condition))
{
for (int i = 0; i < 3 && eErrorCode == eOk ; i+=2)
{
const ::connectivity::OSQLParseNode* pChild = pCondition->getChild(i);
if ( SQL_ISRULE(pChild,search_condition) )
eErrorCode = GetORCriteria(_pView,_pSelectionBrw,pChild,nLevel,bHaving,bAddOrOnOneLine);
else
eErrorCode = GetANDCriteria(_pView,_pSelectionBrw,pChild, bAddOrOnOneLine ? nLevel : nLevel++,bHaving, i == 0 ? false : bAddOrOnOneLine);
}
}
else
eErrorCode = GetANDCriteria( _pView,_pSelectionBrw,pCondition, nLevel, bHaving,bAddOrOnOneLine );
return eErrorCode;
}
//--------------------------------------------------------------------------------------------------
bool CheckOrCriteria(const ::connectivity::OSQLParseNode* _pCondition,::connectivity::OSQLParseNode* _pFirstColumnRef)
{
bool bRet = true;
::connectivity::OSQLParseNode* pFirstColumnRef = _pFirstColumnRef;
for (int i = 0; i < 3 && bRet; i+=2)
{
const ::connectivity::OSQLParseNode* pChild = _pCondition->getChild(i);
if ( SQL_ISRULE(pChild,search_condition) )
bRet = CheckOrCriteria(pChild,pFirstColumnRef);
else
{
// this is a simple way to test columns are the same, may be we have to adjust this algo a little bit in future. :-)
::connectivity::OSQLParseNode* pSecondColumnRef = pChild->getByRule(::connectivity::OSQLParseNode::column_ref);
if ( pFirstColumnRef && pSecondColumnRef )
bRet = *pFirstColumnRef == *pSecondColumnRef;
else if ( !pFirstColumnRef )
pFirstColumnRef = pSecondColumnRef;
}
}
return bRet;
}
//--------------------------------------------------------------------------------------------------
SqlParseError GetANDCriteria( OQueryDesignView* _pView,
OSelectionBrowseBox* _pSelectionBrw,
const ::connectivity::OSQLParseNode * pCondition,
const sal_uInt16 nLevel,
sal_Bool bHaving,
bool bAddOrOnOneLine)
{
const ::com::sun::star::lang::Locale aLocale = _pView->getLocale();
const ::rtl::OUString sDecimal = _pView->getDecimalSeparator();
// ich werde ein paar Mal einen gecasteten Pointer auf meinen ::com::sun::star::sdbcx::Container brauchen
OQueryController& rController = static_cast<OQueryController&>(_pView->getController());
SqlParseError eErrorCode = eOk;
// Runde Klammern
if (SQL_ISRULE(pCondition,boolean_primary))
{
sal_uInt16 nLevel2 = nLevel;
// check if we have to put the or criteria on one line.
bool bMustAddOrOnOneLine = CheckOrCriteria(pCondition->getChild(1),NULL);
eErrorCode = GetORCriteria(_pView,_pSelectionBrw,pCondition->getChild(1), nLevel2,bHaving,bMustAddOrOnOneLine );
}
// Das erste Element ist (wieder) eine AND-Verknuepfung
else if ( SQL_ISRULE(pCondition,boolean_term) )
{
OSL_ENSURE(pCondition->count() == 3,"Illegal definifiton of boolean_term");
eErrorCode = GetANDCriteria(_pView,_pSelectionBrw,pCondition->getChild(0), nLevel,bHaving,bAddOrOnOneLine );
if ( eErrorCode == eOk )
eErrorCode = GetANDCriteria(_pView,_pSelectionBrw,pCondition->getChild(2), nLevel,bHaving,bAddOrOnOneLine );
}
else if (SQL_ISRULE( pCondition, comparison_predicate))
{
eErrorCode = ComparisonPredicate(_pView,_pSelectionBrw,pCondition,nLevel,bHaving,bAddOrOnOneLine);
}
else if( SQL_ISRULE(pCondition,like_predicate) )
{
const ::connectivity::OSQLParseNode* pValueExp = pCondition->getChild(0);
if (SQL_ISRULE(pValueExp, column_ref ) )
{
::rtl::OUString aColumnName;
::rtl::OUString aCondition;
Reference< XConnection> xConnection = rController.getConnection();
if ( xConnection.is() )
{
Reference< XDatabaseMetaData > xMetaData = xConnection->getMetaData();
// the international doesn't matter I have a string
pCondition->parseNodeToPredicateStr(aCondition,
xConnection,
rController.getNumberFormatter(),
aLocale,
static_cast<sal_Char>(sDecimal.toChar()),
&rController.getParser().getContext());
pValueExp->parseNodeToPredicateStr( aColumnName,
xConnection,
rController.getNumberFormatter(),
aLocale,
static_cast<sal_Char>(sDecimal.toChar()),
&rController.getParser().getContext());
// don't display the column name
aCondition = aCondition.copy(aColumnName.getLength());
aCondition = aCondition.trim();
}
OTableFieldDescRef aDragLeft = new OTableFieldDesc();
if ( eOk == ( eErrorCode = FillDragInfo(_pView,pValueExp,aDragLeft) ))
{
if ( bHaving )
aDragLeft->SetGroupBy(sal_True);
_pSelectionBrw->AddCondition(aDragLeft, aCondition, nLevel,bAddOrOnOneLine);
}
}
else if(SQL_ISRULEOR2(pValueExp,general_set_fct ,set_fct_spec) ||
SQL_ISRULEOR2(pValueExp,position_exp,extract_exp) ||
SQL_ISRULEOR2(pValueExp,fold,char_substring_fct) ||
SQL_ISRULEOR2(pValueExp,length_exp,char_value_fct))
{
AddFunctionCondition( _pView,
_pSelectionBrw,
pCondition,
nLevel,
bHaving,
bAddOrOnOneLine);
}
else
{
eErrorCode = eNoColumnInLike;
String sError(ModuleRes(STR_QRY_LIKE_LEFT_NO_COLUMN));
_pView->getController().appendError( sError );
}
}
else if( SQL_ISRULEOR2(pCondition,test_for_null,in_predicate)
|| SQL_ISRULEOR2(pCondition,all_or_any_predicate,between_predicate))
{
if ( SQL_ISRULEOR2(pCondition->getChild(0), set_fct_spec , general_set_fct ) )
{
AddFunctionCondition( _pView,
_pSelectionBrw,
pCondition,
nLevel,
bHaving,
bAddOrOnOneLine);
}
else if ( SQL_ISRULE(pCondition->getChild(0), column_ref ) )
{
// parse condition
::rtl::OUString sCondition = ParseCondition(rController,pCondition,sDecimal,aLocale,1);
OTableFieldDescRef aDragLeft = new OTableFieldDesc();
if ( eOk == ( eErrorCode = FillDragInfo(_pView,pCondition->getChild(0),aDragLeft)) )
{
if ( bHaving )
aDragLeft->SetGroupBy(sal_True);
_pSelectionBrw->AddCondition(aDragLeft, sCondition, nLevel,bAddOrOnOneLine);
}
}
}
else if( SQL_ISRULEOR2(pCondition,existence_test,unique_test) )
{
// Funktions-Bedingung parsen
::rtl::OUString aCondition = ParseCondition(rController,pCondition,sDecimal,aLocale,0);
OTableFieldDescRef aDragLeft = new OTableFieldDesc();
aDragLeft->SetField(aCondition);
aDragLeft->SetFunctionType(FKT_CONDITION);
eErrorCode = _pSelectionBrw->InsertField(aDragLeft,BROWSER_INVALIDID,sal_False,sal_True).isValid() ? eOk : eTooManyColumns;
}
else //! TODO not supported yet
eErrorCode = eStatementTooComplex;
// Fehler einfach weiterreichen.
return eErrorCode;
}
//------------------------------------------------------------------------------
SqlParseError AddFunctionCondition(OQueryDesignView* _pView,
OSelectionBrowseBox* _pSelectionBrw,
const ::connectivity::OSQLParseNode * pCondition,
const sal_uInt16 nLevel,
sal_Bool bHaving,
bool bAddOrOnOneLine)
{
SqlParseError eErrorCode = eOk;
OQueryController& rController = static_cast<OQueryController&>(_pView->getController());
OSQLParseNode* pFunction = pCondition->getChild(0);
OSL_ENSURE(SQL_ISRULEOR2(pFunction,general_set_fct ,set_fct_spec) ||
SQL_ISRULEOR2(pFunction,position_exp,extract_exp) ||
SQL_ISRULEOR2(pFunction,fold,char_substring_fct) ||
SQL_ISRULEOR2(pFunction,length_exp,char_value_fct),"Illegal call!");
::rtl::OUString aCondition;
OTableFieldDescRef aDragLeft = new OTableFieldDesc();
::rtl::OUString aColumnName;
Reference< XConnection> xConnection = rController.getConnection();
if(xConnection.is())
{
Reference< XDatabaseMetaData > xMetaData = xConnection->getMetaData();
pCondition->parseNodeToPredicateStr(aCondition,
xConnection,
rController.getNumberFormatter(),
_pView->getLocale(),
static_cast<sal_Char>(_pView->getDecimalSeparator().toChar()),
&rController.getParser().getContext());
pFunction->parseNodeToStr( aColumnName,
xConnection,
&rController.getParser().getContext(),
sal_True,
sal_True); // quote is to true because we need quoted elements inside the function
// i75557
//pFunction->parseNodeToPredicateStr(aColumnName,
// xConnection,
// rController.getNumberFormatter(),
// _pView->getLocale(),
// static_cast<sal_Char>(_pView->getDecimalSeparator().toChar()),
// &rController.getParser().getContext());
// don't display the column name
aCondition = aCondition.copy(aColumnName.getLength());
aCondition = aCondition.trim();
if ( aCondition.indexOf('=',0) == 0 ) // ignore the equal sign
aCondition = aCondition.copy(1);
if ( SQL_ISRULE(pFunction, general_set_fct ) )
{
sal_Int32 nFunctionType = FKT_AGGREGATE;
OSQLParseNode* pParamNode = pFunction->getChild(pFunction->count()-2);
if ( pParamNode && pParamNode->getTokenValue().toChar() == '*' )
{
OJoinTableView::OTableWindowMap* pTabList = _pView->getTableView()->GetTabWinMap();
OJoinTableView::OTableWindowMap::iterator aIter = pTabList->begin();
OJoinTableView::OTableWindowMap::iterator aTabEnd = pTabList->end();
for(;aIter != aTabEnd;++aIter)
{
OQueryTableWindow* pTabWin = static_cast<OQueryTableWindow*>(aIter->second);
if (pTabWin->ExistsField( ::rtl::OUString::createFromAscii("*"), aDragLeft ))
{
aDragLeft->SetAlias(String());
aDragLeft->SetTable(String());
break;
}
}
}
else if( eOk != ( eErrorCode = FillDragInfo(_pView,pParamNode,aDragLeft))
&& SQL_ISRULE(pParamNode,num_value_exp) )
{
::rtl::OUString sParameterValue;
pParamNode->parseNodeToStr( sParameterValue,
xConnection,
&rController.getParser().getContext());
nFunctionType |= FKT_NUMERIC;
aDragLeft->SetField(sParameterValue);
eErrorCode = eOk;
}
aDragLeft->SetFunctionType(nFunctionType);
if ( bHaving )
aDragLeft->SetGroupBy(sal_True);
sal_Int32 nIndex = 0;
aDragLeft->SetFunction(aColumnName.getToken(0,'(',nIndex));
}
else
{
// bei unbekannten Funktionen wird der gesamte Text in das Field gechrieben
aDragLeft->SetField(aColumnName);
if(bHaving)
aDragLeft->SetGroupBy(sal_True);
aDragLeft->SetFunctionType(FKT_OTHER|FKT_NUMERIC);
}
_pSelectionBrw->AddCondition(aDragLeft, aCondition, nLevel,bAddOrOnOneLine);
}
return eErrorCode;
}
//------------------------------------------------------------------------------
SqlParseError ComparisonPredicate(OQueryDesignView* _pView,
OSelectionBrowseBox* _pSelectionBrw,
const ::connectivity::OSQLParseNode * pCondition,
const sal_uInt16 nLevel,
sal_Bool bHaving
,bool bAddOrOnOneLine)
{
SqlParseError eErrorCode = eOk;
OQueryController& rController = static_cast<OQueryController&>(_pView->getController());
DBG_ASSERT(SQL_ISRULE( pCondition, comparison_predicate),"ComparisonPredicate: pCondition ist kein ComparisonPredicate");
if ( SQL_ISRULE(pCondition->getChild(0), column_ref )
|| SQL_ISRULE(pCondition->getChild(pCondition->count()-1), column_ref) )
{
::rtl::OUString aCondition;
OTableFieldDescRef aDragLeft = new OTableFieldDesc();
if ( SQL_ISRULE(pCondition->getChild(0), column_ref ) && SQL_ISRULE(pCondition->getChild(pCondition->count()-1), column_ref ) )
{
OTableFieldDescRef aDragRight = new OTableFieldDesc();
if (eOk != ( eErrorCode = FillDragInfo(_pView,pCondition->getChild(0),aDragLeft)) ||
eOk != ( eErrorCode = FillDragInfo(_pView,pCondition->getChild(2),aDragRight)))
return eErrorCode;
OQueryTableConnection* pConn = static_cast<OQueryTableConnection*>(
_pView->getTableView()->GetTabConn(static_cast<OQueryTableWindow*>(aDragLeft->GetTabWindow()),
static_cast<OQueryTableWindow*>(aDragRight->GetTabWindow()),
true));
if ( pConn )
{
OConnectionLineDataVec* pLineDataList = pConn->GetData()->GetConnLineDataList();
OConnectionLineDataVec::iterator aIter = pLineDataList->begin();
OConnectionLineDataVec::iterator aEnd = pLineDataList->end();
for(;aIter != aEnd;++aIter)
{
if((*aIter)->GetSourceFieldName() == aDragLeft->GetField() ||
(*aIter)->GetDestFieldName() == aDragLeft->GetField() )
break;
}
if(aIter != aEnd)
return eOk;
}
}
sal_uInt32 nPos = 0;
if(SQL_ISRULE(pCondition->getChild(0), column_ref ))
{
nPos = 0;
sal_uInt32 i=1;
// don't display the equal
if (pCondition->getChild(i)->getNodeType() == SQL_NODE_EQUAL)
i++;
// Bedingung parsen
aCondition = ParseCondition(rController
,pCondition
,_pView->getDecimalSeparator()
,_pView->getLocale()
,i);
}
else if( SQL_ISRULE(pCondition->getChild(pCondition->count()-1), column_ref ) )
{
nPos = pCondition->count()-1;
sal_Int32 i = static_cast<sal_Int32>(pCondition->count() - 2);
switch (pCondition->getChild(i)->getNodeType())
{
case SQL_NODE_EQUAL:
// don't display the equal
i--;
break;
case SQL_NODE_LESS:
// take the opposite as we change the order
i--;
aCondition = aCondition + ::rtl::OUString::createFromAscii(">");
break;
case SQL_NODE_LESSEQ:
// take the opposite as we change the order
i--;
aCondition = aCondition + ::rtl::OUString::createFromAscii(">=");
break;
case SQL_NODE_GREAT:
// take the opposite as we change the order
i--;
aCondition = aCondition + ::rtl::OUString::createFromAscii("<");
break;
case SQL_NODE_GREATEQ:
// take the opposite as we change the order
i--;
aCondition = aCondition + ::rtl::OUString::createFromAscii("<=");
break;
default:
break;
}
// go backward
Reference< XConnection> xConnection = rController.getConnection();
if(xConnection.is())
{
Reference< XDatabaseMetaData > xMetaData = xConnection->getMetaData();
for (; i >= 0; i--)
pCondition->getChild(i)->parseNodeToPredicateStr(aCondition,
xConnection,
rController.getNumberFormatter(),
_pView->getLocale(),
static_cast<sal_Char>(_pView->getDecimalSeparator().toChar()),
&rController.getParser().getContext());
}
}
// else ???
if( eOk == ( eErrorCode = FillDragInfo(_pView,pCondition->getChild(nPos),aDragLeft)))
{
if(bHaving)
aDragLeft->SetGroupBy(sal_True);
_pSelectionBrw->AddCondition(aDragLeft, aCondition, nLevel,bAddOrOnOneLine);
}
}
else if( SQL_ISRULEOR2(pCondition->getChild(0), set_fct_spec , general_set_fct ) )
{
AddFunctionCondition( _pView,
_pSelectionBrw,
pCondition,
nLevel,
bHaving,
bAddOrOnOneLine);
}
else // kann sich nur um einen Expr. Ausdruck handeln
{
::rtl::OUString aName,aCondition;
::connectivity::OSQLParseNode *pLhs = pCondition->getChild(0);
::connectivity::OSQLParseNode *pRhs = pCondition->getChild(2);
// Feldnamen
Reference< XConnection> xConnection = rController.getConnection();
if(xConnection.is())
{
pLhs->parseNodeToStr(aName,
xConnection,
&rController.getParser().getContext(),
sal_True);
// Kriterium
aCondition = pCondition->getChild(1)->getTokenValue();
pRhs->parseNodeToPredicateStr(aCondition,
xConnection,
rController.getNumberFormatter(),
_pView->getLocale(),
static_cast<sal_Char>(_pView->getDecimalSeparator().toChar()),
&rController.getParser().getContext());
}
OTableFieldDescRef aDragLeft = new OTableFieldDesc();
aDragLeft->SetField(aName);
aDragLeft->SetFunctionType(FKT_OTHER|FKT_NUMERIC);
// und anh"angen
_pSelectionBrw->AddCondition(aDragLeft, aCondition, nLevel,bAddOrOnOneLine);
}
return eErrorCode;
}
//------------------------------------------------------------------------------
namespace
{
OQueryTableWindow* lcl_findColumnInTables( const ::rtl::OUString& _rColumName, const OJoinTableView::OTableWindowMap& _rTabList, OTableFieldDescRef& _rInfo )
{
OJoinTableView::OTableWindowMap::const_iterator aIter = _rTabList.begin();
OJoinTableView::OTableWindowMap::const_iterator aEnd = _rTabList.end();
for ( ; aIter != aEnd; ++aIter )
{
OQueryTableWindow* pTabWin = static_cast< OQueryTableWindow* >( aIter->second );
if ( pTabWin && pTabWin->ExistsField( _rColumName, _rInfo ) )
return pTabWin;
}
return NULL;
}
}
//------------------------------------------------------------------------------
void InsertColumnRef(const OQueryDesignView* _pView,
const ::connectivity::OSQLParseNode * pColumnRef,
::rtl::OUString& aColumnName,
const ::rtl::OUString& aColumnAlias,
::rtl::OUString& aTableRange,
OTableFieldDescRef& _raInfo,
OJoinTableView::OTableWindowMap* pTabList)
{
// Tabellennamen zusammen setzen
::connectivity::OSQLParseTreeIterator& rParseIter = static_cast<OQueryController&>(_pView->getController()).getParseIterator();
rParseIter.getColumnRange( pColumnRef, aColumnName, aTableRange );
sal_Bool bFound(sal_False);
DBG_ASSERT(aColumnName.getLength(),"Columnname darf nicht leer sein");
if (!aTableRange.getLength())
{
// SELECT column, ...
bFound = NULL != lcl_findColumnInTables( aColumnName, *pTabList, _raInfo );
if ( bFound && ( aColumnName.toChar() != '*' ) )
_raInfo->SetFieldAlias(aColumnAlias);
}
else
{
// SELECT range.column, ...
OQueryTableWindow* pTabWin = static_cast<OQueryTableView*>(_pView->getTableView())->FindTable(aTableRange);
if (pTabWin && pTabWin->ExistsField(aColumnName, _raInfo))
{
if(aColumnName.toChar() != '*')
_raInfo->SetFieldAlias(aColumnAlias);
bFound = sal_True;
}
}
if (!bFound)
{
_raInfo->SetTable(::rtl::OUString());
_raInfo->SetAlias(::rtl::OUString());
_raInfo->SetField(aColumnName);
_raInfo->SetFieldAlias(aColumnAlias); // nyi : hier ein fortlaufendes Expr_1, Expr_2 ...
_raInfo->SetFunctionType(FKT_OTHER);
}
}
//-----------------------------------------------------------------------------
sal_Bool checkJoinConditions( const OQueryDesignView* _pView,
const ::connectivity::OSQLParseNode* _pNode )
{
const ::connectivity::OSQLParseNode* pJoinNode = NULL;
sal_Bool bRet = sal_True;
if (SQL_ISRULE(_pNode,qualified_join))
pJoinNode = _pNode;
else if (SQL_ISRULE(_pNode,table_ref)
&& _pNode->count() == 3
&& SQL_ISPUNCTUATION(_pNode->getChild(0),"(")
&& SQL_ISPUNCTUATION(_pNode->getChild(2),")") ) // '(' joined_table ')'
pJoinNode = _pNode->getChild(1);
else if (! ( SQL_ISRULE(_pNode, table_ref) && _pNode->count() == 2) ) // table_node table_primary_as_range_column
bRet = sal_False;
if (pJoinNode && !InsertJoin(_pView,pJoinNode))
bRet = sal_False;
return bRet;
}
//-----------------------------------------------------------------------------
sal_Bool InsertJoin(const OQueryDesignView* _pView,
const ::connectivity::OSQLParseNode *pNode)
{
DBG_ASSERT( SQL_ISRULE( pNode, qualified_join ) || SQL_ISRULE( pNode, joined_table ) || SQL_ISRULE( pNode, cross_union ),
"OQueryDesignView::InsertJoin: Fehler im Parse Tree");
if (SQL_ISRULE(pNode,joined_table))
return InsertJoin(_pView,pNode->getChild(1));
// first check the left and right side
const ::connectivity::OSQLParseNode* pRightTableRef = pNode->getChild(3); // table_ref
if ( SQL_ISRULE(pNode, qualified_join) && SQL_ISTOKEN(pNode->getChild(1),NATURAL) )
pRightTableRef = pNode->getChild(4); // table_ref
if ( !checkJoinConditions(_pView,pNode->getChild(0)) || !checkJoinConditions(_pView,pRightTableRef))
return sal_False;
// named column join wird sp<73>ter vieleicht noch implementiert
// SQL_ISRULE(pNode->getChild(4),named_columns_join)
EJoinType eJoinType = INNER_JOIN;
bool bNatural = false;
if ( SQL_ISRULE(pNode, qualified_join) )
{
::connectivity::OSQLParseNode* pJoinType = pNode->getChild(1); // join_type
if ( SQL_ISTOKEN(pJoinType,NATURAL) )
{
bNatural = true;
pJoinType = pNode->getChild(2);
}
if (SQL_ISRULE(pJoinType,join_type) && SQL_ISTOKEN(pJoinType->getChild(0),INNER))
{
eJoinType = INNER_JOIN;
}
else
{
if (SQL_ISRULE(pJoinType,join_type)) // eine Ebene tiefer
pJoinType = pJoinType->getChild(0);
if (SQL_ISTOKEN(pJoinType->getChild(0),LEFT))
eJoinType = LEFT_JOIN;
else if(SQL_ISTOKEN(pJoinType->getChild(0),RIGHT))
eJoinType = RIGHT_JOIN;
else
eJoinType = FULL_JOIN;
}
if ( SQL_ISRULE(pNode->getChild(4),join_condition) )
{
if ( InsertJoinConnection(_pView,pNode->getChild(4)->getChild(1), eJoinType) != eOk )
return sal_False;
}
}
else if ( SQL_ISRULE(pNode, cross_union) )
{
eJoinType = CROSS_JOIN;
pRightTableRef = pNode->getChild(pNode->count() - 1);
}
else
return sal_False;
if ( eJoinType == CROSS_JOIN || bNatural )
{
OQueryTableWindow* pLeftWindow = static_cast<OQueryTableView*>(_pView->getTableView())->FindTable( getTableRange(_pView,pNode->getChild(0)) );
OQueryTableWindow* pRightWindow = static_cast<OQueryTableView*>(_pView->getTableView())->FindTable( getTableRange(_pView,pRightTableRef) );
OSL_ENSURE(pLeftWindow && pRightWindow,"Table Windows could not be found!");
if ( !pLeftWindow || !pRightWindow )
return sal_False;
OTableFieldDescRef aDragLeft = new OTableFieldDesc();
aDragLeft->SetTabWindow(pLeftWindow);
aDragLeft->SetTable(pLeftWindow->GetTableName());
aDragLeft->SetAlias(pLeftWindow->GetAliasName());
OTableFieldDescRef aDragRight = new OTableFieldDesc();
aDragRight->SetTabWindow(pRightWindow);
aDragRight->SetTable(pRightWindow->GetTableName());
aDragRight->SetAlias(pRightWindow->GetAliasName());
insertConnection(_pView,eJoinType,aDragLeft,aDragRight,bNatural);
}
return sal_True;
}
//------------------------------------------------------------------------------
void insertUnUsedFields(OQueryDesignView* _pView,OSelectionBrowseBox* _pSelectionBrw)
{
// now we have to insert the fields which aren't in the statement
OQueryController& rController = static_cast<OQueryController&>(_pView->getController());
OTableFields& rUnUsedFields = rController.getUnUsedFields();
OTableFields::iterator aEnd = rUnUsedFields.end();
for(OTableFields::iterator aIter = rUnUsedFields.begin();aIter != aEnd;++aIter)
if(_pSelectionBrw->InsertField(*aIter,BROWSER_INVALIDID,sal_False,sal_False).isValid())
(*aIter) = NULL;
OTableFields().swap( rUnUsedFields );
}
//------------------------------------------------------------------------------
SqlParseError InitFromParseNodeImpl(OQueryDesignView* _pView,OSelectionBrowseBox* _pSelectionBrw)
{
SqlParseError eErrorCode = eOk;
OQueryController& rController = static_cast<OQueryController&>(_pView->getController());
_pSelectionBrw->PreFill();
_pSelectionBrw->SetReadOnly(rController.isReadOnly());
_pSelectionBrw->Fill();
::connectivity::OSQLParseTreeIterator& aIterator = rController.getParseIterator();
const ::connectivity::OSQLParseNode* pParseTree = aIterator.getParseTree();
do
{
if ( !pParseTree )
{
// now we have to insert the fields which aren't in the statement
insertUnUsedFields(_pView,_pSelectionBrw);
break;
}
if ( !rController.isEsacpeProcessing() ) // not allowed in this mode
{
eErrorCode = eNativeMode;
break;
}
if ( !( SQL_ISRULE( pParseTree, select_statement ) ) )
{
eErrorCode = eNoSelectStatement;
break;
}
Reference< XConnection> xConnection = rController.getConnection();
if ( !xConnection.is() )
{
DBG_ERROR( "InitFromParseNodeImpl: no connection? no connection!" );
break;
}
const OSQLTables& aMap = aIterator.getTables();
::comphelper::UStringMixLess aTmp(aMap.key_comp());
::comphelper::UStringMixEqual aKeyComp( aTmp.isCaseSensitive() );
Reference< XDatabaseMetaData > xMetaData = xConnection->getMetaData();
try
{
sal_Int32 nMax = xMetaData->getMaxTablesInSelect();
if ( nMax && nMax < (sal_Int32)aMap.size() )
{
eErrorCode = eTooManyTables;
break;
}
::rtl::OUString sComposedName;
::rtl::OUString aQualifierName;
::rtl::OUString sAlias;
OQueryTableView* pTableView = static_cast<OQueryTableView*>(_pView->getTableView());
pTableView->clearLayoutInformation();
OSQLTables::const_iterator aIter = aMap.begin();
OSQLTables::const_iterator aEnd = aMap.end();
for(;aIter != aEnd;++aIter)
{
OSQLTable xTable = aIter->second;
Reference< XPropertySet > xTableProps( xTable, UNO_QUERY_THROW );
sAlias = aIter->first;
// check whether this is a query
Reference< XPropertySetInfo > xPSI = xTableProps->getPropertySetInfo();
bool bIsQuery = xPSI.is() && xPSI->hasPropertyByName( PROPERTY_COMMAND );
if ( bIsQuery )
OSL_VERIFY( xTableProps->getPropertyValue( PROPERTY_NAME ) >>= sComposedName );
else
{
sComposedName = ::dbtools::composeTableName( xMetaData, xTableProps, ::dbtools::eInDataManipulation, false, false, false );
// if the alias is the complete (composed) table, then shorten it
if ( aKeyComp( sComposedName, aIter->first ) )
{
::rtl::OUString sCatalog, sSchema, sTable;
::dbtools::qualifiedNameComponents( xMetaData, sComposedName, sCatalog, sSchema, sTable, ::dbtools::eInDataManipulation );
sAlias = sTable;
}
}
// find the existent window for this alias
OQueryTableWindow* pExistentWin = pTableView->FindTable( sAlias );
if ( !pExistentWin )
{
pTableView->AddTabWin( sComposedName, sAlias, sal_False ); // don't create data here
}
else
{
// there already exists a window for this alias ....
if ( !aKeyComp( pExistentWin->GetData()->GetComposedName(), sComposedName ) )
// ... but for another complete table name -> new window
pTableView->AddTabWin(sComposedName, sAlias);
}
}
// now delete the data for which we haven't any tablewindow
OJoinTableView::OTableWindowMap aTableMap(*pTableView->GetTabWinMap());
OJoinTableView::OTableWindowMap::iterator aIterTableMap = aTableMap.begin();
OJoinTableView::OTableWindowMap::iterator aIterTableEnd = aTableMap.end();
for(;aIterTableMap != aIterTableEnd;++aIterTableMap)
{
if(aMap.find(aIterTableMap->second->GetComposedName()) == aMap.end() &&
aMap.find(aIterTableMap->first) == aMap.end())
pTableView->RemoveTabWin(aIterTableMap->second);
}
if ( eOk == (eErrorCode = FillOuterJoins(_pView,pParseTree->getChild(3)->getChild(0)->getChild(1))) )
{
// check if we have a distinct statement
if(SQL_ISTOKEN(pParseTree->getChild(1),DISTINCT))
{
rController.setDistinct(sal_True);
rController.InvalidateFeature(SID_QUERY_DISTINCT_VALUES);
}
if ( (eErrorCode = InstallFields(_pView,pParseTree, pTableView->GetTabWinMap())) == eOk )
{
// GetSelectionCriteria must be called before GetHavingCriteria
sal_uInt16 nLevel=0;
if ( eOk == (eErrorCode = GetSelectionCriteria(_pView,_pSelectionBrw,pParseTree,nLevel)) )
{
if ( eOk == (eErrorCode = GetGroupCriteria(_pView,_pSelectionBrw,pParseTree)) )
{
if ( eOk == (eErrorCode = GetHavingCriteria(_pView,_pSelectionBrw,pParseTree,nLevel)) )
{
if ( eOk == (eErrorCode = GetOrderCriteria(_pView,_pSelectionBrw,pParseTree)) )
insertUnUsedFields(_pView,_pSelectionBrw);
}
}
}
}
}
}
catch(SQLException&)
{
OSL_ASSERT(!"getMaxTablesInSelect!");
}
}
while ( false );
// Durch das Neuerzeugen wurden wieder Undo-Actions in den Manager gestellt
rController.getUndoMgr()->Clear();
_pSelectionBrw->Invalidate();
return eErrorCode;
}
//------------------------------------------------------------------------------
/** fillSelectSubList
@return
<TRUE/> when columns could be inserted otherwise <FALSE/>
*/
//------------------------------------------------------------------------------
SqlParseError fillSelectSubList( OQueryDesignView* _pView,
OJoinTableView::OTableWindowMap* _pTabList)
{
SqlParseError eErrorCode = eOk;
sal_Bool bFirstField = sal_True;
::rtl::OUString sAsterix(RTL_CONSTASCII_USTRINGPARAM("*"));
OJoinTableView::OTableWindowMap::iterator aIter = _pTabList->begin();
OJoinTableView::OTableWindowMap::iterator aEnd = _pTabList->end();
for(;aIter != aEnd && eOk == eErrorCode ;++aIter)
{
OQueryTableWindow* pTabWin = static_cast<OQueryTableWindow*>(aIter->second);
OTableFieldDescRef aInfo = new OTableFieldDesc();
if (pTabWin->ExistsField( sAsterix, aInfo ))
{
eErrorCode = _pView->InsertField(aInfo, sal_True, bFirstField);
bFirstField = sal_False;
}
}
return eErrorCode;
}
//------------------------------------------------------------------------------
void fillFunctionInfo( OQueryDesignView* _pView
,const ::connectivity::OSQLParseNode* pNode
,const ::rtl::OUString& sFunctionTerm
,OTableFieldDescRef& aInfo)
{
// get the type out of the funtion name
OQueryController& rController = static_cast<OQueryController&>(_pView->getController());
sal_Int32 nDataType = DataType::DOUBLE;
::rtl::OUString sFieldName = sFunctionTerm;
OSQLParseNode* pFunctionName = pNode->getChild(0);
if ( !SQL_ISPUNCTUATION(pFunctionName,"{") )
{
if ( SQL_ISRULEOR2(pNode,length_exp,char_value_fct) )
pFunctionName = pFunctionName->getChild(0);
::rtl::OUString sFunctionName = pFunctionName->getTokenValue();
if ( !sFunctionName.getLength() )
sFunctionName = ::rtl::OStringToOUString(OSQLParser::TokenIDToStr(pFunctionName->getTokenID()),RTL_TEXTENCODING_UTF8);
nDataType = OSQLParser::getFunctionReturnType(
sFunctionName
,&rController.getParser().getContext());
}
aInfo->SetDataType(nDataType);
aInfo->SetFieldType(TAB_NORMAL_FIELD);
aInfo->SetField(sFieldName);
aInfo->SetTabWindow(NULL);
}
//------------------------------------------------------------------------------
SqlParseError InstallFields(OQueryDesignView* _pView,
const ::connectivity::OSQLParseNode* pNode,
OJoinTableView::OTableWindowMap* pTabList )
{
if( pNode==0 || !SQL_ISRULE(pNode,select_statement))
return eNoSelectStatement;
::connectivity::OSQLParseNode* pParseTree = pNode->getChild(2);
sal_Bool bFirstField = sal_True; // bei der Initialisierung mu<6D> auf alle Faelle das erste Feld neu aktiviert werden
SqlParseError eErrorCode = eOk;
if ( pParseTree->isRule() && SQL_ISPUNCTUATION(pParseTree->getChild(0),"*") )
{
// SELECT * ...
eErrorCode = fillSelectSubList(_pView,pTabList);
}
else if (SQL_ISRULE(pParseTree,scalar_exp_commalist) )
{
// SELECT column, ...
OQueryController& rController = static_cast<OQueryController&>(_pView->getController());
Reference< XConnection> xConnection = rController.getConnection();
::rtl::OUString aColumnName,aTableRange;
for (sal_uInt32 i = 0; i < pParseTree->count() && eOk == eErrorCode ; ++i)
{
::connectivity::OSQLParseNode * pColumnRef = pParseTree->getChild(i);
do {
if ( SQL_ISRULE(pColumnRef,select_sublist) )
{
eErrorCode = fillSelectSubList(_pView,pTabList);
break;
}
if ( SQL_ISRULE(pColumnRef,derived_column) )
{
if ( !xConnection.is() )
break;
::rtl::OUString aColumnAlias(rController.getParseIterator().getColumnAlias(pColumnRef)); // kann leer sein
pColumnRef = pColumnRef->getChild(0);
OTableFieldDescRef aInfo = new OTableFieldDesc();
if ( pColumnRef->count() == 3 &&
SQL_ISPUNCTUATION(pColumnRef->getChild(0),"(") &&
SQL_ISPUNCTUATION(pColumnRef->getChild(2),")")
)
pColumnRef = pColumnRef->getChild(1);
if (SQL_ISRULE(pColumnRef,column_ref))
{
InsertColumnRef(_pView,pColumnRef,aColumnName,aColumnAlias,aTableRange,aInfo,pTabList);
eErrorCode = _pView->InsertField(aInfo, sal_True, bFirstField);
bFirstField = sal_False;
}
else if(SQL_ISRULEOR2(pColumnRef,general_set_fct ,set_fct_spec) ||
SQL_ISRULEOR2(pColumnRef,position_exp,extract_exp) ||
SQL_ISRULEOR2(pColumnRef,fold,char_substring_fct) ||
SQL_ISRULEOR2(pColumnRef,length_exp,char_value_fct))
{
::rtl::OUString aColumns;
pColumnRef->parseNodeToStr( aColumns,
xConnection,
&rController.getParser().getContext(),
sal_True,
sal_True); // quote is to true because we need quoted elements inside the function
sal_Int32 nFunctionType = FKT_NONE;
::connectivity::OSQLParseNode* pParamRef = NULL;
sal_Int32 nColumnRefPos = pColumnRef->count() - 2;
if ( nColumnRefPos >= 0 && static_cast<sal_uInt32>(nColumnRefPos) < pColumnRef->count() )
pParamRef = pColumnRef->getChild(nColumnRefPos);
if ( SQL_ISRULE(pColumnRef,general_set_fct)
&& SQL_ISRULE(pParamRef,column_ref) )
{
// Parameter auf Columnref pr"ufen
InsertColumnRef(_pView,pParamRef,aColumnName,aColumnAlias,aTableRange,aInfo,pTabList);
}
else if ( SQL_ISRULE(pColumnRef,general_set_fct) )
{
if ( pParamRef && pParamRef->getTokenValue().toChar() == '*' )
{
OJoinTableView::OTableWindowMap::iterator aIter = pTabList->begin();
OJoinTableView::OTableWindowMap::iterator aEnd = pTabList->end();
for(;aIter != aEnd;++aIter)
{
OQueryTableWindow* pTabWin = static_cast<OQueryTableWindow*>(aIter->second);
if (pTabWin->ExistsField( ::rtl::OUString::createFromAscii("*"), aInfo ))
{
aInfo->SetAlias(String());
aInfo->SetTable(String());
break;
}
}
}
else
{
::rtl::OUString sFieldName = aColumns;
if ( pParamRef )
{ // we got an aggregate function but without column name inside
// so we set the whole argument of the function as field name
nFunctionType |= FKT_NUMERIC;
sFieldName = ::rtl::OUString();
pParamRef->parseNodeToStr( sFieldName,
xConnection,
&rController.getParser().getContext(),
sal_True,
sal_True); // quote is to true because we need quoted elements inside the function
}
aInfo->SetDataType(DataType::DOUBLE);
aInfo->SetFieldType(TAB_NORMAL_FIELD);
aInfo->SetField(sFieldName);
}
aInfo->SetTabWindow(NULL);
aInfo->SetFieldAlias(aColumnAlias);
}
else
{
fillFunctionInfo(_pView,pColumnRef,aColumns,aInfo);
aInfo->SetFieldAlias(aColumnAlias);
}
if ( SQL_ISRULE(pColumnRef,general_set_fct) )
{
aInfo->SetFunctionType(nFunctionType|FKT_AGGREGATE);
String aCol(aColumns);
aInfo->SetFunction(aCol.GetToken(0,'(').EraseTrailingChars(' '));
}
else
aInfo->SetFunctionType(nFunctionType|FKT_OTHER);
eErrorCode = _pView->InsertField(aInfo, sal_True, bFirstField);
bFirstField = sal_False;
}
else //if(SQL_ISRULE(pColumnRef,num_value_exp) || SQL_ISRULE(pColumnRef,term))
{
::rtl::OUString aColumns;
pColumnRef->parseNodeToStr( aColumns,
xConnection,
&rController.getParser().getContext(),
sal_True,
sal_True); // quote is to true because we need quoted elements inside the function
aInfo->SetTabWindow( NULL );
// since we support queries in queries, the thingie might belong to an existing "table"
OQueryTableWindow* pExistingTable = lcl_findColumnInTables( aColumns, *pTabList, aInfo );
if ( pExistingTable )
{
aInfo->SetTabWindow( pExistingTable );
aInfo->SetTable( pExistingTable->GetTableName() );
aInfo->SetAlias( pExistingTable->GetAliasName() );
}
aInfo->SetDataType(DataType::DOUBLE);
aInfo->SetFieldType(TAB_NORMAL_FIELD);
aInfo->SetField(aColumns);
aInfo->SetFieldAlias(aColumnAlias);
aInfo->SetFunctionType(FKT_NUMERIC | FKT_OTHER);
eErrorCode = _pView->InsertField(aInfo, sal_True, bFirstField);
bFirstField = sal_False;
}
break;
}
DBG_ERROR( "InstallFields: don't know how to interpret this parse node!" );
} while ( false );
}
}
else
eErrorCode = eStatementTooComplex;
return eErrorCode;
}
//------------------------------------------------------------------------------
SqlParseError GetOrderCriteria( OQueryDesignView* _pView,
OSelectionBrowseBox* _pSelectionBrw,
const ::connectivity::OSQLParseNode* pParseRoot )
{
SqlParseError eErrorCode = eOk;
if (!pParseRoot->getChild(3)->getChild(4)->isLeaf())
{
::connectivity::OSQLParseNode* pNode = pParseRoot->getChild(3)->getChild(4)->getChild(2);
::connectivity::OSQLParseNode* pParamRef = NULL;
OQueryController& rController = static_cast<OQueryController&>(_pView->getController());
EOrderDir eOrderDir;
OTableFieldDescRef aDragLeft = new OTableFieldDesc();
for( sal_uInt32 i=0 ; i<pNode->count() ; i++ )
{
eOrderDir = ORDER_ASC;
::connectivity::OSQLParseNode* pChild = pNode->getChild( i );
if (SQL_ISTOKEN( pChild->getChild(1), DESC ) )
eOrderDir = ORDER_DESC;
::connectivity::OSQLParseNode* pArgument = pChild->getChild(0);
if(SQL_ISRULE(pArgument,column_ref))
{
if( eOk == FillDragInfo(_pView,pArgument,aDragLeft))
_pSelectionBrw->AddOrder( aDragLeft, eOrderDir, i);
else // it could be a alias name for a field
{
::rtl::OUString aTableRange,aColumnName;
::connectivity::OSQLParseTreeIterator& rParseIter = rController.getParseIterator();
rParseIter.getColumnRange( pArgument, aColumnName, aTableRange );
OTableFields& aList = rController.getTableFieldDesc();
OTableFields::iterator aIter = aList.begin();
OTableFields::iterator aEnd = aList.end();
for(;aIter != aEnd;++aIter)
{
OTableFieldDescRef pEntry = *aIter;
if(pEntry.isValid() && pEntry->GetFieldAlias() == aColumnName)
pEntry->SetOrderDir( eOrderDir );
}
}
}
else if(SQL_ISRULE(pArgument, general_set_fct ) &&
SQL_ISRULE(pParamRef = pArgument->getChild(pArgument->count()-2),column_ref) &&
eOk == FillDragInfo(_pView,pParamRef,aDragLeft))
_pSelectionBrw->AddOrder( aDragLeft, eOrderDir, i );
else if( SQL_ISRULE(pArgument, set_fct_spec ) )
{
Reference< XConnection> xConnection = rController.getConnection();
if(xConnection.is())
{
::rtl::OUString sCondition;
pArgument->parseNodeToPredicateStr(sCondition,
xConnection,
rController.getNumberFormatter(),
_pView->getLocale(),
static_cast<sal_Char>(_pView->getDecimalSeparator().toChar()),
&rController.getParser().getContext());
fillFunctionInfo(_pView,pArgument,sCondition,aDragLeft);
aDragLeft->SetFunctionType(FKT_OTHER);
aDragLeft->SetOrderDir(eOrderDir);
aDragLeft->SetVisible(sal_False);
_pSelectionBrw->AddOrder( aDragLeft, eOrderDir, i );
}
else
eErrorCode = eColumnNotFound;
}
else
eErrorCode = eColumnNotFound;
}
}
return eErrorCode;
}
//------------------------------------------------------------------------------
SqlParseError GetHavingCriteria( OQueryDesignView* _pView,
OSelectionBrowseBox* _pSelectionBrw,
const ::connectivity::OSQLParseNode* pSelectRoot,
sal_uInt16& rLevel )
{
SqlParseError eErrorCode = eOk;
if (!pSelectRoot->getChild(3)->getChild(3)->isLeaf())
eErrorCode = GetORCriteria(_pView,_pSelectionBrw,pSelectRoot->getChild(3)->getChild(3)->getChild(1),rLevel, sal_True);
return eErrorCode;
}
//------------------------------------------------------------------------------
SqlParseError GetGroupCriteria( OQueryDesignView* _pView,
OSelectionBrowseBox* _pSelectionBrw,
const ::connectivity::OSQLParseNode* pSelectRoot )
{
SqlParseError eErrorCode = eOk;
if (!pSelectRoot->getChild(3)->getChild(2)->isLeaf())
{
OQueryController& rController = static_cast<OQueryController&>(_pView->getController());
::connectivity::OSQLParseNode* pGroupBy = pSelectRoot->getChild(3)->getChild(2)->getChild(2);
OTableFieldDescRef aDragInfo = new OTableFieldDesc();
for( sal_uInt32 i=0 ; i < pGroupBy->count() && eOk == eErrorCode; ++i )
{
::connectivity::OSQLParseNode* pParamRef = NULL;
::connectivity::OSQLParseNode* pArgument = pGroupBy->getChild( i );
if(SQL_ISRULE(pArgument,column_ref))
{
if ( eOk == (eErrorCode = FillDragInfo(_pView,pArgument,aDragInfo)) )
{
aDragInfo->SetGroupBy(sal_True);
_pSelectionBrw->AddGroupBy(aDragInfo,i);
}
}
else if(SQL_ISRULE(pArgument, general_set_fct ) &&
SQL_ISRULE(pParamRef = pArgument->getChild(pArgument->count()-2),column_ref) &&
eOk == FillDragInfo(_pView,pParamRef,aDragInfo))
{
aDragInfo->SetGroupBy(sal_True);
_pSelectionBrw->AddGroupBy( aDragInfo, i );
}
else if( SQL_ISRULE(pArgument, set_fct_spec ) )
{
Reference< XConnection> xConnection = rController.getConnection();
if(xConnection.is())
{
::rtl::OUString sGroupByExpression;
pArgument->parseNodeToStr( sGroupByExpression,
xConnection,
&rController.getParser().getContext(),
sal_True,
sal_True); // quote is to true because we need quoted elements inside the function
fillFunctionInfo(_pView,pArgument,sGroupByExpression,aDragInfo);
aDragInfo->SetFunctionType(FKT_OTHER);
aDragInfo->SetGroupBy(sal_True);
aDragInfo->SetVisible(sal_False);
_pSelectionBrw->AddGroupBy( aDragInfo, i );
}
else
eErrorCode = eColumnNotFound;
}
}
}
return eErrorCode;
}
//------------------------------------------------------------------------------
String getParseErrorMessage( SqlParseError _eErrorCode )
{
USHORT nResId;
switch(_eErrorCode)
{
case eIllegalJoin:
nResId = STR_QRY_ILLEGAL_JOIN;
break;
case eStatementTooLong:
nResId = STR_QRY_TOO_LONG_STATEMENT;
break;
case eNoConnection:
nResId = STR_QRY_SYNTAX;
break;
case eNoSelectStatement:
nResId = STR_QRY_NOSELECT;
break;
case eColumnInLikeNotFound:
nResId = STR_QRY_SYNTAX;
break;
case eNoColumnInLike:
nResId = STR_QRY_SYNTAX;
break;
case eColumnNotFound:
nResId = STR_QRY_SYNTAX;
break;
case eNativeMode:
nResId = STR_QRY_NATIVE;
break;
case eTooManyTables:
nResId = STR_QRY_TOO_MANY_TABLES;
break;
case eTooManyConditions:
nResId = STR_QRY_TOOMANYCOND;
break;
case eTooManyColumns:
nResId = STR_QRY_TOO_MANY_COLUMNS;
break;
case eStatementTooComplex:
nResId = STR_QRY_TOOCOMPLEX;
break;
default:
nResId = STR_QRY_SYNTAX;
break;
}
;
return String( ModuleRes( nResId ) );
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
}
// end of anonymouse namespace
DBG_NAME(OQueryDesignView)
OQueryDesignView::OQueryDesignView( OQueryContainerWindow* _pParent,
OQueryController& _rController,
const Reference< XMultiServiceFactory >& _rFactory)
:OQueryView( _pParent, _rController, _rFactory )
,m_aSplitter( this )
,m_eChildFocus(NONE)
,m_bInKeyEvent(sal_False)
,m_bInSplitHandler( sal_False )
{
DBG_CTOR(OQueryDesignView,NULL);
try
{
SvtSysLocale aSysLocale;
m_aLocale = aSysLocale.GetLocaleData().getLocale();
m_sDecimalSep = aSysLocale.GetLocaleData().getNumDecimalSep();
}
catch(Exception&)
{
}
m_pSelectionBox = new OSelectionBrowseBox(this);
setNoneVisbleRow(static_cast<OQueryController&>(getController()).getVisibleRows());
m_pSelectionBox->Show();
// Splitter einrichten
m_aSplitter.SetSplitHdl(LINK(this, OQueryDesignView,SplitHdl));
m_aSplitter.Show();
}
// -----------------------------------------------------------------------------
OQueryDesignView::~OQueryDesignView()
{
if ( m_pTableView )
::dbaui::notifySystemWindow(this,m_pTableView,::comphelper::mem_fun(&TaskPaneList::RemoveWindow));
::std::auto_ptr<Window> aTemp(m_pSelectionBox);
m_pSelectionBox = NULL;
DBG_DTOR(OQueryDesignView,NULL);
}
//------------------------------------------------------------------------------
IMPL_LINK( OQueryDesignView, SplitHdl, void*, /*p*/ )
{
if (!getController().isReadOnly())
{
m_bInSplitHandler = sal_True;
m_aSplitter.SetPosPixel( Point( m_aSplitter.GetPosPixel().X(),m_aSplitter.GetSplitPosPixel() ) );
static_cast<OQueryController&>(getController()).setSplitPos(m_aSplitter.GetSplitPosPixel());
static_cast<OQueryController&>(getController()).setModified();
Resize();
m_bInSplitHandler = sal_True;
}
return 0L;
}
// -------------------------------------------------------------------------
void OQueryDesignView::Construct()
{
m_pTableView = new OQueryTableView(m_pScrollWindow,this);
::dbaui::notifySystemWindow(this,m_pTableView,::comphelper::mem_fun(&TaskPaneList::AddWindow));
OQueryView::Construct();
}
// -----------------------------------------------------------------------------
void OQueryDesignView::initialize()
{
if(static_cast<OQueryController&>(getController()).getSplitPos() != -1)
{
m_aSplitter.SetPosPixel( Point( m_aSplitter.GetPosPixel().X(),static_cast<OQueryController&>(getController()).getSplitPos() ) );
m_aSplitter.SetSplitPosPixel(static_cast<OQueryController&>(getController()).getSplitPos());
}
m_pSelectionBox->initialize();
reset();
}
// -------------------------------------------------------------------------
void OQueryDesignView::resizeDocumentView(Rectangle& _rPlayground)
{
Point aPlaygroundPos( _rPlayground.TopLeft() );
Size aPlaygroundSize( _rPlayground.GetSize() );
// calc the split pos, and forward it to the controller
sal_Int32 nSplitPos = static_cast<OQueryController&>(getController()).getSplitPos();
if ( 0 != aPlaygroundSize.Height() )
{
if ( ( -1 == nSplitPos )
|| ( nSplitPos >= aPlaygroundSize.Height() )
)
{
// let the selection browse box determine an optimal size
Size aSelectionBoxSize = m_pSelectionBox->CalcOptimalSize( aPlaygroundSize );
nSplitPos = aPlaygroundSize.Height() - aSelectionBoxSize.Height() - m_aSplitter.GetSizePixel().Height();
// still an invalid size?
if ( nSplitPos == -1 || nSplitPos >= aPlaygroundSize.Height() )
nSplitPos = sal_Int32(aPlaygroundSize.Height()*0.6);
static_cast<OQueryController&>(getController()).setSplitPos(nSplitPos);
}
if ( !m_bInSplitHandler )
{ // the resize is triggered by something else than the split handler
// our main focus is to try to preserve the size of the selectionbrowse box
Size aSelBoxSize = m_pSelectionBox->GetSizePixel();
if ( aSelBoxSize.Height() )
{
// keep the size of the sel box constant
nSplitPos = aPlaygroundSize.Height() - m_aSplitter.GetSizePixel().Height() - aSelBoxSize.Height();
// and if the box is smaller than the optimal size, try to do something about it
Size aSelBoxOptSize = m_pSelectionBox->CalcOptimalSize( aPlaygroundSize );
if ( aSelBoxOptSize.Height() > aSelBoxSize.Height() )
{
nSplitPos = aPlaygroundSize.Height() - m_aSplitter.GetSizePixel().Height() - aSelBoxOptSize.Height();
}
static_cast< OQueryController& >(getController()).setSplitPos( nSplitPos );
}
}
}
// normalize the split pos
Point aSplitPos = Point( _rPlayground.Left(), nSplitPos );
Size aSplitSize = Size( _rPlayground.GetSize().Width(), m_aSplitter.GetSizePixel().Height() );
if( ( aSplitPos.Y() + aSplitSize.Height() ) > ( aPlaygroundSize.Height() ))
aSplitPos.Y() = aPlaygroundSize.Height() - aSplitSize.Height();
if( aSplitPos.Y() <= aPlaygroundPos.Y() )
aSplitPos.Y() = aPlaygroundPos.Y() + sal_Int32(aPlaygroundSize.Height() * 0.2);
// position the table
Size aTableViewSize(aPlaygroundSize.Width(), aSplitPos.Y() - aPlaygroundPos.Y());
m_pScrollWindow->SetPosSizePixel(aPlaygroundPos, aTableViewSize);
// position the selection browse box
Point aPos( aPlaygroundPos.X(), aSplitPos.Y() + aSplitSize.Height() );
m_pSelectionBox->SetPosSizePixel( aPos, Size( aPlaygroundSize.Width(), aPlaygroundSize.Height() - aSplitSize.Height() - aTableViewSize.Height() ));
// set the size of the splitter
m_aSplitter.SetPosSizePixel( aSplitPos, aSplitSize );
m_aSplitter.SetDragRectPixel( _rPlayground );
// just for completeness: there is no space left, we occupied it all ...
_rPlayground.SetPos( _rPlayground.BottomRight() );
_rPlayground.SetSize( Size( 0, 0 ) );
}
// -----------------------------------------------------------------------------
void OQueryDesignView::setReadOnly(sal_Bool _bReadOnly)
{
m_pSelectionBox->SetReadOnly(_bReadOnly);
}
// -----------------------------------------------------------------------------
void OQueryDesignView::clear()
{
m_pSelectionBox->ClearAll(); // clear the whole selection
m_pTableView->ClearAll();
}
// -----------------------------------------------------------------------------
void OQueryDesignView::setStatement(const ::rtl::OUString& /*_rsStatement*/)
{
}
// -----------------------------------------------------------------------------
void OQueryDesignView::copy()
{
if( m_eChildFocus == SELECTION)
m_pSelectionBox->copy();
}
// -----------------------------------------------------------------------------
sal_Bool OQueryDesignView::isCutAllowed()
{
sal_Bool bAllowed = sal_False;
if ( SELECTION == m_eChildFocus )
bAllowed = m_pSelectionBox->isCutAllowed();
return bAllowed;
}
// -----------------------------------------------------------------------------
sal_Bool OQueryDesignView::isPasteAllowed()
{
sal_Bool bAllowed = sal_False;
if ( SELECTION == m_eChildFocus )
bAllowed = m_pSelectionBox->isPasteAllowed();
return bAllowed;
}
// -----------------------------------------------------------------------------
sal_Bool OQueryDesignView::isCopyAllowed()
{
sal_Bool bAllowed = sal_False;
if ( SELECTION == m_eChildFocus )
bAllowed = m_pSelectionBox->isCopyAllowed();
return bAllowed;
}
// -----------------------------------------------------------------------------
void OQueryDesignView::stopTimer()
{
m_pSelectionBox->stopTimer();
}
// -----------------------------------------------------------------------------
void OQueryDesignView::startTimer()
{
m_pSelectionBox->startTimer();
}
// -----------------------------------------------------------------------------
void OQueryDesignView::cut()
{
if( m_eChildFocus == SELECTION)
{
m_pSelectionBox->cut();
static_cast<OQueryController&>(getController()).setModified(sal_True);
}
}
// -----------------------------------------------------------------------------
void OQueryDesignView::paste()
{
if( m_eChildFocus == SELECTION)
{
m_pSelectionBox->paste();
static_cast<OQueryController&>(getController()).setModified(sal_True);
}
}
// -----------------------------------------------------------------------------
void OQueryDesignView::TableDeleted(const ::rtl::OUString& rAliasName)
{
// Nachricht, dass Tabelle aus dem Fenster gel"oscht wurde
DeleteFields(rAliasName);
static_cast<OQueryController&>(getController()).InvalidateFeature(ID_BROWSER_ADDTABLE); // view nochmal bescheid sagen
}
//------------------------------------------------------------------------------
void OQueryDesignView::DeleteFields( const ::rtl::OUString& rAliasName )
{
m_pSelectionBox->DeleteFields( rAliasName );
}
// -----------------------------------------------------------------------------
bool OQueryDesignView::HasFieldByAliasName(const ::rtl::OUString& rFieldName, OTableFieldDescRef& rInfo) const
{
return m_pSelectionBox->HasFieldByAliasName( rFieldName, rInfo);
}
// -----------------------------------------------------------------------------
SqlParseError OQueryDesignView::InsertField( const OTableFieldDescRef& rInfo, sal_Bool bVis, sal_Bool bActivate)
{
return m_pSelectionBox->InsertField( rInfo, BROWSER_INVALIDID,bVis, bActivate ).isValid() ? eOk : eTooManyColumns;
}
// -----------------------------------------------------------------------------
sal_Int32 OQueryDesignView::getColWidth(sal_uInt16 _nColPos) const
{
static sal_Int32 s_nDefaultWidth = GetTextWidth(String(RTL_CONSTASCII_USTRINGPARAM("0"))) * 15;
sal_Int32 nWidth = static_cast<OQueryController&>(getController()).getColWidth(_nColPos);
if ( !nWidth )
nWidth = s_nDefaultWidth;
return nWidth;
}
//------------------------------------------------------------------------------
void OQueryDesignView::fillValidFields(const ::rtl::OUString& sAliasName, ComboBox* pFieldList)
{
DBG_ASSERT(pFieldList != NULL, "OQueryDesignView::FillValidFields : What the hell do you think I can do with a NULL-ptr ? This will crash !");
pFieldList->Clear();
sal_Bool bAllTables = sAliasName.getLength() == 0;
OJoinTableView::OTableWindowMap* pTabWins = m_pTableView->GetTabWinMap();
::rtl::OUString strCurrentPrefix;
::std::vector< ::rtl::OUString> aFields;
OJoinTableView::OTableWindowMap::iterator aIter = pTabWins->begin();
OJoinTableView::OTableWindowMap::iterator aEnd = pTabWins->end();
for(;aIter != aEnd;++aIter)
{
OQueryTableWindow* pCurrentWin = static_cast<OQueryTableWindow*>(aIter->second);
if (bAllTables || (pCurrentWin->GetAliasName() == sAliasName))
{
strCurrentPrefix = pCurrentWin->GetAliasName();
strCurrentPrefix += ::rtl::OUString('.');
pCurrentWin->EnumValidFields(aFields);
::std::vector< ::rtl::OUString>::iterator aStrIter = aFields.begin();
::std::vector< ::rtl::OUString>::iterator aStrEnd = aFields.end();
for(;aStrIter != aStrEnd;++aStrIter)
{
if (bAllTables || aStrIter->toChar() == '*')
pFieldList->InsertEntry(::rtl::OUString(strCurrentPrefix) += *aStrIter);
else
pFieldList->InsertEntry(*aStrIter);
}
if (!bAllTables)
// das heisst, dass ich in diesen Block kam, weil der Tabellenname genau der gesuchte war, also bin ich fertig
// (dadurch verhindere ich auch das doppelte Einfuegen von Feldern, wenn eine Tabelle mehrmals als TabWin vorkommt)
break;
}
}
}
// -----------------------------------------------------------------------------
long OQueryDesignView::PreNotify(NotifyEvent& rNEvt)
{
switch (rNEvt.GetType())
{
case EVENT_GETFOCUS:
#if OSL_DEBUG_LEVEL > 0
{
Window* pFocus = Application::GetFocusWindow();
(void)pFocus;
}
#endif
if ( m_pSelectionBox && m_pSelectionBox->HasChildPathFocus() )
m_eChildFocus = SELECTION;
else
m_eChildFocus = TABLEVIEW;
break;
}
return OQueryView::PreNotify(rNEvt);
}
//------------------------------------------------------------------------------
// -----------------------------------------------------------------------------
// check if the statement is correct when not returning false
sal_Bool OQueryDesignView::checkStatement()
{
sal_Bool bRet = sal_True;
if ( m_pSelectionBox )
bRet = m_pSelectionBox->Save(); // a error occured so we return no
return bRet;
}
//-------------------------------------------------------------------------------
::rtl::OUString OQueryDesignView::getStatement()
{
OQueryController& rController = static_cast<OQueryController&>(getController());
m_rController.clearError();
// used for fields which aren't any longer in the statement
OTableFields& rUnUsedFields = rController.getUnUsedFields();
OTableFields().swap( rUnUsedFields );
// create the select columns
sal_uInt32 nFieldcount = 0;
OTableFields& rFieldList = rController.getTableFieldDesc();
OTableFields::iterator aIter = rFieldList.begin();
OTableFields::iterator aEnd = rFieldList.end();
for(;aIter != aEnd;++aIter)
{
OTableFieldDescRef pEntryField = *aIter;
if ( pEntryField->GetField().getLength() && pEntryField->IsVisible() )
++nFieldcount;
else if (pEntryField->GetField().getLength() &&
!pEntryField->HasCriteria() &&
pEntryField->isNoneFunction() &&
pEntryField->GetOrderDir() == ORDER_NONE &&
!pEntryField->IsGroupBy() &&
!pEntryField->GetFunction().getLength() )
rUnUsedFields.push_back(pEntryField);
}
if ( !nFieldcount ) // keine Felder sichtbar also zur"uck
{
rUnUsedFields = rFieldList;
return ::rtl::OUString();
}
OQueryTableView::OTableWindowMap* pTabList = m_pTableView->GetTabWinMap();
sal_uInt32 nTabcount = pTabList->size();
::rtl::OUString aFieldListStr(GenerateSelectList(this,rFieldList,nTabcount>1));
if( !aFieldListStr.getLength() )
return ::rtl::OUString();
// Ausnahmebehandlung, wenn keine Felder angegeben worden sind
// Dann darf die Tabpage nicht gewechselt werden
// Im TabBarSelectHdl wird der SQL-::rtl::OUString auf STATEMENT_NOFIELDS abgefragt
// und eine Errormeldung erzeugt
// ----------------- Tabellenliste aufbauen ----------------------
const ::std::vector<OTableConnection*>* pConnList = m_pTableView->getTableConnections();
Reference< XConnection> xConnection = rController.getConnection();
::rtl::OUString aTableListStr(GenerateFromClause(xConnection,pTabList,pConnList));
DBG_ASSERT(aTableListStr.getLength(), "OQueryDesignView::getStatement() : unerwartet : habe Felder, aber keine Tabellen !");
// wenn es Felder gibt, koennen die nur durch Einfuegen aus einer schon existenten Tabelle entstanden sein; wenn andererseits
// eine Tabelle geloescht wird, verschwinden auch die zugehoerigen Felder -> ergo KANN es das nicht geben, dass Felder
// existieren, aber keine Tabellen (und aFieldListStr hat schon eine Laenge, das stelle ich oben sicher)
::rtl::OUStringBuffer aHavingStr,aCriteriaListStr;
// ----------------- Kriterien aufbauen ----------------------
if (!GenerateCriterias(this,aCriteriaListStr,aHavingStr,rFieldList, nTabcount > 1))
return ::rtl::OUString();
::rtl::OUString aJoinCrit;
GenerateInnerJoinCriterias(xConnection,aJoinCrit,pConnList);
if(aJoinCrit.getLength())
{
::rtl::OUString aTmp = ::rtl::OUString::createFromAscii("( ");
aTmp += aJoinCrit;
aTmp += ::rtl::OUString::createFromAscii(" )");
if(aCriteriaListStr.getLength())
{
aTmp += C_AND;
aTmp += aCriteriaListStr.makeStringAndClear();
}
aCriteriaListStr = aTmp;
}
// ----------------- Statement aufbauen ----------------------
::rtl::OUStringBuffer aSqlCmd(::rtl::OUString::createFromAscii("SELECT "));
if(static_cast<OQueryController&>(getController()).isDistinct())
aSqlCmd.append(::rtl::OUString::createFromAscii(" DISTINCT "));
aSqlCmd.append(aFieldListStr);
aSqlCmd.append(::rtl::OUString::createFromAscii(" FROM "));
aSqlCmd.append(aTableListStr);
if (aCriteriaListStr.getLength())
{
aSqlCmd.append(::rtl::OUString::createFromAscii(" WHERE "));
aSqlCmd.append(aCriteriaListStr.makeStringAndClear());
}
// ----------------- GroupBy aufbauen und Anh"angen ------------
Reference<XDatabaseMetaData> xMeta;
if ( xConnection.is() )
xMeta = xConnection->getMetaData();
sal_Bool bUseAlias = nTabcount > 1;
if ( xMeta.is() )
bUseAlias = bUseAlias || !xMeta->supportsGroupByUnrelated();
aSqlCmd.append(GenerateGroupBy(this,rFieldList,bUseAlias));
// ----------------- having Anh"angen ------------
if(aHavingStr.getLength())
{
aSqlCmd.append(::rtl::OUString::createFromAscii(" HAVING "));
aSqlCmd.append(aHavingStr.makeStringAndClear());
}
// ----------------- Sortierung aufbauen und Anh"angen ------------
::rtl::OUString sOrder;
SqlParseError eErrorCode = eOk;
if ( (eErrorCode = GenerateOrder(this,rFieldList,nTabcount > 1,sOrder)) == eOk)
aSqlCmd.append(sOrder);
else
{
if ( !m_rController.hasError() )
m_rController.appendError( getParseErrorMessage( eErrorCode ) );
m_rController.displayError();
}
::rtl::OUString sSQL = aSqlCmd.makeStringAndClear();
if ( xConnection.is() )
{
::connectivity::OSQLParser& rParser( rController.getParser() );
::rtl::OUString sErrorMessage;
::std::auto_ptr<OSQLParseNode> pParseNode( rParser.parseTree( sErrorMessage, sSQL, sal_True ) );
if ( pParseNode.get() )
{
OSQLParseNode* pNode = pParseNode->getChild(3)->getChild(1);
if ( pNode->count() > 1 )
{
::connectivity::OSQLParseNode * pCondition = pNode->getChild(1);
if ( pCondition ) // no where clause
{
OSQLParseNode::compress(pCondition);
::rtl::OUString sTemp;
pParseNode->parseNodeToStr(sTemp,xConnection);
sSQL = sTemp;
}
}
}
}
return sSQL;
}
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
void OQueryDesignView::setSlotEnabled(sal_Int32 _nSlotId,sal_Bool _bEnable)
{
sal_uInt16 nRow;
switch (_nSlotId)
{
case SID_QUERY_VIEW_FUNCTIONS:
nRow = BROW_FUNCTION_ROW;
break;
case SID_QUERY_VIEW_TABLES:
nRow = BROW_TABLE_ROW;
break;
case SID_QUERY_VIEW_ALIASES:
nRow = BROW_COLUMNALIAS_ROW;
break;
default:
// ????????????
nRow = 0;
break;
}
m_pSelectionBox->SetRowVisible(nRow,_bEnable);
m_pSelectionBox->Invalidate();
}
// -----------------------------------------------------------------------------
sal_Bool OQueryDesignView::isSlotEnabled(sal_Int32 _nSlotId)
{
sal_uInt16 nRow;
switch (_nSlotId)
{
case SID_QUERY_VIEW_FUNCTIONS:
nRow = BROW_FUNCTION_ROW;
break;
case SID_QUERY_VIEW_TABLES:
nRow = BROW_TABLE_ROW;
break;
case SID_QUERY_VIEW_ALIASES:
nRow = BROW_COLUMNALIAS_ROW;
break;
default:
// ?????????
nRow = 0;
break;
}
return m_pSelectionBox->IsRowVisible(nRow);
}
// -----------------------------------------------------------------------------
void OQueryDesignView::SaveUIConfig()
{
OQueryController& rCtrl = static_cast<OQueryController&>(getController());
rCtrl.SaveTabWinsPosSize( m_pTableView->GetTabWinMap(), m_pScrollWindow->GetHScrollBar()->GetThumbPos(), m_pScrollWindow->GetVScrollBar()->GetThumbPos() );
// rCtrl.SaveTabFieldsWidth( m_pSelectionBox );
rCtrl.setVisibleRows( m_pSelectionBox->GetNoneVisibleRows() );
if ( m_aSplitter.GetSplitPosPixel() != 0 )
rCtrl.setSplitPos( m_aSplitter.GetSplitPosPixel() );
}
// -----------------------------------------------------------------------------
OSQLParseNode* OQueryDesignView::getPredicateTreeFromEntry(OTableFieldDescRef pEntry,
const String& _sCriteria,
::rtl::OUString& _rsErrorMessage,
Reference<XPropertySet>& _rxColumn) const
{
OSL_ENSURE(pEntry.isValid(),"Entry is null!");
if(!pEntry.isValid())
return NULL;
Reference< XConnection> xConnection = static_cast<OQueryController&>(getController()).getConnection();
if(!xConnection.is())
return NULL;
::connectivity::OSQLParser& rParser( static_cast<OQueryController&>(getController()).getParser() );
OQueryTableWindow* pWin = static_cast<OQueryTableWindow*>(pEntry->GetTabWindow());
String sTest(_sCriteria);
// special handling for functions
if ( pEntry->GetFunctionType() & (FKT_OTHER | FKT_AGGREGATE | FKT_NUMERIC) )
{
// we have a function here so we have to distinguish the type of return value
String sFunction;
if ( pEntry->isNumericOrAggreateFunction() )
sFunction = pEntry->GetFunction();
if ( !sFunction.Len() )
sFunction = pEntry->GetField();
if(sFunction.GetTokenCount('(') > 1)
sFunction = sFunction.GetToken(0,'('); // this should be the name of the function
sal_Int32 nType = ::connectivity::OSQLParser::getFunctionReturnType(sFunction,&rParser.getContext());
if ( nType == DataType::OTHER || (!sFunction.Len() && pEntry->isNumericOrAggreateFunction()) )
{
// first try the international version
::rtl::OUString sSql;
sSql += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("SELECT * "));
sSql += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" FROM x WHERE "));
sSql += pEntry->GetField();
sSql += _sCriteria;
::std::auto_ptr<OSQLParseNode> pParseNode( rParser.parseTree( _rsErrorMessage, sSql, sal_True ) );
nType = DataType::DOUBLE;
if ( pParseNode.get() )
{
OSQLParseNode* pColumnRef = pParseNode->getByRule(OSQLParseNode::column_ref);
if ( pColumnRef )
{
OTableFieldDescRef aField = new OTableFieldDesc();
if ( eOk == FillDragInfo(this,pColumnRef,aField) )
{
nType = aField->GetDataType();
}
}
}
}
Reference<XDatabaseMetaData> xMeta = xConnection->getMetaData();
parse::OParseColumn* pColumn = new parse::OParseColumn( pEntry->GetField(),
::rtl::OUString(),
::rtl::OUString(),
ColumnValue::NULLABLE_UNKNOWN,
0,
0,
nType,
sal_False,
sal_False,
xMeta.is() && xMeta->supportsMixedCaseQuotedIdentifiers());
_rxColumn = pColumn;
pColumn->setFunction(sal_True);
pColumn->setRealName(pEntry->GetField());
}
else
{
if (pWin)
{
Reference<XNameAccess> xColumns = pWin->GetOriginalColumns();
if (xColumns.is() && xColumns->hasByName(pEntry->GetField()))
xColumns->getByName(pEntry->GetField()) >>= _rxColumn;
}
}
OSQLParseNode* pParseNode = rParser.predicateTree( _rsErrorMessage,
sTest,
static_cast<OQueryController&>(getController()).getNumberFormatter(),
_rxColumn);
return pParseNode;
}
// -----------------------------------------------------------------------------
void OQueryDesignView::GetFocus()
{
OQueryView::GetFocus();
if ( m_pSelectionBox && !m_pSelectionBox->HasChildPathFocus() )
{
// first we have to deactivate the current cell to refill when nescessary
m_pSelectionBox->DeactivateCell();
m_pSelectionBox->ActivateCell(m_pSelectionBox->GetCurRow(), m_pSelectionBox->GetCurColumnId());
m_pSelectionBox->GrabFocus();
}
}
// -----------------------------------------------------------------------------
void OQueryDesignView::reset()
{
m_pTableView->ClearAll();
m_pTableView->ReSync();
}
// -----------------------------------------------------------------------------
void OQueryDesignView::setNoneVisbleRow(sal_Int32 _nRows)
{
m_pSelectionBox->SetNoneVisbleRow(_nRows);
}
// -----------------------------------------------------------------------------
bool OQueryDesignView::initByParseIterator( ::dbtools::SQLExceptionInfo* _pErrorInfo )
{
SqlParseError eErrorCode = eNativeMode;
m_rController.clearError();
try
{
eErrorCode = InitFromParseNodeImpl( this, m_pSelectionBox );
if ( eErrorCode != eOk )
{
if ( !m_rController.hasError() )
m_rController.appendError( getParseErrorMessage( eErrorCode ) );
if ( _pErrorInfo )
{
*_pErrorInfo = m_rController.getError();
}
else
{
m_rController.displayError();
}
}
}
catch ( const Exception& )
{
DBG_UNHANDLED_EXCEPTION();
}
return eErrorCode == eOk;
}
// -----------------------------------------------------------------------------