Version 4.0.0.1, tag libreoffice-4.0.0.1
[LibreOffice.git] / dbaccess / source / core / api / SingleSelectQueryComposer.cxx
blob837836d311f9c2c46fceb0341dbf45d851d30756
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <string.h>
21 #include "composertools.hxx"
22 #include "core_resource.hrc"
23 #include "core_resource.hxx"
24 #include "dbastrings.hrc"
25 #include "HelperCollections.hxx"
26 #include "SingleSelectQueryComposer.hxx"
27 #include "sdbcoretools.hxx"
29 #include <com/sun/star/beans/PropertyAttribute.hpp>
30 #include <com/sun/star/container/XChild.hpp>
31 #include <com/sun/star/i18n/LocaleData.hpp>
32 #include <com/sun/star/lang/DisposedException.hpp>
33 #include <com/sun/star/script/Converter.hpp>
34 #include <com/sun/star/sdb/BooleanComparisonMode.hpp>
35 #include <com/sun/star/sdb/SQLFilterOperator.hpp>
36 #include <com/sun/star/sdb/XQueriesSupplier.hpp>
37 #include <com/sun/star/sdb/CommandType.hpp>
38 #include <com/sun/star/sdbc/ColumnSearch.hpp>
39 #include <com/sun/star/sdbc/DataType.hpp>
40 #include <com/sun/star/sdbc/XResultSetMetaData.hpp>
41 #include <com/sun/star/sdbc/XResultSetMetaDataSupplier.hpp>
42 #include <com/sun/star/sdbc/XParameters.hpp>
43 #include <com/sun/star/uno/XAggregation.hpp>
44 #include <com/sun/star/util/NumberFormatter.hpp>
46 #include <comphelper/processfactory.hxx>
47 #include <comphelper/sequence.hxx>
48 #include <comphelper/types.hxx>
49 #include <cppuhelper/typeprovider.hxx>
50 #include <connectivity/predicateinput.hxx>
51 #include <rtl/logfile.hxx>
52 #include <unotools/syslocale.hxx>
53 #include <tools/debug.hxx>
54 #include <tools/diagnose_ex.h>
55 #include <osl/diagnose.h>
56 #include <unotools/configmgr.hxx>
57 #include <unotools/sharedunocomponent.hxx>
59 #include <memory>
61 using namespace ::dbaccess;
62 using namespace ::dbtools;
63 using namespace ::comphelper;
64 using namespace ::connectivity;
65 using namespace ::com::sun::star::uno;
66 using namespace ::com::sun::star::beans;
67 using namespace ::com::sun::star::sdbc;
68 using namespace ::com::sun::star::sdb;
69 using namespace ::com::sun::star::sdbcx;
70 using namespace ::com::sun::star::container;
71 using namespace ::com::sun::star::i18n;
72 using namespace ::com::sun::star::lang;
73 using namespace ::com::sun::star::script;
74 using namespace ::com::sun::star::util;
75 using namespace ::cppu;
76 using namespace ::osl;
77 using namespace ::utl;
79 namespace dbaccess {
80 namespace BooleanComparisonMode = ::com::sun::star::sdb::BooleanComparisonMode;
83 #define STR_SELECT ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("SELECT "))
84 #define STR_FROM ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" FROM "))
85 #define STR_WHERE ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" WHERE "))
86 #define STR_GROUP_BY ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" GROUP BY "))
87 #define STR_HAVING ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" HAVING "))
88 #define STR_ORDER_BY ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" ORDER BY "))
89 #define STR_AND ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" AND "))
90 #define STR_OR ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" OR "))
91 #define STR_LIKE ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" LIKE "))
92 #define L_BRACKET ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("("))
93 #define R_BRACKET ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(")"))
94 #define COMMA ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(","))
96 namespace
98 /** parses the given statement, using the given parser, returns a parse node representing
99 the statement
101 If the statement cannot be parsed, an error is thrown.
103 const OSQLParseNode* parseStatement_throwError( OSQLParser& _rParser, const ::rtl::OUString& _rStatement, const Reference< XInterface >& _rxContext )
105 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "frank.schoenheit@sun.com", "SingleSelectQueryComposer.cxx::parseStatement_throwError" );
106 ::rtl::OUString aErrorMsg;
107 const OSQLParseNode* pNewSqlParseNode = _rParser.parseTree( aErrorMsg, _rStatement );
108 if ( !pNewSqlParseNode )
110 ::rtl::OUString sSQLStateGeneralError( getStandardSQLState( SQL_GENERAL_ERROR ) );
111 SQLException aError2( aErrorMsg, _rxContext, sSQLStateGeneralError, 1000, Any() );
112 SQLException aError1( _rStatement, _rxContext, sSQLStateGeneralError, 1000, makeAny( aError2 ) );
113 throw SQLException(_rParser.getContext().getErrorMessage(OParseContext::ERROR_GENERAL),_rxContext,sSQLStateGeneralError,1000,makeAny(aError1));
115 return pNewSqlParseNode;
118 // .....................................................................
119 /** checks whether the given parse node describes a valid single select statement, throws
120 an error if not
122 void checkForSingleSelect_throwError( const OSQLParseNode* pStatementNode, OSQLParseTreeIterator& _rIterator,
123 const Reference< XInterface >& _rxContext, const ::rtl::OUString& _rOriginatingCommand )
125 const OSQLParseNode* pOldNode = _rIterator.getParseTree();
127 // determine the statement type
128 _rIterator.setParseTree( pStatementNode );
129 _rIterator.traverseAll();
130 bool bIsSingleSelect = ( _rIterator.getStatementType() == SQL_STATEMENT_SELECT );
132 // throw the error, if necessary
133 if ( !bIsSingleSelect || SQL_ISRULE( pStatementNode, union_statement ) ) // #i4229# OJ
135 // restore the old node before throwing the exception
136 _rIterator.setParseTree( pOldNode );
137 // and now really ...
138 SQLException aError1( _rOriginatingCommand, _rxContext, getStandardSQLState( SQL_GENERAL_ERROR ), 1000, Any() );
139 throw SQLException( DBACORE_RESSTRING( RID_STR_ONLY_QUERY ), _rxContext,
140 getStandardSQLState( SQL_GENERAL_ERROR ), 1000, makeAny( aError1 ) );
143 delete pOldNode;
146 // .....................................................................
147 /** combines parseStatement_throwError and checkForSingleSelect_throwError
149 void parseAndCheck_throwError( OSQLParser& _rParser, const ::rtl::OUString& _rStatement,
150 OSQLParseTreeIterator& _rIterator, const Reference< XInterface >& _rxContext )
152 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "frank.schoenheit@sun.com", "SingleSelectQueryComposer.cxx::parseAndCheck_throwError" );
153 const OSQLParseNode* pNode = parseStatement_throwError( _rParser, _rStatement, _rxContext );
154 checkForSingleSelect_throwError( pNode, _rIterator, _rxContext, _rStatement );
157 // .....................................................................
158 /** transforms a parse node describing a complete statement into a pure select
159 statement, without any filter/order/groupby/having clauses
161 ::rtl::OUString getPureSelectStatement( const OSQLParseNode* _pRootNode, Reference< XConnection > _rxConnection )
163 ::rtl::OUString sSQL = STR_SELECT;
164 _pRootNode->getChild(1)->parseNodeToStr( sSQL, _rxConnection );
165 _pRootNode->getChild(2)->parseNodeToStr( sSQL, _rxConnection );
166 sSQL += STR_FROM;
167 _pRootNode->getChild(3)->getChild(0)->getChild(1)->parseNodeToStr( sSQL, _rxConnection );
168 return sSQL;
171 /** resets an SQL iterator, including deletion of the parse tree, and disposal if desired
173 void resetIterator( OSQLParseTreeIterator& _rIterator, bool _bDispose )
175 const OSQLParseNode* pSqlParseNode = _rIterator.getParseTree();
176 _rIterator.setParseTree(NULL);
177 delete pSqlParseNode;
178 if ( _bDispose )
179 _rIterator.dispose();
181 void lcl_addFilterCriteria_throw(sal_Int32 i_nFilterOperator,const ::rtl::OUString& i_sValue,::rtl::OUStringBuffer& o_sRet)
183 switch( i_nFilterOperator )
185 case SQLFilterOperator::EQUAL:
186 o_sRet.append(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" = ")));
187 o_sRet.append(i_sValue);
188 break;
189 case SQLFilterOperator::NOT_EQUAL:
190 o_sRet.append(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" <> ")));
191 o_sRet.append(i_sValue);
192 break;
193 case SQLFilterOperator::LESS:
194 o_sRet.append(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" < ")));
195 o_sRet.append(i_sValue);
196 break;
197 case SQLFilterOperator::GREATER:
198 o_sRet.append(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" > ")));
199 o_sRet.append(i_sValue);
200 break;
201 case SQLFilterOperator::LESS_EQUAL:
202 o_sRet.append(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" <= ")));
203 o_sRet.append(i_sValue);
204 break;
205 case SQLFilterOperator::GREATER_EQUAL:
206 o_sRet.append(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" >= ")));
207 o_sRet.append(i_sValue);
208 break;
209 case SQLFilterOperator::LIKE:
210 o_sRet.append(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" LIKE ")));
211 o_sRet.append(i_sValue);
212 break;
213 case SQLFilterOperator::NOT_LIKE:
214 o_sRet.append(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" NOT LIKE ")));
215 o_sRet.append(i_sValue);
216 break;
217 case SQLFilterOperator::SQLNULL:
218 o_sRet.append(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" IS NULL")) );
219 break;
220 case SQLFilterOperator::NOT_SQLNULL:
221 o_sRet.append(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" IS NOT NULL")) );
222 break;
223 default:
224 throw SQLException();
230 DBG_NAME(OSingleSelectQueryComposer)
232 OSingleSelectQueryComposer::OSingleSelectQueryComposer(const Reference< XNameAccess>& _rxTables,
233 const Reference< XConnection>& _xConnection,
234 const ::comphelper::ComponentContext& _rContext )
235 :OSubComponent(m_aMutex,_xConnection)
236 ,OPropertyContainer(m_aBHelper)
237 ,m_aSqlParser( _rContext.getUNOContext() )
238 ,m_aSqlIterator( _xConnection, _rxTables, m_aSqlParser, NULL )
239 ,m_aAdditiveIterator( _xConnection, _rxTables, m_aSqlParser, NULL )
240 ,m_aElementaryParts( (size_t)SQLPartCount )
241 ,m_xConnection(_xConnection)
242 ,m_xMetaData(_xConnection->getMetaData())
243 ,m_xConnectionTables( _rxTables )
244 ,m_aContext( _rContext )
245 ,m_pTables(NULL)
246 ,m_nBoolCompareMode( BooleanComparisonMode::EQUAL_INTEGER )
247 ,m_nCommandType(CommandType::COMMAND)
249 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::OSingleSelectQueryComposer" );
250 DBG_CTOR(OSingleSelectQueryComposer,NULL);
252 if ( !m_aContext.is() || !m_xConnection.is() || !m_xConnectionTables.is() )
253 throw IllegalArgumentException();
255 registerProperty(PROPERTY_ORIGINAL,PROPERTY_ID_ORIGINAL,PropertyAttribute::BOUND|PropertyAttribute::READONLY,&m_sOrignal,::getCppuType(&m_sOrignal));
257 m_aCurrentColumns.resize(4);
259 m_aLocale = SvtSysLocale().GetLanguageTag().getLocale();
260 m_xNumberFormatsSupplier = dbtools::getNumberFormats( m_xConnection, sal_True, m_aContext.getLegacyServiceFactory() );
261 Reference< XLocaleData4 > xLocaleData( LocaleData::create(m_aContext.getUNOContext()) );
262 LocaleDataItem aData = xLocaleData->getLocaleItem(m_aLocale);
263 m_sDecimalSep = aData.decimalSeparator;
264 OSL_ENSURE(m_sDecimalSep.getLength() == 1,"OSingleSelectQueryComposer::OSingleSelectQueryComposer decimal separator is not 1 length");
267 Any aValue;
268 Reference<XInterface> xDs = dbaccess::getDataSource(_xConnection);
269 if ( dbtools::getDataSourceSetting(xDs,static_cast <rtl::OUString> (PROPERTY_BOOLEANCOMPARISONMODE),aValue) )
271 OSL_VERIFY( aValue >>= m_nBoolCompareMode );
273 Reference< XQueriesSupplier > xQueriesAccess(m_xConnection, UNO_QUERY);
274 if (xQueriesAccess.is())
275 m_xConnectionQueries = xQueriesAccess->getQueries();
277 catch(Exception&)
282 OSingleSelectQueryComposer::~OSingleSelectQueryComposer()
284 DBG_DTOR(OSingleSelectQueryComposer,NULL);
285 ::std::vector<OPrivateColumns*>::iterator aColIter = m_aColumnsCollection.begin();
286 ::std::vector<OPrivateColumns*>::iterator aEnd = m_aColumnsCollection.end();
287 for(;aColIter != aEnd;++aColIter)
288 delete *aColIter;
290 ::std::vector<OPrivateTables*>::iterator aTabIter = m_aTablesCollection.begin();
291 ::std::vector<OPrivateTables*>::iterator aTabEnd = m_aTablesCollection.end();
292 for(;aTabIter != aTabEnd;++aTabIter)
293 delete *aTabIter;
296 // OComponentHelper
297 void SAL_CALL OSingleSelectQueryComposer::disposing(void)
299 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::disposing" );
300 OSubComponent::disposing();
302 MutexGuard aGuard(m_aMutex);
304 resetIterator( m_aSqlIterator, true );
305 resetIterator( m_aAdditiveIterator, true );
307 m_xConnectionTables = NULL;
308 m_xConnection = NULL;
310 clearCurrentCollections();
312 IMPLEMENT_FORWARD_XINTERFACE3(OSingleSelectQueryComposer,OSubComponent,OSingleSelectQueryComposer_BASE,OPropertyContainer)
313 IMPLEMENT_SERVICE_INFO1(OSingleSelectQueryComposer,"org.openoffice.comp.dba.OSingleSelectQueryComposer",SERVICE_NAME_SINGLESELECTQUERYCOMPOSER.ascii)
314 IMPLEMENT_TYPEPROVIDER3(OSingleSelectQueryComposer,OSubComponent,OSingleSelectQueryComposer_BASE,OPropertyContainer)
315 IMPLEMENT_PROPERTYCONTAINER_DEFAULTS(OSingleSelectQueryComposer)
317 // com::sun::star::lang::XUnoTunnel
318 sal_Int64 SAL_CALL OSingleSelectQueryComposer::getSomething( const Sequence< sal_Int8 >& rId ) throw(RuntimeException)
320 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getSomething" );
321 if (rId.getLength() == 16 && 0 == memcmp(getImplementationId().getConstArray(), rId.getConstArray(), 16 ) )
322 return reinterpret_cast<sal_Int64>(this);
324 return sal_Int64(0);
327 // XSingleSelectQueryAnalyzer
328 ::rtl::OUString SAL_CALL OSingleSelectQueryComposer::getQuery( ) throw(RuntimeException)
330 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getQuery" );
331 ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
332 ::osl::MutexGuard aGuard( m_aMutex );
334 TGetParseNode F_tmp(&OSQLParseTreeIterator::getParseTree);
335 return getStatementPart(F_tmp,m_aSqlIterator);
338 void SAL_CALL OSingleSelectQueryComposer::setQuery( const ::rtl::OUString& command ) throw(SQLException, RuntimeException)
340 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "frank.schoenheit@sun.com", "OSingleSelectQueryComposer::setQuery" );
341 ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
343 ::osl::MutexGuard aGuard( m_aMutex );
344 m_nCommandType = CommandType::COMMAND;
345 // first clear the tables and columns
346 clearCurrentCollections();
347 // now set the new one
348 setQuery_Impl(command);
349 m_sOrignal = command;
351 // reset the additive iterator to the same statement
352 parseAndCheck_throwError( m_aSqlParser, m_sOrignal, m_aAdditiveIterator, *this );
354 // we have no "elementary" parts anymore (means filter/groupby/having/order clauses)
355 for ( SQLPart eLoopParts = Where; eLoopParts != SQLPartCount; incSQLPart( eLoopParts ) )
356 m_aElementaryParts[ eLoopParts ] = ::rtl::OUString();
359 void SAL_CALL OSingleSelectQueryComposer::setCommand( const ::rtl::OUString& Command,sal_Int32 _nCommandType ) throw(SQLException, RuntimeException)
361 ::rtl::OUStringBuffer sSQL;
362 switch(_nCommandType)
364 case CommandType::COMMAND:
365 setElementaryQuery(Command);
366 return;
367 case CommandType::TABLE:
368 if ( m_xConnectionTables->hasByName(Command) )
370 sSQL.appendAscii("SELECT * FROM ");
371 Reference< XPropertySet > xTable;
374 m_xConnectionTables->getByName( Command ) >>= xTable;
376 catch(const WrappedTargetException& e)
378 SQLException e2;
379 if ( e.TargetException >>= e2 )
380 throw e2;
382 catch(Exception&)
384 DBG_UNHANDLED_EXCEPTION();
387 sSQL.append(dbtools::composeTableNameForSelect(m_xConnection,xTable));
389 else
391 String sMessage( DBACORE_RESSTRING( RID_STR_TABLE_DOES_NOT_EXIST ) );
392 sMessage.SearchAndReplaceAscii( "$table$", Command );
393 throwGenericSQLException(sMessage,*this);
395 break;
396 case CommandType::QUERY:
397 if ( m_xConnectionQueries->hasByName(Command) )
400 Reference<XPropertySet> xQuery(m_xConnectionQueries->getByName(Command),UNO_QUERY);
401 ::rtl::OUString sCommand;
402 xQuery->getPropertyValue(PROPERTY_COMMAND) >>= sCommand;
403 sSQL.append(sCommand);
405 else
407 String sMessage( DBACORE_RESSTRING( RID_STR_QUERY_DOES_NOT_EXIST ) );
408 sMessage.SearchAndReplaceAscii( "$table$", Command );
409 throwGenericSQLException(sMessage,*this);
412 break;
413 default:
414 break;
416 ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
418 ::osl::MutexGuard aGuard( m_aMutex );
419 m_nCommandType = _nCommandType;
420 m_sCommand = Command;
421 // first clear the tables and columns
422 clearCurrentCollections();
423 // now set the new one
424 ::rtl::OUString sCommand = sSQL.makeStringAndClear();
425 setElementaryQuery(sCommand);
426 m_sOrignal = sCommand;
429 void OSingleSelectQueryComposer::setQuery_Impl( const ::rtl::OUString& command )
431 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "frank.schoenheit@sun.com", "OSingleSelectQueryComposer::setQuery_Impl" );
432 // parse this
433 parseAndCheck_throwError( m_aSqlParser, command, m_aSqlIterator, *this );
435 // strip it from all clauses, to have the pure SELECT statement
436 m_aPureSelectSQL = getPureSelectStatement( m_aSqlIterator.getParseTree(), m_xConnection );
438 // update tables
439 getTables();
442 Sequence< Sequence< PropertyValue > > SAL_CALL OSingleSelectQueryComposer::getStructuredHavingClause( ) throw (RuntimeException)
444 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getStructuredHavingClause" );
445 TGetParseNode F_tmp(&OSQLParseTreeIterator::getSimpleHavingTree);
446 return getStructuredCondition(F_tmp);
449 Sequence< Sequence< PropertyValue > > SAL_CALL OSingleSelectQueryComposer::getStructuredFilter( ) throw(RuntimeException)
451 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getStructuredFilter" );
452 TGetParseNode F_tmp(&OSQLParseTreeIterator::getSimpleWhereTree);
453 return getStructuredCondition(F_tmp);
456 void SAL_CALL OSingleSelectQueryComposer::appendHavingClauseByColumn( const Reference< XPropertySet >& column, sal_Bool andCriteria,sal_Int32 filterOperator ) throw (SQLException, RuntimeException)
458 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::appendHavingClauseByColumn" );
459 ::std::mem_fun1_t<bool,OSingleSelectQueryComposer,::rtl::OUString> F_tmp(&OSingleSelectQueryComposer::implSetHavingClause);
460 setConditionByColumn(column,andCriteria,F_tmp,filterOperator);
463 void SAL_CALL OSingleSelectQueryComposer::appendFilterByColumn( const Reference< XPropertySet >& column, sal_Bool andCriteria,sal_Int32 filterOperator ) throw(SQLException, RuntimeException)
465 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::appendFilterByColumn" );
466 ::std::mem_fun1_t<bool,OSingleSelectQueryComposer,::rtl::OUString> F_tmp(&OSingleSelectQueryComposer::implSetFilter);
467 setConditionByColumn(column,andCriteria,F_tmp,filterOperator);
470 ::rtl::OUString OSingleSelectQueryComposer::impl_getColumnName_throw(const Reference< XPropertySet >& column)
472 ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
474 getColumns();
475 if ( !column.is()
476 || !m_aCurrentColumns[SelectColumns]
477 || !column->getPropertySetInfo()->hasPropertyByName(PROPERTY_NAME)
480 String sError(DBACORE_RESSTRING(RID_STR_COLUMN_UNKNOWN_PROP));
481 sError.SearchAndReplaceAscii("%value", ::rtl::OUString(PROPERTY_NAME));
482 SQLException aErr(sError,*this,SQLSTATE_GENERAL,1000,Any() );
483 throw SQLException(DBACORE_RESSTRING(RID_STR_COLUMN_NOT_VALID),*this,SQLSTATE_GENERAL,1000,makeAny(aErr) );
486 ::rtl::OUString aName,aNewName;
487 column->getPropertyValue(PROPERTY_NAME) >>= aName;
489 if ( !m_xMetaData->supportsOrderByUnrelated() && m_aCurrentColumns[SelectColumns] && !m_aCurrentColumns[SelectColumns]->hasByName(aName))
491 String sError(DBACORE_RESSTRING(RID_STR_COLUMN_MUST_VISIBLE));
492 sError.SearchAndReplaceAscii("%name", aName);
493 throw SQLException(sError,*this,SQLSTATE_GENERAL,1000,Any() );
496 // Attach filter
497 // Construct SELECT without WHERE and ORDER BY
498 ::rtl::OUString aQuote = m_xMetaData->getIdentifierQuoteString();
499 if ( m_aCurrentColumns[SelectColumns]->hasByName(aName) )
501 Reference<XPropertySet> xColumn;
502 m_aCurrentColumns[SelectColumns]->getByName(aName) >>= xColumn;
503 OSL_ENSURE(xColumn->getPropertySetInfo()->hasPropertyByName(PROPERTY_REALNAME),"Property REALNAME not available!");
504 OSL_ENSURE(xColumn->getPropertySetInfo()->hasPropertyByName(PROPERTY_TABLENAME),"Property TABLENAME not available!");
505 OSL_ENSURE(xColumn->getPropertySetInfo()->hasPropertyByName(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Function"))),"Property FUNCTION not available!");
507 ::rtl::OUString sRealName,sTableName;
508 xColumn->getPropertyValue(PROPERTY_REALNAME) >>= sRealName;
509 xColumn->getPropertyValue(PROPERTY_TABLENAME) >>= sTableName;
510 sal_Bool bFunction = sal_False;
511 xColumn->getPropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Function"))) >>= bFunction;
512 if ( sRealName == aName )
514 if ( bFunction )
515 aNewName = aName;
516 else
518 if(sTableName.indexOf('.',0) != -1)
520 ::rtl::OUString aCatlog,aSchema,aTable;
521 ::dbtools::qualifiedNameComponents(m_xMetaData,sTableName,aCatlog,aSchema,aTable,::dbtools::eInDataManipulation);
522 sTableName = ::dbtools::composeTableName( m_xMetaData, aCatlog, aSchema, aTable, sal_True, ::dbtools::eInDataManipulation );
524 else
525 sTableName = ::dbtools::quoteName(aQuote,sTableName);
527 aNewName = sTableName;
528 aNewName += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("."));
529 aNewName += ::dbtools::quoteName(aQuote,sRealName);
532 else
533 aNewName = ::dbtools::quoteName(aQuote,aName);
535 else
536 aNewName = getTableAlias(column) + ::dbtools::quoteName(aQuote,aName);
537 return aNewName;
540 void SAL_CALL OSingleSelectQueryComposer::appendOrderByColumn( const Reference< XPropertySet >& column, sal_Bool ascending ) throw(SQLException, RuntimeException)
542 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::appendOrderByColumn" );
543 ::osl::MutexGuard aGuard( m_aMutex );
544 ::rtl::OUString sColumnName( impl_getColumnName_throw(column) );
545 ::rtl::OUString sOrder = getOrder();
546 if ( !(sOrder.isEmpty() || sColumnName.isEmpty()) )
547 sOrder += COMMA;
548 sOrder += sColumnName;
549 if ( !(ascending || sColumnName.isEmpty()) )
550 sOrder += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" DESC "));
552 setOrder(sOrder);
555 void SAL_CALL OSingleSelectQueryComposer::appendGroupByColumn( const Reference< XPropertySet >& column) throw(SQLException, RuntimeException)
557 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::appendGroupByColumn" );
558 ::osl::MutexGuard aGuard( m_aMutex );
559 ::rtl::OUString sColumnName( impl_getColumnName_throw(column) );
560 OrderCreator aComposer;
561 aComposer.append( getGroup() );
562 aComposer.append( sColumnName );
563 setGroup( aComposer.getComposedAndClear() );
566 ::rtl::OUString OSingleSelectQueryComposer::composeStatementFromParts( const ::std::vector< ::rtl::OUString >& _rParts )
568 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::composeStatementFromParts" );
569 OSL_ENSURE( _rParts.size() == (size_t)SQLPartCount, "OSingleSelectQueryComposer::composeStatementFromParts: invalid parts array!" );
571 ::rtl::OUStringBuffer aSql( m_aPureSelectSQL );
572 for ( SQLPart eLoopParts = Where; eLoopParts != SQLPartCount; incSQLPart( eLoopParts ) )
573 if ( !_rParts[ eLoopParts ].isEmpty() )
575 aSql.append( getKeyword( eLoopParts ) );
576 aSql.append( _rParts[ eLoopParts ] );
579 return aSql.makeStringAndClear();
582 ::rtl::OUString SAL_CALL OSingleSelectQueryComposer::getElementaryQuery() throw (::com::sun::star::uno::RuntimeException)
584 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getElementaryQuery" );
585 return composeStatementFromParts( m_aElementaryParts );
588 void SAL_CALL OSingleSelectQueryComposer::setElementaryQuery( const ::rtl::OUString& _rElementary ) throw (::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException)
590 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "frank.schoenheit@sun.com", "OSingleSelectQueryComposer::setElementaryQuery" );
591 ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
592 ::osl::MutexGuard aGuard( m_aMutex );
594 // remember the 4 current "additive" clauses
595 ::std::vector< ::rtl::OUString > aAdditiveClauses( SQLPartCount );
596 for ( SQLPart eLoopParts = Where; eLoopParts != SQLPartCount; incSQLPart( eLoopParts ) )
597 aAdditiveClauses[ eLoopParts ] = getSQLPart( eLoopParts, m_aAdditiveIterator, sal_False );
599 // clear the tables and columns
600 clearCurrentCollections();
601 // set and parse the new query
602 setQuery_Impl( _rElementary );
604 // get the 4 elementary parts of the statement
605 for ( SQLPart eLoopParts = Where; eLoopParts != SQLPartCount; incSQLPart( eLoopParts ) )
606 m_aElementaryParts[ eLoopParts ] = getSQLPart( eLoopParts, m_aSqlIterator, sal_False );
608 // reset the the AdditiveIterator: m_aPureSelectSQL may have changed
611 parseAndCheck_throwError( m_aSqlParser, composeStatementFromParts( aAdditiveClauses ), m_aAdditiveIterator, *this );
613 catch( const Exception& e )
615 (void)e;
616 OSL_FAIL( "OSingleSelectQueryComposer::setElementaryQuery: there should be no error anymore for the additive statement!" );
617 DBG_UNHANDLED_EXCEPTION();
618 // every part of the additive statement should have passed other tests already, and should not
619 // be able to cause any errors ... me thinks
623 namespace
625 ::rtl::OUString getComposedClause( const ::rtl::OUString _rElementaryClause, const ::rtl::OUString _rAdditionalClause,
626 TokenComposer& _rComposer, const ::rtl::OUString _rKeyword )
628 _rComposer.clear();
629 _rComposer.append( _rElementaryClause );
630 _rComposer.append( _rAdditionalClause );
631 ::rtl::OUString sComposed = _rComposer.getComposedAndClear();
632 if ( !sComposed.isEmpty() )
633 sComposed = _rKeyword + sComposed;
634 return sComposed;
638 void OSingleSelectQueryComposer::setSingleAdditiveClause( SQLPart _ePart, const ::rtl::OUString& _rClause )
640 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::setSingleAdditiveClause" );
641 ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
642 ::osl::MutexGuard aGuard( m_aMutex );
644 // if nothing is changed, do nothing
645 if ( getSQLPart( _ePart, m_aAdditiveIterator, sal_False ) == _rClause )
646 return;
648 // collect the 4 single parts as they're currently set
649 ::std::vector< ::rtl::OUString > aClauses;
650 aClauses.reserve( (size_t)SQLPartCount );
651 for ( SQLPart eLoopParts = Where; eLoopParts != SQLPartCount; incSQLPart( eLoopParts ) )
652 aClauses.push_back( getSQLPart( eLoopParts, m_aSqlIterator, sal_True ) );
654 // overwrite the one part in question here
655 SAL_WNODEPRECATED_DECLARATIONS_PUSH
656 ::std::auto_ptr< TokenComposer > pComposer;
657 SAL_WNODEPRECATED_DECLARATIONS_POP
658 if ( ( _ePart == Where ) || ( _ePart == Having ) )
659 pComposer.reset( new FilterCreator );
660 else
661 pComposer.reset( new OrderCreator );
662 aClauses[ _ePart ] = getComposedClause( m_aElementaryParts[ _ePart ], _rClause,
663 *pComposer, getKeyword( _ePart ) );
665 // construct the complete statement
666 ::rtl::OUStringBuffer aSql(m_aPureSelectSQL);
667 for ( SQLPart eLoopParts = Where; eLoopParts != SQLPartCount; incSQLPart( eLoopParts ) )
668 aSql.append(aClauses[ eLoopParts ]);
670 // set the query
671 setQuery_Impl(aSql.makeStringAndClear());
673 // clear column collections which (might) have changed
674 clearColumns( ParameterColumns );
675 if ( _ePart == Order )
676 clearColumns( OrderColumns );
677 if ( _ePart == Group )
678 clearColumns( GroupByColumns );
680 // also, since the "additive filter" change, we need to rebuild our "additive" statement
681 aSql = m_aPureSelectSQL;
682 // again, first get all the old additive parts
683 for ( SQLPart eLoopParts = Where; eLoopParts != SQLPartCount; incSQLPart( eLoopParts ) )
684 aClauses[ eLoopParts ] = getSQLPart( eLoopParts, m_aAdditiveIterator, sal_True );
685 // then overwrite the one in question
686 aClauses[ _ePart ] = getComposedClause( ::rtl::OUString(), _rClause, *pComposer, getKeyword( _ePart ) );
687 // and parse it, so that m_aAdditiveIterator is up to date
688 for ( SQLPart eLoopParts = Where; eLoopParts != SQLPartCount; incSQLPart( eLoopParts ) )
689 aSql.append(aClauses[ eLoopParts ]);
692 parseAndCheck_throwError( m_aSqlParser, aSql.makeStringAndClear(), m_aAdditiveIterator, *this );
694 catch( const Exception& e )
696 (void)e;
697 OSL_FAIL( "OSingleSelectQueryComposer::setSingleAdditiveClause: there should be no error anymore for the additive statement!" );
698 // every part of the additive statement should have passed other tests already, and should not
699 // be able to cause any errors ... me thinks
703 void SAL_CALL OSingleSelectQueryComposer::setFilter( const ::rtl::OUString& filter ) throw(SQLException, RuntimeException)
705 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::setFilter" );
706 setSingleAdditiveClause( Where, filter );
709 void SAL_CALL OSingleSelectQueryComposer::setOrder( const ::rtl::OUString& order ) throw(SQLException, RuntimeException)
711 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::setOrder" );
712 setSingleAdditiveClause( Order, order );
715 void SAL_CALL OSingleSelectQueryComposer::setGroup( const ::rtl::OUString& group ) throw (SQLException, RuntimeException)
717 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::setGroup" );
718 setSingleAdditiveClause( Group, group );
721 void SAL_CALL OSingleSelectQueryComposer::setHavingClause( const ::rtl::OUString& filter ) throw(SQLException, RuntimeException)
723 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::setHavingClause" );
724 setSingleAdditiveClause( Having, filter );
727 // XTablesSupplier
728 Reference< XNameAccess > SAL_CALL OSingleSelectQueryComposer::getTables( ) throw(RuntimeException)
730 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getTables" );
731 ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
733 ::osl::MutexGuard aGuard( m_aMutex );
734 if ( !m_pTables )
736 const OSQLTables& aTables = m_aSqlIterator.getTables();
737 ::std::vector< ::rtl::OUString> aNames;
738 OSQLTables::const_iterator aEnd = aTables.end();
739 for(OSQLTables::const_iterator aIter = aTables.begin(); aIter != aEnd;++aIter)
740 aNames.push_back(aIter->first);
742 m_pTables = new OPrivateTables(aTables,m_xMetaData->supportsMixedCaseQuotedIdentifiers(),*this,m_aMutex,aNames);
745 return m_pTables;
748 // XColumnsSupplier
749 Reference< XNameAccess > SAL_CALL OSingleSelectQueryComposer::getColumns( ) throw(RuntimeException)
751 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getColumns" );
752 ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
753 ::osl::MutexGuard aGuard( m_aMutex );
754 if ( !!m_aCurrentColumns[SelectColumns] )
755 return m_aCurrentColumns[SelectColumns];
757 ::std::vector< ::rtl::OUString> aNames;
758 ::rtl::Reference< OSQLColumns> aSelectColumns;
759 sal_Bool bCase = sal_True;
760 Reference< XNameAccess> xQueryColumns;
761 if ( m_nCommandType == CommandType::QUERY )
763 Reference<XColumnsSupplier> xSup(m_xConnectionQueries->getByName(m_sCommand),UNO_QUERY);
764 if(xSup.is())
765 xQueryColumns = xSup->getColumns();
768 do {
772 SharedUNOComponent< XStatement, DisposableComponent > xStatement;
773 SharedUNOComponent< XPreparedStatement, DisposableComponent > xPreparedStatement;
775 bCase = m_xMetaData->supportsMixedCaseQuotedIdentifiers();
776 aSelectColumns = m_aSqlIterator.getSelectColumns();
778 ::rtl::OUStringBuffer aSQL;
779 aSQL.append( m_aPureSelectSQL );
780 aSQL.append( STR_WHERE );
782 // preserve the original WHERE clause
783 // #i102234#
784 ::rtl::OUString sOriginalWhereClause = getSQLPart( Where, m_aSqlIterator, sal_False );
785 if ( !sOriginalWhereClause.isEmpty() )
787 aSQL.appendAscii( " ( 0 = 1 ) AND ( " );
788 aSQL.append( sOriginalWhereClause );
789 aSQL.appendAscii( " ) " );
791 else
793 aSQL.appendAscii( " ( 0 = 1 ) " );
796 ::rtl::OUString sGroupBy = getSQLPart( Group, m_aSqlIterator, sal_True );
797 if ( !sGroupBy.isEmpty() )
798 aSQL.append( sGroupBy );
800 ::rtl::OUString sSQL( aSQL.makeStringAndClear() );
801 // normalize the statement so that it doesn't contain any application-level features anymore
802 ::rtl::OUString sError;
803 SAL_WNODEPRECATED_DECLARATIONS_PUSH
804 const ::std::auto_ptr< OSQLParseNode > pStatementTree( m_aSqlParser.parseTree( sError, sSQL, false ) );
805 SAL_WNODEPRECATED_DECLARATIONS_POP
806 OSL_ENSURE( pStatementTree.get(), "OSingleSelectQueryComposer::getColumns: could not parse the column retrieval statement!" );
807 if ( pStatementTree.get() )
808 if ( !pStatementTree->parseNodeToExecutableStatement( sSQL, m_xConnection, m_aSqlParser, NULL ) )
809 break;
811 Reference< XResultSetMetaData > xResultSetMeta;
812 Reference< XResultSetMetaDataSupplier > xResMetaDataSup;
815 xPreparedStatement.set( m_xConnection->prepareStatement( sSQL ), UNO_QUERY_THROW );
816 xResMetaDataSup.set( xPreparedStatement, UNO_QUERY_THROW );
817 xResultSetMeta.set( xResMetaDataSup->getMetaData(), UNO_QUERY_THROW );
819 catch( const Exception& ) { }
823 if ( !xResultSetMeta.is() )
825 xStatement.reset( Reference< XStatement >( m_xConnection->createStatement(), UNO_QUERY_THROW ) );
826 Reference< XPropertySet > xStatementProps( xStatement, UNO_QUERY_THROW );
827 try { xStatementProps->setPropertyValue( PROPERTY_ESCAPE_PROCESSING, makeAny( sal_False ) ); }
828 catch ( const Exception& ) { DBG_UNHANDLED_EXCEPTION(); }
829 xResMetaDataSup.set( xStatement->executeQuery( sSQL ), UNO_QUERY_THROW );
830 xResultSetMeta.set( xResMetaDataSup->getMetaData(), UNO_QUERY_THROW );
833 catch( const Exception& )
835 //@see issue http://qa.openoffice.org/issues/show_bug.cgi?id=110111
836 // access returns a different order of column names when executing select * from
837 // and asking the columns from the metadata.
838 Reference< XParameters > xParameters( xPreparedStatement, UNO_QUERY_THROW );
839 Reference< XIndexAccess > xPara = getParameters();
840 for(sal_Int32 i = 1;i <= xPara->getCount();++i)
841 xParameters->setNull(i,DataType::VARCHAR);
842 xResMetaDataSup.set(xPreparedStatement->executeQuery(), UNO_QUERY_THROW );
843 xResultSetMeta.set( xResMetaDataSup->getMetaData(), UNO_QUERY_THROW );
846 if ( aSelectColumns->get().empty() )
848 // This is a valid case. If we can syntactically parse the query, but not semantically
849 // (e.g. because it is based on a table we do not know), then there will be no SelectColumns
850 aSelectColumns = ::connectivity::parse::OParseColumn::createColumnsForResultSet( xResultSetMeta, m_xMetaData ,xQueryColumns);
851 break;
854 const ::comphelper::UStringMixEqual aCaseCompare( bCase );
855 const ::comphelper::TStringMixEqualFunctor aCaseCompareFunctor( bCase );
856 typedef ::std::set< size_t > SizeTSet;
857 SizeTSet aUsedSelectColumns;
858 ::connectivity::parse::OParseColumn::StringMap aColumnNames;
860 sal_Int32 nCount = xResultSetMeta->getColumnCount();
861 OSL_ENSURE( (size_t) nCount == aSelectColumns->get().size(), "OSingleSelectQueryComposer::getColumns: inconsistent column counts, this might result in wrong columns!" );
862 for(sal_Int32 i=1;i<=nCount;++i)
864 ::rtl::OUString sColumnName = xResultSetMeta->getColumnName(i);
865 ::rtl::OUString sColumnLabel;
866 if ( xQueryColumns.is() && xQueryColumns->hasByName(sColumnName) )
868 Reference<XPropertySet> xQueryColumn(xQueryColumns->getByName(sColumnName),UNO_QUERY_THROW);
869 xQueryColumn->getPropertyValue(PROPERTY_LABEL) >>= sColumnLabel;
871 else
872 sColumnLabel = xResultSetMeta->getColumnLabel(i);
873 sal_Bool bFound = sal_False;
874 OSQLColumns::Vector::const_iterator aFind = ::connectivity::find(aSelectColumns->get().begin(),aSelectColumns->get().end(),sColumnLabel,aCaseCompare);
875 size_t nFoundSelectColumnPos = aFind - aSelectColumns->get().begin();
876 if ( aFind != aSelectColumns->get().end() )
878 if ( aUsedSelectColumns.find( nFoundSelectColumnPos ) != aUsedSelectColumns.end() )
879 { // we found a column name which exists twice
880 // so we start after the first found
883 aFind = ::connectivity::findRealName(++aFind,aSelectColumns->get().end(),sColumnName,aCaseCompare);
884 nFoundSelectColumnPos = aFind - aSelectColumns->get().begin();
886 while ( ( aUsedSelectColumns.find( nFoundSelectColumnPos ) != aUsedSelectColumns.end() )
887 && ( aFind != aSelectColumns->get().end() )
890 if ( aFind != aSelectColumns->get().end() )
892 (*aFind)->getPropertyValue(PROPERTY_NAME) >>= sColumnName;
893 aUsedSelectColumns.insert( nFoundSelectColumnPos );
894 aNames.push_back(sColumnName);
895 bFound = sal_True;
899 if ( bFound )
900 continue;
902 OSQLColumns::Vector::const_iterator aRealFind = ::connectivity::findRealName(
903 aSelectColumns->get().begin(), aSelectColumns->get().end(), sColumnName, aCaseCompare );
905 if ( i > static_cast< sal_Int32>( aSelectColumns->get().size() ) )
907 aSelectColumns->get().push_back(
908 ::connectivity::parse::OParseColumn::createColumnForResultSet( xResultSetMeta, m_xMetaData, i ,aColumnNames)
910 OSL_ENSURE( aSelectColumns->get().size() == (size_t)i, "OSingleSelectQueryComposer::getColumns: inconsistency!" );
912 else if ( aRealFind == aSelectColumns->get().end() )
914 // we can now only look if we found it under the realname propertery
915 // here we have to make the assumption that the position is correct
916 OSQLColumns::Vector::iterator aFind2 = aSelectColumns->get().begin() + i-1;
917 Reference<XPropertySet> xProp(*aFind2,UNO_QUERY);
918 if ( !xProp.is() || !xProp->getPropertySetInfo()->hasPropertyByName( PROPERTY_REALNAME ) )
919 continue;
921 ::connectivity::parse::OParseColumn* pColumn = new ::connectivity::parse::OParseColumn(xProp,bCase);
922 pColumn->setFunction(::comphelper::getBOOL(xProp->getPropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Function")))));
923 pColumn->setAggregateFunction(::comphelper::getBOOL(xProp->getPropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("AggregateFunction")))));
925 ::rtl::OUString sRealName;
926 xProp->getPropertyValue(PROPERTY_REALNAME) >>= sRealName;
927 ::std::vector< ::rtl::OUString>::iterator aFindName;
928 if ( sColumnName.isEmpty() )
929 xProp->getPropertyValue(PROPERTY_NAME) >>= sColumnName;
931 aFindName = ::std::find_if(aNames.begin(),aNames.end(),::std::bind2nd(aCaseCompareFunctor,sColumnName));
932 sal_Int32 j = 0;
933 while ( aFindName != aNames.end() )
935 sColumnName += ::rtl::OUString::valueOf(++j);
936 aFindName = ::std::find_if(aNames.begin(),aNames.end(),::std::bind2nd(aCaseCompareFunctor,sColumnName));
939 pColumn->setName(sColumnName);
940 pColumn->setRealName(sRealName);
941 pColumn->setTableName(::comphelper::getString(xProp->getPropertyValue(PROPERTY_TABLENAME)));
943 (aSelectColumns->get())[i-1] = pColumn;
945 else
946 continue;
948 aUsedSelectColumns.insert( (size_t)(i - 1) );
949 aNames.push_back( sColumnName );
952 catch(const Exception&)
956 } while ( false );
958 if ( aNames.empty() )
959 m_aCurrentColumns[ SelectColumns ] = OPrivateColumns::createWithIntrinsicNames( aSelectColumns, bCase, *this, m_aMutex );
960 else
961 m_aCurrentColumns[ SelectColumns ] = new OPrivateColumns( aSelectColumns, bCase, *this, m_aMutex, aNames );
963 return m_aCurrentColumns[SelectColumns];
966 sal_Bool OSingleSelectQueryComposer::setORCriteria(OSQLParseNode* pCondition, OSQLParseTreeIterator& _rIterator,
967 ::std::vector< ::std::vector < PropertyValue > >& rFilters, const Reference< ::com::sun::star::util::XNumberFormatter > & xFormatter) const
969 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::setORCriteria" );
970 // Round brackets around the expression
971 if (pCondition->count() == 3 &&
972 SQL_ISPUNCTUATION(pCondition->getChild(0),"(") &&
973 SQL_ISPUNCTUATION(pCondition->getChild(2),")"))
975 return setORCriteria(pCondition->getChild(1), _rIterator, rFilters, xFormatter);
977 // OR logic expression
978 // a searchcondition can only look like this: search_condition SQL_TOKEN_OR boolean_term
979 else if (SQL_ISRULE(pCondition,search_condition))
981 sal_Bool bResult = sal_True;
982 for (int i = 0; bResult && i < 3; i+=2)
984 // Is the first element a OR logic expression again?
985 // Then descend recursively ...
986 if (SQL_ISRULE(pCondition->getChild(i),search_condition))
987 bResult = setORCriteria(pCondition->getChild(i), _rIterator, rFilters, xFormatter);
988 else
990 rFilters.push_back( ::std::vector < PropertyValue >());
991 bResult = setANDCriteria(pCondition->getChild(i), _rIterator, rFilters[rFilters.size() - 1], xFormatter);
994 return bResult;
996 else
998 rFilters.push_back(::std::vector < PropertyValue >());
999 return setANDCriteria(pCondition, _rIterator, rFilters[rFilters.size() - 1], xFormatter);
1003 sal_Bool OSingleSelectQueryComposer::setANDCriteria( OSQLParseNode * pCondition,
1004 OSQLParseTreeIterator& _rIterator, ::std::vector < PropertyValue >& rFilter, const Reference< XNumberFormatter > & xFormatter) const
1006 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::setANDCriteria" );
1007 // Round brackets
1008 if (SQL_ISRULE(pCondition,boolean_primary))
1010 // this should not occur
1011 OSL_FAIL("boolean_primary in And-Criteria");
1012 return sal_False;
1014 // The first element is an AND logical expression again
1015 else if ( SQL_ISRULE(pCondition,boolean_term) && pCondition->count() == 3 )
1017 return setANDCriteria(pCondition->getChild(0), _rIterator, rFilter, xFormatter) &&
1018 setANDCriteria(pCondition->getChild(2), _rIterator, rFilter, xFormatter);
1020 else if (SQL_ISRULE(pCondition, comparison_predicate))
1022 return setComparsionPredicate(pCondition,_rIterator,rFilter,xFormatter);
1024 else if (SQL_ISRULE(pCondition,like_predicate) ||
1025 SQL_ISRULE(pCondition,test_for_null) ||
1026 SQL_ISRULE(pCondition,in_predicate) ||
1027 SQL_ISRULE(pCondition,all_or_any_predicate) ||
1028 SQL_ISRULE(pCondition,between_predicate))
1030 if (SQL_ISRULE(pCondition->getChild(0), column_ref))
1032 PropertyValue aItem;
1033 ::rtl::OUString aValue;
1034 ::rtl::OUString aColumnName;
1037 pCondition->parseNodeToStr( aValue, m_xConnection, NULL );
1038 pCondition->getChild(0)->parseNodeToStr( aColumnName, m_xConnection, NULL );
1040 // don't display the column name
1041 aValue = aValue.copy(aColumnName.getLength());
1042 aValue = aValue.trim();
1044 aItem.Name = getColumnName(pCondition->getChild(0),_rIterator);
1045 aItem.Value <<= aValue;
1046 aItem.Handle = 0; // just to know that this is not one the known ones
1047 if ( SQL_ISRULE(pCondition,like_predicate) )
1049 if ( SQL_ISTOKEN(pCondition->getChild(1)->getChild(0),NOT) )
1050 aItem.Handle = SQLFilterOperator::NOT_LIKE;
1051 else
1052 aItem.Handle = SQLFilterOperator::LIKE;
1054 else if (SQL_ISRULE(pCondition,test_for_null))
1056 if (SQL_ISTOKEN(pCondition->getChild(1)->getChild(1),NOT) )
1057 aItem.Handle = SQLFilterOperator::NOT_SQLNULL;
1058 else
1059 aItem.Handle = SQLFilterOperator::SQLNULL;
1061 else if (SQL_ISRULE(pCondition,in_predicate))
1063 OSL_FAIL( "OSingleSelectQueryComposer::setANDCriteria: in_predicate not implemented!" );
1065 else if (SQL_ISRULE(pCondition,all_or_any_predicate))
1067 OSL_FAIL( "OSingleSelectQueryComposer::setANDCriteria: all_or_any_predicate not implemented!" );
1069 else if (SQL_ISRULE(pCondition,between_predicate))
1071 OSL_FAIL( "OSingleSelectQueryComposer::setANDCriteria: between_predicate not implemented!" );
1074 rFilter.push_back(aItem);
1076 else
1077 return sal_False;
1079 else if (SQL_ISRULE(pCondition,existence_test) ||
1080 SQL_ISRULE(pCondition,unique_test))
1082 // this couldn't be handled here, too complex
1083 // as we need a field name
1084 return sal_False;
1086 else
1087 return sal_False;
1089 return sal_True;
1092 sal_Int32 OSingleSelectQueryComposer::getPredicateType(OSQLParseNode * _pPredicate) const
1094 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getPredicateType" );
1095 sal_Int32 nPredicate = SQLFilterOperator::EQUAL;
1096 switch (_pPredicate->getNodeType())
1098 case SQL_NODE_EQUAL:
1099 nPredicate = SQLFilterOperator::EQUAL;
1100 break;
1101 case SQL_NODE_NOTEQUAL:
1102 nPredicate = SQLFilterOperator::NOT_EQUAL;
1103 break;
1104 case SQL_NODE_LESS:
1105 nPredicate = SQLFilterOperator::LESS;
1106 break;
1107 case SQL_NODE_LESSEQ:
1108 nPredicate = SQLFilterOperator::LESS_EQUAL;
1109 break;
1110 case SQL_NODE_GREAT:
1111 nPredicate = SQLFilterOperator::GREATER;
1112 break;
1113 case SQL_NODE_GREATEQ:
1114 nPredicate = SQLFilterOperator::GREATER_EQUAL;
1115 break;
1116 default:
1117 OSL_FAIL("Wrong NodeType!");
1119 return nPredicate;
1122 sal_Bool OSingleSelectQueryComposer::setComparsionPredicate(OSQLParseNode * pCondition, OSQLParseTreeIterator& _rIterator,
1123 ::std::vector < PropertyValue >& rFilter, const Reference< ::com::sun::star::util::XNumberFormatter > & xFormatter) const
1125 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::setComparsionPredicate" );
1126 OSL_ENSURE(SQL_ISRULE(pCondition, comparison_predicate),"setComparsionPredicate: pCondition ist kein ComparsionPredicate");
1127 if (SQL_ISRULE(pCondition->getChild(0), column_ref) ||
1128 SQL_ISRULE(pCondition->getChild(pCondition->count()-1), column_ref))
1130 PropertyValue aItem;
1131 ::rtl::OUString aValue;
1132 sal_uInt32 nPos;
1133 if (SQL_ISRULE(pCondition->getChild(0), column_ref))
1135 nPos = 0;
1136 sal_uInt32 i=1;
1138 aItem.Handle = getPredicateType(pCondition->getChild(i));
1139 // don't display the equal
1140 if (pCondition->getChild(i)->getNodeType() == SQL_NODE_EQUAL)
1141 i++;
1143 // go forward
1144 for (;i < pCondition->count();i++)
1145 pCondition->getChild(i)->parseNodeToPredicateStr(
1146 aValue, m_xConnection, xFormatter, m_aLocale, static_cast<sal_Char>(m_sDecimalSep.toChar() ) );
1148 else if (SQL_ISRULE(pCondition->getChild(pCondition->count()-1), column_ref))
1150 nPos = pCondition->count()-1;
1152 sal_Int32 i = pCondition->count() - 2;
1153 switch (pCondition->getChild(i)->getNodeType())
1155 case SQL_NODE_EQUAL:
1156 // don't display the equal
1157 i--;
1158 aItem.Handle = SQLFilterOperator::EQUAL;
1159 break;
1160 case SQL_NODE_NOTEQUAL:
1161 i--;
1162 aItem.Handle = SQLFilterOperator::NOT_EQUAL;
1163 break;
1164 case SQL_NODE_LESS:
1165 // take the opposite as we change the order
1166 i--;
1167 aValue = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(">="));
1168 aItem.Handle = SQLFilterOperator::GREATER_EQUAL;
1169 break;
1170 case SQL_NODE_LESSEQ:
1171 // take the opposite as we change the order
1172 i--;
1173 aValue = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(">"));
1174 aItem.Handle = SQLFilterOperator::GREATER;
1175 break;
1176 case SQL_NODE_GREAT:
1177 // take the opposite as we change the order
1178 i--;
1179 aValue = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("<="));
1180 aItem.Handle = SQLFilterOperator::LESS_EQUAL;
1181 break;
1182 case SQL_NODE_GREATEQ:
1183 // take the opposite as we change the order
1184 i--;
1185 aValue = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("<"));
1186 aItem.Handle = SQLFilterOperator::LESS;
1187 break;
1188 default:
1189 break;
1192 // go backward
1193 for (; i >= 0; i--)
1194 pCondition->getChild(i)->parseNodeToPredicateStr(
1195 aValue, m_xConnection, xFormatter, m_aLocale, static_cast<sal_Char>( m_sDecimalSep.toChar() ) );
1197 else
1198 return sal_False;
1200 aItem.Name = getColumnName(pCondition->getChild(nPos),_rIterator);
1201 aItem.Value <<= aValue;
1202 rFilter.push_back(aItem);
1204 else if (SQL_ISRULE(pCondition->getChild(0), set_fct_spec ) ||
1205 SQL_ISRULE(pCondition->getChild(0), general_set_fct))
1207 PropertyValue aItem;
1208 ::rtl::OUString aValue;
1209 ::rtl::OUString aColumnName;
1211 pCondition->getChild(2)->parseNodeToPredicateStr(aValue, m_xConnection, xFormatter, m_aLocale, static_cast<sal_Char>( m_sDecimalSep.toChar() ) );
1212 pCondition->getChild(0)->parseNodeToPredicateStr( aColumnName, m_xConnection, xFormatter, m_aLocale, static_cast<sal_Char>( m_sDecimalSep .toChar() ) );
1214 aItem.Name = getColumnName(pCondition->getChild(0),_rIterator);
1215 aItem.Value <<= aValue;
1216 aItem.Handle = getPredicateType(pCondition->getChild(1));
1217 rFilter.push_back(aItem);
1219 else // Can only be an expression
1221 PropertyValue aItem;
1222 ::rtl::OUString aName, aValue;
1224 OSQLParseNode *pLhs = pCondition->getChild(0);
1225 OSQLParseNode *pRhs = pCondition->getChild(2);
1227 // Field names
1228 sal_uInt16 i;
1229 for (i=0;i< pLhs->count();i++)
1230 pLhs->getChild(i)->parseNodeToPredicateStr( aName, m_xConnection, xFormatter, m_aLocale, static_cast<sal_Char>( m_sDecimalSep.toChar() ) );
1232 // Criterion
1233 aItem.Handle = getPredicateType(pCondition->getChild(1));
1234 aValue = pCondition->getChild(1)->getTokenValue();
1235 for(i=0;i< pRhs->count();i++)
1236 pRhs->getChild(i)->parseNodeToPredicateStr(aValue, m_xConnection, xFormatter, m_aLocale, static_cast<sal_Char>( m_sDecimalSep.toChar() ) );
1238 aItem.Name = aName;
1239 aItem.Value <<= aValue;
1240 rFilter.push_back(aItem);
1242 return sal_True;
1245 // Functions for analysing SQL
1246 ::rtl::OUString OSingleSelectQueryComposer::getColumnName( ::connectivity::OSQLParseNode* pColumnRef, OSQLParseTreeIterator& _rIterator ) const
1248 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getColumnName" );
1249 ::rtl::OUString aTableRange, aColumnName;
1250 _rIterator.getColumnRange(pColumnRef,aColumnName,aTableRange);
1251 return aColumnName;
1254 ::rtl::OUString SAL_CALL OSingleSelectQueryComposer::getFilter( ) throw(RuntimeException)
1256 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getFilter" );
1257 ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
1258 ::osl::MutexGuard aGuard( m_aMutex );
1259 return getSQLPart(Where,m_aAdditiveIterator,sal_False);
1262 ::rtl::OUString SAL_CALL OSingleSelectQueryComposer::getOrder( ) throw(RuntimeException)
1264 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getOrder" );
1265 ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
1266 ::osl::MutexGuard aGuard( m_aMutex );
1267 return getSQLPart(Order,m_aAdditiveIterator,sal_False);
1270 ::rtl::OUString SAL_CALL OSingleSelectQueryComposer::getGroup( ) throw (RuntimeException)
1272 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getGroup" );
1273 ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
1274 ::osl::MutexGuard aGuard( m_aMutex );
1275 return getSQLPart(Group,m_aAdditiveIterator,sal_False);
1278 ::rtl::OUString OSingleSelectQueryComposer::getHavingClause() throw (RuntimeException)
1280 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getHavingClause" );
1281 ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
1282 ::osl::MutexGuard aGuard( m_aMutex );
1283 return getSQLPart(Having,m_aAdditiveIterator,sal_False);
1286 ::rtl::OUString OSingleSelectQueryComposer::getTableAlias(const Reference< XPropertySet >& column) const
1288 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getTableAlias" );
1289 ::rtl::OUString sReturn;
1290 if(m_pTables && m_pTables->getCount() > 1)
1292 ::rtl::OUString aCatalog,aSchema,aTable,aComposedName,aColumnName;
1293 if(column->getPropertySetInfo()->hasPropertyByName(PROPERTY_CATALOGNAME))
1294 column->getPropertyValue(PROPERTY_CATALOGNAME) >>= aCatalog;
1295 if(column->getPropertySetInfo()->hasPropertyByName(PROPERTY_SCHEMANAME))
1296 column->getPropertyValue(PROPERTY_SCHEMANAME) >>= aSchema;
1297 if(column->getPropertySetInfo()->hasPropertyByName(PROPERTY_TABLENAME))
1298 column->getPropertyValue(PROPERTY_TABLENAME) >>= aTable;
1299 column->getPropertyValue(PROPERTY_NAME) >>= aColumnName;
1301 Sequence< ::rtl::OUString> aNames(m_pTables->getElementNames());
1302 const ::rtl::OUString* pBegin = aNames.getConstArray();
1303 const ::rtl::OUString* pEnd = pBegin + aNames.getLength();
1305 if(aTable.isEmpty())
1306 { // we haven't found a table name, now we must search every table for this column
1307 for(;pBegin != pEnd;++pBegin)
1309 Reference<XColumnsSupplier> xColumnsSupp;
1310 m_pTables->getByName(*pBegin) >>= xColumnsSupp;
1312 if(xColumnsSupp.is() && xColumnsSupp->getColumns()->hasByName(aColumnName))
1314 aTable = *pBegin;
1315 break;
1319 else
1321 aComposedName = ::dbtools::composeTableName( m_xMetaData, aCatalog, aSchema, aTable, sal_False, ::dbtools::eInDataManipulation );
1323 // first check if this is the table we want to or has it a tablealias
1325 if(!m_pTables->hasByName(aComposedName))
1327 ::comphelper::UStringMixLess aTmp(m_aAdditiveIterator.getTables().key_comp());
1328 ::comphelper::UStringMixEqual aComp(static_cast< ::comphelper::UStringMixLess*>(&aTmp)->isCaseSensitive());
1329 for(;pBegin != pEnd;++pBegin)
1331 Reference<XPropertySet> xTableProp;
1332 m_pTables->getByName(*pBegin) >>= xTableProp;
1333 OSL_ENSURE(xTableProp.is(),"Table isn't a propertyset!");
1334 if(xTableProp.is())
1336 ::rtl::OUString aCatalog2,aSchema2,aTable2;
1337 xTableProp->getPropertyValue(PROPERTY_CATALOGNAME) >>= aCatalog2;
1338 xTableProp->getPropertyValue(PROPERTY_SCHEMANAME) >>= aSchema2;
1339 xTableProp->getPropertyValue(PROPERTY_NAME) >>= aTable2;
1340 if(aComp(aCatalog,aCatalog2) && aComp(aSchema,aSchema2) && aComp(aTable,aTable2))
1342 aCatalog = aCatalog2;
1343 aSchema = aSchema2;
1344 aTable = aTable2;
1345 break;
1351 if(pBegin != pEnd)
1353 sReturn = ::dbtools::composeTableName( m_xMetaData, aCatalog, aSchema, aTable, sal_True, ::dbtools::eInDataManipulation );
1354 sReturn += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("."));
1357 return sReturn;
1360 Reference< XIndexAccess > SAL_CALL OSingleSelectQueryComposer::getParameters( ) throw(RuntimeException)
1362 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getParameters" );
1363 // now set the Parameters
1364 if ( !m_aCurrentColumns[ParameterColumns] )
1366 ::rtl::Reference< OSQLColumns> aCols = m_aSqlIterator.getParameters();
1367 ::std::vector< ::rtl::OUString> aNames;
1368 OSQLColumns::Vector::const_iterator aEnd = aCols->get().end();
1369 for(OSQLColumns::Vector::const_iterator aIter = aCols->get().begin(); aIter != aEnd;++aIter)
1370 aNames.push_back(getString((*aIter)->getPropertyValue(PROPERTY_NAME)));
1371 m_aCurrentColumns[ParameterColumns] = new OPrivateColumns(aCols,m_xMetaData->supportsMixedCaseQuotedIdentifiers(),*this,m_aMutex,aNames,sal_True);
1374 return m_aCurrentColumns[ParameterColumns];
1377 void OSingleSelectQueryComposer::clearColumns( const EColumnType _eType )
1379 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::clearColumns" );
1380 OPrivateColumns* pColumns = m_aCurrentColumns[ _eType ];
1381 if ( pColumns != NULL )
1383 pColumns->disposing();
1384 m_aColumnsCollection.push_back( pColumns );
1385 m_aCurrentColumns[ _eType ] = NULL;
1389 void OSingleSelectQueryComposer::clearCurrentCollections()
1391 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::clearCurrentCollections" );
1392 ::std::vector<OPrivateColumns*>::iterator aIter = m_aCurrentColumns.begin();
1393 ::std::vector<OPrivateColumns*>::iterator aEnd = m_aCurrentColumns.end();
1394 for (;aIter != aEnd;++aIter)
1396 if ( *aIter )
1398 (*aIter)->disposing();
1399 m_aColumnsCollection.push_back(*aIter);
1400 *aIter = NULL;
1404 if(m_pTables)
1406 m_pTables->disposing();
1407 m_aTablesCollection.push_back(m_pTables);
1408 m_pTables = NULL;
1412 Reference< XIndexAccess > OSingleSelectQueryComposer::setCurrentColumns( EColumnType _eType,
1413 const ::rtl::Reference< OSQLColumns >& _rCols )
1415 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::setCurrentColumns" );
1416 ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
1418 ::osl::MutexGuard aGuard( m_aMutex );
1419 // now set the group columns
1420 if ( !m_aCurrentColumns[_eType] )
1422 ::std::vector< ::rtl::OUString> aNames;
1423 OSQLColumns::Vector::const_iterator aEnd = _rCols->get().end();
1424 for(OSQLColumns::Vector::const_iterator aIter = _rCols->get().begin(); aIter != aEnd;++aIter)
1425 aNames.push_back(getString((*aIter)->getPropertyValue(PROPERTY_NAME)));
1426 m_aCurrentColumns[_eType] = new OPrivateColumns(_rCols,m_xMetaData->supportsMixedCaseQuotedIdentifiers(),*this,m_aMutex,aNames,sal_True);
1429 return m_aCurrentColumns[_eType];
1432 Reference< XIndexAccess > SAL_CALL OSingleSelectQueryComposer::getGroupColumns( ) throw(RuntimeException)
1434 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getGroupColumns" );
1435 return setCurrentColumns( GroupByColumns, m_aAdditiveIterator.getGroupColumns() );
1438 Reference< XIndexAccess > SAL_CALL OSingleSelectQueryComposer::getOrderColumns( ) throw(RuntimeException)
1440 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getOrderColumns" );
1441 return setCurrentColumns( OrderColumns, m_aAdditiveIterator.getOrderColumns() );
1444 ::rtl::OUString SAL_CALL OSingleSelectQueryComposer::getQueryWithSubstitution( ) throw (SQLException, RuntimeException)
1446 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getQueryWithSubstitution" );
1447 ::osl::MutexGuard aGuard( m_aMutex );
1448 ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
1450 ::rtl::OUString sSqlStatement( getQuery() );
1452 const OSQLParseNode* pStatementNode = m_aSqlIterator.getParseTree();
1453 if ( pStatementNode )
1455 SQLException aError;
1456 if ( !pStatementNode->parseNodeToExecutableStatement( sSqlStatement, m_xConnection, m_aSqlParser, &aError ) )
1457 throw SQLException( aError );
1460 return sSqlStatement;
1463 ::rtl::OUString OSingleSelectQueryComposer::getStatementPart( TGetParseNode& _aGetFunctor, OSQLParseTreeIterator& _rIterator )
1465 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getStatementPart" );
1466 ::rtl::OUString sResult;
1468 const OSQLParseNode* pNode = _aGetFunctor( &_rIterator );
1469 if ( pNode )
1470 pNode->parseNodeToStr( sResult, m_xConnection );
1472 return sResult;
1475 namespace
1477 ::rtl::OUString lcl_getCondition(const Sequence< Sequence< PropertyValue > >& filter,const OPredicateInputController& i_aPredicateInputController,const Reference< XNameAccess >& i_xSelectColumns)
1479 ::rtl::OUStringBuffer sRet;
1480 const Sequence< PropertyValue >* pOrIter = filter.getConstArray();
1481 const Sequence< PropertyValue >* pOrEnd = pOrIter + filter.getLength();
1482 while ( pOrIter != pOrEnd )
1484 if ( pOrIter->getLength() )
1486 sRet.append(L_BRACKET);
1487 const PropertyValue* pAndIter = pOrIter->getConstArray();
1488 const PropertyValue* pAndEnd = pAndIter + pOrIter->getLength();
1489 while ( pAndIter != pAndEnd )
1491 sRet.append(pAndIter->Name);
1492 ::rtl::OUString sValue;
1493 pAndIter->Value >>= sValue;
1494 if ( i_xSelectColumns.is() && i_xSelectColumns->hasByName(pAndIter->Name) )
1496 Reference<XPropertySet> xColumn(i_xSelectColumns->getByName(pAndIter->Name),UNO_QUERY);
1497 sValue = i_aPredicateInputController.getPredicateValue(sValue,xColumn,sal_True);
1499 else
1501 sValue = i_aPredicateInputController.getPredicateValue(pAndIter->Name,sValue,sal_True);
1503 lcl_addFilterCriteria_throw(pAndIter->Handle,sValue,sRet);
1504 ++pAndIter;
1505 if ( pAndIter != pAndEnd )
1506 sRet.append(STR_AND);
1508 sRet.append(R_BRACKET);
1510 ++pOrIter;
1511 if ( pOrIter != pOrEnd && sRet.getLength() )
1512 sRet.append(STR_OR);
1514 return sRet.makeStringAndClear();
1518 void SAL_CALL OSingleSelectQueryComposer::setStructuredFilter( const Sequence< Sequence< PropertyValue > >& filter ) throw (SQLException, ::com::sun::star::lang::IllegalArgumentException, RuntimeException)
1520 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::setStructuredFilter" );
1521 OPredicateInputController aPredicateInput(m_aContext.getUNOContext(),m_xConnection);
1522 setFilter(lcl_getCondition(filter,aPredicateInput,getColumns()));
1525 void SAL_CALL OSingleSelectQueryComposer::setStructuredHavingClause( const Sequence< Sequence< PropertyValue > >& filter ) throw (SQLException, RuntimeException)
1527 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::setStructuredHavingClause" );
1528 OPredicateInputController aPredicateInput(m_aContext.getUNOContext(),m_xConnection);
1529 setHavingClause(lcl_getCondition(filter,aPredicateInput,getColumns()));
1532 void OSingleSelectQueryComposer::setConditionByColumn( const Reference< XPropertySet >& column, sal_Bool andCriteria ,::std::mem_fun1_t<bool,OSingleSelectQueryComposer,::rtl::OUString>& _aSetFunctor,sal_Int32 filterOperator)
1534 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::setConditionByColumn" );
1535 ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
1537 if ( !column.is()
1538 || !column->getPropertySetInfo()->hasPropertyByName(PROPERTY_VALUE)
1539 || !column->getPropertySetInfo()->hasPropertyByName(PROPERTY_NAME)
1540 || !column->getPropertySetInfo()->hasPropertyByName(PROPERTY_TYPE))
1541 throw SQLException(DBACORE_RESSTRING(RID_STR_COLUMN_NOT_VALID),*this,SQLSTATE_GENERAL,1000,Any() );
1543 sal_Int32 nType = 0;
1544 column->getPropertyValue(PROPERTY_TYPE) >>= nType;
1545 sal_Int32 nSearchable = dbtools::getSearchColumnFlag(m_xConnection,nType);
1546 if(nSearchable == ColumnSearch::NONE)
1547 throw SQLException(DBACORE_RESSTRING(RID_STR_COLUMN_NOT_SEARCHABLE),*this,SQLSTATE_GENERAL,1000,Any() );
1549 ::osl::MutexGuard aGuard( m_aMutex );
1551 ::rtl::OUString aName;
1552 column->getPropertyValue(PROPERTY_NAME) >>= aName;
1554 Any aValue;
1555 column->getPropertyValue(PROPERTY_VALUE) >>= aValue;
1557 ::rtl::OUStringBuffer aSQL;
1558 const ::rtl::OUString aQuote = m_xMetaData->getIdentifierQuoteString();
1559 getColumns();
1561 if ( m_aCurrentColumns[SelectColumns] && m_aCurrentColumns[SelectColumns]->hasByName(aName) )
1563 Reference<XPropertySet> xColumn;
1564 m_aCurrentColumns[SelectColumns]->getByName(aName) >>= xColumn;
1565 OSL_ENSURE(xColumn->getPropertySetInfo()->hasPropertyByName(PROPERTY_REALNAME),"Property REALNAME not available!");
1566 OSL_ENSURE(xColumn->getPropertySetInfo()->hasPropertyByName(PROPERTY_TABLENAME),"Property TABLENAME not available!");
1567 OSL_ENSURE(xColumn->getPropertySetInfo()->hasPropertyByName(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("AggregateFunction"))),"Property AggregateFunction not available!");
1569 ::rtl::OUString sRealName,sTableName;
1570 xColumn->getPropertyValue(PROPERTY_REALNAME) >>= sRealName;
1571 xColumn->getPropertyValue(PROPERTY_TABLENAME) >>= sTableName;
1572 if(sTableName.indexOf('.',0) != -1)
1574 ::rtl::OUString aCatlog,aSchema,aTable;
1575 ::dbtools::qualifiedNameComponents(m_xMetaData,sTableName,aCatlog,aSchema,aTable,::dbtools::eInDataManipulation);
1576 sTableName = ::dbtools::composeTableName( m_xMetaData, aCatlog, aSchema, aTable, sal_True, ::dbtools::eInDataManipulation );
1578 else
1579 sTableName = ::dbtools::quoteName(aQuote,sTableName);
1581 if ( !::comphelper::getBOOL(xColumn->getPropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Function")))) )
1583 aSQL = sTableName;
1584 aSQL.appendAscii( "." );
1585 aSQL.append( ::dbtools::quoteName( aQuote, sRealName ) );
1587 else
1588 aSQL = sRealName;
1591 else
1593 aSQL = getTableAlias( column );
1594 aSQL.append( ::dbtools::quoteName( aQuote, aName ) );
1597 if ( aValue.hasValue() )
1599 if( !m_xTypeConverter.is() )
1600 m_xTypeConverter.set( Converter::create(m_aContext.getUNOContext()) );
1601 OSL_ENSURE(m_xTypeConverter.is(),"NO typeconverter!");
1603 if ( nType != DataType::BOOLEAN && DataType::BIT != nType )
1605 ::rtl::OUString sEmpty;
1606 lcl_addFilterCriteria_throw(filterOperator,sEmpty,aSQL);
1609 switch(nType)
1611 case DataType::VARCHAR:
1612 case DataType::CHAR:
1613 case DataType::LONGVARCHAR:
1614 aSQL.append( DBTypeConversion::toSQLString( nType, aValue, sal_True, m_xTypeConverter ) );
1615 break;
1616 case DataType::CLOB:
1618 Reference< XClob > xClob(aValue,UNO_QUERY);
1619 if ( xClob.is() )
1621 const ::sal_Int64 nLength = xClob->length();
1622 if ( sal_Int64(nLength + aSQL.getLength() + STR_LIKE.getLength() ) < sal_Int64(SAL_MAX_INT32) )
1624 aSQL.appendAscii("'");
1625 aSQL.append( xClob->getSubString(1,(sal_Int32)nLength) );
1626 aSQL.appendAscii("'");
1629 else
1631 aSQL.append( DBTypeConversion::toSQLString( nType, aValue, sal_True, m_xTypeConverter ) );
1634 break;
1635 case DataType::VARBINARY:
1636 case DataType::BINARY:
1637 case DataType::LONGVARBINARY:
1639 Sequence<sal_Int8> aSeq;
1640 if(aValue >>= aSeq)
1642 if(nSearchable == ColumnSearch::CHAR)
1644 aSQL.appendAscii( "\'" );
1646 aSQL.appendAscii( "0x" );
1647 const sal_Int8* pBegin = aSeq.getConstArray();
1648 const sal_Int8* pEnd = pBegin + aSeq.getLength();
1649 for(;pBegin != pEnd;++pBegin)
1651 aSQL.append( (sal_Int32)*pBegin, 16 ).getStr();
1653 if(nSearchable == ColumnSearch::CHAR)
1654 aSQL.appendAscii( "\'" );
1656 else
1657 throw SQLException(DBACORE_RESSTRING(RID_STR_NOT_SEQUENCE_INT8),*this,SQLSTATE_GENERAL,1000,Any() );
1659 break;
1660 case DataType::BIT:
1661 case DataType::BOOLEAN:
1663 sal_Bool bValue = sal_False;
1664 m_xTypeConverter->convertToSimpleType(aValue, TypeClass_BOOLEAN) >>= bValue;
1666 ::rtl::OUString sColumnExp = aSQL.makeStringAndClear();
1667 getBoleanComparisonPredicate( sColumnExp, bValue, m_nBoolCompareMode, aSQL );
1669 break;
1670 default:
1671 aSQL.append( DBTypeConversion::toSQLString( nType, aValue, sal_True, m_xTypeConverter ) );
1672 break;
1675 else
1677 sal_Int32 nFilterOp = filterOperator;
1678 if ( filterOperator != SQLFilterOperator::SQLNULL && filterOperator != SQLFilterOperator::NOT_SQLNULL )
1679 nFilterOp = SQLFilterOperator::SQLNULL;
1680 ::rtl::OUString sEmpty;
1681 lcl_addFilterCriteria_throw(nFilterOp,sEmpty,aSQL);
1684 // Attach filter
1685 // Construct SELECT without WHERE and ORDER BY
1686 ::rtl::OUString sFilter = getFilter();
1688 if ( !sFilter.isEmpty() && aSQL.getLength() )
1690 ::rtl::OUString sTemp(L_BRACKET);
1691 sTemp += sFilter;
1692 sTemp += R_BRACKET;
1693 sTemp += andCriteria ? STR_AND : STR_OR;
1694 sFilter = sTemp;
1696 sFilter += aSQL.makeStringAndClear();
1698 // add the filter and the sort order
1699 _aSetFunctor(this,sFilter);
1702 Sequence< Sequence< PropertyValue > > OSingleSelectQueryComposer::getStructuredCondition( TGetParseNode& _aGetFunctor )
1704 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getStructuredCondition" );
1705 ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
1707 MutexGuard aGuard(m_aMutex);
1709 Sequence< Sequence< PropertyValue > > aFilterSeq;
1710 ::rtl::OUString sFilter = getStatementPart( _aGetFunctor, m_aAdditiveIterator );
1712 if ( !sFilter.isEmpty() )
1714 ::rtl::OUString aSql(m_aPureSelectSQL);
1715 // build a temporary parse node
1716 const OSQLParseNode* pTempNode = m_aAdditiveIterator.getParseTree();
1718 aSql += STR_WHERE;
1719 aSql += sFilter;
1721 ::rtl::OUString aErrorMsg;
1722 SAL_WNODEPRECATED_DECLARATIONS_PUSH
1723 ::std::auto_ptr<OSQLParseNode> pSqlParseNode( m_aSqlParser.parseTree(aErrorMsg,aSql));
1724 SAL_WNODEPRECATED_DECLARATIONS_POP
1725 if ( pSqlParseNode.get() )
1727 m_aAdditiveIterator.setParseTree(pSqlParseNode.get());
1728 // normalize the filter
1729 OSQLParseNode* pWhereNode = const_cast<OSQLParseNode*>(m_aAdditiveIterator.getWhereTree());
1731 OSQLParseNode* pCondition = pWhereNode->getChild(1);
1732 #if OSL_DEBUG_LEVEL > 0
1733 ::rtl::OUString sCondition;
1734 pCondition->parseNodeToStr( sCondition, m_xConnection );
1735 #endif
1736 OSQLParseNode::negateSearchCondition(pCondition);
1738 pCondition = pWhereNode->getChild(1);
1739 #if OSL_DEBUG_LEVEL > 0
1740 sCondition = ::rtl::OUString();
1741 pCondition->parseNodeToStr( sCondition, m_xConnection );
1742 #endif
1743 OSQLParseNode::disjunctiveNormalForm(pCondition);
1745 pCondition = pWhereNode->getChild(1);
1746 #if OSL_DEBUG_LEVEL > 0
1747 sCondition = ::rtl::OUString();
1748 pCondition->parseNodeToStr( sCondition, m_xConnection );
1749 #endif
1750 OSQLParseNode::absorptions(pCondition);
1752 pCondition = pWhereNode->getChild(1);
1753 #if OSL_DEBUG_LEVEL > 0
1754 sCondition = ::rtl::OUString();
1755 pCondition->parseNodeToStr( sCondition, m_xConnection );
1756 #endif
1757 if ( pCondition )
1759 ::std::vector< ::std::vector < PropertyValue > > aFilters;
1760 Reference< XNumberFormatter > xFormatter( NumberFormatter::create(m_aContext.getUNOContext()), UNO_QUERY_THROW );
1761 xFormatter->attachNumberFormatsSupplier( m_xNumberFormatsSupplier );
1763 if (setORCriteria(pCondition, m_aAdditiveIterator, aFilters, xFormatter))
1765 aFilterSeq.realloc(aFilters.size());
1766 Sequence<PropertyValue>* pFilters = aFilterSeq.getArray();
1767 ::std::vector< ::std::vector < PropertyValue > >::const_iterator aEnd = aFilters.end();
1768 ::std::vector< ::std::vector < PropertyValue > >::const_iterator i = aFilters.begin();
1769 for ( ; i != aEnd ; ++i)
1771 const ::std::vector < PropertyValue >& rProperties = *i;
1772 pFilters->realloc(rProperties.size());
1773 PropertyValue* pFilter = pFilters->getArray();
1774 ::std::vector < PropertyValue >::const_iterator j = rProperties.begin();
1775 ::std::vector < PropertyValue >::const_iterator aEnd2 = rProperties.end();
1776 for ( ; j != aEnd2 ; ++j)
1778 *pFilter = *j;
1779 ++pFilter;
1781 ++pFilters;
1785 // restore
1786 m_aAdditiveIterator.setParseTree(pTempNode);
1789 return aFilterSeq;
1792 ::rtl::OUString OSingleSelectQueryComposer::getKeyword( SQLPart _ePart ) const
1794 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getKeyword" );
1795 ::rtl::OUString sKeyword;
1796 switch(_ePart)
1798 default:
1799 OSL_FAIL( "OSingleSelectQueryComposer::getKeyWord: Invalid enum value!" );
1800 // no break, fallback to WHERE
1801 case Where:
1802 sKeyword = STR_WHERE;
1803 break;
1804 case Group:
1805 sKeyword = STR_GROUP_BY;
1806 break;
1807 case Having:
1808 sKeyword = STR_HAVING;
1809 break;
1810 case Order:
1811 sKeyword = STR_ORDER_BY;
1812 break;
1814 return sKeyword;
1817 ::rtl::OUString OSingleSelectQueryComposer::getSQLPart( SQLPart _ePart, OSQLParseTreeIterator& _rIterator, sal_Bool _bWithKeyword )
1819 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getSQLPart" );
1820 TGetParseNode F_tmp(&OSQLParseTreeIterator::getSimpleWhereTree);
1821 ::rtl::OUString sKeyword( getKeyword( _ePart ) );
1822 switch(_ePart)
1824 case Where:
1825 F_tmp = TGetParseNode(&OSQLParseTreeIterator::getSimpleWhereTree);
1826 break;
1827 case Group:
1828 F_tmp = TGetParseNode (&OSQLParseTreeIterator::getSimpleGroupByTree);
1829 break;
1830 case Having:
1831 F_tmp = TGetParseNode(&OSQLParseTreeIterator::getSimpleHavingTree);
1832 break;
1833 case Order:
1834 F_tmp = TGetParseNode(&OSQLParseTreeIterator::getSimpleOrderTree);
1835 break;
1836 default:
1837 OSL_FAIL("Invalid enum value!");
1840 ::rtl::OUString sRet = getStatementPart( F_tmp, _rIterator );
1841 if ( _bWithKeyword && !sRet.isEmpty() )
1842 sRet = sKeyword + sRet;
1843 return sRet;
1845 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */