merged tag ooo/DEV300_m102
[LibreOffice.git] / dbaccess / source / core / api / SingleSelectQueryComposer.cxx
blobfa67a3d8cfdbffd8081b0425a51731aed7ff30ed
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2000, 2010 Oracle and/or its affiliates.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
11 * OpenOffice.org is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License version 3
13 * only, as published by the Free Software Foundation.
15 * OpenOffice.org is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License version 3 for more details
19 * (a copy is included in the LICENSE file that accompanied this code).
21 * You should have received a copy of the GNU Lesser General Public License
22 * version 3 along with OpenOffice.org. If not, see
23 * <http://www.openoffice.org/license.html>
24 * for a copy of the LGPLv3 License.
26 ************************************************************************/
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_dbaccess.hxx"
31 #include "composertools.hxx"
32 #include "core_resource.hrc"
33 #include "core_resource.hxx"
34 #include "dbastrings.hrc"
35 #include "HelperCollections.hxx"
36 #include "SingleSelectQueryComposer.hxx"
37 #include "sdbcoretools.hxx"
39 /** === begin UNO includes === **/
40 #include <com/sun/star/beans/PropertyAttribute.hpp>
41 #include <com/sun/star/container/XChild.hpp>
42 #include <com/sun/star/i18n/XLocaleData.hpp>
43 #include <com/sun/star/lang/DisposedException.hpp>
44 #include <com/sun/star/sdb/BooleanComparisonMode.hpp>
45 #include <com/sun/star/sdb/SQLFilterOperator.hpp>
46 #include <com/sun/star/sdb/XQueriesSupplier.hpp>
47 #include <com/sun/star/sdb/CommandType.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/sdbc/XParameters.hpp>
53 #include <com/sun/star/uno/XAggregation.hpp>
54 #include <com/sun/star/util/XNumberFormatter.hpp>
55 /** === end UNO includes === **/
57 #include <comphelper/processfactory.hxx>
58 #include <comphelper/sequence.hxx>
59 #include <comphelper/types.hxx>
60 #include <cppuhelper/typeprovider.hxx>
61 #include <rtl/logfile.hxx>
62 #include <unotools/syslocale.hxx>
63 #include <tools/debug.hxx>
64 #include <tools/diagnose_ex.h>
65 #include <unotools/configmgr.hxx>
66 #include <unotools/sharedunocomponent.hxx>
68 #include <memory>
70 using namespace ::dbaccess;
71 using namespace ::dbtools;
72 using namespace ::comphelper;
73 using namespace ::connectivity;
74 using namespace ::com::sun::star::uno;
75 using namespace ::com::sun::star::beans;
76 using namespace ::com::sun::star::sdbc;
77 using namespace ::com::sun::star::sdb;
78 using namespace ::com::sun::star::sdbcx;
79 using namespace ::com::sun::star::container;
80 using namespace ::com::sun::star::i18n;
81 using namespace ::com::sun::star::lang;
82 using namespace ::com::sun::star::script;
83 using namespace ::com::sun::star::util;
84 using namespace ::cppu;
85 using namespace ::osl;
86 using namespace ::utl;
88 namespace dbaccess {
89 namespace BooleanComparisonMode = ::com::sun::star::sdb::BooleanComparisonMode;
92 #define STR_SELECT ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("SELECT "))
93 #define STR_FROM ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" FROM "))
94 #define STR_WHERE ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" WHERE "))
95 #define STR_GROUP_BY ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" GROUP BY "))
96 #define STR_HAVING ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" HAVING "))
97 #define STR_ORDER_BY ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" ORDER BY "))
98 #define STR_AND ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" AND "))
99 #define STR_OR ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" OR "))
100 #define STR_LIKE ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" LIKE "))
101 #define STR_EQUAL ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" = "))
102 #define L_BRACKET ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("("))
103 #define R_BRACKET ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(")"))
104 #define COMMA ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(","))
106 // -------------------------------------------------------------------------
107 namespace
109 // .....................................................................
110 /** parses the given statement, using the given parser, returns a parse node representing
111 the statement
113 If the statement cannot be parsed, an error is thrown.
115 const OSQLParseNode* parseStatement_throwError( OSQLParser& _rParser, const ::rtl::OUString& _rStatement, const Reference< XInterface >& _rxContext )
117 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "frank.schoenheit@sun.com", "SingleSelectQueryComposer.cxx::parseStatement_throwError" );
118 ::rtl::OUString aErrorMsg;
119 const OSQLParseNode* pNewSqlParseNode = _rParser.parseTree( aErrorMsg, _rStatement );
120 if ( !pNewSqlParseNode )
122 ::rtl::OUString sSQLStateGeneralError( getStandardSQLState( SQL_GENERAL_ERROR ) );
123 SQLException aError2( aErrorMsg, _rxContext, sSQLStateGeneralError, 1000, Any() );
124 SQLException aError1( _rStatement, _rxContext, sSQLStateGeneralError, 1000, makeAny( aError2 ) );
125 throw SQLException(_rParser.getContext().getErrorMessage(OParseContext::ERROR_GENERAL),_rxContext,sSQLStateGeneralError,1000,makeAny(aError1));
127 return pNewSqlParseNode;
130 // .....................................................................
131 /** checks whether the given parse node describes a valid single select statement, throws
132 an error if not
134 void checkForSingleSelect_throwError( const OSQLParseNode* pStatementNode, OSQLParseTreeIterator& _rIterator,
135 const Reference< XInterface >& _rxContext, const ::rtl::OUString& _rOriginatingCommand )
137 const OSQLParseNode* pOldNode = _rIterator.getParseTree();
139 // determine the statement type
140 _rIterator.setParseTree( pStatementNode );
141 _rIterator.traverseAll();
142 bool bIsSingleSelect = ( _rIterator.getStatementType() == SQL_STATEMENT_SELECT );
144 // throw the error, if necessary
145 if ( !bIsSingleSelect || SQL_ISRULE( pStatementNode, union_statement ) ) // #i4229# OJ
147 // restore the old node before throwing the exception
148 _rIterator.setParseTree( pOldNode );
149 // and now really ...
150 SQLException aError1( _rOriginatingCommand, _rxContext, getStandardSQLState( SQL_GENERAL_ERROR ), 1000, Any() );
151 throw SQLException( DBACORE_RESSTRING( RID_STR_ONLY_QUERY ), _rxContext,
152 getStandardSQLState( SQL_GENERAL_ERROR ), 1000, makeAny( aError1 ) );
155 delete pOldNode;
158 // .....................................................................
159 /** combines parseStatement_throwError and checkForSingleSelect_throwError
161 void parseAndCheck_throwError( OSQLParser& _rParser, const ::rtl::OUString& _rStatement,
162 OSQLParseTreeIterator& _rIterator, const Reference< XInterface >& _rxContext )
164 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "frank.schoenheit@sun.com", "SingleSelectQueryComposer.cxx::parseAndCheck_throwError" );
165 const OSQLParseNode* pNode = parseStatement_throwError( _rParser, _rStatement, _rxContext );
166 checkForSingleSelect_throwError( pNode, _rIterator, _rxContext, _rStatement );
169 // .....................................................................
170 /** transforms a parse node describing a complete statement into a pure select
171 statement, without any filter/order/groupby/having clauses
173 ::rtl::OUString getPureSelectStatement( const OSQLParseNode* _pRootNode, Reference< XConnection > _rxConnection )
175 ::rtl::OUString sSQL = STR_SELECT;
176 _pRootNode->getChild(1)->parseNodeToStr( sSQL, _rxConnection );
177 _pRootNode->getChild(2)->parseNodeToStr( sSQL, _rxConnection );
178 sSQL += STR_FROM;
179 _pRootNode->getChild(3)->getChild(0)->getChild(1)->parseNodeToStr( sSQL, _rxConnection );
180 return sSQL;
183 /** resets an SQL iterator, including deletion of the parse tree, and disposal if desired
185 void resetIterator( OSQLParseTreeIterator& _rIterator, bool _bDispose )
187 const OSQLParseNode* pSqlParseNode = _rIterator.getParseTree();
188 _rIterator.setParseTree(NULL);
189 delete pSqlParseNode;
190 if ( _bDispose )
191 _rIterator.dispose();
193 void lcl_addFilterCriteria_throw(sal_Int32 i_nFilterOperator,const ::rtl::OUString& i_sValue,::rtl::OUStringBuffer& o_sRet)
195 switch( i_nFilterOperator )
197 case SQLFilterOperator::EQUAL:
198 o_sRet.append(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" = ")));
199 o_sRet.append(i_sValue);
200 break;
201 case SQLFilterOperator::NOT_EQUAL:
202 o_sRet.append(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" <> ")));
203 o_sRet.append(i_sValue);
204 break;
205 case SQLFilterOperator::LESS:
206 o_sRet.append(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" < ")));
207 o_sRet.append(i_sValue);
208 break;
209 case SQLFilterOperator::GREATER:
210 o_sRet.append(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" > ")));
211 o_sRet.append(i_sValue);
212 break;
213 case SQLFilterOperator::LESS_EQUAL:
214 o_sRet.append(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" <= ")));
215 o_sRet.append(i_sValue);
216 break;
217 case SQLFilterOperator::GREATER_EQUAL:
218 o_sRet.append(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" >= ")));
219 o_sRet.append(i_sValue);
220 break;
221 case SQLFilterOperator::LIKE:
222 o_sRet.append(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" LIKE ")));
223 o_sRet.append(i_sValue);
224 break;
225 case SQLFilterOperator::NOT_LIKE:
226 o_sRet.append(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" NOT LIKE ")));
227 o_sRet.append(i_sValue);
228 break;
229 case SQLFilterOperator::SQLNULL:
230 o_sRet.append(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" IS NULL")) );
231 break;
232 case SQLFilterOperator::NOT_SQLNULL:
233 o_sRet.append(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" IS NOT NULL")) );
234 break;
235 default:
236 throw SQLException();
242 DBG_NAME(OSingleSelectQueryComposer)
243 // -------------------------------------------------------------------------
244 OSingleSelectQueryComposer::OSingleSelectQueryComposer(const Reference< XNameAccess>& _rxTables,
245 const Reference< XConnection>& _xConnection,
246 const ::comphelper::ComponentContext& _rContext )
247 :OSubComponent(m_aMutex,_xConnection)
248 ,OPropertyContainer(m_aBHelper)
249 ,m_aSqlParser( _rContext.getLegacyServiceFactory() )
250 ,m_aSqlIterator( _xConnection, _rxTables, m_aSqlParser, NULL )
251 ,m_aAdditiveIterator( _xConnection, _rxTables, m_aSqlParser, NULL )
252 ,m_aElementaryParts( (size_t)SQLPartCount )
253 ,m_xConnection(_xConnection)
254 ,m_xMetaData(_xConnection->getMetaData())
255 ,m_xConnectionTables( _rxTables )
256 ,m_aContext( _rContext )
257 ,m_pTables(NULL)
258 ,m_nBoolCompareMode( BooleanComparisonMode::EQUAL_INTEGER )
259 ,m_nCommandType(CommandType::COMMAND)
261 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::OSingleSelectQueryComposer" );
262 DBG_CTOR(OSingleSelectQueryComposer,NULL);
264 if ( !m_aContext.is() || !m_xConnection.is() || !m_xConnectionTables.is() )
265 throw IllegalArgumentException();
267 registerProperty(PROPERTY_ORIGINAL,PROPERTY_ID_ORIGINAL,PropertyAttribute::BOUND|PropertyAttribute::READONLY,&m_sOrignal,::getCppuType(&m_sOrignal));
269 m_aCurrentColumns.resize(4);
271 m_aLocale = SvtSysLocale().GetLocaleData().getLocale();
272 m_xNumberFormatsSupplier = dbtools::getNumberFormats( m_xConnection, sal_True, m_aContext.getLegacyServiceFactory() );
273 Reference< XLocaleData > xLocaleData;
274 m_aContext.createComponent( "com.sun.star.i18n.LocaleData", xLocaleData );
275 LocaleDataItem aData = xLocaleData->getLocaleItem(m_aLocale);
276 m_sDecimalSep = aData.decimalSeparator;
277 OSL_ENSURE(m_sDecimalSep.getLength() == 1,"OSingleSelectQueryComposer::OSingleSelectQueryComposer decimal separator is not 1 length");
280 Any aValue;
281 Reference<XInterface> xDs = dbaccess::getDataSource(_xConnection);
282 if ( dbtools::getDataSourceSetting(xDs,static_cast <rtl::OUString> (PROPERTY_BOOLEANCOMPARISONMODE),aValue) )
284 OSL_VERIFY( aValue >>= m_nBoolCompareMode );
286 Reference< XQueriesSupplier > xQueriesAccess(m_xConnection, UNO_QUERY);
287 if (xQueriesAccess.is())
288 m_xConnectionQueries = xQueriesAccess->getQueries();
290 catch(Exception&)
294 // -------------------------------------------------------------------------
295 OSingleSelectQueryComposer::~OSingleSelectQueryComposer()
297 DBG_DTOR(OSingleSelectQueryComposer,NULL);
298 ::std::vector<OPrivateColumns*>::iterator aColIter = m_aColumnsCollection.begin();
299 ::std::vector<OPrivateColumns*>::iterator aEnd = m_aColumnsCollection.end();
300 for(;aColIter != aEnd;++aColIter)
301 delete *aColIter;
303 ::std::vector<OPrivateTables*>::iterator aTabIter = m_aTablesCollection.begin();
304 ::std::vector<OPrivateTables*>::iterator aTabEnd = m_aTablesCollection.end();
305 for(;aTabIter != aTabEnd;++aTabIter)
306 delete *aTabIter;
308 // -------------------------------------------------------------------------
309 // OComponentHelper
310 void SAL_CALL OSingleSelectQueryComposer::disposing(void)
312 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::disposing" );
313 OSubComponent::disposing();
315 MutexGuard aGuard(m_aMutex);
317 resetIterator( m_aSqlIterator, true );
318 resetIterator( m_aAdditiveIterator, true );
320 m_xConnectionTables = NULL;
321 m_xConnection = NULL;
323 clearCurrentCollections();
325 IMPLEMENT_FORWARD_XINTERFACE3(OSingleSelectQueryComposer,OSubComponent,OSingleSelectQueryComposer_BASE,OPropertyContainer)
326 IMPLEMENT_SERVICE_INFO1(OSingleSelectQueryComposer,"org.openoffice.comp.dba.OSingleSelectQueryComposer",SERVICE_NAME_SINGLESELECTQUERYCOMPOSER)
327 IMPLEMENT_TYPEPROVIDER3(OSingleSelectQueryComposer,OSubComponent,OSingleSelectQueryComposer_BASE,OPropertyContainer)
328 IMPLEMENT_PROPERTYCONTAINER_DEFAULTS(OSingleSelectQueryComposer)
330 // -------------------------------------------------------------------------
331 // com::sun::star::lang::XUnoTunnel
332 sal_Int64 SAL_CALL OSingleSelectQueryComposer::getSomething( const Sequence< sal_Int8 >& rId ) throw(RuntimeException)
334 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getSomething" );
335 if (rId.getLength() == 16 && 0 == rtl_compareMemory(getImplementationId().getConstArray(), rId.getConstArray(), 16 ) )
336 return reinterpret_cast<sal_Int64>(this);
338 return sal_Int64(0);
341 // -------------------------------------------------------------------------
342 // XSingleSelectQueryAnalyzer
343 ::rtl::OUString SAL_CALL OSingleSelectQueryComposer::getQuery( ) throw(RuntimeException)
345 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getQuery" );
346 ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
347 ::osl::MutexGuard aGuard( m_aMutex );
349 TGetParseNode F_tmp(&OSQLParseTreeIterator::getParseTree);
350 return getStatementPart(F_tmp,m_aSqlIterator);
353 // -------------------------------------------------------------------------
354 void SAL_CALL OSingleSelectQueryComposer::setQuery( const ::rtl::OUString& command ) throw(SQLException, RuntimeException)
356 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "frank.schoenheit@sun.com", "OSingleSelectQueryComposer::setQuery" );
357 ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
359 ::osl::MutexGuard aGuard( m_aMutex );
360 m_nCommandType = CommandType::COMMAND;
361 // first clear the tables and columns
362 clearCurrentCollections();
363 // now set the new one
364 setQuery_Impl(command);
365 m_sOrignal = command;
367 // reset the additive iterator to the same statement
368 parseAndCheck_throwError( m_aSqlParser, m_sOrignal, m_aAdditiveIterator, *this );
370 // we have no "elementary" parts anymore (means filter/groupby/having/order clauses)
371 for ( SQLPart eLoopParts = Where; eLoopParts != SQLPartCount; incSQLPart( eLoopParts ) )
372 m_aElementaryParts[ eLoopParts ] = ::rtl::OUString();
374 // -------------------------------------------------------------------------
375 void SAL_CALL OSingleSelectQueryComposer::setCommand( const ::rtl::OUString& Command,sal_Int32 _nCommandType ) throw(SQLException, RuntimeException)
377 ::rtl::OUStringBuffer sSQL;
378 switch(_nCommandType)
380 case CommandType::COMMAND:
381 setElementaryQuery(Command);
382 return;
383 case CommandType::TABLE:
384 if ( m_xConnectionTables->hasByName(Command) )
386 sSQL.appendAscii("SELECT * FROM ");
387 Reference< XPropertySet > xTable;
390 m_xConnectionTables->getByName( Command ) >>= xTable;
392 catch(const WrappedTargetException& e)
394 SQLException e2;
395 if ( e.TargetException >>= e2 )
396 throw e2;
398 catch(Exception&)
400 DBG_UNHANDLED_EXCEPTION();
403 sSQL.append(dbtools::composeTableNameForSelect(m_xConnection,xTable));
405 else
407 String sMessage( DBACORE_RESSTRING( RID_STR_TABLE_DOES_NOT_EXIST ) );
408 sMessage.SearchAndReplaceAscii( "$table$", Command );
409 throwGenericSQLException(sMessage,*this);
411 break;
412 case CommandType::QUERY:
413 if ( m_xConnectionQueries->hasByName(Command) )
416 Reference<XPropertySet> xQuery(m_xConnectionQueries->getByName(Command),UNO_QUERY);
417 ::rtl::OUString sCommand;
418 xQuery->getPropertyValue(PROPERTY_COMMAND) >>= sCommand;
419 sSQL.append(sCommand);
421 else
423 String sMessage( DBACORE_RESSTRING( RID_STR_QUERY_DOES_NOT_EXIST ) );
424 sMessage.SearchAndReplaceAscii( "$table$", Command );
425 throwGenericSQLException(sMessage,*this);
428 break;
429 default:
430 break;
432 ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
434 ::osl::MutexGuard aGuard( m_aMutex );
435 m_nCommandType = _nCommandType;
436 m_sCommand = Command;
437 // first clear the tables and columns
438 clearCurrentCollections();
439 // now set the new one
440 ::rtl::OUString sCommand = sSQL.makeStringAndClear();
441 setElementaryQuery(sCommand);
442 m_sOrignal = sCommand;
444 // reset the additive iterator to the same statement
445 parseAndCheck_throwError( m_aSqlParser, m_sOrignal, m_aAdditiveIterator, *this );
447 // we have no "elementary" parts anymore (means filter/groupby/having/order clauses)
448 for ( SQLPart eLoopParts = Where; eLoopParts != SQLPartCount; incSQLPart( eLoopParts ) )
449 m_aElementaryParts[ eLoopParts ] = ::rtl::OUString();
452 // -----------------------------------------------------------------------------
453 void OSingleSelectQueryComposer::setQuery_Impl( const ::rtl::OUString& command )
455 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "frank.schoenheit@sun.com", "OSingleSelectQueryComposer::setQuery_Impl" );
456 // parse this
457 parseAndCheck_throwError( m_aSqlParser, command, m_aSqlIterator, *this );
459 // strip it from all clauses, to have the pure SELECT statement
460 m_aPureSelectSQL = getPureSelectStatement( m_aSqlIterator.getParseTree(), m_xConnection );
462 // update columns and tables
463 // why? Shouldn't this be done on request only?
464 // otherwise nothing is working anymore :-)
465 // getColumns();
466 getTables();
468 // -----------------------------------------------------------------------------
469 Sequence< Sequence< PropertyValue > > SAL_CALL OSingleSelectQueryComposer::getStructuredHavingClause( ) throw (RuntimeException)
471 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getStructuredHavingClause" );
472 TGetParseNode F_tmp(&OSQLParseTreeIterator::getSimpleHavingTree);
473 return getStructuredCondition(F_tmp);
475 // -------------------------------------------------------------------------
476 Sequence< Sequence< PropertyValue > > SAL_CALL OSingleSelectQueryComposer::getStructuredFilter( ) throw(RuntimeException)
478 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getStructuredFilter" );
479 TGetParseNode F_tmp(&OSQLParseTreeIterator::getSimpleWhereTree);
480 return getStructuredCondition(F_tmp);
482 // -----------------------------------------------------------------------------
483 void SAL_CALL OSingleSelectQueryComposer::appendHavingClauseByColumn( const Reference< XPropertySet >& column, sal_Bool andCriteria,sal_Int32 filterOperator ) throw (SQLException, RuntimeException)
485 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::appendHavingClauseByColumn" );
486 ::std::mem_fun1_t<bool,OSingleSelectQueryComposer,::rtl::OUString> F_tmp(&OSingleSelectQueryComposer::implSetHavingClause);
487 setConditionByColumn(column,andCriteria,F_tmp,filterOperator);
489 // -----------------------------------------------------------------------------
490 void SAL_CALL OSingleSelectQueryComposer::appendFilterByColumn( const Reference< XPropertySet >& column, sal_Bool andCriteria,sal_Int32 filterOperator ) throw(SQLException, RuntimeException)
492 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::appendFilterByColumn" );
493 ::std::mem_fun1_t<bool,OSingleSelectQueryComposer,::rtl::OUString> F_tmp(&OSingleSelectQueryComposer::implSetFilter);
494 setConditionByColumn(column,andCriteria,F_tmp,filterOperator);
496 // -----------------------------------------------------------------------------
497 ::rtl::OUString OSingleSelectQueryComposer::impl_getColumnName_throw(const Reference< XPropertySet >& column)
499 ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
501 getColumns();
502 if ( !column.is()
503 || !m_aCurrentColumns[SelectColumns]
504 || !column->getPropertySetInfo()->hasPropertyByName(PROPERTY_NAME)
507 String sError(DBACORE_RESSTRING(RID_STR_COLUMN_UNKNOWN_PROP));
508 sError.SearchAndReplaceAscii("%value", ::rtl::OUString(PROPERTY_NAME));
509 SQLException aErr(sError,*this,SQLSTATE_GENERAL,1000,Any() );
510 throw SQLException(DBACORE_RESSTRING(RID_STR_COLUMN_NOT_VALID),*this,SQLSTATE_GENERAL,1000,makeAny(aErr) );
513 ::rtl::OUString aName,aNewName;
514 column->getPropertyValue(PROPERTY_NAME) >>= aName;
516 if ( !m_xMetaData->supportsOrderByUnrelated() && m_aCurrentColumns[SelectColumns] && !m_aCurrentColumns[SelectColumns]->hasByName(aName))
518 String sError(DBACORE_RESSTRING(RID_STR_COLUMN_MUST_VISIBLE));
519 sError.SearchAndReplaceAscii("%name", aName);
520 throw SQLException(sError,*this,SQLSTATE_GENERAL,1000,Any() );
523 // filter anhaengen
524 // select ohne where und order by aufbauen
525 ::rtl::OUString aQuote = m_xMetaData->getIdentifierQuoteString();
526 if ( m_aCurrentColumns[SelectColumns]->hasByName(aName) )
528 Reference<XPropertySet> xColumn;
529 m_aCurrentColumns[SelectColumns]->getByName(aName) >>= xColumn;
530 OSL_ENSURE(xColumn->getPropertySetInfo()->hasPropertyByName(PROPERTY_REALNAME),"Property REALNAME not available!");
531 OSL_ENSURE(xColumn->getPropertySetInfo()->hasPropertyByName(PROPERTY_TABLENAME),"Property TABLENAME not available!");
532 OSL_ENSURE(xColumn->getPropertySetInfo()->hasPropertyByName(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Function"))),"Property FUNCTION not available!");
534 ::rtl::OUString sRealName,sTableName;
535 xColumn->getPropertyValue(PROPERTY_REALNAME) >>= sRealName;
536 xColumn->getPropertyValue(PROPERTY_TABLENAME) >>= sTableName;
537 sal_Bool bFunction = sal_False;
538 xColumn->getPropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Function"))) >>= bFunction;
539 if ( sRealName == aName )
541 if ( bFunction )
542 aNewName = aName;
543 else
545 if(sTableName.indexOf('.',0) != -1)
547 ::rtl::OUString aCatlog,aSchema,aTable;
548 ::dbtools::qualifiedNameComponents(m_xMetaData,sTableName,aCatlog,aSchema,aTable,::dbtools::eInDataManipulation);
549 sTableName = ::dbtools::composeTableName( m_xMetaData, aCatlog, aSchema, aTable, sal_True, ::dbtools::eInDataManipulation );
551 else
552 sTableName = ::dbtools::quoteName(aQuote,sTableName);
554 aNewName = sTableName;
555 aNewName += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("."));
556 aNewName += ::dbtools::quoteName(aQuote,sRealName);
559 else
560 aNewName = ::dbtools::quoteName(aQuote,aName);
562 else
563 aNewName = getTableAlias(column) + ::dbtools::quoteName(aQuote,aName);
564 return aNewName;
566 // -------------------------------------------------------------------------
567 void SAL_CALL OSingleSelectQueryComposer::appendOrderByColumn( const Reference< XPropertySet >& column, sal_Bool ascending ) throw(SQLException, RuntimeException)
569 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::appendOrderByColumn" );
570 ::osl::MutexGuard aGuard( m_aMutex );
571 ::rtl::OUString sColumnName( impl_getColumnName_throw(column) );
572 ::rtl::OUString sOrder = getOrder();
573 if ( (sOrder.getLength() != 0) && sColumnName.getLength() )
574 sOrder += COMMA;
575 sOrder += sColumnName;
576 if ( !ascending && sColumnName.getLength() )
577 sOrder += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" DESC "));
579 setOrder(sOrder);
582 // -------------------------------------------------------------------------
583 void SAL_CALL OSingleSelectQueryComposer::appendGroupByColumn( const Reference< XPropertySet >& column) throw(SQLException, RuntimeException)
585 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::appendGroupByColumn" );
586 ::osl::MutexGuard aGuard( m_aMutex );
587 ::rtl::OUString sColumnName( impl_getColumnName_throw(column) );
588 OrderCreator aComposer;
589 aComposer.append( getGroup() );
590 aComposer.append( sColumnName );
591 setGroup( aComposer.getComposedAndClear() );
593 // -------------------------------------------------------------------------
594 ::rtl::OUString OSingleSelectQueryComposer::composeStatementFromParts( const ::std::vector< ::rtl::OUString >& _rParts )
596 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::composeStatementFromParts" );
597 DBG_ASSERT( _rParts.size() == (size_t)SQLPartCount, "OSingleSelectQueryComposer::composeStatementFromParts: invalid parts array!" );
599 ::rtl::OUStringBuffer aSql( m_aPureSelectSQL );
600 for ( SQLPart eLoopParts = Where; eLoopParts != SQLPartCount; incSQLPart( eLoopParts ) )
601 if ( _rParts[ eLoopParts ].getLength() )
603 aSql.append( getKeyword( eLoopParts ) );
604 aSql.append( _rParts[ eLoopParts ] );
607 return aSql.makeStringAndClear();
610 // -------------------------------------------------------------------------
611 ::rtl::OUString SAL_CALL OSingleSelectQueryComposer::getElementaryQuery() throw (::com::sun::star::uno::RuntimeException)
613 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getElementaryQuery" );
614 return composeStatementFromParts( m_aElementaryParts );
617 // -------------------------------------------------------------------------
618 void SAL_CALL OSingleSelectQueryComposer::setElementaryQuery( const ::rtl::OUString& _rElementary ) throw (::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException)
620 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "frank.schoenheit@sun.com", "OSingleSelectQueryComposer::setElementaryQuery" );
621 ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
622 ::osl::MutexGuard aGuard( m_aMutex );
624 // remember the 4 current "additive" clauses
625 ::std::vector< ::rtl::OUString > aAdditiveClauses( SQLPartCount );
626 for ( SQLPart eLoopParts = Where; eLoopParts != SQLPartCount; incSQLPart( eLoopParts ) )
627 aAdditiveClauses[ eLoopParts ] = getSQLPart( eLoopParts, m_aAdditiveIterator, sal_False );
629 // clear the tables and columns
630 clearCurrentCollections();
631 // set and parse the new query
632 setQuery_Impl( _rElementary );
634 // get the 4 elementary parts of the statement
635 for ( SQLPart eLoopParts = Where; eLoopParts != SQLPartCount; incSQLPart( eLoopParts ) )
636 m_aElementaryParts[ eLoopParts ] = getSQLPart( eLoopParts, m_aSqlIterator, sal_False );
638 // reset the the AdditiveIterator: m_aPureSelectSQL may have changed
641 parseAndCheck_throwError( m_aSqlParser, composeStatementFromParts( aAdditiveClauses ), m_aAdditiveIterator, *this );
643 catch( const Exception& e )
645 (void)e;
646 DBG_ERROR( "OSingleSelectQueryComposer::setElementaryQuery: there should be no error anymore for the additive statement!" );
647 // every part of the additive statement should have passed other tests already, and should not
648 // be able to cause any errors ... me thinks
652 // -------------------------------------------------------------------------
653 namespace
655 ::rtl::OUString getComposedClause( const ::rtl::OUString _rElementaryClause, const ::rtl::OUString _rAdditionalClause,
656 TokenComposer& _rComposer, const ::rtl::OUString _rKeyword )
658 _rComposer.clear();
659 _rComposer.append( _rElementaryClause );
660 _rComposer.append( _rAdditionalClause );
661 ::rtl::OUString sComposed = _rComposer.getComposedAndClear();
662 if ( sComposed.getLength() )
663 sComposed = _rKeyword + sComposed;
664 return sComposed;
668 // -------------------------------------------------------------------------
669 void OSingleSelectQueryComposer::setSingleAdditiveClause( SQLPart _ePart, const ::rtl::OUString& _rClause )
671 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::setSingleAdditiveClause" );
672 ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
673 ::osl::MutexGuard aGuard( m_aMutex );
675 // if nothing is changed, do nothing
676 if ( getSQLPart( _ePart, m_aAdditiveIterator, sal_False ) == _rClause )
677 return;
679 // collect the 4 single parts as they're currently set
680 ::std::vector< ::rtl::OUString > aClauses;
681 aClauses.reserve( (size_t)SQLPartCount );
682 for ( SQLPart eLoopParts = Where; eLoopParts != SQLPartCount; incSQLPart( eLoopParts ) )
683 aClauses.push_back( getSQLPart( eLoopParts, m_aSqlIterator, sal_True ) );
685 // overwrite the one part in question here
686 ::std::auto_ptr< TokenComposer > pComposer;
687 if ( ( _ePart == Where ) || ( _ePart == Having ) )
688 pComposer.reset( new FilterCreator );
689 else
690 pComposer.reset( new OrderCreator );
691 aClauses[ _ePart ] = getComposedClause( m_aElementaryParts[ _ePart ], _rClause,
692 *pComposer, getKeyword( _ePart ) );
694 // construct the complete statement
695 ::rtl::OUStringBuffer aSql(m_aPureSelectSQL);
696 for ( SQLPart eLoopParts = Where; eLoopParts != SQLPartCount; incSQLPart( eLoopParts ) )
697 aSql.append(aClauses[ eLoopParts ]);
699 // set the query
700 setQuery_Impl(aSql.makeStringAndClear());
702 // clear column collections which (might) have changed
703 clearColumns( ParameterColumns );
704 if ( _ePart == Order )
705 clearColumns( OrderColumns );
706 if ( _ePart == Group )
707 clearColumns( GroupByColumns );
709 // also, since the "additive filter" change, we need to rebuild our "additive" statement
710 aSql = m_aPureSelectSQL;
711 // again, first get all the old additive parts
712 for ( SQLPart eLoopParts = Where; eLoopParts != SQLPartCount; incSQLPart( eLoopParts ) )
713 aClauses[ eLoopParts ] = getSQLPart( eLoopParts, m_aAdditiveIterator, sal_True );
714 // then overwrite the one in question
715 aClauses[ _ePart ] = getComposedClause( ::rtl::OUString(), _rClause, *pComposer, getKeyword( _ePart ) );
716 // and parse it, so that m_aAdditiveIterator is up to date
717 for ( SQLPart eLoopParts = Where; eLoopParts != SQLPartCount; incSQLPart( eLoopParts ) )
718 aSql.append(aClauses[ eLoopParts ]);
721 parseAndCheck_throwError( m_aSqlParser, aSql.makeStringAndClear(), m_aAdditiveIterator, *this );
723 catch( const Exception& e )
725 (void)e;
726 DBG_ERROR( "OSingleSelectQueryComposer::setSingleAdditiveClause: there should be no error anymore for the additive statement!" );
727 // every part of the additive statement should have passed other tests already, and should not
728 // be able to cause any errors ... me thinks
732 // -------------------------------------------------------------------------
733 void SAL_CALL OSingleSelectQueryComposer::setFilter( const ::rtl::OUString& filter ) throw(SQLException, RuntimeException)
735 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::setFilter" );
736 setSingleAdditiveClause( Where, filter );
739 // -------------------------------------------------------------------------
740 void SAL_CALL OSingleSelectQueryComposer::setOrder( const ::rtl::OUString& order ) throw(SQLException, RuntimeException)
742 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::setOrder" );
743 setSingleAdditiveClause( Order, order );
745 // -----------------------------------------------------------------------------
746 void SAL_CALL OSingleSelectQueryComposer::setGroup( const ::rtl::OUString& group ) throw (SQLException, RuntimeException)
748 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::setGroup" );
749 setSingleAdditiveClause( Group, group );
751 // -------------------------------------------------------------------------
752 void SAL_CALL OSingleSelectQueryComposer::setHavingClause( const ::rtl::OUString& filter ) throw(SQLException, RuntimeException)
754 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::setHavingClause" );
755 setSingleAdditiveClause( Having, filter );
758 // -------------------------------------------------------------------------
759 // XTablesSupplier
760 Reference< XNameAccess > SAL_CALL OSingleSelectQueryComposer::getTables( ) throw(RuntimeException)
762 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getTables" );
763 ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
765 ::osl::MutexGuard aGuard( m_aMutex );
766 if ( !m_pTables )
768 const OSQLTables& aTables = m_aSqlIterator.getTables();
769 ::std::vector< ::rtl::OUString> aNames;
770 OSQLTables::const_iterator aEnd = aTables.end();
771 for(OSQLTables::const_iterator aIter = aTables.begin(); aIter != aEnd;++aIter)
772 aNames.push_back(aIter->first);
774 m_pTables = new OPrivateTables(aTables,m_xMetaData->supportsMixedCaseQuotedIdentifiers(),*this,m_aMutex,aNames);
777 return m_pTables;
779 // -------------------------------------------------------------------------
780 // XColumnsSupplier
781 Reference< XNameAccess > SAL_CALL OSingleSelectQueryComposer::getColumns( ) throw(RuntimeException)
783 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getColumns" );
784 ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
785 ::osl::MutexGuard aGuard( m_aMutex );
786 if ( !!m_aCurrentColumns[SelectColumns] )
787 return m_aCurrentColumns[SelectColumns];
789 ::std::vector< ::rtl::OUString> aNames;
790 ::vos::ORef< OSQLColumns> aSelectColumns;
791 sal_Bool bCase = sal_True;
792 Reference< XNameAccess> xQueryColumns;
793 if ( m_nCommandType == CommandType::QUERY )
795 Reference<XColumnsSupplier> xSup(m_xConnectionQueries->getByName(m_sCommand),UNO_QUERY);
796 if(xSup.is())
797 xQueryColumns = xSup->getColumns();
800 do {
804 SharedUNOComponent< XStatement, DisposableComponent > xStatement;
805 SharedUNOComponent< XPreparedStatement, DisposableComponent > xPreparedStatement;
807 bCase = m_xMetaData->supportsMixedCaseQuotedIdentifiers();
808 aSelectColumns = m_aSqlIterator.getSelectColumns();
810 ::rtl::OUStringBuffer aSQL;
811 aSQL.append( m_aPureSelectSQL );
812 aSQL.append( STR_WHERE );
814 // preserve the original WHERE clause
815 // #i102234# / 2009-06-02 / frank.schoenheit@sun.com
816 ::rtl::OUString sOriginalWhereClause = getSQLPart( Where, m_aSqlIterator, sal_False );
817 if ( sOriginalWhereClause.getLength() )
819 aSQL.appendAscii( " ( 0 = 1 ) AND ( " );
820 aSQL.append( sOriginalWhereClause );
821 aSQL.appendAscii( " ) " );
823 else
825 aSQL.appendAscii( " ( 0 = 1 ) " );
828 ::rtl::OUString sGroupBy = getSQLPart( Group, m_aSqlIterator, sal_True );
829 if ( sGroupBy.getLength() )
830 aSQL.append( sGroupBy );
832 ::rtl::OUString sSQL( aSQL.makeStringAndClear() );
833 // normalize the statement so that it doesn't contain any application-level features anymore
834 ::rtl::OUString sError;
835 const ::std::auto_ptr< OSQLParseNode > pStatementTree( m_aSqlParser.parseTree( sError, sSQL, false ) );
836 DBG_ASSERT( pStatementTree.get(), "OSingleSelectQueryComposer::getColumns: could not parse the column retrieval statement!" );
837 if ( pStatementTree.get() )
838 if ( !pStatementTree->parseNodeToExecutableStatement( sSQL, m_xConnection, m_aSqlParser, NULL ) )
839 break;
841 Reference< XResultSetMetaData > xResultSetMeta;
842 Reference< XResultSetMetaDataSupplier > xResMetaDataSup;
845 xPreparedStatement.set( m_xConnection->prepareStatement( sSQL ), UNO_QUERY_THROW );
846 xResMetaDataSup.set( xPreparedStatement, UNO_QUERY_THROW );
847 xResultSetMeta.set( xResMetaDataSup->getMetaData(), UNO_QUERY_THROW );
849 catch( const Exception& ) { }
853 if ( !xResultSetMeta.is() )
855 xStatement.reset( Reference< XStatement >( m_xConnection->createStatement(), UNO_QUERY_THROW ) );
856 Reference< XPropertySet > xStatementProps( xStatement, UNO_QUERY_THROW );
857 try { xStatementProps->setPropertyValue( PROPERTY_ESCAPE_PROCESSING, makeAny( sal_False ) ); }
858 catch ( const Exception& ) { DBG_UNHANDLED_EXCEPTION(); }
859 xResMetaDataSup.set( xStatement->executeQuery( sSQL ), UNO_QUERY_THROW );
860 xResultSetMeta.set( xResMetaDataSup->getMetaData(), UNO_QUERY_THROW );
863 catch( const Exception& )
865 //@see issue http://qa.openoffice.org/issues/show_bug.cgi?id=110111
866 // access returns a different order of column names when executing select * from
867 // and asking the columns from the metadata.
868 Reference< XParameters > xParameters( xPreparedStatement, UNO_QUERY_THROW );
869 Reference< XIndexAccess > xPara = getParameters();
870 for(sal_Int32 i = 1;i <= xPara->getCount();++i)
871 xParameters->setNull(i,DataType::VARCHAR);
872 xResMetaDataSup.set(xPreparedStatement->executeQuery(), UNO_QUERY_THROW );
873 xResultSetMeta.set( xResMetaDataSup->getMetaData(), UNO_QUERY_THROW );
876 if ( aSelectColumns->get().empty() )
878 // This is a valid case. If we can syntactically parse the query, but not semantically
879 // (e.g. because it is based on a table we do not know), then there will be no SelectColumns
880 aSelectColumns = ::connectivity::parse::OParseColumn::createColumnsForResultSet( xResultSetMeta, m_xMetaData ,xQueryColumns);
881 break;
884 const ::comphelper::UStringMixEqual aCaseCompare( bCase );
885 const ::comphelper::TStringMixEqualFunctor aCaseCompareFunctor( bCase );
886 typedef ::std::set< size_t > SizeTSet;
887 SizeTSet aUsedSelectColumns;
888 ::connectivity::parse::OParseColumn::StringMap aColumnNames;
890 sal_Int32 nCount = xResultSetMeta->getColumnCount();
891 OSL_ENSURE( (size_t) nCount == aSelectColumns->get().size(), "OSingleSelectQueryComposer::getColumns: inconsistent column counts, this might result in wrong columns!" );
892 for(sal_Int32 i=1;i<=nCount;++i)
894 ::rtl::OUString sColumnName = xResultSetMeta->getColumnName(i);
895 ::rtl::OUString sColumnLabel;
896 if ( xQueryColumns.is() && xQueryColumns->hasByName(sColumnName) )
898 Reference<XPropertySet> xQueryColumn(xQueryColumns->getByName(sColumnName),UNO_QUERY_THROW);
899 xQueryColumn->getPropertyValue(PROPERTY_LABEL) >>= sColumnLabel;
901 else
902 sColumnLabel = xResultSetMeta->getColumnLabel(i);
903 sal_Bool bFound = sal_False;
904 OSQLColumns::Vector::const_iterator aFind = ::connectivity::find(aSelectColumns->get().begin(),aSelectColumns->get().end(),sColumnLabel,aCaseCompare);
905 size_t nFoundSelectColumnPos = aFind - aSelectColumns->get().begin();
906 if ( aFind != aSelectColumns->get().end() )
908 if ( aUsedSelectColumns.find( nFoundSelectColumnPos ) != aUsedSelectColumns.end() )
909 { // we found a column name which exists twice
910 // so we start after the first found
913 aFind = ::connectivity::findRealName(++aFind,aSelectColumns->get().end(),sColumnName,aCaseCompare);
914 nFoundSelectColumnPos = aFind - aSelectColumns->get().begin();
916 while ( ( aUsedSelectColumns.find( nFoundSelectColumnPos ) != aUsedSelectColumns.end() )
917 && ( aFind != aSelectColumns->get().end() )
920 if ( aFind != aSelectColumns->get().end() )
922 (*aFind)->getPropertyValue(PROPERTY_NAME) >>= sColumnName;
923 aUsedSelectColumns.insert( nFoundSelectColumnPos );
924 aNames.push_back(sColumnName);
925 bFound = sal_True;
929 if ( bFound )
930 continue;
932 OSQLColumns::Vector::const_iterator aRealFind = ::connectivity::findRealName(
933 aSelectColumns->get().begin(), aSelectColumns->get().end(), sColumnName, aCaseCompare );
935 if ( i > static_cast< sal_Int32>( aSelectColumns->get().size() ) )
937 aSelectColumns->get().push_back(
938 ::connectivity::parse::OParseColumn::createColumnForResultSet( xResultSetMeta, m_xMetaData, i ,aColumnNames)
940 OSL_ENSURE( aSelectColumns->get().size() == (size_t)i, "OSingleSelectQueryComposer::getColumns: inconsistency!" );
942 else if ( aRealFind == aSelectColumns->get().end() )
944 // we can now only look if we found it under the realname propertery
945 // here we have to make the assumption that the position is correct
946 OSQLColumns::Vector::iterator aFind2 = aSelectColumns->get().begin() + i-1;
947 Reference<XPropertySet> xProp(*aFind2,UNO_QUERY);
948 if ( !xProp.is() || !xProp->getPropertySetInfo()->hasPropertyByName( PROPERTY_REALNAME ) )
949 continue;
951 ::connectivity::parse::OParseColumn* pColumn = new ::connectivity::parse::OParseColumn(xProp,bCase);
952 pColumn->setFunction(::comphelper::getBOOL(xProp->getPropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Function")))));
953 pColumn->setAggregateFunction(::comphelper::getBOOL(xProp->getPropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("AggregateFunction")))));
955 ::rtl::OUString sRealName;
956 xProp->getPropertyValue(PROPERTY_REALNAME) >>= sRealName;
957 ::std::vector< ::rtl::OUString>::iterator aFindName;
958 if ( !sColumnName.getLength() )
959 xProp->getPropertyValue(PROPERTY_NAME) >>= sColumnName;
962 aFindName = ::std::find_if(aNames.begin(),aNames.end(),::std::bind2nd(aCaseCompareFunctor,sColumnName));
963 sal_Int32 j = 0;
964 while ( aFindName != aNames.end() )
966 sColumnName += ::rtl::OUString::valueOf(++j);
967 aFindName = ::std::find_if(aNames.begin(),aNames.end(),::std::bind2nd(aCaseCompareFunctor,sColumnName));
970 pColumn->setName(sColumnName);
971 pColumn->setRealName(sRealName);
972 pColumn->setTableName(::comphelper::getString(xProp->getPropertyValue(PROPERTY_TABLENAME)));
974 (aSelectColumns->get())[i-1] = pColumn;
976 else
977 continue;
979 aUsedSelectColumns.insert( (size_t)(i - 1) );
980 aNames.push_back( sColumnName );
983 catch(const Exception&)
987 } while ( false );
989 if ( aNames.empty() )
990 m_aCurrentColumns[ SelectColumns ] = OPrivateColumns::createWithIntrinsicNames( aSelectColumns, bCase, *this, m_aMutex );
991 else
992 m_aCurrentColumns[ SelectColumns ] = new OPrivateColumns( aSelectColumns, bCase, *this, m_aMutex, aNames );
994 return m_aCurrentColumns[SelectColumns];
996 // -------------------------------------------------------------------------
997 sal_Bool OSingleSelectQueryComposer::setORCriteria(OSQLParseNode* pCondition, OSQLParseTreeIterator& _rIterator,
998 ::std::vector< ::std::vector < PropertyValue > >& rFilters, const Reference< ::com::sun::star::util::XNumberFormatter > & xFormatter) const
1000 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::setORCriteria" );
1001 // Runde Klammern um den Ausdruck
1002 if (pCondition->count() == 3 &&
1003 SQL_ISPUNCTUATION(pCondition->getChild(0),"(") &&
1004 SQL_ISPUNCTUATION(pCondition->getChild(2),")"))
1006 return setORCriteria(pCondition->getChild(1), _rIterator, rFilters, xFormatter);
1008 // oder Verknuepfung
1009 // a searchcondition can only look like this: search_condition SQL_TOKEN_OR boolean_term
1010 else if (SQL_ISRULE(pCondition,search_condition))
1012 sal_Bool bResult = sal_True;
1013 for (int i = 0; bResult && i < 3; i+=2)
1015 // Ist das erste Element wieder eine OR-Verknuepfung?
1016 // Dann rekursiv absteigen ...
1017 //if (!i && SQL_ISRULE(pCondition->getChild(i),search_condition))
1018 if (SQL_ISRULE(pCondition->getChild(i),search_condition))
1019 bResult = setORCriteria(pCondition->getChild(i), _rIterator, rFilters, xFormatter);
1020 else
1022 rFilters.push_back( ::std::vector < PropertyValue >());
1023 bResult = setANDCriteria(pCondition->getChild(i), _rIterator, rFilters[rFilters.size() - 1], xFormatter);
1026 return bResult;
1028 else
1030 rFilters.push_back(::std::vector < PropertyValue >());
1031 return setANDCriteria(pCondition, _rIterator, rFilters[rFilters.size() - 1], xFormatter);
1035 //--------------------------------------------------------------------------------------------------
1036 sal_Bool OSingleSelectQueryComposer::setANDCriteria( OSQLParseNode * pCondition,
1037 OSQLParseTreeIterator& _rIterator, ::std::vector < PropertyValue >& rFilter, const Reference< XNumberFormatter > & xFormatter) const
1039 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::setANDCriteria" );
1040 // Runde Klammern
1041 if (SQL_ISRULE(pCondition,boolean_primary))
1043 // this should not occur
1044 DBG_ERROR("boolean_primary in And-Criteria");
1045 return sal_False;
1047 // Das erste Element ist (wieder) eine AND-Verknuepfung
1048 else if ( SQL_ISRULE(pCondition,boolean_term) && pCondition->count() == 3 )
1050 return setANDCriteria(pCondition->getChild(0), _rIterator, rFilter, xFormatter) &&
1051 setANDCriteria(pCondition->getChild(2), _rIterator, rFilter, xFormatter);
1053 else if (SQL_ISRULE(pCondition, comparison_predicate))
1055 return setComparsionPredicate(pCondition,_rIterator,rFilter,xFormatter);
1057 else if (SQL_ISRULE(pCondition,like_predicate) ||
1058 SQL_ISRULE(pCondition,test_for_null) ||
1059 SQL_ISRULE(pCondition,in_predicate) ||
1060 SQL_ISRULE(pCondition,all_or_any_predicate) ||
1061 SQL_ISRULE(pCondition,between_predicate))
1063 if (SQL_ISRULE(pCondition->getChild(0), column_ref))
1065 PropertyValue aItem;
1066 ::rtl::OUString aValue;
1067 ::rtl::OUString aColumnName;
1070 // pCondition->parseNodeToStr(aValue,m_xMetaData, xFormatter, m_aLocale,static_cast<sal_Char>(m_sDecimalSep.toChar()));
1071 pCondition->parseNodeToStr( aValue, m_xConnection, NULL );
1072 // pCondition->getChild(0)->parseNodeToStr(aColumnName,m_xMetaData, xFormatter, m_aLocale,static_cast<sal_Char>(m_sDecimalSep.toChar()));
1073 pCondition->getChild(0)->parseNodeToStr( aColumnName, m_xConnection, NULL );
1075 // don't display the column name
1076 aValue = aValue.copy(aColumnName.getLength());
1077 aValue = aValue.trim();
1079 aItem.Name = getColumnName(pCondition->getChild(0),_rIterator);
1080 aItem.Value <<= aValue;
1081 aItem.Handle = 0; // just to know that this is not one the known ones
1082 if ( SQL_ISRULE(pCondition,like_predicate) )
1084 if ( SQL_ISTOKEN(pCondition->getChild(1)->getChild(0),NOT) )
1085 aItem.Handle = SQLFilterOperator::NOT_LIKE;
1086 else
1087 aItem.Handle = SQLFilterOperator::LIKE;
1089 else if (SQL_ISRULE(pCondition,test_for_null))
1091 if (SQL_ISTOKEN(pCondition->getChild(1)->getChild(1),NOT) )
1092 aItem.Handle = SQLFilterOperator::NOT_SQLNULL;
1093 else
1094 aItem.Handle = SQLFilterOperator::SQLNULL;
1096 else if (SQL_ISRULE(pCondition,in_predicate))
1098 OSL_ENSURE( false, "OSingleSelectQueryComposer::setANDCriteria: in_predicate not implemented!" );
1100 else if (SQL_ISRULE(pCondition,all_or_any_predicate))
1102 OSL_ENSURE( false, "OSingleSelectQueryComposer::setANDCriteria: all_or_any_predicate not implemented!" );
1104 else if (SQL_ISRULE(pCondition,between_predicate))
1106 OSL_ENSURE( false, "OSingleSelectQueryComposer::setANDCriteria: between_predicate not implemented!" );
1109 rFilter.push_back(aItem);
1111 else
1112 return sal_False;
1114 else if (SQL_ISRULE(pCondition,existence_test) ||
1115 SQL_ISRULE(pCondition,unique_test))
1117 // this couldn't be handled here, too complex
1118 // as we need a field name
1119 return sal_False;
1121 else
1122 return sal_False;
1124 return sal_True;
1126 // -----------------------------------------------------------------------------
1127 sal_Int32 OSingleSelectQueryComposer::getPredicateType(OSQLParseNode * _pPredicate) const
1129 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getPredicateType" );
1130 sal_Int32 nPredicate = SQLFilterOperator::EQUAL;
1131 switch (_pPredicate->getNodeType())
1133 case SQL_NODE_EQUAL:
1134 nPredicate = SQLFilterOperator::EQUAL;
1135 break;
1136 case SQL_NODE_NOTEQUAL:
1137 nPredicate = SQLFilterOperator::NOT_EQUAL;
1138 break;
1139 case SQL_NODE_LESS:
1140 nPredicate = SQLFilterOperator::LESS;
1141 break;
1142 case SQL_NODE_LESSEQ:
1143 nPredicate = SQLFilterOperator::LESS_EQUAL;
1144 break;
1145 case SQL_NODE_GREAT:
1146 nPredicate = SQLFilterOperator::GREATER;
1147 break;
1148 case SQL_NODE_GREATEQ:
1149 nPredicate = SQLFilterOperator::GREATER_EQUAL;
1150 break;
1151 default:
1152 OSL_ENSURE(0,"Wrong NodeType!");
1154 return nPredicate;
1156 //------------------------------------------------------------------------------
1157 sal_Bool OSingleSelectQueryComposer::setComparsionPredicate(OSQLParseNode * pCondition, OSQLParseTreeIterator& _rIterator,
1158 ::std::vector < PropertyValue >& rFilter, const Reference< ::com::sun::star::util::XNumberFormatter > & xFormatter) const
1160 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::setComparsionPredicate" );
1161 DBG_ASSERT(SQL_ISRULE(pCondition, comparison_predicate),"setComparsionPredicate: pCondition ist kein ComparsionPredicate");
1162 if (SQL_ISRULE(pCondition->getChild(0), column_ref) ||
1163 SQL_ISRULE(pCondition->getChild(pCondition->count()-1), column_ref))
1165 PropertyValue aItem;
1166 ::rtl::OUString aValue;
1167 sal_uInt32 nPos;
1168 if (SQL_ISRULE(pCondition->getChild(0), column_ref))
1170 nPos = 0;
1171 sal_uInt32 i=1;
1173 aItem.Handle = getPredicateType(pCondition->getChild(i));
1174 // don't display the equal
1175 if (pCondition->getChild(i)->getNodeType() == SQL_NODE_EQUAL)
1176 i++;
1178 // go forward
1179 for (;i < pCondition->count();i++)
1180 pCondition->getChild(i)->parseNodeToPredicateStr(
1181 aValue, m_xConnection, xFormatter, m_aLocale, static_cast<sal_Char>(m_sDecimalSep.toChar() ) );
1183 else if (SQL_ISRULE(pCondition->getChild(pCondition->count()-1), column_ref))
1185 nPos = pCondition->count()-1;
1187 sal_Int32 i = pCondition->count() - 2;
1188 switch (pCondition->getChild(i)->getNodeType())
1190 case SQL_NODE_EQUAL:
1191 // don't display the equal
1192 i--;
1193 aItem.Handle = SQLFilterOperator::EQUAL;
1194 break;
1195 case SQL_NODE_NOTEQUAL:
1196 i--;
1197 aItem.Handle = SQLFilterOperator::NOT_EQUAL;
1198 break;
1199 case SQL_NODE_LESS:
1200 // take the opposite as we change the order
1201 i--;
1202 aValue = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(">="));
1203 aItem.Handle = SQLFilterOperator::GREATER_EQUAL;
1204 break;
1205 case SQL_NODE_LESSEQ:
1206 // take the opposite as we change the order
1207 i--;
1208 aValue = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(">"));
1209 aItem.Handle = SQLFilterOperator::GREATER;
1210 break;
1211 case SQL_NODE_GREAT:
1212 // take the opposite as we change the order
1213 i--;
1214 aValue = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("<="));
1215 aItem.Handle = SQLFilterOperator::LESS_EQUAL;
1216 break;
1217 case SQL_NODE_GREATEQ:
1218 // take the opposite as we change the order
1219 i--;
1220 aValue = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("<"));
1221 aItem.Handle = SQLFilterOperator::LESS;
1222 break;
1223 default:
1224 break;
1227 // go backward
1228 for (; i >= 0; i--)
1229 pCondition->getChild(i)->parseNodeToPredicateStr(
1230 aValue, m_xConnection, xFormatter, m_aLocale, static_cast<sal_Char>( m_sDecimalSep.toChar() ) );
1232 else
1233 return sal_False;
1235 aItem.Name = getColumnName(pCondition->getChild(nPos),_rIterator);
1236 aItem.Value <<= aValue;
1237 rFilter.push_back(aItem);
1239 else if (SQL_ISRULE(pCondition->getChild(0), set_fct_spec ) ||
1240 SQL_ISRULE(pCondition->getChild(0), general_set_fct))
1242 PropertyValue aItem;
1243 ::rtl::OUString aValue;
1244 ::rtl::OUString aColumnName;
1246 pCondition->parseNodeToPredicateStr(aValue, m_xConnection, xFormatter, m_aLocale, static_cast<sal_Char>( m_sDecimalSep.toChar() ) );
1247 pCondition->getChild(0)->parseNodeToPredicateStr( aColumnName, m_xConnection, xFormatter, m_aLocale, static_cast<sal_Char>( m_sDecimalSep .toChar() ) );
1249 // don't display the column name
1250 aValue = aValue.copy(aColumnName.getLength());
1251 aValue.trim();
1253 aItem.Name = getColumnName(pCondition->getChild(0),_rIterator);
1254 aItem.Value <<= aValue;
1255 aItem.Handle = pCondition->getNodeType();
1256 rFilter.push_back(aItem);
1258 else // kann sich nur um einen Expr. Ausdruck handeln
1260 PropertyValue aItem;
1261 ::rtl::OUString aName, aValue;
1263 OSQLParseNode *pLhs = pCondition->getChild(0);
1264 OSQLParseNode *pRhs = pCondition->getChild(2);
1266 // Feldnamen
1267 sal_uInt16 i;
1268 for (i=0;i< pLhs->count();i++)
1269 pLhs->getChild(i)->parseNodeToPredicateStr( aName, m_xConnection, xFormatter, m_aLocale, static_cast<sal_Char>( m_sDecimalSep.toChar() ) );
1271 // Kriterium
1272 aItem.Handle = pCondition->getChild(1)->getNodeType();
1273 aValue = pCondition->getChild(1)->getTokenValue();
1274 for(i=0;i< pRhs->count();i++)
1275 pRhs->getChild(i)->parseNodeToPredicateStr(aValue, m_xConnection, xFormatter, m_aLocale, static_cast<sal_Char>( m_sDecimalSep.toChar() ) );
1277 aItem.Name = aName;
1278 aItem.Value <<= aValue;
1279 rFilter.push_back(aItem);
1281 return sal_True;
1283 // functions for analysing SQL
1284 //--------------------------------------------------------------------------------------------------
1285 ::rtl::OUString OSingleSelectQueryComposer::getColumnName( ::connectivity::OSQLParseNode* pColumnRef, OSQLParseTreeIterator& _rIterator ) const
1287 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getColumnName" );
1288 ::rtl::OUString aTableRange, aColumnName;
1289 _rIterator.getColumnRange(pColumnRef,aColumnName,aTableRange);
1290 return aColumnName;
1292 //------------------------------------------------------------------------------
1293 ::rtl::OUString SAL_CALL OSingleSelectQueryComposer::getFilter( ) throw(RuntimeException)
1295 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getFilter" );
1296 ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
1297 ::osl::MutexGuard aGuard( m_aMutex );
1298 return getSQLPart(Where,m_aAdditiveIterator,sal_False);
1300 // -------------------------------------------------------------------------
1301 ::rtl::OUString SAL_CALL OSingleSelectQueryComposer::getOrder( ) throw(RuntimeException)
1303 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getOrder" );
1304 ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
1305 ::osl::MutexGuard aGuard( m_aMutex );
1306 return getSQLPart(Order,m_aAdditiveIterator,sal_False);
1308 // -------------------------------------------------------------------------
1309 ::rtl::OUString SAL_CALL OSingleSelectQueryComposer::getGroup( ) throw (RuntimeException)
1311 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getGroup" );
1312 ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
1313 ::osl::MutexGuard aGuard( m_aMutex );
1314 return getSQLPart(Group,m_aAdditiveIterator,sal_False);
1316 // -----------------------------------------------------------------------------
1317 ::rtl::OUString OSingleSelectQueryComposer::getHavingClause() throw (RuntimeException)
1319 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getHavingClause" );
1320 ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
1321 ::osl::MutexGuard aGuard( m_aMutex );
1322 return getSQLPart(Having,m_aAdditiveIterator,sal_False);
1324 // -----------------------------------------------------------------------------
1325 ::rtl::OUString OSingleSelectQueryComposer::getTableAlias(const Reference< XPropertySet >& column) const
1327 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getTableAlias" );
1328 ::rtl::OUString sReturn;
1329 if(m_pTables && m_pTables->getCount() > 1)
1331 ::rtl::OUString aCatalog,aSchema,aTable,aComposedName,aColumnName;
1332 column->getPropertyValue(PROPERTY_CATALOGNAME) >>= aCatalog;
1333 column->getPropertyValue(PROPERTY_SCHEMANAME) >>= aSchema;
1334 column->getPropertyValue(PROPERTY_TABLENAME) >>= aTable;
1335 column->getPropertyValue(PROPERTY_NAME) >>= aColumnName;
1337 Sequence< ::rtl::OUString> aNames(m_pTables->getElementNames());
1338 const ::rtl::OUString* pBegin = aNames.getConstArray();
1339 const ::rtl::OUString* pEnd = pBegin + aNames.getLength();
1341 if(!aTable.getLength())
1342 { // we don't found a table name, now we must search every table for this column
1343 for(;pBegin != pEnd;++pBegin)
1345 Reference<XColumnsSupplier> xColumnsSupp;
1346 m_pTables->getByName(*pBegin) >>= xColumnsSupp;
1348 if(xColumnsSupp.is() && xColumnsSupp->getColumns()->hasByName(aColumnName))
1350 // Reference<XPropertySet> xTableProp(xColumnsSupp,UNO_QUERY);
1351 // xTableProp->getPropertyValue(PROPERTY_CATALOGNAME) >>= aCatalog;
1352 // xTableProp->getPropertyValue(PROPERTY_SCHEMANAME) >>= aSchema;
1353 // xTableProp->getPropertyValue(PROPERTY_NAME) >>= aTable;
1354 aTable = *pBegin;
1355 break;
1359 else
1361 aComposedName = ::dbtools::composeTableName( m_xMetaData, aCatalog, aSchema, aTable, sal_False, ::dbtools::eInDataManipulation );
1363 // first check if this is the table we want to or has it a tablealias
1365 if(!m_pTables->hasByName(aComposedName))
1367 ::comphelper::UStringMixLess aTmp(m_aAdditiveIterator.getTables().key_comp());
1368 ::comphelper::UStringMixEqual aComp(static_cast< ::comphelper::UStringMixLess*>(&aTmp)->isCaseSensitive());
1369 for(;pBegin != pEnd;++pBegin)
1371 Reference<XPropertySet> xTableProp;
1372 m_pTables->getByName(*pBegin) >>= xTableProp;
1373 OSL_ENSURE(xTableProp.is(),"Table isn't a propertyset!");
1374 if(xTableProp.is())
1376 ::rtl::OUString aCatalog2,aSchema2,aTable2;
1377 xTableProp->getPropertyValue(PROPERTY_CATALOGNAME) >>= aCatalog2;
1378 xTableProp->getPropertyValue(PROPERTY_SCHEMANAME) >>= aSchema2;
1379 xTableProp->getPropertyValue(PROPERTY_NAME) >>= aTable2;
1380 if(aComp(aCatalog,aCatalog2) && aComp(aSchema,aSchema2) && aComp(aTable,aTable2))
1382 aCatalog = aCatalog2;
1383 aSchema = aSchema2;
1384 aTable = aTable2;
1385 break;
1391 if(pBegin != pEnd)
1393 sReturn = ::dbtools::composeTableName( m_xMetaData, aCatalog, aSchema, aTable, sal_True, ::dbtools::eInDataManipulation );
1394 sReturn += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("."));
1397 return sReturn;
1399 // -----------------------------------------------------------------------------
1400 Reference< XIndexAccess > SAL_CALL OSingleSelectQueryComposer::getParameters( ) throw(RuntimeException)
1402 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getParameters" );
1403 // now set the Parameters
1404 if ( !m_aCurrentColumns[ParameterColumns] )
1406 ::vos::ORef< OSQLColumns> aCols = m_aSqlIterator.getParameters();
1407 ::std::vector< ::rtl::OUString> aNames;
1408 OSQLColumns::Vector::const_iterator aEnd = aCols->get().end();
1409 for(OSQLColumns::Vector::const_iterator aIter = aCols->get().begin(); aIter != aEnd;++aIter)
1410 aNames.push_back(getString((*aIter)->getPropertyValue(PROPERTY_NAME)));
1411 m_aCurrentColumns[ParameterColumns] = new OPrivateColumns(aCols,m_xMetaData->supportsMixedCaseQuotedIdentifiers(),*this,m_aMutex,aNames,sal_True);
1414 return m_aCurrentColumns[ParameterColumns];
1416 // -----------------------------------------------------------------------------
1417 void OSingleSelectQueryComposer::clearColumns( const EColumnType _eType )
1419 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::clearColumns" );
1420 OPrivateColumns* pColumns = m_aCurrentColumns[ _eType ];
1421 if ( pColumns != NULL )
1423 pColumns->disposing();
1424 m_aColumnsCollection.push_back( pColumns );
1425 m_aCurrentColumns[ _eType ] = NULL;
1428 // -----------------------------------------------------------------------------
1429 void OSingleSelectQueryComposer::clearCurrentCollections()
1431 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::clearCurrentCollections" );
1432 ::std::vector<OPrivateColumns*>::iterator aIter = m_aCurrentColumns.begin();
1433 ::std::vector<OPrivateColumns*>::iterator aEnd = m_aCurrentColumns.end();
1434 for (;aIter != aEnd;++aIter)
1436 if ( *aIter )
1438 (*aIter)->disposing();
1439 m_aColumnsCollection.push_back(*aIter);
1440 *aIter = NULL;
1444 if(m_pTables)
1446 m_pTables->disposing();
1447 m_aTablesCollection.push_back(m_pTables);
1448 m_pTables = NULL;
1451 // -----------------------------------------------------------------------------
1452 Reference< XIndexAccess > OSingleSelectQueryComposer::setCurrentColumns( EColumnType _eType,
1453 const ::vos::ORef< OSQLColumns >& _rCols )
1455 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::setCurrentColumns" );
1456 ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
1458 ::osl::MutexGuard aGuard( m_aMutex );
1459 // now set the group columns
1460 if ( !m_aCurrentColumns[_eType] )
1462 ::std::vector< ::rtl::OUString> aNames;
1463 OSQLColumns::Vector::const_iterator aEnd = _rCols->get().end();
1464 for(OSQLColumns::Vector::const_iterator aIter = _rCols->get().begin(); aIter != aEnd;++aIter)
1465 aNames.push_back(getString((*aIter)->getPropertyValue(PROPERTY_NAME)));
1466 m_aCurrentColumns[_eType] = new OPrivateColumns(_rCols,m_xMetaData->supportsMixedCaseQuotedIdentifiers(),*this,m_aMutex,aNames,sal_True);
1469 return m_aCurrentColumns[_eType];
1471 // -----------------------------------------------------------------------------
1472 Reference< XIndexAccess > SAL_CALL OSingleSelectQueryComposer::getGroupColumns( ) throw(RuntimeException)
1474 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getGroupColumns" );
1475 return setCurrentColumns( GroupByColumns, m_aAdditiveIterator.getGroupColumns() );
1477 // -------------------------------------------------------------------------
1478 Reference< XIndexAccess > SAL_CALL OSingleSelectQueryComposer::getOrderColumns( ) throw(RuntimeException)
1480 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getOrderColumns" );
1481 return setCurrentColumns( OrderColumns, m_aAdditiveIterator.getOrderColumns() );
1483 // -----------------------------------------------------------------------------
1484 ::rtl::OUString SAL_CALL OSingleSelectQueryComposer::getQueryWithSubstitution( ) throw (SQLException, RuntimeException)
1486 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getQueryWithSubstitution" );
1487 ::osl::MutexGuard aGuard( m_aMutex );
1488 ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
1490 ::rtl::OUString sSqlStatement( getQuery() );
1492 const OSQLParseNode* pStatementNode = m_aSqlIterator.getParseTree();
1493 if ( pStatementNode )
1495 SQLException aError;
1496 if ( !pStatementNode->parseNodeToExecutableStatement( sSqlStatement, m_xConnection, m_aSqlParser, &aError ) )
1497 throw SQLException( aError );
1500 return sSqlStatement;
1502 // -----------------------------------------------------------------------------
1503 ::rtl::OUString OSingleSelectQueryComposer::getStatementPart( TGetParseNode& _aGetFunctor, OSQLParseTreeIterator& _rIterator )
1505 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getStatementPart" );
1506 ::rtl::OUString sResult;
1508 const OSQLParseNode* pNode = _aGetFunctor( &_rIterator );
1509 if ( pNode )
1510 pNode->parseNodeToStr( sResult, m_xConnection );
1512 return sResult;
1514 // -----------------------------------------------------------------------------
1515 namespace
1517 ::rtl::OUString lcl_getCondition(const Sequence< Sequence< PropertyValue > >& filter )
1519 ::rtl::OUStringBuffer sRet;
1520 const Sequence< PropertyValue >* pOrIter = filter.getConstArray();
1521 const Sequence< PropertyValue >* pOrEnd = pOrIter + filter.getLength();
1522 while ( pOrIter != pOrEnd )
1524 if ( pOrIter->getLength() )
1526 sRet.append(L_BRACKET);
1527 const PropertyValue* pAndIter = pOrIter->getConstArray();
1528 const PropertyValue* pAndEnd = pAndIter + pOrIter->getLength();
1529 while ( pAndIter != pAndEnd )
1531 sRet.append(pAndIter->Name);
1532 ::rtl::OUString sValue;
1533 pAndIter->Value >>= sValue;
1534 lcl_addFilterCriteria_throw(pAndIter->Handle,sValue,sRet);
1535 ++pAndIter;
1536 if ( pAndIter != pAndEnd )
1537 sRet.append(STR_AND);
1539 sRet.append(R_BRACKET);
1541 ++pOrIter;
1542 if ( pOrIter != pOrEnd && sRet.getLength() )
1543 sRet.append(STR_OR);
1545 return sRet.makeStringAndClear();
1548 // -----------------------------------------------------------------------------
1549 void SAL_CALL OSingleSelectQueryComposer::setStructuredFilter( const Sequence< Sequence< PropertyValue > >& filter ) throw (SQLException, ::com::sun::star::lang::IllegalArgumentException, RuntimeException)
1551 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::setStructuredFilter" );
1552 setFilter(lcl_getCondition(filter));
1554 // -----------------------------------------------------------------------------
1555 void SAL_CALL OSingleSelectQueryComposer::setStructuredHavingClause( const Sequence< Sequence< PropertyValue > >& filter ) throw (SQLException, RuntimeException)
1557 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::setStructuredHavingClause" );
1558 setHavingClause(lcl_getCondition(filter));
1560 // -----------------------------------------------------------------------------
1561 void OSingleSelectQueryComposer::setConditionByColumn( const Reference< XPropertySet >& column, sal_Bool andCriteria ,::std::mem_fun1_t<bool,OSingleSelectQueryComposer,::rtl::OUString>& _aSetFunctor,sal_Int32 filterOperator)
1563 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::setConditionByColumn" );
1564 ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
1566 if ( !column.is()
1567 || !column->getPropertySetInfo()->hasPropertyByName(PROPERTY_VALUE)
1568 || !column->getPropertySetInfo()->hasPropertyByName(PROPERTY_NAME)
1569 || !column->getPropertySetInfo()->hasPropertyByName(PROPERTY_TYPE))
1570 throw SQLException(DBACORE_RESSTRING(RID_STR_COLUMN_NOT_VALID),*this,SQLSTATE_GENERAL,1000,Any() );
1572 sal_Int32 nType = 0;
1573 column->getPropertyValue(PROPERTY_TYPE) >>= nType;
1574 sal_Int32 nSearchable = dbtools::getSearchColumnFlag(m_xConnection,nType);
1575 if(nSearchable == ColumnSearch::NONE)
1576 throw SQLException(DBACORE_RESSTRING(RID_STR_COLUMN_NOT_SEARCHABLE),*this,SQLSTATE_GENERAL,1000,Any() );
1578 ::osl::MutexGuard aGuard( m_aMutex );
1580 ::rtl::OUString aName;
1581 column->getPropertyValue(PROPERTY_NAME) >>= aName;
1583 Any aValue;
1584 column->getPropertyValue(PROPERTY_VALUE) >>= aValue;
1586 ::rtl::OUStringBuffer aSQL;
1587 const ::rtl::OUString aQuote = m_xMetaData->getIdentifierQuoteString();
1588 getColumns();
1590 if ( m_aCurrentColumns[SelectColumns] && m_aCurrentColumns[SelectColumns]->hasByName(aName) )
1592 Reference<XPropertySet> xColumn;
1593 m_aCurrentColumns[SelectColumns]->getByName(aName) >>= xColumn;
1594 OSL_ENSURE(xColumn->getPropertySetInfo()->hasPropertyByName(PROPERTY_REALNAME),"Property REALNAME not available!");
1595 OSL_ENSURE(xColumn->getPropertySetInfo()->hasPropertyByName(PROPERTY_TABLENAME),"Property TABLENAME not available!");
1596 OSL_ENSURE(xColumn->getPropertySetInfo()->hasPropertyByName(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("AggregateFunction"))),"Property AggregateFunctionnot available!");
1598 ::rtl::OUString sRealName,sTableName;
1599 xColumn->getPropertyValue(PROPERTY_REALNAME) >>= sRealName;
1600 xColumn->getPropertyValue(PROPERTY_TABLENAME) >>= sTableName;
1601 if(sTableName.indexOf('.',0) != -1)
1603 ::rtl::OUString aCatlog,aSchema,aTable;
1604 ::dbtools::qualifiedNameComponents(m_xMetaData,sTableName,aCatlog,aSchema,aTable,::dbtools::eInDataManipulation);
1605 sTableName = ::dbtools::composeTableName( m_xMetaData, aCatlog, aSchema, aTable, sal_True, ::dbtools::eInDataManipulation );
1607 else
1608 sTableName = ::dbtools::quoteName(aQuote,sTableName);
1610 if ( !::comphelper::getBOOL(xColumn->getPropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Function")))) )
1612 aSQL = sTableName;
1613 aSQL.appendAscii( "." );
1614 aSQL.append( ::dbtools::quoteName( aQuote, sRealName ) );
1616 else
1617 aSQL = sRealName;
1620 else
1622 aSQL = getTableAlias( column );
1623 aSQL.append( ::dbtools::quoteName( aQuote, aName ) );
1627 if ( aValue.hasValue() )
1629 if( !m_xTypeConverter.is() )
1630 m_aContext.createComponent( "com.sun.star.script.Converter", m_xTypeConverter );
1631 OSL_ENSURE(m_xTypeConverter.is(),"NO typeconverter!");
1633 if ( nType != DataType::BOOLEAN && DataType::BIT != nType )
1635 ::rtl::OUString sEmpty;
1636 lcl_addFilterCriteria_throw(filterOperator,sEmpty,aSQL);
1639 switch(nType)
1641 case DataType::VARCHAR:
1642 case DataType::CHAR:
1643 case DataType::LONGVARCHAR:
1644 aSQL.append( DBTypeConversion::toSQLString( nType, aValue, sal_True, m_xTypeConverter ) );
1645 break;
1646 case DataType::CLOB:
1648 Reference< XClob > xClob(aValue,UNO_QUERY);
1649 if ( xClob.is() )
1651 const ::sal_Int64 nLength = xClob->length();
1652 if ( sal_Int64(nLength + aSQL.getLength() + STR_LIKE.getLength() ) < sal_Int64(SAL_MAX_INT32) )
1654 aSQL.appendAscii("'");
1655 aSQL.append( xClob->getSubString(1,(sal_Int32)nLength) );
1656 aSQL.appendAscii("'");
1659 else
1661 aSQL.append( DBTypeConversion::toSQLString( nType, aValue, sal_True, m_xTypeConverter ) );
1664 break;
1665 case DataType::VARBINARY:
1666 case DataType::BINARY:
1667 case DataType::LONGVARBINARY:
1669 Sequence<sal_Int8> aSeq;
1670 if(aValue >>= aSeq)
1672 if(nSearchable == ColumnSearch::CHAR)
1674 aSQL.appendAscii( "\'" );
1676 aSQL.appendAscii( "0x" );
1677 const sal_Int8* pBegin = aSeq.getConstArray();
1678 const sal_Int8* pEnd = pBegin + aSeq.getLength();
1679 for(;pBegin != pEnd;++pBegin)
1681 aSQL.append( (sal_Int32)*pBegin, 16 ).getStr();
1683 if(nSearchable == ColumnSearch::CHAR)
1684 aSQL.appendAscii( "\'" );
1686 else
1687 throw SQLException(DBACORE_RESSTRING(RID_STR_NOT_SEQUENCE_INT8),*this,SQLSTATE_GENERAL,1000,Any() );
1689 break;
1690 case DataType::BIT:
1691 case DataType::BOOLEAN:
1693 sal_Bool bValue = sal_False;
1694 m_xTypeConverter->convertToSimpleType(aValue, TypeClass_BOOLEAN) >>= bValue;
1696 ::rtl::OUString sColumnExp = aSQL.makeStringAndClear();
1697 getBoleanComparisonPredicate( sColumnExp, bValue, m_nBoolCompareMode, aSQL );
1699 break;
1700 default:
1701 aSQL.append( DBTypeConversion::toSQLString( nType, aValue, sal_True, m_xTypeConverter ) );
1702 break;
1705 else
1707 sal_Int32 nFilterOp = filterOperator;
1708 if ( filterOperator != SQLFilterOperator::SQLNULL && filterOperator != SQLFilterOperator::NOT_SQLNULL )
1709 nFilterOp = SQLFilterOperator::SQLNULL;
1710 ::rtl::OUString sEmpty;
1711 lcl_addFilterCriteria_throw(nFilterOp,sEmpty,aSQL);
1714 // filter anhaengen
1715 // select ohne where und order by aufbauen
1716 ::rtl::OUString sFilter = getFilter();
1718 if ( sFilter.getLength() && aSQL.getLength() )
1720 ::rtl::OUString sTemp(L_BRACKET);
1721 sTemp += sFilter;
1722 sTemp += R_BRACKET;
1723 sTemp += andCriteria ? STR_AND : STR_OR;
1724 sFilter = sTemp;
1726 sFilter += aSQL.makeStringAndClear();
1728 // add the filter and the sort order
1729 _aSetFunctor(this,sFilter);
1731 // -----------------------------------------------------------------------------
1732 Sequence< Sequence< PropertyValue > > OSingleSelectQueryComposer::getStructuredCondition( TGetParseNode& _aGetFunctor )
1734 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getStructuredCondition" );
1735 ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
1737 MutexGuard aGuard(m_aMutex);
1739 Sequence< Sequence< PropertyValue > > aFilterSeq;
1740 ::rtl::OUString sFilter = getStatementPart( _aGetFunctor, m_aAdditiveIterator );
1742 if ( sFilter.getLength() != 0 )
1744 ::rtl::OUString aSql(m_aPureSelectSQL);
1745 // build a temporary parse node
1746 const OSQLParseNode* pTempNode = m_aAdditiveIterator.getParseTree();
1748 aSql += STR_WHERE;
1749 aSql += sFilter;
1751 ::rtl::OUString aErrorMsg;
1752 ::std::auto_ptr<OSQLParseNode> pSqlParseNode( m_aSqlParser.parseTree(aErrorMsg,aSql));
1753 if ( pSqlParseNode.get() )
1755 m_aAdditiveIterator.setParseTree(pSqlParseNode.get());
1756 // normalize the filter
1757 OSQLParseNode* pWhereNode = const_cast<OSQLParseNode*>(m_aAdditiveIterator.getWhereTree());
1759 OSQLParseNode* pCondition = pWhereNode->getChild(1);
1760 #if OSL_DEBUG_LEVEL > 0
1761 ::rtl::OUString sCondition;
1762 pCondition->parseNodeToStr( sCondition, m_xConnection );
1763 #endif
1764 OSQLParseNode::negateSearchCondition(pCondition);
1766 pCondition = pWhereNode->getChild(1);
1767 #if OSL_DEBUG_LEVEL > 0
1768 sCondition = ::rtl::OUString();
1769 pCondition->parseNodeToStr( sCondition, m_xConnection );
1770 #endif
1771 OSQLParseNode::disjunctiveNormalForm(pCondition);
1773 pCondition = pWhereNode->getChild(1);
1774 #if OSL_DEBUG_LEVEL > 0
1775 sCondition = ::rtl::OUString();
1776 pCondition->parseNodeToStr( sCondition, m_xConnection );
1777 #endif
1778 OSQLParseNode::absorptions(pCondition);
1780 pCondition = pWhereNode->getChild(1);
1781 #if OSL_DEBUG_LEVEL > 0
1782 sCondition = ::rtl::OUString();
1783 pCondition->parseNodeToStr( sCondition, m_xConnection );
1784 #endif
1785 if ( pCondition )
1787 ::std::vector< ::std::vector < PropertyValue > > aFilters;
1788 Reference< XNumberFormatter > xFormatter;
1789 m_aContext.createComponent( "com.sun.star.util.NumberFormatter", xFormatter );
1790 xFormatter->attachNumberFormatsSupplier( m_xNumberFormatsSupplier );
1792 if (setORCriteria(pCondition, m_aAdditiveIterator, aFilters, xFormatter))
1794 aFilterSeq.realloc(aFilters.size());
1795 Sequence<PropertyValue>* pFilters = aFilterSeq.getArray();
1796 ::std::vector< ::std::vector < PropertyValue > >::const_iterator aEnd = aFilters.end();
1797 ::std::vector< ::std::vector < PropertyValue > >::const_iterator i = aFilters.begin();
1798 for ( ; i != aEnd ; ++i)
1800 const ::std::vector < PropertyValue >& rProperties = *i;
1801 pFilters->realloc(rProperties.size());
1802 PropertyValue* pFilter = pFilters->getArray();
1803 ::std::vector < PropertyValue >::const_iterator j = rProperties.begin();
1804 ::std::vector < PropertyValue >::const_iterator aEnd2 = rProperties.end();
1805 for ( ; j != aEnd2 ; ++j)
1807 *pFilter = *j;
1808 ++pFilter;
1810 ++pFilters;
1814 // restore
1815 m_aAdditiveIterator.setParseTree(pTempNode);
1818 return aFilterSeq;
1820 // -----------------------------------------------------------------------------
1821 ::rtl::OUString OSingleSelectQueryComposer::getKeyword( SQLPart _ePart ) const
1823 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getKeyword" );
1824 ::rtl::OUString sKeyword;
1825 switch(_ePart)
1827 default:
1828 OSL_ENSURE( 0, "OSingleSelectQueryComposer::getKeyWord: Invalid enum value!" );
1829 // no break, fallback to WHERE
1830 case Where:
1831 sKeyword = STR_WHERE;
1832 break;
1833 case Group:
1834 sKeyword = STR_GROUP_BY;
1835 break;
1836 case Having:
1837 sKeyword = STR_HAVING;
1838 break;
1839 case Order:
1840 sKeyword = STR_ORDER_BY;
1841 break;
1843 return sKeyword;
1846 // -----------------------------------------------------------------------------
1847 ::rtl::OUString OSingleSelectQueryComposer::getSQLPart( SQLPart _ePart, OSQLParseTreeIterator& _rIterator, sal_Bool _bWithKeyword )
1849 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getSQLPart" );
1850 TGetParseNode F_tmp(&OSQLParseTreeIterator::getSimpleWhereTree);
1851 ::rtl::OUString sKeyword( getKeyword( _ePart ) );
1852 switch(_ePart)
1854 case Where:
1855 F_tmp = TGetParseNode(&OSQLParseTreeIterator::getSimpleWhereTree);
1856 break;
1857 case Group:
1858 F_tmp = TGetParseNode (&OSQLParseTreeIterator::getSimpleGroupByTree);
1859 break;
1860 case Having:
1861 F_tmp = TGetParseNode(&OSQLParseTreeIterator::getSimpleHavingTree);
1862 break;
1863 case Order:
1864 F_tmp = TGetParseNode(&OSQLParseTreeIterator::getSimpleOrderTree);
1865 break;
1866 default:
1867 OSL_ENSURE(0,"Invalid enum value!");
1870 ::rtl::OUString sRet = getStatementPart( F_tmp, _rIterator );
1871 if ( _bWithKeyword && sRet.getLength() )
1872 sRet = sKeyword + sRet;
1873 return sRet;
1875 // -----------------------------------------------------------------------------