Bump version to 5.0-14
[LibreOffice.git] / dbaccess / source / core / api / SingleSelectQueryComposer.cxx
blob6be7270d80ab20a93f00304d8c132f9ac3b14fb9
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
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"
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>
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>
60 #include <boost/scoped_ptr.hpp>
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;
80 namespace dbaccess {
81 namespace BooleanComparisonMode = ::com::sun::star::sdb::BooleanComparisonMode;
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 ","
97 namespace
99 /** parses the given statement, using the given parser, returns a parse node representing
100 the statement
102 If the statement cannot be parsed, an error is thrown.
104 const OSQLParseNode* parseStatement_throwError( OSQLParser& _rParser, const OUString& _rStatement, const Reference< XInterface >& _rxContext )
106 OUString aErrorMsg;
107 const OSQLParseNode* pNewSqlParseNode = _rParser.parseTree( aErrorMsg, _rStatement );
108 if ( !pNewSqlParseNode )
110 OUString sSQLStateGeneralError( getStandardSQLState( SQL_GENERAL_ERROR ) );
111 SQLException aError2( aErrorMsg, _rxContext, sSQLStateGeneralError, 1000, Any() );
112 SQLException aError1( _rStatement, _rxContext, sSQLStateGeneralError, 1000, makeAny( aError2 ) );
113 throw SQLException(_rParser.getContext().getErrorMessage(OParseContext::ERROR_GENERAL),_rxContext,sSQLStateGeneralError,1000,makeAny(aError1));
115 return pNewSqlParseNode;
118 /** checks whether the given parse node describes a valid single select statement, throws
119 an error if not
121 void checkForSingleSelect_throwError( const OSQLParseNode* pStatementNode, OSQLParseTreeIterator& _rIterator,
122 const Reference< XInterface >& _rxContext, const OUString& _rOriginatingCommand )
124 const OSQLParseNode* pOldNode = _rIterator.getParseTree();
126 // determine the statement type
127 _rIterator.setParseTree( pStatementNode );
128 _rIterator.traverseAll();
129 bool bIsSingleSelect = ( _rIterator.getStatementType() == SQL_STATEMENT_SELECT );
131 // throw the error, if necessary
132 if ( !bIsSingleSelect || SQL_ISRULE( pStatementNode, union_statement ) ) // #i4229# OJ
134 // restore the old node before throwing the exception
135 _rIterator.setParseTree( pOldNode );
136 // and now really ...
137 SQLException aError1( _rOriginatingCommand, _rxContext, getStandardSQLState( SQL_GENERAL_ERROR ), 1000, Any() );
138 throw SQLException( DBACORE_RESSTRING( RID_STR_ONLY_QUERY ), _rxContext,
139 getStandardSQLState( SQL_GENERAL_ERROR ), 1000, makeAny( aError1 ) );
142 delete pOldNode;
145 /** combines parseStatement_throwError and checkForSingleSelect_throwError
147 void parseAndCheck_throwError( OSQLParser& _rParser, const OUString& _rStatement,
148 OSQLParseTreeIterator& _rIterator, const Reference< XInterface >& _rxContext )
150 const OSQLParseNode* pNode = parseStatement_throwError( _rParser, _rStatement, _rxContext );
151 checkForSingleSelect_throwError( pNode, _rIterator, _rxContext, _rStatement );
154 /** transforms a parse node describing a complete statement into a pure select
155 statement, without any filter/order/groupby/having clauses
157 OUString getPureSelectStatement( const OSQLParseNode* _pRootNode, Reference< XConnection > _rxConnection )
159 OUString sSQL = STR_SELECT;
160 _pRootNode->getChild(1)->parseNodeToStr( sSQL, _rxConnection );
161 _pRootNode->getChild(2)->parseNodeToStr( sSQL, _rxConnection );
162 sSQL += STR_FROM;
163 _pRootNode->getChild(3)->getChild(0)->getChild(1)->parseNodeToStr( sSQL, _rxConnection );
164 return sSQL;
167 /** resets an SQL iterator, including deletion of the parse tree, and disposal if desired
169 void resetIterator( OSQLParseTreeIterator& _rIterator, bool _bDispose )
171 const OSQLParseNode* pSqlParseNode = _rIterator.getParseTree();
172 _rIterator.setParseTree(NULL);
173 delete pSqlParseNode;
174 if ( _bDispose )
175 _rIterator.dispose();
177 void lcl_addFilterCriteria_throw(sal_Int32 i_nFilterOperator,const OUString& i_sValue,OUStringBuffer& o_sRet)
179 switch( i_nFilterOperator )
181 case SQLFilterOperator::EQUAL:
182 o_sRet.append(" = " + i_sValue);
183 break;
184 case SQLFilterOperator::NOT_EQUAL:
185 o_sRet.append(" <> " + i_sValue);
186 break;
187 case SQLFilterOperator::LESS:
188 o_sRet.append(" < " + i_sValue);
189 break;
190 case SQLFilterOperator::GREATER:
191 o_sRet.append(" > " + i_sValue);
192 break;
193 case SQLFilterOperator::LESS_EQUAL:
194 o_sRet.append(" <= " + i_sValue);
195 break;
196 case SQLFilterOperator::GREATER_EQUAL:
197 o_sRet.append(" >= " + i_sValue);
198 break;
199 case SQLFilterOperator::LIKE:
200 o_sRet.append(" LIKE " + i_sValue);
201 break;
202 case SQLFilterOperator::NOT_LIKE:
203 o_sRet.append(" NOT LIKE " + i_sValue);
204 break;
205 case SQLFilterOperator::SQLNULL:
206 o_sRet.append(" IS NULL");
207 break;
208 case SQLFilterOperator::NOT_SQLNULL:
209 o_sRet.append(" IS NOT NULL");
210 break;
211 default:
212 throw SQLException();
219 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 ,m_xMetaData(_xConnection->getMetaData())
230 ,m_xConnectionTables( _rxTables )
231 ,m_aContext( _rContext )
232 ,m_pTables(NULL)
233 ,m_nBoolCompareMode( BooleanComparisonMode::EQUAL_INTEGER )
234 ,m_nCommandType(CommandType::COMMAND)
236 if ( !m_aContext.is() || !m_xConnection.is() || !m_xConnectionTables.is() )
237 throw IllegalArgumentException();
239 registerProperty(PROPERTY_ORIGINAL,PROPERTY_ID_ORIGINAL,PropertyAttribute::BOUND|PropertyAttribute::READONLY,&m_sOrignal,cppu::UnoType<decltype(m_sOrignal)>::get());
241 m_aCurrentColumns.resize(4);
243 m_aLocale = m_aParseContext.getPreferredLocale();
244 m_xNumberFormatsSupplier = dbtools::getNumberFormats( m_xConnection, true, m_aContext );
245 Reference< XLocaleData4 > xLocaleData( LocaleData::create(m_aContext) );
246 LocaleDataItem aData = xLocaleData->getLocaleItem(m_aLocale);
247 m_sDecimalSep = aData.decimalSeparator;
248 OSL_ENSURE(m_sDecimalSep.getLength() == 1,"OSingleSelectQueryComposer::OSingleSelectQueryComposer decimal separator is not 1 length");
251 Any aValue;
252 Reference<XInterface> xDs = dbaccess::getDataSource(_xConnection);
253 if ( dbtools::getDataSourceSetting(xDs,static_cast <OUString> (PROPERTY_BOOLEANCOMPARISONMODE),aValue) )
255 OSL_VERIFY( aValue >>= m_nBoolCompareMode );
257 Reference< XQueriesSupplier > xQueriesAccess(m_xConnection, UNO_QUERY);
258 if (xQueriesAccess.is())
259 m_xConnectionQueries = xQueriesAccess->getQueries();
261 catch(Exception&)
266 OSingleSelectQueryComposer::~OSingleSelectQueryComposer()
268 ::std::vector<OPrivateColumns*>::iterator aColIter = m_aColumnsCollection.begin();
269 ::std::vector<OPrivateColumns*>::iterator aEnd = m_aColumnsCollection.end();
270 for(;aColIter != aEnd;++aColIter)
271 delete *aColIter;
273 ::std::vector<OPrivateTables*>::iterator aTabIter = m_aTablesCollection.begin();
274 ::std::vector<OPrivateTables*>::iterator aTabEnd = m_aTablesCollection.end();
275 for(;aTabIter != aTabEnd;++aTabIter)
276 delete *aTabIter;
279 // OComponentHelper
280 void SAL_CALL OSingleSelectQueryComposer::disposing()
282 OSubComponent::disposing();
284 MutexGuard aGuard(m_aMutex);
286 resetIterator( m_aSqlIterator, true );
287 resetIterator( m_aAdditiveIterator, true );
289 m_xConnectionTables = NULL;
290 m_xConnection = NULL;
292 clearCurrentCollections();
295 IMPLEMENT_FORWARD_XINTERFACE3(OSingleSelectQueryComposer,OSubComponent,OSingleSelectQueryComposer_BASE,OPropertyContainer)
296 IMPLEMENT_SERVICE_INFO1(OSingleSelectQueryComposer,"org.openoffice.comp.dba.OSingleSelectQueryComposer",SERVICE_NAME_SINGLESELECTQUERYCOMPOSER)
298 css::uno::Sequence<sal_Int8> OSingleSelectQueryComposer::getImplementationId()
299 throw (css::uno::RuntimeException, std::exception)
301 return css::uno::Sequence<sal_Int8>();
304 IMPLEMENT_GETTYPES3(OSingleSelectQueryComposer,OSubComponent,OSingleSelectQueryComposer_BASE,OPropertyContainer)
305 IMPLEMENT_PROPERTYCONTAINER_DEFAULTS(OSingleSelectQueryComposer)
307 // XSingleSelectQueryAnalyzer
308 OUString SAL_CALL OSingleSelectQueryComposer::getQuery( ) throw(RuntimeException, std::exception)
310 ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
311 ::osl::MutexGuard aGuard( m_aMutex );
313 TGetParseNode F_tmp(&OSQLParseTreeIterator::getParseTree);
314 return getStatementPart(F_tmp,m_aSqlIterator);
317 void SAL_CALL OSingleSelectQueryComposer::setQuery( const OUString& command ) throw(SQLException, RuntimeException, std::exception)
319 ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
321 ::osl::MutexGuard aGuard( m_aMutex );
322 m_nCommandType = CommandType::COMMAND;
323 // first clear the tables and columns
324 clearCurrentCollections();
325 // now set the new one
326 setQuery_Impl(command);
327 m_sOrignal = command;
329 // reset the additive iterator to the same statement
330 parseAndCheck_throwError( m_aSqlParser, m_sOrignal, m_aAdditiveIterator, *this );
332 // we have no "elementary" parts anymore (means filter/groupby/having/order clauses)
333 for ( SQLPart eLoopParts = Where; eLoopParts != SQLPartCount; incSQLPart( eLoopParts ) )
334 m_aElementaryParts[ eLoopParts ].clear();
337 void SAL_CALL OSingleSelectQueryComposer::setCommand( const OUString& Command,sal_Int32 _nCommandType ) throw(SQLException, RuntimeException, std::exception)
339 OUStringBuffer sSQL;
340 switch(_nCommandType)
342 case CommandType::COMMAND:
343 setElementaryQuery(Command);
344 return;
345 case CommandType::TABLE:
346 if ( m_xConnectionTables->hasByName(Command) )
348 sSQL.appendAscii("SELECT * FROM ");
349 Reference< XPropertySet > xTable;
352 m_xConnectionTables->getByName( Command ) >>= xTable;
354 catch(const WrappedTargetException& e)
356 SQLException e2;
357 if ( e.TargetException >>= e2 )
358 throw e2;
360 catch(Exception&)
362 DBG_UNHANDLED_EXCEPTION();
365 sSQL.append(dbtools::composeTableNameForSelect(m_xConnection,xTable));
367 else
369 OUString sMessage( DBACORE_RESSTRING( RID_STR_TABLE_DOES_NOT_EXIST ) );
370 throwGenericSQLException(sMessage.replaceAll( "$table$", Command ),*this);
372 break;
373 case CommandType::QUERY:
374 if ( m_xConnectionQueries->hasByName(Command) )
377 Reference<XPropertySet> xQuery(m_xConnectionQueries->getByName(Command),UNO_QUERY);
378 OUString sCommand;
379 xQuery->getPropertyValue(PROPERTY_COMMAND) >>= sCommand;
380 sSQL.append(sCommand);
382 else
384 OUString sMessage( DBACORE_RESSTRING( RID_STR_QUERY_DOES_NOT_EXIST ) );
385 throwGenericSQLException(sMessage.replaceAll( "$table$", Command ),*this);
388 break;
389 default:
390 break;
392 ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
394 ::osl::MutexGuard aGuard( m_aMutex );
395 m_nCommandType = _nCommandType;
396 m_sCommand = Command;
397 // first clear the tables and columns
398 clearCurrentCollections();
399 // now set the new one
400 OUString sCommand = sSQL.makeStringAndClear();
401 setElementaryQuery(sCommand);
402 m_sOrignal = sCommand;
405 void OSingleSelectQueryComposer::setQuery_Impl( const OUString& command )
407 // parse this
408 parseAndCheck_throwError( m_aSqlParser, command, m_aSqlIterator, *this );
410 // strip it from all clauses, to have the pure SELECT statement
411 m_aPureSelectSQL = getPureSelectStatement( m_aSqlIterator.getParseTree(), m_xConnection );
413 // update tables
414 getTables();
417 Sequence< Sequence< PropertyValue > > SAL_CALL OSingleSelectQueryComposer::getStructuredHavingClause( ) throw (RuntimeException, std::exception)
419 TGetParseNode F_tmp(&OSQLParseTreeIterator::getSimpleHavingTree);
420 return getStructuredCondition(F_tmp);
423 Sequence< Sequence< PropertyValue > > SAL_CALL OSingleSelectQueryComposer::getStructuredFilter( ) throw(RuntimeException, std::exception)
425 TGetParseNode F_tmp(&OSQLParseTreeIterator::getSimpleWhereTree);
426 return getStructuredCondition(F_tmp);
429 void SAL_CALL OSingleSelectQueryComposer::appendHavingClauseByColumn( const Reference< XPropertySet >& column, sal_Bool andCriteria,sal_Int32 filterOperator ) throw (SQLException, WrappedTargetException, RuntimeException, std::exception)
431 ::std::mem_fun1_t<bool,OSingleSelectQueryComposer,const OUString&> F_tmp(&OSingleSelectQueryComposer::implSetHavingClause);
432 setConditionByColumn(column,andCriteria,F_tmp,filterOperator);
435 void SAL_CALL OSingleSelectQueryComposer::appendFilterByColumn( const Reference< XPropertySet >& column, sal_Bool andCriteria,sal_Int32 filterOperator ) throw(SQLException, WrappedTargetException, RuntimeException, std::exception)
437 ::std::mem_fun1_t<bool,OSingleSelectQueryComposer,const OUString&> F_tmp(&OSingleSelectQueryComposer::implSetFilter);
438 setConditionByColumn(column,andCriteria,F_tmp,filterOperator);
441 OUString OSingleSelectQueryComposer::impl_getColumnRealName_throw(const Reference< XPropertySet >& column, bool bGroupBy)
443 ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
445 getColumns();
446 if ( !column.is()
447 || !m_aCurrentColumns[SelectColumns]
448 || !column->getPropertySetInfo()->hasPropertyByName(PROPERTY_NAME)
451 OUString sError(DBACORE_RESSTRING(RID_STR_COLUMN_UNKNOWN_PROP));
452 SQLException aErr(sError.replaceAll("%value", OUString(PROPERTY_NAME)),*this,SQLSTATE_GENERAL,1000,Any() );
453 throw SQLException(DBACORE_RESSTRING(RID_STR_COLUMN_NOT_VALID),*this,SQLSTATE_GENERAL,1000,makeAny(aErr) );
456 OUString aName, aNewName;
457 column->getPropertyValue(PROPERTY_NAME) >>= aName;
459 if ( bGroupBy &&
460 !m_xMetaData->supportsGroupByUnrelated() &&
461 m_aCurrentColumns[SelectColumns] &&
462 !m_aCurrentColumns[SelectColumns]->hasByName(aName) )
464 OUString sError(DBACORE_RESSTRING(RID_STR_COLUMN_MUST_VISIBLE));
465 throw SQLException(sError.replaceAll("%name", aName),*this,SQLSTATE_GENERAL,1000,Any() );
468 OUString aQuote = m_xMetaData->getIdentifierQuoteString();
469 if ( m_aCurrentColumns[SelectColumns]->hasByName(aName) )
471 Reference<XPropertySet> xColumn;
472 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!");
477 OUString sRealName, sTableName;
478 xColumn->getPropertyValue(PROPERTY_REALNAME) >>= sRealName;
479 xColumn->getPropertyValue(PROPERTY_TABLENAME) >>= sTableName;
480 bool bFunction = false;
481 xColumn->getPropertyValue("Function") >>= bFunction;
482 if ( sRealName == aName )
484 if ( bFunction )
485 aNewName = aName;
486 else
488 if(sTableName.indexOf('.',0) != -1)
490 OUString aCatlog,aSchema,aTable;
491 ::dbtools::qualifiedNameComponents(m_xMetaData,sTableName,aCatlog,aSchema,aTable,::dbtools::eInDataManipulation);
492 sTableName = ::dbtools::composeTableName( m_xMetaData, aCatlog, aSchema, aTable, true, ::dbtools::eInDataManipulation );
494 else if (!sTableName.isEmpty())
495 sTableName = ::dbtools::quoteName(aQuote,sTableName);
497 if(sTableName.isEmpty())
498 aNewName = ::dbtools::quoteName(aQuote,sRealName);
499 else
500 aNewName = sTableName + "." + ::dbtools::quoteName(aQuote,sRealName);
503 else
504 aNewName = ::dbtools::quoteName(aQuote,aName);
506 else
507 aNewName = getTableAlias(column) + ::dbtools::quoteName(aQuote,aName);
508 return aNewName;
511 OUString OSingleSelectQueryComposer::impl_getColumnName_throw(const Reference< XPropertySet >& column, bool bOrderBy)
513 ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
515 getColumns();
516 if ( !column.is()
517 || !m_aCurrentColumns[SelectColumns]
518 || !column->getPropertySetInfo()->hasPropertyByName(PROPERTY_NAME)
521 OUString sError(DBACORE_RESSTRING(RID_STR_COLUMN_UNKNOWN_PROP));
522 SQLException aErr(sError.replaceAll("%value", OUString(PROPERTY_NAME)),*this,SQLSTATE_GENERAL,1000,Any() );
523 throw SQLException(DBACORE_RESSTRING(RID_STR_COLUMN_NOT_VALID),*this,SQLSTATE_GENERAL,1000,makeAny(aErr) );
526 OUString aName;
527 column->getPropertyValue(PROPERTY_NAME) >>= aName;
529 const OUString aQuote = m_xMetaData->getIdentifierQuoteString();
531 if ( m_aCurrentColumns[SelectColumns] &&
532 m_aCurrentColumns[SelectColumns]->hasByName(aName) )
534 // It is a column from the SELECT list, use it as such.
535 return ::dbtools::quoteName(aQuote,aName);
538 // Nope, it is an unrelated column.
539 // Is that supported?
540 if ( bOrderBy &&
541 !m_xMetaData->supportsOrderByUnrelated() )
543 OUString sError(DBACORE_RESSTRING(RID_STR_COLUMN_MUST_VISIBLE));
544 throw SQLException(sError.replaceAll("%name", aName),*this,SQLSTATE_GENERAL,1000,Any() );
547 // We need to refer to it by its "real" name, that is by schemaName.tableName.columnNameInTable
548 return impl_getColumnRealName_throw(column, false);
551 void SAL_CALL OSingleSelectQueryComposer::appendOrderByColumn( const Reference< XPropertySet >& column, sal_Bool ascending ) throw(SQLException, RuntimeException, std::exception)
553 ::osl::MutexGuard aGuard( m_aMutex );
554 OUString sColumnName( impl_getColumnName_throw(column, true) );
555 OUString sOrder = getOrder();
556 if ( !(sOrder.isEmpty() || sColumnName.isEmpty()) )
557 sOrder += COMMA;
558 sOrder += sColumnName;
559 if ( !(ascending || sColumnName.isEmpty()) )
560 sOrder += " DESC ";
562 setOrder(sOrder);
565 void SAL_CALL OSingleSelectQueryComposer::appendGroupByColumn( const Reference< XPropertySet >& column) throw(SQLException, RuntimeException, std::exception)
567 ::osl::MutexGuard aGuard( m_aMutex );
568 OUString sColumnName( impl_getColumnRealName_throw(column, true) );
569 OrderCreator aComposer;
570 aComposer.append( getGroup() );
571 aComposer.append( sColumnName );
572 setGroup( aComposer.getComposedAndClear() );
575 OUString OSingleSelectQueryComposer::composeStatementFromParts( const ::std::vector< OUString >& _rParts )
577 OSL_ENSURE( _rParts.size() == (size_t)SQLPartCount, "OSingleSelectQueryComposer::composeStatementFromParts: invalid parts array!" );
579 OUStringBuffer aSql( m_aPureSelectSQL );
580 for ( SQLPart eLoopParts = Where; eLoopParts != SQLPartCount; incSQLPart( eLoopParts ) )
581 if ( !_rParts[ eLoopParts ].isEmpty() )
583 aSql.append( getKeyword( eLoopParts ) );
584 aSql.append( _rParts[ eLoopParts ] );
587 return aSql.makeStringAndClear();
590 OUString SAL_CALL OSingleSelectQueryComposer::getElementaryQuery() throw (::com::sun::star::uno::RuntimeException, std::exception)
592 return composeStatementFromParts( m_aElementaryParts );
595 void SAL_CALL OSingleSelectQueryComposer::setElementaryQuery( const OUString& _rElementary ) throw (::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException, std::exception)
597 ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
598 ::osl::MutexGuard aGuard( m_aMutex );
600 // remember the 4 current "additive" clauses
601 ::std::vector< OUString > aAdditiveClauses( SQLPartCount );
602 for ( SQLPart eLoopParts = Where; eLoopParts != SQLPartCount; incSQLPart( eLoopParts ) )
603 aAdditiveClauses[ eLoopParts ] = getSQLPart( eLoopParts, m_aAdditiveIterator, false );
605 // clear the tables and columns
606 clearCurrentCollections();
607 // set and parse the new query
608 setQuery_Impl( _rElementary );
610 // get the 4 elementary parts of the statement
611 for ( SQLPart eLoopParts = Where; eLoopParts != SQLPartCount; incSQLPart( eLoopParts ) )
612 m_aElementaryParts[ eLoopParts ] = getSQLPart( eLoopParts, m_aSqlIterator, false );
614 // reset the AdditiveIterator: m_aPureSelectSQL may have changed
617 parseAndCheck_throwError( m_aSqlParser, composeStatementFromParts( aAdditiveClauses ), m_aAdditiveIterator, *this );
619 catch( const Exception& e )
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
629 namespace
631 OUString getComposedClause( const OUString& _rElementaryClause, const OUString& _rAdditionalClause,
632 TokenComposer& _rComposer, const OUString& _rKeyword )
634 _rComposer.clear();
635 _rComposer.append( _rElementaryClause );
636 _rComposer.append( _rAdditionalClause );
637 OUString sComposed = _rComposer.getComposedAndClear();
638 if ( !sComposed.isEmpty() )
639 sComposed = _rKeyword + sComposed;
640 return sComposed;
644 void OSingleSelectQueryComposer::setSingleAdditiveClause( SQLPart _ePart, const OUString& _rClause )
646 ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
647 ::osl::MutexGuard aGuard( m_aMutex );
649 // if nothing is changed, do nothing
650 if ( getSQLPart( _ePart, m_aAdditiveIterator, false ) == _rClause )
651 return;
653 // collect the 4 single parts as they're currently set
654 ::std::vector< OUString > aClauses;
655 aClauses.reserve( (size_t)SQLPartCount );
656 for ( SQLPart eLoopParts = Where; eLoopParts != SQLPartCount; incSQLPart( eLoopParts ) )
657 aClauses.push_back( getSQLPart( eLoopParts, m_aSqlIterator, true ) );
659 // overwrite the one part in question here
660 boost::scoped_ptr< TokenComposer > pComposer;
661 if ( ( _ePart == Where ) || ( _ePart == Having ) )
662 pComposer.reset( new FilterCreator );
663 else
664 pComposer.reset( new OrderCreator );
665 aClauses[ _ePart ] = getComposedClause( m_aElementaryParts[ _ePart ], _rClause,
666 *pComposer, getKeyword( _ePart ) );
668 // construct the complete statement
669 OUStringBuffer aSql(m_aPureSelectSQL);
670 for ( SQLPart eLoopParts = Where; eLoopParts != SQLPartCount; incSQLPart( eLoopParts ) )
671 aSql.append(aClauses[ eLoopParts ]);
673 // set the query
674 setQuery_Impl(aSql.makeStringAndClear());
676 // clear column collections which (might) have changed
677 clearColumns( ParameterColumns );
678 if ( _ePart == Order )
679 clearColumns( OrderColumns );
680 else if ( _ePart == Group )
681 clearColumns( GroupByColumns );
683 // also, since the "additive filter" change, we need to rebuild our "additive" statement
684 aSql = m_aPureSelectSQL;
685 // again, first get all the old additive parts
686 for ( SQLPart eLoopParts = Where; eLoopParts != SQLPartCount; incSQLPart( eLoopParts ) )
687 aClauses[ eLoopParts ] = getSQLPart( eLoopParts, m_aAdditiveIterator, true );
688 // then overwrite the one in question
689 aClauses[ _ePart ] = getComposedClause( OUString(), _rClause, *pComposer, getKeyword( _ePart ) );
690 // and parse it, so that m_aAdditiveIterator is up to date
691 for ( SQLPart eLoopParts = Where; eLoopParts != SQLPartCount; incSQLPart( eLoopParts ) )
692 aSql.append(aClauses[ eLoopParts ]);
695 parseAndCheck_throwError( m_aSqlParser, aSql.makeStringAndClear(), m_aAdditiveIterator, *this );
697 catch( const Exception& e )
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
706 void SAL_CALL OSingleSelectQueryComposer::setFilter( const OUString& filter ) throw(SQLException, RuntimeException, std::exception)
708 setSingleAdditiveClause( Where, filter );
711 void SAL_CALL OSingleSelectQueryComposer::setOrder( const OUString& order ) throw(SQLException, RuntimeException, std::exception)
713 setSingleAdditiveClause( Order, order );
716 void SAL_CALL OSingleSelectQueryComposer::setGroup( const OUString& group ) throw (SQLException, RuntimeException, std::exception)
718 setSingleAdditiveClause( Group, group );
721 void SAL_CALL OSingleSelectQueryComposer::setHavingClause( const OUString& filter ) throw(SQLException, RuntimeException, std::exception)
723 setSingleAdditiveClause( Having, filter );
726 // XTablesSupplier
727 Reference< XNameAccess > SAL_CALL OSingleSelectQueryComposer::getTables( ) throw(RuntimeException, std::exception)
729 ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
731 ::osl::MutexGuard aGuard( m_aMutex );
732 if ( !m_pTables )
734 const OSQLTables& aTables = m_aSqlIterator.getTables();
735 ::std::vector< OUString> aNames;
736 OSQLTables::const_iterator aEnd = aTables.end();
737 for(OSQLTables::const_iterator aIter = aTables.begin(); aIter != aEnd;++aIter)
738 aNames.push_back(aIter->first);
740 m_pTables = new OPrivateTables(aTables,m_xMetaData->supportsMixedCaseQuotedIdentifiers(),*this,m_aMutex,aNames);
743 return m_pTables;
746 // XColumnsSupplier
747 Reference< XNameAccess > SAL_CALL OSingleSelectQueryComposer::getColumns( ) throw(RuntimeException, std::exception)
749 ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
750 ::osl::MutexGuard aGuard( m_aMutex );
751 if ( !!m_aCurrentColumns[SelectColumns] )
752 return m_aCurrentColumns[SelectColumns];
754 ::std::vector< OUString> aNames;
755 ::rtl::Reference< OSQLColumns> aSelectColumns;
756 bool bCase = true;
757 Reference< XNameAccess> xQueryColumns;
758 if ( m_nCommandType == CommandType::QUERY )
760 Reference<XColumnsSupplier> xSup(m_xConnectionQueries->getByName(m_sCommand),UNO_QUERY);
761 if(xSup.is())
762 xQueryColumns = xSup->getColumns();
765 do {
769 SharedUNOComponent< XStatement, DisposableComponent > xStatement;
770 SharedUNOComponent< XPreparedStatement, DisposableComponent > xPreparedStatement;
772 bCase = m_xMetaData->supportsMixedCaseQuotedIdentifiers();
773 aSelectColumns = m_aSqlIterator.getSelectColumns();
775 OUStringBuffer aSQL( m_aPureSelectSQL + STR_WHERE " ( 0 = 1 )");
777 // preserve the original WHERE clause
778 // #i102234#
779 OUString sOriginalWhereClause = getSQLPart( Where, m_aSqlIterator, false );
780 if ( !sOriginalWhereClause.isEmpty() )
782 aSQL.append( " AND ( " + sOriginalWhereClause + " ) " );
785 OUString sGroupBy = getSQLPart( Group, m_aSqlIterator, true );
786 if ( !sGroupBy.isEmpty() )
787 aSQL.append( sGroupBy );
789 OUString sSQL( aSQL.makeStringAndClear() );
790 // normalize the statement so that it doesn't contain any application-level features anymore
791 OUString sError;
792 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 if ( pStatementTree.get() )
795 if ( !pStatementTree->parseNodeToExecutableStatement( sSQL, m_xConnection, m_aSqlParser, NULL ) )
796 break;
798 Reference< XResultSetMetaData > xResultSetMeta;
799 Reference< XResultSetMetaDataSupplier > xResMetaDataSup;
802 xPreparedStatement.set( m_xConnection->prepareStatement( sSQL ), UNO_QUERY_THROW );
803 xResMetaDataSup.set( xPreparedStatement, UNO_QUERY_THROW );
804 xResultSetMeta.set( xResMetaDataSup->getMetaData(), UNO_QUERY_THROW );
806 catch( const Exception& ) { }
810 if ( !xResultSetMeta.is() )
812 xStatement.reset( Reference< XStatement >( m_xConnection->createStatement(), UNO_QUERY_THROW ) );
813 Reference< XPropertySet > xStatementProps( xStatement, UNO_QUERY_THROW );
814 try { xStatementProps->setPropertyValue( PROPERTY_ESCAPE_PROCESSING, makeAny( sal_False ) ); }
815 catch ( const Exception& ) { DBG_UNHANDLED_EXCEPTION(); }
816 xResMetaDataSup.set( xStatement->executeQuery( sSQL ), UNO_QUERY_THROW );
817 xResultSetMeta.set( xResMetaDataSup->getMetaData(), UNO_QUERY_THROW );
820 catch( const Exception& )
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 Reference< XParameters > xParameters( xPreparedStatement, UNO_QUERY_THROW );
826 Reference< XIndexAccess > xPara = getParameters();
827 for(sal_Int32 i = 1;i <= xPara->getCount();++i)
828 xParameters->setNull(i,DataType::VARCHAR);
829 xResMetaDataSup.set(xPreparedStatement->executeQuery(), UNO_QUERY_THROW );
830 xResultSetMeta.set( xResMetaDataSup->getMetaData(), UNO_QUERY_THROW );
833 if ( aSelectColumns->get().empty() )
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 aSelectColumns = ::connectivity::parse::OParseColumn::createColumnsForResultSet( xResultSetMeta, m_xMetaData ,xQueryColumns);
838 break;
841 const ::comphelper::UStringMixEqual aCaseCompare( bCase );
842 typedef ::std::set< size_t > SizeTSet;
843 SizeTSet aUsedSelectColumns;
844 ::connectivity::parse::OParseColumn::StringMap aColumnNames;
846 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 for(sal_Int32 i=1;i<=nCount;++i)
850 OUString sColumnName = xResultSetMeta->getColumnName(i);
851 OUString sColumnLabel;
852 if ( xQueryColumns.is() && xQueryColumns->hasByName(sColumnName) )
854 Reference<XPropertySet> xQueryColumn(xQueryColumns->getByName(sColumnName),UNO_QUERY_THROW);
855 xQueryColumn->getPropertyValue(PROPERTY_LABEL) >>= sColumnLabel;
857 else
858 sColumnLabel = xResultSetMeta->getColumnLabel(i);
859 bool bFound = false;
860 OSQLColumns::Vector::const_iterator aFind = ::connectivity::find(aSelectColumns->get().begin(),aSelectColumns->get().end(),sColumnLabel,aCaseCompare);
861 size_t nFoundSelectColumnPos = aFind - aSelectColumns->get().begin();
862 if ( aFind != aSelectColumns->get().end() )
864 if ( aUsedSelectColumns.find( nFoundSelectColumnPos ) != aUsedSelectColumns.end() )
865 { // we found a column name which exists twice
866 // so we start after the first found
869 aFind = ::connectivity::findRealName(++aFind,aSelectColumns->get().end(),sColumnName,aCaseCompare);
870 nFoundSelectColumnPos = aFind - aSelectColumns->get().begin();
872 while ( ( aUsedSelectColumns.find( nFoundSelectColumnPos ) != aUsedSelectColumns.end() )
873 && ( aFind != aSelectColumns->get().end() )
876 if ( aFind != aSelectColumns->get().end() )
878 (*aFind)->getPropertyValue(PROPERTY_NAME) >>= sColumnName;
879 aUsedSelectColumns.insert( nFoundSelectColumnPos );
880 aNames.push_back(sColumnName);
881 bFound = true;
885 if ( bFound )
886 continue;
888 OSQLColumns::Vector::const_iterator aRealFind = ::connectivity::findRealName(
889 aSelectColumns->get().begin(), aSelectColumns->get().end(), sColumnName, aCaseCompare );
891 if ( i > static_cast< sal_Int32>( aSelectColumns->get().size() ) )
893 aSelectColumns->get().push_back(
894 ::connectivity::parse::OParseColumn::createColumnForResultSet( xResultSetMeta, m_xMetaData, i ,aColumnNames)
896 OSL_ENSURE( aSelectColumns->get().size() == (size_t)i, "OSingleSelectQueryComposer::getColumns: inconsistency!" );
898 else if ( aRealFind == aSelectColumns->get().end() )
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 OSQLColumns::Vector::iterator aFind2 = aSelectColumns->get().begin() + i-1;
903 Reference<XPropertySet> xProp(*aFind2,UNO_QUERY);
904 if ( !xProp.is() || !xProp->getPropertySetInfo()->hasPropertyByName( PROPERTY_REALNAME ) )
905 continue;
907 ::connectivity::parse::OParseColumn* pColumn = new ::connectivity::parse::OParseColumn(xProp,bCase);
908 pColumn->setFunction(::comphelper::getBOOL(xProp->getPropertyValue("Function")));
909 pColumn->setAggregateFunction(::comphelper::getBOOL(xProp->getPropertyValue("AggregateFunction")));
911 OUString sRealName;
912 xProp->getPropertyValue(PROPERTY_REALNAME) >>= sRealName;
913 ::std::vector< OUString>::iterator aFindName;
914 if ( sColumnName.isEmpty() )
915 xProp->getPropertyValue(PROPERTY_NAME) >>= sColumnName;
917 aFindName = ::std::find_if(aNames.begin(),aNames.end(),::std::bind2nd(aCaseCompare,sColumnName));
918 sal_Int32 j = 0;
919 while ( aFindName != aNames.end() )
921 sColumnName += OUString::number(++j);
922 aFindName = ::std::find_if(aNames.begin(),aNames.end(),::std::bind2nd(aCaseCompare,sColumnName));
925 pColumn->setName(sColumnName);
926 pColumn->setRealName(sRealName);
927 pColumn->setTableName(::comphelper::getString(xProp->getPropertyValue(PROPERTY_TABLENAME)));
929 (aSelectColumns->get())[i-1] = pColumn;
931 else
932 continue;
934 aUsedSelectColumns.insert( (size_t)(i - 1) );
935 aNames.push_back( sColumnName );
938 catch(const Exception&)
942 } while ( false );
944 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
952 //This is all a horrible mess
953 if (bMissingSomeColumnLabels)
954 aNames.clear();
956 if ( aNames.empty() )
957 m_aCurrentColumns[ SelectColumns ] = OPrivateColumns::createWithIntrinsicNames( aSelectColumns, bCase, *this, m_aMutex );
958 else
959 m_aCurrentColumns[ SelectColumns ] = new OPrivateColumns( aSelectColumns, bCase, *this, m_aMutex, aNames );
961 return m_aCurrentColumns[SelectColumns];
964 bool OSingleSelectQueryComposer::setORCriteria(OSQLParseNode* pCondition, OSQLParseTreeIterator& _rIterator,
965 ::std::vector< ::std::vector < PropertyValue > >& rFilters, const Reference< ::com::sun::star::util::XNumberFormatter > & xFormatter) const
967 // Round brackets around the expression
968 if (pCondition->count() == 3 &&
969 SQL_ISPUNCTUATION(pCondition->getChild(0),"(") &&
970 SQL_ISPUNCTUATION(pCondition->getChild(2),")"))
972 return setORCriteria(pCondition->getChild(1), _rIterator, rFilters, xFormatter);
974 // OR logic expression
975 // a searchcondition can only look like this: search_condition SQL_TOKEN_OR boolean_term
976 else if (SQL_ISRULE(pCondition,search_condition))
978 bool bResult = true;
979 for (int i = 0; bResult && i < 3; i+=2)
981 // Is the first element a OR logic expression again?
982 // Then descend recursively ...
983 if (SQL_ISRULE(pCondition->getChild(i),search_condition))
984 bResult = setORCriteria(pCondition->getChild(i), _rIterator, rFilters, xFormatter);
985 else
987 rFilters.push_back( ::std::vector < PropertyValue >());
988 bResult = setANDCriteria(pCondition->getChild(i), _rIterator, rFilters[rFilters.size() - 1], xFormatter);
991 return bResult;
993 else
995 rFilters.push_back(::std::vector < PropertyValue >());
996 return setANDCriteria(pCondition, _rIterator, rFilters[rFilters.size() - 1], xFormatter);
1000 bool OSingleSelectQueryComposer::setANDCriteria( OSQLParseNode * pCondition,
1001 OSQLParseTreeIterator& _rIterator, ::std::vector < PropertyValue >& rFilter, const Reference< XNumberFormatter > & xFormatter) const
1003 // Round brackets
1004 if (SQL_ISRULE(pCondition,boolean_primary))
1006 // this should not occur
1007 SAL_WARN("dbaccess","boolean_primary in And-Criteria");
1008 return false;
1010 // The first element is an AND logical expression again
1011 else if ( SQL_ISRULE(pCondition,boolean_term) && pCondition->count() == 3 )
1013 return setANDCriteria(pCondition->getChild(0), _rIterator, rFilter, xFormatter) &&
1014 setANDCriteria(pCondition->getChild(2), _rIterator, rFilter, xFormatter);
1016 else if (SQL_ISRULE(pCondition, comparison_predicate))
1018 return setComparsionPredicate(pCondition,_rIterator,rFilter,xFormatter);
1020 else if (SQL_ISRULE(pCondition,like_predicate) ||
1021 SQL_ISRULE(pCondition,test_for_null) ||
1022 SQL_ISRULE(pCondition,in_predicate) ||
1023 SQL_ISRULE(pCondition,all_or_any_predicate) ||
1024 SQL_ISRULE(pCondition,between_predicate))
1026 if (SQL_ISRULE(pCondition->getChild(0), column_ref))
1028 PropertyValue aItem;
1029 OUString aValue;
1030 OUString aColumnName;
1032 pCondition->parseNodeToStr( aValue, m_xConnection, NULL );
1033 pCondition->getChild(0)->parseNodeToStr( aColumnName, m_xConnection, NULL );
1035 // don't display the column name
1036 aValue = aValue.copy(aColumnName.getLength());
1037 aValue = aValue.trim();
1039 aItem.Name = getColumnName(pCondition->getChild(0),_rIterator);
1040 aItem.Value <<= aValue;
1041 aItem.Handle = 0; // just to know that this is not one the known ones
1042 if ( SQL_ISRULE(pCondition,like_predicate) )
1044 if ( SQL_ISTOKEN(pCondition->getChild(1)->getChild(0),NOT) )
1045 aItem.Handle = SQLFilterOperator::NOT_LIKE;
1046 else
1047 aItem.Handle = SQLFilterOperator::LIKE;
1049 else if (SQL_ISRULE(pCondition,test_for_null))
1051 if (SQL_ISTOKEN(pCondition->getChild(1)->getChild(1),NOT) )
1052 aItem.Handle = SQLFilterOperator::NOT_SQLNULL;
1053 else
1054 aItem.Handle = SQLFilterOperator::SQLNULL;
1056 else if (SQL_ISRULE(pCondition,in_predicate))
1058 SAL_WARN("dbaccess", "OSingleSelectQueryComposer::setANDCriteria: in_predicate not implemented!" );
1060 else if (SQL_ISRULE(pCondition,all_or_any_predicate))
1062 SAL_WARN("dbaccess", "OSingleSelectQueryComposer::setANDCriteria: all_or_any_predicate not implemented!" );
1064 else if (SQL_ISRULE(pCondition,between_predicate))
1066 SAL_WARN("dbaccess", "OSingleSelectQueryComposer::setANDCriteria: between_predicate not implemented!" );
1069 rFilter.push_back(aItem);
1071 else
1072 return false;
1074 else if (SQL_ISRULE(pCondition,existence_test) ||
1075 SQL_ISRULE(pCondition,unique_test))
1077 // this couldn't be handled here, too complex
1078 // as we need a field name
1079 return false;
1081 else
1082 return false;
1084 return true;
1087 sal_Int32 OSingleSelectQueryComposer::getPredicateType(OSQLParseNode * _pPredicate)
1089 sal_Int32 nPredicate = SQLFilterOperator::EQUAL;
1090 switch (_pPredicate->getNodeType())
1092 case SQL_NODE_EQUAL:
1093 nPredicate = SQLFilterOperator::EQUAL;
1094 break;
1095 case SQL_NODE_NOTEQUAL:
1096 nPredicate = SQLFilterOperator::NOT_EQUAL;
1097 break;
1098 case SQL_NODE_LESS:
1099 nPredicate = SQLFilterOperator::LESS;
1100 break;
1101 case SQL_NODE_LESSEQ:
1102 nPredicate = SQLFilterOperator::LESS_EQUAL;
1103 break;
1104 case SQL_NODE_GREAT:
1105 nPredicate = SQLFilterOperator::GREATER;
1106 break;
1107 case SQL_NODE_GREATEQ:
1108 nPredicate = SQLFilterOperator::GREATER_EQUAL;
1109 break;
1110 default:
1111 SAL_WARN("dbaccess","Wrong NodeType!");
1113 return nPredicate;
1116 bool OSingleSelectQueryComposer::setComparsionPredicate(OSQLParseNode * pCondition, OSQLParseTreeIterator& _rIterator,
1117 ::std::vector < PropertyValue >& rFilter, const Reference< ::com::sun::star::util::XNumberFormatter > & xFormatter) const
1119 OSL_ENSURE(SQL_ISRULE(pCondition, comparison_predicate),"setComparsionPredicate: pCondition ist kein ComparsionPredicate");
1120 if (SQL_ISRULE(pCondition->getChild(0), column_ref) ||
1121 SQL_ISRULE(pCondition->getChild(pCondition->count()-1), column_ref))
1123 PropertyValue aItem;
1124 OUString aValue;
1125 sal_uInt32 nPos;
1126 if (SQL_ISRULE(pCondition->getChild(0), column_ref))
1128 nPos = 0;
1129 sal_uInt32 i=1;
1131 aItem.Handle = getPredicateType(pCondition->getChild(i));
1132 // don't display the equal
1133 if (pCondition->getChild(i)->getNodeType() == SQL_NODE_EQUAL)
1134 i++;
1136 // go forward
1137 for (;i < pCondition->count();i++)
1138 pCondition->getChild(i)->parseNodeToPredicateStr(
1139 aValue, m_xConnection, xFormatter, m_aLocale, static_cast<sal_Char>(m_sDecimalSep.toChar() ) );
1141 else if (SQL_ISRULE(pCondition->getChild(pCondition->count()-1), column_ref))
1143 nPos = pCondition->count()-1;
1145 sal_Int32 i = pCondition->count() - 2;
1146 switch (pCondition->getChild(i)->getNodeType())
1148 case SQL_NODE_EQUAL:
1149 // don't display the equal
1150 i--;
1151 aItem.Handle = SQLFilterOperator::EQUAL;
1152 break;
1153 case SQL_NODE_NOTEQUAL:
1154 i--;
1155 aItem.Handle = SQLFilterOperator::NOT_EQUAL;
1156 break;
1157 case SQL_NODE_LESS:
1158 // take the opposite as we change the order
1159 i--;
1160 aValue = ">=";
1161 aItem.Handle = SQLFilterOperator::GREATER_EQUAL;
1162 break;
1163 case SQL_NODE_LESSEQ:
1164 // take the opposite as we change the order
1165 i--;
1166 aValue = ">";
1167 aItem.Handle = SQLFilterOperator::GREATER;
1168 break;
1169 case SQL_NODE_GREAT:
1170 // take the opposite as we change the order
1171 i--;
1172 aValue = "<=";
1173 aItem.Handle = SQLFilterOperator::LESS_EQUAL;
1174 break;
1175 case SQL_NODE_GREATEQ:
1176 // take the opposite as we change the order
1177 i--;
1178 aValue = "<";
1179 aItem.Handle = SQLFilterOperator::LESS;
1180 break;
1181 default:
1182 break;
1185 // go backward
1186 for (; i >= 0; i--)
1187 pCondition->getChild(i)->parseNodeToPredicateStr(
1188 aValue, m_xConnection, xFormatter, m_aLocale, static_cast<sal_Char>( m_sDecimalSep.toChar() ) );
1190 else
1191 return false;
1193 aItem.Name = getColumnName(pCondition->getChild(nPos),_rIterator);
1194 aItem.Value <<= aValue;
1195 rFilter.push_back(aItem);
1197 else if (SQL_ISRULE(pCondition->getChild(0), set_fct_spec ) ||
1198 SQL_ISRULE(pCondition->getChild(0), general_set_fct))
1200 PropertyValue aItem;
1201 OUString aValue;
1202 OUString aColumnName;
1204 pCondition->getChild(2)->parseNodeToPredicateStr(aValue, m_xConnection, xFormatter, m_aLocale, static_cast<sal_Char>( m_sDecimalSep.toChar() ) );
1205 pCondition->getChild(0)->parseNodeToPredicateStr( aColumnName, m_xConnection, xFormatter, m_aLocale, static_cast<sal_Char>( m_sDecimalSep .toChar() ) );
1207 aItem.Name = getColumnName(pCondition->getChild(0),_rIterator);
1208 aItem.Value <<= aValue;
1209 aItem.Handle = getPredicateType(pCondition->getChild(1));
1210 rFilter.push_back(aItem);
1212 else // Can only be an expression
1214 PropertyValue aItem;
1215 OUString aName, aValue;
1217 OSQLParseNode *pLhs = pCondition->getChild(0);
1218 OSQLParseNode *pRhs = pCondition->getChild(2);
1220 // Field names
1221 sal_uInt16 i;
1222 for (i=0;i< pLhs->count();i++)
1223 pLhs->getChild(i)->parseNodeToPredicateStr( aName, m_xConnection, xFormatter, m_aLocale, static_cast<sal_Char>( m_sDecimalSep.toChar() ) );
1225 // Criterion
1226 aItem.Handle = getPredicateType(pCondition->getChild(1));
1227 aValue = pCondition->getChild(1)->getTokenValue();
1228 for(i=0;i< pRhs->count();i++)
1229 pRhs->getChild(i)->parseNodeToPredicateStr(aValue, m_xConnection, xFormatter, m_aLocale, static_cast<sal_Char>( m_sDecimalSep.toChar() ) );
1231 aItem.Name = aName;
1232 aItem.Value <<= aValue;
1233 rFilter.push_back(aItem);
1235 return true;
1238 // Functions for analysing SQL
1239 OUString OSingleSelectQueryComposer::getColumnName( ::connectivity::OSQLParseNode* pColumnRef, OSQLParseTreeIterator& _rIterator )
1241 OUString aTableRange, aColumnName;
1242 _rIterator.getColumnRange(pColumnRef,aColumnName,aTableRange);
1243 return aColumnName;
1246 OUString SAL_CALL OSingleSelectQueryComposer::getFilter( ) throw(RuntimeException, std::exception)
1248 ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
1249 ::osl::MutexGuard aGuard( m_aMutex );
1250 return getSQLPart(Where,m_aAdditiveIterator,false);
1253 OUString SAL_CALL OSingleSelectQueryComposer::getOrder( ) throw(RuntimeException, std::exception)
1255 ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
1256 ::osl::MutexGuard aGuard( m_aMutex );
1257 return getSQLPart(Order,m_aAdditiveIterator,false);
1260 OUString SAL_CALL OSingleSelectQueryComposer::getGroup( ) throw (RuntimeException, std::exception)
1262 ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
1263 ::osl::MutexGuard aGuard( m_aMutex );
1264 return getSQLPart(Group,m_aAdditiveIterator,false);
1267 OUString OSingleSelectQueryComposer::getHavingClause() throw (RuntimeException, std::exception)
1269 ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
1270 ::osl::MutexGuard aGuard( m_aMutex );
1271 return getSQLPart(Having,m_aAdditiveIterator,false);
1274 OUString OSingleSelectQueryComposer::getTableAlias(const Reference< XPropertySet >& column) const
1276 OUString sReturn;
1277 if(m_pTables && m_pTables->getCount() > 1)
1279 OUString aCatalog,aSchema,aTable,aComposedName,aColumnName;
1280 if(column->getPropertySetInfo()->hasPropertyByName(PROPERTY_CATALOGNAME))
1281 column->getPropertyValue(PROPERTY_CATALOGNAME) >>= aCatalog;
1282 if(column->getPropertySetInfo()->hasPropertyByName(PROPERTY_SCHEMANAME))
1283 column->getPropertyValue(PROPERTY_SCHEMANAME) >>= aSchema;
1284 if(column->getPropertySetInfo()->hasPropertyByName(PROPERTY_TABLENAME))
1285 column->getPropertyValue(PROPERTY_TABLENAME) >>= aTable;
1286 column->getPropertyValue(PROPERTY_NAME) >>= aColumnName;
1288 Sequence< OUString> aNames(m_pTables->getElementNames());
1289 const OUString* pBegin = aNames.getConstArray();
1290 const OUString* const pEnd = pBegin + aNames.getLength();
1292 if(aTable.isEmpty())
1293 { // we haven't found a table name, now we must search every table for this column
1294 for(;pBegin != pEnd;++pBegin)
1296 Reference<XColumnsSupplier> xColumnsSupp;
1297 m_pTables->getByName(*pBegin) >>= xColumnsSupp;
1299 if(xColumnsSupp.is() && xColumnsSupp->getColumns()->hasByName(aColumnName))
1301 aTable = *pBegin;
1302 break;
1306 else
1308 aComposedName = ::dbtools::composeTableName( m_xMetaData, aCatalog, aSchema, aTable, false, ::dbtools::eInDataManipulation );
1310 // Is this the right case for the table name?
1311 // Else, look for it with different case, if applicable.
1313 if(!m_pTables->hasByName(aComposedName))
1315 ::comphelper::UStringMixLess aTmp(m_aAdditiveIterator.getTables().key_comp());
1316 ::comphelper::UStringMixEqual aComp(static_cast< ::comphelper::UStringMixLess*>(&aTmp)->isCaseSensitive());
1317 for(;pBegin != pEnd;++pBegin)
1319 Reference<XPropertySet> xTableProp;
1320 m_pTables->getByName(*pBegin) >>= xTableProp;
1321 OSL_ENSURE(xTableProp.is(),"Table isn't a propertyset!");
1322 if(xTableProp.is())
1324 OUString aCatalog2,aSchema2,aTable2;
1325 xTableProp->getPropertyValue(PROPERTY_CATALOGNAME) >>= aCatalog2;
1326 xTableProp->getPropertyValue(PROPERTY_SCHEMANAME) >>= aSchema2;
1327 xTableProp->getPropertyValue(PROPERTY_NAME) >>= aTable2;
1328 if(aComp(aCatalog,aCatalog2) && aComp(aSchema,aSchema2) && aComp(aTable,aTable2))
1330 aCatalog = aCatalog2;
1331 aSchema = aSchema2;
1332 aTable = aTable2;
1333 break;
1339 if(pBegin != pEnd)
1341 sReturn = ::dbtools::composeTableName( m_xMetaData, aCatalog, aSchema, aTable, true, ::dbtools::eInDataManipulation ) + ".";
1344 return sReturn;
1347 Reference< XIndexAccess > SAL_CALL OSingleSelectQueryComposer::getParameters( ) throw(RuntimeException, std::exception)
1349 // now set the Parameters
1350 if ( !m_aCurrentColumns[ParameterColumns] )
1352 ::rtl::Reference< OSQLColumns> aCols = m_aSqlIterator.getParameters();
1353 ::std::vector< OUString> aNames;
1354 OSQLColumns::Vector::const_iterator aEnd = aCols->get().end();
1355 for(OSQLColumns::Vector::const_iterator aIter = aCols->get().begin(); aIter != aEnd;++aIter)
1356 aNames.push_back(getString((*aIter)->getPropertyValue(PROPERTY_NAME)));
1357 m_aCurrentColumns[ParameterColumns] = new OPrivateColumns(aCols,m_xMetaData->supportsMixedCaseQuotedIdentifiers(),*this,m_aMutex,aNames,true);
1360 return m_aCurrentColumns[ParameterColumns];
1363 void OSingleSelectQueryComposer::clearColumns( const EColumnType _eType )
1365 OPrivateColumns* pColumns = m_aCurrentColumns[ _eType ];
1366 if ( pColumns != NULL )
1368 pColumns->disposing();
1369 m_aColumnsCollection.push_back( pColumns );
1370 m_aCurrentColumns[ _eType ] = NULL;
1374 void OSingleSelectQueryComposer::clearCurrentCollections()
1376 ::std::vector<OPrivateColumns*>::iterator aIter = m_aCurrentColumns.begin();
1377 ::std::vector<OPrivateColumns*>::iterator aEnd = m_aCurrentColumns.end();
1378 for (;aIter != aEnd;++aIter)
1380 if ( *aIter )
1382 (*aIter)->disposing();
1383 m_aColumnsCollection.push_back(*aIter);
1384 *aIter = NULL;
1388 if(m_pTables)
1390 m_pTables->disposing();
1391 m_aTablesCollection.push_back(m_pTables);
1392 m_pTables = NULL;
1396 Reference< XIndexAccess > OSingleSelectQueryComposer::setCurrentColumns( EColumnType _eType,
1397 const ::rtl::Reference< OSQLColumns >& _rCols )
1399 ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
1401 ::osl::MutexGuard aGuard( m_aMutex );
1402 // now set the group columns
1403 if ( !m_aCurrentColumns[_eType] )
1405 ::std::vector< OUString> aNames;
1406 OSQLColumns::Vector::const_iterator aEnd = _rCols->get().end();
1407 for(OSQLColumns::Vector::const_iterator aIter = _rCols->get().begin(); aIter != aEnd;++aIter)
1408 aNames.push_back(getString((*aIter)->getPropertyValue(PROPERTY_NAME)));
1409 m_aCurrentColumns[_eType] = new OPrivateColumns(_rCols,m_xMetaData->supportsMixedCaseQuotedIdentifiers(),*this,m_aMutex,aNames,true);
1412 return m_aCurrentColumns[_eType];
1415 Reference< XIndexAccess > SAL_CALL OSingleSelectQueryComposer::getGroupColumns( ) throw(RuntimeException, std::exception)
1417 return setCurrentColumns( GroupByColumns, m_aAdditiveIterator.getGroupColumns() );
1420 Reference< XIndexAccess > SAL_CALL OSingleSelectQueryComposer::getOrderColumns( ) throw(RuntimeException, std::exception)
1422 return setCurrentColumns( OrderColumns, m_aAdditiveIterator.getOrderColumns() );
1425 OUString SAL_CALL OSingleSelectQueryComposer::getQueryWithSubstitution( ) throw (SQLException, RuntimeException, std::exception)
1427 ::osl::MutexGuard aGuard( m_aMutex );
1428 ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
1430 OUString sSqlStatement( getQuery() );
1432 const OSQLParseNode* pStatementNode = m_aSqlIterator.getParseTree();
1433 if ( pStatementNode )
1435 SQLException aError;
1436 if ( !pStatementNode->parseNodeToExecutableStatement( sSqlStatement, m_xConnection, m_aSqlParser, &aError ) )
1437 throw SQLException( aError );
1440 return sSqlStatement;
1443 OUString OSingleSelectQueryComposer::getStatementPart( TGetParseNode& _aGetFunctor, OSQLParseTreeIterator& _rIterator )
1445 OUString sResult;
1447 const OSQLParseNode* pNode = _aGetFunctor( &_rIterator );
1448 if ( pNode )
1449 pNode->parseNodeToStr( sResult, m_xConnection );
1451 return sResult;
1454 namespace
1456 OUString lcl_getDecomposedColumnName(const OUString& rComposedName, const OUString& rQuoteString)
1458 const sal_Int32 nQuoteLength = rQuoteString.getLength();
1459 OUString sName = rComposedName.trim();
1460 OUString sColumnName;
1461 sal_Int32 nPos, nRPos = 0;
1463 for (;;)
1465 nPos = sName.indexOf( rQuoteString, nRPos );
1466 if ( nPos >= 0 )
1468 nRPos = sName.indexOf( rQuoteString, nPos + nQuoteLength );
1469 if ( nRPos > nPos )
1471 if ( nRPos + nQuoteLength < sName.getLength() )
1473 nRPos += nQuoteLength; // -1 + 1 skip dot
1475 else
1477 sColumnName = sName.copy( nPos + nQuoteLength, nRPos - nPos - nQuoteLength );
1478 break;
1481 else
1482 break;
1484 else
1485 break;
1487 return sColumnName.isEmpty() ? rComposedName : sColumnName;
1490 OUString lcl_getCondition(const Sequence< Sequence< PropertyValue > >& filter,
1491 const OPredicateInputController& i_aPredicateInputController,
1492 const Reference< XNameAccess >& i_xSelectColumns,
1493 const OUString& rQuoteString)
1495 OUStringBuffer sRet;
1496 const Sequence< PropertyValue >* pOrIter = filter.getConstArray();
1497 const Sequence< PropertyValue >* pOrEnd = pOrIter + filter.getLength();
1498 while ( pOrIter != pOrEnd )
1500 if ( pOrIter->getLength() )
1502 sRet.append(L_BRACKET);
1503 const PropertyValue* pAndIter = pOrIter->getConstArray();
1504 const PropertyValue* pAndEnd = pAndIter + pOrIter->getLength();
1505 while ( pAndIter != pAndEnd )
1507 sRet.append(pAndIter->Name);
1508 OUString sValue;
1509 pAndIter->Value >>= sValue;
1510 const OUString sColumnName = lcl_getDecomposedColumnName( pAndIter->Name, rQuoteString );
1511 if ( i_xSelectColumns.is() && i_xSelectColumns->hasByName(sColumnName) )
1513 Reference<XPropertySet> xColumn(i_xSelectColumns->getByName(sColumnName),UNO_QUERY);
1514 sValue = i_aPredicateInputController.getPredicateValueStr(sValue,xColumn);
1516 else
1518 sValue = i_aPredicateInputController.getPredicateValueStr(pAndIter->Name,sValue);
1520 lcl_addFilterCriteria_throw(pAndIter->Handle,sValue,sRet);
1521 ++pAndIter;
1522 if ( pAndIter != pAndEnd )
1523 sRet.append(STR_AND);
1525 sRet.append(R_BRACKET);
1527 ++pOrIter;
1528 if ( pOrIter != pOrEnd && !sRet.isEmpty() )
1529 sRet.append(STR_OR);
1531 return sRet.makeStringAndClear();
1535 void SAL_CALL OSingleSelectQueryComposer::setStructuredFilter( const Sequence< Sequence< PropertyValue > >& filter ) throw (SQLException, ::com::sun::star::lang::IllegalArgumentException, RuntimeException, std::exception)
1537 OPredicateInputController aPredicateInput(m_aContext, m_xConnection, &m_aParseContext);
1538 setFilter(lcl_getCondition(filter, aPredicateInput, getColumns(), m_xMetaData->getIdentifierQuoteString()));
1541 void SAL_CALL OSingleSelectQueryComposer::setStructuredHavingClause( const Sequence< Sequence< PropertyValue > >& filter ) throw (SQLException, RuntimeException, std::exception)
1543 OPredicateInputController aPredicateInput(m_aContext, m_xConnection);
1544 setHavingClause(lcl_getCondition(filter, aPredicateInput, getColumns(), m_xMetaData->getIdentifierQuoteString()));
1547 void OSingleSelectQueryComposer::setConditionByColumn( const Reference< XPropertySet >& column, bool andCriteria ,::std::mem_fun1_t<bool,OSingleSelectQueryComposer,const OUString& >& _aSetFunctor,sal_Int32 filterOperator)
1551 ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
1553 if ( !column.is()
1554 || !column->getPropertySetInfo()->hasPropertyByName(PROPERTY_VALUE)
1555 || !column->getPropertySetInfo()->hasPropertyByName(PROPERTY_NAME)
1556 || !column->getPropertySetInfo()->hasPropertyByName(PROPERTY_TYPE))
1557 throw SQLException(DBACORE_RESSTRING(RID_STR_COLUMN_NOT_VALID),*this,SQLSTATE_GENERAL,1000,Any() );
1559 sal_Int32 nType = 0;
1560 column->getPropertyValue(PROPERTY_TYPE) >>= nType;
1561 sal_Int32 nSearchable = dbtools::getSearchColumnFlag(m_xConnection,nType);
1562 if(nSearchable == ColumnSearch::NONE)
1563 throw SQLException(DBACORE_RESSTRING(RID_STR_COLUMN_NOT_SEARCHABLE),*this,SQLSTATE_GENERAL,1000,Any() );
1565 ::osl::MutexGuard aGuard( m_aMutex );
1567 OUString aName;
1568 column->getPropertyValue(PROPERTY_NAME) >>= aName;
1570 Any aValue;
1571 column->getPropertyValue(PROPERTY_VALUE) >>= aValue;
1573 OUStringBuffer aSQL;
1574 const OUString aQuote = m_xMetaData->getIdentifierQuoteString();
1575 getColumns();
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
1580 if ( m_aCurrentColumns[SelectColumns] && m_aCurrentColumns[SelectColumns]->hasByName(aName) )
1582 Reference<XPropertySet> xColumn;
1583 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!");
1588 OUString sRealName,sTableName;
1589 xColumn->getPropertyValue(PROPERTY_REALNAME) >>= sRealName;
1590 xColumn->getPropertyValue(PROPERTY_TABLENAME) >>= sTableName;
1591 if(sTableName.indexOf('.',0) != -1)
1593 OUString aCatlog,aSchema,aTable;
1594 ::dbtools::qualifiedNameComponents(m_xMetaData,sTableName,aCatlog,aSchema,aTable,::dbtools::eInDataManipulation);
1595 sTableName = ::dbtools::composeTableName( m_xMetaData, aCatlog, aSchema, aTable, true, ::dbtools::eInDataManipulation );
1597 else
1598 sTableName = ::dbtools::quoteName(aQuote,sTableName);
1600 if ( !::comphelper::getBOOL(xColumn->getPropertyValue("Function")) )
1602 aSQL = sTableName + "." + ::dbtools::quoteName( aQuote, sRealName );
1604 else
1605 aSQL = sRealName;
1607 else
1609 aSQL = getTableAlias( column ) + ::dbtools::quoteName( aQuote, aName );
1612 if ( aValue.hasValue() )
1614 if( !m_xTypeConverter.is() )
1615 m_xTypeConverter.set( Converter::create(m_aContext) );
1616 OSL_ENSURE(m_xTypeConverter.is(),"NO typeconverter!");
1618 if ( nType != DataType::BOOLEAN && DataType::BIT != nType )
1620 OUString sEmpty;
1621 lcl_addFilterCriteria_throw(filterOperator,sEmpty,aSQL);
1624 switch(nType)
1626 case DataType::VARCHAR:
1627 case DataType::CHAR:
1628 case DataType::LONGVARCHAR:
1629 aSQL.append( DBTypeConversion::toSQLString( nType, aValue, true, m_xTypeConverter ) );
1630 break;
1631 case DataType::CLOB:
1633 Reference< XClob > xClob(aValue,UNO_QUERY);
1634 if ( xClob.is() )
1636 const ::sal_Int64 nLength = xClob->length();
1637 if ( sal_Int64(nLength + aSQL.getLength() + STR_LIKE.getLength() ) < sal_Int64(SAL_MAX_INT32) )
1639 aSQL.append("'" + xClob->getSubString(1,(sal_Int32)nLength) + "'");
1642 else
1644 aSQL.append( DBTypeConversion::toSQLString( nType, aValue, true, m_xTypeConverter ) );
1647 break;
1648 case DataType::VARBINARY:
1649 case DataType::BINARY:
1650 case DataType::LONGVARBINARY:
1652 Sequence<sal_Int8> aSeq;
1653 if(aValue >>= aSeq)
1655 if(nSearchable == ColumnSearch::CHAR)
1657 aSQL.append( "\'" );
1659 aSQL.appendAscii( "0x" );
1660 const sal_Int8* pBegin = aSeq.getConstArray();
1661 const sal_Int8* pEnd = pBegin + aSeq.getLength();
1662 for(;pBegin != pEnd;++pBegin)
1664 aSQL.append( (sal_Int32)*pBegin, 16 );
1666 if(nSearchable == ColumnSearch::CHAR)
1667 aSQL.append( "\'" );
1669 else
1670 throw SQLException(DBACORE_RESSTRING(RID_STR_NOT_SEQUENCE_INT8),*this,SQLSTATE_GENERAL,1000,Any() );
1672 break;
1673 case DataType::BIT:
1674 case DataType::BOOLEAN:
1676 bool bValue = false;
1677 m_xTypeConverter->convertToSimpleType(aValue, TypeClass_BOOLEAN) >>= bValue;
1679 OUString sColumnExp = aSQL.makeStringAndClear();
1680 getBooleanComparisonPredicate( sColumnExp, bValue, m_nBoolCompareMode, aSQL );
1682 break;
1683 default:
1684 aSQL.append( DBTypeConversion::toSQLString( nType, aValue, true, m_xTypeConverter ) );
1685 break;
1688 else
1690 sal_Int32 nFilterOp = filterOperator;
1691 if ( filterOperator != SQLFilterOperator::SQLNULL && filterOperator != SQLFilterOperator::NOT_SQLNULL )
1692 nFilterOp = SQLFilterOperator::SQLNULL;
1693 OUString sEmpty;
1694 lcl_addFilterCriteria_throw(nFilterOp,sEmpty,aSQL);
1697 // Attach filter
1698 // Construct SELECT without WHERE and ORDER BY
1699 OUString sFilter = getFilter();
1701 if ( !sFilter.isEmpty() && !aSQL.isEmpty() )
1703 OUString sTemp(L_BRACKET + sFilter + R_BRACKET);
1704 sTemp += andCriteria ? OUString(STR_AND) : OUString(STR_OR);
1705 sFilter = sTemp;
1707 sFilter += aSQL.makeStringAndClear();
1709 // add the filter and the sort order
1710 _aSetFunctor(this,sFilter);
1712 catch (css::lang::WrappedTargetException & e)
1714 if (e.TargetException.isExtractableTo(
1715 cppu::UnoType<css::sdbc::SQLException>::get()))
1717 cppu::throwException(e.TargetException);
1719 else
1721 throw;
1726 Sequence< Sequence< PropertyValue > > OSingleSelectQueryComposer::getStructuredCondition( TGetParseNode& _aGetFunctor )
1728 ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
1730 MutexGuard aGuard(m_aMutex);
1732 Sequence< Sequence< PropertyValue > > aFilterSeq;
1733 OUString sFilter = getStatementPart( _aGetFunctor, m_aAdditiveIterator );
1735 if ( !sFilter.isEmpty() )
1737 OUString aSql(m_aPureSelectSQL + STR_WHERE + sFilter);
1738 // build a temporary parse node
1739 const OSQLParseNode* pTempNode = m_aAdditiveIterator.getParseTree();
1741 OUString aErrorMsg;
1742 boost::scoped_ptr<OSQLParseNode> pSqlParseNode( m_aSqlParser.parseTree(aErrorMsg,aSql));
1743 if ( pSqlParseNode.get() )
1745 m_aAdditiveIterator.setParseTree(pSqlParseNode.get());
1746 // normalize the filter
1747 OSQLParseNode* pWhereNode = const_cast<OSQLParseNode*>(m_aAdditiveIterator.getWhereTree());
1749 OSQLParseNode* pCondition = pWhereNode->getChild(1);
1750 #if OSL_DEBUG_LEVEL > 0
1751 OUString sCondition;
1752 pCondition->parseNodeToStr( sCondition, m_xConnection );
1753 #endif
1754 OSQLParseNode::negateSearchCondition(pCondition);
1756 pCondition = pWhereNode->getChild(1);
1757 #if OSL_DEBUG_LEVEL > 0
1758 sCondition.clear();
1759 pCondition->parseNodeToStr( sCondition, m_xConnection );
1760 #endif
1761 OSQLParseNode::disjunctiveNormalForm(pCondition);
1763 pCondition = pWhereNode->getChild(1);
1764 #if OSL_DEBUG_LEVEL > 0
1765 sCondition.clear();
1766 pCondition->parseNodeToStr( sCondition, m_xConnection );
1767 #endif
1768 OSQLParseNode::absorptions(pCondition);
1770 pCondition = pWhereNode->getChild(1);
1771 #if OSL_DEBUG_LEVEL > 0
1772 sCondition.clear();
1773 pCondition->parseNodeToStr( sCondition, m_xConnection );
1774 #endif
1775 if ( pCondition )
1777 ::std::vector< ::std::vector < PropertyValue > > aFilters;
1778 Reference< XNumberFormatter > xFormatter( NumberFormatter::create(m_aContext), UNO_QUERY_THROW );
1779 xFormatter->attachNumberFormatsSupplier( m_xNumberFormatsSupplier );
1781 if (setORCriteria(pCondition, m_aAdditiveIterator, aFilters, xFormatter))
1783 aFilterSeq.realloc(aFilters.size());
1784 Sequence<PropertyValue>* pFilters = aFilterSeq.getArray();
1785 ::std::vector< ::std::vector < PropertyValue > >::const_iterator aEnd = aFilters.end();
1786 ::std::vector< ::std::vector < PropertyValue > >::const_iterator i = aFilters.begin();
1787 for ( ; i != aEnd ; ++i)
1789 const ::std::vector < PropertyValue >& rProperties = *i;
1790 pFilters->realloc(rProperties.size());
1791 PropertyValue* pFilter = pFilters->getArray();
1792 ::std::vector < PropertyValue >::const_iterator j = rProperties.begin();
1793 ::std::vector < PropertyValue >::const_iterator aEnd2 = rProperties.end();
1794 for ( ; j != aEnd2 ; ++j)
1796 *pFilter = *j;
1797 ++pFilter;
1799 ++pFilters;
1803 // restore
1804 m_aAdditiveIterator.setParseTree(pTempNode);
1807 return aFilterSeq;
1810 OUString OSingleSelectQueryComposer::getKeyword( SQLPart _ePart )
1812 OUString sKeyword;
1813 switch(_ePart)
1815 default:
1816 SAL_WARN("dbaccess", "OSingleSelectQueryComposer::getKeyWord: Invalid enum value!" );
1817 // no break, fallback to WHERE
1818 case Where:
1819 sKeyword = STR_WHERE;
1820 break;
1821 case Group:
1822 sKeyword = STR_GROUP_BY;
1823 break;
1824 case Having:
1825 sKeyword = STR_HAVING;
1826 break;
1827 case Order:
1828 sKeyword = STR_ORDER_BY;
1829 break;
1831 return sKeyword;
1834 OUString OSingleSelectQueryComposer::getSQLPart( SQLPart _ePart, OSQLParseTreeIterator& _rIterator, bool _bWithKeyword )
1836 TGetParseNode F_tmp(&OSQLParseTreeIterator::getSimpleWhereTree);
1837 OUString sKeyword( getKeyword( _ePart ) );
1838 switch(_ePart)
1840 case Where:
1841 F_tmp = TGetParseNode(&OSQLParseTreeIterator::getSimpleWhereTree);
1842 break;
1843 case Group:
1844 F_tmp = TGetParseNode (&OSQLParseTreeIterator::getSimpleGroupByTree);
1845 break;
1846 case Having:
1847 F_tmp = TGetParseNode(&OSQLParseTreeIterator::getSimpleHavingTree);
1848 break;
1849 case Order:
1850 F_tmp = TGetParseNode(&OSQLParseTreeIterator::getSimpleOrderTree);
1851 break;
1852 default:
1853 SAL_WARN("dbaccess","Invalid enum value!");
1856 OUString sRet = getStatementPart( F_tmp, _rIterator );
1857 if ( _bWithKeyword && !sRet.isEmpty() )
1858 sRet = sKeyword + sRet;
1859 return sRet;
1862 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */