1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
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>
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
;
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(","))
98 /** parses the given statement, using the given parser, returns a parse node representing
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
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
) );
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
);
167 _pRootNode
->getChild(3)->getChild(0)->getChild(1)->parseNodeToStr( sSQL
, _rxConnection
);
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
;
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
);
189 case SQLFilterOperator::NOT_EQUAL
:
190 o_sRet
.append(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" <> ")));
191 o_sRet
.append(i_sValue
);
193 case SQLFilterOperator::LESS
:
194 o_sRet
.append(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" < ")));
195 o_sRet
.append(i_sValue
);
197 case SQLFilterOperator::GREATER
:
198 o_sRet
.append(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" > ")));
199 o_sRet
.append(i_sValue
);
201 case SQLFilterOperator::LESS_EQUAL
:
202 o_sRet
.append(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" <= ")));
203 o_sRet
.append(i_sValue
);
205 case SQLFilterOperator::GREATER_EQUAL
:
206 o_sRet
.append(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" >= ")));
207 o_sRet
.append(i_sValue
);
209 case SQLFilterOperator::LIKE
:
210 o_sRet
.append(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" LIKE ")));
211 o_sRet
.append(i_sValue
);
213 case SQLFilterOperator::NOT_LIKE
:
214 o_sRet
.append(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" NOT LIKE ")));
215 o_sRet
.append(i_sValue
);
217 case SQLFilterOperator::SQLNULL
:
218 o_sRet
.append(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" IS NULL")) );
220 case SQLFilterOperator::NOT_SQLNULL
:
221 o_sRet
.append(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" IS NOT NULL")) );
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
)
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");
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();
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
)
290 ::std::vector
<OPrivateTables
*>::iterator aTabIter
= m_aTablesCollection
.begin();
291 ::std::vector
<OPrivateTables
*>::iterator aTabEnd
= m_aTablesCollection
.end();
292 for(;aTabIter
!= aTabEnd
;++aTabIter
)
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);
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
);
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
)
379 if ( e
.TargetException
>>= e2
)
384 DBG_UNHANDLED_EXCEPTION();
387 sSQL
.append(dbtools::composeTableNameForSelect(m_xConnection
,xTable
));
391 String
sMessage( DBACORE_RESSTRING( RID_STR_TABLE_DOES_NOT_EXIST
) );
392 sMessage
.SearchAndReplaceAscii( "$table$", Command
);
393 throwGenericSQLException(sMessage
,*this);
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
);
407 String
sMessage( DBACORE_RESSTRING( RID_STR_QUERY_DOES_NOT_EXIST
) );
408 sMessage
.SearchAndReplaceAscii( "$table$", Command
);
409 throwGenericSQLException(sMessage
,*this);
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" );
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
);
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
);
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() );
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
)
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
);
525 sTableName
= ::dbtools::quoteName(aQuote
,sTableName
);
527 aNewName
= sTableName
;
528 aNewName
+= ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("."));
529 aNewName
+= ::dbtools::quoteName(aQuote
,sRealName
);
533 aNewName
= ::dbtools::quoteName(aQuote
,aName
);
536 aNewName
= getTableAlias(column
) + ::dbtools::quoteName(aQuote
,aName
);
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()) )
548 sOrder
+= sColumnName
;
549 if ( !(ascending
|| sColumnName
.isEmpty()) )
550 sOrder
+= ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" DESC "));
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
)
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
625 ::rtl::OUString
getComposedClause( const ::rtl::OUString _rElementaryClause
, const ::rtl::OUString _rAdditionalClause
,
626 TokenComposer
& _rComposer
, const ::rtl::OUString _rKeyword
)
629 _rComposer
.append( _rElementaryClause
);
630 _rComposer
.append( _rAdditionalClause
);
631 ::rtl::OUString sComposed
= _rComposer
.getComposedAndClear();
632 if ( !sComposed
.isEmpty() )
633 sComposed
= _rKeyword
+ 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
)
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
);
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
]);
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
)
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
);
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
);
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
);
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
);
765 xQueryColumns
= xSup
->getColumns();
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
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( " ) " );
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
) )
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
);
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
;
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
);
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
) )
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
));
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
;
948 aUsedSelectColumns
.insert( (size_t)(i
- 1) );
949 aNames
.push_back( sColumnName
);
952 catch(const Exception
&)
958 if ( aNames
.empty() )
959 m_aCurrentColumns
[ SelectColumns
] = OPrivateColumns::createWithIntrinsicNames( aSelectColumns
, bCase
, *this, m_aMutex
);
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
);
990 rFilters
.push_back( ::std::vector
< PropertyValue
>());
991 bResult
= setANDCriteria(pCondition
->getChild(i
), _rIterator
, rFilters
[rFilters
.size() - 1], xFormatter
);
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" );
1008 if (SQL_ISRULE(pCondition
,boolean_primary
))
1010 // this should not occur
1011 OSL_FAIL("boolean_primary in And-Criteria");
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
;
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
;
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
);
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
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
;
1101 case SQL_NODE_NOTEQUAL
:
1102 nPredicate
= SQLFilterOperator::NOT_EQUAL
;
1105 nPredicate
= SQLFilterOperator::LESS
;
1107 case SQL_NODE_LESSEQ
:
1108 nPredicate
= SQLFilterOperator::LESS_EQUAL
;
1110 case SQL_NODE_GREAT
:
1111 nPredicate
= SQLFilterOperator::GREATER
;
1113 case SQL_NODE_GREATEQ
:
1114 nPredicate
= SQLFilterOperator::GREATER_EQUAL
;
1117 OSL_FAIL("Wrong NodeType!");
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
;
1133 if (SQL_ISRULE(pCondition
->getChild(0), column_ref
))
1138 aItem
.Handle
= getPredicateType(pCondition
->getChild(i
));
1139 // don't display the equal
1140 if (pCondition
->getChild(i
)->getNodeType() == SQL_NODE_EQUAL
)
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
1158 aItem
.Handle
= SQLFilterOperator::EQUAL
;
1160 case SQL_NODE_NOTEQUAL
:
1162 aItem
.Handle
= SQLFilterOperator::NOT_EQUAL
;
1165 // take the opposite as we change the order
1167 aValue
= ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(">="));
1168 aItem
.Handle
= SQLFilterOperator::GREATER_EQUAL
;
1170 case SQL_NODE_LESSEQ
:
1171 // take the opposite as we change the order
1173 aValue
= ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(">"));
1174 aItem
.Handle
= SQLFilterOperator::GREATER
;
1176 case SQL_NODE_GREAT
:
1177 // take the opposite as we change the order
1179 aValue
= ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("<="));
1180 aItem
.Handle
= SQLFilterOperator::LESS_EQUAL
;
1182 case SQL_NODE_GREATEQ
:
1183 // take the opposite as we change the order
1185 aValue
= ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("<"));
1186 aItem
.Handle
= SQLFilterOperator::LESS
;
1194 pCondition
->getChild(i
)->parseNodeToPredicateStr(
1195 aValue
, m_xConnection
, xFormatter
, m_aLocale
, static_cast<sal_Char
>( m_sDecimalSep
.toChar() ) );
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);
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() ) );
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() ) );
1239 aItem
.Value
<<= aValue
;
1240 rFilter
.push_back(aItem
);
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
);
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
))
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!");
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
;
1353 sReturn
= ::dbtools::composeTableName( m_xMetaData
, aCatalog
, aSchema
, aTable
, sal_True
, ::dbtools::eInDataManipulation
);
1354 sReturn
+= ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("."));
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
)
1398 (*aIter
)->disposing();
1399 m_aColumnsCollection
.push_back(*aIter
);
1406 m_pTables
->disposing();
1407 m_aTablesCollection
.push_back(m_pTables
);
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
);
1470 pNode
->parseNodeToStr( sResult
, m_xConnection
);
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
);
1501 sValue
= i_aPredicateInputController
.getPredicateValue(pAndIter
->Name
,sValue
,sal_True
);
1503 lcl_addFilterCriteria_throw(pAndIter
->Handle
,sValue
,sRet
);
1505 if ( pAndIter
!= pAndEnd
)
1506 sRet
.append(STR_AND
);
1508 sRet
.append(R_BRACKET
);
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
);
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
;
1555 column
->getPropertyValue(PROPERTY_VALUE
) >>= aValue
;
1557 ::rtl::OUStringBuffer aSQL
;
1558 const ::rtl::OUString aQuote
= m_xMetaData
->getIdentifierQuoteString();
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
);
1579 sTableName
= ::dbtools::quoteName(aQuote
,sTableName
);
1581 if ( !::comphelper::getBOOL(xColumn
->getPropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Function")))) )
1584 aSQL
.appendAscii( "." );
1585 aSQL
.append( ::dbtools::quoteName( aQuote
, sRealName
) );
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
);
1611 case DataType::VARCHAR
:
1612 case DataType::CHAR
:
1613 case DataType::LONGVARCHAR
:
1614 aSQL
.append( DBTypeConversion::toSQLString( nType
, aValue
, sal_True
, m_xTypeConverter
) );
1616 case DataType::CLOB
:
1618 Reference
< XClob
> xClob(aValue
,UNO_QUERY
);
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("'");
1631 aSQL
.append( DBTypeConversion::toSQLString( nType
, aValue
, sal_True
, m_xTypeConverter
) );
1635 case DataType::VARBINARY
:
1636 case DataType::BINARY
:
1637 case DataType::LONGVARBINARY
:
1639 Sequence
<sal_Int8
> 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( "\'" );
1657 throw SQLException(DBACORE_RESSTRING(RID_STR_NOT_SEQUENCE_INT8
),*this,SQLSTATE_GENERAL
,1000,Any() );
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
);
1671 aSQL
.append( DBTypeConversion::toSQLString( nType
, aValue
, sal_True
, m_xTypeConverter
) );
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
);
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
);
1693 sTemp
+= andCriteria
? STR_AND
: STR_OR
;
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();
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
);
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
);
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
);
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
);
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
)
1786 m_aAdditiveIterator
.setParseTree(pTempNode
);
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
;
1799 OSL_FAIL( "OSingleSelectQueryComposer::getKeyWord: Invalid enum value!" );
1800 // no break, fallback to WHERE
1802 sKeyword
= STR_WHERE
;
1805 sKeyword
= STR_GROUP_BY
;
1808 sKeyword
= STR_HAVING
;
1811 sKeyword
= STR_ORDER_BY
;
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
) );
1825 F_tmp
= TGetParseNode(&OSQLParseTreeIterator::getSimpleWhereTree
);
1828 F_tmp
= TGetParseNode (&OSQLParseTreeIterator::getSimpleGroupByTree
);
1831 F_tmp
= TGetParseNode(&OSQLParseTreeIterator::getSimpleHavingTree
);
1834 F_tmp
= TGetParseNode(&OSQLParseTreeIterator::getSimpleOrderTree
);
1837 OSL_FAIL("Invalid enum value!");
1840 ::rtl::OUString sRet
= getStatementPart( F_tmp
, _rIterator
);
1841 if ( _bWithKeyword
&& !sRet
.isEmpty() )
1842 sRet
= sKeyword
+ sRet
;
1845 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */