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