Update ooo320-m1
[ooovba.git] / dbaccess / source / core / api / SingleSelectQueryComposer.cxx
blobd62ee8d8b1629d1852d6144d0f135a4e6b42601d
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: SingleSelectQueryComposer.cxx,v $
10 * $Revision: 1.28.18.1 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_dbaccess.hxx"
34 #include "composertools.hxx"
35 #include "core_resource.hrc"
36 #include "core_resource.hxx"
37 #include "dbastrings.hrc"
38 #include "HelperCollections.hxx"
39 #include "SingleSelectQueryComposer.hxx"
41 /** === begin UNO includes === **/
42 #include <com/sun/star/beans/PropertyAttribute.hpp>
43 #include <com/sun/star/container/XChild.hpp>
44 #include <com/sun/star/i18n/XLocaleData.hpp>
45 #include <com/sun/star/lang/DisposedException.hpp>
46 #include <com/sun/star/sdb/BooleanComparisonMode.hpp>
47 #include <com/sun/star/sdb/SQLFilterOperator.hpp>
48 #include <com/sun/star/sdbc/ColumnSearch.hpp>
49 #include <com/sun/star/sdbc/DataType.hpp>
50 #include <com/sun/star/sdbc/XResultSetMetaData.hpp>
51 #include <com/sun/star/sdbc/XResultSetMetaDataSupplier.hpp>
52 #include <com/sun/star/uno/XAggregation.hpp>
53 #include <com/sun/star/util/XNumberFormatter.hpp>
54 /** === end UNO includes === **/
56 #include <comphelper/processfactory.hxx>
57 #include <comphelper/sequence.hxx>
58 #include <comphelper/types.hxx>
59 #include <cppuhelper/typeprovider.hxx>
60 #include <rtl/logfile.hxx>
61 #include <svtools/syslocale.hxx>
62 #include <tools/debug.hxx>
63 #include <tools/diagnose_ex.h>
64 #include <unotools/configmgr.hxx>
65 #include <unotools/sharedunocomponent.hxx>
67 #include <memory>
69 using namespace ::dbaccess;
70 using namespace ::dbtools;
71 using namespace ::comphelper;
72 using namespace ::connectivity;
73 using namespace ::com::sun::star::uno;
74 using namespace ::com::sun::star::beans;
75 using namespace ::com::sun::star::sdbc;
76 using namespace ::com::sun::star::sdb;
77 using namespace ::com::sun::star::sdbcx;
78 using namespace ::com::sun::star::container;
79 using namespace ::com::sun::star::i18n;
80 using namespace ::com::sun::star::lang;
81 using namespace ::com::sun::star::script;
82 using namespace ::com::sun::star::util;
83 using namespace ::cppu;
84 using namespace ::osl;
85 using namespace ::utl;
87 namespace dbaccess {
88 namespace BooleanComparisonMode = ::com::sun::star::sdb::BooleanComparisonMode;
91 #define STR_SELECT ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("SELECT "))
92 #define STR_FROM ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" FROM "))
93 #define STR_WHERE ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" WHERE "))
94 #define STR_GROUP_BY ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" GROUP BY "))
95 #define STR_HAVING ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" HAVING "))
96 #define STR_ORDER_BY ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" ORDER BY "))
97 #define STR_AND ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" AND "))
98 #define STR_OR ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" OR "))
99 #define STR_LIKE ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" LIKE "))
100 #define STR_EQUAL ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" = "))
101 #define L_BRACKET ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("("))
102 #define R_BRACKET ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(")"))
103 #define COMMA ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(","))
105 // -------------------------------------------------------------------------
106 namespace
108 // .....................................................................
109 /** parses the given statement, using the given parser, returns a parse node representing
110 the statement
112 If the statement cannot be parsed, an error is thrown.
114 const OSQLParseNode* parseStatement_throwError( OSQLParser& _rParser, const ::rtl::OUString& _rStatement, const Reference< XInterface >& _rxContext )
116 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "frank.schoenheit@sun.com", "SingleSelectQueryComposer.cxx::parseStatement_throwError" );
117 ::rtl::OUString aErrorMsg;
118 const OSQLParseNode* pNewSqlParseNode = _rParser.parseTree( aErrorMsg, _rStatement );
119 if ( !pNewSqlParseNode )
121 ::rtl::OUString sSQLStateGeneralError( getStandardSQLState( SQL_GENERAL_ERROR ) );
122 SQLException aError2( aErrorMsg, _rxContext, sSQLStateGeneralError, 1000, Any() );
123 SQLException aError1( _rStatement, _rxContext, sSQLStateGeneralError, 1000, makeAny( aError2 ) );
124 throw SQLException(_rParser.getContext().getErrorMessage(OParseContext::ERROR_GENERAL),_rxContext,sSQLStateGeneralError,1000,makeAny(aError1));
126 return pNewSqlParseNode;
129 // .....................................................................
130 /** checks whether the given parse node describes a valid single select statement, throws
131 an error if not
133 void checkForSingleSelect_throwError( const OSQLParseNode* pStatementNode, OSQLParseTreeIterator& _rIterator,
134 const Reference< XInterface >& _rxContext, const ::rtl::OUString& _rOriginatingCommand )
136 const OSQLParseNode* pOldNode = _rIterator.getParseTree();
138 // determine the statement type
139 _rIterator.setParseTree( pStatementNode );
140 _rIterator.traverseAll();
141 bool bIsSingleSelect = ( _rIterator.getStatementType() == SQL_STATEMENT_SELECT );
143 // throw the error, if necessary
144 if ( !bIsSingleSelect || SQL_ISRULE( pStatementNode, union_statement ) ) // #i4229# OJ
146 // restore the old node before throwing the exception
147 _rIterator.setParseTree( pOldNode );
148 // and now really ...
149 SQLException aError1( _rOriginatingCommand, _rxContext, getStandardSQLState( SQL_GENERAL_ERROR ), 1000, Any() );
150 throw SQLException( DBACORE_RESSTRING( RID_STR_ONLY_QUERY ), _rxContext,
151 getStandardSQLState( SQL_GENERAL_ERROR ), 1000, makeAny( aError1 ) );
154 delete pOldNode;
157 // .....................................................................
158 /** combines parseStatement_throwError and checkForSingleSelect_throwError
160 void parseAndCheck_throwError( OSQLParser& _rParser, const ::rtl::OUString& _rStatement,
161 OSQLParseTreeIterator& _rIterator, const Reference< XInterface >& _rxContext )
163 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "frank.schoenheit@sun.com", "SingleSelectQueryComposer.cxx::parseAndCheck_throwError" );
164 const OSQLParseNode* pNode = parseStatement_throwError( _rParser, _rStatement, _rxContext );
165 checkForSingleSelect_throwError( pNode, _rIterator, _rxContext, _rStatement );
168 // .....................................................................
169 /** transforms a parse node describing a complete statement into a pure select
170 statement, without any filter/order/groupby/having clauses
172 ::rtl::OUString getPureSelectStatement( const OSQLParseNode* _pRootNode, Reference< XConnection > _rxConnection )
174 ::rtl::OUString sSQL = STR_SELECT;
175 _pRootNode->getChild(1)->parseNodeToStr( sSQL, _rxConnection );
176 _pRootNode->getChild(2)->parseNodeToStr( sSQL, _rxConnection );
177 sSQL += STR_FROM;
178 _pRootNode->getChild(3)->getChild(0)->getChild(1)->parseNodeToStr( sSQL, _rxConnection );
179 return sSQL;
182 /** resets an SQL iterator, including deletion of the parse tree, and disposal if desired
184 void resetIterator( OSQLParseTreeIterator& _rIterator, bool _bDispose )
186 const OSQLParseNode* pSqlParseNode = _rIterator.getParseTree();
187 _rIterator.setParseTree(NULL);
188 delete pSqlParseNode;
189 if ( _bDispose )
190 _rIterator.dispose();
194 DBG_NAME(OSingleSelectQueryComposer)
195 // -------------------------------------------------------------------------
196 OSingleSelectQueryComposer::OSingleSelectQueryComposer(const Reference< XNameAccess>& _rxTables,
197 const Reference< XConnection>& _xConnection,
198 const ::comphelper::ComponentContext& _rContext )
199 :OSubComponent(m_aMutex,_xConnection)
200 ,OPropertyContainer(m_aBHelper)
201 ,m_aSqlParser( _rContext.getLegacyServiceFactory() )
202 ,m_aSqlIterator( _xConnection, _rxTables, m_aSqlParser, NULL )
203 ,m_aAdditiveIterator( _xConnection, _rxTables, m_aSqlParser, NULL )
204 ,m_aElementaryParts( (size_t)SQLPartCount )
205 ,m_xConnection(_xConnection)
206 ,m_xMetaData(_xConnection->getMetaData())
207 ,m_xConnectionTables( _rxTables )
208 ,m_aContext( _rContext )
209 ,m_pTables(NULL)
210 ,m_nBoolCompareMode( BooleanComparisonMode::EQUAL_INTEGER )
212 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::OSingleSelectQueryComposer" );
213 DBG_CTOR(OSingleSelectQueryComposer,NULL);
215 if ( !m_aContext.is() || !m_xConnection.is() || !m_xConnectionTables.is() )
216 throw IllegalArgumentException();
218 registerProperty(PROPERTY_ORIGINAL,PROPERTY_ID_ORIGINAL,PropertyAttribute::BOUND|PropertyAttribute::READONLY,&m_sOrignal,::getCppuType(&m_sOrignal));
220 m_aCurrentColumns.resize(4);
222 m_aLocale = SvtSysLocale().GetLocaleData().getLocale();
223 m_xNumberFormatsSupplier = dbtools::getNumberFormats( m_xConnection, sal_True, m_aContext.getLegacyServiceFactory() );
224 Reference< XLocaleData > xLocaleData;
225 m_aContext.createComponent( "com.sun.star.i18n.LocaleData", xLocaleData );
226 LocaleDataItem aData = xLocaleData->getLocaleItem(m_aLocale);
227 m_sDecimalSep = aData.decimalSeparator;
228 OSL_ENSURE(m_sDecimalSep.getLength() == 1,"OSingleSelectQueryComposer::OSingleSelectQueryComposer decimal separator is not 1 length");
231 Reference< XChild> xChild(_xConnection, UNO_QUERY);
232 if(xChild.is())
234 Reference< XPropertySet> xProp(xChild->getParent(),UNO_QUERY);
235 if ( xProp.is() )
237 Sequence< PropertyValue > aInfo;
238 xProp->getPropertyValue(PROPERTY_INFO) >>= aInfo;
239 const PropertyValue* pBegin = aInfo.getConstArray();
240 const PropertyValue* pEnd = pBegin + aInfo.getLength();
241 for (; pBegin != pEnd; ++pBegin)
243 if ( pBegin->Name == static_cast <rtl::OUString> (PROPERTY_BOOLEANCOMPARISONMODE) )
245 OSL_VERIFY( pBegin->Value >>= m_nBoolCompareMode );
251 catch(Exception&)
255 // -------------------------------------------------------------------------
256 OSingleSelectQueryComposer::~OSingleSelectQueryComposer()
258 DBG_DTOR(OSingleSelectQueryComposer,NULL);
259 ::std::vector<OPrivateColumns*>::iterator aColIter = m_aColumnsCollection.begin();
260 ::std::vector<OPrivateColumns*>::iterator aEnd = m_aColumnsCollection.end();
261 for(;aColIter != aEnd;++aColIter)
262 delete *aColIter;
264 ::std::vector<OPrivateTables*>::iterator aTabIter = m_aTablesCollection.begin();
265 ::std::vector<OPrivateTables*>::iterator aTabEnd = m_aTablesCollection.end();
266 for(;aTabIter != aTabEnd;++aTabIter)
267 delete *aTabIter;
269 // -------------------------------------------------------------------------
270 // OComponentHelper
271 void SAL_CALL OSingleSelectQueryComposer::disposing(void)
273 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::disposing" );
274 OSubComponent::disposing();
276 MutexGuard aGuard(m_aMutex);
278 resetIterator( m_aSqlIterator, true );
279 resetIterator( m_aAdditiveIterator, true );
281 m_xConnectionTables = NULL;
282 m_xConnection = NULL;
284 clearCurrentCollections();
286 IMPLEMENT_FORWARD_XINTERFACE3(OSingleSelectQueryComposer,OSubComponent,OSingleSelectQueryComposer_BASE,OPropertyContainer)
287 IMPLEMENT_SERVICE_INFO1(OSingleSelectQueryComposer,"org.openoffice.comp.dba.OSingleSelectQueryComposer",SERVICE_NAME_SINGLESELECTQUERYCOMPOSER)
288 IMPLEMENT_TYPEPROVIDER3(OSingleSelectQueryComposer,OSubComponent,OSingleSelectQueryComposer_BASE,OPropertyContainer)
289 IMPLEMENT_PROPERTYCONTAINER_DEFAULTS(OSingleSelectQueryComposer)
291 // -------------------------------------------------------------------------
292 // com::sun::star::lang::XUnoTunnel
293 sal_Int64 SAL_CALL OSingleSelectQueryComposer::getSomething( const Sequence< sal_Int8 >& rId ) throw(RuntimeException)
295 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getSomething" );
296 if (rId.getLength() == 16 && 0 == rtl_compareMemory(getImplementationId().getConstArray(), rId.getConstArray(), 16 ) )
297 return reinterpret_cast<sal_Int64>(this);
299 return sal_Int64(0);
302 // -------------------------------------------------------------------------
303 // XSingleSelectQueryAnalyzer
304 ::rtl::OUString SAL_CALL OSingleSelectQueryComposer::getQuery( ) throw(RuntimeException)
306 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getQuery" );
307 ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
308 ::osl::MutexGuard aGuard( m_aMutex );
310 TGetParseNode F_tmp(&OSQLParseTreeIterator::getParseTree);
311 return getStatementPart(F_tmp,m_aSqlIterator);
314 // -------------------------------------------------------------------------
315 void SAL_CALL OSingleSelectQueryComposer::setQuery( const ::rtl::OUString& command ) throw(SQLException, RuntimeException)
317 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "frank.schoenheit@sun.com", "OSingleSelectQueryComposer::setQuery" );
318 ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
320 ::osl::MutexGuard aGuard( m_aMutex );
321 // first clear the tables and columns
322 clearCurrentCollections();
323 // now set the new one
324 setQuery_Impl(command);
325 m_sOrignal = command;
327 // reset the additive iterator to the same statement
328 parseAndCheck_throwError( m_aSqlParser, m_sOrignal, m_aAdditiveIterator, *this );
330 // we have no "elementary" parts anymore (means filter/groupby/having/order clauses)
331 for ( SQLPart eLoopParts = Where; eLoopParts != SQLPartCount; incSQLPart( eLoopParts ) )
332 m_aElementaryParts[ eLoopParts ] = ::rtl::OUString();
334 // -----------------------------------------------------------------------------
335 void OSingleSelectQueryComposer::setQuery_Impl( const ::rtl::OUString& command )
337 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "frank.schoenheit@sun.com", "OSingleSelectQueryComposer::setQuery_Impl" );
338 // parse this
339 parseAndCheck_throwError( m_aSqlParser, command, m_aSqlIterator, *this );
341 // strip it from all clauses, to have the pure SELECT statement
342 m_aPureSelectSQL = getPureSelectStatement( m_aSqlIterator.getParseTree(), m_xConnection );
344 // update columns and tables
345 // why? Shouldn't this be done on request only?
346 // otherwise nothing is working anymore :-)
347 // getColumns();
348 getTables();
350 // -----------------------------------------------------------------------------
351 Sequence< Sequence< PropertyValue > > SAL_CALL OSingleSelectQueryComposer::getStructuredHavingClause( ) throw (RuntimeException)
353 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getStructuredHavingClause" );
354 TGetParseNode F_tmp(&OSQLParseTreeIterator::getSimpleHavingTree);
355 return getStructuredCondition(F_tmp);
357 // -------------------------------------------------------------------------
358 Sequence< Sequence< PropertyValue > > SAL_CALL OSingleSelectQueryComposer::getStructuredFilter( ) throw(RuntimeException)
360 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getStructuredFilter" );
361 TGetParseNode F_tmp(&OSQLParseTreeIterator::getSimpleWhereTree);
362 return getStructuredCondition(F_tmp);
364 // -----------------------------------------------------------------------------
365 void SAL_CALL OSingleSelectQueryComposer::appendHavingClauseByColumn( const Reference< XPropertySet >& column, sal_Bool andCriteria ) throw (SQLException, RuntimeException)
367 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::appendHavingClauseByColumn" );
368 ::std::mem_fun1_t<bool,OSingleSelectQueryComposer,::rtl::OUString> F_tmp(&OSingleSelectQueryComposer::implSetHavingClause);
369 setConditionByColumn(column,andCriteria,F_tmp);
371 // -----------------------------------------------------------------------------
372 void SAL_CALL OSingleSelectQueryComposer::appendFilterByColumn( const Reference< XPropertySet >& column, sal_Bool andCriteria ) throw(SQLException, RuntimeException)
374 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::appendFilterByColumn" );
375 ::std::mem_fun1_t<bool,OSingleSelectQueryComposer,::rtl::OUString> F_tmp(&OSingleSelectQueryComposer::implSetFilter);
376 setConditionByColumn(column,andCriteria,F_tmp);
378 // -----------------------------------------------------------------------------
379 ::rtl::OUString OSingleSelectQueryComposer::impl_getColumnName_throw(const Reference< XPropertySet >& column)
381 ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
383 getColumns();
384 if ( !column.is()
385 || !m_aCurrentColumns[SelectColumns]
386 || !column->getPropertySetInfo()->hasPropertyByName(PROPERTY_NAME)
389 String sError(DBACORE_RESSTRING(RID_STR_COLUMN_UNKNOWN_PROP));
390 sError.SearchAndReplaceAscii("%value", ::rtl::OUString(PROPERTY_NAME));
391 SQLException aErr(sError,*this,SQLSTATE_GENERAL,1000,Any() );
392 throw SQLException(DBACORE_RESSTRING(RID_STR_COLUMN_NOT_VALID),*this,SQLSTATE_GENERAL,1000,makeAny(aErr) );
395 ::rtl::OUString aName,aNewName;
396 column->getPropertyValue(PROPERTY_NAME) >>= aName;
398 if ( !m_xMetaData->supportsOrderByUnrelated() && m_aCurrentColumns[SelectColumns] && !m_aCurrentColumns[SelectColumns]->hasByName(aName))
400 String sError(DBACORE_RESSTRING(RID_STR_COLUMN_MUST_VISIBLE));
401 sError.SearchAndReplaceAscii("%name", aName);
402 throw SQLException(sError,*this,SQLSTATE_GENERAL,1000,Any() );
405 // filter anhaengen
406 // select ohne where und order by aufbauen
407 ::rtl::OUString aQuote = m_xMetaData->getIdentifierQuoteString();
408 if ( m_aCurrentColumns[SelectColumns]->hasByName(aName) )
410 Reference<XPropertySet> xColumn;
411 m_aCurrentColumns[SelectColumns]->getByName(aName) >>= xColumn;
412 OSL_ENSURE(xColumn->getPropertySetInfo()->hasPropertyByName(PROPERTY_REALNAME),"Property REALNAME not available!");
413 OSL_ENSURE(xColumn->getPropertySetInfo()->hasPropertyByName(PROPERTY_TABLENAME),"Property TABLENAME not available!");
414 OSL_ENSURE(xColumn->getPropertySetInfo()->hasPropertyByName(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Function"))),"Property FUNCTION not available!");
416 ::rtl::OUString sRealName,sTableName;
417 xColumn->getPropertyValue(PROPERTY_REALNAME) >>= sRealName;
418 xColumn->getPropertyValue(PROPERTY_TABLENAME) >>= sTableName;
419 sal_Bool bFunction = sal_False;
420 xColumn->getPropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Function"))) >>= bFunction;
421 if ( sRealName == aName )
423 if ( bFunction )
424 aNewName = aName;
425 else
427 if(sTableName.indexOf('.',0) != -1)
429 ::rtl::OUString aCatlog,aSchema,aTable;
430 ::dbtools::qualifiedNameComponents(m_xMetaData,sTableName,aCatlog,aSchema,aTable,::dbtools::eInDataManipulation);
431 sTableName = ::dbtools::composeTableName( m_xMetaData, aCatlog, aSchema, aTable, sal_True, ::dbtools::eInDataManipulation );
433 else
434 sTableName = ::dbtools::quoteName(aQuote,sTableName);
436 aNewName = sTableName;
437 aNewName += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("."));
438 aNewName += ::dbtools::quoteName(aQuote,sRealName);
441 else
442 aNewName = ::dbtools::quoteName(aQuote,aName);
444 else
445 aNewName = getTableAlias(column) + ::dbtools::quoteName(aQuote,aName);
446 return aNewName;
448 // -------------------------------------------------------------------------
449 void SAL_CALL OSingleSelectQueryComposer::appendOrderByColumn( const Reference< XPropertySet >& column, sal_Bool ascending ) throw(SQLException, RuntimeException)
451 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::appendOrderByColumn" );
452 ::osl::MutexGuard aGuard( m_aMutex );
453 ::rtl::OUString sColumnName( impl_getColumnName_throw(column) );
454 ::rtl::OUString sOrder = getOrder();
455 if ( (sOrder.getLength() != 0) && sColumnName.getLength() )
456 sOrder += COMMA;
457 sOrder += sColumnName;
458 if ( !ascending && sColumnName.getLength() )
459 sOrder += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" DESC "));
461 setOrder(sOrder);
464 // -------------------------------------------------------------------------
465 void SAL_CALL OSingleSelectQueryComposer::appendGroupByColumn( const Reference< XPropertySet >& column) throw(SQLException, RuntimeException)
467 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::appendGroupByColumn" );
468 ::osl::MutexGuard aGuard( m_aMutex );
469 ::rtl::OUString sColumnName( impl_getColumnName_throw(column) );
470 OrderCreator aComposer;
471 aComposer.append( getGroup() );
472 aComposer.append( sColumnName );
473 setGroup( aComposer.getComposedAndClear() );
475 // -------------------------------------------------------------------------
476 ::rtl::OUString OSingleSelectQueryComposer::composeStatementFromParts( const ::std::vector< ::rtl::OUString >& _rParts )
478 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::composeStatementFromParts" );
479 DBG_ASSERT( _rParts.size() == (size_t)SQLPartCount, "OSingleSelectQueryComposer::composeStatementFromParts: invalid parts array!" );
481 ::rtl::OUStringBuffer aSql( m_aPureSelectSQL );
482 for ( SQLPart eLoopParts = Where; eLoopParts != SQLPartCount; incSQLPart( eLoopParts ) )
483 if ( _rParts[ eLoopParts ].getLength() )
485 aSql.append( getKeyword( eLoopParts ) );
486 aSql.append( _rParts[ eLoopParts ] );
489 return aSql.makeStringAndClear();
492 // -------------------------------------------------------------------------
493 ::rtl::OUString SAL_CALL OSingleSelectQueryComposer::getElementaryQuery() throw (::com::sun::star::uno::RuntimeException)
495 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getElementaryQuery" );
496 return composeStatementFromParts( m_aElementaryParts );
499 // -------------------------------------------------------------------------
500 void SAL_CALL OSingleSelectQueryComposer::setElementaryQuery( const ::rtl::OUString& _rElementary ) throw (::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException)
502 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "frank.schoenheit@sun.com", "OSingleSelectQueryComposer::setElementaryQuery" );
503 ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
504 ::osl::MutexGuard aGuard( m_aMutex );
506 // remember the 4 current "additive" clauses
507 ::std::vector< ::rtl::OUString > aAdditiveClauses( SQLPartCount );
508 for ( SQLPart eLoopParts = Where; eLoopParts != SQLPartCount; incSQLPart( eLoopParts ) )
509 aAdditiveClauses[ eLoopParts ] = getSQLPart( eLoopParts, m_aAdditiveIterator, sal_False );
511 // clear the tables and columns
512 clearCurrentCollections();
513 // set and parse the new query
514 setQuery_Impl( _rElementary );
516 // get the 4 elementary parts of the statement
517 for ( SQLPart eLoopParts = Where; eLoopParts != SQLPartCount; incSQLPart( eLoopParts ) )
518 m_aElementaryParts[ eLoopParts ] = getSQLPart( eLoopParts, m_aSqlIterator, sal_False );
520 // reset the the AdditiveIterator: m_aPureSelectSQL may have changed
523 parseAndCheck_throwError( m_aSqlParser, composeStatementFromParts( aAdditiveClauses ), m_aAdditiveIterator, *this );
525 catch( const Exception& e )
527 (void)e;
528 DBG_ERROR( "OSingleSelectQueryComposer::setElementaryQuery: there should be no error anymore for the additive statement!" );
529 // every part of the additive statement should have passed other tests already, and should not
530 // be able to cause any errors ... me thinks
534 // -------------------------------------------------------------------------
535 namespace
537 ::rtl::OUString getComposedClause( const ::rtl::OUString _rElementaryClause, const ::rtl::OUString _rAdditionalClause,
538 TokenComposer& _rComposer, const ::rtl::OUString _rKeyword )
540 _rComposer.clear();
541 _rComposer.append( _rElementaryClause );
542 _rComposer.append( _rAdditionalClause );
543 ::rtl::OUString sComposed = _rComposer.getComposedAndClear();
544 if ( sComposed.getLength() )
545 sComposed = _rKeyword + sComposed;
546 return sComposed;
550 // -------------------------------------------------------------------------
551 void OSingleSelectQueryComposer::setSingleAdditiveClause( SQLPart _ePart, const ::rtl::OUString& _rClause )
553 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::setSingleAdditiveClause" );
554 ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
555 ::osl::MutexGuard aGuard( m_aMutex );
557 // if nothing is changed, do nothing
558 if ( getSQLPart( _ePart, m_aAdditiveIterator, sal_False ) == _rClause )
559 return;
561 // collect the 4 single parts as they're currently set
562 ::std::vector< ::rtl::OUString > aClauses;
563 aClauses.reserve( (size_t)SQLPartCount );
564 for ( SQLPart eLoopParts = Where; eLoopParts != SQLPartCount; incSQLPart( eLoopParts ) )
565 aClauses.push_back( getSQLPart( eLoopParts, m_aSqlIterator, sal_True ) );
567 // overwrite the one part in question here
568 ::std::auto_ptr< TokenComposer > pComposer;
569 if ( ( _ePart == Where ) || ( _ePart == Having ) )
570 pComposer.reset( new FilterCreator );
571 else
572 pComposer.reset( new OrderCreator );
573 aClauses[ _ePart ] = getComposedClause( m_aElementaryParts[ _ePart ], _rClause,
574 *pComposer, getKeyword( _ePart ) );
576 // construct the complete statement
577 ::rtl::OUStringBuffer aSql(m_aPureSelectSQL);
578 for ( SQLPart eLoopParts = Where; eLoopParts != SQLPartCount; incSQLPart( eLoopParts ) )
579 aSql.append(aClauses[ eLoopParts ]);
581 // set the query
582 setQuery_Impl(aSql.makeStringAndClear());
584 // clear column collections which (might) have changed
585 clearColumns( ParameterColumns );
586 if ( _ePart == Order )
587 clearColumns( OrderColumns );
588 if ( _ePart == Group )
589 clearColumns( GroupByColumns );
591 // also, since the "additive filter" change, we need to rebuild our "additive" statement
592 aSql = m_aPureSelectSQL;
593 // again, first get all the old additive parts
594 for ( SQLPart eLoopParts = Where; eLoopParts != SQLPartCount; incSQLPart( eLoopParts ) )
595 aClauses[ eLoopParts ] = getSQLPart( eLoopParts, m_aAdditiveIterator, sal_True );
596 // then overwrite the one in question
597 aClauses[ _ePart ] = getComposedClause( ::rtl::OUString(), _rClause, *pComposer, getKeyword( _ePart ) );
598 // and parse it, so that m_aAdditiveIterator is up to date
599 for ( SQLPart eLoopParts = Where; eLoopParts != SQLPartCount; incSQLPart( eLoopParts ) )
600 aSql.append(aClauses[ eLoopParts ]);
603 parseAndCheck_throwError( m_aSqlParser, aSql.makeStringAndClear(), m_aAdditiveIterator, *this );
605 catch( const Exception& e )
607 (void)e;
608 DBG_ERROR( "OSingleSelectQueryComposer::setSingleAdditiveClause: there should be no error anymore for the additive statement!" );
609 // every part of the additive statement should have passed other tests already, and should not
610 // be able to cause any errors ... me thinks
614 // -------------------------------------------------------------------------
615 void SAL_CALL OSingleSelectQueryComposer::setFilter( const ::rtl::OUString& filter ) throw(SQLException, RuntimeException)
617 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::setFilter" );
618 setSingleAdditiveClause( Where, filter );
621 // -------------------------------------------------------------------------
622 void SAL_CALL OSingleSelectQueryComposer::setOrder( const ::rtl::OUString& order ) throw(SQLException, RuntimeException)
624 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::setOrder" );
625 setSingleAdditiveClause( Order, order );
627 // -----------------------------------------------------------------------------
628 void SAL_CALL OSingleSelectQueryComposer::setGroup( const ::rtl::OUString& group ) throw (SQLException, RuntimeException)
630 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::setGroup" );
631 setSingleAdditiveClause( Group, group );
633 // -------------------------------------------------------------------------
634 void SAL_CALL OSingleSelectQueryComposer::setHavingClause( const ::rtl::OUString& filter ) throw(SQLException, RuntimeException)
636 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::setHavingClause" );
637 setSingleAdditiveClause( Having, filter );
640 // -------------------------------------------------------------------------
641 // XTablesSupplier
642 Reference< XNameAccess > SAL_CALL OSingleSelectQueryComposer::getTables( ) throw(RuntimeException)
644 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getTables" );
645 ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
647 ::osl::MutexGuard aGuard( m_aMutex );
648 if ( !m_pTables )
650 const OSQLTables& aTables = m_aSqlIterator.getTables();
651 ::std::vector< ::rtl::OUString> aNames;
652 OSQLTables::const_iterator aEnd = aTables.end();
653 for(OSQLTables::const_iterator aIter = aTables.begin(); aIter != aEnd;++aIter)
654 aNames.push_back(aIter->first);
656 m_pTables = new OPrivateTables(aTables,m_xMetaData->supportsMixedCaseQuotedIdentifiers(),*this,m_aMutex,aNames);
659 return m_pTables;
661 // -------------------------------------------------------------------------
662 // XColumnsSupplier
663 Reference< XNameAccess > SAL_CALL OSingleSelectQueryComposer::getColumns( ) throw(RuntimeException)
665 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getColumns" );
666 ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
667 ::osl::MutexGuard aGuard( m_aMutex );
668 if ( !!m_aCurrentColumns[SelectColumns] )
669 return m_aCurrentColumns[SelectColumns];
671 ::std::vector< ::rtl::OUString> aNames;
672 ::vos::ORef< OSQLColumns> aSelectColumns;
673 sal_Bool bCase = sal_True;
675 do {
679 SharedUNOComponent< XStatement, DisposableComponent > xStatement;
680 SharedUNOComponent< XPreparedStatement, DisposableComponent > xPreparedStatement;
682 bCase = m_xMetaData->supportsMixedCaseQuotedIdentifiers();
683 aSelectColumns = m_aSqlIterator.getSelectColumns();
685 ::rtl::OUStringBuffer aSQL;
686 aSQL.append( m_aPureSelectSQL );
687 aSQL.append( STR_WHERE );
689 // preserve the original WHERE clause
690 // #i102234# / 2009-06-02 / frank.schoenheit@sun.com
691 ::rtl::OUString sOriginalWhereClause = getSQLPart( Where, m_aSqlIterator, sal_False );
692 if ( sOriginalWhereClause.getLength() )
694 aSQL.appendAscii( " ( 0 = 1 ) AND ( " );
695 aSQL.append( sOriginalWhereClause );
696 aSQL.appendAscii( " ) " );
698 else
700 aSQL.appendAscii( " ( 0 = 1 ) " );
703 ::rtl::OUString sGroupBy = getSQLPart( Group, m_aSqlIterator, sal_True );
704 if ( sGroupBy.getLength() )
705 aSQL.append( sGroupBy );
707 ::rtl::OUString sSQL( aSQL.makeStringAndClear() );
708 // normalize the statement so that it doesn't contain any application-level features anymore
709 ::rtl::OUString sError;
710 const ::std::auto_ptr< OSQLParseNode > pStatementTree( m_aSqlParser.parseTree( sError, sSQL, false ) );
711 DBG_ASSERT( pStatementTree.get(), "OSingleSelectQueryComposer::getColumns: could not parse the column retrieval statement!" );
712 if ( pStatementTree.get() )
713 if ( !pStatementTree->parseNodeToExecutableStatement( sSQL, m_xConnection, m_aSqlParser, NULL ) )
714 break;
716 Reference< XResultSetMetaData > xResultSetMeta;
717 Reference< XResultSetMetaDataSupplier > xResMetaDataSup;
720 xPreparedStatement.set( m_xConnection->prepareStatement( sSQL ), UNO_QUERY_THROW );
721 xResMetaDataSup.set( xPreparedStatement, UNO_QUERY_THROW );
722 xResultSetMeta.set( xResMetaDataSup->getMetaData(), UNO_QUERY_THROW );
724 catch( const Exception& ) { }
726 if ( !xResultSetMeta.is() )
728 xStatement.reset( Reference< XStatement >( m_xConnection->createStatement(), UNO_QUERY_THROW ) );
729 Reference< XPropertySet > xStatementProps( xStatement, UNO_QUERY_THROW );
730 try { xStatementProps->setPropertyValue( PROPERTY_ESCAPE_PROCESSING, makeAny( sal_False ) ); }
731 catch ( const Exception& ) { DBG_UNHANDLED_EXCEPTION(); }
732 xResMetaDataSup.set( xStatement->executeQuery( sSQL ), UNO_QUERY_THROW );
733 xResultSetMeta.set( xResMetaDataSup->getMetaData(), UNO_QUERY_THROW );
736 if ( aSelectColumns->get().empty() )
738 // This is a valid case. If we can syntactically parse the query, but not semantically
739 // (e.g. because it is based on a table we do not know), then there will be no SelectColumns
740 aSelectColumns = ::connectivity::parse::OParseColumn::createColumnsForResultSet( xResultSetMeta, m_xMetaData );
741 break;
744 const ::comphelper::UStringMixEqual aCaseCompare( bCase );
745 const ::comphelper::TStringMixEqualFunctor aCaseCompareFunctor( bCase );
746 typedef ::std::set< size_t > SizeTSet;
747 SizeTSet aUsedSelectColumns;
749 sal_Int32 nCount = xResultSetMeta->getColumnCount();
750 OSL_ENSURE( (size_t) nCount == aSelectColumns->get().size(), "OSingleSelectQueryComposer::getColumns: inconsistent column counts, this might result in wrong columns!" );
751 for(sal_Int32 i=1;i<=nCount;++i)
753 ::rtl::OUString sName = xResultSetMeta->getColumnName(i);
754 sal_Bool bFound = sal_False;
755 OSQLColumns::Vector::const_iterator aFind = ::connectivity::find(aSelectColumns->get().begin(),aSelectColumns->get().end(),sName,aCaseCompare);
756 size_t nFoundSelectColumnPos = aFind - aSelectColumns->get().begin();
757 if ( aFind != aSelectColumns->get().end() )
759 if ( aUsedSelectColumns.find( nFoundSelectColumnPos ) != aUsedSelectColumns.end() )
760 { // we found a column name which exists twice
761 // so we start after the first found
764 aFind = ::connectivity::findRealName(++aFind,aSelectColumns->get().end(),sName,aCaseCompare);
765 nFoundSelectColumnPos = aFind - aSelectColumns->get().begin();
767 while ( ( aUsedSelectColumns.find( nFoundSelectColumnPos ) != aUsedSelectColumns.end() )
768 && ( aFind != aSelectColumns->get().end() )
771 if ( aFind != aSelectColumns->get().end() )
773 (*aFind)->getPropertyValue(PROPERTY_NAME) >>= sName;
774 aUsedSelectColumns.insert( nFoundSelectColumnPos );
775 aNames.push_back(sName);
776 bFound = sal_True;
780 if ( bFound )
781 continue;
783 OSQLColumns::Vector::const_iterator aRealFind = ::connectivity::findRealName(
784 aSelectColumns->get().begin(), aSelectColumns->get().end(), sName, aCaseCompare );
786 if ( i > static_cast< sal_Int32>( aSelectColumns->get().size() ) )
788 aSelectColumns->get().push_back(
789 ::connectivity::parse::OParseColumn::createColumnForResultSet( xResultSetMeta, m_xMetaData, i )
791 OSL_ENSURE( aSelectColumns->get().size() == (size_t)i, "OSingleSelectQueryComposer::getColumns: inconsistency!" );
793 else if ( aRealFind == aSelectColumns->get().end() )
795 // we can now only look if we found it under the realname propertery
796 // here we have to make the assumption that the position is correct
797 OSQLColumns::Vector::iterator aFind2 = aSelectColumns->get().begin() + i-1;
798 Reference<XPropertySet> xProp(*aFind2,UNO_QUERY);
799 if ( !xProp.is() || !xProp->getPropertySetInfo()->hasPropertyByName( PROPERTY_REALNAME ) )
800 continue;
802 ::connectivity::parse::OParseColumn* pColumn = new ::connectivity::parse::OParseColumn(xProp,bCase);
803 pColumn->setFunction(::comphelper::getBOOL(xProp->getPropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Function")))));
804 pColumn->setAggregateFunction(::comphelper::getBOOL(xProp->getPropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("AggregateFunction")))));
806 ::rtl::OUString sRealName;
807 xProp->getPropertyValue(PROPERTY_REALNAME) >>= sRealName;
808 ::std::vector< ::rtl::OUString>::iterator aFindName;
809 if ( !sName.getLength() )
810 xProp->getPropertyValue(PROPERTY_NAME) >>= sName;
813 aFindName = ::std::find_if(aNames.begin(),aNames.end(),::std::bind2nd(aCaseCompareFunctor,sName));
814 sal_Int32 j = 0;
815 while ( aFindName != aNames.end() )
817 sName += ::rtl::OUString::valueOf(++j);
818 aFindName = ::std::find_if(aNames.begin(),aNames.end(),::std::bind2nd(aCaseCompareFunctor,sName));
821 pColumn->setName(sName);
822 pColumn->setRealName(sRealName);
823 pColumn->setTableName(::comphelper::getString(xProp->getPropertyValue(PROPERTY_TABLENAME)));
825 (aSelectColumns->get())[i-1] = pColumn;
827 else
828 continue;
830 aUsedSelectColumns.insert( (size_t)(i - 1) );
831 aNames.push_back( sName );
834 catch(const Exception&)
838 } while ( false );
840 if ( aNames.empty() )
841 m_aCurrentColumns[ SelectColumns ] = OPrivateColumns::createWithIntrinsicNames( aSelectColumns, bCase, *this, m_aMutex );
842 else
843 m_aCurrentColumns[ SelectColumns ] = new OPrivateColumns( aSelectColumns, bCase, *this, m_aMutex, aNames );
845 return m_aCurrentColumns[SelectColumns];
847 // -------------------------------------------------------------------------
848 sal_Bool OSingleSelectQueryComposer::setORCriteria(OSQLParseNode* pCondition, OSQLParseTreeIterator& _rIterator,
849 ::std::vector< ::std::vector < PropertyValue > >& rFilters, const Reference< ::com::sun::star::util::XNumberFormatter > & xFormatter) const
851 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::setORCriteria" );
852 // Runde Klammern um den Ausdruck
853 if (pCondition->count() == 3 &&
854 SQL_ISPUNCTUATION(pCondition->getChild(0),"(") &&
855 SQL_ISPUNCTUATION(pCondition->getChild(2),")"))
857 return setORCriteria(pCondition->getChild(1), _rIterator, rFilters, xFormatter);
859 // oder Verknuepfung
860 // a searchcondition can only look like this: search_condition SQL_TOKEN_OR boolean_term
861 else if (SQL_ISRULE(pCondition,search_condition))
863 sal_Bool bResult = sal_True;
864 for (int i = 0; bResult && i < 3; i+=2)
866 // Ist das erste Element wieder eine OR-Verknuepfung?
867 // Dann rekursiv absteigen ...
868 //if (!i && SQL_ISRULE(pCondition->getChild(i),search_condition))
869 if (SQL_ISRULE(pCondition->getChild(i),search_condition))
870 bResult = setORCriteria(pCondition->getChild(i), _rIterator, rFilters, xFormatter);
871 else
873 rFilters.push_back( ::std::vector < PropertyValue >());
874 bResult = setANDCriteria(pCondition->getChild(i), _rIterator, rFilters[rFilters.size() - 1], xFormatter);
877 return bResult;
879 else
881 rFilters.push_back(::std::vector < PropertyValue >());
882 return setANDCriteria(pCondition, _rIterator, rFilters[rFilters.size() - 1], xFormatter);
886 //--------------------------------------------------------------------------------------------------
887 sal_Bool OSingleSelectQueryComposer::setANDCriteria( OSQLParseNode * pCondition,
888 OSQLParseTreeIterator& _rIterator, ::std::vector < PropertyValue >& rFilter, const Reference< XNumberFormatter > & xFormatter) const
890 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::setANDCriteria" );
891 // Runde Klammern
892 if (SQL_ISRULE(pCondition,boolean_primary))
894 // this should not occur
895 DBG_ERROR("boolean_primary in And-Criteria");
896 return sal_False;
898 // Das erste Element ist (wieder) eine AND-Verknuepfung
899 else if ( SQL_ISRULE(pCondition,boolean_term) && pCondition->count() == 3 )
901 return setANDCriteria(pCondition->getChild(0), _rIterator, rFilter, xFormatter) &&
902 setANDCriteria(pCondition->getChild(2), _rIterator, rFilter, xFormatter);
904 else if (SQL_ISRULE(pCondition, comparison_predicate))
906 return setComparsionPredicate(pCondition,_rIterator,rFilter,xFormatter);
908 else if (SQL_ISRULE(pCondition,like_predicate) ||
909 SQL_ISRULE(pCondition,test_for_null) ||
910 SQL_ISRULE(pCondition,in_predicate) ||
911 SQL_ISRULE(pCondition,all_or_any_predicate) ||
912 SQL_ISRULE(pCondition,between_predicate))
914 if (SQL_ISRULE(pCondition->getChild(0), column_ref))
916 PropertyValue aItem;
917 ::rtl::OUString aValue;
918 ::rtl::OUString aColumnName;
921 // pCondition->parseNodeToStr(aValue,m_xMetaData, xFormatter, m_aLocale,static_cast<sal_Char>(m_sDecimalSep.toChar()));
922 pCondition->parseNodeToStr( aValue, m_xConnection, NULL );
923 // pCondition->getChild(0)->parseNodeToStr(aColumnName,m_xMetaData, xFormatter, m_aLocale,static_cast<sal_Char>(m_sDecimalSep.toChar()));
924 pCondition->getChild(0)->parseNodeToStr( aColumnName, m_xConnection, NULL );
926 // don't display the column name
927 aValue = aValue.copy(aColumnName.getLength());
928 aValue = aValue.trim();
930 aItem.Name = getColumnName(pCondition->getChild(0),_rIterator);
931 aItem.Value <<= aValue;
932 aItem.Handle = 0; // just to know that this is not one the known ones
933 if (SQL_ISRULE(pCondition,like_predicate))
935 if (pCondition->count() == 5)
936 aItem.Handle = SQLFilterOperator::NOT_LIKE;
937 else
938 aItem.Handle = SQLFilterOperator::LIKE;
940 else if (SQL_ISRULE(pCondition,test_for_null))
942 if (SQL_ISTOKEN(pCondition->getChild(2),NOT) )
943 aItem.Handle = SQLFilterOperator::NOT_SQLNULL;
944 else
945 aItem.Handle = SQLFilterOperator::SQLNULL;
947 else if (SQL_ISRULE(pCondition,in_predicate))
949 OSL_ENSURE( false, "OSingleSelectQueryComposer::setANDCriteria: in_predicate not implemented!" );
951 else if (SQL_ISRULE(pCondition,all_or_any_predicate))
953 OSL_ENSURE( false, "OSingleSelectQueryComposer::setANDCriteria: all_or_any_predicate not implemented!" );
955 else if (SQL_ISRULE(pCondition,between_predicate))
957 OSL_ENSURE( false, "OSingleSelectQueryComposer::setANDCriteria: between_predicate not implemented!" );
960 rFilter.push_back(aItem);
962 else
963 return sal_False;
965 else if (SQL_ISRULE(pCondition,existence_test) ||
966 SQL_ISRULE(pCondition,unique_test))
968 // this couldn't be handled here, too complex
969 // as we need a field name
970 return sal_False;
972 else
973 return sal_False;
975 return sal_True;
977 // -----------------------------------------------------------------------------
978 sal_Int32 OSingleSelectQueryComposer::getPredicateType(OSQLParseNode * _pPredicate) const
980 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getPredicateType" );
981 sal_Int32 nPredicate = SQLFilterOperator::EQUAL;
982 switch (_pPredicate->getNodeType())
984 case SQL_NODE_EQUAL:
985 nPredicate = SQLFilterOperator::EQUAL;
986 break;
987 case SQL_NODE_NOTEQUAL:
988 nPredicate = SQLFilterOperator::NOT_EQUAL;
989 break;
990 case SQL_NODE_LESS:
991 nPredicate = SQLFilterOperator::LESS;
992 break;
993 case SQL_NODE_LESSEQ:
994 nPredicate = SQLFilterOperator::LESS_EQUAL;
995 break;
996 case SQL_NODE_GREAT:
997 nPredicate = SQLFilterOperator::GREATER;
998 break;
999 case SQL_NODE_GREATEQ:
1000 nPredicate = SQLFilterOperator::GREATER_EQUAL;
1001 break;
1002 default:
1003 OSL_ENSURE(0,"Wrong NodeType!");
1005 return nPredicate;
1007 //------------------------------------------------------------------------------
1008 sal_Bool OSingleSelectQueryComposer::setComparsionPredicate(OSQLParseNode * pCondition, OSQLParseTreeIterator& _rIterator,
1009 ::std::vector < PropertyValue >& rFilter, const Reference< ::com::sun::star::util::XNumberFormatter > & xFormatter) const
1011 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::setComparsionPredicate" );
1012 DBG_ASSERT(SQL_ISRULE(pCondition, comparison_predicate),"setComparsionPredicate: pCondition ist kein ComparsionPredicate");
1013 if (SQL_ISRULE(pCondition->getChild(0), column_ref) ||
1014 SQL_ISRULE(pCondition->getChild(pCondition->count()-1), column_ref))
1016 PropertyValue aItem;
1017 ::rtl::OUString aValue;
1018 sal_uInt32 nPos;
1019 if (SQL_ISRULE(pCondition->getChild(0), column_ref))
1021 nPos = 0;
1022 sal_uInt32 i=1;
1024 aItem.Handle = getPredicateType(pCondition->getChild(i));
1025 // don't display the equal
1026 if (pCondition->getChild(i)->getNodeType() == SQL_NODE_EQUAL)
1027 i++;
1029 // go forward
1030 for (;i < pCondition->count();i++)
1031 pCondition->getChild(i)->parseNodeToPredicateStr(
1032 aValue, m_xConnection, xFormatter, m_aLocale, static_cast<sal_Char>(m_sDecimalSep.toChar() ) );
1034 else if (SQL_ISRULE(pCondition->getChild(pCondition->count()-1), column_ref))
1036 nPos = pCondition->count()-1;
1038 sal_Int32 i = pCondition->count() - 2;
1039 switch (pCondition->getChild(i)->getNodeType())
1041 case SQL_NODE_EQUAL:
1042 // don't display the equal
1043 i--;
1044 aItem.Handle = SQLFilterOperator::EQUAL;
1045 break;
1046 case SQL_NODE_NOTEQUAL:
1047 i--;
1048 aItem.Handle = SQLFilterOperator::NOT_EQUAL;
1049 break;
1050 case SQL_NODE_LESS:
1051 // take the opposite as we change the order
1052 i--;
1053 aValue = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(">="));
1054 aItem.Handle = SQLFilterOperator::GREATER_EQUAL;
1055 break;
1056 case SQL_NODE_LESSEQ:
1057 // take the opposite as we change the order
1058 i--;
1059 aValue = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(">"));
1060 aItem.Handle = SQLFilterOperator::GREATER;
1061 break;
1062 case SQL_NODE_GREAT:
1063 // take the opposite as we change the order
1064 i--;
1065 aValue = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("<="));
1066 aItem.Handle = SQLFilterOperator::LESS_EQUAL;
1067 break;
1068 case SQL_NODE_GREATEQ:
1069 // take the opposite as we change the order
1070 i--;
1071 aValue = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("<"));
1072 aItem.Handle = SQLFilterOperator::LESS;
1073 break;
1074 default:
1075 break;
1078 // go backward
1079 for (; i >= 0; i--)
1080 pCondition->getChild(i)->parseNodeToPredicateStr(
1081 aValue, m_xConnection, xFormatter, m_aLocale, static_cast<sal_Char>( m_sDecimalSep.toChar() ) );
1083 else
1084 return sal_False;
1086 aItem.Name = getColumnName(pCondition->getChild(nPos),_rIterator);
1087 aItem.Value <<= aValue;
1088 rFilter.push_back(aItem);
1090 else if (SQL_ISRULE(pCondition->getChild(0), set_fct_spec ) ||
1091 SQL_ISRULE(pCondition->getChild(0), general_set_fct))
1093 PropertyValue aItem;
1094 ::rtl::OUString aValue;
1095 ::rtl::OUString aColumnName;
1097 pCondition->parseNodeToPredicateStr(aValue, m_xConnection, xFormatter, m_aLocale, static_cast<sal_Char>( m_sDecimalSep.toChar() ) );
1098 pCondition->getChild(0)->parseNodeToPredicateStr( aColumnName, m_xConnection, xFormatter, m_aLocale, static_cast<sal_Char>( m_sDecimalSep .toChar() ) );
1100 // don't display the column name
1101 aValue = aValue.copy(aColumnName.getLength());
1102 aValue.trim();
1104 aItem.Name = UniString(getColumnName(pCondition->getChild(0),_rIterator));
1105 aItem.Value <<= aValue;
1106 aItem.Handle = pCondition->getNodeType();
1107 rFilter.push_back(aItem);
1109 else // kann sich nur um einen Expr. Ausdruck handeln
1111 PropertyValue aItem;
1112 ::rtl::OUString aName, aValue;
1114 OSQLParseNode *pLhs = pCondition->getChild(0);
1115 OSQLParseNode *pRhs = pCondition->getChild(2);
1117 // Feldnamen
1118 sal_uInt16 i;
1119 for (i=0;i< pLhs->count();i++)
1120 pCondition->getChild(i)->parseNodeToPredicateStr( aName, m_xConnection, xFormatter, m_aLocale, static_cast<sal_Char>( m_sDecimalSep.toChar() ) );
1122 // Kriterium
1123 aItem.Handle = pCondition->getChild(1)->getNodeType();
1124 aValue = pCondition->getChild(1)->getTokenValue();
1125 for(i=0;i< pRhs->count();i++)
1126 pCondition->getChild(i)->parseNodeToPredicateStr(aValue, m_xConnection, xFormatter, m_aLocale, static_cast<sal_Char>( m_sDecimalSep.toChar() ) );
1128 aItem.Name = aName;
1129 aItem.Value <<= aValue;
1130 rFilter.push_back(aItem);
1132 return sal_True;
1134 // functions for analysing SQL
1135 //--------------------------------------------------------------------------------------------------
1136 ::rtl::OUString OSingleSelectQueryComposer::getColumnName( ::connectivity::OSQLParseNode* pColumnRef, OSQLParseTreeIterator& _rIterator ) const
1138 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getColumnName" );
1139 ::rtl::OUString aTableRange, aColumnName;
1140 _rIterator.getColumnRange(pColumnRef,aColumnName,aTableRange);
1141 return aColumnName;
1143 //------------------------------------------------------------------------------
1144 ::rtl::OUString SAL_CALL OSingleSelectQueryComposer::getFilter( ) throw(RuntimeException)
1146 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getFilter" );
1147 ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
1148 ::osl::MutexGuard aGuard( m_aMutex );
1149 return getSQLPart(Where,m_aAdditiveIterator,sal_False);
1151 // -------------------------------------------------------------------------
1152 ::rtl::OUString SAL_CALL OSingleSelectQueryComposer::getOrder( ) throw(RuntimeException)
1154 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getOrder" );
1155 ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
1156 ::osl::MutexGuard aGuard( m_aMutex );
1157 return getSQLPart(Order,m_aAdditiveIterator,sal_False);
1159 // -------------------------------------------------------------------------
1160 ::rtl::OUString SAL_CALL OSingleSelectQueryComposer::getGroup( ) throw (RuntimeException)
1162 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getGroup" );
1163 ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
1164 ::osl::MutexGuard aGuard( m_aMutex );
1165 return getSQLPart(Group,m_aAdditiveIterator,sal_False);
1167 // -----------------------------------------------------------------------------
1168 ::rtl::OUString OSingleSelectQueryComposer::getHavingClause() throw (RuntimeException)
1170 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getHavingClause" );
1171 ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
1172 ::osl::MutexGuard aGuard( m_aMutex );
1173 return getSQLPart(Having,m_aAdditiveIterator,sal_False);
1175 // -----------------------------------------------------------------------------
1176 ::rtl::OUString OSingleSelectQueryComposer::getTableAlias(const Reference< XPropertySet >& column) const
1178 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getTableAlias" );
1179 ::rtl::OUString sReturn;
1180 if(m_pTables && m_pTables->getCount() > 1)
1182 ::rtl::OUString aCatalog,aSchema,aTable,aComposedName,aColumnName;
1183 column->getPropertyValue(PROPERTY_CATALOGNAME) >>= aCatalog;
1184 column->getPropertyValue(PROPERTY_SCHEMANAME) >>= aSchema;
1185 column->getPropertyValue(PROPERTY_TABLENAME) >>= aTable;
1186 column->getPropertyValue(PROPERTY_NAME) >>= aColumnName;
1188 Sequence< ::rtl::OUString> aNames(m_pTables->getElementNames());
1189 const ::rtl::OUString* pBegin = aNames.getConstArray();
1190 const ::rtl::OUString* pEnd = pBegin + aNames.getLength();
1192 if(!aTable.getLength())
1193 { // we don't found a table name, now we must search every table for this column
1194 for(;pBegin != pEnd;++pBegin)
1196 Reference<XColumnsSupplier> xColumnsSupp;
1197 m_pTables->getByName(*pBegin) >>= xColumnsSupp;
1199 if(xColumnsSupp.is() && xColumnsSupp->getColumns()->hasByName(aColumnName))
1201 // Reference<XPropertySet> xTableProp(xColumnsSupp,UNO_QUERY);
1202 // xTableProp->getPropertyValue(PROPERTY_CATALOGNAME) >>= aCatalog;
1203 // xTableProp->getPropertyValue(PROPERTY_SCHEMANAME) >>= aSchema;
1204 // xTableProp->getPropertyValue(PROPERTY_NAME) >>= aTable;
1205 aTable = *pBegin;
1206 break;
1210 else
1212 aComposedName = ::dbtools::composeTableName( m_xMetaData, aCatalog, aSchema, aTable, sal_False, ::dbtools::eInDataManipulation );
1214 // first check if this is the table we want to or has it a tablealias
1216 if(!m_pTables->hasByName(aComposedName))
1218 ::comphelper::UStringMixLess aTmp(m_aAdditiveIterator.getTables().key_comp());
1219 ::comphelper::UStringMixEqual aComp(static_cast< ::comphelper::UStringMixLess*>(&aTmp)->isCaseSensitive());
1220 for(;pBegin != pEnd;++pBegin)
1222 Reference<XPropertySet> xTableProp;
1223 m_pTables->getByName(*pBegin) >>= xTableProp;
1224 OSL_ENSURE(xTableProp.is(),"Table isn't a propertyset!");
1225 if(xTableProp.is())
1227 ::rtl::OUString aCatalog2,aSchema2,aTable2;
1228 xTableProp->getPropertyValue(PROPERTY_CATALOGNAME) >>= aCatalog2;
1229 xTableProp->getPropertyValue(PROPERTY_SCHEMANAME) >>= aSchema2;
1230 xTableProp->getPropertyValue(PROPERTY_NAME) >>= aTable2;
1231 if(aComp(aCatalog,aCatalog2) && aComp(aSchema,aSchema2) && aComp(aTable,aTable2))
1233 aCatalog = aCatalog2;
1234 aSchema = aSchema2;
1235 aTable = aTable2;
1236 break;
1242 if(pBegin != pEnd)
1244 sReturn = ::dbtools::composeTableName( m_xMetaData, aCatalog, aSchema, aTable, sal_True, ::dbtools::eInDataManipulation );
1245 sReturn += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("."));
1248 return sReturn;
1250 // -----------------------------------------------------------------------------
1251 Reference< XIndexAccess > SAL_CALL OSingleSelectQueryComposer::getParameters( ) throw(RuntimeException)
1253 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getParameters" );
1254 // now set the Parameters
1255 if ( !m_aCurrentColumns[ParameterColumns] )
1257 ::vos::ORef< OSQLColumns> aCols = m_aSqlIterator.getParameters();
1258 ::std::vector< ::rtl::OUString> aNames;
1259 OSQLColumns::Vector::const_iterator aEnd = aCols->get().end();
1260 for(OSQLColumns::Vector::const_iterator aIter = aCols->get().begin(); aIter != aEnd;++aIter)
1261 aNames.push_back(getString((*aIter)->getPropertyValue(PROPERTY_NAME)));
1262 m_aCurrentColumns[ParameterColumns] = new OPrivateColumns(aCols,m_xMetaData->supportsMixedCaseQuotedIdentifiers(),*this,m_aMutex,aNames,sal_True);
1265 return m_aCurrentColumns[ParameterColumns];
1267 // -----------------------------------------------------------------------------
1268 void OSingleSelectQueryComposer::clearColumns( const EColumnType _eType )
1270 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::clearColumns" );
1271 OPrivateColumns* pColumns = m_aCurrentColumns[ _eType ];
1272 if ( pColumns != NULL )
1274 pColumns->disposing();
1275 m_aColumnsCollection.push_back( pColumns );
1276 m_aCurrentColumns[ _eType ] = NULL;
1279 // -----------------------------------------------------------------------------
1280 void OSingleSelectQueryComposer::clearCurrentCollections()
1282 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::clearCurrentCollections" );
1283 ::std::vector<OPrivateColumns*>::iterator aIter = m_aCurrentColumns.begin();
1284 ::std::vector<OPrivateColumns*>::iterator aEnd = m_aCurrentColumns.end();
1285 for (;aIter != aEnd;++aIter)
1287 if ( *aIter )
1289 (*aIter)->disposing();
1290 m_aColumnsCollection.push_back(*aIter);
1291 *aIter = NULL;
1295 if(m_pTables)
1297 m_pTables->disposing();
1298 m_aTablesCollection.push_back(m_pTables);
1299 m_pTables = NULL;
1302 // -----------------------------------------------------------------------------
1303 Reference< XIndexAccess > OSingleSelectQueryComposer::setCurrentColumns( EColumnType _eType,
1304 const ::vos::ORef< OSQLColumns >& _rCols )
1306 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::setCurrentColumns" );
1307 ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
1309 ::osl::MutexGuard aGuard( m_aMutex );
1310 // now set the group columns
1311 if ( !m_aCurrentColumns[_eType] )
1313 ::std::vector< ::rtl::OUString> aNames;
1314 OSQLColumns::Vector::const_iterator aEnd = _rCols->get().end();
1315 for(OSQLColumns::Vector::const_iterator aIter = _rCols->get().begin(); aIter != aEnd;++aIter)
1316 aNames.push_back(getString((*aIter)->getPropertyValue(PROPERTY_NAME)));
1317 m_aCurrentColumns[_eType] = new OPrivateColumns(_rCols,m_xMetaData->supportsMixedCaseQuotedIdentifiers(),*this,m_aMutex,aNames,sal_True);
1320 return m_aCurrentColumns[_eType];
1322 // -----------------------------------------------------------------------------
1323 Reference< XIndexAccess > SAL_CALL OSingleSelectQueryComposer::getGroupColumns( ) throw(RuntimeException)
1325 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getGroupColumns" );
1326 return setCurrentColumns( GroupByColumns, m_aAdditiveIterator.getGroupColumns() );
1328 // -------------------------------------------------------------------------
1329 Reference< XIndexAccess > SAL_CALL OSingleSelectQueryComposer::getOrderColumns( ) throw(RuntimeException)
1331 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getOrderColumns" );
1332 return setCurrentColumns( OrderColumns, m_aAdditiveIterator.getOrderColumns() );
1334 // -----------------------------------------------------------------------------
1335 ::rtl::OUString SAL_CALL OSingleSelectQueryComposer::getQueryWithSubstitution( ) throw (SQLException, RuntimeException)
1337 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getQueryWithSubstitution" );
1338 ::osl::MutexGuard aGuard( m_aMutex );
1339 ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
1341 ::rtl::OUString sSqlStatement( getQuery() );
1343 const OSQLParseNode* pStatementNode = m_aSqlIterator.getParseTree();
1344 if ( pStatementNode )
1346 SQLException aError;
1347 if ( !pStatementNode->parseNodeToExecutableStatement( sSqlStatement, m_xConnection, m_aSqlParser, &aError ) )
1348 throw SQLException( aError );
1351 return sSqlStatement;
1353 // -----------------------------------------------------------------------------
1354 ::rtl::OUString OSingleSelectQueryComposer::getStatementPart( TGetParseNode& _aGetFunctor, OSQLParseTreeIterator& _rIterator )
1356 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getStatementPart" );
1357 ::rtl::OUString sResult;
1359 const OSQLParseNode* pNode = _aGetFunctor( &_rIterator );
1360 if ( pNode )
1361 pNode->parseNodeToStr( sResult, m_xConnection );
1363 return sResult;
1365 // -----------------------------------------------------------------------------
1366 namespace
1368 ::rtl::OUString lcl_getCondition(const Sequence< Sequence< PropertyValue > >& filter )
1370 ::rtl::OUStringBuffer sRet;
1371 const Sequence< PropertyValue >* pOrIter = filter.getConstArray();
1372 const Sequence< PropertyValue >* pOrEnd = pOrIter + filter.getLength();
1373 while ( pOrIter != pOrEnd )
1375 if ( pOrIter->getLength() )
1377 sRet.append(L_BRACKET);
1378 const PropertyValue* pAndIter = pOrIter->getConstArray();
1379 const PropertyValue* pAndEnd = pAndIter + pOrIter->getLength();
1380 while ( pAndIter != pAndEnd )
1382 sRet.append(pAndIter->Name);
1383 ::rtl::OUString sValue;
1384 pAndIter->Value >>= sValue;
1385 switch( pAndIter->Handle )
1387 case SQLFilterOperator::EQUAL:
1388 sRet.append(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" = ")));
1389 sRet.append(sValue);
1390 break;
1391 case SQLFilterOperator::NOT_EQUAL:
1392 sRet.append(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" <> ")));
1393 sRet.append(sValue);
1394 break;
1395 case SQLFilterOperator::LESS:
1396 sRet.append(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" < ")));
1397 sRet.append(sValue);
1398 break;
1399 case SQLFilterOperator::GREATER:
1400 sRet.append(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" > ")));
1401 sRet.append(sValue);
1402 break;
1403 case SQLFilterOperator::LESS_EQUAL:
1404 sRet.append(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" <= ")));
1405 sRet.append(sValue);
1406 break;
1407 case SQLFilterOperator::GREATER_EQUAL:
1408 sRet.append(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" >= ")));
1409 sRet.append(sValue);
1410 break;
1411 case SQLFilterOperator::LIKE:
1412 sRet.append(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" LIKE ")));
1413 sRet.append(sValue);
1414 break;
1415 case SQLFilterOperator::NOT_LIKE:
1416 sRet.append(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" NOT LIKE ")));
1417 sRet.append(sValue);
1418 break;
1419 case SQLFilterOperator::SQLNULL:
1420 sRet.append(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" IS NULL")) );
1421 break;
1422 case SQLFilterOperator::NOT_SQLNULL:
1423 sRet.append(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" IS NOT NULL")) );
1424 break;
1425 default:
1426 throw IllegalArgumentException();
1428 ++pAndIter;
1429 if ( pAndIter != pAndEnd )
1430 sRet.append(STR_AND);
1432 sRet.append(R_BRACKET);
1434 ++pOrIter;
1435 if ( pOrIter != pOrEnd && sRet.getLength() )
1436 sRet.append(STR_OR);
1438 return sRet.makeStringAndClear();
1441 // -----------------------------------------------------------------------------
1442 void SAL_CALL OSingleSelectQueryComposer::setStructuredFilter( const Sequence< Sequence< PropertyValue > >& filter ) throw (SQLException, ::com::sun::star::lang::IllegalArgumentException, RuntimeException)
1444 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::setStructuredFilter" );
1445 setFilter(lcl_getCondition(filter));
1447 // -----------------------------------------------------------------------------
1448 void SAL_CALL OSingleSelectQueryComposer::setStructuredHavingClause( const Sequence< Sequence< PropertyValue > >& filter ) throw (SQLException, RuntimeException)
1450 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::setStructuredHavingClause" );
1451 setHavingClause(lcl_getCondition(filter));
1453 // -----------------------------------------------------------------------------
1454 void OSingleSelectQueryComposer::setConditionByColumn( const Reference< XPropertySet >& column, sal_Bool andCriteria ,::std::mem_fun1_t<bool,OSingleSelectQueryComposer,::rtl::OUString>& _aSetFunctor)
1456 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::setConditionByColumn" );
1457 ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
1459 if ( !column.is()
1460 || !column->getPropertySetInfo()->hasPropertyByName(PROPERTY_VALUE)
1461 || !column->getPropertySetInfo()->hasPropertyByName(PROPERTY_NAME)
1462 || !column->getPropertySetInfo()->hasPropertyByName(PROPERTY_TYPE))
1463 throw SQLException(DBACORE_RESSTRING(RID_STR_COLUMN_NOT_VALID),*this,SQLSTATE_GENERAL,1000,Any() );
1465 sal_Int32 nType = 0;
1466 column->getPropertyValue(PROPERTY_TYPE) >>= nType;
1467 sal_Int32 nSearchable = dbtools::getSearchColumnFlag(m_xConnection,nType);
1468 if(nSearchable == ColumnSearch::NONE)
1469 throw SQLException(DBACORE_RESSTRING(RID_STR_COLUMN_NOT_SEARCHABLE),*this,SQLSTATE_GENERAL,1000,Any() );
1471 ::osl::MutexGuard aGuard( m_aMutex );
1473 ::rtl::OUString aName;
1474 column->getPropertyValue(PROPERTY_NAME) >>= aName;
1476 Any aValue;
1477 column->getPropertyValue(PROPERTY_VALUE) >>= aValue;
1479 ::rtl::OUStringBuffer aSQL;
1480 const ::rtl::OUString aQuote = m_xMetaData->getIdentifierQuoteString();
1481 getColumns();
1483 if ( m_aCurrentColumns[SelectColumns] && m_aCurrentColumns[SelectColumns]->hasByName(aName) )
1485 Reference<XPropertySet> xColumn;
1486 m_aCurrentColumns[SelectColumns]->getByName(aName) >>= xColumn;
1487 OSL_ENSURE(xColumn->getPropertySetInfo()->hasPropertyByName(PROPERTY_REALNAME),"Property REALNAME not available!");
1488 OSL_ENSURE(xColumn->getPropertySetInfo()->hasPropertyByName(PROPERTY_TABLENAME),"Property TABLENAME not available!");
1489 OSL_ENSURE(xColumn->getPropertySetInfo()->hasPropertyByName(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("AggregateFunction"))),"Property AggregateFunctionnot available!");
1491 ::rtl::OUString sRealName,sTableName;
1492 xColumn->getPropertyValue(PROPERTY_REALNAME) >>= sRealName;
1493 xColumn->getPropertyValue(PROPERTY_TABLENAME) >>= sTableName;
1494 if(sTableName.indexOf('.',0) != -1)
1496 ::rtl::OUString aCatlog,aSchema,aTable;
1497 ::dbtools::qualifiedNameComponents(m_xMetaData,sTableName,aCatlog,aSchema,aTable,::dbtools::eInDataManipulation);
1498 sTableName = ::dbtools::composeTableName( m_xMetaData, aCatlog, aSchema, aTable, sal_True, ::dbtools::eInDataManipulation );
1500 else
1501 sTableName = ::dbtools::quoteName(aQuote,sTableName);
1503 if ( !::comphelper::getBOOL(xColumn->getPropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Function")))) )
1505 aSQL = sTableName;
1506 aSQL.appendAscii( "." );
1507 aSQL.append( ::dbtools::quoteName( aQuote, sRealName ) );
1509 else
1510 aSQL = sRealName;
1513 else
1515 aSQL = getTableAlias( column );
1516 aSQL.append( ::dbtools::quoteName( aQuote, aName ) );
1519 if ( aValue.hasValue() )
1521 if( !m_xTypeConverter.is() )
1522 m_aContext.createComponent( "com.sun.star.script.Converter", m_xTypeConverter );
1523 OSL_ENSURE(m_xTypeConverter.is(),"NO typeconverter!");
1525 switch(nType)
1527 case DataType::VARCHAR:
1528 case DataType::CHAR:
1529 case DataType::LONGVARCHAR:
1530 aSQL.append( STR_LIKE );
1531 aSQL.append( DBTypeConversion::toSQLString( nType, aValue, sal_True, m_xTypeConverter ) );
1532 break;
1533 case DataType::VARBINARY:
1534 case DataType::BINARY:
1535 case DataType::LONGVARBINARY:
1537 Sequence<sal_Int8> aSeq;
1538 if(aValue >>= aSeq)
1540 if(nSearchable == ColumnSearch::CHAR)
1542 aSQL.append( STR_LIKE );
1543 aSQL.appendAscii( "\'" );
1545 else
1546 aSQL.append( STR_EQUAL );
1547 aSQL.appendAscii( "0x" );
1548 const sal_Int8* pBegin = aSeq.getConstArray();
1549 const sal_Int8* pEnd = pBegin + aSeq.getLength();
1550 for(;pBegin != pEnd;++pBegin)
1552 aSQL.append( (sal_Int32)*pBegin, 16 ).getStr();
1554 if(nSearchable == ColumnSearch::CHAR)
1555 aSQL.appendAscii( "\'" );
1557 else
1558 throw SQLException(DBACORE_RESSTRING(RID_STR_NOT_SEQUENCE_INT8),*this,SQLSTATE_GENERAL,1000,Any() );
1560 break;
1561 case DataType::BIT:
1562 case DataType::BOOLEAN:
1564 sal_Bool bValue = sal_False;
1565 m_xTypeConverter->convertToSimpleType(aValue, TypeClass_BOOLEAN) >>= bValue;
1567 ::rtl::OUString sColumnExp = aSQL.makeStringAndClear();
1568 getBoleanComparisonPredicate( sColumnExp, bValue, m_nBoolCompareMode, aSQL );
1570 break;
1571 default:
1572 aSQL.append( STR_EQUAL );
1573 aSQL.append( DBTypeConversion::toSQLString( nType, aValue, sal_True, m_xTypeConverter ) );
1574 break;
1577 else
1578 aSQL.appendAscii( " IS NULL" ) ;
1580 // filter anhaengen
1581 // select ohne where und order by aufbauen
1582 ::rtl::OUString sFilter = getFilter();
1584 if ( sFilter.getLength() && aSQL.getLength() )
1586 ::rtl::OUString sTemp(L_BRACKET);
1587 sTemp += sFilter;
1588 sTemp += R_BRACKET;
1589 sTemp += andCriteria ? STR_AND : STR_OR;
1590 sFilter = sTemp;
1592 sFilter += aSQL.makeStringAndClear();
1594 // add the filter and the sort order
1595 _aSetFunctor(this,sFilter);
1597 // -----------------------------------------------------------------------------
1598 Sequence< Sequence< PropertyValue > > OSingleSelectQueryComposer::getStructuredCondition( TGetParseNode& _aGetFunctor )
1600 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getStructuredCondition" );
1601 ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
1603 MutexGuard aGuard(m_aMutex);
1605 Sequence< Sequence< PropertyValue > > aFilterSeq;
1606 ::rtl::OUString sFilter = getStatementPart( _aGetFunctor, m_aAdditiveIterator );
1608 if ( sFilter.getLength() != 0 )
1610 ::rtl::OUString aSql(m_aPureSelectSQL);
1611 // build a temporary parse node
1612 const OSQLParseNode* pTempNode = m_aAdditiveIterator.getParseTree();
1614 aSql += STR_WHERE;
1615 aSql += sFilter;
1617 ::rtl::OUString aErrorMsg;
1618 ::std::auto_ptr<OSQLParseNode> pSqlParseNode( m_aSqlParser.parseTree(aErrorMsg,aSql));
1619 if ( pSqlParseNode.get() )
1621 m_aAdditiveIterator.setParseTree(pSqlParseNode.get());
1622 // normalize the filter
1623 OSQLParseNode* pWhereNode = const_cast<OSQLParseNode*>(m_aAdditiveIterator.getWhereTree());
1625 OSQLParseNode* pCondition = pWhereNode->getChild(1);
1626 #if OSL_DEBUG_LEVEL > 0
1627 ::rtl::OUString sCondition;
1628 pCondition->parseNodeToStr( sCondition, m_xConnection );
1629 #endif
1630 OSQLParseNode::negateSearchCondition(pCondition);
1632 pCondition = pWhereNode->getChild(1);
1633 #if OSL_DEBUG_LEVEL > 0
1634 sCondition = ::rtl::OUString();
1635 pCondition->parseNodeToStr( sCondition, m_xConnection );
1636 #endif
1637 OSQLParseNode::disjunctiveNormalForm(pCondition);
1639 pCondition = pWhereNode->getChild(1);
1640 #if OSL_DEBUG_LEVEL > 0
1641 sCondition = ::rtl::OUString();
1642 pCondition->parseNodeToStr( sCondition, m_xConnection );
1643 #endif
1644 OSQLParseNode::absorptions(pCondition);
1646 pCondition = pWhereNode->getChild(1);
1647 #if OSL_DEBUG_LEVEL > 0
1648 sCondition = ::rtl::OUString();
1649 pCondition->parseNodeToStr( sCondition, m_xConnection );
1650 #endif
1651 if ( pCondition )
1653 ::std::vector< ::std::vector < PropertyValue > > aFilters;
1654 Reference< XNumberFormatter > xFormatter;
1655 m_aContext.createComponent( "com.sun.star.util.NumberFormatter", xFormatter );
1656 xFormatter->attachNumberFormatsSupplier( m_xNumberFormatsSupplier );
1658 if (setORCriteria(pCondition, m_aAdditiveIterator, aFilters, xFormatter))
1660 aFilterSeq.realloc(aFilters.size());
1661 Sequence<PropertyValue>* pFilters = aFilterSeq.getArray();
1662 ::std::vector< ::std::vector < PropertyValue > >::const_iterator aEnd = aFilters.end();
1663 ::std::vector< ::std::vector < PropertyValue > >::const_iterator i = aFilters.begin();
1664 for ( ; i != aEnd ; ++i)
1666 const ::std::vector < PropertyValue >& rProperties = *i;
1667 pFilters->realloc(rProperties.size());
1668 PropertyValue* pFilter = pFilters->getArray();
1669 ::std::vector < PropertyValue >::const_iterator j = rProperties.begin();
1670 ::std::vector < PropertyValue >::const_iterator aEnd2 = rProperties.end();
1671 for ( ; j != aEnd2 ; ++j)
1673 *pFilter = *j;
1674 ++pFilter;
1676 ++pFilters;
1680 // restore
1681 m_aAdditiveIterator.setParseTree(pTempNode);
1684 return aFilterSeq;
1686 // -----------------------------------------------------------------------------
1687 ::rtl::OUString OSingleSelectQueryComposer::getKeyword( SQLPart _ePart ) const
1689 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getKeyword" );
1690 ::rtl::OUString sKeyword;
1691 switch(_ePart)
1693 default:
1694 OSL_ENSURE( 0, "OSingleSelectQueryComposer::getKeyWord: Invalid enum value!" );
1695 // no break, fallback to WHERE
1696 case Where:
1697 sKeyword = STR_WHERE;
1698 break;
1699 case Group:
1700 sKeyword = STR_GROUP_BY;
1701 break;
1702 case Having:
1703 sKeyword = STR_HAVING;
1704 break;
1705 case Order:
1706 sKeyword = STR_ORDER_BY;
1707 break;
1709 return sKeyword;
1712 // -----------------------------------------------------------------------------
1713 ::rtl::OUString OSingleSelectQueryComposer::getSQLPart( SQLPart _ePart, OSQLParseTreeIterator& _rIterator, sal_Bool _bWithKeyword )
1715 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getSQLPart" );
1716 TGetParseNode F_tmp(&OSQLParseTreeIterator::getSimpleWhereTree);
1717 ::rtl::OUString sKeyword( getKeyword( _ePart ) );
1718 switch(_ePart)
1720 case Where:
1721 F_tmp = TGetParseNode(&OSQLParseTreeIterator::getSimpleWhereTree);
1722 break;
1723 case Group:
1724 F_tmp = TGetParseNode (&OSQLParseTreeIterator::getSimpleGroupByTree);
1725 break;
1726 case Having:
1727 F_tmp = TGetParseNode(&OSQLParseTreeIterator::getSimpleHavingTree);
1728 break;
1729 case Order:
1730 F_tmp = TGetParseNode(&OSQLParseTreeIterator::getSimpleOrderTree);
1731 break;
1732 default:
1733 OSL_ENSURE(0,"Invalid enum value!");
1736 ::rtl::OUString sRet = getStatementPart( F_tmp, _rIterator );
1737 if ( _bWithKeyword && sRet.getLength() )
1738 sRet = sKeyword + sRet;
1739 return sRet;
1741 // -----------------------------------------------------------------------------