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