xref: /trunk/main/dbaccess/source/core/api/SingleSelectQueryComposer.cxx (revision 46c69c84579d1f1df536015e7d54c9965db90b69)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_dbaccess.hxx"
26 
27 #include "composertools.hxx"
28 #include "core_resource.hrc"
29 #include "core_resource.hxx"
30 #include "dbastrings.hrc"
31 #include "HelperCollections.hxx"
32 #include "SingleSelectQueryComposer.hxx"
33 #include "sdbcoretools.hxx"
34 
35 /** === begin UNO includes === **/
36 #include <com/sun/star/beans/PropertyAttribute.hpp>
37 #include <com/sun/star/container/XChild.hpp>
38 #include <com/sun/star/i18n/XLocaleData.hpp>
39 #include <com/sun/star/lang/DisposedException.hpp>
40 #include <com/sun/star/sdb/BooleanComparisonMode.hpp>
41 #include <com/sun/star/sdb/SQLFilterOperator.hpp>
42 #include <com/sun/star/sdb/XQueriesSupplier.hpp>
43 #include <com/sun/star/sdb/CommandType.hpp>
44 #include <com/sun/star/sdbc/ColumnSearch.hpp>
45 #include <com/sun/star/sdbc/DataType.hpp>
46 #include <com/sun/star/sdbc/XResultSetMetaData.hpp>
47 #include <com/sun/star/sdbc/XResultSetMetaDataSupplier.hpp>
48 #include <com/sun/star/sdbc/XParameters.hpp>
49 #include <com/sun/star/uno/XAggregation.hpp>
50 #include <com/sun/star/util/XNumberFormatter.hpp>
51 /** === end UNO includes === **/
52 
53 #include <comphelper/processfactory.hxx>
54 #include <comphelper/sequence.hxx>
55 #include <comphelper/types.hxx>
56 #include <cppuhelper/typeprovider.hxx>
57 #include <connectivity/predicateinput.hxx>
58 #include <rtl/logfile.hxx>
59 #include <unotools/syslocale.hxx>
60 #include <tools/debug.hxx>
61 #include <tools/diagnose_ex.h>
62 #include <unotools/configmgr.hxx>
63 #include <unotools/sharedunocomponent.hxx>
64 
65 #include <memory>
66 #include <functional>
67 
68 using namespace ::dbaccess;
69 using namespace ::dbtools;
70 using namespace ::comphelper;
71 using namespace ::connectivity;
72 using namespace ::com::sun::star::uno;
73 using namespace ::com::sun::star::beans;
74 using namespace ::com::sun::star::sdbc;
75 using namespace ::com::sun::star::sdb;
76 using namespace ::com::sun::star::sdbcx;
77 using namespace ::com::sun::star::container;
78 using namespace ::com::sun::star::i18n;
79 using namespace ::com::sun::star::lang;
80 using namespace ::com::sun::star::script;
81 using namespace ::com::sun::star::util;
82 using namespace ::cppu;
83 using namespace ::osl;
84 using namespace ::utl;
85 
86 namespace dbaccess {
87 namespace BooleanComparisonMode = ::com::sun::star::sdb::BooleanComparisonMode;
88 }
89 
90 #define STR_SELECT      ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("SELECT "))
91 #define STR_FROM        ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" FROM "))
92 #define STR_WHERE       ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" WHERE "))
93 #define STR_GROUP_BY    ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" GROUP BY "))
94 #define STR_HAVING      ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" HAVING "))
95 #define STR_ORDER_BY    ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" ORDER BY "))
96 #define STR_AND         ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" AND "))
97 #define STR_OR          ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" OR "))
98 #define STR_LIKE        ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" LIKE "))
99 #define STR_EQUAL       ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" = "))
100 #define L_BRACKET       ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("("))
101 #define R_BRACKET       ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(")"))
102 #define COMMA           ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(","))
103 
104 // -------------------------------------------------------------------------
105 namespace
106 {
107     // .....................................................................
108     /** parses the given statement, using the given parser, returns a parse node representing
109         the statement
110 
111         If the statement cannot be parsed, an error is thrown.
112     */
parseStatement_throwError(OSQLParser & _rParser,const::rtl::OUString & _rStatement,const Reference<XInterface> & _rxContext)113     const OSQLParseNode* parseStatement_throwError( OSQLParser& _rParser, const ::rtl::OUString& _rStatement, const Reference< XInterface >& _rxContext )
114     {
115         RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "frank.schoenheit@sun.com", "SingleSelectQueryComposer.cxx::parseStatement_throwError" );
116         ::rtl::OUString aErrorMsg;
117         const OSQLParseNode* pNewSqlParseNode = _rParser.parseTree( aErrorMsg, _rStatement );
118         if ( !pNewSqlParseNode )
119         {
120             ::rtl::OUString sSQLStateGeneralError( getStandardSQLState( SQL_GENERAL_ERROR ) );
121             SQLException aError2( aErrorMsg, _rxContext, sSQLStateGeneralError, 1000, Any() );
122             SQLException aError1( _rStatement, _rxContext, sSQLStateGeneralError, 1000, makeAny( aError2 ) );
123             throw SQLException(_rParser.getContext().getErrorMessage(OParseContext::ERROR_GENERAL),_rxContext,sSQLStateGeneralError,1000,makeAny(aError1));
124         }
125         return pNewSqlParseNode;
126     }
127 
128     // .....................................................................
129     /** checks whether the given parse node describes a valid single select statement, throws
130         an error if not
131     */
checkForSingleSelect_throwError(const OSQLParseNode * pStatementNode,OSQLParseTreeIterator & _rIterator,const Reference<XInterface> & _rxContext,const::rtl::OUString & _rOriginatingCommand)132     void checkForSingleSelect_throwError( const OSQLParseNode* pStatementNode, OSQLParseTreeIterator& _rIterator,
133         const Reference< XInterface >& _rxContext, const ::rtl::OUString& _rOriginatingCommand )
134     {
135         const OSQLParseNode* pOldNode = _rIterator.getParseTree();
136 
137         // determine the statement type
138         _rIterator.setParseTree( pStatementNode );
139         _rIterator.traverseAll();
140         bool bIsSingleSelect = ( _rIterator.getStatementType() == SQL_STATEMENT_SELECT );
141 
142         // throw the error, if necessary
143         if ( !bIsSingleSelect || SQL_ISRULE( pStatementNode, union_statement ) ) // #i4229# OJ
144         {
145             // restore the old node before throwing the exception
146             _rIterator.setParseTree( pOldNode );
147             // and now really ...
148             SQLException aError1( _rOriginatingCommand, _rxContext, getStandardSQLState( SQL_GENERAL_ERROR ), 1000, Any() );
149             throw SQLException( DBACORE_RESSTRING( RID_STR_ONLY_QUERY ), _rxContext,
150                 getStandardSQLState( SQL_GENERAL_ERROR ), 1000, makeAny( aError1 ) );
151         }
152 
153         delete pOldNode;
154     }
155 
156     // .....................................................................
157     /** combines parseStatement_throwError and checkForSingleSelect_throwError
158     */
parseAndCheck_throwError(OSQLParser & _rParser,const::rtl::OUString & _rStatement,OSQLParseTreeIterator & _rIterator,const Reference<XInterface> & _rxContext)159     void parseAndCheck_throwError( OSQLParser& _rParser, const ::rtl::OUString& _rStatement,
160         OSQLParseTreeIterator& _rIterator, const Reference< XInterface >& _rxContext )
161     {
162         RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "frank.schoenheit@sun.com", "SingleSelectQueryComposer.cxx::parseAndCheck_throwError" );
163         const OSQLParseNode* pNode = parseStatement_throwError( _rParser, _rStatement, _rxContext );
164         checkForSingleSelect_throwError( pNode, _rIterator, _rxContext, _rStatement );
165     }
166 
167     // .....................................................................
168     /** transforms a parse node describing a complete statement into a pure select
169         statement, without any filter/order/groupby/having clauses
170     */
getPureSelectStatement(const OSQLParseNode * _pRootNode,Reference<XConnection> _rxConnection)171     ::rtl::OUString getPureSelectStatement( const OSQLParseNode* _pRootNode, Reference< XConnection > _rxConnection )
172     {
173         ::rtl::OUString sSQL = STR_SELECT;
174         _pRootNode->getChild(1)->parseNodeToStr( sSQL, _rxConnection );
175         _pRootNode->getChild(2)->parseNodeToStr( sSQL, _rxConnection );
176         sSQL += STR_FROM;
177         _pRootNode->getChild(3)->getChild(0)->getChild(1)->parseNodeToStr( sSQL, _rxConnection );
178         return sSQL;
179     }
180 
181     /** resets an SQL iterator, including deletion of the parse tree, and disposal if desired
182     */
resetIterator(OSQLParseTreeIterator & _rIterator,bool _bDispose)183     void resetIterator( OSQLParseTreeIterator& _rIterator, bool _bDispose )
184     {
185         const OSQLParseNode* pSqlParseNode = _rIterator.getParseTree();
186         _rIterator.setParseTree(NULL);
187         delete pSqlParseNode;
188         if ( _bDispose )
189             _rIterator.dispose();
190     }
lcl_addFilterCriteria_throw(sal_Int32 i_nFilterOperator,const::rtl::OUString & i_sValue,::rtl::OUStringBuffer & o_sRet)191     void lcl_addFilterCriteria_throw(sal_Int32 i_nFilterOperator,const ::rtl::OUString& i_sValue,::rtl::OUStringBuffer& o_sRet)
192     {
193         switch( i_nFilterOperator )
194         {
195             case SQLFilterOperator::EQUAL:
196                 o_sRet.append(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" = ")));
197                 o_sRet.append(i_sValue);
198                 break;
199             case SQLFilterOperator::NOT_EQUAL:
200                 o_sRet.append(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" <> ")));
201                 o_sRet.append(i_sValue);
202                 break;
203             case SQLFilterOperator::LESS:
204                 o_sRet.append(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" < ")));
205                 o_sRet.append(i_sValue);
206                 break;
207             case SQLFilterOperator::GREATER:
208                 o_sRet.append(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" > ")));
209                 o_sRet.append(i_sValue);
210                 break;
211             case SQLFilterOperator::LESS_EQUAL:
212                 o_sRet.append(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" <= ")));
213                 o_sRet.append(i_sValue);
214                 break;
215             case SQLFilterOperator::GREATER_EQUAL:
216                 o_sRet.append(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" >= ")));
217                 o_sRet.append(i_sValue);
218                 break;
219             case SQLFilterOperator::LIKE:
220                 o_sRet.append(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" LIKE ")));
221                 o_sRet.append(i_sValue);
222                 break;
223             case SQLFilterOperator::NOT_LIKE:
224                 o_sRet.append(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" NOT LIKE ")));
225                 o_sRet.append(i_sValue);
226                 break;
227             case SQLFilterOperator::SQLNULL:
228                 o_sRet.append(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" IS NULL")) );
229                 break;
230             case SQLFilterOperator::NOT_SQLNULL:
231                 o_sRet.append(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" IS NOT NULL")) );
232                 break;
233             default:
234                 throw SQLException();
235         }
236     }
237 
238 }
239 
DBG_NAME(OSingleSelectQueryComposer)240 DBG_NAME(OSingleSelectQueryComposer)
241 // -------------------------------------------------------------------------
242 OSingleSelectQueryComposer::OSingleSelectQueryComposer(const Reference< XNameAccess>& _rxTables,
243                                const Reference< XConnection>& _xConnection,
244                                const ::comphelper::ComponentContext& _rContext )
245     :OSubComponent(m_aMutex,_xConnection)
246     ,OPropertyContainer(m_aBHelper)
247     ,m_aSqlParser( _rContext.getLegacyServiceFactory() )
248     ,m_aSqlIterator( _xConnection, _rxTables, m_aSqlParser, NULL )
249     ,m_aAdditiveIterator( _xConnection, _rxTables, m_aSqlParser, NULL )
250     ,m_aElementaryParts( (size_t)SQLPartCount )
251     ,m_xConnection(_xConnection)
252     ,m_xMetaData(_xConnection->getMetaData())
253     ,m_xConnectionTables( _rxTables )
254     ,m_aContext( _rContext )
255     ,m_pTables(NULL)
256     ,m_nBoolCompareMode( BooleanComparisonMode::EQUAL_INTEGER )
257     ,m_nCommandType(CommandType::COMMAND)
258 {
259     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::OSingleSelectQueryComposer" );
260     DBG_CTOR(OSingleSelectQueryComposer,NULL);
261 
262     if ( !m_aContext.is() || !m_xConnection.is() || !m_xConnectionTables.is() )
263         throw IllegalArgumentException();
264 
265     registerProperty(PROPERTY_ORIGINAL,PROPERTY_ID_ORIGINAL,PropertyAttribute::BOUND|PropertyAttribute::READONLY,&m_sOrignal,::getCppuType(&m_sOrignal));
266 
267     m_aCurrentColumns.resize(4);
268 
269     m_aLocale = SvtSysLocale().GetLocaleData().getLocale();
270     m_xNumberFormatsSupplier = dbtools::getNumberFormats( m_xConnection, sal_True, m_aContext.getLegacyServiceFactory() );
271     Reference< XLocaleData > xLocaleData;
272     m_aContext.createComponent( "com.sun.star.i18n.LocaleData", xLocaleData );
273     LocaleDataItem aData = xLocaleData->getLocaleItem(m_aLocale);
274     m_sDecimalSep = aData.decimalSeparator;
275     OSL_ENSURE(m_sDecimalSep.getLength() == 1,"OSingleSelectQueryComposer::OSingleSelectQueryComposer decimal separator is not 1 length");
276     try
277     {
278         Any aValue;
279         Reference<XInterface> xDs = dbaccess::getDataSource(_xConnection);
280         if ( dbtools::getDataSourceSetting(xDs,static_cast <rtl::OUString> (PROPERTY_BOOLEANCOMPARISONMODE),aValue) )
281         {
282             OSL_VERIFY( aValue >>= m_nBoolCompareMode );
283         }
284         Reference< XQueriesSupplier >  xQueriesAccess(m_xConnection, UNO_QUERY);
285         if (xQueriesAccess.is())
286             m_xConnectionQueries = xQueriesAccess->getQueries();
287     }
288     catch(Exception&)
289     {
290     }
291 }
292 // -------------------------------------------------------------------------
~OSingleSelectQueryComposer()293 OSingleSelectQueryComposer::~OSingleSelectQueryComposer()
294 {
295     DBG_DTOR(OSingleSelectQueryComposer,NULL);
296     ::std::vector<OPrivateColumns*>::iterator aColIter = m_aColumnsCollection.begin();
297     ::std::vector<OPrivateColumns*>::iterator aEnd = m_aColumnsCollection.end();
298     for(;aColIter != aEnd;++aColIter)
299         delete *aColIter;
300 
301     ::std::vector<OPrivateTables*>::iterator aTabIter = m_aTablesCollection.begin();
302     ::std::vector<OPrivateTables*>::iterator aTabEnd = m_aTablesCollection.end();
303     for(;aTabIter != aTabEnd;++aTabIter)
304         delete *aTabIter;
305 }
306 // -------------------------------------------------------------------------
307 // OComponentHelper
disposing(void)308 void SAL_CALL OSingleSelectQueryComposer::disposing(void)
309 {
310     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::disposing" );
311     OSubComponent::disposing();
312 
313     MutexGuard aGuard(m_aMutex);
314 
315     resetIterator( m_aSqlIterator, true );
316     resetIterator( m_aAdditiveIterator, true );
317 
318     m_xConnectionTables = NULL;
319     m_xConnection       = NULL;
320 
321     clearCurrentCollections();
322 }
IMPLEMENT_FORWARD_XINTERFACE3(OSingleSelectQueryComposer,OSubComponent,OSingleSelectQueryComposer_BASE,OPropertyContainer)323 IMPLEMENT_FORWARD_XINTERFACE3(OSingleSelectQueryComposer,OSubComponent,OSingleSelectQueryComposer_BASE,OPropertyContainer)
324 IMPLEMENT_SERVICE_INFO1(OSingleSelectQueryComposer,"org.openoffice.comp.dba.OSingleSelectQueryComposer",SERVICE_NAME_SINGLESELECTQUERYCOMPOSER)
325 IMPLEMENT_TYPEPROVIDER3(OSingleSelectQueryComposer,OSubComponent,OSingleSelectQueryComposer_BASE,OPropertyContainer)
326 IMPLEMENT_PROPERTYCONTAINER_DEFAULTS(OSingleSelectQueryComposer)
327 
328 // -------------------------------------------------------------------------
329 // com::sun::star::lang::XUnoTunnel
330 sal_Int64 SAL_CALL OSingleSelectQueryComposer::getSomething( const Sequence< sal_Int8 >& rId )
331 {
332     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getSomething" );
333     if (rId.getLength() == 16 && 0 == rtl_compareMemory(getImplementationId().getConstArray(),  rId.getConstArray(), 16 ) )
334         return reinterpret_cast<sal_Int64>(this);
335 
336     return sal_Int64(0);
337 }
338 
339 // -------------------------------------------------------------------------
340 // XSingleSelectQueryAnalyzer
getQuery()341 ::rtl::OUString SAL_CALL OSingleSelectQueryComposer::getQuery(  )
342 {
343     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getQuery" );
344     ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
345     ::osl::MutexGuard aGuard( m_aMutex );
346 
347     TGetParseNode F_tmp(&OSQLParseTreeIterator::getParseTree);
348     return getStatementPart(F_tmp,m_aSqlIterator);
349 }
350 
351 // -------------------------------------------------------------------------
setQuery(const::rtl::OUString & command)352 void SAL_CALL OSingleSelectQueryComposer::setQuery( const ::rtl::OUString& command )
353 {
354     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "frank.schoenheit@sun.com", "OSingleSelectQueryComposer::setQuery" );
355     ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
356 
357     ::osl::MutexGuard aGuard( m_aMutex );
358     m_nCommandType = CommandType::COMMAND;
359     // first clear the tables and columns
360     clearCurrentCollections();
361     // now set the new one
362     setQuery_Impl(command);
363     m_sOrignal = command;
364 
365     // reset the additive iterator to the same statement
366     parseAndCheck_throwError( m_aSqlParser, m_sOrignal, m_aAdditiveIterator, *this );
367 
368     // we have no "elementary" parts anymore (means filter/groupby/having/order clauses)
369     for ( SQLPart eLoopParts = Where; eLoopParts != SQLPartCount; incSQLPart( eLoopParts ) )
370         m_aElementaryParts[ eLoopParts ] = ::rtl::OUString();
371 }
372 // -------------------------------------------------------------------------
setCommand(const::rtl::OUString & Command,sal_Int32 _nCommandType)373 void SAL_CALL OSingleSelectQueryComposer::setCommand( const ::rtl::OUString& Command,sal_Int32 _nCommandType )
374 {
375     ::rtl::OUStringBuffer sSQL;
376     switch(_nCommandType)
377     {
378         case CommandType::COMMAND:
379             setElementaryQuery(Command);
380             return;
381         case CommandType::TABLE:
382             if ( m_xConnectionTables->hasByName(Command) )
383             {
384                 sSQL.appendAscii("SELECT * FROM ");
385                 Reference< XPropertySet > xTable;
386                 try
387                 {
388                     m_xConnectionTables->getByName( Command ) >>= xTable;
389                 }
390                 catch(const WrappedTargetException& e)
391                 {
392                     SQLException e2;
393                     if ( e.TargetException >>= e2 )
394                         throw e2;
395                 }
396                 catch(Exception&)
397                 {
398                     DBG_UNHANDLED_EXCEPTION();
399                 }
400 
401                 sSQL.append(dbtools::composeTableNameForSelect(m_xConnection,xTable));
402             }
403             else
404             {
405                 String sMessage( DBACORE_RESSTRING( RID_STR_TABLE_DOES_NOT_EXIST ) );
406                 sMessage.SearchAndReplaceAscii( "$table$", Command );
407                 throwGenericSQLException(sMessage,*this);
408             }
409             break;
410         case CommandType::QUERY:
411             if ( m_xConnectionQueries->hasByName(Command) )
412             {
413 
414                 Reference<XPropertySet> xQuery(m_xConnectionQueries->getByName(Command),UNO_QUERY);
415                 ::rtl::OUString sCommand;
416                 xQuery->getPropertyValue(PROPERTY_COMMAND) >>= sCommand;
417                 sSQL.append(sCommand);
418             }
419             else
420             {
421                 String sMessage( DBACORE_RESSTRING( RID_STR_QUERY_DOES_NOT_EXIST ) );
422                 sMessage.SearchAndReplaceAscii( "$table$", Command );
423                 throwGenericSQLException(sMessage,*this);
424             }
425 
426             break;
427         default:
428             break;
429     }
430     ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
431 
432     ::osl::MutexGuard aGuard( m_aMutex );
433     m_nCommandType = _nCommandType;
434     m_sCommand = Command;
435     // first clear the tables and columns
436     clearCurrentCollections();
437     // now set the new one
438     ::rtl::OUString sCommand = sSQL.makeStringAndClear();
439     setElementaryQuery(sCommand);
440     m_sOrignal = sCommand;
441 /*
442     // reset the additive iterator to the same statement
443     parseAndCheck_throwError( m_aSqlParser, m_sOrignal, m_aAdditiveIterator, *this );
444 
445     // we have no "elementary" parts anymore (means filter/groupby/having/order clauses)
446     for ( SQLPart eLoopParts = Where; eLoopParts != SQLPartCount; incSQLPart( eLoopParts ) )
447         m_aElementaryParts[ eLoopParts ] = ::rtl::OUString();
448 */
449 }
450 // -----------------------------------------------------------------------------
setQuery_Impl(const::rtl::OUString & command)451 void OSingleSelectQueryComposer::setQuery_Impl( const ::rtl::OUString& command )
452 {
453     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "frank.schoenheit@sun.com", "OSingleSelectQueryComposer::setQuery_Impl" );
454     // parse this
455     parseAndCheck_throwError( m_aSqlParser, command, m_aSqlIterator, *this );
456 
457     // strip it from all clauses, to have the pure SELECT statement
458     m_aPureSelectSQL = getPureSelectStatement( m_aSqlIterator.getParseTree(), m_xConnection );
459 
460     // update columns and tables
461     // why? Shouldn't this be done on request only?
462     // otherwise nothing is working anymore :-)
463 //  getColumns();
464     getTables();
465 }
466 // -----------------------------------------------------------------------------
getStructuredHavingClause()467 Sequence< Sequence< PropertyValue > > SAL_CALL OSingleSelectQueryComposer::getStructuredHavingClause(  )
468 {
469     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getStructuredHavingClause" );
470     TGetParseNode F_tmp(&OSQLParseTreeIterator::getSimpleHavingTree);
471     return getStructuredCondition(F_tmp);
472 }
473 // -------------------------------------------------------------------------
getStructuredFilter()474 Sequence< Sequence< PropertyValue > > SAL_CALL OSingleSelectQueryComposer::getStructuredFilter(  )
475 {
476     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getStructuredFilter" );
477     TGetParseNode F_tmp(&OSQLParseTreeIterator::getSimpleWhereTree);
478     return getStructuredCondition(F_tmp);
479 }
480 // -----------------------------------------------------------------------------
appendHavingClauseByColumn(const Reference<XPropertySet> & column,sal_Bool andCriteria,sal_Int32 filterOperator)481 void SAL_CALL OSingleSelectQueryComposer::appendHavingClauseByColumn( const Reference< XPropertySet >& column, sal_Bool andCriteria,sal_Int32 filterOperator )
482 {
483     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::appendHavingClauseByColumn" );
484     ::std::function<bool(OSingleSelectQueryComposer*,::rtl::OUString)> F_tmp(&OSingleSelectQueryComposer::implSetHavingClause);
485     setConditionByColumn(column,andCriteria,F_tmp,filterOperator);
486 }
487 // -----------------------------------------------------------------------------
appendFilterByColumn(const Reference<XPropertySet> & column,sal_Bool andCriteria,sal_Int32 filterOperator)488 void SAL_CALL OSingleSelectQueryComposer::appendFilterByColumn( const Reference< XPropertySet >& column, sal_Bool andCriteria,sal_Int32 filterOperator )
489 {
490     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::appendFilterByColumn" );
491     ::std::function<bool(OSingleSelectQueryComposer*,::rtl::OUString)> F_tmp(&OSingleSelectQueryComposer::implSetFilter);
492     setConditionByColumn(column,andCriteria,F_tmp,filterOperator);
493 }
494 // -----------------------------------------------------------------------------
impl_getColumnName_throw(const Reference<XPropertySet> & column)495 ::rtl::OUString OSingleSelectQueryComposer::impl_getColumnName_throw(const Reference< XPropertySet >& column)
496 {
497     ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
498 
499     getColumns();
500     if ( !column.is()
501         || !m_aCurrentColumns[SelectColumns]
502         || !column->getPropertySetInfo()->hasPropertyByName(PROPERTY_NAME)
503         )
504         {
505             String sError(DBACORE_RESSTRING(RID_STR_COLUMN_UNKNOWN_PROP));
506             sError.SearchAndReplaceAscii("%value", ::rtl::OUString(PROPERTY_NAME));
507             SQLException aErr(sError,*this,SQLSTATE_GENERAL,1000,Any() );
508             throw SQLException(DBACORE_RESSTRING(RID_STR_COLUMN_NOT_VALID),*this,SQLSTATE_GENERAL,1000,makeAny(aErr) );
509         }
510 
511     ::rtl::OUString aName,aNewName;
512     column->getPropertyValue(PROPERTY_NAME)         >>= aName;
513 
514     if ( !m_xMetaData->supportsOrderByUnrelated() && m_aCurrentColumns[SelectColumns] && !m_aCurrentColumns[SelectColumns]->hasByName(aName))
515     {
516         String sError(DBACORE_RESSTRING(RID_STR_COLUMN_MUST_VISIBLE));
517         sError.SearchAndReplaceAscii("%name", aName);
518         throw SQLException(sError,*this,SQLSTATE_GENERAL,1000,Any() );
519     }
520 
521     // filter anhaengen
522     // select ohne where und order by aufbauen
523     ::rtl::OUString aQuote  = m_xMetaData->getIdentifierQuoteString();
524     if ( m_aCurrentColumns[SelectColumns]->hasByName(aName) )
525     {
526         Reference<XPropertySet> xColumn;
527         m_aCurrentColumns[SelectColumns]->getByName(aName) >>= xColumn;
528         OSL_ENSURE(xColumn->getPropertySetInfo()->hasPropertyByName(PROPERTY_REALNAME),"Property REALNAME not available!");
529         OSL_ENSURE(xColumn->getPropertySetInfo()->hasPropertyByName(PROPERTY_TABLENAME),"Property TABLENAME not available!");
530         OSL_ENSURE(xColumn->getPropertySetInfo()->hasPropertyByName(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Function"))),"Property FUNCTION not available!");
531 
532         ::rtl::OUString sRealName,sTableName;
533         xColumn->getPropertyValue(PROPERTY_REALNAME)    >>= sRealName;
534         xColumn->getPropertyValue(PROPERTY_TABLENAME)   >>= sTableName;
535         sal_Bool bFunction = sal_False;
536         xColumn->getPropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Function"))) >>= bFunction;
537         if ( sRealName == aName )
538         {
539             if ( bFunction )
540                 aNewName = aName;
541             else
542             {
543                 if(sTableName.indexOf('.',0) != -1)
544                 {
545                     ::rtl::OUString aCatlog,aSchema,aTable;
546                     ::dbtools::qualifiedNameComponents(m_xMetaData,sTableName,aCatlog,aSchema,aTable,::dbtools::eInDataManipulation);
547                     sTableName = ::dbtools::composeTableName( m_xMetaData, aCatlog, aSchema, aTable, sal_True, ::dbtools::eInDataManipulation );
548                 }
549                 else
550                     sTableName = ::dbtools::quoteName(aQuote,sTableName);
551 
552                 aNewName =  sTableName;
553                 aNewName += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("."));
554                 aNewName += ::dbtools::quoteName(aQuote,sRealName);
555             }
556         }
557         else
558             aNewName = ::dbtools::quoteName(aQuote,aName);
559     }
560     else
561         aNewName = getTableAlias(column) + ::dbtools::quoteName(aQuote,aName);
562     return aNewName;
563 }
564 // -------------------------------------------------------------------------
appendOrderByColumn(const Reference<XPropertySet> & column,sal_Bool ascending)565 void SAL_CALL OSingleSelectQueryComposer::appendOrderByColumn( const Reference< XPropertySet >& column, sal_Bool ascending )
566 {
567     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::appendOrderByColumn" );
568     ::osl::MutexGuard aGuard( m_aMutex );
569     ::rtl::OUString sColumnName( impl_getColumnName_throw(column) );
570     ::rtl::OUString sOrder = getOrder();
571     if ( (sOrder.getLength() != 0) && sColumnName.getLength() )
572         sOrder += COMMA;
573     sOrder += sColumnName;
574     if ( !ascending && sColumnName.getLength() )
575         sOrder += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" DESC "));
576 
577     setOrder(sOrder);
578 }
579 
580 // -------------------------------------------------------------------------
appendGroupByColumn(const Reference<XPropertySet> & column)581 void SAL_CALL OSingleSelectQueryComposer::appendGroupByColumn( const Reference< XPropertySet >& column)
582 {
583     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::appendGroupByColumn" );
584     ::osl::MutexGuard aGuard( m_aMutex );
585     ::rtl::OUString sColumnName( impl_getColumnName_throw(column) );
586     OrderCreator aComposer;
587     aComposer.append( getGroup() );
588     aComposer.append( sColumnName );
589     setGroup( aComposer.getComposedAndClear() );
590 }
591 // -------------------------------------------------------------------------
composeStatementFromParts(const::std::vector<::rtl::OUString> & _rParts)592 ::rtl::OUString OSingleSelectQueryComposer::composeStatementFromParts( const ::std::vector< ::rtl::OUString >& _rParts )
593 {
594     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::composeStatementFromParts" );
595     DBG_ASSERT( _rParts.size() == (size_t)SQLPartCount, "OSingleSelectQueryComposer::composeStatementFromParts: invalid parts array!" );
596 
597     ::rtl::OUStringBuffer aSql( m_aPureSelectSQL );
598     for ( SQLPart eLoopParts = Where; eLoopParts != SQLPartCount; incSQLPart( eLoopParts ) )
599         if ( _rParts[ eLoopParts ].getLength() )
600         {
601             aSql.append( getKeyword( eLoopParts ) );
602             aSql.append( _rParts[ eLoopParts ] );
603         }
604 
605     return aSql.makeStringAndClear();
606 }
607 
608 // -------------------------------------------------------------------------
getElementaryQuery()609 ::rtl::OUString SAL_CALL OSingleSelectQueryComposer::getElementaryQuery()
610 {
611     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getElementaryQuery" );
612     return composeStatementFromParts( m_aElementaryParts );
613 }
614 
615 // -------------------------------------------------------------------------
setElementaryQuery(const::rtl::OUString & _rElementary)616 void SAL_CALL OSingleSelectQueryComposer::setElementaryQuery( const ::rtl::OUString& _rElementary )
617 {
618     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "frank.schoenheit@sun.com", "OSingleSelectQueryComposer::setElementaryQuery" );
619     ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
620     ::osl::MutexGuard aGuard( m_aMutex );
621 
622     // remember the 4 current "additive" clauses
623     ::std::vector< ::rtl::OUString > aAdditiveClauses( SQLPartCount );
624     for ( SQLPart eLoopParts = Where; eLoopParts != SQLPartCount; incSQLPart( eLoopParts ) )
625         aAdditiveClauses[ eLoopParts ] = getSQLPart( eLoopParts, m_aAdditiveIterator, sal_False );
626 
627     // clear the tables and columns
628     clearCurrentCollections();
629     // set and parse the new query
630     setQuery_Impl( _rElementary );
631 
632     // get the 4 elementary parts of the statement
633     for ( SQLPart eLoopParts = Where; eLoopParts != SQLPartCount; incSQLPart( eLoopParts ) )
634         m_aElementaryParts[ eLoopParts ] = getSQLPart( eLoopParts, m_aSqlIterator, sal_False );
635 
636     // reset the AdditiveIterator: m_aPureSelectSQL may have changed
637     try
638     {
639         parseAndCheck_throwError( m_aSqlParser, composeStatementFromParts( aAdditiveClauses ), m_aAdditiveIterator, *this );
640     }
641     catch( const Exception& e )
642     {
643         (void)e;
644         DBG_ERROR( "OSingleSelectQueryComposer::setElementaryQuery: there should be no error anymore for the additive statement!" );
645         // every part of the additive statement should have passed other tests already, and should not
646         // be able to cause any errors ... me thinks
647     }
648 }
649 
650 // -------------------------------------------------------------------------
651 namespace
652 {
getComposedClause(const::rtl::OUString _rElementaryClause,const::rtl::OUString _rAdditionalClause,TokenComposer & _rComposer,const::rtl::OUString _rKeyword)653     ::rtl::OUString getComposedClause( const ::rtl::OUString _rElementaryClause, const ::rtl::OUString _rAdditionalClause,
654         TokenComposer& _rComposer, const ::rtl::OUString _rKeyword )
655     {
656         _rComposer.clear();
657         _rComposer.append( _rElementaryClause );
658         _rComposer.append( _rAdditionalClause );
659         ::rtl::OUString sComposed = _rComposer.getComposedAndClear();
660         if ( sComposed.getLength() )
661             sComposed = _rKeyword + sComposed;
662         return sComposed;
663     }
664 }
665 
666 // -------------------------------------------------------------------------
setSingleAdditiveClause(SQLPart _ePart,const::rtl::OUString & _rClause)667 void OSingleSelectQueryComposer::setSingleAdditiveClause( SQLPart _ePart, const ::rtl::OUString& _rClause )
668 {
669     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::setSingleAdditiveClause" );
670     ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
671     ::osl::MutexGuard aGuard( m_aMutex );
672 
673     // if nothing is changed, do nothing
674     if ( getSQLPart( _ePart, m_aAdditiveIterator, sal_False ) == _rClause )
675         return;
676 
677     // collect the 4 single parts as they're currently set
678     ::std::vector< ::rtl::OUString > aClauses;
679     aClauses.reserve( (size_t)SQLPartCount );
680     for ( SQLPart eLoopParts = Where; eLoopParts != SQLPartCount; incSQLPart( eLoopParts ) )
681         aClauses.push_back( getSQLPart( eLoopParts, m_aSqlIterator, sal_True ) );
682 
683     // overwrite the one part in question here
684     ::std::unique_ptr< TokenComposer > pComposer;
685     if ( ( _ePart == Where ) || ( _ePart == Having ) )
686         pComposer.reset( new FilterCreator );
687     else
688         pComposer.reset( new OrderCreator );
689     aClauses[ _ePart ] = getComposedClause( m_aElementaryParts[ _ePart ], _rClause,
690         *pComposer, getKeyword( _ePart ) );
691 
692     // construct the complete statement
693     ::rtl::OUStringBuffer aSql(m_aPureSelectSQL);
694     for ( SQLPart eLoopParts = Where; eLoopParts != SQLPartCount; incSQLPart( eLoopParts ) )
695         aSql.append(aClauses[ eLoopParts ]);
696 
697     // set the query
698     setQuery_Impl(aSql.makeStringAndClear());
699 
700     // clear column collections which (might) have changed
701     clearColumns( ParameterColumns );
702     if ( _ePart == Order )
703         clearColumns( OrderColumns );
704     if ( _ePart == Group )
705         clearColumns( GroupByColumns );
706 
707     // also, since the "additive filter" change, we need to rebuild our "additive" statement
708     aSql = m_aPureSelectSQL;
709     // again, first get all the old additive parts
710     for ( SQLPart eLoopParts = Where; eLoopParts != SQLPartCount; incSQLPart( eLoopParts ) )
711         aClauses[ eLoopParts ] = getSQLPart( eLoopParts, m_aAdditiveIterator, sal_True );
712     // then overwrite the one in question
713     aClauses[ _ePart ] = getComposedClause( ::rtl::OUString(), _rClause, *pComposer, getKeyword( _ePart ) );
714     // and parse it, so that m_aAdditiveIterator is up to date
715     for ( SQLPart eLoopParts = Where; eLoopParts != SQLPartCount; incSQLPart( eLoopParts ) )
716         aSql.append(aClauses[ eLoopParts ]);
717     try
718     {
719         parseAndCheck_throwError( m_aSqlParser, aSql.makeStringAndClear(), m_aAdditiveIterator, *this );
720     }
721     catch( const Exception& e )
722     {
723         (void)e;
724         DBG_ERROR( "OSingleSelectQueryComposer::setSingleAdditiveClause: there should be no error anymore for the additive statement!" );
725         // every part of the additive statement should have passed other tests already, and should not
726         // be able to cause any errors ... me thinks
727     }
728 }
729 
730 // -------------------------------------------------------------------------
setFilter(const::rtl::OUString & filter)731 void SAL_CALL OSingleSelectQueryComposer::setFilter( const ::rtl::OUString& filter )
732 {
733     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::setFilter" );
734     setSingleAdditiveClause( Where, filter );
735 }
736 
737 // -------------------------------------------------------------------------
setOrder(const::rtl::OUString & order)738 void SAL_CALL OSingleSelectQueryComposer::setOrder( const ::rtl::OUString& order )
739 {
740     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::setOrder" );
741     setSingleAdditiveClause( Order, order );
742 }
743 // -----------------------------------------------------------------------------
setGroup(const::rtl::OUString & group)744 void SAL_CALL OSingleSelectQueryComposer::setGroup( const ::rtl::OUString& group )
745 {
746     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::setGroup" );
747     setSingleAdditiveClause( Group, group );
748 }
749 // -------------------------------------------------------------------------
setHavingClause(const::rtl::OUString & filter)750 void SAL_CALL OSingleSelectQueryComposer::setHavingClause( const ::rtl::OUString& filter )
751 {
752     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::setHavingClause" );
753     setSingleAdditiveClause( Having, filter );
754 }
755 
756 // -------------------------------------------------------------------------
757 // XTablesSupplier
getTables()758 Reference< XNameAccess > SAL_CALL OSingleSelectQueryComposer::getTables(  )
759 {
760     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getTables" );
761     ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
762 
763     ::osl::MutexGuard aGuard( m_aMutex );
764     if ( !m_pTables )
765     {
766         const OSQLTables& aTables = m_aSqlIterator.getTables();
767         ::std::vector< ::rtl::OUString> aNames;
768         OSQLTables::const_iterator aEnd = aTables.end();
769         for(OSQLTables::const_iterator aIter = aTables.begin(); aIter != aEnd;++aIter)
770             aNames.push_back(aIter->first);
771 
772         m_pTables = new OPrivateTables(aTables,m_xMetaData->supportsMixedCaseQuotedIdentifiers(),*this,m_aMutex,aNames);
773     }
774 
775     return m_pTables;
776 }
777 // -------------------------------------------------------------------------
778 // XColumnsSupplier
getColumns()779 Reference< XNameAccess > SAL_CALL OSingleSelectQueryComposer::getColumns(  )
780 {
781     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getColumns" );
782     ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
783     ::osl::MutexGuard aGuard( m_aMutex );
784     if ( !!m_aCurrentColumns[SelectColumns] )
785         return m_aCurrentColumns[SelectColumns];
786 
787     ::std::vector< ::rtl::OUString> aNames;
788     ::vos::ORef< OSQLColumns> aSelectColumns;
789     sal_Bool bCase = sal_True;
790     Reference< XNameAccess> xQueryColumns;
791     if ( m_nCommandType == CommandType::QUERY )
792     {
793         Reference<XColumnsSupplier> xSup(m_xConnectionQueries->getByName(m_sCommand),UNO_QUERY);
794         if(xSup.is())
795             xQueryColumns = xSup->getColumns();
796     }
797 
798     do {
799 
800     try
801     {
802         SharedUNOComponent< XStatement, DisposableComponent > xStatement;
803         SharedUNOComponent< XPreparedStatement, DisposableComponent > xPreparedStatement;
804 
805         bCase = m_xMetaData->supportsMixedCaseQuotedIdentifiers();
806         aSelectColumns = m_aSqlIterator.getSelectColumns();
807 
808         ::rtl::OUStringBuffer aSQL;
809         aSQL.append( m_aPureSelectSQL );
810         aSQL.append( STR_WHERE );
811 
812         // preserve the original WHERE clause
813         // #i102234# / 2009-06-02 / frank.schoenheit@sun.com
814         ::rtl::OUString sOriginalWhereClause = getSQLPart( Where, m_aSqlIterator, sal_False );
815         if ( sOriginalWhereClause.getLength() )
816         {
817             aSQL.appendAscii( " ( 0 = 1 ) AND ( " );
818             aSQL.append( sOriginalWhereClause );
819             aSQL.appendAscii( " ) " );
820         }
821         else
822         {
823             aSQL.appendAscii( " ( 0 = 1 ) " );
824         }
825 
826         ::rtl::OUString sGroupBy = getSQLPart( Group, m_aSqlIterator, sal_True );
827         if ( sGroupBy.getLength() )
828             aSQL.append( sGroupBy );
829 
830         ::rtl::OUString sSQL( aSQL.makeStringAndClear() );
831         // normalize the statement so that it doesn't contain any application-level features anymore
832         ::rtl::OUString sError;
833         const ::std::unique_ptr< OSQLParseNode > pStatementTree( m_aSqlParser.parseTree( sError, sSQL, false ) );
834         DBG_ASSERT( pStatementTree.get(), "OSingleSelectQueryComposer::getColumns: could not parse the column retrieval statement!" );
835         if ( pStatementTree.get() )
836             if ( !pStatementTree->parseNodeToExecutableStatement( sSQL, m_xConnection, m_aSqlParser, NULL ) )
837                 break;
838 
839         Reference< XResultSetMetaData > xResultSetMeta;
840         Reference< XResultSetMetaDataSupplier > xResMetaDataSup;
841         try
842         {
843             xPreparedStatement.set( m_xConnection->prepareStatement( sSQL ), UNO_QUERY_THROW );
844             xResMetaDataSup.set( xPreparedStatement, UNO_QUERY_THROW );
845             xResultSetMeta.set( xResMetaDataSup->getMetaData(), UNO_QUERY_THROW );
846         }
847         catch( const Exception& ) { }
848 
849         try
850         {
851             if ( !xResultSetMeta.is() )
852             {
853                 xStatement.reset( Reference< XStatement >( m_xConnection->createStatement(), UNO_QUERY_THROW ) );
854                 Reference< XPropertySet > xStatementProps( xStatement, UNO_QUERY_THROW );
855                 try { xStatementProps->setPropertyValue( PROPERTY_ESCAPE_PROCESSING, makeAny( sal_False ) ); }
856                 catch ( const Exception& ) { DBG_UNHANDLED_EXCEPTION(); }
857                 xResMetaDataSup.set( xStatement->executeQuery( sSQL ), UNO_QUERY_THROW );
858                 xResultSetMeta.set( xResMetaDataSup->getMetaData(), UNO_QUERY_THROW );
859             }
860         }
861         catch( const Exception& )
862         {
863             //@see issue http://qa.openoffice.org/issues/show_bug.cgi?id=110111
864             // access returns a different order of column names when executing select * from
865             // and asking the columns from the metadata.
866             Reference< XParameters > xParameters( xPreparedStatement, UNO_QUERY_THROW );
867             Reference< XIndexAccess > xPara = getParameters();
868             for(sal_Int32 i = 1;i <= xPara->getCount();++i)
869                 xParameters->setNull(i,DataType::VARCHAR);
870             xResMetaDataSup.set(xPreparedStatement->executeQuery(), UNO_QUERY_THROW );
871             xResultSetMeta.set( xResMetaDataSup->getMetaData(), UNO_QUERY_THROW );
872         }
873 
874         if ( aSelectColumns->get().empty() )
875         {
876             // This is a valid case. If we can syntactically parse the query, but not semantically
877             // (e.g. because it is based on a table we do not know), then there will be no SelectColumns
878             aSelectColumns = ::connectivity::parse::OParseColumn::createColumnsForResultSet( xResultSetMeta, m_xMetaData ,xQueryColumns);
879             break;
880         }
881 
882         const ::comphelper::UStringMixEqual aCaseCompare( bCase );
883         const ::comphelper::TStringMixEqualFunctor aCaseCompareFunctor( bCase );
884         typedef ::std::set< size_t > SizeTSet;
885         SizeTSet aUsedSelectColumns;
886         ::connectivity::parse::OParseColumn::StringMap aColumnNames;
887 
888         sal_Int32 nCount = xResultSetMeta->getColumnCount();
889         OSL_ENSURE( (size_t) nCount == aSelectColumns->get().size(), "OSingleSelectQueryComposer::getColumns: inconsistent column counts, this might result in wrong columns!" );
890         for(sal_Int32 i=1;i<=nCount;++i)
891         {
892             ::rtl::OUString sColumnName = xResultSetMeta->getColumnName(i);
893             ::rtl::OUString sColumnLabel;
894             if ( xQueryColumns.is() && xQueryColumns->hasByName(sColumnName) )
895             {
896                 Reference<XPropertySet> xQueryColumn(xQueryColumns->getByName(sColumnName),UNO_QUERY_THROW);
897                 xQueryColumn->getPropertyValue(PROPERTY_LABEL) >>= sColumnLabel;
898             }
899             else
900                 sColumnLabel = xResultSetMeta->getColumnLabel(i);
901             sal_Bool bFound = sal_False;
902             OSQLColumns::Vector::const_iterator aFind = ::connectivity::find(aSelectColumns->get().begin(),aSelectColumns->get().end(),sColumnLabel,aCaseCompare);
903             size_t nFoundSelectColumnPos = aFind - aSelectColumns->get().begin();
904             if ( aFind != aSelectColumns->get().end() )
905             {
906                 if ( aUsedSelectColumns.find( nFoundSelectColumnPos ) != aUsedSelectColumns.end() )
907                 {   // we found a column name which exists twice
908                     // so we start after the first found
909                     do
910                     {
911                         aFind = ::connectivity::findRealName(++aFind,aSelectColumns->get().end(),sColumnName,aCaseCompare);
912                         nFoundSelectColumnPos = aFind - aSelectColumns->get().begin();
913                     }
914                     while   (   ( aUsedSelectColumns.find( nFoundSelectColumnPos ) != aUsedSelectColumns.end() )
915                                 &&  ( aFind != aSelectColumns->get().end() )
916                             );
917                 }
918                 if ( aFind != aSelectColumns->get().end() )
919                 {
920                     (*aFind)->getPropertyValue(PROPERTY_NAME) >>= sColumnName;
921                     aUsedSelectColumns.insert( nFoundSelectColumnPos );
922                     aNames.push_back(sColumnName);
923                     bFound = sal_True;
924                 }
925             }
926 
927             if ( bFound )
928                 continue;
929 
930             OSQLColumns::Vector::const_iterator aRealFind = ::connectivity::findRealName(
931                 aSelectColumns->get().begin(), aSelectColumns->get().end(), sColumnName, aCaseCompare );
932 
933             if ( i > static_cast< sal_Int32>( aSelectColumns->get().size() ) )
934             {
935                 aSelectColumns->get().push_back(
936                     ::connectivity::parse::OParseColumn::createColumnForResultSet( xResultSetMeta, m_xMetaData, i ,aColumnNames)
937                 );
938                 OSL_ENSURE( aSelectColumns->get().size() == (size_t)i, "OSingleSelectQueryComposer::getColumns: inconsistency!" );
939             }
940             else if ( aRealFind == aSelectColumns->get().end() )
941             {
942                 // we can now only look if we found it under the realname property
943                 // here we have to make the assumption that the position is correct
944                 OSQLColumns::Vector::iterator aFind2 = aSelectColumns->get().begin() + i-1;
945                 Reference<XPropertySet> xProp(*aFind2,UNO_QUERY);
946                 if ( !xProp.is() || !xProp->getPropertySetInfo()->hasPropertyByName( PROPERTY_REALNAME ) )
947                     continue;
948 
949                 ::connectivity::parse::OParseColumn* pColumn = new ::connectivity::parse::OParseColumn(xProp,bCase);
950                 pColumn->setFunction(::comphelper::getBOOL(xProp->getPropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Function")))));
951                 pColumn->setAggregateFunction(::comphelper::getBOOL(xProp->getPropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("AggregateFunction")))));
952 
953                 ::rtl::OUString sRealName;
954                 xProp->getPropertyValue(PROPERTY_REALNAME) >>= sRealName;
955                 ::std::vector< ::rtl::OUString>::iterator aFindName;
956                 if ( !sColumnName.getLength() )
957                     xProp->getPropertyValue(PROPERTY_NAME) >>= sColumnName;
958 
959 
960                 aFindName = ::std::find_if(aNames.begin(),aNames.end(),::std::bind(aCaseCompareFunctor, ::std::placeholders::_1,sColumnName));
961                 sal_Int32 j = 0;
962                 while ( aFindName != aNames.end() )
963                 {
964                     sColumnName += ::rtl::OUString::valueOf(++j);
965                     aFindName = ::std::find_if(aNames.begin(),aNames.end(),::std::bind(aCaseCompareFunctor, ::std::placeholders::_1,sColumnName));
966                 }
967 
968                 pColumn->setName(sColumnName);
969                 pColumn->setRealName(sRealName);
970                 pColumn->setTableName(::comphelper::getString(xProp->getPropertyValue(PROPERTY_TABLENAME)));
971 
972                 (aSelectColumns->get())[i-1] = pColumn;
973             }
974             else
975                 continue;
976 
977             aUsedSelectColumns.insert( (size_t)(i - 1) );
978             aNames.push_back( sColumnName );
979         }
980     }
981     catch(const Exception&)
982     {
983     }
984 
985     } while ( false );
986 
987     if ( aNames.empty() )
988         m_aCurrentColumns[ SelectColumns ] = OPrivateColumns::createWithIntrinsicNames( aSelectColumns, bCase, *this, m_aMutex );
989     else
990         m_aCurrentColumns[ SelectColumns ] = new OPrivateColumns( aSelectColumns, bCase, *this, m_aMutex, aNames );
991 
992     return m_aCurrentColumns[SelectColumns];
993 }
994 // -------------------------------------------------------------------------
setORCriteria(OSQLParseNode * pCondition,OSQLParseTreeIterator & _rIterator,::std::vector<::std::vector<PropertyValue>> & rFilters,const Reference<::com::sun::star::util::XNumberFormatter> & xFormatter) const995 sal_Bool OSingleSelectQueryComposer::setORCriteria(OSQLParseNode* pCondition, OSQLParseTreeIterator& _rIterator,
996                                     ::std::vector< ::std::vector < PropertyValue > >& rFilters, const Reference< ::com::sun::star::util::XNumberFormatter > & xFormatter) const
997 {
998     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::setORCriteria" );
999     // Runde Klammern um den Ausdruck
1000     if (pCondition->count() == 3 &&
1001         SQL_ISPUNCTUATION(pCondition->getChild(0),"(") &&
1002         SQL_ISPUNCTUATION(pCondition->getChild(2),")"))
1003     {
1004         return setORCriteria(pCondition->getChild(1), _rIterator, rFilters, xFormatter);
1005     }
1006     // oder Verknuepfung
1007     // a searchcondition can only look like this: search_condition SQL_TOKEN_OR boolean_term
1008     else if (SQL_ISRULE(pCondition,search_condition))
1009     {
1010         sal_Bool bResult = sal_True;
1011         for (int i = 0; bResult && i < 3; i+=2)
1012         {
1013             // Ist das erste Element wieder eine OR-Verknuepfung?
1014             // Dann rekursiv absteigen ...
1015             //if (!i && SQL_ISRULE(pCondition->getChild(i),search_condition))
1016             if (SQL_ISRULE(pCondition->getChild(i),search_condition))
1017                 bResult = setORCriteria(pCondition->getChild(i), _rIterator, rFilters, xFormatter);
1018             else
1019             {
1020                 rFilters.push_back( ::std::vector < PropertyValue >());
1021                 bResult = setANDCriteria(pCondition->getChild(i), _rIterator, rFilters[rFilters.size() - 1], xFormatter);
1022             }
1023         }
1024         return bResult;
1025     }
1026     else
1027     {
1028         rFilters.push_back(::std::vector < PropertyValue >());
1029         return setANDCriteria(pCondition, _rIterator, rFilters[rFilters.size() - 1], xFormatter);
1030     }
1031 }
1032 
1033 //--------------------------------------------------------------------------------------------------
setANDCriteria(OSQLParseNode * pCondition,OSQLParseTreeIterator & _rIterator,::std::vector<PropertyValue> & rFilter,const Reference<XNumberFormatter> & xFormatter) const1034 sal_Bool OSingleSelectQueryComposer::setANDCriteria( OSQLParseNode * pCondition,
1035     OSQLParseTreeIterator& _rIterator, ::std::vector < PropertyValue >& rFilter, const Reference< XNumberFormatter > & xFormatter) const
1036 {
1037     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::setANDCriteria" );
1038     // Runde Klammern
1039     if (SQL_ISRULE(pCondition,boolean_primary))
1040     {
1041         // this should not occur
1042         DBG_ERROR("boolean_primary in And-Criteria");
1043         return sal_False;
1044     }
1045     // Das erste Element ist (wieder) eine AND-Verknuepfung
1046     else if ( SQL_ISRULE(pCondition,boolean_term) && pCondition->count() == 3 )
1047     {
1048         return setANDCriteria(pCondition->getChild(0), _rIterator, rFilter, xFormatter) &&
1049                setANDCriteria(pCondition->getChild(2), _rIterator, rFilter, xFormatter);
1050     }
1051     else if (SQL_ISRULE(pCondition, comparison_predicate))
1052     {
1053         return setComparsionPredicate(pCondition,_rIterator,rFilter,xFormatter);
1054     }
1055     else if (SQL_ISRULE(pCondition,like_predicate) ||
1056              SQL_ISRULE(pCondition,test_for_null) ||
1057              SQL_ISRULE(pCondition,in_predicate) ||
1058              SQL_ISRULE(pCondition,all_or_any_predicate) ||
1059              SQL_ISRULE(pCondition,between_predicate))
1060     {
1061         if (SQL_ISRULE(pCondition->getChild(0), column_ref))
1062         {
1063             PropertyValue aItem;
1064             ::rtl::OUString aValue;
1065             ::rtl::OUString aColumnName;
1066 
1067 
1068             //  pCondition->parseNodeToStr(aValue,m_xMetaData, xFormatter, m_aLocale,static_cast<sal_Char>(m_sDecimalSep.toChar()));
1069             pCondition->parseNodeToStr( aValue, m_xConnection, NULL );
1070             //  pCondition->getChild(0)->parseNodeToStr(aColumnName,m_xMetaData, xFormatter, m_aLocale,static_cast<sal_Char>(m_sDecimalSep.toChar()));
1071             pCondition->getChild(0)->parseNodeToStr( aColumnName, m_xConnection, NULL );
1072 
1073             // don't display the column name
1074             aValue = aValue.copy(aColumnName.getLength());
1075             aValue = aValue.trim();
1076 
1077             aItem.Name = getColumnName(pCondition->getChild(0),_rIterator);
1078             aItem.Value <<= aValue;
1079             aItem.Handle = 0; // just to know that this is not one the known ones
1080             if ( SQL_ISRULE(pCondition,like_predicate) )
1081             {
1082                 if ( SQL_ISTOKEN(pCondition->getChild(1)->getChild(0),NOT) )
1083                     aItem.Handle = SQLFilterOperator::NOT_LIKE;
1084                 else
1085                     aItem.Handle = SQLFilterOperator::LIKE;
1086             }
1087             else if (SQL_ISRULE(pCondition,test_for_null))
1088             {
1089                 if (SQL_ISTOKEN(pCondition->getChild(1)->getChild(1),NOT) )
1090                     aItem.Handle = SQLFilterOperator::NOT_SQLNULL;
1091                 else
1092                     aItem.Handle = SQLFilterOperator::SQLNULL;
1093             }
1094             else if (SQL_ISRULE(pCondition,in_predicate))
1095             {
1096                 OSL_ENSURE( false, "OSingleSelectQueryComposer::setANDCriteria: in_predicate not implemented!" );
1097             }
1098             else if (SQL_ISRULE(pCondition,all_or_any_predicate))
1099             {
1100                 OSL_ENSURE( false, "OSingleSelectQueryComposer::setANDCriteria: all_or_any_predicate not implemented!" );
1101             }
1102             else if (SQL_ISRULE(pCondition,between_predicate))
1103             {
1104                 OSL_ENSURE( false, "OSingleSelectQueryComposer::setANDCriteria: between_predicate not implemented!" );
1105             }
1106 
1107             rFilter.push_back(aItem);
1108         }
1109         else
1110             return sal_False;
1111     }
1112     else if (SQL_ISRULE(pCondition,existence_test) ||
1113              SQL_ISRULE(pCondition,unique_test))
1114     {
1115         // this couldn't be handled here, too complex
1116         // as we need a field name
1117         return sal_False;
1118     }
1119     else
1120         return sal_False;
1121 
1122     return sal_True;
1123 }
1124 // -----------------------------------------------------------------------------
getPredicateType(OSQLParseNode * _pPredicate) const1125 sal_Int32 OSingleSelectQueryComposer::getPredicateType(OSQLParseNode * _pPredicate) const
1126 {
1127     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getPredicateType" );
1128     sal_Int32 nPredicate = SQLFilterOperator::EQUAL;
1129     switch (_pPredicate->getNodeType())
1130     {
1131         case SQL_NODE_EQUAL:
1132             nPredicate = SQLFilterOperator::EQUAL;
1133             break;
1134         case SQL_NODE_NOTEQUAL:
1135             nPredicate = SQLFilterOperator::NOT_EQUAL;
1136             break;
1137         case SQL_NODE_LESS:
1138             nPredicate = SQLFilterOperator::LESS;
1139             break;
1140         case SQL_NODE_LESSEQ:
1141             nPredicate = SQLFilterOperator::LESS_EQUAL;
1142             break;
1143         case SQL_NODE_GREAT:
1144             nPredicate = SQLFilterOperator::GREATER;
1145             break;
1146         case SQL_NODE_GREATEQ:
1147             nPredicate = SQLFilterOperator::GREATER_EQUAL;
1148             break;
1149         default:
1150             OSL_ENSURE(0,"Wrong NodeType!");
1151     }
1152     return nPredicate;
1153 }
1154 //------------------------------------------------------------------------------
setComparsionPredicate(OSQLParseNode * pCondition,OSQLParseTreeIterator & _rIterator,::std::vector<PropertyValue> & rFilter,const Reference<::com::sun::star::util::XNumberFormatter> & xFormatter) const1155 sal_Bool OSingleSelectQueryComposer::setComparsionPredicate(OSQLParseNode * pCondition, OSQLParseTreeIterator& _rIterator,
1156                                             ::std::vector < PropertyValue >& rFilter, const Reference< ::com::sun::star::util::XNumberFormatter > & xFormatter) const
1157 {
1158     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::setComparsionPredicate" );
1159     DBG_ASSERT(SQL_ISRULE(pCondition, comparison_predicate),"setComparsionPredicate: pCondition ist kein ComparsionPredicate");
1160     if (SQL_ISRULE(pCondition->getChild(0), column_ref) ||
1161         SQL_ISRULE(pCondition->getChild(pCondition->count()-1), column_ref))
1162     {
1163         PropertyValue aItem;
1164         ::rtl::OUString aValue;
1165         sal_uInt32 nPos;
1166         if (SQL_ISRULE(pCondition->getChild(0), column_ref))
1167         {
1168             nPos = 0;
1169             sal_uInt32 i=1;
1170 
1171             aItem.Handle = getPredicateType(pCondition->getChild(i));
1172             // don't display the equal
1173             if (pCondition->getChild(i)->getNodeType() == SQL_NODE_EQUAL)
1174                 i++;
1175 
1176             // go forward
1177             for (;i < pCondition->count();i++)
1178                 pCondition->getChild(i)->parseNodeToPredicateStr(
1179                     aValue, m_xConnection, xFormatter, m_aLocale, static_cast<sal_Char>(m_sDecimalSep.toChar() ) );
1180         }
1181         else if (SQL_ISRULE(pCondition->getChild(pCondition->count()-1), column_ref))
1182         {
1183             nPos = pCondition->count()-1;
1184 
1185             sal_Int32 i = pCondition->count() - 2;
1186             switch (pCondition->getChild(i)->getNodeType())
1187             {
1188                 case SQL_NODE_EQUAL:
1189                     // don't display the equal
1190                     i--;
1191                     aItem.Handle = SQLFilterOperator::EQUAL;
1192                     break;
1193                 case SQL_NODE_NOTEQUAL:
1194                     i--;
1195                     aItem.Handle = SQLFilterOperator::NOT_EQUAL;
1196                     break;
1197                 case SQL_NODE_LESS:
1198                     // take the opposite as we change the order
1199                     i--;
1200                     aValue = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(">="));
1201                     aItem.Handle = SQLFilterOperator::GREATER_EQUAL;
1202                     break;
1203                 case SQL_NODE_LESSEQ:
1204                     // take the opposite as we change the order
1205                     i--;
1206                     aValue = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(">"));
1207                     aItem.Handle = SQLFilterOperator::GREATER;
1208                     break;
1209                 case SQL_NODE_GREAT:
1210                     // take the opposite as we change the order
1211                     i--;
1212                     aValue = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("<="));
1213                     aItem.Handle = SQLFilterOperator::LESS_EQUAL;
1214                     break;
1215                 case SQL_NODE_GREATEQ:
1216                     // take the opposite as we change the order
1217                     i--;
1218                     aValue = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("<"));
1219                     aItem.Handle = SQLFilterOperator::LESS;
1220                     break;
1221                 default:
1222                     break;
1223             }
1224 
1225             // go backward
1226             for (; i >= 0; i--)
1227                 pCondition->getChild(i)->parseNodeToPredicateStr(
1228                     aValue, m_xConnection, xFormatter, m_aLocale, static_cast<sal_Char>( m_sDecimalSep.toChar() ) );
1229         }
1230         else
1231             return sal_False;
1232 
1233         aItem.Name = getColumnName(pCondition->getChild(nPos),_rIterator);
1234         aItem.Value <<= aValue;
1235         rFilter.push_back(aItem);
1236     }
1237     else if (SQL_ISRULE(pCondition->getChild(0), set_fct_spec ) ||
1238              SQL_ISRULE(pCondition->getChild(0), general_set_fct))
1239     {
1240         PropertyValue aItem;
1241         ::rtl::OUString aValue;
1242         ::rtl::OUString aColumnName;
1243 
1244         pCondition->getChild(2)->parseNodeToPredicateStr(aValue, m_xConnection, xFormatter, m_aLocale, static_cast<sal_Char>( m_sDecimalSep.toChar() ) );
1245         pCondition->getChild(0)->parseNodeToPredicateStr( aColumnName, m_xConnection, xFormatter, m_aLocale, static_cast<sal_Char>( m_sDecimalSep .toChar() ) );
1246 
1247         aItem.Name = getColumnName(pCondition->getChild(0),_rIterator);
1248         aItem.Value <<= aValue;
1249         aItem.Handle = getPredicateType(pCondition->getChild(1));
1250         rFilter.push_back(aItem);
1251     }
1252     else // kann sich nur um einen Expr. Ausdruck handeln
1253     {
1254         PropertyValue aItem;
1255         ::rtl::OUString aName, aValue;
1256 
1257         OSQLParseNode *pLhs = pCondition->getChild(0);
1258         OSQLParseNode *pRhs = pCondition->getChild(2);
1259 
1260         // Feldnamen
1261         sal_uInt16 i;
1262         for (i=0;i< pLhs->count();i++)
1263              pLhs->getChild(i)->parseNodeToPredicateStr( aName, m_xConnection, xFormatter, m_aLocale, static_cast<sal_Char>( m_sDecimalSep.toChar() ) );
1264 
1265         // Kriterium
1266         aItem.Handle = getPredicateType(pCondition->getChild(1));
1267         aValue       = pCondition->getChild(1)->getTokenValue();
1268         for(i=0;i< pRhs->count();i++)
1269             pRhs->getChild(i)->parseNodeToPredicateStr(aValue, m_xConnection, xFormatter, m_aLocale, static_cast<sal_Char>( m_sDecimalSep.toChar() ) );
1270 
1271         aItem.Name = aName;
1272         aItem.Value <<= aValue;
1273         rFilter.push_back(aItem);
1274     }
1275     return sal_True;
1276 }
1277 // functions for analysing SQL
1278 //--------------------------------------------------------------------------------------------------
getColumnName(::connectivity::OSQLParseNode * pColumnRef,OSQLParseTreeIterator & _rIterator) const1279 ::rtl::OUString OSingleSelectQueryComposer::getColumnName( ::connectivity::OSQLParseNode* pColumnRef, OSQLParseTreeIterator& _rIterator ) const
1280 {
1281     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getColumnName" );
1282     ::rtl::OUString aTableRange, aColumnName;
1283     _rIterator.getColumnRange(pColumnRef,aColumnName,aTableRange);
1284     return aColumnName;
1285 }
1286 //------------------------------------------------------------------------------
getFilter()1287 ::rtl::OUString SAL_CALL OSingleSelectQueryComposer::getFilter(  )
1288 {
1289     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getFilter" );
1290     ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
1291     ::osl::MutexGuard aGuard( m_aMutex );
1292     return getSQLPart(Where,m_aAdditiveIterator,sal_False);
1293 }
1294 // -------------------------------------------------------------------------
getOrder()1295 ::rtl::OUString SAL_CALL OSingleSelectQueryComposer::getOrder(  )
1296 {
1297     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getOrder" );
1298     ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
1299     ::osl::MutexGuard aGuard( m_aMutex );
1300     return getSQLPart(Order,m_aAdditiveIterator,sal_False);
1301 }
1302 // -------------------------------------------------------------------------
getGroup()1303 ::rtl::OUString SAL_CALL OSingleSelectQueryComposer::getGroup(  )
1304 {
1305     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getGroup" );
1306     ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
1307     ::osl::MutexGuard aGuard( m_aMutex );
1308     return getSQLPart(Group,m_aAdditiveIterator,sal_False);
1309 }
1310 // -----------------------------------------------------------------------------
getHavingClause()1311 ::rtl::OUString OSingleSelectQueryComposer::getHavingClause()
1312 {
1313     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getHavingClause" );
1314     ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
1315     ::osl::MutexGuard aGuard( m_aMutex );
1316     return getSQLPart(Having,m_aAdditiveIterator,sal_False);
1317 }
1318 // -----------------------------------------------------------------------------
getTableAlias(const Reference<XPropertySet> & column) const1319 ::rtl::OUString OSingleSelectQueryComposer::getTableAlias(const Reference< XPropertySet >& column) const
1320 {
1321     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getTableAlias" );
1322     ::rtl::OUString sReturn;
1323     if(m_pTables && m_pTables->getCount() > 1)
1324     {
1325         ::rtl::OUString aCatalog,aSchema,aTable,aComposedName,aColumnName;
1326         column->getPropertyValue(PROPERTY_CATALOGNAME)  >>= aCatalog;
1327         column->getPropertyValue(PROPERTY_SCHEMANAME)   >>= aSchema;
1328         column->getPropertyValue(PROPERTY_TABLENAME)    >>= aTable;
1329         column->getPropertyValue(PROPERTY_NAME)         >>= aColumnName;
1330 
1331         Sequence< ::rtl::OUString> aNames(m_pTables->getElementNames());
1332         const ::rtl::OUString* pBegin   = aNames.getConstArray();
1333         const ::rtl::OUString* pEnd     = pBegin + aNames.getLength();
1334 
1335         if(!aTable.getLength())
1336         { // we don't found a table name, now we must search every table for this column
1337             for(;pBegin != pEnd;++pBegin)
1338             {
1339                 Reference<XColumnsSupplier> xColumnsSupp;
1340                 m_pTables->getByName(*pBegin) >>= xColumnsSupp;
1341 
1342                 if(xColumnsSupp.is() && xColumnsSupp->getColumns()->hasByName(aColumnName))
1343                 {
1344 //                  Reference<XPropertySet> xTableProp(xColumnsSupp,UNO_QUERY);
1345 //                  xTableProp->getPropertyValue(PROPERTY_CATALOGNAME)  >>= aCatalog;
1346 //                  xTableProp->getPropertyValue(PROPERTY_SCHEMANAME)   >>= aSchema;
1347 //                  xTableProp->getPropertyValue(PROPERTY_NAME)         >>= aTable;
1348                     aTable = *pBegin;
1349                     break;
1350                 }
1351             }
1352         }
1353         else
1354         {
1355             aComposedName = ::dbtools::composeTableName( m_xMetaData, aCatalog, aSchema, aTable, sal_False, ::dbtools::eInDataManipulation );
1356 
1357             // first check if this is the table we want to or has it a tablealias
1358 
1359             if(!m_pTables->hasByName(aComposedName))
1360             {
1361                 ::comphelper::UStringMixLess aTmp(m_aAdditiveIterator.getTables().key_comp());
1362                 ::comphelper::UStringMixEqual aComp(static_cast< ::comphelper::UStringMixLess*>(&aTmp)->isCaseSensitive());
1363                 for(;pBegin != pEnd;++pBegin)
1364                 {
1365                     Reference<XPropertySet> xTableProp;
1366                     m_pTables->getByName(*pBegin) >>= xTableProp;
1367                     OSL_ENSURE(xTableProp.is(),"Table isn't a propertyset!");
1368                     if(xTableProp.is())
1369                     {
1370                         ::rtl::OUString aCatalog2,aSchema2,aTable2;
1371                         xTableProp->getPropertyValue(PROPERTY_CATALOGNAME)  >>= aCatalog2;
1372                         xTableProp->getPropertyValue(PROPERTY_SCHEMANAME)   >>= aSchema2;
1373                         xTableProp->getPropertyValue(PROPERTY_NAME)         >>= aTable2;
1374                         if(aComp(aCatalog,aCatalog2) && aComp(aSchema,aSchema2) && aComp(aTable,aTable2))
1375                         {
1376                             aCatalog    = aCatalog2;
1377                             aSchema     = aSchema2;
1378                             aTable      = aTable2;
1379                             break;
1380                         }
1381                     }
1382                 }
1383             }
1384         }
1385         if(pBegin != pEnd)
1386         {
1387             sReturn = ::dbtools::composeTableName( m_xMetaData, aCatalog, aSchema, aTable, sal_True, ::dbtools::eInDataManipulation );
1388             sReturn += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("."));
1389         }
1390     }
1391     return sReturn;
1392 }
1393 // -----------------------------------------------------------------------------
getParameters()1394 Reference< XIndexAccess > SAL_CALL OSingleSelectQueryComposer::getParameters(  )
1395 {
1396     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getParameters" );
1397     // now set the Parameters
1398     if ( !m_aCurrentColumns[ParameterColumns] )
1399     {
1400         ::vos::ORef< OSQLColumns> aCols = m_aSqlIterator.getParameters();
1401         ::std::vector< ::rtl::OUString> aNames;
1402         OSQLColumns::Vector::const_iterator aEnd = aCols->get().end();
1403         for(OSQLColumns::Vector::const_iterator aIter = aCols->get().begin(); aIter != aEnd;++aIter)
1404             aNames.push_back(getString((*aIter)->getPropertyValue(PROPERTY_NAME)));
1405         m_aCurrentColumns[ParameterColumns] = new OPrivateColumns(aCols,m_xMetaData->supportsMixedCaseQuotedIdentifiers(),*this,m_aMutex,aNames,sal_True);
1406     }
1407 
1408     return m_aCurrentColumns[ParameterColumns];
1409 }
1410 // -----------------------------------------------------------------------------
clearColumns(const EColumnType _eType)1411 void OSingleSelectQueryComposer::clearColumns( const EColumnType _eType )
1412 {
1413     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::clearColumns" );
1414     OPrivateColumns* pColumns = m_aCurrentColumns[ _eType ];
1415     if ( pColumns != NULL )
1416     {
1417         pColumns->disposing();
1418         m_aColumnsCollection.push_back( pColumns );
1419         m_aCurrentColumns[ _eType ] = NULL;
1420     }
1421 }
1422 // -----------------------------------------------------------------------------
clearCurrentCollections()1423 void OSingleSelectQueryComposer::clearCurrentCollections()
1424 {
1425     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::clearCurrentCollections" );
1426     ::std::vector<OPrivateColumns*>::iterator aIter = m_aCurrentColumns.begin();
1427     ::std::vector<OPrivateColumns*>::iterator aEnd = m_aCurrentColumns.end();
1428     for (;aIter != aEnd;++aIter)
1429     {
1430         if ( *aIter )
1431         {
1432             (*aIter)->disposing();
1433             m_aColumnsCollection.push_back(*aIter);
1434             *aIter = NULL;
1435         }
1436     }
1437 
1438     if(m_pTables)
1439     {
1440         m_pTables->disposing();
1441         m_aTablesCollection.push_back(m_pTables);
1442         m_pTables = NULL;
1443     }
1444 }
1445 // -----------------------------------------------------------------------------
setCurrentColumns(EColumnType _eType,const::vos::ORef<OSQLColumns> & _rCols)1446 Reference< XIndexAccess > OSingleSelectQueryComposer::setCurrentColumns( EColumnType _eType,
1447     const ::vos::ORef< OSQLColumns >& _rCols )
1448 {
1449     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::setCurrentColumns" );
1450     ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
1451 
1452     ::osl::MutexGuard aGuard( m_aMutex );
1453     // now set the group columns
1454     if ( !m_aCurrentColumns[_eType] )
1455     {
1456         ::std::vector< ::rtl::OUString> aNames;
1457         OSQLColumns::Vector::const_iterator aEnd = _rCols->get().end();
1458         for(OSQLColumns::Vector::const_iterator aIter = _rCols->get().begin(); aIter != aEnd;++aIter)
1459             aNames.push_back(getString((*aIter)->getPropertyValue(PROPERTY_NAME)));
1460         m_aCurrentColumns[_eType] = new OPrivateColumns(_rCols,m_xMetaData->supportsMixedCaseQuotedIdentifiers(),*this,m_aMutex,aNames,sal_True);
1461     }
1462 
1463     return m_aCurrentColumns[_eType];
1464 }
1465 // -----------------------------------------------------------------------------
getGroupColumns()1466 Reference< XIndexAccess > SAL_CALL OSingleSelectQueryComposer::getGroupColumns(  )
1467 {
1468     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getGroupColumns" );
1469     return setCurrentColumns( GroupByColumns, m_aAdditiveIterator.getGroupColumns() );
1470 }
1471 // -------------------------------------------------------------------------
getOrderColumns()1472 Reference< XIndexAccess > SAL_CALL OSingleSelectQueryComposer::getOrderColumns(  )
1473 {
1474     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getOrderColumns" );
1475     return setCurrentColumns( OrderColumns, m_aAdditiveIterator.getOrderColumns() );
1476 }
1477 // -----------------------------------------------------------------------------
getQueryWithSubstitution()1478 ::rtl::OUString SAL_CALL OSingleSelectQueryComposer::getQueryWithSubstitution(  )
1479 {
1480     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getQueryWithSubstitution" );
1481     ::osl::MutexGuard aGuard( m_aMutex );
1482     ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
1483 
1484     ::rtl::OUString sSqlStatement( getQuery() );
1485 
1486     const OSQLParseNode* pStatementNode = m_aSqlIterator.getParseTree();
1487     if ( pStatementNode )
1488     {
1489         SQLException aError;
1490         if ( !pStatementNode->parseNodeToExecutableStatement( sSqlStatement, m_xConnection, m_aSqlParser, &aError ) )
1491             throw SQLException( aError );
1492     }
1493 
1494     return sSqlStatement;
1495 }
1496 // -----------------------------------------------------------------------------
getStatementPart(TGetParseNode & _aGetFunctor,OSQLParseTreeIterator & _rIterator)1497 ::rtl::OUString OSingleSelectQueryComposer::getStatementPart( TGetParseNode& _aGetFunctor, OSQLParseTreeIterator& _rIterator )
1498 {
1499     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getStatementPart" );
1500     ::rtl::OUString sResult;
1501 
1502     const OSQLParseNode* pNode = _aGetFunctor( &_rIterator );
1503     if ( pNode )
1504         pNode->parseNodeToStr( sResult, m_xConnection );
1505 
1506     return sResult;
1507 }
1508 // -----------------------------------------------------------------------------
1509 namespace
1510 {
lcl_getDecomposedColumnName(const::rtl::OUString & rComposedName,const::rtl::OUString & rQuoteString)1511     ::rtl::OUString lcl_getDecomposedColumnName( const ::rtl::OUString& rComposedName, const ::rtl::OUString& rQuoteString )
1512     {
1513         const sal_Int32 nQuoteLength = rQuoteString.getLength();
1514         ::rtl::OUString sName = rComposedName.trim();
1515         ::rtl::OUString sColumnName;
1516         sal_Int32 nPos, nRPos = 0;
1517 
1518         for (;;)
1519         {
1520             nPos = sName.indexOf( rQuoteString, nRPos );
1521             if ( nPos >= 0 )
1522             {
1523                 nRPos = sName.indexOf( rQuoteString, nPos + nQuoteLength );
1524                 if ( nRPos > nPos )
1525                 {
1526                     if ( nRPos + nQuoteLength < sName.getLength() )
1527                     {
1528                         nRPos += nQuoteLength; // -1 + 1 skip dot
1529                     }
1530                     else
1531                     {
1532                         sColumnName = sName.copy( nPos + nQuoteLength, nRPos - nPos - nQuoteLength );
1533                         break;
1534                     }
1535                 }
1536                 else
1537                     break;
1538             }
1539             else
1540                 break;
1541         }
1542         return sColumnName.isEmpty() ? rComposedName : sColumnName;
1543     }
1544 
lcl_getCondition(const Sequence<Sequence<PropertyValue>> & filter,const OPredicateInputController & i_aPredicateInputController,const Reference<XNameAccess> & i_xSelectColumns,const::rtl::OUString & rQuoteString)1545     ::rtl::OUString lcl_getCondition(const Sequence< Sequence< PropertyValue > >& filter,
1546             const OPredicateInputController& i_aPredicateInputController,
1547             const Reference< XNameAccess >& i_xSelectColumns,
1548             const ::rtl::OUString& rQuoteString )
1549     {
1550         ::rtl::OUStringBuffer sRet;
1551         const Sequence< PropertyValue >* pOrIter = filter.getConstArray();
1552         const Sequence< PropertyValue >* pOrEnd = pOrIter + filter.getLength();
1553         while ( pOrIter != pOrEnd )
1554         {
1555             if ( pOrIter->getLength() )
1556             {
1557                 sRet.append(L_BRACKET);
1558                 const PropertyValue* pAndIter = pOrIter->getConstArray();
1559                 const PropertyValue* pAndEnd = pAndIter + pOrIter->getLength();
1560                 while ( pAndIter != pAndEnd )
1561                 {
1562                     sRet.append(pAndIter->Name);
1563                     ::rtl::OUString sValue;
1564                     pAndIter->Value >>= sValue;
1565                     const ::rtl::OUString sColumnName = lcl_getDecomposedColumnName( pAndIter->Name, rQuoteString );
1566                     if ( i_xSelectColumns.is() && i_xSelectColumns->hasByName(sColumnName) )
1567                     {
1568                         Reference<XPropertySet> xColumn(i_xSelectColumns->getByName(sColumnName),UNO_QUERY);
1569                         sValue = i_aPredicateInputController.getPredicateValue(sValue,xColumn,sal_True);
1570                     }
1571                     else
1572                     {
1573                         sValue = i_aPredicateInputController.getPredicateValue(pAndIter->Name,sValue,sal_True);
1574                     }
1575                     lcl_addFilterCriteria_throw(pAndIter->Handle,sValue,sRet);
1576                     ++pAndIter;
1577                     if ( pAndIter != pAndEnd )
1578                         sRet.append(STR_AND);
1579                 }
1580                 sRet.append(R_BRACKET);
1581             }
1582             ++pOrIter;
1583             if ( pOrIter != pOrEnd && sRet.getLength() )
1584                 sRet.append(STR_OR);
1585         }
1586         return sRet.makeStringAndClear();
1587     }
1588 }
1589 // -----------------------------------------------------------------------------
setStructuredFilter(const Sequence<Sequence<PropertyValue>> & filter)1590 void SAL_CALL OSingleSelectQueryComposer::setStructuredFilter( const Sequence< Sequence< PropertyValue > >& filter )
1591 {
1592     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::setStructuredFilter" );
1593     OPredicateInputController aPredicateInput(m_aContext.getLegacyServiceFactory(),m_xConnection);
1594     setFilter(lcl_getCondition(filter,aPredicateInput,getColumns(), m_xMetaData->getIdentifierQuoteString()));
1595 }
1596 // -----------------------------------------------------------------------------
setStructuredHavingClause(const Sequence<Sequence<PropertyValue>> & filter)1597 void SAL_CALL OSingleSelectQueryComposer::setStructuredHavingClause( const Sequence< Sequence< PropertyValue > >& filter )
1598 {
1599     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::setStructuredHavingClause" );
1600     OPredicateInputController aPredicateInput(m_aContext.getLegacyServiceFactory(),m_xConnection);
1601     setHavingClause(lcl_getCondition(filter,aPredicateInput,getColumns(), m_xMetaData->getIdentifierQuoteString()));
1602 }
1603 // -----------------------------------------------------------------------------
setConditionByColumn(const Reference<XPropertySet> & column,sal_Bool andCriteria,::std::function<bool (OSingleSelectQueryComposer *,::rtl::OUString)> & _aSetFunctor,sal_Int32 filterOperator)1604 void OSingleSelectQueryComposer::setConditionByColumn( const Reference< XPropertySet >& column, sal_Bool andCriteria ,::std::function<bool(OSingleSelectQueryComposer*,::rtl::OUString)>& _aSetFunctor,sal_Int32 filterOperator)
1605 {
1606     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::setConditionByColumn" );
1607     ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
1608 
1609     if ( !column.is()
1610         || !column->getPropertySetInfo()->hasPropertyByName(PROPERTY_VALUE)
1611         || !column->getPropertySetInfo()->hasPropertyByName(PROPERTY_NAME)
1612         || !column->getPropertySetInfo()->hasPropertyByName(PROPERTY_TYPE))
1613         throw SQLException(DBACORE_RESSTRING(RID_STR_COLUMN_NOT_VALID),*this,SQLSTATE_GENERAL,1000,Any() );
1614 
1615     sal_Int32 nType = 0;
1616     column->getPropertyValue(PROPERTY_TYPE) >>= nType;
1617     sal_Int32 nSearchable = dbtools::getSearchColumnFlag(m_xConnection,nType);
1618     if(nSearchable == ColumnSearch::NONE)
1619         throw SQLException(DBACORE_RESSTRING(RID_STR_COLUMN_NOT_SEARCHABLE),*this,SQLSTATE_GENERAL,1000,Any() );
1620 
1621     ::osl::MutexGuard aGuard( m_aMutex );
1622 
1623     ::rtl::OUString aName;
1624     column->getPropertyValue(PROPERTY_NAME) >>= aName;
1625 
1626     Any aValue;
1627     column->getPropertyValue(PROPERTY_VALUE) >>= aValue;
1628 
1629     ::rtl::OUStringBuffer aSQL;
1630     const ::rtl::OUString aQuote    = m_xMetaData->getIdentifierQuoteString();
1631     getColumns();
1632 
1633     if ( m_aCurrentColumns[SelectColumns] && m_aCurrentColumns[SelectColumns]->hasByName(aName) )
1634     {
1635         Reference<XPropertySet> xColumn;
1636         m_aCurrentColumns[SelectColumns]->getByName(aName) >>= xColumn;
1637         OSL_ENSURE(xColumn->getPropertySetInfo()->hasPropertyByName(PROPERTY_REALNAME),"Property REALNAME not available!");
1638         OSL_ENSURE(xColumn->getPropertySetInfo()->hasPropertyByName(PROPERTY_TABLENAME),"Property TABLENAME not available!");
1639         OSL_ENSURE(xColumn->getPropertySetInfo()->hasPropertyByName(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("AggregateFunction"))),"Property AggregateFunctionnot available!");
1640 
1641         ::rtl::OUString sRealName,sTableName;
1642         xColumn->getPropertyValue(PROPERTY_REALNAME)    >>= sRealName;
1643         xColumn->getPropertyValue(PROPERTY_TABLENAME)   >>= sTableName;
1644         if(sTableName.indexOf('.',0) != -1)
1645         {
1646             ::rtl::OUString aCatlog,aSchema,aTable;
1647             ::dbtools::qualifiedNameComponents(m_xMetaData,sTableName,aCatlog,aSchema,aTable,::dbtools::eInDataManipulation);
1648             sTableName = ::dbtools::composeTableName( m_xMetaData, aCatlog, aSchema, aTable, sal_True, ::dbtools::eInDataManipulation );
1649         }
1650         else
1651             sTableName = ::dbtools::quoteName(aQuote,sTableName);
1652 
1653         if ( !::comphelper::getBOOL(xColumn->getPropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Function")))) )
1654         {
1655             aSQL =  sTableName;
1656             aSQL.appendAscii( "." );
1657             aSQL.append( ::dbtools::quoteName( aQuote, sRealName ) );
1658         }
1659         else
1660             aSQL = sRealName;
1661 
1662     }
1663     else
1664     {
1665         aSQL = getTableAlias( column );
1666         aSQL.append( ::dbtools::quoteName( aQuote, aName ) );
1667     }
1668 
1669 
1670     if ( aValue.hasValue() )
1671     {
1672         if(  !m_xTypeConverter.is() )
1673             m_aContext.createComponent( "com.sun.star.script.Converter", m_xTypeConverter );
1674         OSL_ENSURE(m_xTypeConverter.is(),"NO typeconverter!");
1675 
1676         if ( nType != DataType::BOOLEAN && DataType::BIT != nType )
1677         {
1678             ::rtl::OUString sEmpty;
1679             lcl_addFilterCriteria_throw(filterOperator,sEmpty,aSQL);
1680         }
1681 
1682         switch(nType)
1683         {
1684             case DataType::VARCHAR:
1685             case DataType::CHAR:
1686             case DataType::LONGVARCHAR:
1687                 aSQL.append( DBTypeConversion::toSQLString( nType, aValue, sal_True, m_xTypeConverter ) );
1688                 break;
1689             case DataType::CLOB:
1690                 {
1691                     Reference< XClob > xClob(aValue,UNO_QUERY);
1692                     if ( xClob.is() )
1693                     {
1694                         const ::sal_Int64 nLength = xClob->length();
1695                         if ( sal_Int64(nLength + aSQL.getLength() + STR_LIKE.getLength() ) < sal_Int64(SAL_MAX_INT32) )
1696                         {
1697                             aSQL.appendAscii("'");
1698                             aSQL.append( xClob->getSubString(1,(sal_Int32)nLength) );
1699                             aSQL.appendAscii("'");
1700                         }
1701                     }
1702                     else
1703                     {
1704                         aSQL.append( DBTypeConversion::toSQLString( nType, aValue, sal_True, m_xTypeConverter ) );
1705                     }
1706                 }
1707                 break;
1708             case DataType::VARBINARY:
1709             case DataType::BINARY:
1710             case DataType::LONGVARBINARY:
1711                 {
1712                     Sequence<sal_Int8> aSeq;
1713                     if(aValue >>= aSeq)
1714                     {
1715                         if(nSearchable == ColumnSearch::CHAR)
1716                         {
1717                             aSQL.appendAscii( "\'" );
1718                         }
1719                         aSQL.appendAscii( "0x" );
1720                         const sal_Int8* pBegin  = aSeq.getConstArray();
1721                         const sal_Int8* pEnd    = pBegin + aSeq.getLength();
1722                         for(;pBegin != pEnd;++pBegin)
1723                         {
1724                             aSQL.append( (sal_Int32)*pBegin, 16 ).getStr();
1725                         }
1726                         if(nSearchable == ColumnSearch::CHAR)
1727                             aSQL.appendAscii( "\'" );
1728                     }
1729                     else
1730                         throw SQLException(DBACORE_RESSTRING(RID_STR_NOT_SEQUENCE_INT8),*this,SQLSTATE_GENERAL,1000,Any() );
1731                 }
1732                 break;
1733             case DataType::BIT:
1734             case DataType::BOOLEAN:
1735                 {
1736                     sal_Bool bValue = sal_False;
1737                     m_xTypeConverter->convertToSimpleType(aValue, TypeClass_BOOLEAN) >>= bValue;
1738 
1739                     ::rtl::OUString sColumnExp = aSQL.makeStringAndClear();
1740                     getBoleanComparisonPredicate( sColumnExp, bValue, m_nBoolCompareMode, aSQL );
1741                 }
1742                 break;
1743             default:
1744                 aSQL.append( DBTypeConversion::toSQLString( nType, aValue, sal_True, m_xTypeConverter ) );
1745                 break;
1746         }
1747     }
1748     else
1749     {
1750         sal_Int32 nFilterOp = filterOperator;
1751         if ( filterOperator != SQLFilterOperator::SQLNULL && filterOperator != SQLFilterOperator::NOT_SQLNULL )
1752             nFilterOp = SQLFilterOperator::SQLNULL;
1753         ::rtl::OUString sEmpty;
1754         lcl_addFilterCriteria_throw(nFilterOp,sEmpty,aSQL);
1755     }
1756 
1757     // filter anhaengen
1758     // select ohne where und order by aufbauen
1759     ::rtl::OUString sFilter = getFilter();
1760 
1761     if ( sFilter.getLength() && aSQL.getLength() )
1762     {
1763         ::rtl::OUString sTemp(L_BRACKET);
1764         sTemp += sFilter;
1765         sTemp += R_BRACKET;
1766         sTemp += andCriteria ? STR_AND : STR_OR;
1767         sFilter = sTemp;
1768     }
1769     sFilter += aSQL.makeStringAndClear();
1770 
1771     // add the filter and the sort order
1772     _aSetFunctor(this,sFilter);
1773 }
1774 // -----------------------------------------------------------------------------
getStructuredCondition(TGetParseNode & _aGetFunctor)1775 Sequence< Sequence< PropertyValue > > OSingleSelectQueryComposer::getStructuredCondition( TGetParseNode& _aGetFunctor )
1776 {
1777     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getStructuredCondition" );
1778     ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
1779 
1780     MutexGuard aGuard(m_aMutex);
1781 
1782     Sequence< Sequence< PropertyValue > > aFilterSeq;
1783     ::rtl::OUString sFilter = getStatementPart( _aGetFunctor, m_aAdditiveIterator );
1784 
1785     if ( sFilter.getLength() != 0 )
1786     {
1787         ::rtl::OUString aSql(m_aPureSelectSQL);
1788         // build a temporary parse node
1789         const OSQLParseNode* pTempNode = m_aAdditiveIterator.getParseTree();
1790 
1791         aSql += STR_WHERE;
1792         aSql += sFilter;
1793 
1794         ::rtl::OUString aErrorMsg;
1795         ::std::unique_ptr<OSQLParseNode> pSqlParseNode( m_aSqlParser.parseTree(aErrorMsg,aSql));
1796         if ( pSqlParseNode.get() )
1797         {
1798             m_aAdditiveIterator.setParseTree(pSqlParseNode.get());
1799             // normalize the filter
1800             OSQLParseNode* pWhereNode = const_cast<OSQLParseNode*>(m_aAdditiveIterator.getWhereTree());
1801 
1802             OSQLParseNode* pCondition = pWhereNode->getChild(1);
1803         #if OSL_DEBUG_LEVEL > 0
1804             ::rtl::OUString sCondition;
1805             pCondition->parseNodeToStr( sCondition, m_xConnection );
1806         #endif
1807             OSQLParseNode::negateSearchCondition(pCondition);
1808 
1809             pCondition = pWhereNode->getChild(1);
1810         #if OSL_DEBUG_LEVEL > 0
1811             sCondition = ::rtl::OUString();
1812             pCondition->parseNodeToStr( sCondition, m_xConnection );
1813         #endif
1814             OSQLParseNode::disjunctiveNormalForm(pCondition);
1815 
1816             pCondition = pWhereNode->getChild(1);
1817         #if OSL_DEBUG_LEVEL > 0
1818             sCondition = ::rtl::OUString();
1819             pCondition->parseNodeToStr( sCondition, m_xConnection );
1820         #endif
1821             OSQLParseNode::absorptions(pCondition);
1822 
1823             pCondition = pWhereNode->getChild(1);
1824         #if OSL_DEBUG_LEVEL > 0
1825             sCondition = ::rtl::OUString();
1826             pCondition->parseNodeToStr( sCondition, m_xConnection );
1827         #endif
1828             if ( pCondition )
1829             {
1830                 ::std::vector< ::std::vector < PropertyValue > > aFilters;
1831                 Reference< XNumberFormatter > xFormatter;
1832                 m_aContext.createComponent( "com.sun.star.util.NumberFormatter", xFormatter );
1833                 xFormatter->attachNumberFormatsSupplier( m_xNumberFormatsSupplier );
1834 
1835                 if (setORCriteria(pCondition, m_aAdditiveIterator, aFilters, xFormatter))
1836                 {
1837                     aFilterSeq.realloc(aFilters.size());
1838                     Sequence<PropertyValue>* pFilters = aFilterSeq.getArray();
1839                     ::std::vector< ::std::vector < PropertyValue > >::const_iterator aEnd = aFilters.end();
1840                     ::std::vector< ::std::vector < PropertyValue > >::const_iterator i = aFilters.begin();
1841                     for ( ; i != aEnd ; ++i)
1842                     {
1843                         const ::std::vector < PropertyValue >& rProperties = *i;
1844                         pFilters->realloc(rProperties.size());
1845                         PropertyValue* pFilter = pFilters->getArray();
1846                         ::std::vector < PropertyValue >::const_iterator j = rProperties.begin();
1847                         ::std::vector < PropertyValue >::const_iterator aEnd2 = rProperties.end();
1848                         for ( ; j != aEnd2 ; ++j)
1849                         {
1850                             *pFilter = *j;
1851                             ++pFilter;
1852                         }
1853                         ++pFilters;
1854                     }
1855                 }
1856             }
1857             // restore
1858             m_aAdditiveIterator.setParseTree(pTempNode);
1859         }
1860     }
1861     return aFilterSeq;
1862 }
1863 // -----------------------------------------------------------------------------
getKeyword(SQLPart _ePart) const1864 ::rtl::OUString OSingleSelectQueryComposer::getKeyword( SQLPart _ePart ) const
1865 {
1866     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getKeyword" );
1867     ::rtl::OUString sKeyword;
1868     switch(_ePart)
1869     {
1870         default:
1871             OSL_ENSURE( 0, "OSingleSelectQueryComposer::getKeyWord: Invalid enum value!" );
1872             // no break, fallback to WHERE
1873         case Where:
1874             sKeyword = STR_WHERE;
1875             break;
1876         case Group:
1877             sKeyword = STR_GROUP_BY;
1878             break;
1879         case Having:
1880             sKeyword = STR_HAVING;
1881             break;
1882         case Order:
1883             sKeyword = STR_ORDER_BY;
1884             break;
1885     }
1886     return sKeyword;
1887 }
1888 
1889 // -----------------------------------------------------------------------------
getSQLPart(SQLPart _ePart,OSQLParseTreeIterator & _rIterator,sal_Bool _bWithKeyword)1890 ::rtl::OUString OSingleSelectQueryComposer::getSQLPart( SQLPart _ePart, OSQLParseTreeIterator& _rIterator, sal_Bool _bWithKeyword )
1891 {
1892     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getSQLPart" );
1893     TGetParseNode F_tmp(&OSQLParseTreeIterator::getSimpleWhereTree);
1894     ::rtl::OUString sKeyword( getKeyword( _ePart ) );
1895     switch(_ePart)
1896     {
1897         case Where:
1898             F_tmp = TGetParseNode(&OSQLParseTreeIterator::getSimpleWhereTree);
1899             break;
1900         case Group:
1901             F_tmp = TGetParseNode (&OSQLParseTreeIterator::getSimpleGroupByTree);
1902             break;
1903         case Having:
1904             F_tmp = TGetParseNode(&OSQLParseTreeIterator::getSimpleHavingTree);
1905             break;
1906         case Order:
1907             F_tmp = TGetParseNode(&OSQLParseTreeIterator::getSimpleOrderTree);
1908             break;
1909         default:
1910             OSL_ENSURE(0,"Invalid enum value!");
1911     }
1912 
1913     ::rtl::OUString sRet = getStatementPart( F_tmp, _rIterator );
1914     if ( _bWithKeyword && sRet.getLength() )
1915         sRet = sKeyword + sRet;
1916     return sRet;
1917 }
1918 // -----------------------------------------------------------------------------
1919