1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include "composertools.hxx"
22 #include "core_resource.hrc"
23 #include "core_resource.hxx"
24 #include "dbastrings.hrc"
25 #include "HelperCollections.hxx"
26 #include "SingleSelectQueryComposer.hxx"
27 #include "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
;
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 "
92 #define STR_LIKE OUString(" LIKE ")
99 /** parses the given statement, using the given parser, returns a parse node representing
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
)
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
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
) );
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
);
163 _pRootNode
->getChild(3)->getChild(0)->getChild(1)->parseNodeToStr( sSQL
, _rxConnection
);
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
;
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
);
184 case SQLFilterOperator::NOT_EQUAL
:
185 o_sRet
.append(" <> " + i_sValue
);
187 case SQLFilterOperator::LESS
:
188 o_sRet
.append(" < " + i_sValue
);
190 case SQLFilterOperator::GREATER
:
191 o_sRet
.append(" > " + i_sValue
);
193 case SQLFilterOperator::LESS_EQUAL
:
194 o_sRet
.append(" <= " + i_sValue
);
196 case SQLFilterOperator::GREATER_EQUAL
:
197 o_sRet
.append(" >= " + i_sValue
);
199 case SQLFilterOperator::LIKE
:
200 o_sRet
.append(" LIKE " + i_sValue
);
202 case SQLFilterOperator::NOT_LIKE
:
203 o_sRet
.append(" NOT LIKE " + i_sValue
);
205 case SQLFilterOperator::SQLNULL
:
206 o_sRet
.append(" IS NULL");
208 case SQLFilterOperator::NOT_SQLNULL
:
209 o_sRet
.append(" IS NOT NULL");
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
)
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");
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();
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
)
273 ::std::vector
<OPrivateTables
*>::iterator aTabIter
= m_aTablesCollection
.begin();
274 ::std::vector
<OPrivateTables
*>::iterator aTabEnd
= m_aTablesCollection
.end();
275 for(;aTabIter
!= aTabEnd
;++aTabIter
)
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
)
340 switch(_nCommandType
)
342 case CommandType::COMMAND
:
343 setElementaryQuery(Command
);
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
)
357 if ( e
.TargetException
>>= e2
)
362 DBG_UNHANDLED_EXCEPTION();
365 sSQL
.append(dbtools::composeTableNameForSelect(m_xConnection
,xTable
));
369 OUString
sMessage( DBACORE_RESSTRING( RID_STR_TABLE_DOES_NOT_EXIST
) );
370 throwGenericSQLException(sMessage
.replaceAll( "$table$", Command
),*this);
373 case CommandType::QUERY
:
374 if ( m_xConnectionQueries
->hasByName(Command
) )
377 Reference
<XPropertySet
> xQuery(m_xConnectionQueries
->getByName(Command
),UNO_QUERY
);
379 xQuery
->getPropertyValue(PROPERTY_COMMAND
) >>= sCommand
;
380 sSQL
.append(sCommand
);
384 OUString
sMessage( DBACORE_RESSTRING( RID_STR_QUERY_DOES_NOT_EXIST
) );
385 throwGenericSQLException(sMessage
.replaceAll( "$table$", Command
),*this);
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
)
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
);
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
);
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
;
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
)
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
);
500 aNewName
= sTableName
+ "." + ::dbtools::quoteName(aQuote
,sRealName
);
504 aNewName
= ::dbtools::quoteName(aQuote
,aName
);
507 aNewName
= getTableAlias(column
) + ::dbtools::quoteName(aQuote
,aName
);
511 OUString
OSingleSelectQueryComposer::impl_getColumnName_throw(const Reference
< XPropertySet
>& column
, bool bOrderBy
)
513 ::connectivity::checkDisposed(OSubComponent::rBHelper
.bDisposed
);
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
) );
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?
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()) )
558 sOrder
+= sColumnName
;
559 if ( !(ascending
|| sColumnName
.isEmpty()) )
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
)
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
631 OUString
getComposedClause( const OUString
& _rElementaryClause
, const OUString
& _rAdditionalClause
,
632 TokenComposer
& _rComposer
, const OUString
& _rKeyword
)
635 _rComposer
.append( _rElementaryClause
);
636 _rComposer
.append( _rAdditionalClause
);
637 OUString sComposed
= _rComposer
.getComposedAndClear();
638 if ( !sComposed
.isEmpty() )
639 sComposed
= _rKeyword
+ 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
)
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
);
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
]);
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
)
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
);
727 Reference
< XNameAccess
> SAL_CALL
OSingleSelectQueryComposer::getTables( ) throw(RuntimeException
, std::exception
)
729 ::connectivity::checkDisposed(OSubComponent::rBHelper
.bDisposed
);
731 ::osl::MutexGuard
aGuard( m_aMutex
);
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
);
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
;
757 Reference
< XNameAccess
> xQueryColumns
;
758 if ( m_nCommandType
== CommandType::QUERY
)
760 Reference
<XColumnsSupplier
> xSup(m_xConnectionQueries
->getByName(m_sCommand
),UNO_QUERY
);
762 xQueryColumns
= xSup
->getColumns();
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
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
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
) )
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
);
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
;
858 sColumnLabel
= xResultSetMeta
->getColumnLabel(i
);
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
);
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
) )
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")));
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
));
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
;
934 aUsedSelectColumns
.insert( (size_t)(i
- 1) );
935 aNames
.push_back( sColumnName
);
938 catch(const Exception
&)
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
)
956 if ( aNames
.empty() )
957 m_aCurrentColumns
[ SelectColumns
] = OPrivateColumns::createWithIntrinsicNames( aSelectColumns
, bCase
, *this, m_aMutex
);
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
))
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
);
987 rFilters
.push_back( ::std::vector
< PropertyValue
>());
988 bResult
= setANDCriteria(pCondition
->getChild(i
), _rIterator
, rFilters
[rFilters
.size() - 1], xFormatter
);
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
1004 if (SQL_ISRULE(pCondition
,boolean_primary
))
1006 // this should not occur
1007 SAL_WARN("dbaccess","boolean_primary in And-Criteria");
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
;
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
;
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
;
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
);
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
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
;
1095 case SQL_NODE_NOTEQUAL
:
1096 nPredicate
= SQLFilterOperator::NOT_EQUAL
;
1099 nPredicate
= SQLFilterOperator::LESS
;
1101 case SQL_NODE_LESSEQ
:
1102 nPredicate
= SQLFilterOperator::LESS_EQUAL
;
1104 case SQL_NODE_GREAT
:
1105 nPredicate
= SQLFilterOperator::GREATER
;
1107 case SQL_NODE_GREATEQ
:
1108 nPredicate
= SQLFilterOperator::GREATER_EQUAL
;
1111 SAL_WARN("dbaccess","Wrong NodeType!");
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
;
1126 if (SQL_ISRULE(pCondition
->getChild(0), column_ref
))
1131 aItem
.Handle
= getPredicateType(pCondition
->getChild(i
));
1132 // don't display the equal
1133 if (pCondition
->getChild(i
)->getNodeType() == SQL_NODE_EQUAL
)
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
1151 aItem
.Handle
= SQLFilterOperator::EQUAL
;
1153 case SQL_NODE_NOTEQUAL
:
1155 aItem
.Handle
= SQLFilterOperator::NOT_EQUAL
;
1158 // take the opposite as we change the order
1161 aItem
.Handle
= SQLFilterOperator::GREATER_EQUAL
;
1163 case SQL_NODE_LESSEQ
:
1164 // take the opposite as we change the order
1167 aItem
.Handle
= SQLFilterOperator::GREATER
;
1169 case SQL_NODE_GREAT
:
1170 // take the opposite as we change the order
1173 aItem
.Handle
= SQLFilterOperator::LESS_EQUAL
;
1175 case SQL_NODE_GREATEQ
:
1176 // take the opposite as we change the order
1179 aItem
.Handle
= SQLFilterOperator::LESS
;
1187 pCondition
->getChild(i
)->parseNodeToPredicateStr(
1188 aValue
, m_xConnection
, xFormatter
, m_aLocale
, static_cast<sal_Char
>( m_sDecimalSep
.toChar() ) );
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
;
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);
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() ) );
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() ) );
1232 aItem
.Value
<<= aValue
;
1233 rFilter
.push_back(aItem
);
1238 // Functions for analysing SQL
1239 OUString
OSingleSelectQueryComposer::getColumnName( ::connectivity::OSQLParseNode
* pColumnRef
, OSQLParseTreeIterator
& _rIterator
)
1241 OUString aTableRange
, aColumnName
;
1242 _rIterator
.getColumnRange(pColumnRef
,aColumnName
,aTableRange
);
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
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
))
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!");
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
;
1341 sReturn
= ::dbtools::composeTableName( m_xMetaData
, aCatalog
, aSchema
, aTable
, true, ::dbtools::eInDataManipulation
) + ".";
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
)
1382 (*aIter
)->disposing();
1383 m_aColumnsCollection
.push_back(*aIter
);
1390 m_pTables
->disposing();
1391 m_aTablesCollection
.push_back(m_pTables
);
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
)
1447 const OSQLParseNode
* pNode
= _aGetFunctor( &_rIterator
);
1449 pNode
->parseNodeToStr( sResult
, m_xConnection
);
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;
1465 nPos
= sName
.indexOf( rQuoteString
, nRPos
);
1468 nRPos
= sName
.indexOf( rQuoteString
, nPos
+ nQuoteLength
);
1471 if ( nRPos
+ nQuoteLength
< sName
.getLength() )
1473 nRPos
+= nQuoteLength
; // -1 + 1 skip dot
1477 sColumnName
= sName
.copy( nPos
+ nQuoteLength
, nRPos
- nPos
- nQuoteLength
);
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
);
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
);
1518 sValue
= i_aPredicateInputController
.getPredicateValueStr(pAndIter
->Name
,sValue
);
1520 lcl_addFilterCriteria_throw(pAndIter
->Handle
,sValue
,sRet
);
1522 if ( pAndIter
!= pAndEnd
)
1523 sRet
.append(STR_AND
);
1525 sRet
.append(R_BRACKET
);
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
);
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
);
1568 column
->getPropertyValue(PROPERTY_NAME
) >>= aName
;
1571 column
->getPropertyValue(PROPERTY_VALUE
) >>= aValue
;
1573 OUStringBuffer aSQL
;
1574 const OUString aQuote
= m_xMetaData
->getIdentifierQuoteString();
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
);
1598 sTableName
= ::dbtools::quoteName(aQuote
,sTableName
);
1600 if ( !::comphelper::getBOOL(xColumn
->getPropertyValue("Function")) )
1602 aSQL
= sTableName
+ "." + ::dbtools::quoteName( aQuote
, sRealName
);
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
)
1621 lcl_addFilterCriteria_throw(filterOperator
,sEmpty
,aSQL
);
1626 case DataType::VARCHAR
:
1627 case DataType::CHAR
:
1628 case DataType::LONGVARCHAR
:
1629 aSQL
.append( DBTypeConversion::toSQLString( nType
, aValue
, true, m_xTypeConverter
) );
1631 case DataType::CLOB
:
1633 Reference
< XClob
> xClob(aValue
,UNO_QUERY
);
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
) + "'");
1644 aSQL
.append( DBTypeConversion::toSQLString( nType
, aValue
, true, m_xTypeConverter
) );
1648 case DataType::VARBINARY
:
1649 case DataType::BINARY
:
1650 case DataType::LONGVARBINARY
:
1652 Sequence
<sal_Int8
> 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( "\'" );
1670 throw SQLException(DBACORE_RESSTRING(RID_STR_NOT_SEQUENCE_INT8
),*this,SQLSTATE_GENERAL
,1000,Any() );
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
);
1684 aSQL
.append( DBTypeConversion::toSQLString( nType
, aValue
, true, m_xTypeConverter
) );
1690 sal_Int32 nFilterOp
= filterOperator
;
1691 if ( filterOperator
!= SQLFilterOperator::SQLNULL
&& filterOperator
!= SQLFilterOperator::NOT_SQLNULL
)
1692 nFilterOp
= SQLFilterOperator::SQLNULL
;
1694 lcl_addFilterCriteria_throw(nFilterOp
,sEmpty
,aSQL
);
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
);
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
);
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();
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
);
1754 OSQLParseNode::negateSearchCondition(pCondition
);
1756 pCondition
= pWhereNode
->getChild(1);
1757 #if OSL_DEBUG_LEVEL > 0
1759 pCondition
->parseNodeToStr( sCondition
, m_xConnection
);
1761 OSQLParseNode::disjunctiveNormalForm(pCondition
);
1763 pCondition
= pWhereNode
->getChild(1);
1764 #if OSL_DEBUG_LEVEL > 0
1766 pCondition
->parseNodeToStr( sCondition
, m_xConnection
);
1768 OSQLParseNode::absorptions(pCondition
);
1770 pCondition
= pWhereNode
->getChild(1);
1771 #if OSL_DEBUG_LEVEL > 0
1773 pCondition
->parseNodeToStr( sCondition
, m_xConnection
);
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
)
1804 m_aAdditiveIterator
.setParseTree(pTempNode
);
1810 OUString
OSingleSelectQueryComposer::getKeyword( SQLPart _ePart
)
1816 SAL_WARN("dbaccess", "OSingleSelectQueryComposer::getKeyWord: Invalid enum value!" );
1817 // no break, fallback to WHERE
1819 sKeyword
= STR_WHERE
;
1822 sKeyword
= STR_GROUP_BY
;
1825 sKeyword
= STR_HAVING
;
1828 sKeyword
= STR_ORDER_BY
;
1834 OUString
OSingleSelectQueryComposer::getSQLPart( SQLPart _ePart
, OSQLParseTreeIterator
& _rIterator
, bool _bWithKeyword
)
1836 TGetParseNode
F_tmp(&OSQLParseTreeIterator::getSimpleWhereTree
);
1837 OUString
sKeyword( getKeyword( _ePart
) );
1841 F_tmp
= TGetParseNode(&OSQLParseTreeIterator::getSimpleWhereTree
);
1844 F_tmp
= TGetParseNode (&OSQLParseTreeIterator::getSimpleGroupByTree
);
1847 F_tmp
= TGetParseNode(&OSQLParseTreeIterator::getSimpleHavingTree
);
1850 F_tmp
= TGetParseNode(&OSQLParseTreeIterator::getSimpleOrderTree
);
1853 SAL_WARN("dbaccess","Invalid enum value!");
1856 OUString sRet
= getStatementPart( F_tmp
, _rIterator
);
1857 if ( _bWithKeyword
&& !sRet
.isEmpty() )
1858 sRet
= sKeyword
+ sRet
;
1862 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */